From 518ddc93174a8cdc5d848aa8e8756c62b8cae63d Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Fri, 24 Oct 2014 07:29:39 +0000 Subject: [PATCH] Make block writes in the serializer more efficient. And also fix a OOB read in SerializeExternalString. R=vogelheim@chromium.org Review URL: https://codereview.chromium.org/671633004 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24858 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/serialize.cc | 40 +++++++++++++++++++++++----------------- src/snapshot-source-sink.cc | 4 +--- test/cctest/test-serialize.cc | 2 +- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/serialize.cc b/src/serialize.cc index c11f94a..b862c76 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -1586,29 +1586,34 @@ void Serializer::ObjectSerializer::SerializeExternalString() { ExternalString* string = ExternalString::cast(object_); int length = string->length(); Map* map; - int size; - const char* resource; + int content_size; + int allocation_size; + const byte* resource; // Find the map and size for the imaginary sequential string. bool internalized = object_->IsInternalizedString(); if (object_->IsExternalOneByteString()) { map = internalized ? isolate->heap()->one_byte_internalized_string_map() : isolate->heap()->one_byte_string_map(); - size = SeqOneByteString::SizeFor(length); - resource = ExternalOneByteString::cast(string)->resource()->data(); + allocation_size = SeqOneByteString::SizeFor(length); + content_size = length * kCharSize; + resource = reinterpret_cast( + ExternalOneByteString::cast(string)->resource()->data()); } else { map = internalized ? isolate->heap()->internalized_string_map() : isolate->heap()->string_map(); - size = SeqTwoByteString::SizeFor(length); - resource = reinterpret_cast( + allocation_size = SeqTwoByteString::SizeFor(length); + content_size = length * kShortSize; + resource = reinterpret_cast( ExternalTwoByteString::cast(string)->resource()->data()); } - AllocationSpace space = - (size > Page::kMaxRegularHeapObjectSize) ? LO_SPACE : OLD_DATA_SPACE; - SerializePrologue(space, size, map); + AllocationSpace space = (allocation_size > Page::kMaxRegularHeapObjectSize) + ? LO_SPACE + : OLD_DATA_SPACE; + SerializePrologue(space, allocation_size, map); // Output the rest of the imaginary string. - int bytes_to_output = size - HeapObject::kHeaderSize; + int bytes_to_output = allocation_size - HeapObject::kHeaderSize; // Output raw data header. Do not bother with common raw length cases here. sink_->Put(kRawData, "RawDataForString"); @@ -1621,10 +1626,13 @@ void Serializer::ObjectSerializer::SerializeExternalString() { } // Serialize string content. - int content_length = size - SeqString::kHeaderSize; - for (int i = 0; i < content_length; i++) { - sink_->PutSection(resource[i], "StringContent"); - } + sink_->PutRaw(const_cast(resource), content_size, "StringContent"); + + // Since the allocation size is rounded up to object alignment, there + // maybe left-over bytes that need to be padded. + int padding_size = allocation_size - SeqString::kHeaderSize - content_size; + DCHECK(0 <= padding_size && padding_size < kObjectAlignment); + for (int i = 0; i < padding_size; i++) sink_->PutSection(0, "StringPadding"); sink_->Put(kSkip, "SkipAfterString"); sink_->PutInt(bytes_to_output, "SkipDistance"); @@ -1871,9 +1879,7 @@ int Serializer::ObjectSerializer::OutputRawData( } const char* description = code_object_ ? "Code" : "Byte"; - for (int i = 0; i < bytes_to_output; i++) { - sink_->PutSection(object_start[base + i], description); - } + sink_->PutRaw(object_start + base, bytes_to_output, description); if (code_object_) delete[] object_start; } if (to_skip != 0 && return_skip == kIgnoringReturn) { diff --git a/src/snapshot-source-sink.cc b/src/snapshot-source-sink.cc index 8e3b8a9..9935ff7 100644 --- a/src/snapshot-source-sink.cc +++ b/src/snapshot-source-sink.cc @@ -54,9 +54,7 @@ void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) { void SnapshotByteSink::PutRaw(byte* data, int number_of_bytes, const char* description) { - for (int i = 0; i < number_of_bytes; ++i) { - Put(data[i], description); - } + data_.AddAll(Vector(data, number_of_bytes)); } void SnapshotByteSink::PutBlob(byte* data, int number_of_bytes, diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc index 62c1d82..83903e2 100644 --- a/test/cctest/test-serialize.cc +++ b/test/cctest/test-serialize.cc @@ -1054,7 +1054,7 @@ TEST(SerializeToplevelLargeExternalString) { // Create a huge external internalized string to use as variable name. Vector string = ConstructSource(STATIC_CHAR_VECTOR(""), STATIC_CHAR_VECTOR("abcdef"), - STATIC_CHAR_VECTOR(""), 1000000); + STATIC_CHAR_VECTOR(""), 999999); Handle name = f->NewStringFromOneByte(string).ToHandleChecked(); SerializerOneByteResource one_byte_resource( reinterpret_cast(string.start()), string.length()); -- 2.7.4