[runtime] Replace many buggy uses of %_CallFunction with %_Call.
authorbmeurer <bmeurer@chromium.org>
Tue, 8 Sep 2015 13:35:20 +0000 (06:35 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 8 Sep 2015 13:35:32 +0000 (13:35 +0000)
The semantics of the %_CallFunction intrinsic seem to be very unclear,
which resulted in a lot of bugs. Especially the combination with
%IsSloppyModeFunction is always a bug, because the receiver would be
wrapped in the wrong context. So the %IsSloppyModeFunction helper is
gone now, and many of the buggy uses of %_CallFunction are also
eliminated.

If you ever need to call something with a different receiver, then
%_Call is your friend now. It does what you want and implements the
call sequence fully (and correct).

BUG=v8:4413
LOG=n

Review URL: https://codereview.chromium.org/1325573004

Cr-Commit-Position: refs/heads/master@{#30634}

35 files changed:
src/arm/interface-descriptors-arm.cc
src/arm64/interface-descriptors-arm64.cc
src/array.js
src/collection.js
src/compiler/linkage.cc
src/full-codegen/arm/full-codegen-arm.cc
src/full-codegen/arm64/full-codegen-arm64.cc
src/full-codegen/full-codegen.h
src/full-codegen/ia32/full-codegen-ia32.cc
src/full-codegen/mips/full-codegen-mips.cc
src/full-codegen/mips64/full-codegen-mips64.cc
src/full-codegen/x64/full-codegen-x64.cc
src/harmony-array.js
src/harmony-typedarray.js
src/hydrogen.cc
src/hydrogen.h
src/ia32/interface-descriptors-ia32.cc
src/interface-descriptors.cc
src/interface-descriptors.h
src/json.js
src/macros.py
src/mips/interface-descriptors-mips.cc
src/mips64/interface-descriptors-mips64.cc
src/object-observe.js
src/promise.js
src/runtime.js
src/runtime/runtime-function.cc
src/runtime/runtime.h
src/string.js
src/typedarray.js
src/weak-collection.js
src/x64/interface-descriptors-x64.cc
test/mjsunit/debug-liveedit-check-stack.js
test/mjsunit/harmony/proxies-function.js
test/mjsunit/strong/function-arity.js

index 7de994b..1054a25 100644 (file)
@@ -192,6 +192,15 @@ void CallConstructDescriptor::InitializePlatformSpecific(
 }
 
 
+void CallTrampolineDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // r0 : number of arguments
+  // r1 : the target to call
+  Register registers[] = {r1, r0};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
 void RegExpConstructResultDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {r2, r1, r0};
index 5e6ba60..d013362 100644 (file)
@@ -207,6 +207,15 @@ void CallConstructDescriptor::InitializePlatformSpecific(
 }
 
 
+void CallTrampolineDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // x1: target
+  // x0: number of arguments
+  Register registers[] = {x1, x0};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
 void RegExpConstructResultDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // x2: length
index 265e80b..26f050d 100644 (file)
@@ -390,7 +390,7 @@ function ArrayToString() {
   if (!IS_CALLABLE(func)) {
     return %_CallFunction(array, ObjectToString);
   }
-  return %_CallFunction(array, func);
+  return %_Call(func, array);
 }
 
 
@@ -903,7 +903,7 @@ function InnerArraySort(array, length, comparefn) {
       var element = a[i];
       for (var j = i - 1; j >= from; j--) {
         var tmp = a[j];
-        var order = %_CallFunction(UNDEFINED, tmp, element, comparefn);
+        var order = comparefn(tmp, element);
         if (order > 0) {
           a[j + 1] = tmp;
         } else {
@@ -922,7 +922,7 @@ function InnerArraySort(array, length, comparefn) {
       t_array[j] = [i, a[i]];
     }
     %_CallFunction(t_array, function(a, b) {
-      return %_CallFunction(UNDEFINED, a[1], b[1], comparefn);
+      return comparefn(a[1], b[1]);
     }, ArraySort);
     var third_index = t_array[t_array.length >> 1][0];
     return third_index;
@@ -945,14 +945,14 @@ function InnerArraySort(array, length, comparefn) {
       var v0 = a[from];
       var v1 = a[to - 1];
       var v2 = a[third_index];
-      var c01 = %_CallFunction(UNDEFINED, v0, v1, comparefn);
+      var c01 = comparefn(v0, v1);
       if (c01 > 0) {
         // v1 < v0, so swap them.
         var tmp = v0;
         v0 = v1;
         v1 = tmp;
       } // v0 <= v1.
-      var c02 = %_CallFunction(UNDEFINED, v0, v2, comparefn);
+      var c02 = comparefn(v0, v2);
       if (c02 >= 0) {
         // v2 <= v0 <= v1.
         var tmp = v0;
@@ -961,7 +961,7 @@ function InnerArraySort(array, length, comparefn) {
         v1 = tmp;
       } else {
         // v0 <= v1 && v0 < v2
-        var c12 = %_CallFunction(UNDEFINED, v1, v2, comparefn);
+        var c12 = comparefn(v1, v2);
         if (c12 > 0) {
           // v0 <= v2 < v1
           var tmp = v1;
@@ -982,7 +982,7 @@ function InnerArraySort(array, length, comparefn) {
       // From i to high_start are elements that haven't been compared yet.
       partition: for (var i = low_end + 1; i < high_start; i++) {
         var element = a[i];
-        var order = %_CallFunction(UNDEFINED, element, pivot, comparefn);
+        var order = comparefn(element, pivot);
         if (order < 0) {
           a[i] = a[low_end];
           a[low_end] = element;
@@ -992,7 +992,7 @@ function InnerArraySort(array, length, comparefn) {
             high_start--;
             if (high_start == i) break partition;
             var top_elem = a[high_start];
-            order = %_CallFunction(UNDEFINED, top_elem, pivot, comparefn);
+            order = comparefn(top_elem, pivot);
           } while (order > 0);
           a[i] = a[high_start];
           a[high_start] = element;
@@ -1179,12 +1179,6 @@ function ArraySort(comparefn) {
 // or delete elements from the array.
 function InnerArrayFilter(f, receiver, array, length) {
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
-  var needs_wrapper = false;
-  if (IS_NULL(receiver)) {
-    if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
-  } else if (!IS_UNDEFINED(receiver)) {
-    needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
-  }
 
   var accumulator = new InternalArray();
   var accumulator_length = 0;
@@ -1195,8 +1189,7 @@ function InnerArrayFilter(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
-      if (%_CallFunction(new_receiver, element, i, array, f)) {
+      if (%_Call(f, receiver, element, i, array)) {
         accumulator[accumulator_length++] = element;
       }
     }
@@ -1219,12 +1212,6 @@ function ArrayFilter(f, receiver) {
 
 function InnerArrayForEach(f, receiver, array, length) {
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
-  var needs_wrapper = false;
-  if (IS_NULL(receiver)) {
-    if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
-  } else if (!IS_UNDEFINED(receiver)) {
-    needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
-  }
 
   var is_array = IS_ARRAY(array);
   var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
@@ -1233,8 +1220,7 @@ function InnerArrayForEach(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
-      %_CallFunction(new_receiver, element, i, array, f);
+      %_Call(f, receiver, element, i, array);
     }
   }
 }
@@ -1252,12 +1238,6 @@ function ArrayForEach(f, receiver) {
 
 function InnerArraySome(f, receiver, array, length) {
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
-  var needs_wrapper = false;
-  if (IS_NULL(receiver)) {
-    if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
-  } else if (!IS_UNDEFINED(receiver)) {
-    needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
-  }
 
   var is_array = IS_ARRAY(array);
   var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
@@ -1266,8 +1246,7 @@ function InnerArraySome(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
-      if (%_CallFunction(new_receiver, element, i, array, f)) return true;
+      if (%_Call(f, receiver, element, i, array)) return true;
     }
   }
   return false;
@@ -1289,12 +1268,6 @@ function ArraySome(f, receiver) {
 
 function InnerArrayEvery(f, receiver, array, length) {
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
-  var needs_wrapper = false;
-  if (IS_NULL(receiver)) {
-    if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
-  } else if (!IS_UNDEFINED(receiver)) {
-    needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
-  }
 
   var is_array = IS_ARRAY(array);
   var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
@@ -1303,8 +1276,7 @@ function InnerArrayEvery(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
-      if (!%_CallFunction(new_receiver, element, i, array, f)) return false;
+      if (!%_Call(f, receiver, element, i, array)) return false;
     }
   }
   return true;
@@ -1323,12 +1295,6 @@ function ArrayEvery(f, receiver) {
 
 function InnerArrayMap(f, receiver, array, length) {
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
-  var needs_wrapper = false;
-  if (IS_NULL(receiver)) {
-    if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
-  } else if (!IS_UNDEFINED(receiver)) {
-    needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
-  }
 
   var accumulator = new InternalArray(length);
   var is_array = IS_ARRAY(array);
@@ -1338,8 +1304,7 @@ function InnerArrayMap(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
-      accumulator[i] = %_CallFunction(new_receiver, element, i, array, f);
+      accumulator[i] = %_Call(f, receiver, element, i, array);
     }
   }
   return accumulator;
@@ -1508,7 +1473,7 @@ function InnerArrayReduce(callback, current, array, length, argumentsLength) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(callback);
-      current = %_CallFunction(UNDEFINED, current, element, i, array, callback);
+      current = callback(current, element, i, array);
     }
   }
   return current;
@@ -1551,7 +1516,7 @@ function InnerArrayReduceRight(callback, current, array, length,
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(callback);
-      current = %_CallFunction(UNDEFINED, current, element, i, array, callback);
+      current = callback(current, element, i, array);
     }
   }
   return current;
index f7db862..8bf6ec3 100644 (file)
@@ -139,7 +139,7 @@ function SetConstructor(iterable) {
     }
 
     for (var value of iterable) {
-      %_CallFunction(this, value, adder);
+      %_Call(adder, this, value);
     }
   }
 }
@@ -246,12 +246,6 @@ function SetForEach(f, receiver) {
   }
 
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
-  var needs_wrapper = false;
-  if (IS_NULL(receiver)) {
-    if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
-  } else if (!IS_UNDEFINED(receiver)) {
-    needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
-  }
 
   var iterator = new SetIterator(this, ITERATOR_KIND_VALUES);
   var key;
@@ -260,8 +254,7 @@ function SetForEach(f, receiver) {
   while (%SetIteratorNext(iterator, value_array)) {
     if (stepping) %DebugPrepareStepInIfStepping(f);
     key = value_array[0];
-    var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
-    %_CallFunction(new_receiver, key, key, this, f);
+    %_Call(f, receiver, key, key, this);
   }
 }
 
@@ -307,7 +300,7 @@ function MapConstructor(iterable) {
       if (!IS_SPEC_OBJECT(nextItem)) {
         throw MakeTypeError(kIteratorValueNotAnObject, nextItem);
       }
-      %_CallFunction(this, nextItem[0], nextItem[1], adder);
+      %_Call(adder, this, nextItem[0], nextItem[1]);
     }
   }
 }
@@ -437,20 +430,13 @@ function MapForEach(f, receiver) {
   }
 
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
-  var needs_wrapper = false;
-  if (IS_NULL(receiver)) {
-    if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
-  } else if (!IS_UNDEFINED(receiver)) {
-    needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
-  }
 
   var iterator = new MapIterator(this, ITERATOR_KIND_ENTRIES);
   var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
   var value_array = [UNDEFINED, UNDEFINED];
   while (%MapIteratorNext(iterator, value_array)) {
     if (stepping) %DebugPrepareStepInIfStepping(f);
-    var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
-    %_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
+    %_Call(f, receiver, value_array[1], value_array[0], this);
   }
 }
 
@@ -486,7 +472,7 @@ function MapFromArray(array) {
   for (var i = 0; i < length; i += 2) {
     var key = array[i];
     var value = array[i + 1];
-    %_CallFunction(map, key, value, MapSet);
+    %_Call(MapSet, map, key, value);
   }
   return map;
 };
@@ -495,7 +481,7 @@ function SetFromArray(array) {
   var set = new GlobalSet;
   var length = array.length;
   for (var i = 0; i < length; ++i) {
-    %_CallFunction(set, array[i], SetAdd);
+    %_Call(SetAdd, set, array[i]);
   }
   return set;
 };
index 53a4ecc..fdef8e0 100644 (file)
@@ -238,6 +238,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
     case Runtime::kTraceExit:
       return 0;
     case Runtime::kInlineArguments:
+    case Runtime::kInlineCall:
     case Runtime::kInlineCallFunction:
     case Runtime::kInlineDefaultConstructorCallSuper:
     case Runtime::kInlineGetCallerJSFunction:
index 24dc516..02363c1 100644 (file)
@@ -4056,6 +4056,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCall(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_LE(2, args->length());
+  // Push target, receiver and arguments onto the stack.
+  for (Expression* const arg : *args) {
+    VisitForStackValue(arg);
+  }
+  // Move target to r1.
+  int const argc = args->length() - 2;
+  __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
+  // Call the target.
+  __ mov(r0, Operand(argc));
+  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
+  // Restore context register.
+  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  // Discard the function left on TOS.
+  context()->DropAndPlug(1, r0);
+}
+
+
 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() >= 2);
@@ -4081,7 +4101,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
   __ bind(&runtime);
   __ push(r0);
-  __ CallRuntime(Runtime::kCall, args->length());
+  __ CallRuntime(Runtime::kCallFunction, args->length());
   __ bind(&done);
 
   context()->Plug(r0);
index 59d5920..0fb38b1 100644 (file)
@@ -3785,6 +3785,27 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCall(CallRuntime* expr) {
+  ASM_LOCATION("FullCodeGenerator::EmitCallFunction");
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_LE(2, args->length());
+  // Push target, receiver and arguments onto the stack.
+  for (Expression* const arg : *args) {
+    VisitForStackValue(arg);
+  }
+  // Move target to x1.
+  int const argc = args->length() - 2;
+  __ Peek(x1, (argc + 1) * kXRegSize);
+  // Call the target.
+  __ Mov(x0, argc);
+  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
+  // Restore context register.
+  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  // Discard the function left on TOS.
+  context()->DropAndPlug(1, x0);
+}
+
+
 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
   ASM_LOCATION("FullCodeGenerator::EmitCallFunction");
   ZoneList<Expression*>* args = expr->arguments();
@@ -3810,7 +3831,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
   __ Bind(&runtime);
   __ Push(x0);
-  __ CallRuntime(Runtime::kCall, args->length());
+  __ CallRuntime(Runtime::kCallFunction, args->length());
   __ Bind(&done);
 
   context()->Plug(x0);
index 78304c4..bc78fda 100644 (file)
@@ -493,6 +493,7 @@ class FullCodeGenerator: public AstVisitor {
   F(IsRegExp)                             \
   F(IsJSProxy)                            \
   F(IsConstructCall)                      \
+  F(Call)                                 \
   F(CallFunction)                         \
   F(DefaultConstructorCallSuper)          \
   F(ArgumentsLength)                      \
index 1f1c19e..e47243a 100644 (file)
@@ -3965,6 +3965,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCall(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_LE(2, args->length());
+  // Push target, receiver and arguments onto the stack.
+  for (Expression* const arg : *args) {
+    VisitForStackValue(arg);
+  }
+  // Move target to edi.
+  int const argc = args->length() - 2;
+  __ mov(edi, Operand(esp, (argc + 1) * kPointerSize));
+  // Call the target.
+  __ mov(eax, Immediate(argc));
+  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
+  // Restore context register.
+  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  // Discard the function left on TOS.
+  context()->DropAndPlug(1, eax);
+}
+
+
 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() >= 2);
@@ -3990,7 +4010,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
   __ bind(&runtime);
   __ push(eax);
-  __ CallRuntime(Runtime::kCall, args->length());
+  __ CallRuntime(Runtime::kCallFunction, args->length());
   __ bind(&done);
 
   context()->Plug(eax);
index 0a3e5bb..1dde30c 100644 (file)
@@ -4078,6 +4078,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCall(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_LE(2, args->length());
+  // Push target, receiver and arguments onto the stack.
+  for (Expression* const arg : *args) {
+    VisitForStackValue(arg);
+  }
+  // Move target to a1.
+  int const argc = args->length() - 2;
+  __ lw(a1, MemOperand(sp, (argc + 1) * kPointerSize));
+  // Call the target.
+  __ li(a0, Operand(argc));
+  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
+  // Restore context register.
+  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  // Discard the function left on TOS.
+  context()->DropAndPlug(1, v0);
+}
+
+
 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() >= 2);
@@ -4103,7 +4123,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
   __ bind(&runtime);
   __ push(v0);
-  __ CallRuntime(Runtime::kCall, args->length());
+  __ CallRuntime(Runtime::kCallFunction, args->length());
   __ bind(&done);
 
   context()->Plug(v0);
index 1052817..1e7ae09 100644 (file)
@@ -4082,6 +4082,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCall(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_LE(2, args->length());
+  // Push target, receiver and arguments onto the stack.
+  for (Expression* const arg : *args) {
+    VisitForStackValue(arg);
+  }
+  // Move target to a1.
+  int const argc = args->length() - 2;
+  __ ld(a1, MemOperand(sp, (argc + 1) * kPointerSize));
+  // Call the target.
+  __ li(a0, Operand(argc));
+  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
+  // Restore context register.
+  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  // Discard the function left on TOS.
+  context()->DropAndPlug(1, v0);
+}
+
+
 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() >= 2);
@@ -4107,7 +4127,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
   __ bind(&runtime);
   __ push(v0);
-  __ CallRuntime(Runtime::kCall, args->length());
+  __ CallRuntime(Runtime::kCallFunction, args->length());
   __ bind(&done);
 
   context()->Plug(v0);
index e6bb7ed..b7adbfd 100644 (file)
@@ -3952,6 +3952,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCall(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_LE(2, args->length());
+  // Push target, receiver and arguments onto the stack.
+  for (Expression* const arg : *args) {
+    VisitForStackValue(arg);
+  }
+  // Move target to rdi.
+  int const argc = args->length() - 2;
+  __ movp(rdi, Operand(rsp, (argc + 1) * kPointerSize));
+  // Call the target.
+  __ Set(rax, argc);
+  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
+  // Restore context register.
+  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  // Discard the function left on TOS.
+  context()->DropAndPlug(1, rax);
+}
+
+
 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() >= 2);
@@ -3977,7 +3997,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
   __ bind(&runtime);
   __ Push(rax);
-  __ CallRuntime(Runtime::kCall, args->length());
+  __ CallRuntime(Runtime::kCallFunction, args->length());
   __ bind(&done);
 
   context()->Plug(rax);
index 779b67a..705adcd 100644 (file)
@@ -95,17 +95,9 @@ function InnerArrayFind(predicate, thisArg, array, length) {
     throw MakeTypeError(kCalledNonCallable, predicate);
   }
 
-  var needs_wrapper = false;
-  if (IS_NULL(thisArg)) {
-    if (%IsSloppyModeFunction(predicate)) thisArg = UNDEFINED;
-  } else if (!IS_UNDEFINED(thisArg)) {
-    needs_wrapper = SHOULD_CREATE_WRAPPER(predicate, thisArg);
-  }
-
   for (var i = 0; i < length; i++) {
     var element = array[i];
-    var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg;
-    if (%_CallFunction(newThisArg, element, i, array, predicate)) {
+    if (%_Call(predicate, thisArg, element, i, array)) {
       return element;
     }
   }
@@ -128,17 +120,9 @@ function InnerArrayFindIndex(predicate, thisArg, array, length) {
     throw MakeTypeError(kCalledNonCallable, predicate);
   }
 
-  var needs_wrapper = false;
-  if (IS_NULL(thisArg)) {
-    if (%IsSloppyModeFunction(predicate)) thisArg = UNDEFINED;
-  } else if (!IS_UNDEFINED(thisArg)) {
-    needs_wrapper = SHOULD_CREATE_WRAPPER(predicate, thisArg);
-  }
-
   for (var i = 0; i < length; i++) {
     var element = array[i];
-    var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg;
-    if (%_CallFunction(newThisArg, element, i, array, predicate)) {
+    if (%_Call(predicate, thisArg, element, i, array)) {
       return i;
     }
   }
@@ -212,12 +196,6 @@ function ArrayFrom(arrayLike, mapfn, receiver) {
   if (mapping) {
     if (!IS_CALLABLE(mapfn)) {
       throw MakeTypeError(kCalledNonCallable, mapfn);
-    } else if (%IsSloppyModeFunction(mapfn)) {
-      if (IS_NULL(receiver)) {
-        receiver = UNDEFINED;
-      } else if (!IS_UNDEFINED(receiver)) {
-        receiver = TO_OBJECT(receiver);
-      }
     }
   }
 
@@ -247,7 +225,7 @@ function ArrayFrom(arrayLike, mapfn, receiver) {
 
       nextValue = next.value;
       if (mapping) {
-        mappedValue = %_CallFunction(receiver, nextValue, k, mapfn);
+        mappedValue = %_Call(mapfn, receiver, nextValue, k);
       } else {
         mappedValue = nextValue;
       }
@@ -261,7 +239,7 @@ function ArrayFrom(arrayLike, mapfn, receiver) {
     for (k = 0; k < len; ++k) {
       nextValue = items[k];
       if (mapping) {
-        mappedValue = %_CallFunction(receiver, nextValue, k, mapfn);
+        mappedValue = %_Call(mapfn, receiver, nextValue, k);
       } else {
         mappedValue = nextValue;
       }
index 94d5f9a..9d66e21 100644 (file)
@@ -277,7 +277,7 @@ function TypedArrayToLocaleString() {
 
 // ES6 section 22.2.3.28
 function TypedArrayToString() {
-  return %_CallFunction(this, ArrayToString);
+  return %_Call(ArrayToString, this);
 }
 
 
@@ -372,7 +372,7 @@ function TypedArrayOf() {
 function TypedArrayFrom(source, mapfn, thisArg) {
   // TODO(littledan): Investigate if there is a receiver which could be
   // faster to accumulate on than Array, e.g., a TypedVector.
-  var array = %_CallFunction(GlobalArray, source, mapfn, thisArg, ArrayFrom);
+  var array = %_Call(ArrayFrom, GlobalArray, source, mapfn, thisArg);
   return ConstructTypedArray(this, array);
 }
 %FunctionSetLength(TypedArrayFrom, 1);
index 99b4ddd..40d4c83 100644 (file)
@@ -12477,6 +12477,23 @@ void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
 }
 
 
+// Fast support for calls.
+void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) {
+  DCHECK_LE(2, call->arguments()->length());
+  CHECK_ALIVE(VisitExpressions(call->arguments()));
+  CallTrampolineDescriptor descriptor(isolate());
+  PushArgumentsFromEnvironment(call->arguments()->length() - 1);
+  HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call());
+  HValue* target = Pop();
+  HValue* values[] = {context(), target,
+                      Add<HConstant>(call->arguments()->length() - 2)};
+  HInstruction* result = New<HCallWithDescriptor>(
+      trampoline, call->arguments()->length() - 1, descriptor,
+      Vector<HValue*>(values, arraysize(values)));
+  return ast_context()->ReturnInstruction(result, call->id());
+}
+
+
 // Fast call for custom callbacks.
 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
   // 1 ~ The function to call is not itself an argument to the call.
index 45c15ba..88a9fd8 100644 (file)
@@ -2209,6 +2209,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
   F(IsRegExp)                          \
   F(IsJSProxy)                         \
   F(IsConstructCall)                   \
+  F(Call)                              \
   F(CallFunction)                      \
   F(ArgumentsLength)                   \
   F(Arguments)                         \
index 1c0402f..821e57d 100644 (file)
@@ -198,6 +198,15 @@ void CallConstructDescriptor::InitializePlatformSpecific(
 }
 
 
+void CallTrampolineDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // eax : number of arguments
+  // edi : the target to call
+  Register registers[] = {edi, eax};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
 void RegExpConstructResultDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {ecx, ebx, eax};
index 9975815..b66f67c 100644 (file)
@@ -355,6 +355,19 @@ CreateWeakCellDescriptor::BuildCallInterfaceDescriptorFunctionType(
 
 
 Type::FunctionType*
+CallTrampolineDescriptor::BuildCallInterfaceDescriptorFunctionType(
+    Isolate* isolate, int paramater_count) {
+  Zone* zone = isolate->interface_descriptor_zone();
+  Type::FunctionType* function =
+      Type::FunctionType::New(AnyTagged(zone), Type::Undefined(), 2, zone);
+  function->InitParameter(0, AnyTagged(zone));  // target
+  function->InitParameter(
+      1, UntaggedSigned32(zone));  // actual number of arguments
+  return function;
+}
+
+
+Type::FunctionType*
 CallFunctionWithFeedbackDescriptor::BuildCallInterfaceDescriptorFunctionType(
     Isolate* isolate, int paramater_count) {
   Zone* zone = isolate->interface_descriptor_zone();
index 1168fe9..495a621 100644 (file)
@@ -37,6 +37,7 @@ class PlatformInterfaceDescriptor;
   V(CallFunctionWithFeedback)                 \
   V(CallFunctionWithFeedbackAndVector)        \
   V(CallConstruct)                            \
+  V(CallTrampoline)                           \
   V(RegExpConstructResult)                    \
   V(TransitionElementsKind)                   \
   V(AllocateHeapNumber)                       \
@@ -430,6 +431,13 @@ class CreateWeakCellDescriptor : public CallInterfaceDescriptor {
 };
 
 
+class CallTrampolineDescriptor : public CallInterfaceDescriptor {
+ public:
+  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CallTrampolineDescriptor,
+                                               CallInterfaceDescriptor)
+};
+
+
 class CallFunctionDescriptor : public CallInterfaceDescriptor {
  public:
   DECLARE_DESCRIPTOR(CallFunctionDescriptor, CallInterfaceDescriptor)
index 5ddf869..a0a88a0 100644 (file)
@@ -52,7 +52,7 @@ function Revive(holder, name, reviver) {
       }
     }
   }
-  return %_CallFunction(holder, name, val, reviver);
+  return %_Call(reviver, holder, name, val);
 }
 
 
@@ -147,11 +147,11 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) {
   if (IS_SPEC_OBJECT(value)) {
     var toJSON = value.toJSON;
     if (IS_CALLABLE(toJSON)) {
-      value = %_CallFunction(value, key, toJSON);
+      value = %_Call(toJSON, value, key);
     }
   }
   if (IS_CALLABLE(replacer)) {
-    value = %_CallFunction(holder, key, value, replacer);
+    value = %_Call(replacer, holder, key, value);
   }
   if (IS_STRING(value)) {
     return %QuoteJSONString(value);
index baaea93..6ea6d16 100644 (file)
@@ -156,7 +156,6 @@ macro TO_PRIMITIVE_STRING(arg) = (%_ToPrimitive_String(arg));
 macro TO_NAME(arg) = (%_ToName(arg));
 macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");
 macro HAS_OWN_PROPERTY(arg, index) = (%_CallFunction(arg, index, ObjectHasOwnProperty));
-macro SHOULD_CREATE_WRAPPER(functionName, receiver) = (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(functionName));
 macro HAS_INDEX(array, index, is_array) = ((is_array && %_HasFastPackedElements(%IS_VAR(array))) ? (index < array.length) : (index in array));
 
 # Private names.
index 2f6bf5c..b02cdad 100644 (file)
@@ -190,6 +190,15 @@ void CallConstructDescriptor::InitializePlatformSpecific(
 }
 
 
+void CallTrampolineDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // a1: target
+  // a0: number of arguments
+  Register registers[] = {a1, a0};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
 void RegExpConstructResultDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {a2, a1, a0};
index 4f896b7..f861513 100644 (file)
@@ -190,6 +190,15 @@ void CallConstructDescriptor::InitializePlatformSpecific(
 }
 
 
+void CallTrampolineDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // a1: target
+  // a0: number of arguments
+  Register registers[] = {a1, a0};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
 void RegExpConstructResultDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {a2, a1, a0};
index be4c24e..ef3f0aa 100644 (file)
@@ -601,7 +601,7 @@ function NativeObjectNotifierPerformChange(objectInfo, changeType, changeFn) {
 
   var changeRecord;
   try {
-    changeRecord = %_CallFunction(UNDEFINED, changeFn);
+    changeRecord = changeFn();
   } finally {
     ObjectInfoRemovePerformingType(objectInfo, changeType);
   }
index f119a0a..97fc69c 100644 (file)
@@ -88,7 +88,7 @@ function PromiseCoerce(constructor, x) {
     if (IS_CALLABLE(then)) {
       var deferred = %_CallFunction(constructor, PromiseDeferred);
       try {
-        %_CallFunction(x, deferred.resolve, deferred.reject, then);
+        %_Call(then, x, deferred.resolve, deferred.reject);
       } catch(r) {
         deferred.reject(r);
       }
index 82c668a..e5e306d 100644 (file)
@@ -717,14 +717,14 @@ function IsConcatSpreadable(O) {
 function DefaultNumber(x) {
   var valueOf = x.valueOf;
   if (IS_CALLABLE(valueOf)) {
-    var v = %_CallFunction(x, valueOf);
+    var v = %_Call(valueOf, x);
     if (IS_SYMBOL(v)) throw MakeTypeError(kSymbolToNumber);
     if (IS_SIMD_VALUE(x)) throw MakeTypeError(kSimdToNumber);
     if (IsPrimitive(v)) return v;
   }
   var toString = x.toString;
   if (IS_CALLABLE(toString)) {
-    var s = %_CallFunction(x, toString);
+    var s = %_Call(toString, x);
     if (IsPrimitive(s)) return s;
   }
   throw MakeTypeError(kCannotConvertToPrimitive);
@@ -736,13 +736,13 @@ function DefaultString(x) {
     if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToString);
     var toString = x.toString;
     if (IS_CALLABLE(toString)) {
-      var s = %_CallFunction(x, toString);
+      var s = %_Call(toString, x);
       if (IsPrimitive(s)) return s;
     }
 
     var valueOf = x.valueOf;
     if (IS_CALLABLE(valueOf)) {
-      var v = %_CallFunction(x, valueOf);
+      var v = %_Call(valueOf, x);
       if (IsPrimitive(v)) return v;
     }
   }
index 51befee..9b33544 100644 (file)
 namespace v8 {
 namespace internal {
 
-// TODO(bmeurer): This is an awful hack resulting from our inability to decide
-// who's responsible for doing the receiver patching. By any means, we really
-// need to kill this runtime function and just do things right instead!!
-RUNTIME_FUNCTION(Runtime_IsSloppyModeFunction) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
-  if (!callable->IsJSFunction()) {
-    HandleScope scope(isolate);
-    Handle<JSFunction> delegate;
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, delegate,
-        Execution::GetFunctionDelegate(isolate, Handle<JSReceiver>(callable)));
-    callable = JSFunction::cast(*delegate);
-  }
-  JSFunction* function = JSFunction::cast(callable);
-  SharedFunctionInfo* shared = function->shared();
-  return isolate->heap()->ToBoolean(is_sloppy(shared->language_mode()));
-}
-
-
 RUNTIME_FUNCTION(Runtime_FunctionGetName) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 1);
@@ -532,32 +511,18 @@ RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
 
 RUNTIME_FUNCTION(Runtime_Call) {
   HandleScope scope(isolate);
-  DCHECK(args.length() >= 2);
-  int argc = args.length() - 2;
-  CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
-  Object* receiver = args[0];
-
-  // If there are too many arguments, allocate argv via malloc.
-  const int argv_small_size = 10;
-  Handle<Object> argv_small_buffer[argv_small_size];
-  base::SmartArrayPointer<Handle<Object> > argv_large_buffer;
-  Handle<Object>* argv = argv_small_buffer;
-  if (argc > argv_small_size) {
-    argv = new Handle<Object>[argc];
-    if (argv == NULL) return isolate->StackOverflow();
-    argv_large_buffer = base::SmartArrayPointer<Handle<Object> >(argv);
-  }
-
+  DCHECK_LE(2, args.length());
+  int const argc = args.length() - 2;
+  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
+  ScopedVector<Handle<Object>> argv(argc);
   for (int i = 0; i < argc; ++i) {
-    argv[i] = Handle<Object>(args[1 + i], isolate);
+    argv[i] = args.at<Object>(2 + i);
   }
-
-  Handle<JSReceiver> hfun(fun);
-  Handle<Object> hreceiver(receiver, isolate);
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
       isolate, result,
-      Execution::Call(isolate, hfun, hreceiver, argc, argv, true));
+      Execution::Call(isolate, target, receiver, argc, argv.start(), true));
   return *result;
 }
 
@@ -634,9 +599,37 @@ RUNTIME_FUNCTION(Runtime_GetOriginalConstructor) {
 }
 
 
+// TODO(bmeurer): Kill %_CallFunction ASAP as it is almost never used
+// correctly because of the weird semantics underneath.
 RUNTIME_FUNCTION(Runtime_CallFunction) {
-  SealHandleScope shs(isolate);
-  return __RT_impl_Runtime_Call(args, isolate);
+  HandleScope scope(isolate);
+  DCHECK(args.length() >= 2);
+  int argc = args.length() - 2;
+  CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
+  Object* receiver = args[0];
+
+  // If there are too many arguments, allocate argv via malloc.
+  const int argv_small_size = 10;
+  Handle<Object> argv_small_buffer[argv_small_size];
+  base::SmartArrayPointer<Handle<Object>> argv_large_buffer;
+  Handle<Object>* argv = argv_small_buffer;
+  if (argc > argv_small_size) {
+    argv = new Handle<Object>[argc];
+    if (argv == NULL) return isolate->StackOverflow();
+    argv_large_buffer = base::SmartArrayPointer<Handle<Object>>(argv);
+  }
+
+  for (int i = 0; i < argc; ++i) {
+    argv[i] = Handle<Object>(args[1 + i], isolate);
+  }
+
+  Handle<JSReceiver> hfun(fun);
+  Handle<Object> hreceiver(receiver, isolate);
+  Handle<Object> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result,
+      Execution::Call(isolate, hfun, hreceiver, argc, argv, true));
+  return *result;
 }
 
 
index 11366f5..15ecf04 100644 (file)
@@ -218,7 +218,6 @@ namespace internal {
 
 
 #define FOR_EACH_INTRINSIC_FUNCTION(F)                      \
-  F(IsSloppyModeFunction, 1, 1)                             \
   F(FunctionGetName, 1, 1)                                  \
   F(FunctionSetName, 2, 1)                                  \
   F(FunctionNameShouldPrintAsAnonymous, 1, 1)               \
index 97ed3cd..a8a9e8b 100644 (file)
@@ -314,8 +314,7 @@ function StringReplace(search, replace) {
 
   // Compute the string to replace with.
   if (IS_CALLABLE(replace)) {
-    var receiver = UNDEFINED;
-    result += %_CallFunction(receiver, search, start, subject, replace);
+    result += replace(search, start, subject);
   } else {
     reusableMatchInfo[CAPTURE0] = start;
     reusableMatchInfo[CAPTURE1] = end;
@@ -478,8 +477,7 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
         override[0] = elem;
         override[1] = match_start;
         $regexpLastMatchInfoOverride = override;
-        var func_result =
-            %_CallFunction(UNDEFINED, elem, match_start, subject, replace);
+        var func_result = replace(elem, match_start, subject);
         // Overwrite the i'th element in the results with the string we got
         // back from the callback function.
         res[i] = TO_STRING_INLINE(func_result);
@@ -525,7 +523,7 @@ function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) {
     // No captures, only the match, which is always valid.
     var s = %_SubString(subject, index, endOfMatch);
     // Don't call directly to avoid exposing the built-in global object.
-    replacement = %_CallFunction(UNDEFINED, s, index, subject, replace);
+    replacement = replace(s, index, subject);
   } else {
     var parameters = new InternalArray(m + 2);
     for (var j = 0; j < m; j++) {
index 416fd68..81fc13e 100644 (file)
@@ -143,7 +143,7 @@ function NAMEConstructByIterable(obj, iterable, iteratorFn) {
   // was already looked up, and wrap it in another iterable. The
   // __proto__ of the new iterable is set to null to avoid any chance
   // of modifications to Object.prototype being observable here.
-  var iterator = %_CallFunction(iterable, iteratorFn);
+  var iterator = %_Call(iteratorFn, iterable);
   var newIterable = {
     __proto__: null
   };
index 67deddb..1c60a2f 100644 (file)
@@ -32,7 +32,7 @@ function WeakMapConstructor(iterable) {
       if (!IS_SPEC_OBJECT(nextItem)) {
         throw MakeTypeError(kIteratorValueNotAnObject, nextItem);
       }
-      %_CallFunction(this, nextItem[0], nextItem[1], adder);
+      %_Call(adder, this, nextItem[0], nextItem[1]);
     }
   }
 }
@@ -118,7 +118,7 @@ function WeakSetConstructor(iterable) {
       throw MakeTypeError(kPropertyNotFunction, 'add', this);
     }
     for (var value of iterable) {
-      %_CallFunction(this, value, adder);
+      %_Call(adder, this, value);
     }
   }
 }
index 67e4970..d9f6d05 100644 (file)
@@ -191,6 +191,15 @@ void CallConstructDescriptor::InitializePlatformSpecific(
 }
 
 
+void CallTrampolineDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // rax : number of arguments
+  // rdi : the target to call
+  Register registers[] = {rdi, rax};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
 void RegExpConstructResultDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {rcx, rbx, rax};
index d843ca6..ba10122 100644 (file)
@@ -87,7 +87,7 @@ function WrapInCatcher(f, holder) {
 
 function WrapInNativeCall(f) {
   return function() {
-    return %Call(undefined, f);
+    return %Call(f, undefined);
   };
 }
 
index c024cef..3c36a4f 100644 (file)
@@ -106,10 +106,10 @@ function TestCall(isStrict, callTrap) {
   assertEquals(32, Function.prototype.apply.call(f, o, [17, 15]))
   assertSame(o, receiver)
   receiver = 333
-  assertEquals(42, %Call(o, 11, 31, f))
+  assertEquals(42, %Call(f, o, 11, 31));
   assertSame(o, receiver)
   receiver = 333
-  assertEquals(42, %Call(null, 11, 31, f))
+  assertEquals(42, %Call(f, null, 11, 31));
   assertSame(isStrict ? null : global_object, receiver)
   receiver = 333
   assertEquals(42, %Apply(f, o, [11, 31], 0, 2))
@@ -136,10 +136,10 @@ function TestCall(isStrict, callTrap) {
   assertEquals(32, Function.prototype.apply.call(ff, {}, [20]))
   assertSame(o, receiver)
   receiver = 333
-  assertEquals(23, %Call({}, 11, ff))
+  assertEquals(23, %Call(ff, {}, 11));
   assertSame(o, receiver)
   receiver = 333
-  assertEquals(23, %Call({}, 11, 3, ff))
+  assertEquals(23, %Call(ff, {}, 11, 3));
   assertSame(o, receiver)
   receiver = 333
   assertEquals(24, %Apply(ff, {}, [12, 13], 0, 1))
@@ -166,10 +166,10 @@ function TestCall(isStrict, callTrap) {
   assertEquals(42, Function.prototype.apply.call(fff, {}))
   assertSame(o, receiver)
   receiver = 333
-  assertEquals(42, %Call({}, fff))
+  assertEquals(42, %Call(fff, {}));
   assertSame(o, receiver)
   receiver = 333
-  assertEquals(42, %Call({}, 11, 3, fff))
+  assertEquals(42, %Call(fff, {}, 11, 3))
   assertSame(o, receiver)
   receiver = 333
   assertEquals(42, %Apply(fff, {}, [], 0, 0))
@@ -211,7 +211,7 @@ function TestCall(isStrict, callTrap) {
   assertEquals(32, Function.prototype.apply.call(f, o, [17, 15]))
   assertSame(o, receiver)
   receiver = 333
-  assertEquals(23, %Call(o, 11, 12, f))
+  assertEquals(23, %Call(f, o, 11, 12))
   assertSame(o, receiver)
   receiver = 333
   assertEquals(27, %Apply(f, o, [12, 13, 14], 1, 2))
@@ -280,8 +280,8 @@ function TestCallThrow(callTrap) {
   assertThrows(function(){ ({x: f})["x"](11) }, "myexn")
   assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
   assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
-  assertThrows(function(){ %Call({}, f) }, "myexn")
-  assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn")
+  assertThrows(function(){ %Call(f, {}) }, "myexn")
+  assertThrows(function(){ %Call(f, {}, 1, 2) }, "myexn")
   assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn")
   assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn")
   assertThrows(function(){ %_CallFunction({}, f) }, "myexn")
@@ -293,8 +293,8 @@ function TestCallThrow(callTrap) {
   assertThrows(function(){ ({x: f})["x"](11) }, "myexn")
   assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
   assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
-  assertThrows(function(){ %Call({}, f) }, "myexn")
-  assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn")
+  assertThrows(function(){ %Call(f, {}) }, "myexn")
+  assertThrows(function(){ %Call(f, {}, 1, 2) }, "myexn")
   assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn")
   assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn")
   assertThrows(function(){ %_CallFunction({}, f) }, "myexn")
@@ -698,7 +698,7 @@ function TestCalls() {
     function(f, x, y, o) { return Function.prototype.call.call(f, o, x, y) },
     function(f, x, y, o) { return Function.prototype.apply.call(f, o, [x, y]) },
     function(f, x, y, o) { return %_CallFunction(o, x, y, f) },
-    function(f, x, y, o) { return %Call(o, x, y, f) },
+    function(f, x, y, o) { return %Call(f, o, x, y) },
     function(f, x, y, o) { return %Apply(f, o, [null, x, y, null], 1, 2) },
     function(f, x, y, o) { return %Apply(f, o, arguments, 2, 2) },
     function(f, x, y, o) { if (typeof o == "object") return o.f(x, y) },
index 64d76c1..9a4f2fc 100644 (file)
@@ -72,7 +72,7 @@ function generateSpread(n) {
           `f.bind(undefined)(${generateArguments(argumentCount)})`,
           `%_CallFunction(${generateArguments(argumentCount, 'undefined')},
                           f)`,
-          `%Call(${generateArguments(argumentCount, 'undefined')}, f)`,
+          `%Call(f, ${generateArguments(argumentCount, 'undefined')})`,
           `%Apply(f, undefined, [${generateArguments(argumentCount)}], 0,
                   ${argumentCount})`,
         ];
@@ -135,7 +135,7 @@ function generateSpread(n) {
             `o.m.apply(o, [${generateArguments(argumentCount)}])`,
             `o.m.bind(o)(${generateArguments(argumentCount)})`,
             `%_CallFunction(${generateArguments(argumentCount, 'o')}, o.m)`,
-            `%Call(${generateArguments(argumentCount, 'o')}, o.m)`,
+            `%Call(o.m, ${generateArguments(argumentCount, 'o')})`,
             `%Apply(o.m, o, [${generateArguments(argumentCount)}], 0,
                     ${argumentCount})`,
           ];