[vm/kernel/bytecode] Add invocation kind to StaticICData constant

VM will use the invocation kind to distinguish between getters,
setters and calls via field/getter.

Change-Id: I97cf36bc8778533e53f8251c25b373fddec3c2e8
Reviewed-on: https://dart-review.googlesource.com/55581
Reviewed-by: Régis Crelier <regis@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov 2018-05-21 23:03:01 +00:00 committed by commit-bot@chromium.org
parent 929b79e865
commit 68b19b4ff4
4 changed files with 44 additions and 19 deletions

View file

@ -63,8 +63,15 @@ type ConstantICData extends ConstantPoolEntry {
ConstantIndex argDesc;
}
enum InvocationKind {
method, // x.foo(...) or foo(...)
getter, // x.foo
setter // x.foo = ...
}
type ConstantStaticICData extends ConstantPoolEntry {
Byte tag = 8;
Byte invocationKind; // Index in InvocationKind enum.
CanonicalNameReference target;
ConstantIndex argDesc;
}
@ -468,13 +475,20 @@ class ConstantICData extends ConstantPoolEntry {
bool operator ==(other) => identical(this, other);
}
enum InvocationKind { method, getter, setter }
class ConstantStaticICData extends ConstantPoolEntry {
final InvocationKind invocationKind;
final Reference _reference;
final int argDescConstantIndex;
ConstantStaticICData(Member member, int argDescConstantIndex)
: this.byReference(member.reference, argDescConstantIndex);
ConstantStaticICData.byReference(this._reference, this.argDescConstantIndex);
ConstantStaticICData(
InvocationKind invocationKind, Member member, int argDescConstantIndex)
: this.byReference(
invocationKind, member.reference, argDescConstantIndex);
ConstantStaticICData.byReference(
this.invocationKind, this._reference, this.argDescConstantIndex);
Member get target => _reference.asMember;
@ -483,17 +497,23 @@ class ConstantStaticICData extends ConstantPoolEntry {
@override
void writeValueToBinary(BinarySink sink) {
sink.writeByte(invocationKind.index);
sink.writeCanonicalNameReference(getCanonicalNameOfMember(target));
sink.writeUInt30(argDescConstantIndex);
}
ConstantStaticICData.readFromBinary(BinarySource source)
: _reference = source.readCanonicalNameReference().getReference(),
: invocationKind = InvocationKind.values[source.readByte()],
_reference = source.readCanonicalNameReference().getReference(),
argDescConstantIndex = source.readUInt();
@override
String toString() =>
'StaticICData target \'$target\', arg-desc CP#$argDescConstantIndex';
'StaticICData ' +
(invocationKind == InvocationKind.getter
? 'get '
: (invocationKind == InvocationKind.setter ? 'set ' : '')) +
'target \'$target\', arg-desc CP#$argDescConstantIndex';
// ConstantStaticICData entries are created per call site and should not be
// merged, so ConstantStaticICData class uses identity [hashCode] and

View file

@ -235,10 +235,15 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
asm.emitReturnTOS();
}
void _genStaticCall(
Member target, ConstantArgDesc argDesc, int totalArgCount) {
void _genStaticCall(Member target, ConstantArgDesc argDesc, int totalArgCount,
{bool isGet: false, bool isSet: false}) {
assert(!isGet || !isSet);
final argDescIndex = cp.add(argDesc);
final icdataIndex = cp.add(new ConstantStaticICData(target, argDescIndex));
final kind = isGet
? InvocationKind.getter
: (isSet ? InvocationKind.setter : InvocationKind.method);
final icdataIndex =
cp.add(new ConstantStaticICData(kind, target, argDescIndex));
asm.emitPushConstant(icdataIndex);
asm.emitIndirectStaticCall(totalArgCount, argDescIndex);
@ -848,7 +853,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
node.receiver.accept(this);
final target = node.target;
if (target is Field || (target is Procedure && target.isGetter)) {
_genStaticCall(target, new ConstantArgDesc(1), 1);
_genStaticCall(target, new ConstantArgDesc(1), 1, isGet: true);
} else {
throw new UnsupportedOperationError(
'Unsupported DirectPropertyGet with ${target.runtimeType} $target');
@ -1053,7 +1058,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
'Unsupported SuperPropertyGet without target');
}
if (target is Field || (target is Procedure && target.isGetter)) {
_genStaticCall(target, new ConstantArgDesc(1), 1);
_genStaticCall(target, new ConstantArgDesc(1), 1, isGet: true);
} else {
throw new UnsupportedOperationError(
'Unsupported SuperPropertyGet with target ${target.runtimeType} $target');
@ -1113,11 +1118,11 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
fieldIndex); // TODO(alexmarkov): do we really need this?
asm.emitPushStatic(fieldIndex);
} else {
_genStaticCall(target, new ConstantArgDesc(0), 0);
_genStaticCall(target, new ConstantArgDesc(0), 0, isGet: true);
}
} else if (target is Procedure) {
if (target.isGetter) {
_genStaticCall(target, new ConstantArgDesc(0), 0);
_genStaticCall(target, new ConstantArgDesc(0), 0, isGet: true);
} else {
final tearOffIndex = cp.add(new ConstantTearOff(target));
asm.emitPushConstant(tearOffIndex);
@ -1152,7 +1157,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
int cpIndex = cp.add(new ConstantField(target));
asm.emitStoreStaticTOS(cpIndex);
} else {
_genStaticCall(target, new ConstantArgDesc(1), 1);
_genStaticCall(target, new ConstantArgDesc(1), 1, isSet: true);
asm.emitDrop1();
}
}

