Object allocation

TEST=tools/test.py -n vm-modaot-mac-debug-arm64 language
Issue: https://github.com/dart-lang/sdk/issues/61635
Change-Id: Ie569c19ef37e27f7f711dfc3d62db818691f28fd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/476600
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
This commit is contained in:
Alexander Markov
2026-02-03 13:09:02 -08:00
committed by Commit Queue
parent ab311f476c
commit 151bc79032
31 changed files with 985 additions and 106 deletions
+1
View File
@@ -12,4 +12,5 @@ extension type CField(ast.Field _raw) {
bool get isFinal => _raw.isFinal;
bool get hasInitializer => _raw.initializer != null;
CType get type => CType.fromStaticType(_raw.type);
ast.Class get enclosingClass => _raw.enclosingClass!;
}
+3 -1
View File
@@ -1644,7 +1644,9 @@ abstract base class MoveOp {}
enum ParallelMoveStage {
// Move fixed output of the instruction to its desired location.
output,
// Split/spill live ranges.
// Spill output of the instruction.
spill,
// Split live ranges.
split,
// Moves at control flow edges (including phi moves).
control,
+1
View File
@@ -181,6 +181,7 @@ final class IrToText extends VoidInstructionVisitor {
DynamicCallKind.getter => 'get ',
DynamicCallKind.setter => 'set ',
}}${instr.selector}',
AllocateObject() => 'AllocateObject ${instr.type}',
BinaryIntOp() => 'BinaryIntOp ${instr.op.token}',
UnaryIntOp() => 'UnaryIntOp ${instr.op.token}',
BinaryDoubleOp() => 'BinaryDoubleOp ${instr.op.token}',
+1 -1
View File
@@ -209,7 +209,7 @@ B0 = EntryBlock()
B0 = EntryBlock()
v13 = Constant(null)
v1 = Parameter(a)
v2 = AllocateObject()
v2 = AllocateObject B()
DirectCall B.(v2, v1)
v8 = InterfaceCall getter C.y(v2)
v10 = InterfaceCall getter C.x(v2)
+1 -1
View File
@@ -53,7 +53,7 @@ B0 = EntryBlock()
B0 = EntryBlock()
v1 = TypeParameters()
v2 = TypeArguments(v1, <A..T%>)
v3 = AllocateObject(v2)
v3 = AllocateObject A<A..T%>(v2)
DirectCall A._(v3)
Return(v3)
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:native_compiler/back_end/assembler.dart';
import 'package:native_compiler/back_end/code.dart';
import 'package:native_compiler/back_end/locations.dart';
import 'package:native_compiler/runtime/vm_defs.dart';
import 'package:cfg/ir/constant_value.dart';
@@ -328,6 +329,49 @@ final class Arm64Assembler extends Assembler with Uint32OutputBuffer {
}
}
/// Create a [base + offset] address for arbitrary offset,
/// generating extra code if necessary.
/// The resulting address can be used in ldp/stp instructions.
Address pairAddress(
Register base,
int offset, [
OperandSize sz = OperandSize.s64,
]) {
final scale = sz.log2sizeInBytes;
if (_isInt(7 + scale, offset) && ((offset & (sz.sizeInBytes - 1)) == 0)) {
return RegOffsetAddress(base, offset);
} else {
throw 'Large address offsets are not implemented yet: $offset';
}
}
@override
void enterDartFrame() {
pushPair(FP, LR);
mov(FP, stackPointerReg);
// Tag and save caller pool pointer.
add(poolPointerReg, poolPointerReg, Immediate(heapObjectTag));
pushPair(poolPointerReg, codeReg);
// Load and untag current pool pointer.
ldr(
poolPointerReg,
fieldAddress(codeReg, vmOffsets.Code_object_pool_offset),
);
sub(poolPointerReg, poolPointerReg, Immediate(heapObjectTag));
}
@override
void leaveDartFrame() {
// Restore and untag pool pointer.
ldr(poolPointerReg, RegOffsetAddress(FP, -2 * wordSize));
sub(poolPointerReg, poolPointerReg, Immediate(heapObjectTag));
mov(stackPointerReg, FP);
popPair(FP, LR);
}
@override
void push(Register reg) {
str(
@@ -503,6 +547,56 @@ final class Arm64Assembler extends Assembler with Uint32OutputBuffer {
bool canEncodeBitMasks(int value, [OperandSize sz = OperandSize.s64]) =>
Immediate(value).tryEncodingBitMasks(sz) != null;
@override
void addImmediate(
Register dst,
Register src,
int value, [
OperandSize sz = OperandSize.s64,
]) {
assert(sz.is32or64);
assert(_isInt(sz.bitWidth, value) || _isUint(sz.bitWidth, value));
if (value == 0) {
if (dst != src) {
mov(dst, src, sz);
}
} else if (canEncodeImm12(value)) {
add(dst, src, Immediate(value), sz);
} else if (canEncodeImm12(-value)) {
sub(dst, src, Immediate(-value), sz);
} else {
assert(src != tempReg);
loadImmediate(tempReg, value);
if (dst == SP || src == SP) {
add(dst, src, ExtRegOperand(tempReg, .UXTX, 0), sz);
} else {
add(dst, src, tempReg, sz);
}
}
}
@override
void andImmediate(
Register dst,
Register src,
int value, [
OperandSize sz = OperandSize.s64,
]) {
assert(sz.is32or64);
assert(_isInt(sz.bitWidth, value) || _isUint(sz.bitWidth, value));
if (value == 0) {
movz(dst, 0);
} else if (value == -1) {
mov(dst, src, sz);
} else if (canEncodeBitMasks(value, sz)) {
and(dst, src, Immediate(value), sz);
} else {
assert(src != tempReg);
loadImmediate(tempReg, value);
and(dst, src, tempReg, sz);
}
}
@override
void callRuntime(RuntimeEntry entry, int argumentCount) {
ldr(
@@ -520,6 +614,18 @@ final class Arm64Assembler extends Assembler with Uint32OutputBuffer {
blr(LR);
}
@override
void callLeafRuntime(LeafRuntimeEntry entry) {
unimplemented("callLeafRuntime $entry");
}
@override
void callStub(Code stub) {
loadFromPool(codeReg, stub);
ldr(LR, fieldAddress(codeReg, vmOffsets.Code_entry_point_offset.first));
blr(LR);
}
@override
void unimplemented(String message) {
loadConstant(R0, ConstantValue.fromString(message));
@@ -5,10 +5,14 @@
import 'package:cfg/ir/constant_value.dart';
import 'package:cfg/ir/instructions.dart';
import 'package:cfg/utils/misc.dart';
import 'package:kernel/ast.dart' as ast;
import 'package:native_compiler/back_end/arm64/assembler.dart';
import 'package:native_compiler/back_end/arm64/stub_code_generator.dart';
import 'package:native_compiler/back_end/assembler.dart';
import 'package:native_compiler/back_end/code_generator.dart';
import 'package:native_compiler/back_end/locations.dart';
import 'package:native_compiler/back_end/object_pool.dart';
import 'package:native_compiler/runtime/type_utils.dart';
import 'package:native_compiler/runtime/vm_defs.dart';
final class Arm64CodeGenerator extends CodeGenerator {
@@ -21,19 +25,7 @@ final class Arm64CodeGenerator extends CodeGenerator {
@override
void enterFrame() {
_asm.pushPair(FP, LR);
_asm.mov(FP, stackPointerReg);
// Tag and save caller pool pointer.
_asm.add(poolPointerReg, poolPointerReg, Immediate(heapObjectTag));
_asm.pushPair(poolPointerReg, codeReg);
// Load and untag current pool pointer.
_asm.ldr(
poolPointerReg,
_asm.fieldAddress(codeReg, _asm.vmOffsets.Code_object_pool_offset),
);
_asm.sub(poolPointerReg, poolPointerReg, Immediate(heapObjectTag));
_asm.enterDartFrame();
// TODO: calculate stack frame size.
_asm.sub(stackPointerReg, stackPointerReg, Immediate(64));
@@ -185,12 +177,7 @@ final class Arm64CodeGenerator extends CodeGenerator {
@override
void visitReturn(Return instr) {
assert(inputReg(instr, 0) == returnReg);
// Restore and untag pool pointer.
_asm.ldr(poolPointerReg, RegOffsetAddress(FP, -2 * wordSize));
_asm.sub(poolPointerReg, poolPointerReg, Immediate(heapObjectTag));
_asm.mov(stackPointerReg, FP);
_asm.popPair(FP, LR);
_asm.leaveDartFrame();
_asm.ret();
}
@@ -255,13 +242,13 @@ final class Arm64CodeGenerator extends CodeGenerator {
// TODO: call directly through Code.
_asm.ldr(
codeReg,
_asm.fieldAddress(functionReg, _asm.vmOffsets.Function_code_offset),
_asm.fieldAddress(functionReg, vmOffsets.Function_code_offset),
);
_asm.ldr(
tempReg,
_asm.fieldAddress(
functionReg,
_asm.vmOffsets.Function_entry_point_offset.first,
vmOffsets.Function_entry_point_offset.first,
),
);
_asm.blr(tempReg);
@@ -350,7 +337,107 @@ final class Arm64CodeGenerator extends CodeGenerator {
@override
void visitAllocateObject(AllocateObject instr) {
_asm.unimplemented('Unimplemented: code generation for AllocateObject');
final cls = (instr.type.dartType as ast.InterfaceType).classNode;
final instanceSize = objectLayout.getInstanceSize(cls);
final typeArgsField = objectLayout.getTypeArgumentsField(cls);
final typeArgumentsReg = AllocationStub.typeArgumentsReg;
final tagsReg = AllocationStub.tagsReg;
final resultReg = AllocationStub.resultReg;
assert(!instr.hasTypeArguments || inputReg(instr, 0) == typeArgumentsReg);
assert(outputReg(instr) == resultReg);
// TODO: support huge objects
final done = Label();
Label slowPath = addSlowPath(() {
_asm.callStub(backEndState.stubFactory.getAllocationStub(cls));
_asm.b(done);
});
final endReg = AllocationStub.scratch1Reg;
final newTopReg = AllocationStub.scratch2Reg;
// Load Thread.top_ and Thread.end_.
_asm.ldp(
resultReg,
endReg,
_asm.pairAddress(threadReg, vmOffsets.Thread_top_offset),
);
_asm.addImmediate(newTopReg, resultReg, instanceSize);
_asm.cmp(endReg, newTopReg);
_asm.b(slowPath, Condition.unsignedLessOrEqual);
// TLAB has enough space. Update top and initialize object.
_asm.loadFromPool(tagsReg, NewObjectTags(cls));
_asm.str(newTopReg, _asm.address(threadReg, vmOffsets.Thread_top_offset));
_asm.str(tagsReg, _asm.address(resultReg, vmOffsets.Object_tags_offset));
// TODO: figure out if we need store-store barrier here.
// TODO: support compressed pointers.
const maxUnrolledSize = 16 * wordSize;
if (instanceSize <= maxUnrolledSize) {
int offset = vmOffsets.Instance_first_field_offset;
for (; offset + 2 * wordSize <= instanceSize; offset += 2 * wordSize) {
_asm.stp(nullReg, nullReg, _asm.pairAddress(resultReg, offset));
}
if (offset < instanceSize) {
_asm.str(nullReg, _asm.address(resultReg, offset));
offset += wordSize;
}
assert(offset == instanceSize);
} else {
final fieldReg = AllocationStub.scratch1Reg;
_asm.addImmediate(
fieldReg,
resultReg,
vmOffsets.Instance_first_field_offset,
);
final loop = Label();
_asm.bind(loop);
_asm.stp(
nullReg,
nullReg,
WritebackRegOffsetAddress(fieldReg, 2 * wordSize, isPostIndexed: true),
);
// There is at least two word (kAllocationRedZoneSize) gap at the end of page
// which makes it possible to initialize objects by two words at once and
// write slightly beyond the end.
_asm.cmp(fieldReg, newTopReg);
_asm.b(loop, Condition.unsignedLess);
}
_asm.addImmediate(resultReg, resultReg, heapObjectTag);
if (typeArgsField != null) {
if (instr.hasTypeArguments) {
_asm.str(
typeArgumentsReg,
_asm.fieldAddress(
resultReg,
objectLayout.getFieldOffset(typeArgsField),
),
);
} else {
final typeArgs = getInstantiatorTypeArguments(cls, []);
if (typeArgs != null) {
_asm.loadConstant(
typeArgumentsReg,
ConstantValue(TypeArgumentsConstant(typeArgs)),
);
_asm.str(
typeArgumentsReg,
_asm.fieldAddress(
resultReg,
objectLayout.getFieldOffset(typeArgsField),
),
);
}
}
}
// TODO: allocation profile; allocation probe points.
_asm.bind(done);
}
@override
@@ -395,11 +482,32 @@ final class Arm64CodeGenerator extends CodeGenerator {
@override
void generateMove(Location from, Location to) {
if (from is Register && to is Register) {
_asm.mov(to, from);
return;
switch (from) {
case Register():
switch (to) {
case Register():
_asm.mov(to, from);
return;
case StackLocation():
_asm.str(from, _asm.address(FP, to.frameOffset));
return;
default:
break;
}
case StackLocation():
switch (to) {
case Register():
_asm.ldr(to, _asm.address(FP, from.frameOffset));
return;
default:
break;
}
default:
break;
}
_asm.unimplemented('Unimplemented: code generation for generateMove');
_asm.unimplemented(
'Unimplemented: code generation for generateMove ${from.runtimeType} -> ${to.runtimeType}',
);
}
@override
@@ -445,3 +553,7 @@ extension on ComparisonOpcode {
ComparisonOpcode.doubleGreaterOrEqual => Condition.greaterOrEqual,
};
}
extension on StackLocation {
int get frameOffset => -(2 + index) * wordSize;
}
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:native_compiler/back_end/arm64/assembler.dart';
import 'package:native_compiler/back_end/arm64/stub_code_generator.dart';
import 'package:native_compiler/back_end/constraints.dart';
import 'package:native_compiler/back_end/locations.dart';
import 'package:cfg/ir/instructions.dart';
@@ -190,9 +191,16 @@ final class Arm64Constraints extends Constraints {
@override
InstructionConstraints? visitAllocateObject(AllocateObject instr) =>
InstructionConstraints(anyCpuRegister, [
if (instr.inputCount == 1) anyCpuRegister,
]);
InstructionConstraints(
AllocationStub.resultReg,
[if (instr.hasTypeArguments) AllocationStub.typeArgumentsReg],
[
if (!instr.hasTypeArguments) AllocationStub.typeArgumentsReg,
AllocationStub.tagsReg,
AllocationStub.scratch1Reg,
AllocationStub.scratch2Reg,
],
);
@override
InstructionConstraints? visitAllocateClosure(AllocateClosure instr) =>
@@ -0,0 +1,95 @@
// Copyright (c) 2026 the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:cfg/ir/constant_value.dart';
import 'package:kernel/ast.dart' as ast show Class;
import 'package:native_compiler/back_end/arm64/assembler.dart';
import 'package:native_compiler/back_end/assembler.dart';
import 'package:native_compiler/back_end/locations.dart';
import 'package:native_compiler/back_end/stub_code_generator.dart';
import 'package:native_compiler/runtime/type_utils.dart';
import 'package:native_compiler/runtime/vm_defs.dart';
abstract base class Arm64StubCodeGenerator implements StubCodeGenerator {
final Arm64Assembler _asm;
Arm64StubCodeGenerator(VMOffsets vmOffsets)
: _asm = Arm64Assembler(vmOffsets);
void _generate();
void enterStubFrame() {
_asm.enterDartFrame();
}
void leaveStubFrame() {
_asm.leaveDartFrame();
}
@override
Assembler generate() {
_generate();
return _asm;
}
}
final class AllocationStub extends Arm64StubCodeGenerator {
static const Register resultReg = R0;
static const Register typeArgumentsReg = R1;
static const Register tagsReg = R2;
static const Register scratch1Reg = R3;
static const Register scratch2Reg = R4;
final ast.Class cls;
AllocationStub(super.vmOffsets, this.cls);
@override
void _generate() {
enterStubFrame();
if (cls.typeParameters.isEmpty) {
final typeArgs = hasInstantiatorTypeArguments(cls)
? getInstantiatorTypeArguments(cls, [])
: null;
if (typeArgs == null) {
_asm.mov(typeArgumentsReg, nullReg);
} else {
_asm.loadConstant(
typeArgumentsReg,
ConstantValue(TypeArgumentsConstant(typeArgs)),
);
}
}
_generateRuntimeCall();
leaveStubFrame();
_asm.ret();
}
void _generateRuntimeCall() {
_asm.loadFromPool(scratch1Reg, cls);
// Space for result.
_asm.push(nullReg);
// Class and type arguments.
_asm.pushPair(typeArgumentsReg, scratch1Reg);
_asm.callRuntime(RuntimeEntry.AllocateObject, 2);
_asm.ldr(resultReg, _asm.address(stackPointerReg, 2 * wordSize));
// TODO: EnsureIsNewOrRemembered after write barrier elimination is implemented.
}
}
final class Arm64StubFactory extends StubFactory {
final VMOffsets vmOffsets;
Arm64StubFactory(this.vmOffsets, super.consumeGeneratedCode);
@override
StubCodeGenerator allocationStubGenerator(ast.Class cls) =>
AllocationStub(vmOffsets, cls);
}
@@ -4,6 +4,7 @@
import 'dart:typed_data';
import 'package:native_compiler/back_end/code.dart';
import 'package:native_compiler/back_end/locations.dart';
import 'package:native_compiler/back_end/object_pool.dart';
import 'package:native_compiler/runtime/vm_defs.dart';
@@ -132,6 +133,9 @@ abstract base class Assembler {
Address fieldAddress(Register obj, int offset) =>
address(obj, offset - heapObjectTag);
void enterDartFrame();
void leaveDartFrame();
// Push and pop values using Dart stackPointerReg.
void push(Register reg);
void pop(Register reg);
@@ -149,7 +153,25 @@ abstract base class Assembler {
/// Load arbitrary integer [value] into register.
void loadImmediate(Register reg, int value);
/// [dst] = [src] + arbitrary integer [value].
void addImmediate(
Register dst,
Register src,
int value, [
OperandSize sz = OperandSize.s64,
]);
/// [dst] = bitwise and ([src], arbitrary integer [value]).
void andImmediate(
Register dst,
Register src,
int value, [
OperandSize sz = OperandSize.s64,
]);
void callRuntime(RuntimeEntry entry, int argumentCount);
void callLeafRuntime(LeafRuntimeEntry entry);
void callStub(Code stub);
void unimplemented(String message);
}
@@ -3,15 +3,24 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:cfg/ir/instructions.dart';
import 'package:native_compiler/back_end/code_generator.dart';
import 'package:native_compiler/back_end/code.dart';
import 'package:native_compiler/back_end/locations.dart';
import 'package:native_compiler/back_end/stub_code_generator.dart';
import 'package:native_compiler/runtime/object_layout.dart';
import 'package:native_compiler/runtime/vm_defs.dart';
/// Hold back-end state shared between code generation
/// and register allocation.
class BackEndState {
/// Runtime offsets and constants.
late final VMOffsets vmOffsets;
/// Layout of Dart objects.
late final ObjectLayout objectLayout;
/// Reusable stubs.
late final StubFactory stubFactory;
/// Block order for the code generation.
late final List<Block> codeGenBlockOrder;
@@ -0,0 +1,23 @@
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:typed_data';
import 'package:cfg/ir/functions.dart';
import 'package:native_compiler/back_end/object_pool.dart';
/// Generated code for a function or a stub.
class Code {
final CFunction? function;
final Uint8List instructions;
final ObjectPool objectPool;
/// Offset of instructions in the resulting image.
int? instructionsImageOffset;
Code(this.function, this.instructions, this.objectPool);
}
/// Comsumer of the generated code.
typedef CodeConsumer = void Function(Code);
@@ -5,29 +5,15 @@
import 'dart:typed_data';
import 'package:cfg/ir/constant_value.dart';
import 'package:cfg/ir/functions.dart';
import 'package:cfg/ir/instructions.dart';
import 'package:cfg/ir/visitor.dart';
import 'package:cfg/passes/pass.dart';
import 'package:native_compiler/back_end/assembler.dart';
import 'package:native_compiler/back_end/back_end_state.dart';
import 'package:native_compiler/back_end/code.dart';
import 'package:native_compiler/back_end/locations.dart';
import 'package:native_compiler/back_end/object_pool.dart';
/// Generated code for a function.
class Code {
final CFunction function;
final Uint8List instructions;
final ObjectPool objectPool;
/// Offset of instructions in the resulting image.
int? instructionsImageOffset;
Code(this.function, this.instructions, this.objectPool);
}
/// Comsumer of the generated code.
typedef CodeConsumer = void Function(Code);
import 'package:native_compiler/runtime/object_layout.dart';
import 'package:native_compiler/runtime/vm_defs.dart';
/// Base class for architecture-specific code generator.
///
@@ -53,8 +39,13 @@ abstract base class CodeGenerator extends Pass
(i) => Label(),
);
/// Slow paths generated after all blocks.
final List<SlowPath> _slowPaths = [];
CodeGenerator(this.backEndState) : super('CodeGen');
VMOffsets get vmOffsets => backEndState.vmOffsets;
ObjectLayout get objectLayout => backEndState.objectLayout;
List<Block> get codeGenBlockOrder => backEndState.codeGenBlockOrder;
Location loc(OperandId operandId) =>
@@ -108,6 +99,11 @@ abstract base class CodeGenerator extends Pass
}
_currentBlockIndex = -1;
for (final slowPath in _slowPaths) {
_asm.bind(slowPath.entry);
slowPath.generator();
}
backEndState.consumeGeneratedCode(
Code(graph.function, _asm.bytes, _asm.objectPool),
);
@@ -164,6 +160,12 @@ abstract base class CodeGenerator extends Pass
return firstNonEmpty;
}
Label addSlowPath(void Function() generator) {
final entry = Label();
_slowPaths.add(SlowPath(entry, generator));
return entry;
}
@override
void visitEntryBlock(EntryBlock instr) {}
@@ -202,24 +204,33 @@ abstract base class CodeGenerator extends Pass
// TODO: merge subsequent ParallelMove instructions.
final map = <Location, Location>{};
for (final move in instr.moves) {
if (move is Move && move.from != move.to) {
assert(!map.containsKey(move.from));
map[move.from] = move.to;
if (move is Move) {
final from = move.from.physicalLocation;
final to = move.to.physicalLocation;
if (from != to) {
assert(!map.containsKey(from));
map[from] = to;
}
}
}
for (final move in instr.moves) {
if (move is Move && map.containsKey(move.from)) {
if (map.containsKey(move.to)) {
_generateDependentMoves(move.from, move.to, map);
} else {
generateMove(move.from, move.to);
map.remove(move.from);
if (move is Move) {
final from = move.from.physicalLocation;
final to = move.to.physicalLocation;
if (map.containsKey(from)) {
if (map.containsKey(to)) {
_generateDependentMoves(from, to, map);
} else {
generateMove(from, to);
map.remove(from);
}
}
}
}
for (final move in instr.moves) {
if (move is LoadConstant) {
generateLoadConstant(move.value, move.to);
generateLoadConstant(move.value, move.to.physicalLocation);
}
}
}
@@ -280,3 +291,9 @@ abstract base class CodeGenerator extends Pass
void visitStringInterpolation(StringInterpolation instr) =>
throw 'Unexpected StringInterpolation (should be lowered)';
}
class SlowPath {
final Label entry;
final void Function() generator;
SlowPath(this.entry, this.generator);
}
@@ -2,9 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart' as ast;
/// Helper class for building object pool accessible from generated code.
///
/// TODO: add tags, different kinds of entries.
class ObjectPool {
final List<Object> entries = [];
final Map<Object, int> _objects = {};
@@ -17,3 +17,20 @@ class ObjectPool {
return index;
}
}
/// Base class for specialized object pool entries which are not just
/// object references.
sealed class SpecializedEntry {}
/// Object pool entry representing tags for the new objects of the given class.
final class NewObjectTags extends SpecializedEntry {
final ast.Class cls;
NewObjectTags(this.cls);
@override
int get hashCode => cls.hashCode + 19;
@override
bool operator ==(Object other) =>
other is NewObjectTags && this.cls == other.cls;
}
@@ -42,7 +42,7 @@ final class LinearScanRegisterAllocator extends RegisterAllocator {
// which can be inserted later between instructions.
static const int step = 2;
static const bool trace = false;
static const bool trace = const bool.fromEnvironment('trace.regalloc');
static const int maxPosition = 0x7fffffff;
@@ -818,7 +818,7 @@ final class LinearScanRegisterAllocator extends RegisterAllocator {
if (liveRange.allocatedLocation is! StackLocation) {
_insertMoveBefore(
_nextInstruction(instr),
ParallelMoveStage.split,
ParallelMoveStage.spill,
liveRange.allocatedLocation!,
spillSlot,
);
@@ -0,0 +1,34 @@
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart' as ast show Class;
import 'package:native_compiler/back_end/assembler.dart';
import 'package:native_compiler/back_end/code.dart';
/// Interface class for architecture-specific stub code generator.
abstract interface class StubCodeGenerator {
Assembler generate();
}
/// Base class for architecture-specific stub factory.
///
/// Generates and caches stubs on demand.
abstract base class StubFactory {
final CodeConsumer consumeGeneratedCode;
Map<ast.Class, Code> _allocationStubs = {};
StubFactory(this.consumeGeneratedCode);
StubCodeGenerator allocationStubGenerator(ast.Class cls);
Code _generateCode(StubCodeGenerator generator) {
final asm = generator.generate();
final code = Code(null, asm.bytes, asm.objectPool);
consumeGeneratedCode(code);
return code;
}
Code getAllocationStub(ast.Class cls) =>
_allocationStubs[cls] ??= _generateCode(allocationStubGenerator(cls));
}
+7 -2
View File
@@ -7,7 +7,8 @@ import 'package:cfg/front_end/recognized_methods.dart';
import 'package:cfg/ir/flow_graph.dart';
import 'package:cfg/ir/functions.dart';
import 'package:kernel/ast.dart' as ast;
import 'package:native_compiler/back_end/code_generator.dart';
import 'package:native_compiler/back_end/code.dart';
import 'package:native_compiler/back_end/stub_code_generator.dart';
import 'package:native_compiler/configuration.dart';
import 'package:native_compiler/snapshot/image_writer.dart';
import 'package:native_compiler/snapshot/snapshot.dart';
@@ -21,10 +22,12 @@ class CompilationSet {
final List<CFunction> _pendingFunctions = [];
final ImageWriter _imageWriter;
late final SnapshotSerializer _snapshot;
late final StubFactory _stubFactory;
CompilationSet(this.libraries, this.config)
: _imageWriter = config.createImageWriter() {
_snapshot = SnapshotSerializer(config.targetCPU, functionRegistry);
_stubFactory = config.createStubFactory(_consumeGeneratedCode);
}
/// Add [function] to be compiled.
@@ -111,7 +114,9 @@ class CompilationSet {
rethrow;
}
config.createPipeline(functionRegistry, _consumeGeneratedCode).run(graph);
config
.createPipeline(functionRegistry, _stubFactory, _consumeGeneratedCode)
.run(graph);
}
void _consumeGeneratedCode(Code code) {
+29 -2
View File
@@ -11,13 +11,17 @@ import 'package:cfg/passes/simplification.dart';
import 'package:cfg/passes/value_numbering.dart';
import 'package:native_compiler/back_end/arm64/code_generator.dart';
import 'package:native_compiler/back_end/arm64/constraints.dart';
import 'package:native_compiler/back_end/arm64/stub_code_generator.dart';
import 'package:native_compiler/back_end/back_end_state.dart';
import 'package:native_compiler/back_end/code.dart';
import 'package:native_compiler/back_end/code_generator.dart';
import 'package:native_compiler/back_end/constraints.dart';
import 'package:native_compiler/back_end/regalloc_checker.dart';
import 'package:native_compiler/back_end/register_allocator.dart';
import 'package:native_compiler/back_end/stub_code_generator.dart';
import 'package:native_compiler/passes/lowering.dart';
import 'package:native_compiler/passes/reorder_blocks.dart';
import 'package:native_compiler/runtime/object_layout.dart';
import 'package:native_compiler/runtime/vm_defs.dart';
import 'package:native_compiler/snapshot/image_writer.dart';
import 'package:native_compiler/snapshot/macho/macho_image_writer.dart';
@@ -51,8 +55,13 @@ abstract base class Configuration {
required this.outputLibraryName,
});
VMOffsets get vmOffsets;
ObjectLayout get objectLayout;
Pipeline createPipeline(
FunctionRegistry functionRegistry,
StubFactory stubFactory,
CodeConsumer consumeGeneratedCode,
);
@@ -65,6 +74,11 @@ abstract base class Configuration {
TargetCPU.arm64 => Arm64CodeGenerator(backEndState),
};
StubFactory createStubFactory(CodeConsumer consumeGeneratedCode) =>
switch (targetCPU) {
TargetCPU.arm64 => Arm64StubFactory(vmOffsets, consumeGeneratedCode),
};
ImageWriter createImageWriter() => switch (imageFormat) {
ImageFormat.macho => MachoImageWriter(targetCPU, outputLibraryName),
};
@@ -78,17 +92,30 @@ final class DevelopmentCompilerConfiguration extends Configuration {
required super.outputLibraryName,
});
VMOffsets createVMOffsets() => switch (targetCPU) {
@override
late final VMOffsets vmOffsets = switch (targetCPU) {
TargetCPU.arm64 => Arm64VMOffsets(),
};
@override
late final ObjectLayout objectLayout = switch (targetCPU) {
TargetCPU.arm64 => ObjectLayout(
vmOffsets,
wordSize: 8,
compressedWordSize: 8,
),
};
@override
Pipeline createPipeline(
FunctionRegistry functionRegistry,
StubFactory stubFactory,
CodeConsumer consumeGeneratedCode,
) {
final backEndState = BackEndState();
backEndState.vmOffsets = createVMOffsets();
backEndState.vmOffsets = vmOffsets;
backEndState.objectLayout = objectLayout;
backEndState.stubFactory = stubFactory;
backEndState.consumeGeneratedCode = consumeGeneratedCode;
final constraints = createConstraints();
return Pipeline([
@@ -0,0 +1,159 @@
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:cfg/ir/field.dart';
import 'package:cfg/ir/global_context.dart';
import 'package:cfg/utils/misc.dart';
import 'package:kernel/ast.dart' as ast;
import 'package:native_compiler/runtime/vm_defs.dart';
/// Computes layout of Dart objects (field offsets and instance size).
class ObjectLayout {
final VMOffsets vmOffsets;
final int wordSize;
final int compressedWordSize;
/// Instance size before rounding.
final Map<ast.Class, int> _instanceSize = {};
/// Name of the implicit type arguments field.
late final ast.Name _typeArgumentsFieldName = ast.Name('#typeArguments');
/// Implicit type arguments field for a class.
final Map<ast.Class, CField> _typeArgumentsField = {};
/// Field offsets.
final Map<CField, int> _fieldOffset = {};
ObjectLayout(
this.vmOffsets, {
required this.wordSize,
required this.compressedWordSize,
});
int getInstanceSize(ast.Class cls) {
_ensureComputed(cls);
return roundUp(_instanceSize[cls]!, objectAlignment(wordSize));
}
int getFieldOffset(CField field) {
assert(!field.isStatic);
_ensureComputed(field.enclosingClass);
return _fieldOffset[field]!;
}
bool isUnboxedField(CField field) {
// TODO: support unboxed fields.
return false;
}
CField? getTypeArgumentsField(ast.Class cls) {
_ensureComputed(cls);
return _typeArgumentsField[cls];
}
bool _isComputed(ast.Class cls) => _instanceSize.containsKey(cls);
void _ensureComputed(ast.Class cls) {
if (!_isComputed(cls)) {
_computeLayout(cls);
}
}
void _computeLayout(ast.Class cls) {
if (_computeLayoutOfBuiltInClass(cls)) {
return;
}
final superclass = cls.superclass;
if (superclass != null) {
_ensureComputed(superclass);
}
int nextOffset = _instanceSize[superclass]!;
final superTypeArgs = superclass != null
? _typeArgumentsField[superclass]
: null;
if (superTypeArgs != null) {
// Inherit type arguments field from generic superclass.
_typeArgumentsField[cls] = superTypeArgs;
} else if (cls.typeParameters.isNotEmpty) {
// This class is generic but superclass is not, so
// introduce a new implicit type arguments field.
final typeArgs = CField(
ast.Field.immutable(
_typeArgumentsFieldName,
isFinal: true,
isStatic: false,
fileUri: ast.dummyUri,
)..parent = cls,
);
_typeArgumentsField[cls] = typeArgs;
_fieldOffset[typeArgs] = nextOffset;
nextOffset += compressedWordSize;
}
for (final field in cls.fields) {
if (!field.isStatic) {
_fieldOffset[CField(field)] = nextOffset;
nextOffset += compressedWordSize;
}
}
_instanceSize[cls] = nextOffset;
}
late final Map<String, int> _dartCoreInstanceSize = {
'_Double': vmOffsets.Double_InstanceSize,
'_GrowableList': vmOffsets.GrowableObjectArray_InstanceSize,
'_Mint': vmOffsets.Mint_InstanceSize,
'_WeakProperty': vmOffsets.WeakProperty_InstanceSize,
'_WeakReference': vmOffsets.WeakReference_InstanceSize,
'Object': vmOffsets.Instance_InstanceSize,
};
late final Map<String, int> _dartTypedDataInstanceSize = {
'_Int32x4': vmOffsets.Int32x4_InstanceSize,
'_Float32x4': vmOffsets.Float32x4_InstanceSize,
'_Float64x2': vmOffsets.Float64x2_InstanceSize,
// TODO: add other built-in classes from dart:typed_data
};
late final Map<String, int> _dartCompactHashInstanceSize = {
'_HashVMBase': vmOffsets.LinkedHashBase_InstanceSize,
};
late final ast.Library _typedDataLibrary = GlobalContext
.instance
.coreTypes
.index
.getLibrary('dart:typed_data');
late final ast.Library _compactHashLibrary = GlobalContext
.instance
.coreTypes
.index
.getLibrary('dart:_compact_hash');
bool _computeLayoutOfBuiltInClass(ast.Class cls) {
final library = cls.enclosingLibrary;
if (!library.importUri.isScheme('dart')) {
return false;
}
int? size;
if (library == GlobalContext.instance.coreTypes.coreLibrary) {
size = _dartCoreInstanceSize[cls.name];
} else if (library == _typedDataLibrary) {
size = _dartTypedDataInstanceSize[cls.name];
} else if (library == _compactHashLibrary) {
size = _dartCompactHashInstanceSize[cls.name];
}
// TODO: add built-in classes from dart:ffi
if (size != null) {
_instanceSize[cls] = size;
return true;
}
return false;
}
}
@@ -107,6 +107,7 @@ base class VMOffsets {
int get ICData_entries_offset => throw 'Unknown';
int get ICData_owner_offset => throw 'Unknown';
int get ICData_state_bits_offset => throw 'Unknown';
int get Instance_first_field_offset => throw 'Unknown';
int get Int32x4_value_offset => throw 'Unknown';
int get Isolate_finalizers_offset => throw 'Unknown';
int get Isolate_has_resumption_breakpoints_offset => throw 'Unknown';
@@ -130,6 +131,7 @@ base class VMOffsets {
int get NativeArguments_argv_offset => throw 'Unknown';
int get NativeArguments_retval_offset => throw 'Unknown';
int get NativeArguments_thread_offset => throw 'Unknown';
int get Object_tags_offset => throw 'Unknown';
int get ObjectStore_double_type_offset => throw 'Unknown';
int get ObjectStore_int_type_offset => throw 'Unknown';
int get ObjectStore_record_field_names_offset => throw 'Unknown';
@@ -752,6 +754,8 @@ final class Arm64VMOffsets extends VMOffsets {
@override
int get ICData_state_bits_offset => 0x34;
@override
int get Instance_first_field_offset => 0x8;
@override
int get Int32x4_value_offset => 0x8;
@override
int get Isolate_finalizers_offset => 0x18;
@@ -798,6 +802,8 @@ final class Arm64VMOffsets extends VMOffsets {
@override
int get NativeArguments_thread_offset => 0x0;
@override
int get Object_tags_offset => 0x0;
@override
int get ObjectStore_double_type_offset => 0x1b0;
@override
int get ObjectStore_int_type_offset => 0x160;
@@ -1661,6 +1667,8 @@ final class Arm64ProductVMOffsets extends VMOffsets {
@override
int get ICData_state_bits_offset => 0x34;
@override
int get Instance_first_field_offset => 0x8;
@override
int get Int32x4_value_offset => 0x8;
@override
int get Isolate_finalizers_offset => 0x18;
@@ -1705,6 +1713,8 @@ final class Arm64ProductVMOffsets extends VMOffsets {
@override
int get NativeArguments_thread_offset => 0x0;
@override
int get Object_tags_offset => 0x0;
@override
int get ObjectStore_double_type_offset => 0x1b0;
@override
int get ObjectStore_int_type_offset => 0x160;
+25 -3
View File
@@ -8,7 +8,7 @@ import 'dart:typed_data';
import 'package:cfg/ir/constant_value.dart';
import 'package:cfg/ir/global_context.dart';
import 'package:kernel/ast.dart' as ast;
import 'package:native_compiler/back_end/code_generator.dart' show Code;
import 'package:native_compiler/back_end/code.dart';
import 'package:native_compiler/back_end/object_pool.dart';
import 'package:native_compiler/configuration.dart';
import 'package:cfg/ir/functions.dart';
@@ -81,6 +81,12 @@ enum FunctionKind {
fieldInitializer,
}
/// Object pool entry kinds in the module snapshots.
///
/// This enum should match ModuleSnapshot::ObjectPoolEntryKind
/// enum declared in runtime/vm/module_snapshot.cc.
enum ObjectPoolEntryKind { objectRef, newObjectTags }
abstract base class SerializationCluster {
/// Add [object] to the cluster and push its outgoing references.
void trace(SnapshotSerializer serializer, Object object);
@@ -717,7 +723,14 @@ final class ObjectPoolSerializationCluster extends SerializationCluster {
final pool = object as ObjectPool;
_objects.add(pool);
for (final entry in pool.entries) {
serializer.push(entry);
if (entry is SpecializedEntry) {
switch (entry) {
case NewObjectTags():
serializer.push(entry.cls);
}
} else {
serializer.push(entry);
}
}
}
@@ -740,7 +753,16 @@ final class ObjectPoolSerializationCluster extends SerializationCluster {
for (final pool in _objects) {
serializer.writeUint(pool.entries.length);
for (final entry in pool.entries) {
serializer.writeRefId(entry);
if (entry is SpecializedEntry) {
switch (entry) {
case NewObjectTags():
serializer.writeUint(ObjectPoolEntryKind.newObjectTags.index);
serializer.writeRefId(entry.cls);
}
} else {
serializer.writeUint(ObjectPoolEntryKind.objectRef.index);
serializer.writeRefId(entry);
}
}
}
}
@@ -7,6 +7,8 @@ import 'dart:typed_data';
import 'package:cfg/ir/constant_value.dart';
import 'package:native_compiler/back_end/arm64/assembler.dart';
import 'package:native_compiler/back_end/assembler.dart';
import 'package:native_compiler/back_end/code.dart';
import 'package:native_compiler/back_end/object_pool.dart';
import 'package:native_compiler/runtime/vm_defs.dart';
import 'package:test/test.dart';
import 'disassembler.dart' show Disassembler;
@@ -69,6 +71,47 @@ void main() {
'str r1, [r0, #32760]\n',
);
});
test('pairAddress', () {
asm.ldp(R1, R2, asm.pairAddress(R0, -0x200));
asm.stp(R1, R2, asm.pairAddress(R0, 0x1f8));
// TODO: support large and unaligned offsets
expectThrows(() {
asm.pairAddress(R0, 3);
});
expectThrows(() {
asm.pairAddress(R0, -1);
});
expectThrows(() {
asm.pairAddress(R0, -0x208);
});
expectThrows(() {
asm.pairAddress(R0, 0x200);
});
expectDisassembly(
'ldp r1, r2, [r0, #-512]\n'
'stp r1, r2, [r0, #504]\n',
);
});
test('enterDartFrame', () {
asm.enterDartFrame();
expectDisassembly(
'stp fp, lr, [sp, #-16]!\n'
'mov fp, sp\n'
'add pp, pp, #0x1\n'
'stp pp, code, [sp, #-16]!\n'
'ldr pp, [code, #${vmOffsets.Code_object_pool_offset - heapObjectTag}]\n'
'sub pp, pp, #0x1\n',
);
});
test('leaveDartFrame', () {
asm.leaveDartFrame();
expectDisassembly(
'ldr pp, [fp, #-16]\n'
'sub pp, pp, #0x1\n'
'mov sp, fp\n'
'ldp fp, lr, [sp], #16 !\n',
);
});
test('push', () {
asm.push(R0);
asm.push(ZR);
@@ -196,6 +239,55 @@ void main() {
'mov r5, 0xff00ff00ff00ff00\n',
);
});
test('addImmediate', () {
asm.addImmediate(R0, R0, 0);
asm.addImmediate(R1, R2, 0);
asm.addImmediate(R1, R2, 0, .s32);
asm.addImmediate(R1, R2, 0xabc);
asm.addImmediate(R1, R2, -0xabc);
asm.addImmediate(R1, R2, 0xabc000);
asm.addImmediate(R1, R2, -0xabc000);
asm.addImmediate(R1, R2, 0x11223344_55667788);
asm.addImmediate(SP, FP, 0x11223344_55667788);
expectDisassembly(
'mov r1, r2\n'
'movw r1, r2\n'
'add r1, r2, #0xabc\n'
'sub r1, r2, #0xabc\n'
'add r1, r2, #0xabc000\n'
'sub r1, r2, #0xabc000\n'
'movz tmp, #0x7788\n'
'movk tmp, #0x5566 lsl 16\n'
'movk tmp, #0x3344 lsl 32\n'
'movk tmp, #0x1122 lsl 48\n'
'add r1, r2, tmp\n'
'movz tmp, #0x7788\n'
'movk tmp, #0x5566 lsl 16\n'
'movk tmp, #0x3344 lsl 32\n'
'movk tmp, #0x1122 lsl 48\n'
'add csp, fp, tmp uxtx 0\n',
);
});
test('andImmediate', () {
asm.andImmediate(R1, R2, 0);
asm.andImmediate(R1, R2, 0, .u32);
asm.andImmediate(R1, R2, -1);
asm.andImmediate(R1, R2, -1, .u32);
asm.andImmediate(R1, R2, 0xff);
asm.andImmediate(R1, R2, 0x11223344_55667788);
expectDisassembly(
'movz r1, #0x0\n'
'movz r1, #0x0\n'
'mov r1, r2\n'
'movw r1, r2\n'
'and r1, r2, 0xff\n'
'movz tmp, #0x7788\n'
'movk tmp, #0x5566 lsl 16\n'
'movk tmp, #0x3344 lsl 32\n'
'movk tmp, #0x1122 lsl 48\n'
'and r1, r2, tmp\n',
);
});
test('callRuntime', () {
asm.callRuntime(RuntimeEntry.AllocateObject, 2);
expectDisassembly(
@@ -205,6 +297,15 @@ void main() {
'blr lr\n',
);
});
test('callStub', () {
final stub = Code(null, Uint8List(0), ObjectPool());
asm.callStub(stub);
expectDisassembly(
'ldr code, [pp, #${objectPoolBase}]\n'
'ldr lr, [code, #${vmOffsets.Code_entry_point_offset.first - heapObjectTag}]\n'
'blr lr\n',
);
});
});
group('instruction', () {
@@ -1606,14 +1606,14 @@ class ARM64Decoder {
void decodeAddSubShiftExt(Instr instr) {
switch (instr.bit(30)) {
case 0:
if (instr.rdField() == R31) {
if ((instr.rdField() == R31) && (instr.sField() == 1)) {
format(instr, "cmn'sf 'rn, 'shift_op");
} else {
format(instr, "add'sf's 'rd, 'rn, 'shift_op");
}
break;
case 1:
if (instr.rdField() == R31) {
if ((instr.rdField() == R31) && (instr.sField() == 1)) {
format(instr, "cmp'sf 'rn, 'shift_op");
} else {
if (instr.rnField() == R31) {
@@ -16,7 +16,7 @@ B0 = EntryBlock() dominates:(B9, B11, B8)
v1 = Parameter(a) # RA: R0 <- ()
v2 = Parameter(b) # RA: R1 <- ()
v7 = Comparison int & == 0(v1, v2) # RA: R0 <- (R0, R1)
ParallelMove split(R0 -> stack[0])
ParallelMove spill(R0 -> stack[0])
Branch(v7, true: B8, false: B9) # RA: (R0)
B8 = TargetBlock() idom:B0
DirectCall print(v13) # RA: R0 <- (-) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
@@ -42,7 +42,7 @@ B0 = EntryBlock() dominates:(B11, B13, B10)
v1 = Parameter(a) # RA: R0 <- ()
v2 = Parameter(b) # RA: R1 <- ()
v7 = Comparison int & == 0(v1, v2) # RA: R0 <- (R0, R1)
ParallelMove split(R0 -> stack[0])
ParallelMove spill(R0 -> stack[0])
Branch(v7, true: B10, false: B11) # RA: (R0)
B10 = TargetBlock() idom:B0
DirectCall print(v15) # RA: R0 <- (-) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
@@ -63,7 +63,7 @@ B0 = EntryBlock() dominates:(B8, B14, B16, B7)
v2 = Parameter(b) # RA: R1 <- ()
v3 = Parameter(c) # RA: R2 <- ()
v6 = Comparison int >(v1, v2) # RA: R0 <- (R0, R1)
ParallelMove split(R0 -> stack[0])
ParallelMove spill(R0 -> stack[0])
Branch(v6, true: B7, false: B8) # RA: (R0)
B7 = TargetBlock() idom:B0
Goto(B16)
@@ -149,15 +149,15 @@ B0 = EntryBlock()
v21 = Constant(9)
v36 = Constant(null)
v1 = Parameter(x) # RA: R0 <- ()
ParallelMove split(R0 -> stack[0])
ParallelMove spill(R0 -> stack[0])
v2 = TypeParameters() # RA: R1 <- ()
ParallelMove split(R1 -> stack[1])
ParallelMove spill(R1 -> stack[1])
v5 = DirectCall _GrowableList.(v3, v4) # RA: R0 <- (-, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
ParallelMove output(R0 -> vloc:R0)
DirectCall print(v5) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
ParallelMove split(stack[1] -> R1)
v7 = TypeArguments(v2, <listLiterals.T%>) # RA: R0 <- (R1)
ParallelMove split(R0 -> stack[2])
ParallelMove spill(R0 -> stack[2])
v8 = DirectCall _GrowableList.(v7, v4) # RA: R0 <- (R0, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
ParallelMove output(R0 -> vloc:R0)
DirectCall print(v8) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
@@ -231,21 +231,21 @@ B0 = EntryBlock()
v38 = Constant(2)
v40 = Constant(3)
v1 = Parameter(key) # RA: R0 <- ()
ParallelMove split(R0 -> stack[0])
ParallelMove spill(R0 -> stack[0])
v2 = Parameter(value) # RA: R1 <- ()
ParallelMove split(R1 -> stack[1])
ParallelMove spill(R1 -> stack[1])
v3 = Parameter(key2) # RA: R2 <- ()
ParallelMove split(R2 -> stack[2])
ParallelMove spill(R2 -> stack[2])
v4 = Parameter(value2) # RA: R3 <- ()
ParallelMove split(R3 -> stack[3])
ParallelMove spill(R3 -> stack[3])
v5 = TypeParameters() # RA: R4 <- ()
ParallelMove split(R4 -> stack[4])
ParallelMove spill(R4 -> stack[4])
v30 = DirectCall Map._fromLiteral(v6, v29) # RA: R0 <- (-, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
ParallelMove output(R0 -> vloc:R0)
DirectCall print(v30) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
ParallelMove split(stack[4] -> R1)
v9 = TypeArguments(v5, <mapLiterals.S%, mapLiterals.T%>) # RA: R0 <- (R1)
ParallelMove split(R0 -> stack[5])
ParallelMove spill(R0 -> stack[5])
v31 = DirectCall Map._fromLiteral(v9, v29) # RA: R0 <- (R0, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
ParallelMove output(R0 -> vloc:R0)
DirectCall print(v31) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
@@ -299,11 +299,11 @@ B0 = EntryBlock()
v28 = Constant(4)
v30 = Constant(5)
v1 = Parameter(x) # RA: R0 <- ()
ParallelMove split(R0 -> stack[0])
ParallelMove spill(R0 -> stack[0])
v2 = Parameter(s) # RA: R1 <- ()
ParallelMove split(R1 -> stack[1])
ParallelMove spill(R1 -> stack[1])
v3 = Parameter(o) # RA: R2 <- ()
ParallelMove split(R2 -> stack[2])
ParallelMove spill(R2 -> stack[2])
v17 = DirectCall _StringBase._interpolateSingle(v3) # RA: R0 <- (R2) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
ParallelMove output(R0 -> vloc:R0)
DirectCall print(v17) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
@@ -7,7 +7,7 @@ B0 = EntryBlock() dominates:(B5, B7, B4)
v24 = Constant(4)
v1 = Parameter(c1) # RA: R0 <- ()
v2 = Parameter(c2) # RA: R1 <- ()
ParallelMove split(R1 -> stack[0])
ParallelMove spill(R1 -> stack[0])
Branch(v1, true: B4, false: B5) # RA: (R0)
B4 = TargetBlock() idom:B0
DirectCall print(v9) # RA: R0 <- (-) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
@@ -64,7 +64,7 @@ B0 = EntryBlock() dominates:(B3)
Goto(B3)
B3 = JoinBlock(B0, B30) idom:B0 dominates:(B9, B8) loop-header (depth:1 body:(B3, B8, B12, B17, B30, B16, B24, B23) back-edges:(B30))
v44 = Phi(v1, v39) # RA: R0 <- (-, R0)
ParallelMove split(R0 -> stack[0])
ParallelMove spill(R0 -> stack[0])
CompareAndBranch int <(v44, v6, true: B8, false: B9) # RA: (R0, -)
B8 = TargetBlock() idom:B3 dominates:(B12) in-loop:B3
ParallelMove control(IntConstant(0) -> R1)
@@ -86,7 +86,7 @@ B17 = TargetBlock() idom:B12 in-loop:B3
B30 = JoinBlock(B17, B23) idom:B12 in-loop:B3
ParallelMove split(stack[0] -> R0)
v39 = BinaryIntOp +(v44, v33) # RA: R0 <- (R0, -)
ParallelMove split(R0 -> stack[0])
ParallelMove spill(R0 -> stack[0])
Goto(B3)
B9 = TargetBlock() idom:B3
ParallelMove input(NullConstant(null) -> R0)
-8
View File
@@ -370,10 +370,6 @@ uword MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size) {
dart::Object::ShouldHaveDeeplyImmutabilityBitSet(cid));
}
word Object::tags_offset() {
return 0;
}
const word UntaggedObject::kCardRememberedBit =
dart::UntaggedObject::CardRememberedBit::shift();
@@ -557,10 +553,6 @@ bool Class::TraceAllocation(const dart::Class& klass) {
return klass.TraceAllocation(dart::IsolateGroup::Current());
}
word Instance::first_field_offset() {
return TranslateOffsetInWords(dart::Instance::NextFieldOffset());
}
word Instance::native_fields_array_offset() {
return TranslateOffsetInWords(dart::Instance::NativeFieldsOffset());
}
@@ -205,6 +205,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x14;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x1c;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x4;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0xc;
static constexpr dart::compiler::target::word
@@ -245,6 +246,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0xc;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0xd8;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -927,6 +929,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word
@@ -968,6 +971,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -1651,6 +1655,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x14;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x1c;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x4;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0xc;
static constexpr dart::compiler::target::word
@@ -1691,6 +1696,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0xc;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0xd8;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -2372,6 +2378,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word
@@ -2413,6 +2420,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -3099,6 +3107,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word
@@ -3140,6 +3149,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -3823,6 +3833,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word
@@ -3864,6 +3875,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -4548,6 +4560,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x14;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x1c;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x4;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0xc;
static constexpr dart::compiler::target::word
@@ -4588,6 +4601,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0xc;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0xd8;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -5271,6 +5285,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word
@@ -5312,6 +5327,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -5991,6 +6007,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x14;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x1c;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x4;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0xc;
static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
@@ -6029,6 +6046,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0xc;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0xd8;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -6705,6 +6723,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
@@ -6744,6 +6763,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -7421,6 +7441,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x14;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x1c;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x4;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0xc;
static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
@@ -7459,6 +7480,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0xc;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0xd8;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -8134,6 +8156,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
@@ -8173,6 +8196,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -8853,6 +8877,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
@@ -8892,6 +8917,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -9569,6 +9595,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
@@ -9608,6 +9635,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -10286,6 +10314,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x14;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x1c;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x4;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0xc;
static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
@@ -10324,6 +10353,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0xc;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0xd8;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -11001,6 +11031,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0x0;
static constexpr dart::compiler::target::word ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word ICData_owner_offset = 0x28;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 0x34;
static constexpr dart::compiler::target::word Instance_first_field_offset = 0x8;
static constexpr dart::compiler::target::word Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word Isolate_finalizers_offset = 0x18;
static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
@@ -11040,6 +11071,7 @@ static constexpr dart::compiler::target::word NativeArguments_retval_offset =
0x18;
static constexpr dart::compiler::target::word NativeArguments_thread_offset =
0x0;
static constexpr dart::compiler::target::word Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
0x1b0;
static constexpr dart::compiler::target::word ObjectStore_int_type_offset =
@@ -11743,6 +11775,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x10;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x14;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x4;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0xc;
@@ -11786,6 +11820,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0xc;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0xd8;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -12544,6 +12579,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -12587,6 +12624,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -13352,6 +13390,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -13395,6 +13435,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -14156,6 +14197,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -14199,6 +14242,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -14960,6 +15004,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -15003,6 +15049,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -15766,6 +15813,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x10;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x14;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x4;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0xc;
@@ -15809,6 +15858,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0xc;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0xd8;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -16568,6 +16618,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -16611,6 +16663,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -17366,6 +17419,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x10;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x14;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x4;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0xc;
@@ -17407,6 +17462,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0xc;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0xd8;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -18158,6 +18214,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -18199,6 +18257,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -18957,6 +19016,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -18998,6 +19059,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -19752,6 +19814,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -19793,6 +19857,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -20547,6 +20612,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -20588,6 +20655,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -21344,6 +21412,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0xc;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x10;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x14;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x4;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0xc;
@@ -21385,6 +21455,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0xc;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0xd8;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -22137,6 +22208,8 @@ static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 0x18;
static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 0x20;
static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset =
0x28;
static constexpr dart::compiler::target::word AOT_Instance_first_field_offset =
0x8;
static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 0x8;
static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
0x18;
@@ -22178,6 +22251,7 @@ static constexpr dart::compiler::target::word
AOT_NativeArguments_retval_offset = 0x18;
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0x0;
static constexpr dart::compiler::target::word AOT_Object_tags_offset = 0x0;
static constexpr dart::compiler::target::word
AOT_ObjectStore_double_type_offset = 0x1b0;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
@@ -168,6 +168,7 @@
FIELD(ICData, entries_offset) \
FIELD(ICData, owner_offset) \
FIELD(ICData, state_bits_offset) \
FIELD(Instance, first_field_offset) \
FIELD(Int32x4, value_offset) \
FIELD(Isolate, finalizers_offset) \
NOT_IN_PRODUCT(FIELD(Isolate, has_resumption_breakpoints_offset)) \
@@ -191,6 +192,7 @@
FIELD(NativeArguments, argv_offset) \
FIELD(NativeArguments, retval_offset) \
FIELD(NativeArguments, thread_offset) \
FIELD(Object, tags_offset) \
FIELD(ObjectStore, double_type_offset) \
FIELD(ObjectStore, int_type_offset) \
FIELD(ObjectStore, record_field_names_offset) \
+43 -7
View File
@@ -82,6 +82,14 @@ class ModuleSnapshot : public AllStatic {
kImplicitSetter,
kFieldInitializer,
};
// Object pool entry kinds in the module snapshots.
// Should match ObjectPoolEntryKind enum
// declared in pkg/native_compiler/lib/snapshot/snapshot.dart.
enum ObjectPoolEntryKind {
kObjectRef,
kNewObjectTags,
};
};
class Deserializer;
@@ -714,7 +722,11 @@ class CodeDeserializationCluster : public DeserializationCluster {
}
#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
} else {
UNREACHABLE();
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
if (FLAG_disassemble_stubs) {
Disassembler::DisassembleStub("", code);
}
#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
}
#if !defined(PRODUCT)
@@ -744,10 +756,14 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster {
void ReadFill(Deserializer* d_) override {
Deserializer::Local d(d_);
const uint8_t entry_bits =
const uint8_t tagged_entry_bits =
ObjectPool::EncodeBits(ObjectPool::EntryType::kTaggedObject,
ObjectPool::Patchability::kPatchable,
ObjectPool::SnapshotBehavior::kSnapshotable);
ObjectPool::Patchability::kNotPatchable,
ObjectPool::SnapshotBehavior::kNotSnapshotable);
const uint8_t immediate_entry_bits =
ObjectPool::EncodeBits(ObjectPool::EntryType::kImmediate,
ObjectPool::Patchability::kNotPatchable,
ObjectPool::SnapshotBehavior::kNotSnapshotable);
for (intptr_t id = start_index_, n = stop_index_; id < n; id++) {
const intptr_t length = d.ReadUnsigned();
@@ -756,9 +772,26 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster {
ObjectPool::InstanceSize(length));
pool->untag()->length_ = length;
for (intptr_t j = 0; j < length; j++) {
pool->untag()->entry_bits()[j] = entry_bits;
UntaggedObjectPool::Entry& entry = pool->untag()->data()[j];
entry.raw_obj_ = d.ReadRef();
const auto kind =
static_cast<ModuleSnapshot::ObjectPoolEntryKind>(d.ReadUnsigned());
switch (kind) {
case ModuleSnapshot::kObjectRef: {
pool->untag()->entry_bits()[j] = tagged_entry_bits;
UntaggedObjectPool::Entry& entry = pool->untag()->data()[j];
entry.raw_obj_ = d.ReadRef();
break;
}
case ModuleSnapshot::kNewObjectTags: {
ClassPtr cls = static_cast<ClassPtr>(d.ReadRef());
pool->untag()->entry_bits()[j] = immediate_entry_bits;
UntaggedObjectPool::Entry& entry = pool->untag()->data()[j];
entry.raw_value_ = compiler::target::MakeTagWordForNewSpaceObject(
cls->untag()->id_,
Object::RoundedAllocationSize(Class::host_instance_size(cls) *
kCompressedWordSize));
break;
}
}
}
}
}
@@ -771,6 +804,9 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster {
pool ^= refs.At(id);
for (intptr_t i = 0, length = pool.Length(); i < length; ++i) {
if (pool.TypeAt(i) != ObjectPool::EntryType::kTaggedObject) {
continue;
}
obj = pool.ObjectAt(i);
if (obj.IsAbstractType() || obj.IsTypeArguments()) {
obj = Instance::Cast(obj).Canonicalize(d->thread());
+3
View File
@@ -1140,6 +1140,7 @@ class Object {
friend class OneByteString;
friend class TwoByteString;
friend class Thread;
friend class module_snapshot::ObjectPoolDeserializationCluster;
#define REUSABLE_FRIEND_DECLARATION(name) \
friend class Reusable##name##HandleScope;
@@ -8690,6 +8691,8 @@ class Instance : public Object {
static intptr_t NativeFieldsOffset() { return sizeof(UntaggedObject); }
static intptr_t first_field_offset() { return NextFieldOffset(); }
protected:
#ifndef PRODUCT
virtual void PrintSharedInstanceJSON(JSONObject* jsobj,
+1
View File
@@ -1325,6 +1325,7 @@ class UntaggedClass : public UntaggedObject {
friend class CidRewriteVisitor;
friend class FinalizeVMIsolateVisitor;
friend class Api;
friend class module_snapshot::ObjectPoolDeserializationCluster;
};
class UntaggedPatchClass : public UntaggedObject {