Use a per-isolate cache for the date object JS bits
authorjochen@chromium.org <jochen@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 11 Mar 2014 09:04:14 +0000 (09:04 +0000)
committerjochen@chromium.org <jochen@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 11 Mar 2014 09:04:14 +0000 (09:04 +0000)
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

src/api.cc
src/date.js
src/global-handles.h
src/runtime.cc
src/runtime.h
test/cctest/test-date.cc

index f2b4cb3..714e005 100644 (file)
@@ -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<i::String> 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<i::JSFunction> func =
-        i::Handle<i::JSFunction>(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<i::FixedArray> date_cache_version =
+      i::Handle<i::FixedArray>::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));
 }
 
 
index f3d4af2..5eece68 100644 (file)
@@ -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;
index a406451..f46a22a 100644 (file)
@@ -340,6 +340,7 @@ class EternalHandles {
   enum SingletonHandle {
     I18N_TEMPLATE_ONE,
     I18N_TEMPLATE_TWO,
+    DATE_CACHE_VERSION,
 
     NUMBER_OF_SINGLETON_HANDLES
   };
index 7e47615..5e7731b 100644 (file)
@@ -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<FixedArray> 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<FixedArray> date_cache_version =
+      Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
+          EternalHandles::DATE_CACHE_VERSION));
+  // Return result as a JS array.
+  Handle<JSObject> result =
+      isolate->factory()->NewJSObject(isolate->array_function());
+  isolate->factory()->SetContent(Handle<JSArray>::cast(result),
+                                 date_cache_version);
+  return *result;
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
   SealHandleScope shs(isolate);
   ASSERT(args.length() == 1);
index d770968..b03e4e1 100644 (file)
@@ -257,6 +257,7 @@ namespace internal {
   F(DateToUTC, 1, 1) \
   F(DateMakeDay, 2, 1) \
   F(DateSetValue, 3, 1) \
+  F(DateCacheVersion, 0, 1) \
   \
   /* Numbers */ \
   \
index 460c07e..5190729 100644 (file)
@@ -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<v8::Context> context = v8::Context::New(isolate);
+  v8::Context::Scope context_scope(context);
+  v8::Handle<v8::Array> date_cache_version =
+      v8::Handle<v8::Array>::Cast(CompileRun("%DateCacheVersion()"));
+
+  CHECK_EQ(1, static_cast<int32_t>(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<int32_t>(date_cache_version->Length()));
+  CHECK(date_cache_version->Get(0)->IsNumber());
+  CHECK_EQ(1.0, date_cache_version->Get(0)->NumberValue());
+}