Commit 4f674da2 authored by ishell's avatar ishell Committed by Commit bot

[ic] Don't compile load interceptor handlers for LoadGlobalIC.

As a result LoadGlobalIC requires different slow stubs for each TypeofMode.

This CL is a prerequisite for not passing variable name to LoadGlobalIC:
the interceptor handler is the only kind of handler that requires a name
and therefore LoadGlobalIC dispatcher does not need a variable name as well.

BUG=chromium:576312

Review-Url: https://codereview.chromium.org/2081143002
Cr-Commit-Position: refs/heads/master@{#37222}
parent 25d59e9d
......@@ -5516,7 +5516,7 @@ void Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
}
void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) {
void Generate_LoadGlobalIC_SlowInsideTypeof(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* name = assembler->Parameter(0);
......@@ -5524,7 +5524,18 @@ void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) {
// Node* vector = assembler->Parameter(2);
Node* context = assembler->Parameter(3);
assembler->TailCallRuntime(Runtime::kGetGlobal, context, name);
assembler->TailCallRuntime(Runtime::kGetGlobalInsideTypeof, context, name);
}
void Generate_LoadGlobalIC_SlowNotInsideTypeof(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* name = assembler->Parameter(0);
// Node* slot = assembler->Parameter(1);
// Node* vector = assembler->Parameter(2);
Node* context = assembler->Parameter(3);
assembler->TailCallRuntime(Runtime::kGetGlobalNotInsideTypeof, context, name);
}
void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
......
......@@ -334,10 +334,13 @@ class CodeStubAssembler;
V(AtomicsStore, 4)
// Define list of builtins implemented in TurboFan (with CallStub linkage).
#define BUILTIN_LIST_S(V) \
V(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector) \
V(LoadGlobalIC_Slow, HANDLER, Code::LOAD_GLOBAL_IC, LoadGlobalWithVector) \
V(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector) \
#define BUILTIN_LIST_S(V) \
V(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector) \
V(LoadGlobalIC_SlowNotInsideTypeof, HANDLER, Code::LOAD_GLOBAL_IC, \
LoadGlobalWithVector) \
V(LoadGlobalIC_SlowInsideTypeof, HANDLER, Code::LOAD_GLOBAL_IC, \
LoadGlobalWithVector) \
V(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector) \
V(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector)
// Define list of builtin handlers implemented in assembly.
......
......@@ -938,15 +938,22 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
code = slow_stub();
}
} else if (lookup->state() == LookupIterator::INTERCEPTOR) {
// Perform a lookup behind the interceptor. Copy the LookupIterator since
// the original iterator will be used to fetch the value.
LookupIterator it = *lookup;
it.Next();
LookupForRead(&it);
if (it.state() == LookupIterator::ACCESSOR &&
!IsCompatibleReceiver(&it, receiver_map())) {
TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
if (kind() == Code::LOAD_GLOBAL_IC) {
// The interceptor handler requires name but it is not passed explicitly
// to LoadGlobalIC and the LoadGlobalIC dispatcher also does not load
// it so we will just use slow stub.
code = slow_stub();
} else {
// Perform a lookup behind the interceptor. Copy the LookupIterator
// since the original iterator will be used to fetch the value.
LookupIterator it = *lookup;
it.Next();
LookupForRead(&it);
if (it.state() == LookupIterator::ACCESSOR &&
!IsCompatibleReceiver(&it, receiver_map())) {
TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
code = slow_stub();
}
}
}
if (code.is_null()) code = ComputeHandler(lookup);
......@@ -2879,17 +2886,15 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
if (it.IsFound()) return *result;
#ifdef DEBUG
LoadICNexus nexus(isolate);
LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
// It could actually be any kind of LoadICs here but the predicate handles
// all the cases properly.
if (!ic.ShouldThrowReferenceError()) {
return isolate->heap()->undefined_value();
}
DCHECK(!ic.ShouldThrowReferenceError());
#endif
// Throw a reference error.
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name()));
return isolate->heap()->undefined_value();
}
......
......@@ -328,7 +328,12 @@ class LoadGlobalIC : public LoadIC {
protected:
Handle<Code> slow_stub() const override {
return isolate()->builtins()->LoadGlobalIC_Slow();
if (LoadGlobalICState::GetTypeofMode(extra_ic_state()) ==
NOT_INSIDE_TYPEOF) {
return isolate()->builtins()->LoadGlobalIC_SlowNotInsideTypeof();
} else {
return isolate()->builtins()->LoadGlobalIC_SlowInsideTypeof();
}
}
};
......
......@@ -15,9 +15,9 @@
namespace v8 {
namespace internal {
MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
Handle<Object> object,
Handle<Object> key) {
MaybeHandle<Object> Runtime::GetObjectProperty(
Isolate* isolate, Handle<Object> object, Handle<Object> key,
bool should_throw_reference_error) {
if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
THROW_NEW_ERROR(
isolate,
......@@ -30,7 +30,12 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
LookupIterator::PropertyOrElement(isolate, object, key, &success);
if (!success) return MaybeHandle<Object>();
return Object::GetProperty(&it);
MaybeHandle<Object> result = Object::GetProperty(&it);
if (!result.is_null() && should_throw_reference_error && !it.IsFound()) {
THROW_NEW_ERROR(
isolate, NewReferenceError(MessageTemplate::kNotDefined, key), Object);
}
return result;
}
static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate,
......@@ -343,12 +348,10 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
Runtime::GetObjectProperty(isolate, object, key));
}
RUNTIME_FUNCTION(Runtime_GetGlobal) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
namespace {
Object* GetGlobal(Isolate* isolate, Handle<String> name,
bool should_throw_reference_error) {
Handle<JSGlobalObject> global = isolate->global_object();
Handle<ScriptContextTable> script_contexts(
......@@ -364,16 +367,33 @@ RUNTIME_FUNCTION(Runtime_GetGlobal) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
}
return *result;
}
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Runtime::GetObjectProperty(isolate, global, name));
isolate, result,
Runtime::GetObjectProperty(isolate, global, name,
should_throw_reference_error));
return *result;
}
} // namespace
RUNTIME_FUNCTION(Runtime_GetGlobalInsideTypeof) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
return GetGlobal(isolate, name, false);
}
RUNTIME_FUNCTION(Runtime_GetGlobalNotInsideTypeof) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
return GetGlobal(isolate, name, true);
}
// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
HandleScope scope(isolate);
......
......@@ -384,7 +384,8 @@ namespace internal {
F(SetPrototype, 2, 1) \
F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
F(GetProperty, 2, 1) \
F(GetGlobal, 1, 1) \
F(GetGlobalInsideTypeof, 1, 1) \
F(GetGlobalNotInsideTypeof, 1, 1) \
F(KeyedGetProperty, 2, 1) \
F(StoreGlobalViaContext_Sloppy, 2, 1) \
F(StoreGlobalViaContext_Strict, 2, 1) \
......@@ -1073,7 +1074,8 @@ class Runtime : public AllStatic {
Handle<Object> value, LanguageMode language_mode);
MUST_USE_RESULT static MaybeHandle<Object> GetObjectProperty(
Isolate* isolate, Handle<Object> object, Handle<Object> key);
Isolate* isolate, Handle<Object> object, Handle<Object> key,
bool should_throw_reference_error = false);
enum TypedArrayId {
// arrayIds below should be synchronized with typedarray.js natives.
......
......@@ -854,6 +854,52 @@ THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
CHECK_EQ(42 * 10, value->Int32Value(context.local()).FromJust());
}
// Test load of a non-existing global when a global object has an interceptor.
THREADED_TEST(InterceptorLoadGlobalICGlobalWithInterceptor) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::Local<v8::ObjectTemplate> templ_global = v8::ObjectTemplate::New(isolate);
templ_global->SetHandler(v8::NamedPropertyHandlerConfiguration(
EmptyInterceptorGetter, EmptyInterceptorSetter));
LocalContext context(nullptr, templ_global);
i::Handle<i::JSReceiver> global_proxy =
v8::Utils::OpenHandle<Object, i::JSReceiver>(context->Global());
CHECK(global_proxy->IsJSGlobalProxy());
i::Handle<i::JSGlobalObject> global(
i::JSGlobalObject::cast(global_proxy->map()->prototype()));
CHECK(global->map()->has_named_interceptor());
v8::Local<Value> value = CompileRun(
"var f = function() { "
" try {"
" x;"
" return false;"
" } catch(e) {"
" return true;"
" }"
"};"
"for (var i = 0; i < 10; i++) {"
" f();"
"};"
"f();");
CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
value = CompileRun(
"var f = function() { "
" try {"
" typeof(x);"
" return true;"
" } catch(e) {"
" return false;"
" }"
"};"
"for (var i = 0; i < 10; i++) {"
" f();"
"};"
"f();");
CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
}
static void InterceptorLoadICGetter0(
Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
......
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