Avoid calling ToObject on JSFunction receiver arguments for Function.call and Functio...
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 23 May 2011 15:17:10 +0000 (15:17 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 23 May 2011 15:17:10 +0000 (15:17 +0000)
BUG=
TEST=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8000 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/builtins-arm.cc
src/ia32/builtins-ia32.cc
src/mips/builtins-mips.cc
src/x64/builtins-x64.cc

index 1b2b919..931c6bb 100644 (file)
@@ -1264,10 +1264,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     __ cmp(r2, r3);
     __ b(eq, &use_global_receiver);
 
+    STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
+    STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
     __ CompareObjectType(r2, r3, r3, FIRST_JS_OBJECT_TYPE);
-    __ b(lt, &convert_to_object);
-    __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
-    __ b(le, &shift_arguments);
+    __ b(ge, &shift_arguments);
 
     __ bind(&convert_to_object);
     __ EnterInternalFrame();  // In order to preserve argument count.
@@ -1443,10 +1443,10 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
 
   // Check if the receiver is already a JavaScript object.
   // r0: receiver
+  STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
+  STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
   __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
-  __ b(lt, &call_to_object);
-  __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
-  __ b(le, &push_receiver);
+  __ b(ge, &push_receiver);
 
   // Convert the receiver to a regular object.
   // r0: receiver
index 44f0a97..b140b57 100644 (file)
@@ -606,20 +606,19 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
 
     // Compute the receiver in non-strict mode.
     __ mov(ebx, Operand(esp, eax, times_4, 0));  // First argument.
+
+    // Call ToObject on the receiver if it is not an object, or use the
+    // global object if it is null or undefined.
     __ test(ebx, Immediate(kSmiTagMask));
     __ j(zero, &convert_to_object);
-
     __ cmp(ebx, factory->null_value());
     __ j(equal, &use_global_receiver);
     __ cmp(ebx, factory->undefined_value());
     __ j(equal, &use_global_receiver);
-
-    // We don't use IsObjectJSObjectType here because we jump on success.
-    __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
-    __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
-    __ sub(Operand(ecx), Immediate(FIRST_JS_OBJECT_TYPE));
-    __ cmp(ecx, LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE);
-    __ j(below_equal, &shift_arguments);
+    STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
+    STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+    __ CmpObjectType(ebx, FIRST_JS_OBJECT_TYPE, ecx);
+    __ j(above_equal, &shift_arguments);
 
     __ bind(&convert_to_object);
     __ EnterInternalFrame();  // In order to preserve argument count.
@@ -768,23 +767,19 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
   __ j(not_equal, &push_receiver);
 
   // Compute the receiver in non-strict mode.
+  // Call ToObject on the receiver if it is not an object, or use the
+  // global object if it is null or undefined.
   __ test(ebx, Immediate(kSmiTagMask));
   __ j(zero, &call_to_object);
   __ cmp(ebx, factory->null_value());
   __ j(equal, &use_global_receiver);
   __ cmp(ebx, factory->undefined_value());
   __ j(equal, &use_global_receiver);
+  STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
+  STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+  __ CmpObjectType(ebx, FIRST_JS_OBJECT_TYPE, ecx);
+  __ j(above_equal, &push_receiver);
 
-  // If given receiver is already a JavaScript object then there's no
-  // reason for converting it.
-  // We don't use IsObjectJSObjectType here because we jump on success.
-  __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
-  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
-  __ sub(Operand(ecx), Immediate(FIRST_JS_OBJECT_TYPE));
-  __ cmp(ecx, LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE);
-  __ j(below_equal, &push_receiver);
-
-  // Convert the receiver to an object.
   __ bind(&call_to_object);
   __ push(ebx);
   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
index fdcb7c7..732915f 100644 (file)
@@ -1222,9 +1222,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     __ LoadRoot(a3, Heap::kNullValueRootIndex);
     __ Branch(&use_global_receiver, eq, a2, Operand(a3));
 
+    STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
+    STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
     __ GetObjectType(a2, a3, a3);
-    __ Branch(&convert_to_object, lt, a3, Operand(FIRST_JS_OBJECT_TYPE));
-    __ Branch(&shift_arguments, le, a3, Operand(LAST_JS_OBJECT_TYPE));
+    __ Branch(&shift_arguments, ge, a3, Operand(FIRST_JS_OBJECT_TYPE));
 
     __ bind(&convert_to_object);
     __ EnterInternalFrame();  // In order to preserve argument count.
@@ -1401,9 +1402,10 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
 
   // Check if the receiver is already a JavaScript object.
   // a0: receiver
+  STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
+  STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
   __ GetObjectType(a0, a1, a1);
-  __ Branch(&call_to_object, lt, a1, Operand(FIRST_JS_OBJECT_TYPE));
-  __ Branch(&push_receiver, le, a1, Operand(LAST_JS_OBJECT_TYPE));
+  __ Branch(&push_receiver, ge, a1, Operand(FIRST_JS_OBJECT_TYPE));
 
   // Convert the receiver to a regular object.
   // a0: receiver
index 57cde65..a5e392f 100644 (file)
@@ -666,17 +666,17 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
 
     // Compute the receiver in non-strict mode.
     __ movq(rbx, Operand(rsp, rax, times_pointer_size, 0));
-    __ JumpIfSmi(rbx, &convert_to_object);
+    __ JumpIfSmi(rbx, &convert_to_object, Label::kNear);
 
     __ CompareRoot(rbx, Heap::kNullValueRootIndex);
     __ j(equal, &use_global_receiver);
     __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
     __ j(equal, &use_global_receiver);
 
+    STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
+    STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
     __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx);
-    __ j(below, &convert_to_object);
-    __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE);
-    __ j(below_equal, &shift_arguments);
+    __ j(above_equal, &shift_arguments);
 
     __ bind(&convert_to_object);
     __ EnterInternalFrame();  // In order to preserve argument count.
@@ -692,7 +692,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     __ LeaveInternalFrame();
     // Restore the function to rdi.
     __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize));
-    __ jmp(&patch_receiver);
+    __ jmp(&patch_receiver, Label::kNear);
 
     // Use the global receiver object from the called function as the
     // receiver.
@@ -834,7 +834,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
   __ j(not_zero, &push_receiver);
 
   // Compute the receiver in non-strict mode.
-  __ JumpIfSmi(rbx, &call_to_object);
+  __ JumpIfSmi(rbx, &call_to_object, Label::kNear);
   __ CompareRoot(rbx, Heap::kNullValueRootIndex);
   __ j(equal, &use_global_receiver);
   __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
@@ -842,17 +842,17 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
 
   // If given receiver is already a JavaScript object then there's no
   // reason for converting it.
+  STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
+  STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
   __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx);
-  __ j(below, &call_to_object);
-  __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE);
-  __ j(below_equal, &push_receiver);
+  __ j(above_equal, &push_receiver);
 
   // Convert the receiver to an object.
   __ bind(&call_to_object);
   __ push(rbx);
   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
   __ movq(rbx, rax);
-  __ jmp(&push_receiver);
+  __ jmp(&push_receiver, Label::kNear);
 
   // Use the current global receiver object as the receiver.
   __ bind(&use_global_receiver);