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

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

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: ia32 port, addressed comments 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
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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 // The expected pattern of a Dart unoptimized call (static and instance): 19 // The expected pattern of a Dart unoptimized call (static and instance):
20 // mov ECX, ic-data 20 // mov ECX, ic-data
21 // mov EDI, target-code-object
21 // call target_address (stub) 22 // call target_address (stub)
22 // <- return address 23 // <- return address
23 class UnoptimizedCall : public ValueObject { 24 class UnoptimizedCall : public ValueObject {
24 public: 25 public:
25 explicit UnoptimizedCall(uword return_address) 26 explicit UnoptimizedCall(uword return_address)
26 : start_(return_address - (kNumInstructions * kInstructionSize)) { 27 : start_(return_address - kPatternSize) {
27 ASSERT(IsValid(return_address)); 28 ASSERT(IsValid());
28 ASSERT(kInstructionSize == Assembler::kCallExternalLabelSize);
29 }
30
31 static bool IsValid(uword return_address) {
32 uint8_t* code_bytes =
33 reinterpret_cast<uint8_t*>(
34 return_address - (kNumInstructions * kInstructionSize));
35 return (code_bytes[0] == 0xB9) &&
36 (code_bytes[1 * kInstructionSize] == 0xE8);
37 }
38
39 uword target() const {
40 const uword offset = *reinterpret_cast<uword*>(call_address() + 1);
41 return return_address() + offset;
42 }
43
44 void set_target(uword target) const {
45 uword* target_addr = reinterpret_cast<uword*>(call_address() + 1);
46 uword offset = target - return_address();
47 WritableInstructionsScope writable(reinterpret_cast<uword>(target_addr),
48 sizeof(offset));
49 *target_addr = offset;
50 CPU::FlushICache(call_address(), kInstructionSize);
51 } 29 }
52 30
53 RawObject* ic_data() const { 31 RawObject* ic_data() const {
54 return *reinterpret_cast<RawObject**>(start_ + 1); 32 return *reinterpret_cast<RawObject**>(start_ + 1);
55 } 33 }
56 34
57 static const int kNumInstructions = 2; 35 static const int kMovInstructionSize = 5;
58 static const int kInstructionSize = 5; // All instructions have same length. 36 static const int kCallInstructionSize = 3;
37 static const int kPatternSize =
38 2 * kMovInstructionSize + kCallInstructionSize;
59 39
60 private: 40 private:
41 bool IsValid() {
42 uint8_t* code_bytes = reinterpret_cast<uint8_t*>(start_);
43 return (code_bytes[0] == 0xB9) &&
44 (code_bytes[2 * kMovInstructionSize] == 0xFF);
45 }
46
61 uword return_address() const { 47 uword return_address() const {
62 return start_ + kNumInstructions * kInstructionSize; 48 return start_ + kPatternSize;
63 } 49 }
64 50
65 uword call_address() const { 51 uword call_address() const {
66 return start_ + 1 * kInstructionSize; 52 return start_ + 2 * kMovInstructionSize;
67 } 53 }
68 54
69 protected: 55 protected:
70 uword start_; 56 uword start_;
71 57
72 private: 58 private:
73 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); 59 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall);
74 }; 60 };
75 61
76 62
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 #endif // DEBUG 106 #endif // DEBUG
121 } 107 }
122 108
123 private: 109 private:
124 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); 110 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall);
125 }; 111 };
126 112
127 113
128 // The expected pattern of a dart static call: 114 // The expected pattern of a dart static call:
129 // mov EDX, arguments_descriptor_array (optional in polymorphic calls) 115 // mov EDX, arguments_descriptor_array (optional in polymorphic calls)
130 // call target_address 116 // mov EDI, Immediate(code_object)
117 // call [EDI + entry_point_offset]
131 // <- return address 118 // <- return address
132 class StaticCall : public ValueObject { 119 class StaticCall : public ValueObject {
133 public: 120 public:
134 explicit StaticCall(uword return_address) 121 explicit StaticCall(uword return_address)
135 : start_(return_address - (kNumInstructions * kInstructionSize)) { 122 : start_(return_address - (kMovInstructionSize + kCallInstructionSize)) {
136 ASSERT(IsValid(return_address)); 123 ASSERT(IsValid());
137 ASSERT(kInstructionSize == Assembler::kCallExternalLabelSize);
138 } 124 }
139 125
140 static bool IsValid(uword return_address) { 126 bool IsValid() {
141 uint8_t* code_bytes = 127 uint8_t* code_bytes = reinterpret_cast<uint8_t*>(start_);
142 reinterpret_cast<uint8_t*>( 128 return (code_bytes[0] == 0xBF) && (code_bytes[5] == 0xFF);
143 return_address - (kNumInstructions * kInstructionSize));
144 return (code_bytes[0] == 0xE8);
145 } 129 }
146 130
147 uword target() const { 131 RawCode* target() const {
148 const uword offset = *reinterpret_cast<uword*>(call_address() + 1); 132 const uword imm = *reinterpret_cast<uword*>(start_ + 1);
149 return return_address() + offset; 133 return reinterpret_cast<RawCode*>(imm);
150 } 134 }
151 135
152 void set_target(uword target) const { 136 void set_target(const Code& target) const {
153 uword* target_addr = reinterpret_cast<uword*>(call_address() + 1); 137 uword* target_addr = reinterpret_cast<uword*>(start_ + 1);
154 uword offset = target - return_address(); 138 uword imm = reinterpret_cast<uword>(target.raw());
155 *target_addr = offset; 139 *target_addr = imm;
156 CPU::FlushICache(call_address(), kInstructionSize); 140 CPU::FlushICache(start_ + 1, sizeof(imm));
157 } 141 }
158 142
159 static const int kNumInstructions = 1; 143 static const int kNumInstructions = 2;
160 static const int kInstructionSize = 5; // All instructions have same length. 144 static const int kMovInstructionSize = 5;
145 static const int kCallInstructionSize = 3;
161 146
162 private: 147 private:
163 uword return_address() const { 148 uword return_address() const {
164 return start_ + kNumInstructions * kInstructionSize; 149 return start_ + kMovInstructionSize + kCallInstructionSize;
165 } 150 }
166 151
167 uword call_address() const { 152 uword call_address() const {
168 return start_; 153 return start_ + kMovInstructionSize;
169 } 154 }
170 155
171 uword start_; 156 uword start_;
172 157
173 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); 158 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
174 }; 159 };
175 160
176 161
177 uword CodePatcher::GetStaticCallTargetAt(uword return_address, 162 RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address,
178 const Code& code) { 163 const Code& code) {
179 ASSERT(code.ContainsInstructionAt(return_address)); 164 ASSERT(code.ContainsInstructionAt(return_address));
180 StaticCall call(return_address); 165 StaticCall call(return_address);
181 return call.target(); 166 return call.target();
182 } 167 }
183 168
184 169
185 void CodePatcher::PatchStaticCallAt(uword return_address, 170 void CodePatcher::PatchStaticCallAt(uword return_address,
186 const Code& code, 171 const Code& code,
187 uword new_target) { 172 const Code& new_target) {
188 ASSERT(code.ContainsInstructionAt(return_address)); 173 ASSERT(code.ContainsInstructionAt(return_address));
189 StaticCall call(return_address); 174 StaticCall call(return_address);
190 call.set_target(new_target); 175 call.set_target(new_target);
191 } 176 }
192 177
193 178
194 void CodePatcher::PatchInstanceCallAt(uword return_address, 179 void CodePatcher::InsertDeoptimizationCallAt(uword start, uword target) {
195 const Code& code,
196 uword new_target) {
197 ASSERT(code.ContainsInstructionAt(return_address));
198 InstanceCall call(return_address);
199 call.set_target(new_target);
200 }
201
202
203 void CodePatcher::InsertCallAt(uword start, uword target) {
204 // The inserted call should not overlap the lazy deopt jump code. 180 // The inserted call should not overlap the lazy deopt jump code.
205 ASSERT(start + CallPattern::pattern_length_in_bytes() <= target); 181 ASSERT(start + CallPattern::pattern_length_in_bytes() <= target);
206 *reinterpret_cast<uint8_t*>(start) = 0xE8; 182 *reinterpret_cast<uint8_t*>(start) = 0xE8;
207 CallPattern call(start); 183 CallPattern call(start);
208 call.SetTargetAddress(target); 184 call.SetTargetAddress(target);
209 CPU::FlushICache(start, CallPattern::pattern_length_in_bytes()); 185 CPU::FlushICache(start, CallPattern::pattern_length_in_bytes());
210 } 186 }
211 187
212 188
213 uword CodePatcher::GetInstanceCallAt( 189 RawCode* CodePatcher::GetInstanceCallAt(
214 uword return_address, const Code& code, ICData* ic_data) { 190 uword return_address, const Code& code, ICData* ic_data) {
215 ASSERT(code.ContainsInstructionAt(return_address)); 191 ASSERT(code.ContainsInstructionAt(return_address));
216 InstanceCall call(return_address); 192 InstanceCall call(return_address);
217 if (ic_data != NULL) { 193 if (ic_data != NULL) {
218 *ic_data ^= call.ic_data(); 194 *ic_data ^= call.ic_data();
219 } 195 }
220 return call.target(); 196 return Code::null();
221 } 197 }
222 198
223 199
224 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( 200 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
225 uword return_address, const Code& code, ICData* ic_data_result) { 201 uword return_address, const Code& code, ICData* ic_data_result) {
226 ASSERT(code.ContainsInstructionAt(return_address)); 202 ASSERT(code.ContainsInstructionAt(return_address));
227 UnoptimizedStaticCall static_call(return_address); 203 UnoptimizedStaticCall static_call(return_address);
228 ICData& ic_data = ICData::Handle(); 204 ICData& ic_data = ICData::Handle();
229 ic_data ^= static_call.ic_data(); 205 ic_data ^= static_call.ic_data();
230 if (ic_data_result != NULL) { 206 if (ic_data_result != NULL) {
231 *ic_data_result = ic_data.raw(); 207 *ic_data_result = ic_data.raw();
232 } 208 }
233 return ic_data.GetTargetAt(0); 209 return ic_data.GetTargetAt(0);
234 } 210 }
235 211
236 212
237 void CodePatcher::PatchNativeCallAt(uword return_address, 213 void CodePatcher::PatchNativeCallAt(uword return_address,
238 const Code& code, 214 const Code& code,
239 NativeFunction target, 215 NativeFunction target,
240 const Code& trampoline) { 216 const Code& trampoline) {
241 ASSERT(code.ContainsInstructionAt(return_address)); 217 UNREACHABLE();
242 NativeCall call(return_address);
243 call.set_target(trampoline.EntryPoint());
244 call.set_native_function(target);
245 } 218 }
246 219
247 220
248 uword CodePatcher::GetNativeCallAt(uword return_address, 221 RawCode* CodePatcher::GetNativeCallAt(uword return_address,
249 const Code& code, 222 const Code& code,
250 NativeFunction* target) { 223 NativeFunction* target) {
251 ASSERT(code.ContainsInstructionAt(return_address)); 224 UNREACHABLE();
252 NativeCall call(return_address); 225 return NULL;
253 *target = call.native_function();
254 return call.target();
255 } 226 }
256 227
257 228
258 229
259 intptr_t CodePatcher::InstanceCallSizeInBytes() { 230 intptr_t CodePatcher::InstanceCallSizeInBytes() {
260 return InstanceCall::kNumInstructions * InstanceCall::kInstructionSize; 231 return InstanceCall::kPatternSize;
261 } 232 }
262 233
263 234
264 // The expected code pattern of an edge counter in unoptimized code: 235 // The expected code pattern of an edge counter in unoptimized code:
265 // b8 imm32 mov EAX, immediate 236 // b8 imm32 mov EAX, immediate
266 class EdgeCounter : public ValueObject { 237 class EdgeCounter : public ValueObject {
267 public: 238 public:
268 EdgeCounter(uword pc, const Code& ignored) 239 EdgeCounter(uword pc, const Code& ignored)
269 : end_(pc - FlowGraphCompiler::EdgeCounterIncrementSizeInBytes()) { 240 : end_(pc - FlowGraphCompiler::EdgeCounterIncrementSizeInBytes()) {
270 ASSERT(IsValid(end_)); 241 ASSERT(IsValid(end_));
(...skipping 14 matching lines...) Expand all
285 256
286 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { 257 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) {
287 ASSERT(code.ContainsInstructionAt(pc)); 258 ASSERT(code.ContainsInstructionAt(pc));
288 EdgeCounter counter(pc, code); 259 EdgeCounter counter(pc, code);
289 return counter.edge_counter(); 260 return counter.edge_counter();
290 } 261 }
291 262
292 } // namespace dart 263 } // namespace dart
293 264
294 #endif // defined TARGET_ARCH_IA32 265 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698