Index: runtime/vm/code_patcher_x64.cc |
diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc |
index b8863dc721b87999568d37e2d1adbf56b3a37f1b..0e18f6f046672c96a3ed6ce8403c38999f1e7616 100644 |
--- a/runtime/vm/code_patcher_x64.cc |
+++ b/runtime/vm/code_patcher_x64.cc |
@@ -190,10 +190,11 @@ class PoolPointerCall : public ValueObject { |
}; |
-// Instance call that can switch from an IC call to a megamorphic call |
-// load ICData load MegamorphicCache |
-// call ICLookup stub -> call MegamorphicLookup stub |
-// call target call target |
+// Instance call that can switch between a direct monomorphic call, an IC call, |
+// and a megamorphic call. |
+// load guarded cid load ICData load MegamorphicCache |
+// load monomorphic target <-> load ICLookup stub -> load MMLookup stub |
+// call target.entry call stub.entry call stub.entry |
class SwitchableCall : public ValueObject { |
public: |
SwitchableCall(uword return_address, const Code& code) |
@@ -202,39 +203,42 @@ class SwitchableCall : public ValueObject { |
ASSERT(IsValid()); |
} |
- static const int kCallPatternSize = 24; |
+ static const int kCallPatternSize = 21; |
bool IsValid() const { |
static int16_t pattern[kCallPatternSize] = { |
0x49, 0x8b, 0x9f, -1, -1, -1, -1, // movq rbx, [PP + cache_offs] |
0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq r12, [PP + code_offs] |
- 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq r11, [r12 + entrypoint_off] |
- 0x41, 0xff, 0xd3, // call r11 |
+ 0x49, 0x8b, 0x4c, 0x24, 0x0f, // movq rcx, [r12 + entrypoint_off] |
0xff, 0xd1, // call rcx |
}; |
+ ASSERT(ARRAY_SIZE(pattern) == kCallPatternSize); |
return MatchesPattern(start_, pattern, kCallPatternSize); |
} |
- intptr_t cache_index() const { |
+ intptr_t data_index() const { |
return IndexFromPPLoad(start_ + 3); |
} |
- intptr_t lookup_stub_index() const { |
+ intptr_t target_index() const { |
return IndexFromPPLoad(start_ + 10); |
} |
- RawObject* cache() const { |
- return object_pool_.ObjectAt(cache_index()); |
+ RawObject* data() const { |
+ return object_pool_.ObjectAt(data_index()); |
+ } |
+ RawCode* target() const { |
+ return reinterpret_cast<RawCode*>(object_pool_.ObjectAt(target_index())); |
} |
- void SetCache(const MegamorphicCache& cache) const { |
- ASSERT(Object::Handle(object_pool_.ObjectAt(cache_index())).IsICData()); |
- object_pool_.SetObjectAt(cache_index(), cache); |
+ void SetData(const Object& data) const { |
+ ASSERT(!Object::Handle(object_pool_.ObjectAt(data_index())).IsCode()); |
+ object_pool_.SetObjectAt(data_index(), data); |
// No need to flush the instruction cache, since the code is not modified. |
} |
- void SetLookupStub(const Code& lookup_stub) const { |
- ASSERT(Object::Handle(object_pool_.ObjectAt(lookup_stub_index())).IsCode()); |
- object_pool_.SetObjectAt(lookup_stub_index(), lookup_stub); |
+ void SetTarget(const Code& target) const { |
+ ASSERT(Object::Handle(object_pool_.ObjectAt(target_index())).IsCode()); |
+ object_pool_.SetObjectAt(target_index(), target); |
// No need to flush the instruction cache, since the code is not modified. |
} |
@@ -313,15 +317,29 @@ RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( |
void CodePatcher::PatchSwitchableCallAt(uword return_address, |
- const Code& code, |
- const ICData& ic_data, |
- const MegamorphicCache& cache, |
- const Code& lookup_stub) { |
- ASSERT(code.ContainsInstructionAt(return_address)); |
- SwitchableCall call(return_address, code); |
- ASSERT(call.cache() == ic_data.raw()); |
- call.SetLookupStub(lookup_stub); |
- call.SetCache(cache); |
+ const Code& caller_code, |
+ const Object& data, |
+ const Code& target) { |
+ ASSERT(caller_code.ContainsInstructionAt(return_address)); |
+ SwitchableCall call(return_address, caller_code); |
+ call.SetData(data); |
+ call.SetTarget(target); |
+} |
+ |
+ |
+RawCode* CodePatcher::GetSwitchableCallTargetAt(uword return_address, |
+ const Code& caller_code) { |
+ ASSERT(caller_code.ContainsInstructionAt(return_address)); |
+ SwitchableCall call(return_address, caller_code); |
+ return call.target(); |
+} |
+ |
+ |
+RawObject* CodePatcher::GetSwitchableCallDataAt(uword return_address, |
+ const Code& caller_code) { |
+ ASSERT(caller_code.ContainsInstructionAt(return_address)); |
+ SwitchableCall call(return_address, caller_code); |
+ return call.data(); |
} |