Skip to content

Commit

Permalink
rt: Improve support for new default method implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Feb 5, 2025
1 parent d3efa7e commit 4e39d56
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 17 deletions.
6 changes: 6 additions & 0 deletions dora-runtime/src/boots/serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ fn encode_compilation_info(
buffer.emit_id(compilation_data.fct_id.0 as usize);
encode_type_params(vm, &compilation_data.type_params, buffer);
encode_bytecode_type(vm, &compilation_data.return_type, buffer);
if let Some(ref specialize_self) = compilation_data.specialize_self {
buffer.emit_bool(true);
encode_bytecode_type(vm, specialize_self, buffer);
} else {
buffer.emit_bool(false);
}
encode_location(&compilation_data.loc, buffer);
buffer.emit_u8(mode as u8);
buffer.emit_bool(compilation_data.emit_debug);
Expand Down
16 changes: 13 additions & 3 deletions dora-runtime/src/cannon/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2634,11 +2634,22 @@ impl<'a> CannonCodeGen<'a> {
}

fn emit_invoke_generic(&mut self, dest: Register, fct_idx: ConstPoolIdx, is_static: bool) {
let (id, trait_fct_id, type_params) = match self.bytecode.const_pool(fct_idx) {
ConstPoolEntry::Generic(id, fct_id, type_params) => (*id, *fct_id, type_params.clone()),
let (ty, trait_fct_id, type_params) = match self.bytecode.const_pool(fct_idx) {
ConstPoolEntry::Generic(id, fct_id, type_params) => (
self.type_params[*id as usize].clone(),
*fct_id,
type_params.clone(),
),
ConstPoolEntry::GenericSelf(fct_id, type_params) => (
self.specialize_self.clone().expect("missing Self type"),
*fct_id,
type_params.clone(),
),
_ => unreachable!(),
};

assert!(ty.is_concrete_type());

let fct = self.vm.fct(trait_fct_id);
let trait_id = match fct.kind {
FunctionKind::Trait(trait_id) => trait_id,
Expand All @@ -2650,7 +2661,6 @@ impl<'a> CannonCodeGen<'a> {
bindings: Vec::new(),
};

let ty = self.type_params[id as usize].clone();
let (callee_id, type_params) = find_trait_impl(self.vm, trait_fct_id, trait_ty, ty);

let pos = self.bytecode.offset_location(self.current_offset.to_u32());
Expand Down
4 changes: 2 additions & 2 deletions dora-runtime/src/compiler/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ fn compile_function(
.insert((fct_id, type_params), code.instruction_start());
assert!(existing.is_none());
ctc.code_objects.push(code);
} else if let Some(_) = fct.bytecode {
} else if let Some(_) = get_bytecode(vm, fct) {
let (_code_id, code) = compile_fct_aot(vm, fct_id, &type_params, compiler, mode);
ctc.counter += 1;
let existing = ctc
Expand Down Expand Up @@ -569,7 +569,7 @@ fn prepare_lazy_call_sites(
println!(
"code = {:?} {}",
code.descriptor(),
display_fct(&_vm.program, *fct_id)
display_fct(&_vm.program, code.fct_id())
);
println!(
" calls {} with {:?}",
Expand Down
6 changes: 4 additions & 2 deletions pkgs/boots/bytecode/data.dora
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub enum ConstPoolEntry {
Fct(FunctionId, Array[BytecodeType]),
TraitObjectMethod(BytecodeType, FunctionId),
Generic(Int32, FunctionId, Array[BytecodeType]),
GenericSelf(FunctionId, Array[BytecodeType]),
Enum(EnumId, Array[BytecodeType]),
EnumVariant(EnumId, Array[BytecodeType], Int32),
EnumElement(EnumId, Array[BytecodeType], Int32, Int32),
Expand Down Expand Up @@ -149,6 +150,7 @@ impl Stringable for ConstPoolEntry {
ConstPoolEntry::Fct(id, typeParams) => "Fct ${id}${typeParams}",
ConstPoolEntry::TraitObjectMethod(ty, id) => "TraitObjectMethod ${ty} ${id}",
ConstPoolEntry::Generic(tp, id, typeParams) => "Generic ${tp} ${id}${typeParams}",
ConstPoolEntry::GenericSelf(id, typeParams) => "GenericSelf ${id}${typeParams}",
ConstPoolEntry::Enum(id, typeParams) => "Enum ${id}${typeParams}",
ConstPoolEntry::EnumVariant(id, typeParams, variant) => "EnumVariant ${id}${typeParams}::${variant}",
ConstPoolEntry::EnumElement(id, typeParams, variant, element) => "EnumVariant ${id}${typeParams}::${variant}.${element}",
Expand Down Expand Up @@ -249,8 +251,8 @@ impl BytecodeType {
| BytecodeType::Int32
| BytecodeType::Int64
| BytecodeType::Float32
| BytecodeType::Float64
| BytecodeType::This => false,
| BytecodeType::Float64 => false,
BytecodeType::This => true,
BytecodeType::Struct(struct_id, type_params) => type_params.isGeneric(),
BytecodeType::Enum(enum_id, type_params) => type_params.isGeneric(),
BytecodeType::Class(class_id, type_params) => type_params.isGeneric(),
Expand Down
3 changes: 3 additions & 0 deletions pkgs/boots/compilation.dora
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub class CompilationInfo {
pub fctId: Option[FunctionId],
pub typeParams: Array[BytecodeType],
pub returnType: BytecodeType,
pub specializeSelf: Option[BytecodeType],
pub loc: Location,
pub compilationMode: iface::CompilationMode,
pub emitDebug: Bool,
Expand All @@ -26,6 +27,7 @@ impl CompilationInfo {
id: FunctionId,
typeParams: Array[BytecodeType],
returnType: BytecodeType,
specializeSelf: Option[BytecodeType],
loc: Location,
compilationMode: iface::CompilationMode,
emitDebug: Bool,
Expand All @@ -38,6 +40,7 @@ impl CompilationInfo {
fctId = Some[FunctionId](id),
typeParams,
returnType,
specializeSelf,
loc,
compilationMode,
emitDebug,
Expand Down
17 changes: 16 additions & 1 deletion pkgs/boots/deserializer.dora
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,14 @@ pub fn decodeCompilationInfo(reader: ByteReader): CompilationInfo {
let fctId = FunctionId(reader.readInt32());
let typeParams = decodeTypeParams(reader);
let returnType = decodeBytecodeType(reader);
let specializeSelf = decodeOptionBytecodeType(reader);
let loc = decodeLocation(reader);
let compilationMode = decodeCompilationMode(reader);
let emitDebug = reader.readBool();
let emitGraph = reader.readBool();
let emitHtml = reader.readBool();
let emitCodeComments = reader.readBool();
CompilationInfo::new(bc, fctId, typeParams, returnType, loc, compilationMode, emitDebug, emitGraph, emitHtml, emitCodeComments)
CompilationInfo::new(bc, fctId, typeParams, returnType, specializeSelf, loc, compilationMode, emitDebug, emitGraph, emitHtml, emitCodeComments)
}

pub fn decodeStructData(reader: ByteReader): StructData {
Expand Down Expand Up @@ -132,6 +133,14 @@ fn decodeRegisters(reader: ByteReader): Array[BytecodeType] {
data
}

pub fn decodeOptionBytecodeType(reader: ByteReader): Option[BytecodeType] {
if reader.readBool() {
Some[BytecodeType](decodeBytecodeType(reader))
} else {
None[BytecodeType]
}
}

pub fn decodeBytecodeType(reader: ByteReader): BytecodeType {
let opcode = reader.readUInt8().toInt32();

Expand Down Expand Up @@ -188,6 +197,8 @@ pub fn decodeBytecodeType(reader: ByteReader): BytecodeType {
let traitTy = decodeBytecodeTraitType(reader);
let assocId = AliasId(reader.readId());
BytecodeType::GenericAssoc(typeParamId, traitTy, assocId)
} else if opcode == opc::BC_TYPE_THIS {
BytecodeType::This
} else {
println("unknown bytecode type opcode = ${opcode}");
unreachable[BytecodeType]()
Expand Down Expand Up @@ -267,6 +278,10 @@ fn decodeConstPoolEntry(reader: ByteReader): ConstPoolEntry {
let fct_id = FunctionId(reader.readInt32());
let type_params = decodeBytecodeTypeArray(reader);
ConstPoolEntry::Generic(idx, fct_id, type_params)
} else if opcode == opc::CONSTPOOL_OPCODE_GENERIC_SELF {
let fct_id = FunctionId(reader.readInt32());
let type_params = decodeBytecodeTypeArray(reader);
ConstPoolEntry::GenericSelf(fct_id, type_params)
} else if opcode == opc::CONSTPOOL_OPCODE_ENUM {
let enum_id = EnumId(reader.readInt32());
let type_params = decodeBytecodeTypeArray(reader);
Expand Down
19 changes: 15 additions & 4 deletions pkgs/boots/graph_builder.dora
Original file line number Diff line number Diff line change
Expand Up @@ -1464,8 +1464,20 @@ impl SsaGen {
fn emitInvokeGeneric(dest: BytecodeRegister, idx: ConstPoolId, kind: CallKind): Bool {
let ty = self.regGraphTy(dest);

let ConstPoolEntry::Generic(type_param_idx, trait_fct_id, trait_type_params) = self.bc.constPool(idx);
let object_ty = self.typeParams(type_param_idx.toInt64());
let (object_ty, trait_fct_id, trait_type_params) = match self.bc.constPool(idx) {
ConstPoolEntry::Generic(type_param_idx, trait_fct_id, trait_type_params) => {
(self.typeParams(type_param_idx.toInt64()), trait_fct_id, trait_type_params)
}

ConstPoolEntry::GenericSelf(trait_fct_id, trait_type_params) => {
(self.ci.specializeSelf.getOrPanic(), trait_fct_id, trait_type_params)
}

_ => unreachable[(BytecodeType, FunctionId, Array[BytecodeType])](),
};

assert(!object_ty.isGeneric());

let (callee_id, type_params) = iface::findTraitImpl(self.ci, trait_fct_id, trait_type_params, object_ty);

let intrinsic = iface::getIntrinsicForFunction(callee_id);
Expand Down Expand Up @@ -2725,8 +2737,7 @@ impl SsaGen {
}
BytecodeType::Struct(..)
| BytecodeType::Tuple(_) => Type::Address,
BytecodeType::This
| BytecodeType::TypeParam(_) => unreachable[Type](),
BytecodeType::This | BytecodeType::TypeParam(_) => unreachable[Type](),
BytecodeType::TypeAlias(..) | BytecodeType::Assoc(..) | BytecodeType::GenericAssoc(..) => unreachable[Type](),
}
}
Expand Down
5 changes: 3 additions & 2 deletions pkgs/boots/location.dora
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use package::codegen::CodeGen;
use package::compilation::CompilationInfo;
use package::graph::{Graph, InputOutputOverlap, Inst, Location, LocationData, Op, Operand, Policy, StackSlot, Type};
use package::interface::{config, PTR_SIZE, Architecture};
use package::specialize::specializeTy;

pub fn ensureLocationData(graph: Graph, codegen: CodeGen, ci: CompilationInfo): Int32 {
let argumentLocations = computeArgumentLocations(codegen, ci);
Expand Down Expand Up @@ -471,7 +472,7 @@ fn computeArgumentLocations(codegen: CodeGen, ci: CompilationInfo): ArgumentLoca
let gp_argument_registers = codegen.argumentRegisters();
let fp_argument_registers = codegen.argumentFloatRegisters();

let retTy = ci.returnType.specialize(ci.typeParams);
let retTy = specializeTy(ci, ci.returnType, ci.typeParams);

if retTy.isStruct() || retTy.isTuple() {
locations.push(gp_argument_registers(gp_idx).toLocation());
Expand All @@ -480,7 +481,7 @@ fn computeArgumentLocations(codegen: CodeGen, ci: CompilationInfo): ArgumentLoca

for idx in std::range(0, arguments) {
let ty = ci.bc.registers(idx);
let ty = ty.specialize(ci.typeParams);
let ty = specializeTy(ci, ty, ci.typeParams);

if ty.isUnit() {
continue;
Expand Down
6 changes: 3 additions & 3 deletions pkgs/boots/specialize.dora
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use package::interface as iface;
use package::CompilationInfo;

pub fn specializeTy(ci: CompilationInfo, ty: BytecodeType, type_params: Array[BytecodeType]): BytecodeType {
if type_params.isEmpty() || !ty.isGeneric() {
if !ty.isGeneric() {
return ty;
}

Expand All @@ -16,8 +16,8 @@ pub fn specializeTy(ci: CompilationInfo, ty: BytecodeType, type_params: Array[By
| BytecodeType::Int32
| BytecodeType::Int64
| BytecodeType::Float32
| BytecodeType::Float64
| BytecodeType::This => ty,
| BytecodeType::Float64 => ty,
BytecodeType::This => ci.specializeSelf.getOrPanic(),
BytecodeType::Struct(struct_id, struct_type_params) => {
BytecodeType::Struct(struct_id, specializeArray(ci, struct_type_params, type_params))
},
Expand Down

0 comments on commit 4e39d56

Please sign in to comment.