Chromium Code Reviews| 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(); |