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

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

Powered by Google App Engine
This is Rietveld 408576698