Commit 1d92fd2e authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[turbofan] Fix missing holder lookup in AccessInfoFactory.

This makes sure we perform a proper holder lookup when trying to inline
API accessors calls in TurboFan. Inlining is completely disabled in case
the holder is not found, otherwise the appropriate holder is passed via
the {PropertyAccessInfo} structure (if different from the receiver).

R=bmeurer@chromium.org
TEST=cctest/test-api/ReceiverSignature
BUG=chromium:752149

Change-Id: I7b192724afd99d651b6477b2f2c8b403a10efb9d
Reviewed-on: https://chromium-review.googlesource.com/603615
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47216}
parent 2070a4fe
......@@ -409,9 +409,15 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
isolate());
if (!accessor->IsJSFunction()) {
CallOptimization optimization(accessor);
if (!optimization.is_simple_api_call()) {
return false;
}
if (!optimization.is_simple_api_call()) return false;
CallOptimization::HolderLookup lookup;
holder =
optimization.LookupHolderOfExpectedType(receiver_map, &lookup);
if (lookup == CallOptimization::kHolderNotFound) return false;
DCHECK_IMPLIES(lookup == CallOptimization::kHolderIsReceiver,
holder.is_null());
DCHECK_IMPLIES(lookup == CallOptimization::kHolderFound,
!holder.is_null());
if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
}
if (access_mode == AccessMode::kLoad) {
......
......@@ -1451,8 +1451,13 @@ Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
Handle<FunctionTemplateInfo> function_template_info(
Handle<FunctionTemplateInfo>::cast(access_info.constant()));
DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
value = InlineApiCall(receiver, context, target, frame_state0, nullptr,
effect, control, shared_info, function_template_info);
Node* holder =
access_info.holder().is_null()
? receiver
: jsgraph()->Constant(access_info.holder().ToHandleChecked());
value =
InlineApiCall(receiver, holder, context, target, frame_state0, nullptr,
effect, control, shared_info, function_template_info);
}
// Remember to rewire the IfException edge if this is inside a try-block.
if (if_exceptions != nullptr) {
......@@ -1498,8 +1503,13 @@ Node* JSNativeContextSpecialization::InlinePropertySetterCall(
Handle<FunctionTemplateInfo> function_template_info(
Handle<FunctionTemplateInfo>::cast(access_info.constant()));
DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
value = InlineApiCall(receiver, context, target, frame_state0, value,
effect, control, shared_info, function_template_info);
Node* holder =
access_info.holder().is_null()
? receiver
: jsgraph()->Constant(access_info.holder().ToHandleChecked());
value =
InlineApiCall(receiver, holder, context, target, frame_state0, value,
effect, control, shared_info, function_template_info);
}
// Remember to rewire the IfException edge if this is inside a try-block.
if (if_exceptions != nullptr) {
......@@ -1514,8 +1524,9 @@ Node* JSNativeContextSpecialization::InlinePropertySetterCall(
}
Node* JSNativeContextSpecialization::InlineApiCall(
Node* receiver, Node* context, Node* target, Node* frame_state, Node* value,
Node** effect, Node** control, Handle<SharedFunctionInfo> shared_info,
Node* receiver, Node* holder, Node* context, Node* target,
Node* frame_state, Node* value, Node** effect, Node** control,
Handle<SharedFunctionInfo> shared_info,
Handle<FunctionTemplateInfo> function_template_info) {
Handle<CallHandlerInfo> call_handler_info = handle(
CallHandlerInfo::cast(function_template_info->call_code()), isolate());
......@@ -1544,8 +1555,7 @@ Node* JSNativeContextSpecialization::InlineApiCall(
Node* code = jsgraph()->HeapConstant(stub.GetCode());
// Add CallApiCallbackStub's register argument as well.
Node* inputs[11] = {
code, target, data, receiver /* holder */, function_reference, receiver};
Node* inputs[11] = {code, target, data, holder, function_reference, receiver};
int index = 6 + argc;
inputs[index++] = context;
inputs[index++] = frame_state;
......
......@@ -146,7 +146,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
Node** control,
ZoneVector<Node*>* if_exceptions,
PropertyAccessInfo const& access_info);
Node* InlineApiCall(Node* receiver, Node* context, Node* target,
Node* InlineApiCall(Node* receiver, Node* holder, Node* context, Node* target,
Node* frame_state, Node* value, Node** effect,
Node** control, Handle<SharedFunctionInfo> shared_info,
Handle<FunctionTemplateInfo> function_template_info);
......
......@@ -195,15 +195,14 @@ THREADED_TEST(IsolateOfContext) {
CHECK(env->GetIsolate() == CcTest::isolate());
}
static void TestSignature(const char* loop_js, Local<Value> receiver,
v8::Isolate* isolate) {
static void TestSignatureLooped(const char* operation, Local<Value> receiver,
v8::Isolate* isolate) {
i::ScopedVector<char> source(200);
i::SNPrintF(source,
"for (var i = 0; i < 10; i++) {"
" %s"
"}",
loop_js);
operation);
signature_callback_count = 0;
signature_expected_receiver = receiver;
bool expected_to_throw = receiver.IsEmpty();
......@@ -222,8 +221,44 @@ static void TestSignature(const char* loop_js, Local<Value> receiver,
}
}
static void TestSignatureOptimized(const char* operation, Local<Value> receiver,
v8::Isolate* isolate) {
i::ScopedVector<char> source(200);
i::SNPrintF(source,
"function test() {"
" %s"
"}"
"try { test() } catch(e) {}"
"try { test() } catch(e) {}"
"%%OptimizeFunctionOnNextCall(test);"
"test()",
operation);
signature_callback_count = 0;
signature_expected_receiver = receiver;
bool expected_to_throw = receiver.IsEmpty();
v8::TryCatch try_catch(isolate);
CompileRun(source.start());
CHECK_EQ(expected_to_throw, try_catch.HasCaught());
if (!expected_to_throw) {
CHECK_EQ(3, signature_callback_count);
} else {
CHECK(v8_str("TypeError: Illegal invocation")
->Equals(isolate->GetCurrentContext(),
try_catch.Exception()
->ToString(isolate->GetCurrentContext())
.ToLocalChecked())
.FromJust());
}
}
static void TestSignature(const char* operation, Local<Value> receiver,
v8::Isolate* isolate) {
TestSignatureLooped(operation, receiver, isolate);
TestSignatureOptimized(operation, receiver, isolate);
}
THREADED_TEST(ReceiverSignature) {
i::FLAG_allow_natives_syntax = true;
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
......@@ -281,13 +316,14 @@ THREADED_TEST(ReceiverSignature) {
" }"
"}"
""
"var obj = {};"
"copy_props(obj);"
"var unrel = new UnrelFun();"
"copy_props(unrel);");
"var plain = {};"
"copy_props(plain);"
"var unrelated = new UnrelFun();"
"copy_props(unrelated);"
"var inherited = { __proto__: fun_instance };");
// Test with and without ICs
const char* test_objects[] = {
"fun_instance", "sub_fun_instance", "obj", "unrel" };
const char* test_objects[] = {"fun_instance", "sub_fun_instance", "plain",
"unrelated", "inherited"};
unsigned bad_signature_start_offset = 2;
for (unsigned i = 0; i < arraysize(test_objects); i++) {
i::ScopedVector<char> source(200);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment