Index: src/ic-ia32.cc |
=================================================================== |
--- src/ic-ia32.cc (revision 599) |
+++ src/ic-ia32.cc (working copy) |
@@ -472,11 +472,42 @@ |
} |
+static void GenerateNormalHelper(MacroAssembler* masm, |
+ int argc, |
+ bool is_global_object, |
+ Label* miss) { |
+ // Search dictionary - put result in register edx. |
+ GenerateDictionaryLoad(masm, miss, eax, edx, ebx, ecx); |
+ |
+ // Move the result to register edi and check that it isn't a smi. |
+ __ mov(edi, Operand(edx)); |
+ __ test(edx, Immediate(kSmiTagMask)); |
+ __ j(zero, miss, not_taken); |
+ |
+ // Check that the value is a JavaScript function. |
+ __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); |
+ __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
+ __ cmp(edx, JS_FUNCTION_TYPE); |
+ __ j(not_equal, miss, not_taken); |
+ |
+ // Patch the receiver with the global proxy if necessary. |
+ if (is_global_object) { |
+ __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
+ __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
+ __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
+ } |
+ |
+ // Invoke the function. |
+ ParameterCount actual(argc); |
+ __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
+} |
+ |
+ |
void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
// ----------- S t a t e ------------- |
// ----------------------------------- |
- Label miss, probe, global; |
+ Label miss, global_object, non_global_object; |
// Get the receiver of the function from the stack; 1 ~ return address. |
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
@@ -496,36 +527,28 @@ |
// If this assert fails, we have to check upper bound too. |
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
- // Check for access to global proxy. |
- __ cmp(eax, JS_GLOBAL_PROXY_TYPE); |
- __ j(equal, &global, not_taken); |
+ // Check for access to global object. |
+ __ cmp(eax, JS_GLOBAL_OBJECT_TYPE); |
+ __ j(equal, &global_object); |
+ __ cmp(eax, JS_BUILTINS_OBJECT_TYPE); |
+ __ j(not_equal, &non_global_object); |
- // Search the dictionary placing the result in edx. |
- __ bind(&probe); |
- GenerateDictionaryLoad(masm, &miss, eax, edx, ebx, ecx); |
+ // Accessing global object: Load and invoke. |
+ __ bind(&global_object); |
+ GenerateNormalHelper(masm, argc, true, &miss); |
- // Move the result to register edi and check that it isn't a smi. |
- __ mov(edi, Operand(edx)); |
- __ test(edx, Immediate(kSmiTagMask)); |
- __ j(zero, &miss, not_taken); |
+ // Accessing non-global object: Check for access to global proxy. |
+ Label global_proxy, invoke; |
+ __ bind(&non_global_object); |
+ __ cmp(eax, JS_GLOBAL_PROXY_TYPE); |
+ __ j(equal, &global_proxy, not_taken); |
+ __ bind(&invoke); |
+ GenerateNormalHelper(masm, argc, false, &miss); |
- // Check that the value is a JavaScript function. |
- __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); |
- __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
- __ cmp(edx, JS_FUNCTION_TYPE); |
- __ j(not_equal, &miss, not_taken); |
- |
- // TODO(120): Check for access to global object. Needs patching of |
- // receiver but no security check. |
- |
- // Invoke the function. |
- ParameterCount actual(argc); |
- __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
- |
// Global object proxy access: Check access rights. |
- __ bind(&global); |
+ __ bind(&global_proxy); |
__ CheckAccessGlobalProxy(edx, eax, &miss); |
- __ jmp(&probe); |
+ __ jmp(&invoke); |
// Cache miss: Jump to runtime. |
__ bind(&miss); |
@@ -562,11 +585,26 @@ |
__ mov(Operand(edi), eax); |
__ LeaveInternalFrame(); |
- // TODO(120): Check for access to to global object. Needs patching |
- // of receiver but no security check. |
+ // Check if the receiver is a global object of some sort. |
+ Label invoke, global; |
+ __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver |
+ __ test(edx, Immediate(kSmiTagMask)); |
+ __ j(zero, &invoke, not_taken); |
+ __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
+ __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
+ __ cmp(ecx, JS_GLOBAL_OBJECT_TYPE); |
+ __ j(equal, &global); |
+ __ cmp(ecx, JS_BUILTINS_OBJECT_TYPE); |
+ __ j(not_equal, &invoke); |
+ // Patch the receiver on the stack. |
+ __ bind(&global); |
+ __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
+ __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
+ |
// Invoke the function. |
ParameterCount actual(argc); |
+ __ bind(&invoke); |
__ InvokeFunction(edi, actual, JUMP_FUNCTION); |
} |