mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:43:18 +00:00
[vm/kernel/bytecode] Revise access to instance fields in bytecode
Constant pool: * Field constant pool entry is renamed to StaticField * FieldOffset constant pool entry is replaced with InstanceField. InstanceField occupies 2 slots for field offset and field object. * ContextOffset constant pool entry is removed. * TypeArgumentsFieldOffset is renamed to TypeArgumentsField Bytecodes: * LoadFieldTOS and StoreFieldTOS require InstanceField entry. * New bytecodes added: LoadContextParent, StoreContextParent, LoadContextVar, StoreContextVar, LoadTypeArgumentsField. This CL is a preparation for compilation of bytecodes related to instance field accesses. Change-Id: I1d6274e94bd7cd764e4fc83d9847daf4f21e5a25 Reviewed-on: https://dart-review.googlesource.com/68843 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Régis Crelier <regis@google.com>
This commit is contained in:
parent
af45552aa5
commit
85d85246ad
|
@ -776,6 +776,14 @@ class BytecodeAssembler {
|
|||
emitWord(_encodeD(Opcode.kStoreFieldTOS, rd));
|
||||
}
|
||||
|
||||
void emitStoreContextParent() {
|
||||
emitWord(_encode0(Opcode.kStoreContextParent));
|
||||
}
|
||||
|
||||
void emitStoreContextVar(int rd) {
|
||||
emitWord(_encodeD(Opcode.kStoreContextVar, rd));
|
||||
}
|
||||
|
||||
void emitLoadField(int ra, int rb, int rc) {
|
||||
emitWord(_encodeABC(Opcode.kLoadField, ra, rb, rc));
|
||||
}
|
||||
|
@ -792,6 +800,18 @@ class BytecodeAssembler {
|
|||
emitWord(_encodeD(Opcode.kLoadFieldTOS, rd));
|
||||
}
|
||||
|
||||
void emitLoadTypeArgumentsField(int rd) {
|
||||
emitWord(_encodeD(Opcode.kLoadTypeArgumentsField, rd));
|
||||
}
|
||||
|
||||
void emitLoadContextParent() {
|
||||
emitWord(_encode0(Opcode.kLoadContextParent));
|
||||
}
|
||||
|
||||
void emitLoadContextVar(int rd) {
|
||||
emitWord(_encodeD(Opcode.kLoadContextVar, rd));
|
||||
}
|
||||
|
||||
void emitBooleanNegateTOS() {
|
||||
emitWord(_encode0(Opcode.kBooleanNegateTOS));
|
||||
}
|
||||
|
|
|
@ -77,12 +77,13 @@ type ConstantStaticICData extends ConstantPoolEntry {
|
|||
ConstantIndex argDesc;
|
||||
}
|
||||
|
||||
type ConstantField extends ConstantPoolEntry {
|
||||
type ConstantStaticField extends ConstantPoolEntry {
|
||||
Byte tag = 9;
|
||||
CanonicalNameReference field;
|
||||
}
|
||||
|
||||
type ConstantFieldOffset extends ConstantPoolEntry {
|
||||
// Occupies 2 entries in the constant pool.
|
||||
type ConstantInstanceField extends ConstantPoolEntry {
|
||||
Byte tag = 10;
|
||||
CanonicalNameReference field;
|
||||
}
|
||||
|
@ -92,7 +93,7 @@ type ConstantClass extends ConstantPoolEntry {
|
|||
CanonicalNameReference class;
|
||||
}
|
||||
|
||||
type ConstantTypeArgumentsFieldOffset extends ConstantPoolEntry {
|
||||
type ConstantTypeArgumentsField extends ConstantPoolEntry {
|
||||
Byte tag = 12;
|
||||
CanonicalNameReference class;
|
||||
}
|
||||
|
@ -136,34 +137,27 @@ type ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
|
|||
List<DartType> types;
|
||||
}
|
||||
|
||||
type ConstantContextOffset extends ConstantPoolEntry {
|
||||
Byte tag = 20;
|
||||
// 0 = Offset of 'parent' field in Context object.
|
||||
// 1 + i = Offset of i-th variable in Context object.
|
||||
UInt index;
|
||||
}
|
||||
|
||||
type ConstantClosureFunction extends ConstantPoolEntry {
|
||||
Byte tag = 21;
|
||||
Byte tag = 20;
|
||||
StringReference name;
|
||||
FunctionNode function; // Doesn't have a body.
|
||||
}
|
||||
|
||||
type ConstantEndClosureFunctionScope extends ConstantPoolEntry {
|
||||
Byte tag = 22;
|
||||
Byte tag = 21;
|
||||
}
|
||||
|
||||
type ConstantNativeEntry extends ConstantPoolEntry {
|
||||
Byte tag = 23;
|
||||
Byte tag = 22;
|
||||
StringReference nativeName;
|
||||
}
|
||||
|
||||
type ConstantSubtypeTestCache extends ConstantPoolEntry {
|
||||
Byte tag = 24;
|
||||
Byte tag = 23;
|
||||
}
|
||||
|
||||
type ConstantPartialTearOffInstantiation extends ConstantPoolEntry {
|
||||
Byte tag = 25;
|
||||
Byte tag = 24;
|
||||
ConstantIndex tearOffConstant;
|
||||
ConstantIndex typeArguments;
|
||||
}
|
||||
|
@ -180,10 +174,10 @@ enum ConstantTag {
|
|||
kArgDesc,
|
||||
kICData,
|
||||
kStaticICData,
|
||||
kField,
|
||||
kFieldOffset,
|
||||
kStaticField,
|
||||
kInstanceField,
|
||||
kClass,
|
||||
kTypeArgumentsFieldOffset,
|
||||
kTypeArgumentsField,
|
||||
kTearOff,
|
||||
kType,
|
||||
kTypeArguments,
|
||||
|
@ -191,7 +185,6 @@ enum ConstantTag {
|
|||
kInstance,
|
||||
kSymbol,
|
||||
kTypeArgumentsForInstanceAllocation,
|
||||
kContextOffset,
|
||||
kClosureFunction,
|
||||
kEndClosureFunctionScope,
|
||||
kNativeEntry,
|
||||
|
@ -204,6 +197,10 @@ abstract class ConstantPoolEntry {
|
|||
|
||||
ConstantTag get tag;
|
||||
|
||||
// Returns number of extra reserved constant pool entries
|
||||
// following this entry.
|
||||
int get numReservedEntries => 0;
|
||||
|
||||
void writeToBinary(BinarySink sink) {
|
||||
sink.writeUInt30(tag.index);
|
||||
writeValueToBinary(sink);
|
||||
|
@ -232,14 +229,14 @@ abstract class ConstantPoolEntry {
|
|||
return new ConstantStaticICData.readFromBinary(source);
|
||||
case ConstantTag.kArgDesc:
|
||||
return new ConstantArgDesc.readFromBinary(source);
|
||||
case ConstantTag.kField:
|
||||
return new ConstantField.readFromBinary(source);
|
||||
case ConstantTag.kFieldOffset:
|
||||
return new ConstantFieldOffset.readFromBinary(source);
|
||||
case ConstantTag.kStaticField:
|
||||
return new ConstantStaticField.readFromBinary(source);
|
||||
case ConstantTag.kInstanceField:
|
||||
return new ConstantInstanceField.readFromBinary(source);
|
||||
case ConstantTag.kClass:
|
||||
return new ConstantClass.readFromBinary(source);
|
||||
case ConstantTag.kTypeArgumentsFieldOffset:
|
||||
return new ConstantTypeArgumentsFieldOffset.readFromBinary(source);
|
||||
case ConstantTag.kTypeArgumentsField:
|
||||
return new ConstantTypeArgumentsField.readFromBinary(source);
|
||||
case ConstantTag.kTearOff:
|
||||
return new ConstantTearOff.readFromBinary(source);
|
||||
case ConstantTag.kType:
|
||||
|
@ -255,8 +252,6 @@ abstract class ConstantPoolEntry {
|
|||
case ConstantTag.kTypeArgumentsForInstanceAllocation:
|
||||
return new ConstantTypeArgumentsForInstanceAllocation.readFromBinary(
|
||||
source);
|
||||
case ConstantTag.kContextOffset:
|
||||
return new ConstantContextOffset.readFromBinary(source);
|
||||
case ConstantTag.kClosureFunction:
|
||||
return new ConstantClosureFunction.readFromBinary(source);
|
||||
case ConstantTag.kEndClosureFunctionScope:
|
||||
|
@ -572,64 +567,65 @@ class ConstantStaticICData extends ConstantPoolEntry {
|
|||
bool operator ==(other) => identical(this, other);
|
||||
}
|
||||
|
||||
class ConstantField extends ConstantPoolEntry {
|
||||
class ConstantStaticField extends ConstantPoolEntry {
|
||||
final Reference _reference;
|
||||
|
||||
Field get field => _reference.asField;
|
||||
|
||||
ConstantField(Field field) : this.byReference(field.reference);
|
||||
ConstantField.byReference(this._reference);
|
||||
ConstantStaticField(Field field) : this.byReference(field.reference);
|
||||
ConstantStaticField.byReference(this._reference);
|
||||
|
||||
@override
|
||||
ConstantTag get tag => ConstantTag.kField;
|
||||
ConstantTag get tag => ConstantTag.kStaticField;
|
||||
|
||||
@override
|
||||
void writeValueToBinary(BinarySink sink) {
|
||||
sink.writeCanonicalNameReference(getCanonicalNameOfMember(field));
|
||||
}
|
||||
|
||||
ConstantField.readFromBinary(BinarySource source)
|
||||
ConstantStaticField.readFromBinary(BinarySource source)
|
||||
: _reference = source.readCanonicalNameReference().getReference();
|
||||
|
||||
@override
|
||||
String toString() => 'Field $field';
|
||||
String toString() => 'StaticField $field';
|
||||
|
||||
@override
|
||||
int get hashCode => field.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is ConstantField && this.field == other.field;
|
||||
other is ConstantStaticField && this.field == other.field;
|
||||
}
|
||||
|
||||
class ConstantFieldOffset extends ConstantPoolEntry {
|
||||
class ConstantInstanceField extends ConstantPoolEntry {
|
||||
final Reference _reference;
|
||||
|
||||
Field get field => _reference.asField;
|
||||
int get numReservedEntries => 1;
|
||||
|
||||
ConstantFieldOffset(Field field) : this.byReference(field.reference);
|
||||
ConstantFieldOffset.byReference(this._reference);
|
||||
ConstantInstanceField(Field field) : this.byReference(field.reference);
|
||||
ConstantInstanceField.byReference(this._reference);
|
||||
|
||||
@override
|
||||
ConstantTag get tag => ConstantTag.kFieldOffset;
|
||||
ConstantTag get tag => ConstantTag.kInstanceField;
|
||||
|
||||
@override
|
||||
void writeValueToBinary(BinarySink sink) {
|
||||
sink.writeCanonicalNameReference(getCanonicalNameOfMember(field));
|
||||
}
|
||||
|
||||
ConstantFieldOffset.readFromBinary(BinarySource source)
|
||||
ConstantInstanceField.readFromBinary(BinarySource source)
|
||||
: _reference = source.readCanonicalNameReference().getReference();
|
||||
|
||||
@override
|
||||
String toString() => 'FieldOffset $field';
|
||||
String toString() => 'InstanceField $field';
|
||||
|
||||
@override
|
||||
int get hashCode => field.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is ConstantFieldOffset && this.field == other.field;
|
||||
other is ConstantInstanceField && this.field == other.field;
|
||||
}
|
||||
|
||||
class ConstantClass extends ConstantPoolEntry {
|
||||
|
@ -662,36 +658,34 @@ class ConstantClass extends ConstantPoolEntry {
|
|||
other is ConstantClass && this.classNode == other.classNode;
|
||||
}
|
||||
|
||||
class ConstantTypeArgumentsFieldOffset extends ConstantPoolEntry {
|
||||
class ConstantTypeArgumentsField extends ConstantPoolEntry {
|
||||
final Reference _reference;
|
||||
|
||||
Class get classNode => _reference.asClass;
|
||||
|
||||
ConstantTypeArgumentsFieldOffset(Class class_)
|
||||
: this.byReference(class_.reference);
|
||||
ConstantTypeArgumentsFieldOffset.byReference(this._reference);
|
||||
ConstantTypeArgumentsField(Class class_) : this.byReference(class_.reference);
|
||||
ConstantTypeArgumentsField.byReference(this._reference);
|
||||
|
||||
@override
|
||||
ConstantTag get tag => ConstantTag.kTypeArgumentsFieldOffset;
|
||||
ConstantTag get tag => ConstantTag.kTypeArgumentsField;
|
||||
|
||||
@override
|
||||
void writeValueToBinary(BinarySink sink) {
|
||||
sink.writeCanonicalNameReference(getCanonicalNameOfClass(classNode));
|
||||
}
|
||||
|
||||
ConstantTypeArgumentsFieldOffset.readFromBinary(BinarySource source)
|
||||
ConstantTypeArgumentsField.readFromBinary(BinarySource source)
|
||||
: _reference = source.readCanonicalNameReference().getReference();
|
||||
|
||||
@override
|
||||
String toString() => 'TypeArgumentsFieldOffset $classNode';
|
||||
String toString() => 'TypeArgumentsField $classNode';
|
||||
|
||||
@override
|
||||
int get hashCode => classNode.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is ConstantTypeArgumentsFieldOffset &&
|
||||
this.classNode == other.classNode;
|
||||
other is ConstantTypeArgumentsField && this.classNode == other.classNode;
|
||||
}
|
||||
|
||||
class ConstantTearOff extends ConstantPoolEntry {
|
||||
|
@ -949,39 +943,6 @@ class ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
|
|||
listEquals(this.typeArgs, other.typeArgs);
|
||||
}
|
||||
|
||||
class ConstantContextOffset extends ConstantPoolEntry {
|
||||
static const int kParent = 0;
|
||||
static const int kVariableBase = 1;
|
||||
|
||||
final int _index;
|
||||
|
||||
ConstantContextOffset._(this._index);
|
||||
ConstantContextOffset.parent() : this._(kParent);
|
||||
ConstantContextOffset.variable(int index) : this._(index + kVariableBase);
|
||||
|
||||
@override
|
||||
ConstantTag get tag => ConstantTag.kContextOffset;
|
||||
|
||||
@override
|
||||
void writeValueToBinary(BinarySink sink) {
|
||||
sink.writeUInt30(_index);
|
||||
}
|
||||
|
||||
ConstantContextOffset.readFromBinary(BinarySource source)
|
||||
: _index = source.readUInt();
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'ContextOffset ${_index == kParent ? 'parent' : 'var [${_index - kVariableBase}]'}';
|
||||
|
||||
@override
|
||||
int get hashCode => _index;
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is ConstantContextOffset && this._index == other._index;
|
||||
}
|
||||
|
||||
class ConstantClosureFunction extends ConstantPoolEntry {
|
||||
final String name;
|
||||
final FunctionNode function;
|
||||
|
@ -1133,6 +1094,18 @@ class ConstantPartialTearOffInstantiation extends ConstantPoolEntry {
|
|||
this.typeArgumentsConstantIndex == other.typeArgumentsConstantIndex;
|
||||
}
|
||||
|
||||
/// Reserved constant pool entry.
|
||||
class _ReservedConstantPoolEntry extends ConstantPoolEntry {
|
||||
const _ReservedConstantPoolEntry();
|
||||
|
||||
ConstantTag get tag => throw 'This constant pool entry is reserved';
|
||||
void writeValueToBinary(BinarySink sink) =>
|
||||
throw 'This constant pool entry is reserved';
|
||||
|
||||
@override
|
||||
String toString() => 'Reserved';
|
||||
}
|
||||
|
||||
class ConstantPool {
|
||||
final List<ConstantPoolEntry> entries = <ConstantPoolEntry>[];
|
||||
final Map<ConstantPoolEntry, int> _canonicalizationCache =
|
||||
|
@ -1143,11 +1116,18 @@ class ConstantPool {
|
|||
int add(ConstantPoolEntry entry) {
|
||||
return _canonicalizationCache.putIfAbsent(entry, () {
|
||||
int index = entries.length;
|
||||
entries.add(entry);
|
||||
_addEntry(entry);
|
||||
return index;
|
||||
});
|
||||
}
|
||||
|
||||
void _addEntry(ConstantPoolEntry entry) {
|
||||
entries.add(entry);
|
||||
for (int i = 0; i < entry.numReservedEntries; ++i) {
|
||||
entries.add(const _ReservedConstantPoolEntry());
|
||||
}
|
||||
}
|
||||
|
||||
void writeToBinary(Node node, BinarySink sink) {
|
||||
final function = (node as Member).function;
|
||||
sink.enterScope(
|
||||
|
@ -1157,6 +1137,10 @@ class ConstantPool {
|
|||
|
||||
sink.writeUInt30(entries.length);
|
||||
entries.forEach((e) {
|
||||
if (e is _ReservedConstantPoolEntry) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.writeToBinary(sink);
|
||||
|
||||
if (e is ConstantClosureFunction) {
|
||||
|
@ -1185,7 +1169,8 @@ class ConstantPool {
|
|||
int len = source.readUInt();
|
||||
for (int i = 0; i < len; i++) {
|
||||
final e = new ConstantPoolEntry.readFromBinary(source);
|
||||
entries.add(e);
|
||||
_addEntry(e);
|
||||
i += e.numReservedEntries;
|
||||
|
||||
if (e is ConstantClosureFunction) {
|
||||
source.enterScope(typeParameters: e.function.typeParameters);
|
||||
|
|
|
@ -7,8 +7,7 @@ library vm.bytecode.dbc;
|
|||
// List of changes from original DBC (described in runtime/vm/constants_dbc.h):
|
||||
//
|
||||
// 1. StoreFieldTOS, LoadFieldTOS instructions:
|
||||
// D = index of constant pool entry with FieldOffset,
|
||||
// TypeArgumentsFieldOffset or ConstantContextOffset tags
|
||||
// D = index of constant pool entry with InstanceField tag.
|
||||
// (instead of field offset in words).
|
||||
//
|
||||
// 2. EntryOptional instruction is revived in order to re-shuffle optional
|
||||
|
@ -22,6 +21,19 @@ library vm.bytecode.dbc;
|
|||
// target if assertions are not enabled. It has the same format as Jump
|
||||
// instruction.
|
||||
//
|
||||
// 5. StoreContextParent stores context SP[0] into `parent` field of context SP[-1].
|
||||
//
|
||||
// 6. LoadContextParent loads parent from context SP[0].
|
||||
//
|
||||
// 7. StoreContextVar stores value SP[0] into context SP[-1] at index D.
|
||||
//
|
||||
// 8. LoadContextVar loads value from context SP[0] at index D.
|
||||
//
|
||||
// 9. LoadTypeArgumentsField loads instantiator type arguments from an
|
||||
// instance SP[0].
|
||||
// D = index of TypeArgumentsField constant pool entry corresponding
|
||||
// to an instance's class.
|
||||
//
|
||||
|
||||
enum Opcode {
|
||||
kTrap,
|
||||
|
@ -183,10 +195,15 @@ enum Opcode {
|
|||
kStoreField,
|
||||
kStoreFieldExt,
|
||||
kStoreFieldTOS,
|
||||
kStoreContextParent,
|
||||
kStoreContextVar,
|
||||
kLoadField,
|
||||
kLoadFieldExt,
|
||||
kLoadUntagged,
|
||||
kLoadFieldTOS,
|
||||
kLoadTypeArgumentsField,
|
||||
kLoadContextParent,
|
||||
kLoadContextVar,
|
||||
kBooleanNegateTOS,
|
||||
kBooleanNegate,
|
||||
kThrow,
|
||||
|
@ -571,6 +588,10 @@ const Map<Opcode, Format> BytecodeFormats = const {
|
|||
Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
|
||||
Opcode.kStoreFieldTOS: const Format(
|
||||
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
|
||||
Opcode.kStoreContextParent: const Format(
|
||||
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
|
||||
Opcode.kStoreContextVar: const Format(
|
||||
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
|
||||
Opcode.kLoadField: const Format(
|
||||
Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]),
|
||||
Opcode.kLoadFieldExt: const Format(
|
||||
|
@ -579,6 +600,12 @@ const Map<Opcode, Format> BytecodeFormats = const {
|
|||
Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]),
|
||||
Opcode.kLoadFieldTOS: const Format(
|
||||
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
|
||||
Opcode.kLoadTypeArgumentsField: const Format(
|
||||
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
|
||||
Opcode.kLoadContextParent: const Format(
|
||||
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
|
||||
Opcode.kLoadContextVar: const Format(
|
||||
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
|
||||
Opcode.kBooleanNegateTOS: const Format(
|
||||
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
|
||||
Opcode.kBooleanNegate: const Format(
|
||||
|
|
|
@ -277,7 +277,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
_genPushReceiver();
|
||||
initializer.accept(this);
|
||||
|
||||
final int cpIndex = cp.add(new ConstantFieldOffset(field));
|
||||
final int cpIndex = cp.add(new ConstantInstanceField(field));
|
||||
asm.emitStoreFieldTOS(cpIndex);
|
||||
}
|
||||
|
||||
|
@ -411,8 +411,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
} else {
|
||||
_genPushReceiver();
|
||||
final int cpIndex =
|
||||
cp.add(new ConstantTypeArgumentsFieldOffset(enclosingClass));
|
||||
asm.emitLoadFieldTOS(cpIndex);
|
||||
cp.add(new ConstantTypeArgumentsField(enclosingClass));
|
||||
asm.emitLoadTypeArgumentsField(cpIndex);
|
||||
}
|
||||
} else {
|
||||
_genPushNull();
|
||||
|
@ -477,9 +477,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
|
||||
asm.emitPush(locals.contextVarIndexInFrame);
|
||||
if (depth > 0) {
|
||||
int cpIndex = cp.add(new ConstantContextOffset.parent());
|
||||
for (; depth > 0; --depth) {
|
||||
asm.emitLoadFieldTOS(cpIndex);
|
||||
asm.emitLoadContextParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -493,9 +492,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
void _genLoadVar(VariableDeclaration v, {int currentContextLevel}) {
|
||||
if (locals.isCaptured(v)) {
|
||||
_genPushContextForVariable(v, currentContextLevel: currentContextLevel);
|
||||
final int cpIndex = cp.add(
|
||||
new ConstantContextOffset.variable(locals.getVarIndexInContext(v)));
|
||||
asm.emitLoadFieldTOS(cpIndex);
|
||||
asm.emitLoadContextVar(locals.getVarIndexInContext(v));
|
||||
} else {
|
||||
asm.emitPush(locals.getVarIndexInFrame(v));
|
||||
}
|
||||
|
@ -511,9 +508,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
// If variable is captured, context should be pushed before value.
|
||||
void _genStoreVar(VariableDeclaration variable) {
|
||||
if (locals.isCaptured(variable)) {
|
||||
final int cpIndex = cp.add(new ConstantContextOffset.variable(
|
||||
locals.getVarIndexInContext(variable)));
|
||||
asm.emitStoreFieldTOS(cpIndex);
|
||||
asm.emitStoreContextVar(locals.getVarIndexInContext(variable));
|
||||
} else {
|
||||
asm.emitPopLocal(locals.getVarIndexInFrame(variable));
|
||||
}
|
||||
|
@ -732,7 +727,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
|
||||
if (isClosure) {
|
||||
asm.emitPush(locals.closureVarIndexInFrame);
|
||||
asm.emitLoadFieldTOS(cp.add(new ConstantFieldOffset(closureContext)));
|
||||
asm.emitLoadFieldTOS(cp.add(new ConstantInstanceField(closureContext)));
|
||||
asm.emitPopLocal(locals.contextVarIndexInFrame);
|
||||
}
|
||||
|
||||
|
@ -749,7 +744,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
|
||||
asm.emitPush(locals.closureVarIndexInFrame);
|
||||
asm.emitLoadFieldTOS(
|
||||
cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
|
||||
cp.add(new ConstantInstanceField(closureFunctionTypeArguments)));
|
||||
_genPushInt(numParentTypeArgs);
|
||||
_genPushInt(numParentTypeArgs + function.typeParameters.length);
|
||||
_genStaticCall(prependTypeArguments, new ConstantArgDesc(4), 4);
|
||||
|
@ -757,7 +752,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
} else {
|
||||
asm.emitPush(locals.closureVarIndexInFrame);
|
||||
asm.emitLoadFieldTOS(
|
||||
cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
|
||||
cp.add(new ConstantInstanceField(closureFunctionTypeArguments)));
|
||||
asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
|
||||
}
|
||||
}
|
||||
|
@ -962,23 +957,23 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
asm.emitPush(temp);
|
||||
_genPushInstantiatorTypeArguments();
|
||||
asm.emitStoreFieldTOS(
|
||||
cp.add(new ConstantFieldOffset(closureInstantiatorTypeArguments)));
|
||||
cp.add(new ConstantInstanceField(closureInstantiatorTypeArguments)));
|
||||
|
||||
asm.emitPush(temp);
|
||||
_genPushFunctionTypeArguments();
|
||||
asm.emitStoreFieldTOS(
|
||||
cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
|
||||
cp.add(new ConstantInstanceField(closureFunctionTypeArguments)));
|
||||
|
||||
// TODO(alexmarkov): How to put Object::empty_type_arguments()
|
||||
// to _delayed_type_arguments?
|
||||
|
||||
asm.emitPush(temp);
|
||||
asm.emitPushConstant(closureFunctionIndex);
|
||||
asm.emitStoreFieldTOS(cp.add(new ConstantFieldOffset(closureFunction)));
|
||||
asm.emitStoreFieldTOS(cp.add(new ConstantInstanceField(closureFunction)));
|
||||
|
||||
asm.emitPush(temp);
|
||||
asm.emitPush(locals.contextVarIndexInFrame);
|
||||
asm.emitStoreFieldTOS(cp.add(new ConstantFieldOffset(closureContext)));
|
||||
asm.emitStoreFieldTOS(cp.add(new ConstantInstanceField(closureContext)));
|
||||
}
|
||||
|
||||
void _genClosure(TreeNode node, String name, FunctionNode function) {
|
||||
|
@ -994,7 +989,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
if (locals.currentContextLevel > 0) {
|
||||
_genDupTOS(locals.scratchVarIndexInFrame);
|
||||
asm.emitPush(locals.contextVarIndexInFrame);
|
||||
asm.emitStoreFieldTOS(cp.add(new ConstantContextOffset.parent()));
|
||||
asm.emitStoreContextParent();
|
||||
}
|
||||
|
||||
asm.emitPopLocal(locals.contextVarIndexInFrame);
|
||||
|
@ -1018,7 +1013,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
assert(currentContextLevel >= targetContextLevel);
|
||||
while (currentContextLevel > targetContextLevel) {
|
||||
asm.emitPush(locals.contextVarIndexInFrame);
|
||||
asm.emitLoadFieldTOS(cp.add(new ConstantContextOffset.parent()));
|
||||
asm.emitLoadContextParent();
|
||||
asm.emitPopLocal(locals.contextVarIndexInFrame);
|
||||
--currentContextLevel;
|
||||
}
|
||||
|
@ -1305,7 +1300,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
|
||||
_genTypeArguments(node.typeArguments);
|
||||
asm.emitStoreFieldTOS(
|
||||
cp.add(new ConstantFieldOffset(closureDelayedTypeArguments)));
|
||||
cp.add(new ConstantInstanceField(closureDelayedTypeArguments)));
|
||||
|
||||
// Copy the rest of the fields from old closure to a new closure.
|
||||
final fieldsToCopy = <Field>[
|
||||
|
@ -1316,7 +1311,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
];
|
||||
|
||||
for (Field field in fieldsToCopy) {
|
||||
final fieldOffsetCpIndex = cp.add(new ConstantFieldOffset(field));
|
||||
final fieldOffsetCpIndex = cp.add(new ConstantInstanceField(field));
|
||||
asm.emitPush(newClosure);
|
||||
asm.emitPush(oldClosure);
|
||||
asm.emitLoadFieldTOS(fieldOffsetCpIndex);
|
||||
|
@ -1604,7 +1599,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
if (target.isConst) {
|
||||
_genPushConstExpr(target.initializer);
|
||||
} else if (_hasTrivialInitializer(target)) {
|
||||
final fieldIndex = cp.add(new ConstantField(target));
|
||||
final fieldIndex = cp.add(new ConstantStaticField(target));
|
||||
asm.emitPushConstant(
|
||||
fieldIndex); // TODO(alexmarkov): do we really need this?
|
||||
asm.emitPushStatic(fieldIndex);
|
||||
|
@ -1656,7 +1651,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
|
||||
final target = node.target;
|
||||
if (target is Field) {
|
||||
int cpIndex = cp.add(new ConstantField(target));
|
||||
int cpIndex = cp.add(new ConstantStaticField(target));
|
||||
asm.emitStoreStaticTOS(cpIndex);
|
||||
} else {
|
||||
_genStaticCall(target, new ConstantArgDesc(1), 1, isSet: true);
|
||||
|
@ -2124,7 +2119,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
// 1. Restore context from closure var.
|
||||
// This context has a context level at frame entry.
|
||||
asm.emitPush(locals.closureVarIndexInFrame);
|
||||
asm.emitLoadFieldTOS(cp.add(new ConstantFieldOffset(closureContext)));
|
||||
asm.emitLoadFieldTOS(cp.add(new ConstantInstanceField(closureContext)));
|
||||
asm.emitPopLocal(locals.contextVarIndexInFrame);
|
||||
|
||||
// 2. Restore context from captured :saved_try_context_var${depth}.
|
||||
|
@ -2309,9 +2304,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
_genPushNull();
|
||||
}
|
||||
if (isCaptured) {
|
||||
final int cpIndex = cp.add(new ConstantContextOffset.variable(
|
||||
locals.getVarIndexInContext(node)));
|
||||
asm.emitStoreFieldTOS(cpIndex);
|
||||
asm.emitStoreContextVar(locals.getVarIndexInContext(node));
|
||||
} else {
|
||||
asm.emitPopLocal(locals.getVarIndexInFrame(node));
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -109,7 +109,7 @@ ConstantPool {
|
|||
[2] = StaticICData target '#lib::_NamespaceImpl::_', arg-desc CP#1
|
||||
[3] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[4] = StaticICData target '#lib::_NamespaceImpl::_create', arg-desc CP#3
|
||||
[5] = Field #lib::_NamespaceImpl::_cachedNamespace
|
||||
[5] = StaticField #lib::_NamespaceImpl::_cachedNamespace
|
||||
[6] = Null
|
||||
}
|
||||
] static method _setupNamespace(dynamic namespace) → void {
|
||||
|
@ -146,7 +146,7 @@ L1:
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Field #lib::_NamespaceImpl::_cachedNamespace
|
||||
[0] = StaticField #lib::_NamespaceImpl::_cachedNamespace
|
||||
[1] = Null
|
||||
[2] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[3] = ICData target-name '==', arg-desc CP#2
|
||||
|
@ -303,9 +303,9 @@ Bytecode {
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Field #lib::VMLibraryHooks::_computeScriptUri
|
||||
[0] = StaticField #lib::VMLibraryHooks::_computeScriptUri
|
||||
[1] = Null
|
||||
[2] = Field #lib::VMLibraryHooks::_cachedScript
|
||||
[2] = StaticField #lib::VMLibraryHooks::_cachedScript
|
||||
}
|
||||
] static set platformScript(dynamic f) → void {
|
||||
self::VMLibraryHooks::_computeScriptUri = f;
|
||||
|
@ -352,12 +352,12 @@ L3:
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Field #lib::VMLibraryHooks::_cachedScript
|
||||
[0] = StaticField #lib::VMLibraryHooks::_cachedScript
|
||||
[1] = Null
|
||||
[2] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[3] = ICData target-name '==', arg-desc CP#2
|
||||
[4] = Bool true
|
||||
[5] = Field #lib::VMLibraryHooks::_computeScriptUri
|
||||
[5] = StaticField #lib::VMLibraryHooks::_computeScriptUri
|
||||
[6] = ICData target-name '==', arg-desc CP#2
|
||||
[7] = Bool false
|
||||
[8] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
|
@ -433,7 +433,7 @@ Bytecode {
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Field #lib::_ScheduleImmediate::_closure
|
||||
[0] = StaticField #lib::_ScheduleImmediate::_closure
|
||||
[1] = Null
|
||||
}
|
||||
]static method _setScheduleImmediateClosure((() → void) → void closure) → void {
|
||||
|
@ -453,9 +453,9 @@ Bytecode {
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Field #lib::_stdinFD
|
||||
[1] = Field #lib::_stdoutFD
|
||||
[2] = Field #lib::_stderrFD
|
||||
[0] = StaticField #lib::_stdinFD
|
||||
[1] = StaticField #lib::_stdoutFD
|
||||
[2] = StaticField #lib::_stderrFD
|
||||
[3] = Null
|
||||
}
|
||||
]static method _setStdioFDs(core::int stdin, core::int stdout, core::int stderr) → void {
|
||||
|
@ -528,7 +528,7 @@ L6:
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Field #lib::_rawScript
|
||||
[0] = StaticField #lib::_rawScript
|
||||
[1] = String 'http:'
|
||||
[2] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[3] = ICData target-name 'startsWith', arg-desc CP#2
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,26 +17,29 @@ Bytecode {
|
|||
StoreFieldTOS CP#1
|
||||
Push FP[-6]
|
||||
Push FP[-5]
|
||||
StoreFieldTOS CP#2
|
||||
StoreFieldTOS CP#3
|
||||
Push FP[-6]
|
||||
PushConstant CP#3
|
||||
StoreFieldTOS CP#4
|
||||
PushConstant CP#5
|
||||
StoreFieldTOS CP#6
|
||||
Push FP[-6]
|
||||
PushConstant CP#6
|
||||
IndirectStaticCall 1, CP#5
|
||||
PushConstant CP#9
|
||||
IndirectStaticCall 1, CP#8
|
||||
Drop1
|
||||
PushConstant CP#7
|
||||
PushConstant CP#10
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Int 42
|
||||
[1] = FieldOffset #lib::A::foo3
|
||||
[2] = FieldOffset #lib::A::foo4
|
||||
[3] = Int 44
|
||||
[4] = FieldOffset #lib::A::foo5
|
||||
[5] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[6] = StaticICData target 'dart.core::Object::', arg-desc CP#5
|
||||
[7] = Null
|
||||
[1] = InstanceField #lib::A::foo3
|
||||
[2] = Reserved
|
||||
[3] = InstanceField #lib::A::foo4
|
||||
[4] = Reserved
|
||||
[5] = Int 44
|
||||
[6] = InstanceField #lib::A::foo5
|
||||
[7] = Reserved
|
||||
[8] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[9] = StaticICData target 'dart.core::Object::', arg-desc CP#8
|
||||
[10] = Null
|
||||
}
|
||||
] constructor •(core::int foo4) → void
|
||||
: self::A::foo1 = null, self::A::foo4 = foo4, self::A::foo5 = 44, super core::Object::•()
|
||||
|
@ -50,30 +53,33 @@ Bytecode {
|
|||
StoreFieldTOS CP#1
|
||||
Push FP[-7]
|
||||
Push FP[-6]
|
||||
StoreFieldTOS CP#2
|
||||
StoreFieldTOS CP#3
|
||||
Push FP[-7]
|
||||
Push FP[-5]
|
||||
PushConstant CP#3
|
||||
InstanceCall1 2, CP#5
|
||||
StoreFieldTOS CP#6
|
||||
PushConstant CP#5
|
||||
InstanceCall1 2, CP#7
|
||||
StoreFieldTOS CP#8
|
||||
Push FP[-7]
|
||||
PushConstant CP#8
|
||||
IndirectStaticCall 1, CP#7
|
||||
PushConstant CP#11
|
||||
IndirectStaticCall 1, CP#10
|
||||
Drop1
|
||||
PushConstant CP#9
|
||||
PushConstant CP#12
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Int 42
|
||||
[1] = FieldOffset #lib::A::foo3
|
||||
[2] = FieldOffset #lib::A::foo1
|
||||
[3] = Int 1
|
||||
[4] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[5] = ICData target-name '+', arg-desc CP#4
|
||||
[6] = FieldOffset #lib::A::foo5
|
||||
[7] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[8] = StaticICData target 'dart.core::Object::', arg-desc CP#7
|
||||
[9] = Null
|
||||
[1] = InstanceField #lib::A::foo3
|
||||
[2] = Reserved
|
||||
[3] = InstanceField #lib::A::foo1
|
||||
[4] = Reserved
|
||||
[5] = Int 1
|
||||
[6] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[7] = ICData target-name '+', arg-desc CP#6
|
||||
[8] = InstanceField #lib::A::foo5
|
||||
[9] = Reserved
|
||||
[10] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[11] = StaticICData target 'dart.core::Object::', arg-desc CP#10
|
||||
[12] = Null
|
||||
}
|
||||
] constructor constr2(core::int x, core::int y) → void
|
||||
: self::A::foo4 = null, self::A::foo1 = x, self::A::foo5 = y.{core::num::+}(1), super core::Object::•()
|
||||
|
@ -137,20 +143,21 @@ Bytecode {
|
|||
PushConstant CP#0
|
||||
StoreFieldTOS CP#1
|
||||
Push FP[-5]
|
||||
PushConstant CP#2
|
||||
PushConstant CP#4
|
||||
IndirectStaticCall 2, CP#3
|
||||
Drop1
|
||||
PushConstant CP#3
|
||||
PushConstant CP#5
|
||||
IndirectStaticCall 2, CP#4
|
||||
Drop1
|
||||
PushConstant CP#6
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Int 46
|
||||
[1] = FieldOffset #lib::B::foo6
|
||||
[2] = Int 49
|
||||
[3] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[4] = StaticICData target '#lib::A::', arg-desc CP#3
|
||||
[5] = Null
|
||||
[1] = InstanceField #lib::B::foo6
|
||||
[2] = Reserved
|
||||
[3] = Int 49
|
||||
[4] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[5] = StaticICData target '#lib::A::', arg-desc CP#4
|
||||
[6] = Null
|
||||
}
|
||||
] constructor •() → void
|
||||
: super self::A::•(49)
|
||||
|
@ -165,20 +172,21 @@ Bytecode {
|
|||
Push FP[-7]
|
||||
Push FP[-6]
|
||||
Push FP[-5]
|
||||
PushConstant CP#2
|
||||
PushConstant CP#4
|
||||
IndirectStaticCall 4, CP#3
|
||||
Drop1
|
||||
PushConstant CP#3
|
||||
PushConstant CP#5
|
||||
IndirectStaticCall 4, CP#4
|
||||
Drop1
|
||||
PushConstant CP#6
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Int 50
|
||||
[1] = FieldOffset #lib::B::foo6
|
||||
[2] = Int 51
|
||||
[3] = ArgDesc num-args 4, num-type-args 0, names []
|
||||
[4] = StaticICData target '#lib::A::redirecting2', arg-desc CP#3
|
||||
[5] = Null
|
||||
[1] = InstanceField #lib::B::foo6
|
||||
[2] = Reserved
|
||||
[3] = Int 51
|
||||
[4] = ArgDesc num-args 4, num-type-args 0, names []
|
||||
[5] = StaticICData target '#lib::A::redirecting2', arg-desc CP#4
|
||||
[6] = Null
|
||||
}
|
||||
] constructor c2(core::int i, core::int j) → void
|
||||
: self::B::foo6 = 50, super self::A::redirecting2(i, j, 51)
|
||||
|
|
|
@ -25,7 +25,7 @@ Bytecode {
|
|||
Push r0
|
||||
PushConstant CP#6
|
||||
Push FP[-5]
|
||||
LoadFieldTOS CP#8
|
||||
LoadTypeArgumentsField CP#8
|
||||
PushConstant CP#2
|
||||
InstantiateType CP#7
|
||||
StoreIndexedTOS
|
||||
|
@ -36,7 +36,7 @@ Bytecode {
|
|||
Push r0
|
||||
PushConstant CP#11
|
||||
Push FP[-5]
|
||||
LoadFieldTOS CP#8
|
||||
LoadTypeArgumentsField CP#8
|
||||
PushConstant CP#2
|
||||
InstantiateType CP#12
|
||||
StoreIndexedTOS
|
||||
|
@ -57,7 +57,7 @@ ConstantPool {
|
|||
[5] = String 'Base: '
|
||||
[6] = Int 1
|
||||
[7] = Type #lib::Base::T1
|
||||
[8] = TypeArgumentsFieldOffset #lib::Base
|
||||
[8] = TypeArgumentsField #lib::Base
|
||||
[9] = Int 2
|
||||
[10] = String ', '
|
||||
[11] = Int 3
|
||||
|
@ -111,7 +111,7 @@ Bytecode {
|
|||
Push r0
|
||||
PushConstant CP#6
|
||||
Push FP[-5]
|
||||
LoadFieldTOS CP#8
|
||||
LoadTypeArgumentsField CP#8
|
||||
PushConstant CP#2
|
||||
InstantiateType CP#7
|
||||
StoreIndexedTOS
|
||||
|
@ -132,7 +132,7 @@ ConstantPool {
|
|||
[5] = String 'B: '
|
||||
[6] = Int 1
|
||||
[7] = Type #lib::B::T
|
||||
[8] = TypeArgumentsFieldOffset #lib::B
|
||||
[8] = TypeArgumentsField #lib::B
|
||||
[9] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#0
|
||||
[10] = StaticICData target 'dart.core::print', arg-desc CP#0
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ Bytecode {
|
|||
Entry 0
|
||||
CheckStack
|
||||
Push FP[-5]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushConstant CP#2
|
||||
IndirectStaticCall 1, CP#1
|
||||
ReturnTOS
|
||||
|
@ -219,7 +219,7 @@ Bytecode {
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = TypeArgumentsFieldOffset #lib::E
|
||||
[0] = TypeArgumentsField #lib::E
|
||||
[1] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[2] = StaticICData target 'dart.core::Map::', arg-desc CP#1
|
||||
[3] = Null
|
||||
|
@ -252,7 +252,7 @@ Bytecode {
|
|||
Entry 0
|
||||
CheckStack
|
||||
Push FP[-5]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushConstant CP#2
|
||||
IndirectStaticCall 1, CP#1
|
||||
ReturnTOS
|
||||
|
@ -260,7 +260,7 @@ Bytecode {
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = TypeArgumentsFieldOffset #lib::F
|
||||
[0] = TypeArgumentsField #lib::F
|
||||
[1] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[2] = StaticICData target 'dart.core::Map::', arg-desc CP#1
|
||||
[3] = Null
|
||||
|
|
|
@ -95,20 +95,22 @@ Bytecode {
|
|||
StoreFieldTOS CP#0
|
||||
Push FP[-7]
|
||||
Push FP[-5]
|
||||
StoreFieldTOS CP#1
|
||||
StoreFieldTOS CP#2
|
||||
Push FP[-7]
|
||||
PushConstant CP#3
|
||||
IndirectStaticCall 1, CP#2
|
||||
PushConstant CP#5
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
PushConstant CP#4
|
||||
PushConstant CP#6
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = FieldOffset #lib::A::index
|
||||
[1] = FieldOffset #lib::A::_name
|
||||
[2] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[3] = StaticICData target 'dart.core::Object::', arg-desc CP#2
|
||||
[4] = Null
|
||||
[0] = InstanceField #lib::A::index
|
||||
[1] = Reserved
|
||||
[2] = InstanceField #lib::A::_name
|
||||
[3] = Reserved
|
||||
[4] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[5] = StaticICData target 'dart.core::Object::', arg-desc CP#4
|
||||
[6] = Null
|
||||
}
|
||||
] const constructor •(core::int index, core::String _name) → void
|
||||
: self::A::index = index, self::A::_name = _name, super core::Object::•()
|
||||
|
@ -142,17 +144,18 @@ Bytecode {
|
|||
Push FP[-5]
|
||||
StoreFieldTOS CP#0
|
||||
Push FP[-6]
|
||||
PushConstant CP#2
|
||||
IndirectStaticCall 1, CP#1
|
||||
Drop1
|
||||
PushConstant CP#3
|
||||
IndirectStaticCall 1, CP#2
|
||||
Drop1
|
||||
PushConstant CP#4
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = FieldOffset #lib::B::i
|
||||
[1] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[2] = StaticICData target 'dart.core::Object::', arg-desc CP#1
|
||||
[3] = Null
|
||||
[0] = InstanceField #lib::B::i
|
||||
[1] = Reserved
|
||||
[2] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[3] = StaticICData target 'dart.core::Object::', arg-desc CP#2
|
||||
[4] = Null
|
||||
}
|
||||
] const constructor •(core::int i) → void
|
||||
: self::B::i = i, super core::Object::•()
|
||||
|
@ -171,22 +174,23 @@ Bytecode {
|
|||
StoreFieldTOS CP#2
|
||||
Push FP[-8]
|
||||
Push FP[-5]
|
||||
PushConstant CP#3
|
||||
InstanceCall1 2, CP#4
|
||||
PushConstant CP#5
|
||||
PushConstant CP#4
|
||||
InstanceCall1 2, CP#5
|
||||
PushConstant CP#6
|
||||
IndirectStaticCall 2, CP#0
|
||||
Drop1
|
||||
PushConstant CP#6
|
||||
PushConstant CP#7
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[1] = ICData target-name '+', arg-desc CP#0
|
||||
[2] = FieldOffset #lib::C::j
|
||||
[3] = Int 5
|
||||
[4] = ICData target-name '*', arg-desc CP#0
|
||||
[5] = StaticICData target '#lib::B::', arg-desc CP#0
|
||||
[6] = Null
|
||||
[2] = InstanceField #lib::C::j
|
||||
[3] = Reserved
|
||||
[4] = Int 5
|
||||
[5] = ICData target-name '*', arg-desc CP#0
|
||||
[6] = StaticICData target '#lib::B::', arg-desc CP#0
|
||||
[7] = Null
|
||||
}
|
||||
] const constructor •(core::int a, core::int b, core::int c) → void
|
||||
: self::C::j = a.{core::num::+}(b), super self::B::•(c.{core::num::*}(5))
|
||||
|
@ -206,20 +210,22 @@ Bytecode {
|
|||
StoreFieldTOS CP#1
|
||||
Push r0
|
||||
Push r2
|
||||
StoreFieldTOS CP#2
|
||||
StoreFieldTOS CP#3
|
||||
Push r0
|
||||
PushConstant CP#4
|
||||
IndirectStaticCall 1, CP#3
|
||||
PushConstant CP#6
|
||||
IndirectStaticCall 1, CP#5
|
||||
Drop1
|
||||
PushConstant CP#0
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Null
|
||||
[1] = FieldOffset #lib::D::x
|
||||
[2] = FieldOffset #lib::D::y
|
||||
[3] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[4] = StaticICData target 'dart.core::Object::', arg-desc CP#3
|
||||
[1] = InstanceField #lib::D::x
|
||||
[2] = Reserved
|
||||
[3] = InstanceField #lib::D::y
|
||||
[4] = Reserved
|
||||
[5] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[6] = StaticICData target 'dart.core::Object::', arg-desc CP#5
|
||||
}
|
||||
] const constructor •(dynamic x, [dynamic y = null]) → void
|
||||
: self::D::x = x, self::D::y = y, super core::Object::•()
|
||||
|
@ -740,7 +746,7 @@ Bytecode {
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Field #lib::fieldWithDoubleLiteralInitializer
|
||||
[0] = StaticField #lib::fieldWithDoubleLiteralInitializer
|
||||
[1] = Null
|
||||
}
|
||||
]static method testFieldWithDoubleLiteralInitializer() → dynamic
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -74,28 +74,29 @@ Bytecode {
|
|||
Push FP[-6]
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushConstant CP#1
|
||||
PushConstant CP#2
|
||||
PushConstant CP#3
|
||||
AssertAssignable 0, CP#4
|
||||
StoreFieldTOS CP#5
|
||||
Push FP[-6]
|
||||
PushConstant CP#7
|
||||
IndirectStaticCall 1, CP#6
|
||||
PushConstant CP#8
|
||||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
PushConstant CP#1
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = TypeArgumentsFieldOffset #lib::D
|
||||
[0] = TypeArgumentsField #lib::D
|
||||
[1] = Null
|
||||
[2] = Type dart.core::Map<#lib::D::P, #lib::D::Q>
|
||||
[3] = String ''
|
||||
[4] = SubtypeTestCache
|
||||
[5] = FieldOffset #lib::D::foo
|
||||
[6] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[7] = StaticICData target '#lib::C::', arg-desc CP#6
|
||||
[5] = InstanceField #lib::D::foo
|
||||
[6] = Reserved
|
||||
[7] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[8] = StaticICData target '#lib::C::', arg-desc CP#7
|
||||
}
|
||||
] constructor •(dynamic tt) → void
|
||||
: self::D::foo = tt as{TypeError} core::Map<self::D::P, self::D::Q>, super self::C::•()
|
||||
|
@ -106,7 +107,7 @@ Bytecode {
|
|||
CheckStack
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushConstant CP#1
|
||||
PushConstant CP#2
|
||||
InstanceCall1 4, CP#4
|
||||
|
@ -121,7 +122,7 @@ Bytecode {
|
|||
L1:
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushConstant CP#1
|
||||
PushConstant CP#9
|
||||
InstanceCall1 4, CP#10
|
||||
|
@ -137,7 +138,7 @@ L2:
|
|||
Push FP[-6]
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushConstant CP#1
|
||||
PushConstant CP#13
|
||||
PushConstant CP#14
|
||||
|
@ -148,7 +149,7 @@ L2:
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = TypeArgumentsFieldOffset #lib::D
|
||||
[0] = TypeArgumentsField #lib::D
|
||||
[1] = Null
|
||||
[2] = Type #lib::A<#lib::D::P>
|
||||
[3] = ArgDesc num-args 4, num-type-args 0, names []
|
||||
|
@ -197,7 +198,7 @@ Bytecode {
|
|||
L1:
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#8
|
||||
LoadTypeArgumentsField CP#8
|
||||
Push r0
|
||||
PushConstant CP#9
|
||||
InstanceCall1 4, CP#10
|
||||
|
@ -212,7 +213,7 @@ L1:
|
|||
L2:
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#8
|
||||
LoadTypeArgumentsField CP#8
|
||||
Push r0
|
||||
PushConstant CP#13
|
||||
InstanceCall1 4, CP#14
|
||||
|
@ -230,7 +231,7 @@ ConstantPool {
|
|||
[5] = String '31'
|
||||
[6] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[7] = StaticICData target 'dart.core::print', arg-desc CP#6
|
||||
[8] = TypeArgumentsFieldOffset #lib::D
|
||||
[8] = TypeArgumentsField #lib::D
|
||||
[9] = Type #lib::C<dart.core::Map<#lib::D::foo3::T1, #lib::D::P>, dart.core::List<#lib::D::foo3::T2>, #lib::D::Q>
|
||||
[10] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
|
||||
[11] = String '32'
|
||||
|
@ -253,7 +254,7 @@ Bytecode {
|
|||
Entry 2
|
||||
CheckStack
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushConstant CP#1
|
||||
InstantiateTypeArgumentsTOS 0, CP#2
|
||||
StoreLocal r1
|
||||
|
@ -265,7 +266,7 @@ Bytecode {
|
|||
PushConstant CP#4
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushConstant CP#1
|
||||
PushConstant CP#5
|
||||
PushConstant CP#6
|
||||
|
@ -276,7 +277,7 @@ Bytecode {
|
|||
PopLocal r0
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushConstant CP#1
|
||||
PushConstant CP#5
|
||||
PushConstant CP#6
|
||||
|
@ -286,7 +287,7 @@ Bytecode {
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = TypeArgumentsFieldOffset #lib::D
|
||||
[0] = TypeArgumentsField #lib::D
|
||||
[1] = Null
|
||||
[2] = TypeArgs [dart.core::Map<#lib::D::P, #lib::D::Q>]
|
||||
[3] = Int 1
|
||||
|
@ -324,7 +325,7 @@ Bytecode {
|
|||
CheckStack
|
||||
CheckFunctionTypeArgs 2, 0
|
||||
Push FP[-6]
|
||||
LoadFieldTOS CP#0
|
||||
LoadTypeArgumentsField CP#0
|
||||
Push r0
|
||||
PushConstant CP#1
|
||||
PushConstant CP#2
|
||||
|
@ -347,7 +348,7 @@ Bytecode {
|
|||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = TypeArgumentsFieldOffset #lib::E
|
||||
[0] = TypeArgumentsField #lib::E
|
||||
[1] = Type #lib::E::foo6::T
|
||||
[2] = Type #lib::E::P
|
||||
[3] = String 'T'
|
||||
|
@ -447,7 +448,7 @@ ConstantPool {
|
|||
[1] = Type dart.core::List<dart.core::Iterable<dynamic>>
|
||||
[2] = String ''
|
||||
[3] = SubtypeTestCache
|
||||
[4] = Field #lib::globalVar
|
||||
[4] = StaticField #lib::globalVar
|
||||
}
|
||||
]static method foo5(dynamic x) → void {
|
||||
self::globalVar = x as{TypeError} core::List<core::Iterable<dynamic>>;
|
||||
|
|
|
@ -97,10 +97,10 @@ intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
|
|||
kArgDesc,
|
||||
kICData,
|
||||
kStaticICData,
|
||||
kField,
|
||||
kFieldOffset,
|
||||
kStaticField,
|
||||
kInstanceField,
|
||||
kClass,
|
||||
kTypeArgumentsFieldOffset,
|
||||
kTypeArgumentsField,
|
||||
kTearOff,
|
||||
kType,
|
||||
kTypeArguments,
|
||||
|
@ -108,7 +108,6 @@ intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
|
|||
kInstance,
|
||||
kSymbol,
|
||||
kTypeArgumentsForInstanceAllocation,
|
||||
kContextOffset,
|
||||
kClosureFunction,
|
||||
kEndClosureFunctionScope,
|
||||
kNativeEntry,
|
||||
|
@ -242,20 +241,28 @@ intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
|
|||
ICData::Cast(obj).set_tag(ICData::Tag::kStaticCall);
|
||||
#endif
|
||||
} break;
|
||||
case ConstantPoolTag::kField:
|
||||
case ConstantPoolTag::kStaticField:
|
||||
obj = H.LookupFieldByKernelField(helper_->ReadCanonicalNameReference());
|
||||
ASSERT(obj.IsField());
|
||||
break;
|
||||
case ConstantPoolTag::kFieldOffset:
|
||||
obj = H.LookupFieldByKernelField(helper_->ReadCanonicalNameReference());
|
||||
ASSERT(obj.IsField());
|
||||
obj = Smi::New(Field::Cast(obj).Offset() / kWordSize);
|
||||
case ConstantPoolTag::kInstanceField:
|
||||
field =
|
||||
H.LookupFieldByKernelField(helper_->ReadCanonicalNameReference());
|
||||
// InstanceField constant occupies 2 entries.
|
||||
// The first entry is used for field offset.
|
||||
obj = Smi::New(field.Offset() / kWordSize);
|
||||
pool.SetTypeAt(i, ObjectPool::kTaggedObject);
|
||||
pool.SetObjectAt(i, obj);
|
||||
++i;
|
||||
ASSERT(i < obj_count);
|
||||
// The second entry is used for field object.
|
||||
obj = field.raw();
|
||||
break;
|
||||
case ConstantPoolTag::kClass:
|
||||
obj = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
|
||||
ASSERT(obj.IsClass());
|
||||
break;
|
||||
case ConstantPoolTag::kTypeArgumentsFieldOffset:
|
||||
case ConstantPoolTag::kTypeArgumentsField:
|
||||
cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
|
||||
obj = Smi::New(cls.type_arguments_field_offset() / kWordSize);
|
||||
break;
|
||||
|
@ -325,14 +332,6 @@ intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
|
|||
.raw();
|
||||
ASSERT(obj.IsNull() || obj.IsTypeArguments());
|
||||
} break;
|
||||
case ConstantPoolTag::kContextOffset: {
|
||||
intptr_t index = helper_->ReadUInt();
|
||||
if (index == 0) {
|
||||
obj = Smi::New(Context::parent_offset() / kWordSize);
|
||||
} else {
|
||||
obj = Smi::New(Context::variable_offset(index - 1) / kWordSize);
|
||||
}
|
||||
} break;
|
||||
case ConstantPoolTag::kClosureFunction: {
|
||||
name = H.DartSymbolPlain(helper_->ReadStringReference()).raw();
|
||||
const Function& closure = Function::Handle(
|
||||
|
|
|
@ -499,6 +499,14 @@ namespace dart {
|
|||
//
|
||||
// Store value SP[0] into object SP[-1] at offset (in words) PP[D].
|
||||
//
|
||||
// - StoreContextParent
|
||||
//
|
||||
// Store context SP[0] into `parent` field of context SP[-1].
|
||||
//
|
||||
// - StoreContextVar D
|
||||
//
|
||||
// Store value SP[0] into context SP[-1] at index D.
|
||||
//
|
||||
// - LoadField rA, rB, C
|
||||
//
|
||||
// Load value at offset (in words) C from object FP[rB] into FP[rA].
|
||||
|
@ -517,6 +525,20 @@ namespace dart {
|
|||
//
|
||||
// Push value at offset (in words) PP[D] from object SP[0].
|
||||
//
|
||||
// - LoadTypeArgumentsField D
|
||||
//
|
||||
// Load instantiator type arguments from an instance SP[0].
|
||||
// PP[D] = offset (in words) of type arguments field corresponding
|
||||
// to an instance's class.
|
||||
//
|
||||
// - LoadContextParent
|
||||
//
|
||||
// Load parent from context SP[0].
|
||||
//
|
||||
// - LoadContextVar D
|
||||
//
|
||||
// Load value from context SP[0] at index D.
|
||||
//
|
||||
// - BooleanNegateTOS
|
||||
//
|
||||
// SP[0] = !SP[0]
|
||||
|
@ -929,10 +951,15 @@ namespace dart {
|
|||
V(StoreField, A_B_C, reg, num, reg) \
|
||||
V(StoreFieldExt, A_D, reg, reg, ___) \
|
||||
V(StoreFieldTOS, D, lit, ___, ___) \
|
||||
V(StoreContextParent, 0, ___, ___, ___) \
|
||||
V(StoreContextVar, D, num, ___, ___) \
|
||||
V(LoadField, A_B_C, reg, reg, num) \
|
||||
V(LoadFieldExt, A_D, reg, reg, ___) \
|
||||
V(LoadUntagged, A_B_C, reg, reg, num) \
|
||||
V(LoadFieldTOS, D, lit, ___, ___) \
|
||||
V(LoadTypeArgumentsField, D, lit, ___, ___) \
|
||||
V(LoadContextParent, 0, ___, ___, ___) \
|
||||
V(LoadContextVar, D, num, ___, ___) \
|
||||
V(BooleanNegateTOS, 0, ___, ___, ___) \
|
||||
V(BooleanNegate, A_D, reg, reg, ___) \
|
||||
V(Throw, A, num, ___, ___) \
|
||||
|
|
|
@ -3524,6 +3524,36 @@ RawObject* Interpreter::Call(RawFunction* function,
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(StoreContextParent, 0);
|
||||
const uword offset_in_words =
|
||||
static_cast<uword>(Context::parent_offset() / kWordSize);
|
||||
RawContext* instance = reinterpret_cast<RawContext*>(SP[-1]);
|
||||
RawContext* value = reinterpret_cast<RawContext*>(SP[0]);
|
||||
SP -= 2; // Drop instance and value.
|
||||
|
||||
instance->StorePointer(
|
||||
reinterpret_cast<RawContext**>(instance->ptr()) + offset_in_words,
|
||||
value);
|
||||
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(StoreContextVar, __D);
|
||||
const uword offset_in_words =
|
||||
static_cast<uword>(Context::variable_offset(rD) / kWordSize);
|
||||
RawContext* instance = reinterpret_cast<RawContext*>(SP[-1]);
|
||||
RawObject* value = reinterpret_cast<RawContext*>(SP[0]);
|
||||
SP -= 2; // Drop instance and value.
|
||||
|
||||
instance->StorePointer(
|
||||
reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
|
||||
value);
|
||||
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(LoadField, A_B_C);
|
||||
const uint16_t instance_reg = rB;
|
||||
|
@ -3561,6 +3591,33 @@ RawObject* Interpreter::Call(RawFunction* function,
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(LoadTypeArgumentsField, __D);
|
||||
const uword offset_in_words =
|
||||
static_cast<uword>(Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))));
|
||||
RawInstance* instance = static_cast<RawInstance*>(SP[0]);
|
||||
SP[0] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(LoadContextParent, 0);
|
||||
const uword offset_in_words =
|
||||
static_cast<uword>(Context::parent_offset() / kWordSize);
|
||||
RawContext* instance = static_cast<RawContext*>(SP[0]);
|
||||
SP[0] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(LoadContextVar, __D);
|
||||
const uword offset_in_words =
|
||||
static_cast<uword>(Context::variable_offset(rD) / kWordSize);
|
||||
RawContext* instance = static_cast<RawContext*>(SP[0]);
|
||||
SP[0] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(InitStaticTOS, 0);
|
||||
UNREACHABLE(); // Not used. TODO(regis): Remove this bytecode.
|
||||
|
|
Loading…
Reference in a new issue