OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
11 #include "vm/instructions.h" | 11 #include "vm/instructions.h" |
12 #include "vm/object.h" | 12 #include "vm/object.h" |
13 #include "vm/raw_object.h" | 13 #include "vm/raw_object.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
17 // The pattern of a Dart call is: | 17 // The pattern of a Dart instance call is: |
18 // 00: 48 bb imm64 mov RBX, immediate 1 | 18 // 00: 48 bb imm64 mov RBX, immediate 1 |
19 // 10: 49 ba imm64 mov R10, immediate 2 | 19 // 10: 49 ba imm64 mov R10, immediate 2 |
20 // 20: 49 bb imm64 mov R11, target_address | 20 // 20: 49 bb imm64 mov R11, target_address |
21 // 30: 41 ff d3 call R11 | 21 // 30: 41 ff d3 call R11 |
22 // 33: <- return_address | 22 // 33: <- return_address |
23 class DartCallPattern : public ValueObject { | 23 class DartCallPattern : public ValueObject { |
24 public: | 24 public: |
25 explicit DartCallPattern(uword return_address) | 25 explicit DartCallPattern(uword return_address) |
26 : start_(return_address - kCallPatternSize) { | 26 : start_(return_address - kCallPatternSize) { |
27 ASSERT(IsValid(return_address)); | 27 ASSERT(IsValid(return_address)); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 Smi& num_pos_args = Smi::Handle(); | 80 Smi& num_pos_args = Smi::Handle(); |
81 num_pos_args ^= args_desc.At(1); | 81 num_pos_args ^= args_desc.At(1); |
82 return num_args.Value() - num_pos_args.Value(); | 82 return num_args.Value() - num_pos_args.Value(); |
83 } | 83 } |
84 | 84 |
85 uword start_; | 85 uword start_; |
86 DISALLOW_IMPLICIT_CONSTRUCTORS(DartCallPattern); | 86 DISALLOW_IMPLICIT_CONSTRUCTORS(DartCallPattern); |
87 }; | 87 }; |
88 | 88 |
89 | 89 |
90 // A Dart static call passes the function object in RBX. | |
91 class StaticCall : public DartCallPattern { | |
92 public: | |
93 explicit StaticCall(uword return_address) | |
94 : DartCallPattern(return_address) {} | |
95 | |
96 RawFunction* function() const { | |
97 Function& f = Function::Handle(); | |
98 f ^= reinterpret_cast<RawObject*>(immediate_one()); | |
99 return f.raw(); | |
100 } | |
101 | |
102 private: | |
103 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); | |
104 }; | |
105 | |
106 | |
107 // A Dart instance call passes the ic-data in RBX. | 90 // A Dart instance call passes the ic-data in RBX. |
| 91 // The expected pattern of a dart instance call: |
| 92 // mov RBX, ic-data |
| 93 // mov R10, argument_descriptor_array |
| 94 // mov R11, target_address |
| 95 // call R11 |
| 96 // <- return address |
108 class InstanceCall : public DartCallPattern { | 97 class InstanceCall : public DartCallPattern { |
109 public: | 98 public: |
110 explicit InstanceCall(uword return_address) | 99 explicit InstanceCall(uword return_address) |
111 : DartCallPattern(return_address) {} | 100 : DartCallPattern(return_address) {} |
112 | 101 |
113 RawICData* ic_data() const { | 102 RawICData* ic_data() const { |
114 ICData& ic_data = ICData::Handle(); | 103 ICData& ic_data = ICData::Handle(); |
115 ic_data ^= reinterpret_cast<RawObject*>(immediate_one()); | 104 ic_data ^= reinterpret_cast<RawObject*>(immediate_one()); |
116 return ic_data.raw(); | 105 return ic_data.raw(); |
117 } | 106 } |
118 | 107 |
119 private: | 108 private: |
120 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); | 109 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); |
121 }; | 110 }; |
122 | 111 |
123 | 112 |
| 113 // The expected pattern of a dart static call: |
| 114 // mov R10, argument_descriptor_array (10 bytes) |
| 115 // mov R11, target_address (10 bytes) |
| 116 // call R11 (3 bytes) |
| 117 // <- return address |
| 118 class StaticCall : public ValueObject { |
| 119 public: |
| 120 explicit StaticCall(uword return_address) |
| 121 : start_(return_address - kCallPatternSize) { |
| 122 ASSERT(IsValid(return_address)); |
| 123 ASSERT((kCallPatternSize - 10) == Assembler::kCallExternalLabelSize); |
| 124 } |
| 125 |
| 126 static const int kCallPatternSize = 23; |
| 127 |
| 128 static bool IsValid(uword return_address) { |
| 129 uint8_t* code_bytes = |
| 130 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); |
| 131 return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) && |
| 132 (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) && |
| 133 (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) && |
| 134 (code_bytes[22] == 0xD3); |
| 135 } |
| 136 |
| 137 uword target() const { |
| 138 return *reinterpret_cast<uword*>(start_ + 10 + 2); |
| 139 } |
| 140 |
| 141 void set_target(uword target) const { |
| 142 uword* target_addr = reinterpret_cast<uword*>(start_ + 10 + 2); |
| 143 *target_addr = target; |
| 144 CPU::FlushICache(start_ + 10, 2 + 8); |
| 145 } |
| 146 |
| 147 private: |
| 148 uword start_; |
| 149 |
| 150 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); |
| 151 }; |
| 152 |
| 153 |
124 uword CodePatcher::GetStaticCallTargetAt(uword return_address) { | 154 uword CodePatcher::GetStaticCallTargetAt(uword return_address) { |
125 StaticCall call(return_address); | 155 StaticCall call(return_address); |
126 return call.target(); | 156 return call.target(); |
127 } | 157 } |
128 | 158 |
129 | 159 |
130 void CodePatcher::PatchStaticCallAt(uword return_address, uword new_target) { | 160 void CodePatcher::PatchStaticCallAt(uword return_address, uword new_target) { |
131 StaticCall call(return_address); | 161 StaticCall call(return_address); |
132 call.set_target(new_target); | 162 call.set_target(new_target); |
133 } | 163 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 *reinterpret_cast<uint8_t*>(start) = 0xE8; | 271 *reinterpret_cast<uint8_t*>(start) = 0xE8; |
242 ShortCallPattern call(start); | 272 ShortCallPattern call(start); |
243 call.SetTargetAddress(target); | 273 call.SetTargetAddress(target); |
244 CPU::FlushICache(start, ShortCallPattern::InstructionLength()); | 274 CPU::FlushICache(start, ShortCallPattern::InstructionLength()); |
245 } | 275 } |
246 | 276 |
247 | 277 |
248 } // namespace dart | 278 } // namespace dart |
249 | 279 |
250 #endif // defined TARGET_ARCH_X64 | 280 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |