Index: test/cctest/test-serialize.cc |
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc |
index c309944f3d5499f75d338714d1664f706e031cb3..c4654868aa43646c71632b704f06f812fb6ff81a 100644 |
--- a/test/cctest/test-serialize.cc |
+++ b/test/cctest/test-serialize.cc |
@@ -196,7 +196,8 @@ class FileByteSink : public SnapshotByteSink { |
int data_space_used, |
int code_space_used, |
int map_space_used, |
- int cell_space_used); |
+ int cell_space_used, |
+ int large_space_used); |
private: |
FILE* fp_; |
@@ -210,7 +211,8 @@ void FileByteSink::WriteSpaceUsed( |
int data_space_used, |
int code_space_used, |
int map_space_used, |
- int cell_space_used) { |
+ int cell_space_used, |
+ int large_space_used) { |
int file_name_length = StrLength(file_name_) + 10; |
Vector<char> name = Vector<char>::New(file_name_length + 1); |
OS::SNPrintF(name, "%s.size", file_name_); |
@@ -222,6 +224,7 @@ void FileByteSink::WriteSpaceUsed( |
fprintf(fp, "code %d\n", code_space_used); |
fprintf(fp, "map %d\n", map_space_used); |
fprintf(fp, "cell %d\n", cell_space_used); |
+ fprintf(fp, "large %d\n", large_space_used); |
fclose(fp); |
} |
@@ -230,15 +233,6 @@ static bool WriteToFile(const char* snapshot_file) { |
FileByteSink file(snapshot_file); |
StartupSerializer ser(&file); |
ser.Serialize(); |
- |
- file.WriteSpaceUsed( |
- ser.CurrentAllocationAddress(NEW_SPACE), |
- ser.CurrentAllocationAddress(OLD_POINTER_SPACE), |
- ser.CurrentAllocationAddress(OLD_DATA_SPACE), |
- ser.CurrentAllocationAddress(CODE_SPACE), |
- ser.CurrentAllocationAddress(MAP_SPACE), |
- ser.CurrentAllocationAddress(CELL_SPACE)); |
- |
return true; |
} |
@@ -390,6 +384,7 @@ TEST(PartialSerialization) { |
env.Dispose(); |
FileByteSink startup_sink(startup_name.start()); |
+ startup_name.Dispose(); |
StartupSerializer startup_serializer(&startup_sink); |
startup_serializer.SerializeStrongReferences(); |
@@ -397,35 +392,26 @@ TEST(PartialSerialization) { |
PartialSerializer p_ser(&startup_serializer, &partial_sink); |
p_ser.Serialize(&raw_foo); |
startup_serializer.SerializeWeakReferences(); |
- |
partial_sink.WriteSpaceUsed( |
p_ser.CurrentAllocationAddress(NEW_SPACE), |
p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE), |
p_ser.CurrentAllocationAddress(OLD_DATA_SPACE), |
p_ser.CurrentAllocationAddress(CODE_SPACE), |
p_ser.CurrentAllocationAddress(MAP_SPACE), |
- p_ser.CurrentAllocationAddress(CELL_SPACE)); |
- |
- startup_sink.WriteSpaceUsed( |
- startup_serializer.CurrentAllocationAddress(NEW_SPACE), |
- startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE), |
- startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE), |
- startup_serializer.CurrentAllocationAddress(CODE_SPACE), |
- startup_serializer.CurrentAllocationAddress(MAP_SPACE), |
- startup_serializer.CurrentAllocationAddress(CELL_SPACE)); |
- startup_name.Dispose(); |
+ p_ser.CurrentAllocationAddress(CELL_SPACE), |
+ p_ser.CurrentAllocationAddress(LO_SPACE)); |
} |
} |
-static void ReserveSpaceForSnapshot(Deserializer* deserializer, |
- const char* file_name) { |
+static void ReserveSpaceForPartialSnapshot(const char* file_name) { |
int file_name_length = StrLength(file_name) + 10; |
Vector<char> name = Vector<char>::New(file_name_length + 1); |
OS::SNPrintF(name, "%s.size", file_name); |
FILE* fp = OS::FOpen(name.start(), "r"); |
name.Dispose(); |
int new_size, pointer_size, data_size, code_size, map_size, cell_size; |
+ int large_size; |
#ifdef _MSC_VER |
// Avoid warning about unsafe fscanf from MSVC. |
// Please note that this is only fine if %c and %s are not being used. |
@@ -437,16 +423,18 @@ static void ReserveSpaceForSnapshot(Deserializer* deserializer, |
CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size)); |
CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size)); |
CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size)); |
+ CHECK_EQ(1, fscanf(fp, "large %d\n", &large_size)); |
#ifdef _MSC_VER |
#undef fscanf |
#endif |
fclose(fp); |
- deserializer->set_reservation(NEW_SPACE, new_size); |
- deserializer->set_reservation(OLD_POINTER_SPACE, pointer_size); |
- deserializer->set_reservation(OLD_DATA_SPACE, data_size); |
- deserializer->set_reservation(CODE_SPACE, code_size); |
- deserializer->set_reservation(MAP_SPACE, map_size); |
- deserializer->set_reservation(CELL_SPACE, cell_size); |
+ HEAP->ReserveSpace(new_size, |
+ pointer_size, |
+ data_size, |
+ code_size, |
+ map_size, |
+ cell_size, |
+ large_size); |
} |
@@ -460,6 +448,7 @@ DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { |
startup_name.Dispose(); |
const char* file_name = FLAG_testing_serialization_file; |
+ ReserveSpaceForPartialSnapshot(file_name); |
int snapshot_size = 0; |
byte* snapshot = ReadBytes(file_name, &snapshot_size); |
@@ -468,19 +457,18 @@ DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { |
{ |
SnapshotByteSource source(snapshot, snapshot_size); |
Deserializer deserializer(&source); |
- ReserveSpaceForSnapshot(&deserializer, file_name); |
deserializer.DeserializePartial(&root); |
CHECK(root->IsString()); |
} |
v8::HandleScope handle_scope; |
Handle<Object> root_handle(root); |
+ ReserveSpaceForPartialSnapshot(file_name); |
Object* root2; |
{ |
SnapshotByteSource source(snapshot, snapshot_size); |
Deserializer deserializer(&source); |
- ReserveSpaceForSnapshot(&deserializer, file_name); |
deserializer.DeserializePartial(&root2); |
CHECK(root2->IsString()); |
CHECK(*root_handle == root2); |
@@ -518,6 +506,7 @@ TEST(ContextSerialization) { |
env.Dispose(); |
FileByteSink startup_sink(startup_name.start()); |
+ startup_name.Dispose(); |
StartupSerializer startup_serializer(&startup_sink); |
startup_serializer.SerializeStrongReferences(); |
@@ -525,23 +514,14 @@ TEST(ContextSerialization) { |
PartialSerializer p_ser(&startup_serializer, &partial_sink); |
p_ser.Serialize(&raw_context); |
startup_serializer.SerializeWeakReferences(); |
- |
partial_sink.WriteSpaceUsed( |
p_ser.CurrentAllocationAddress(NEW_SPACE), |
p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE), |
p_ser.CurrentAllocationAddress(OLD_DATA_SPACE), |
p_ser.CurrentAllocationAddress(CODE_SPACE), |
p_ser.CurrentAllocationAddress(MAP_SPACE), |
- p_ser.CurrentAllocationAddress(CELL_SPACE)); |
- |
- startup_sink.WriteSpaceUsed( |
- startup_serializer.CurrentAllocationAddress(NEW_SPACE), |
- startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE), |
- startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE), |
- startup_serializer.CurrentAllocationAddress(CODE_SPACE), |
- startup_serializer.CurrentAllocationAddress(MAP_SPACE), |
- startup_serializer.CurrentAllocationAddress(CELL_SPACE)); |
- startup_name.Dispose(); |
+ p_ser.CurrentAllocationAddress(CELL_SPACE), |
+ p_ser.CurrentAllocationAddress(LO_SPACE)); |
} |
} |
@@ -556,6 +536,7 @@ DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { |
startup_name.Dispose(); |
const char* file_name = FLAG_testing_serialization_file; |
+ ReserveSpaceForPartialSnapshot(file_name); |
int snapshot_size = 0; |
byte* snapshot = ReadBytes(file_name, &snapshot_size); |
@@ -564,19 +545,18 @@ DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { |
{ |
SnapshotByteSource source(snapshot, snapshot_size); |
Deserializer deserializer(&source); |
- ReserveSpaceForSnapshot(&deserializer, file_name); |
deserializer.DeserializePartial(&root); |
CHECK(root->IsContext()); |
} |
v8::HandleScope handle_scope; |
Handle<Object> root_handle(root); |
+ ReserveSpaceForPartialSnapshot(file_name); |
Object* root2; |
{ |
SnapshotByteSource source(snapshot, snapshot_size); |
Deserializer deserializer(&source); |
- ReserveSpaceForSnapshot(&deserializer, file_name); |
deserializer.DeserializePartial(&root2); |
CHECK(root2->IsContext()); |
CHECK(*root_handle != root2); |
@@ -585,6 +565,120 @@ DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { |
} |
+TEST(LinearAllocation) { |
+ v8::V8::Initialize(); |
+ int new_space_max = 512 * KB; |
+ int paged_space_max = Page::kMaxNonCodeHeapObjectSize; |
+ int code_space_max = HEAP->code_space()->AreaSize(); |
+ |
+ for (int size = 1000; size < 5 * MB; size += size >> 1) { |
+ size &= ~8; // Round. |
+ int new_space_size = (size < new_space_max) ? size : new_space_max; |
+ int paged_space_size = (size < paged_space_max) ? size : paged_space_max; |
+ HEAP->ReserveSpace( |
+ new_space_size, |
+ paged_space_size, // Old pointer space. |
+ paged_space_size, // Old data space. |
+ HEAP->code_space()->RoundSizeDownToObjectAlignment(code_space_max), |
+ HEAP->map_space()->RoundSizeDownToObjectAlignment(paged_space_size), |
+ HEAP->cell_space()->RoundSizeDownToObjectAlignment(paged_space_size), |
+ size); // Large object space. |
+ LinearAllocationScope linear_allocation_scope; |
+ DisallowAllocationFailure disallow_allocation_failure; |
+ const int kSmallFixedArrayLength = 4; |
+ const int kSmallFixedArraySize = |
+ FixedArray::kHeaderSize + kSmallFixedArrayLength * kPointerSize; |
+ const int kSmallStringLength = 16; |
+ const int kSmallStringSize = |
+ (SeqAsciiString::kHeaderSize + kSmallStringLength + |
+ kObjectAlignmentMask) & ~kObjectAlignmentMask; |
+ const int kMapSize = Map::kSize; |
+ |
+ Object* new_last = NULL; |
+ for (int i = 0; |
+ i + kSmallFixedArraySize <= new_space_size; |
+ i += kSmallFixedArraySize) { |
+ Object* obj = |
+ HEAP->AllocateFixedArray(kSmallFixedArrayLength)->ToObjectChecked(); |
+ if (new_last != NULL) { |
+ CHECK(reinterpret_cast<char*>(obj) == |
+ reinterpret_cast<char*>(new_last) + kSmallFixedArraySize); |
+ } |
+ new_last = obj; |
+ } |
+ |
+ Object* pointer_last = NULL; |
+ for (int i = 0; |
+ i + kSmallFixedArraySize <= paged_space_size; |
+ i += kSmallFixedArraySize) { |
+ Object* obj = HEAP->AllocateFixedArray(kSmallFixedArrayLength, |
+ TENURED)->ToObjectChecked(); |
+ int old_page_fullness = i % Page::kPageSize; |
+ int page_fullness = (i + kSmallFixedArraySize) % Page::kPageSize; |
+ if (page_fullness < old_page_fullness || |
+ page_fullness > HEAP->old_pointer_space()->AreaSize()) { |
+ i = RoundUp(i, Page::kPageSize); |
+ pointer_last = NULL; |
+ } |
+ if (pointer_last != NULL) { |
+ CHECK(reinterpret_cast<char*>(obj) == |
+ reinterpret_cast<char*>(pointer_last) + kSmallFixedArraySize); |
+ } |
+ pointer_last = obj; |
+ } |
+ |
+ Object* data_last = NULL; |
+ for (int i = 0; |
+ i + kSmallStringSize <= paged_space_size; |
+ i += kSmallStringSize) { |
+ Object* obj = HEAP->AllocateRawAsciiString(kSmallStringLength, |
+ TENURED)->ToObjectChecked(); |
+ int old_page_fullness = i % Page::kPageSize; |
+ int page_fullness = (i + kSmallStringSize) % Page::kPageSize; |
+ if (page_fullness < old_page_fullness || |
+ page_fullness > HEAP->old_data_space()->AreaSize()) { |
+ i = RoundUp(i, Page::kPageSize); |
+ data_last = NULL; |
+ } |
+ if (data_last != NULL) { |
+ CHECK(reinterpret_cast<char*>(obj) == |
+ reinterpret_cast<char*>(data_last) + kSmallStringSize); |
+ } |
+ data_last = obj; |
+ } |
+ |
+ Object* map_last = NULL; |
+ for (int i = 0; i + kMapSize <= paged_space_size; i += kMapSize) { |
+ Object* obj = HEAP->AllocateMap(JS_OBJECT_TYPE, |
+ 42 * kPointerSize)->ToObjectChecked(); |
+ int old_page_fullness = i % Page::kPageSize; |
+ int page_fullness = (i + kMapSize) % Page::kPageSize; |
+ if (page_fullness < old_page_fullness || |
+ page_fullness > HEAP->map_space()->AreaSize()) { |
+ i = RoundUp(i, Page::kPageSize); |
+ map_last = NULL; |
+ } |
+ if (map_last != NULL) { |
+ CHECK(reinterpret_cast<char*>(obj) == |
+ reinterpret_cast<char*>(map_last) + kMapSize); |
+ } |
+ map_last = obj; |
+ } |
+ |
+ if (size > Page::kMaxNonCodeHeapObjectSize) { |
+ // Support for reserving space in large object space is not there yet, |
+ // but using an always-allocate scope is fine for now. |
+ AlwaysAllocateScope always; |
+ int large_object_array_length = |
+ (size - FixedArray::kHeaderSize) / kPointerSize; |
+ Object* obj = HEAP->AllocateFixedArray(large_object_array_length, |
+ TENURED)->ToObjectChecked(); |
+ CHECK(!obj->IsFailure()); |
+ } |
+ } |
+} |
+ |
+ |
TEST(TestThatAlwaysSucceeds) { |
} |