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); |
} |