From 046031e02d2de2b7f8565975db41c1826d2d790d Mon Sep 17 00:00:00 2001 From: Igor Sheludko Date: Wed, 5 Jul 2017 20:29:13 +0200 Subject: [PATCH] deps: cherry-pick 6cb999b97b from V8 upstream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: Properly handle loads from global interceptor via prototype chain. ... when receiver is in dictionary mode. Bug: v8:6490 Change-Id: Ic5a8d214adcc4efd4cb163cbc6b351c4e6b596af Reviewed-on: https://chromium-review.googlesource.com/559548 Reviewed-by: Camillo Bruni Commit-Queue: Igor Sheludko Cr-Commit-Position: refs/heads/master@{#46428} Ref: https://chromium.googlesource.com/v8/v8.git/+/6cb999b97b7953ebfd4aabf2e1f62bf405f21c69 Fixes: https://github.com/nodejs/node/issues/13804 PR-URL: https://github.com/nodejs/node/pull/14188 Reviewed-By: Ben Noordhuis Reviewed-By: Michaƫl Zasso --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/ic/handler-configuration-inl.h | 5 +++ deps/v8/src/ic/handler-configuration.h | 3 ++ deps/v8/src/ic/ic.cc | 21 +++++++++--- deps/v8/test/cctest/test-api-interceptors.cc | 35 ++++++++++++++++++++ 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 0d920efac46d52..f1b394a8c4a1ab 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 5 #define V8_MINOR_VERSION 9 #define V8_BUILD_NUMBER 211 -#define V8_PATCH_LEVEL 37 +#define V8_PATCH_LEVEL 38 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/ic/handler-configuration-inl.h b/deps/v8/src/ic/handler-configuration-inl.h index 2b9dc04b5a9395..5f31d15d46fcc3 100644 --- a/deps/v8/src/ic/handler-configuration-inl.h +++ b/deps/v8/src/ic/handler-configuration-inl.h @@ -13,6 +13,11 @@ namespace v8 { namespace internal { +// Decodes kind from Smi-handler. +LoadHandler::Kind LoadHandler::GetHandlerKind(Smi* smi_handler) { + return KindBits::decode(smi_handler->value()); +} + Handle LoadHandler::LoadNormal(Isolate* isolate) { int config = KindBits::encode(kNormal); return handle(Smi::FromInt(config), isolate); diff --git a/deps/v8/src/ic/handler-configuration.h b/deps/v8/src/ic/handler-configuration.h index ab117d5c9bd5cb..eed548b4d5edeb 100644 --- a/deps/v8/src/ic/handler-configuration.h +++ b/deps/v8/src/ic/handler-configuration.h @@ -90,6 +90,9 @@ class LoadHandler { static const int kHolderCellIndex = 2; static const int kFirstPrototypeIndex = 3; + // Decodes kind from Smi-handler. + static inline Kind GetHandlerKind(Smi* smi_handler); + // Creates a Smi-handler for loading a property from a slow object. static inline Handle LoadNormal(Isolate* isolate); diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc index b3b0eb4c849e52..ca3f70df2ab41d 100644 --- a/deps/v8/src/ic/ic.cc +++ b/deps/v8/src/ic/ic.cc @@ -868,10 +868,15 @@ int GetPrototypeCheckCount(Isolate* isolate, Handle receiver_map, Handle(), 0); } +enum class HolderCellRequest { + kGlobalPropertyCell, + kHolder, +}; + Handle HolderCell(Isolate* isolate, Handle holder, - Handle name, Handle smi_handler) { - if (holder->IsJSGlobalObject() && - *smi_handler != *LoadHandler::LoadInterceptor(isolate)) { + Handle name, HolderCellRequest request) { + if (request == HolderCellRequest::kGlobalPropertyCell) { + DCHECK(holder->IsJSGlobalObject()); Handle global = Handle::cast(holder); GlobalDictionary* dict = global->global_dictionary(); int number = dict->FindEntry(name); @@ -908,8 +913,14 @@ Handle LoadIC::LoadFromPrototype(Handle receiver_map, Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); DCHECK(!validity_cell.is_null()); - Handle holder_cell = - HolderCell(isolate(), holder, name, smi_handler); + // LoadIC dispatcher expects PropertyCell as a "holder" in case of kGlobal + // handler kind. + HolderCellRequest request = + LoadHandler::GetHandlerKind(*smi_handler) == LoadHandler::kGlobal + ? HolderCellRequest::kGlobalPropertyCell + : HolderCellRequest::kHolder; + + Handle holder_cell = HolderCell(isolate(), holder, name, request); if (checks_count == 0) { return isolate()->factory()->NewTuple3(holder_cell, smi_handler, diff --git a/deps/v8/test/cctest/test-api-interceptors.cc b/deps/v8/test/cctest/test-api-interceptors.cc index 9680b4241b8521..9e739687b4c3c5 100644 --- a/deps/v8/test/cctest/test-api-interceptors.cc +++ b/deps/v8/test/cctest/test-api-interceptors.cc @@ -1383,6 +1383,41 @@ THREADED_TEST(InterceptorLoadGlobalICGlobalWithInterceptor) { CHECK(value->BooleanValue(context.local()).FromJust()); } +// Test load of a non-existing global through prototype chain when a global +// object has an interceptor. +THREADED_TEST(InterceptorLoadICGlobalWithInterceptor) { + i::FLAG_allow_natives_syntax = true; + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + v8::Local templ_global = v8::ObjectTemplate::New(isolate); + templ_global->SetHandler(v8::NamedPropertyHandlerConfiguration( + GenericInterceptorGetter, GenericInterceptorSetter)); + + LocalContext context(nullptr, templ_global); + i::Handle global_proxy = + v8::Utils::OpenHandle(context->Global()); + CHECK(global_proxy->IsJSGlobalProxy()); + i::Handle global( + i::JSGlobalObject::cast(global_proxy->map()->prototype())); + CHECK(global->map()->has_named_interceptor()); + + ExpectInt32( + "(function() {" + " var f = function(obj) { " + " return obj.foo;" + " };" + " var obj = { __proto__: this, _str_foo: 42 };" + " for (var i = 0; i < 1500; i++) obj['p' + i] = 0;" + " /* Ensure that |obj| is in dictionary mode. */" + " if (%HasFastProperties(obj)) return -1;" + " for (var i = 0; i < 3; i++) {" + " f(obj);" + " };" + " return f(obj);" + "})();", + 42); +} + static void InterceptorLoadICGetter0( Local name, const v8::PropertyCallbackInfo& info) { ApiTestFuzzer::Fuzz();