[compiler] Wrong receiver in API calls with --turbo-optimize-apply

Enabling --turbo-optimize-apply breaks tests because we are
passing the wrong receiver;
in JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread
we create a Call node with the wrong ConvertReceiverMode, we
pass kNullOrUndefined while it should be kAny. This may break
calls to API or in general calls to functions that use the
receiver.

Bug: chromium:1231108, v8:9974
Change-Id: Ib35a1bf8746ad254b6d63274f3ae11b12aa83de8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3043690
Commit-Queue: Paolo Severini <paolosev@microsoft.com>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75886}
This commit is contained in:
Paolo Severini 2021-07-23 05:55:45 -07:00 committed by V8 LUCI CQ
parent 66b4c39d95
commit 6a5568b48e
3 changed files with 73 additions and 4 deletions

View File

@ -4301,10 +4301,10 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
}
NodeProperties::ChangeOp(
node, javascript()->Call(
JSCallNode::ArityForArgc(new_argument_count), frequency,
feedback_source, ConvertReceiverMode::kNullOrUndefined,
speculation_mode, CallFeedbackRelation::kUnrelated));
node,
javascript()->Call(JSCallNode::ArityForArgc(new_argument_count),
frequency, feedback_source, ConvertReceiverMode::kAny,
speculation_mode, CallFeedbackRelation::kUnrelated));
NodeProperties::ReplaceEffectInput(node, effect);
return Changed(node).FollowedBy(ReduceJSCall(node));
}

View File

@ -126,6 +126,57 @@ TEST(ReduceJSCreateBoundFunction) {
IrOpcode::kPhi);
}
static void SumF(const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
int this_x = args.This()
->Get(context, v8_str("x"))
.ToLocalChecked()
->Int32Value(context)
.FromJust();
args.GetReturnValue().Set(v8_num(
args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust() +
args[1]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust() +
this_x));
}
TEST(ReduceCAPICallWithArrayLike) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
FLAG_allow_natives_syntax = true;
FLAG_turbo_optimize_apply = true;
Local<v8::FunctionTemplate> sum = v8::FunctionTemplate::New(isolate, SumF);
CHECK(env->Global()
->Set(env.local(), v8_str("sum"),
sum->GetFunction(env.local()).ToLocalChecked())
.FromJust());
Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
v8::Local<v8::String> class_name = v8_str("the_class_name");
fun->SetClassName(class_name);
Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
templ1->Set(isolate, "x", v8_num(42));
templ1->Set(isolate, "foo", sum);
Local<v8::Object> instance1 =
templ1->NewInstance(env.local()).ToLocalChecked();
CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
std::string js_code =
"function bar(a, b) { return sum.apply(p, [a, b]); }"
"%PrepareFunctionForOptimization(bar);"
"bar(20, 22);"
"%OptimizeFunctionOnNextCall(bar);"
"bar(20, 22);";
v8::Local<v8::Value> result_value = CompileRun(js_code.c_str());
CHECK(result_value->IsNumber());
int32_t result =
ConvertJSValue<int32_t>::Get(result_value, env.local()).ToChecked();
CHECK_EQ(result, 84);
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -37,6 +37,24 @@
assertFalse(sum_js_got_interpreted);
})();
// Test using receiver
(function () {
function bar() {
return this.gaga;
}
function foo(receiver) {
return bar.apply(receiver, [""]);
}
%PrepareFunctionForOptimization(bar);
%PrepareFunctionForOptimization(foo);
var receiver = { gaga: 42 };
assertEquals(42, foo(receiver));
%OptimizeFunctionOnNextCall(foo);
assertEquals(42, foo(receiver));
assertOptimized(foo);
})();
// Test with holey array.
(function () {
"use strict";