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) { ...@@ -333,11 +333,12 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ LeaveInternalFrame(); __ LeaveInternalFrame();
__ b(&patch_receiver); __ 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); __ bind(&use_global_receiver);
const int kGlobalIndex = const int kGlobalIndex =
Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
__ ldr(r2, FieldMemOperand(cp, kGlobalIndex)); __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
__ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
__ bind(&patch_receiver); __ bind(&patch_receiver);
__ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2)); __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
...@@ -472,10 +473,12 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { ...@@ -472,10 +473,12 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
__ b(&push_receiver); __ b(&push_receiver);
// Use the current global object as the receiver. // Use the current global receiver object as the receiver.
__ bind(&use_global_receiver); __ bind(&use_global_receiver);
__ ldr(r0, FieldMemOperand(cp, Context::kHeaderSize + const int kGlobalOffset =
Context::GLOBAL_INDEX * kPointerSize)); Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
__ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
// Push the receiver. // Push the receiver.
// r0: receiver // r0: receiver
......
...@@ -415,6 +415,13 @@ void CodeGenerator::LoadGlobal() { ...@@ -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 // 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 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global
// variables w/o reference errors elsewhere. // variables w/o reference errors elsewhere.
...@@ -2220,7 +2227,10 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2220,7 +2227,10 @@ void CodeGenerator::VisitCall(Call* node) {
// Push the name of the function and the receiver onto the stack. // Push the name of the function and the receiver onto the stack.
__ mov(r0, Operand(var->name())); __ mov(r0, Operand(var->name()));
__ push(r0); __ 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. // Load the arguments.
for (int i = 0; i < args->length(); i++) Load(args->at(i)); for (int i = 0; i < args->length(); i++) Load(args->at(i));
...@@ -2308,7 +2318,10 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2308,7 +2318,10 @@ void CodeGenerator::VisitCall(Call* node) {
// Load the function. // Load the function.
Load(function); Load(function);
// Pass the global object as the receiver. // 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. // Call the function.
CallWithArguments(args, node->position()); CallWithArguments(args, node->position());
__ push(r0); __ push(r0);
...@@ -2328,7 +2341,7 @@ void CodeGenerator::VisitCallNew(CallNew* node) { ...@@ -2328,7 +2341,7 @@ void CodeGenerator::VisitCallNew(CallNew* node) {
// Compute function to call and use the global object as the // Compute function to call and use the global object as the
// receiver. // receiver.
Load(node->expression()); Load(node->expression());
LoadGlobal(); LoadGlobalReceiver(r0);
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = node->arguments(); ZoneList<Expression*>* args = node->arguments();
...@@ -2873,12 +2886,11 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) { ...@@ -2873,12 +2886,11 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
// inlining a null check instead of calling the (very) general // inlining a null check instead of calling the (very) general
// runtime routine for checking equality. // runtime routine for checking equality.
if (op == Token::EQ || op == Token::EQ_STRICT) {
bool left_is_null = bool left_is_null =
left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
bool right_is_null = bool right_is_null =
right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
if (op == Token::EQ || op == Token::EQ_STRICT) {
// The 'null' value is only equal to 'null' or 'undefined'. // The 'null' value is only equal to 'null' or 'undefined'.
if (left_is_null || right_is_null) { if (left_is_null || right_is_null) {
Load(left_is_null ? right : left); Load(left_is_null ? right : left);
......
...@@ -225,6 +225,7 @@ class CodeGenerator: public Visitor { ...@@ -225,6 +225,7 @@ class CodeGenerator: public Visitor {
bool force_cc); bool force_cc);
void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF); void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
void LoadGlobal(); void LoadGlobal();
void LoadGlobalReceiver(Register scratch);
// Read a value from a slot and leave it on top of the expression stack. // Read a value from a slot and leave it on top of the expression stack.
void LoadFromSlot(Slot* slot, TypeofState typeof_state); void LoadFromSlot(Slot* slot, TypeofState typeof_state);
......
...@@ -366,7 +366,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { ...@@ -366,7 +366,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
// Check for access to global object (unlikely). // Check for access to global object (unlikely).
__ cmp(r0, Operand(JS_GLOBAL_OBJECT_TYPE)); __ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE));
__ b(eq, &global); __ b(eq, &global);
// Search the dictionary placing the result in r1. // Search the dictionary placing the result in r1.
...@@ -392,7 +392,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { ...@@ -392,7 +392,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
// Global object access: Check access rights. // Global object access: Check access rights.
__ bind(&global); __ bind(&global);
__ CheckAccessGlobal(r1, r0, &miss); __ CheckAccessGlobalProxy(r1, r0, &miss);
__ b(&probe); __ b(&probe);
// Cache miss: Jump to runtime. // Cache miss: Jump to runtime.
...@@ -482,7 +482,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { ...@@ -482,7 +482,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
// Check for access to global object (unlikely). // Check for access to global object (unlikely).
__ cmp(r1, Operand(JS_GLOBAL_OBJECT_TYPE)); __ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE));
__ b(eq, &global); __ b(eq, &global);
...@@ -492,7 +492,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { ...@@ -492,7 +492,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
// Global object access: Check access rights. // Global object access: Check access rights.
__ bind(&global); __ bind(&global);
__ CheckAccessGlobal(r0, r1, &miss); __ CheckAccessGlobalProxy(r0, r1, &miss);
__ b(&probe); __ b(&probe);
// Cache miss: Restore receiver from stack and jump to runtime. // Cache miss: Restore receiver from stack and jump to runtime.
......
...@@ -593,7 +593,7 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg, ...@@ -593,7 +593,7 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
// Only global objects and objects that do not require access // Only global objects and objects that do not require access
// checks are allowed in stubs. // checks are allowed in stubs.
ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded()); ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
// Get the map of the current object. // Get the map of the current object.
ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
...@@ -605,8 +605,8 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg, ...@@ -605,8 +605,8 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
// Check access rights to the global object. This has to happen // Check access rights to the global object. This has to happen
// after the map check so that we know that the object is // after the map check so that we know that the object is
// actually a global object. // actually a global object.
if (object->IsJSGlobalObject()) { if (object->IsJSGlobalProxy()) {
CheckAccessGlobal(reg, scratch, miss); CheckAccessGlobalProxy(reg, scratch, miss);
// Restore scratch register to be the map of the object. In the // Restore scratch register to be the map of the object. In the
// new space case below, we load the prototype from the map in // new space case below, we load the prototype from the map in
// the scratch register. // the scratch register.
...@@ -639,38 +639,73 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg, ...@@ -639,38 +639,73 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
// Perform security check for access to the global object and return // Perform security check for access to the global object and return
// the holder register. // the holder register.
ASSERT(object == holder); ASSERT(object == holder);
ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded()); ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
if (object->IsJSGlobalObject()) { if (object->IsJSGlobalProxy()) {
CheckAccessGlobal(reg, scratch, miss); CheckAccessGlobalProxy(reg, scratch, miss);
} }
return reg; return reg;
} }
void MacroAssembler::CheckAccessGlobal(Register holder_reg, void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
Register scratch, Register scratch,
Label* miss) { Label* miss) {
Label same_contexts;
ASSERT(!holder_reg.is(scratch)); ASSERT(!holder_reg.is(scratch));
ASSERT(!holder_reg.is(ip));
ASSERT(!scratch.is(ip));
// Load the security context. // Load current lexical context from the stack frame.
mov(scratch, Operand(Top::security_context_address())); ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
ldr(scratch, MemOperand(scratch)); // In debug mode, make sure the lexical context is set.
// In debug mode, make sure the security context is set.
if (kDebug) { if (kDebug) {
cmp(scratch, Operand(0)); 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; int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
ldr(scratch, FieldMemOperand(scratch, offset)); 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 // Check that the security token in the calling global object is
// compatible with the security token in the receiving global // compatible with the security token in the receiving global
// object. // object.
ldr(scratch, FieldMemOperand(scratch, JSGlobalObject::kSecurityTokenOffset)); int token_offset = Context::kHeaderSize +
ldr(ip, FieldMemOperand(holder_reg, JSGlobalObject::kSecurityTokenOffset)); Context::SECURITY_TOKEN_INDEX * kPointerSize;
ldr(scratch, FieldMemOperand(scratch, token_offset));
ldr(ip, FieldMemOperand(ip, token_offset));
cmp(scratch, Operand(ip)); cmp(scratch, Operand(ip));
b(ne, miss); b(ne, miss);
bind(&same_contexts);
} }
......
...@@ -176,7 +176,9 @@ class MacroAssembler: public Assembler { ...@@ -176,7 +176,9 @@ class MacroAssembler: public Assembler {
// Generate code for checking access rights - used for security checks // Generate code for checking access rights - used for security checks
// on access to global objects across environments. The holder register // on access to global objects across environments. The holder register
// is left untouched, whereas both scratch registers are clobbered. // 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, ...@@ -420,13 +420,13 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
__ b(ne, &miss); __ b(ne, &miss);
// Perform global security token check if needed. // Perform global security token check if needed.
if (object->IsJSGlobalObject()) { if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobal(r3, r1, &miss); __ CheckAccessGlobalProxy(r3, r1, &miss);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
// checks. // checks.
ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded()); ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
// Perform map transition for the receiver if necessary. // Perform map transition for the receiver if necessary.
if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
...@@ -522,13 +522,13 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, ...@@ -522,13 +522,13 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
__ b(ne, &miss); __ b(ne, &miss);
// Perform global security token check if needed. // Perform global security token check if needed.
if (object->IsJSGlobalObject()) { if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobal(r3, r1, &miss); __ CheckAccessGlobalProxy(r3, r1, &miss);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
// checks. // checks.
ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded()); ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ ldr(ip, MemOperand(sp)); // receiver __ ldr(ip, MemOperand(sp)); // receiver
__ push(ip); __ push(ip);
...@@ -578,13 +578,13 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, ...@@ -578,13 +578,13 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
__ b(ne, &miss); __ b(ne, &miss);
// Perform global security token check if needed. // Perform global security token check if needed.
if (receiver->IsJSGlobalObject()) { if (receiver->IsJSGlobalProxy()) {
__ CheckAccessGlobal(r3, r1, &miss); __ CheckAccessGlobalProxy(r3, r1, &miss);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
// checks. // checks.
ASSERT(receiver->IsJSGlobalObject() || !receiver->IsAccessCheckNeeded()); ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
__ ldr(ip, MemOperand(sp)); // receiver __ ldr(ip, MemOperand(sp)); // receiver
__ push(ip); __ 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