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/deferred_objects.h" | 5 #include "vm/deferred_objects.h" |
6 | 6 |
7 #include "vm/code_patcher.h" | 7 #include "vm/code_patcher.h" |
8 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
9 #include "vm/deopt_instructions.h" | 9 #include "vm/deopt_instructions.h" |
10 #include "vm/flags.h" | 10 #include "vm/flags.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 } | 87 } |
88 | 88 |
89 | 89 |
90 void DeferredObjectRef::Materialize(DeoptContext* deopt_context) { | 90 void DeferredObjectRef::Materialize(DeoptContext* deopt_context) { |
91 DeferredObject* obj = deopt_context->GetDeferredObject(index()); | 91 DeferredObject* obj = deopt_context->GetDeferredObject(index()); |
92 *slot() = obj->object(); | 92 *slot() = obj->object(); |
93 if (FLAG_trace_deoptimization_verbose) { | 93 if (FLAG_trace_deoptimization_verbose) { |
94 const Class& cls = Class::Handle(Isolate::Current()->class_table()->At( | 94 const Class& cls = Class::Handle(Isolate::Current()->class_table()->At( |
95 Object::Handle(obj->object()).GetClassId())); | 95 Object::Handle(obj->object()).GetClassId())); |
96 OS::PrintErr("writing instance of class %s ref at %" Px ".\n", | 96 OS::PrintErr("writing instance of class %s ref at %" Px ".\n", |
97 cls.ToCString(), | 97 cls.ToCString(), reinterpret_cast<uword>(slot())); |
98 reinterpret_cast<uword>(slot())); | |
99 } | 98 } |
100 } | 99 } |
101 | 100 |
102 | 101 |
103 void DeferredRetAddr::Materialize(DeoptContext* deopt_context) { | 102 void DeferredRetAddr::Materialize(DeoptContext* deopt_context) { |
104 Thread* thread = deopt_context->thread(); | 103 Thread* thread = deopt_context->thread(); |
105 Zone* zone = deopt_context->zone(); | 104 Zone* zone = deopt_context->zone(); |
106 Function& function = Function::Handle(zone); | 105 Function& function = Function::Handle(zone); |
107 function ^= deopt_context->ObjectAt(index_); | 106 function ^= deopt_context->ObjectAt(index_); |
108 const Error& error = Error::Handle(zone, | 107 const Error& error = |
109 Compiler::EnsureUnoptimizedCode(thread, function)); | 108 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); |
110 if (!error.IsNull()) { | 109 if (!error.IsNull()) { |
111 Exceptions::PropagateError(error); | 110 Exceptions::PropagateError(error); |
112 } | 111 } |
113 const Code& code = Code::Handle(zone, function.unoptimized_code()); | 112 const Code& code = Code::Handle(zone, function.unoptimized_code()); |
114 // Check that deopt_id exists. | 113 // Check that deopt_id exists. |
115 // TODO(vegorov): verify after deoptimization targets as well. | 114 // TODO(vegorov): verify after deoptimization targets as well. |
116 #ifdef DEBUG | 115 #ifdef DEBUG |
117 ASSERT(Thread::IsDeoptAfter(deopt_id_) || | 116 ASSERT(Thread::IsDeoptAfter(deopt_id_) || |
118 (code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kDeopt) != 0)); | 117 (code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kDeopt) != 0)); |
119 #endif | 118 #endif |
120 | 119 |
121 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, | 120 uword continue_at_pc = |
122 RawPcDescriptors::kDeopt); | 121 code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kDeopt); |
123 ASSERT(continue_at_pc != 0); | 122 ASSERT(continue_at_pc != 0); |
124 uword* dest_addr = reinterpret_cast<uword*>(slot()); | 123 uword* dest_addr = reinterpret_cast<uword*>(slot()); |
125 *dest_addr = continue_at_pc; | 124 *dest_addr = continue_at_pc; |
126 | 125 |
127 if (FLAG_trace_deoptimization_verbose) { | 126 if (FLAG_trace_deoptimization_verbose) { |
128 OS::PrintErr("materializing return addr at 0x%" Px ": 0x%" Px "\n", | 127 OS::PrintErr("materializing return addr at 0x%" Px ": 0x%" Px "\n", |
129 reinterpret_cast<uword>(slot()), continue_at_pc); | 128 reinterpret_cast<uword>(slot()), continue_at_pc); |
130 } | 129 } |
131 | 130 |
132 uword pc = code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kIcCall); | 131 uword pc = code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kIcCall); |
(...skipping 22 matching lines...) Expand all Loading... |
155 } | 154 } |
156 | 155 |
157 | 156 |
158 void DeferredPcMarker::Materialize(DeoptContext* deopt_context) { | 157 void DeferredPcMarker::Materialize(DeoptContext* deopt_context) { |
159 Thread* thread = deopt_context->thread(); | 158 Thread* thread = deopt_context->thread(); |
160 Zone* zone = deopt_context->zone(); | 159 Zone* zone = deopt_context->zone(); |
161 uword* dest_addr = reinterpret_cast<uword*>(slot()); | 160 uword* dest_addr = reinterpret_cast<uword*>(slot()); |
162 Function& function = Function::Handle(zone); | 161 Function& function = Function::Handle(zone); |
163 function ^= deopt_context->ObjectAt(index_); | 162 function ^= deopt_context->ObjectAt(index_); |
164 ASSERT(!function.IsNull()); | 163 ASSERT(!function.IsNull()); |
165 const Error& error = Error::Handle(zone, | 164 const Error& error = |
166 Compiler::EnsureUnoptimizedCode(thread, function)); | 165 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); |
167 if (!error.IsNull()) { | 166 if (!error.IsNull()) { |
168 Exceptions::PropagateError(error); | 167 Exceptions::PropagateError(error); |
169 } | 168 } |
170 const Code& code = Code::Handle(zone, function.unoptimized_code()); | 169 const Code& code = Code::Handle(zone, function.unoptimized_code()); |
171 ASSERT(!code.IsNull()); | 170 ASSERT(!code.IsNull()); |
172 ASSERT(function.HasCode()); | 171 ASSERT(function.HasCode()); |
173 *reinterpret_cast<RawObject**>(dest_addr) = code.raw(); | 172 *reinterpret_cast<RawObject**>(dest_addr) = code.raw(); |
174 | 173 |
175 if (FLAG_trace_deoptimization_verbose) { | 174 if (FLAG_trace_deoptimization_verbose) { |
176 THR_Print("materializing pc marker at 0x%" Px ": %s, %s\n", | 175 THR_Print("materializing pc marker at 0x%" Px ": %s, %s\n", |
177 reinterpret_cast<uword>(slot()), code.ToCString(), | 176 reinterpret_cast<uword>(slot()), code.ToCString(), |
178 function.ToCString()); | 177 function.ToCString()); |
179 } | 178 } |
180 | 179 |
181 // Increment the deoptimization counter. This effectively increments each | 180 // Increment the deoptimization counter. This effectively increments each |
182 // function occurring in the optimized frame. | 181 // function occurring in the optimized frame. |
183 if (deopt_context->deoptimizing_code()) { | 182 if (deopt_context->deoptimizing_code()) { |
184 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 183 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
185 } | 184 } |
186 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 185 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
187 THR_Print("Deoptimizing '%s' (count %d)\n", | 186 THR_Print("Deoptimizing '%s' (count %d)\n", |
188 function.ToFullyQualifiedCString(), | 187 function.ToFullyQualifiedCString(), |
189 function.deoptimization_counter()); | 188 function.deoptimization_counter()); |
190 } | 189 } |
191 // Clear invocation counter so that hopefully the function gets reoptimized | 190 // Clear invocation counter so that hopefully the function gets reoptimized |
192 // only after more feedback has been collected. | 191 // only after more feedback has been collected. |
193 function.set_usage_counter(0); | 192 function.set_usage_counter(0); |
194 if (function.HasOptimizedCode()) { | 193 if (function.HasOptimizedCode()) { |
195 function.SwitchToUnoptimizedCode(); | 194 function.SwitchToUnoptimizedCode(); |
196 } | 195 } |
197 } | 196 } |
198 | 197 |
199 | 198 |
200 void DeferredPp::Materialize(DeoptContext* deopt_context) { | 199 void DeferredPp::Materialize(DeoptContext* deopt_context) { |
201 Thread* thread = deopt_context->thread(); | 200 Thread* thread = deopt_context->thread(); |
202 Zone* zone = deopt_context->zone(); | 201 Zone* zone = deopt_context->zone(); |
203 Function& function = Function::Handle(zone); | 202 Function& function = Function::Handle(zone); |
204 function ^= deopt_context->ObjectAt(index_); | 203 function ^= deopt_context->ObjectAt(index_); |
205 ASSERT(!function.IsNull()); | 204 ASSERT(!function.IsNull()); |
206 const Error& error = Error::Handle(zone, | 205 const Error& error = |
207 Compiler::EnsureUnoptimizedCode(thread, function)); | 206 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); |
208 if (!error.IsNull()) { | 207 if (!error.IsNull()) { |
209 Exceptions::PropagateError(error); | 208 Exceptions::PropagateError(error); |
210 } | 209 } |
211 const Code& code = Code::Handle(zone, function.unoptimized_code()); | 210 const Code& code = Code::Handle(zone, function.unoptimized_code()); |
212 ASSERT(!code.IsNull()); | 211 ASSERT(!code.IsNull()); |
213 ASSERT(code.GetObjectPool() != Object::null()); | 212 ASSERT(code.GetObjectPool() != Object::null()); |
214 *slot() = code.GetObjectPool(); | 213 *slot() = code.GetObjectPool(); |
215 | 214 |
216 if (FLAG_trace_deoptimization_verbose) { | 215 if (FLAG_trace_deoptimization_verbose) { |
217 OS::PrintErr("materializing pp at 0x%" Px ": 0x%" Px "\n", | 216 OS::PrintErr("materializing pp at 0x%" Px ": 0x%" Px "\n", |
(...skipping 15 matching lines...) Expand all Loading... |
233 if (object_ != NULL) { | 232 if (object_ != NULL) { |
234 return; | 233 return; |
235 } | 234 } |
236 | 235 |
237 Class& cls = Class::Handle(); | 236 Class& cls = Class::Handle(); |
238 cls ^= GetClass(); | 237 cls ^= GetClass(); |
239 | 238 |
240 if (cls.raw() == Object::context_class()) { | 239 if (cls.raw() == Object::context_class()) { |
241 intptr_t num_variables = Smi::Cast(Object::Handle(GetLength())).Value(); | 240 intptr_t num_variables = Smi::Cast(Object::Handle(GetLength())).Value(); |
242 if (FLAG_trace_deoptimization_verbose) { | 241 if (FLAG_trace_deoptimization_verbose) { |
243 OS::PrintErr( | 242 OS::PrintErr("materializing context of length %" Pd " (%" Px ", %" Pd |
244 "materializing context of length %" Pd " (%" Px ", %" Pd " vars)\n", | 243 " vars)\n", |
245 num_variables, | 244 num_variables, reinterpret_cast<uword>(args_), field_count_); |
246 reinterpret_cast<uword>(args_), | |
247 field_count_); | |
248 } | 245 } |
249 object_ = &Context::ZoneHandle(Context::New(num_variables)); | 246 object_ = &Context::ZoneHandle(Context::New(num_variables)); |
250 | 247 |
251 } else { | 248 } else { |
252 if (FLAG_trace_deoptimization_verbose) { | 249 if (FLAG_trace_deoptimization_verbose) { |
253 OS::PrintErr("materializing instance of %s (%" Px ", %" Pd " fields)\n", | 250 OS::PrintErr("materializing instance of %s (%" Px ", %" Pd " fields)\n", |
254 cls.ToCString(), | 251 cls.ToCString(), reinterpret_cast<uword>(args_), |
255 reinterpret_cast<uword>(args_), | |
256 field_count_); | 252 field_count_); |
257 } | 253 } |
258 | 254 |
259 object_ = &Instance::ZoneHandle(Instance::New(cls)); | 255 object_ = &Instance::ZoneHandle(Instance::New(cls)); |
260 } | 256 } |
261 } | 257 } |
262 | 258 |
263 | 259 |
264 static intptr_t ToContextIndex(intptr_t offset_in_bytes) { | 260 static intptr_t ToContextIndex(intptr_t offset_in_bytes) { |
265 intptr_t result = (offset_in_bytes - Context::variable_offset(0)) / kWordSize; | 261 intptr_t result = (offset_in_bytes - Context::variable_offset(0)) / kWordSize; |
(...skipping 16 matching lines...) Expand all Loading... |
282 | 278 |
283 for (intptr_t i = 0; i < field_count_; i++) { | 279 for (intptr_t i = 0; i < field_count_; i++) { |
284 offset ^= GetFieldOffset(i); | 280 offset ^= GetFieldOffset(i); |
285 if (offset.Value() == Context::parent_offset()) { | 281 if (offset.Value() == Context::parent_offset()) { |
286 // Copy parent. | 282 // Copy parent. |
287 Context& parent = Context::Handle(); | 283 Context& parent = Context::Handle(); |
288 parent ^= GetValue(i); | 284 parent ^= GetValue(i); |
289 context.set_parent(parent); | 285 context.set_parent(parent); |
290 if (FLAG_trace_deoptimization_verbose) { | 286 if (FLAG_trace_deoptimization_verbose) { |
291 OS::PrintErr(" ctx@parent (offset %" Pd ") <- %s\n", | 287 OS::PrintErr(" ctx@parent (offset %" Pd ") <- %s\n", |
292 offset.Value(), | 288 offset.Value(), value.ToCString()); |
293 value.ToCString()); | |
294 } | 289 } |
295 } else { | 290 } else { |
296 intptr_t context_index = ToContextIndex(offset.Value()); | 291 intptr_t context_index = ToContextIndex(offset.Value()); |
297 value = GetValue(i); | 292 value = GetValue(i); |
298 context.SetAt(context_index, value); | 293 context.SetAt(context_index, value); |
299 if (FLAG_trace_deoptimization_verbose) { | 294 if (FLAG_trace_deoptimization_verbose) { |
300 OS::PrintErr(" ctx@%" Pd " (offset %" Pd ") <- %s\n", | 295 OS::PrintErr(" ctx@%" Pd " (offset %" Pd ") <- %s\n", |
301 context_index, | 296 context_index, offset.Value(), value.ToCString()); |
302 offset.Value(), | |
303 value.ToCString()); | |
304 } | 297 } |
305 } | 298 } |
306 } | 299 } |
307 } else if (cls.id() == kClosureCid) { | 300 } else if (cls.id() == kClosureCid) { |
308 // TODO(regis): It would be better to programmatically add these fields to | 301 // TODO(regis): It would be better to programmatically add these fields to |
309 // the VM Closure class. Declaring them in the Dart class _Closure does not | 302 // the VM Closure class. Declaring them in the Dart class _Closure does not |
310 // work, because the class is prefinalized and CalculateFieldOffsets is | 303 // work, because the class is prefinalized and CalculateFieldOffsets is |
311 // therefore not called. Resetting the finalization state may be an option. | 304 // therefore not called. Resetting the finalization state may be an option. |
312 const Closure& closure = Closure::Cast(*object_); | 305 const Closure& closure = Closure::Cast(*object_); |
313 | 306 |
314 Smi& offset = Smi::Handle(); | 307 Smi& offset = Smi::Handle(); |
315 Object& value = Object::Handle(); | 308 Object& value = Object::Handle(); |
316 | 309 |
317 for (intptr_t i = 0; i < field_count_; i++) { | 310 for (intptr_t i = 0; i < field_count_; i++) { |
318 offset ^= GetFieldOffset(i); | 311 offset ^= GetFieldOffset(i); |
319 if (offset.Value() == Closure::type_arguments_offset()) { | 312 if (offset.Value() == Closure::type_arguments_offset()) { |
320 TypeArguments& arguments = TypeArguments::Handle(); | 313 TypeArguments& arguments = TypeArguments::Handle(); |
321 arguments ^= GetValue(i); | 314 arguments ^= GetValue(i); |
322 closure.SetTypeArguments(arguments); | 315 closure.SetTypeArguments(arguments); |
323 if (FLAG_trace_deoptimization_verbose) { | 316 if (FLAG_trace_deoptimization_verbose) { |
324 OS::PrintErr(" closure@type_arguments (offset %" Pd ") <- %s\n", | 317 OS::PrintErr(" closure@type_arguments (offset %" Pd ") <- %s\n", |
325 offset.Value(), | 318 offset.Value(), value.ToCString()); |
326 value.ToCString()); | |
327 } | 319 } |
328 } else if (offset.Value() == Closure::function_offset()) { | 320 } else if (offset.Value() == Closure::function_offset()) { |
329 Function& function = Function::Handle(); | 321 Function& function = Function::Handle(); |
330 function ^= GetValue(i); | 322 function ^= GetValue(i); |
331 closure.set_function(function); | 323 closure.set_function(function); |
332 if (FLAG_trace_deoptimization_verbose) { | 324 if (FLAG_trace_deoptimization_verbose) { |
333 OS::PrintErr(" closure@function (offset %" Pd ") <- %s\n", | 325 OS::PrintErr(" closure@function (offset %" Pd ") <- %s\n", |
334 offset.Value(), | 326 offset.Value(), value.ToCString()); |
335 value.ToCString()); | |
336 } | 327 } |
337 } else { | 328 } else { |
338 ASSERT(offset.Value() == Closure::context_offset()); | 329 ASSERT(offset.Value() == Closure::context_offset()); |
339 Context& context = Context::Handle(); | 330 Context& context = Context::Handle(); |
340 context ^= GetValue(i); | 331 context ^= GetValue(i); |
341 closure.set_context(context); | 332 closure.set_context(context); |
342 if (FLAG_trace_deoptimization_verbose) { | 333 if (FLAG_trace_deoptimization_verbose) { |
343 OS::PrintErr(" closure@context (offset %" Pd ") <- %s\n", | 334 OS::PrintErr(" closure@context (offset %" Pd ") <- %s\n", |
344 offset.Value(), | 335 offset.Value(), value.ToCString()); |
345 value.ToCString()); | |
346 } | 336 } |
347 } | 337 } |
348 } | 338 } |
349 } else { | 339 } else { |
350 const Instance& obj = Instance::Cast(*object_); | 340 const Instance& obj = Instance::Cast(*object_); |
351 | 341 |
352 Smi& offset = Smi::Handle(); | 342 Smi& offset = Smi::Handle(); |
353 Field& field = Field::Handle(); | 343 Field& field = Field::Handle(); |
354 Object& value = Object::Handle(); | 344 Object& value = Object::Handle(); |
355 const Array& offset_map = Array::Handle(cls.OffsetToFieldMap()); | 345 const Array& offset_map = Array::Handle(cls.OffsetToFieldMap()); |
356 | 346 |
357 for (intptr_t i = 0; i < field_count_; i++) { | 347 for (intptr_t i = 0; i < field_count_; i++) { |
358 offset ^= GetFieldOffset(i); | 348 offset ^= GetFieldOffset(i); |
359 field ^= offset_map.At(offset.Value() / kWordSize); | 349 field ^= offset_map.At(offset.Value() / kWordSize); |
360 value = GetValue(i); | 350 value = GetValue(i); |
361 if (!field.IsNull()) { | 351 if (!field.IsNull()) { |
362 obj.SetField(field, value); | 352 obj.SetField(field, value); |
363 if (FLAG_trace_deoptimization_verbose) { | 353 if (FLAG_trace_deoptimization_verbose) { |
364 OS::PrintErr(" %s <- %s\n", | 354 OS::PrintErr(" %s <- %s\n", |
365 String::Handle(field.name()).ToCString(), | 355 String::Handle(field.name()).ToCString(), |
366 value.ToCString()); | 356 value.ToCString()); |
367 } | 357 } |
368 } else { | 358 } else { |
369 ASSERT(offset.Value() == cls.type_arguments_field_offset()); | 359 ASSERT(offset.Value() == cls.type_arguments_field_offset()); |
370 obj.SetFieldAtOffset(offset.Value(), value); | 360 obj.SetFieldAtOffset(offset.Value(), value); |
371 if (FLAG_trace_deoptimization_verbose) { | 361 if (FLAG_trace_deoptimization_verbose) { |
372 OS::PrintErr(" null Field @ offset(%" Pd ") <- %s\n", | 362 OS::PrintErr(" null Field @ offset(%" Pd ") <- %s\n", |
373 offset.Value(), | 363 offset.Value(), value.ToCString()); |
374 value.ToCString()); | |
375 } | 364 } |
376 } | 365 } |
377 } | 366 } |
378 } | 367 } |
379 } | 368 } |
380 | 369 |
381 } // namespace dart | 370 } // namespace dart |
OLD | NEW |