From db2ba190dba6983b94eae36e111b0feebb97587e Mon Sep 17 00:00:00 2001 From: bmeurer Date: Tue, 8 Sep 2015 06:35:20 -0700 Subject: [PATCH] [runtime] Replace many buggy uses of %_CallFunction with %_Call. 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} --- src/arm/interface-descriptors-arm.cc | 9 +++ src/arm64/interface-descriptors-arm64.cc | 9 +++ src/array.js | 65 +++++---------------- src/collection.js | 26 ++------- src/compiler/linkage.cc | 1 + src/full-codegen/arm/full-codegen-arm.cc | 22 ++++++- src/full-codegen/arm64/full-codegen-arm64.cc | 23 +++++++- src/full-codegen/full-codegen.h | 1 + src/full-codegen/ia32/full-codegen-ia32.cc | 22 ++++++- src/full-codegen/mips/full-codegen-mips.cc | 22 ++++++- src/full-codegen/mips64/full-codegen-mips64.cc | 22 ++++++- src/full-codegen/x64/full-codegen-x64.cc | 22 ++++++- src/harmony-array.js | 30 ++-------- src/harmony-typedarray.js | 4 +- src/hydrogen.cc | 17 ++++++ src/hydrogen.h | 1 + src/ia32/interface-descriptors-ia32.cc | 9 +++ src/interface-descriptors.cc | 13 +++++ src/interface-descriptors.h | 8 +++ src/json.js | 6 +- src/macros.py | 1 - src/mips/interface-descriptors-mips.cc | 9 +++ src/mips64/interface-descriptors-mips64.cc | 9 +++ src/object-observe.js | 2 +- src/promise.js | 2 +- src/runtime.js | 8 +-- src/runtime/runtime-function.cc | 81 ++++++++++++-------------- src/runtime/runtime.h | 1 - src/string.js | 8 +-- src/typedarray.js | 2 +- src/weak-collection.js | 4 +- src/x64/interface-descriptors-x64.cc | 9 +++ test/mjsunit/debug-liveedit-check-stack.js | 2 +- test/mjsunit/harmony/proxies-function.js | 24 ++++---- test/mjsunit/strong/function-arity.js | 4 +- 35 files changed, 316 insertions(+), 182 deletions(-) diff --git a/src/arm/interface-descriptors-arm.cc b/src/arm/interface-descriptors-arm.cc index 7de994b..1054a25 100644 --- a/src/arm/interface-descriptors-arm.cc +++ b/src/arm/interface-descriptors-arm.cc @@ -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}; diff --git a/src/arm64/interface-descriptors-arm64.cc b/src/arm64/interface-descriptors-arm64.cc index 5e6ba60..d013362 100644 --- a/src/arm64/interface-descriptors-arm64.cc +++ b/src/arm64/interface-descriptors-arm64.cc @@ -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 diff --git a/src/array.js b/src/array.js index 265e80b..26f050d 100644 --- a/src/array.js +++ b/src/array.js @@ -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; diff --git a/src/collection.js b/src/collection.js index f7db862..8bf6ec3 100644 --- a/src/collection.js +++ b/src/collection.js @@ -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; }; diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc index 53a4ecc..fdef8e0 100644 --- a/src/compiler/linkage.cc +++ b/src/compiler/linkage.cc @@ -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: diff --git a/src/full-codegen/arm/full-codegen-arm.cc b/src/full-codegen/arm/full-codegen-arm.cc index 24dc516..02363c1 100644 --- a/src/full-codegen/arm/full-codegen-arm.cc +++ b/src/full-codegen/arm/full-codegen-arm.cc @@ -4056,6 +4056,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { } +void FullCodeGenerator::EmitCall(CallRuntime* expr) { + ZoneList* 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* 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); diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc index 59d5920..0fb38b1 100644 --- a/src/full-codegen/arm64/full-codegen-arm64.cc +++ b/src/full-codegen/arm64/full-codegen-arm64.cc @@ -3785,6 +3785,27 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { } +void FullCodeGenerator::EmitCall(CallRuntime* expr) { + ASM_LOCATION("FullCodeGenerator::EmitCallFunction"); + ZoneList* 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* 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); diff --git a/src/full-codegen/full-codegen.h b/src/full-codegen/full-codegen.h index 78304c4..bc78fda 100644 --- a/src/full-codegen/full-codegen.h +++ b/src/full-codegen/full-codegen.h @@ -493,6 +493,7 @@ class FullCodeGenerator: public AstVisitor { F(IsRegExp) \ F(IsJSProxy) \ F(IsConstructCall) \ + F(Call) \ F(CallFunction) \ F(DefaultConstructorCallSuper) \ F(ArgumentsLength) \ diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc index 1f1c19e..e47243a 100644 --- a/src/full-codegen/ia32/full-codegen-ia32.cc +++ b/src/full-codegen/ia32/full-codegen-ia32.cc @@ -3965,6 +3965,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { } +void FullCodeGenerator::EmitCall(CallRuntime* expr) { + ZoneList* 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* 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); diff --git a/src/full-codegen/mips/full-codegen-mips.cc b/src/full-codegen/mips/full-codegen-mips.cc index 0a3e5bb..1dde30c 100644 --- a/src/full-codegen/mips/full-codegen-mips.cc +++ b/src/full-codegen/mips/full-codegen-mips.cc @@ -4078,6 +4078,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { } +void FullCodeGenerator::EmitCall(CallRuntime* expr) { + ZoneList* 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* 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); diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc index 1052817..1e7ae09 100644 --- a/src/full-codegen/mips64/full-codegen-mips64.cc +++ b/src/full-codegen/mips64/full-codegen-mips64.cc @@ -4082,6 +4082,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { } +void FullCodeGenerator::EmitCall(CallRuntime* expr) { + ZoneList* 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* 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); diff --git a/src/full-codegen/x64/full-codegen-x64.cc b/src/full-codegen/x64/full-codegen-x64.cc index e6bb7ed..b7adbfd 100644 --- a/src/full-codegen/x64/full-codegen-x64.cc +++ b/src/full-codegen/x64/full-codegen-x64.cc @@ -3952,6 +3952,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { } +void FullCodeGenerator::EmitCall(CallRuntime* expr) { + ZoneList* 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* 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); diff --git a/src/harmony-array.js b/src/harmony-array.js index 779b67a..705adcd 100644 --- a/src/harmony-array.js +++ b/src/harmony-array.js @@ -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; } diff --git a/src/harmony-typedarray.js b/src/harmony-typedarray.js index 94d5f9a..9d66e21 100644 --- a/src/harmony-typedarray.js +++ b/src/harmony-typedarray.js @@ -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); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 99b4ddd..40d4c83 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -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(isolate()->builtins()->Call()); + HValue* target = Pop(); + HValue* values[] = {context(), target, + Add(call->arguments()->length() - 2)}; + HInstruction* result = New( + trampoline, call->arguments()->length() - 1, descriptor, + Vector(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. diff --git a/src/hydrogen.h b/src/hydrogen.h index 45c15ba..88a9fd8 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -2209,6 +2209,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { F(IsRegExp) \ F(IsJSProxy) \ F(IsConstructCall) \ + F(Call) \ F(CallFunction) \ F(ArgumentsLength) \ F(Arguments) \ diff --git a/src/ia32/interface-descriptors-ia32.cc b/src/ia32/interface-descriptors-ia32.cc index 1c0402f..821e57d 100644 --- a/src/ia32/interface-descriptors-ia32.cc +++ b/src/ia32/interface-descriptors-ia32.cc @@ -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}; diff --git a/src/interface-descriptors.cc b/src/interface-descriptors.cc index 9975815..b66f67c 100644 --- a/src/interface-descriptors.cc +++ b/src/interface-descriptors.cc @@ -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(); diff --git a/src/interface-descriptors.h b/src/interface-descriptors.h index 1168fe9..495a621 100644 --- a/src/interface-descriptors.h +++ b/src/interface-descriptors.h @@ -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) diff --git a/src/json.js b/src/json.js index 5ddf869..a0a88a0 100644 --- a/src/json.js +++ b/src/json.js @@ -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); diff --git a/src/macros.py b/src/macros.py index baaea93..6ea6d16 100644 --- a/src/macros.py +++ b/src/macros.py @@ -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. diff --git a/src/mips/interface-descriptors-mips.cc b/src/mips/interface-descriptors-mips.cc index 2f6bf5c..b02cdad 100644 --- a/src/mips/interface-descriptors-mips.cc +++ b/src/mips/interface-descriptors-mips.cc @@ -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}; diff --git a/src/mips64/interface-descriptors-mips64.cc b/src/mips64/interface-descriptors-mips64.cc index 4f896b7..f861513 100644 --- a/src/mips64/interface-descriptors-mips64.cc +++ b/src/mips64/interface-descriptors-mips64.cc @@ -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}; diff --git a/src/object-observe.js b/src/object-observe.js index be4c24e..ef3f0aa 100644 --- a/src/object-observe.js +++ b/src/object-observe.js @@ -601,7 +601,7 @@ function NativeObjectNotifierPerformChange(objectInfo, changeType, changeFn) { var changeRecord; try { - changeRecord = %_CallFunction(UNDEFINED, changeFn); + changeRecord = changeFn(); } finally { ObjectInfoRemovePerformingType(objectInfo, changeType); } diff --git a/src/promise.js b/src/promise.js index f119a0a..97fc69c 100644 --- a/src/promise.js +++ b/src/promise.js @@ -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); } diff --git a/src/runtime.js b/src/runtime.js index 82c668a..e5e306d 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -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; } } diff --git a/src/runtime/runtime-function.cc b/src/runtime/runtime-function.cc index 51befee..9b33544 100644 --- a/src/runtime/runtime-function.cc +++ b/src/runtime/runtime-function.cc @@ -16,27 +16,6 @@ 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 delegate; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, delegate, - Execution::GetFunctionDelegate(isolate, Handle(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 argv_small_buffer[argv_small_size]; - base::SmartArrayPointer > argv_large_buffer; - Handle* argv = argv_small_buffer; - if (argc > argv_small_size) { - argv = new Handle[argc]; - if (argv == NULL) return isolate->StackOverflow(); - argv_large_buffer = base::SmartArrayPointer >(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> argv(argc); for (int i = 0; i < argc; ++i) { - argv[i] = Handle(args[1 + i], isolate); + argv[i] = args.at(2 + i); } - - Handle hfun(fun); - Handle hreceiver(receiver, isolate); Handle 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 argv_small_buffer[argv_small_size]; + base::SmartArrayPointer> argv_large_buffer; + Handle* argv = argv_small_buffer; + if (argc > argv_small_size) { + argv = new Handle[argc]; + if (argv == NULL) return isolate->StackOverflow(); + argv_large_buffer = base::SmartArrayPointer>(argv); + } + + for (int i = 0; i < argc; ++i) { + argv[i] = Handle(args[1 + i], isolate); + } + + Handle hfun(fun); + Handle hreceiver(receiver, isolate); + Handle result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, + Execution::Call(isolate, hfun, hreceiver, argc, argv, true)); + return *result; } diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 11366f5..15ecf04 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -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) \ diff --git a/src/string.js b/src/string.js index 97ed3cd..a8a9e8b 100644 --- a/src/string.js +++ b/src/string.js @@ -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++) { diff --git a/src/typedarray.js b/src/typedarray.js index 416fd68..81fc13e 100644 --- a/src/typedarray.js +++ b/src/typedarray.js @@ -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 }; diff --git a/src/weak-collection.js b/src/weak-collection.js index 67deddb..1c60a2f 100644 --- a/src/weak-collection.js +++ b/src/weak-collection.js @@ -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); } } } diff --git a/src/x64/interface-descriptors-x64.cc b/src/x64/interface-descriptors-x64.cc index 67e4970..d9f6d05 100644 --- a/src/x64/interface-descriptors-x64.cc +++ b/src/x64/interface-descriptors-x64.cc @@ -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}; diff --git a/test/mjsunit/debug-liveedit-check-stack.js b/test/mjsunit/debug-liveedit-check-stack.js index d843ca6..ba10122 100644 --- a/test/mjsunit/debug-liveedit-check-stack.js +++ b/test/mjsunit/debug-liveedit-check-stack.js @@ -87,7 +87,7 @@ function WrapInCatcher(f, holder) { function WrapInNativeCall(f) { return function() { - return %Call(undefined, f); + return %Call(f, undefined); }; } diff --git a/test/mjsunit/harmony/proxies-function.js b/test/mjsunit/harmony/proxies-function.js index c024cef..3c36a4f 100644 --- a/test/mjsunit/harmony/proxies-function.js +++ b/test/mjsunit/harmony/proxies-function.js @@ -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) }, diff --git a/test/mjsunit/strong/function-arity.js b/test/mjsunit/strong/function-arity.js index 64d76c1..9a4f2fc 100644 --- a/test/mjsunit/strong/function-arity.js +++ b/test/mjsunit/strong/function-arity.js @@ -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})`, ]; -- 2.7.4