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 {
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
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
// to avoid that resource-constrained embedders run low on memory.
......
......@@ -57,6 +57,8 @@ Handle<String> Bootstrapper::NativesSourceLookup(int index) {
Handle<String> source_code = isolate_->factory()
->NewExternalStringFromOneByte(resource)
.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);
}
Handle<Object> cached_source(heap->natives_source_cache()->get(index),
......
......@@ -2522,6 +2522,13 @@ bool Heap::CreateInitialMaps() {
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)
undetectable_string_map()->set_is_undetectable();
......
......@@ -83,6 +83,7 @@ namespace internal {
V(Map, external_string_with_one_byte_data_map, \
ExternalStringWithOneByteDataMap) \
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_with_one_byte_data_map, \
ShortExternalStringWithOneByteDataMap) \
......
......@@ -1552,8 +1552,9 @@ void Serializer::ObjectSerializer::SerializePrologue(int space, int size,
void Serializer::ObjectSerializer::SerializeExternalString() {
// Instead of serializing this as an external string, we serialize
// an imaginary sequential string with the same content.
DCHECK(object_->IsExternalString() && object_->IsInternalizedString());
Isolate* isolate = serializer_->isolate();
DCHECK(object_->IsExternalString());
DCHECK(object_->map() != isolate->heap()->native_source_string_map());
ExternalString* string = ExternalString::cast(object_);
int length = string->length();
Map* map;
......@@ -1600,24 +1601,30 @@ void Serializer::ObjectSerializer::SerializeExternalString() {
void Serializer::ObjectSerializer::Serialize() {
if (object_->IsExternalString() && object_->IsInternalizedString()) {
// Native source code strings are not internalized and are handled in
// VisitExternalOneByteString. We deal with embedded external strings
// by serializing them as sequential strings on the heap.
// This can only happen with CodeSerializer.
SerializeExternalString();
} else {
int size = object_->Size();
Map* map = object_->map();
SerializePrologue(Serializer::SpaceOfObject(object_), size, map);
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();
return;
}
}
// Serialize the rest of the object.
CHECK_EQ(0, bytes_processed_so_far_);
bytes_processed_so_far_ = kPointerSize;
int size = object_->Size();
Map* map = object_->map();
SerializePrologue(Serializer::SpaceOfObject(object_), size, map);
object_->IterateBody(map->instance_type(), size, this);
OutputRawData(object_->address() + size);
}
// Serialize the rest of the object.
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) {
CHECK_NE(*orig, *copy);
Handle<JSFunction> copy_fun =
isolate->factory()->NewFunctionFromSharedFunctionInfo(
copy, isolate->native_context());
f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
......@@ -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) {
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