| Index: src/bootstrapper.cc
 | 
| ===================================================================
 | 
| --- src/bootstrapper.cc	(revision 539)
 | 
| +++ src/bootstrapper.cc	(working copy)
 | 
| @@ -275,7 +275,9 @@
 | 
|    bool InstallExtension(const char* name);
 | 
|    bool InstallExtension(v8::RegisteredExtension* current);
 | 
|    bool InstallSpecialObjects();
 | 
| -  bool ConfigureGlobalObject(v8::Handle<v8::ObjectTemplate> global_template);
 | 
| +  bool ConfigureApiObject(Handle<JSObject> object,
 | 
| +                          Handle<ObjectTemplateInfo> object_template);
 | 
| +  bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template);
 | 
|  
 | 
|    // Migrates all properties from the 'from' object to the 'to'
 | 
|    // object and overrides the prototype in 'to' with the one from
 | 
| @@ -337,11 +339,30 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
 | 
| +  // object.__proto__ = proto;
 | 
| +  Handle<Map> old_to_map = Handle<Map>(object->map());
 | 
| +  Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
 | 
| +  new_to_map->set_prototype(*proto);
 | 
| +  object->set_map(*new_to_map);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Bootstrapper::DetachGlobal(Handle<Context> env) {
 | 
| +  JSGlobalProxy::cast(env->global_proxy())->set_context(*Factory::null_value());
 | 
| +  SetObjectPrototype(Handle<JSObject>(env->global_proxy()),
 | 
| +                     Factory::null_value());
 | 
| +  env->set_global_proxy(env->global());
 | 
| +  env->global()->set_global_receiver(env->global());
 | 
| +}
 | 
| +
 | 
| +
 | 
|  Genesis::~Genesis() {
 | 
|    ASSERT(current_ == this);
 | 
|    current_ = previous_;
 | 
|  }
 | 
|  
 | 
| +
 | 
|  static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
 | 
|                                            const char* name,
 | 
|                                            InstanceType type,
 | 
| @@ -431,7 +452,6 @@
 | 
|    global_context_ =
 | 
|        Handle<Context>::cast(
 | 
|            GlobalHandles::Create(*Factory::NewGlobalContext()));
 | 
| -  Top::set_security_context(*global_context());
 | 
|    Top::set_context(*global_context());
 | 
|  
 | 
|    // Allocate the message listeners object.
 | 
| @@ -506,55 +526,101 @@
 | 
|    }
 | 
|  
 | 
|    {  // --- G l o b a l ---
 | 
| -    Handle<String> global_name = Factory::LookupAsciiSymbol("global");
 | 
| -    Handle<JSFunction> global_function;
 | 
|  
 | 
| -    if (global_template.IsEmpty()) {
 | 
| -      Handle<String> name = Handle<String>(Heap::empty_symbol());
 | 
| -      Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
 | 
| -      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(global_function->instance_prototype()));
 | 
| -      SetProperty(prototype, Factory::constructor_symbol(),
 | 
| -                  Top::object_function(), NONE);
 | 
| -    } else {
 | 
| -      Handle<ObjectTemplateInfo> data = v8::Utils::OpenHandle(*global_template);
 | 
| -      Handle<FunctionTemplateInfo> global_constructor =
 | 
| -          Handle<FunctionTemplateInfo>(
 | 
| -              FunctionTemplateInfo::cast(data->constructor()));
 | 
| -      global_function = Factory::CreateApiFunction(global_constructor, true);
 | 
| -    }
 | 
| +    // Step 1: create a fresh inner JSGlobalObject
 | 
| +    Handle<JSGlobalObject> 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);
 | 
| +        } 
 | 
| +      }
 | 
|  
 | 
| -    SetExpectedNofProperties(global_function, 100);
 | 
| -    global_function->shared()->set_instance_class_name(*global_name);
 | 
| -    global_function->initial_map()->set_needs_access_check();
 | 
| +      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);
 | 
| +      }
 | 
|  
 | 
| -    Handle<JSGlobalObject> object;
 | 
