Chromium Code Reviews| Index: runtime/vm/object.cc |
| =================================================================== |
| --- runtime/vm/object.cc (revision 22914) |
| +++ runtime/vm/object.cc (working copy) |
| @@ -29,6 +29,7 @@ |
| #include "vm/heap.h" |
| #include "vm/intermediate_language.h" |
| #include "vm/intrinsifier.h" |
| +#include "vm/longjump.h" |
| #include "vm/object_store.h" |
| #include "vm/parser.h" |
| #include "vm/runtime_entry.h" |
| @@ -363,6 +364,8 @@ |
| cls.set_id(Class::kClassId); |
| cls.raw_ptr()->state_bits_ = 0; |
| cls.set_is_finalized(); |
| + cls.set_is_type_finalized(); |
| + cls.set_is_parsed(); |
| cls.raw_ptr()->type_arguments_field_offset_in_words_ = |
| Class::kNoTypeArguments; |
| cls.raw_ptr()->num_native_fields_ = 0; |
| @@ -373,11 +376,15 @@ |
| // Allocate and initialize the null class. |
| cls = Class::New<Instance>(kNullCid); |
| cls.set_is_finalized(); |
| + cls.set_is_type_finalized(); |
| + cls.set_is_parsed(); |
| null_class_ = cls.raw(); |
| // Allocate and initialize the free list element class. |
| cls = Class::New<FreeListElement::FakeInstance>(kFreeListElement); |
| cls.set_is_finalized(); |
| + cls.set_is_type_finalized(); |
| + cls.set_is_parsed(); |
| // Allocate and initialize the sentinel values of Null class. |
| { |
| @@ -398,6 +405,8 @@ |
| cls = Class::New<Instance>(kDynamicCid); |
| cls.set_is_finalized(); |
| + cls.set_is_type_finalized(); |
| + cls.set_is_parsed(); |
| cls.set_is_abstract(); |
| dynamic_class_ = cls.raw(); |
| @@ -407,6 +416,8 @@ |
| cls = Class::New<Instance>(kVoidCid); |
| cls.set_is_finalized(); |
| + cls.set_is_type_finalized(); |
| + cls.set_is_parsed(); |
| void_class_ = cls.raw(); |
| cls = Class::New<TypeArguments>(); |
| @@ -994,6 +1005,7 @@ |
| cls = Class::New<Instance>(kIllegalCid); |
| cls.set_is_prefinalized(); |
| RegisterClass(cls, name, core_lib); |
| + cls.set_is_prefinalized(); |
| pending_classes.Add(cls, Heap::kOld); |
| type = Type::NewNonParameterizedType(cls); |
| object_store->set_string_type(type); |
| @@ -1543,7 +1555,7 @@ |
| void Class::set_state_bits(intptr_t bits) const { |
| - raw_ptr()->state_bits_ = static_cast<uint8_t>(bits); |
| + raw_ptr()->state_bits_ = static_cast<uint16_t>(bits); |
| } |
| @@ -1589,7 +1601,7 @@ |
| bool Class::HasTypeArguments() const { |
| - if (!IsSignatureClass() && (is_finalized() || is_prefinalized())) { |
| + if (!IsSignatureClass() && (is_type_finalized() || is_prefinalized())) { |
| // More efficient than calling NumTypeArguments(). |
| return type_arguments_field_offset() != kNoTypeArguments; |
| } else { |
| @@ -1783,6 +1795,21 @@ |
| } |
| +// Ensure that top level parsing of the class has been done. |
| +RawError* Class::EnsureIsParsed(Isolate* isolate) const { |
| + if (!is_parsed()) { |
| + ASSERT(isolate != NULL); |
| + const Error& error = Error::Handle(isolate, Compiler::ParseClass(*this)); |
| + if (!error.IsNull() && (isolate->long_jump_base() != NULL)) { |
| + isolate->long_jump_base()->Jump(1, error); |
| + UNREACHABLE(); |
| + } |
| + return error.raw(); |
| + } |
| + return Error::null(); |
| +} |
| + |
| + |
| void Class::SetFields(const Array& value) const { |
| ASSERT(!value.IsNull()); |
| #if defined(DEBUG) |
| @@ -1848,6 +1875,7 @@ |
| result.set_instance_size(Closure::InstanceSize()); |
| result.set_next_field_offset(Closure::InstanceSize()); |
| result.set_super_type(super_type); |
| + result.set_is_parsed(); |
| result.set_type_arguments_field_offset(Closure::type_arguments_offset()); |
| // Implements interface "Function". |
| const Type& function_type = Type::Handle(Type::Function()); |
| @@ -1908,6 +1936,8 @@ |
| cls.set_next_field_offset(instance_size); |
| cls.set_num_native_fields(field_count); |
| cls.set_is_finalized(); |
| + cls.set_is_type_finalized(); |
| + cls.set_is_parsed(); |
| library.AddClass(cls); |
| return cls.raw(); |
| } else { |
| @@ -1994,6 +2024,26 @@ |
| } |
| +void Class::set_is_type_finalized() const { |
| + set_state_bits(TypeFinalizedBit::update(true, raw_ptr()->state_bits_)); |
| +} |
| + |
| + |
| +void Class::set_is_patch() const { |
| + set_state_bits(PatchBit::update(true, raw_ptr()->state_bits_)); |
| +} |
| + |
| + |
| +void Class::set_is_parsed() const { |
| + set_state_bits(ParsedBit::update(true, raw_ptr()->state_bits_)); |
| +} |
| + |
| + |
| +void Class::set_is_synthesized_class() const { |
| + set_state_bits(SynthesizedClassBit::update(true, raw_ptr()->state_bits_)); |
| +} |
| + |
| + |
| void Class::set_is_const() const { |
| set_state_bits(ConstBit::update(true, raw_ptr()->state_bits_)); |
| } |
| @@ -2027,6 +2077,18 @@ |
| } |
| +void Class::add_patch_class(const Class& patch_class) const { |
| + ASSERT(!patch_class.IsNull()); |
| + GrowableObjectArray& patch_classes = GrowableObjectArray::Handle(); |
| + patch_classes ^= raw_ptr()->patch_classes_; |
| + if (patch_classes.IsNull()) { |
| + patch_classes ^= GrowableObjectArray::New(1, Heap::kOld); |
| + StorePointer(&raw_ptr()->patch_classes_, patch_classes.raw()); |
| + } |
| + patch_classes.Add(patch_class); |
| +} |
| + |
| + |
| void Class::AddDirectSubclass(const Class& subclass) const { |
| ASSERT(!subclass.IsNull()); |
| ASSERT(subclass.SuperClass() == raw()); |
| @@ -2342,6 +2404,9 @@ |
| RawFunction* Class::LookupFunction(const String& name) const { |
| Isolate* isolate = Isolate::Current(); |
| + if (EnsureIsParsed(isolate) != Error::null()) { |
|
hausner
2013/05/21 20:07:30
How do errors during parsing get propagated to the
siva
2013/05/23 00:54:31
The function EnsureIsParsed does a Longjump on err
|
| + return Function::null(); |
| + } |
| Array& funcs = Array::Handle(isolate, functions()); |
| if (funcs.IsNull()) { |
| // This can occur, e.g., for Null classes. |
| @@ -2375,6 +2440,9 @@ |
| RawFunction* Class::LookupFunctionAllowPrivate(const String& name) const { |
| Isolate* isolate = Isolate::Current(); |
| + if (EnsureIsParsed(isolate) != Error::null()) { |
| + return Function::null(); |
| + } |
| Array& funcs = Array::Handle(isolate, functions()); |
| if (funcs.IsNull()) { |
| // This can occur, e.g., for Null classes. |
| @@ -2409,6 +2477,9 @@ |
| intptr_t prefix_length, |
| const String& name) const { |
| Isolate* isolate = Isolate::Current(); |
| + if (EnsureIsParsed(isolate) != Error::null()) { |
| + return Function::null(); |
| + } |
| Array& funcs = Array::Handle(isolate, functions()); |
| Function& function = Function::Handle(isolate, Function::null()); |
| String& function_name = String::Handle(isolate, String::null()); |
| @@ -2429,12 +2500,16 @@ |
| RawFunction* Class::LookupFunctionAtToken(intptr_t token_pos) const { |
| // TODO(hausner): we can shortcut the negative case if we knew the |
| // beginning and end token position of the class. |
| - Function& func = Function::Handle(); |
| + Isolate* isolate = Isolate::Current(); |
| + if (EnsureIsParsed(isolate) != Error::null()) { |
| + return Function::null(); |
| + } |
| + Function& func = Function::Handle(isolate); |
| func = LookupClosureFunction(token_pos); |
| if (!func.IsNull()) { |
| return func.raw(); |
| } |
| - Array& funcs = Array::Handle(functions()); |
| + Array& funcs = Array::Handle(isolate, functions()); |
| intptr_t len = funcs.Length(); |
| for (intptr_t i = 0; i < len; i++) { |
| func ^= funcs.At(i); |
| @@ -2449,8 +2524,12 @@ |
| RawField* Class::LookupInstanceField(const String& name) const { |
| + Isolate* isolate = Isolate::Current(); |
| + if (EnsureIsParsed(isolate) != Error::null()) { |
| + return Field::null(); |
| + } |
| ASSERT(is_finalized()); |
| - const Field& field = Field::Handle(LookupField(name)); |
| + const Field& field = Field::Handle(isolate, LookupField(name)); |
| if (!field.IsNull()) { |
| if (field.is_static()) { |
| // Name matches but it is not of the correct kind, return NULL. |
| @@ -2464,8 +2543,12 @@ |
| RawField* Class::LookupStaticField(const String& name) const { |
| + Isolate* isolate = Isolate::Current(); |
| + if (EnsureIsParsed(isolate) != Error::null()) { |
| + return Field::null(); |
| + } |
| ASSERT(is_finalized()); |
| - const Field& field = Field::Handle(LookupField(name)); |
| + const Field& field = Field::Handle(isolate, LookupField(name)); |
| if (!field.IsNull()) { |
| if (!field.is_static()) { |
| // Name matches but it is not of the correct kind, return NULL. |
| @@ -2480,6 +2563,9 @@ |
| RawField* Class::LookupField(const String& name) const { |
| Isolate* isolate = Isolate::Current(); |
| + if (EnsureIsParsed(isolate) != Error::null()) { |
| + return Field::null(); |
| + } |
| const Array& flds = Array::Handle(isolate, fields()); |
| Field& field = Field::Handle(isolate, Field::null()); |
| String& field_name = String::Handle(isolate, String::null()); |
| @@ -6896,6 +6982,10 @@ |
| ClassDictionaryIterator it(lib); |
| while (it.HasNext()) { |
| cls = it.GetNextClass(); |
| + error = cls.EnsureIsParsed(Isolate::Current()); |
| + if (!error.IsNull()) { |
| + return error.raw(); |
| + } |
| error = Compiler::CompileAllFunctions(cls); |
| if (!error.IsNull()) { |
| return error.raw(); |
| @@ -9180,7 +9270,11 @@ |
| RawInstance* Instance::New(const Class& cls, Heap::Space space) { |
| - Instance& result = Instance::Handle(); |
| + Isolate* isolate = Isolate::Current(); |
| + if (cls.EnsureIsParsed(isolate) != Error::null()) { |
| + return Instance::null(); |
| + } |
| + Instance& result = Instance::Handle(isolate); |
| { |
| intptr_t instance_size = cls.instance_size(); |
| ASSERT(instance_size > 0); |
| @@ -9384,7 +9478,7 @@ |
| } else { |
| // The actual type argument vector can be longer than necessary, because |
| // of type optimizations. |
| - if (IsFinalized() && cls.is_finalized()) { |
| + if (IsFinalized() && cls.is_type_finalized()) { |
| first_type_param_index = cls.NumTypeArguments() - num_type_params; |
| } else { |
| first_type_param_index = num_args - num_type_params; |