Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/object.h" | 5 #include "vm/object.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 2316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2327 // Prefinalized classes have a VM internal representation and no Dart fields. | 2327 // Prefinalized classes have a VM internal representation and no Dart fields. |
| 2328 // Their instance size is precomputed and field offsets are known. | 2328 // Their instance size is precomputed and field offsets are known. |
| 2329 if (!is_prefinalized()) { | 2329 if (!is_prefinalized()) { |
| 2330 // Compute offsets of instance fields and instance size. | 2330 // Compute offsets of instance fields and instance size. |
| 2331 CalculateFieldOffsets(); | 2331 CalculateFieldOffsets(); |
| 2332 } | 2332 } |
| 2333 set_is_finalized(); | 2333 set_is_finalized(); |
| 2334 } | 2334 } |
| 2335 | 2335 |
| 2336 | 2336 |
| 2337 // Helper class to handle an array of code weak properties. Implements | |
| 2338 // registration and disabling of stored code objects. | |
| 2339 class WeakCodeReferences : public ValueObject { | |
|
Florian Schneider
2014/02/05 10:36:31
This class and it's two subclasses seem good candi
srdjan
2014/02/05 16:20:51
Templates are hard to work with: harder on compile
Florian Schneider
2014/02/05 17:07:28
I don't really care that much - so land it either
| |
| 2340 public: | |
| 2341 explicit WeakCodeReferences(const Array& value) : array_(value) {} | |
|
Florian Schneider
2014/02/05 10:36:31
explicit WeakCodeReferences(const T& owner)
:
| |
| 2342 virtual ~WeakCodeReferences() {} | |
| 2343 | |
| 2344 void Register(const Code& value) { | |
| 2345 if (!array_.IsNull()) { | |
| 2346 // Try to find and reuse cleared WeakProperty to avoid allocating new one. | |
| 2347 WeakProperty& weak_property = WeakProperty::Handle(); | |
| 2348 for (intptr_t i = 0; i < array_.Length(); i++) { | |
| 2349 weak_property ^= array_.At(i); | |
| 2350 if (weak_property.key() == Code::null()) { | |
| 2351 // Empty property found. Reuse it. | |
| 2352 weak_property.set_key(value); | |
| 2353 return; | |
| 2354 } | |
| 2355 } | |
| 2356 } | |
| 2357 | |
| 2358 const WeakProperty& weak_property = WeakProperty::Handle( | |
| 2359 WeakProperty::New(Heap::kOld)); | |
| 2360 weak_property.set_key(value); | |
| 2361 | |
| 2362 intptr_t length = array_.IsNull() ? 0 : array_.Length(); | |
| 2363 const Array& new_array = Array::Handle( | |
| 2364 Array::Grow(array_, length + 1, Heap::kOld)); | |
| 2365 new_array.SetAt(length, weak_property); | |
| 2366 UpdateArrayTo(new_array); | |
| 2367 } | |
| 2368 | |
| 2369 virtual void UpdateArrayTo(const Array& array) = 0; | |
|
Florian Schneider
2014/02/05 10:36:31
void UpdateArrayTo(const Array& array) {
owner_.
| |
| 2370 virtual void ReportDeoptimization(const Code& code) = 0; | |
| 2371 virtual void ReportSwitchingCode(const Code& code) = 0; | |
| 2372 | |
| 2373 static bool IsOptimizedCode(const Array& dependent_code, const Code& code) { | |
|
Florian Schneider
2014/02/05 17:07:28
This checks for two things: the code is optimized
| |
| 2374 if (!code.is_optimized()) { | |
| 2375 return false; | |
| 2376 } | |
| 2377 WeakProperty& weak_property = WeakProperty::Handle(); | |
| 2378 for (intptr_t i = 0; i < dependent_code.Length(); i++) { | |
| 2379 weak_property ^= dependent_code.At(i); | |
| 2380 if (code.raw() == weak_property.key()) { | |
| 2381 return true; | |
| 2382 } | |
| 2383 } | |
| 2384 return false; | |
| 2385 } | |
| 2386 | |
| 2387 void DisableCode() { | |
| 2388 const Array& code_objects = Array::Handle(array_.raw()); | |
| 2389 if (code_objects.IsNull()) { | |
| 2390 return; | |
| 2391 } | |
| 2392 UpdateArrayTo(Object::null_array()); | |
| 2393 // Disable all code on stack. | |
| 2394 Code& code = Code::Handle(); | |
| 2395 { | |
| 2396 DartFrameIterator iterator; | |
| 2397 StackFrame* frame = iterator.NextFrame(); | |
| 2398 while (frame != NULL) { | |
| 2399 code = frame->LookupDartCode(); | |
| 2400 if (IsOptimizedCode(code_objects, code)) { | |
| 2401 ReportDeoptimization(code); | |
| 2402 DeoptimizeAt(code, frame->pc()); | |
| 2403 } | |
| 2404 frame = iterator.NextFrame(); | |
| 2405 } | |
| 2406 } | |
| 2407 | |
| 2408 // Switch functions that use dependent code to unoptimized code. | |
| 2409 WeakProperty& weak_property = WeakProperty::Handle(); | |
| 2410 Function& function = Function::Handle(); | |
| 2411 for (intptr_t i = 0; i < code_objects.Length(); i++) { | |
| 2412 weak_property ^= code_objects.At(i); | |
| 2413 code ^= weak_property.key(); | |
| 2414 if (code.IsNull()) { | |
| 2415 // Code was garbage collected already. | |
| 2416 continue; | |
| 2417 } | |
| 2418 | |
| 2419 function ^= code.function(); | |
| 2420 // If function uses dependent code switch it to unoptimized. | |
| 2421 if (function.CurrentCode() == code.raw()) { | |
| 2422 ASSERT(function.HasOptimizedCode()); | |
| 2423 ReportSwitchingCode(code); | |
| 2424 function.SwitchToUnoptimizedCode(); | |
| 2425 } | |
| 2426 } | |
| 2427 } | |
| 2428 | |
| 2429 private: | |
| 2430 const Array& array_; | |
|
Florian Schneider
2014/02/05 10:36:31
Replace array_ with owner_.dependent_code() in all
| |
| 2431 DISALLOW_COPY_AND_ASSIGN(WeakCodeReferences); | |
| 2432 }; | |
| 2433 | |
| 2434 | |
| 2435 class CHACodeArray : public WeakCodeReferences { | |
| 2436 public: | |
| 2437 explicit CHACodeArray(const Class& cls) | |
| 2438 : WeakCodeReferences(Array::Handle(cls.cha_codes())), cls_(cls) { | |
| 2439 } | |
| 2440 | |
| 2441 virtual void UpdateArrayTo(const Array& value) { | |
| 2442 cls_.set_cha_codes(value); | |
| 2443 } | |
| 2444 | |
| 2445 virtual void ReportDeoptimization(const Code& code) { | |
| 2446 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | |
| 2447 Function& function = Function::Handle(code.function()); | |
| 2448 OS::PrintErr("Deoptimizing %s because CHA optimized (%s).\n", | |
| 2449 function.ToFullyQualifiedCString(), | |
| 2450 cls_.ToCString()); | |
| 2451 } | |
| 2452 } | |
| 2453 | |
| 2454 virtual void ReportSwitchingCode(const Code& code) { | |
| 2455 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | |
| 2456 Function& function = Function::Handle(code.function()); | |
| 2457 OS::PrintErr("Switching %s to unoptimized code because CHA invalid" | |
| 2458 " (%s)\n", | |
| 2459 function.ToFullyQualifiedCString(), | |
| 2460 cls_.ToCString()); | |
| 2461 } | |
| 2462 } | |
| 2463 | |
| 2464 private: | |
| 2465 const Class& cls_; | |
| 2466 DISALLOW_COPY_AND_ASSIGN(CHACodeArray); | |
| 2467 }; | |
| 2468 | |
| 2469 | |
| 2470 void Class::RegisterCHACode(const Code& code) { | |
| 2471 ASSERT(code.is_optimized()); | |
| 2472 CHACodeArray a(*this); | |
| 2473 a.Register(code); | |
| 2474 } | |
| 2475 | |
| 2476 | |
| 2477 void Class::DisableCHAOptimizedCode() { | |
| 2478 CHACodeArray a(*this); | |
|
Florian Schneider
2014/02/05 10:36:31
WeakCodeReferences<Class> a(*this);
| |
| 2479 a.DisableCode(); | |
| 2480 } | |
| 2481 | |
| 2482 | |
| 2483 void Class::set_cha_codes(const Array& cache) const { | |
|
Florian Schneider
2014/02/05 10:36:31
s/set_cha_codes/set_dependent_code_/g
s/cha_codes
srdjan
2014/02/05 16:20:51
Yes they would have 'compatible' interface but tha
Florian Schneider
2014/02/05 17:07:28
Imo, fragile would imply that something bad could
| |
| 2484 StorePointer(&raw_ptr()->cha_codes_, cache.raw()); | |
| 2485 } | |
| 2486 | |
| 2487 | |
| 2337 // Apply the members from the patch class to the original class. | 2488 // Apply the members from the patch class to the original class. |
| 2338 bool Class::ApplyPatch(const Class& patch, Error* error) const { | 2489 bool Class::ApplyPatch(const Class& patch, Error* error) const { |
| 2339 ASSERT(error != NULL); | 2490 ASSERT(error != NULL); |
| 2340 ASSERT(!is_finalized()); | 2491 ASSERT(!is_finalized()); |
| 2341 // Shared handles used during the iteration. | 2492 // Shared handles used during the iteration. |
| 2342 String& member_name = String::Handle(); | 2493 String& member_name = String::Handle(); |
| 2343 | 2494 |
| 2344 const PatchClass& patch_class = | 2495 const PatchClass& patch_class = |
| 2345 PatchClass::Handle(PatchClass::New(*this, patch)); | 2496 PatchClass::Handle(PatchClass::New(*this, patch)); |
| 2346 | 2497 |
| (...skipping 4039 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6386 } | 6537 } |
| 6387 } | 6538 } |
| 6388 | 6539 |
| 6389 | 6540 |
| 6390 RawArray* Field::dependent_code() const { | 6541 RawArray* Field::dependent_code() const { |
| 6391 return raw_ptr()->dependent_code_; | 6542 return raw_ptr()->dependent_code_; |
| 6392 } | 6543 } |
| 6393 | 6544 |
| 6394 | 6545 |
| 6395 void Field::set_dependent_code(const Array& array) const { | 6546 void Field::set_dependent_code(const Array& array) const { |
| 6396 raw_ptr()->dependent_code_ = array.raw(); | 6547 StorePointer(&raw_ptr()->dependent_code_, array.raw()); |
| 6397 } | 6548 } |
| 6398 | 6549 |
| 6399 | 6550 |
| 6400 void Field::RegisterDependentCode(const Code& code) const { | 6551 class FieldDependentArray : public WeakCodeReferences { |
| 6401 const Array& dependent = Array::Handle(dependent_code()); | 6552 public: |
| 6553 explicit FieldDependentArray(const Field& field) | |
| 6554 : WeakCodeReferences(Array::Handle(field.dependent_code())), | |
| 6555 field_(field) {} | |
| 6402 | 6556 |
| 6403 if (!dependent.IsNull()) { | 6557 virtual void UpdateArrayTo(const Array& value) { |
| 6404 // Try to find and reuse cleared WeakProperty to avoid allocating new one. | 6558 field_.set_dependent_code(value); |
| 6405 WeakProperty& weak_property = WeakProperty::Handle(); | 6559 } |
| 6406 for (intptr_t i = 0; i < dependent.Length(); i++) { | 6560 |
| 6407 weak_property ^= dependent.At(i); | 6561 virtual void ReportDeoptimization(const Code& code) { |
| 6408 if (weak_property.key() == Code::null()) { | 6562 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| 6409 // Empty property found. Reuse it. | 6563 Function& function = Function::Handle(code.function()); |
| 6410 weak_property.set_key(code); | 6564 OS::PrintErr("Deoptimizing %s because guard on field %s failed.\n", |
| 6411 return; | 6565 function.ToFullyQualifiedCString(), |
| 6412 } | 6566 field_.ToCString()); |
| 6413 } | 6567 } |
| 6414 } | 6568 } |
| 6415 | 6569 |
| 6416 const WeakProperty& weak_property = WeakProperty::Handle( | 6570 virtual void ReportSwitchingCode(const Code& code) { |
| 6417 WeakProperty::New(Heap::kOld)); | 6571 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| 6418 weak_property.set_key(code); | 6572 Function& function = Function::Handle(code.function()); |
| 6419 | 6573 OS::PrintErr("Switching %s to unoptimized code because guard" |
| 6420 intptr_t length = dependent.IsNull() ? 0 : dependent.Length(); | 6574 " on field %s was violated.\n", |
| 6421 const Array& new_dependent = Array::Handle( | 6575 function.ToFullyQualifiedCString(), |
| 6422 Array::Grow(dependent, length + 1, Heap::kOld)); | 6576 field_.ToCString()); |
| 6423 new_dependent.SetAt(length, weak_property); | |
| 6424 set_dependent_code(new_dependent); | |
| 6425 } | |
| 6426 | |
| 6427 | |
| 6428 static bool IsDependentCode(const Array& dependent_code, const Code& code) { | |
| 6429 if (!code.is_optimized()) { | |
| 6430 return false; | |
| 6431 } | |
| 6432 | |
| 6433 WeakProperty& weak_property = WeakProperty::Handle(); | |
| 6434 for (intptr_t i = 0; i < dependent_code.Length(); i++) { | |
| 6435 weak_property ^= dependent_code.At(i); | |
| 6436 if (code.raw() == weak_property.key()) { | |
| 6437 return true; | |
| 6438 } | 6577 } |
| 6439 } | 6578 } |
| 6440 | 6579 |
| 6441 return false; | 6580 private: |
| 6581 const Field& field_; | |
| 6582 DISALLOW_COPY_AND_ASSIGN(FieldDependentArray); | |
| 6583 }; | |
| 6584 | |
| 6585 | |
| 6586 void Field::RegisterDependentCode(const Code& code) const { | |
| 6587 ASSERT(code.is_optimized()); | |
| 6588 FieldDependentArray a(*this); | |
| 6589 a.Register(code); | |
| 6442 } | 6590 } |
| 6443 | 6591 |
| 6444 | 6592 |
| 6445 void Field::DeoptimizeDependentCode() const { | 6593 void Field::DeoptimizeDependentCode() const { |
| 6446 const Array& code_objects = Array::Handle(dependent_code()); | 6594 FieldDependentArray a(*this); |
|
Florian Schneider
2014/02/05 10:36:31
WeakCodeReferences<Field> a(*this);
| |
| 6447 | 6595 a.DisableCode(); |
| 6448 if (code_objects.IsNull()) { | |
| 6449 return; | |
| 6450 } | |
| 6451 set_dependent_code(Object::null_array()); | |
| 6452 | |
| 6453 // Deoptimize all dependent code on the stack. | |
| 6454 Code& code = Code::Handle(); | |
| 6455 { | |
| 6456 DartFrameIterator iterator; | |
| 6457 StackFrame* frame = iterator.NextFrame(); | |
| 6458 while (frame != NULL) { | |
| 6459 code = frame->LookupDartCode(); | |
| 6460 if (IsDependentCode(code_objects, code)) { | |
| 6461 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | |
| 6462 Function& function = Function::Handle(code.function()); | |
| 6463 OS::PrintErr("Deoptimizing %s because guard on field %s failed.\n", | |
| 6464 function.ToFullyQualifiedCString(), | |
| 6465 ToCString()); | |
| 6466 } | |
| 6467 DeoptimizeAt(code, frame->pc()); | |
| 6468 } | |
| 6469 frame = iterator.NextFrame(); | |
| 6470 } | |
| 6471 } | |
| 6472 | |
| 6473 // Switch functions that use dependent code to unoptimized code. | |
| 6474 WeakProperty& weak_property = WeakProperty::Handle(); | |
| 6475 Function& function = Function::Handle(); | |
| 6476 for (intptr_t i = 0; i < code_objects.Length(); i++) { | |
| 6477 weak_property ^= code_objects.At(i); | |
| 6478 code ^= weak_property.key(); | |
| 6479 if (code.IsNull()) { | |
| 6480 // Code was garbage collected already. | |
| 6481 continue; | |
| 6482 } | |
| 6483 | |
| 6484 function ^= code.function(); | |
| 6485 // If function uses dependent code switch it to unoptimized. | |
| 6486 if (function.CurrentCode() == code.raw()) { | |
| 6487 ASSERT(function.HasOptimizedCode()); | |
| 6488 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | |
| 6489 OS::PrintErr("Switching %s to unoptimized code because guard" | |
| 6490 " on field %s was violated.\n", | |
| 6491 function.ToFullyQualifiedCString(), | |
| 6492 ToCString()); | |
| 6493 } | |
| 6494 function.SwitchToUnoptimizedCode(); | |
| 6495 } | |
| 6496 } | |
| 6497 } | 6596 } |
| 6498 | 6597 |
| 6499 | 6598 |
| 6500 bool Field::IsUninitialized() const { | 6599 bool Field::IsUninitialized() const { |
| 6501 const Instance& value = Instance::Handle(raw_ptr()->value_); | 6600 const Instance& value = Instance::Handle(raw_ptr()->value_); |
| 6502 ASSERT(value.raw() != Object::transition_sentinel().raw()); | 6601 ASSERT(value.raw() != Object::transition_sentinel().raw()); |
| 6503 return value.raw() == Object::sentinel().raw(); | 6602 return value.raw() == Object::sentinel().raw(); |
| 6504 } | 6603 } |
| 6505 | 6604 |
| 6506 | 6605 |
| (...skipping 10718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 17225 return "_MirrorReference"; | 17324 return "_MirrorReference"; |
| 17226 } | 17325 } |
| 17227 | 17326 |
| 17228 | 17327 |
| 17229 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { | 17328 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { |
| 17230 Instance::PrintToJSONStream(stream, ref); | 17329 Instance::PrintToJSONStream(stream, ref); |
| 17231 } | 17330 } |
| 17232 | 17331 |
| 17233 | 17332 |
| 17234 } // namespace dart | 17333 } // namespace dart |
| OLD | NEW |