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

Unified Diff: runtime/vm/object.cc

Issue 26682003: Cache number of type arguments in class object instead of recalculating it. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 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
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 28616)
+++ runtime/vm/object.cc (working copy)
@@ -481,12 +481,13 @@
cls.set_instance_size(Class::InstanceSize());
cls.set_next_field_offset(Class::InstanceSize());
cls.set_id(Class::kClassId);
- cls.raw_ptr()->state_bits_ = 0;
+ cls.set_state_bits(0);
cls.set_is_finalized();
cls.set_is_type_finalized();
- cls.raw_ptr()->type_arguments_field_offset_in_words_ =
- Class::kNoTypeArguments;
- cls.raw_ptr()->num_native_fields_ = 0;
+ cls.set_type_arguments_field_offset_in_words(Class::kNoTypeArguments);
+ cls.set_num_type_arguments(0);
+ cls.set_num_own_type_arguments(0);
+ cls.set_num_native_fields(0);
cls.InitEmptyFields();
isolate->RegisterClass(cls);
}
@@ -637,16 +638,22 @@
cls.set_is_finalized();
cls.set_is_type_finalized();
cls.set_is_abstract();
+ cls.set_num_type_arguments(0);
+ cls.set_num_own_type_arguments(0);
dynamic_class_ = cls.raw();
cls = Class::New<Instance>(kVoidCid);
cls.set_is_finalized();
cls.set_is_type_finalized();
+ cls.set_num_type_arguments(0);
+ cls.set_num_own_type_arguments(0);
void_class_ = cls.raw();
cls = Class::New<Type>();
cls.set_is_finalized();
cls.set_is_type_finalized();
+ cls.set_num_type_arguments(0);
+ cls.set_num_own_type_arguments(0);
isolate->object_store()->set_type_class(cls);
cls = dynamic_class_;
@@ -657,6 +664,8 @@
// Allocate and initialize singleton true and false boolean objects.
cls = Class::New<Bool>();
+ cls.set_num_type_arguments(0);
+ cls.set_num_own_type_arguments(0);
isolate->object_store()->set_bool_class(cls);
*bool_true_ = Bool::New(true);
*bool_false_ = Bool::New(false);
@@ -1615,19 +1624,64 @@
result.set_next_field_offset(FakeObject::InstanceSize());
ASSERT((FakeObject::kClassId != kInstanceCid));
result.set_id(FakeObject::kClassId);
- result.raw_ptr()->state_bits_ = 0;
+ result.set_state_bits(0);
// VM backed classes are almost ready: run checks and resolve class
// references, but do not recompute size.
result.set_is_prefinalized();
- result.raw_ptr()->type_arguments_field_offset_in_words_ = kNoTypeArguments;
- result.raw_ptr()->num_native_fields_ = 0;
- result.raw_ptr()->token_pos_ = Scanner::kDummyTokenIndex;
+ result.set_type_arguments_field_offset_in_words(kNoTypeArguments);
+ result.set_num_type_arguments(kUnknownNumTypeArguments);
+ result.set_num_own_type_arguments(kUnknownNumTypeArguments);
+ result.set_num_native_fields(0);
+ result.set_token_pos(Scanner::kDummyTokenIndex);
result.InitEmptyFields();
Isolate::Current()->RegisterClass(result);
return result.raw();
}
+static RawError* FormatError(const Error& prev_error,
+ const Script& script,
+ intptr_t token_pos,
+ const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ if (prev_error.IsNull()) {
+ return Parser::FormatError(script, token_pos, "Error", format, args);
+ } else {
+ return Parser::FormatErrorWithAppend(prev_error, script, token_pos,
+ "Error", format, args);
+ }
+}
+
+
+static void ReportTooManyTypeArguments(const Class& cls) {
+ const Error& error = Error::Handle(
+ FormatError(Error::Handle(), // No previous error.
+ Script::Handle(cls.script()), cls.token_pos(),
+ "too many type parameters declared in class '%s' or in its "
+ "super classes",
+ String::Handle(cls.Name()).ToCString()));
+ Isolate::Current()->long_jump_base()->Jump(1, error);
+ UNREACHABLE();
+}
+
+
+void Class::set_num_type_arguments(intptr_t value) const {
+ if (!Utils::IsInt(16, value)) {
+ ReportTooManyTypeArguments(*this);
+ }
+ raw_ptr()->num_type_arguments_ = value;
+}
+
+
+void Class::set_num_own_type_arguments(intptr_t value) const {
+ if (!Utils::IsInt(16, value)) {
+ ReportTooManyTypeArguments(*this);
+ }
+ raw_ptr()->num_own_type_arguments_ = value;
+}
+
+
// Initialize class fields of type Array with empty array.
void Class::InitEmptyFields() {
if (Object::empty_array().raw() == Array::null()) {
@@ -1755,12 +1809,17 @@
intptr_t Class::NumOwnTypeArguments() const {
+ // Return cached value if already calculated.
+ if (num_own_type_arguments() != kUnknownNumTypeArguments) {
+ return num_own_type_arguments();
+ }
Isolate* isolate = Isolate::Current();
const intptr_t num_type_params = NumTypeParameters();
if (!FLAG_overlap_type_arguments ||
(num_type_params == 0) ||
(super_type() == AbstractType::null()) ||
(super_type() == isolate->object_store()->object_type())) {
+ set_num_own_type_arguments(num_type_params);
return num_type_params;
}
ASSERT(!IsMixinApplication() || is_mixin_type_applied());
@@ -1771,6 +1830,7 @@
if (sup_type_args.IsNull()) {
// The super type is raw or the super class is non generic.
// In either case, overlapping is not possible.
+ set_num_own_type_arguments(num_type_params);
return num_type_params;
}
const intptr_t num_sup_type_args = sup_type_args.Length();
@@ -1810,15 +1870,21 @@
}
if (i == num_overlapping_type_args) {
// Overlap found.
+ set_num_own_type_arguments(num_type_params - num_overlapping_type_args);
return num_type_params - num_overlapping_type_args;
}
}
// No overlap found.
+ set_num_own_type_arguments(num_type_params);
return num_type_params;
}
intptr_t Class::NumTypeArguments() const {
+ // Return cached value if already calculated.
+ if (num_type_arguments() != kUnknownNumTypeArguments) {
+ return num_type_arguments();
+ }
// To work properly, this call requires the super class of this class to be
// resolved, which is checked by the type_class() call on the super type.
// Note that calling type_class() on a MixinAppType fails.
@@ -1847,12 +1913,17 @@
sup_type = cls.super_type();
cls = sup_type.type_class();
} while (true);
+ set_num_type_arguments(num_type_args);
return num_type_args;
}
// More efficient than calling NumTypeArguments().
bool Class::HasTypeArguments() const {
siva 2013/10/15 00:06:57 Is this HasTypeArguments optimization necessary an
regis 2013/10/15 17:49:15 You are right. This is now overkill. I have remove
+ // Check cached number of type arguments if already calculated.
+ if (num_type_arguments() != kUnknownNumTypeArguments) {
+ return num_type_arguments() > 0;
+ }
// Fast check for a non-signature finalized class.
if (!IsSignatureClass() && (is_finalized() || is_prefinalized())) {
return type_arguments_field_offset() != kNoTypeArguments;
@@ -2093,21 +2164,6 @@
}
-static RawError* FormatError(const Error& prev_error,
- const Script& script,
- intptr_t token_pos,
- const char* format, ...) {
- va_list args;
- va_start(args, format);
- if (prev_error.IsNull()) {
- return Parser::FormatError(script, token_pos, "Error", format, args);
- } else {
- return Parser::FormatErrorWithAppend(prev_error, script, token_pos,
- "Error", format, args);
- }
-}
-
-
// Apply the members from the patch class to the original class.
bool Class::ApplyPatch(const Class& patch, Error* error) const {
ASSERT(error != NULL);
@@ -2313,10 +2369,12 @@
result.set_instance_size(FakeInstance::InstanceSize());
result.set_next_field_offset(FakeInstance::InstanceSize());
result.set_id(index);
- result.raw_ptr()->state_bits_ = 0;
- result.raw_ptr()->type_arguments_field_offset_in_words_ = kNoTypeArguments;
- result.raw_ptr()->num_native_fields_ = 0;
- result.raw_ptr()->token_pos_ = Scanner::kDummyTokenIndex;
+ result.set_state_bits(0);
+ result.set_type_arguments_field_offset_in_words(kNoTypeArguments);
+ result.set_num_type_arguments(kUnknownNumTypeArguments);
+ result.set_num_own_type_arguments(kUnknownNumTypeArguments);
+ result.set_num_native_fields(0);
+ result.set_token_pos(Scanner::kDummyTokenIndex);
result.InitEmptyFields();
Isolate::Current()->RegisterClass(result);
return result.raw();
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698