summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-heap.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/cctest/test-heap.cc')
-rw-r--r--deps/v8/test/cctest/test-heap.cc840
1 files changed, 534 insertions, 306 deletions
diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc
index 3cc61ed5f..ab000dc6a 100644
--- a/deps/v8/test/cctest/test-heap.cc
+++ b/deps/v8/test/cctest/test-heap.cc
@@ -28,37 +28,18 @@
#include <stdlib.h>
#include <utility>
-#include "v8.h"
+#include "src/v8.h"
-#include "compilation-cache.h"
-#include "execution.h"
-#include "factory.h"
-#include "macro-assembler.h"
-#include "global-handles.h"
-#include "stub-cache.h"
-#include "cctest.h"
+#include "src/compilation-cache.h"
+#include "src/execution.h"
+#include "src/factory.h"
+#include "src/global-handles.h"
+#include "src/macro-assembler.h"
+#include "src/stub-cache.h"
+#include "test/cctest/cctest.h"
using namespace v8::internal;
-// Go through all incremental marking steps in one swoop.
-static void SimulateIncrementalMarking() {
- MarkCompactCollector* collector = CcTest::heap()->mark_compact_collector();
- IncrementalMarking* marking = CcTest::heap()->incremental_marking();
- if (collector->IsConcurrentSweepingInProgress()) {
- collector->WaitUntilSweepingCompleted();
- }
- CHECK(marking->IsMarking() || marking->IsStopped());
- if (marking->IsStopped()) {
- marking->Start();
- }
- CHECK(marking->IsMarking());
- while (!marking->IsComplete()) {
- marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
- }
- CHECK(marking->IsComplete());
-}
-
-
static void CheckMap(Map* map, int type, int instance_size) {
CHECK(map->IsHeapObject());
#ifdef DEBUG
@@ -179,7 +160,8 @@ TEST(HeapObjects) {
CHECK(value->IsNumber());
CHECK_EQ(Smi::kMaxValue, Handle<Smi>::cast(value)->value());
-#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM64)
+#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM64) && \
+ !defined(V8_TARGET_ARCH_MIPS64)
// TODO(lrn): We need a NumberFromIntptr function in order to test this.
value = factory->NewNumberFromInt(Smi::kMinValue - 1);
CHECK(value->IsHeapNumber());
@@ -209,7 +191,9 @@ TEST(HeapObjects) {
Handle<String> object_string = Handle<String>::cast(factory->Object_string());
Handle<GlobalObject> global(CcTest::i_isolate()->context()->global_object());
- CHECK(JSReceiver::HasLocalProperty(global, object_string));
+ v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, object_string);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
// Check ToString for oddballs
CheckOddball(isolate, heap->true_value(), "true");
@@ -260,18 +244,12 @@ TEST(GarbageCollection) {
{
HandleScope inner_scope(isolate);
// Allocate a function and keep it in global object's property.
- Handle<JSFunction> function = factory->NewFunctionWithPrototype(
- name, factory->undefined_value());
- Handle<Map> initial_map =
- factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
- function->set_initial_map(*initial_map);
- JSReceiver::SetProperty(global, name, function, NONE, SLOPPY).Check();
+ Handle<JSFunction> function = factory->NewFunction(name);
+ JSReceiver::SetProperty(global, name, function, SLOPPY).Check();
// Allocate an object. Unrooted after leaving the scope.
Handle<JSObject> obj = factory->NewJSObject(function);
- JSReceiver::SetProperty(
- obj, prop_name, twenty_three, NONE, SLOPPY).Check();
- JSReceiver::SetProperty(
- obj, prop_namex, twenty_four, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, prop_name, twenty_three, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, prop_namex, twenty_four, SLOPPY).Check();
CHECK_EQ(Smi::FromInt(23),
*Object::GetProperty(obj, prop_name).ToHandleChecked());
@@ -282,7 +260,9 @@ TEST(GarbageCollection) {
heap->CollectGarbage(NEW_SPACE);
// Function should be alive.
- CHECK(JSReceiver::HasLocalProperty(global, name));
+ v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, name);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
// Check function is retained.
Handle<Object> func_value =
Object::GetProperty(global, name).ToHandleChecked();
@@ -293,15 +273,16 @@ TEST(GarbageCollection) {
HandleScope inner_scope(isolate);
// Allocate another object, make it reachable from global.
Handle<JSObject> obj = factory->NewJSObject(function);
- JSReceiver::SetProperty(global, obj_name, obj, NONE, SLOPPY).Check();
- JSReceiver::SetProperty(
- obj, prop_name, twenty_three, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(global, obj_name, obj, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, prop_name, twenty_three, SLOPPY).Check();
}
// After gc, it should survive.
heap->CollectGarbage(NEW_SPACE);
- CHECK(JSReceiver::HasLocalProperty(global, obj_name));
+ maybe = JSReceiver::HasOwnProperty(global, obj_name);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
Handle<Object> obj =
Object::GetProperty(global, obj_name).ToHandleChecked();
CHECK(obj->IsJSObject());
@@ -623,23 +604,18 @@ TEST(FunctionAllocation) {
v8::HandleScope sc(CcTest::isolate());
Handle<String> name = factory->InternalizeUtf8String("theFunction");
- Handle<JSFunction> function = factory->NewFunctionWithPrototype(
- name, factory->undefined_value());
- Handle<Map> initial_map =
- factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
- function->set_initial_map(*initial_map);
+ Handle<JSFunction> function = factory->NewFunction(name);
Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
Handle<Smi> twenty_four(Smi::FromInt(24), isolate);
Handle<String> prop_name = factory->InternalizeUtf8String("theSlot");
Handle<JSObject> obj = factory->NewJSObject(function);
- JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, prop_name, twenty_three, SLOPPY).Check();
CHECK_EQ(Smi::FromInt(23),
*Object::GetProperty(obj, prop_name).ToHandleChecked());
// Check that we can add properties to function objects.
- JSReceiver::SetProperty(
- function, prop_name, twenty_four, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(function, prop_name, twenty_four, SLOPPY).Check();
CHECK_EQ(Smi::FromInt(24),
*Object::GetProperty(function, prop_name).ToHandleChecked());
}
@@ -663,55 +639,85 @@ TEST(ObjectProperties) {
Handle<Smi> two(Smi::FromInt(2), isolate);
// check for empty
- CHECK(!JSReceiver::HasLocalProperty(obj, first));
+ v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(obj, first);
+ CHECK(maybe.has_value);
+ CHECK(!maybe.value);
// add first
- JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, first));
+ JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
+ maybe = JSReceiver::HasOwnProperty(obj, first);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
// delete first
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
- CHECK(!JSReceiver::HasLocalProperty(obj, first));
+ maybe = JSReceiver::HasOwnProperty(obj, first);
+ CHECK(maybe.has_value);
+ CHECK(!maybe.value);
// add first and then second
- JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY).Check();
- JSReceiver::SetProperty(obj, second, two, NONE, SLOPPY).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, first));
- CHECK(JSReceiver::HasLocalProperty(obj, second));
+ JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
+ maybe = JSReceiver::HasOwnProperty(obj, first);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
+ maybe = JSReceiver::HasOwnProperty(obj, second);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
// delete first and then second
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, second));
+ maybe = JSReceiver::HasOwnProperty(obj, second);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION).Check();
- CHECK(!JSReceiver::HasLocalProperty(obj, first));
- CHECK(!JSReceiver::HasLocalProperty(obj, second));
+ maybe = JSReceiver::HasOwnProperty(obj, first);
+ CHECK(maybe.has_value);
+ CHECK(!maybe.value);
+ maybe = JSReceiver::HasOwnProperty(obj, second);
+ CHECK(maybe.has_value);
+ CHECK(!maybe.value);
// add first and then second
- JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY).Check();
- JSReceiver::SetProperty(obj, second, two, NONE, SLOPPY).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, first));
- CHECK(JSReceiver::HasLocalProperty(obj, second));
+ JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
+ maybe = JSReceiver::HasOwnProperty(obj, first);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
+ maybe = JSReceiver::HasOwnProperty(obj, second);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
// delete second and then first
JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, first));
+ maybe = JSReceiver::HasOwnProperty(obj, first);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
- CHECK(!JSReceiver::HasLocalProperty(obj, first));
- CHECK(!JSReceiver::HasLocalProperty(obj, second));
+ maybe = JSReceiver::HasOwnProperty(obj, first);
+ CHECK(maybe.has_value);
+ CHECK(!maybe.value);
+ maybe = JSReceiver::HasOwnProperty(obj, second);
+ CHECK(maybe.has_value);
+ CHECK(!maybe.value);
// check string and internalized string match
const char* string1 = "fisk";
Handle<String> s1 = factory->NewStringFromAsciiChecked(string1);
- JSReceiver::SetProperty(obj, s1, one, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, s1, one, SLOPPY).Check();
Handle<String> s1_string = factory->InternalizeUtf8String(string1);
- CHECK(JSReceiver::HasLocalProperty(obj, s1_string));
+ maybe = JSReceiver::HasOwnProperty(obj, s1_string);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
// check internalized string and string match
const char* string2 = "fugl";
Handle<String> s2_string = factory->InternalizeUtf8String(string2);
- JSReceiver::SetProperty(obj, s2_string, one, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, s2_string, one, SLOPPY).Check();
Handle<String> s2 = factory->NewStringFromAsciiChecked(string2);
- CHECK(JSReceiver::HasLocalProperty(obj, s2));
+ maybe = JSReceiver::HasOwnProperty(obj, s2);
+ CHECK(maybe.has_value);
+ CHECK(maybe.value);
}
@@ -722,18 +728,15 @@ TEST(JSObjectMaps) {
v8::HandleScope sc(CcTest::isolate());
Handle<String> name = factory->InternalizeUtf8String("theFunction");
- Handle<JSFunction> function = factory->NewFunctionWithPrototype(
- name, factory->undefined_value());
- Handle<Map> initial_map =
- factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
- function->set_initial_map(*initial_map);
+ Handle<JSFunction> function = factory->NewFunction(name);
Handle<String> prop_name = factory->InternalizeUtf8String("theSlot");
Handle<JSObject> obj = factory->NewJSObject(function);
+ Handle<Map> initial_map(function->initial_map());
// Set a propery
Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
- JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, prop_name, twenty_three, SLOPPY).Check();
CHECK_EQ(Smi::FromInt(23),
*Object::GetProperty(obj, prop_name).ToHandleChecked());
@@ -811,8 +814,8 @@ TEST(JSObjectCopy) {
Handle<Smi> one(Smi::FromInt(1), isolate);
Handle<Smi> two(Smi::FromInt(2), isolate);
- JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY).Check();
- JSReceiver::SetProperty(obj, second, two, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
+ JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
JSReceiver::SetElement(obj, 0, first, NONE, SLOPPY).Check();
JSReceiver::SetElement(obj, 1, second, NONE, SLOPPY).Check();
@@ -837,8 +840,8 @@ TEST(JSObjectCopy) {
CHECK_EQ(*value1, *value2);
// Flip the values.
- JSReceiver::SetProperty(clone, first, two, NONE, SLOPPY).Check();
- JSReceiver::SetProperty(clone, second, one, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(clone, first, two, SLOPPY).Check();
+ JSReceiver::SetProperty(clone, second, one, SLOPPY).Check();
JSReceiver::SetElement(clone, 0, second, NONE, SLOPPY).Check();
JSReceiver::SetElement(clone, 1, first, NONE, SLOPPY).Check();
@@ -901,7 +904,6 @@ TEST(StringAllocation) {
static int ObjectsFoundInHeap(Heap* heap, Handle<Object> objs[], int size) {
// Count the number of objects found in the heap.
int found_count = 0;
- heap->EnsureHeapIsIterable();
HeapIterator iterator(heap);
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
for (int i = 0; i < size; i++) {
@@ -1030,7 +1032,9 @@ TEST(Regression39128) {
CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
CHECK_EQ(0, jsobject->properties()->length());
// Create a reference to object in new space in jsobject.
- jsobject->FastPropertyAtPut(-1, array);
+ FieldIndex index = FieldIndex::ForInObjectOffset(
+ JSObject::kHeaderSize - kPointerSize);
+ jsobject->FastPropertyAtPut(index, array);
CHECK_EQ(0, static_cast<int>(*limit_addr - *top_addr));
@@ -1200,7 +1204,7 @@ TEST(TestCodeFlushingIncremental) {
// Simulate several GCs that use incremental marking.
const int kAgingThreshold = 6;
for (int i = 0; i < kAgingThreshold; i++) {
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
}
CHECK(!function->shared()->is_compiled() || function->IsOptimized());
@@ -1214,7 +1218,7 @@ TEST(TestCodeFlushingIncremental) {
// Simulate several GCs that use incremental marking but make sure
// the loop breaks once the function is enqueued as a candidate.
for (int i = 0; i < kAgingThreshold; i++) {
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(CcTest::heap());
if (!function->next_function_link()->IsUndefined()) break;
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
}
@@ -1290,7 +1294,7 @@ TEST(TestCodeFlushingIncrementalScavenge) {
// Simulate incremental marking so that the functions are enqueued as
// code flushing candidates. Then kill one of the functions. Finally
// perform a scavenge while incremental marking is still running.
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(CcTest::heap());
*function2.location() = NULL;
CcTest::heap()->CollectGarbage(NEW_SPACE, "test scavenge while marking");
@@ -1344,7 +1348,7 @@ TEST(TestCodeFlushingIncrementalAbort) {
// Simulate incremental marking so that the function is enqueued as
// code flushing candidate.
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(heap);
// Enable the debugger and add a breakpoint while incremental marking
// is running so that incremental marking aborts and code flushing is
@@ -1604,8 +1608,8 @@ TEST(TestSizeOfObjects) {
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
MarkCompactCollector* collector = CcTest::heap()->mark_compact_collector();
- if (collector->IsConcurrentSweepingInProgress()) {
- collector->WaitUntilSweepingCompleted();
+ if (collector->sweeping_in_progress()) {
+ collector->EnsureSweepingCompleted();
}
int initial_size = static_cast<int>(CcTest::heap()->SizeOfObjects());
@@ -1631,8 +1635,8 @@ TEST(TestSizeOfObjects) {
CHECK_EQ(initial_size, static_cast<int>(CcTest::heap()->SizeOfObjects()));
// Waiting for sweeper threads should not change heap size.
- if (collector->IsConcurrentSweepingInProgress()) {
- collector->WaitUntilSweepingCompleted();
+ if (collector->sweeping_in_progress()) {
+ collector->EnsureSweepingCompleted();
}
CHECK_EQ(initial_size, static_cast<int>(CcTest::heap()->SizeOfObjects()));
}
@@ -1640,9 +1644,8 @@ TEST(TestSizeOfObjects) {
TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
CcTest::InitializeVM();
- CcTest::heap()->EnsureHeapIsIterable();
- intptr_t size_of_objects_1 = CcTest::heap()->SizeOfObjects();
HeapIterator iterator(CcTest::heap());
+ intptr_t size_of_objects_1 = CcTest::heap()->SizeOfObjects();
intptr_t size_of_objects_2 = 0;
for (HeapObject* obj = iterator.next();
obj != NULL;
@@ -1811,7 +1814,7 @@ TEST(LeakNativeContextViaMap) {
ctx2->Exit();
v8::Local<v8::Context>::New(isolate, ctx1)->Exit();
ctx1p.Reset();
- v8::V8::ContextDisposedNotification();
+ isolate->ContextDisposedNotification();
}
CcTest::heap()->CollectAllAvailableGarbage();
CHECK_EQ(2, NumberOfGlobalObjects());
@@ -1857,7 +1860,7 @@ TEST(LeakNativeContextViaFunction) {
ctx2->Exit();
ctx1->Exit();
ctx1p.Reset();
- v8::V8::ContextDisposedNotification();
+ isolate->ContextDisposedNotification();
}
CcTest::heap()->CollectAllAvailableGarbage();
CHECK_EQ(2, NumberOfGlobalObjects());
@@ -1901,7 +1904,7 @@ TEST(LeakNativeContextViaMapKeyed) {
ctx2->Exit();
ctx1->Exit();
ctx1p.Reset();
- v8::V8::ContextDisposedNotification();
+ isolate->ContextDisposedNotification();
}
CcTest::heap()->CollectAllAvailableGarbage();
CHECK_EQ(2, NumberOfGlobalObjects());
@@ -1949,7 +1952,7 @@ TEST(LeakNativeContextViaMapProto) {
ctx2->Exit();
ctx1->Exit();
ctx1p.Reset();
- v8::V8::ContextDisposedNotification();
+ isolate->ContextDisposedNotification();
}
CcTest::heap()->CollectAllAvailableGarbage();
CHECK_EQ(2, NumberOfGlobalObjects());
@@ -2110,8 +2113,8 @@ TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) {
// The following two calls will increment CcTest::heap()->global_ic_age().
const int kLongIdlePauseInMs = 1000;
- v8::V8::ContextDisposedNotification();
- v8::V8::IdleNotification(kLongIdlePauseInMs);
+ CcTest::isolate()->ContextDisposedNotification();
+ CcTest::isolate()->IdleNotification(kLongIdlePauseInMs);
while (!marking->IsStopped() && !marking->IsComplete()) {
marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
@@ -2166,8 +2169,8 @@ TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) {
// The following two calls will increment CcTest::heap()->global_ic_age().
// Since incremental marking is off, IdleNotification will do full GC.
const int kLongIdlePauseInMs = 1000;
- v8::V8::ContextDisposedNotification();
- v8::V8::IdleNotification(kLongIdlePauseInMs);
+ CcTest::isolate()->ContextDisposedNotification();
+ CcTest::isolate()->IdleNotification(kLongIdlePauseInMs);
CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
CHECK_EQ(0, f->shared()->opt_count());
@@ -2207,100 +2210,70 @@ TEST(OptimizedAllocationAlwaysInNewSpace) {
TEST(OptimizedPretenuringAllocationFolding) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
- i::FLAG_allocation_site_pretenuring = false;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- CcTest::heap()->SetNewSpaceHighPromotionModeActive(true);
- v8::Local<v8::Value> res = CompileRun(
- "function DataObject() {"
- " this.a = 1.1;"
- " this.b = [{}];"
- " this.c = 1.2;"
- " this.d = [{}];"
- " this.e = 1.3;"
- " this.f = [{}];"
- "}"
- "var number_elements = 20000;"
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+ i::ScopedVector<char> source(1024);
+ i::SNPrintF(
+ source,
+ "var number_elements = %d;"
"var elements = new Array();"
"function f() {"
" for (var i = 0; i < number_elements; i++) {"
- " elements[i] = new DataObject();"
+ " elements[i] = [[{}], [1.1]];"
" }"
" return elements[number_elements-1]"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
-
- Handle<JSObject> o =
- v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
-
- CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(0)));
- CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(1)));
- CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(2)));
- CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(3)));
- CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(4)));
- CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(5)));
-}
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
+ "f();",
+ AllocationSite::kPretenureMinimumCreated);
+ v8::Local<v8::Value> res = CompileRun(source.start());
-TEST(OptimizedPretenuringAllocationFoldingBlocks) {
- i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
- i::FLAG_allocation_site_pretenuring = false;
- CcTest::InitializeVM();
- if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
- if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
- v8::HandleScope scope(CcTest::isolate());
- CcTest::heap()->SetNewSpaceHighPromotionModeActive(true);
-
- v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 30000;"
- "var elements = new Array(number_elements);"
- "function DataObject() {"
- " this.a = [{}];"
- " this.b = [{}];"
- " this.c = 1.1;"
- " this.d = 1.2;"
- " this.e = [{}];"
- " this.f = 1.3;"
- "}"
- "function f() {"
- " for (var i = 0; i < number_elements; i++) {"
- " elements[i] = new DataObject();"
- " }"
- " return elements[number_elements - 1];"
- "};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
+ v8::Local<v8::Value> int_array = v8::Object::Cast(*res)->Get(v8_str("0"));
+ Handle<JSObject> int_array_handle =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(int_array));
+ v8::Local<v8::Value> double_array = v8::Object::Cast(*res)->Get(v8_str("1"));
+ Handle<JSObject> double_array_handle =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(double_array));
Handle<JSObject> o =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
-
- CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(0)));
- CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(1)));
- CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(2)));
- CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(3)));
- CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(4)));
- CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(5)));
+ CHECK(CcTest::heap()->InOldPointerSpace(*o));
+ CHECK(CcTest::heap()->InOldPointerSpace(*int_array_handle));
+ CHECK(CcTest::heap()->InOldPointerSpace(int_array_handle->elements()));
+ CHECK(CcTest::heap()->InOldPointerSpace(*double_array_handle));
+ CHECK(CcTest::heap()->InOldDataSpace(double_array_handle->elements()));
}
TEST(OptimizedPretenuringObjectArrayLiterals) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 20000;"
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+ i::ScopedVector<char> source(1024);
+ i::SNPrintF(
+ source,
+ "var number_elements = %d;"
"var elements = new Array(number_elements);"
"function f() {"
" for (var i = 0; i < number_elements; i++) {"
@@ -2308,9 +2281,13 @@ TEST(OptimizedPretenuringObjectArrayLiterals) {
" }"
" return elements[number_elements - 1];"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
+ "f();",
+ AllocationSite::kPretenureMinimumCreated);
+
+ v8::Local<v8::Value> res = CompileRun(source.start());
Handle<JSObject> o =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
@@ -2322,14 +2299,22 @@ TEST(OptimizedPretenuringObjectArrayLiterals) {
TEST(OptimizedPretenuringMixedInObjectProperties) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 20000;"
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+
+ i::ScopedVector<char> source(1024);
+ i::SNPrintF(
+ source,
+ "var number_elements = %d;"
"var elements = new Array(number_elements);"
"function f() {"
" for (var i = 0; i < number_elements; i++) {"
@@ -2337,34 +2322,49 @@ TEST(OptimizedPretenuringMixedInObjectProperties) {
" }"
" return elements[number_elements - 1];"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
+ "f();",
+ AllocationSite::kPretenureMinimumCreated);
+
+ v8::Local<v8::Value> res = CompileRun(source.start());
Handle<JSObject> o =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
CHECK(CcTest::heap()->InOldPointerSpace(*o));
- CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(0)));
- CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(1)));
+ FieldIndex idx1 = FieldIndex::ForPropertyIndex(o->map(), 0);
+ FieldIndex idx2 = FieldIndex::ForPropertyIndex(o->map(), 1);
+ CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(idx1)));
+ CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(idx2)));
- JSObject* inner_object = reinterpret_cast<JSObject*>(o->RawFastPropertyAt(0));
+ JSObject* inner_object =
+ reinterpret_cast<JSObject*>(o->RawFastPropertyAt(idx1));
CHECK(CcTest::heap()->InOldPointerSpace(inner_object));
- CHECK(CcTest::heap()->InOldDataSpace(inner_object->RawFastPropertyAt(0)));
- CHECK(CcTest::heap()->InOldPointerSpace(inner_object->RawFastPropertyAt(1)));
+ CHECK(CcTest::heap()->InOldDataSpace(inner_object->RawFastPropertyAt(idx1)));
+ CHECK(CcTest::heap()->InOldPointerSpace(
+ inner_object->RawFastPropertyAt(idx2)));
}
TEST(OptimizedPretenuringDoubleArrayProperties) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 30000;"
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+ i::ScopedVector<char> source(1024);
+ i::SNPrintF(
+ source,
+ "var number_elements = %d;"
"var elements = new Array(number_elements);"
"function f() {"
" for (var i = 0; i < number_elements; i++) {"
@@ -2372,9 +2372,13 @@ TEST(OptimizedPretenuringDoubleArrayProperties) {
" }"
" return elements[i - 1];"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
+ "f();",
+ AllocationSite::kPretenureMinimumCreated);
+
+ v8::Local<v8::Value> res = CompileRun(source.start());
Handle<JSObject> o =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
@@ -2386,14 +2390,21 @@ TEST(OptimizedPretenuringDoubleArrayProperties) {
TEST(OptimizedPretenuringdoubleArrayLiterals) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 30000;"
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+ i::ScopedVector<char> source(1024);
+ i::SNPrintF(
+ source,
+ "var number_elements = %d;"
"var elements = new Array(number_elements);"
"function f() {"
" for (var i = 0; i < number_elements; i++) {"
@@ -2401,9 +2412,13 @@ TEST(OptimizedPretenuringdoubleArrayLiterals) {
" }"
" return elements[number_elements - 1];"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
+ "f();",
+ AllocationSite::kPretenureMinimumCreated);
+
+ v8::Local<v8::Value> res = CompileRun(source.start());
Handle<JSObject> o =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
@@ -2415,14 +2430,21 @@ TEST(OptimizedPretenuringdoubleArrayLiterals) {
TEST(OptimizedPretenuringNestedMixedArrayLiterals) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 20000;"
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+ i::ScopedVector<char> source(1024);
+ i::SNPrintF(
+ source,
+ "var number_elements = 100;"
"var elements = new Array(number_elements);"
"function f() {"
" for (var i = 0; i < number_elements; i++) {"
@@ -2430,10 +2452,13 @@ TEST(OptimizedPretenuringNestedMixedArrayLiterals) {
" }"
" return elements[number_elements - 1];"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
"f();");
+ v8::Local<v8::Value> res = CompileRun(source.start());
+
v8::Local<v8::Value> int_array = v8::Object::Cast(*res)->Get(v8_str("0"));
Handle<JSObject> int_array_handle =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(int_array));
@@ -2453,14 +2478,21 @@ TEST(OptimizedPretenuringNestedMixedArrayLiterals) {
TEST(OptimizedPretenuringNestedObjectLiterals) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 20000;"
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+ i::ScopedVector<char> source(1024);
+ i::SNPrintF(
+ source,
+ "var number_elements = %d;"
"var elements = new Array(number_elements);"
"function f() {"
" for (var i = 0; i < number_elements; i++) {"
@@ -2468,9 +2500,13 @@ TEST(OptimizedPretenuringNestedObjectLiterals) {
" }"
" return elements[number_elements - 1];"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
+ "f();",
+ AllocationSite::kPretenureMinimumCreated);
+
+ v8::Local<v8::Value> res = CompileRun(source.start());
v8::Local<v8::Value> int_array_1 = v8::Object::Cast(*res)->Get(v8_str("0"));
Handle<JSObject> int_array_handle_1 =
@@ -2491,14 +2527,21 @@ TEST(OptimizedPretenuringNestedObjectLiterals) {
TEST(OptimizedPretenuringNestedDoubleLiterals) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 20000;"
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+ i::ScopedVector<char> source(1024);
+ i::SNPrintF(
+ source,
+ "var number_elements = %d;"
"var elements = new Array(number_elements);"
"function f() {"
" for (var i = 0; i < number_elements; i++) {"
@@ -2506,9 +2549,13 @@ TEST(OptimizedPretenuringNestedDoubleLiterals) {
" }"
" return elements[number_elements - 1];"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
+ "f();",
+ AllocationSite::kPretenureMinimumCreated);
+
+ v8::Local<v8::Value> res = CompileRun(source.start());
v8::Local<v8::Value> double_array_1 =
v8::Object::Cast(*res)->Get(v8_str("0"));
@@ -2532,19 +2579,29 @@ TEST(OptimizedPretenuringNestedDoubleLiterals) {
// Make sure pretenuring feedback is gathered for constructed objects as well
// as for literals.
TEST(OptimizedPretenuringConstructorCalls) {
- if (!FLAG_allocation_site_pretenuring || !i::FLAG_pretenuring_call_new) {
+ if (!i::FLAG_pretenuring_call_new) {
// FLAG_pretenuring_call_new needs to be synced with the snapshot.
return;
}
i::FLAG_allow_natives_syntax = true;
- i::FLAG_max_new_space_size = 2;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 20000;"
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+ i::ScopedVector<char> source(1024);
+ // Call new is doing slack tracking for the first
+ // JSFunction::kGenerousAllocationCount allocations, and we can't find
+ // mementos during that time.
+ i::SNPrintF(
+ source,
+ "var number_elements = %d;"
"var elements = new Array(number_elements);"
"function foo() {"
" this.a = 3;"
@@ -2556,9 +2613,14 @@ TEST(OptimizedPretenuringConstructorCalls) {
" }"
" return elements[number_elements - 1];"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
+ "f();",
+ AllocationSite::kPretenureMinimumCreated +
+ JSFunction::kGenerousAllocationCount);
+
+ v8::Local<v8::Value> res = CompileRun(source.start());
Handle<JSObject> o =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
@@ -2567,57 +2629,77 @@ TEST(OptimizedPretenuringConstructorCalls) {
}
-// Test regular array literals allocation.
-TEST(OptimizedAllocationArrayLiterals) {
+TEST(OptimizedPretenuringCallNew) {
+ if (!i::FLAG_pretenuring_call_new) {
+ // FLAG_pretenuring_call_new needs to be synced with the snapshot.
+ return;
+ }
i::FLAG_allow_natives_syntax = true;
+ i::FLAG_expose_gc = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Value> res = CompileRun(
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+ i::ScopedVector<char> source(1024);
+ // Call new is doing slack tracking for the first
+ // JSFunction::kGenerousAllocationCount allocations, and we can't find
+ // mementos during that time.
+ i::SNPrintF(
+ source,
+ "var number_elements = %d;"
+ "var elements = new Array(number_elements);"
+ "function g() { this.a = 0; }"
"function f() {"
- " var numbers = new Array(1, 2, 3);"
- " numbers[0] = 3.14;"
- " return numbers;"
+ " for (var i = 0; i < number_elements; i++) {"
+ " elements[i] = new g();"
+ " }"
+ " return elements[number_elements - 1];"
"};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
- CHECK_EQ(static_cast<int>(3.14),
- v8::Object::Cast(*res)->Get(v8_str("0"))->Int32Value());
+ "f(); gc();"
+ "f(); f();"
+ "%%OptimizeFunctionOnNextCall(f);"
+ "f();",
+ AllocationSite::kPretenureMinimumCreated +
+ JSFunction::kGenerousAllocationCount);
+
+ v8::Local<v8::Value> res = CompileRun(source.start());
Handle<JSObject> o =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
-
- CHECK(CcTest::heap()->InNewSpace(o->elements()));
+ CHECK(CcTest::heap()->InOldPointerSpace(*o));
}
-// Test global pretenuring call new.
-TEST(OptimizedPretenuringCallNew) {
+// Test regular array literals allocation.
+TEST(OptimizedAllocationArrayLiterals) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_allocation_site_pretenuring = false;
- i::FLAG_pretenuring_call_new = true;
CcTest::InitializeVM();
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- CcTest::heap()->SetNewSpaceHighPromotionModeActive(true);
- AlwaysAllocateScope always_allocate(CcTest::i_isolate());
v8::Local<v8::Value> res = CompileRun(
- "function g() { this.a = 0; }"
"function f() {"
- " return new g();"
+ " var numbers = new Array(1, 2, 3);"
+ " numbers[0] = 3.14;"
+ " return numbers;"
"};"
"f(); f(); f();"
"%OptimizeFunctionOnNextCall(f);"
"f();");
+ CHECK_EQ(static_cast<int>(3.14),
+ v8::Object::Cast(*res)->Get(v8_str("0"))->Int32Value());
Handle<JSObject> o =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
- CHECK(CcTest::heap()->InOldPointerSpace(*o));
+
+ CHECK(CcTest::heap()->InNewSpace(o->elements()));
}
@@ -2641,7 +2723,7 @@ TEST(Regress1465) {
AlwaysAllocateScope always_allocate(CcTest::i_isolate());
for (int i = 0; i < transitions_count; i++) {
EmbeddedVector<char, 64> buffer;
- OS::SNPrintF(buffer, "var o = new F; o.prop%d = %d;", i, i);
+ SNPrintF(buffer, "var o = new F; o.prop%d = %d;", i, i);
CompileRun(buffer.start());
}
CompileRun("var root = new F;");
@@ -2657,7 +2739,7 @@ TEST(Regress1465) {
CompileRun("%DebugPrint(root);");
CHECK_EQ(transitions_count, transitions_before);
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
// Count number of live transitions after marking. Note that one transition
@@ -2673,7 +2755,7 @@ static void AddTransitions(int transitions_count) {
AlwaysAllocateScope always_allocate(CcTest::i_isolate());
for (int i = 0; i < transitions_count; i++) {
EmbeddedVector<char, 64> buffer;
- OS::SNPrintF(buffer, "var o = new F; o.prop%d = %d;", i, i);
+ SNPrintF(buffer, "var o = new F; o.prop%d = %d;", i, i);
CompileRun(buffer.start());
}
}
@@ -2695,8 +2777,7 @@ static void AddPropertyTo(
i::FLAG_gc_interval = gc_count;
i::FLAG_gc_global = true;
CcTest::heap()->set_allocation_timeout(gc_count);
- JSReceiver::SetProperty(
- object, prop_name, twenty_three, NONE, SLOPPY).Check();
+ JSReceiver::SetProperty(object, prop_name, twenty_three, SLOPPY).Check();
}
@@ -2799,7 +2880,7 @@ TEST(TransitionArraySimpleToFull) {
CompileRun("o = new F;"
"root = new F");
root = GetByName("root");
- ASSERT(root->map()->transitions()->IsSimpleTransition());
+ DCHECK(root->map()->transitions()->IsSimpleTransition());
AddPropertyTo(2, root, "happy");
// Count number of live transitions after marking. Note that one transition
@@ -2823,7 +2904,7 @@ TEST(Regress2143a) {
"root.foo = 0;"
"root = new Object;");
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(CcTest::heap());
// Compile a StoreIC that performs the prepared map transition. This
// will restart incremental marking and should make sure the root is
@@ -2864,7 +2945,7 @@ TEST(Regress2143b) {
"root.foo = 0;"
"root = new Object;");
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(CcTest::heap());
// Compile an optimized LStoreNamedField that performs the prepared
// map transition. This will restart incremental marking and should
@@ -2920,7 +3001,8 @@ TEST(ReleaseOverReservedPages) {
// Triggering one GC will cause a lot of garbage to be discovered but
// even spread across all allocated pages.
- heap->CollectAllGarbage(Heap::kNoGCFlags, "triggered for preparation");
+ heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask,
+ "triggered for preparation");
CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages());
// Triggering subsequent GCs should cause at least half of the pages
@@ -2986,8 +3068,9 @@ TEST(PrintSharedFunctionInfo) {
*v8::Handle<v8::Function>::Cast(
CcTest::global()->Get(v8_str("g"))));
- DisallowHeapAllocation no_allocation;
- g->shared()->PrintLn();
+ OFStream os(stdout);
+ g->shared()->Print(os);
+ os << endl;
}
#endif // OBJECT_PRINT
@@ -3018,9 +3101,9 @@ TEST(Regress2211) {
CHECK(value->Equals(obj->GetHiddenValue(v8_str("key string"))));
// Check size.
- DescriptorArray* descriptors = internal_obj->map()->instance_descriptors();
+ FieldIndex index = FieldIndex::ForDescriptor(internal_obj->map(), 0);
ObjectHashTable* hashtable = ObjectHashTable::cast(
- internal_obj->RawFastPropertyAt(descriptors->GetFieldIndex(0)));
+ internal_obj->RawFastPropertyAt(index));
// HashTable header (5) and 4 initial entries (8).
CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize);
}
@@ -3058,18 +3141,22 @@ TEST(IncrementalMarkingClearsTypeFeedbackInfo) {
Handle<FixedArray> feedback_vector(f->shared()->feedback_vector());
- CHECK_EQ(2, feedback_vector->length());
- CHECK(feedback_vector->get(0)->IsJSFunction());
- CHECK(feedback_vector->get(1)->IsJSFunction());
+ int expected_length = FLAG_vector_ics ? 4 : 2;
+ CHECK_EQ(expected_length, feedback_vector->length());
+ for (int i = 0; i < expected_length; i++) {
+ if ((i % 2) == 1) {
+ CHECK(feedback_vector->get(i)->IsJSFunction());
+ }
+ }
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
- CHECK_EQ(2, feedback_vector->length());
- CHECK_EQ(feedback_vector->get(0),
- *TypeFeedbackInfo::UninitializedSentinel(CcTest::i_isolate()));
- CHECK_EQ(feedback_vector->get(1),
- *TypeFeedbackInfo::UninitializedSentinel(CcTest::i_isolate()));
+ CHECK_EQ(expected_length, feedback_vector->length());
+ for (int i = 0; i < expected_length; i++) {
+ CHECK_EQ(feedback_vector->get(i),
+ *TypeFeedbackInfo::UninitializedSentinel(CcTest::i_isolate()));
+ }
}
@@ -3105,7 +3192,7 @@ TEST(IncrementalMarkingPreservesMonomorphicIC) {
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
CHECK(ic_before->ic_state() == MONOMORPHIC);
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
@@ -3138,8 +3225,8 @@ TEST(IncrementalMarkingClearsMonomorphicIC) {
CHECK(ic_before->ic_state() == MONOMORPHIC);
// Fire context dispose notification.
- v8::V8::ContextDisposedNotification();
- SimulateIncrementalMarking();
+ CcTest::isolate()->ContextDisposedNotification();
+ SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
@@ -3179,8 +3266,8 @@ TEST(IncrementalMarkingClearsPolymorphicIC) {
CHECK(ic_before->ic_state() == POLYMORPHIC);
// Fire context dispose notification.
- v8::V8::ContextDisposedNotification();
- SimulateIncrementalMarking();
+ CcTest::isolate()->ContextDisposedNotification();
+ SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
@@ -3341,7 +3428,7 @@ TEST(Regress159140) {
// Simulate incremental marking so that the functions are enqueued as
// code flushing candidates. Then optimize one function. Finally
// finish the GC to complete code flushing.
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(heap);
CompileRun("%OptimizeFunctionOnNextCall(g); g(3);");
heap->CollectAllGarbage(Heap::kNoGCFlags);
@@ -3388,7 +3475,7 @@ TEST(Regress165495) {
// Simulate incremental marking so that unoptimized code is flushed
// even though it still is cached in the optimized code map.
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(heap);
heap->CollectAllGarbage(Heap::kNoGCFlags);
// Make a new closure that will get code installed from the code map.
@@ -3456,7 +3543,7 @@ TEST(Regress169209) {
}
// Simulate incremental marking and collect code flushing candidates.
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(heap);
CHECK(shared1->code()->gc_metadata() != NULL);
// Optimize function and make sure the unoptimized code is replaced.
@@ -3602,7 +3689,7 @@ TEST(Regress168801) {
// Simulate incremental marking so that unoptimized function is enqueued as a
// candidate for code flushing. The shared function info however will not be
// explicitly enqueued.
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(heap);
// Now optimize the function so that it is taken off the candidate list.
{
@@ -3659,7 +3746,7 @@ TEST(Regress173458) {
// Simulate incremental marking so that unoptimized function is enqueued as a
// candidate for code flushing. The shared function info however will not be
// explicitly enqueued.
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(heap);
// Now enable the debugger which in turn will disable code flushing.
CHECK(isolate->debug()->Load());
@@ -3688,7 +3775,7 @@ TEST(DeferredHandles) {
}
// An entire block of handles has been filled.
// Next handle would require a new block.
- ASSERT(data->next == data->limit);
+ DCHECK(data->next == data->limit);
DeferredHandleScope deferred(isolate);
DummyVisitor visitor;
@@ -3709,7 +3796,7 @@ TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) {
if (marking->IsStopped()) marking->Start();
// This big step should be sufficient to mark the whole array.
marking->Step(100 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
- ASSERT(marking->IsComplete());
+ DCHECK(marking->IsComplete());
}
@@ -3736,10 +3823,6 @@ TEST(DisableInlineAllocation) {
CcTest::heap()->DisableInlineAllocation();
CompileRun("run()");
- // Run test with inline allocation disabled and pretenuring.
- CcTest::heap()->SetNewSpaceHighPromotionModeActive(true);
- CompileRun("run()");
-
// Run test with inline allocation re-enabled.
CcTest::heap()->EnableInlineAllocation();
CompileRun("run()");
@@ -3803,7 +3886,7 @@ TEST(EnsureAllocationSiteDependentCodesProcessed) {
// Now make sure that a gc should get rid of the function, even though we
// still have the allocation site alive.
for (int i = 0; i < 4; i++) {
- heap->CollectAllGarbage(false);
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
}
// The site still exists because of our global handle, but the code is no
@@ -3853,7 +3936,7 @@ TEST(CellsInOptimizedCodeAreWeak) {
heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
}
- ASSERT(code->marked_for_deoptimization());
+ DCHECK(code->marked_for_deoptimization());
}
@@ -3894,7 +3977,7 @@ TEST(ObjectsInOptimizedCodeAreWeak) {
heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
}
- ASSERT(code->marked_for_deoptimization());
+ DCHECK(code->marked_for_deoptimization());
}
@@ -3911,37 +3994,41 @@ TEST(NoWeakHashTableLeakWithIncrementalMarking) {
if (!isolate->use_crankshaft()) return;
HandleScope outer_scope(heap->isolate());
for (int i = 0; i < 3; i++) {
- SimulateIncrementalMarking();
+ SimulateIncrementalMarking(heap);
{
LocalContext context;
HandleScope scope(heap->isolate());
EmbeddedVector<char, 256> source;
- OS::SNPrintF(source,
- "function bar%d() {"
- " return foo%d(1);"
- "};"
- "function foo%d(x) { with (x) { return 1 + x; } };"
- "bar%d();"
- "bar%d();"
- "bar%d();"
- "%OptimizeFunctionOnNextCall(bar%d);"
- "bar%d();", i, i, i, i, i, i, i, i);
+ SNPrintF(source,
+ "function bar%d() {"
+ " return foo%d(1);"
+ "};"
+ "function foo%d(x) { with (x) { return 1 + x; } };"
+ "bar%d();"
+ "bar%d();"
+ "bar%d();"
+ "%%OptimizeFunctionOnNextCall(bar%d);"
+ "bar%d();", i, i, i, i, i, i, i, i);
CompileRun(source.start());
}
heap->CollectAllGarbage(i::Heap::kNoGCFlags);
}
- WeakHashTable* table = WeakHashTable::cast(heap->weak_object_to_code_table());
- CHECK_EQ(0, table->NumberOfElements());
+ int elements = 0;
+ if (heap->weak_object_to_code_table()->IsHashTable()) {
+ WeakHashTable* t = WeakHashTable::cast(heap->weak_object_to_code_table());
+ elements = t->NumberOfElements();
+ }
+ CHECK_EQ(0, elements);
}
static Handle<JSFunction> OptimizeDummyFunction(const char* name) {
EmbeddedVector<char, 256> source;
- OS::SNPrintF(source,
- "function %s() { return 0; }"
- "%s(); %s();"
- "%%OptimizeFunctionOnNextCall(%s);"
- "%s();", name, name, name, name, name);
+ SNPrintF(source,
+ "function %s() { return 0; }"
+ "%s(); %s();"
+ "%%OptimizeFunctionOnNextCall(%s);"
+ "%s();", name, name, name, name, name);
CompileRun(source.start());
Handle<JSFunction> fun =
v8::Utils::OpenHandle(
@@ -3993,7 +4080,8 @@ static Handle<Code> DummyOptimizedCode(Isolate* isolate) {
i::byte buffer[i::Assembler::kMinimalBufferSize];
MacroAssembler masm(isolate, buffer, sizeof(buffer));
CodeDesc desc;
- masm.Prologue(BUILD_FUNCTION_FRAME);
+ masm.Push(isolate->factory()->undefined_value());
+ masm.Drop(1);
masm.GetCode(&desc);
Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
Handle<Code> code = isolate->factory()->NewCode(
@@ -4221,7 +4309,7 @@ TEST(Regress357137) {
global->Set(v8::String::NewFromUtf8(isolate, "interrupt"),
v8::FunctionTemplate::New(isolate, RequestInterrupt));
v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
- ASSERT(!context.IsEmpty());
+ DCHECK(!context.IsEmpty());
v8::Context::Scope cscope(context);
v8::Local<v8::Value> result = CompileRun(
@@ -4246,6 +4334,7 @@ TEST(ArrayShiftSweeping) {
"var tmp = new Array(100000);"
"array[0] = 10;"
"gc();"
+ "gc();"
"array.shift();"
"array;");
@@ -4254,6 +4343,145 @@ TEST(ArrayShiftSweeping) {
CHECK(heap->InOldPointerSpace(o->elements()));
CHECK(heap->InOldPointerSpace(*o));
Page* page = Page::FromAddress(o->elements()->address());
- CHECK(page->WasSwept() ||
+ CHECK(page->parallel_sweeping() <= MemoryChunk::SWEEPING_FINALIZE ||
Marking::IsBlack(Marking::MarkBitFrom(o->elements())));
}
+
+
+TEST(PromotionQueue) {
+ i::FLAG_expose_gc = true;
+ i::FLAG_max_semi_space_size = 2;
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+ Isolate* isolate = CcTest::i_isolate();
+ Heap* heap = isolate->heap();
+ NewSpace* new_space = heap->new_space();
+
+ // In this test we will try to overwrite the promotion queue which is at the
+ // end of to-space. To actually make that possible, we need at least two
+ // semi-space pages and take advantage of fragementation.
+ // (1) Grow semi-space to two pages.
+ // (2) Create a few small long living objects and call the scavenger to
+ // move them to the other semi-space.
+ // (3) Create a huge object, i.e., remainder of first semi-space page and
+ // create another huge object which should be of maximum allocatable memory
+ // size of the second semi-space page.
+ // (4) Call the scavenger again.
+ // What will happen is: the scavenger will promote the objects created in (2)
+ // and will create promotion queue entries at the end of the second
+ // semi-space page during the next scavenge when it promotes the objects to
+ // the old generation. The first allocation of (3) will fill up the first
+ // semi-space page. The second allocation in (3) will not fit into the first
+ // semi-space page, but it will overwrite the promotion queue which are in
+ // the second semi-space page. If the right guards are in place, the promotion
+ // queue will be evacuated in that case.
+
+ // Grow the semi-space to two pages to make semi-space copy overwrite the
+ // promotion queue, which will be at the end of the second page.
+ intptr_t old_capacity = new_space->Capacity();
+ new_space->Grow();
+ CHECK(new_space->IsAtMaximumCapacity());
+ CHECK(2 * old_capacity == new_space->Capacity());
+
+ // Call the scavenger two times to get an empty new space
+ heap->CollectGarbage(NEW_SPACE);
+ heap->CollectGarbage(NEW_SPACE);
+
+ // First create a few objects which will survive a scavenge, and will get
+ // promoted to the old generation later on. These objects will create
+ // promotion queue entries at the end of the second semi-space page.
+ const int number_handles = 12;
+ Handle<FixedArray> handles[number_handles];
+ for (int i = 0; i < number_handles; i++) {
+ handles[i] = isolate->factory()->NewFixedArray(1, NOT_TENURED);
+ }
+ heap->CollectGarbage(NEW_SPACE);
+
+ // Create the first huge object which will exactly fit the first semi-space
+ // page.
+ int new_linear_size = static_cast<int>(
+ *heap->new_space()->allocation_limit_address() -
+ *heap->new_space()->allocation_top_address());
+ int length = new_linear_size / kPointerSize - FixedArray::kHeaderSize;
+ Handle<FixedArray> first =
+ isolate->factory()->NewFixedArray(length, NOT_TENURED);
+ CHECK(heap->InNewSpace(*first));
+
+ // Create the second huge object of maximum allocatable second semi-space
+ // page size.
+ new_linear_size = static_cast<int>(
+ *heap->new_space()->allocation_limit_address() -
+ *heap->new_space()->allocation_top_address());
+ length = Page::kMaxRegularHeapObjectSize / kPointerSize -
+ FixedArray::kHeaderSize;
+ Handle<FixedArray> second =
+ isolate->factory()->NewFixedArray(length, NOT_TENURED);
+ CHECK(heap->InNewSpace(*second));
+
+ // This scavenge will corrupt memory if the promotion queue is not evacuated.
+ heap->CollectGarbage(NEW_SPACE);
+}
+
+
+TEST(Regress388880) {
+ i::FLAG_expose_gc = true;
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+ Isolate* isolate = CcTest::i_isolate();
+ Factory* factory = isolate->factory();
+ Heap* heap = isolate->heap();
+
+ Handle<Map> map1 = Map::Create(isolate->object_function(), 1);
+ Handle<Map> map2 =
+ Map::CopyWithField(map1, factory->NewStringFromStaticAscii("foo"),
+ HeapType::Any(isolate), NONE, Representation::Tagged(),
+ OMIT_TRANSITION).ToHandleChecked();
+
+ int desired_offset = Page::kPageSize - map1->instance_size();
+
+ // Allocate fixed array in old pointer space so, that object allocated
+ // afterwards would end at the end of the page.
+ {
+ SimulateFullSpace(heap->old_pointer_space());
+ int padding_size = desired_offset - Page::kObjectStartOffset;
+ int padding_array_length =
+ (padding_size - FixedArray::kHeaderSize) / kPointerSize;
+
+ Handle<FixedArray> temp2 =
+ factory->NewFixedArray(padding_array_length, TENURED);
+ Page* page = Page::FromAddress(temp2->address());
+ CHECK_EQ(Page::kObjectStartOffset, page->Offset(temp2->address()));
+ }
+
+ Handle<JSObject> o = factory->NewJSObjectFromMap(map1, TENURED, false);
+ o->set_properties(*factory->empty_fixed_array());
+
+ // Ensure that the object allocated where we need it.
+ Page* page = Page::FromAddress(o->address());
+ CHECK_EQ(desired_offset, page->Offset(o->address()));
+
+ // Now we have an object right at the end of the page.
+
+ // Enable incremental marking to trigger actions in Heap::AdjustLiveBytes()
+ // that would cause crash.
+ IncrementalMarking* marking = CcTest::heap()->incremental_marking();
+ marking->Abort();
+ marking->Start();
+ CHECK(marking->IsMarking());
+
+ // Now everything is set up for crashing in JSObject::MigrateFastToFast()
+ // when it calls heap->AdjustLiveBytes(...).
+ JSObject::MigrateToMap(o, map2);
+}
+
+
+#ifdef DEBUG
+TEST(PathTracer) {
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+
+ v8::Local<v8::Value> result = CompileRun("'abc'");
+ Handle<Object> o = v8::Utils::OpenHandle(*result);
+ CcTest::i_isolate()->heap()->TracePathToObject(*o);
+}
+#endif // DEBUG