Skip to content

Commit db2ba19

Browse files
bmeurerCommit bot
authored andcommitted
[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}
1 parent e615c03 commit db2ba19

35 files changed

Lines changed: 316 additions & 182 deletions

src/arm/interface-descriptors-arm.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ void CallConstructDescriptor::InitializePlatformSpecific(
192192
}
193193

194194

195+
void CallTrampolineDescriptor::InitializePlatformSpecific(
196+
CallInterfaceDescriptorData* data) {
197+
// r0 : number of arguments
198+
// r1 : the target to call
199+
Register registers[] = {r1, r0};
200+
data->InitializePlatformSpecific(arraysize(registers), registers);
201+
}
202+
203+
195204
void RegExpConstructResultDescriptor::InitializePlatformSpecific(
196205
CallInterfaceDescriptorData* data) {
197206
Register registers[] = {r2, r1, r0};

src/arm64/interface-descriptors-arm64.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,15 @@ void CallConstructDescriptor::InitializePlatformSpecific(
207207
}
208208

209209

210+
void CallTrampolineDescriptor::InitializePlatformSpecific(
211+
CallInterfaceDescriptorData* data) {
212+
// x1: target
213+
// x0: number of arguments
214+
Register registers[] = {x1, x0};
215+
data->InitializePlatformSpecific(arraysize(registers), registers);
216+
}
217+
218+
210219
void RegExpConstructResultDescriptor::InitializePlatformSpecific(
211220
CallInterfaceDescriptorData* data) {
212221
// x2: length

src/array.js

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ function ArrayToString() {
390390
if (!IS_CALLABLE(func)) {
391391
return %_CallFunction(array, ObjectToString);
392392
}
393-
return %_CallFunction(array, func);
393+
return %_Call(func, array);
394394
}
395395

396396

@@ -903,7 +903,7 @@ function InnerArraySort(array, length, comparefn) {
903903
var element = a[i];
904904
for (var j = i - 1; j >= from; j--) {
905905
var tmp = a[j];
906-
var order = %_CallFunction(UNDEFINED, tmp, element, comparefn);
906+
var order = comparefn(tmp, element);
907907
if (order > 0) {
908908
a[j + 1] = tmp;
909909
} else {
@@ -922,7 +922,7 @@ function InnerArraySort(array, length, comparefn) {
922922
t_array[j] = [i, a[i]];
923923
}
924924
%_CallFunction(t_array, function(a, b) {
925-
return %_CallFunction(UNDEFINED, a[1], b[1], comparefn);
925+
return comparefn(a[1], b[1]);
926926
}, ArraySort);
927927
var third_index = t_array[t_array.length >> 1][0];
928928
return third_index;
@@ -945,14 +945,14 @@ function InnerArraySort(array, length, comparefn) {
945945
var v0 = a[from];
946946
var v1 = a[to - 1];
947947
var v2 = a[third_index];
948-
var c01 = %_CallFunction(UNDEFINED, v0, v1, comparefn);
948+
var c01 = comparefn(v0, v1);
949949
if (c01 > 0) {
950950
// v1 < v0, so swap them.
951951
var tmp = v0;
952952
v0 = v1;
953953
v1 = tmp;
954954
} // v0 <= v1.
955-
var c02 = %_CallFunction(UNDEFINED, v0, v2, comparefn);
955+
var c02 = comparefn(v0, v2);
956956
if (c02 >= 0) {
957957
// v2 <= v0 <= v1.
958958
var tmp = v0;
@@ -961,7 +961,7 @@ function InnerArraySort(array, length, comparefn) {
961961
v1 = tmp;
962962
} else {
963963
// v0 <= v1 && v0 < v2
964-
var c12 = %_CallFunction(UNDEFINED, v1, v2, comparefn);
964+
var c12 = comparefn(v1, v2);
965965
if (c12 > 0) {
966966
// v0 <= v2 < v1
967967
var tmp = v1;
@@ -982,7 +982,7 @@ function InnerArraySort(array, length, comparefn) {
982982
// From i to high_start are elements that haven't been compared yet.
983983
partition: for (var i = low_end + 1; i < high_start; i++) {
984984
var element = a[i];
985-
var order = %_CallFunction(UNDEFINED, element, pivot, comparefn);
985+
var order = comparefn(element, pivot);
986986
if (order < 0) {
987987
a[i] = a[low_end];
988988
a[low_end] = element;
@@ -992,7 +992,7 @@ function InnerArraySort(array, length, comparefn) {
992992
high_start--;
993993
if (high_start == i) break partition;
994994
var top_elem = a[high_start];
995-
order = %_CallFunction(UNDEFINED, top_elem, pivot, comparefn);
995+
order = comparefn(top_elem, pivot);
996996
} while (order > 0);
997997
a[i] = a[high_start];
998998
a[high_start] = element;
@@ -1179,12 +1179,6 @@ function ArraySort(comparefn) {
11791179
// or delete elements from the array.
11801180
function InnerArrayFilter(f, receiver, array, length) {
11811181
if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
1182-
var needs_wrapper = false;
1183-
if (IS_NULL(receiver)) {
1184-
if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
1185-
} else if (!IS_UNDEFINED(receiver)) {
1186-
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
1187-
}
11881182

11891183
var accumulator = new InternalArray();
11901184
var accumulator_length = 0;
@@ -1195,8 +1189,7 @@ function InnerArrayFilter(f, receiver, array, length) {
11951189
var element = array[i];
11961190
// Prepare break slots for debugger step in.
11971191
if (stepping) %DebugPrepareStepInIfStepping(f);
1198-
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
1199-
if (%_CallFunction(new_receiver, element, i, array, f)) {
1192+
if (%_Call(f, receiver, element, i, array)) {
12001193
accumulator[accumulator_length++] = element;
12011194
}
12021195
}
@@ -1219,12 +1212,6 @@ function ArrayFilter(f, receiver) {
12191212

12201213
function InnerArrayForEach(f, receiver, array, length) {
12211214
if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
1222-
var needs_wrapper = false;
1223-
if (IS_NULL(receiver)) {
1224-
if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
1225-
} else if (!IS_UNDEFINED(receiver)) {
1226-
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
1227-
}
12281215

12291216
var is_array = IS_ARRAY(array);
12301217
var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
@@ -1233,8 +1220,7 @@ function InnerArrayForEach(f, receiver, array, length) {
12331220
var element = array[i];
12341221
// Prepare break slots for debugger step in.
12351222
if (stepping) %DebugPrepareStepInIfStepping(f);
1236-
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
1237-
%_CallFunction(new_receiver, element, i, array, f);
1223+
%_Call(f, receiver, element, i, array);
12381224
}
12391225
}
12401226
}
@@ -1252,12 +1238,6 @@ function ArrayForEach(f, receiver) {
12521238

12531239
function InnerArraySome(f, receiver, array, length) {
12541240
if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
1255-
var needs_wrapper = false;
1256-
if (IS_NULL(receiver)) {
1257-
if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
1258-
} else if (!IS_UNDEFINED(receiver)) {
1259-
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
1260-
}
12611241

12621242
var is_array = IS_ARRAY(array);
12631243
var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
@@ -1266,8 +1246,7 @@ function InnerArraySome(f, receiver, array, length) {
12661246
var element = array[i];
12671247
// Prepare break slots for debugger step in.
12681248
if (stepping) %DebugPrepareStepInIfStepping(f);
1269-
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
1270-
if (%_CallFunction(new_receiver, element, i, array, f)) return true;
1249+
if (%_Call(f, receiver, element, i, array)) return true;
12711250
}
12721251
}
12731252
return false;
@@ -1289,12 +1268,6 @@ function ArraySome(f, receiver) {
12891268

12901269
function InnerArrayEvery(f, receiver, array, length) {
12911270
if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
1292-
var needs_wrapper = false;
1293-
if (IS_NULL(receiver)) {
1294-
if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
1295-
} else if (!IS_UNDEFINED(receiver)) {
1296-
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
1297-
}
12981271

12991272
var is_array = IS_ARRAY(array);
13001273
var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
@@ -1303,8 +1276,7 @@ function InnerArrayEvery(f, receiver, array, length) {
13031276
var element = array[i];
13041277
// Prepare break slots for debugger step in.
13051278
if (stepping) %DebugPrepareStepInIfStepping(f);
1306-
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
1307-
if (!%_CallFunction(new_receiver, element, i, array, f)) return false;
1279+
if (!%_Call(f, receiver, element, i, array)) return false;
13081280
}
13091281
}
13101282
return true;
@@ -1323,12 +1295,6 @@ function ArrayEvery(f, receiver) {
13231295

13241296
function InnerArrayMap(f, receiver, array, length) {
13251297
if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
1326-
var needs_wrapper = false;
1327-
if (IS_NULL(receiver)) {
1328-
if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
1329-
} else if (!IS_UNDEFINED(receiver)) {
1330-
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
1331-
}
13321298

13331299
var accumulator = new InternalArray(length);
13341300
var is_array = IS_ARRAY(array);
@@ -1338,8 +1304,7 @@ function InnerArrayMap(f, receiver, array, length) {
13381304
var element = array[i];
13391305
// Prepare break slots for debugger step in.
13401306
if (stepping) %DebugPrepareStepInIfStepping(f);
1341-
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
1342-
accumulator[i] = %_CallFunction(new_receiver, element, i, array, f);
1307+
accumulator[i] = %_Call(f, receiver, element, i, array);
13431308
}
13441309
}
13451310
return accumulator;
@@ -1508,7 +1473,7 @@ function InnerArrayReduce(callback, current, array, length, argumentsLength) {
15081473
var element = array[i];
15091474
// Prepare break slots for debugger step in.
15101475
if (stepping) %DebugPrepareStepInIfStepping(callback);
1511-
current = %_CallFunction(UNDEFINED, current, element, i, array, callback);
1476+
current = callback(current, element, i, array);
15121477
}
15131478
}
15141479
return current;
@@ -1551,7 +1516,7 @@ function InnerArrayReduceRight(callback, current, array, length,
15511516
var element = array[i];
15521517
// Prepare break slots for debugger step in.
15531518
if (stepping) %DebugPrepareStepInIfStepping(callback);
1554-
current = %_CallFunction(UNDEFINED, current, element, i, array, callback);
1519+
current = callback(current, element, i, array);
15551520
}
15561521
}
15571522
return current;

src/collection.js

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ function SetConstructor(iterable) {
139139
}
140140

141141
for (var value of iterable) {
142-
%_CallFunction(this, value, adder);
142+
%_Call(adder, this, value);
143143
}
144144
}
145145
}
@@ -246,12 +246,6 @@ function SetForEach(f, receiver) {
246246
}
247247

248248
if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
249-
var needs_wrapper = false;
250-
if (IS_NULL(receiver)) {
251-
if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
252-
} else if (!IS_UNDEFINED(receiver)) {
253-
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
254-
}
255249

256250
var iterator = new SetIterator(this, ITERATOR_KIND_VALUES);
257251
var key;
@@ -260,8 +254,7 @@ function SetForEach(f, receiver) {
260254
while (%SetIteratorNext(iterator, value_array)) {
261255
if (stepping) %DebugPrepareStepInIfStepping(f);
262256
key = value_array[0];
263-
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
264-
%_CallFunction(new_receiver, key, key, this, f);
257+
%_Call(f, receiver, key, key, this);
265258
}
266259
}
267260

@@ -307,7 +300,7 @@ function MapConstructor(iterable) {
307300
if (!IS_SPEC_OBJECT(nextItem)) {
308301
throw MakeTypeError(kIteratorValueNotAnObject, nextItem);
309302
}
310-
%_CallFunction(this, nextItem[0], nextItem[1], adder);
303+
%_Call(adder, this, nextItem[0], nextItem[1]);
311304
}
312305
}
313306
}
@@ -437,20 +430,13 @@ function MapForEach(f, receiver) {
437430
}
438431

439432
if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
440-
var needs_wrapper = false;
441-
if (IS_NULL(receiver)) {
442-
if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
443-
} else if (!IS_UNDEFINED(receiver)) {
444-
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
445-
}
446433

447434
var iterator = new MapIterator(this, ITERATOR_KIND_ENTRIES);
448435
var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
449436
var value_array = [UNDEFINED, UNDEFINED];
450437
while (%MapIteratorNext(iterator, value_array)) {
451438
if (stepping) %DebugPrepareStepInIfStepping(f);
452-
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
453-
%_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
439+
%_Call(f, receiver, value_array[1], value_array[0], this);
454440
}
455441
}
456442

@@ -486,7 +472,7 @@ function MapFromArray(array) {
486472
for (var i = 0; i < length; i += 2) {
487473
var key = array[i];
488474
var value = array[i + 1];
489-
%_CallFunction(map, key, value, MapSet);
475+
%_Call(MapSet, map, key, value);
490476
}
491477
return map;
492478
};
@@ -495,7 +481,7 @@ function SetFromArray(array) {
495481
var set = new GlobalSet;
496482
var length = array.length;
497483
for (var i = 0; i < length; ++i) {
498-
%_CallFunction(set, array[i], SetAdd);
484+
%_Call(SetAdd, set, array[i]);
499485
}
500486
return set;
501487
};

src/compiler/linkage.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
238238
case Runtime::kTraceExit:
239239
return 0;
240240
case Runtime::kInlineArguments:
241+
case Runtime::kInlineCall:
241242
case Runtime::kInlineCallFunction:
242243
case Runtime::kInlineDefaultConstructorCallSuper:
243244
case Runtime::kInlineGetCallerJSFunction:

src/full-codegen/arm/full-codegen-arm.cc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4056,6 +4056,26 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
40564056
}
40574057

40584058

4059+
void FullCodeGenerator::EmitCall(CallRuntime* expr) {
4060+
ZoneList<Expression*>* args = expr->arguments();
4061+
DCHECK_LE(2, args->length());
4062+
// Push target, receiver and arguments onto the stack.
4063+
for (Expression* const arg : *args) {
4064+
VisitForStackValue(arg);
4065+
}
4066+
// Move target to r1.
4067+
int const argc = args->length() - 2;
4068+
__ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
4069+
// Call the target.
4070+
__ mov(r0, Operand(argc));
4071+
__ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
4072+
// Restore context register.
4073+
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4074+
// Discard the function left on TOS.
4075+
context()->DropAndPlug(1, r0);
4076+
}
4077+
4078+
40594079
void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
40604080
ZoneList<Expression*>* args = expr->arguments();
40614081
DCHECK(args->length() >= 2);
@@ -4081,7 +4101,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
40814101

40824102
__ bind(&runtime);
40834103
__ push(r0);
4084-
__ CallRuntime(Runtime::kCall, args->length());
4104+
__ CallRuntime(Runtime::kCallFunction, args->length());
40854105
__ bind(&done);
40864106

40874107
context()->Plug(r0);

src/full-codegen/arm64/full-codegen-arm64.cc

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3785,6 +3785,27 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
37853785
}
37863786

37873787

3788+
void FullCodeGenerator::EmitCall(CallRuntime* expr) {
3789+
ASM_LOCATION("FullCodeGenerator::EmitCallFunction");
3790+
ZoneList<Expression*>* args = expr->arguments();
3791+
DCHECK_LE(2, args->length());
3792+
// Push target, receiver and arguments onto the stack.
3793+
for (Expression* const arg : *args) {
3794+
VisitForStackValue(arg);
3795+
}
3796+
// Move target to x1.
3797+
int const argc = args->length() - 2;
3798+
__ Peek(x1, (argc + 1) * kXRegSize);
3799+
// Call the target.
3800+
__ Mov(x0, argc);
3801+
__ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
3802+
// Restore context register.
3803+
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3804+
// Discard the function left on TOS.
3805+
context()->DropAndPlug(1, x0);
3806+
}
3807+
3808+
37883809
void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
37893810
ASM_LOCATION("FullCodeGenerator::EmitCallFunction");
37903811
ZoneList<Expression*>* args = expr->arguments();
@@ -3810,7 +3831,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
38103831

38113832
__ Bind(&runtime);
38123833
__ Push(x0);
3813-
__ CallRuntime(Runtime::kCall, args->length());
3834+
__ CallRuntime(Runtime::kCallFunction, args->length());
38143835
__ Bind(&done);
38153836

38163837
context()->Plug(x0);

0 commit comments

Comments
 (0)