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

Unified Diff: vm/object.cc

Issue 8342046: Add an imported into list for libraries so that it is possible to lookup (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: '' Created 9 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 | « vm/object.h ('k') | vm/object_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: vm/object.cc
===================================================================
--- vm/object.cc (revision 591)
+++ vm/object.cc (working copy)
@@ -3414,22 +3414,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();
}
@@ -3585,16 +3609,23 @@
}
-RawObject* Library::LookupObject(const String& name) const {
+RawObject* Library::LookupObjectFiltered(const String& name,
+ const Library& filter_lib) const {
+ // First check if name is found in the local scope of the library.
Object& obj = Object::Handle(LookupLocalObject(name));
if (!obj.IsNull()) {
return obj.raw();
}
- Library& import = Library::Handle();
- Array& imports = Array::Handle(this->imports());
- for (intptr_t i = 0; i < num_imports(); i++) {
- import ^= imports.At(i);
- obj = import.LookupLocalObject(name);
+ // Now check if name is found in the top level scope of any imported libs.
+ const Array& imports = Array::Handle(this->imports());
+ Library& import_lib = Library::Handle();
+ for (intptr_t j = 0; j < this->num_imports(); j++) {
+ import_lib ^= imports.At(j);
+ // Skip over the library that we need to filter out.
+ if (!filter_lib.IsNull() && import_lib.raw() == filter_lib.raw()) {
+ continue;
+ }
+ obj = import_lib.LookupLocalObject(name);
if (!obj.IsNull()) {
return obj.raw();
}
@@ -3603,6 +3634,100 @@
}
+RawObject* Library::LookupObject(const String& name) const {
+ return LookupObjectFiltered(name, Library::Handle());
+}
+
+
+RawLibrary* Library::LookupObjectInImporter(const String& name) const {
+ const Array& imported_into_libs = Array::Handle(this->imported_into());
+ Library& lib = Library::Handle();
+ Object& obj = Object::Handle();
+ for (intptr_t i = 0; i < this->num_imported_into(); i++) {
+ lib ^= imported_into_libs.At(i);
+ obj = lib.LookupObjectFiltered(name, *this);
+ if (!obj.IsNull()) {
+ // If the object found is a class, field or function extract the
+ // library in which it is defined as it might be defined in one of
+ // the imported libraries.
+ Class& cls = Class::Handle();
+ Function& func = Function::Handle();
+ Field& field = Field::Handle();
+ if (obj.IsClass()) {
+ cls ^= obj.raw();
+ lib ^= cls.library();
+ } else if (obj.IsFunction()) {
+ func ^= obj.raw();
+ cls ^= func.owner();
+ lib ^= cls.library();
+ } else if (obj.IsField()) {
+ field ^= obj.raw();
+ cls ^= field.owner();
+ lib ^= cls.library();
+ }
+ return lib.raw();
+ }
+ }
+ return Library::null();
+}
+
+
+RawString* Library::DuplicateDefineErrorString(const String& entry_name,
+ const Library& conflict) const {
+ String& errstr = String::Handle();
+ Array& array = Array::Handle(Array::New(7));
+ errstr = String::New("'");
+ array.SetAt(0, errstr);
+ array.SetAt(1, entry_name);
+ errstr = String::New("' is defined in '");
+ array.SetAt(2, errstr);
+ errstr = url();
+ array.SetAt(3, errstr);
+ errstr = String::New("' and '");
+ array.SetAt(4, errstr);
+ errstr = conflict.url();
+ array.SetAt(5, errstr);
+ errstr = String::New("'");
+ array.SetAt(6, errstr);
+ errstr = String::ConcatAll(array);
+ return errstr.raw();
+}
+
+
+RawString* Library::FindDuplicateDefinition(Library* conflicting_lib) 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();
+ ASSERT(!obj.IsNull());
+ 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 {
+ // We don't check for library prefixes defined in this library because
+ // they are not visible in the importing scope and hence cannot
+ // cause any duplicate definitions.
+ continue;
+ }
+ *conflicting_lib = LookupObjectInImporter(entry_name);
+ if (!conflicting_lib->IsNull()) {
+ return entry_name.raw();
+ }
+ }
+ return String::null();
+}
+
+
RawClass* Library::LookupClass(const String& name) const {
Object& obj = Object::Handle(LookupObject(name));
if (!obj.IsNull() && obj.IsClass()) {
@@ -3662,9 +3787,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.
@@ -3685,6 +3825,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,
@@ -3710,6 +3858,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());
@@ -3761,6 +3910,26 @@
}
+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();
+ String& entry_name = String::Handle();
+ Library& conflicting_lib = Library::Handle();
+ while (!lib.IsNull()) {
+ entry_name = lib.FindDuplicateDefinition(&conflicting_lib);
+ if (!entry_name.IsNull()) {
+ return lib.DuplicateDefineErrorString(entry_name, conflicting_lib);
+ }
+ lib ^= lib.next_registered();
+ }
+ return String::null();
+}
+
+
bool Library::IsKeyUsed(intptr_t key) {
intptr_t lib_key;
Library& lib = Library::Handle();
@@ -3854,7 +4023,7 @@
while (!lib.IsNull()) {
ClassDictionaryIterator it(lib);
while (it.HasNext()) {
- cls ^= it.GetNext();
+ cls ^= it.GetNextClass();
if (!cls.is_interface()) {
Compiler::CompileAllFunctions(cls);
}
« no previous file with comments | « vm/object.h ('k') | vm/object_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698