| -    if (global_object.location() != NULL) {
 | 
| -      ASSERT(global_object->IsJSGlobalObject());
 | 
| -      object =
 | 
| -          ReinitializeJSGlobalObject(
 | 
| -              global_function,
 | 
| -              Handle<JSGlobalObject>::cast(global_object));
 | 
| -    } else {
 | 
| -      object =
 | 
| -          Handle<JSGlobalObject>::cast(Factory::NewJSObject(global_function,
 | 
| -                                                            TENURED));
 | 
| +      js_global_function->initial_map()->set_is_hidden_prototype();
 | 
| +      SetExpectedNofProperties(js_global_function, 100);
 | 
| +      object = Handle<JSGlobalObject>::cast(
 | 
| +          Factory::NewJSObject(js_global_function, TENURED));
 | 
|      }
 | 
|  
 | 
|      // Set the global context for the global object.
 | 
|      object->set_global_context(*global_context());
 | 
|  
 | 
| -    // Security setup: Set the security token of the global object to
 | 
| -    // its global context. This makes the security check between two
 | 
| -    // different contexts fail by default even in case of global
 | 
| -    // object reinitialization.
 | 
| -    object->set_security_token(*global_context());
 | 
| +    // Step 2: create or re-initialize the outer global 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);
 | 
| +      }
 | 
|  
 | 
| +      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();
 | 
| +
 | 
| +      // Set global_proxy.__proto__ to js_global after ConfigureGlobalObjects
 | 
| +
 | 
| +      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));
 | 
| +      }
 | 
| +
 | 
| +      // 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());
 | 
| +    }
 | 
| +
 | 
|      {  // --- 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);
 | 
| @@ -564,6 +630,9 @@
 | 
|        // 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);
 | 
|      }
 | 
|  
 | 
|      Handle<JSObject> global = Handle<JSObject>(global_context()->global());
 | 
| @@ -835,6 +904,7 @@
 | 
|                                                            TENURED));
 | 
|    builtins->set_builtins(*builtins);
 | 
|    builtins->set_global_context(*global_context());
 | 
| +  builtins->set_global_receiver(*builtins);
 | 
|  
 | 
|    // Setup the 'global' properties of the builtins object. The
 | 
|    // 'global' property that refers to the global object is the only
 | 
| @@ -932,13 +1002,11 @@
 | 
|      SetupLazy(Handle<JSFunction>(global_context()->date_function()),
 | 
|                Natives::GetIndex("date"),
 | 
|                Top::global_context(),
 | 
| -              Handle<Context>(Top::context()->runtime_context()),
 | 
| -              Handle<Context>(Top::security_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()),
 | 
| -              Handle<Context>(Top::security_context()));
 | 
| +              Handle<Context>(Top::context()->runtime_context()));
 | 
|  
 | 
