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

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

Issue 11040058: Compress deoptimization information by sharing common suffixes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 2 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/deopt_instructions.h" 5 #include "vm/deopt_instructions.h"
6 6
7 #include "vm/assembler_macros.h" 7 #include "vm/assembler_macros.h"
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 #include "vm/locations.h" 9 #include "vm/locations.h"
10 #include "vm/parser.h" 10 #include "vm/parser.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 // 'from_index' represents the slot index of the frame (0 being first argument) 54 // 'from_index' represents the slot index of the frame (0 being first argument)
55 // and accounts for saved return address, frame pointer and pc marker. 55 // and accounts for saved return address, frame pointer and pc marker.
56 class DeoptStackSlotInstr : public DeoptInstr { 56 class DeoptStackSlotInstr : public DeoptInstr {
57 public: 57 public:
58 explicit DeoptStackSlotInstr(intptr_t from_index) 58 explicit DeoptStackSlotInstr(intptr_t from_index)
59 : stack_slot_index_(from_index) { 59 : stack_slot_index_(from_index) {
60 ASSERT(stack_slot_index_ >= 0); 60 ASSERT(stack_slot_index_ >= 0);
61 } 61 }
62 62
63 virtual intptr_t from_index() const { return stack_slot_index_; } 63 virtual intptr_t from_index() const { return stack_slot_index_; }
64 virtual DeoptInstr::Kind kind() const { return kCopyStackSlot; } 64 virtual DeoptInstr::Kind kind() const { return kStackSlot; }
65 65
66 virtual const char* ToCString() const { 66 virtual const char* ToCString() const {
67 const char* format = "s%"Pd""; 67 const char* format = "s%"Pd"";
68 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); 68 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_);
69 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 69 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
70 OS::SNPrint(chars, len + 1, format, stack_slot_index_); 70 OS::SNPrint(chars, len + 1, format, stack_slot_index_);
71 return chars; 71 return chars;
72 } 72 }
73 73
74 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 74 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
(...skipping 12 matching lines...) Expand all
87 87
88 88
89 class DeoptDoubleStackSlotInstr : public DeoptInstr { 89 class DeoptDoubleStackSlotInstr : public DeoptInstr {
90 public: 90 public:
91 explicit DeoptDoubleStackSlotInstr(intptr_t from_index) 91 explicit DeoptDoubleStackSlotInstr(intptr_t from_index)
92 : stack_slot_index_(from_index) { 92 : stack_slot_index_(from_index) {
93 ASSERT(stack_slot_index_ >= 0); 93 ASSERT(stack_slot_index_ >= 0);
94 } 94 }
95 95
96 virtual intptr_t from_index() const { return stack_slot_index_; } 96 virtual intptr_t from_index() const { return stack_slot_index_; }
97 virtual DeoptInstr::Kind kind() const { return kCopyDoubleStackSlot; } 97 virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; }
98 98
99 virtual const char* ToCString() const { 99 virtual const char* ToCString() const {
100 const char* format = "ds%"Pd""; 100 const char* format = "ds%"Pd"";
101 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); 101 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_);
102 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 102 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
103 OS::SNPrint(chars, len + 1, format, stack_slot_index_); 103 OS::SNPrint(chars, len + 1, format, stack_slot_index_);
104 return chars; 104 return chars;
105 } 105 }
106 106
107 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 107 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
(...skipping 15 matching lines...) Expand all
123 123
124 124
125 class DeoptInt64StackSlotInstr : public DeoptInstr { 125 class DeoptInt64StackSlotInstr : public DeoptInstr {
126 public: 126 public:
127 explicit DeoptInt64StackSlotInstr(intptr_t from_index) 127 explicit DeoptInt64StackSlotInstr(intptr_t from_index)
128 : stack_slot_index_(from_index) { 128 : stack_slot_index_(from_index) {
129 ASSERT(stack_slot_index_ >= 0); 129 ASSERT(stack_slot_index_ >= 0);
130 } 130 }
131 131
132 virtual intptr_t from_index() const { return stack_slot_index_; } 132 virtual intptr_t from_index() const { return stack_slot_index_; }
133 virtual DeoptInstr::Kind kind() const { return kCopyInt64StackSlot; } 133 virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; }
134 134
135 virtual const char* ToCString() const { 135 virtual const char* ToCString() const {
136 const char* format = "ms%"Pd""; 136 const char* format = "ms%"Pd"";
137 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); 137 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_);
138 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 138 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
139 OS::SNPrint(chars, len + 1, format, stack_slot_index_); 139 OS::SNPrint(chars, len + 1, format, stack_slot_index_);
140 return chars; 140 return chars;
141 } 141 }
142 142
143 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 143 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
(...skipping 15 matching lines...) Expand all
159 private: 159 private:
160 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. 160 const intptr_t stack_slot_index_; // First argument is 0, always >= 0.
161 161
162 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr); 162 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr);
163 }; 163 };
164 164
165 165
166 // Deoptimization instruction creating return address using function and 166 // Deoptimization instruction creating return address using function and
167 // deopt-id stored at 'object_table_index'. Uses the deopt-after 167 // deopt-id stored at 'object_table_index'. Uses the deopt-after
168 // continuation point. 168 // continuation point.
169 class DeoptRetAddrAfterInstr : public DeoptInstr { 169 class DeoptRetAfterAddressInstr : public DeoptInstr {
170 public: 170 public:
171 DeoptRetAddrAfterInstr(intptr_t object_table_index, intptr_t deopt_id) 171 DeoptRetAfterAddressInstr(intptr_t object_table_index, intptr_t deopt_id)
172 : object_table_index_(object_table_index), deopt_id_(deopt_id) { 172 : object_table_index_(object_table_index), deopt_id_(deopt_id) {
173 ASSERT(object_table_index >= 0); 173 ASSERT(object_table_index >= 0);
174 ASSERT(deopt_id >= 0); 174 ASSERT(deopt_id >= 0);
175 } 175 }
176 176
177 explicit DeoptRetAddrAfterInstr(intptr_t from_index) 177 explicit DeoptRetAfterAddressInstr(intptr_t from_index)
178 : object_table_index_(ObjectTableIndex::decode(from_index)), 178 : object_table_index_(ObjectTableIndex::decode(from_index)),
179 deopt_id_(DeoptId::decode(from_index)) { 179 deopt_id_(DeoptId::decode(from_index)) {
180 } 180 }
181 181
182 virtual intptr_t from_index() const { 182 virtual intptr_t from_index() const {
183 return ObjectTableIndex::encode(object_table_index_) | 183 return ObjectTableIndex::encode(object_table_index_) |
184 DeoptId::encode(deopt_id_); 184 DeoptId::encode(deopt_id_);
185 } 185 }
186 virtual DeoptInstr::Kind kind() const { return kSetRetAfterAddress; } 186 virtual DeoptInstr::Kind kind() const { return kRetAfterAddress; }
187 187
188 virtual const char* ToCString() const { 188 virtual const char* ToCString() const {
189 const char* format = "ret aft oti:%"Pd"(%"Pd")"; 189 const char* format = "ret aft oti:%"Pd"(%"Pd")";
190 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_); 190 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_);
191 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 191 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
192 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_); 192 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_);
193 return chars; 193 return chars;
194 } 194 }
195 195
196 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 196 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
197 Function& function = Function::Handle(deopt_context->isolate()); 197 Function& function = Function::Handle(deopt_context->isolate());
198 function ^= deopt_context->ObjectAt(object_table_index_); 198 function ^= deopt_context->ObjectAt(object_table_index_);
199 const Code& code = 199 const Code& code =
200 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); 200 Code::Handle(deopt_context->isolate(), function.unoptimized_code());
201 uword continue_at_pc = code.GetDeoptAfterPcAtDeoptId(deopt_id_); 201 uword continue_at_pc = code.GetDeoptAfterPcAtDeoptId(deopt_id_);
202 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); 202 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
203 *to_addr = continue_at_pc; 203 *to_addr = continue_at_pc;
204 } 204 }
205 205
206 private: 206 private:
207 static const intptr_t kFieldWidth = kBitsPerWord / 2; 207 static const intptr_t kFieldWidth = kBitsPerWord / 2;
208 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { }; 208 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { };
209 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; 209 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
210 210
211 const intptr_t object_table_index_; 211 const intptr_t object_table_index_;
212 const intptr_t deopt_id_; 212 const intptr_t deopt_id_;
213 213
214 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrAfterInstr); 214 DISALLOW_COPY_AND_ASSIGN(DeoptRetAfterAddressInstr);
215 }; 215 };
216 216
217 217
218 // Deoptimization instruction creating return address using function and 218 // Deoptimization instruction creating return address using function and
219 // deopt-id stored at 'object_table_index'. Uses the deopt-before 219 // deopt-id stored at 'object_table_index'. Uses the deopt-before
220 // continuation point. 220 // continuation point.
221 class DeoptRetAddrBeforeInstr : public DeoptInstr { 221 class DeoptRetBeforeAddressInstr : public DeoptInstr {
222 public: 222 public:
223 DeoptRetAddrBeforeInstr(intptr_t object_table_index, intptr_t deopt_id) 223 DeoptRetBeforeAddressInstr(intptr_t object_table_index, intptr_t deopt_id)
224 : object_table_index_(object_table_index), deopt_id_(deopt_id) { 224 : object_table_index_(object_table_index), deopt_id_(deopt_id) {
225 ASSERT(object_table_index >= 0); 225 ASSERT(object_table_index >= 0);
226 ASSERT(deopt_id_ >= 0); 226 ASSERT(deopt_id >= 0);
227 } 227 }
228 228
229 explicit DeoptRetAddrBeforeInstr(intptr_t from_index) 229 explicit DeoptRetBeforeAddressInstr(intptr_t from_index)
230 : object_table_index_(ObjectTableIndex::decode(from_index)), 230 : object_table_index_(ObjectTableIndex::decode(from_index)),
231 deopt_id_(DeoptId::decode(from_index)) { 231 deopt_id_(DeoptId::decode(from_index)) {
232 } 232 }
233 233
234 virtual intptr_t from_index() const { 234 virtual intptr_t from_index() const {
235 return ObjectTableIndex::encode(object_table_index_) | 235 return ObjectTableIndex::encode(object_table_index_) |
236 DeoptId::encode(deopt_id_); 236 DeoptId::encode(deopt_id_);
237 } 237 }
238 virtual DeoptInstr::Kind kind() const { return kSetRetBeforeAddress; } 238 virtual DeoptInstr::Kind kind() const { return kRetBeforeAddress; }
239 239
240 virtual const char* ToCString() const { 240 virtual const char* ToCString() const {
241 const char* format = "ret bef oti:%"Pd"(%"Pd")"; 241 const char* format = "ret bef oti:%"Pd"(%"Pd")";
242 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_); 242 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_);
243 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 243 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
244 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_); 244 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_);
245 return chars; 245 return chars;
246 } 246 }
247 247
248 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 248 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
249 Function& function = Function::Handle(deopt_context->isolate()); 249 Function& function = Function::Handle(deopt_context->isolate());
250 function ^= deopt_context->ObjectAt(object_table_index_); 250 function ^= deopt_context->ObjectAt(object_table_index_);
251 const Code& code = 251 const Code& code =
252 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); 252 Code::Handle(deopt_context->isolate(), function.unoptimized_code());
253 uword continue_at_pc = code.GetDeoptBeforePcAtDeoptId(deopt_id_); 253 uword continue_at_pc = code.GetDeoptBeforePcAtDeoptId(deopt_id_);
254 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); 254 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
255 *to_addr = continue_at_pc; 255 *to_addr = continue_at_pc;
256 } 256 }
257 257
258 private: 258 private:
259 static const intptr_t kFieldWidth = kBitsPerWord / 2; 259 static const intptr_t kFieldWidth = kBitsPerWord / 2;
260 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { }; 260 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { };
261 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; 261 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
262 262
263 const intptr_t object_table_index_; 263 const intptr_t object_table_index_;
264 const intptr_t deopt_id_; 264 const intptr_t deopt_id_;
265 265
266 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrBeforeInstr); 266 DISALLOW_COPY_AND_ASSIGN(DeoptRetBeforeAddressInstr);
267 }; 267 };
268 268
269 269
270 // Deoptimization instruction moving a constant stored at 'object_table_index'. 270 // Deoptimization instruction moving a constant stored at 'object_table_index'.
271 class DeoptConstantInstr : public DeoptInstr { 271 class DeoptConstantInstr : public DeoptInstr {
272 public: 272 public:
273 explicit DeoptConstantInstr(intptr_t object_table_index) 273 explicit DeoptConstantInstr(intptr_t object_table_index)
274 : object_table_index_(object_table_index) { 274 : object_table_index_(object_table_index) {
275 ASSERT(object_table_index >= 0); 275 ASSERT(object_table_index >= 0);
276 } 276 }
277 277
278 virtual intptr_t from_index() const { return object_table_index_; } 278 virtual intptr_t from_index() const { return object_table_index_; }
279 virtual DeoptInstr::Kind kind() const { return kCopyConstant; } 279 virtual DeoptInstr::Kind kind() const { return kConstant; }
280 280
281 virtual const char* ToCString() const { 281 virtual const char* ToCString() const {
282 const char* format = "const oti:%"Pd""; 282 const char* format = "const oti:%"Pd"";
283 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); 283 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_);
284 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 284 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
285 OS::SNPrint(chars, len + 1, format, object_table_index_); 285 OS::SNPrint(chars, len + 1, format, object_table_index_);
286 return chars; 286 return chars;
287 } 287 }
288 288
289 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 289 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
(...skipping 11 matching lines...) Expand all
301 }; 301 };
302 302
303 303
304 // Deoptimization instruction moving a CPU register. 304 // Deoptimization instruction moving a CPU register.
305 class DeoptRegisterInstr: public DeoptInstr { 305 class DeoptRegisterInstr: public DeoptInstr {
306 public: 306 public:
307 explicit DeoptRegisterInstr(intptr_t reg_as_int) 307 explicit DeoptRegisterInstr(intptr_t reg_as_int)
308 : reg_(static_cast<Register>(reg_as_int)) {} 308 : reg_(static_cast<Register>(reg_as_int)) {}
309 309
310 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } 310 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
311 virtual DeoptInstr::Kind kind() const { return kCopyRegister; } 311 virtual DeoptInstr::Kind kind() const { return kRegister; }
312 312
313 virtual const char* ToCString() const { 313 virtual const char* ToCString() const {
314 return Assembler::RegisterName(reg_); 314 return Assembler::RegisterName(reg_);
315 } 315 }
316 316
317 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 317 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
318 intptr_t value = deopt_context->RegisterValue(reg_); 318 intptr_t value = deopt_context->RegisterValue(reg_);
319 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); 319 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
320 *to_addr = value; 320 *to_addr = value;
321 } 321 }
322 322
323 private: 323 private:
324 const Register reg_; 324 const Register reg_;
325 325
326 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); 326 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr);
327 }; 327 };
328 328
329 329
330 // Deoptimization instruction moving an XMM register. 330 // Deoptimization instruction moving an XMM register.
331 class DeoptXmmRegisterInstr: public DeoptInstr { 331 class DeoptXmmRegisterInstr: public DeoptInstr {
332 public: 332 public:
333 explicit DeoptXmmRegisterInstr(intptr_t reg_as_int) 333 explicit DeoptXmmRegisterInstr(intptr_t reg_as_int)
334 : reg_(static_cast<XmmRegister>(reg_as_int)) {} 334 : reg_(static_cast<XmmRegister>(reg_as_int)) {}
335 335
336 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } 336 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
337 virtual DeoptInstr::Kind kind() const { return kCopyXmmRegister; } 337 virtual DeoptInstr::Kind kind() const { return kXmmRegister; }
338 338
339 virtual const char* ToCString() const { 339 virtual const char* ToCString() const {
340 return Assembler::XmmRegisterName(reg_); 340 return Assembler::XmmRegisterName(reg_);
341 } 341 }
342 342
343 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 343 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
344 double value = deopt_context->XmmRegisterValue(reg_); 344 double value = deopt_context->XmmRegisterValue(reg_);
345 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); 345 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
346 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); 346 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
347 Isolate::Current()->DeferDoubleMaterialization( 347 Isolate::Current()->DeferDoubleMaterialization(
348 value, reinterpret_cast<RawDouble**>(to_addr)); 348 value, reinterpret_cast<RawDouble**>(to_addr));
349 } 349 }
350 350
351 private: 351 private:
352 const XmmRegister reg_; 352 const XmmRegister reg_;
353 353
354 DISALLOW_COPY_AND_ASSIGN(DeoptXmmRegisterInstr); 354 DISALLOW_COPY_AND_ASSIGN(DeoptXmmRegisterInstr);
355 }; 355 };
356 356
357 357
358 class DeoptInt64XmmRegisterInstr: public DeoptInstr { 358 class DeoptInt64XmmRegisterInstr: public DeoptInstr {
359 public: 359 public:
360 explicit DeoptInt64XmmRegisterInstr(intptr_t reg_as_int) 360 explicit DeoptInt64XmmRegisterInstr(intptr_t reg_as_int)
361 : reg_(static_cast<XmmRegister>(reg_as_int)) {} 361 : reg_(static_cast<XmmRegister>(reg_as_int)) {}
362 362
363 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } 363 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
364 virtual DeoptInstr::Kind kind() const { return kCopyInt64XmmRegister; } 364 virtual DeoptInstr::Kind kind() const { return kInt64XmmRegister; }
365 365
366 virtual const char* ToCString() const { 366 virtual const char* ToCString() const {
367 const char* format = "%s(m)"; 367 const char* format = "%s(m)";
368 intptr_t len = 368 intptr_t len =
369 OS::SNPrint(NULL, 0, format, Assembler::XmmRegisterName(reg_)); 369 OS::SNPrint(NULL, 0, format, Assembler::XmmRegisterName(reg_));
370 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 370 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
371 OS::SNPrint(chars, len + 1, format, Assembler::XmmRegisterName(reg_)); 371 OS::SNPrint(chars, len + 1, format, Assembler::XmmRegisterName(reg_));
372 return chars; 372 return chars;
373 } 373 }
374 374
(...skipping 20 matching lines...) Expand all
395 // Deoptimization instruction creating a PC marker for the code of 395 // Deoptimization instruction creating a PC marker for the code of
396 // function at 'object_table_index'. 396 // function at 'object_table_index'.
397 class DeoptPcMarkerInstr : public DeoptInstr { 397 class DeoptPcMarkerInstr : public DeoptInstr {
398 public: 398 public:
399 explicit DeoptPcMarkerInstr(intptr_t object_table_index) 399 explicit DeoptPcMarkerInstr(intptr_t object_table_index)
400 : object_table_index_(object_table_index) { 400 : object_table_index_(object_table_index) {
401 ASSERT(object_table_index >= 0); 401 ASSERT(object_table_index >= 0);
402 } 402 }
403 403
404 virtual intptr_t from_index() const { return object_table_index_; } 404 virtual intptr_t from_index() const { return object_table_index_; }
405 virtual DeoptInstr::Kind kind() const { return kSetPcMarker; } 405 virtual DeoptInstr::Kind kind() const { return kPcMarker; }
406 406
407 virtual const char* ToCString() const { 407 virtual const char* ToCString() const {
408 const char* format = "pcmark oti:%"Pd""; 408 const char* format = "pcmark oti:%"Pd"";
409 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); 409 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_);
410 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 410 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
411 OS::SNPrint(chars, len + 1, format, object_table_index_); 411 OS::SNPrint(chars, len + 1, format, object_table_index_);
412 return chars; 412 return chars;
413 } 413 }
414 414
415 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 415 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
(...skipping 20 matching lines...) Expand all
436 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); 436 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr);
437 }; 437 };
438 438
439 439
440 // Deoptimization instruction copying the caller saved FP from optimized frame. 440 // Deoptimization instruction copying the caller saved FP from optimized frame.
441 class DeoptCallerFpInstr : public DeoptInstr { 441 class DeoptCallerFpInstr : public DeoptInstr {
442 public: 442 public:
443 DeoptCallerFpInstr() {} 443 DeoptCallerFpInstr() {}
444 444
445 virtual intptr_t from_index() const { return 0; } 445 virtual intptr_t from_index() const { return 0; }
446 virtual DeoptInstr::Kind kind() const { return kSetCallerFp; } 446 virtual DeoptInstr::Kind kind() const { return kCallerFp; }
447 447
448 virtual const char* ToCString() const { 448 virtual const char* ToCString() const {
449 return "callerfp"; 449 return "callerfp";
450 } 450 }
451 451
452 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 452 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
453 intptr_t from = deopt_context->GetCallerFp(); 453 intptr_t from = deopt_context->GetCallerFp();
454 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); 454 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
455 *to_addr = from; 455 *to_addr = from;
456 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr)); 456 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr));
457 } 457 }
458 458
459 private: 459 private:
460 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); 460 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr);
461 }; 461 };
462 462
463 463
464 // Deoptimization instruction copying the caller return address from optimized 464 // Deoptimization instruction copying the caller return address from optimized
465 // frame. 465 // frame.
466 class DeoptCallerPcInstr : public DeoptInstr { 466 class DeoptCallerPcInstr : public DeoptInstr {
467 public: 467 public:
468 DeoptCallerPcInstr() {} 468 DeoptCallerPcInstr() {}
469 469
470 virtual intptr_t from_index() const { return 0; } 470 virtual intptr_t from_index() const { return 0; }
471 virtual DeoptInstr::Kind kind() const { return kSetCallerPc; } 471 virtual DeoptInstr::Kind kind() const { return kCallerPc; }
472 472
473 virtual const char* ToCString() const { 473 virtual const char* ToCString() const {
474 return "callerpc"; 474 return "callerpc";
475 } 475 }
476 476
477 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 477 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
478 intptr_t from = deopt_context->GetFromPc(); 478 intptr_t from = deopt_context->GetFromPc();
479 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); 479 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
480 *to_addr = from; 480 *to_addr = from;
481 } 481 }
482 482
483 private: 483 private:
484 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); 484 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr);
485 }; 485 };
486 486
487 487
488 class DeoptSuffixInstr : public DeoptInstr {
srdjan 2012/10/08 16:37:58 Add brief comment about the class.
489 public:
490 DeoptSuffixInstr(intptr_t info_number, intptr_t suffix_length)
491 : info_number_(info_number), suffix_length_(suffix_length) {
492 ASSERT(info_number >= 0);
493 ASSERT(suffix_length >= 0);
494 }
495
496 explicit DeoptSuffixInstr(intptr_t from_index)
497 : info_number_(InfoNumber::decode(from_index)),
498 suffix_length_(SuffixLength::decode(from_index)) {
499 }
500
501 virtual intptr_t from_index() const {
502 return InfoNumber::encode(info_number_) |
503 SuffixLength::encode(suffix_length_);
504 }
505 virtual DeoptInstr::Kind kind() const { return kSuffix; }
506
507 virtual const char* ToCString() const {
508 const char* format = "suffix %"Pd":%"Pd;
509 intptr_t len = OS::SNPrint(NULL, 0, format, info_number_, suffix_length_);
510 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
511 OS::SNPrint(chars, len + 1, format, info_number_, suffix_length_);
512 return chars;
513 }
514
515 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
516 UNREACHABLE();
Kevin Millikin (Google) 2012/10/05 14:31:55 Notice. The strategy is to 'uncompress' the entry
517 }
518
519 private:
520 friend class DeoptInstr;
521
522 static const intptr_t kFieldWidth = kBitsPerWord / 2;
523 class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { };
524 class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
525
526 const intptr_t info_number_;
527 const intptr_t suffix_length_;
528
529 DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr);
530 };
531
532
533 intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) {
534 *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index);
535 return DeoptSuffixInstr::SuffixLength::decode(from_index);
536 }
537
538
488 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { 539 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) {
489 Kind kind = static_cast<Kind>(kind_as_int); 540 Kind kind = static_cast<Kind>(kind_as_int);
490 switch (kind) { 541 switch (kind) {
491 case kCopyStackSlot: return new DeoptStackSlotInstr(from_index); 542 case kStackSlot: return new DeoptStackSlotInstr(from_index);
492 case kCopyDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); 543 case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index);
493 case kCopyInt64StackSlot: return new DeoptInt64StackSlotInstr(from_index); 544 case kInt64StackSlot: return new DeoptInt64StackSlotInstr(from_index);
494 case kSetRetAfterAddress: return new DeoptRetAddrAfterInstr(from_index); 545 case kRetAfterAddress: return new DeoptRetAfterAddressInstr(from_index);
495 case kSetRetBeforeAddress: return new DeoptRetAddrBeforeInstr(from_index); 546 case kRetBeforeAddress: return new DeoptRetBeforeAddressInstr(from_index);
496 case kCopyConstant: return new DeoptConstantInstr(from_index); 547 case kConstant: return new DeoptConstantInstr(from_index);
497 case kCopyRegister: return new DeoptRegisterInstr(from_index); 548 case kRegister: return new DeoptRegisterInstr(from_index);
498 case kCopyXmmRegister: return new DeoptXmmRegisterInstr(from_index); 549 case kXmmRegister: return new DeoptXmmRegisterInstr(from_index);
499 case kCopyInt64XmmRegister: 550 case kInt64XmmRegister: return new DeoptInt64XmmRegisterInstr(from_index);
500 return new DeoptInt64XmmRegisterInstr(from_index); 551 case kPcMarker: return new DeoptPcMarkerInstr(from_index);
501 case kSetPcMarker: return new DeoptPcMarkerInstr(from_index); 552 case kCallerFp: return new DeoptCallerFpInstr();
502 case kSetCallerFp: return new DeoptCallerFpInstr(); 553 case kCallerPc: return new DeoptCallerPcInstr();
503 case kSetCallerPc: return new DeoptCallerPcInstr(); 554 case kSuffix: return new DeoptSuffixInstr(from_index);
504 } 555 }
505 UNREACHABLE(); 556 UNREACHABLE();
506 return NULL; 557 return NULL;
507 } 558 }
508 559
509 560
561 class DeoptInfoBuilder::TrieNode : public ZoneAllocated {
562 public:
563 // Construct the root node representing the implicit "shared" terminator
564 // at the end of each deopt info.
565 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) { }
566
567 // Construct a node representing a written instruction.
568 TrieNode(DeoptInstr* instruction, intptr_t info_number)
569 : instruction_(instruction), info_number_(info_number), children_(4) { }
570
571 intptr_t info_number() const { return info_number_; }
572
573 void AddChild(TrieNode* child) {
574 if (child != NULL) children_.Add(child);
srdjan 2012/10/08 16:37:58 When can you call this with child==NULL ?
575 }
576
577 TrieNode* FindChild(const DeoptInstr& instruction) {
578 for (intptr_t i = 0; i < children_.length(); ++i) {
579 TrieNode* child = children_[i];
580 if (child->instruction_->Equals(instruction)) return child;
581 }
582 return NULL;
583 }
584
585 private:
586 const DeoptInstr* instruction_; // Istruction that was written.
srdjan 2012/10/08 16:37:58 s/Istruction/Instruction/
587 const intptr_t info_number_; // Index of the deopt info it was written to.
588
589 GrowableArray<TrieNode*> children_;
590 };
591
592
593 DeoptInfoBuilder::DeoptInfoBuilder(const intptr_t num_args)
594 : instructions_(),
595 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
596 num_args_(num_args),
597 trie_root_(new TrieNode()),
598 current_info_number_(0) {
599 }
600
601
510 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { 602 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const {
511 for (intptr_t i = 0; i < object_table_.Length(); i++) { 603 for (intptr_t i = 0; i < object_table_.Length(); i++) {
512 if (object_table_.At(i) == obj.raw()) { 604 if (object_table_.At(i) == obj.raw()) {
513 return i; 605 return i;
514 } 606 }
515 } 607 }
516 // Add object. 608 // Add object.
517 const intptr_t result = object_table_.Length(); 609 const intptr_t result = object_table_.Length();
518 object_table_.Add(obj); 610 object_table_.Add(obj);
519 return result; 611 return result;
520 } 612 }
521 613
522 614
523 void DeoptInfoBuilder::AddReturnAddressBefore(const Function& function, 615 void DeoptInfoBuilder::AddReturnAddressBefore(const Function& function,
524 intptr_t deopt_id, 616 intptr_t deopt_id,
525 intptr_t to_index) { 617 intptr_t to_index) {
526 const intptr_t object_table_index = FindOrAddObjectInTable(function); 618 const intptr_t object_table_index = FindOrAddObjectInTable(function);
527 ASSERT(to_index == instructions_.length()); 619 ASSERT(to_index == instructions_.length());
528 instructions_.Add(new DeoptRetAddrBeforeInstr(object_table_index, deopt_id)); 620 instructions_.Add(new DeoptRetBeforeAddressInstr(object_table_index,
621 deopt_id));
529 } 622 }
530 623
531 624
532 void DeoptInfoBuilder::AddReturnAddressAfter(const Function& function, 625 void DeoptInfoBuilder::AddReturnAddressAfter(const Function& function,
533 intptr_t deopt_id, 626 intptr_t deopt_id,
534 intptr_t to_index) { 627 intptr_t to_index) {
535 const intptr_t object_table_index = FindOrAddObjectInTable(function); 628 const intptr_t object_table_index = FindOrAddObjectInTable(function);
536 ASSERT(to_index == instructions_.length()); 629 ASSERT(to_index == instructions_.length());
537 instructions_.Add(new DeoptRetAddrAfterInstr(object_table_index, deopt_id)); 630 instructions_.Add(new DeoptRetAfterAddressInstr(object_table_index,
631 deopt_id));
538 } 632 }
539 633
540 634
541 void DeoptInfoBuilder::AddPcMarker(const Function& function, 635 void DeoptInfoBuilder::AddPcMarker(const Function& function,
542 intptr_t to_index) { 636 intptr_t to_index) {
543 // Function object was already added by AddReturnAddress, find it. 637 // Function object was already added by AddReturnAddress, find it.
544 intptr_t from_index = FindOrAddObjectInTable(function); 638 intptr_t from_index = FindOrAddObjectInTable(function);
545 ASSERT(to_index == instructions_.length()); 639 ASSERT(to_index == instructions_.length());
546 instructions_.Add(new DeoptPcMarkerInstr(from_index)); 640 instructions_.Add(new DeoptPcMarkerInstr(from_index));
547 } 641 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 instructions_.Add(new DeoptCallerFpInstr()); 687 instructions_.Add(new DeoptCallerFpInstr());
594 } 688 }
595 689
596 690
597 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) { 691 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) {
598 ASSERT(to_index == instructions_.length()); 692 ASSERT(to_index == instructions_.length());
599 instructions_.Add(new DeoptCallerPcInstr()); 693 instructions_.Add(new DeoptCallerPcInstr());
600 } 694 }
601 695
602 696
603 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() const { 697 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() {
604 const intptr_t len = instructions_.length(); 698 intptr_t length = instructions_.length();
605 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(len)); 699
606 for (intptr_t i = 0; i < len; i++) { 700 // Count the number of instructions that are a shared suffix of some deopt
701 // info already written.
702 TrieNode* suffix = trie_root_;
703 intptr_t suffix_length = 0;
704 for (intptr_t i = length - 1; i >= 0; --i) {
705 TrieNode* node = suffix->FindChild(*instructions_[i]);
706 if (node == NULL) break;
707 suffix = node;
708 ++suffix_length;
709 }
710
711 // Allocate space for the translation. If the shared suffix is longer
712 // than one instruction, we replace it with a single suffix instruction.
713 if (suffix_length > 1) length -= (suffix_length - 1);
714 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(length));
715
716 // Write the unshared instructions and build their sub-tree.
717 TrieNode* node = NULL;
718 intptr_t write_count = (suffix_length > 1) ? length - 1 : length;
719 for (intptr_t i = 0; i < write_count; ++i) {
607 DeoptInstr* instr = instructions_[i]; 720 DeoptInstr* instr = instructions_[i];
608 deopt_info.SetAt(i, instr->kind(), instr->from_index()); 721 deopt_info.SetAt(i, instr->kind(), instr->from_index());
722 TrieNode* child = node;
723 node = new TrieNode(instr, current_info_number_);
724 node->AddChild(child);
609 } 725 }
726 suffix->AddChild(node);
727
728 if (suffix_length > 1) {
729 DeoptInstr* instr =
730 new DeoptSuffixInstr(suffix->info_number(), suffix_length);
731 deopt_info.SetAt(length - 1, instr->kind(), instr->from_index());
732 }
733
734 instructions_.Clear();
735 ++current_info_number_;
610 return deopt_info.raw(); 736 return deopt_info.raw();
611 } 737 }
612 738
613 739
614 intptr_t DeoptTable::SizeFor(intptr_t length) { 740 intptr_t DeoptTable::SizeFor(intptr_t length) {
615 return length * kEntrySize; 741 return length * kEntrySize;
616 } 742 }
617 743
618 void DeoptTable::SetEntry(const Array& table, 744 void DeoptTable::SetEntry(const Array& table,
619 intptr_t index, 745 intptr_t index,
(...skipping 19 matching lines...) Expand all
639 Smi* offset, 765 Smi* offset,
640 DeoptInfo* info, 766 DeoptInfo* info,
641 Smi* reason) { 767 Smi* reason) {
642 intptr_t i = index * kEntrySize; 768 intptr_t i = index * kEntrySize;
643 *offset ^= table.At(i); 769 *offset ^= table.At(i);
644 *info ^= table.At(i + 1); 770 *info ^= table.At(i + 1);
645 *reason ^= table.At(i + 2); 771 *reason ^= table.At(i + 2);
646 } 772 }
647 773
648 } // namespace dart 774 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698