Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(840)

Unified Diff: runtime/vm/stub_code_ia32.cc

Issue 2131583002: Optimized megamorphic stubs (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Addressed Florians comments. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/stub_code_ia32.cc
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 139a4a24bfd4508be799f9ab0721d5a05dc72789..d837eb8a7b03559b4e8cc0495b4701a776ffaac3 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -2029,8 +2029,12 @@ void StubCode::EmitMegamorphicLookup(Assembler* assembler) {
// EDI: cache buckets array.
// EBX: mask.
__ pushl(ECX); // Spill MegamorphicCache.
- __ movl(ECX, EAX);
- __ imull(ECX, Immediate(MegamorphicCache::kSpreadFactor));
+
+ // Compute the table index.
+ ASSERT(MegamorphicCache::kSpreadFactor == 7);
+ // Use leal and subl multiply with 7 == 8 - 1.
+ __ leal(ECX, Address(EAX, TIMES_8, 0));
+ __ subl(ECX, EAX);
// ECX: probe.
Label loop, update, load_target_function;
@@ -2070,10 +2074,68 @@ void StubCode::EmitMegamorphicLookup(Assembler* assembler) {
// EBX: target entry point
// EDX: argument descriptor
void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
- EmitMegamorphicLookup(assembler);
+ // Jump if receiver is a smi.
+ Label smi_case;
+ // Check if object (in tmp) is a Smi.
+ __ testl(EBX, Immediate(kSmiTagMask));
+ // Jump out of line for smi case.
+ __ j(ZERO, &smi_case, Assembler::kNearJump);
+
+ // Loads the cid of the instance.
+ __ LoadClassId(EAX, EBX);
+
+ Label cid_loaded;
+ __ Bind(&cid_loaded);
+ __ movl(EBX, FieldAddress(ECX, MegamorphicCache::mask_offset()));
+ __ movl(EDI, FieldAddress(ECX, MegamorphicCache::buckets_offset()));
+ // EDI: cache buckets array.
+ // EBX: mask.
+
+ // Tag cid as a smi.
+ __ addl(EAX, EAX);
+
+ // Compute the table index.
+ ASSERT(MegamorphicCache::kSpreadFactor == 7);
+ // Use leal and subl multiply with 7 == 8 - 1.
+ __ leal(EDX, Address(EAX, TIMES_8, 0));
+ __ subl(EDX, EAX);
+
+ Label loop;
+ __ Bind(&loop);
+ __ andl(EDX, EBX);
+
+ const intptr_t base = Array::data_offset();
+ Label probe_failed;
+ // EDX is smi tagged, but table entries are two words, so TIMES_4.
+ __ cmpl(EAX, FieldAddress(EDI, EDX, TIMES_4, base));
+ __ j(NOT_EQUAL, &probe_failed, Assembler::kNearJump);
+
+ Label load_target;
+ __ Bind(&load_target);
+ // 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.
+ __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, base + kWordSize));
+ __ movl(EDX,
+ FieldAddress(ECX, MegamorphicCache::arguments_descriptor_offset()));
+ __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
__ ret();
-}
+ __ Bind(&probe_failed);
+ // Probe failed, check if it is a miss.
+ __ cmpl(FieldAddress(EDI, EDX, TIMES_4, base), Immediate(kIllegalCid));
+ __ j(ZERO, &load_target, Assembler::kNearJump);
+
+ // Try next extry in the table.
+ __ AddImmediate(EDX, Immediate(Smi::RawValue(1)));
+ __ jmp(&loop);
+
+ // Load cid for the Smi case.
+ __ Bind(&smi_case);
+ __ movl(EAX, Immediate(kSmiCid));
+ __ jmp(&cid_loaded);
+}
// Called from switchable IC calls.
// EBX: receiver

Powered by Google App Engine
This is Rietveld 408576698