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) { ...@@ -5516,7 +5516,7 @@ void Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name); assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
} }
void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) { void Generate_LoadGlobalIC_SlowInsideTypeof(CodeStubAssembler* assembler) {
typedef compiler::Node Node; typedef compiler::Node Node;
Node* name = assembler->Parameter(0); Node* name = assembler->Parameter(0);
...@@ -5524,7 +5524,18 @@ void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) { ...@@ -5524,7 +5524,18 @@ void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) {
// Node* vector = assembler->Parameter(2); // Node* vector = assembler->Parameter(2);
Node* context = assembler->Parameter(3); 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) { void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
......
...@@ -336,7 +336,10 @@ class CodeStubAssembler; ...@@ -336,7 +336,10 @@ class CodeStubAssembler;
// Define list of builtins implemented in TurboFan (with CallStub linkage). // Define list of builtins implemented in TurboFan (with CallStub linkage).
#define BUILTIN_LIST_S(V) \ #define BUILTIN_LIST_S(V) \
V(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector) \ V(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector) \
V(LoadGlobalIC_Slow, HANDLER, Code::LOAD_GLOBAL_IC, 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_Miss, BUILTIN, kNoExtraICState, LoadWithVector) \
V(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector) V(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector)
......
...@@ -938,8 +938,14 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { ...@@ -938,8 +938,14 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
code = slow_stub(); code = slow_stub();
} }
} else if (lookup->state() == LookupIterator::INTERCEPTOR) { } else if (lookup->state() == LookupIterator::INTERCEPTOR) {
// Perform a lookup behind the interceptor. Copy the LookupIterator since if (kind() == Code::LOAD_GLOBAL_IC) {
// the original iterator will be used to fetch the value. // 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; LookupIterator it = *lookup;
it.Next(); it.Next();
LookupForRead(&it); LookupForRead(&it);
...@@ -949,6 +955,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { ...@@ -949,6 +955,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
code = slow_stub(); code = slow_stub();
} }
} }
}
if (code.is_null()) code = ComputeHandler(lookup); if (code.is_null()) code = ComputeHandler(lookup);
} }
...@@ -2879,17 +2886,15 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) { ...@@ -2879,17 +2886,15 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
if (it.IsFound()) return *result; if (it.IsFound()) return *result;
#ifdef DEBUG
LoadICNexus nexus(isolate); LoadICNexus nexus(isolate);
LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
// It could actually be any kind of LoadICs here but the predicate handles // It could actually be any kind of LoadICs here but the predicate handles
// all the cases properly. // all the cases properly.
if (!ic.ShouldThrowReferenceError()) { DCHECK(!ic.ShouldThrowReferenceError());
return isolate->heap()->undefined_value(); #endif
}
// Throw a reference error. return isolate->heap()->undefined_value();
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name()));
} }
......
...@@ -328,7 +328,12 @@ class LoadGlobalIC : public LoadIC { ...@@ -328,7 +328,12 @@ class LoadGlobalIC : public LoadIC {
protected: protected:
Handle<Code> slow_stub() const override { 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 @@ ...@@ -15,9 +15,9 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, MaybeHandle<Object> Runtime::GetObjectProperty(
Handle<Object> object, Isolate* isolate, Handle<Object> object, Handle<Object> key,
Handle<Object> key) { bool should_throw_reference_error) {
if (object->IsUndefined(isolate) || object->IsNull(isolate)) { if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
THROW_NEW_ERROR( THROW_NEW_ERROR(
isolate, isolate,
...@@ -30,7 +30,12 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, ...@@ -30,7 +30,12 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
LookupIterator::PropertyOrElement(isolate, object, key, &success); LookupIterator::PropertyOrElement(isolate, object, key, &success);
if (!success) return MaybeHandle<Object>(); 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, static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate,
...@@ -343,12 +348,10 @@ RUNTIME_FUNCTION(Runtime_GetProperty) { ...@@ -343,12 +348,10 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
Runtime::GetObjectProperty(isolate, object, key)); Runtime::GetObjectProperty(isolate, object, key));
} }
RUNTIME_FUNCTION(Runtime_GetGlobal) { namespace {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Object* GetGlobal(Isolate* isolate, Handle<String> name,
bool should_throw_reference_error) {
Handle<JSGlobalObject> global = isolate->global_object(); Handle<JSGlobalObject> global = isolate->global_object();
Handle<ScriptContextTable> script_contexts( Handle<ScriptContextTable> script_contexts(
...@@ -364,16 +367,33 @@ RUNTIME_FUNCTION(Runtime_GetGlobal) { ...@@ -364,16 +367,33 @@ RUNTIME_FUNCTION(Runtime_GetGlobal) {
THROW_NEW_ERROR_RETURN_FAILURE( THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
} }
return *result; return *result;
} }
Handle<Object> result; Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 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; 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. // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
HandleScope scope(isolate); HandleScope scope(isolate);
......
...@@ -384,7 +384,8 @@ namespace internal { ...@@ -384,7 +384,8 @@ namespace internal {
F(SetPrototype, 2, 1) \ F(SetPrototype, 2, 1) \
F(OptimizeObjectForAddingMultipleProperties, 2, 1) \ F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
F(GetProperty, 2, 1) \ F(GetProperty, 2, 1) \
F(GetGlobal, 1, 1) \ F(GetGlobalInsideTypeof, 1, 1) \
F(GetGlobalNotInsideTypeof, 1, 1) \
F(KeyedGetProperty, 2, 1) \ F(KeyedGetProperty, 2, 1) \
F(StoreGlobalViaContext_Sloppy, 2, 1) \ F(StoreGlobalViaContext_Sloppy, 2, 1) \
F(StoreGlobalViaContext_Strict, 2, 1) \ F(StoreGlobalViaContext_Strict, 2, 1) \
...@@ -1073,7 +1074,8 @@ class Runtime : public AllStatic { ...@@ -1073,7 +1074,8 @@ class Runtime : public AllStatic {
Handle<Object> value, LanguageMode language_mode); Handle<Object> value, LanguageMode language_mode);
MUST_USE_RESULT static MaybeHandle<Object> GetObjectProperty( 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 { enum TypedArrayId {
// arrayIds below should be synchronized with typedarray.js natives. // arrayIds below should be synchronized with typedarray.js natives.
......
...@@ -854,6 +854,52 @@ THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) { ...@@ -854,6 +854,52 @@ THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
CHECK_EQ(42 * 10, value->Int32Value(context.local()).FromJust()); 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( static void InterceptorLoadICGetter0(
Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { 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