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

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

Issue 14935005: Implement a variation of scalar replacement for non-escaping allocations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address comments Created 7 years, 7 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.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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.h" 7 #include "vm/assembler.h"
8 #include "vm/code_patcher.h" 8 #include "vm/code_patcher.h"
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 #include "vm/locations.h" 10 #include "vm/locations.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 public: 65 public:
66 explicit DeoptStackSlotInstr(intptr_t from_index) 66 explicit DeoptStackSlotInstr(intptr_t from_index)
67 : stack_slot_index_(from_index) { 67 : stack_slot_index_(from_index) {
68 ASSERT(stack_slot_index_ >= 0); 68 ASSERT(stack_slot_index_ >= 0);
69 } 69 }
70 70
71 virtual intptr_t from_index() const { return stack_slot_index_; } 71 virtual intptr_t from_index() const { return stack_slot_index_; }
72 virtual DeoptInstr::Kind kind() const { return kStackSlot; } 72 virtual DeoptInstr::Kind kind() const { return kStackSlot; }
73 73
74 virtual const char* ToCString() const { 74 virtual const char* ToCString() const {
75 const char* format = "s%"Pd""; 75 return Isolate::Current()->current_zone()->PrintToString(
76 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); 76 "s%"Pd"", stack_slot_index_);
77 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
78 OS::SNPrint(chars, len + 1, format, stack_slot_index_);
79 return chars;
80 } 77 }
81 78
82 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 79 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
83 intptr_t from_index = 80 intptr_t from_index =
84 deopt_context->from_frame_size() - stack_slot_index_ - 1; 81 deopt_context->from_frame_size() - stack_slot_index_ - 1;
85 intptr_t* from_addr = deopt_context->GetFromFrameAddressAt(from_index); 82 intptr_t* from_addr = deopt_context->GetFromFrameAddressAt(from_index);
86 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
87 *to_addr = *from_addr; 83 *to_addr = *from_addr;
88 } 84 }
89 85
90 private: 86 private:
91 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. 87 const intptr_t stack_slot_index_; // First argument is 0, always >= 0.
92 88
93 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); 89 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr);
94 }; 90 };
95 91
96 92
97 class DeoptDoubleStackSlotInstr : public DeoptInstr { 93 class DeoptDoubleStackSlotInstr : public DeoptInstr {
98 public: 94 public:
99 explicit DeoptDoubleStackSlotInstr(intptr_t from_index) 95 explicit DeoptDoubleStackSlotInstr(intptr_t from_index)
100 : stack_slot_index_(from_index) { 96 : stack_slot_index_(from_index) {
101 ASSERT(stack_slot_index_ >= 0); 97 ASSERT(stack_slot_index_ >= 0);
102 } 98 }
103 99
104 virtual intptr_t from_index() const { return stack_slot_index_; } 100 virtual intptr_t from_index() const { return stack_slot_index_; }
105 virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; } 101 virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; }
106 102
107 virtual const char* ToCString() const { 103 virtual const char* ToCString() const {
108 const char* format = "ds%"Pd""; 104 return Isolate::Current()->current_zone()->PrintToString(
109 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); 105 "ds%"Pd"", stack_slot_index_);
110 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
111 OS::SNPrint(chars, len + 1, format, stack_slot_index_);
112 return chars;
113 } 106 }
114 107
115 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 108 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
116 intptr_t from_index = 109 intptr_t from_index =
117 deopt_context->from_frame_size() - stack_slot_index_ - 1; 110 deopt_context->from_frame_size() - stack_slot_index_ - 1;
118 double* from_addr = reinterpret_cast<double*>( 111 double* from_addr = reinterpret_cast<double*>(
119 deopt_context->GetFromFrameAddressAt(from_index)); 112 deopt_context->GetFromFrameAddressAt(from_index));
120 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
121 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); 113 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
122 Isolate::Current()->DeferDoubleMaterialization( 114 Isolate::Current()->DeferDoubleMaterialization(
123 *from_addr, reinterpret_cast<RawDouble**>(to_addr)); 115 *from_addr, reinterpret_cast<RawDouble**>(to_addr));
124 } 116 }
125 117
126 private: 118 private:
127 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. 119 const intptr_t stack_slot_index_; // First argument is 0, always >= 0.
128 120
129 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); 121 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr);
130 }; 122 };
131 123
132 124
133 class DeoptInt64StackSlotInstr : public DeoptInstr { 125 class DeoptInt64StackSlotInstr : public DeoptInstr {
134 public: 126 public:
135 explicit DeoptInt64StackSlotInstr(intptr_t from_index) 127 explicit DeoptInt64StackSlotInstr(intptr_t from_index)
136 : stack_slot_index_(from_index) { 128 : stack_slot_index_(from_index) {
137 ASSERT(stack_slot_index_ >= 0); 129 ASSERT(stack_slot_index_ >= 0);
138 } 130 }
139 131
140 virtual intptr_t from_index() const { return stack_slot_index_; } 132 virtual intptr_t from_index() const { return stack_slot_index_; }
141 virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; } 133 virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; }
142 134
143 virtual const char* ToCString() const { 135 virtual const char* ToCString() const {
144 const char* format = "ms%"Pd""; 136 return Isolate::Current()->current_zone()->PrintToString(
145 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); 137 "ms%"Pd"", stack_slot_index_);
146 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
147 OS::SNPrint(chars, len + 1, format, stack_slot_index_);
148 return chars;
149 } 138 }
150 139
151 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 140 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
152 intptr_t from_index = 141 intptr_t from_index =
153 deopt_context->from_frame_size() - stack_slot_index_ - 1; 142 deopt_context->from_frame_size() - stack_slot_index_ - 1;
154 int64_t* from_addr = reinterpret_cast<int64_t*>( 143 int64_t* from_addr = reinterpret_cast<int64_t*>(
155 deopt_context->GetFromFrameAddressAt(from_index)); 144 deopt_context->GetFromFrameAddressAt(from_index));
156 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
157 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); 145 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
158 if (Smi::IsValid64(*from_addr)) { 146 if (Smi::IsValid64(*from_addr)) {
159 *to_addr = reinterpret_cast<intptr_t>( 147 *to_addr = reinterpret_cast<intptr_t>(
160 Smi::New(static_cast<intptr_t>(*from_addr))); 148 Smi::New(static_cast<intptr_t>(*from_addr)));
161 } else { 149 } else {
162 Isolate::Current()->DeferMintMaterialization( 150 Isolate::Current()->DeferMintMaterialization(
163 *from_addr, reinterpret_cast<RawMint**>(to_addr)); 151 *from_addr, reinterpret_cast<RawMint**>(to_addr));
164 } 152 }
165 } 153 }
166 154
167 private: 155 private:
168 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. 156 const intptr_t stack_slot_index_; // First argument is 0, always >= 0.
169 157
170 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr); 158 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr);
171 }; 159 };
172 160
173 161
174 class DeoptFloat32x4StackSlotInstr : public DeoptInstr { 162 class DeoptFloat32x4StackSlotInstr : public DeoptInstr {
175 public: 163 public:
176 explicit DeoptFloat32x4StackSlotInstr(intptr_t from_index) 164 explicit DeoptFloat32x4StackSlotInstr(intptr_t from_index)
177 : stack_slot_index_(from_index) { 165 : stack_slot_index_(from_index) {
178 ASSERT(stack_slot_index_ >= 0); 166 ASSERT(stack_slot_index_ >= 0);
179 } 167 }
180 168
181 virtual intptr_t from_index() const { return stack_slot_index_; } 169 virtual intptr_t from_index() const { return stack_slot_index_; }
182 virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; } 170 virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; }
183 171
184 virtual const char* ToCString() const { 172 virtual const char* ToCString() const {
185 const char* format = "f32x4s%"Pd""; 173 return Isolate::Current()->current_zone()->PrintToString(
186 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); 174 "f32x4s%"Pd"", stack_slot_index_);
187 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
188 OS::SNPrint(chars, len + 1, format, stack_slot_index_);
189 return chars;
190 } 175 }
191 176
192 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 177 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
193 intptr_t from_index = 178 intptr_t from_index =
194 deopt_context->from_frame_size() - stack_slot_index_ - 1; 179 deopt_context->from_frame_size() - stack_slot_index_ - 1;
195 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( 180 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>(
196 deopt_context->GetFromFrameAddressAt(from_index)); 181 deopt_context->GetFromFrameAddressAt(from_index));
197 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
198 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); 182 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
199 Isolate::Current()->DeferFloat32x4Materialization( 183 Isolate::Current()->DeferFloat32x4Materialization(
200 *from_addr, reinterpret_cast<RawFloat32x4**>(to_addr)); 184 *from_addr, reinterpret_cast<RawFloat32x4**>(to_addr));
201 } 185 }
202 186
203 private: 187 private:
204 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. 188 const intptr_t stack_slot_index_; // First argument is 0, always >= 0.
205 189
206 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr); 190 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr);
207 }; 191 };
208 192
209 193
210 class DeoptUint32x4StackSlotInstr : public DeoptInstr { 194 class DeoptUint32x4StackSlotInstr : public DeoptInstr {
211 public: 195 public:
212 explicit DeoptUint32x4StackSlotInstr(intptr_t from_index) 196 explicit DeoptUint32x4StackSlotInstr(intptr_t from_index)
213 : stack_slot_index_(from_index) { 197 : stack_slot_index_(from_index) {
214 ASSERT(stack_slot_index_ >= 0); 198 ASSERT(stack_slot_index_ >= 0);
215 } 199 }
216 200
217 virtual intptr_t from_index() const { return stack_slot_index_; } 201 virtual intptr_t from_index() const { return stack_slot_index_; }
218 virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; } 202 virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; }
219 203
220 virtual const char* ToCString() const { 204 virtual const char* ToCString() const {
221 const char* format = "ui32x4s%"Pd""; 205 return Isolate::Current()->current_zone()->PrintToString(
222 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); 206 "ui32x4s%"Pd"", stack_slot_index_);
223 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
224 OS::SNPrint(chars, len + 1, format, stack_slot_index_);
225 return chars;
226 } 207 }
227 208
228 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 209 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
229 intptr_t from_index = 210 intptr_t from_index =
230 deopt_context->from_frame_size() - stack_slot_index_ - 1; 211 deopt_context->from_frame_size() - stack_slot_index_ - 1;
231 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( 212 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>(
232 deopt_context->GetFromFrameAddressAt(from_index)); 213 deopt_context->GetFromFrameAddressAt(from_index));
233 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
234 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); 214 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
235 Isolate::Current()->DeferUint32x4Materialization( 215 Isolate::Current()->DeferUint32x4Materialization(
236 *from_addr, reinterpret_cast<RawUint32x4**>(to_addr)); 216 *from_addr, reinterpret_cast<RawUint32x4**>(to_addr));
237 } 217 }
238 218
239 private: 219 private:
240 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. 220 const intptr_t stack_slot_index_; // First argument is 0, always >= 0.
241 221
242 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr); 222 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr);
243 }; 223 };
(...skipping 19 matching lines...) Expand all
263 DeoptId::encode(deopt_id_); 243 DeoptId::encode(deopt_id_);
264 } 244 }
265 245
266 virtual DeoptInstr::Kind kind() const { return kRetAddress; } 246 virtual DeoptInstr::Kind kind() const { return kRetAddress; }
267 247
268 virtual const char* ToCString() const { 248 virtual const char* ToCString() const {
269 return Isolate::Current()->current_zone()->PrintToString( 249 return Isolate::Current()->current_zone()->PrintToString(
270 "ret oti:%"Pd"(%"Pd")", object_table_index_, deopt_id_); 250 "ret oti:%"Pd"(%"Pd")", object_table_index_, deopt_id_);
271 } 251 }
272 252
273 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 253 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
274 Function& function = Function::Handle(deopt_context->isolate()); 254 Function& function = Function::Handle(deopt_context->isolate());
275 function ^= deopt_context->ObjectAt(object_table_index_); 255 function ^= deopt_context->ObjectAt(object_table_index_);
276 const Code& code = 256 const Code& code =
277 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); 257 Code::Handle(deopt_context->isolate(), function.unoptimized_code());
278 ASSERT(!code.IsNull()); 258 ASSERT(!code.IsNull());
279 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, 259 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_,
280 PcDescriptors::kDeopt); 260 PcDescriptors::kDeopt);
281 ASSERT(continue_at_pc != 0); 261 ASSERT(continue_at_pc != 0);
282 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
283 *to_addr = continue_at_pc; 262 *to_addr = continue_at_pc;
284 263
285 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); 264 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall);
286 if (pc != 0) { 265 if (pc != 0) {
287 // If the deoptimization happened at an IC call, update the IC data 266 // If the deoptimization happened at an IC call, update the IC data
288 // to avoid repeated deoptimization at the same site next time around. 267 // to avoid repeated deoptimization at the same site next time around.
289 ICData& ic_data = ICData::Handle(); 268 ICData& ic_data = ICData::Handle();
290 CodePatcher::GetInstanceCallAt(pc, code, &ic_data, NULL); 269 CodePatcher::GetInstanceCallAt(pc, code, &ic_data, NULL);
291 if (!ic_data.IsNull()) { 270 if (!ic_data.IsNull()) {
292 ic_data.set_deopt_reason(deopt_context->deopt_reason()); 271 ic_data.set_deopt_reason(deopt_context->deopt_reason());
(...skipping 21 matching lines...) Expand all
314 public: 293 public:
315 explicit DeoptConstantInstr(intptr_t object_table_index) 294 explicit DeoptConstantInstr(intptr_t object_table_index)
316 : object_table_index_(object_table_index) { 295 : object_table_index_(object_table_index) {
317 ASSERT(object_table_index >= 0); 296 ASSERT(object_table_index >= 0);
318 } 297 }
319 298
320 virtual intptr_t from_index() const { return object_table_index_; } 299 virtual intptr_t from_index() const { return object_table_index_; }
321 virtual DeoptInstr::Kind kind() const { return kConstant; } 300 virtual DeoptInstr::Kind kind() const { return kConstant; }
322 301
323 virtual const char* ToCString() const { 302 virtual const char* ToCString() const {
324 const char* format = "const oti:%"Pd""; 303 return Isolate::Current()->current_zone()->PrintToString(
325 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); 304 "const oti:%"Pd"", object_table_index_);
326 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
327 OS::SNPrint(chars, len + 1, format, object_table_index_);
328 return chars;
329 } 305 }
330 306
331 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 307 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
332 const Object& obj = Object::Handle( 308 const Object& obj = Object::Handle(
333 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); 309 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_));
334 RawObject** to_addr = reinterpret_cast<RawObject**>( 310 *reinterpret_cast<RawObject**>(to_addr) = obj.raw();
335 deopt_context->GetToFrameAddressAt(to_index));
336 *to_addr = obj.raw();
337 } 311 }
338 312
339 private: 313 private:
340 const intptr_t object_table_index_; 314 const intptr_t object_table_index_;
341 315
342 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); 316 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr);
343 }; 317 };
344 318
345 319
346 // Deoptimization instruction moving a CPU register. 320 // Deoptimization instruction moving a CPU register.
347 class DeoptRegisterInstr: public DeoptInstr { 321 class DeoptRegisterInstr: public DeoptInstr {
348 public: 322 public:
349 explicit DeoptRegisterInstr(intptr_t reg_as_int) 323 explicit DeoptRegisterInstr(intptr_t reg_as_int)
350 : reg_(static_cast<Register>(reg_as_int)) {} 324 : reg_(static_cast<Register>(reg_as_int)) {}
351 325
352 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } 326 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
353 virtual DeoptInstr::Kind kind() const { return kRegister; } 327 virtual DeoptInstr::Kind kind() const { return kRegister; }
354 328
355 virtual const char* ToCString() const { 329 virtual const char* ToCString() const {
356 return Assembler::RegisterName(reg_); 330 return Assembler::RegisterName(reg_);
357 } 331 }
358 332
359 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 333 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
360 intptr_t value = deopt_context->RegisterValue(reg_); 334 *to_addr = deopt_context->RegisterValue(reg_);
361 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
362 *to_addr = value;
363 } 335 }
364 336
365 private: 337 private:
366 const Register reg_; 338 const Register reg_;
367 339
368 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); 340 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr);
369 }; 341 };
370 342
371 343
372 // Deoptimization instruction moving an XMM register. 344 // Deoptimization instruction moving an XMM register.
373 class DeoptFpuRegisterInstr: public DeoptInstr { 345 class DeoptFpuRegisterInstr: public DeoptInstr {
374 public: 346 public:
375 explicit DeoptFpuRegisterInstr(intptr_t reg_as_int) 347 explicit DeoptFpuRegisterInstr(intptr_t reg_as_int)
376 : reg_(static_cast<FpuRegister>(reg_as_int)) {} 348 : reg_(static_cast<FpuRegister>(reg_as_int)) {}
377 349
378 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } 350 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
379 virtual DeoptInstr::Kind kind() const { return kFpuRegister; } 351 virtual DeoptInstr::Kind kind() const { return kFpuRegister; }
380 352
381 virtual const char* ToCString() const { 353 virtual const char* ToCString() const {
382 return Assembler::FpuRegisterName(reg_); 354 return Assembler::FpuRegisterName(reg_);
383 } 355 }
384 356
385 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 357 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
386 double value = deopt_context->FpuRegisterValue(reg_); 358 double value = deopt_context->FpuRegisterValue(reg_);
387 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
388 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); 359 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
389 Isolate::Current()->DeferDoubleMaterialization( 360 Isolate::Current()->DeferDoubleMaterialization(
390 value, reinterpret_cast<RawDouble**>(to_addr)); 361 value, reinterpret_cast<RawDouble**>(to_addr));
391 } 362 }
392 363
393 private: 364 private:
394 const FpuRegister reg_; 365 const FpuRegister reg_;
395 366
396 DISALLOW_COPY_AND_ASSIGN(DeoptFpuRegisterInstr); 367 DISALLOW_COPY_AND_ASSIGN(DeoptFpuRegisterInstr);
397 }; 368 };
398 369
399 370
400 class DeoptInt64FpuRegisterInstr: public DeoptInstr { 371 class DeoptInt64FpuRegisterInstr: public DeoptInstr {
401 public: 372 public:
402 explicit DeoptInt64FpuRegisterInstr(intptr_t reg_as_int) 373 explicit DeoptInt64FpuRegisterInstr(intptr_t reg_as_int)
403 : reg_(static_cast<FpuRegister>(reg_as_int)) {} 374 : reg_(static_cast<FpuRegister>(reg_as_int)) {}
404 375
405 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } 376 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
406 virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; } 377 virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; }
407 378
408 virtual const char* ToCString() const { 379 virtual const char* ToCString() const {
409 const char* format = "%s(m)"; 380 return Isolate::Current()->current_zone()->PrintToString(
410 intptr_t len = 381 "%s(m)", Assembler::FpuRegisterName(reg_));
411 OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_));
412 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
413 OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_));
414 return chars;
415 } 382 }
416 383
417 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 384 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
418 int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_); 385 int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_);
419 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
420 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); 386 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
421 if (Smi::IsValid64(value)) { 387 if (Smi::IsValid64(value)) {
422 *to_addr = reinterpret_cast<intptr_t>( 388 *to_addr = reinterpret_cast<intptr_t>(
423 Smi::New(static_cast<intptr_t>(value))); 389 Smi::New(static_cast<intptr_t>(value)));
424 } else { 390 } else {
425 Isolate::Current()->DeferMintMaterialization( 391 Isolate::Current()->DeferMintMaterialization(
426 value, reinterpret_cast<RawMint**>(to_addr)); 392 value, reinterpret_cast<RawMint**>(to_addr));
427 } 393 }
428 } 394 }
429 395
430 private: 396 private:
431 const FpuRegister reg_; 397 const FpuRegister reg_;
432 398
433 DISALLOW_COPY_AND_ASSIGN(DeoptInt64FpuRegisterInstr); 399 DISALLOW_COPY_AND_ASSIGN(DeoptInt64FpuRegisterInstr);
434 }; 400 };
435 401
436 402
437 // Deoptimization instruction moving an XMM register. 403 // Deoptimization instruction moving an XMM register.
438 class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr { 404 class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr {
439 public: 405 public:
440 explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int) 406 explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int)
441 : reg_(static_cast<FpuRegister>(reg_as_int)) {} 407 : reg_(static_cast<FpuRegister>(reg_as_int)) {}
442 408
443 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } 409 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
444 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } 410 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; }
445 411
446 virtual const char* ToCString() const { 412 virtual const char* ToCString() const {
447 const char* format = "%s(f32x4)"; 413 return Isolate::Current()->current_zone()->PrintToString(
448 intptr_t len = 414 "%s(f32x4)", Assembler::FpuRegisterName(reg_));
449 OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_));
450 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
451 OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_));
452 return chars;
453 } 415 }
454 416
455 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 417 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
456 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); 418 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_);
457 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
458 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); 419 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
459 Isolate::Current()->DeferFloat32x4Materialization( 420 Isolate::Current()->DeferFloat32x4Materialization(
460 value, reinterpret_cast<RawFloat32x4**>(to_addr)); 421 value, reinterpret_cast<RawFloat32x4**>(to_addr));
461 } 422 }
462 423
463 private: 424 private:
464 const FpuRegister reg_; 425 const FpuRegister reg_;
465 426
466 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr); 427 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr);
467 }; 428 };
468 429
469 430
470 // Deoptimization instruction moving an XMM register. 431 // Deoptimization instruction moving an XMM register.
471 class DeoptUint32x4FpuRegisterInstr: public DeoptInstr { 432 class DeoptUint32x4FpuRegisterInstr: public DeoptInstr {
472 public: 433 public:
473 explicit DeoptUint32x4FpuRegisterInstr(intptr_t reg_as_int) 434 explicit DeoptUint32x4FpuRegisterInstr(intptr_t reg_as_int)
474 : reg_(static_cast<FpuRegister>(reg_as_int)) {} 435 : reg_(static_cast<FpuRegister>(reg_as_int)) {}
475 436
476 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } 437 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
477 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } 438 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; }
478 439
479 virtual const char* ToCString() const { 440 virtual const char* ToCString() const {
480 const char* format = "%s(f32x4)"; 441 return Isolate::Current()->current_zone()->PrintToString(
481 intptr_t len = 442 "%s(f32x4)", Assembler::FpuRegisterName(reg_));
482 OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_));
483 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
484 OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_));
485 return chars;
486 } 443 }
487 444
488 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 445 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
489 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); 446 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_);
490 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
491 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); 447 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
492 Isolate::Current()->DeferUint32x4Materialization( 448 Isolate::Current()->DeferUint32x4Materialization(
493 value, reinterpret_cast<RawUint32x4**>(to_addr)); 449 value, reinterpret_cast<RawUint32x4**>(to_addr));
494 } 450 }
495 451
496 private: 452 private:
497 const FpuRegister reg_; 453 const FpuRegister reg_;
498 454
499 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4FpuRegisterInstr); 455 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4FpuRegisterInstr);
500 }; 456 };
501 457
502 458
503 // Deoptimization instruction creating a PC marker for the code of 459 // Deoptimization instruction creating a PC marker for the code of
504 // function at 'object_table_index'. 460 // function at 'object_table_index'.
505 class DeoptPcMarkerInstr : public DeoptInstr { 461 class DeoptPcMarkerInstr : public DeoptInstr {
506 public: 462 public:
507 explicit DeoptPcMarkerInstr(intptr_t object_table_index) 463 explicit DeoptPcMarkerInstr(intptr_t object_table_index)
508 : object_table_index_(object_table_index) { 464 : object_table_index_(object_table_index) {
509 ASSERT(object_table_index >= 0); 465 ASSERT(object_table_index >= 0);
510 } 466 }
511 467
512 virtual intptr_t from_index() const { return object_table_index_; } 468 virtual intptr_t from_index() const { return object_table_index_; }
513 virtual DeoptInstr::Kind kind() const { return kPcMarker; } 469 virtual DeoptInstr::Kind kind() const { return kPcMarker; }
514 470
515 virtual const char* ToCString() const { 471 virtual const char* ToCString() const {
516 const char* format = "pcmark oti:%"Pd""; 472 return Isolate::Current()->current_zone()->PrintToString(
517 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); 473 "pcmark oti:%"Pd"", object_table_index_);
518 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
519 OS::SNPrint(chars, len + 1, format, object_table_index_);
520 return chars;
521 } 474 }
522 475
523 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 476 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
524 Function& function = Function::Handle(deopt_context->isolate()); 477 Function& function = Function::Handle(deopt_context->isolate());
525 function ^= deopt_context->ObjectAt(object_table_index_); 478 function ^= deopt_context->ObjectAt(object_table_index_);
526 const Code& code = 479 const Code& code =
527 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); 480 Code::Handle(deopt_context->isolate(), function.unoptimized_code());
528 ASSERT(!code.IsNull()); 481 ASSERT(!code.IsNull());
529 intptr_t pc_marker = code.EntryPoint() + 482 intptr_t pc_marker = code.EntryPoint() +
530 Assembler::kOffsetOfSavedPCfromEntrypoint; 483 Assembler::kOffsetOfSavedPCfromEntrypoint;
531 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
532 *to_addr = pc_marker; 484 *to_addr = pc_marker;
533 // Increment the deoptimization counter. This effectively increments each 485 // Increment the deoptimization counter. This effectively increments each
534 // function occurring in the optimized frame. 486 // function occurring in the optimized frame.
535 function.set_deoptimization_counter(function.deoptimization_counter() + 1); 487 function.set_deoptimization_counter(function.deoptimization_counter() + 1);
536 if (FLAG_trace_deoptimization) { 488 if (FLAG_trace_deoptimization) {
537 OS::PrintErr("Deoptimizing %s (count %d)\n", 489 OS::PrintErr("Deoptimizing %s (count %d)\n",
538 function.ToFullyQualifiedCString(), 490 function.ToFullyQualifiedCString(),
539 function.deoptimization_counter()); 491 function.deoptimization_counter());
540 } 492 }
541 // Clear invocation counter so that hopefully the function gets reoptimized 493 // Clear invocation counter so that hopefully the function gets reoptimized
(...skipping 14 matching lines...) Expand all
556 public: 508 public:
557 DeoptCallerFpInstr() {} 509 DeoptCallerFpInstr() {}
558 510
559 virtual intptr_t from_index() const { return 0; } 511 virtual intptr_t from_index() const { return 0; }
560 virtual DeoptInstr::Kind kind() const { return kCallerFp; } 512 virtual DeoptInstr::Kind kind() const { return kCallerFp; }
561 513
562 virtual const char* ToCString() const { 514 virtual const char* ToCString() const {
563 return "callerfp"; 515 return "callerfp";
564 } 516 }
565 517
566 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 518 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
567 intptr_t from = deopt_context->GetCallerFp(); 519 *to_addr = deopt_context->GetCallerFp();
568 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
569 *to_addr = from;
570 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr)); 520 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr));
571 } 521 }
572 522
573 private: 523 private:
574 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); 524 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr);
575 }; 525 };
576 526
577 527
578 // Deoptimization instruction copying the caller return address from optimized 528 // Deoptimization instruction copying the caller return address from optimized
579 // frame. 529 // frame.
580 class DeoptCallerPcInstr : public DeoptInstr { 530 class DeoptCallerPcInstr : public DeoptInstr {
581 public: 531 public:
582 DeoptCallerPcInstr() {} 532 DeoptCallerPcInstr() {}
583 533
584 virtual intptr_t from_index() const { return 0; } 534 virtual intptr_t from_index() const { return 0; }
585 virtual DeoptInstr::Kind kind() const { return kCallerPc; } 535 virtual DeoptInstr::Kind kind() const { return kCallerPc; }
586 536
587 virtual const char* ToCString() const { 537 virtual const char* ToCString() const {
588 return "callerpc"; 538 return "callerpc";
589 } 539 }
590 540
591 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 541 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
592 intptr_t from = deopt_context->GetFromPc(); 542 *to_addr = deopt_context->GetFromPc();
593 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
594 *to_addr = from;
595 } 543 }
596 544
597 private: 545 private:
598 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); 546 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr);
599 }; 547 };
600 548
601 549
602 // Deoptimization instruction that indicates the rest of this DeoptInfo is a 550 // Deoptimization instruction that indicates the rest of this DeoptInfo is a
603 // suffix of another one. The suffix contains the info number (0 based 551 // suffix of another one. The suffix contains the info number (0 based
604 // index in the deopt table of the DeoptInfo to share) and the length of the 552 // index in the deopt table of the DeoptInfo to share) and the length of the
(...skipping 11 matching lines...) Expand all
616 suffix_length_(SuffixLength::decode(from_index)) { 564 suffix_length_(SuffixLength::decode(from_index)) {
617 } 565 }
618 566
619 virtual intptr_t from_index() const { 567 virtual intptr_t from_index() const {
620 return InfoNumber::encode(info_number_) | 568 return InfoNumber::encode(info_number_) |
621 SuffixLength::encode(suffix_length_); 569 SuffixLength::encode(suffix_length_);
622 } 570 }
623 virtual DeoptInstr::Kind kind() const { return kSuffix; } 571 virtual DeoptInstr::Kind kind() const { return kSuffix; }
624 572
625 virtual const char* ToCString() const { 573 virtual const char* ToCString() const {
626 const char* format = "suffix %"Pd":%"Pd; 574 return Isolate::Current()->current_zone()->PrintToString(
627 intptr_t len = OS::SNPrint(NULL, 0, format, info_number_, suffix_length_); 575 "suffix %"Pd":%"Pd, info_number_, suffix_length_);
628 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
629 OS::SNPrint(chars, len + 1, format, info_number_, suffix_length_);
630 return chars;
631 } 576 }
632 577
633 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 578 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
634 // The deoptimization info is uncompressed by translating away suffixes 579 // The deoptimization info is uncompressed by translating away suffixes
635 // before executing the instructions. 580 // before executing the instructions.
636 UNREACHABLE(); 581 UNREACHABLE();
637 } 582 }
638 583
639 private: 584 private:
640 // Static decoder functions in DeoptInstr have access to the bitfield 585 // Static decoder functions in DeoptInstr have access to the bitfield
641 // definitions. 586 // definitions.
642 friend class DeoptInstr; 587 friend class DeoptInstr;
643 588
644 static const intptr_t kFieldWidth = kBitsPerWord / 2; 589 static const intptr_t kFieldWidth = kBitsPerWord / 2;
645 class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { }; 590 class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { };
646 class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; 591 class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
647 592
648 const intptr_t info_number_; 593 const intptr_t info_number_;
649 const intptr_t suffix_length_; 594 const intptr_t suffix_length_;
650 595
651 DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr); 596 DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr);
652 }; 597 };
653 598
654 599
600 // Write reference to a materialized object with the given index into the
601 // stack slot.
602 class DeoptMaterializedObjectRefInstr : public DeoptInstr {
603 public:
604 explicit DeoptMaterializedObjectRefInstr(intptr_t index)
605 : index_(index) {
606 ASSERT(index >= 0);
607 }
608
609 virtual intptr_t from_index() const { return index_; }
610 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; }
611
612 virtual const char* ToCString() const {
613 return Isolate::Current()->current_zone()->PrintToString(
614 "mat ref #%"Pd"", index_);
615 }
616
617 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
618 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
619 Isolate::Current()->DeferMaterializedObjectRef(
620 index_, to_addr);
621 }
622
623 private:
624 intptr_t index_;
625
626 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr);
627 };
628
629
630 // Materialize object with the given number of fields.
631 // Arguments for materialization (class and field-value pairs) are pushed
632 // to the expression stack of the bottom-most frame.
633 class DeoptMaterializeObjectInstr : public DeoptInstr {
634 public:
635 explicit DeoptMaterializeObjectInstr(intptr_t field_count)
636 : field_count_(field_count) {
637 ASSERT(field_count >= 0);
638 }
639
640 virtual intptr_t from_index() const { return field_count_; }
641 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; }
642
643 virtual const char* ToCString() const {
644 return Isolate::Current()->current_zone()->PrintToString(
645 "mat obj len:%"Pd"", field_count_);
646 }
647
648 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
649 // This instructions are executed manually by the DeoptimizeWithDeoptInfo.
650 UNREACHABLE();
651 }
652
653 private:
654 intptr_t field_count_;
655
656 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr);
657 };
658
659
655 intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) { 660 intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) {
656 *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index); 661 *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index);
657 return DeoptSuffixInstr::SuffixLength::decode(from_index); 662 return DeoptSuffixInstr::SuffixLength::decode(from_index);
658 } 663 }
659 664
660 665
661 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, 666 uword DeoptInstr::GetRetAddress(DeoptInstr* instr,
662 const Array& object_table, 667 const Array& object_table,
663 Function* func) { 668 Function* func) {
664 ASSERT(instr->kind() == kRetAddress); 669 ASSERT(instr->kind() == kRetAddress);
(...skipping 28 matching lines...) Expand all
693 case kFpuRegister: return new DeoptFpuRegisterInstr(from_index); 698 case kFpuRegister: return new DeoptFpuRegisterInstr(from_index);
694 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(from_index); 699 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(from_index);
695 case kFloat32x4FpuRegister: 700 case kFloat32x4FpuRegister:
696 return new DeoptFloat32x4FpuRegisterInstr(from_index); 701 return new DeoptFloat32x4FpuRegisterInstr(from_index);
697 case kUint32x4FpuRegister: 702 case kUint32x4FpuRegister:
698 return new DeoptUint32x4FpuRegisterInstr(from_index); 703 return new DeoptUint32x4FpuRegisterInstr(from_index);
699 case kPcMarker: return new DeoptPcMarkerInstr(from_index); 704 case kPcMarker: return new DeoptPcMarkerInstr(from_index);
700 case kCallerFp: return new DeoptCallerFpInstr(); 705 case kCallerFp: return new DeoptCallerFpInstr();
701 case kCallerPc: return new DeoptCallerPcInstr(); 706 case kCallerPc: return new DeoptCallerPcInstr();
702 case kSuffix: return new DeoptSuffixInstr(from_index); 707 case kSuffix: return new DeoptSuffixInstr(from_index);
708 case kMaterializedObjectRef:
709 return new DeoptMaterializedObjectRefInstr(from_index);
710 case kMaterializeObject: return new DeoptMaterializeObjectInstr(from_index);
703 } 711 }
704 UNREACHABLE(); 712 UNREACHABLE();
705 return NULL; 713 return NULL;
706 } 714 }
707 715
708 716
709 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { 717 class DeoptInfoBuilder::TrieNode : public ZoneAllocated {
710 public: 718 public:
711 // Construct the root node representing the implicit "shared" terminator 719 // Construct the root node representing the implicit "shared" terminator
712 // at the end of each deopt info. 720 // at the end of each deopt info.
(...skipping 23 matching lines...) Expand all
736 744
737 GrowableArray<TrieNode*> children_; 745 GrowableArray<TrieNode*> children_;
738 }; 746 };
739 747
740 748
741 DeoptInfoBuilder::DeoptInfoBuilder(const intptr_t num_args) 749 DeoptInfoBuilder::DeoptInfoBuilder(const intptr_t num_args)
742 : instructions_(), 750 : instructions_(),
743 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())), 751 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
744 num_args_(num_args), 752 num_args_(num_args),
745 trie_root_(new TrieNode()), 753 trie_root_(new TrieNode()),
746 current_info_number_(0) { 754 current_info_number_(0),
755 frame_start_(-1),
756 materializations_() {
747 } 757 }
748 758
749 759
750 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { 760 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const {
751 for (intptr_t i = 0; i < object_table_.Length(); i++) { 761 for (intptr_t i = 0; i < object_table_.Length(); i++) {
752 if (object_table_.At(i) == obj.raw()) { 762 if (object_table_.At(i) == obj.raw()) {
753 return i; 763 return i;
754 } 764 }
755 } 765 }
756 // Add object. 766 // Add object.
(...skipping 14 matching lines...) Expand all
771 intptr_t deopt_id, 781 intptr_t deopt_id,
772 intptr_t to_index) { 782 intptr_t to_index) {
773 // Check that deopt_id exists. 783 // Check that deopt_id exists.
774 // TODO(vegorov): verify after deoptimization targets as well. 784 // TODO(vegorov): verify after deoptimization targets as well.
775 #ifdef DEBUG 785 #ifdef DEBUG
776 const Code& code = Code::Handle(function.unoptimized_code()); 786 const Code& code = Code::Handle(function.unoptimized_code());
777 ASSERT(Isolate::IsDeoptAfter(deopt_id) || 787 ASSERT(Isolate::IsDeoptAfter(deopt_id) ||
778 (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0)); 788 (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0));
779 #endif 789 #endif
780 const intptr_t object_table_index = FindOrAddObjectInTable(function); 790 const intptr_t object_table_index = FindOrAddObjectInTable(function);
781 ASSERT(to_index == instructions_.length()); 791 ASSERT(to_index == FrameSize());
782 instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id)); 792 instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id));
783 } 793 }
784 794
785 795
786 void DeoptInfoBuilder::AddPcMarker(const Function& function, 796 void DeoptInfoBuilder::AddPcMarker(const Function& function,
787 intptr_t to_index) { 797 intptr_t to_index) {
788 // Function object was already added by AddReturnAddress, find it. 798 // Function object was already added by AddReturnAddress, find it.
789 intptr_t from_index = FindOrAddObjectInTable(function); 799 intptr_t from_index = FindOrAddObjectInTable(function);
790 ASSERT(to_index == instructions_.length()); 800 ASSERT(to_index == FrameSize());
791 instructions_.Add(new DeoptPcMarkerInstr(from_index)); 801 instructions_.Add(new DeoptPcMarkerInstr(from_index));
792 } 802 }
793 803
794 804
795 void DeoptInfoBuilder::AddCopy(Value* value, 805 void DeoptInfoBuilder::AddCopy(Value* value,
796 const Location& from_loc, 806 const Location& from_loc,
797 const intptr_t to_index) { 807 const intptr_t to_index) {
798 DeoptInstr* deopt_instr = NULL; 808 DeoptInstr* deopt_instr = NULL;
799 if (from_loc.IsConstant()) { 809 if (from_loc.IsConstant()) {
800 intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant()); 810 intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant());
(...skipping 25 matching lines...) Expand all
826 deopt_instr = new DeoptInt64StackSlotInstr(from_index); 836 deopt_instr = new DeoptInt64StackSlotInstr(from_index);
827 } 837 }
828 } else if (from_loc.IsQuadStackSlot()) { 838 } else if (from_loc.IsQuadStackSlot()) {
829 intptr_t from_index = CalculateStackIndex(from_loc); 839 intptr_t from_index = CalculateStackIndex(from_loc);
830 if (value->definition()->representation() == kUnboxedFloat32x4) { 840 if (value->definition()->representation() == kUnboxedFloat32x4) {
831 deopt_instr = new DeoptFloat32x4StackSlotInstr(from_index); 841 deopt_instr = new DeoptFloat32x4StackSlotInstr(from_index);
832 } else { 842 } else {
833 ASSERT(value->definition()->representation() == kUnboxedUint32x4); 843 ASSERT(value->definition()->representation() == kUnboxedUint32x4);
834 deopt_instr = new DeoptUint32x4StackSlotInstr(from_index); 844 deopt_instr = new DeoptUint32x4StackSlotInstr(from_index);
835 } 845 }
846 } else if (from_loc.IsInvalid() &&
847 value->definition()->IsMaterializeObject()) {
848 const intptr_t index = FindMaterialization(
849 value->definition()->AsMaterializeObject());
850 ASSERT(index >= 0);
851 deopt_instr = new DeoptMaterializedObjectRefInstr(index);
836 } else { 852 } else {
837 UNREACHABLE(); 853 UNREACHABLE();
838 } 854 }
839 ASSERT(to_index == instructions_.length()); 855 ASSERT(to_index == FrameSize());
840 ASSERT(deopt_instr != NULL); 856 ASSERT(deopt_instr != NULL);
841 instructions_.Add(deopt_instr); 857 instructions_.Add(deopt_instr);
842 } 858 }
843 859
844 860
845 void DeoptInfoBuilder::AddCallerFp(intptr_t to_index) { 861 void DeoptInfoBuilder::AddCallerFp(intptr_t to_index) {
846 ASSERT(to_index == instructions_.length()); 862 ASSERT(to_index == FrameSize());
847 instructions_.Add(new DeoptCallerFpInstr()); 863 instructions_.Add(new DeoptCallerFpInstr());
848 } 864 }
849 865
850 866
851 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) { 867 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) {
852 ASSERT(to_index == instructions_.length()); 868 ASSERT(to_index == FrameSize());
853 instructions_.Add(new DeoptCallerPcInstr()); 869 instructions_.Add(new DeoptCallerPcInstr());
854 } 870 }
855 871
856 872
873 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t to_index) {
874 ASSERT(to_index == FrameSize());
875 intptr_t object_table_index = FindOrAddObjectInTable(obj);
876 instructions_.Add(new DeoptConstantInstr(object_table_index));
877 }
878
879
880 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) {
881 const intptr_t index = FindMaterialization(mat);
882 if (index >= 0) {
883 return; // Already added.
884 }
885 materializations_.Add(mat);
886
887 // Count initialized fields and emit kMaterializeObject instruction.
888 // There is no need to write nulls into fields because object is null
889 // initialized by default.
890 intptr_t non_null_fields = 0;
891 for (intptr_t i = 0; i < mat->InputCount(); i++) {
892 if (!mat->InputAt(i)->BindsToConstantNull()) {
893 non_null_fields++;
894 }
895 }
896
897 instructions_.Add(new DeoptMaterializeObjectInstr(non_null_fields));
898 }
899
900
901 intptr_t DeoptInfoBuilder::EmitMaterializationArguments() {
902 intptr_t slot_idx = 1; // Return address is emitted at 0.
903 for (intptr_t i = 0; i < materializations_.length(); i++) {
904 MaterializeObjectInstr* mat = materializations_[i];
905 AddConstant(mat->cls(), slot_idx++); // Class of the instance to allocate.
906 for (intptr_t i = 0; i < mat->InputCount(); i++) {
907 if (!mat->InputAt(i)->BindsToConstantNull()) {
908 // Emit field-value pair.
909 AddConstant(mat->FieldAt(i), slot_idx++);
910 AddCopy(mat->InputAt(i), mat->LocationAt(i), slot_idx++);
911 }
912 }
913 }
914 return slot_idx;
915 }
916
917
918 intptr_t DeoptInfoBuilder::FindMaterialization(
919 MaterializeObjectInstr* mat) const {
920 for (intptr_t i = 0; i < materializations_.length(); i++) {
921 if (materializations_[i] == mat) {
922 return i;
923 }
924 }
925 return -1;
926 }
927
928
857 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() { 929 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() {
930 // TODO(vegorov): enable compression of deoptimization info containing object
931 // materialization instructions.
932 const bool disable_compression =
933 (instructions_[0]->kind() == DeoptInstr::kMaterializeObject);
934
858 intptr_t length = instructions_.length(); 935 intptr_t length = instructions_.length();
859 936
860 // Count the number of instructions that are a shared suffix of some deopt 937 // Count the number of instructions that are a shared suffix of some deopt
861 // info already written. 938 // info already written.
862 TrieNode* suffix = trie_root_; 939 TrieNode* suffix = trie_root_;
863 intptr_t suffix_length = 0; 940 intptr_t suffix_length = 0;
864 if (FLAG_compress_deopt_info) { 941 if (FLAG_compress_deopt_info && !disable_compression) {
865 for (intptr_t i = length - 1; i >= 0; --i) { 942 for (intptr_t i = length - 1; i >= 0; --i) {
866 TrieNode* node = suffix->FindChild(*instructions_[i]); 943 TrieNode* node = suffix->FindChild(*instructions_[i]);
867 if (node == NULL) break; 944 if (node == NULL) break;
868 suffix = node; 945 suffix = node;
869 ++suffix_length; 946 ++suffix_length;
870 } 947 }
871 } 948 }
872 949
873 // Allocate space for the translation. If the shared suffix is longer 950 // Allocate space for the translation. If the shared suffix is longer
874 // than one instruction, we replace it with a single suffix instruction. 951 // than one instruction, we replace it with a single suffix instruction.
(...skipping 12 matching lines...) Expand all
887 } 964 }
888 suffix->AddChild(node); 965 suffix->AddChild(node);
889 966
890 if (suffix_length > 1) { 967 if (suffix_length > 1) {
891 DeoptInstr* instr = 968 DeoptInstr* instr =
892 new DeoptSuffixInstr(suffix->info_number(), suffix_length); 969 new DeoptSuffixInstr(suffix->info_number(), suffix_length);
893 deopt_info.SetAt(length - 1, instr->kind(), instr->from_index()); 970 deopt_info.SetAt(length - 1, instr->kind(), instr->from_index());
894 } 971 }
895 972
896 instructions_.Clear(); 973 instructions_.Clear();
974 materializations_.Clear();
975 frame_start_ = -1;
976
897 ++current_info_number_; 977 ++current_info_number_;
898 return deopt_info.raw(); 978 return deopt_info.raw();
899 } 979 }
900 980
901 981
902 intptr_t DeoptTable::SizeFor(intptr_t length) { 982 intptr_t DeoptTable::SizeFor(intptr_t length) {
903 return length * kEntrySize; 983 return length * kEntrySize;
904 } 984 }
905 985
906 void DeoptTable::SetEntry(const Array& table, 986 void DeoptTable::SetEntry(const Array& table,
(...skipping 20 matching lines...) Expand all
927 Smi* offset, 1007 Smi* offset,
928 DeoptInfo* info, 1008 DeoptInfo* info,
929 Smi* reason) { 1009 Smi* reason) {
930 intptr_t i = index * kEntrySize; 1010 intptr_t i = index * kEntrySize;
931 *offset ^= table.At(i); 1011 *offset ^= table.At(i);
932 *info ^= table.At(i + 1); 1012 *info ^= table.At(i + 1);
933 *reason ^= table.At(i + 2); 1013 *reason ^= table.At(i + 2);
934 } 1014 }
935 1015
936 } // namespace dart 1016 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/deopt_instructions.h ('k') | runtime/vm/flow_graph.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698