| 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 26 matching lines...) Expand all Loading... |
| 37 #include "vm/parser.h" | 37 #include "vm/parser.h" |
| 38 #include "vm/report.h" | 38 #include "vm/report.h" |
| 39 #include "vm/reusable_handles.h" | 39 #include "vm/reusable_handles.h" |
| 40 #include "vm/runtime_entry.h" | 40 #include "vm/runtime_entry.h" |
| 41 #include "vm/scopes.h" | 41 #include "vm/scopes.h" |
| 42 #include "vm/stack_frame.h" | 42 #include "vm/stack_frame.h" |
| 43 #include "vm/symbols.h" | 43 #include "vm/symbols.h" |
| 44 #include "vm/tags.h" | 44 #include "vm/tags.h" |
| 45 #include "vm/timer.h" | 45 #include "vm/timer.h" |
| 46 #include "vm/unicode.h" | 46 #include "vm/unicode.h" |
| 47 #include "vm/weak_code.h" |
| 47 | 48 |
| 48 namespace dart { | 49 namespace dart { |
| 49 | 50 |
| 50 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, | 51 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, |
| 51 "Huge method cutoff in unoptimized code size (in bytes)."); | 52 "Huge method cutoff in unoptimized code size (in bytes)."); |
| 52 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, | 53 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, |
| 53 "Huge method cutoff in tokens: Disables optimizations for huge methods."); | 54 "Huge method cutoff in tokens: Disables optimizations for huge methods."); |
| 54 DEFINE_FLAG(bool, overlap_type_arguments, true, | 55 DEFINE_FLAG(bool, overlap_type_arguments, true, |
| 55 "When possible, partially or fully overlap the type arguments of a type " | 56 "When possible, partially or fully overlap the type arguments of a type " |
| 56 "with the type arguments of its super type."); | 57 "with the type arguments of its super type."); |
| (...skipping 2526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2583 // Prefinalized classes have a VM internal representation and no Dart fields. | 2584 // Prefinalized classes have a VM internal representation and no Dart fields. |
| 2584 // Their instance size is precomputed and field offsets are known. | 2585 // Their instance size is precomputed and field offsets are known. |
| 2585 if (!is_prefinalized()) { | 2586 if (!is_prefinalized()) { |
| 2586 // Compute offsets of instance fields and instance size. | 2587 // Compute offsets of instance fields and instance size. |
| 2587 CalculateFieldOffsets(); | 2588 CalculateFieldOffsets(); |
| 2588 } | 2589 } |
| 2589 set_is_finalized(); | 2590 set_is_finalized(); |
| 2590 } | 2591 } |
| 2591 | 2592 |
| 2592 | 2593 |
| 2593 // Helper class to handle an array of code weak properties. Implements | |
| 2594 // registration and disabling of stored code objects. | |
| 2595 class WeakCodeReferences : public ValueObject { | |
| 2596 public: | |
| 2597 explicit WeakCodeReferences(const Array& value) : array_(value) {} | |
| 2598 virtual ~WeakCodeReferences() {} | |
| 2599 | |
| 2600 void Register(const Code& value) { | |
| 2601 if (!array_.IsNull()) { | |
| 2602 // Try to find and reuse cleared WeakProperty to avoid allocating new one. | |
| 2603 WeakProperty& weak_property = WeakProperty::Handle(); | |
| 2604 for (intptr_t i = 0; i < array_.Length(); i++) { | |
| 2605 weak_property ^= array_.At(i); | |
| 2606 if (weak_property.key() == Code::null()) { | |
| 2607 // Empty property found. Reuse it. | |
| 2608 weak_property.set_key(value); | |
| 2609 return; | |
| 2610 } | |
| 2611 } | |
| 2612 } | |
| 2613 | |
| 2614 const WeakProperty& weak_property = WeakProperty::Handle( | |
| 2615 WeakProperty::New(Heap::kOld)); | |
| 2616 weak_property.set_key(value); | |
| 2617 | |
| 2618 intptr_t length = array_.IsNull() ? 0 : array_.Length(); | |
| 2619 const Array& new_array = Array::Handle( | |
| 2620 Array::Grow(array_, length + 1, Heap::kOld)); | |
| 2621 new_array.SetAt(length, weak_property); | |
| 2622 UpdateArrayTo(new_array); | |
| 2623 } | |
| 2624 | |
| 2625 virtual void UpdateArrayTo(const Array& array) = 0; | |
| 2626 virtual void ReportDeoptimization(const Code& code) = 0; | |
| 2627 virtual void ReportSwitchingCode(const Code& code) = 0; | |
| 2628 | |
| 2629 static bool IsOptimizedCode(const Array& dependent_code, const Code& code) { | |
| 2630 if (!code.is_optimized()) { | |
| 2631 return false; | |
| 2632 } | |
| 2633 WeakProperty& weak_property = WeakProperty::Handle(); | |
| 2634 for (intptr_t i = 0; i < dependent_code.Length(); i++) { | |
| 2635 weak_property ^= dependent_code.At(i); | |
| 2636 if (code.raw() == weak_property.key()) { | |
| 2637 return true; | |
| 2638 } | |
| 2639 } | |
| 2640 return false; | |
| 2641 } | |
| 2642 | |
| 2643 void DisableCode() { | |
| 2644 const Array& code_objects = Array::Handle(array_.raw()); | |
| 2645 if (code_objects.IsNull()) { | |
| 2646 return; | |
| 2647 } | |
| 2648 UpdateArrayTo(Object::null_array()); | |
| 2649 // Disable all code on stack. | |
| 2650 Code& code = Code::Handle(); | |
| 2651 { | |
| 2652 DartFrameIterator iterator; | |
| 2653 StackFrame* frame = iterator.NextFrame(); | |
| 2654 while (frame != NULL) { | |
| 2655 code = frame->LookupDartCode(); | |
| 2656 if (IsOptimizedCode(code_objects, code)) { | |
| 2657 ReportDeoptimization(code); | |
| 2658 DeoptimizeAt(code, frame->pc()); | |
| 2659 } | |
| 2660 frame = iterator.NextFrame(); | |
| 2661 } | |
| 2662 } | |
| 2663 | |
| 2664 // Switch functions that use dependent code to unoptimized code. | |
| 2665 WeakProperty& weak_property = WeakProperty::Handle(); | |
| 2666 Function& function = Function::Handle(); | |
| 2667 for (intptr_t i = 0; i < code_objects.Length(); i++) { | |
| 2668 weak_property ^= code_objects.At(i); | |
| 2669 code ^= weak_property.key(); | |
| 2670 if (code.IsNull()) { | |
| 2671 // Code was garbage collected already. | |
| 2672 continue; | |
| 2673 } | |
| 2674 | |
| 2675 function ^= code.function(); | |
| 2676 // If function uses dependent code switch it to unoptimized. | |
| 2677 if (code.is_optimized() && (function.CurrentCode() == code.raw())) { | |
| 2678 ReportSwitchingCode(code); | |
| 2679 function.SwitchToUnoptimizedCode(); | |
| 2680 } else if (function.unoptimized_code() == code.raw()) { | |
| 2681 ReportSwitchingCode(code); | |
| 2682 function.ClearICData(); | |
| 2683 // Remove the code object from the function. The next time the | |
| 2684 // function is invoked, it will be compiled again. | |
| 2685 function.ClearCode(); | |
| 2686 // Invalidate the old code object so existing references to it | |
| 2687 // (from optimized code) will fail when invoked. | |
| 2688 if (!CodePatcher::IsEntryPatched(code)) { | |
| 2689 CodePatcher::PatchEntry(code); | |
| 2690 } | |
| 2691 } else { | |
| 2692 // Make non-OSR code non-entrant. | |
| 2693 if (code.GetEntryPatchPc() != 0) { | |
| 2694 if (!CodePatcher::IsEntryPatched(code)) { | |
| 2695 ReportSwitchingCode(code); | |
| 2696 CodePatcher::PatchEntry(code); | |
| 2697 } | |
| 2698 } | |
| 2699 } | |
| 2700 } | |
| 2701 } | |
| 2702 | |
| 2703 private: | |
| 2704 const Array& array_; | |
| 2705 DISALLOW_COPY_AND_ASSIGN(WeakCodeReferences); | |
| 2706 }; | |
| 2707 | |
| 2708 | |
| 2709 class CHACodeArray : public WeakCodeReferences { | 2594 class CHACodeArray : public WeakCodeReferences { |
| 2710 public: | 2595 public: |
| 2711 explicit CHACodeArray(const Class& cls) | 2596 explicit CHACodeArray(const Class& cls) |
| 2712 : WeakCodeReferences(Array::Handle(cls.cha_codes())), cls_(cls) { | 2597 : WeakCodeReferences(Array::Handle(cls.cha_codes())), cls_(cls) { |
| 2713 } | 2598 } |
| 2714 | 2599 |
| 2715 virtual void UpdateArrayTo(const Array& value) { | 2600 virtual void UpdateArrayTo(const Array& value) { |
| 2716 // TODO(fschneider): Fails for classes in the VM isolate. | 2601 // TODO(fschneider): Fails for classes in the VM isolate. |
| 2717 cls_.set_cha_codes(value); | 2602 cls_.set_cha_codes(value); |
| 2718 } | 2603 } |
| (...skipping 17671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20390 return tag_label.ToCString(); | 20275 return tag_label.ToCString(); |
| 20391 } | 20276 } |
| 20392 | 20277 |
| 20393 | 20278 |
| 20394 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 20279 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
| 20395 Instance::PrintJSONImpl(stream, ref); | 20280 Instance::PrintJSONImpl(stream, ref); |
| 20396 } | 20281 } |
| 20397 | 20282 |
| 20398 | 20283 |
| 20399 } // namespace dart | 20284 } // namespace dart |
| OLD | NEW |