From: jochen@chromium.org Date: Tue, 11 Mar 2014 09:04:14 +0000 (+0000) Subject: Use a per-isolate cache for the date object JS bits X-Git-Tag: upstream/4.7.83~10399 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=00ba711658a1f0a105b0fe00a0641dfcaec68ea8;p=platform%2Fupstream%2Fv8.git Use a per-isolate cache for the date object JS bits The old per-context cache made it difficult for the embedder to notify v8 of date/time configuration changes. The embedder had to enter all contexts for the isolate and notify v8 for each context. With the new per-isolate cache, the embedder only needs to notify v8 once per isolate. BUG=348856 LOG=y R=dcarney@chromium.org, ulan@chromium.org TEST=cctest/test-date Review URL: https://codereview.chromium.org/189913023 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19784 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/api.cc b/src/api.cc index f2b4cb3..714e005 100644 --- a/src/api.cc +++ b/src/api.cc @@ -5618,30 +5618,17 @@ void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) { i_isolate->date_cache()->ResetDateCache(); - i::HandleScope scope(i_isolate); - // Get the function ResetDateCache (defined in date.js). - i::Handle func_name_str = - i_isolate->factory()->InternalizeOneByteString( - STATIC_ASCII_VECTOR("ResetDateCache")); - i::MaybeObject* result = - i_isolate->js_builtins_object()->GetProperty(*func_name_str); - i::Object* object_func; - if (!result->ToObject(&object_func)) { + if (!i_isolate->eternal_handles()->Exists( + i::EternalHandles::DATE_CACHE_VERSION)) { return; } - - if (object_func->IsJSFunction()) { - i::Handle func = - i::Handle(i::JSFunction::cast(object_func)); - - // Call ResetDateCache(0 but expect no exceptions: - bool caught_exception = false; - i::Execution::TryCall(func, - i_isolate->js_builtins_object(), - 0, - NULL, - &caught_exception); - } + i::Handle date_cache_version = + i::Handle::cast(i_isolate->eternal_handles()->GetSingleton( + i::EternalHandles::DATE_CACHE_VERSION)); + ASSERT_EQ(1, date_cache_version->length()); + ASSERT(date_cache_version->get(0)->IsNumber()); + date_cache_version->set(0, i::Smi::FromInt( + date_cache_version->get(0)->Number() + 1)); } diff --git a/src/date.js b/src/date.js index f3d4af2..5eece68 100644 --- a/src/date.js +++ b/src/date.js @@ -46,6 +46,7 @@ var timezone_cache_timezone; function LocalTimezone(t) { if (NUMBER_IS_NAN(t)) return ""; + CheckDateCacheCurrent(); if (t == timezone_cache_time) { return timezone_cache_timezone; } @@ -156,6 +157,7 @@ function DateConstructor(year, month, date, hours, minutes, seconds, ms) { } else if (IS_STRING(year)) { // Probe the Date cache. If we already have a time value for the // given time, we re-use that instead of parsing the string again. + CheckDateCacheCurrent(); var cache = Date_cache; if (cache.string === year) { value = cache.time; @@ -743,10 +745,22 @@ function DateToJSON(key) { } -function ResetDateCache() { +var date_cache_version_holder; +var date_cache_version = NAN; + + +function CheckDateCacheCurrent() { + if (!date_cache_version_holder) { + date_cache_version_holder = %DateCacheVersion(); + } + if (date_cache_version_holder[0] == date_cache_version) { + return; + } + date_cache_version = date_cache_version_holder[0]; + // Reset the timezone cache: timezone_cache_time = NAN; - timezone_cache_timezone = undefined; + timezone_cache_timezone = UNDEFINED; // Reset the date cache: cache = Date_cache; diff --git a/src/global-handles.h b/src/global-handles.h index a406451..f46a22a 100644 --- a/src/global-handles.h +++ b/src/global-handles.h @@ -340,6 +340,7 @@ class EternalHandles { enum SingletonHandle { I18N_TEMPLATE_ONE, I18N_TEMPLATE_TWO, + DATE_CACHE_VERSION, NUMBER_OF_SINGLETON_HANDLES }; diff --git a/src/runtime.cc b/src/runtime.cc index 7e47615..5e7731b 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -9612,6 +9612,28 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) { } +RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCacheVersion) { + HandleScope hs(isolate); + ASSERT(args.length() == 0); + if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) { + Handle date_cache_version = + isolate->factory()->NewFixedArray(1, TENURED); + date_cache_version->set(0, Smi::FromInt(0)); + isolate->eternal_handles()->CreateSingleton( + isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION); + } + Handle date_cache_version = + Handle::cast(isolate->eternal_handles()->GetSingleton( + EternalHandles::DATE_CACHE_VERSION)); + // Return result as a JS array. + Handle result = + isolate->factory()->NewJSObject(isolate->array_function()); + isolate->factory()->SetContent(Handle::cast(result), + date_cache_version); + return *result; +} + + RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) { SealHandleScope shs(isolate); ASSERT(args.length() == 1); diff --git a/src/runtime.h b/src/runtime.h index d770968..b03e4e1 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -257,6 +257,7 @@ namespace internal { F(DateToUTC, 1, 1) \ F(DateMakeDay, 2, 1) \ F(DateSetValue, 3, 1) \ + F(DateCacheVersion, 0, 1) \ \ /* Numbers */ \ \ diff --git a/test/cctest/test-date.cc b/test/cctest/test-date.cc index 460c07e..5190729 100644 --- a/test/cctest/test-date.cc +++ b/test/cctest/test-date.cc @@ -167,3 +167,25 @@ TEST(DaylightSavingsTime) { CheckDST(august_20 + 2 * 3600 - 1000); CheckDST(august_20); } + + +TEST(DateCacheVersion) { + FLAG_allow_natives_syntax = true; + v8::Isolate* isolate = CcTest::isolate(); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope scope(isolate); + v8::Handle context = v8::Context::New(isolate); + v8::Context::Scope context_scope(context); + v8::Handle date_cache_version = + v8::Handle::Cast(CompileRun("%DateCacheVersion()")); + + CHECK_EQ(1, static_cast(date_cache_version->Length())); + CHECK(date_cache_version->Get(0)->IsNumber()); + CHECK_EQ(0.0, date_cache_version->Get(0)->NumberValue()); + + v8::Date::DateTimeConfigurationChangeNotification(isolate); + + CHECK_EQ(1, static_cast(date_cache_version->Length())); + CHECK(date_cache_version->Get(0)->IsNumber()); + CHECK_EQ(1.0, date_cache_version->Get(0)->NumberValue()); +}