|    } else if (strlen(FLAG_natives_file) != 0) {
 | 
|      // Otherwise install natives from natives file if file exists and
 | 
| @@ -1004,14 +1072,14 @@
 | 
|  
 | 
|  bool Genesis::InstallSpecialObjects() {
 | 
|    HandleScope scope;
 | 
| -  Handle<JSGlobalObject> global(
 | 
| +  Handle<JSGlobalObject> js_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 =
 | 
|          Factory::LookupAsciiSymbol(FLAG_expose_natives_as);
 | 
| -    SetProperty(global, natives_string,
 | 
| -                Handle<JSObject>(global->builtins()), DONT_ENUM);
 | 
| +    SetProperty(js_global, natives_string,
 | 
| +                Handle<JSObject>(js_global->builtins()), DONT_ENUM);
 | 
|    }
 | 
|  
 | 
|    // Expose the debug global object in global if a name for it is specified.
 | 
| @@ -1020,18 +1088,16 @@
 | 
|      // debugger but without tanking the whole context.
 | 
|      if (!Debug::Load())
 | 
|        return true;
 | 
| -    Handle<JSGlobalObject> debug_global =
 | 
| -        Handle<JSGlobalObject>(
 | 
| -            JSGlobalObject::cast(Debug::debug_context()->global()));
 | 
| +    // 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());
 | 
| +
 | 
|      Handle<String> debug_string =
 | 
|          Factory::LookupAsciiSymbol(FLAG_expose_debug_as);
 | 
| -    SetProperty(global, debug_string,
 | 
| -                Handle<JSObject>(debug_global), DONT_ENUM);
 | 
| -
 | 
| -    // Set the security token for the debugger global object to the same as
 | 
| -    // the shell global object to allow calling between these (otherwise
 | 
| -    // exposing debug global object doesn't make much sense).
 | 
| -    debug_global->set_security_token(global->security_token());
 | 
| +    SetProperty(js_global, debug_string,
 | 
| +        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
 | 
|    }
 | 
|  
 | 
|    return true;
 | 
| @@ -1122,25 +1188,52 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| -bool Genesis::ConfigureGlobalObject(
 | 
| -    v8::Handle<v8::ObjectTemplate> global_template) {
 | 
| -  Handle<JSObject> global = Handle<JSObject>(global_context()->global());
 | 
| -  if (!global_template.IsEmpty()) {
 | 
| -    Handle<ObjectTemplateInfo> data = v8::Utils::OpenHandle(*global_template);
 | 
| -    bool pending_exception = false;
 | 
| -    Handle<JSObject> obj =
 | 
| -        Execution::InstantiateObject(data, &pending_exception);
 | 
| -    if (pending_exception) {
 | 
| -      ASSERT(Top::has_pending_exception());
 | 
| -      Top::clear_pending_exception();
 | 
| -      return false;
 | 
| +bool Genesis::ConfigureGlobalObjects(
 | 
| +    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()));
 | 
| +
 | 
| +  if (!global_proxy_template.IsEmpty()) {
 | 
| +    // Configure the outer global object. 
 | 
| +    Handle<ObjectTemplateInfo> outer_data =
 | 
| +        v8::Utils::OpenHandle(*global_proxy_template);
 | 
| +    if (!ConfigureApiObject(global_proxy, outer_data)) return false;
 | 
| +
 | 
| +    // Configure the inner global object.
 | 
| +    Handle<FunctionTemplateInfo> outer_constructor(
 | 
| +        FunctionTemplateInfo::cast(outer_data->constructor()));
 | 
| +    if (!outer_constructor->prototype_template()->IsUndefined()) {
 | 
| +      Handle<ObjectTemplateInfo> inner_data( 
 | 
| +          ObjectTemplateInfo::cast(outer_constructor->prototype_template()));
 | 
| +      if (!ConfigureApiObject(js_global, inner_data)) return false;
 | 
|      }
 | 
| -    TransferObject(obj, global);
 | 
|    }
 | 
| +
 | 
| +  SetObjectPrototype(global_proxy, js_global);
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| + 
 | 
| +bool Genesis::ConfigureApiObject(Handle<JSObject> object,
 | 
| +    Handle<ObjectTemplateInfo> object_template) {
 | 
| +  ASSERT(!object_template.is_null());
 | 
| +  ASSERT(object->IsInstanceOf(
 | 
| +      FunctionTemplateInfo::cast(object_template->constructor())));
 | 
|  
 | 
| +  bool pending_exception = false;
 | 
| +  Handle<JSObject> obj =
 | 
| +      Execution::InstantiateObject(object_template, &pending_exception);
 | 
| +  if (pending_exception) {
 | 
| +    ASSERT(Top::has_pending_exception());
 | 
| +    Top::clear_pending_exception();
 | 
| +    return false;
 | 
| +  }
 | 
| +  TransferObject(obj, object);
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void Genesis::TransferNamedProperties(Handle<JSObject> from,
 | 
|                                        Handle<JSObject> to) {
 | 
|    if (from->HasFastProperties()) {
 | 
| @@ -1331,8 +1424,9 @@
 | 
|  
 | 
|    MakeFunctionInstancePrototypeWritable();
 | 
|    BuildSpecialFunctionTable();
 | 
| -  if (!ConfigureGlobalObject(global_template)) return;
 | 
|  
 | 
| +  if (!ConfigureGlobalObjects(global_template)) return;
 | 
| +
 | 
|    if (!InstallExtensions(extensions)) return;
 | 
|  
 | 
|    if (!InstallSpecialObjects()) return;
 | 
| 
 |