| Index: src/bootstrapper.cc
|
| ===================================================================
|
| --- src/bootstrapper.cc (revision 4215)
|
| +++ src/bootstrapper.cc (working copy)
|
| @@ -91,7 +91,6 @@
|
| DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
|
| };
|
|
|
| -static SourceCodeCache natives_cache(Script::TYPE_NATIVE);
|
| static SourceCodeCache extensions_cache(Script::TYPE_EXTENSION);
|
| // This is for delete, not delete[].
|
| static List<char*>* delete_these_non_arrays_on_tear_down = NULL;
|
| @@ -134,20 +133,7 @@
|
| }
|
|
|
|
|
| -bool Bootstrapper::NativesCacheLookup(Vector<const char> name,
|
| - Handle<SharedFunctionInfo>* handle) {
|
| - return natives_cache.Lookup(name, handle);
|
| -}
|
| -
|
| -
|
| -void Bootstrapper::NativesCacheAdd(Vector<const char> name,
|
| - Handle<SharedFunctionInfo> fun) {
|
| - natives_cache.Add(name, fun);
|
| -}
|
| -
|
| -
|
| void Bootstrapper::Initialize(bool create_heap_objects) {
|
| - natives_cache.Initialize(create_heap_objects);
|
| extensions_cache.Initialize(create_heap_objects);
|
| }
|
|
|
| @@ -187,8 +173,7 @@
|
| delete_these_arrays_on_tear_down = NULL;
|
| }
|
|
|
| - natives_cache.Initialize(false); // Yes, symmetrical
|
| - extensions_cache.Initialize(false);
|
| + extensions_cache.Initialize(false); // Yes, symmetrical
|
| }
|
|
|
|
|
| @@ -197,18 +182,12 @@
|
| Genesis(Handle<Object> global_object,
|
| v8::Handle<v8::ObjectTemplate> global_template,
|
| v8::ExtensionConfiguration* extensions);
|
| - ~Genesis();
|
| + ~Genesis() { }
|
|
|
| Handle<Context> result() { return result_; }
|
|
|
| Genesis* previous() { return previous_; }
|
| - static Genesis* current() { return current_; }
|
|
|
| - // Support for thread preemption.
|
| - static int ArchiveSpacePerThread();
|
| - static char* ArchiveState(char* to);
|
| - static char* RestoreState(char* from);
|
| -
|
| private:
|
| Handle<Context> global_context_;
|
|
|
| @@ -216,18 +195,46 @@
|
| // triggered during environment creation there may be weak handle
|
| // processing callbacks which may create new environments.
|
| Genesis* previous_;
|
| - static Genesis* current_;
|
|
|
| Handle<Context> global_context() { return global_context_; }
|
|
|
| - void CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
|
| - Handle<Object> global_object);
|
| + // Creates some basic objects. Used for creating a context from scratch.
|
| + void CreateRoots();
|
| + // Creates the empty function. Used for creating a context from scratch.
|
| + Handle<JSFunction> CreateEmptyFunction();
|
| + // Creates the global objects using the global and the template passed in
|
| + // through the API. We call this regardless of whether we are building a
|
| + // context from scratch or using a deserialized one from the partial snapshot
|
| + // but in the latter case we don't use the objects it produces directly, as
|
| + // we have to used the deserialized ones that are linked together with the
|
| + // rest of the context snapshot.
|
| + Handle<JSGlobalProxy> CreateNewGlobals(
|
| + v8::Handle<v8::ObjectTemplate> global_template,
|
| + Handle<Object> global_object,
|
| + Handle<GlobalObject>* global_proxy_out);
|
| + // Hooks the given global proxy into the context. If the context was created
|
| + // by deserialization then this will unhook the global proxy that was
|
| + // deserialized, leaving the GC to pick it up.
|
| + void HookUpGlobalProxy(Handle<GlobalObject> inner_global,
|
| + Handle<JSGlobalProxy> global_proxy);
|
| + // Similarly, we want to use the inner global that has been created by the
|
| + // templates passed through the API. The inner global from the snapshot is
|
| + // detached from the other objects in the snapshot.
|
| + void HookUpInnerGlobal(Handle<GlobalObject> inner_global);
|
| + // New context initialization. Used for creating a context from scratch.
|
| + void InitializeGlobal(Handle<GlobalObject> inner_global,
|
| + Handle<JSFunction> empty_function);
|
| + // Installs the contents of the native .js files on the global objects.
|
| + // Used for creating a context from scratch.
|
| void InstallNativeFunctions();
|
| bool InstallNatives();
|
| - bool InstallExtensions(v8::ExtensionConfiguration* extensions);
|
| - bool InstallExtension(const char* name);
|
| - bool InstallExtension(v8::RegisteredExtension* current);
|
| - bool InstallSpecialObjects();
|
| + // 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 void InstallSpecialObjects(Handle<Context> global_context);
|
| bool InstallJSBuiltins(Handle<JSBuiltinsObject> builtins);
|
| bool ConfigureApiObject(Handle<JSObject> object,
|
| Handle<ObjectTemplateInfo> object_template);
|
| @@ -251,33 +258,36 @@
|
| Handle<String> source,
|
| SourceCodeCache* cache,
|
| v8::Extension* extension,
|
| + Handle<Context> top_context,
|
| bool use_runtime_context);
|
|
|
| Handle<Context> result_;
|
| + Handle<JSFunction> empty_function_;
|
| + BootstrapperActive active_;
|
| + friend class Bootstrapper;
|
| };
|
|
|
| -Genesis* Genesis::current_ = NULL;
|
|
|
| -
|
| void Bootstrapper::Iterate(ObjectVisitor* v) {
|
| - natives_cache.Iterate(v);
|
| - v->Synchronize("NativesCache");
|
| extensions_cache.Iterate(v);
|
| v->Synchronize("Extensions");
|
| }
|
|
|
|
|
| -bool Bootstrapper::IsActive() {
|
| - return Genesis::current() != NULL;
|
| -}
|
| -
|
| -
|
| Handle<Context> Bootstrapper::CreateEnvironment(
|
| Handle<Object> global_object,
|
| v8::Handle<v8::ObjectTemplate> global_template,
|
| v8::ExtensionConfiguration* extensions) {
|
| + HandleScope scope;
|
| + Handle<Context> env;
|
| Genesis genesis(global_object, global_template, extensions);
|
| - return genesis.result();
|
| + env = genesis.result();
|
| + if (!env.is_null()) {
|
| + if (InstallExtensions(env, extensions)) {
|
| + return env;
|
| + }
|
| + }
|
| + return Handle<Context>();
|
| }
|
|
|
|
|
| @@ -299,12 +309,6 @@
|
| }
|
|
|
|
|
| -Genesis::~Genesis() {
|
| - ASSERT(current_ == this);
|
| - current_ = previous_;
|
| -}
|
| -
|
| -
|
| static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
|
| const char* name,
|
| InstanceType type,
|
| @@ -384,22 +388,7 @@
|
| }
|
|
|
|
|
| -void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
|
| - Handle<Object> global_object) {
|
| - HandleScope scope;
|
| - // Allocate the global context FixedArray first and then patch the
|
| - // closure and extension object later (we need the empty function
|
| - // and the global object, but in order to create those, we need the
|
| - // global context).
|
| - global_context_ =
|
| - Handle<Context>::cast(
|
| - GlobalHandles::Create(*Factory::NewGlobalContext()));
|
| - Top::set_context(*global_context());
|
| -
|
| - // Allocate the message listeners object.
|
| - v8::NeanderArray listeners;
|
| - global_context()->set_message_listeners(*listeners.value());
|
| -
|
| +Handle<JSFunction> Genesis::CreateEmptyFunction() {
|
| // Allocate the map for function instances.
|
| Handle<Map> fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
|
| global_context()->set_function_instance_map(*fm);
|
| @@ -443,138 +432,196 @@
|
| Handle<JSFunction> empty_function =
|
| Factory::NewFunction(symbol, Factory::null_value());
|
|
|
| - { // --- E m p t y ---
|
| - Handle<Code> code =
|
| - Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
|
| - empty_function->set_code(*code);
|
| - Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
|
| - Handle<Script> script = Factory::NewScript(source);
|
| - script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
|
| - empty_function->shared()->set_script(*script);
|
| - empty_function->shared()->set_start_position(0);
|
| - empty_function->shared()->set_end_position(source->length());
|
| - empty_function->shared()->DontAdaptArguments();
|
| - global_context()->function_map()->set_prototype(*empty_function);
|
| - global_context()->function_instance_map()->set_prototype(*empty_function);
|
| + // --- E m p t y ---
|
| + Handle<Code> code =
|
| + Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
|
| + empty_function->set_code(*code);
|
| + Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
|
| + Handle<Script> script = Factory::NewScript(source);
|
| + script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
|
| + empty_function->shared()->set_script(*script);
|
| + empty_function->shared()->set_start_position(0);
|
| + empty_function->shared()->set_end_position(source->length());
|
| + empty_function->shared()->DontAdaptArguments();
|
| + global_context()->function_map()->set_prototype(*empty_function);
|
| + global_context()->function_instance_map()->set_prototype(*empty_function);
|
|
|
| - // Allocate the function map first and then patch the prototype later
|
| - Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm);
|
| - empty_fm->set_instance_descriptors(*function_map_descriptors);
|
| - empty_fm->set_prototype(global_context()->object_function()->prototype());
|
| - empty_function->set_map(*empty_fm);
|
| + // Allocate the function map first and then patch the prototype later
|
| + Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm);
|
| + empty_fm->set_instance_descriptors(*function_map_descriptors);
|
| + empty_fm->set_prototype(global_context()->object_function()->prototype());
|
| + empty_function->set_map(*empty_fm);
|
| + return empty_function;
|
| +}
|
| +
|
| +
|
| +void Genesis::CreateRoots() {
|
| + // Allocate the global context FixedArray first and then patch the
|
| + // closure and extension object later (we need the empty function
|
| + // and the global object, but in order to create those, we need the
|
| + // global context).
|
| + global_context_ =
|
| + Handle<Context>::cast(
|
| + GlobalHandles::Create(*Factory::NewGlobalContext()));
|
| + Top::set_context(*global_context());
|
| +
|
| + // Allocate the message listeners object.
|
| + {
|
| + v8::NeanderArray listeners;
|
| + global_context()->set_message_listeners(*listeners.value());
|
| }
|
| +}
|
|
|
| - { // --- G l o b a l ---
|
| - // Step 1: create a fresh inner JSGlobalObject
|
| - Handle<GlobalObject> object;
|
| - {
|
| - Handle<JSFunction> js_global_function;
|
| - Handle<ObjectTemplateInfo> js_global_template;
|
| - if (!global_template.IsEmpty()) {
|
| - // Get prototype template of the global_template
|
| - Handle<ObjectTemplateInfo> data =
|
| - v8::Utils::OpenHandle(*global_template);
|
| - Handle<FunctionTemplateInfo> global_constructor =
|
| - Handle<FunctionTemplateInfo>(
|
| - FunctionTemplateInfo::cast(data->constructor()));
|
| - Handle<Object> proto_template(global_constructor->prototype_template());
|
| - if (!proto_template->IsUndefined()) {
|
| - js_global_template =
|
| - Handle<ObjectTemplateInfo>::cast(proto_template);
|
| - }
|
| - }
|
|
|
| - if (js_global_template.is_null()) {
|
| - Handle<String> name = Handle<String>(Heap::empty_symbol());
|
| - Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
|
| - js_global_function =
|
| - Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE,
|
| - JSGlobalObject::kSize, code, true);
|
| - // Change the constructor property of the prototype of the
|
| - // hidden global function to refer to the Object function.
|
| - Handle<JSObject> prototype =
|
| - Handle<JSObject>(
|
| - JSObject::cast(js_global_function->instance_prototype()));
|
| - SetProperty(prototype, Factory::constructor_symbol(),
|
| - Top::object_function(), NONE);
|
| - } else {
|
| - Handle<FunctionTemplateInfo> js_global_constructor(
|
| - FunctionTemplateInfo::cast(js_global_template->constructor()));
|
| - js_global_function =
|
| - Factory::CreateApiFunction(js_global_constructor,
|
| - Factory::InnerGlobalObject);
|
| - }
|
| -
|
| - js_global_function->initial_map()->set_is_hidden_prototype();
|
| - object = Factory::NewGlobalObject(js_global_function);
|
| +Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
|
| + v8::Handle<v8::ObjectTemplate> global_template,
|
| + Handle<Object> global_object,
|
| + Handle<GlobalObject>* inner_global_out) {
|
| + // The argument global_template aka data is an ObjectTemplateInfo.
|
| + // It has a constructor pointer that points at global_constructor which is a
|
| + // FunctionTemplateInfo.
|
| + // The global_constructor is used to create or reinitialize the global_proxy.
|
| + // The global_constructor also has a prototype_template pointer that points at
|
| + // js_global_template which is an ObjectTemplateInfo.
|
| + // That in turn has a constructor pointer that points at
|
| + // js_global_constructor which is a FunctionTemplateInfo.
|
| + // js_global_constructor is used to make js_global_function
|
| + // js_global_function is used to make the new inner_global.
|
| + //
|
| + // --- G l o b a l ---
|
| + // Step 1: Create a fresh inner JSGlobalObject.
|
| + Handle<JSFunction> js_global_function;
|
| + Handle<ObjectTemplateInfo> js_global_template;
|
| + if (!global_template.IsEmpty()) {
|
| + // Get prototype template of the global_template.
|
| + Handle<ObjectTemplateInfo> data =
|
| + v8::Utils::OpenHandle(*global_template);
|
| + Handle<FunctionTemplateInfo> global_constructor =
|
| + Handle<FunctionTemplateInfo>(
|
| + FunctionTemplateInfo::cast(data->constructor()));
|
| + Handle<Object> proto_template(global_constructor->prototype_template());
|
| + if (!proto_template->IsUndefined()) {
|
| + js_global_template =
|
| + Handle<ObjectTemplateInfo>::cast(proto_template);
|
| }
|
| + }
|
|
|
| - // Set the global context for the global object.
|
| - object->set_global_context(*global_context());
|
| + if (js_global_template.is_null()) {
|
| + Handle<String> name = Handle<String>(Heap::empty_symbol());
|
| + Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
|
| + js_global_function =
|
| + Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE,
|
| + JSGlobalObject::kSize, code, true);
|
| + // Change the constructor property of the prototype of the
|
| + // hidden global function to refer to the Object function.
|
| + Handle<JSObject> prototype =
|
| + Handle<JSObject>(
|
| + JSObject::cast(js_global_function->instance_prototype()));
|
| + SetProperty(prototype, Factory::constructor_symbol(),
|
| + Top::object_function(), NONE);
|
| + } else {
|
| + Handle<FunctionTemplateInfo> js_global_constructor(
|
| + FunctionTemplateInfo::cast(js_global_template->constructor()));
|
| + js_global_function =
|
| + Factory::CreateApiFunction(js_global_constructor,
|
| + Factory::InnerGlobalObject);
|
| + }
|
|
|
| - // Step 2: create or re-initialize the global proxy object.
|
| - Handle<JSGlobalProxy> global_proxy;
|
| - {
|
| - Handle<JSFunction> global_proxy_function;
|
| - if (global_template.IsEmpty()) {
|
| - Handle<String> name = Handle<String>(Heap::empty_symbol());
|
| - Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
|
| - global_proxy_function =
|
| - Factory::NewFunction(name, JS_GLOBAL_PROXY_TYPE,
|
| - JSGlobalProxy::kSize, code, true);
|
| - } else {
|
| - Handle<ObjectTemplateInfo> data =
|
| - v8::Utils::OpenHandle(*global_template);
|
| - Handle<FunctionTemplateInfo> global_constructor(
|
| - FunctionTemplateInfo::cast(data->constructor()));
|
| - global_proxy_function =
|
| - Factory::CreateApiFunction(global_constructor,
|
| - Factory::OuterGlobalObject);
|
| - }
|
| + js_global_function->initial_map()->set_is_hidden_prototype();
|
| + Handle<GlobalObject> inner_global =
|
| + Factory::NewGlobalObject(js_global_function);
|
| + if (inner_global_out != NULL) {
|
| + *inner_global_out = inner_global;
|
| + }
|
|
|
| - Handle<String> global_name = Factory::LookupAsciiSymbol("global");
|
| - global_proxy_function->shared()->set_instance_class_name(*global_name);
|
| - global_proxy_function->initial_map()->set_is_access_check_needed(true);
|
| + // Step 2: create or re-initialize the global proxy object.
|
| + Handle<JSFunction> global_proxy_function;
|
| + if (global_template.IsEmpty()) {
|
| + Handle<String> name = Handle<String>(Heap::empty_symbol());
|
| + Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
|
| + global_proxy_function =
|
| + Factory::NewFunction(name, JS_GLOBAL_PROXY_TYPE,
|
| + JSGlobalProxy::kSize, code, true);
|
| + } else {
|
| + Handle<ObjectTemplateInfo> data =
|
| + v8::Utils::OpenHandle(*global_template);
|
| + Handle<FunctionTemplateInfo> global_constructor(
|
| + FunctionTemplateInfo::cast(data->constructor()));
|
| + global_proxy_function =
|
| + Factory::CreateApiFunction(global_constructor,
|
| + Factory::OuterGlobalObject);
|
| + }
|
|
|
| - // Set global_proxy.__proto__ to js_global after ConfigureGlobalObjects
|
| + Handle<String> global_name = Factory::LookupAsciiSymbol("global");
|
| + global_proxy_function->shared()->set_instance_class_name(*global_name);
|
| + global_proxy_function->initial_map()->set_is_access_check_needed(true);
|
|
|
| - if (global_object.location() != NULL) {
|
| - ASSERT(global_object->IsJSGlobalProxy());
|
| - global_proxy =
|
| - ReinitializeJSGlobalProxy(
|
| - global_proxy_function,
|
| - Handle<JSGlobalProxy>::cast(global_object));
|
| - } else {
|
| - global_proxy = Handle<JSGlobalProxy>::cast(
|
| - Factory::NewJSObject(global_proxy_function, TENURED));
|
| - }
|
| + // Set global_proxy.__proto__ to js_global after ConfigureGlobalObjects
|
| + // Return the global proxy.
|
|
|
| - // Security setup: Set the security token of the global object to
|
| - // its the inner global. This makes the security check between two
|
| - // different contexts fail by default even in case of global
|
| - // object reinitialization.
|
| - object->set_global_receiver(*global_proxy);
|
| - global_proxy->set_context(*global_context());
|
| - }
|
| + if (global_object.location() != NULL) {
|
| + ASSERT(global_object->IsJSGlobalProxy());
|
| + return ReinitializeJSGlobalProxy(
|
| + global_proxy_function,
|
| + Handle<JSGlobalProxy>::cast(global_object));
|
| + } else {
|
| + return Handle<JSGlobalProxy>::cast(
|
| + Factory::NewJSObject(global_proxy_function, TENURED));
|
| + }
|
| +}
|
|
|
| - { // --- G l o b a l C o n t e x t ---
|
| - // use the empty function as closure (no scope info)
|
| - global_context()->set_closure(*empty_function);
|
| - global_context()->set_fcontext(*global_context());
|
| - global_context()->set_previous(NULL);
|
|
|
| - // set extension and global object
|
| - global_context()->set_extension(*object);
|
| - global_context()->set_global(*object);
|
| - global_context()->set_global_proxy(*global_proxy);
|
| - // use inner global object as security token by default
|
| - global_context()->set_security_token(*object);
|
| - }
|
| +void Genesis::HookUpGlobalProxy(Handle<GlobalObject> inner_global,
|
| + Handle<JSGlobalProxy> global_proxy) {
|
| + // Set the global context for the global object.
|
| + inner_global->set_global_context(*global_context());
|
| + inner_global->set_global_receiver(*global_proxy);
|
| + global_proxy->set_context(*global_context());
|
| + global_context()->set_global_proxy(*global_proxy);
|
| +}
|
|
|
| - Handle<JSObject> global = Handle<JSObject>(global_context()->global());
|
| - SetProperty(global, object_name, Top::object_function(), DONT_ENUM);
|
| - }
|
|
|
| +void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) {
|
| + Handle<GlobalObject> inner_global_from_snapshot(
|
| + GlobalObject::cast(global_context_->extension()));
|
| + Handle<JSBuiltinsObject> builtins_global(global_context_->builtins());
|
| + global_context_->set_extension(*inner_global);
|
| + global_context_->set_global(*inner_global);
|
| + global_context_->set_security_token(*inner_global);
|
| + static const PropertyAttributes attributes =
|
| + static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
|
| + ForceSetProperty(builtins_global,
|
| + Factory::LookupAsciiSymbol("global"),
|
| + inner_global,
|
| + attributes);
|
| + // Setup the reference from the global object to the builtins object.
|
| + JSGlobalObject::cast(*inner_global)->set_builtins(*builtins_global);
|
| + TransferNamedProperties(inner_global_from_snapshot, inner_global);
|
| + TransferIndexedProperties(inner_global_from_snapshot, inner_global);
|
| +}
|
| +
|
| +
|
| +// This is only called if we are not using snapshots. The equivalent
|
| +// work in the snapshot case is done in HookUpInnerGlobal.
|
| +void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
| + Handle<JSFunction> empty_function) {
|
| + // --- G l o b a l C o n t e x t ---
|
| + // Use the empty function as closure (no scope info).
|
| + global_context()->set_closure(*empty_function);
|
| + global_context()->set_fcontext(*global_context());
|
| + global_context()->set_previous(NULL);
|
| + // Set extension and global object.
|
| + global_context()->set_extension(*inner_global);
|
| + global_context()->set_global(*inner_global);
|
| + // Security setup: Set the security token of the global object to
|
| + // its the inner global. This makes the security check between two
|
| + // different contexts fail by default even in case of global
|
| + // object reinitialization.
|
| + global_context()->set_security_token(*inner_global);
|
| +
|
| + Handle<String> object_name = Handle<String>(Heap::Object_symbol());
|
| + SetProperty(inner_global, object_name, Top::object_function(), DONT_ENUM);
|
| +
|
| Handle<JSObject> global = Handle<JSObject>(global_context()->global());
|
|
|
| // Install global Function object
|
| @@ -791,8 +838,12 @@
|
| #ifdef ENABLE_DEBUGGER_SUPPORT
|
| Debugger::set_compiling_natives(true);
|
| #endif
|
| - bool result =
|
| - CompileScriptCached(name, source, &natives_cache, NULL, true);
|
| + bool result = CompileScriptCached(name,
|
| + source,
|
| + NULL,
|
| + NULL,
|
| + Handle<Context>(Top::context()),
|
| + true);
|
| ASSERT(Top::has_pending_exception() != result);
|
| if (!result) Top::clear_pending_exception();
|
| #ifdef ENABLE_DEBUGGER_SUPPORT
|
| @@ -806,13 +857,14 @@
|
| Handle<String> source,
|
| SourceCodeCache* cache,
|
| v8::Extension* extension,
|
| + Handle<Context> top_context,
|
| bool use_runtime_context) {
|
| HandleScope scope;
|
| Handle<SharedFunctionInfo> function_info;
|
|
|
| // If we can't find the function in the cache, we compile a new
|
| // function and insert it into the cache.
|
| - if (!cache->Lookup(name, &function_info)) {
|
| + if (cache == NULL || !cache->Lookup(name, &function_info)) {
|
| ASSERT(source->IsAsciiRepresentation());
|
| Handle<String> script_name = Factory::NewStringFromUtf8(name);
|
| function_info = Compiler::Compile(
|
| @@ -825,17 +877,17 @@
|
| Handle<String>::null(),
|
| use_runtime_context ? NATIVES_CODE : NOT_NATIVES_CODE);
|
| if (function_info.is_null()) return false;
|
| - cache->Add(name, function_info);
|
| + if (cache != NULL) cache->Add(name, function_info);
|
| }
|
|
|
| // Setup the function context. Conceptually, we should clone the
|
| // function before overwriting the context but since we're in a
|
| // single-threaded environment it is not strictly necessary.
|
| - ASSERT(Top::context()->IsGlobalContext());
|
| + ASSERT(top_context->IsGlobalContext());
|
| Handle<Context> context =
|
| Handle<Context>(use_runtime_context
|
| - ? Top::context()->runtime_context()
|
| - : Top::context());
|
| + ? Handle<Context>(top_context->runtime_context())
|
| + : top_context);
|
| Handle<JSFunction> fun =
|
| Factory::NewFunctionFromSharedFunctionInfo(function_info, context);
|
|
|
| @@ -843,8 +895,8 @@
|
| // object as the receiver. Provide no parameters.
|
| Handle<Object> receiver =
|
| Handle<Object>(use_runtime_context
|
| - ? Top::context()->builtins()
|
| - : Top::context()->global());
|
| + ? top_context->builtins()
|
| + : top_context->global());
|
| bool has_pending_exception;
|
| Handle<Object> result =
|
| Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
|
| @@ -1046,7 +1098,7 @@
|
| // Allocate the empty script.
|
| Handle<Script> script = Factory::NewScript(Factory::empty_string());
|
| script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
|
| - global_context()->set_empty_script(*script);
|
| + Heap::public_set_empty_script(*script);
|
| }
|
| {
|
| // Builtin function for OpaqueReference -- a JSValue-based object,
|
| @@ -1062,46 +1114,16 @@
|
| global_context()->set_opaque_reference_function(*opaque_reference_fun);
|
| }
|
|
|
| - if (FLAG_natives_file == NULL) {
|
| - // Without natives file, install default natives.
|
| - for (int i = Natives::GetDelayCount();
|
| - i < Natives::GetBuiltinsCount();
|
| - i++) {
|
| - if (!CompileBuiltin(i)) return false;
|
| - // TODO(ager): We really only need to install the JS builtin
|
| - // functions on the builtins object after compiling and running
|
| - // runtime.js.
|
| - if (!InstallJSBuiltins(builtins)) return false;
|
| - }
|
| -
|
| - // Setup natives with lazy loading.
|
| - SetupLazy(Handle<JSFunction>(global_context()->date_function()),
|
| - Natives::GetIndex("date"),
|
| - Top::global_context(),
|
| - Handle<Context>(Top::context()->runtime_context()));
|
| - SetupLazy(Handle<JSFunction>(global_context()->regexp_function()),
|
| - Natives::GetIndex("regexp"),
|
| - Top::global_context(),
|
| - Handle<Context>(Top::context()->runtime_context()));
|
| - SetupLazy(Handle<JSObject>(global_context()->json_object()),
|
| - Natives::GetIndex("json"),
|
| - Top::global_context(),
|
| - Handle<Context>(Top::context()->runtime_context()));
|
| -
|
| - } else if (strlen(FLAG_natives_file) != 0) {
|
| - // Otherwise install natives from natives file if file exists and
|
| - // compiles.
|
| - bool exists;
|
| - Vector<const char> source = ReadFile(FLAG_natives_file, &exists);
|
| - Handle<String> source_string = Factory::NewStringFromAscii(source);
|
| - if (source.is_empty()) return false;
|
| - bool result = CompileNative(CStrVector(FLAG_natives_file), source_string);
|
| - if (!result) return false;
|
| -
|
| - } else {
|
| - // Empty natives file name - do not install any natives.
|
| - PrintF("Warning: Running without installed natives!\n");
|
| - return true;
|
| + // Install natives.
|
| + for (int i = Natives::GetDebuggerCount();
|
| + i < Natives::GetBuiltinsCount();
|
| + i++) {
|
| + Vector<const char> name = Natives::GetScriptName(i);
|
| + if (!CompileBuiltin(i)) return false;
|
| + // TODO(ager): We really only need to install the JS builtin
|
| + // functions on the builtins object after compiling and running
|
| + // runtime.js.
|
| + if (!InstallJSBuiltins(builtins)) return false;
|
| }
|
|
|
| InstallNativeFunctions();
|
| @@ -1142,14 +1164,29 @@
|
| #ifdef DEBUG
|
| builtins->Verify();
|
| #endif
|
| +
|
| return true;
|
| }
|
|
|
|
|
| -bool Genesis::InstallSpecialObjects() {
|
| +int BootstrapperActive::nesting_ = 0;
|
| +
|
| +
|
| +bool Bootstrapper::InstallExtensions(Handle<Context> global_context,
|
| + v8::ExtensionConfiguration* extensions) {
|
| + BootstrapperActive active;
|
| + SaveContext saved_context;
|
| + Top::set_context(*global_context);
|
| + if (!Genesis::InstallExtensions(global_context, extensions)) return false;
|
| + Genesis::InstallSpecialObjects(global_context);
|
| + return true;
|
| +}
|
| +
|
| +
|
| +void Genesis::InstallSpecialObjects(Handle<Context> global_context) {
|
| HandleScope scope;
|
| Handle<JSGlobalObject> js_global(
|
| - JSGlobalObject::cast(global_context()->global()));
|
| + JSGlobalObject::cast(global_context->global()));
|
| // Expose the natives in global if a name for it is specified.
|
| if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
|
| Handle<String> natives_string =
|
| @@ -1172,13 +1209,12 @@
|
| if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) {
|
| // If loading fails we just bail out without installing the
|
| // debugger but without tanking the whole context.
|
| - if (!Debug::Load())
|
| - return true;
|
| + if (!Debug::Load()) return;
|
| // Set the security token for the debugger context to the same as
|
| // the shell global context to allow calling between these (otherwise
|
| // exposing debug global object doesn't make much sense).
|
| Debug::debug_context()->set_security_token(
|
| - global_context()->security_token());
|
| + global_context->security_token());
|
|
|
| Handle<String> debug_string =
|
| Factory::LookupAsciiSymbol(FLAG_expose_debug_as);
|
| @@ -1186,19 +1222,18 @@
|
| Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
|
| }
|
| #endif
|
| -
|
| - return true;
|
| }
|
|
|
|
|
| -bool Genesis::InstallExtensions(v8::ExtensionConfiguration* extensions) {
|
| +bool Genesis::InstallExtensions(Handle<Context> global_context,
|
| + v8::ExtensionConfiguration* extensions) {
|
| // Clear coloring of extension list
|
| v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
|
| while (current != NULL) {
|
| current->set_state(v8::UNVISITED);
|
| current = current->next();
|
| }
|
| - // Install auto extensions
|
| + // Install auto extensions.
|
| current = v8::RegisteredExtension::first_extension();
|
| while (current != NULL) {
|
| if (current->extension()->auto_enable())
|
| @@ -1262,7 +1297,9 @@
|
| Handle<String> source_code = Factory::NewStringFromAscii(source);
|
| bool result = CompileScriptCached(CStrVector(extension->name()),
|
| source_code,
|
| - &extensions_cache, extension,
|
| + &extensions_cache,
|
| + extension,
|
| + Handle<Context>(Top::context()),
|
| false);
|
| ASSERT(Top::has_pending_exception() != result);
|
| if (!result) {
|
| @@ -1293,7 +1330,7 @@
|
| v8::Handle<v8::ObjectTemplate> global_proxy_template) {
|
| Handle<JSObject> global_proxy(
|
| JSObject::cast(global_context()->global_proxy()));
|
| - Handle<JSObject> js_global(JSObject::cast(global_context()->global()));
|
| + Handle<JSObject> inner_global(JSObject::cast(global_context()->global()));
|
|
|
| if (!global_proxy_template.IsEmpty()) {
|
| // Configure the global proxy object.
|
| @@ -1307,11 +1344,11 @@
|
| if (!proxy_constructor->prototype_template()->IsUndefined()) {
|
| Handle<ObjectTemplateInfo> inner_data(
|
| ObjectTemplateInfo::cast(proxy_constructor->prototype_template()));
|
| - if (!ConfigureApiObject(js_global, inner_data)) return false;
|
| + if (!ConfigureApiObject(inner_global, inner_data)) return false;
|
| }
|
| }
|
|
|
| - SetObjectPrototype(global_proxy, js_global);
|
| + SetObjectPrototype(global_proxy, inner_global);
|
| return true;
|
| }
|
|
|
| @@ -1365,15 +1402,13 @@
|
| // If the property is already there we skip it
|
| if (result.IsProperty()) continue;
|
| HandleScope inner;
|
| - Handle<DescriptorArray> inst_descs =
|
| - Handle<DescriptorArray>(to->map()->instance_descriptors());
|
| + ASSERT(!to->HasFastProperties());
|
| + // Add to dictionary.
|
| Handle<String> key = Handle<String>(descs->GetKey(i));
|
| - Handle<Object> entry = Handle<Object>(descs->GetCallbacksObject(i));
|
| - inst_descs = Factory::CopyAppendProxyDescriptor(inst_descs,
|
| - key,
|
| - entry,
|
| - details.attributes());
|
| - to->map()->set_instance_descriptors(*inst_descs);
|
| + Handle<Object> callbacks(descs->GetCallbacksObject(i));
|
| + PropertyDetails d =
|
| + PropertyDetails(details.attributes(), CALLBACKS, details.index());
|
| + SetNormalizedProperty(to, key, callbacks, d);
|
| break;
|
| }
|
| case MAP_TRANSITION:
|
| @@ -1458,33 +1493,52 @@
|
| Genesis::Genesis(Handle<Object> global_object,
|
| v8::Handle<v8::ObjectTemplate> global_template,
|
| v8::ExtensionConfiguration* extensions) {
|
| - // Link this genesis object into the stacked genesis chain. This
|
| - // must be done before any early exits because the destructor
|
| - // will always do unlinking.
|
| - previous_ = current_;
|
| - current_ = this;
|
| result_ = Handle<Context>::null();
|
| -
|
| // If V8 isn't running and cannot be initialized, just return.
|
| if (!V8::IsRunning() && !V8::Initialize(NULL)) return;
|
|
|
| // Before creating the roots we must save the context and restore it
|
| // on all function exits.
|
| HandleScope scope;
|
| - SaveContext context;
|
| + SaveContext saved_context;
|
|
|
| - CreateRoots(global_template, global_object);
|
| + Handle<Context> new_context = Snapshot::NewContextFromSnapshot();
|
| + if (!new_context.is_null()) {
|
| + global_context_ =
|
| + Handle<Context>::cast(GlobalHandles::Create(*new_context));
|
| + Top::set_context(*global_context_);
|
| + i::Counters::contexts_created_by_snapshot.Increment();
|
| + result_ = global_context_;
|
| + JSFunction* empty_function =
|
| + JSFunction::cast(result_->function_map()->prototype());
|
| + empty_function_ = Handle<JSFunction>(empty_function);
|
| + Handle<GlobalObject> inner_global;
|
| + Handle<JSGlobalProxy> global_proxy =
|
| + CreateNewGlobals(global_template,
|
| + global_object,
|
| + &inner_global);
|
|
|
| - if (!InstallNatives()) return;
|
| + HookUpGlobalProxy(inner_global, global_proxy);
|
| + HookUpInnerGlobal(inner_global);
|
|
|
| - MakeFunctionInstancePrototypeWritable();
|
| + if (!ConfigureGlobalObjects(global_template)) return;
|
| + } else {
|
| + // We get here if there was no context snapshot.
|
| + CreateRoots();
|
| + Handle<JSFunction> empty_function = CreateEmptyFunction();
|
| + Handle<GlobalObject> inner_global;
|
| + Handle<JSGlobalProxy> global_proxy =
|
| + CreateNewGlobals(global_template, global_object, &inner_global);
|
| + HookUpGlobalProxy(inner_global, global_proxy);
|
| + InitializeGlobal(inner_global, empty_function);
|
| + if (!InstallNatives()) return;
|
|
|
| - if (!ConfigureGlobalObjects(global_template)) return;
|
| + MakeFunctionInstancePrototypeWritable();
|
|
|
| - if (!InstallExtensions(extensions)) return;
|
| + if (!ConfigureGlobalObjects(global_template)) return;
|
| + i::Counters::contexts_created_from_scratch.Increment();
|
| + }
|
|
|
| - if (!InstallSpecialObjects()) return;
|
| -
|
| result_ = global_context_;
|
| }
|
|
|
| @@ -1493,46 +1547,46 @@
|
|
|
| // Reserve space for statics needing saving and restoring.
|
| int Bootstrapper::ArchiveSpacePerThread() {
|
| - return Genesis::ArchiveSpacePerThread();
|
| + return BootstrapperActive::ArchiveSpacePerThread();
|
| }
|
|
|
|
|
| // Archive statics that are thread local.
|
| char* Bootstrapper::ArchiveState(char* to) {
|
| - return Genesis::ArchiveState(to);
|
| + return BootstrapperActive::ArchiveState(to);
|
| }
|
|
|
|
|
| // Restore statics that are thread local.
|
| char* Bootstrapper::RestoreState(char* from) {
|
| - return Genesis::RestoreState(from);
|
| + return BootstrapperActive::RestoreState(from);
|
| }
|
|
|
|
|
| // Called when the top-level V8 mutex is destroyed.
|
| void Bootstrapper::FreeThreadResources() {
|
| - ASSERT(Genesis::current() == NULL);
|
| + ASSERT(!BootstrapperActive::IsActive());
|
| }
|
|
|
|
|
| // Reserve space for statics needing saving and restoring.
|
| -int Genesis::ArchiveSpacePerThread() {
|
| - return sizeof(current_);
|
| +int BootstrapperActive::ArchiveSpacePerThread() {
|
| + return sizeof(nesting_);
|
| }
|
|
|
|
|
| // Archive statics that are thread local.
|
| -char* Genesis::ArchiveState(char* to) {
|
| - *reinterpret_cast<Genesis**>(to) = current_;
|
| - current_ = NULL;
|
| - return to + sizeof(current_);
|
| +char* BootstrapperActive::ArchiveState(char* to) {
|
| + *reinterpret_cast<int*>(to) = nesting_;
|
| + nesting_ = 0;
|
| + return to + sizeof(nesting_);
|
| }
|
|
|
|
|
| // Restore statics that are thread local.
|
| -char* Genesis::RestoreState(char* from) {
|
| - current_ = *reinterpret_cast<Genesis**>(from);
|
| - return from + sizeof(current_);
|
| +char* BootstrapperActive::RestoreState(char* from) {
|
| + nesting_ = *reinterpret_cast<int*>(from);
|
| + return from + sizeof(nesting_);
|
| }
|
|
|
| } } // namespace v8::internal
|
|
|