Fix |RunMicrotasks()| leaking reference to the last context being run on.
authorharaken@chromium.org <haraken@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 2 May 2014 08:00:47 +0000 (08:00 +0000)
committerharaken@chromium.org <haraken@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 2 May 2014 08:00:47 +0000 (08:00 +0000)
RunMicrotasks() executes pending tasks and swaps the old array with a new array. However, the new array contains the reference to the current context as its creation context. This prevents the context from gc-ed until RunMicrotasks() is executed in the different context.

BUG=crbug.com/367016
LOG=y
R=rafaelw@chromium.org, rossberg@chromium.org

Review URL: https://codereview.chromium.org/250883002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21111 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/bootstrapper.cc
src/contexts.h
src/execution.cc
src/object-observe.js
src/promise.js
src/v8natives.js

index 4f56394..b644a37 100644 (file)
@@ -1561,8 +1561,7 @@ void Genesis::InstallNativeFunctions() {
 
 void Genesis::InstallExperimentalNativeFunctions() {
   INSTALL_NATIVE(JSFunction, "RunMicrotasks", run_microtasks);
-  INSTALL_NATIVE(JSFunction, "EnqueueExternalMicrotask",
-                 enqueue_external_microtask);
+  INSTALL_NATIVE(JSFunction, "EnqueueMicrotask", enqueue_microtask);
 
   if (FLAG_harmony_promises) {
     INSTALL_NATIVE(JSFunction, "IsPromise", is_promise);
index 50b6a2b..43b2329 100644 (file)
@@ -155,7 +155,7 @@ enum BindingFlags {
   V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
     error_message_for_code_gen_from_strings) \
   V(RUN_MICROTASKS_INDEX, JSFunction, run_microtasks) \
-  V(ENQUEUE_EXTERNAL_MICROTASK_INDEX, JSFunction, enqueue_external_microtask) \
+  V(ENQUEUE_MICROTASK_INDEX, JSFunction, enqueue_microtask) \
   V(IS_PROMISE_INDEX, JSFunction, is_promise) \
   V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \
   V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \
@@ -326,7 +326,7 @@ class Context: public FixedArray {
     ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
     ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX,
     RUN_MICROTASKS_INDEX,
-    ENQUEUE_EXTERNAL_MICROTASK_INDEX,
+    ENQUEUE_MICROTASK_INDEX,
     IS_PROMISE_INDEX,
     PROMISE_CREATE_INDEX,
     PROMISE_RESOLVE_INDEX,
index dd62ee2..b74ef4d 100644 (file)
@@ -322,7 +322,7 @@ void Execution::EnqueueMicrotask(Isolate* isolate, Handle<Object> microtask) {
   Handle<Object> args[] = { microtask };
   Execution::Call(
       isolate,
-      isolate->enqueue_external_microtask(),
+      isolate->enqueue_microtask(),
       isolate->factory()->undefined_value(),
       1,
       args).Check();
index e14614f..1d1be93 100644 (file)
@@ -411,8 +411,7 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord,
   var callbackInfo = CallbackInfoNormalize(callback);
   if (IS_NULL(GetPendingObservers())) {
     SetPendingObservers(nullProtoObject())
-    GetMicrotaskQueue().push(ObserveMicrotaskRunner);
-    %SetMicrotaskPending(true);
+    EnqueueMicrotask(ObserveMicrotaskRunner);
   }
   GetPendingObservers()[callbackInfo.priority] = callback;
   callbackInfo.push(changeRecord);
index f3140a1..f638f63 100644 (file)
@@ -153,13 +153,11 @@ function PromiseCatch(onReject) {
 }
 
 function PromiseEnqueue(value, tasks) {
-  GetMicrotaskQueue().push(function() {
+  EnqueueMicrotask(function() {
     for (var i = 0; i < tasks.length; i += 2) {
       PromiseHandle(value, tasks[i], tasks[i + 1])
     }
   });
-
-  %SetMicrotaskPending(true);
 }
 
 function PromiseHandle(value, handler, deferred) {
index c5f6fbc..cd60cb4 100644 (file)
@@ -1870,14 +1870,6 @@ SetUpFunction();
 // Eventually, we should move to a real event queue that allows to maintain
 // relative ordering of different kinds of tasks.
 
-function GetMicrotaskQueue() {
-  var microtaskState = %GetMicrotaskState();
-  if (IS_UNDEFINED(microtaskState.queue)) {
-    microtaskState.queue = new InternalArray;
-  }
-  return microtaskState.queue;
-}
-
 function RunMicrotasks() {
   while (%SetMicrotaskPending(false)) {
     var microtaskState = %GetMicrotaskState();
@@ -1885,7 +1877,7 @@ function RunMicrotasks() {
       return;
 
     var microtasks = microtaskState.queue;
-    microtaskState.queue = new InternalArray;
+    microtaskState.queue = null;
 
     for (var i = 0; i < microtasks.length; i++) {
       microtasks[i]();
@@ -1893,7 +1885,11 @@ function RunMicrotasks() {
   }
 }
 
-function EnqueueExternalMicrotask(fn) {
-  GetMicrotaskQueue().push(fn);
+function EnqueueMicrotask(fn) {
+  var microtaskState = %GetMicrotaskState();
+  if (IS_UNDEFINED(microtaskState.queue) || IS_NULL(microtaskState.queue)) {
+    microtaskState.queue = new InternalArray;
+  }
+  microtaskState.queue.push(fn);
   %SetMicrotaskPending(true);
 }