mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:59:38 +00:00
[vm/bytecode] Replace InstanceCall instruction with InterfaceCall and DynamicCall.
Dispatch interface calls via hashtable rather than inline cache. InterfaceCall doesn't need to take arguments descriptor into account when doing method lookup. Change-Id: I30eae6ea638d1d2ad2cf3ff073c653fee3377f31 Reviewed-on: https://dart-review.googlesource.com/c/86106 Reviewed-by: Zach Anderson <zra@google.com> Commit-Queue: Régis Crelier <regis@google.com>
This commit is contained in:
parent
e2007126eb
commit
25851db73d
|
@ -271,9 +271,14 @@ class BytecodeAssembler {
|
|||
emitWord(_encodeAD(Opcode.kIndirectStaticCall, ra, rd));
|
||||
}
|
||||
|
||||
void emitInstanceCall(int ra, int rd) {
|
||||
void emitInterfaceCall(int ra, int rd) {
|
||||
emitSourcePosition();
|
||||
emitWord(_encodeAD(Opcode.kInstanceCall, ra, rd));
|
||||
emitWord(_encodeAD(Opcode.kInterfaceCall, ra, rd));
|
||||
}
|
||||
|
||||
void emitDynamicCall(int ra, int rd) {
|
||||
emitSourcePosition();
|
||||
emitWord(_encodeAD(Opcode.kDynamicCall, ra, rd));
|
||||
}
|
||||
|
||||
void emitNativeCall(int rd) {
|
||||
|
|
|
@ -169,6 +169,15 @@ type ConstantSymbol extends ConstantPoolEntry {
|
|||
PackedObject name;
|
||||
}
|
||||
|
||||
// Occupies 2 entries in the constant pool.
|
||||
type ConstantInterfaceCall extends ConstantPoolEntry {
|
||||
Byte tag = 26;
|
||||
Byte flags(invocationKindBit0, invocationKindBit1);
|
||||
// Where invocationKind is index into InvocationKind.
|
||||
PackedObject targetName;
|
||||
ConstantIndex argDesc;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
enum ConstantTag {
|
||||
|
@ -198,6 +207,7 @@ enum ConstantTag {
|
|||
kPartialTearOffInstantiation,
|
||||
kEmptyTypeArguments,
|
||||
kSymbol,
|
||||
kInterfaceCall,
|
||||
}
|
||||
|
||||
abstract class ConstantPoolEntry {
|
||||
|
@ -271,6 +281,8 @@ abstract class ConstantPoolEntry {
|
|||
return new ConstantEmptyTypeArguments.read(reader);
|
||||
case ConstantTag.kSymbol:
|
||||
return new ConstantSymbol.read(reader);
|
||||
case ConstantTag.kInterfaceCall:
|
||||
return new ConstantInterfaceCall.read(reader);
|
||||
}
|
||||
throw 'Unexpected constant tag $tag';
|
||||
}
|
||||
|
@ -1071,6 +1083,50 @@ class ConstantSymbol extends ConstantPoolEntry {
|
|||
bool operator ==(other) => other is ConstantSymbol && this.name == other.name;
|
||||
}
|
||||
|
||||
class ConstantInterfaceCall extends ConstantPoolEntry {
|
||||
final InvocationKind invocationKind;
|
||||
final ObjectHandle targetName;
|
||||
final int argDescConstantIndex;
|
||||
|
||||
ConstantInterfaceCall(
|
||||
this.invocationKind, this.targetName, this.argDescConstantIndex);
|
||||
|
||||
// Reserve 1 extra slot for arguments descriptor, following target name slot.
|
||||
int get numReservedEntries => 1;
|
||||
|
||||
@override
|
||||
ConstantTag get tag => ConstantTag.kInterfaceCall;
|
||||
|
||||
@override
|
||||
void writeValue(BufferedWriter writer) {
|
||||
writer.writeByte(invocationKind.index);
|
||||
writer.writePackedObject(targetName);
|
||||
writer.writePackedUInt30(argDescConstantIndex);
|
||||
}
|
||||
|
||||
ConstantInterfaceCall.read(BufferedReader reader)
|
||||
: invocationKind = InvocationKind.values[reader.readByte()],
|
||||
targetName = reader.readPackedObject(),
|
||||
argDescConstantIndex = reader.readPackedUInt30();
|
||||
|
||||
@override
|
||||
String toString() => 'InterfaceCall '
|
||||
'${_invocationKindToString(invocationKind)}'
|
||||
'target-name \'$targetName\', arg-desc CP#$argDescConstantIndex';
|
||||
|
||||
@override
|
||||
int get hashCode => _combineHashes(
|
||||
_combineHashes(invocationKind.index, targetName.hashCode),
|
||||
argDescConstantIndex);
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is ConstantInterfaceCall &&
|
||||
this.invocationKind == other.invocationKind &&
|
||||
this.targetName == other.targetName &&
|
||||
this.argDescConstantIndex == other.argDescConstantIndex;
|
||||
}
|
||||
|
||||
/// Reserved constant pool entry.
|
||||
class _ReservedConstantPoolEntry extends ConstantPoolEntry {
|
||||
const _ReservedConstantPoolEntry();
|
||||
|
@ -1131,6 +1187,23 @@ class ConstantPool {
|
|||
isSetter: invocationKind == InvocationKind.setter),
|
||||
argDescCpIndex));
|
||||
|
||||
int addInterfaceCall(
|
||||
InvocationKind invocationKind, Name targetName, int argDescCpIndex) =>
|
||||
_add(new ConstantInterfaceCall(
|
||||
invocationKind,
|
||||
objectTable.getSelectorNameHandle(targetName,
|
||||
isGetter: invocationKind == InvocationKind.getter,
|
||||
isSetter: invocationKind == InvocationKind.setter),
|
||||
argDescCpIndex));
|
||||
|
||||
int addInstanceCall(
|
||||
InvocationKind invocationKind, Name targetName, int argDescCpIndex,
|
||||
{bool isDynamic: false}) =>
|
||||
isDynamic
|
||||
? addICData(invocationKind, targetName, argDescCpIndex,
|
||||
isDynamic: true)
|
||||
: addInterfaceCall(invocationKind, targetName, argDescCpIndex);
|
||||
|
||||
int addStaticField(Field field) =>
|
||||
_add(new ConstantStaticField(objectTable.getHandle(field)));
|
||||
|
||||
|
|
|
@ -82,7 +82,8 @@ enum Opcode {
|
|||
|
||||
// Calls.
|
||||
kIndirectStaticCall,
|
||||
kInstanceCall,
|
||||
kInterfaceCall,
|
||||
kDynamicCall,
|
||||
kNativeCall,
|
||||
kReturnTOS,
|
||||
|
||||
|
@ -235,7 +236,9 @@ const Map<Opcode, Format> BytecodeFormats = const {
|
|||
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
|
||||
Opcode.kIndirectStaticCall: const Format(
|
||||
Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
|
||||
Opcode.kInstanceCall: const Format(
|
||||
Opcode.kInterfaceCall: const Format(
|
||||
Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
|
||||
Opcode.kDynamicCall: const Format(
|
||||
Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
|
||||
Opcode.kNativeCall: const Format(
|
||||
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
|
||||
|
@ -312,7 +315,8 @@ bool isThrow(Opcode opcode) => opcode == Opcode.kThrow;
|
|||
bool isCall(Opcode opcode) {
|
||||
switch (opcode) {
|
||||
case Opcode.kIndirectStaticCall:
|
||||
case Opcode.kInstanceCall:
|
||||
case Opcode.kInterfaceCall:
|
||||
case Opcode.kDynamicCall:
|
||||
case Opcode.kNativeCall:
|
||||
return true;
|
||||
default:
|
||||
|
|
|
@ -772,9 +772,9 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
assert(type.classNode.typeParameters.isEmpty);
|
||||
asm.emitPushConstant(cp.addType(type));
|
||||
final argDescIndex = cp.addArgDesc(2);
|
||||
final icdataIndex = cp.addICData(
|
||||
final icdataIndex = cp.addInterfaceCall(
|
||||
InvocationKind.method, objectSimpleInstanceOf.name, argDescIndex);
|
||||
asm.emitInstanceCall(2, icdataIndex);
|
||||
asm.emitInterfaceCall(2, icdataIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -786,9 +786,9 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
}
|
||||
asm.emitPushConstant(cp.addType(type));
|
||||
final argDescIndex = cp.addArgDesc(4);
|
||||
final icdataIndex = cp.addICData(
|
||||
final icdataIndex = cp.addInterfaceCall(
|
||||
InvocationKind.method, objectInstanceOf.name, argDescIndex);
|
||||
asm.emitInstanceCall(4, icdataIndex);
|
||||
asm.emitInterfaceCall(4, icdataIndex);
|
||||
}
|
||||
|
||||
void start(Member node) {
|
||||
|
@ -1945,6 +1945,14 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
asm.emitBytecode0(opcode);
|
||||
}
|
||||
|
||||
void _genInstanceCall(int totalArgCount, int icdataCpIndex, bool isDynamic) {
|
||||
if (isDynamic) {
|
||||
asm.emitDynamicCall(totalArgCount, icdataCpIndex);
|
||||
} else {
|
||||
asm.emitInterfaceCall(totalArgCount, icdataCpIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
visitMethodInvocation(MethodInvocation node) {
|
||||
final Opcode opcode = recognizedMethods.specializedBytecodeFor(node);
|
||||
|
@ -1953,26 +1961,28 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
return;
|
||||
}
|
||||
final args = node.arguments;
|
||||
final isDynamic = node.interfaceTarget == null;
|
||||
_genArguments(node.receiver, args);
|
||||
final argDescIndex = cp.addArgDescByArguments(args, hasReceiver: true);
|
||||
final icdataIndex = cp.addICData(
|
||||
final icdataIndex = cp.addInstanceCall(
|
||||
InvocationKind.method, node.name, argDescIndex,
|
||||
isDynamic: node.interfaceTarget == null);
|
||||
isDynamic: isDynamic);
|
||||
final totalArgCount = args.positional.length +
|
||||
args.named.length +
|
||||
1 /* receiver */ +
|
||||
(args.types.isNotEmpty ? 1 : 0) /* type arguments */;
|
||||
asm.emitInstanceCall(totalArgCount, icdataIndex);
|
||||
_genInstanceCall(totalArgCount, icdataIndex, isDynamic);
|
||||
}
|
||||
|
||||
@override
|
||||
visitPropertyGet(PropertyGet node) {
|
||||
_generateNode(node.receiver);
|
||||
final isDynamic = node.interfaceTarget == null;
|
||||
final argDescIndex = cp.addArgDesc(1);
|
||||
final icdataIndex = cp.addICData(
|
||||
final icdataIndex = cp.addInstanceCall(
|
||||
InvocationKind.getter, node.name, argDescIndex,
|
||||
isDynamic: node.interfaceTarget == null);
|
||||
asm.emitInstanceCall(1, icdataIndex);
|
||||
isDynamic: isDynamic);
|
||||
_genInstanceCall(1, icdataIndex, isDynamic);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1987,11 +1997,12 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
asm.emitStoreLocal(temp);
|
||||
}
|
||||
|
||||
final isDynamic = node.interfaceTarget == null;
|
||||
final argDescIndex = cp.addArgDesc(2);
|
||||
final icdataIndex = cp.addICData(
|
||||
final icdataIndex = cp.addInstanceCall(
|
||||
InvocationKind.setter, node.name, argDescIndex,
|
||||
isDynamic: node.interfaceTarget == null);
|
||||
asm.emitInstanceCall(2, icdataIndex);
|
||||
isDynamic: isDynamic);
|
||||
_genInstanceCall(2, icdataIndex, isDynamic);
|
||||
asm.emitDrop1();
|
||||
|
||||
if (hasResult) {
|
||||
|
@ -2402,9 +2413,11 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
const kMoveNext = 'moveNext'; // Iterator.moveNext
|
||||
const kCurrent = 'current'; // Iterator.current
|
||||
|
||||
asm.emitInstanceCall(
|
||||
// Front-end inserts implicit cast (type check) which ensures that
|
||||
// result of iterable expression is Iterable<dynamic>.
|
||||
asm.emitInterfaceCall(
|
||||
1,
|
||||
cp.addICData(
|
||||
cp.addInterfaceCall(
|
||||
InvocationKind.getter, new Name(kIterator), cp.addArgDesc(1)));
|
||||
|
||||
final iteratorTemp = locals.tempIndexInFrame(node);
|
||||
|
@ -2436,9 +2449,9 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
asm.emitPush(iteratorTemp);
|
||||
}
|
||||
|
||||
asm.emitInstanceCall(
|
||||
asm.emitInterfaceCall(
|
||||
1,
|
||||
cp.addICData(
|
||||
cp.addInterfaceCall(
|
||||
InvocationKind.method, new Name(kMoveNext), cp.addArgDesc(1)));
|
||||
_genJumpIfFalse(/* negated = */ false, done);
|
||||
|
||||
|
@ -2447,9 +2460,9 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
_genPushContextIfCaptured(node.variable);
|
||||
|
||||
asm.emitPush(iteratorTemp);
|
||||
asm.emitInstanceCall(
|
||||
asm.emitInterfaceCall(
|
||||
1,
|
||||
cp.addICData(
|
||||
cp.addInterfaceCall(
|
||||
InvocationKind.getter, new Name(kCurrent), cp.addArgDesc(1)));
|
||||
|
||||
_genStoreVar(node.variable);
|
||||
|
@ -2606,9 +2619,9 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
for (var expr in switchCase.expressions) {
|
||||
asm.emitPush(temp);
|
||||
_genPushConstExpr(expr);
|
||||
asm.emitInstanceCall(
|
||||
asm.emitInterfaceCall(
|
||||
2,
|
||||
cp.addICData(
|
||||
cp.addInterfaceCall(
|
||||
InvocationKind.method, new Name('=='), equalsArgDesc));
|
||||
_genJumpIfTrue(/* negated = */ false, caseLabel);
|
||||
}
|
||||
|
|
|
@ -33,13 +33,13 @@ Bytecode {
|
|||
CheckStack 0
|
||||
JumpIfNoAsserts L1
|
||||
Push FP[-6]
|
||||
InstanceCall 1, CP#1
|
||||
DynamicCall 1, CP#1
|
||||
AssertBoolean 0
|
||||
JumpIfTrue L1
|
||||
PushInt 0
|
||||
PushInt 0
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#2
|
||||
DynamicCall 1, CP#2
|
||||
PushConstant CP#4
|
||||
IndirectStaticCall 3, CP#3
|
||||
Drop1
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -308,7 +308,7 @@ L2:
|
|||
JumpIfFalse L3
|
||||
PushConstant CP#1
|
||||
PushStatic CP#1
|
||||
InstanceCall 1, CP#3
|
||||
DynamicCall 1, CP#3
|
||||
StoreStaticTOS CP#0
|
||||
L3:
|
||||
PushConstant CP#0
|
||||
|
@ -402,8 +402,8 @@ Bytecode {
|
|||
Entry 0
|
||||
CheckStack 0
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#1
|
||||
PushConstant CP#2
|
||||
InterfaceCall 1, CP#1
|
||||
PushConstant CP#3
|
||||
IndirectStaticCall 1, CP#0
|
||||
Drop1
|
||||
PushNull
|
||||
|
@ -411,8 +411,9 @@ Bytecode {
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[1] = ICData target-name 'toString', arg-desc CP#0
|
||||
[2] = StaticICData target '#lib::_printString', arg-desc CP#0
|
||||
[1] = InterfaceCall target-name 'toString', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = StaticICData target '#lib::_printString', arg-desc CP#0
|
||||
}
|
||||
]static method _print(dynamic arg) → void {
|
||||
self::_printString(arg.{core::Object::toString}());
|
||||
|
@ -474,13 +475,13 @@ Bytecode {
|
|||
PushConstant CP#0
|
||||
PushStatic CP#0
|
||||
PushConstant CP#1
|
||||
InstanceCall 2, CP#3
|
||||
InterfaceCall 2, CP#3
|
||||
AssertBoolean 0
|
||||
JumpIfTrue L1
|
||||
PushConstant CP#0
|
||||
PushStatic CP#0
|
||||
PushConstant CP#4
|
||||
InstanceCall 2, CP#5
|
||||
PushConstant CP#5
|
||||
InterfaceCall 2, CP#3
|
||||
AssertBoolean 0
|
||||
PopLocal r1
|
||||
Jump L2
|
||||
|
@ -493,7 +494,7 @@ L2:
|
|||
PushConstant CP#0
|
||||
PushStatic CP#0
|
||||
PushConstant CP#6
|
||||
InstanceCall 2, CP#7
|
||||
InterfaceCall 2, CP#3
|
||||
AssertBoolean 0
|
||||
PopLocal r0
|
||||
Jump L4
|
||||
|
@ -505,35 +506,35 @@ L4:
|
|||
JumpIfFalse L5
|
||||
PushConstant CP#0
|
||||
PushStatic CP#0
|
||||
PushConstant CP#9
|
||||
IndirectStaticCall 1, CP#8
|
||||
PushConstant CP#8
|
||||
IndirectStaticCall 1, CP#7
|
||||
ReturnTOS
|
||||
L5:
|
||||
PushConstant CP#11
|
||||
IndirectStaticCall 0, CP#10
|
||||
PushConstant CP#10
|
||||
IndirectStaticCall 0, CP#9
|
||||
PushNull
|
||||
PushConstant CP#0
|
||||
PushStatic CP#0
|
||||
PushConstant CP#12
|
||||
PushConstant CP#11
|
||||
IndirectStaticCall 2, CP#2
|
||||
InstanceCall 2, CP#13
|
||||
InterfaceCall 2, CP#12
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = StaticField #lib::_rawScript (field)
|
||||
[1] = String 'http:'
|
||||
[2] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[3] = ICData target-name 'startsWith', arg-desc CP#2
|
||||
[4] = String 'https:'
|
||||
[5] = ICData target-name 'startsWith', arg-desc CP#2
|
||||
[3] = InterfaceCall target-name 'startsWith', arg-desc CP#2
|
||||
[4] = Reserved
|
||||
[5] = String 'https:'
|
||||
[6] = String 'file:'
|
||||
[7] = ICData target-name 'startsWith', arg-desc CP#2
|
||||
[8] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[9] = StaticICData target 'dart:core::Uri::parse', arg-desc CP#8
|
||||
[10] = ArgDesc num-args 0, num-type-args 0, names []
|
||||
[11] = StaticICData target 'dart:core::Uri::get:base', arg-desc CP#10
|
||||
[12] = StaticICData target 'dart:core::_Uri::file (constructor)', arg-desc CP#2
|
||||
[13] = ICData target-name 'resolveUri', arg-desc CP#2
|
||||
[7] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[8] = StaticICData target 'dart:core::Uri::parse', arg-desc CP#7
|
||||
[9] = ArgDesc num-args 0, num-type-args 0, names []
|
||||
[10] = StaticICData target 'dart:core::Uri::get:base', arg-desc CP#9
|
||||
[11] = StaticICData target 'dart:core::_Uri::file (constructor)', arg-desc CP#2
|
||||
[12] = InterfaceCall target-name 'resolveUri', arg-desc CP#2
|
||||
[13] = Reserved
|
||||
}
|
||||
]static method _scriptUri() → core::Uri {
|
||||
if(self::_rawScript.{core::String::startsWith}("http:") || self::_rawScript.{core::String::startsWith}("https:") || self::_rawScript.{core::String::startsWith}("file:")) {
|
||||
|
|
|
@ -213,11 +213,11 @@ Bytecode {
|
|||
PopLocal r3
|
||||
PushConstant CP#44
|
||||
Push r3
|
||||
InstanceCall 2, CP#45
|
||||
DynamicCall 2, CP#45
|
||||
Drop1
|
||||
PushConstant CP#46
|
||||
Push r3
|
||||
InstanceCall 2, CP#47
|
||||
DynamicCall 2, CP#47
|
||||
Drop1
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
@ -319,11 +319,11 @@ L2:
|
|||
PopLocal r3
|
||||
PushConstant CP#38
|
||||
Push r3
|
||||
InstanceCall 2, CP#40
|
||||
DynamicCall 2, CP#40
|
||||
Drop1
|
||||
PushConstant CP#41
|
||||
Push r3
|
||||
InstanceCall 2, CP#42
|
||||
DynamicCall 2, CP#42
|
||||
Drop1
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
@ -376,7 +376,7 @@ L2:
|
|||
StoreFieldTOS CP#1
|
||||
PopLocal r3
|
||||
Push r3
|
||||
InstanceCall 1, CP#36
|
||||
DynamicCall 1, CP#36
|
||||
Drop1
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
@ -522,69 +522,69 @@ Bytecode {
|
|||
Push r0
|
||||
PushInt 3
|
||||
StoreContextVar 0, 2
|
||||
Allocate CP#10
|
||||
Allocate CP#11
|
||||
StoreLocal r4
|
||||
Push r4
|
||||
PushNull
|
||||
StoreFieldTOS CP#11
|
||||
StoreFieldTOS CP#12
|
||||
Push r4
|
||||
PushNull
|
||||
StoreFieldTOS CP#13
|
||||
StoreFieldTOS CP#14
|
||||
Push r4
|
||||
PushConstant CP#15
|
||||
StoreFieldTOS CP#16
|
||||
PushConstant CP#16
|
||||
StoreFieldTOS CP#17
|
||||
Push r4
|
||||
PushConstant CP#0
|
||||
StoreFieldTOS CP#18
|
||||
StoreFieldTOS CP#19
|
||||
Push r4
|
||||
Push r0
|
||||
StoreFieldTOS CP#1
|
||||
PopLocal r3
|
||||
Push r3
|
||||
PushInt 10
|
||||
InstanceCall 2, CP#24
|
||||
DynamicCall 2, CP#25
|
||||
Drop1
|
||||
Push r3
|
||||
PushInt 11
|
||||
InstanceCall 2, CP#25
|
||||
DynamicCall 2, CP#26
|
||||
Drop1
|
||||
Push r2
|
||||
PushConstant CP#26
|
||||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 2
|
||||
PushConstant CP#27
|
||||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 1
|
||||
LoadContextVar 0, 2
|
||||
PushConstant CP#28
|
||||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 1
|
||||
PushConstant CP#29
|
||||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
Push r0
|
||||
PushInt 42
|
||||
StoreContextVar 0, 3
|
||||
Allocate CP#10
|
||||
Allocate CP#11
|
||||
StoreLocal r3
|
||||
Push r3
|
||||
PushNull
|
||||
StoreFieldTOS CP#11
|
||||
StoreFieldTOS CP#12
|
||||
Push r3
|
||||
PushNull
|
||||
StoreFieldTOS CP#13
|
||||
StoreFieldTOS CP#14
|
||||
Push r3
|
||||
PushConstant CP#15
|
||||
StoreFieldTOS CP#16
|
||||
PushConstant CP#16
|
||||
StoreFieldTOS CP#17
|
||||
Push r3
|
||||
PushConstant CP#29
|
||||
StoreFieldTOS CP#18
|
||||
PushConstant CP#30
|
||||
StoreFieldTOS CP#19
|
||||
Push r3
|
||||
Push r0
|
||||
StoreFieldTOS CP#1
|
||||
PopLocal r2
|
||||
Push r2
|
||||
InstanceCall 1, CP#32
|
||||
DynamicCall 1, CP#34
|
||||
Drop1
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
@ -598,31 +598,33 @@ ConstantPool {
|
|||
[5] = SubtypeTestCache
|
||||
[6] = ClosureFunction 1
|
||||
[7] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[8] = ICData get target-name 'get:foo', arg-desc CP#7
|
||||
[9] = EndClosureFunctionScope
|
||||
[10] = Class dart:core::_Closure
|
||||
[11] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
|
||||
[12] = Reserved
|
||||
[13] = InstanceField dart:core::_Closure::_function_type_arguments (field)
|
||||
[14] = Reserved
|
||||
[15] = EmptyTypeArguments
|
||||
[16] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
|
||||
[17] = Reserved
|
||||
[18] = InstanceField dart:core::_Closure::_function (field)
|
||||
[19] = Reserved
|
||||
[20] = ICData dynamic target-name 'call', arg-desc CP#7
|
||||
[21] = StaticICData target 'dart:core::print', arg-desc CP#7
|
||||
[22] = EndClosureFunctionScope
|
||||
[23] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[24] = ICData dynamic target-name 'call', arg-desc CP#23
|
||||
[25] = ICData dynamic target-name 'call', arg-desc CP#23
|
||||
[26] = StaticICData target 'dart:core::print', arg-desc CP#7
|
||||
[8] = InterfaceCall get target-name 'get:foo', arg-desc CP#7
|
||||
[9] = Reserved
|
||||
[10] = EndClosureFunctionScope
|
||||
[11] = Class dart:core::_Closure
|
||||
[12] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
|
||||
[13] = Reserved
|
||||
[14] = InstanceField dart:core::_Closure::_function_type_arguments (field)
|
||||
[15] = Reserved
|
||||
[16] = EmptyTypeArguments
|
||||
[17] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
|
||||
[18] = Reserved
|
||||
[19] = InstanceField dart:core::_Closure::_function (field)
|
||||
[20] = Reserved
|
||||
[21] = ICData dynamic target-name 'call', arg-desc CP#7
|
||||
[22] = StaticICData target 'dart:core::print', arg-desc CP#7
|
||||
[23] = EndClosureFunctionScope
|
||||
[24] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[25] = ICData dynamic target-name 'call', arg-desc CP#24
|
||||
[26] = ICData dynamic target-name 'call', arg-desc CP#24
|
||||
[27] = StaticICData target 'dart:core::print', arg-desc CP#7
|
||||
[28] = StaticICData target 'dart:core::print', arg-desc CP#7
|
||||
[29] = ClosureFunction 2
|
||||
[30] = ICData set target-name 'set:foo', arg-desc CP#23
|
||||
[31] = EndClosureFunctionScope
|
||||
[32] = ICData dynamic target-name 'call', arg-desc CP#7
|
||||
[29] = StaticICData target 'dart:core::print', arg-desc CP#7
|
||||
[30] = ClosureFunction 2
|
||||
[31] = InterfaceCall set target-name 'set:foo', arg-desc CP#24
|
||||
[32] = Reserved
|
||||
[33] = EndClosureFunctionScope
|
||||
[34] = ICData dynamic target-name 'call', arg-desc CP#7
|
||||
}
|
||||
Closure #lib::B::topLevel::<anonymous closure> (dart:core::int y) -> dart:core::Null
|
||||
ClosureBytecode {
|
||||
|
@ -663,30 +665,30 @@ ClosureBytecode {
|
|||
Push r0
|
||||
PushInt 4
|
||||
StoreContextVar 1, 1
|
||||
Allocate CP#10
|
||||
Allocate CP#11
|
||||
StoreLocal r2
|
||||
Push r2
|
||||
PushNull
|
||||
StoreFieldTOS CP#11
|
||||
StoreFieldTOS CP#12
|
||||
Push r2
|
||||
PushNull
|
||||
StoreFieldTOS CP#13
|
||||
StoreFieldTOS CP#14
|
||||
Push r2
|
||||
PushConstant CP#15
|
||||
StoreFieldTOS CP#16
|
||||
PushConstant CP#16
|
||||
StoreFieldTOS CP#17
|
||||
Push r2
|
||||
PushConstant CP#6
|
||||
StoreFieldTOS CP#18
|
||||
StoreFieldTOS CP#19
|
||||
Push r2
|
||||
Push r0
|
||||
StoreFieldTOS CP#1
|
||||
PopLocal r3
|
||||
Push r3
|
||||
InstanceCall 1, CP#20
|
||||
DynamicCall 1, CP#21
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 1, 1
|
||||
PushConstant CP#21
|
||||
PushConstant CP#22
|
||||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
L1:
|
||||
|
@ -714,7 +716,7 @@ ClosureBytecode {
|
|||
Push r0
|
||||
LoadContextParent
|
||||
LoadContextVar 0, 0
|
||||
InstanceCall 1, CP#8
|
||||
InterfaceCall 1, CP#8
|
||||
Push r0
|
||||
LoadContextVar 1, 0
|
||||
AddInt
|
||||
|
@ -735,7 +737,7 @@ ClosureBytecode {
|
|||
LoadContextVar 0, 0
|
||||
Push r0
|
||||
LoadContextVar 0, 3
|
||||
InstanceCall 2, CP#30
|
||||
InterfaceCall 2, CP#31
|
||||
Drop1
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
@ -855,7 +857,7 @@ L2:
|
|||
Push r3
|
||||
Push r0
|
||||
StoreFieldTOS CP#5
|
||||
InstanceCall 2, CP#18
|
||||
InterfaceCall 2, CP#18
|
||||
Drop1
|
||||
Push r4
|
||||
Allocate CP#8
|
||||
|
@ -870,12 +872,12 @@ L2:
|
|||
PushConstant CP#13
|
||||
StoreFieldTOS CP#14
|
||||
Push r3
|
||||
PushConstant CP#19
|
||||
PushConstant CP#20
|
||||
StoreFieldTOS CP#16
|
||||
Push r3
|
||||
Push r0
|
||||
StoreFieldTOS CP#5
|
||||
InstanceCall 2, CP#24
|
||||
InterfaceCall 2, CP#18
|
||||
Drop1
|
||||
Push r0
|
||||
CloneContext 1, 1
|
||||
|
@ -919,13 +921,13 @@ ConstantPool {
|
|||
[15] = Reserved
|
||||
[16] = InstanceField dart:core::_Closure::_function (field)
|
||||
[17] = Reserved
|
||||
[18] = ICData target-name 'add', arg-desc CP#1
|
||||
[19] = ClosureFunction 1
|
||||
[20] = Type dart:core::int
|
||||
[21] = String 'ii'
|
||||
[22] = SubtypeTestCache
|
||||
[23] = EndClosureFunctionScope
|
||||
[24] = ICData target-name 'add', arg-desc CP#1
|
||||
[18] = InterfaceCall target-name 'add', arg-desc CP#1
|
||||
[19] = Reserved
|
||||
[20] = ClosureFunction 1
|
||||
[21] = Type dart:core::int
|
||||
[22] = String 'ii'
|
||||
[23] = SubtypeTestCache
|
||||
[24] = EndClosureFunctionScope
|
||||
}
|
||||
Closure #lib::C::testForLoop::<anonymous closure> () -> dart:core::int
|
||||
ClosureBytecode {
|
||||
|
@ -952,11 +954,11 @@ ClosureBytecode {
|
|||
LoadFieldTOS CP#5
|
||||
PopLocal r0
|
||||
Push FP[-5]
|
||||
PushConstant CP#20
|
||||
PushNull
|
||||
PushNull
|
||||
PushConstant CP#21
|
||||
AssertAssignable 1, CP#22
|
||||
PushNull
|
||||
PushNull
|
||||
PushConstant CP#22
|
||||
AssertAssignable 1, CP#23
|
||||
Drop1
|
||||
Push r0
|
||||
Push FP[-5]
|
||||
|
@ -985,43 +987,43 @@ Bytecode {
|
|||
Entry 5
|
||||
CheckStack 0
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#1
|
||||
InterfaceCall 1, CP#1
|
||||
PopLocal r2
|
||||
L2:
|
||||
CheckStack 1
|
||||
Push r2
|
||||
InstanceCall 1, CP#2
|
||||
InterfaceCall 1, CP#3
|
||||
JumpIfFalse L1
|
||||
AllocateContext 0, 1
|
||||
PopLocal r0
|
||||
Push r0
|
||||
Push r2
|
||||
InstanceCall 1, CP#3
|
||||
InterfaceCall 1, CP#5
|
||||
StoreContextVar 0, 0
|
||||
Allocate CP#8
|
||||
Allocate CP#11
|
||||
StoreLocal r4
|
||||
Push r4
|
||||
PushNull
|
||||
StoreFieldTOS CP#9
|
||||
StoreFieldTOS CP#12
|
||||
Push r4
|
||||
PushNull
|
||||
StoreFieldTOS CP#11
|
||||
Push r4
|
||||
PushConstant CP#13
|
||||
StoreFieldTOS CP#14
|
||||
Push r4
|
||||
PushConstant CP#4
|
||||
StoreFieldTOS CP#16
|
||||
PushConstant CP#16
|
||||
StoreFieldTOS CP#17
|
||||
Push r4
|
||||
PushConstant CP#7
|
||||
StoreFieldTOS CP#19
|
||||
Push r4
|
||||
Push r0
|
||||
StoreFieldTOS CP#5
|
||||
StoreFieldTOS CP#8
|
||||
PopLocal r3
|
||||
Push r3
|
||||
InstanceCall 1, CP#18
|
||||
DynamicCall 1, CP#21
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#19
|
||||
PushConstant CP#22
|
||||
IndirectStaticCall 1, CP#0
|
||||
Drop1
|
||||
Push r0
|
||||
|
@ -1034,32 +1036,35 @@ L1:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[1] = ICData get target-name 'get:iterator', arg-desc CP#0
|
||||
[2] = ICData target-name 'moveNext', arg-desc CP#0
|
||||
[3] = ICData get target-name 'get:current', arg-desc CP#0
|
||||
[4] = ClosureFunction 0
|
||||
[5] = InstanceField dart:core::_Closure::_context (field)
|
||||
[1] = InterfaceCall get target-name 'get:iterator', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = InterfaceCall target-name 'moveNext', arg-desc CP#0
|
||||
[4] = Reserved
|
||||
[5] = InterfaceCall get target-name 'get:current', arg-desc CP#0
|
||||
[6] = Reserved
|
||||
[7] = EndClosureFunctionScope
|
||||
[8] = Class dart:core::_Closure
|
||||
[9] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
|
||||
[10] = Reserved
|
||||
[11] = InstanceField dart:core::_Closure::_function_type_arguments (field)
|
||||
[12] = Reserved
|
||||
[13] = EmptyTypeArguments
|
||||
[14] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
|
||||
[7] = ClosureFunction 0
|
||||
[8] = InstanceField dart:core::_Closure::_context (field)
|
||||
[9] = Reserved
|
||||
[10] = EndClosureFunctionScope
|
||||
[11] = Class dart:core::_Closure
|
||||
[12] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
|
||||
[13] = Reserved
|
||||
[14] = InstanceField dart:core::_Closure::_function_type_arguments (field)
|
||||
[15] = Reserved
|
||||
[16] = InstanceField dart:core::_Closure::_function (field)
|
||||
[17] = Reserved
|
||||
[18] = ICData dynamic target-name 'call', arg-desc CP#0
|
||||
[19] = StaticICData target 'dart:core::print', arg-desc CP#0
|
||||
[16] = EmptyTypeArguments
|
||||
[17] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
|
||||
[18] = Reserved
|
||||
[19] = InstanceField dart:core::_Closure::_function (field)
|
||||
[20] = Reserved
|
||||
[21] = ICData dynamic target-name 'call', arg-desc CP#0
|
||||
[22] = StaticICData target 'dart:core::print', arg-desc CP#0
|
||||
}
|
||||
Closure #lib::C::testForInLoop::<anonymous closure> () -> dart:core::Null
|
||||
ClosureBytecode {
|
||||
EntryFixed 1, 3
|
||||
CheckStack 0
|
||||
Push FP[-5]
|
||||
LoadFieldTOS CP#5
|
||||
LoadFieldTOS CP#8
|
||||
PopLocal r0
|
||||
Push r0
|
||||
Push r0
|
||||
|
@ -1202,7 +1207,7 @@ Bytecode {
|
|||
PopLocal r2
|
||||
Push r2
|
||||
PushInt 3
|
||||
InstanceCall 2, CP#18
|
||||
DynamicCall 2, CP#18
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 0
|
||||
|
@ -1359,20 +1364,20 @@ Bytecode {
|
|||
PushConstant CP#4
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
InstanceCall 2, CP#6
|
||||
InterfaceCall 2, CP#6
|
||||
Drop1
|
||||
PushConstant CP#7
|
||||
PushConstant CP#8
|
||||
PushConstant CP#2
|
||||
PushConstant CP#1
|
||||
AllocateT
|
||||
StoreLocal r0
|
||||
Push r0
|
||||
PushConstant CP#8
|
||||
PushConstant CP#9
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
InstanceCall 2, CP#9
|
||||
InterfaceCall 2, CP#6
|
||||
Drop1
|
||||
PushConstant CP#7
|
||||
PushConstant CP#8
|
||||
PushConstant CP#10
|
||||
PushConstant CP#1
|
||||
AllocateT
|
||||
|
@ -1381,7 +1386,7 @@ Bytecode {
|
|||
PushConstant CP#11
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
InstanceCall 2, CP#12
|
||||
InterfaceCall 2, CP#6
|
||||
Drop1
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
@ -1393,13 +1398,12 @@ ConstantPool {
|
|||
[3] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[4] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
|
||||
[5] = ArgDesc num-args 1, num-type-args 2, names []
|
||||
[6] = ICData target-name 'foo', arg-desc CP#5
|
||||
[7] = TypeArgs [dart:core::List < #lib::C3 >, dart:core::List < #lib::C4 >]
|
||||
[8] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
|
||||
[9] = ICData target-name 'foo', arg-desc CP#5
|
||||
[6] = InterfaceCall target-name 'foo', arg-desc CP#5
|
||||
[7] = Reserved
|
||||
[8] = TypeArgs [dart:core::List < #lib::C3 >, dart:core::List < #lib::C4 >]
|
||||
[9] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
|
||||
[10] = TypeArgumentsForInstanceAllocation #lib::A [dart:core::List < #lib::C1 >, dart:core::List < #lib::C2 >]
|
||||
[11] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
|
||||
[12] = ICData target-name 'foo', arg-desc CP#5
|
||||
}
|
||||
]static method callA() → void {
|
||||
new self::A::•<self::C1, self::C2>().{self::A::foo}<self::C3, self::C4>();
|
||||
|
|
|
@ -483,15 +483,15 @@ Bytecode {
|
|||
Push r0
|
||||
PushInt 1
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#7
|
||||
InterfaceCall 1, CP#7
|
||||
StoreIndexedTOS
|
||||
Push r0
|
||||
PushInt 2
|
||||
PushConstant CP#8
|
||||
StoreIndexedTOS
|
||||
PushConstant CP#9
|
||||
IndirectStaticCall 2, CP#1
|
||||
StoreIndexedTOS
|
||||
PushConstant CP#10
|
||||
IndirectStaticCall 2, CP#1
|
||||
PushConstant CP#11
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
PushNull
|
||||
|
@ -505,10 +505,11 @@ ConstantPool {
|
|||
[4] = StaticICData target 'dart:core::print', arg-desc CP#3
|
||||
[5] = TypeArgs [dart:core::String]
|
||||
[6] = String 'a'
|
||||
[7] = ICData target-name 'toString', arg-desc CP#3
|
||||
[8] = String 'b'
|
||||
[9] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#1
|
||||
[10] = StaticICData target 'dart:core::print', arg-desc CP#3
|
||||
[7] = InterfaceCall target-name 'toString', arg-desc CP#3
|
||||
[8] = Reserved
|
||||
[9] = String 'b'
|
||||
[10] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#1
|
||||
[11] = StaticICData target 'dart:core::print', arg-desc CP#3
|
||||
}
|
||||
]static method test_list_literal(core::int a) → void {
|
||||
core::print(<core::int>[1, a, 3]);
|
||||
|
@ -561,29 +562,29 @@ Bytecode {
|
|||
Push r1
|
||||
PushInt 2
|
||||
Push FP[-6]
|
||||
InstanceCall 1, CP#8
|
||||
InterfaceCall 1, CP#8
|
||||
StoreIndexedTOS
|
||||
Push r1
|
||||
PushInt 3
|
||||
PushInt 3
|
||||
StoreIndexedTOS
|
||||
PushConstant CP#9
|
||||
IndirectStaticCall 2, CP#2
|
||||
PushConstant CP#10
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
PushNull
|
||||
Push r0
|
||||
InstantiateTypeArgumentsTOS 0, CP#11
|
||||
PushConstant CP#12
|
||||
PushConstant CP#13
|
||||
IndirectStaticCall 2, CP#2
|
||||
PushConstant CP#14
|
||||
PushConstant CP#11
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
PushNull
|
||||
Push r0
|
||||
InstantiateTypeArgumentsTOS 0, CP#15
|
||||
InstantiateTypeArgumentsTOS 0, CP#12
|
||||
PushConstant CP#13
|
||||
PushConstant CP#14
|
||||
IndirectStaticCall 2, CP#2
|
||||
PushConstant CP#15
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
PushNull
|
||||
Push r0
|
||||
InstantiateTypeArgumentsTOS 0, CP#16
|
||||
PushConstant CP#1
|
||||
PushInt 2
|
||||
CreateArrayTOS
|
||||
|
@ -596,9 +597,9 @@ Bytecode {
|
|||
PushInt 1
|
||||
PushInt 4
|
||||
StoreIndexedTOS
|
||||
PushConstant CP#16
|
||||
IndirectStaticCall 2, CP#2
|
||||
PushConstant CP#17
|
||||
IndirectStaticCall 2, CP#2
|
||||
PushConstant CP#18
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
PushNull
|
||||
|
@ -613,16 +614,17 @@ ConstantPool {
|
|||
[5] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[6] = TypeArgs [dart:core::String, dart:core::int]
|
||||
[7] = String 'foo'
|
||||
[8] = ICData target-name 'toString', arg-desc CP#4
|
||||
[9] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
|
||||
[10] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[11] = TypeArgs [dart:core::String, #lib::test_map_literal::TypeParam/0]
|
||||
[12] = List type-arg dynamic, entries CP# []
|
||||
[13] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
|
||||
[14] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[15] = TypeArgs [#lib::test_map_literal::TypeParam/0, dart:core::int]
|
||||
[16] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
|
||||
[17] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[8] = InterfaceCall target-name 'toString', arg-desc CP#4
|
||||
[9] = Reserved
|
||||
[10] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
|
||||
[11] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[12] = TypeArgs [dart:core::String, #lib::test_map_literal::TypeParam/0]
|
||||
[13] = List type-arg dynamic, entries CP# []
|
||||
[14] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
|
||||
[15] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[16] = TypeArgs [#lib::test_map_literal::TypeParam/0, dart:core::int]
|
||||
[17] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
|
||||
[18] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
}
|
||||
]static method test_map_literal<T extends core::Object = dynamic>(core::int a, core::int b, self::test_map_literal::T c) → void {
|
||||
core::print(<core::int, core::int>{1: a, b: 2});
|
||||
|
|
|
@ -14,13 +14,13 @@ L2:
|
|||
CheckStack 1
|
||||
Push r1
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#1
|
||||
InterfaceCall 1, CP#1
|
||||
CompareIntLt
|
||||
JumpIfFalse L1
|
||||
Push r0
|
||||
Push FP[-5]
|
||||
Push r1
|
||||
InstanceCall 2, CP#3
|
||||
InterfaceCall 2, CP#4
|
||||
AddInt
|
||||
PopLocal r0
|
||||
Push r1
|
||||
|
@ -35,9 +35,11 @@ L1:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[1] = ICData get target-name 'get:length', arg-desc CP#0
|
||||
[2] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[3] = ICData target-name '[]', arg-desc CP#2
|
||||
[1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[4] = InterfaceCall target-name '[]', arg-desc CP#3
|
||||
[5] = Reserved
|
||||
}
|
||||
]static method test_for(core::List<core::int> list) → core::int {
|
||||
core::int sum = 0;
|
||||
|
@ -62,7 +64,7 @@ L3:
|
|||
JumpIfFalse L1
|
||||
Push r1
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#1
|
||||
InterfaceCall 1, CP#1
|
||||
CompareIntGe
|
||||
JumpIfFalse L2
|
||||
Jump L1
|
||||
|
@ -70,7 +72,7 @@ L2:
|
|||
Push r0
|
||||
Push FP[-5]
|
||||
Push r1
|
||||
InstanceCall 2, CP#3
|
||||
InterfaceCall 2, CP#4
|
||||
AddInt
|
||||
PopLocal r0
|
||||
Push r1
|
||||
|
@ -85,9 +87,11 @@ L1:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[1] = ICData get target-name 'get:length', arg-desc CP#0
|
||||
[2] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[3] = ICData target-name '[]', arg-desc CP#2
|
||||
[1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[4] = InterfaceCall target-name '[]', arg-desc CP#3
|
||||
[5] = Reserved
|
||||
}
|
||||
]static method test_for_break(core::List<core::int> list) → core::int {
|
||||
core::int sum = 0;
|
||||
|
@ -113,7 +117,7 @@ L4:
|
|||
CheckStack 1
|
||||
Push r1
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#1
|
||||
InterfaceCall 1, CP#1
|
||||
CompareIntLt
|
||||
JumpIfFalse L1
|
||||
Push r1
|
||||
|
@ -125,7 +129,7 @@ L2:
|
|||
Push r0
|
||||
Push FP[-5]
|
||||
Push r1
|
||||
InstanceCall 2, CP#3
|
||||
InterfaceCall 2, CP#4
|
||||
AddInt
|
||||
PopLocal r0
|
||||
L3:
|
||||
|
@ -141,9 +145,11 @@ L1:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[1] = ICData get target-name 'get:length', arg-desc CP#0
|
||||
[2] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[3] = ICData target-name '[]', arg-desc CP#2
|
||||
[1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[4] = InterfaceCall target-name '[]', arg-desc CP#3
|
||||
[5] = Reserved
|
||||
}
|
||||
]static method test_for_continue(core::List<core::int> list) → core::int {
|
||||
core::int sum = 0;
|
||||
|
@ -169,7 +175,7 @@ L2:
|
|||
CheckStack 1
|
||||
Push r1
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#1
|
||||
InterfaceCall 1, CP#1
|
||||
CompareIntLt
|
||||
JumpIfFalse L1
|
||||
Push r0
|
||||
|
@ -182,7 +188,7 @@ L2:
|
|||
StoreLocal r1
|
||||
PopLocal r3
|
||||
Push r2
|
||||
InstanceCall 2, CP#3
|
||||
InterfaceCall 2, CP#4
|
||||
AddInt
|
||||
PopLocal r0
|
||||
Jump L2
|
||||
|
@ -192,9 +198,11 @@ L1:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[1] = ICData get target-name 'get:length', arg-desc CP#0
|
||||
[2] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[3] = ICData target-name '[]', arg-desc CP#2
|
||||
[1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[4] = InterfaceCall target-name '[]', arg-desc CP#3
|
||||
[5] = Reserved
|
||||
}
|
||||
]static method test_while(core::List<core::int> list) → core::int {
|
||||
core::int sum = 0;
|
||||
|
@ -217,7 +225,7 @@ L1:
|
|||
Push r0
|
||||
Push FP[-5]
|
||||
Push r1
|
||||
InstanceCall 2, CP#1
|
||||
InterfaceCall 2, CP#1
|
||||
AddInt
|
||||
PopLocal r0
|
||||
Push r1
|
||||
|
@ -226,7 +234,7 @@ L1:
|
|||
PopLocal r1
|
||||
Push r1
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#3
|
||||
InterfaceCall 1, CP#4
|
||||
CompareIntLt
|
||||
JumpIfTrue L1
|
||||
Push r0
|
||||
|
@ -234,9 +242,11 @@ L1:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[1] = ICData target-name '[]', arg-desc CP#0
|
||||
[2] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[3] = ICData get target-name 'get:length', arg-desc CP#2
|
||||
[1] = InterfaceCall target-name '[]', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[4] = InterfaceCall get target-name 'get:length', arg-desc CP#3
|
||||
[5] = Reserved
|
||||
}
|
||||
]static method test_do_while(core::List<core::int> list) → core::int {
|
||||
core::int sum = 0;
|
||||
|
@ -255,15 +265,15 @@ Bytecode {
|
|||
PushInt 0
|
||||
PopLocal r0
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#1
|
||||
InterfaceCall 1, CP#1
|
||||
PopLocal r1
|
||||
L2:
|
||||
CheckStack 1
|
||||
Push r1
|
||||
InstanceCall 1, CP#2
|
||||
InterfaceCall 1, CP#3
|
||||
JumpIfFalse L1
|
||||
Push r1
|
||||
InstanceCall 1, CP#3
|
||||
InterfaceCall 1, CP#5
|
||||
PopLocal r2
|
||||
Push r0
|
||||
Push r2
|
||||
|
@ -276,9 +286,12 @@ L1:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[1] = ICData get target-name 'get:iterator', arg-desc CP#0
|
||||
[2] = ICData target-name 'moveNext', arg-desc CP#0
|
||||
[3] = ICData get target-name 'get:current', arg-desc CP#0
|
||||
[1] = InterfaceCall get target-name 'get:iterator', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = InterfaceCall target-name 'moveNext', arg-desc CP#0
|
||||
[4] = Reserved
|
||||
[5] = InterfaceCall get target-name 'get:current', arg-desc CP#0
|
||||
[6] = Reserved
|
||||
}
|
||||
]static method test_for_in(core::List<core::int> list) → core::int {
|
||||
core::int sum = 0;
|
||||
|
@ -296,15 +309,15 @@ Bytecode {
|
|||
PushInt 42
|
||||
PopLocal r1
|
||||
Push FP[-5]
|
||||
InstanceCall 1, CP#1
|
||||
InterfaceCall 1, CP#1
|
||||
PopLocal r2
|
||||
L2:
|
||||
CheckStack 1
|
||||
Push r2
|
||||
InstanceCall 1, CP#2
|
||||
InterfaceCall 1, CP#3
|
||||
JumpIfFalse L1
|
||||
Push r2
|
||||
InstanceCall 1, CP#3
|
||||
InterfaceCall 1, CP#5
|
||||
PopLocal r3
|
||||
Push r3
|
||||
PopLocal r1
|
||||
|
@ -319,9 +332,12 @@ L1:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[1] = ICData get target-name 'get:iterator', arg-desc CP#0
|
||||
[2] = ICData target-name 'moveNext', arg-desc CP#0
|
||||
[3] = ICData get target-name 'get:current', arg-desc CP#0
|
||||
[1] = InterfaceCall get target-name 'get:iterator', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = InterfaceCall target-name 'moveNext', arg-desc CP#0
|
||||
[4] = Reserved
|
||||
[5] = InterfaceCall get target-name 'get:current', arg-desc CP#0
|
||||
[6] = Reserved
|
||||
}
|
||||
]static method test_for_in_with_outer_var(core::List<core::int> list) → core::int {
|
||||
core::int sum = 0;
|
||||
|
|
|
@ -132,7 +132,7 @@ Bytecode {
|
|||
PushConstant CP#2
|
||||
IndirectStaticCall 1, CP#1
|
||||
PushConstant CP#3
|
||||
InstanceCall 3, CP#5
|
||||
DynamicCall 3, CP#5
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
|
@ -347,7 +347,7 @@ Bytecode {
|
|||
PushConstant CP#7
|
||||
IndirectStaticCall 2, CP#6
|
||||
PushConstant CP#8
|
||||
InstanceCall 3, CP#10
|
||||
DynamicCall 3, CP#10
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
|
|
|
@ -12,15 +12,15 @@ Bytecode {
|
|||
PopLocal r1
|
||||
Push r1
|
||||
PushInt 1
|
||||
InstanceCall 2, CP#1
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L1
|
||||
Push r1
|
||||
PushInt 2
|
||||
InstanceCall 2, CP#2
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L2
|
||||
Push r1
|
||||
PushInt 3
|
||||
InstanceCall 2, CP#3
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L3
|
||||
Jump L4
|
||||
L1:
|
||||
|
@ -41,9 +41,8 @@ L4:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[1] = ICData target-name '==', arg-desc CP#0
|
||||
[2] = ICData target-name '==', arg-desc CP#0
|
||||
[3] = ICData target-name '==', arg-desc CP#0
|
||||
[1] = InterfaceCall target-name '==', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
}
|
||||
]static method foo1(core::int x) → core::int {
|
||||
core::int y;
|
||||
|
@ -80,27 +79,27 @@ Bytecode {
|
|||
PopLocal r1
|
||||
Push r1
|
||||
PushInt 1
|
||||
InstanceCall 2, CP#1
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L1
|
||||
Push r1
|
||||
PushInt 2
|
||||
InstanceCall 2, CP#2
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L1
|
||||
Push r1
|
||||
PushInt 3
|
||||
InstanceCall 2, CP#3
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L1
|
||||
Push r1
|
||||
PushInt 4
|
||||
InstanceCall 2, CP#4
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L2
|
||||
Push r1
|
||||
PushInt 5
|
||||
InstanceCall 2, CP#5
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L2
|
||||
Push r1
|
||||
PushInt 6
|
||||
InstanceCall 2, CP#6
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L2
|
||||
Jump L3
|
||||
L1:
|
||||
|
@ -120,12 +119,8 @@ L4:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[1] = ICData target-name '==', arg-desc CP#0
|
||||
[2] = ICData target-name '==', arg-desc CP#0
|
||||
[3] = ICData target-name '==', arg-desc CP#0
|
||||
[4] = ICData target-name '==', arg-desc CP#0
|
||||
[5] = ICData target-name '==', arg-desc CP#0
|
||||
[6] = ICData target-name '==', arg-desc CP#0
|
||||
[1] = InterfaceCall target-name '==', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
}
|
||||
]static method foo2(core::int x) → core::int {
|
||||
core::int y;
|
||||
|
@ -165,27 +160,27 @@ Bytecode {
|
|||
PopLocal r1
|
||||
Push r1
|
||||
PushInt 1
|
||||
InstanceCall 2, CP#1
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L1
|
||||
Push r1
|
||||
PushInt 2
|
||||
InstanceCall 2, CP#2
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L1
|
||||
Push r1
|
||||
PushInt 3
|
||||
InstanceCall 2, CP#3
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L1
|
||||
Push r1
|
||||
PushInt 4
|
||||
InstanceCall 2, CP#4
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L2
|
||||
Push r1
|
||||
PushInt 5
|
||||
InstanceCall 2, CP#5
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L2
|
||||
Push r1
|
||||
PushInt 6
|
||||
InstanceCall 2, CP#6
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L2
|
||||
Jump L3
|
||||
L1:
|
||||
|
@ -205,12 +200,8 @@ L3:
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[1] = ICData target-name '==', arg-desc CP#0
|
||||
[2] = ICData target-name '==', arg-desc CP#0
|
||||
[3] = ICData target-name '==', arg-desc CP#0
|
||||
[4] = ICData target-name '==', arg-desc CP#0
|
||||
[5] = ICData target-name '==', arg-desc CP#0
|
||||
[6] = ICData target-name '==', arg-desc CP#0
|
||||
[1] = InterfaceCall target-name '==', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
}
|
||||
]static method foo3(core::int x) → core::int {
|
||||
core::int y;
|
||||
|
|
|
@ -78,17 +78,17 @@ Try #0 handler:
|
|||
MoveSpecial stackTrace, r1
|
||||
Push r0
|
||||
PushConstant CP#3
|
||||
InstanceCall 2, CP#5
|
||||
InterfaceCall 2, CP#5
|
||||
JumpIfFalse L2
|
||||
PushConstant CP#6
|
||||
PushConstant CP#7
|
||||
PushConstant CP#8
|
||||
IndirectStaticCall 1, CP#1
|
||||
Drop1
|
||||
Jump L1
|
||||
L2:
|
||||
Push r0
|
||||
PushConstant CP#8
|
||||
InstanceCall 2, CP#9
|
||||
PushConstant CP#9
|
||||
InterfaceCall 2, CP#5
|
||||
JumpIfFalse L3
|
||||
Push r0
|
||||
PopLocal r2
|
||||
|
@ -113,7 +113,7 @@ L2:
|
|||
L3:
|
||||
Push r0
|
||||
PushConstant CP#13
|
||||
InstanceCall 2, CP#14
|
||||
InterfaceCall 2, CP#5
|
||||
JumpIfFalse L4
|
||||
Push r0
|
||||
PopLocal r2
|
||||
|
@ -125,7 +125,7 @@ L3:
|
|||
StoreLocal r4
|
||||
Push r4
|
||||
PushInt 0
|
||||
PushConstant CP#15
|
||||
PushConstant CP#14
|
||||
StoreIndexedTOS
|
||||
Push r4
|
||||
PushInt 1
|
||||
|
@ -133,15 +133,15 @@ L3:
|
|||
StoreIndexedTOS
|
||||
Push r4
|
||||
PushInt 2
|
||||
PushConstant CP#16
|
||||
PushConstant CP#15
|
||||
StoreIndexedTOS
|
||||
Push r4
|
||||
PushInt 3
|
||||
Push r3
|
||||
StoreIndexedTOS
|
||||
PushConstant CP#17
|
||||
PushConstant CP#16
|
||||
IndirectStaticCall 1, CP#1
|
||||
PushConstant CP#18
|
||||
PushConstant CP#17
|
||||
IndirectStaticCall 1, CP#1
|
||||
Drop1
|
||||
Jump L1
|
||||
|
@ -156,7 +156,7 @@ L4:
|
|||
StoreLocal r4
|
||||
Push r4
|
||||
PushInt 0
|
||||
PushConstant CP#20
|
||||
PushConstant CP#19
|
||||
StoreIndexedTOS
|
||||
Push r4
|
||||
PushInt 1
|
||||
|
@ -164,15 +164,15 @@ L4:
|
|||
StoreIndexedTOS
|
||||
Push r4
|
||||
PushInt 2
|
||||
PushConstant CP#16
|
||||
PushConstant CP#15
|
||||
StoreIndexedTOS
|
||||
Push r4
|
||||
PushInt 3
|
||||
Push r3
|
||||
StoreIndexedTOS
|
||||
PushConstant CP#21
|
||||
PushConstant CP#20
|
||||
IndirectStaticCall 1, CP#1
|
||||
PushConstant CP#22
|
||||
PushConstant CP#21
|
||||
IndirectStaticCall 1, CP#1
|
||||
Drop1
|
||||
Jump L1
|
||||
|
@ -181,7 +181,7 @@ L1:
|
|||
ReturnTOS
|
||||
}
|
||||
ExceptionsTable {
|
||||
try-index 0, outer -1, start 2, end 7, handler 7, needs-stack-trace, types [CP#3, CP#8, CP#13, CP#19]
|
||||
try-index 0, outer -1, start 2, end 7, handler 7, needs-stack-trace, types [CP#3, CP#9, CP#13, CP#18]
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = String 'danger!'
|
||||
|
@ -189,24 +189,23 @@ ConstantPool {
|
|||
[2] = StaticICData target 'dart:core::print', arg-desc CP#1
|
||||
[3] = Type dart:core::TypeError
|
||||
[4] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[5] = ICData target-name '_simpleInstanceOf', arg-desc CP#4
|
||||
[6] = String 'caught type error'
|
||||
[7] = StaticICData target 'dart:core::print', arg-desc CP#1
|
||||
[8] = Type dart:core::AssertionError
|
||||
[9] = ICData target-name '_simpleInstanceOf', arg-desc CP#4
|
||||
[5] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#4
|
||||
[6] = Reserved
|
||||
[7] = String 'caught type error'
|
||||
[8] = StaticICData target 'dart:core::print', arg-desc CP#1
|
||||
[9] = Type dart:core::AssertionError
|
||||
[10] = String 'caught assertion error '
|
||||
[11] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
|
||||
[12] = StaticICData target 'dart:core::print', arg-desc CP#1
|
||||
[13] = Type dart:core::Error
|
||||
[14] = ICData target-name '_simpleInstanceOf', arg-desc CP#4
|
||||
[15] = String 'caught error '
|
||||
[16] = String ' '
|
||||
[17] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
|
||||
[18] = StaticICData target 'dart:core::print', arg-desc CP#1
|
||||
[19] = Type dynamic
|
||||
[20] = String 'caught something '
|
||||
[21] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
|
||||
[22] = StaticICData target 'dart:core::print', arg-desc CP#1
|
||||
[14] = String 'caught error '
|
||||
[15] = String ' '
|
||||
[16] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
|
||||
[17] = StaticICData target 'dart:core::print', arg-desc CP#1
|
||||
[18] = Type dynamic
|
||||
[19] = String 'caught something '
|
||||
[20] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
|
||||
[21] = StaticICData target 'dart:core::print', arg-desc CP#1
|
||||
}
|
||||
]static method testTryCatch2() → dynamic {
|
||||
try {
|
||||
|
@ -259,7 +258,7 @@ Try #0 start:
|
|||
StoreFieldTOS CP#1
|
||||
PopLocal r4
|
||||
Push r4
|
||||
InstanceCall 1, CP#19
|
||||
DynamicCall 1, CP#19
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 1
|
||||
|
@ -366,12 +365,13 @@ ConstantPool {
|
|||
[27] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[28] = Type dart:core::Error
|
||||
[29] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[30] = ICData target-name '_simpleInstanceOf', arg-desc CP#29
|
||||
[31] = String 'error '
|
||||
[32] = String ', captured stack trace: '
|
||||
[33] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#4
|
||||
[34] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[35] = EndClosureFunctionScope
|
||||
[30] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#29
|
||||
[31] = Reserved
|
||||
[32] = String 'error '
|
||||
[33] = String ', captured stack trace: '
|
||||
[34] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#4
|
||||
[35] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[36] = EndClosureFunctionScope
|
||||
}
|
||||
Closure #lib::testTryCatch3::foo () -> void
|
||||
ClosureBytecode {
|
||||
|
@ -436,7 +436,7 @@ Try #0 handler:
|
|||
MoveSpecial stackTrace, r3
|
||||
Push r2
|
||||
PushConstant CP#28
|
||||
InstanceCall 2, CP#30
|
||||
InterfaceCall 2, CP#30
|
||||
JumpIfFalse L2
|
||||
Push r2
|
||||
PopLocal r4
|
||||
|
@ -446,7 +446,7 @@ Try #0 handler:
|
|||
StoreLocal r5
|
||||
Push r5
|
||||
PushInt 0
|
||||
PushConstant CP#31
|
||||
PushConstant CP#32
|
||||
StoreIndexedTOS
|
||||
Push r5
|
||||
PushInt 1
|
||||
|
@ -454,17 +454,17 @@ Try #0 handler:
|
|||
StoreIndexedTOS
|
||||
Push r5
|
||||
PushInt 2
|
||||
PushConstant CP#32
|
||||
PushConstant CP#33
|
||||
StoreIndexedTOS
|
||||
Push r5
|
||||
PushInt 3
|
||||
Push r0
|
||||
LoadContextVar 0, 2
|
||||
StoreIndexedTOS
|
||||
PushConstant CP#33
|
||||
IndirectStaticCall 1, CP#4
|
||||
PushConstant CP#34
|
||||
IndirectStaticCall 1, CP#4
|
||||
PushConstant CP#35
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
Jump L1
|
||||
L2:
|
||||
|
@ -704,11 +704,11 @@ Bytecode {
|
|||
PopLocal r2
|
||||
Push r2
|
||||
PushInt 1
|
||||
InstanceCall 2, CP#1
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L1
|
||||
Push r2
|
||||
PushInt 2
|
||||
InstanceCall 2, CP#2
|
||||
InterfaceCall 2, CP#1
|
||||
JumpIfTrue L2
|
||||
Jump L3
|
||||
L1:
|
||||
|
@ -748,7 +748,7 @@ Try #1 start:
|
|||
StoreFieldTOS CP#9
|
||||
PopLocal r7
|
||||
Push r7
|
||||
InstanceCall 1, CP#24
|
||||
DynamicCall 1, CP#24
|
||||
Drop1
|
||||
Jump L4
|
||||
Try #1 end:
|
||||
|
@ -811,8 +811,8 @@ ExceptionsTable {
|
|||
}
|
||||
ConstantPool {
|
||||
[0] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[1] = ICData target-name '==', arg-desc CP#0
|
||||
[2] = ICData target-name '==', arg-desc CP#0
|
||||
[1] = InterfaceCall target-name '==', arg-desc CP#0
|
||||
[2] = Reserved
|
||||
[3] = String 'before try 1'
|
||||
[4] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[5] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
|
@ -950,7 +950,7 @@ Try #0 handler:
|
|||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
Push r2
|
||||
InstanceCall 1, CP#27
|
||||
DynamicCall 1, CP#27
|
||||
Drop1
|
||||
Push r3
|
||||
Push r4
|
||||
|
@ -964,7 +964,7 @@ L1:
|
|||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
Push r2
|
||||
InstanceCall 1, CP#29
|
||||
DynamicCall 1, CP#29
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextParent
|
||||
|
|
|
@ -106,23 +106,23 @@ Bytecode {
|
|||
LoadTypeArgumentsField CP#0
|
||||
PushNull
|
||||
PushConstant CP#1
|
||||
InstanceCall 4, CP#3
|
||||
InterfaceCall 4, CP#3
|
||||
JumpIfFalse L1
|
||||
PushConstant CP#4
|
||||
PushConstant CP#6
|
||||
IndirectStaticCall 1, CP#5
|
||||
PushConstant CP#5
|
||||
PushConstant CP#7
|
||||
IndirectStaticCall 1, CP#6
|
||||
Drop1
|
||||
L1:
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadTypeArgumentsField CP#0
|
||||
PushNull
|
||||
PushConstant CP#7
|
||||
InstanceCall 4, CP#8
|
||||
PushConstant CP#8
|
||||
InterfaceCall 4, CP#3
|
||||
JumpIfFalse L2
|
||||
PushConstant CP#9
|
||||
PushConstant CP#10
|
||||
IndirectStaticCall 1, CP#5
|
||||
IndirectStaticCall 1, CP#6
|
||||
Drop1
|
||||
L2:
|
||||
Push FP[-6]
|
||||
|
@ -133,7 +133,7 @@ L2:
|
|||
PushNull
|
||||
PushConstant CP#12
|
||||
AssertAssignable 0, CP#13
|
||||
InstanceCall 2, CP#15
|
||||
InterfaceCall 2, CP#15
|
||||
Drop1
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
@ -142,19 +142,20 @@ ConstantPool {
|
|||
[0] = TypeArgumentsField #lib::D
|
||||
[1] = Type #lib::A < #lib::D::TypeParam/0 >
|
||||
[2] = ArgDesc num-args 4, num-type-args 0, names []
|
||||
[3] = ICData target-name '_instanceOf', arg-desc CP#2
|
||||
[4] = String '21'
|
||||
[5] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[6] = StaticICData target 'dart:core::print', arg-desc CP#5
|
||||
[7] = Type #lib::C < dynamic, #lib::D::TypeParam/1, dart:core::List < #lib::D::TypeParam/0 > >
|
||||
[8] = ICData target-name '_instanceOf', arg-desc CP#2
|
||||
[3] = InterfaceCall target-name '_instanceOf', arg-desc CP#2
|
||||
[4] = Reserved
|
||||
[5] = String '21'
|
||||
[6] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[7] = StaticICData target 'dart:core::print', arg-desc CP#6
|
||||
[8] = Type #lib::C < dynamic, #lib::D::TypeParam/1, dart:core::List < #lib::D::TypeParam/0 > >
|
||||
[9] = String '22'
|
||||
[10] = StaticICData target 'dart:core::print', arg-desc CP#5
|
||||
[10] = StaticICData target 'dart:core::print', arg-desc CP#6
|
||||
[11] = Type dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 >
|
||||
[12] = String ''
|
||||
[13] = SubtypeTestCache
|
||||
[14] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[15] = ICData set target-name 'set:foo', arg-desc CP#14
|
||||
[15] = InterfaceCall set target-name 'set:foo', arg-desc CP#14
|
||||
[16] = Reserved
|
||||
}
|
||||
] method foo2(dynamic y) → dynamic {
|
||||
if(y is self::A<self::D::P>) {
|
||||
|
@ -174,51 +175,52 @@ Bytecode {
|
|||
PushNull
|
||||
Push r0
|
||||
PushConstant CP#0
|
||||
InstanceCall 4, CP#2
|
||||
InterfaceCall 4, CP#2
|
||||
JumpIfFalse L1
|
||||
PushConstant CP#3
|
||||
PushConstant CP#5
|
||||
IndirectStaticCall 1, CP#4
|
||||
PushConstant CP#4
|
||||
PushConstant CP#6
|
||||
IndirectStaticCall 1, CP#5
|
||||
Drop1
|
||||
L1:
|
||||
Push FP[-5]
|
||||
Push FP[-6]
|
||||
LoadTypeArgumentsField CP#6
|
||||
LoadTypeArgumentsField CP#7
|
||||
Push r0
|
||||
PushConstant CP#7
|
||||
InstanceCall 4, CP#8
|
||||
PushConstant CP#8
|
||||
InterfaceCall 4, CP#2
|
||||
JumpIfFalse L2
|
||||
PushConstant CP#9
|
||||
PushConstant CP#10
|
||||
IndirectStaticCall 1, CP#4
|
||||
IndirectStaticCall 1, CP#5
|
||||
Drop1
|
||||
L2:
|
||||
Push FP[-5]
|
||||
PushConstant CP#11
|
||||
Push FP[-6]
|
||||
LoadTypeArgumentsField CP#6
|
||||
LoadTypeArgumentsField CP#7
|
||||
Push r0
|
||||
PushConstant CP#12
|
||||
AssertAssignable 0, CP#13
|
||||
InstanceCall 1, CP#14
|
||||
InterfaceCall 1, CP#14
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Type #lib::A < #lib::D::foo3::TypeParam/0 >
|
||||
[1] = ArgDesc num-args 4, num-type-args 0, names []
|
||||
[2] = ICData target-name '_instanceOf', arg-desc CP#1
|
||||
[3] = String '31'
|
||||
[4] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[5] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[6] = TypeArgumentsField #lib::D
|
||||
[7] = Type #lib::C < dart:core::Map < #lib::D::foo3::TypeParam/0, #lib::D::TypeParam/0 >, dart:core::List < #lib::D::foo3::TypeParam/1 >, #lib::D::TypeParam/1 >
|
||||
[8] = ICData target-name '_instanceOf', arg-desc CP#1
|
||||
[2] = InterfaceCall target-name '_instanceOf', arg-desc CP#1
|
||||
[3] = Reserved
|
||||
[4] = String '31'
|
||||
[5] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[6] = StaticICData target 'dart:core::print', arg-desc CP#5
|
||||
[7] = TypeArgumentsField #lib::D
|
||||
[8] = Type #lib::C < dart:core::Map < #lib::D::foo3::TypeParam/0, #lib::D::TypeParam/0 >, dart:core::List < #lib::D::foo3::TypeParam/1 >, #lib::D::TypeParam/1 >
|
||||
[9] = String '32'
|
||||
[10] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[10] = StaticICData target 'dart:core::print', arg-desc CP#5
|
||||
[11] = Type dart:core::Map < #lib::D::foo3::TypeParam/1, #lib::D::TypeParam/1 >
|
||||
[12] = String ' in type cast'
|
||||
[13] = SubtypeTestCache
|
||||
[14] = ICData get target-name 'get:values', arg-desc CP#4
|
||||
[14] = InterfaceCall get target-name 'get:values', arg-desc CP#5
|
||||
[15] = Reserved
|
||||
}
|
||||
] method foo3<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic>(dynamic z) → dynamic {
|
||||
if(z is self::A<self::D::foo3::T1>) {
|
||||
|
@ -329,47 +331,49 @@ Bytecode {
|
|||
CheckStack 0
|
||||
Push FP[-5]
|
||||
PushConstant CP#0
|
||||
InstanceCall 2, CP#2
|
||||
InterfaceCall 2, CP#2
|
||||
JumpIfFalse L1
|
||||
PushConstant CP#3
|
||||
PushConstant CP#5
|
||||
IndirectStaticCall 1, CP#4
|
||||
PushConstant CP#4
|
||||
PushConstant CP#6
|
||||
IndirectStaticCall 1, CP#5
|
||||
Drop1
|
||||
L1:
|
||||
Push FP[-5]
|
||||
PushNull
|
||||
PushNull
|
||||
PushConstant CP#6
|
||||
InstanceCall 4, CP#8
|
||||
PushConstant CP#7
|
||||
InterfaceCall 4, CP#9
|
||||
JumpIfFalse L2
|
||||
PushConstant CP#9
|
||||
PushConstant CP#10
|
||||
IndirectStaticCall 1, CP#4
|
||||
PushConstant CP#11
|
||||
PushConstant CP#12
|
||||
IndirectStaticCall 1, CP#5
|
||||
Drop1
|
||||
L2:
|
||||
Push FP[-5]
|
||||
PushConstant CP#11
|
||||
PushConstant CP#13
|
||||
PushNull
|
||||
PushNull
|
||||
PushConstant CP#12
|
||||
AssertAssignable 0, CP#13
|
||||
PushConstant CP#14
|
||||
AssertAssignable 0, CP#15
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
[0] = Type #lib::B
|
||||
[1] = ArgDesc num-args 2, num-type-args 0, names []
|
||||
[2] = ICData target-name '_simpleInstanceOf', arg-desc CP#1
|
||||
[3] = String '11'
|
||||
[4] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[5] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[6] = Type #lib::C < dart:core::int, dart:core::Object, dynamic >
|
||||
[7] = ArgDesc num-args 4, num-type-args 0, names []
|
||||
[8] = ICData target-name '_instanceOf', arg-desc CP#7
|
||||
[9] = String '12'
|
||||
[10] = StaticICData target 'dart:core::print', arg-desc CP#4
|
||||
[11] = Type #lib::A < dart:core::int >
|
||||
[12] = String ' in type cast'
|
||||
[13] = SubtypeTestCache
|
||||
[2] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#1
|
||||
[3] = Reserved
|
||||
[4] = String '11'
|
||||
[5] = ArgDesc num-args 1, num-type-args 0, names []
|
||||
[6] = StaticICData target 'dart:core::print', arg-desc CP#5
|
||||
[7] = Type #lib::C < dart:core::int, dart:core::Object, dynamic >
|
||||
[8] = ArgDesc num-args 4, num-type-args 0, names []
|
||||
[9] = InterfaceCall target-name '_instanceOf', arg-desc CP#8
|
||||
[10] = Reserved
|
||||
[11] = String '12'
|
||||
[12] = StaticICData target 'dart:core::print', arg-desc CP#5
|
||||
[13] = Type #lib::A < dart:core::int >
|
||||
[14] = String ' in type cast'
|
||||
[15] = SubtypeTestCache
|
||||
}
|
||||
]static method foo1(dynamic x) → dynamic {
|
||||
if(x is self::B) {
|
||||
|
|
|
@ -214,7 +214,8 @@ static bool HasLoadFromPool(KBCInstr instr) {
|
|||
case KernelBytecode::kLoadConstant:
|
||||
case KernelBytecode::kPushConstant:
|
||||
case KernelBytecode::kIndirectStaticCall:
|
||||
case KernelBytecode::kInstanceCall:
|
||||
case KernelBytecode::kInterfaceCall:
|
||||
case KernelBytecode::kDynamicCall:
|
||||
case KernelBytecode::kStoreStaticTOS:
|
||||
case KernelBytecode::kPushStatic:
|
||||
case KernelBytecode::kAllocate:
|
||||
|
|
|
@ -701,7 +701,47 @@ void BytecodeFlowGraphBuilder::BuildIndirectStaticCall() {
|
|||
B->Push(call);
|
||||
}
|
||||
|
||||
void BytecodeFlowGraphBuilder::BuildInstanceCall() {
|
||||
void BytecodeFlowGraphBuilder::BuildInterfaceCall() {
|
||||
if (is_generating_interpreter()) {
|
||||
UNIMPLEMENTED(); // TODO(alexmarkov): interpreter
|
||||
}
|
||||
|
||||
const String& name = String::Cast(ConstantAt(DecodeOperandD()).value());
|
||||
ASSERT(name.IsSymbol());
|
||||
|
||||
const Array& arg_desc_array =
|
||||
Array::Cast(ConstantAt(DecodeOperandD(), 1).value());
|
||||
const ArgumentsDescriptor arg_desc(arg_desc_array);
|
||||
|
||||
const intptr_t argc = DecodeOperandA().value();
|
||||
const Token::Kind token_kind =
|
||||
MethodTokenRecognizer::RecognizeTokenKind(name);
|
||||
|
||||
intptr_t checked_argument_count = 1;
|
||||
if ((token_kind != Token::kILLEGAL) ||
|
||||
(name.raw() ==
|
||||
Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()).raw())) {
|
||||
intptr_t argument_count = arg_desc.Count();
|
||||
ASSERT(argument_count <= 2);
|
||||
checked_argument_count = argument_count;
|
||||
}
|
||||
|
||||
const ArgumentArray arguments = GetArguments(argc);
|
||||
|
||||
// TODO(alexmarkov): store interface_target in bytecode and pass it here.
|
||||
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
position_, name, token_kind, arguments, arg_desc.TypeArgsLen(),
|
||||
Array::ZoneHandle(Z, arg_desc.GetArgumentNames()), checked_argument_count,
|
||||
*ic_data_array_, B->GetNextDeoptId());
|
||||
|
||||
// TODO(alexmarkov): add type info - call->SetResultType()
|
||||
|
||||
code_ <<= call;
|
||||
B->Push(call);
|
||||
}
|
||||
|
||||
void BytecodeFlowGraphBuilder::BuildDynamicCall() {
|
||||
if (is_generating_interpreter()) {
|
||||
UNIMPLEMENTED(); // TODO(alexmarkov): interpreter
|
||||
}
|
||||
|
|
|
@ -344,6 +344,7 @@ void BytecodeMetadataHelper::ReadConstantPool(const Function& function,
|
|||
kPartialTearOffInstantiation,
|
||||
kEmptyTypeArguments,
|
||||
kSymbol,
|
||||
kInterfaceCall,
|
||||
};
|
||||
|
||||
enum InvocationKind {
|
||||
|
@ -618,6 +619,22 @@ void BytecodeMetadataHelper::ReadConstantPool(const Function& function,
|
|||
Instance::Cast(obj).SetField(*symbol_name_field, name);
|
||||
obj = H.Canonicalize(Instance::Cast(obj));
|
||||
} break;
|
||||
case ConstantPoolTag::kInterfaceCall: {
|
||||
helper_->ReadByte(); // TODO(regis): Remove, unneeded.
|
||||
name ^= ReadObject();
|
||||
ASSERT(name.IsSymbol());
|
||||
intptr_t arg_desc_index = helper_->ReadUInt();
|
||||
ASSERT(arg_desc_index < i);
|
||||
array ^= pool.ObjectAt(arg_desc_index);
|
||||
// InterfaceCall constant occupies 2 entries.
|
||||
// The first entry is used for selector name.
|
||||
pool.SetTypeAt(i, ObjectPool::kTaggedObject, ObjectPool::kNotPatchable);
|
||||
pool.SetObjectAt(i, name);
|
||||
++i;
|
||||
ASSERT(i < obj_count);
|
||||
// The second entry is used for arguments descriptor.
|
||||
obj = array.raw();
|
||||
} break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
|
|
@ -271,7 +271,16 @@ namespace dart {
|
|||
// SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D], which
|
||||
// indicates whether the first argument is a type argument vector.
|
||||
//
|
||||
// - InstanceCall ArgC, D
|
||||
// - InterfaceCall ArgC, D
|
||||
//
|
||||
// Lookup and invoke method using ICData in PP[D]
|
||||
// with arguments SP[-(1+ArgC)], ..., SP[-1].
|
||||
// Method has to be declared (explicitly or implicitly) in an interface
|
||||
// implemented by a receiver, and passed arguments are valid for the
|
||||
// interface method declaration.
|
||||
// The ICData indicates whether the first argument is a type argument vector.
|
||||
//
|
||||
// - DynamicCall ArgC, D
|
||||
//
|
||||
// Lookup and invoke method using ICData in PP[D]
|
||||
// with arguments SP[-(1+ArgC)], ..., SP[-1].
|
||||
|
@ -439,7 +448,8 @@ namespace dart {
|
|||
V(JumpIfNull, T, tgt, ___, ___) \
|
||||
V(JumpIfNotNull, T, tgt, ___, ___) \
|
||||
V(IndirectStaticCall, A_D, num, num, ___) \
|
||||
V(InstanceCall, A_D, num, num, ___) \
|
||||
V(InterfaceCall, A_D, num, num, ___) \
|
||||
V(DynamicCall, A_D, num, num, ___) \
|
||||
V(NativeCall, D, lit, ___, ___) \
|
||||
V(ReturnTOS, 0, ___, ___, ___) \
|
||||
V(AssertAssignable, A_D, num, lit, ___) \
|
||||
|
@ -595,7 +605,8 @@ class KernelBytecode {
|
|||
DART_FORCE_INLINE static bool IsCallOpcode(KBCInstr instr) {
|
||||
switch (DecodeOpcode(instr)) {
|
||||
case KernelBytecode::kIndirectStaticCall:
|
||||
case KernelBytecode::kInstanceCall:
|
||||
case KernelBytecode::kInterfaceCall:
|
||||
case KernelBytecode::kDynamicCall:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
|
|
@ -86,7 +86,6 @@ class ArgumentsDescriptor : public ValueObject {
|
|||
enum {
|
||||
kTypeArgsLenIndex,
|
||||
kCountIndex,
|
||||
|
||||
kPositionalCountIndex,
|
||||
kFirstNamedEntryIndex,
|
||||
};
|
||||
|
|
|
@ -479,6 +479,15 @@ class MarkingWeakVisitor : public HandleVisitor {
|
|||
|
||||
void GCMarker::Prologue() {
|
||||
isolate_->ReleaseStoreBuffers();
|
||||
|
||||
#ifndef DART_PRECOMPILED_RUNTIME
|
||||
if (isolate_->IsMutatorThreadScheduled()) {
|
||||
Interpreter* interpreter = isolate_->mutator_thread()->interpreter();
|
||||
if (interpreter != NULL) {
|
||||
interpreter->MajorGC();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GCMarker::Epilogue() {
|
||||
|
|
|
@ -499,6 +499,66 @@ DART_FORCE_INLINE static RawFunction* FrameFunction(RawObject** FP) {
|
|||
return function;
|
||||
}
|
||||
|
||||
void LookupCache::Clear() {
|
||||
for (intptr_t i = 0; i < kNumEntries; i++) {
|
||||
entries_[i].receiver_cid = kIllegalCid;
|
||||
}
|
||||
}
|
||||
|
||||
bool LookupCache::Lookup(intptr_t receiver_cid,
|
||||
RawString* function_name,
|
||||
RawFunction** target) const {
|
||||
ASSERT(receiver_cid != kIllegalCid); // Sentinel value.
|
||||
|
||||
const intptr_t hash =
|
||||
receiver_cid ^ reinterpret_cast<intptr_t>(function_name);
|
||||
const intptr_t probe1 = hash & kTableMask;
|
||||
if (entries_[probe1].receiver_cid == receiver_cid &&
|
||||
entries_[probe1].function_name == function_name) {
|
||||
*target = entries_[probe1].target;
|
||||
return true;
|
||||
}
|
||||
|
||||
intptr_t probe2 = (hash >> 3) & kTableMask;
|
||||
if (entries_[probe2].receiver_cid == receiver_cid &&
|
||||
entries_[probe2].function_name == function_name) {
|
||||
*target = entries_[probe2].target;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LookupCache::Insert(intptr_t receiver_cid,
|
||||
RawString* function_name,
|
||||
RawFunction* target) {
|
||||
// Otherwise we have to clear the cache or rehash on scavenges too.
|
||||
ASSERT(function_name->IsOldObject());
|
||||
ASSERT(target->IsOldObject());
|
||||
|
||||
const intptr_t hash =
|
||||
receiver_cid ^ reinterpret_cast<intptr_t>(function_name);
|
||||
const intptr_t probe1 = hash & kTableMask;
|
||||
if (entries_[probe1].receiver_cid == kIllegalCid) {
|
||||
entries_[probe1].receiver_cid = receiver_cid;
|
||||
entries_[probe1].function_name = function_name;
|
||||
entries_[probe1].target = target;
|
||||
return;
|
||||
}
|
||||
|
||||
const intptr_t probe2 = (hash >> 3) & kTableMask;
|
||||
if (entries_[probe2].receiver_cid == kIllegalCid) {
|
||||
entries_[probe2].receiver_cid = receiver_cid;
|
||||
entries_[probe2].function_name = function_name;
|
||||
entries_[probe2].target = target;
|
||||
return;
|
||||
}
|
||||
|
||||
entries_[probe1].receiver_cid = receiver_cid;
|
||||
entries_[probe1].function_name = function_name;
|
||||
entries_[probe1].target = target;
|
||||
}
|
||||
|
||||
IntrinsicHandler Interpreter::intrinsics_[Interpreter::kIntrinsicCount];
|
||||
|
||||
// Synchronization primitives support.
|
||||
|
@ -545,7 +605,7 @@ void Interpreter::InitOnce() {
|
|||
}
|
||||
|
||||
Interpreter::Interpreter()
|
||||
: stack_(NULL), fp_(NULL), pp_(NULL), argdesc_(NULL) {
|
||||
: stack_(NULL), fp_(NULL), pp_(NULL), argdesc_(NULL), lookup_cache_() {
|
||||
// Setup interpreter support first. Some of this information is needed to
|
||||
// setup the architecture state.
|
||||
// We allocate the stack here, the size is computed as the sum of
|
||||
|
@ -584,6 +644,8 @@ Interpreter::Interpreter()
|
|||
|
||||
Interpreter::~Interpreter() {
|
||||
delete[] stack_;
|
||||
pp_ = NULL;
|
||||
argdesc_ = NULL;
|
||||
#if defined(DEBUG)
|
||||
if (trace_file_ != NULL) {
|
||||
FlushTraceBuffer();
|
||||
|
@ -601,8 +663,10 @@ Interpreter::~Interpreter() {
|
|||
|
||||
// Get the active Interpreter for the current isolate.
|
||||
Interpreter* Interpreter::Current() {
|
||||
Interpreter* interpreter = Thread::Current()->interpreter();
|
||||
Thread* thread = Thread::Current();
|
||||
Interpreter* interpreter = thread->interpreter();
|
||||
if (interpreter == NULL) {
|
||||
TransitionGeneratedToVM transition(thread);
|
||||
interpreter = new Interpreter();
|
||||
Thread::Current()->set_interpreter(interpreter);
|
||||
}
|
||||
|
@ -697,19 +761,6 @@ void Interpreter::Exit(Thread* thread,
|
|||
#endif
|
||||
}
|
||||
|
||||
void Interpreter::CallRuntime(Thread* thread,
|
||||
RawObject** base,
|
||||
RawObject** exit_frame,
|
||||
uint32_t* pc,
|
||||
intptr_t argc_tag,
|
||||
RawObject** args,
|
||||
RawObject** result,
|
||||
uword target) {
|
||||
Exit(thread, base, exit_frame, pc);
|
||||
NativeArguments native_args(thread, argc_tag, args, result);
|
||||
reinterpret_cast<RuntimeFunction>(target)(native_args);
|
||||
}
|
||||
|
||||
// Calling into runtime may trigger garbage collection and relocate objects,
|
||||
// so all RawObject* pointers become outdated and should not be used across
|
||||
// runtime calls.
|
||||
|
@ -1171,8 +1222,48 @@ void Interpreter::InlineCacheMiss(int checked_args,
|
|||
// Handler arguments: arguments to check and an ICData object.
|
||||
const intptr_t miss_handler_argc = checked_args + 1;
|
||||
RawObject** exit_frame = miss_handler_args + miss_handler_argc;
|
||||
CallRuntime(thread, FP, exit_frame, pc, miss_handler_argc, miss_handler_args,
|
||||
result, reinterpret_cast<uword>(handler));
|
||||
Exit(thread, FP, exit_frame, pc);
|
||||
NativeArguments native_args(thread, miss_handler_argc, miss_handler_args,
|
||||
result);
|
||||
handler(native_args);
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE bool Interpreter::InterfaceCall(Thread* thread,
|
||||
RawString* target_name,
|
||||
RawObject** call_base,
|
||||
RawObject** top,
|
||||
uint32_t** pc,
|
||||
RawObject*** FP,
|
||||
RawObject*** SP) {
|
||||
const intptr_t type_args_len =
|
||||
InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
|
||||
const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
|
||||
|
||||
intptr_t receiver_cid =
|
||||
InterpreterHelpers::GetClassId(call_base[receiver_idx]);
|
||||
|
||||
RawFunction* target;
|
||||
if (UNLIKELY(!lookup_cache_.Lookup(receiver_cid, target_name, &target))) {
|
||||
// Table lookup miss.
|
||||
top[1] = call_base[receiver_idx];
|
||||
top[2] = target_name;
|
||||
top[3] = argdesc_;
|
||||
top[4] = 0; // Result slot.
|
||||
|
||||
Exit(thread, *FP, top + 5, *pc);
|
||||
NativeArguments native_args(thread, 3, /* argv */ top + 1,
|
||||
/* result */ top + 4);
|
||||
DRT_InterpretedInterfaceCallMissHandler(native_args);
|
||||
|
||||
target = static_cast<RawFunction*>(top[4]);
|
||||
target_name = static_cast<RawString*>(top[2]);
|
||||
argdesc_ = static_cast<RawArray*>(top[3]);
|
||||
ASSERT(target->IsFunction());
|
||||
lookup_cache_.Insert(receiver_cid, target_name, target);
|
||||
}
|
||||
|
||||
top[0] = target;
|
||||
return Invoke(thread, call_base, top, pc, FP, SP);
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE bool Interpreter::InstanceCall1(Thread* thread,
|
||||
|
@ -2111,7 +2202,36 @@ SwitchDispatch:
|
|||
}
|
||||
|
||||
{
|
||||
BYTECODE(InstanceCall, A_D);
|
||||
BYTECODE(InterfaceCall, A_D);
|
||||
|
||||
// Check if single stepping.
|
||||
if (thread->isolate()->single_step()) {
|
||||
Exit(thread, FP, SP + 1, pc);
|
||||
NativeArguments args(thread, 0, NULL, NULL);
|
||||
INVOKE_RUNTIME(DRT_SingleStepHandler, args);
|
||||
}
|
||||
|
||||
{
|
||||
const uint16_t argc = rA;
|
||||
const uint16_t kidx = rD;
|
||||
|
||||
RawObject** call_base = SP - argc + 1;
|
||||
RawObject** call_top = SP + 1;
|
||||
|
||||
InterpreterHelpers::IncrementUsageCounter(FrameFunction(FP));
|
||||
RawString* target_name = static_cast<RawString*>(LOAD_CONSTANT(kidx));
|
||||
argdesc_ = static_cast<RawArray*>(LOAD_CONSTANT(kidx + 1));
|
||||
if (!InterfaceCall(thread, target_name, call_base, call_top, &pc, &FP,
|
||||
&SP)) {
|
||||
HANDLE_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(DynamicCall, A_D);
|
||||
|
||||
// Check if single stepping.
|
||||
if (thread->isolate()->single_step()) {
|
||||
|
|
|
@ -27,6 +27,36 @@ class RawFunction;
|
|||
class RawSubtypeTestCache;
|
||||
class ObjectPointerVisitor;
|
||||
|
||||
class LookupCache : public ValueObject {
|
||||
public:
|
||||
LookupCache() {
|
||||
ASSERT(Utils::IsPowerOfTwo(sizeof(Entry)));
|
||||
ASSERT(Utils::IsPowerOfTwo(sizeof(kNumEntries)));
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear();
|
||||
bool Lookup(intptr_t receiver_cid,
|
||||
RawString* function_name,
|
||||
RawFunction** target) const;
|
||||
void Insert(intptr_t receiver_cid,
|
||||
RawString* function_name,
|
||||
RawFunction* target);
|
||||
|
||||
private:
|
||||
struct Entry {
|
||||
intptr_t receiver_cid;
|
||||
RawString* function_name;
|
||||
RawFunction* target;
|
||||
intptr_t padding;
|
||||
};
|
||||
|
||||
static const intptr_t kNumEntries = 1024;
|
||||
static const intptr_t kTableMask = kNumEntries - 1;
|
||||
|
||||
Entry entries_[kNumEntries];
|
||||
};
|
||||
|
||||
// Interpreter intrinsic handler. It is invoked on entry to the intrinsified
|
||||
// function via Intrinsic bytecode before the frame is setup.
|
||||
// If the handler returns true then Intrinsic bytecode works as a return
|
||||
|
@ -97,6 +127,7 @@ class Interpreter {
|
|||
}
|
||||
|
||||
void VisitObjectPointers(ObjectPointerVisitor* visitor);
|
||||
void MajorGC() { lookup_cache_.Clear(); }
|
||||
|
||||
private:
|
||||
uintptr_t* stack_;
|
||||
|
@ -115,6 +146,8 @@ class Interpreter {
|
|||
// call instruction and the function entry.
|
||||
RawObject* special_[KernelBytecode::kSpecialIndexCount];
|
||||
|
||||
LookupCache lookup_cache_;
|
||||
|
||||
static IntrinsicHandler intrinsics_[kIntrinsicCount];
|
||||
|
||||
void Exit(Thread* thread,
|
||||
|
@ -122,15 +155,6 @@ class Interpreter {
|
|||
RawObject** exit_frame,
|
||||
uint32_t* pc);
|
||||
|
||||
void CallRuntime(Thread* thread,
|
||||
RawObject** base,
|
||||
RawObject** exit_frame,
|
||||
uint32_t* pc,
|
||||
intptr_t argc_tag,
|
||||
RawObject** args,
|
||||
RawObject** result,
|
||||
uword target);
|
||||
|
||||
bool Invoke(Thread* thread,
|
||||
RawObject** call_base,
|
||||
RawObject** call_top,
|
||||
|
@ -164,6 +188,14 @@ class Interpreter {
|
|||
RawObject** FP,
|
||||
RawObject** SP);
|
||||
|
||||
bool InterfaceCall(Thread* thread,
|
||||
RawString* target_name,
|
||||
RawObject** call_base,
|
||||
RawObject** call_top,
|
||||
uint32_t** pc,
|
||||
RawObject*** FP,
|
||||
RawObject*** SP);
|
||||
|
||||
bool InstanceCall1(Thread* thread,
|
||||
RawICData* icdata,
|
||||
RawObject** call_base,
|
||||
|
|
|
@ -1618,6 +1618,37 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
|
|||
#endif // !defined(TARGET_ARCH_DBC)
|
||||
}
|
||||
|
||||
// Handles interpreted interface call cache miss.
|
||||
// Arg0: receiver
|
||||
// Arg1: target name
|
||||
// Arg2: arguments descriptor
|
||||
// Returns: target function
|
||||
// Modifies the instance call table in current interpreter.
|
||||
DEFINE_RUNTIME_ENTRY(InterpretedInterfaceCallMissHandler, 3) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
UNREACHABLE();
|
||||
#else
|
||||
ASSERT(FLAG_enable_interpreter);
|
||||
const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
|
||||
const String& target_name = String::CheckedHandle(zone, arguments.ArgAt(1));
|
||||
const Array& arg_desc = Array::CheckedHandle(zone, arguments.ArgAt(2));
|
||||
|
||||
ArgumentsDescriptor arguments_descriptor(arg_desc);
|
||||
Function& target_function = Function::Handle(
|
||||
zone,
|
||||
Resolver::ResolveDynamic(receiver, target_name, arguments_descriptor));
|
||||
|
||||
// TODO(regis): In order to substitute 'simple_instance_of_function', the 2nd
|
||||
// arg to the call, the type, is needed.
|
||||
|
||||
if (target_function.IsNull()) {
|
||||
target_function = InlineCacheMissHelper(receiver, arg_desc, target_name);
|
||||
}
|
||||
ASSERT(!target_function.IsNull());
|
||||
arguments.SetReturn(target_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Invoke appropriate noSuchMethod or closure from getter.
|
||||
// Arg0: receiver
|
||||
// Arg1: ICData or MegamorphicCache
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace dart {
|
|||
V(InlineCacheMissHandlerTwoArgs) \
|
||||
V(StaticCallMissHandlerOneArg) \
|
||||
V(StaticCallMissHandlerTwoArgs) \
|
||||
V(InterpretedInterfaceCallMissHandler) \
|
||||
V(Instanceof) \
|
||||
V(SubtypeCheck) \
|
||||
V(TypeCheck) \
|
||||
|
|
|
@ -716,15 +716,15 @@ void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor,
|
|||
// Only the mutator thread can run Dart code.
|
||||
if (IsMutatorThread()) {
|
||||
// The MarkTask, which calls this method, can run on a different thread. We
|
||||
// therefore assume the mutator is at a safepoint and we can iterate it's
|
||||
// therefore assume the mutator is at a safepoint and we can iterate its
|
||||
// stack.
|
||||
// TODO(vm-team): It would be beneficial to be able to ask the mutator
|
||||
// thread whether it is in fact blocked at the moment (at a "safepoint") so
|
||||
// we can safely iterate it's stack.
|
||||
// we can safely iterate its stack.
|
||||
//
|
||||
// Unfortunately we cannot use `this->IsAtSafepoint()` here because that
|
||||
// will return `false` even though the mutator thread is waiting for mark
|
||||
// tasks (which iterate it's stack) to finish.
|
||||
// tasks (which iterate its stack) to finish.
|
||||
const StackFrameIterator::CrossThreadPolicy cross_thread_policy =
|
||||
StackFrameIterator::kAllowCrossThreadIteration;
|
||||
|
||||
|
|
Loading…
Reference in a new issue