Commit 039617d7 authored by ulan's avatar ulan Committed by Commit bot

Handle ExternalStrings directly in the serializer without ObjectVisitor.

The serializer already has code that special cases for some external
strings. We can handle all external strings in one place instead of
splitting the logic between the serializer and the object visitor.

The main benefit is that we remove two virtual functions from the
ObjectVisitor and thus simplify it for all other users.

BUG=chromium:709075

Review-Url: https://codereview.chromium.org/2799943002
Cr-Commit-Position: refs/heads/master@{#44485}
parent e6ca0146
......@@ -1679,10 +1679,6 @@ class RecordMigratedSlotVisitor final : public ObjectVisitor {
inline void VisitExternalReference(RelocInfo* rinfo) final {}
inline void VisitExternalReference(Address* p) final {}
inline void VisitRuntimeEntry(RelocInfo* rinfo) final {}
inline void VisitExternalOneByteString(
v8::String::ExternalOneByteStringResource** resource) final {}
inline void VisitExternalTwoByteString(
v8::String::ExternalStringResource** resource) final {}
inline void VisitInternalReference(RelocInfo* rinfo) final {}
private:
......
......@@ -329,16 +329,10 @@ class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
template <typename ObjectVisitor>
static inline void IterateBody(HeapObject* obj, int object_size,
ObjectVisitor* v) {
typedef v8::String::ExternalOneByteStringResource Resource;
v->VisitExternalOneByteString(reinterpret_cast<Resource**>(
HeapObject::RawField(obj, kResourceOffset)));
}
template <typename StaticVisitor>
static inline void IterateBody(HeapObject* obj, int object_size) {
typedef v8::String::ExternalOneByteStringResource Resource;
StaticVisitor::VisitExternalOneByteString(reinterpret_cast<Resource**>(
HeapObject::RawField(obj, kResourceOffset)));
}
static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
......@@ -351,16 +345,10 @@ class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
template <typename ObjectVisitor>
static inline void IterateBody(HeapObject* obj, int object_size,
ObjectVisitor* v) {
typedef v8::String::ExternalStringResource Resource;
v->VisitExternalTwoByteString(reinterpret_cast<Resource**>(
HeapObject::RawField(obj, kResourceOffset)));
}
template <typename StaticVisitor>
static inline void IterateBody(HeapObject* obj, int object_size) {
typedef v8::String::ExternalStringResource Resource;
StaticVisitor::VisitExternalTwoByteString(reinterpret_cast<Resource**>(
HeapObject::RawField(obj, kResourceOffset)));
}
static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
......
......@@ -10201,12 +10201,6 @@ class ObjectVisitor BASE_EMBEDDED {
// Visits a runtime entry in the instruction stream.
virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
// Visits the resource of an one-byte or two-byte string.
virtual void VisitExternalOneByteString(
v8::String::ExternalOneByteStringResource** resource) {}
virtual void VisitExternalTwoByteString(
v8::String::ExternalStringResource** resource) {}
// Visits a debug call target in the instruction stream.
virtual void VisitDebugTarget(RelocInfo* rinfo);
......
......@@ -401,6 +401,69 @@ void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space,
}
void Serializer::ObjectSerializer::SerializeExternalString() {
Heap* heap = serializer_->isolate()->heap();
if (object_->map() != heap->native_source_string_map()) {
// Usually we cannot recreate resources for external strings. To work
// around this, external strings are serialized to look like ordinary
// sequential strings.
// The exception are native source code strings, since we can recreate
// their resources.
SerializeExternalStringAsSequentialString();
} else {
DCHECK(object_->IsExternalOneByteString());
DCHECK(ExternalOneByteString::cast(object_)->is_short());
int size = object_->Size();
Map* map = object_->map();
AllocationSpace space =
MemoryChunk::FromAddress(object_->address())->owner()->identity();
SerializePrologue(space, size, map);
// Serialize the rest of the object.
CHECK_EQ(0, bytes_processed_so_far_);
bytes_processed_so_far_ = kPointerSize;
typedef v8::String::ExternalOneByteStringResource Resource;
Resource** resource_pointer = reinterpret_cast<Resource**>(
HeapObject::RawField(object_, ExternalString::kResourceOffset));
Address references_start = reinterpret_cast<Address>(resource_pointer);
OutputRawData(references_start);
if (!SerializeExternalNativeSourceString(
Natives::GetBuiltinsCount(), resource_pointer,
Natives::GetSourceCache(heap), kNativesStringResource)) {
bool result = SerializeExternalNativeSourceString(
ExtraNatives::GetBuiltinsCount(), resource_pointer,
ExtraNatives::GetSourceCache(heap), kExtraNativesStringResource);
// One of the strings in the natives cache should match the resource. We
// don't expect any other kinds of external strings here.
USE(result);
DCHECK(result);
}
OutputRawData(object_->address() + size);
}
}
bool Serializer::ObjectSerializer::SerializeExternalNativeSourceString(
int builtin_count,
v8::String::ExternalOneByteStringResource** resource_pointer,
FixedArray* source_cache, int resource_index) {
Isolate* isolate = serializer_->isolate();
for (int i = 0; i < builtin_count; i++) {
Object* source = source_cache->get(i);
if (!source->IsUndefined(isolate)) {
ExternalOneByteString* string = ExternalOneByteString::cast(source);
typedef v8::String::ExternalOneByteStringResource Resource;
const Resource* resource = string->resource();
if (resource == *resource_pointer) {
sink_->Put(resource_index, "NativesStringResource");
sink_->PutSection(i, "NativesStringResourceEnd");
bytes_processed_so_far_ += sizeof(resource);
return true;
}
}
}
return false;
}
void Serializer::ObjectSerializer::SerializeExternalStringAsSequentialString() {
// Instead of serializing this as an external string, we serialize
// an imaginary sequential string with the same content.
Isolate* isolate = serializer_->isolate();
......@@ -501,55 +564,45 @@ void Serializer::ObjectSerializer::Serialize() {
PrintF("\n");
}
// We cannot serialize typed array objects correctly.
DCHECK(!object_->IsJSTypedArray());
if (object_->IsExternalString()) {
SerializeExternalString();
} else {
// We cannot serialize typed array objects correctly.
DCHECK(!object_->IsJSTypedArray());
// We don't expect fillers.
DCHECK(!object_->IsFiller());
// We don't expect fillers.
DCHECK(!object_->IsFiller());
if (object_->IsScript()) {
// Clear cached line ends.
Object* undefined = serializer_->isolate()->heap()->undefined_value();
Script::cast(object_)->set_line_ends(undefined);
}
if (object_->IsScript()) {
// Clear cached line ends.
Object* undefined = serializer_->isolate()->heap()->undefined_value();
Script::cast(object_)->set_line_ends(undefined);
}
if (object_->IsExternalString()) {
Heap* heap = serializer_->isolate()->heap();
if (object_->map() != heap->native_source_string_map()) {
// Usually we cannot recreate resources for external strings. To work
// around this, external strings are serialized to look like ordinary
// sequential strings.
// The exception are native source code strings, since we can recreate
// their resources. In that case we fall through and leave it to
// VisitExternalOneByteString further down.
SerializeExternalString();
int size = object_->Size();
Map* map = object_->map();
AllocationSpace space =
MemoryChunk::FromAddress(object_->address())->owner()->identity();
SerializePrologue(space, size, map);
// Serialize the rest of the object.
CHECK_EQ(0, bytes_processed_so_far_);
bytes_processed_so_far_ = kPointerSize;
RecursionScope recursion(serializer_);
// Objects that are immediately post processed during deserialization
// cannot be deferred, since post processing requires the object content.
if (recursion.ExceedsMaximum() && CanBeDeferred(object_)) {
serializer_->QueueDeferredObject(object_);
sink_->Put(kDeferred, "Deferring object content");
return;
}
}
int size = object_->Size();
Map* map = object_->map();
AllocationSpace space =
MemoryChunk::FromAddress(object_->address())->owner()->identity();
SerializePrologue(space, size, map);
// Serialize the rest of the object.
CHECK_EQ(0, bytes_processed_so_far_);
bytes_processed_so_far_ = kPointerSize;
UnlinkWeakNextScope unlink_weak_next(object_);
RecursionScope recursion(serializer_);
// Objects that are immediately post processed during deserialization
// cannot be deferred, since post processing requires the object content.
if (recursion.ExceedsMaximum() && CanBeDeferred(object_)) {
serializer_->QueueDeferredObject(object_);
sink_->Put(kDeferred, "Deferring object content");
return;
object_->IterateBody(map->instance_type(), size, this);
OutputRawData(object_->address() + size);
}
UnlinkWeakNextScope unlink_weak_next(object_);
object_->IterateBody(map->instance_type(), size, this);
OutputRawData(object_->address() + size);
}
void Serializer::ObjectSerializer::SerializeDeferred() {
......@@ -715,52 +768,6 @@ void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) {
bytes_processed_so_far_ += kPointerSize;
}
bool Serializer::ObjectSerializer::SerializeExternalNativeSourceString(
int builtin_count,
v8::String::ExternalOneByteStringResource** resource_pointer,
FixedArray* source_cache, int resource_index) {
Isolate* isolate = serializer_->isolate();
for (int i = 0; i < builtin_count; i++) {
Object* source = source_cache->get(i);
if (!source->IsUndefined(isolate)) {
ExternalOneByteString* string = ExternalOneByteString::cast(source);
typedef v8::String::ExternalOneByteStringResource Resource;
const Resource* resource = string->resource();
if (resource == *resource_pointer) {
sink_->Put(resource_index, "NativesStringResource");
sink_->PutSection(i, "NativesStringResourceEnd");
bytes_processed_so_far_ += sizeof(resource);
return true;
}
}
}
return false;
}
void Serializer::ObjectSerializer::VisitExternalOneByteString(
v8::String::ExternalOneByteStringResource** resource_pointer) {
DCHECK_EQ(serializer_->isolate()->heap()->native_source_string_map(),
object_->map());
DCHECK(ExternalOneByteString::cast(object_)->is_short());
Address references_start = reinterpret_cast<Address>(resource_pointer);
OutputRawData(references_start);
if (SerializeExternalNativeSourceString(
Natives::GetBuiltinsCount(), resource_pointer,
Natives::GetSourceCache(serializer_->isolate()->heap()),
kNativesStringResource)) {
return;
}
if (SerializeExternalNativeSourceString(
ExtraNatives::GetBuiltinsCount(), resource_pointer,
ExtraNatives::GetSourceCache(serializer_->isolate()->heap()),
kExtraNativesStringResource)) {
return;
}
// One of the strings in the natives cache should match the resource. We
// don't expect any other kinds of external strings here.
UNREACHABLE();
}
Address Serializer::ObjectSerializer::PrepareCode() {
Code* code = Code::cast(object_);
if (FLAG_predictable) {
......
......@@ -290,24 +290,12 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
void VisitCodeEntry(Address entry_address) override;
void VisitCell(RelocInfo* rinfo) override;
void VisitRuntimeEntry(RelocInfo* reloc) override;
// Used for seralizing the external strings that hold the natives source.
void VisitExternalOneByteString(
v8::String::ExternalOneByteStringResource** resource) override;
// We can't serialize a heap with external two byte strings.
void VisitExternalTwoByteString(
v8::String::ExternalStringResource** resource) override {
UNREACHABLE();
}
private:
bool TryEncodeDeoptimizationEntry(HowToCode how_to_code, Address target,
int skip);
void SerializePrologue(AllocationSpace space, int size, Map* map);
bool SerializeExternalNativeSourceString(
int builtin_count,
v8::String::ExternalOneByteStringResource** resource_pointer,
FixedArray* source_cache, int resource_index);
enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
// This function outputs or skips the raw data between the last pointer and
......@@ -315,8 +303,12 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
// bytes to skip instead of performing a skip instruction, in case the skip
// can be merged into the next instruction.
int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn);
// External strings are serialized in a way to resemble sequential strings.
void SerializeExternalString();
void SerializeExternalStringAsSequentialString();
bool SerializeExternalNativeSourceString(
int builtin_count,
v8::String::ExternalOneByteStringResource** resource_pointer,
FixedArray* source_cache, int resource_index);
Address PrepareCode();
......
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