Commit 7753ace1 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Small fixes for the code serializer.

- assertions regarding max heap object size.
- ensure string table capacity upfront.

R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/671843003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24824 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6442348d
......@@ -14769,6 +14769,16 @@ MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
}
void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
int expected) {
Handle<StringTable> table = isolate->factory()->string_table();
// We need a key instance for the virtual hash function.
InternalizedStringKey dummy_key(Handle<String>::null());
table = StringTable::EnsureCapacity(table, expected, &dummy_key);
isolate->factory()->set_string_table(table);
}
Handle<String> StringTable::LookupString(Isolate* isolate,
Handle<String> string) {
InternalizedStringKey key(string);
......
......@@ -3446,6 +3446,8 @@ class StringTable: public HashTable<StringTable,
uint16_t c1,
uint16_t c2);
static void EnsureCapacityForDeserialization(Isolate* isolate, int expected);
DECLARE_CAST(StringTable)
private:
......
......@@ -1594,12 +1594,15 @@ void Serializer::ObjectSerializer::SerializeExternalString() {
int size;
const char* resource;
// Find the map and size for the imaginary sequential string.
bool internalized = object_->IsInternalizedString();
if (object_->IsExternalOneByteString()) {
map = isolate->heap()->one_byte_internalized_string_map();
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();
} else {
map = isolate->heap()->internalized_string_map();
map = internalized ? isolate->heap()->internalized_string_map()
: isolate->heap()->string_map();
size = SeqTwoByteString::SizeFor(length);
resource = reinterpret_cast<const char*>(
ExternalTwoByteString::cast(string)->resource()->data());
......@@ -1910,7 +1913,7 @@ uint32_t Serializer::AllocateLargeObject(int size) {
uint32_t Serializer::Allocate(int space, int size) {
CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
DCHECK(size > 0 && size < Page::kMaxRegularHeapObjectSize);
DCHECK(size > 0 && size <= Page::kMaxRegularHeapObjectSize);
uint32_t new_chunk_size = pending_chunk_[space] + size;
uint32_t allocation;
if (new_chunk_size > static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize)) {
......@@ -2081,6 +2084,8 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
PrintF("\n");
}
if (heap_object->IsInternalizedString()) num_internalized_strings_++;
// Object has not yet been serialized. Serialize it here.
ObjectSerializer serializer(this, heap_object, sink_, how_to_code,
where_to_point);
......@@ -2201,6 +2206,11 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
Deserializer deserializer(&payload);
// Eagerly expand string table to avoid allocations during deserialization.
StringTable::EnsureCapacityForDeserialization(isolate,
scd.NumInternalizedStrings());
// Set reservations.
STATIC_ASSERT(NEW_SPACE == 0);
int current_space = NEW_SPACE;
Vector<const SerializedCodeData::Reservation> res = scd.Reservations();
......@@ -2254,7 +2264,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i);
for (int j = 0; j < chunks.length(); j++) {
DCHECK(i == LO_SPACE ||
chunks[j] <
chunks[j] <=
static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
uint32_t chunk = ChunkSizeBits::encode(chunks[j]) |
IsLastChunkBits::encode(j == chunks.length() - 1);
......@@ -2277,6 +2287,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
// Set header values.
SetHeaderValue(kCheckSumOffset, CheckSum(cs->source()));
SetHeaderValue(kNumInternalizedStringsOffset, cs->num_internalized_strings());
SetHeaderValue(kReservationsOffset, reservations.length());
SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
SetHeaderValue(kPayloadLengthOffset, payload->length());
......
......@@ -264,7 +264,7 @@ class Deserializer: public SerializerDeserializer {
DCHECK(space >= 0);
DCHECK(space < kNumberOfSpaces);
DCHECK(space == LO_SPACE ||
chunk < static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
chunk <= static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
reservations_[space].Add({chunk, NULL, NULL});
}
......@@ -619,17 +619,21 @@ class CodeSerializer : public Serializer {
static const int kSourceObjectIndex = 0;
static const int kCodeStubsBaseIndex = 1;
String* source() {
String* source() const {
DCHECK(!AllowHeapAllocation::IsAllowed());
return source_;
}
List<uint32_t>* stub_keys() { return &stub_keys_; }
int num_internalized_strings() const { return num_internalized_strings_; }
private:
CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source,
Code* main_code)
: Serializer(isolate, sink), source_(source), main_code_(main_code) {
: Serializer(isolate, sink),
source_(source),
main_code_(main_code),
num_internalized_strings_(0) {
set_root_index_wave_front(Heap::kStrongRootListLength);
InitializeCodeAddressMap();
}
......@@ -652,6 +656,7 @@ class CodeSerializer : public Serializer {
DisallowHeapAllocation no_gc_;
String* source_;
Code* main_code_;
int num_internalized_strings_;
List<uint32_t> stub_keys_;
DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
};
......@@ -694,6 +699,10 @@ class SerializedCodeData {
DISALLOW_COPY_AND_ASSIGN(Reservation);
};
int NumInternalizedStrings() const {
return GetHeaderValue(kNumInternalizedStringsOffset);
}
Vector<const Reservation> Reservations() const {
return Vector<const Reservation>(reinterpret_cast<const Reservation*>(
script_data_->data() + kHeaderSize),
......@@ -737,13 +746,15 @@ class SerializedCodeData {
// The data header consists of int-sized entries:
// [0] version hash
// [1] number of code stub keys
// [2] payload length
// [3..9] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
// [1] number of internalized strings
// [2] number of code stub keys
// [3] payload length
// [4..10] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
static const int kCheckSumOffset = 0;
static const int kReservationsOffset = 1;
static const int kNumCodeStubKeysOffset = 2;
static const int kPayloadLengthOffset = 3;
static const int kNumInternalizedStringsOffset = 1;
static const int kReservationsOffset = 2;
static const int kNumCodeStubKeysOffset = 3;
static const int kPayloadLengthOffset = 4;
static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize;
class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment