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_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/instructions.h" | 12 #include "vm/instructions.h" |
13 #include "vm/object.h" | 13 #include "vm/object.h" |
14 #include "vm/raw_object.h" | 14 #include "vm/raw_object.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 // The pattern of a Dart instance call is: | 18 // The expected pattern of a dart instance call: |
19 // 1: mov ECX, immediate 1 | 19 // mov ECX, ic-data |
20 // 2: mov EDX, immediate 2 | 20 // call target_address |
21 // 3: call target_address | 21 // <- return address |
22 // <- return_address | 22 class InstanceCall : public ValueObject { |
23 class DartCallPattern : public ValueObject { | |
24 public: | 23 public: |
25 explicit DartCallPattern(uword return_address) | 24 explicit InstanceCall(uword return_address) |
26 : start_(return_address - (kNumInstructions * kInstructionSize)) { | 25 : start_(return_address - (kNumInstructions * kInstructionSize)) { |
27 ASSERT(IsValid(return_address)); | 26 ASSERT(IsValid(return_address)); |
28 ASSERT(kInstructionSize == Assembler::kCallExternalLabelSize); | 27 ASSERT(kInstructionSize == Assembler::kCallExternalLabelSize); |
29 } | 28 } |
30 | 29 |
31 static bool IsValid(uword return_address) { | 30 static bool IsValid(uword return_address) { |
32 uint8_t* code_bytes = | 31 uint8_t* code_bytes = |
33 reinterpret_cast<uint8_t*>( | 32 reinterpret_cast<uint8_t*>( |
34 return_address - (kNumInstructions * kInstructionSize)); | 33 return_address - (kNumInstructions * kInstructionSize)); |
35 return (code_bytes[0] == 0xB9) && | 34 return (code_bytes[0] == 0xB9) && |
36 (code_bytes[kInstructionSize] == 0xBA) && | 35 (code_bytes[1 * kInstructionSize] == 0xE8); |
37 (code_bytes[2 * kInstructionSize] == 0xE8); | |
38 } | 36 } |
39 | 37 |
40 uword target() const { | 38 uword target() const { |
41 const uword offset = *reinterpret_cast<uword*>(call_address() + 1); | 39 const uword offset = *reinterpret_cast<uword*>(call_address() + 1); |
42 return return_address() + offset; | 40 return return_address() + offset; |
43 } | 41 } |
44 | 42 |
45 void set_target(uword target) const { | 43 void set_target(uword target) const { |
46 uword* target_addr = reinterpret_cast<uword*>(call_address() + 1); | 44 uword* target_addr = reinterpret_cast<uword*>(call_address() + 1); |
47 uword offset = target - return_address(); | 45 uword offset = target - return_address(); |
48 *target_addr = offset; | 46 *target_addr = offset; |
49 CPU::FlushICache(call_address(), kInstructionSize); | 47 CPU::FlushICache(call_address(), kInstructionSize); |
50 } | 48 } |
51 | 49 |
52 RawObject* immediate_one() const { | 50 RawObject* ic_data() const { |
53 return *reinterpret_cast<RawObject**>(start_ + 1); | 51 return *reinterpret_cast<RawObject**>(start_ + 1); |
54 } | 52 } |
55 | 53 |
56 RawObject* immediate_two() const { | 54 static const int kNumInstructions = 2; |
57 return *reinterpret_cast<RawObject**>(start_ + kInstructionSize + 1); | |
58 } | |
59 | |
60 static const int kNumInstructions = 3; | |
61 static const int kInstructionSize = 5; // All instructions have same length. | 55 static const int kInstructionSize = 5; // All instructions have same length. |
62 | 56 |
63 private: | 57 private: |
64 uword return_address() const { | 58 uword return_address() const { |
65 return start_ + kNumInstructions * kInstructionSize; | 59 return start_ + kNumInstructions * kInstructionSize; |
66 } | 60 } |
67 | 61 |
68 uword call_address() const { | 62 uword call_address() const { |
69 return start_ + 2 * kInstructionSize; | 63 return start_ + 1 * kInstructionSize; |
70 } | 64 } |
71 | 65 |
72 uword start_; | 66 uword start_; |
73 DISALLOW_IMPLICIT_CONSTRUCTORS(DartCallPattern); | |
74 }; | |
75 | |
76 | |
77 // The expected pattern of a dart instance call: | |
78 // mov ECX, ic-data | |
79 // mov EDX, arguments_descriptor_array | |
80 // call target_address | |
81 // <- return address | |
82 class InstanceCall : public DartCallPattern { | |
83 public: | |
84 explicit InstanceCall(uword return_address) | |
85 : DartCallPattern(return_address) {} | |
86 | |
87 RawObject* ic_data() const { return immediate_one(); } | |
88 RawObject* arguments_descriptor() const { return immediate_two(); } | |
89 | |
90 private: | |
91 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); | 67 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); |
92 }; | 68 }; |
93 | 69 |
94 | 70 |
95 // The expected pattern of a dart static call: | 71 // The expected pattern of a dart static call: |
96 // mov EDX, arguments_descriptor_array (optional in polymorphic calls) | 72 // mov EDX, arguments_descriptor_array (optional in polymorphic calls) |
97 // call target_address | 73 // call target_address |
98 // <- return address | 74 // <- return address |
99 class StaticCall : public ValueObject { | 75 class StaticCall : public ValueObject { |
100 public: | 76 public: |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 ASSERT(start + CallPattern::InstructionLength() <= target); | 194 ASSERT(start + CallPattern::InstructionLength() <= target); |
219 *reinterpret_cast<uint8_t*>(start) = 0xE8; | 195 *reinterpret_cast<uint8_t*>(start) = 0xE8; |
220 CallPattern call(start); | 196 CallPattern call(start); |
221 call.SetTargetAddress(target); | 197 call.SetTargetAddress(target); |
222 CPU::FlushICache(start, CallPattern::InstructionLength()); | 198 CPU::FlushICache(start, CallPattern::InstructionLength()); |
223 } | 199 } |
224 | 200 |
225 | 201 |
226 uword CodePatcher::GetInstanceCallAt(uword return_address, | 202 uword CodePatcher::GetInstanceCallAt(uword return_address, |
227 const Code& code, | 203 const Code& code, |
228 ICData* ic_data, | 204 ICData* ic_data) { |
229 Array* arguments_descriptor) { | |
230 ASSERT(code.ContainsInstructionAt(return_address)); | 205 ASSERT(code.ContainsInstructionAt(return_address)); |
231 InstanceCall call(return_address); | 206 InstanceCall call(return_address); |
232 if (ic_data != NULL) { | 207 if (ic_data != NULL) { |
233 *ic_data ^= call.ic_data(); | 208 *ic_data ^= call.ic_data(); |
234 } | 209 } |
235 if (arguments_descriptor != NULL) { | |
236 *arguments_descriptor ^= call.arguments_descriptor(); | |
237 } | |
238 return call.target(); | 210 return call.target(); |
239 } | 211 } |
240 | 212 |
241 | 213 |
242 intptr_t CodePatcher::InstanceCallSizeInBytes() { | 214 intptr_t CodePatcher::InstanceCallSizeInBytes() { |
243 return DartCallPattern::kNumInstructions * DartCallPattern::kInstructionSize; | 215 return InstanceCall::kNumInstructions * InstanceCall::kInstructionSize; |
244 } | 216 } |
245 | 217 |
246 } // namespace dart | 218 } // namespace dart |
247 | 219 |
248 #endif // defined TARGET_ARCH_IA32 | 220 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |