Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Side by Side Diff: runtime/vm/code_patcher_x64.cc

Issue 1343373003: Revert "VM: New calling convention for generated code." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/code_patcher_mips.cc ('k') | runtime/vm/compiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/dart_entry.h" 11 #include "vm/dart_entry.h"
12 #include "vm/flow_graph_compiler.h" 12 #include "vm/flow_graph_compiler.h"
13 #include "vm/instructions.h" 13 #include "vm/instructions.h"
14 #include "vm/object.h" 14 #include "vm/object.h"
15 #include "vm/raw_object.h" 15 #include "vm/raw_object.h"
16 16
17 namespace dart { 17 namespace dart {
18 18
19 19 // The expected pattern of a Dart unoptimized call (static and instance):
20 static bool MatchesPattern(uword addr, int16_t* pattern, intptr_t size) { 20 // 0: 49 8b 9f imm32 mov RBX, [PP + off]
21 uint8_t* bytes = reinterpret_cast<uint8_t*>(addr); 21 // 7: 41 ff 97 imm32 call [PP + off]
22 for (intptr_t i = 0; i < size; i++) { 22 // 14 <- return address
23 int16_t val = pattern[i];
24 if ((val >= 0) && (val != bytes[i])) {
25 return false;
26 }
27 }
28 return true;
29 }
30
31
32 intptr_t IndexFromPPLoad(uword start) {
33 int32_t offset = *reinterpret_cast<int32_t*>(start);
34 return ObjectPool::IndexFromOffset(offset);
35 }
36
37
38 class UnoptimizedCall : public ValueObject { 23 class UnoptimizedCall : public ValueObject {
39 public: 24 public:
40 UnoptimizedCall(uword return_address, const Code& code) 25 UnoptimizedCall(uword return_address, const Code& code)
41 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), 26 : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
42 start_(return_address - kCallPatternSize) { 27 start_(return_address - kCallPatternSize) {
28 ASSERT(IsValid(return_address));
43 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); 29 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize);
44 ASSERT(IsValid());
45 } 30 }
46 31
47 static const int kCallPatternSize = 22; 32 static const int kCallPatternSize = 14;
48 33
49 bool IsValid() const { 34 static bool IsValid(uword return_address) {
50 static int16_t pattern[kCallPatternSize] = { 35 uint8_t* code_bytes =
51 0x49, 0x8b, 0x9f, -1, -1, -1, -1, // movq RBX, [PP + offs] 36 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
52 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs] 37 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) &&
53 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + entry_point_offs] 38 (code_bytes[2] == 0x9F) &&
54 0x41, 0xff, 0xd3 // callq TMP 39 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
55 }; 40 (code_bytes[9] == 0x97);
56 return MatchesPattern(start_, pattern, kCallPatternSize);
57 } 41 }
58 42
59 intptr_t argument_index() const { 43 intptr_t argument_index() const {
60 return IndexFromPPLoad(start_ + 3); 44 return IndexFromPPLoad(start_ + 3);
61 } 45 }
62 46
63 RawObject* ic_data() const { 47 RawObject* ic_data() const {
64 return object_pool_.ObjectAt(argument_index()); 48 return object_pool_.ObjectAt(argument_index());
65 } 49 }
66 50
67 RawCode* target() const { 51 uword target() const {
68 intptr_t index = IndexFromPPLoad(start_ + 10); 52 intptr_t index = IndexFromPPLoad(start_ + 10);
69 Code& code = Code::Handle(); 53 return object_pool_.RawValueAt(index);
70 code ^= object_pool_.ObjectAt(index);
71 return code.raw();
72 } 54 }
73 55
74 void set_target(const Code& target) const { 56 void set_target(uword target) const {
75 intptr_t index = IndexFromPPLoad(start_ + 10); 57 intptr_t index = IndexFromPPLoad(start_ + 10);
76 object_pool_.SetObjectAt(index, target); 58 object_pool_.SetRawValueAt(index, target);
77 // No need to flush the instruction cache, since the code is not modified. 59 // No need to flush the instruction cache, since the code is not modified.
78 } 60 }
79 61
80 protected: 62 protected:
81 const ObjectPool& object_pool_; 63 const ObjectPool& object_pool_;
82 64
83 private: 65 private:
84 uword start_; 66 uword start_;
85 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); 67 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall);
86 }; 68 };
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 ASSERT(test_ic_data.NumArgsTested() >= 0); 115 ASSERT(test_ic_data.NumArgsTested() >= 0);
134 #endif // DEBUG 116 #endif // DEBUG
135 } 117 }
136 118
137 private: 119 private:
138 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); 120 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall);
139 }; 121 };
140 122
141 123
142 // The expected pattern of a call where the target is loaded from 124 // The expected pattern of a call where the target is loaded from
143 // the object pool. 125 // the object pool:
126 // 0: 41 ff 97 imm32 call [PP + off]
127 // 7: <- return address
144 class PoolPointerCall : public ValueObject { 128 class PoolPointerCall : public ValueObject {
145 public: 129 public:
146 explicit PoolPointerCall(uword return_address, const Code& code) 130 explicit PoolPointerCall(uword return_address, const Code& code)
147 : start_(return_address - kCallPatternSize), 131 : start_(return_address - kCallPatternSize),
148 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { 132 object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
149 ASSERT(IsValid()); 133 ASSERT(IsValid(return_address));
150 } 134 }
151 135
152 static const int kCallPatternSize = 15; 136 static const int kCallPatternSize = 7;
153 137
154 bool IsValid() const { 138 static bool IsValid(uword return_address) {
155 static int16_t pattern[kCallPatternSize] = { 139 uint8_t* code_bytes =
156 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs] 140 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
157 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + entry_point_off] 141 return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) &&
158 0x41, 0xff, 0xd3 // callq TMP 142 (code_bytes[2] == 0x97);
159 };
160 return MatchesPattern(start_, pattern, kCallPatternSize);
161 } 143 }
162 144
163 intptr_t pp_index() const { 145 intptr_t pp_index() const {
164 return IndexFromPPLoad(start_ + 3); 146 return IndexFromPPLoad(start_ + 3);
165 } 147 }
166 148
167 RawCode* Target() const { 149 uword Target() const {
168 Code& code = Code::Handle(); 150 return object_pool_.RawValueAt(pp_index());
169 code ^= object_pool_.ObjectAt(pp_index());
170 return code.raw();
171 } 151 }
172 152
173 void SetTarget(const Code& target) const { 153 void SetTarget(uword target) const {
174 object_pool_.SetObjectAt(pp_index(), target); 154 object_pool_.SetRawValueAt(pp_index(), target);
175 // No need to flush the instruction cache, since the code is not modified. 155 // No need to flush the instruction cache, since the code is not modified.
176 } 156 }
177 157
178 protected: 158 protected:
179 uword start_; 159 uword start_;
180 const ObjectPool& object_pool_; 160 const ObjectPool& object_pool_;
181 161
182 private: 162 private:
183 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); 163 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall);
184 }; 164 };
185 165
186 166
187 RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address, 167 uword CodePatcher::GetStaticCallTargetAt(uword return_address,
188 const Code& code) { 168 const Code& code) {
189 ASSERT(code.ContainsInstructionAt(return_address)); 169 ASSERT(code.ContainsInstructionAt(return_address));
190 PoolPointerCall call(return_address, code); 170 PoolPointerCall call(return_address, code);
191 return call.Target(); 171 return call.Target();
192 } 172 }
193 173
194 174
195 void CodePatcher::PatchStaticCallAt(uword return_address, 175 void CodePatcher::PatchStaticCallAt(uword return_address,
196 const Code& code, 176 const Code& code,
197 const Code& new_target) { 177 uword new_target) {
198 PatchPoolPointerCallAt(return_address, code, new_target); 178 PatchPoolPointerCallAt(return_address, code, new_target);
199 } 179 }
200 180
201 181
202 void CodePatcher::PatchPoolPointerCallAt(uword return_address, 182 void CodePatcher::PatchPoolPointerCallAt(uword return_address,
203 const Code& code, 183 const Code& code,
204 const Code& new_target) { 184 uword new_target) {
205 ASSERT(code.ContainsInstructionAt(return_address)); 185 ASSERT(code.ContainsInstructionAt(return_address));
206 PoolPointerCall call(return_address, code); 186 PoolPointerCall call(return_address, code);
207 call.SetTarget(new_target); 187 call.SetTarget(new_target);
208 } 188 }
209 189
210 190
211 RawCode* CodePatcher::GetInstanceCallAt(uword return_address, 191 void CodePatcher::PatchInstanceCallAt(uword return_address,
212 const Code& code, 192 const Code& code,
213 ICData* ic_data) { 193 uword new_target) {
194 ASSERT(code.ContainsInstructionAt(return_address));
195 InstanceCall call(return_address, code);
196 call.set_target(new_target);
197 }
198
199
200 uword CodePatcher::GetInstanceCallAt(uword return_address,
201 const Code& code,
202 ICData* ic_data) {
214 ASSERT(code.ContainsInstructionAt(return_address)); 203 ASSERT(code.ContainsInstructionAt(return_address));
215 InstanceCall call(return_address, code); 204 InstanceCall call(return_address, code);
216 if (ic_data != NULL) { 205 if (ic_data != NULL) {
217 *ic_data ^= call.ic_data(); 206 *ic_data ^= call.ic_data();
218 } 207 }
219 return call.target(); 208 return call.target();
220 } 209 }
221 210
222 211
223 intptr_t CodePatcher::InstanceCallSizeInBytes() { 212 intptr_t CodePatcher::InstanceCallSizeInBytes() {
224 return InstanceCall::kCallPatternSize; 213 return InstanceCall::kCallPatternSize;
225 } 214 }
226 215
227 216
228 void CodePatcher::InsertDeoptimizationCallAt(uword start, uword target) { 217 void CodePatcher::InsertCallAt(uword start, uword target) {
229 // The inserted call should not overlap the lazy deopt jump code. 218 // The inserted call should not overlap the lazy deopt jump code.
230 ASSERT(start + ShortCallPattern::pattern_length_in_bytes() <= target); 219 ASSERT(start + ShortCallPattern::pattern_length_in_bytes() <= target);
231 *reinterpret_cast<uint8_t*>(start) = 0xE8; 220 *reinterpret_cast<uint8_t*>(start) = 0xE8;
232 ShortCallPattern call(start); 221 ShortCallPattern call(start);
233 call.SetTargetAddress(target); 222 call.SetTargetAddress(target);
234 CPU::FlushICache(start, ShortCallPattern::pattern_length_in_bytes()); 223 CPU::FlushICache(start, ShortCallPattern::pattern_length_in_bytes());
235 } 224 }
236 225
237 226
238 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( 227 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
239 uword return_address, const Code& code, ICData* ic_data_result) { 228 uword return_address, const Code& code, ICData* ic_data_result) {
240 ASSERT(code.ContainsInstructionAt(return_address)); 229 ASSERT(code.ContainsInstructionAt(return_address));
241 UnoptimizedStaticCall static_call(return_address, code); 230 UnoptimizedStaticCall static_call(return_address, code);
242 ICData& ic_data = ICData::Handle(); 231 ICData& ic_data = ICData::Handle();
243 ic_data ^= static_call.ic_data(); 232 ic_data ^= static_call.ic_data();
244 if (ic_data_result != NULL) { 233 if (ic_data_result != NULL) {
245 *ic_data_result = ic_data.raw(); 234 *ic_data_result = ic_data.raw();
246 } 235 }
247 return ic_data.GetTargetAt(0); 236 return ic_data.GetTargetAt(0);
248 } 237 }
249 238
250 239
251 void CodePatcher::PatchNativeCallAt(uword return_address, 240 void CodePatcher::PatchNativeCallAt(uword return_address,
252 const Code& code, 241 const Code& code,
253 NativeFunction target, 242 NativeFunction target,
254 const Code& trampoline) { 243 const Code& trampoline) {
255 ASSERT(code.ContainsInstructionAt(return_address)); 244 ASSERT(code.ContainsInstructionAt(return_address));
256 NativeCall call(return_address, code); 245 NativeCall call(return_address, code);
257 call.set_target(trampoline); 246 call.set_target(trampoline.EntryPoint());
258 call.set_native_function(target); 247 call.set_native_function(target);
259 } 248 }
260 249
261 250
262 RawCode* CodePatcher::GetNativeCallAt(uword return_address, 251 uword CodePatcher::GetNativeCallAt(uword return_address,
263 const Code& code, 252 const Code& code,
264 NativeFunction* target) { 253 NativeFunction* target) {
265 ASSERT(code.ContainsInstructionAt(return_address)); 254 ASSERT(code.ContainsInstructionAt(return_address));
266 NativeCall call(return_address, code); 255 NativeCall call(return_address, code);
267 *target = call.native_function(); 256 *target = call.native_function();
268 return call.target(); 257 return call.target();
269 } 258 }
270 259
271 260
272 // The expected code pattern of an edge counter in unoptimized code: 261 // The expected code pattern of an edge counter in unoptimized code:
273 // 49 8b 87 imm32 mov RAX, [PP + offset] 262 // 49 8b 87 imm32 mov RAX, [PP + offset]
274 class EdgeCounter : public ValueObject { 263 class EdgeCounter : public ValueObject {
(...skipping 21 matching lines...) Expand all
296 285
297 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { 286 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) {
298 ASSERT(code.ContainsInstructionAt(pc)); 287 ASSERT(code.ContainsInstructionAt(pc));
299 EdgeCounter counter(pc, code); 288 EdgeCounter counter(pc, code);
300 return counter.edge_counter(); 289 return counter.edge_counter();
301 } 290 }
302 291
303 } // namespace dart 292 } // namespace dart
304 293
305 #endif // defined TARGET_ARCH_X64 294 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/code_patcher_mips.cc ('k') | runtime/vm/compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698