| 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();
|
| }
|
|
|
|
|
|
|