[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:
Alexander Markov 2018-08-08 16:35:25 +00:00 committed by commit-bot@chromium.org
parent af45552aa5
commit 85d85246ad
15 changed files with 2460 additions and 2352 deletions

View file

@ -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));
}

View file

@ -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);

View file

@ -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(

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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>>;

View file

@ -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(

View file

@ -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, ___, ___) \

View file

@ -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.