OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |