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

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

Issue 22825023: Uses an object pool on x64 (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
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/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 static int IndexFromPPLoad(uword start) {
19 uint8_t which = *reinterpret_cast<uint8_t*>(start);
20 if (which == 0x9F) {
21 int32_t offset = *reinterpret_cast<int32_t*>(start + 1);
22 offset += kHeapObjectTag;
23 return (offset - Array::data_offset())/kWordSize;
24 } else {
25 ASSERT(which == 0x5F);
26 int32_t offset = *reinterpret_cast<int8_t*>(start + 1);
27 offset += kHeapObjectTag;
28 return (offset - Array::data_offset())/kWordSize;
29 }
30 }
31
18 // The expected pattern of a Dart unoptimized call (static and instance): 32 // The expected pattern of a Dart unoptimized call (static and instance):
19 // 00: 48 bb imm64 mov RBX, ic-data 33 // 00: 49 8b 9f imm32 mov RBX, [PP + off]
20 // 10: 49 bb imm64 mov R11, target_address 34 // OR:
21 // 20: 41 ff d3 call R11 35 // 00: 49 8b 5f imm8 mov RBX, [PP + off]
22 // 23 <- return address 36 // 04: 0f 1f 00 nop
37 // Then:
38 // 07: 4d 8b 9f imm32 mov R11, [PP + off]
39 // OR:
40 // 07: 4d 8b 5f imm8 mov R11, [PP + off]
41 // 11: 0f 1f 00 nop
42 // Then:
43 // 14: 41 ff d3 call R11
44 // 17 <- return address
23 class UnoptimizedCall : public ValueObject { 45 class UnoptimizedCall : public ValueObject {
24 public: 46 public:
25 explicit UnoptimizedCall(uword return_address) 47 UnoptimizedCall(uword return_address, const Code& code)
26 : start_(return_address - kCallPatternSize) { 48 : start_(return_address - kCallPatternSize),
49 object_pool_(Array::Handle(code.ObjectPool())) {
27 ASSERT(IsValid(return_address)); 50 ASSERT(IsValid(return_address));
28 ASSERT((kCallPatternSize - 10) == Assembler::kCallExternalLabelSize); 51 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize);
29 } 52 }
30 53
31 static const int kCallPatternSize = 23; 54 static const int kCallPatternSize = 17;
32 55
33 static bool IsValid(uword return_address) { 56 static bool IsValid(uword return_address) {
34 uint8_t* code_bytes = 57 uint8_t* code_bytes =
35 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 58 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
36 return (code_bytes[00] == 0x48) && (code_bytes[01] == 0xBB) && 59 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) &&
37 (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) && 60 ((code_bytes[2] == 0x5F) || (code_bytes[2] == 0x9F)) &&
38 (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) && 61 (code_bytes[7] == 0x4D) && (code_bytes[8] == 0x8B) &&
39 (code_bytes[22] == 0xD3); 62 ((code_bytes[9] == 0x5F) || (code_bytes[9] == 0x9F)) &&
63 (code_bytes[14] == 0x41) && (code_bytes[15] == 0xFF) &&
64 (code_bytes[16] == 0xD3);
40 } 65 }
41 66
42 RawObject* ic_data() const { 67 RawObject* ic_data() const {
43 return *reinterpret_cast<RawObject**>(start_ + 0 + 2); 68 int index = IndexFromPPLoad(start_ + 2);
69 return object_pool_.At(index);
44 } 70 }
45 71
46 uword target() const { 72 uword target() const {
47 return *reinterpret_cast<uword*>(start_ + 10 + 2); 73 int index = IndexFromPPLoad(start_ + 9);
74 return reinterpret_cast<uword>(object_pool_.At(index));
48 } 75 }
49 76
50 void set_target(uword target) const { 77 void set_target(uword target) const {
51 uword* target_addr = reinterpret_cast<uword*>(start_ + 10 + 2); 78 int index = IndexFromPPLoad(start_ + 9);
52 *target_addr = target; 79 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
53 CPU::FlushICache(start_ + 10, 2 + 8); 80 object_pool_.SetAt(index, smi);
81 // No need to flush the instruction cache, since the code is not modified.
54 } 82 }
55 83
56 private: 84 private:
57 uword start_; 85 uword start_;
86 const Array& object_pool_;
58 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); 87 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall);
59 }; 88 };
60 89
61 90
62 class InstanceCall : public UnoptimizedCall { 91 class InstanceCall : public UnoptimizedCall {
63 public: 92 public:
64 explicit InstanceCall(uword return_address) 93 InstanceCall(uword return_address, const Code& code)
65 : UnoptimizedCall(return_address) { 94 : UnoptimizedCall(return_address, code) {
66 #if defined(DEBUG) 95 #if defined(DEBUG)
67 ICData& test_ic_data = ICData::Handle(); 96 ICData& test_ic_data = ICData::Handle();
68 test_ic_data ^= ic_data(); 97 test_ic_data ^= ic_data();
69 ASSERT(test_ic_data.num_args_tested() > 0); 98 ASSERT(test_ic_data.num_args_tested() > 0);
70 #endif // DEBUG 99 #endif // DEBUG
71 } 100 }
72 101
73 private: 102 private:
74 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); 103 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall);
75 }; 104 };
76 105
77 106
78 class UnoptimizedStaticCall : public UnoptimizedCall { 107 class UnoptimizedStaticCall : public UnoptimizedCall {
79 public: 108 public:
80 explicit UnoptimizedStaticCall(uword return_address) 109 UnoptimizedStaticCall(uword return_address, const Code& code)
81 : UnoptimizedCall(return_address) { 110 : UnoptimizedCall(return_address, code) {
82 #if defined(DEBUG) 111 #if defined(DEBUG)
83 ICData& test_ic_data = ICData::Handle(); 112 ICData& test_ic_data = ICData::Handle();
84 test_ic_data ^= ic_data(); 113 test_ic_data ^= ic_data();
85 ASSERT(test_ic_data.num_args_tested() >= 0); 114 ASSERT(test_ic_data.num_args_tested() >= 0);
86 #endif // DEBUG 115 #endif // DEBUG
87 } 116 }
88 117
89 private: 118 private:
90 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); 119 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall);
91 }; 120 };
92 121
93 122
94 // The expected pattern of a dart static call: 123 // The expected pattern of a dart static call:
95 // mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls) 124 // 00 mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls)
96 // mov R11, target_address (10 bytes) 125 // 11: 4d 8b 9f imm32 mov R11, [PP + off]
97 // call R11 (3 bytes) 126 // OR:
127 // 11: 4d 8b 5f imm8 mov R11, [PP + off]
128 // 15: 0f 1f 00 nop
129 // Then:
130 // 16: call R11 (3 bytes)
98 // <- return address 131 // <- return address
99 class StaticCall : public ValueObject { 132 class StaticCall : public ValueObject {
100 public: 133 public:
101 explicit StaticCall(uword return_address) 134 explicit StaticCall(uword return_address, const Code& code)
102 : start_(return_address - kCallPatternSize) { 135 : start_(return_address - kCallPatternSize),
136 object_pool_(Array::Handle(code.ObjectPool())) {
103 ASSERT(IsValid(return_address)); 137 ASSERT(IsValid(return_address));
104 ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize); 138 ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize);
105 } 139 }
106 140
107 static const int kCallPatternSize = 13; 141 static const int kCallPatternSize = 10;
108 142
109 static bool IsValid(uword return_address) { 143 static bool IsValid(uword return_address) {
110 uint8_t* code_bytes = 144 uint8_t* code_bytes =
111 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 145 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
112 return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBB) && 146 return (code_bytes[0] == 0x4D) && (code_bytes[1] == 0x8B) &&
113 (code_bytes[10] == 0x41) && (code_bytes[11] == 0xFF) && 147 ((code_bytes[2] == 0x5F) || (code_bytes[2] == 0x9F)) &&
114 (code_bytes[12] == 0xD3); 148 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
149 (code_bytes[9] == 0xD3);
115 } 150 }
116 151
117 uword target() const { 152 uword target() const {
118 return *reinterpret_cast<uword*>(start_ + 2); 153 int index = IndexFromPPLoad(start_ + 2);
154 return reinterpret_cast<uword>(object_pool_.At(index));
119 } 155 }
120 156
121 void set_target(uword target) const { 157 void set_target(uword target) const {
122 uword* target_addr = reinterpret_cast<uword*>(start_ + 2); 158 int index = IndexFromPPLoad(start_ + 2);
123 *target_addr = target; 159 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
124 CPU::FlushICache(start_, 2 + 8); 160 object_pool_.SetAt(index, smi);
161 // No need to flush the instruction cache, since the code is not modified.
125 } 162 }
126 163
127 private: 164 private:
128 uword start_; 165 uword start_;
129 166 const Array& object_pool_;
130 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); 167 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
131 }; 168 };
132 169
133 170
134 // The expected code pattern of a dart closure call: 171 // The expected code pattern of a dart closure call:
135 // 00: 49 ba imm64 mov R10, immediate 2 ; 10 bytes 172 // 00: 49 ba imm64 mov R10, immediate 2 ; 10 bytes
136 // 10: 49 bb imm64 mov R11, target_address ; 10 bytes 173 // 10: 4d 8b 9f imm32 mov R11, [PP + off]
137 // 20: 41 ff d3 call R11 ; 3 bytes 174 // OR:
138 // 23: <- return_address 175 // 10: 4d 8b 5f imm8 mov R11, [PP + off]
176 // 14: 0f 1f 00 nop
177 // Then:
178 // 17: 41 ff d3 call R11 ; 3 bytes
179 // 20: <- return_address
139 class ClosureCall : public ValueObject { 180 class ClosureCall : public ValueObject {
140 public: 181 public:
141 explicit ClosureCall(uword return_address) 182 explicit ClosureCall(uword return_address)
142 : start_(return_address - kCallPatternSize) { 183 : start_(return_address - kCallPatternSize) {
143 ASSERT(IsValid(return_address)); 184 ASSERT(IsValid(return_address));
144 } 185 }
145 186
146 static bool IsValid(uword return_address) { 187 static bool IsValid(uword return_address) {
147 uint8_t* code_bytes = 188 uint8_t* code_bytes =
148 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 189 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
149 return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) && 190 return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) &&
150 (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) && 191 (code_bytes[10] == 0x4D) && (code_bytes[11] == 0x8B) &&
151 (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) && 192 ((code_bytes[12] == 0x5F) || (code_bytes[12] == 0x9F)) &&
152 (code_bytes[22] == 0xD3); 193 (code_bytes[17] == 0x41) && (code_bytes[18] == 0xFF) &&
194 (code_bytes[19] == 0xD3);
153 } 195 }
154 196
155 RawArray* arguments_descriptor() const { 197 RawArray* arguments_descriptor() const {
156 return *reinterpret_cast<RawArray**>(start_ + 2); 198 return *reinterpret_cast<RawArray**>(start_ + 2);
157 } 199 }
158 200
159 private: 201 private:
160 static const int kCallPatternSize = 10 + 10 + 3; 202 static const int kCallPatternSize = 10 + 7 + 3;
161 uword start_; 203 uword start_;
162 DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall); 204 DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall);
163 }; 205 };
164 206
165 207
166 RawArray* CodePatcher::GetClosureArgDescAt(uword return_address, 208 RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
167 const Code& code) { 209 const Code& code) {
168 ASSERT(code.ContainsInstructionAt(return_address)); 210 ASSERT(code.ContainsInstructionAt(return_address));
169 ClosureCall call(return_address); 211 ClosureCall call(return_address);
170 return call.arguments_descriptor(); 212 return call.arguments_descriptor();
171 } 213 }
172 214
173 215
174 uword CodePatcher::GetStaticCallTargetAt(uword return_address, 216 uword CodePatcher::GetStaticCallTargetAt(uword return_address,
175 const Code& code) { 217 const Code& code) {
176 ASSERT(code.ContainsInstructionAt(return_address)); 218 ASSERT(code.ContainsInstructionAt(return_address));
177 StaticCall call(return_address); 219 StaticCall call(return_address, code);
178 return call.target(); 220 return call.target();
179 } 221 }
180 222
181 223
182 void CodePatcher::PatchStaticCallAt(uword return_address, 224 void CodePatcher::PatchStaticCallAt(uword return_address,
183 const Code& code, 225 const Code& code,
184 uword new_target) { 226 uword new_target) {
185 ASSERT(code.ContainsInstructionAt(return_address)); 227 ASSERT(code.ContainsInstructionAt(return_address));
186 StaticCall call(return_address); 228 StaticCall call(return_address, code);
187 call.set_target(new_target); 229 call.set_target(new_target);
188 } 230 }
189 231
190 232
191 void CodePatcher::PatchInstanceCallAt(uword return_address, 233 void CodePatcher::PatchInstanceCallAt(uword return_address,
192 const Code& code, 234 const Code& code,
193 uword new_target) { 235 uword new_target) {
194 ASSERT(code.ContainsInstructionAt(return_address)); 236 ASSERT(code.ContainsInstructionAt(return_address));
195 InstanceCall call(return_address); 237 InstanceCall call(return_address, code);
196 call.set_target(new_target); 238 call.set_target(new_target);
197 } 239 }
198 240
199 241
200 uword CodePatcher::GetInstanceCallAt(uword return_address, 242 uword CodePatcher::GetInstanceCallAt(uword return_address,
201 const Code& code, 243 const Code& code,
202 ICData* ic_data) { 244 ICData* ic_data) {
203 ASSERT(code.ContainsInstructionAt(return_address)); 245 ASSERT(code.ContainsInstructionAt(return_address));
204 InstanceCall call(return_address); 246 InstanceCall call(return_address, code);
205 if (ic_data != NULL) { 247 if (ic_data != NULL) {
206 *ic_data ^= call.ic_data(); 248 *ic_data ^= call.ic_data();
207 } 249 }
208 return call.target(); 250 return call.target();
209 } 251 }
210 252
211 253
212 intptr_t CodePatcher::InstanceCallSizeInBytes() { 254 intptr_t CodePatcher::InstanceCallSizeInBytes() {
213 return InstanceCall::kCallPatternSize; 255 return InstanceCall::kCallPatternSize;
214 } 256 }
215 257
216 258
217 void CodePatcher::InsertCallAt(uword start, uword target) { 259 void CodePatcher::InsertCallAt(uword start, uword target) {
218 // The inserted call should not overlap the lazy deopt jump code. 260 // The inserted call should not overlap the lazy deopt jump code.
219 ASSERT(start + ShortCallPattern::InstructionLength() <= target); 261 ASSERT(start + ShortCallPattern::InstructionLength() <= target);
220 *reinterpret_cast<uint8_t*>(start) = 0xE8; 262 *reinterpret_cast<uint8_t*>(start) = 0xE8;
221 ShortCallPattern call(start); 263 ShortCallPattern call(start);
222 call.SetTargetAddress(target); 264 call.SetTargetAddress(target);
223 CPU::FlushICache(start, ShortCallPattern::InstructionLength()); 265 CPU::FlushICache(start, ShortCallPattern::InstructionLength());
224 } 266 }
225 267
226 268
227 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( 269 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
228 uword return_address, const Code& code, ICData* ic_data_result) { 270 uword return_address, const Code& code, ICData* ic_data_result) {
229 ASSERT(code.ContainsInstructionAt(return_address)); 271 ASSERT(code.ContainsInstructionAt(return_address));
230 UnoptimizedStaticCall static_call(return_address); 272 UnoptimizedStaticCall static_call(return_address, code);
231 ICData& ic_data = ICData::Handle(); 273 ICData& ic_data = ICData::Handle();
232 ic_data ^= static_call.ic_data(); 274 ic_data ^= static_call.ic_data();
233 if (ic_data_result != NULL) { 275 if (ic_data_result != NULL) {
234 *ic_data_result = ic_data.raw(); 276 *ic_data_result = ic_data.raw();
235 } 277 }
236 return ic_data.GetTargetAt(0); 278 return ic_data.GetTargetAt(0);
237 } 279 }
238 280
239 } // namespace dart 281 } // namespace dart
240 282
241 #endif // defined TARGET_ARCH_X64 283 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698