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); |
} |