diff options
Diffstat (limited to 'deps/v8/test/cctest/heap/test-heap.cc')
-rw-r--r-- | deps/v8/test/cctest/heap/test-heap.cc | 405 |
1 files changed, 288 insertions, 117 deletions
diff --git a/deps/v8/test/cctest/heap/test-heap.cc b/deps/v8/test/cctest/heap/test-heap.cc index c7c1d93f87..f12ba10979 100644 --- a/deps/v8/test/cctest/heap/test-heap.cc +++ b/deps/v8/test/cctest/heap/test-heap.cc @@ -37,8 +37,10 @@ #include "src/execution.h" #include "src/field-type.h" #include "src/global-handles.h" +#include "src/hash-seed-inl.h" #include "src/heap/factory.h" #include "src/heap/gc-tracer.h" +#include "src/heap/heap-inl.h" #include "src/heap/incremental-marking.h" #include "src/heap/mark-compact.h" #include "src/heap/memory-reducer.h" @@ -46,6 +48,7 @@ #include "src/ic/ic.h" #include "src/macro-assembler-inl.h" #include "src/objects-inl.h" +#include "src/objects/frame-array-inl.h" #include "src/objects/heap-number-inl.h" #include "src/objects/js-array-inl.h" #include "src/objects/js-collection-inl.h" @@ -188,7 +191,7 @@ HEAP_TEST(TestNewSpaceRefsInCopiedCode) { HandleScope sc(isolate); Handle<HeapNumber> value = factory->NewHeapNumber(1.000123); - CHECK(Heap::InNewSpace(*value)); + CHECK(Heap::InYoungGeneration(*value)); i::byte buffer[i::Assembler::kMinimalBufferSize]; MacroAssembler masm(isolate, v8::internal::CodeObjectRequired::kYes, @@ -368,16 +371,11 @@ TEST(GarbageCollection) { HandleScope inner_scope(isolate); // Allocate a function and keep it in global object's property. Handle<JSFunction> function = factory->NewFunctionForTest(name); - Object::SetProperty(isolate, global, name, function, LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, global, name, function).Check(); // Allocate an object. Unrooted after leaving the scope. Handle<JSObject> obj = factory->NewJSObject(function); - Object::SetProperty(isolate, obj, prop_name, twenty_three, - LanguageMode::kSloppy) - .Check(); - Object::SetProperty(isolate, obj, prop_namex, twenty_four, - LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, obj, prop_name, twenty_three).Check(); + Object::SetProperty(isolate, obj, prop_namex, twenty_four).Check(); CHECK_EQ(Smi::FromInt(23), *Object::GetProperty(isolate, obj, prop_name).ToHandleChecked()); @@ -399,11 +397,8 @@ TEST(GarbageCollection) { HandleScope inner_scope(isolate); // Allocate another object, make it reachable from global. Handle<JSObject> obj = factory->NewJSObject(function); - Object::SetProperty(isolate, global, obj_name, obj, LanguageMode::kSloppy) - .Check(); - Object::SetProperty(isolate, obj, prop_name, twenty_three, - LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, global, obj_name, obj).Check(); + Object::SetProperty(isolate, obj, prop_name, twenty_three).Check(); } // After gc, it should survive. @@ -698,7 +693,7 @@ TEST(WeakGlobalHandlesMark) { // Make sure the objects are promoted. CcTest::CollectGarbage(OLD_SPACE); CcTest::CollectGarbage(NEW_SPACE); - CHECK(!Heap::InNewSpace(*h1) && !Heap::InNewSpace(*h2)); + CHECK(!Heap::InYoungGeneration(*h1) && !Heap::InYoungGeneration(*h2)); std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234); GlobalHandles::MakeWeak( @@ -944,15 +939,11 @@ TEST(FunctionAllocation) { Handle<String> prop_name = factory->InternalizeUtf8String("theSlot"); Handle<JSObject> obj = factory->NewJSObject(function); - Object::SetProperty(isolate, obj, prop_name, twenty_three, - LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, obj, prop_name, twenty_three).Check(); CHECK_EQ(Smi::FromInt(23), *Object::GetProperty(isolate, obj, prop_name).ToHandleChecked()); // Check that we can add properties to function objects. - Object::SetProperty(isolate, function, prop_name, twenty_four, - LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, function, prop_name, twenty_four).Check(); CHECK_EQ( Smi::FromInt(24), *Object::GetProperty(isolate, function, prop_name).ToHandleChecked()); @@ -983,7 +974,7 @@ TEST(ObjectProperties) { CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first)); // add first - Object::SetProperty(isolate, obj, first, one, LanguageMode::kSloppy).Check(); + Object::SetProperty(isolate, obj, first, one).Check(); CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first)); // delete first @@ -992,8 +983,8 @@ TEST(ObjectProperties) { CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first)); // add first and then second - Object::SetProperty(isolate, obj, first, one, LanguageMode::kSloppy).Check(); - Object::SetProperty(isolate, obj, second, two, LanguageMode::kSloppy).Check(); + Object::SetProperty(isolate, obj, first, one).Check(); + Object::SetProperty(isolate, obj, second, two).Check(); CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first)); CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, second)); @@ -1007,8 +998,8 @@ TEST(ObjectProperties) { CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, second)); // add first and then second - Object::SetProperty(isolate, obj, first, one, LanguageMode::kSloppy).Check(); - Object::SetProperty(isolate, obj, second, two, LanguageMode::kSloppy).Check(); + Object::SetProperty(isolate, obj, first, one).Check(); + Object::SetProperty(isolate, obj, second, two).Check(); CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first)); CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, second)); @@ -1024,15 +1015,14 @@ TEST(ObjectProperties) { // check string and internalized string match const char* string1 = "fisk"; Handle<String> s1 = factory->NewStringFromAsciiChecked(string1); - Object::SetProperty(isolate, obj, s1, one, LanguageMode::kSloppy).Check(); + Object::SetProperty(isolate, obj, s1, one).Check(); Handle<String> s1_string = factory->InternalizeUtf8String(string1); CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, s1_string)); // check internalized string and string match const char* string2 = "fugl"; Handle<String> s2_string = factory->InternalizeUtf8String(string2); - Object::SetProperty(isolate, obj, s2_string, one, LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, obj, s2_string, one).Check(); Handle<String> s2 = factory->NewStringFromAsciiChecked(string2); CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, s2)); } @@ -1053,9 +1043,7 @@ TEST(JSObjectMaps) { // Set a propery Handle<Smi> twenty_three(Smi::FromInt(23), isolate); - Object::SetProperty(isolate, obj, prop_name, twenty_three, - LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, obj, prop_name, twenty_three).Check(); CHECK_EQ(Smi::FromInt(23), *Object::GetProperty(isolate, obj, prop_name).ToHandleChecked()); @@ -1090,7 +1078,7 @@ TEST(JSArray) { CHECK(array->HasSmiOrObjectElements()); // array[length] = name. - Object::SetElement(isolate, array, 0, name, LanguageMode::kSloppy).Check(); + Object::SetElement(isolate, array, 0, name, ShouldThrow::kDontThrow).Check(); CHECK_EQ(Smi::FromInt(1), array->length()); element = i::Object::GetElement(isolate, array, 0).ToHandleChecked(); CHECK_EQ(*element, *name); @@ -1104,7 +1092,7 @@ TEST(JSArray) { CHECK(array->HasDictionaryElements()); // Must be in slow mode. // array[length] = name. - Object::SetElement(isolate, array, int_length, name, LanguageMode::kSloppy) + Object::SetElement(isolate, array, int_length, name, ShouldThrow::kDontThrow) .Check(); uint32_t new_int_length = 0; CHECK(array->length()->ToArrayIndex(&new_int_length)); @@ -1136,11 +1124,11 @@ TEST(JSObjectCopy) { Handle<Smi> one(Smi::FromInt(1), isolate); Handle<Smi> two(Smi::FromInt(2), isolate); - Object::SetProperty(isolate, obj, first, one, LanguageMode::kSloppy).Check(); - Object::SetProperty(isolate, obj, second, two, LanguageMode::kSloppy).Check(); + Object::SetProperty(isolate, obj, first, one).Check(); + Object::SetProperty(isolate, obj, second, two).Check(); - Object::SetElement(isolate, obj, 0, first, LanguageMode::kSloppy).Check(); - Object::SetElement(isolate, obj, 1, second, LanguageMode::kSloppy).Check(); + Object::SetElement(isolate, obj, 0, first, ShouldThrow::kDontThrow).Check(); + Object::SetElement(isolate, obj, 1, second, ShouldThrow::kDontThrow).Check(); // Make the clone. Handle<Object> value1, value2; @@ -1162,13 +1150,12 @@ TEST(JSObjectCopy) { CHECK_EQ(*value1, *value2); // Flip the values. - Object::SetProperty(isolate, clone, first, two, LanguageMode::kSloppy) - .Check(); - Object::SetProperty(isolate, clone, second, one, LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, clone, first, two).Check(); + Object::SetProperty(isolate, clone, second, one).Check(); - Object::SetElement(isolate, clone, 0, second, LanguageMode::kSloppy).Check(); - Object::SetElement(isolate, clone, 1, first, LanguageMode::kSloppy).Check(); + Object::SetElement(isolate, clone, 0, second, ShouldThrow::kDontThrow) + .Check(); + Object::SetElement(isolate, clone, 1, first, ShouldThrow::kDontThrow).Check(); value1 = Object::GetElement(isolate, obj, 1).ToHandleChecked(); value2 = Object::GetElement(isolate, clone, 0).ToHandleChecked(); @@ -1800,8 +1787,9 @@ static HeapObject NewSpaceAllocateAligned(int size, static Address AlignNewSpace(AllocationAlignment alignment, int offset) { Address* top_addr = CcTest::heap()->new_space()->allocation_top_address(); int fill = Heap::GetFillToAlign(*top_addr, alignment); - if (fill) { - NewSpaceAllocateAligned(fill + offset, kWordAligned); + int allocation = fill + offset; + if (allocation) { + NewSpaceAllocateAligned(allocation, kWordAligned); } return *top_addr; } @@ -1923,6 +1911,64 @@ TEST(TestAlignedOverAllocation) { } } +TEST(HeapNumberAlignment) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + Factory* factory = isolate->factory(); + Heap* heap = isolate->heap(); + HandleScope sc(isolate); + + const auto required_alignment = + HeapObject::RequiredAlignment(*factory->heap_number_map()); + const int maximum_misalignment = + Heap::GetMaximumFillToAlign(required_alignment); + + for (int offset = 0; offset <= maximum_misalignment; offset += kTaggedSize) { + AlignNewSpace(required_alignment, offset); + Handle<Object> number_new = factory->NewNumber(1.000123); + CHECK(number_new->IsHeapNumber()); + CHECK(Heap::InYoungGeneration(*number_new)); + CHECK_EQ(0, Heap::GetFillToAlign(HeapObject::cast(*number_new)->address(), + required_alignment)); + + AlignOldSpace(required_alignment, offset); + Handle<Object> number_old = factory->NewNumber(1.000321, TENURED); + CHECK(number_old->IsHeapNumber()); + CHECK(heap->InOldSpace(*number_old)); + CHECK_EQ(0, Heap::GetFillToAlign(HeapObject::cast(*number_old)->address(), + required_alignment)); + } +} + +TEST(MutableHeapNumberAlignment) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + Factory* factory = isolate->factory(); + Heap* heap = isolate->heap(); + HandleScope sc(isolate); + + const auto required_alignment = + HeapObject::RequiredAlignment(*factory->mutable_heap_number_map()); + const int maximum_misalignment = + Heap::GetMaximumFillToAlign(required_alignment); + + for (int offset = 0; offset <= maximum_misalignment; offset += kTaggedSize) { + AlignNewSpace(required_alignment, offset); + Handle<Object> number_new = factory->NewMutableHeapNumber(1.000123); + CHECK(number_new->IsMutableHeapNumber()); + CHECK(Heap::InYoungGeneration(*number_new)); + CHECK_EQ(0, Heap::GetFillToAlign(HeapObject::cast(*number_new)->address(), + required_alignment)); + + AlignOldSpace(required_alignment, offset); + Handle<Object> number_old = + factory->NewMutableHeapNumber(1.000321, TENURED); + CHECK(number_old->IsMutableHeapNumber()); + CHECK(heap->InOldSpace(*number_old)); + CHECK_EQ(0, Heap::GetFillToAlign(HeapObject::cast(*number_old)->address(), + required_alignment)); + } +} TEST(TestSizeOfObjectsVsHeapIteratorPrecision) { CcTest::InitializeVM(); @@ -1975,6 +2021,8 @@ TEST(GrowAndShrinkNewSpace) { // Make sure we're in a consistent state to start out. CcTest::CollectAllGarbage(); + CcTest::CollectAllGarbage(); + new_space->Shrink(); // Explicitly growing should double the space capacity. size_t old_capacity, new_capacity; @@ -2285,11 +2333,12 @@ TEST(InstanceOfStubWriteBarrier) { IncrementalMarking::MarkingState* marking_state = marking->marking_state(); + const double kStepSizeInMs = 100; while (!marking_state->IsBlack(f->code()) && !marking->IsStopped()) { // Discard any pending GC requests otherwise we will get GC when we enter // code below. - marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD, - StepOrigin::kV8); + marking->V8Step(kStepSizeInMs, IncrementalMarking::NO_GC_VIA_STACK_GUARD, + StepOrigin::kV8); } CHECK(marking->IsMarking()); @@ -2352,7 +2401,7 @@ HEAP_TEST(Regress845060) { // Preparation: create a string in new space. Local<Value> str = CompileRun("var str = (new Array(10000)).join('x'); str"); - CHECK(Heap::InNewSpace(*v8::Utils::OpenHandle(*str))); + CHECK(Heap::InYoungGeneration(*v8::Utils::OpenHandle(*str))); // Idle incremental marking sets the "kReduceMemoryFootprint" flag, which // causes from_space to be unmapped after scavenging. @@ -2363,7 +2412,7 @@ HEAP_TEST(Regress845060) { // promoted to old space. Unmapping of from_space causes accesses to any // stale raw pointers to crash. CompileRun("while (%InNewSpace(str)) { str.split(''); }"); - CHECK(!Heap::InNewSpace(*v8::Utils::OpenHandle(*str))); + CHECK(!Heap::InYoungGeneration(*v8::Utils::OpenHandle(*str))); } TEST(IdleNotificationFinishMarking) { @@ -2380,9 +2429,10 @@ TEST(IdleNotificationFinishMarking) { CHECK_EQ(CcTest::heap()->gc_count(), initial_gc_count); + const double kStepSizeInMs = 100; do { - marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD, - StepOrigin::kV8); + marking->V8Step(kStepSizeInMs, IncrementalMarking::NO_GC_VIA_STACK_GUARD, + StepOrigin::kV8); } while ( !CcTest::heap()->mark_compact_collector()->marking_worklist()->IsEmpty()); @@ -2431,7 +2481,7 @@ TEST(OptimizedAllocationAlwaysInNewSpace) { i::Handle<JSReceiver> o = v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res)); - CHECK(Heap::InNewSpace(*o)); + CHECK(Heap::InYoungGeneration(*o)); } @@ -2569,7 +2619,7 @@ TEST(OptimizedPretenuringNestedInObjectProperties) { // Nested literal sites are only pretenured if the top level // literal is pretenured - CHECK(Heap::InNewSpace(*o)); + CHECK(Heap::InYoungGeneration(*o)); } TEST(OptimizedPretenuringMixedInObjectProperties) { @@ -2897,7 +2947,7 @@ TEST(OptimizedAllocationArrayLiterals) { i::Handle<JSObject> o = Handle<JSObject>::cast( v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res))); - CHECK(Heap::InNewSpace(o->elements())); + CHECK(Heap::InYoungGeneration(o->elements())); } static int CountMapTransitions(i::Isolate* isolate, Map map) { @@ -2952,6 +3002,13 @@ TEST(Regress1465) { CHECK_EQ(1, transitions_after); } +static i::Handle<JSObject> GetByName(const char* name) { + return i::Handle<JSObject>::cast( + v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast( + CcTest::global() + ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name)) + .ToLocalChecked()))); +} #ifdef DEBUG static void AddTransitions(int transitions_count) { @@ -2964,15 +3021,6 @@ static void AddTransitions(int transitions_count) { } -static i::Handle<JSObject> GetByName(const char* name) { - return i::Handle<JSObject>::cast( - v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast( - CcTest::global() - ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name)) - .ToLocalChecked()))); -} - - static void AddPropertyTo( int gc_count, Handle<JSObject> object, const char* property_name) { Isolate* isolate = CcTest::i_isolate(); @@ -2983,9 +3031,7 @@ static void AddPropertyTo( FLAG_gc_global = true; FLAG_retain_maps_for_n_gc = 0; CcTest::heap()->set_allocation_timeout(gc_count); - Object::SetProperty(isolate, object, prop_name, twenty_three, - LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, object, prop_name, twenty_three).Check(); } @@ -3106,6 +3152,9 @@ TEST(ReleaseOverReservedPages) { Factory* factory = isolate->factory(); Heap* heap = isolate->heap(); v8::HandleScope scope(CcTest::isolate()); + // Ensure that the young generation is empty. + CcTest::CollectGarbage(NEW_SPACE); + CcTest::CollectGarbage(NEW_SPACE); static const int number_of_test_pages = 20; // Prepare many pages with low live-bytes count. @@ -3139,7 +3188,7 @@ TEST(ReleaseOverReservedPages) { // boots, but if the 20 small arrays don't fit on the first page then that's // an indication that it is too small. CcTest::CollectAllAvailableGarbage(); - CHECK_EQ(initial_page_count, old_space->CountTotalPages()); + CHECK_GE(initial_page_count, old_space->CountTotalPages()); } static int forced_gc_counter = 0; @@ -3239,7 +3288,7 @@ static void CheckVectorIC(Handle<JSFunction> f, int slot_index, FeedbackVectorHelper helper(vector); FeedbackSlot slot = helper.slot(slot_index); FeedbackNexus nexus(vector, slot); - CHECK(nexus.StateFromFeedback() == desired_state); + CHECK(nexus.ic_state() == desired_state); } TEST(IncrementalMarkingPreservesMonomorphicConstructor) { @@ -3488,6 +3537,119 @@ UNINITIALIZED_TEST(ReleaseStackTraceData) { isolate->Dispose(); } +// TODO(mmarchini) also write tests for async/await and Promise.all +void DetailedErrorStackTraceTest(const char* src, + std::function<void(Handle<FrameArray>)> test) { + FLAG_detailed_error_stack_trace = true; + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + + v8::TryCatch try_catch(CcTest::isolate()); + CompileRun(src); + + CHECK(try_catch.HasCaught()); + Handle<Object> exception = v8::Utils::OpenHandle(*try_catch.Exception()); + + Isolate* isolate = CcTest::i_isolate(); + Handle<Name> key = isolate->factory()->stack_trace_symbol(); + + Handle<FrameArray> stack_trace( + FrameArray::cast( + Handle<JSArray>::cast( + Object::GetProperty(isolate, exception, key).ToHandleChecked()) + ->elements()), + isolate); + + test(stack_trace); +} + +// * Test interpreted function error +TEST(DetailedErrorStackTrace) { + static const char* source = + "function func1(arg1) { " + " let err = new Error(); " + " throw err; " + "} " + "function func2(arg1, arg2) { " + " func1(42); " + "} " + "class Foo {}; " + "function main(arg1, arg2) { " + " func2(arg1, false); " + "} " + "var foo = new Foo(); " + "main(foo); "; + + DetailedErrorStackTraceTest(source, [](Handle<FrameArray> stack_trace) { + FixedArray foo_parameters = stack_trace->Parameters(0); + CHECK_EQ(foo_parameters->length(), 1); + CHECK(foo_parameters->get(0)->IsSmi()); + CHECK_EQ(Smi::ToInt(foo_parameters->get(0)), 42); + + FixedArray bar_parameters = stack_trace->Parameters(1); + CHECK_EQ(bar_parameters->length(), 2); + CHECK(bar_parameters->get(0)->IsJSObject()); + CHECK(bar_parameters->get(1)->IsBoolean()); + Handle<Object> foo = Handle<Object>::cast(GetByName("foo")); + CHECK_EQ(bar_parameters->get(0), *foo); + CHECK(!bar_parameters->get(1)->BooleanValue(CcTest::i_isolate())); + + FixedArray main_parameters = stack_trace->Parameters(2); + CHECK_EQ(main_parameters->length(), 2); + CHECK(main_parameters->get(0)->IsJSObject()); + CHECK(main_parameters->get(1)->IsUndefined()); + CHECK_EQ(main_parameters->get(0), *foo); + }); +} + +// * Test optimized function with inline frame error +TEST(DetailedErrorStackTraceInline) { + FLAG_allow_natives_syntax = true; + static const char* source = + "function add(x) { " + " if (x == 42) " + " throw new Error(); " + " return x + x; " + "} " + "add(0); " + "add(1); " + "function foo(x) { " + " return add(x + 1) " + "} " + "foo(40); " + "%OptimizeFunctionOnNextCall(foo); " + "foo(41); "; + + DetailedErrorStackTraceTest(source, [](Handle<FrameArray> stack_trace) { + FixedArray parameters_add = stack_trace->Parameters(0); + CHECK_EQ(parameters_add->length(), 1); + CHECK(parameters_add->get(0)->IsSmi()); + CHECK_EQ(Smi::ToInt(parameters_add->get(0)), 42); + + FixedArray parameters_foo = stack_trace->Parameters(1); + CHECK_EQ(parameters_foo->length(), 1); + CHECK(parameters_foo->get(0)->IsSmi()); + CHECK_EQ(Smi::ToInt(parameters_foo->get(0)), 41); + }); +} + +// * Test builtin exit error +TEST(DetailedErrorStackTraceBuiltinExit) { + static const char* source = + "function test(arg1) { " + " (new Number()).toFixed(arg1); " + "} " + "test(9999); "; + + DetailedErrorStackTraceTest(source, [](Handle<FrameArray> stack_trace) { + FixedArray parameters = stack_trace->Parameters(0); + + CHECK_EQ(parameters->length(), 2); + CHECK(parameters->get(0)->IsSmi()); + CHECK_EQ(Smi::ToInt(parameters->get(0)), 9999); + }); +} + TEST(Regress169928) { FLAG_allow_natives_syntax = true; #ifndef V8_LITE_MODE @@ -3595,8 +3757,6 @@ TEST(LargeObjectSlotRecording) { // Start incremental marking to active write barrier. heap::SimulateIncrementalMarking(heap, false); - heap->incremental_marking()->AdvanceIncrementalMarking( - 10000000, IncrementalMarking::NO_GC_VIA_STACK_GUARD, StepOrigin::kV8); // Create references from the large object to the object on the evacuation // candidate. @@ -3606,6 +3766,8 @@ TEST(LargeObjectSlotRecording) { CHECK(lo->get(i) == old_location); } + heap::SimulateIncrementalMarking(heap, true); + // Move the evaucation candidate object. CcTest::CollectAllGarbage(); @@ -3659,9 +3821,7 @@ TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) { CcTest::heap()->StartIncrementalMarking( i::Heap::kNoGCFlags, i::GarbageCollectionReason::kTesting); } - // This big step should be sufficient to mark the whole array. - marking->Step(100 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD, - StepOrigin::kV8); + heap::SimulateIncrementalMarking(CcTest::heap()); CHECK(marking->IsComplete() || marking->IsReadyToOverApproximateWeakClosure()); } @@ -4069,10 +4229,10 @@ TEST(NewSpaceObjectsInOptimizedCode) { ->Get(context.local(), v8_str("foo")) .ToLocalChecked()))); - CHECK(Heap::InNewSpace(*foo)); + CHECK(Heap::InYoungGeneration(*foo)); CcTest::CollectGarbage(NEW_SPACE); CcTest::CollectGarbage(NEW_SPACE); - CHECK(!Heap::InNewSpace(*foo)); + CHECK(!Heap::InYoungGeneration(*foo)); #ifdef VERIFY_HEAP CcTest::heap()->Verify(); #endif @@ -4519,7 +4679,7 @@ void CheckIC(Handle<JSFunction> function, int slot_index, FeedbackVector vector = function->feedback_vector(); FeedbackSlot slot(slot_index); FeedbackNexus nexus(vector, slot); - CHECK_EQ(nexus.StateFromFeedback(), state); + CHECK_EQ(nexus.ic_state(), state); } TEST(MonomorphicStaysMonomorphicAfterGC) { @@ -4735,8 +4895,8 @@ TEST(Regress507979) { Handle<FixedArray> o1 = isolate->factory()->NewFixedArray(kFixedArrayLen); Handle<FixedArray> o2 = isolate->factory()->NewFixedArray(kFixedArrayLen); - CHECK(Heap::InNewSpace(*o1)); - CHECK(Heap::InNewSpace(*o2)); + CHECK(Heap::InYoungGeneration(*o1)); + CHECK(Heap::InYoungGeneration(*o2)); HeapIterator it(isolate->heap(), i::HeapIterator::kFilterUnreachable); @@ -4826,12 +4986,7 @@ TEST(Regress3631) { Handle<JSReceiver> obj = v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(result)); Handle<JSWeakCollection> weak_map(JSWeakCollection::cast(*obj), isolate); - HeapObject weak_map_table = HeapObject::cast(weak_map->table()); - IncrementalMarking::MarkingState* marking_state = marking->marking_state(); - while (!marking_state->IsBlack(weak_map_table) && !marking->IsStopped()) { - marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD, - StepOrigin::kV8); - } + SimulateIncrementalMarking(heap); // Stash the backing store in a handle. Handle<Object> save(weak_map->table(), isolate); // The following line will update the backing store. @@ -4855,8 +5010,7 @@ TEST(Regress442710) { Handle<JSArray> array = factory->NewJSArray(2); Handle<String> name = factory->InternalizeUtf8String("testArray"); - Object::SetProperty(isolate, global, name, array, LanguageMode::kSloppy) - .Check(); + Object::SetProperty(isolate, global, name, array).Check(); CompileRun("testArray[0] = 1; testArray[1] = 2; testArray.shift();"); CcTest::CollectGarbage(OLD_SPACE); } @@ -4991,7 +5145,7 @@ void AllocateInSpace(Isolate* isolate, size_t bytes, AllocationSpace space) { static_cast<int>((bytes - FixedArray::kHeaderSize) / kTaggedSize); Handle<FixedArray> array = factory->NewFixedArray( elements, space == NEW_SPACE ? NOT_TENURED : TENURED); - CHECK((space == NEW_SPACE) == Heap::InNewSpace(*array)); + CHECK((space == NEW_SPACE) == Heap::InYoungGeneration(*array)); CHECK_EQ(bytes, static_cast<size_t>(array->Size())); } @@ -5213,7 +5367,8 @@ AllocationResult HeapTester::AllocateByteArrayForTest(Heap* heap, int length, AllocationSpace space = heap->SelectSpace(pretenure); HeapObject result; { - AllocationResult allocation = heap->AllocateRaw(size, space); + AllocationResult allocation = + heap->AllocateRaw(size, Heap::SelectType(space)); if (!allocation.To(&result)) return allocation; } @@ -5239,7 +5394,7 @@ HEAP_TEST(Regress587004) { Handle<FixedArray> array = factory->NewFixedArray(N, TENURED); CHECK(heap->old_space()->Contains(*array)); Handle<Object> number = factory->NewHeapNumber(1.0); - CHECK(Heap::InNewSpace(*number)); + CHECK(Heap::InYoungGeneration(*number)); for (int i = 0; i < N; i++) { array->set(i, *number); } @@ -5349,7 +5504,8 @@ TEST(Regress598319) { Heap* heap = CcTest::heap(); Isolate* isolate = heap->isolate(); - const int kNumberOfObjects = kMaxRegularHeapObjectSize / kTaggedSize; + // The size of the array should be larger than kProgressBarScanningChunk. + const int kNumberOfObjects = Max(FixedArray::kMaxRegularLength + 1, 128 * KB); struct Arr { Arr(Isolate* isolate, int number_of_objects) { @@ -5374,7 +5530,7 @@ TEST(Regress598319) { CHECK_EQ(arr.get()->length(), kNumberOfObjects); CHECK(heap->lo_space()->Contains(arr.get())); - LargePage* page = heap->lo_space()->FindPage(arr.get()->address()); + LargePage* page = LargePage::FromHeapObject(arr.get()); CHECK_NOT_NULL(page); // GC to cleanup state @@ -5409,11 +5565,13 @@ TEST(Regress598319) { // Now we search for a state where we are in incremental marking and have // only partially marked the large object. + const double kSmallStepSizeInMs = 0.1; while (!marking->IsComplete()) { - marking->Step(i::KB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD, - StepOrigin::kV8); - if (page->IsFlagSet(Page::HAS_PROGRESS_BAR) && page->progress_bar() > 0) { - CHECK_NE(page->progress_bar(), arr.get()->Size()); + marking->V8Step(kSmallStepSizeInMs, + i::IncrementalMarking::NO_GC_VIA_STACK_GUARD, + StepOrigin::kV8); + if (page->IsFlagSet(Page::HAS_PROGRESS_BAR) && page->ProgressBar() > 0) { + CHECK_NE(page->ProgressBar(), arr.get()->Size()); { // Shift by 1, effectively moving one white object across the progress // bar, meaning that we will miss marking it. @@ -5427,9 +5585,11 @@ TEST(Regress598319) { } // Finish marking with bigger steps to speed up test. + const double kLargeStepSizeInMs = 1000; while (!marking->IsComplete()) { - marking->Step(10 * i::MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD, - StepOrigin::kV8); + marking->V8Step(kLargeStepSizeInMs, + i::IncrementalMarking::NO_GC_VIA_STACK_GUARD, + StepOrigin::kV8); if (marking->IsReadyToOverApproximateWeakClosure()) { marking->FinalizeIncrementally(); } @@ -5509,9 +5669,10 @@ TEST(Regress615489) { v8::HandleScope inner(CcTest::isolate()); isolate->factory()->NewFixedArray(500, TENURED)->Size(); } + const double kStepSizeInMs = 100; while (!marking->IsComplete()) { - marking->Step(i::MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD, - StepOrigin::kV8); + marking->V8Step(kStepSizeInMs, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD, + StepOrigin::kV8); if (marking->IsReadyToOverApproximateWeakClosure()) { marking->FinalizeIncrementally(); } @@ -5568,10 +5729,11 @@ TEST(Regress631969) { CcTest::CollectGarbage(NEW_SPACE); // Finish incremental marking. + const double kStepSizeInMs = 100; IncrementalMarking* marking = heap->incremental_marking(); while (!marking->IsComplete()) { - marking->Step(MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD, - StepOrigin::kV8); + marking->V8Step(kStepSizeInMs, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD, + StepOrigin::kV8); if (marking->IsReadyToOverApproximateWeakClosure()) { marking->FinalizeIncrementally(); } @@ -5657,7 +5819,8 @@ TEST(ContinuousLeftTrimFixedArrayInBlackArea) { Address start_address = array->address(); Address end_address = start_address + array->Size(); Page* page = Page::FromAddress(start_address); - IncrementalMarking::MarkingState* marking_state = marking->marking_state(); + IncrementalMarking::NonAtomicMarkingState* marking_state = + marking->non_atomic_marking_state(); CHECK(marking_state->IsBlack(*array)); CHECK(marking_state->bitmap(page)->AllBitsSetInRange( page->AddressToMarkbitIndex(start_address), @@ -5724,7 +5887,8 @@ TEST(ContinuousRightTrimFixedArrayInBlackArea) { Address start_address = array->address(); Address end_address = start_address + array->Size(); Page* page = Page::FromAddress(start_address); - IncrementalMarking::MarkingState* marking_state = marking->marking_state(); + IncrementalMarking::NonAtomicMarkingState* marking_state = + marking->non_atomic_marking_state(); CHECK(marking_state->IsBlack(*array)); CHECK(marking_state->bitmap(page)->AllBitsSetInRange( @@ -5786,7 +5950,8 @@ TEST(YoungGenerationLargeObjectAllocationScavenge) { Handle<FixedArray> array_small = isolate->factory()->NewFixedArray(200000); MemoryChunk* chunk = MemoryChunk::FromHeapObject(*array_small); CHECK_EQ(NEW_LO_SPACE, chunk->owner()->identity()); - CHECK(chunk->IsFlagSet(MemoryChunk::IN_TO_SPACE)); + CHECK(chunk->IsFlagSet(MemoryChunk::LARGE_PAGE)); + CHECK(chunk->IsFlagSet(MemoryChunk::TO_PAGE)); Handle<Object> number = isolate->factory()->NewHeapNumber(123.456); array_small->set(0, *number); @@ -5797,7 +5962,7 @@ TEST(YoungGenerationLargeObjectAllocationScavenge) { // generation large object space. chunk = MemoryChunk::FromHeapObject(*array_small); CHECK_EQ(LO_SPACE, chunk->owner()->identity()); - CHECK(!chunk->IsFlagSet(MemoryChunk::IN_TO_SPACE)); + CHECK(!chunk->InYoungGeneration()); CcTest::CollectAllAvailableGarbage(); } @@ -5815,7 +5980,8 @@ TEST(YoungGenerationLargeObjectAllocationMarkCompact) { Handle<FixedArray> array_small = isolate->factory()->NewFixedArray(200000); MemoryChunk* chunk = MemoryChunk::FromHeapObject(*array_small); CHECK_EQ(NEW_LO_SPACE, chunk->owner()->identity()); - CHECK(chunk->IsFlagSet(MemoryChunk::IN_TO_SPACE)); + CHECK(chunk->IsFlagSet(MemoryChunk::LARGE_PAGE)); + CHECK(chunk->IsFlagSet(MemoryChunk::TO_PAGE)); Handle<Object> number = isolate->factory()->NewHeapNumber(123.456); array_small->set(0, *number); @@ -5826,7 +5992,7 @@ TEST(YoungGenerationLargeObjectAllocationMarkCompact) { // large object space. chunk = MemoryChunk::FromHeapObject(*array_small); CHECK_EQ(LO_SPACE, chunk->owner()->identity()); - CHECK(!chunk->IsFlagSet(MemoryChunk::IN_TO_SPACE)); + CHECK(!chunk->InYoungGeneration()); CcTest::CollectAllAvailableGarbage(); } @@ -5846,7 +6012,7 @@ TEST(YoungGenerationLargeObjectAllocationReleaseScavenger) { Handle<FixedArray> array_small = isolate->factory()->NewFixedArray(20000); MemoryChunk* chunk = MemoryChunk::FromHeapObject(*array_small); CHECK_EQ(NEW_LO_SPACE, chunk->owner()->identity()); - CHECK(chunk->IsFlagSet(MemoryChunk::IN_TO_SPACE)); + CHECK(chunk->IsFlagSet(MemoryChunk::TO_PAGE)); } } @@ -5975,7 +6141,7 @@ HEAP_TEST(Regress670675) { if (marking->IsStopped()) { marking->Start(i::GarbageCollectionReason::kTesting); } - size_t array_length = Page::kPageSize / kTaggedSize + 100; + size_t array_length = 128 * KB; size_t n = heap->OldGenerationSpaceAvailable() / array_length; for (size_t i = 0; i < n + 40; i++) { { @@ -5985,7 +6151,7 @@ HEAP_TEST(Regress670675) { } if (marking->IsStopped()) break; double deadline = heap->MonotonicallyIncreasingTimeInMs() + 1; - marking->AdvanceIncrementalMarking( + marking->AdvanceWithDeadline( deadline, IncrementalMarking::GC_VIA_STACK_GUARD, StepOrigin::kV8); } DCHECK(marking->IsStopped()); @@ -6159,7 +6325,7 @@ UNINITIALIZED_TEST(ReinitializeStringHashSeed) { { v8::Isolate::Scope isolate_scope(isolate); CHECK_EQ(static_cast<uint64_t>(1337 * i), - reinterpret_cast<i::Isolate*>(isolate)->heap()->HashSeed()); + HashSeed(reinterpret_cast<i::Isolate*>(isolate))); v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate); CHECK(!context.IsEmpty()); @@ -6258,7 +6424,7 @@ HEAP_TEST(Regress779503) { // The byte array filled with kHeapObjectTag ensures that we cannot read // from the slot again and interpret it as heap value. Doing so will crash. Handle<ByteArray> byte_array = isolate->factory()->NewByteArray(kArraySize); - CHECK(Heap::InNewSpace(*byte_array)); + CHECK(Heap::InYoungGeneration(*byte_array)); for (int i = 0; i < kArraySize; i++) { byte_array->set(i, kHeapObjectTag); } @@ -6268,7 +6434,7 @@ HEAP_TEST(Regress779503) { // The FixedArray in old space serves as space for slots. Handle<FixedArray> fixed_array = isolate->factory()->NewFixedArray(kArraySize, TENURED); - CHECK(!Heap::InNewSpace(*fixed_array)); + CHECK(!Heap::InYoungGeneration(*fixed_array)); for (int i = 0; i < kArraySize; i++) { fixed_array->set(i, *byte_array); } @@ -6277,7 +6443,7 @@ HEAP_TEST(Regress779503) { // currently scavenging. heap->delay_sweeper_tasks_for_testing_ = true; CcTest::CollectGarbage(OLD_SPACE); - CHECK(Heap::InNewSpace(*byte_array)); + CHECK(Heap::InYoungGeneration(*byte_array)); } // Scavenging and sweeping the same page will crash as slots will be // overridden. @@ -6291,6 +6457,7 @@ struct OutOfMemoryState { size_t old_generation_capacity_at_oom; size_t memory_allocator_size_at_oom; size_t new_space_capacity_at_oom; + size_t new_lo_space_size_at_oom; size_t current_heap_limit; size_t initial_heap_limit; }; @@ -6303,6 +6470,7 @@ size_t NearHeapLimitCallback(void* raw_state, size_t current_heap_limit, state->old_generation_capacity_at_oom = heap->OldGenerationCapacity(); state->memory_allocator_size_at_oom = heap->memory_allocator()->Size(); state->new_space_capacity_at_oom = heap->new_space()->Capacity(); + state->new_lo_space_size_at_oom = heap->new_lo_space()->Size(); state->current_heap_limit = current_heap_limit; state->initial_heap_limit = initial_heap_limit; return initial_heap_limit + 100 * MB; @@ -6378,11 +6546,14 @@ UNINITIALIZED_TEST(OutOfMemoryLargeObjects) { } CHECK_LE(state.old_generation_capacity_at_oom, kOldGenerationLimit); CHECK_LE(kOldGenerationLimit, state.old_generation_capacity_at_oom + + state.new_space_capacity_at_oom + + state.new_lo_space_size_at_oom + FixedArray::SizeFor(kFixedArrayLength)); CHECK_LE( state.memory_allocator_size_at_oom, MemoryAllocatorSizeFromHeapCapacity(state.old_generation_capacity_at_oom + - 2 * state.new_space_capacity_at_oom)); + 2 * state.new_space_capacity_at_oom + + state.new_lo_space_size_at_oom)); reinterpret_cast<v8::Isolate*>(isolate)->Dispose(); } @@ -6466,7 +6637,7 @@ TEST(Regress8617) { Handle<Object> foo = v8::Utils::OpenHandle(*CompileRun("function foo() { return 42; };" "foo;")); - if (heap->InNewSpace(*foo)) { + if (heap->InYoungGeneration(*foo)) { CcTest::CollectGarbage(NEW_SPACE); CcTest::CollectGarbage(NEW_SPACE); } |