Chromium Code Reviews| Index: src/bootstrapper.cc |
| diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc |
| index 6735ff454933f0933f4b3a3b15e4b035625be565..d60a52b88d09ca9f4185d7951001c38acd831623 100644 |
| --- a/src/bootstrapper.cc |
| +++ b/src/bootstrapper.cc |
| @@ -211,12 +211,28 @@ class Genesis BASE_EMBEDDED { |
| void InstallBuiltinFunctionIds(); |
| void InstallJSFunctionResultCaches(); |
| void InitializeNormalizedMapCaches(); |
| + enum ExtensionTraversalState { |
|
Vitaly Repeshko
2011/11/15 22:13:02
nit: Insert a blank line.
|
| + UNVISITED, VISITED, INSTALLED |
| + }; |
| + |
| + class ExtensionStates { |
| + public: |
| + ExtensionStates(); |
| + ExtensionTraversalState get_state(RegisteredExtension* extension); |
| + void set_state(RegisteredExtension* extension, |
| + ExtensionTraversalState state); |
| + private: |
| + HashMap map_; |
| + }; |
|
Vitaly Repeshko
2011/11/15 22:13:02
nit: DISALLOW_COPY_AND_ASSIGN.
|
| + |
| // 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 +1951,39 @@ void Genesis::InstallSpecialObjects(Handle<Context> global_context) { |
| #endif |
| } |
| +static uint32_t Hash(RegisteredExtension* extension) { |
| + return v8::internal::ComputeIntegerHash( |
|
Vitaly Repeshko
2011/11/15 22:13:02
Oh, actually there's already ComputePointerHash in
|
| + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(extension))); |
| +} |
| + |
| +static bool MatchRegisteredExtensions(void* key1, void* key2) { |
| + return key1 == key2; |
| +} |
| + |
| +static Allocator* ExtensionStatesAllocator() { |
| + static Allocator default_allocator; |
| + return &default_allocator; |
| +} |
| + |
| +Genesis::ExtensionStates::ExtensionStates() |
| + : map_(MatchRegisteredExtensions, ExtensionStatesAllocator(), 8) |
|
Vitaly Repeshko
2011/11/15 22:13:02
... and does the default allocator (if you omit ar
|
| + {} |
| + |
| +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, |
| + Genesis::ExtensionTraversalState state) { |
|
Vitaly Repeshko
2011/11/15 22:13:02
nit: Formatting.
|
| + 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 +1991,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 +2020,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 +2034,28 @@ 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) { |
|
Vitaly Repeshko
2011/11/15 22:13:02
nit: Formatting.
|
| 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 +2077,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->extension_installed(); |
| return result; |
| } |