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

Unified Diff: runtime/vm/object.cc

Issue 18097004: Support fast noSuchMethod dispatch for any number of arguments. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 7 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
===================================================================
--- runtime/vm/object.cc (revision 24510)
+++ runtime/vm/object.cc (working copy)
@@ -1492,6 +1492,7 @@
StorePointer(&raw_ptr()->canonical_types_, Object::empty_array().raw());
StorePointer(&raw_ptr()->functions_, Object::empty_array().raw());
StorePointer(&raw_ptr()->fields_, Object::empty_array().raw());
+ StorePointer(&raw_ptr()->no_such_method_cache_, Object::empty_array().raw());
}
@@ -1748,6 +1749,97 @@
}
+RawFunction* Class::GetNoSuchMethodDispatcher(const String& target_name,
+ const Array& args_desc) const {
+ enum {
+ kNameIndex = 0,
+ kArgsDescIndex,
+ kFunctionIndex,
+ kEntrySize
+ };
+
+ Function& dispatcher = Function::Handle();
+ Array& cache = Array::Handle(no_such_method_cache());
+ ASSERT(!cache.IsNull());
+ String& name = String::Handle();
+ Array& desc = Array::Handle();
+ intptr_t i = 0;
+ for (; i < cache.Length(); i += kEntrySize) {
+ name ^= cache.At(i + kNameIndex);
+ if (name.IsNull()) break; // Reached last entry.
+ if (!name.Equals(target_name)) continue;
+ desc ^= cache.At(i + kArgsDescIndex);
+ if (desc.raw() == args_desc.raw()) {
+ // Found match.
+ dispatcher ^= cache.At(i + kFunctionIndex);
+ ASSERT(dispatcher.IsFunction());
+ break;
+ }
+ }
+
+ if (dispatcher.IsNull()) {
+ if (i == cache.Length()) {
+ // Allocate new larger cache.
+ intptr_t new_len = cache.Length() == 0 ? kEntrySize : cache.Length() * 2;
+ cache ^= Array::Grow(cache, new_len);
+ set_no_such_method_cache(cache);
+ }
+ dispatcher ^= CreateNoSuchMethodDispatcher(target_name, args_desc);
+ cache.SetAt(i + kNameIndex, target_name);
+ cache.SetAt(i + kArgsDescIndex, args_desc);
+ cache.SetAt(i + kFunctionIndex, dispatcher);
+ }
+ return dispatcher.raw();
+}
+
+
+RawFunction* Class::CreateNoSuchMethodDispatcher(const String& target_name,
+ const Array& args_desc) const {
+ Function& invocation = Function::Handle(
+ Function::New(String::Handle(Symbols::New(target_name)),
+ RawFunction::kNoSuchMethodDispatcher,
+ false, // Not static.
+ false, // Not const.
+ false, // Not abstract.
+ false, // Not external.
+ *this,
+ 0)); // No token position.
+ ArgumentsDescriptor desc(args_desc);
+ const intptr_t num_parameters = desc.Count();
+ invocation.set_num_fixed_parameters(num_parameters);
+ invocation.SetNumOptionalParameters(0, true);
+ invocation.set_parameter_types(Array::Handle(Array::New(num_parameters,
+ Heap::kOld)));
+ invocation.set_parameter_names(Array::Handle(Array::New(num_parameters,
+ Heap::kOld)));
+ // Receiver.
+ invocation.SetParameterTypeAt(0, Type::Handle(Type::DynamicType()));
+ invocation.SetParameterNameAt(0, Symbols::This());
+ // Remaining parameters.
+ for (intptr_t i = 1; i < num_parameters; i++) {
+ invocation.SetParameterTypeAt(i, Type::Handle(Type::DynamicType()));
+ char name[64];
+ OS::SNPrint(name, 64, ":p%"Pd, i);
+ invocation.SetParameterNameAt(i, String::Handle(Symbols::New(name)));
+ }
+ invocation.set_result_type(Type::Handle(Type::DynamicType()));
+ invocation.set_is_visible(false); // Not visible in stack trace.
+ invocation.set_saved_args_desc(args_desc);
+
+ return invocation.raw();
+}
+
+
+RawArray* Class::no_such_method_cache() const {
+ return raw_ptr()->no_such_method_cache_;
+}
+
+
+void Class::set_no_such_method_cache(const Array& cache) const {
+ StorePointer(&raw_ptr()->no_such_method_cache_, cache.raw());
+}
+
+
void Class::Finalize() const {
ASSERT(!is_finalized());
// Prefinalized classes have a VM internal representation and no Dart fields.
@@ -3555,6 +3647,21 @@
}
+RawArray* Function::saved_args_desc() const {
+ ASSERT(kind() == RawFunction::kNoSuchMethodDispatcher);
+ const Object& obj = Object::Handle(raw_ptr()->data_);
+ ASSERT(obj.IsArray());
+ return Array::Cast(obj).raw();
+}
+
+
+void Function::set_saved_args_desc(const Array& value) const {
+ ASSERT(kind() == RawFunction::kNoSuchMethodDispatcher);
+ ASSERT(raw_ptr()->data_ == Object::null());
+ set_data(value);
+}
+
+
RawFunction* Function::parent_function() const {
if (IsClosureFunction()) {
const Object& obj = Object::Handle(raw_ptr()->data_);

Powered by Google App Engine
This is Rietveld 408576698