| Index: runtime/vm/code_patcher_x64.cc
|
| ===================================================================
|
| --- runtime/vm/code_patcher_x64.cc (revision 27291)
|
| +++ runtime/vm/code_patcher_x64.cc (working copy)
|
| @@ -16,53 +16,60 @@
|
| namespace dart {
|
|
|
| // The expected pattern of a Dart unoptimized call (static and instance):
|
| -// 00: 48 bb imm64 mov RBX, ic-data
|
| -// 10: 49 bb imm64 mov R11, target_address
|
| -// 20: 41 ff d3 call R11
|
| -// 23 <- return address
|
| +// 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
|
| class UnoptimizedCall : public ValueObject {
|
| public:
|
| - explicit UnoptimizedCall(uword return_address)
|
| - : start_(return_address - kCallPatternSize) {
|
| + UnoptimizedCall(uword return_address, const Code& code)
|
| + : start_(return_address - kCallPatternSize),
|
| + object_pool_(Array::Handle(code.ObjectPool())) {
|
| ASSERT(IsValid(return_address));
|
| - ASSERT((kCallPatternSize - 10) == Assembler::kCallExternalLabelSize);
|
| + ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize);
|
| }
|
|
|
| - static const int kCallPatternSize = 23;
|
| + static const int kCallPatternSize = 17;
|
|
|
| static bool IsValid(uword return_address) {
|
| uint8_t* code_bytes =
|
| reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
|
| - return (code_bytes[00] == 0x48) && (code_bytes[01] == 0xBB) &&
|
| - (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) &&
|
| - (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) &&
|
| - (code_bytes[22] == 0xD3);
|
| + 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);
|
| }
|
|
|
| RawObject* ic_data() const {
|
| - return *reinterpret_cast<RawObject**>(start_ + 0 + 2);
|
| + int index = InstructionPattern::IndexFromPPLoad(start_ + 3);
|
| + return object_pool_.At(index);
|
| }
|
|
|
| uword target() const {
|
| - return *reinterpret_cast<uword*>(start_ + 10 + 2);
|
| + int index = InstructionPattern::IndexFromPPLoad(start_ + 10);
|
| + return reinterpret_cast<uword>(object_pool_.At(index));
|
| }
|
|
|
| void set_target(uword target) const {
|
| - uword* target_addr = reinterpret_cast<uword*>(start_ + 10 + 2);
|
| - *target_addr = target;
|
| - CPU::FlushICache(start_ + 10, 2 + 8);
|
| + int index = InstructionPattern::IndexFromPPLoad(start_ + 10);
|
| + 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(UnoptimizedCall);
|
| };
|
|
|
|
|
| class InstanceCall : public UnoptimizedCall {
|
| public:
|
| - explicit InstanceCall(uword return_address)
|
| - : UnoptimizedCall(return_address) {
|
| + InstanceCall(uword return_address, const Code& code)
|
| + : UnoptimizedCall(return_address, code) {
|
| #if defined(DEBUG)
|
| ICData& test_ic_data = ICData::Handle();
|
| test_ic_data ^= ic_data();
|
| @@ -77,8 +84,8 @@
|
|
|
| class UnoptimizedStaticCall : public UnoptimizedCall {
|
| public:
|
| - explicit UnoptimizedStaticCall(uword return_address)
|
| - : UnoptimizedCall(return_address) {
|
| + UnoptimizedStaticCall(uword return_address, const Code& code)
|
| + : UnoptimizedCall(return_address, code) {
|
| #if defined(DEBUG)
|
| ICData& test_ic_data = ICData::Handle();
|
| test_ic_data ^= ic_data();
|
| @@ -92,50 +99,54 @@
|
|
|
|
|
| // The expected pattern of a dart static call:
|
| -// mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls)
|
| -// mov R11, target_address (10 bytes)
|
| -// call R11 (3 bytes)
|
| +// 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)
|
| - : start_(return_address - kCallPatternSize) {
|
| + 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 = 13;
|
| + 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[00] == 0x49) && (code_bytes[01] == 0xBB) &&
|
| - (code_bytes[10] == 0x41) && (code_bytes[11] == 0xFF) &&
|
| - (code_bytes[12] == 0xD3);
|
| + 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 {
|
| - return *reinterpret_cast<uword*>(start_ + 2);
|
| + int index = InstructionPattern::IndexFromPPLoad(start_ + 3);
|
| + return reinterpret_cast<uword>(object_pool_.At(index));
|
| }
|
|
|
| void set_target(uword target) const {
|
| - uword* target_addr = reinterpret_cast<uword*>(start_ + 2);
|
| - *target_addr = target;
|
| - CPU::FlushICache(start_, 2 + 8);
|
| + int 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 code pattern of a dart closure call:
|
| -// 00: 49 ba imm64 mov R10, immediate 2 ; 10 bytes
|
| -// 10: 49 bb imm64 mov R11, target_address ; 10 bytes
|
| -// 20: 41 ff d3 call R11 ; 3 bytes
|
| -// 23: <- return_address
|
| +// 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 {
|
| public:
|
| explicit ClosureCall(uword return_address)
|
| @@ -147,9 +158,10 @@
|
| uint8_t* code_bytes =
|
| reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
|
| return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) &&
|
| - (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) &&
|
| - (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) &&
|
| - (code_bytes[22] == 0xD3);
|
| + (code_bytes[10] == 0x4D) && (code_bytes[11] == 0x8B) &&
|
| + (code_bytes[12] == 0x9F) &&
|
| + (code_bytes[17] == 0x41) && (code_bytes[18] == 0xFF) &&
|
| + (code_bytes[19] == 0xD3);
|
| }
|
|
|
| RawArray* arguments_descriptor() const {
|
| @@ -157,7 +169,7 @@
|
| }
|
|
|
| private:
|
| - static const int kCallPatternSize = 10 + 10 + 3;
|
| + static const int kCallPatternSize = 10 + 7 + 3;
|
| uword start_;
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall);
|
| };
|
| @@ -174,7 +186,7 @@
|
| uword CodePatcher::GetStaticCallTargetAt(uword return_address,
|
| const Code& code) {
|
| ASSERT(code.ContainsInstructionAt(return_address));
|
| - StaticCall call(return_address);
|
| + StaticCall call(return_address, code);
|
| return call.target();
|
| }
|
|
|
| @@ -183,7 +195,7 @@
|
| const Code& code,
|
| uword new_target) {
|
| ASSERT(code.ContainsInstructionAt(return_address));
|
| - StaticCall call(return_address);
|
| + StaticCall call(return_address, code);
|
| call.set_target(new_target);
|
| }
|
|
|
| @@ -192,7 +204,7 @@
|
| const Code& code,
|
| uword new_target) {
|
| ASSERT(code.ContainsInstructionAt(return_address));
|
| - InstanceCall call(return_address);
|
| + InstanceCall call(return_address, code);
|
| call.set_target(new_target);
|
| }
|
|
|
| @@ -201,7 +213,7 @@
|
| const Code& code,
|
| ICData* ic_data) {
|
| ASSERT(code.ContainsInstructionAt(return_address));
|
| - InstanceCall call(return_address);
|
| + InstanceCall call(return_address, code);
|
| if (ic_data != NULL) {
|
| *ic_data ^= call.ic_data();
|
| }
|
| @@ -227,7 +239,7 @@
|
| RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
|
| uword return_address, const Code& code, ICData* ic_data_result) {
|
| ASSERT(code.ContainsInstructionAt(return_address));
|
| - UnoptimizedStaticCall static_call(return_address);
|
| + UnoptimizedStaticCall static_call(return_address, code);
|
| ICData& ic_data = ICData::Handle();
|
| ic_data ^= static_call.ic_data();
|
| if (ic_data_result != NULL) {
|
|
|