Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index f674cd4b80669a4b9a64444e12601acb5135aed4..6491077caa7e96ed1d7897a6420dcecb2366daba 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -7386,6 +7386,73 @@ void Field::PrintJSONImpl(JSONStream* stream, bool ref) const { |
} |
} |
+// Build a closure object that gets (or sets) the contents of a static |
+// field f and cache the closure in a newly created static field |
+// named #f (or #f= in case of a setter). |
+RawInstance* Field::AccessorClosure(bool make_setter) const { |
+ ASSERT(is_static()); |
+ const Class& field_owner = Class::Handle(owner()); |
+ |
+ String& closure_name = String::Handle(this->name()); |
+ closure_name = Symbols::FromConcat(Symbols::HashMark(), closure_name); |
+ if (make_setter) { |
+ 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 closure for this field is requested. |
+ // Create the closure and a new static field in which it is stored. |
+ const char* field_name = String::Handle(name()).ToCString(); |
+ String& expr_src = String::Handle(); |
+ if (make_setter) { |
+ expr_src = |
+ String::NewFormatted("(%s_) { return %s = %s_; }", |
+ field_name, field_name, field_name); |
+ } else { |
+ expr_src = 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()); |
+} |
+ |
+ |
+RawInstance* Field::GetterClosure() const { |
+ return AccessorClosure(false); |
+} |
+ |
+ |
+RawInstance* Field::SetterClosure() const { |
+ return AccessorClosure(true); |
+} |
+ |
RawArray* Field::dependent_code() const { |
return raw_ptr()->dependent_code_; |