Commit cfbd1617 authored by jkummerow's avatar jkummerow Committed by Commit bot

[IC] Fix "compatible receiver" checks hidden behind interceptors

BUG=chromium:497632
LOG=y

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

Cr-Commit-Position: refs/heads/master@{#32945}
parent 641cdd30
...@@ -972,6 +972,39 @@ Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { ...@@ -972,6 +972,39 @@ Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
} }
bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
DCHECK(lookup->state() == LookupIterator::ACCESSOR);
Isolate* isolate = lookup->isolate();
Handle<Object> accessors = lookup->GetAccessors();
if (accessors->IsExecutableAccessorInfo()) {
Handle<ExecutableAccessorInfo> info =
Handle<ExecutableAccessorInfo>::cast(accessors);
if (info->getter() != NULL &&
!ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate, info,
receiver_map)) {
return false;
}
} else if (accessors->IsAccessorPair()) {
Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
isolate);
Handle<JSObject> holder = lookup->GetHolder<JSObject>();
Handle<Object> receiver = lookup->GetReceiver();
if (getter->IsJSFunction() && holder->HasFastProperties()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
if (receiver->IsJSObject() || function->shared()->IsBuiltin() ||
!is_sloppy(function->shared()->language_mode())) {
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
!call_optimization.IsCompatibleReceiverMap(receiver_map, holder)) {
return false;
}
}
}
}
return true;
}
void LoadIC::UpdateCaches(LookupIterator* lookup) { void LoadIC::UpdateCaches(LookupIterator* lookup) {
if (state() == UNINITIALIZED) { if (state() == UNINITIALIZED) {
// This is the first time we execute this inline cache. Set the target to // This is the first time we execute this inline cache. Set the target to
...@@ -996,37 +1029,22 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { ...@@ -996,37 +1029,22 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
} }
} else { } else {
if (lookup->state() == LookupIterator::ACCESSOR) { if (lookup->state() == LookupIterator::ACCESSOR) {
Handle<Object> accessors = lookup->GetAccessors(); if (!IsCompatibleReceiver(lookup, receiver_map())) {
Handle<Map> map = receiver_map();
if (accessors->IsExecutableAccessorInfo()) {
Handle<ExecutableAccessorInfo> info =
Handle<ExecutableAccessorInfo>::cast(accessors);
if ((v8::ToCData<Address>(info->getter()) != 0) &&
!ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate(), info,
map)) {
TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type"); TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
code = slow_stub(); code = slow_stub();
} }
} else if (accessors->IsAccessorPair()) { } else if (lookup->state() == LookupIterator::INTERCEPTOR) {
Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), // Perform a lookup behind the interceptor. Copy the LookupIterator since
isolate()); // the original iterator will be used to fetch the value.
Handle<JSObject> holder = lookup->GetHolder<JSObject>(); LookupIterator it = *lookup;
Handle<Object> receiver = lookup->GetReceiver(); it.Next();
if (getter->IsJSFunction() && holder->HasFastProperties()) { LookupForRead(&it);
Handle<JSFunction> function = Handle<JSFunction>::cast(getter); if (it.state() == LookupIterator::ACCESSOR &&
if (receiver->IsJSObject() || function->shared()->IsBuiltin() || !IsCompatibleReceiver(&it, receiver_map())) {
!is_sloppy(function->shared()->language_mode())) { TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
!call_optimization.IsCompatibleReceiver(receiver, holder)) {
TRACE_GENERIC_IC(isolate(), "LoadIC",
"incompatible receiver type");
code = slow_stub(); code = slow_stub();
} }
} }
}
}
}
if (code.is_null()) code = ComputeHandler(lookup); if (code.is_null()) code = ComputeHandler(lookup);
} }
......
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