Index: test/cctest/test-heap.cc |
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc |
index 5895e77f039d5f6670f0733b9e835bbd5dcb945e..d39e85078234bb57ba77bb6b66df1e497f0e3c40 100644 |
--- a/test/cctest/test-heap.cc |
+++ b/test/cctest/test-heap.cc |
@@ -3387,6 +3387,66 @@ static void CheckVectorICCleared(Handle<JSFunction> f, int ic_slot_index) { |
} |
+TEST(IncrementalMarkingPreservesMonomorphicConstructor) { |
+ if (i::FLAG_always_opt) return; |
+ CcTest::InitializeVM(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ // Prepare function f that contains a monomorphic IC for object |
+ // originating from the same native context. |
+ CompileRun( |
+ "function fun() { this.x = 1; };" |
+ "function f(o) { return new o(); } f(fun); f(fun);"); |
+ Handle<JSFunction> f = v8::Utils::OpenHandle( |
+ *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); |
+ |
+ |
+ Handle<TypeFeedbackVector> vector(f->shared()->feedback_vector()); |
+ CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell()); |
+ |
+ SimulateIncrementalMarking(CcTest::heap()); |
+ CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
+ |
+ CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell()); |
+} |
+ |
+ |
+TEST(IncrementalMarkingClearsMonomorphicConstructor) { |
+ if (i::FLAG_always_opt) return; |
+ CcTest::InitializeVM(); |
+ Isolate* isolate = CcTest::i_isolate(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ v8::Local<v8::Value> fun1; |
+ |
+ { |
+ LocalContext env; |
+ CompileRun("function fun() { this.x = 1; };"); |
+ fun1 = env->Global()->Get(v8_str("fun")); |
+ } |
+ |
+ // Prepare function f that contains a monomorphic constructor for object |
+ // originating from a different native context. |
+ CcTest::global()->Set(v8_str("fun1"), fun1); |
+ CompileRun( |
+ "function fun() { this.x = 1; };" |
+ "function f(o) { return new o(); } f(fun1); f(fun1);"); |
+ Handle<JSFunction> f = v8::Utils::OpenHandle( |
+ *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); |
+ |
+ |
+ Handle<TypeFeedbackVector> vector(f->shared()->feedback_vector()); |
+ CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell()); |
+ |
+ // Fire context dispose notification. |
+ CcTest::isolate()->ContextDisposedNotification(); |
+ SimulateIncrementalMarking(CcTest::heap()); |
+ CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
+ |
+ CHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(isolate), |
+ vector->Get(FeedbackVectorSlot(0))); |
+} |
+ |
+ |
TEST(IncrementalMarkingPreservesMonomorphicIC) { |
if (i::FLAG_always_opt) return; |
CcTest::InitializeVM(); |
@@ -4415,6 +4475,60 @@ static void ClearWeakIC(const v8::WeakCallbackData<v8::Object, void>& data) { |
} |
+TEST(WeakFunctionInConstructor) { |
+ if (i::FLAG_always_opt) return; |
+ i::FLAG_stress_compaction = false; |
+ CcTest::InitializeVM(); |
+ v8::Isolate* isolate = CcTest::isolate(); |
+ v8::HandleScope scope(isolate); |
+ CompileRun( |
+ "function createObj(obj) {" |
+ " return new obj();" |
+ "}"); |
+ Handle<JSFunction> createObj = |
+ v8::Utils::OpenHandle(*v8::Handle<v8::Function>::Cast( |
+ CcTest::global()->Get(v8_str("createObj")))); |
+ |
+ v8::Persistent<v8::Object> garbage; |
+ { |
+ v8::HandleScope scope(isolate); |
+ const char* source = |
+ " (function() {" |
+ " function hat() { this.x = 5; }" |
+ " createObj(hat);" |
+ " createObj(hat);" |
+ " return hat;" |
+ " })();"; |
+ garbage.Reset(isolate, CompileRun(source)->ToObject(isolate)); |
+ } |
+ weak_ic_cleared = false; |
+ garbage.SetWeak(static_cast<void*>(&garbage), &ClearWeakIC); |
+ Heap* heap = CcTest::i_isolate()->heap(); |
+ heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
+ CHECK(weak_ic_cleared); |
+ |
+ // We've determined the constructor in createObj has had it's weak cell |
+ // cleared. Now, verify that one additional call with a new function |
+ // allows monomorphicity. |
+ Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>( |
+ createObj->shared()->feedback_vector(), CcTest::i_isolate()); |
+ for (int i = 0; i < 20; i++) { |
+ Object* slot_value = feedback_vector->Get(FeedbackVectorSlot(0)); |
+ CHECK(slot_value->IsWeakCell()); |
+ if (WeakCell::cast(slot_value)->cleared()) break; |
+ heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
+ } |
+ |
+ Object* slot_value = feedback_vector->Get(FeedbackVectorSlot(0)); |
+ CHECK(slot_value->IsWeakCell() && WeakCell::cast(slot_value)->cleared()); |
+ CompileRun( |
+ "function coat() { this.x = 6; }" |
+ "createObj(coat);"); |
+ slot_value = feedback_vector->Get(FeedbackVectorSlot(0)); |
+ CHECK(slot_value->IsWeakCell() && !WeakCell::cast(slot_value)->cleared()); |
+} |
+ |
+ |
// Checks that the value returned by execution of the source is weak. |
void CheckWeakness(const char* source) { |
i::FLAG_stress_compaction = false; |