Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: runtime/vm/object.cc

Issue 12529008: Collect type feedback for fields. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address Ivan's comments Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/bigint_operations.h" 10 #include "vm/bigint_operations.h"
(...skipping 3209 matching lines...) Expand 10 before | Expand all | Expand 10 after
3220 void Function::SetCode(const Code& value) const { 3220 void Function::SetCode(const Code& value) const {
3221 StorePointer(&raw_ptr()->code_, value.raw()); 3221 StorePointer(&raw_ptr()->code_, value.raw());
3222 ASSERT(Function::Handle(value.function()).IsNull() || 3222 ASSERT(Function::Handle(value.function()).IsNull() ||
3223 (value.function() == this->raw())); 3223 (value.function() == this->raw()));
3224 value.set_function(*this); 3224 value.set_function(*this);
3225 } 3225 }
3226 3226
3227 3227
3228 void Function::SwitchToUnoptimizedCode() const { 3228 void Function::SwitchToUnoptimizedCode() const {
3229 ASSERT(HasOptimizedCode()); 3229 ASSERT(HasOptimizedCode());
3230
3230 const Code& current_code = Code::Handle(CurrentCode()); 3231 const Code& current_code = Code::Handle(CurrentCode());
3232
3233 // Optimized code object might have been actually fully produced by the
3234 // intrinsifier in this case nothing has to be done. In fact an attempt to
3235 // patch such code will cause crash.
3236 // TODO(vegorov): if intrisifier can fully intrisify the function then we
3237 // should not later try to optimize it.
3238 if (PcDescriptors::Handle(current_code.pc_descriptors()).Length() == 0) {
3239 return;
3240 }
3241
3231 if (FLAG_trace_disabling_optimized_code) { 3242 if (FLAG_trace_disabling_optimized_code) {
3232 OS::Print("Disabling optimized code: '%s' entry: %#"Px"\n", 3243 OS::Print("Disabling optimized code: '%s' entry: %#"Px"\n",
3233 ToFullyQualifiedCString(), 3244 ToFullyQualifiedCString(),
3234 current_code.EntryPoint()); 3245 current_code.EntryPoint());
3235 } 3246 }
3236 // Patch entry of the optimized code. 3247 // Patch entry of the optimized code.
3237 CodePatcher::PatchEntry(current_code); 3248 CodePatcher::PatchEntry(current_code);
3238 // Use previously compiled unoptimized code. 3249 // Use previously compiled unoptimized code.
3239 SetCode(Code::Handle(unoptimized_code())); 3250 SetCode(Code::Handle(unoptimized_code()));
3240 CodePatcher::RestoreEntry(Code::Handle(unoptimized_code())); 3251 CodePatcher::RestoreEntry(Code::Handle(unoptimized_code()));
(...skipping 1439 matching lines...) Expand 10 before | Expand all | Expand 10 after
4680 if (is_static) { 4691 if (is_static) {
4681 result.set_value(Instance::Handle()); 4692 result.set_value(Instance::Handle());
4682 } else { 4693 } else {
4683 result.SetOffset(0); 4694 result.SetOffset(0);
4684 } 4695 }
4685 result.set_is_final(is_final); 4696 result.set_is_final(is_final);
4686 result.set_is_const(is_const); 4697 result.set_is_const(is_const);
4687 result.set_owner(owner); 4698 result.set_owner(owner);
4688 result.set_token_pos(token_pos); 4699 result.set_token_pos(token_pos);
4689 result.set_has_initializer(false); 4700 result.set_has_initializer(false);
4701 result.set_guarded_cid(kIllegalCid);
4702 result.set_is_nullable(false);
4703 result.set_dependent_code(Array::Handle());
4690 return result.raw(); 4704 return result.raw();
4691 } 4705 }
4692 4706
4693 4707
4694 4708
4695 RawField* Field::Clone(const Class& new_owner) const { 4709 RawField* Field::Clone(const Class& new_owner) const {
4696 Field& clone = Field::Handle(); 4710 Field& clone = Field::Handle();
4697 clone ^= Object::Clone(*this, Heap::kOld); 4711 clone ^= Object::Clone(*this, Heap::kOld);
4698 const Class& owner = Class::Handle(this->owner()); 4712 const Class& owner = Class::Handle(this->owner());
4699 const PatchClass& clone_owner = 4713 const PatchClass& clone_owner =
4700 PatchClass::Handle(PatchClass::New(new_owner, owner)); 4714 PatchClass::Handle(PatchClass::New(new_owner, owner));
4701 clone.set_owner(clone_owner); 4715 clone.set_owner(clone_owner);
4716 clone.set_dependent_code(Array::Handle());
4702 if (!clone.is_static()) { 4717 if (!clone.is_static()) {
4703 clone.SetOffset(0); 4718 clone.SetOffset(0);
4704 } 4719 }
4705 return clone.raw(); 4720 return clone.raw();
4706 } 4721 }
4707 4722
4708 4723
4709 RawString* Field::UserVisibleName() const { 4724 RawString* Field::UserVisibleName() const {
4710 const String& str = String::Handle(name()); 4725 const String& str = String::Handle(name());
4711 return IdentifierPrettyName(str); 4726 return IdentifierPrettyName(str);
4712 } 4727 }
4713 4728
4714 4729
4715 const char* Field::ToCString() const { 4730 const char* Field::ToCString() const {
4716 const char* kF0 = is_static() ? " static" : ""; 4731 const char* kF0 = is_static() ? " static" : "";
4717 const char* kF1 = is_final() ? " final" : ""; 4732 const char* kF1 = is_final() ? " final" : "";
4718 const char* kF2 = is_const() ? " const" : ""; 4733 const char* kF2 = is_const() ? " const" : "";
4719 const char* kFormat = "Field <%s.%s>:%s%s%s"; 4734 const char* kFormat = "Field <%s.%s>:%s%s%s";
4720 const char* field_name = String::Handle(name()).ToCString(); 4735 const char* field_name = String::Handle(name()).ToCString();
4721 const Class& cls = Class::Handle(owner()); 4736 const Class& cls = Class::Handle(owner());
4722 const char* cls_name = String::Handle(cls.Name()).ToCString(); 4737 const char* cls_name = String::Handle(cls.Name()).ToCString();
4723 intptr_t len = 4738 intptr_t len =
4724 OS::SNPrint(NULL, 0, kFormat, cls_name, field_name, kF0, kF1, kF2) + 1; 4739 OS::SNPrint(NULL, 0, kFormat, cls_name, field_name, kF0, kF1, kF2) + 1;
4725 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 4740 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
4726 OS::SNPrint(chars, len, kFormat, cls_name, field_name, kF0, kF1, kF2); 4741 OS::SNPrint(chars, len, kFormat, cls_name, field_name, kF0, kF1, kF2);
4727 return chars; 4742 return chars;
4728 } 4743 }
4729 4744
4730 4745
4746 RawArray* Field::dependent_code() const {
4747 return raw_ptr()->dependent_code_;
4748 }
4749
4750
4751 void Field::set_dependent_code(const Array& array) const {
4752 raw_ptr()->dependent_code_ = array.raw();
4753 }
4754
4755
4756 void Field::RegisterDependentCode(const Code& code) const {
4757 const Array& dependent = Array::Handle(dependent_code());
4758
4759 if (!dependent.IsNull()) {
4760 // Try to find and reuse cleared WeakProperty to avoid allocating new one.
4761 WeakProperty& weak_property = WeakProperty::Handle();
4762 for (intptr_t i = 0; i < dependent.Length(); i++) {
4763 weak_property ^= dependent.At(i);
4764 if (weak_property.key() == Code::null()) {
4765 // Empty property found. Reuse it.
4766 weak_property.set_key(code);
4767 return;
4768 }
4769 }
4770 }
4771
4772 const WeakProperty& weak_property = WeakProperty::Handle(
4773 WeakProperty::New(Heap::kOld));
4774 weak_property.set_key(code);
4775
4776 intptr_t length = dependent.IsNull() ? 0 : dependent.Length();
4777 const Array& new_dependent = Array::Handle(
4778 Array::Grow(dependent, length + 1, Heap::kOld));
4779 new_dependent.SetAt(length, weak_property);
4780 set_dependent_code(new_dependent);
4781 }
4782
4783
4784 static bool IsDependentCode(const Array& dependent_code, const Code& code) {
4785 if (!code.is_optimized()) {
4786 return false;
4787 }
4788
4789 WeakProperty& weak_property = WeakProperty::Handle();
4790 for (intptr_t i = 0; i < dependent_code.Length(); i++) {
4791 weak_property ^= dependent_code.At(i);
4792 if (code.raw() == weak_property.key()) {
4793 return true;
4794 }
4795 }
4796
4797 return false;
4798 }
4799
4800
4801 void Field::DeoptimizeDependentCode() const {
4802 const Array& code_objects = Array::Handle(dependent_code());
4803
4804 if (code_objects.IsNull()) {
4805 return;
4806 }
4807 set_dependent_code(Array::Handle());
4808
4809 // Deoptimize all dependent code on the stack.
4810 Code& code = Code::Handle();
4811 {
4812 DartFrameIterator iterator;
4813 StackFrame* frame = iterator.NextFrame();
4814 while (frame != NULL) {
4815 code = frame->LookupDartCode();
4816 if (IsDependentCode(code_objects, code)) {
4817 DeoptimizeAt(code, frame->pc());
4818 }
4819 frame = iterator.NextFrame();
4820 }
4821 }
4822
4823 // Switch functions that use dependent code to unoptimized code.
4824 WeakProperty& weak_property = WeakProperty::Handle();
4825 Function& function = Function::Handle();
4826 for (intptr_t i = 0; i < code_objects.Length(); i++) {
4827 weak_property ^= code_objects.At(i);
4828 code ^= weak_property.key();
4829 if (code.IsNull()) {
4830 // Code was garbage collected already.
4831 continue;
4832 }
4833
4834 function ^= code.function();
4835 // If function uses dependent code switch it to unoptimized.
4836 if (function.CurrentCode() == code.raw()) {
4837 ASSERT(function.HasOptimizedCode());
4838 function.SwitchToUnoptimizedCode();
4839 }
4840 }
4841 }
4842
4843
4844 void Field::UpdateCid(intptr_t cid) const {
4845 if (guarded_cid() == kIllegalCid) {
4846 // Field is assigned first time.
4847 set_guarded_cid(cid);
4848 set_is_nullable(cid == kNullCid);
4849 return;
4850 }
4851
4852 if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
4853 // Class id of the assigned value matches expected class id and nullability.
4854 return;
4855 }
4856
4857 if ((cid == kNullCid) && !is_nullable()) {
4858 // Assigning null value to a non-nullable field makes it nullable.
4859 set_is_nullable(true);
4860 } else if ((cid != kNullCid) && (guarded_cid() == kNullCid)) {
4861 // Assigning non-null value to a field that previously contained only null
4862 // turns it into a nullable field with the given class id.
4863 ASSERT(is_nullable());
4864 set_guarded_cid(cid);
4865 } else {
4866 // Give up on tracking class id of values contained in this field.
4867 ASSERT(guarded_cid() != cid);
4868 set_guarded_cid(kDynamicCid);
4869 set_is_nullable(true);
4870 }
4871
4872 // Expected class id or nullability of the field changed.
4873 DeoptimizeDependentCode();
4874 }
4875
4876
4731 void LiteralToken::set_literal(const String& literal) const { 4877 void LiteralToken::set_literal(const String& literal) const {
4732 StorePointer(&raw_ptr()->literal_, literal.raw()); 4878 StorePointer(&raw_ptr()->literal_, literal.raw());
4733 } 4879 }
4734 4880
4735 4881
4736 void LiteralToken::set_value(const Object& value) const { 4882 void LiteralToken::set_value(const Object& value) const {
4737 StorePointer(&raw_ptr()->value_, value.raw()); 4883 StorePointer(&raw_ptr()->value_, value.raw());
4738 } 4884 }
4739 4885
4740 4886
(...skipping 8656 matching lines...) Expand 10 before | Expand all | Expand 10 after
13397 } 13543 }
13398 return result.raw(); 13544 return result.raw();
13399 } 13545 }
13400 13546
13401 13547
13402 const char* WeakProperty::ToCString() const { 13548 const char* WeakProperty::ToCString() const {
13403 return "_WeakProperty"; 13549 return "_WeakProperty";
13404 } 13550 }
13405 13551
13406 } // namespace dart 13552 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698