| Index: runtime/vm/code_patcher_x64.cc
|
| ===================================================================
|
| --- runtime/vm/code_patcher_x64.cc (revision 42687)
|
| +++ runtime/vm/code_patcher_x64.cc (working copy)
|
| @@ -17,10 +17,9 @@
|
| namespace dart {
|
|
|
| // The expected pattern of a Dart unoptimized call (static and instance):
|
| -// 00: 49 8b 9f imm32 mov RBX, [PP + off]
|
| -// 07: 4d 8b 9f imm32 mov R11, [PP + off]
|
| -// 14: 41 ff d3 call R11
|
| -// 17 <- return address
|
| +// 0: 49 8b 9f imm32 mov RBX, [PP + off]
|
| +// 7: 41 ff 97 imm32 call [PP + off]
|
| +// 14 <- return address
|
| class UnoptimizedCall : public ValueObject {
|
| public:
|
| UnoptimizedCall(uword return_address, const Code& code)
|
| @@ -30,7 +29,7 @@
|
| ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize);
|
| }
|
|
|
| - static const int kCallPatternSize = 17;
|
| + static const int kCallPatternSize = 14;
|
|
|
| static bool IsValid(uword return_address) {
|
| uint8_t* code_bytes =
|
| @@ -37,10 +36,8 @@
|
| reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
|
| return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) &&
|
| (code_bytes[2] == 0x9F) &&
|
| - (code_bytes[7] == 0x4D) && (code_bytes[8] == 0x8B) &&
|
| - (code_bytes[9] == 0x9F) &&
|
| - (code_bytes[14] == 0x41) && (code_bytes[15] == 0xFF) &&
|
| - (code_bytes[16] == 0xD3);
|
| + (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
|
| + (code_bytes[9] == 0x97);
|
| }
|
|
|
| RawObject* ic_data() const {
|
| @@ -99,55 +96,10 @@
|
| };
|
|
|
|
|
| -// The expected pattern of a dart static call:
|
| -// 00 mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls)
|
| -// 11: 4d 8b 9f imm32 mov R11, [PP + off]
|
| -// 16: call R11 (3 bytes)
|
| -// <- return address
|
| -class StaticCall : public ValueObject {
|
| - public:
|
| - explicit StaticCall(uword return_address, const Code& code)
|
| - : start_(return_address - kCallPatternSize),
|
| - object_pool_(Array::Handle(code.ObjectPool())) {
|
| - ASSERT(IsValid(return_address));
|
| - ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize);
|
| - }
|
| -
|
| - static const int kCallPatternSize = 10;
|
| -
|
| - static bool IsValid(uword return_address) {
|
| - uint8_t* code_bytes =
|
| - reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
|
| - return (code_bytes[0] == 0x4D) && (code_bytes[1] == 0x8B) &&
|
| - (code_bytes[2] == 0x9F) &&
|
| - (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
|
| - (code_bytes[9] == 0xD3);
|
| - }
|
| -
|
| - uword target() const {
|
| - intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
|
| - return reinterpret_cast<uword>(object_pool_.At(index));
|
| - }
|
| -
|
| - void set_target(uword target) const {
|
| - intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
|
| - const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
|
| - object_pool_.SetAt(index, smi);
|
| - // No need to flush the instruction cache, since the code is not modified.
|
| - }
|
| -
|
| - private:
|
| - uword start_;
|
| - const Array& object_pool_;
|
| - DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
|
| -};
|
| -
|
| -
|
| // The expected pattern of a call where the target is loaded from
|
| // the object pool:
|
| -// 00: 4d 8b 9f imm32 mov R11, [PP + off]
|
| -// 07: 41 ff d3 call R11
|
| -// 10 <- return address
|
| +// 0: 41 ff 97 imm32 call [PP + off]
|
| +// 7: <- return address
|
| class PoolPointerCall : public ValueObject {
|
| public:
|
| explicit PoolPointerCall(uword return_address)
|
| @@ -155,13 +107,13 @@
|
| ASSERT(IsValid(return_address));
|
| }
|
|
|
| + static const int kCallPatternSize = 7;
|
| +
|
| static bool IsValid(uword return_address) {
|
| uint8_t* code_bytes =
|
| reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
|
| - return (code_bytes[0] == 0x4D) && (code_bytes[1] == 0x8B) &&
|
| - (code_bytes[2] == 0x9F) &&
|
| - (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
|
| - (code_bytes[9] == 0xD3);
|
| + return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) &&
|
| + (code_bytes[2] == 0x97);
|
| }
|
|
|
| int32_t pp_offset() const {
|
| @@ -173,54 +125,44 @@
|
| CPU::FlushICache(start_, kCallPatternSize);
|
| }
|
|
|
| + protected:
|
| + uword start_;
|
| +
|
| private:
|
| - static const int kCallPatternSize = 7 + 3;
|
| - uword start_;
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall);
|
| };
|
|
|
|
|
| -// The expected code pattern of a Dart closure call:
|
| -// 00: 49 ba imm64 mov R10, immediate 2 ; 10 bytes
|
| -// 10: 4d 8b 9f imm32 mov R11, [PP + off]
|
| -// 17: 41 ff d3 call R11 ; 3 bytes
|
| -// 20: <- return_address
|
| -class ClosureCall : public ValueObject {
|
| +// The expected pattern of a dart static call:
|
| +// 0: 41 ff 97 imm32 call [PP + off]
|
| +// 7: <- return address
|
| +class StaticCall : public PoolPointerCall {
|
| public:
|
| - explicit ClosureCall(uword return_address)
|
| - : start_(return_address - kCallPatternSize) {
|
| + StaticCall(uword return_address, const Code& code)
|
| + : PoolPointerCall(return_address),
|
| + object_pool_(Array::Handle(code.ObjectPool())) {
|
| ASSERT(IsValid(return_address));
|
| + ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize);
|
| }
|
|
|
| - static bool IsValid(uword return_address) {
|
| - uint8_t* code_bytes =
|
| - reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
|
| - return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) &&
|
| - (code_bytes[10] == 0x4D) && (code_bytes[11] == 0x8B) &&
|
| - (code_bytes[12] == 0x9F) &&
|
| - (code_bytes[17] == 0x41) && (code_bytes[18] == 0xFF) &&
|
| - (code_bytes[19] == 0xD3);
|
| + uword target() const {
|
| + intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
|
| + return reinterpret_cast<uword>(object_pool_.At(index));
|
| }
|
|
|
| - RawArray* arguments_descriptor() const {
|
| - return *reinterpret_cast<RawArray**>(start_ + 2);
|
| + void set_target(uword target) const {
|
| + intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
|
| + const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
|
| + object_pool_.SetAt(index, smi);
|
| + // No need to flush the instruction cache, since the code is not modified.
|
| }
|
|
|
| private:
|
| - static const int kCallPatternSize = 10 + 7 + 3;
|
| - uword start_;
|
| - DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall);
|
| + const Array& object_pool_;
|
| + DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
|
| };
|
|
|
|
|
| -RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
|
| - const Code& code) {
|
| - ASSERT(code.ContainsInstructionAt(return_address));
|
| - ClosureCall call(return_address);
|
| - return call.arguments_descriptor();
|
| -}
|
| -
|
| -
|
| uword CodePatcher::GetStaticCallTargetAt(uword return_address,
|
| const Code& code) {
|
| ASSERT(code.ContainsInstructionAt(return_address));
|
|
|