Commit e6e53390 authored by epertoso's avatar epertoso Committed by Commit bot

Let the second pass phantom callbacks run in a separate task on the foreground thread.

R=jochen@chromium.org
LOG=y
BUG=

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

Cr-Commit-Position: refs/heads/master@{#29680}
parent 9386b861
...@@ -133,6 +133,8 @@ class DefaultGlobalMapTraits : public StdMapTraits<K, V> { ...@@ -133,6 +133,8 @@ class DefaultGlobalMapTraits : public StdMapTraits<K, V> {
return K(); return K();
} }
static void DisposeCallbackData(WeakCallbackDataType* data) {} static void DisposeCallbackData(WeakCallbackDataType* data) {}
static void OnWeakCallback(
const WeakCallbackInfo<WeakCallbackDataType>& data) {}
static void Dispose(Isolate* isolate, Global<V> value, K key) {} static void Dispose(Isolate* isolate, Global<V> value, K key) {}
// This is a second pass callback, so SetSecondPassCallback cannot be called. // This is a second pass callback, so SetSecondPassCallback cannot be called.
static void DisposeWeak(const WeakCallbackInfo<WeakCallbackDataType>& data) {} static void DisposeWeak(const WeakCallbackInfo<WeakCallbackDataType>& data) {}
...@@ -452,7 +454,7 @@ class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> { ...@@ -452,7 +454,7 @@ class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
: WeakCallbackType::kParameter; : WeakCallbackType::kParameter;
Local<V> value(Local<V>::New(this->isolate(), *persistent)); Local<V> value(Local<V>::New(this->isolate(), *persistent));
persistent->template SetWeak<typename Traits::WeakCallbackDataType>( persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
Traits::WeakCallbackParameter(this, key, value), FirstWeakCallback, Traits::WeakCallbackParameter(this, key, value), OnWeakCallback,
callback_type); callback_type);
} }
PersistentContainerValue old_value = PersistentContainerValue old_value =
...@@ -471,12 +473,13 @@ class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> { ...@@ -471,12 +473,13 @@ class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
} }
private: private:
static void FirstWeakCallback( static void OnWeakCallback(
const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) { const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
if (Traits::kCallbackType != kNotWeak) { if (Traits::kCallbackType != kNotWeak) {
auto map = Traits::MapFromWeakCallbackInfo(data); auto map = Traits::MapFromWeakCallbackInfo(data);
K key = Traits::KeyFromWeakCallbackInfo(data); K key = Traits::KeyFromWeakCallbackInfo(data);
map->RemoveWeak(key); map->RemoveWeak(key);
Traits::OnWeakCallback(data);
data.SetSecondPassCallback(SecondWeakCallback); data.SetSecondPassCallback(SecondWeakCallback);
} }
} }
......
...@@ -666,11 +666,13 @@ StringHttpRequest kSampleRequests[kSampleSize] = { ...@@ -666,11 +666,13 @@ StringHttpRequest kSampleRequests[kSampleSize] = {
}; };
bool ProcessEntries(HttpRequestProcessor* processor, int count, bool ProcessEntries(v8::Platform* platform, HttpRequestProcessor* processor,
StringHttpRequest* reqs) { int count, StringHttpRequest* reqs) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (!processor->Process(&reqs[i])) bool result = processor->Process(&reqs[i]);
return false; while (v8::platform::PumpMessageLoop(platform, Isolate::GetCurrent()))
continue;
if (!result) return false;
} }
return true; return true;
} }
...@@ -713,7 +715,7 @@ int main(int argc, char* argv[]) { ...@@ -713,7 +715,7 @@ int main(int argc, char* argv[]) {
fprintf(stderr, "Error initializing processor.\n"); fprintf(stderr, "Error initializing processor.\n");
return 1; return 1;
} }
if (!ProcessEntries(&processor, kSampleSize, kSampleRequests)) if (!ProcessEntries(platform, &processor, kSampleSize, kSampleRequests))
return 1; return 1;
PrintMap(&output); PrintMap(&output);
} }
...@@ -45,8 +45,9 @@ ...@@ -45,8 +45,9 @@
v8::Local<v8::Context> CreateShellContext(v8::Isolate* isolate); v8::Local<v8::Context> CreateShellContext(v8::Isolate* isolate);
void RunShell(v8::Local<v8::Context> context); void RunShell(v8::Local<v8::Context> context, v8::Platform* platform);
int RunMain(v8::Isolate* isolate, int argc, char* argv[]); int RunMain(v8::Isolate* isolate, v8::Platform* platform, int argc,
char* argv[]);
bool ExecuteString(v8::Isolate* isolate, v8::Local<v8::String> source, bool ExecuteString(v8::Isolate* isolate, v8::Local<v8::String> source,
v8::Local<v8::Value> name, bool print_result, v8::Local<v8::Value> name, bool print_result,
bool report_exceptions); bool report_exceptions);
...@@ -94,8 +95,8 @@ int main(int argc, char* argv[]) { ...@@ -94,8 +95,8 @@ int main(int argc, char* argv[]) {
return 1; return 1;
} }
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
result = RunMain(isolate, argc, argv); result = RunMain(isolate, platform, argc, argv);
if (run_shell) RunShell(context); if (run_shell) RunShell(context, platform);
} }
isolate->Dispose(); isolate->Dispose();
v8::V8::Dispose(); v8::V8::Dispose();
...@@ -269,7 +270,8 @@ v8::MaybeLocal<v8::String> ReadFile(v8::Isolate* isolate, const char* name) { ...@@ -269,7 +270,8 @@ v8::MaybeLocal<v8::String> ReadFile(v8::Isolate* isolate, const char* name) {
// Process remaining command line arguments and execute files // Process remaining command line arguments and execute files
int RunMain(v8::Isolate* isolate, int argc, char* argv[]) { int RunMain(v8::Isolate* isolate, v8::Platform* platform, int argc,
char* argv[]) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
const char* str = argv[i]; const char* str = argv[i];
if (strcmp(str, "--shell") == 0) { if (strcmp(str, "--shell") == 0) {
...@@ -292,7 +294,9 @@ int RunMain(v8::Isolate* isolate, int argc, char* argv[]) { ...@@ -292,7 +294,9 @@ int RunMain(v8::Isolate* isolate, int argc, char* argv[]) {
.ToLocal(&source)) { .ToLocal(&source)) {
return 1; return 1;
} }
if (!ExecuteString(isolate, source, file_name, false, true)) return 1; bool success = ExecuteString(isolate, source, file_name, false, true);
while (v8::platform::PumpMessageLoop(platform, isolate)) continue;
if (!success) return 1;
} else { } else {
// Use all other arguments as names of files to load and run. // Use all other arguments as names of files to load and run.
v8::Local<v8::String> file_name = v8::Local<v8::String> file_name =
...@@ -303,7 +307,9 @@ int RunMain(v8::Isolate* isolate, int argc, char* argv[]) { ...@@ -303,7 +307,9 @@ int RunMain(v8::Isolate* isolate, int argc, char* argv[]) {
fprintf(stderr, "Error reading '%s'\n", str); fprintf(stderr, "Error reading '%s'\n", str);
continue; continue;
} }
if (!ExecuteString(isolate, source, file_name, false, true)) return 1; bool success = ExecuteString(isolate, source, file_name, false, true);
while (v8::platform::PumpMessageLoop(platform, isolate)) continue;
if (!success) return 1;
} }
} }
return 0; return 0;
...@@ -311,7 +317,7 @@ int RunMain(v8::Isolate* isolate, int argc, char* argv[]) { ...@@ -311,7 +317,7 @@ int RunMain(v8::Isolate* isolate, int argc, char* argv[]) {
// The read-eval-execute loop of the shell. // The read-eval-execute loop of the shell.
void RunShell(v8::Local<v8::Context> context) { void RunShell(v8::Local<v8::Context> context, v8::Platform* platform) {
fprintf(stderr, "V8 version %s [sample shell]\n", v8::V8::GetVersion()); fprintf(stderr, "V8 version %s [sample shell]\n", v8::V8::GetVersion());
static const int kBufferSize = 256; static const int kBufferSize = 256;
// Enter the execution environment before evaluating any code. // Enter the execution environment before evaluating any code.
...@@ -330,6 +336,8 @@ void RunShell(v8::Local<v8::Context> context) { ...@@ -330,6 +336,8 @@ void RunShell(v8::Local<v8::Context> context) {
v8::String::NewFromUtf8(context->GetIsolate(), str, v8::String::NewFromUtf8(context->GetIsolate(), str,
v8::NewStringType::kNormal).ToLocalChecked(), v8::NewStringType::kNormal).ToLocalChecked(),
name, true, true); name, true, true);
while (v8::platform::PumpMessageLoop(platform, context->GetIsolate()))
continue;
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
......
...@@ -349,6 +349,7 @@ bool Shell::ExecuteString(Isolate* isolate, Handle<String> source, ...@@ -349,6 +349,7 @@ bool Shell::ExecuteString(Isolate* isolate, Handle<String> source,
return false; return false;
} }
result = script->Run(); result = script->Run();
EmptyMessageQueues(isolate);
data->realm_current_ = data->realm_switch_; data->realm_current_ = data->realm_switch_;
} }
if (result.IsEmpty()) { if (result.IsEmpty()) {
...@@ -2009,6 +2010,11 @@ void Shell::CollectGarbage(Isolate* isolate) { ...@@ -2009,6 +2010,11 @@ void Shell::CollectGarbage(Isolate* isolate) {
} }
void Shell::EmptyMessageQueues(Isolate* isolate) {
while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue;
}
#ifndef V8_SHARED #ifndef V8_SHARED
bool Shell::SerializeValue(Isolate* isolate, Handle<Value> value, bool Shell::SerializeValue(Isolate* isolate, Handle<Value> value,
const ObjectList& to_transfer, const ObjectList& to_transfer,
......
...@@ -366,6 +366,7 @@ class Shell : public i::AllStatic { ...@@ -366,6 +366,7 @@ class Shell : public i::AllStatic {
static void Exit(int exit_code); static void Exit(int exit_code);
static void OnExit(Isolate* isolate); static void OnExit(Isolate* isolate);
static void CollectGarbage(Isolate* isolate); static void CollectGarbage(Isolate* isolate);
static void EmptyMessageQueues(Isolate* isolate);
#ifndef V8_SHARED #ifndef V8_SHARED
// TODO(binji): stupid implementation for now. Is there an easy way to hash an // TODO(binji): stupid implementation for now. Is there an easy way to hash an
......
...@@ -495,6 +495,29 @@ class GlobalHandles::NodeIterator { ...@@ -495,6 +495,29 @@ class GlobalHandles::NodeIterator {
DISALLOW_COPY_AND_ASSIGN(NodeIterator); DISALLOW_COPY_AND_ASSIGN(NodeIterator);
}; };
class GlobalHandles::PendingPhantomCallbacksSecondPassTask : public v8::Task {
public:
// Takes ownership of the contents of pending_phantom_callbacks, leaving it in
// the same state it would be after a call to Clear().
PendingPhantomCallbacksSecondPassTask(
List<PendingPhantomCallback>* pending_phantom_callbacks, Isolate* isolate)
: isolate_(isolate) {
pending_phantom_callbacks_.Swap(pending_phantom_callbacks);
}
~PendingPhantomCallbacksSecondPassTask() override {}
void Run() override {
InvokeSecondPassPhantomCallbacks(&pending_phantom_callbacks_, isolate_);
}
private:
List<PendingPhantomCallback> pending_phantom_callbacks_;
Isolate* isolate_;
DISALLOW_COPY_AND_ASSIGN(PendingPhantomCallbacksSecondPassTask);
};
GlobalHandles::GlobalHandles(Isolate* isolate) GlobalHandles::GlobalHandles(Isolate* isolate)
: isolate_(isolate), : isolate_(isolate),
...@@ -709,6 +732,19 @@ bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, ...@@ -709,6 +732,19 @@ bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v,
} }
void GlobalHandles::InvokeSecondPassPhantomCallbacks(
List<PendingPhantomCallback>* callbacks, Isolate* isolate) {
while (callbacks->length() != 0) {
auto callback = callbacks->RemoveLast();
DCHECK(callback.node() == nullptr);
// No second pass callback required.
if (callback.callback() == nullptr) continue;
// Fire second pass callback
callback.Invoke(isolate);
}
}
int GlobalHandles::PostScavengeProcessing( int GlobalHandles::PostScavengeProcessing(
const int initial_post_gc_processing_count) { const int initial_post_gc_processing_count) {
int freed_nodes = 0; int freed_nodes = 0;
...@@ -791,7 +827,8 @@ void GlobalHandles::UpdateListOfNewSpaceNodes() { ...@@ -791,7 +827,8 @@ void GlobalHandles::UpdateListOfNewSpaceNodes() {
} }
int GlobalHandles::DispatchPendingPhantomCallbacks() { int GlobalHandles::DispatchPendingPhantomCallbacks(
bool synchronous_second_pass) {
int freed_nodes = 0; int freed_nodes = 0;
{ {
// The initial pass callbacks must simply clear the nodes. // The initial pass callbacks must simply clear the nodes.
...@@ -804,14 +841,15 @@ int GlobalHandles::DispatchPendingPhantomCallbacks() { ...@@ -804,14 +841,15 @@ int GlobalHandles::DispatchPendingPhantomCallbacks() {
freed_nodes++; freed_nodes++;
} }
} }
// The second pass empties the list. if (pending_phantom_callbacks_.length() > 0) {
while (pending_phantom_callbacks_.length() != 0) { if (synchronous_second_pass) {
auto callback = pending_phantom_callbacks_.RemoveLast(); InvokeSecondPassPhantomCallbacks(&pending_phantom_callbacks_, isolate());
DCHECK(callback.node() == nullptr); } else {
// No second pass callback required. auto* task = new PendingPhantomCallbacksSecondPassTask(
if (callback.callback() == nullptr) continue; &pending_phantom_callbacks_, isolate());
// Fire second pass callback. V8::GetCurrentPlatform()->CallOnForegroundThread(
callback.Invoke(isolate()); reinterpret_cast<v8::Isolate*>(isolate()), task);
}
} }
pending_phantom_callbacks_.Clear(); pending_phantom_callbacks_.Clear();
return freed_nodes; return freed_nodes;
...@@ -838,14 +876,17 @@ void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) { ...@@ -838,14 +876,17 @@ void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) {
} }
int GlobalHandles::PostGarbageCollectionProcessing(GarbageCollector collector) { int GlobalHandles::PostGarbageCollectionProcessing(
GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) {
// Process weak global handle callbacks. This must be done after the // Process weak global handle callbacks. This must be done after the
// GC is completely done, because the callbacks may invoke arbitrary // GC is completely done, because the callbacks may invoke arbitrary
// API functions. // API functions.
DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC);
const int initial_post_gc_processing_count = ++post_gc_processing_count_; const int initial_post_gc_processing_count = ++post_gc_processing_count_;
int freed_nodes = 0; int freed_nodes = 0;
freed_nodes += DispatchPendingPhantomCallbacks(); bool synchronous_second_pass =
(gc_callback_flags & kGCCallbackFlagForced) != 0;
freed_nodes += DispatchPendingPhantomCallbacks(synchronous_second_pass);
if (initial_post_gc_processing_count != post_gc_processing_count_) { if (initial_post_gc_processing_count != post_gc_processing_count_) {
// If the callbacks caused a nested GC, then return. See comment in // If the callbacks caused a nested GC, then return. See comment in
// PostScavengeProcessing. // PostScavengeProcessing.
......
...@@ -181,7 +181,8 @@ class GlobalHandles { ...@@ -181,7 +181,8 @@ class GlobalHandles {
// Process pending weak handles. // Process pending weak handles.
// Returns the number of freed nodes. // Returns the number of freed nodes.
int PostGarbageCollectionProcessing(GarbageCollector collector); int PostGarbageCollectionProcessing(
GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
// Iterates over all strong handles. // Iterates over all strong handles.
void IterateStrongRoots(ObjectVisitor* v); void IterateStrongRoots(ObjectVisitor* v);
...@@ -287,17 +288,21 @@ class GlobalHandles { ...@@ -287,17 +288,21 @@ class GlobalHandles {
// don't assign any initial capacity. // don't assign any initial capacity.
static const int kObjectGroupConnectionsCapacity = 20; static const int kObjectGroupConnectionsCapacity = 20;
class PendingPhantomCallback;
// Helpers for PostGarbageCollectionProcessing. // Helpers for PostGarbageCollectionProcessing.
static void InvokeSecondPassPhantomCallbacks(
List<PendingPhantomCallback>* callbacks, Isolate* isolate);
int PostScavengeProcessing(int initial_post_gc_processing_count); int PostScavengeProcessing(int initial_post_gc_processing_count);
int PostMarkSweepProcessing(int initial_post_gc_processing_count); int PostMarkSweepProcessing(int initial_post_gc_processing_count);
int DispatchPendingPhantomCallbacks(); int DispatchPendingPhantomCallbacks(bool synchronous_second_pass);
void UpdateListOfNewSpaceNodes(); void UpdateListOfNewSpaceNodes();
// Internal node structures. // Internal node structures.
class Node; class Node;
class NodeBlock; class NodeBlock;
class NodeIterator; class NodeIterator;
class PendingPhantomCallback; class PendingPhantomCallbacksSecondPassTask;
Isolate* isolate_; Isolate* isolate_;
......
...@@ -1306,7 +1306,8 @@ bool Heap::PerformGarbageCollection( ...@@ -1306,7 +1306,8 @@ bool Heap::PerformGarbageCollection(
AllowHeapAllocation allow_allocation; AllowHeapAllocation allow_allocation;
GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL);
freed_global_handles = freed_global_handles =
isolate_->global_handles()->PostGarbageCollectionProcessing(collector); isolate_->global_handles()->PostGarbageCollectionProcessing(
collector, gc_callback_flags);
} }
gc_post_processing_depth_--; gc_post_processing_depth_--;
......
...@@ -125,6 +125,12 @@ bool List<T, P>::RemoveElement(const T& elm) { ...@@ -125,6 +125,12 @@ bool List<T, P>::RemoveElement(const T& elm) {
return false; return false;
} }
template <typename T, class P>
void List<T, P>::Swap(List<T, P>* list) {
std::swap(data_, list->data_);
std::swap(length_, list->length_);
std::swap(capacity_, list->capacity_);
}
template<typename T, class P> template<typename T, class P>
void List<T, P>::Allocate(int length, P allocator) { void List<T, P>::Allocate(int length, P allocator) {
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef V8_LIST_H_ #ifndef V8_LIST_H_
#define V8_LIST_H_ #define V8_LIST_H_
#include <algorithm>
#include "src/checks.h" #include "src/checks.h"
#include "src/utils.h" #include "src/utils.h"
...@@ -137,6 +139,9 @@ class List { ...@@ -137,6 +139,9 @@ class List {
// Drop the last 'count' elements from the list. // Drop the last 'count' elements from the list.
INLINE(void RewindBy(int count)) { Rewind(length_ - count); } INLINE(void RewindBy(int count)) { Rewind(length_ - count); }
// Swaps the contents of the two lists.
INLINE(void Swap(List<T, AllocationPolicy>* list));
// Halve the capacity if fill level is less than a quarter. // Halve the capacity if fill level is less than a quarter.
INLINE(void Trim(AllocationPolicy allocator = AllocationPolicy())); INLINE(void Trim(AllocationPolicy allocator = AllocationPolicy()));
......
...@@ -97,6 +97,7 @@ void CcTest::Run() { ...@@ -97,6 +97,7 @@ void CcTest::Run() {
} }
callback_(); callback_();
if (initialize_) { if (initialize_) {
EmptyMessageQueues(isolate_);
isolate_->Exit(); isolate_->Exit();
} }
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#ifndef CCTEST_H_ #ifndef CCTEST_H_
#define CCTEST_H_ #define CCTEST_H_
#include "include/libplatform/libplatform.h"
#include "src/v8.h" #include "src/v8.h"
#ifndef TEST #ifndef TEST
...@@ -594,6 +595,13 @@ static inline void EnableDebugger() { ...@@ -594,6 +595,13 @@ static inline void EnableDebugger() {
static inline void DisableDebugger() { v8::Debug::SetDebugEventListener(NULL); } static inline void DisableDebugger() { v8::Debug::SetDebugEventListener(NULL); }
static inline void EmptyMessageQueues(v8::Isolate* isolate) {
while (v8::platform::PumpMessageLoop(v8::internal::V8::GetCurrentPlatform(),
isolate))
;
}
// Helper class for new allocations tracking and checking. // Helper class for new allocations tracking and checking.
// To use checking of JS allocations tracking in a test, // To use checking of JS allocations tracking in a test,
// just create an instance of this class. // just create an instance of this class.
......
...@@ -3275,6 +3275,7 @@ TEST(TwoPassPhantomCallbacks) { ...@@ -3275,6 +3275,7 @@ TEST(TwoPassPhantomCallbacks) {
} }
CHECK_EQ(static_cast<int>(kLength), instance_counter); CHECK_EQ(static_cast<int>(kLength), instance_counter);
CcTest::heap()->CollectAllGarbage(); CcTest::heap()->CollectAllGarbage();
EmptyMessageQueues(isolate);
CHECK_EQ(0, instance_counter); CHECK_EQ(0, instance_counter);
} }
...@@ -3293,6 +3294,7 @@ TEST(TwoPassPhantomCallbacksNestedGc) { ...@@ -3293,6 +3294,7 @@ TEST(TwoPassPhantomCallbacksNestedGc) {
array[15]->MarkTriggerGc(); array[15]->MarkTriggerGc();
CHECK_EQ(static_cast<int>(kLength), instance_counter); CHECK_EQ(static_cast<int>(kLength), instance_counter);
CcTest::heap()->CollectAllGarbage(); CcTest::heap()->CollectAllGarbage();
EmptyMessageQueues(isolate);
CHECK_EQ(0, instance_counter); CHECK_EQ(0, instance_counter);
} }
...@@ -3342,6 +3344,8 @@ class PhantomStdMapTraits : public v8::StdMapTraits<K, V> { ...@@ -3342,6 +3344,8 @@ class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
CHECK_EQ(IntKeyToVoidPointer(key), CHECK_EQ(IntKeyToVoidPointer(key),
v8::Object::GetAlignedPointerFromInternalField(value, 0)); v8::Object::GetAlignedPointerFromInternalField(value, 0));
} }
static void OnWeakCallback(
const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
static void DisposeWeak( static void DisposeWeak(
const v8::WeakCallbackInfo<WeakCallbackDataType>& info) { const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
K key = KeyFromWeakCallbackInfo(info); K key = KeyFromWeakCallbackInfo(info);
...@@ -6806,6 +6810,7 @@ THREADED_TEST(GCFromWeakCallbacks) { ...@@ -6806,6 +6810,7 @@ THREADED_TEST(GCFromWeakCallbacks) {
v8::WeakCallbackType::kParameter); v8::WeakCallbackType::kParameter);
object.handle.MarkIndependent(); object.handle.MarkIndependent();
invoke_gc[outer_gc](); invoke_gc[outer_gc]();
EmptyMessageQueues(isolate);
CHECK(object.flag); CHECK(object.flag);
} }
} }
...@@ -11885,6 +11890,7 @@ THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { ...@@ -11885,6 +11890,7 @@ THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
handle3.SetWeak(&handle3, HandleCreatingCallback1, handle3.SetWeak(&handle3, HandleCreatingCallback1,
v8::WeakCallbackType::kParameter); v8::WeakCallbackType::kParameter);
CcTest::heap()->CollectAllGarbage(); CcTest::heap()->CollectAllGarbage();
EmptyMessageQueues(isolate);
} }
......
...@@ -4,10 +4,12 @@ ...@@ -4,10 +4,12 @@
#include "test/unittests/test-utils.h" #include "test/unittests/test-utils.h"
#include "include/libplatform/libplatform.h"
#include "src/base/platform/time.h" #include "src/base/platform/time.h"
#include "src/debug.h" #include "src/debug.h"
#include "src/flags.h" #include "src/flags.h"
#include "src/isolate.h" #include "src/isolate.h"
#include "src/v8.h"
namespace v8 { namespace v8 {
...@@ -51,6 +53,9 @@ void TestWithIsolate::SetUpTestCase() { ...@@ -51,6 +53,9 @@ void TestWithIsolate::SetUpTestCase() {
// static // static
void TestWithIsolate::TearDownTestCase() { void TestWithIsolate::TearDownTestCase() {
ASSERT_TRUE(isolate_ != NULL); ASSERT_TRUE(isolate_ != NULL);
v8::Platform* platform = internal::V8::GetCurrentPlatform();
ASSERT_TRUE(platform != NULL);
while (platform::PumpMessageLoop(platform, isolate_)) continue;
isolate_->Dispose(); isolate_->Dispose();
isolate_ = NULL; isolate_ = NULL;
delete array_buffer_allocator_; delete array_buffer_allocator_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment