Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index f674cd4b80669a4b9a64444e12601acb5135aed4..7320872b0c6e7de052919eff36d745e7e4096386 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -7387,6 +7387,115 @@ void Field::PrintJSONImpl(JSONStream* stream, bool ref) const { |
} |
+// Build a closure object that gets the contents of a static field f |
+// and cache the closure in a newly created static field named #f. |
+RawInstance* Field::GetterClosure() const { |
+ ASSERT(is_static()); |
+ const Class& field_owner = Class::Handle(owner()); |
+ |
+ String& closure_name = String::Handle(); |
Florian Schneider
2015/07/22 08:25:53
String& closure_name = String::Handle(this->name()
hausner
2015/07/22 18:41:09
vertigo prevented :)
|
+ closure_name = this->name(); |
+ closure_name = Symbols::FromConcat(Symbols::HashMark(), closure_name); |
+ |
+ Field& closure_field = Field::Handle(); |
+ closure_field = field_owner.LookupStaticField(closure_name); |
+ if (!closure_field.IsNull()) { |
+ ASSERT(closure_field.is_static()); |
+ const Instance& closure = Instance::Handle(closure_field.value()); |
+ ASSERT(!closure.IsNull()); |
+ ASSERT(closure.IsClosure()); |
+ return closure.raw(); |
+ } |
+ |
+ // This is the first time a getter closure for this field is requested. |
+ // Create the closure and a new static field in which the closure is |
+ // stored. |
+ const char* field_name = String::Handle(name()).ToCString(); |
+ String& expr_src = String::Handle( |
+ String::NewFormatted("() { return %s; }", field_name)); |
+ Object& result = |
+ Object::Handle(field_owner.Evaluate(expr_src, |
+ Object::empty_array(), |
+ Object::empty_array())); |
+ ASSERT(result.IsInstance()); |
+ // The caller may expect the closure to be allocated in old space. Copy |
+ // the result here, since Object::Clone() is a private method. |
+ result = Object::Clone(result, Heap::kOld); |
+ |
+ closure_field = Field::New(closure_name, |
+ true, // is_static |
+ true, // is_final |
+ true, // is_const |
+ true, // is_synthetic |
+ field_owner, |
+ this->token_pos()); |
+ closure_field.set_value(Instance::Cast(result)); |
+ closure_field.set_type(Type::Handle(Type::DynamicType())); |
+ field_owner.AddField(closure_field); |
+ |
+ return Instance::RawCast(result.raw()); |
+} |
+ |
+ |
+// Build a closure object that sets the contents of a static field f |
+// and cache the closure in a newly created static field named #f=. |
+RawInstance* Field::SetterClosure() const { |
+ ASSERT(is_static()); |
+ const Class& field_owner = Class::Handle(owner()); |
+ |
+ String& closure_name = String::Handle(); |
Florian Schneider
2015/07/22 08:25:53
String& closure_name = String::Handle(this->name()
hausner
2015/07/22 18:41:09
Done.
|
+ closure_name = this->name(); |
+ closure_name = String::Concat(closure_name, Symbols::Equals()); |
+ closure_name = Symbols::FromConcat(Symbols::HashMark(), closure_name); |
+ |
+ Field& closure_field = Field::Handle(); |
+ closure_field = field_owner.LookupStaticField(closure_name); |
+ if (!closure_field.IsNull()) { |
+ ASSERT(closure_field.is_static()); |
+ const Instance& closure = Instance::Handle(closure_field.value()); |
+ ASSERT(!closure.IsNull()); |
+ ASSERT(closure.IsClosure()); |
+ return closure.raw(); |
+ } |
+ |
+ // This is the first time a getter closure for this field is requested. |
Florian Schneider
2015/07/22 08:25:53
Update comment for setter closure.
hausner
2015/07/22 18:41:09
Done.
|
+ // Create the closure and a new static field in which the closure is |
+ // stored. |
+ const String& field_name = String::Handle(name()); |
+ String& expr_src = String::Handle(); |
+ if (field_owner.IsTopLevel()) { |
Florian Schneider
2015/07/22 08:25:54
Why is the top-level case needed here, and not for
hausner
2015/07/22 18:41:09
The class name is added to avoid name conflicts wh
|
+ expr_src = String::NewFormatted("(value) { return %s = value; }", |
+ field_name.ToCString()); |
+ } else { |
+ const String& owner_name = String::Handle(field_owner.Name()); |
+ expr_src = String::NewFormatted("(value) { return %s.%s = value; }", |
+ owner_name.ToCString(), |
+ field_name.ToCString()); |
+ } |
+ Object& result = |
+ Object::Handle(field_owner.Evaluate(expr_src, |
+ Object::empty_array(), |
+ Object::empty_array())); |
+ ASSERT(result.IsInstance()); |
+ // The caller may expect the closure to be allocated in old space. Copy |
+ // the result here, since Object::Clone() is a private method. |
+ result = Object::Clone(result, Heap::kOld); |
+ |
+ closure_field = Field::New(closure_name, |
+ true, // is_static |
+ true, // is_final |
+ true, // is_const |
+ true, // is_synthetic |
+ field_owner, |
+ this->token_pos()); |
+ closure_field.set_value(Instance::Cast(result)); |
+ closure_field.set_type(Type::Handle(Type::DynamicType())); |
+ field_owner.AddField(closure_field); |
Florian Schneider
2015/07/22 08:25:54
Maybe factor the creation of the field into a file
hausner
2015/07/22 18:41:09
Factoring out 4 lines of code that would require 3
|
+ |
+ return Instance::RawCast(result.raw()); |
+} |
+ |
+ |
RawArray* Field::dependent_code() const { |
return raw_ptr()->dependent_code_; |
} |