| 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 |