Chromium Code Reviews| Index: vm/object.cc |
| =================================================================== |
| --- vm/object.cc (revision 557) |
| +++ vm/object.cc (working copy) |
| @@ -3406,22 +3406,46 @@ |
| } |
| -ClassDictionaryIterator::ClassDictionaryIterator(const Library& library) |
| +DictionaryIterator::DictionaryIterator(const Library& library) |
| : array_(Array::Handle(library.dictionary())), |
| // Last element in array is a Smi. |
| size_(Array::Handle(library.dictionary()).Length() - 1), |
| next_ix_(0) { |
| + MoveToNextObject(); |
| +} |
| + |
| + |
| +RawObject* DictionaryIterator::GetNext() { |
| + ASSERT(HasNext()); |
| + int ix = next_ix_++; |
| + MoveToNextObject(); |
| + ASSERT(array_.At(ix) != Object::null()); |
| + return array_.At(ix); |
| +} |
| + |
| + |
| +void DictionaryIterator::MoveToNextObject() { |
| + Object& obj = Object::Handle(array_.At(next_ix_)); |
| + while (obj.IsNull() && HasNext()) { |
| + next_ix_++; |
| + obj = array_.At(next_ix_); |
| + } |
| +} |
| + |
| + |
| +ClassDictionaryIterator::ClassDictionaryIterator(const Library& library) |
| + : DictionaryIterator(library) { |
| MoveToNextClass(); |
| } |
| -RawClass* ClassDictionaryIterator::GetNext() { |
| +RawClass* ClassDictionaryIterator::GetNextClass() { |
| ASSERT(HasNext()); |
| int ix = next_ix_++; |
| + Object& obj = Object::Handle(array_.At(ix)); |
| MoveToNextClass(); |
| - ASSERT(array_.At(ix) != Object::null()); |
| Class& cls = Class::Handle(); |
| - cls ^= array_.At(ix); |
| + cls ^= obj.raw(); |
| return cls.raw(); |
| } |
| @@ -3578,10 +3602,12 @@ |
| RawObject* Library::LookupObject(const String& name) const { |
| + // First check if the name is found in the local scope. |
| Object& obj = Object::Handle(LookupLocalObject(name)); |
| if (!obj.IsNull()) { |
| return obj.raw(); |
| } |
| + // Now check if the name is found in the local scope of any imported libs. |
| Library& import = Library::Handle(); |
| Array& imports = Array::Handle(this->imports()); |
| for (intptr_t i = 0; i < num_imports(); i++) { |
| @@ -3595,6 +3621,106 @@ |
| } |
| +RawObject* Library::LookupObjectInImporter(const String& name) const { |
| + const Array& imported_into_libs = Array::Handle(this->imported_into()); |
| + Library& importer_lib = Library::Handle(); |
| + Object& obj = Object::Handle(); |
| + for (intptr_t i = 0; i < this->num_imported_into(); i++) { |
| + importer_lib ^= imported_into_libs.At(i); |
| + // Check if name is found in the top level scope of the importer. |
| + ASSERT(importer_lib.raw() != raw()); |
| + // First check if name is found in the local scope of the library into |
|
Ivan Posva
2011/10/20 08:46:04
Please factor this out as it is essentially Lookup
siva
2011/10/20 23:08:47
Done.
|
| + // which this is imported into. |
| + obj = importer_lib.LookupLocalObject(name); |
| + if (!obj.IsNull()) { |
| + return obj.raw(); |
| + } |
| + // Now check if name is found in the top level scope of libs imported |
| + // by the importer. |
| + const Array& imports = Array::Handle(importer_lib.imports()); |
| + Library& import_lib = Library::Handle(); |
| + for (intptr_t j = 0; j < importer_lib.num_imports(); j++) { |
| + import_lib ^= imports.At(j); |
| + if (import_lib.raw() == raw()) { |
| + continue; |
| + } |
| + obj = import_lib.LookupLocalObject(name); |
| + if (!obj.IsNull()) { |
| + return obj.raw(); |
| + } |
| + } |
| + } |
| + return Object::null(); |
| +} |
| + |
| + |
| +RawString* Library::DuplicateDefineErrorString(const Object& obj) const { |
| + Class& cls = Class::Handle(); |
| + Function& func = Function::Handle(); |
| + Field& field = Field::Handle(); |
| + String& errstr = String::Handle(); |
| + if (obj.IsClass()) { |
| + cls ^= obj.raw(); |
| + errstr = cls.Name(); |
| + } else if (obj.IsFunction()) { |
| + func ^= obj.raw(); |
| + cls ^= func.owner(); |
| + errstr = func.name(); |
| + } else if (obj.IsField()) { |
| + field ^= obj.raw(); |
| + cls ^= field.owner(); |
| + errstr = field.name(); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + const Library& lib = Library::Handle(cls.library()); |
| + Array& array = Array::Handle(Array::New(5)); |
| + array.SetAt(0, errstr); |
| + errstr = String::New(" is defined in libraries "); |
| + array.SetAt(1, errstr); |
| + errstr = url(); |
| + array.SetAt(2, errstr); |
| + errstr = String::New(" and "); |
| + array.SetAt(3, errstr); |
| + errstr = lib.url(); |
| + array.SetAt(4, errstr); |
| + errstr = String::ConcatAll(array); |
| + return errstr.raw(); |
| +} |
| + |
| + |
| +RawObject* Library::FindDuplicateDefinition() const { |
| + DictionaryIterator it(*this); |
| + Object& obj = Object::Handle(); |
| + Class& cls = Class::Handle(); |
| + Function& func = Function::Handle(); |
| + Field& field = Field::Handle(); |
| + String& entry_name = String::Handle(); |
| + while (it.HasNext()) { |
| + obj = it.GetNext(); |
| + if (obj.IsNull()) { |
|
Ivan Posva
2011/10/20 08:46:04
I don't think the iterator is ever handing out nul
siva
2011/10/20 23:08:47
True, I changed this to an assertion.
On 2011/10/
|
| + continue; |
| + } else if (obj.IsClass()) { |
| + cls ^= obj.raw(); |
| + entry_name = cls.Name(); |
| + } else if (obj.IsFunction()) { |
| + func ^= obj.raw(); |
| + entry_name = func.name(); |
| + } else if (obj.IsField()) { |
| + field ^= obj.raw(); |
| + entry_name = field.name(); |
| + } else { |
|
Ivan Posva
2011/10/20 08:46:04
Please add a comment explaining why you can skip l
siva
2011/10/20 23:08:47
Added comment stating that library prefixes in thi
|
| + continue; |
| + } |
| + obj = LookupObjectInImporter(entry_name); |
| + if (!obj.IsNull()) { |
| + return obj.raw(); |
| + } |
| + } |
| + return Object::null(); |
| +} |
| + |
| + |
| RawClass* Library::LookupClass(const String& name) const { |
| Object& obj = Object::Handle(LookupObject(name)); |
| if (!obj.IsNull() && obj.IsClass()) { |
| @@ -3654,9 +3780,24 @@ |
| intptr_t index = num_imports(); |
| imports.SetAt(index, library); |
| set_num_imports(index + 1); |
| + library.AddImportedInto(*this); |
| } |
| +void Library::AddImportedInto(const Library& library) const { |
| + Array& imported_into = Array::Handle(this->imported_into()); |
| + intptr_t capacity = imported_into.Length(); |
| + if (num_imported_into() == capacity) { |
| + capacity = capacity + kImportedIntoCapacityIncrement; |
| + imported_into = Array::Grow(imported_into, capacity); |
| + StorePointer(&raw_ptr()->imported_into_, imported_into.raw()); |
| + } |
| + intptr_t index = num_imported_into(); |
| + imported_into.SetAt(index, library); |
| + set_num_imported_into(index + 1); |
| +} |
| + |
| + |
| void Library::InitClassDictionary() const { |
| // The last element of the dictionary specifies the number of in use slots. |
| // TODO(iposva): Find reasonable initial size. |
| @@ -3677,6 +3818,14 @@ |
| } |
| +void Library::InitImportedIntoList() const { |
| + const Array& imported_into = |
| + Array::Handle(Array::New(kInitialImportedIntoCapacity, Heap::kOld)); |
| + StorePointer(&raw_ptr()->imported_into_, imported_into.raw()); |
| + raw_ptr()->num_imported_into_ = 0; |
| +} |
| + |
| + |
| RawLibrary* Library::New() { |
| const Class& library_class = Class::Handle(Object::library_class()); |
| RawObject* raw = Object::Allocate(library_class, |
| @@ -3702,6 +3851,7 @@ |
| result.raw_ptr()->loaded_ = false; |
| result.InitClassDictionary(); |
| result.InitImportList(); |
| + result.InitImportedIntoList(); |
| if (import_core_lib) { |
| Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| ASSERT(!core_lib.IsNull()); |
| @@ -3753,6 +3903,25 @@ |
| } |
| +RawString* Library::CheckForDuplicateDefinition() { |
| + Library& lib = Library::Handle(); |
| + Isolate* isolate = Isolate::Current(); |
| + ASSERT(isolate != NULL); |
| + ObjectStore* object_store = isolate->object_store(); |
| + ASSERT(object_store != NULL); |
| + lib ^= object_store->registered_libraries(); |
| + Object& obj = Object::Handle(); |
| + while (!lib.IsNull()) { |
| + obj = lib.FindDuplicateDefinition(); |
| + if (!obj.IsNull()) { |
| + return lib.DuplicateDefineErrorString(obj); |
| + } |
| + lib ^= lib.next_registered(); |
| + } |
| + return String::null(); |
| +} |
| + |
| + |
| bool Library::IsKeyUsed(intptr_t key) { |
| intptr_t lib_key; |
| Library& lib = Library::Handle(); |
| @@ -3846,7 +4015,7 @@ |
| while (!lib.IsNull()) { |
| ClassDictionaryIterator it(lib); |
| while (it.HasNext()) { |
| - cls ^= it.GetNext(); |
| + cls ^= it.GetNextClass(); |
| if (!cls.is_interface()) { |
| Compiler::CompileAllFunctions(cls); |
| } |