| Index: src/macro-assembler-arm.cc | 
| =================================================================== | 
| --- src/macro-assembler-arm.cc	(revision 542) | 
| +++ src/macro-assembler-arm.cc	(working copy) | 
| @@ -593,7 +593,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()); | 
|  | 
| // Get the map of the current object. | 
| ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 
| @@ -605,8 +605,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); | 
| // Restore scratch register to be the map of the object.  In the | 
| // new space case below, we load the prototype from the map in | 
| // the scratch register. | 
| @@ -639,38 +639,73 @@ | 
| // 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)); | 
| +  ASSERT(!holder_reg.is(ip)); | 
| +  ASSERT(!scratch.is(ip)); | 
|  | 
| -  // Load the security context. | 
| -  mov(scratch, Operand(Top::security_context_address())); | 
| -  ldr(scratch, MemOperand(scratch)); | 
| -  // In debug mode, make sure the security context is set. | 
| +  // Load current lexical context from the stack frame. | 
| +  ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 
| +  // In debug mode, make sure the lexical context is set. | 
| if (kDebug) { | 
| cmp(scratch, Operand(0)); | 
| -    Check(ne, "we should not have an empty security context"); | 
| +    Check(ne, "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; | 
| ldr(scratch, FieldMemOperand(scratch, offset)); | 
| +  ldr(scratch, FieldMemOperand(scratch, GlobalObject::kGlobalContextOffset)); | 
| + | 
| +  // Check the context is a global context. | 
| +  if (FLAG_debug_code) { | 
| +    // Read the first word and compare to the global_context_map. | 
| +    ldr(ip, FieldMemOperand(scratch, HeapObject::kMapOffset)); | 
| +    cmp(ip, Operand(Factory::global_context_map())); | 
| +    Check(eq, "JSGlobalObject::global_context should be a global context."); | 
| +  } | 
| + | 
| +  // Check if both contexts are the same. | 
| +  ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 
| +  cmp(scratch, Operand(ip)); | 
| +  b(eq, &same_contexts); | 
| + | 
| +  // Check the context is a global context. | 
| +  if (FLAG_debug_code) { | 
| +    cmp(ip, Operand(Factory::null_value())); | 
| +    Check(ne, "JSGlobalProxy::context() should not be null."); | 
| + | 
| +    ldr(ip, FieldMemOperand(ip, HeapObject::kMapOffset)); | 
| +    cmp(ip, Operand(Factory::global_context_map())); | 
| +    Check(eq, "JSGlobalObject::global_context should be a global context."); | 
| +    // Restore ip to holder's context. | 
| +    ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 
| +  } | 
| + | 
| // Check that the security token in the calling global object is | 
| // compatible with the security token in the receiving global | 
| // object. | 
| -  ldr(scratch, FieldMemOperand(scratch, JSGlobalObject::kSecurityTokenOffset)); | 
| -  ldr(ip, FieldMemOperand(holder_reg, JSGlobalObject::kSecurityTokenOffset)); | 
| +  int token_offset = Context::kHeaderSize + | 
| +                     Context::SECURITY_TOKEN_INDEX * kPointerSize; | 
| + | 
| +  ldr(scratch, FieldMemOperand(scratch, token_offset)); | 
| +  ldr(ip, FieldMemOperand(ip, token_offset)); | 
| cmp(scratch, Operand(ip)); | 
| b(ne, miss); | 
| + | 
| +  bind(&same_contexts); | 
| } | 
|  | 
|  | 
|  |