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/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 | |
20 static bool MatchesPattern(uword addr, int16_t* pattern, intptr_t size) { | |
21 uint8_t* bytes = reinterpret_cast<uint8_t*>(addr); | |
22 for (intptr_t i = 0; i < size; i++) { | |
23 int16_t val = pattern[i]; | |
24 if ((val >= 0) && (val != bytes[i])) { | |
25 return false; | |
26 } | |
27 } | |
28 return true; | |
29 } | |
30 | |
31 | |
19 // The expected pattern of a Dart unoptimized call (static and instance): | 32 // The expected pattern of a Dart unoptimized call (static and instance): |
20 // 0: 49 8b 9f imm32 mov RBX, [PP + off] | 33 // 0: 49 8b 9f imm32 mov RBX, [PP + off] |
21 // 7: 41 ff 97 imm32 call [PP + off] | 34 // 7: 41 ff 97 imm32 call [PP + off] |
srdjan
2015/06/18 21:29:47
You may need to update this comment.
Florian Schneider
2015/06/29 14:50:24
Done.
| |
22 // 14 <- return address | 35 // 14 <- return address |
23 class UnoptimizedCall : public ValueObject { | 36 class UnoptimizedCall : public ValueObject { |
24 public: | 37 public: |
25 UnoptimizedCall(uword return_address, const Code& code) | 38 UnoptimizedCall(uword return_address, const Code& code) |
26 : start_(return_address - kCallPatternSize), | 39 : start_(return_address - kCallPatternSize), |
27 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { | 40 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
28 ASSERT(IsValid(return_address)); | |
29 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); | 41 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); |
42 ASSERT(IsValid()); | |
30 } | 43 } |
31 | 44 |
32 static const int kCallPatternSize = 14; | 45 static const int kCallPatternSize = 26; |
33 | 46 |
34 static bool IsValid(uword return_address) { | 47 bool IsValid() const { |
35 uint8_t* code_bytes = | 48 static int16_t pattern[kCallPatternSize] = { |
36 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); | 49 0x49, 0x8b, 0x9f, -1, -1, -1, -1, // movq RBX, [PP + offs] |
37 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) && | 50 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs] |
38 (code_bytes[2] == 0x9F) && | 51 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + insns_offs] |
39 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) && | 52 0x49, 0x83, 0xc3, 0x1f, // addq TMP, entry_offs |
40 (code_bytes[9] == 0x97); | 53 0x41, 0xff, 0xd3 // callq TMP |
54 }; | |
55 return MatchesPattern(start_, pattern, kCallPatternSize); | |
41 } | 56 } |
42 | 57 |
43 RawObject* ic_data() const { | 58 RawObject* ic_data() const { |
44 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); | 59 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); |
45 return object_pool_.ObjectAt(index); | 60 return object_pool_.ObjectAt(index); |
46 } | 61 } |
47 | 62 |
48 uword target() const { | 63 RawCode* target() const { |
49 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); | 64 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); |
50 return object_pool_.RawValueAt(index); | 65 Code& code = Code::Handle(); |
66 code ^= object_pool_.ObjectAt(index); | |
67 return code.raw(); | |
51 } | 68 } |
52 | 69 |
53 void set_target(uword target) const { | 70 void set_target(const Code& target) const { |
54 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); | 71 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); |
55 object_pool_.SetRawValueAt(index, target); | 72 object_pool_.SetObjectAt(index, target); |
56 // No need to flush the instruction cache, since the code is not modified. | 73 // No need to flush the instruction cache, since the code is not modified. |
57 } | 74 } |
58 | 75 |
59 private: | 76 private: |
60 uword start_; | 77 uword start_; |
61 const ObjectPool& object_pool_; | 78 const ObjectPool& object_pool_; |
62 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); | 79 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); |
63 }; | 80 }; |
64 | 81 |
65 | 82 |
(...skipping 24 matching lines...) Expand all Loading... | |
90 #endif // DEBUG | 107 #endif // DEBUG |
91 } | 108 } |
92 | 109 |
93 private: | 110 private: |
94 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); | 111 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); |
95 }; | 112 }; |
96 | 113 |
97 | 114 |
98 // The expected pattern of a call where the target is loaded from | 115 // The expected pattern of a call where the target is loaded from |
99 // the object pool: | 116 // the object pool: |
100 // 0: 41 ff 97 imm32 call [PP + off] | 117 // 0: 4d 8b a7 imm32 movq CR, [PP + offs] |
101 // 7: <- return address | 118 // 7: 4d 8b 5c 24 07 movq TMP, [CR + insns_offs] |
119 // 12: 49 83 c3 1f addq TMP, entry_offs | |
120 // 16: 41 ff d3 callq TMP | |
121 // 19: <- return address | |
102 class PoolPointerCall : public ValueObject { | 122 class PoolPointerCall : public ValueObject { |
103 public: | 123 public: |
104 explicit PoolPointerCall(uword return_address, const Code& code) | 124 explicit PoolPointerCall(uword return_address, const Code& code) |
105 : start_(return_address - kCallPatternSize), | 125 : start_(return_address - kCallPatternSize), |
106 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { | 126 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
107 ASSERT(IsValid(return_address)); | 127 ASSERT(IsValid()); |
108 } | 128 } |
109 | 129 |
110 static const int kCallPatternSize = 7; | 130 static const int kCallPatternSize = 19; |
111 | 131 |
112 static bool IsValid(uword return_address) { | 132 bool IsValid() const { |
113 uint8_t* code_bytes = | 133 static int16_t pattern[kCallPatternSize] = { |
114 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); | 134 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs] |
115 return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) && | 135 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + insns_offs] |
116 (code_bytes[2] == 0x97); | 136 0x49, 0x83, 0xc3, 0x1f, // addq TMP, entry_offs |
137 0x41, 0xff, 0xd3 // callq TMP | |
138 }; | |
139 return MatchesPattern(start_, pattern, kCallPatternSize); | |
117 } | 140 } |
118 | 141 |
119 intptr_t pp_index() const { | 142 intptr_t pp_index() const { |
120 return InstructionPattern::IndexFromPPLoad(start_ + 3); | 143 return InstructionPattern::IndexFromPPLoad(start_ + 3); |
121 } | 144 } |
122 | 145 |
123 uword Target() const { | 146 RawCode* Target() const { |
124 return object_pool_.RawValueAt(pp_index()); | 147 Code& code = Code::Handle(); |
148 code ^= object_pool_.ObjectAt(pp_index()); | |
149 return code.raw(); | |
125 } | 150 } |
126 | 151 |
127 void SetTarget(uword target) const { | 152 void SetTarget(const Code& target) const { |
128 object_pool_.SetRawValueAt(pp_index(), target); | 153 object_pool_.SetObjectAt(pp_index(), target); |
129 // No need to flush the instruction cache, since the code is not modified. | 154 // No need to flush the instruction cache, since the code is not modified. |
130 } | 155 } |
131 | 156 |
132 protected: | 157 protected: |
133 uword start_; | 158 uword start_; |
134 const ObjectPool& object_pool_; | 159 const ObjectPool& object_pool_; |
135 | 160 |
136 private: | 161 private: |
137 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); | 162 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); |
138 }; | 163 }; |
139 | 164 |
140 | 165 |
141 uword CodePatcher::GetStaticCallTargetAt(uword return_address, | 166 RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address, |
142 const Code& code) { | 167 const Code& code) { |
143 ASSERT(code.ContainsInstructionAt(return_address)); | 168 ASSERT(code.ContainsInstructionAt(return_address)); |
144 PoolPointerCall call(return_address, code); | 169 PoolPointerCall call(return_address, code); |
145 return call.Target(); | 170 return call.Target(); |
146 } | 171 } |
147 | 172 |
148 | 173 |
149 void CodePatcher::PatchStaticCallAt(uword return_address, | 174 void CodePatcher::PatchStaticCallAt(uword return_address, |
150 const Code& code, | 175 const Code& code, |
151 uword new_target) { | 176 const Code& new_target) { |
152 PatchPoolPointerCallAt(return_address, code, new_target); | 177 PatchPoolPointerCallAt(return_address, code, new_target); |
153 } | 178 } |
154 | 179 |
155 | 180 |
156 void CodePatcher::PatchPoolPointerCallAt(uword return_address, | 181 void CodePatcher::PatchPoolPointerCallAt(uword return_address, |
157 const Code& code, | 182 const Code& code, |
158 uword new_target) { | 183 const Code& new_target) { |
159 ASSERT(code.ContainsInstructionAt(return_address)); | 184 ASSERT(code.ContainsInstructionAt(return_address)); |
160 PoolPointerCall call(return_address, code); | 185 PoolPointerCall call(return_address, code); |
161 call.SetTarget(new_target); | 186 call.SetTarget(new_target); |
162 } | 187 } |
163 | 188 |
164 | 189 |
165 void CodePatcher::PatchInstanceCallAt(uword return_address, | 190 void CodePatcher::PatchInstanceCallAt(uword return_address, |
166 const Code& code, | 191 const Code& code, |
167 uword new_target) { | 192 const Code& new_target) { |
168 ASSERT(code.ContainsInstructionAt(return_address)); | 193 ASSERT(code.ContainsInstructionAt(return_address)); |
169 InstanceCall call(return_address, code); | 194 InstanceCall call(return_address, code); |
170 call.set_target(new_target); | 195 call.set_target(new_target); |
171 } | 196 } |
172 | 197 |
173 | 198 |
174 uword CodePatcher::GetInstanceCallAt(uword return_address, | 199 RawCode* CodePatcher::GetInstanceCallAt(uword return_address, |
175 const Code& code, | 200 const Code& code, |
176 ICData* ic_data) { | 201 ICData* ic_data) { |
177 ASSERT(code.ContainsInstructionAt(return_address)); | 202 ASSERT(code.ContainsInstructionAt(return_address)); |
178 InstanceCall call(return_address, code); | 203 InstanceCall call(return_address, code); |
179 if (ic_data != NULL) { | 204 if (ic_data != NULL) { |
180 *ic_data ^= call.ic_data(); | 205 *ic_data ^= call.ic_data(); |
181 } | 206 } |
182 return call.target(); | 207 return call.target(); |
183 } | 208 } |
184 | 209 |
185 | 210 |
186 intptr_t CodePatcher::InstanceCallSizeInBytes() { | 211 intptr_t CodePatcher::InstanceCallSizeInBytes() { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 | 263 |
239 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { | 264 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { |
240 ASSERT(code.ContainsInstructionAt(pc)); | 265 ASSERT(code.ContainsInstructionAt(pc)); |
241 EdgeCounter counter(pc, code); | 266 EdgeCounter counter(pc, code); |
242 return counter.edge_counter(); | 267 return counter.edge_counter(); |
243 } | 268 } |
244 | 269 |
245 } // namespace dart | 270 } // namespace dart |
246 | 271 |
247 #endif // defined TARGET_ARCH_X64 | 272 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |