| Index: src/macro-assembler-ia32.cc
 | 
| ===================================================================
 | 
| --- src/macro-assembler-ia32.cc	(revision 539)
 | 
| +++ src/macro-assembler-ia32.cc	(working copy)
 | 
| @@ -469,7 +469,7 @@
 | 
|  
 | 
|      // Only global objects and objects that do not require access
 | 
|      // checks are allowed in stubs.
 | 
| -    ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
 | 
| +    ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 | 
|  
 | 
|      JSObject* prototype = JSObject::cast(object->GetPrototype());
 | 
|      if (Heap::InNewSpace(prototype)) {
 | 
| @@ -481,16 +481,18 @@
 | 
|        // Check access rights to the global object.  This has to happen
 | 
|        // after the map check so that we know that the object is
 | 
|        // actually a global object.
 | 
| -      if (object->IsJSGlobalObject()) {
 | 
| -        CheckAccessGlobal(reg, scratch, miss);
 | 
| -        // Restore scratch register to be the map of the object.  We
 | 
| -        // load the prototype from the map in the scratch register.
 | 
| +      if (object->IsJSGlobalProxy()) {
 | 
| +        CheckAccessGlobalProxy(reg, scratch, miss);
 | 
| +
 | 
| +        // Restore scratch register to be the map of the object.
 | 
| +        // We load the prototype from the map in the scratch register.
 | 
|          mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
 | 
|        }
 | 
|        // The prototype is in new space; we cannot store a reference
 | 
|        // to it in the code. Load it from the map.
 | 
|        reg = holder_reg;  // from now the object is in holder_reg
 | 
|        mov(reg, FieldOperand(scratch, Map::kPrototypeOffset));
 | 
| +
 | 
|      } else {
 | 
|        // Check the map of the current object.
 | 
|        cmp(FieldOperand(reg, HeapObject::kMapOffset),
 | 
| @@ -500,8 +502,8 @@
 | 
|        // Check access rights to the global object.  This has to happen
 | 
|        // after the map check so that we know that the object is
 | 
|        // actually a global object.
 | 
| -      if (object->IsJSGlobalObject()) {
 | 
| -        CheckAccessGlobal(reg, scratch, miss);
 | 
| +      if (object->IsJSGlobalProxy()) {
 | 
| +        CheckAccessGlobalProxy(reg, scratch, miss);
 | 
|        }
 | 
|        // The prototype is in old space; load it directly.
 | 
|        reg = holder_reg;  // from now the object is in holder_reg
 | 
| @@ -523,37 +525,79 @@
 | 
|    // Perform security check for access to the global object and return
 | 
|    // the holder register.
 | 
|    ASSERT(object == holder);
 | 
| -  ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
 | 
| -  if (object->IsJSGlobalObject()) {
 | 
| -    CheckAccessGlobal(reg, scratch, miss);
 | 
| +  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 | 
| +  if (object->IsJSGlobalProxy()) {
 | 
| +    CheckAccessGlobalProxy(reg, scratch, miss);
 | 
|    }
 | 
|    return reg;
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void MacroAssembler::CheckAccessGlobal(Register holder_reg,
 | 
| -                                       Register scratch,
 | 
| -                                       Label* miss) {
 | 
| +void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
 | 
| +                                          Register scratch,
 | 
| +                                          Label* miss) {
 | 
| +  Label same_contexts;
 | 
| +
 | 
|    ASSERT(!holder_reg.is(scratch));
 | 
|  
 | 
| -  // Load the security context.
 | 
| -  ExternalReference security_context =
 | 
| -      ExternalReference(Top::k_security_context_address);
 | 
| -  mov(scratch, Operand::StaticVariable(security_context));
 | 
| -  // When generating debug code, make sure the security context is set.
 | 
| +  // Load current lexical context from the stack frame.
 | 
| +  mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset));
 | 
| +
 | 
| +  // When generating debug code, make sure the lexical context is set.
 | 
|    if (FLAG_debug_code) {
 | 
|      cmp(Operand(scratch), Immediate(0));
 | 
| -    Check(not_equal, "we should not have an empty security context");
 | 
| +    Check(not_equal, "we should not have an empty lexical context");
 | 
|    }
 | 
| -  // Load the global object of the security context.
 | 
| +  // Load the global context of the current context.
 | 
|    int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
 | 
|    mov(scratch, FieldOperand(scratch, offset));
 | 
| +  mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
 | 
| + 
 | 
| +  // Check the context is a global context. 
 | 
| +  if (FLAG_debug_code) {
 | 
| +    push(scratch);
 | 
| +    // Read the first word and compare to global_context_map.
 | 
| +    mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
 | 
| +    cmp(scratch, Factory::global_context_map());
 | 
| +    Check(equal, "JSGlobalObject::global_context should be a global context.");
 | 
| +    pop(scratch); 
 | 
| +  }
 | 
| +
 | 
| +  // Check if both contexts are the same.
 | 
| +  cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
 | 
| +  j(equal, &same_contexts, taken);
 | 
| +
 | 
| +  // Compare security tokens, save holder_reg on the stack so we can use it
 | 
| +  // as a temporary register.
 | 
| +  //
 | 
| +  // TODO(119): avoid push(holder_reg)/pop(holder_reg)
 | 
| +  push(holder_reg); 
 | 
|    // Check that the security token in the calling global object is
 | 
|    // compatible with the security token in the receiving global
 | 
|    // object.
 | 
| -  mov(scratch, FieldOperand(scratch, JSGlobalObject::kSecurityTokenOffset));
 | 
| -  cmp(scratch, FieldOperand(holder_reg, JSGlobalObject::kSecurityTokenOffset));
 | 
| +  mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
 | 
| +
 | 
| +  // Check the context is a global context.
 | 
| +  if (FLAG_debug_code) {
 | 
| +    cmp(holder_reg, Factory::null_value());
 | 
| +    Check(not_equal, "JSGlobalProxy::context() should not be null.");
 | 
| +
 | 
| +    push(holder_reg);
 | 
| +    // Read the first word and compare to global_context_map(),
 | 
| +    mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
 | 
| +    cmp(holder_reg, Factory::global_context_map());
 | 
| +    Check(equal, "JSGlobalObject::global_context should be a global context.");
 | 
| +    pop(holder_reg); 
 | 
| +  }
 | 
| +
 | 
| +  int token_offset = Context::kHeaderSize +
 | 
| +                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
 | 
| +  mov(scratch, FieldOperand(scratch, token_offset));
 | 
| +  cmp(scratch, FieldOperand(holder_reg, token_offset));
 | 
| +  pop(holder_reg); 
 | 
|    j(not_equal, miss, not_taken);
 | 
| +
 | 
| +  bind(&same_contexts);
 | 
|  }
 | 
|  
 | 
|  
 | 
| 
 |