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