Index: runtime/vm/stub_code_arm.cc |
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc |
index fcf6843ec1207df20d009bfb19411e0c2a71c2cb..94cf00b33d08a8d5f0183fe5343adce3998d91ae 100644 |
--- a/runtime/vm/stub_code_arm.cc |
+++ b/runtime/vm/stub_code_arm.cc |
@@ -539,9 +539,9 @@ static void GenerateDispatcherCode(Assembler* assembler, |
__ add(IP, FP, Operand(R2, LSL, 1)); // R2 is Smi. |
__ ldr(R8, Address(IP, kParamEndSlotFromFp * kWordSize)); |
__ PushObject(Object::null_object()); |
- __ Push(R8); |
- __ Push(R9); |
- __ Push(R4); |
+ __ Push(R8); // Receiver. |
+ __ Push(R9); // ICData/MegamorphicCache. |
+ __ Push(R4); // Arguments descriptor. |
// R2: Smi-tagged arguments array length. |
PushArgumentsArray(assembler); |
const intptr_t kNumArgs = 4; |
@@ -2044,18 +2044,18 @@ void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
} |
-void StubCode::EmitMegamorphicLookup( |
- Assembler* assembler, Register receiver, Register cache, Register target) { |
- ASSERT((cache != R0) && (cache != R2)); |
- __ LoadTaggedClassIdMayBeSmi(R0, receiver); |
- // R0: class ID of the receiver (smi). |
- __ ldr(R2, FieldAddress(cache, MegamorphicCache::buckets_offset())); |
- __ ldr(R1, FieldAddress(R1, MegamorphicCache::mask_offset())); |
+void StubCode::EmitMegamorphicLookup(Assembler* assembler) { |
+ __ LoadTaggedClassIdMayBeSmi(R0, R0); |
+ // R0: receiver cid as Smi. |
+ __ ldr(R4, FieldAddress(R9, MegamorphicCache::arguments_descriptor_offset())); |
+ __ ldr(R2, FieldAddress(R9, MegamorphicCache::buckets_offset())); |
+ __ ldr(R1, FieldAddress(R9, MegamorphicCache::mask_offset())); |
// R2: cache buckets array. |
// R1: mask. |
__ mov(R3, Operand(R0)); |
+ // R3: probe. |
- Label loop, update, call_target_function; |
+ Label loop, update, load_target_function; |
__ b(&loop); |
__ Bind(&update); |
@@ -2065,33 +2065,77 @@ void StubCode::EmitMegamorphicLookup( |
const intptr_t base = Array::data_offset(); |
// R3 is smi tagged, but table entries are two words, so LSL 2. |
__ add(IP, R2, Operand(R3, LSL, 2)); |
- __ ldr(R4, FieldAddress(IP, base)); |
+ __ ldr(R6, FieldAddress(IP, base)); |
ASSERT(kIllegalCid == 0); |
- __ tst(R4, Operand(R4)); |
- __ b(&call_target_function, EQ); |
- __ cmp(R4, Operand(R0)); |
+ __ tst(R6, Operand(R6)); |
+ __ b(&load_target_function, EQ); |
+ __ cmp(R6, Operand(R0)); |
__ b(&update, NE); |
- __ Bind(&call_target_function); |
+ __ Bind(&load_target_function); |
// Call the target found in the cache. For a class id match, this is a |
// proper target for the given name and arguments descriptor. If the |
// illegal class id was found, the target is a cache miss handler that can |
// be invoked as a normal Dart function. |
__ add(IP, R2, Operand(R3, LSL, 2)); |
__ ldr(R0, FieldAddress(IP, base + kWordSize)); |
+ __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
__ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
- __ ldr(target, FieldAddress(R0, Function::entry_point_offset())); |
} |
// Called from megamorphic calls. |
-// R0: receiver. |
-// R1: lookup cache. |
+// R0: receiver |
+// R9: MegamorphicCache (preserved) |
// Result: |
-// R1: entry point. |
+// R1: target entry point |
+// CODE_REG: target Code |
+// R4: arguments descriptor |
void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
- EmitMegamorphicLookup(assembler, R0, R1, R1); |
+ EmitMegamorphicLookup(assembler); |
+ __ Ret(); |
+} |
+ |
+ |
+// Called from switchable IC calls. |
+// R0: receiver |
+// R9: ICData (preserved) |
+// Result: |
+// R1: target entry point |
+// CODE_REG: target Code object |
+// R4: arguments descriptor |
+void StubCode::GenerateICLookupStub(Assembler* assembler) { |
+ Label loop, found, miss; |
+ __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); |
+ __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); |
+ __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); |
+ // R8: first IC entry |
+ __ LoadTaggedClassIdMayBeSmi(R1, R0); |
+ // R1: receiver cid as Smi |
+ |
+ __ Bind(&loop); |
+ __ ldr(R2, Address(R8, 0)); |
+ __ cmp(R1, Operand(R2)); |
+ __ b(&found, EQ); |
+ __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); |
+ __ b(&miss, EQ); |
+ |
+ const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; |
+ __ AddImmediate(R8, entry_length); // Next entry. |
+ __ b(&loop); |
+ |
+ __ Bind(&found); |
+ const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; |
+ __ LoadFromOffset(kWord, R0, R8, target_offset); |
+ __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
+ __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
+ __ Ret(); |
+ |
+ __ Bind(&miss); |
+ __ LoadIsolate(R2); |
+ __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); |
+ __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); |
__ Ret(); |
} |