View file

@ -200,7 +200,7 @@ Bytecode {
}
ConstantPool {
[0] = ArgDesc num-args 0, num-type-args 0, names []
[1] = StaticICData target '#lib::_NamespaceImpl::_namespace', arg-desc CP#0
[1] = StaticICData get target '#lib::_NamespaceImpl::_namespace', arg-desc CP#0
[2] = ArgDesc num-args 1, num-type-args 0, names []
[3] = StaticICData target '#lib::_NamespaceImpl::_getPointer', arg-desc CP#2
[4] = Null
@ -259,7 +259,7 @@ Bytecode {
}
ConstantPool {
[0] = ArgDesc num-args 0, num-type-args 0, names []
[1] = StaticICData target '#lib::_NamespaceImpl::_namespace', arg-desc CP#0
[1] = StaticICData get target '#lib::_NamespaceImpl::_namespace', arg-desc CP#0
[2] = Null
}
] static get _namespace() → self::_Namespace
@ -276,7 +276,7 @@ Bytecode {
}
ConstantPool {
[0] = ArgDesc num-args 0, num-type-args 0, names []
[1] = StaticICData target '#lib::_NamespaceImpl::_namespacePointer', arg-desc CP#0
[1] = StaticICData get target '#lib::_NamespaceImpl::_namespacePointer', arg-desc CP#0
[2] = Null
}
] static get _namespacePointer() → core::int
@ -714,7 +714,7 @@ ConstantPool {
[9] = ArgDesc num-args 1, num-type-args 0, names []
[10] = StaticICData target 'dart.core::Uri::parse', arg-desc CP#9
[11] = ArgDesc num-args 0, num-type-args 0, names []
[12] = StaticICData target 'dart.core::Uri::base', arg-desc CP#11
[12] = StaticICData get target 'dart.core::Uri::base', arg-desc CP#11
[13] = Null
[14] = StaticICData target 'dart.core::_Uri::file', arg-desc CP#9
[15] = ICData target-name 'resolveUri', arg-desc CP#2
@ -744,7 +744,7 @@ Bytecode {
ConstantPool {
[0] = TearOff #lib::_scriptUri
[1] = ArgDesc num-args 1, num-type-args 0, names []
[2] = StaticICData target '#lib::VMLibraryHooks::platformScript', arg-desc CP#1
[2] = StaticICData set target '#lib::VMLibraryHooks::platformScript', arg-desc CP#1
[3] = Null
}
]static method _setupHooks() → dynamic {

View file

@ -125,7 +125,7 @@ Bytecode {
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
[1] = StaticICData target '#lib::A::_name', arg-desc CP#0
[1] = StaticICData get target '#lib::A::_name', arg-desc CP#0
[2] = Null
}
] method toString() → core::String