Commit a2099f52 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Serialize all external strings except for native source code strings.

R=mvstanton@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24391 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6e3b54ae
...@@ -5912,7 +5912,7 @@ class Internals { ...@@ -5912,7 +5912,7 @@ class Internals {
static const int kNullValueRootIndex = 7; static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8; static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9; static const int kFalseValueRootIndex = 9;
static const int kEmptyStringRootIndex = 152; static const int kEmptyStringRootIndex = 153;
// The external allocation limit should be below 256 MB on all architectures // The external allocation limit should be below 256 MB on all architectures
// to avoid that resource-constrained embedders run low on memory. // to avoid that resource-constrained embedders run low on memory.
......
...@@ -57,6 +57,8 @@ Handle<String> Bootstrapper::NativesSourceLookup(int index) { ...@@ -57,6 +57,8 @@ Handle<String> Bootstrapper::NativesSourceLookup(int index) {
Handle<String> source_code = isolate_->factory() Handle<String> source_code = isolate_->factory()
->NewExternalStringFromOneByte(resource) ->NewExternalStringFromOneByte(resource)
.ToHandleChecked(); .ToHandleChecked();
// Mark this external string with a special map.
source_code->set_map(isolate_->heap()->native_source_string_map());
heap->natives_source_cache()->set(index, *source_code); heap->natives_source_cache()->set(index, *source_code);
} }
Handle<Object> cached_source(heap->natives_source_cache()->get(index), Handle<Object> cached_source(heap->natives_source_cache()->get(index),
......
...@@ -2522,6 +2522,13 @@ bool Heap::CreateInitialMaps() { ...@@ -2522,6 +2522,13 @@ bool Heap::CreateInitialMaps() {
roots_[entry.index] = map; roots_[entry.index] = map;
} }
{ // Create a separate external one byte string map for native sources.
AllocationResult allocation = AllocateMap(EXTERNAL_ONE_BYTE_STRING_TYPE,
ExternalOneByteString::kSize);
if (!allocation.To(&obj)) return false;
set_native_source_string_map(Map::cast(obj));
}
ALLOCATE_VARSIZE_MAP(STRING_TYPE, undetectable_string) ALLOCATE_VARSIZE_MAP(STRING_TYPE, undetectable_string)
undetectable_string_map()->set_is_undetectable(); undetectable_string_map()->set_is_undetectable();
......
...@@ -83,6 +83,7 @@ namespace internal { ...@@ -83,6 +83,7 @@ namespace internal {
V(Map, external_string_with_one_byte_data_map, \ V(Map, external_string_with_one_byte_data_map, \
ExternalStringWithOneByteDataMap) \ ExternalStringWithOneByteDataMap) \
V(Map, external_one_byte_string_map, ExternalOneByteStringMap) \ V(Map, external_one_byte_string_map, ExternalOneByteStringMap) \
V(Map, native_source_string_map, NativeSourceStringMap) \
V(Map, short_external_string_map, ShortExternalStringMap) \ V(Map, short_external_string_map, ShortExternalStringMap) \
V(Map, short_external_string_with_one_byte_data_map, \ V(Map, short_external_string_with_one_byte_data_map, \
ShortExternalStringWithOneByteDataMap) \ ShortExternalStringWithOneByteDataMap) \
......
...@@ -1552,8 +1552,9 @@ void Serializer::ObjectSerializer::SerializePrologue(int space, int size, ...@@ -1552,8 +1552,9 @@ void Serializer::ObjectSerializer::SerializePrologue(int space, int size,
void Serializer::ObjectSerializer::SerializeExternalString() { void Serializer::ObjectSerializer::SerializeExternalString() {
// Instead of serializing this as an external string, we serialize // Instead of serializing this as an external string, we serialize
// an imaginary sequential string with the same content. // an imaginary sequential string with the same content.
DCHECK(object_->IsExternalString() && object_->IsInternalizedString());
Isolate* isolate = serializer_->isolate(); Isolate* isolate = serializer_->isolate();
DCHECK(object_->IsExternalString());
DCHECK(object_->map() != isolate->heap()->native_source_string_map());
ExternalString* string = ExternalString::cast(object_); ExternalString* string = ExternalString::cast(object_);
int length = string->length(); int length = string->length();
Map* map; Map* map;
...@@ -1600,24 +1601,30 @@ void Serializer::ObjectSerializer::SerializeExternalString() { ...@@ -1600,24 +1601,30 @@ void Serializer::ObjectSerializer::SerializeExternalString() {
void Serializer::ObjectSerializer::Serialize() { void Serializer::ObjectSerializer::Serialize() {
if (object_->IsExternalString() && object_->IsInternalizedString()) { if (object_->IsExternalString()) {
// Native source code strings are not internalized and are handled in Heap* heap = serializer_->isolate()->heap();
// VisitExternalOneByteString. We deal with embedded external strings if (object_->map() != heap->native_source_string_map()) {
// by serializing them as sequential strings on the heap. // Usually we cannot recreate resources for external strings. To work
// This can only happen with CodeSerializer. // around this, external strings are serialized to look like ordinary
SerializeExternalString(); // sequential strings.
} else { // The exception are native source code strings, since we can recreate
int size = object_->Size(); // their resources. In that case we fall through and leave it to
Map* map = object_->map(); // VisitExternalOneByteString further down.
SerializePrologue(Serializer::SpaceOfObject(object_), size, map); SerializeExternalString();
return;
}
}
// Serialize the rest of the object. int size = object_->Size();
CHECK_EQ(0, bytes_processed_so_far_); Map* map = object_->map();
bytes_processed_so_far_ = kPointerSize; SerializePrologue(Serializer::SpaceOfObject(object_), size, map);
object_->IterateBody(map->instance_type(), size, this); // Serialize the rest of the object.
OutputRawData(object_->address() + size); CHECK_EQ(0, bytes_processed_so_far_);
} bytes_processed_so_far_ = kPointerSize;
object_->IterateBody(map->instance_type(), size, this);
OutputRawData(object_->address() + size);
} }
......
...@@ -1046,8 +1046,7 @@ TEST(SerializeToplevelLargeExternalString) { ...@@ -1046,8 +1046,7 @@ TEST(SerializeToplevelLargeExternalString) {
CHECK_NE(*orig, *copy); CHECK_NE(*orig, *copy);
Handle<JSFunction> copy_fun = Handle<JSFunction> copy_fun =
isolate->factory()->NewFunctionFromSharedFunctionInfo( f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
copy, isolate->native_context());
Handle<Object> copy_result = Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked(); Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
...@@ -1059,6 +1058,59 @@ TEST(SerializeToplevelLargeExternalString) { ...@@ -1059,6 +1058,59 @@ TEST(SerializeToplevelLargeExternalString) {
} }
TEST(SerializeToplevelExternalScriptName) {
FLAG_serialize_toplevel = true;
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
Factory* f = isolate->factory();
v8::HandleScope scope(CcTest::isolate());
const char* source =
"var a = [1, 2, 3, 4];"
"a.reduce(function(x, y) { return x + y }, 0)";
Handle<String> source_string =
f->NewStringFromUtf8(CStrVector(source)).ToHandleChecked();
const SerializerOneByteResource one_byte_resource("one_byte", 8);
Handle<String> name =
f->NewExternalStringFromOneByte(&one_byte_resource).ToHandleChecked();
CHECK(name->IsExternalOneByteString());
CHECK(!name->IsInternalizedString());
Handle<JSObject> global(isolate->context()->global_object());
ScriptData* cache = NULL;
Handle<SharedFunctionInfo> orig = Compiler::CompileScript(
source_string, name, 0, 0, false,
Handle<Context>(isolate->native_context()), NULL, &cache,
v8::ScriptCompiler::kProduceCodeCache, NOT_NATIVES_CODE);
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = Compiler::CompileScript(
source_string, name, 0, 0, false,
Handle<Context>(isolate->native_context()), NULL, &cache,
v8::ScriptCompiler::kConsumeCodeCache, NOT_NATIVES_CODE);
}
CHECK_NE(*orig, *copy);
Handle<JSFunction> copy_fun =
f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
CHECK_EQ(10.0f, copy_result->Number());
delete cache;
}
TEST(SerializeToplevelIsolates) { TEST(SerializeToplevelIsolates) {
FLAG_serialize_toplevel = true; FLAG_serialize_toplevel = true;
......
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