Index: src/bootstrapper.cc |
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc |
index 6735ff454933f0933f4b3a3b15e4b035625be565..16c332f0fd02a621fc0a2e937c741ab840e7b620 100644 |
--- a/src/bootstrapper.cc |
+++ b/src/bootstrapper.cc |
@@ -211,12 +211,31 @@ class Genesis BASE_EMBEDDED { |
void InstallBuiltinFunctionIds(); |
void InstallJSFunctionResultCaches(); |
void InitializeNormalizedMapCaches(); |
+ |
+ enum ExtensionTraversalState { |
+ UNVISITED, VISITED, INSTALLED |
+ }; |
+ |
+ class ExtensionStates { |
+ DISALLOW_COPY_AND_ASSIGN(ExtensionStates); |
+ public: |
+ ExtensionStates(); |
+ ExtensionTraversalState get_state(RegisteredExtension* extension); |
+ void set_state(RegisteredExtension* extension, |
+ ExtensionTraversalState state); |
+ private: |
+ Allocator allocator_; |
+ HashMap map_; |
+ }; |
+ |
// Used both for deserialized and from-scratch contexts to add the extensions |
// provided. |
static bool InstallExtensions(Handle<Context> global_context, |
v8::ExtensionConfiguration* extensions); |
- static bool InstallExtension(const char* name); |
- static bool InstallExtension(v8::RegisteredExtension* current); |
+ static bool InstallExtension(const char* name, |
+ ExtensionStates* extension_states); |
+ static bool InstallExtension(v8::RegisteredExtension* current, |
+ ExtensionStates* extension_states); |
static void InstallSpecialObjects(Handle<Context> global_context); |
bool InstallJSBuiltins(Handle<JSBuiltinsObject> builtins); |
bool ConfigureApiObject(Handle<JSObject> object, |
@@ -1935,6 +1954,34 @@ void Genesis::InstallSpecialObjects(Handle<Context> global_context) { |
#endif |
} |
+static uint32_t Hash(RegisteredExtension* extension) { |
+ return v8::internal::ComputePointerHash(extension); |
+} |
+ |
+static bool MatchRegisteredExtensions(void* key1, void* key2) { |
+ return key1 == key2; |
+} |
+ |
+Genesis::ExtensionStates::ExtensionStates() |
+ : allocator_(), |
+ map_(MatchRegisteredExtensions, &allocator_, 8) |
+ {} |
+ |
+Genesis::ExtensionTraversalState Genesis::ExtensionStates::get_state( |
+ RegisteredExtension* extension) { |
+ i::HashMap::Entry* entry = map_.Lookup(extension, Hash(extension), false); |
+ if (entry == NULL) { |
+ return UNVISITED; |
+ } |
+ return static_cast<ExtensionTraversalState>( |
+ reinterpret_cast<intptr_t>(entry->value)); |
+} |
+ |
+void Genesis::ExtensionStates::set_state(RegisteredExtension* extension, |
+ ExtensionTraversalState state) { |
+ map_.Lookup(extension, Hash(extension), true)->value = |
+ reinterpret_cast<void*>(static_cast<intptr_t>(state)); |
+} |
bool Genesis::InstallExtensions(Handle<Context> global_context, |
v8::ExtensionConfiguration* extensions) { |
@@ -1942,29 +1989,26 @@ bool Genesis::InstallExtensions(Handle<Context> global_context, |
// effort. (The external API reads 'ignore'-- does that mean |
// we can break the interface?) |
- // Clear coloring of extension list |
- v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension(); |
- while (current != NULL) { |
- current->set_state(v8::UNVISITED); |
- current = current->next(); |
- } |
+ ExtensionStates extension_states; // All extensions have state UNVISITED. |
// Install auto extensions. |
- current = v8::RegisteredExtension::first_extension(); |
+ v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension(); |
while (current != NULL) { |
if (current->extension()->auto_enable()) |
- InstallExtension(current); |
+ InstallExtension(current, &extension_states); |
current = current->next(); |
} |
- if (FLAG_expose_gc) InstallExtension("v8/gc"); |
- if (FLAG_expose_externalize_string) InstallExtension("v8/externalize"); |
+ if (FLAG_expose_gc) InstallExtension("v8/gc", &extension_states); |
+ if (FLAG_expose_externalize_string) { |
+ InstallExtension("v8/externalize", &extension_states); |
+ } |
if (extensions == NULL) return true; |
// Install required extensions |
int count = v8::ImplementationUtilities::GetNameCount(extensions); |
const char** names = v8::ImplementationUtilities::GetNames(extensions); |
for (int i = 0; i < count; i++) { |
- if (!InstallExtension(names[i])) |
+ if (!InstallExtension(names[i], &extension_states)) |
return false; |
} |
@@ -1974,7 +2018,8 @@ bool Genesis::InstallExtensions(Handle<Context> global_context, |
// Installs a named extension. This methods is unoptimized and does |
// not scale well if we want to support a large number of extensions. |
-bool Genesis::InstallExtension(const char* name) { |
+bool Genesis::InstallExtension(const char* name, |
+ ExtensionStates* extension_states) { |
v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension(); |
// Loop until we find the relevant extension |
while (current != NULL) { |
@@ -1987,27 +2032,29 @@ bool Genesis::InstallExtension(const char* name) { |
"v8::Context::New()", "Cannot find required extension"); |
return false; |
} |
- return InstallExtension(current); |
+ return InstallExtension(current, extension_states); |
} |
-bool Genesis::InstallExtension(v8::RegisteredExtension* current) { |
+bool Genesis::InstallExtension(v8::RegisteredExtension* current, |
+ ExtensionStates* extension_states) { |
HandleScope scope; |
- if (current->state() == v8::INSTALLED) return true; |
+ if (extension_states->get_state(current) == INSTALLED) return true; |
// The current node has already been visited so there must be a |
// cycle in the dependency graph; fail. |
- if (current->state() == v8::VISITED) { |
+ if (extension_states->get_state(current) == VISITED) { |
v8::Utils::ReportApiFailure( |
"v8::Context::New()", "Circular extension dependency"); |
return false; |
} |
- ASSERT(current->state() == v8::UNVISITED); |
- current->set_state(v8::VISITED); |
+ ASSERT(extension_states->get_state(current) == UNVISITED); |
+ extension_states->set_state(current, VISITED); |
v8::Extension* extension = current->extension(); |
// Install the extension's dependencies |
for (int i = 0; i < extension->dependency_count(); i++) { |
- if (!InstallExtension(extension->dependencies()[i])) return false; |
+ if (!InstallExtension(extension->dependencies()[i], extension_states)) |
+ return false; |
} |
Isolate* isolate = Isolate::Current(); |
Handle<String> source_code = |
@@ -2029,7 +2076,8 @@ bool Genesis::InstallExtension(v8::RegisteredExtension* current) { |
current->extension()->name()); |
isolate->clear_pending_exception(); |
} |
- current->set_state(v8::INSTALLED); |
+ extension_states->set_state(current, INSTALLED); |
+ isolate->NotifyExtensionInstalled(); |
return result; |
} |