Chromium Code Reviews| Index: runtime/vm/object.cc |
| =================================================================== |
| --- runtime/vm/object.cc (revision 32284) |
| +++ runtime/vm/object.cc (working copy) |
| @@ -2334,6 +2334,157 @@ |
| } |
| +// Helper class to handle an array of code weak properties. Implements |
| +// registration and disabling of stored code objects. |
| +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
|
| + public: |
| + explicit WeakCodeReferences(const Array& value) : array_(value) {} |
|
Florian Schneider
2014/02/05 10:36:31
explicit WeakCodeReferences(const T& owner)
:
|
| + virtual ~WeakCodeReferences() {} |
| + |
| + void Register(const Code& value) { |
| + if (!array_.IsNull()) { |
| + // Try to find and reuse cleared WeakProperty to avoid allocating new one. |
| + WeakProperty& weak_property = WeakProperty::Handle(); |
| + for (intptr_t i = 0; i < array_.Length(); i++) { |
| + weak_property ^= array_.At(i); |
| + if (weak_property.key() == Code::null()) { |
| + // Empty property found. Reuse it. |
| + weak_property.set_key(value); |
| + return; |
| + } |
| + } |
| + } |
| + |
| + const WeakProperty& weak_property = WeakProperty::Handle( |
| + WeakProperty::New(Heap::kOld)); |
| + weak_property.set_key(value); |
| + |
| + intptr_t length = array_.IsNull() ? 0 : array_.Length(); |
| + const Array& new_array = Array::Handle( |
| + Array::Grow(array_, length + 1, Heap::kOld)); |
| + new_array.SetAt(length, weak_property); |
| + UpdateArrayTo(new_array); |
| + } |
| + |
| + virtual void UpdateArrayTo(const Array& array) = 0; |
|
Florian Schneider
2014/02/05 10:36:31
void UpdateArrayTo(const Array& array) {
owner_.
|
| + virtual void ReportDeoptimization(const Code& code) = 0; |
| + virtual void ReportSwitchingCode(const Code& code) = 0; |
| + |
| + 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
|
| + if (!code.is_optimized()) { |
| + return false; |
| + } |
| + WeakProperty& weak_property = WeakProperty::Handle(); |
| + for (intptr_t i = 0; i < dependent_code.Length(); i++) { |
| + weak_property ^= dependent_code.At(i); |
| + if (code.raw() == weak_property.key()) { |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + void DisableCode() { |
| + const Array& code_objects = Array::Handle(array_.raw()); |
| + if (code_objects.IsNull()) { |
| + return; |
| + } |
| + UpdateArrayTo(Object::null_array()); |
| + // Disable all code on stack. |
| + Code& code = Code::Handle(); |
| + { |
| + DartFrameIterator iterator; |
| + StackFrame* frame = iterator.NextFrame(); |
| + while (frame != NULL) { |
| + code = frame->LookupDartCode(); |
| + if (IsOptimizedCode(code_objects, code)) { |
| + ReportDeoptimization(code); |
| + DeoptimizeAt(code, frame->pc()); |
| + } |
| + frame = iterator.NextFrame(); |
| + } |
| + } |
| + |
| + // Switch functions that use dependent code to unoptimized code. |
| + WeakProperty& weak_property = WeakProperty::Handle(); |
| + Function& function = Function::Handle(); |
| + for (intptr_t i = 0; i < code_objects.Length(); i++) { |
| + weak_property ^= code_objects.At(i); |
| + code ^= weak_property.key(); |
| + if (code.IsNull()) { |
| + // Code was garbage collected already. |
| + continue; |
| + } |
| + |
| + function ^= code.function(); |
| + // If function uses dependent code switch it to unoptimized. |
| + if (function.CurrentCode() == code.raw()) { |
| + ASSERT(function.HasOptimizedCode()); |
| + ReportSwitchingCode(code); |
| + function.SwitchToUnoptimizedCode(); |
| + } |
| + } |
| + } |
| + |
| + private: |
| + const Array& array_; |
|
Florian Schneider
2014/02/05 10:36:31
Replace array_ with owner_.dependent_code() in all
|
| + DISALLOW_COPY_AND_ASSIGN(WeakCodeReferences); |
| +}; |
| + |
| + |
| +class CHACodeArray : public WeakCodeReferences { |
| + public: |
| + explicit CHACodeArray(const Class& cls) |
| + : WeakCodeReferences(Array::Handle(cls.cha_codes())), cls_(cls) { |
| + } |
| + |
| + virtual void UpdateArrayTo(const Array& value) { |
| + cls_.set_cha_codes(value); |
| + } |
| + |
| + virtual void ReportDeoptimization(const Code& code) { |
| + if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| + Function& function = Function::Handle(code.function()); |
| + OS::PrintErr("Deoptimizing %s because CHA optimized (%s).\n", |
| + function.ToFullyQualifiedCString(), |
| + cls_.ToCString()); |
| + } |
| + } |
| + |
| + virtual void ReportSwitchingCode(const Code& code) { |
| + if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| + Function& function = Function::Handle(code.function()); |
| + OS::PrintErr("Switching %s to unoptimized code because CHA invalid" |
| + " (%s)\n", |
| + function.ToFullyQualifiedCString(), |
| + cls_.ToCString()); |
| + } |
| + } |
| + |
| + private: |
| + const Class& cls_; |
| + DISALLOW_COPY_AND_ASSIGN(CHACodeArray); |
| +}; |
| + |
| + |
| +void Class::RegisterCHACode(const Code& code) { |
| + ASSERT(code.is_optimized()); |
| + CHACodeArray a(*this); |
| + a.Register(code); |
| +} |
| + |
| + |
| +void Class::DisableCHAOptimizedCode() { |
| + CHACodeArray a(*this); |
|
Florian Schneider
2014/02/05 10:36:31
WeakCodeReferences<Class> a(*this);
|
| + a.DisableCode(); |
| +} |
| + |
| + |
| +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
|
| + StorePointer(&raw_ptr()->cha_codes_, cache.raw()); |
| +} |
| + |
| + |
| // Apply the members from the patch class to the original class. |
| bool Class::ApplyPatch(const Class& patch, Error* error) const { |
| ASSERT(error != NULL); |
| @@ -6393,107 +6544,55 @@ |
| void Field::set_dependent_code(const Array& array) const { |
| - raw_ptr()->dependent_code_ = array.raw(); |
| + StorePointer(&raw_ptr()->dependent_code_, array.raw()); |
| } |
| -void Field::RegisterDependentCode(const Code& code) const { |
| - const Array& dependent = Array::Handle(dependent_code()); |
| +class FieldDependentArray : public WeakCodeReferences { |
| + public: |
| + explicit FieldDependentArray(const Field& field) |
| + : WeakCodeReferences(Array::Handle(field.dependent_code())), |
| + field_(field) {} |
| - if (!dependent.IsNull()) { |
| - // Try to find and reuse cleared WeakProperty to avoid allocating new one. |
| - WeakProperty& weak_property = WeakProperty::Handle(); |
| - for (intptr_t i = 0; i < dependent.Length(); i++) { |
| - weak_property ^= dependent.At(i); |
| - if (weak_property.key() == Code::null()) { |
| - // Empty property found. Reuse it. |
| - weak_property.set_key(code); |
| - return; |
| - } |
| - } |
| + virtual void UpdateArrayTo(const Array& value) { |
| + field_.set_dependent_code(value); |
| } |
| - const WeakProperty& weak_property = WeakProperty::Handle( |
| - WeakProperty::New(Heap::kOld)); |
| - weak_property.set_key(code); |
| - |
| - intptr_t length = dependent.IsNull() ? 0 : dependent.Length(); |
| - const Array& new_dependent = Array::Handle( |
| - Array::Grow(dependent, length + 1, Heap::kOld)); |
| - new_dependent.SetAt(length, weak_property); |
| - set_dependent_code(new_dependent); |
| -} |
| - |
| - |
| -static bool IsDependentCode(const Array& dependent_code, const Code& code) { |
| - if (!code.is_optimized()) { |
| - return false; |
| + virtual void ReportDeoptimization(const Code& code) { |
| + if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| + Function& function = Function::Handle(code.function()); |
| + OS::PrintErr("Deoptimizing %s because guard on field %s failed.\n", |
| + function.ToFullyQualifiedCString(), |
| + field_.ToCString()); |
| + } |
| } |
| - WeakProperty& weak_property = WeakProperty::Handle(); |
| - for (intptr_t i = 0; i < dependent_code.Length(); i++) { |
| - weak_property ^= dependent_code.At(i); |
| - if (code.raw() == weak_property.key()) { |
| - return true; |
| + virtual void ReportSwitchingCode(const Code& code) { |
| + if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| + Function& function = Function::Handle(code.function()); |
| + OS::PrintErr("Switching %s to unoptimized code because guard" |
| + " on field %s was violated.\n", |
| + function.ToFullyQualifiedCString(), |
| + field_.ToCString()); |
| } |
| } |
| - return false; |
| + private: |
| + const Field& field_; |
| + DISALLOW_COPY_AND_ASSIGN(FieldDependentArray); |
| +}; |
| + |
| + |
| +void Field::RegisterDependentCode(const Code& code) const { |
| + ASSERT(code.is_optimized()); |
| + FieldDependentArray a(*this); |
| + a.Register(code); |
| } |
| void Field::DeoptimizeDependentCode() const { |
| - const Array& code_objects = Array::Handle(dependent_code()); |
| - |
| - if (code_objects.IsNull()) { |
| - return; |
| - } |
| - set_dependent_code(Object::null_array()); |
| - |
| - // Deoptimize all dependent code on the stack. |
| - Code& code = Code::Handle(); |
| - { |
| - DartFrameIterator iterator; |
| - StackFrame* frame = iterator.NextFrame(); |
| - while (frame != NULL) { |
| - code = frame->LookupDartCode(); |
| - if (IsDependentCode(code_objects, code)) { |
| - if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| - Function& function = Function::Handle(code.function()); |
| - OS::PrintErr("Deoptimizing %s because guard on field %s failed.\n", |
| - function.ToFullyQualifiedCString(), |
| - ToCString()); |
| - } |
| - DeoptimizeAt(code, frame->pc()); |
| - } |
| - frame = iterator.NextFrame(); |
| - } |
| - } |
| - |
| - // Switch functions that use dependent code to unoptimized code. |
| - WeakProperty& weak_property = WeakProperty::Handle(); |
| - Function& function = Function::Handle(); |
| - for (intptr_t i = 0; i < code_objects.Length(); i++) { |
| - weak_property ^= code_objects.At(i); |
| - code ^= weak_property.key(); |
| - if (code.IsNull()) { |
| - // Code was garbage collected already. |
| - continue; |
| - } |
| - |
| - function ^= code.function(); |
| - // If function uses dependent code switch it to unoptimized. |
| - if (function.CurrentCode() == code.raw()) { |
| - ASSERT(function.HasOptimizedCode()); |
| - if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| - OS::PrintErr("Switching %s to unoptimized code because guard" |
| - " on field %s was violated.\n", |
| - function.ToFullyQualifiedCString(), |
| - ToCString()); |
| - } |
| - function.SwitchToUnoptimizedCode(); |
| - } |
| - } |
| + FieldDependentArray a(*this); |
|
Florian Schneider
2014/02/05 10:36:31
WeakCodeReferences<Field> a(*this);
|
| + a.DisableCode(); |
| } |