Commit 202dedbd authored by feng@chromium.org's avatar feng@chromium.org

No more failures than before. It is ready to be reviewed.

Review URL: http://codereview.chromium.org/7420

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@544 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 648f6d21
......@@ -333,11 +333,12 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ LeaveInternalFrame();
__ b(&patch_receiver);
// Use the global object from the called function as the receiver.
// Use the global receiver object from the called function as the receiver.
__ bind(&use_global_receiver);
const int kGlobalIndex =
Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
__ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
__ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
__ bind(&patch_receiver);
__ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
......@@ -472,10 +473,12 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
__ b(&push_receiver);
// Use the current global object as the receiver.
// Use the current global receiver object as the receiver.
__ bind(&use_global_receiver);
__ ldr(r0, FieldMemOperand(cp, Context::kHeaderSize +
Context::GLOBAL_INDEX * kPointerSize));
const int kGlobalOffset =
Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
__ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
// Push the receiver.
// r0: receiver
......
......@@ -415,6 +415,13 @@ void CodeGenerator::LoadGlobal() {
}
void CodeGenerator::LoadGlobalReceiver(Register s) {
__ ldr(s, ContextOperand(cp, Context::GLOBAL_INDEX));
__ ldr(s, FieldMemOperand(s, GlobalObject::kGlobalReceiverOffset));
__ push(s);
}
// TODO(1241834): Get rid of this function in favor of just using Load, now
// that we have the INSIDE_TYPEOF typeof state. => Need to handle global
// variables w/o reference errors elsewhere.
......@@ -2220,7 +2227,10 @@ void CodeGenerator::VisitCall(Call* node) {
// Push the name of the function and the receiver onto the stack.
__ mov(r0, Operand(var->name()));
__ push(r0);
LoadGlobal();
// TODO(120): use JSGlobalObject for function lookup and inline cache,
// and use global proxy as 'this' for invocation.
LoadGlobalReceiver(r0);
// Load the arguments.
for (int i = 0; i < args->length(); i++) Load(args->at(i));
......@@ -2308,7 +2318,10 @@ void CodeGenerator::VisitCall(Call* node) {
// Load the function.
Load(function);
// Pass the global object as the receiver.
LoadGlobal();
// TODO(120): use JSGlobalObject for function lookup and inline cache,
// and use global proxy as 'this' for invocation.
LoadGlobalReceiver(r0);
// Call the function.
CallWithArguments(args, node->position());
__ push(r0);
......@@ -2328,7 +2341,7 @@ void CodeGenerator::VisitCallNew(CallNew* node) {
// Compute function to call and use the global object as the
// receiver.
Load(node->expression());
LoadGlobal();
LoadGlobalReceiver(r0);
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = node->arguments();
......@@ -2873,12 +2886,11 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
// inlining a null check instead of calling the (very) general
// runtime routine for checking equality.
if (op == Token::EQ || op == Token::EQ_STRICT) {
bool left_is_null =
left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
bool right_is_null =
right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
if (op == Token::EQ || op == Token::EQ_STRICT) {
// The 'null' value is only equal to 'null' or 'undefined'.
if (left_is_null || right_is_null) {
Load(left_is_null ? right : left);
......
......@@ -225,6 +225,7 @@ class CodeGenerator: public Visitor {
bool force_cc);
void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
void LoadGlobal();
void LoadGlobalReceiver(Register scratch);
// Read a value from a slot and leave it on top of the expression stack.
void LoadFromSlot(Slot* slot, TypeofState typeof_state);
......
......@@ -366,7 +366,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
// Check for access to global object (unlikely).
__ cmp(r0, Operand(JS_GLOBAL_OBJECT_TYPE));
__ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE));
__ b(eq, &global);
// Search the dictionary placing the result in r1.
......@@ -392,7 +392,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
// Global object access: Check access rights.
__ bind(&global);
__ CheckAccessGlobal(r1, r0, &miss);
__ CheckAccessGlobalProxy(r1, r0, &miss);
__ b(&probe);
// Cache miss: Jump to runtime.
......@@ -482,7 +482,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
// Check for access to global object (unlikely).
__ cmp(r1, Operand(JS_GLOBAL_OBJECT_TYPE));
__ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE));
__ b(eq, &global);
......@@ -492,7 +492,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
// Global object access: Check access rights.
__ bind(&global);
__ CheckAccessGlobal(r0, r1, &miss);
__ CheckAccessGlobalProxy(r0, r1, &miss);
__ b(&probe);
// Cache miss: Restore receiver from stack and jump to runtime.
......
......@@ -593,7 +593,7 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
// 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 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
// 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 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
// 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,
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);
}
......
......@@ -176,7 +176,9 @@ class MacroAssembler: public Assembler {
// Generate code for checking access rights - used for security checks
// on access to global objects across environments. The holder register
// is left untouched, whereas both scratch registers are clobbered.
void CheckAccessGlobal(Register holder_reg, Register scratch, Label* miss);
void CheckAccessGlobalProxy(Register holder_reg,
Register scratch,
Label* miss);
// ---------------------------------------------------------------------------
......
......@@ -420,13 +420,13 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
__ b(ne, &miss);
// Perform global security token check if needed.
if (object->IsJSGlobalObject()) {
__ CheckAccessGlobal(r3, r1, &miss);
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(r3, r1, &miss);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
// Perform map transition for the receiver if necessary.
if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
......@@ -522,13 +522,13 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
__ b(ne, &miss);
// Perform global security token check if needed.
if (object->IsJSGlobalObject()) {
__ CheckAccessGlobal(r3, r1, &miss);
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(r3, r1, &miss);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ ldr(ip, MemOperand(sp)); // receiver
__ push(ip);
......@@ -578,13 +578,13 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
__ b(ne, &miss);
// Perform global security token check if needed.
if (receiver->IsJSGlobalObject()) {
__ CheckAccessGlobal(r3, r1, &miss);
if (receiver->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(r3, r1, &miss);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(receiver->IsJSGlobalObject() || !receiver->IsAccessCheckNeeded());
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
__ ldr(ip, MemOperand(sp)); // receiver
__ push(ip);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment