deps: upgrade v8 to 4.2.77.15
authorBen Noordhuis <info@bnoordhuis.nl>
Sat, 11 Apr 2015 17:37:48 +0000 (19:37 +0200)
committerChris Dickinson <christopher.s.dickinson@gmail.com>
Tue, 28 Apr 2015 21:38:16 +0000 (14:38 -0700)
This includes the out-of-tree patch (but fixed in upstream HEAD) from
commit 41c00a2 ("deps: enable v8 postmortem debugging again".)

PR-URL: https://github.com/iojs/io.js/pull/1399
Reviewed-By: Fedor Indutny <fedor@indutny.com>
deps/v8/include/v8-version.h
deps/v8/src/api-natives.cc
deps/v8/src/api-natives.h
deps/v8/src/bootstrapper.cc
deps/v8/src/contexts.h
deps/v8/src/type-info.cc
deps/v8/test/cctest/test-api.cc
deps/v8/tools/testrunner/local/progress.py

index 49f41f0..c5318ac 100644 (file)
@@ -11,7 +11,7 @@
 #define V8_MAJOR_VERSION 4
 #define V8_MINOR_VERSION 2
 #define V8_BUILD_NUMBER 77
-#define V8_PATCH_LEVEL 13
+#define V8_PATCH_LEVEL 15
 
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
index ed434ca..11f20ef 100644 (file)
@@ -207,36 +207,33 @@ MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
 }
 
 
-void InstallInCache(Isolate* isolate, int serial_number,
-                    Handle<JSFunction> function) {
+void CacheFunction(Isolate* isolate, Handle<Smi> serial_number,
+                   Handle<JSFunction> function) {
   auto cache = isolate->function_cache();
-  if (cache->length() <= serial_number) {
-    int new_size;
-    if (isolate->next_serial_number() < 50) {
-      new_size = 100;
-    } else {
-      new_size = 3 * isolate->next_serial_number() / 2;
-    }
-    cache = FixedArray::CopySize(cache, new_size);
-    isolate->native_context()->set_function_cache(*cache);
-  }
-  cache->set(serial_number, *function);
+  auto new_cache = ObjectHashTable::Put(cache, serial_number, function);
+  isolate->native_context()->set_function_cache(*new_cache);
+}
+
+
+void UncacheFunction(Isolate* isolate, Handle<Smi> serial_number) {
+  auto cache = isolate->function_cache();
+  bool was_present = false;
+  auto new_cache = ObjectHashTable::Remove(cache, serial_number, &was_present);
+  DCHECK(was_present);
+  isolate->native_context()->set_function_cache(*new_cache);
 }
 
 
 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
                                             Handle<FunctionTemplateInfo> data,
                                             Handle<Name> name) {
-  int serial_number = Smi::cast(data->serial_number())->value();
+  auto serial_number = handle(Smi::cast(data->serial_number()), isolate);
   // Probe cache.
   if (!data->do_not_cache()) {
     auto cache = isolate->function_cache();
-    // Fast case: see if the function has already been instantiated
-    if (serial_number < cache->length()) {
-      Handle<Object> element = FixedArray::get(cache, serial_number);
-      if (element->IsJSFunction()) {
-        return Handle<JSFunction>::cast(element);
-      }
+    Object* element = cache->Lookup(serial_number);
+    if (element->IsJSFunction()) {
+      return handle(JSFunction::cast(element), isolate);
     }
   }
   // Enter a new scope.  Recursion could otherwise create a lot of handles.
@@ -279,15 +276,14 @@ MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
     function->shared()->set_name(*name);
   }
   if (!data->do_not_cache()) {
-    // Cache the function to limit recursion.
-    InstallInCache(isolate, serial_number, function);
+    // Cache the function.
+    CacheFunction(isolate, serial_number, function);
   }
   auto result = ConfigureInstance(isolate, function, data);
   if (result.is_null()) {
-    // uncache on error.
+    // Uncache on error.
     if (!data->do_not_cache()) {
-      auto cache = isolate->function_cache();
-      cache->set(serial_number, isolate->heap()->undefined_value());
+      UncacheFunction(isolate, serial_number);
     }
     return MaybeHandle<JSFunction>();
   }
index 9f97b5d..224c78a 100644 (file)
@@ -12,6 +12,8 @@ namespace internal {
 
 class ApiNatives {
  public:
+  static const int kInitialFunctionCacheSize = 256;
+
   MUST_USE_RESULT static MaybeHandle<JSFunction> InstantiateFunction(
       Handle<FunctionTemplateInfo> data);
 
index 31d6e3e..2592bb7 100644 (file)
@@ -2059,7 +2059,9 @@ bool Genesis::InstallNatives() {
 
   InstallNativeFunctions();
 
-  native_context()->set_function_cache(heap()->empty_fixed_array());
+  auto function_cache =
+      ObjectHashTable::New(isolate(), ApiNatives::kInitialFunctionCacheSize);
+  native_context()->set_function_cache(*function_cache);
 
   // Store the map for the string prototype after the natives has been compiled
   // and the String function has been set up.
index f932c60..3d34e0e 100644 (file)
@@ -138,7 +138,7 @@ enum BindingFlags {
   V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun)                      \
   V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun)          \
   V(CONFIGURE_GLOBAL_INDEX, JSFunction, configure_global_fun)                  \
-  V(FUNCTION_CACHE_INDEX, FixedArray, function_cache)                          \
+  V(FUNCTION_CACHE_INDEX, ObjectHashTable, function_cache)                     \
   V(JSFUNCTION_RESULT_CACHES_INDEX, FixedArray, jsfunction_result_caches)      \
   V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache)                  \
   V(RUNTIME_CONTEXT_INDEX, Context, runtime_context)                           \
index 0194341..96bd0ed 100644 (file)
@@ -437,6 +437,9 @@ bool TypeFeedbackOracle::CanRetainOtherContext(Map* map,
   }
   constructor = map->constructor();
   if (constructor->IsNull()) return false;
+  // If the constructor is not null or a JSFunction, we have to conservatively
+  // assume that it may retain a native context.
+  if (!constructor->IsJSFunction()) return true;
   JSFunction* function = JSFunction::cast(constructor);
   return CanRetainOtherContext(function, native_context);
 }
index 096e52b..d963614 100644 (file)
@@ -20367,15 +20367,15 @@ THREADED_TEST(FunctionNew) {
   env->Global()->Set(v8_str("func"), func);
   Local<Value> result = CompileRun("func();");
   CHECK(v8::Integer::New(isolate, 17)->Equals(result));
-  // Verify function not cached
-  int serial_number =
-      i::Smi::cast(v8::Utils::OpenHandle(*func)
-          ->shared()->get_api_func_data()->serial_number())->value();
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  i::Handle<i::FixedArray> cache(i_isolate->native_context()->function_cache());
-  if (serial_number < cache->length()) {
-    CHECK(cache->get(serial_number)->IsUndefined());
-  }
+  // Verify function not cached
+  auto serial_number = handle(i::Smi::cast(v8::Utils::OpenHandle(*func)
+                                               ->shared()
+                                               ->get_api_func_data()
+                                               ->serial_number()),
+                              i_isolate);
+  auto cache = i_isolate->function_cache();
+  CHECK(cache->Lookup(serial_number)->IsTheHole());
   // Verify that each Function::New creates a new function instance
   Local<Object> data2 = v8::Object::New(isolate);
   function_new_expected_env = data2;
index 2616958..ed9d315 100644 (file)
@@ -291,6 +291,7 @@ class JsonTestProgressIndicator(ProgressIndicator):
     self.arch = arch
     self.mode = mode
     self.results = []
+    self.tests = []
 
   def Starting(self):
     self.progress_indicator.runner = self.runner
@@ -304,10 +305,24 @@ class JsonTestProgressIndicator(ProgressIndicator):
         # Buildbot might start out with an empty file.
         complete_results = json.loads(f.read() or "[]")
 
+    # Sort tests by duration.
+    timed_tests = [t for t in self.tests if t.duration is not None]
+    timed_tests.sort(lambda a, b: cmp(b.duration, a.duration))
+    slowest_tests = [
+      {
+        "name": test.GetLabel(),
+        "flags": test.flags,
+        "command": EscapeCommand(self.runner.GetCommand(test)).replace(
+            ABS_PATH_PREFIX, ""),
+        "duration": test.duration,
+      } for test in timed_tests[:20]
+    ]
+
     complete_results.append({
       "arch": self.arch,
       "mode": self.mode,
       "results": self.results,
+      "slowest_tests": slowest_tests,
     })
 
     with open(self.json_test_results, "w") as f:
@@ -318,6 +333,8 @@ class JsonTestProgressIndicator(ProgressIndicator):
 
   def HasRun(self, test, has_unexpected_output):
     self.progress_indicator.HasRun(test, has_unexpected_output)
+    # Buffer all tests for sorting the durations in the end.
+    self.tests.append(test)
     if not has_unexpected_output:
       # Omit tests that run as expected. Passing tests of reruns after failures
       # will have unexpected_output to be reported here has well.
@@ -334,6 +351,7 @@ class JsonTestProgressIndicator(ProgressIndicator):
       "exit_code": test.output.exit_code,
       "result": test.suite.GetOutcome(test),
       "expected": list(test.outcomes or ["PASS"]),
+      "duration": test.duration,
     })