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

Unified Diff: runtime/vm/object.cc

Issue 1234883005: Implement tear-off closure operator # (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Reuse previously created closures Created 5 years, 5 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 side-by-side diff with in-line comments
Download patch
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_;
}
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.h » ('j') | runtime/vm/parser.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698