Revision: 22371
Author: yang...@chromium.org
Date: Mon Jul 14 11:22:03 2014 UTC
Log: Serialize builtins by referencing canonical ones.
R=mvstan...@chromium.org
Review URL: https://codereview.chromium.org/383173002
http://code.google.com/p/v8/source/detail?r=22371
Modified:
/branches/bleeding_edge/src/serialize.cc
/branches/bleeding_edge/src/serialize.h
/branches/bleeding_edge/test/cctest/test-compiler.cc
/branches/bleeding_edge/test/cctest/test-serialize.cc
=======================================
--- /branches/bleeding_edge/src/serialize.cc Fri Jul 11 07:04:51 2014 UTC
+++ /branches/bleeding_edge/src/serialize.cc Mon Jul 14 11:22:03 2014 UTC
@@ -889,83 +889,88 @@
STATIC_ASSERT((space_number & ~kSpaceMask) == 0);
#define CASE_BODY(where, how, within,
space_number_if_any) \
-
{ \
- bool emit_write_barrier =
false; \
- bool current_was_incremented =
false; \
- int space_number = space_number_if_any ==
kAnyOldSpace ? \
- (data & kSpaceMask) :
space_number_if_any; \
- if (where == kNewObject && how == kPlain && within ==
kStartOfObject) {\
- ReadObject(space_number,
current); \
- emit_write_barrier = (space_number ==
NEW_SPACE); \
+
{
\
+ bool emit_write_barrier =
false; \
+ bool current_was_incremented =
false; \
+ int space_number = space_number_if_any ==
kAnyOldSpace \
+ ? (data &
kSpaceMask) \
+ :
space_number_if_any; \
+ if (where == kNewObject && how == kPlain && within == kStartOfObject)
{ \
+ ReadObject(space_number,
current); \
+ emit_write_barrier = (space_number ==
NEW_SPACE); \
+ } else
{ \
+ Object* new_object = NULL; /* May not be a real Object pointer.
*/ \
+ if (where == kNewObject)
{ \
+ ReadObject(space_number,
&new_object); \
+ } else if (where == kRootArray)
{ \
+ int root_id =
source_->GetInt(); \
+ new_object =
isolate->heap()->roots_array_start()[root_id]; \
+ emit_write_barrier =
isolate->heap()->InNewSpace(new_object); \
+ } else if (where == kPartialSnapshotCache)
{ \
+ int cache_index =
source_->GetInt(); \
+ new_object =
isolate->serialize_partial_snapshot_cache()[cache_index]; \
+ emit_write_barrier =
isolate->heap()->InNewSpace(new_object); \
+ } else if (where == kExternalReference)
{ \
+ int skip =
source_->GetInt(); \
+ current =
reinterpret_cast<Object**>( \
+ reinterpret_cast<Address>(current) +
skip); \
+ int reference_id =
source_->GetInt(); \
+ Address address =
external_reference_decoder_->Decode(reference_id); \
+ new_object =
reinterpret_cast<Object*>(address); \
+ } else if (where == kBackref)
{ \
+ emit_write_barrier = (space_number ==
NEW_SPACE); \
+ new_object = GetAddressFromEnd(data &
kSpaceMask); \
+ } else if (where == kBuiltin)
{ \
+ int builtin_id =
source_->GetInt(); \
+ ASSERT_LE(0,
builtin_id); \
+ ASSERT_LT(builtin_id,
Builtins::builtin_count); \
+ Builtins::Name name =
static_cast<Builtins::Name>(builtin_id); \
+ new_object =
isolate->builtins()->builtin(name); \
+ emit_write_barrier =
false; \
+ PrintF("BUILTIN how within %d, %d\n", how,
within); \
+ } else
{ \
+ ASSERT(where ==
kBackrefWithSkip); \
+ int skip =
source_->GetInt(); \
+ current =
reinterpret_cast<Object**>( \
+ reinterpret_cast<Address>(current) +
skip); \
+ emit_write_barrier = (space_number ==
NEW_SPACE); \
+ new_object = GetAddressFromEnd(data &
kSpaceMask); \
+
} \
+ if (within == kInnerPointer)
{ \
+ if (space_number != CODE_SPACE || new_object->IsCode())
{ \
+ Code* new_code_object =
reinterpret_cast<Code*>(new_object); \
+ new_object
= \
+
reinterpret_cast<Object*>(new_code_object->instruction_start()); \
} else
{ \
- Object* new_object = NULL; /* May not be a real Object pointer.
*/ \
- if (where == kNewObject)
{ \
- ReadObject(space_number,
&new_object); \
- } else if (where == kRootArray)
{ \
- int root_id =
source_->GetInt(); \
- new_object =
isolate->heap()->roots_array_start()[root_id]; \
- emit_write_barrier =
isolate->heap()->InNewSpace(new_object); \
- } else if (where == kPartialSnapshotCache)
{ \
- int cache_index =
source_->GetInt(); \
- new_object =
isolate->serialize_partial_snapshot_cache() \
-
[cache_index]; \
- emit_write_barrier =
isolate->heap()->InNewSpace(new_object); \
- } else if (where == kExternalReference)
{ \
- int skip =
source_->GetInt(); \
- current =
reinterpret_cast<Object**>(reinterpret_cast<Address>( \
- current) +
skip); \
- int reference_id =
source_->GetInt(); \
- Address address =
external_reference_decoder_-> \
-
Decode(reference_id); \
- new_object =
reinterpret_cast<Object*>(address); \
- } else if (where == kBackref)
{ \
- emit_write_barrier = (space_number ==
NEW_SPACE); \
- new_object = GetAddressFromEnd(data &
kSpaceMask); \
- } else
{ \
- ASSERT(where ==
kBackrefWithSkip); \
- int skip =
source_->GetInt(); \
- current =
reinterpret_cast<Object**>( \
- reinterpret_cast<Address>(current) +
skip); \
- emit_write_barrier = (space_number ==
NEW_SPACE); \
- new_object = GetAddressFromEnd(data &
kSpaceMask); \
-
} \
- if (within == kInnerPointer)
{ \
- if (space_number != CODE_SPACE || new_object->IsCode())
{ \
- Code* new_code_object =
reinterpret_cast<Code*>(new_object); \
- new_object =
reinterpret_cast<Object*>( \
-
new_code_object->instruction_start()); \
- } else
{ \
- ASSERT(space_number ==
CODE_SPACE); \
- Cell* cell =
Cell::cast(new_object); \
- new_object =
reinterpret_cast<Object*>( \
-
cell->ValueAddress()); \
-
} \
-
} \
- if (how == kFromCode)
{ \
- Address location_of_branch_data
= \
-
reinterpret_cast<Address>(current); \
-
Assembler::deserialization_set_special_target_at( \
-
location_of_branch_data, \
-
Code::cast(HeapObject::FromAddress(current_object_address)), \
-
reinterpret_cast<Address>(new_object)); \
- location_of_branch_data +=
Assembler::kSpecialTargetSize; \
- current =
reinterpret_cast<Object**>(location_of_branch_data); \
- current_was_incremented =
true; \
- } else
{ \
- *current =
new_object; \
-
} \
+ ASSERT(space_number ==
CODE_SPACE); \
+ Cell* cell =
Cell::cast(new_object); \
+ new_object =
reinterpret_cast<Object*>(cell->ValueAddress()); \
} \
- if (emit_write_barrier && write_barrier_needed)
{ \
- Address current_address =
reinterpret_cast<Address>(current); \
-
isolate->heap()->RecordWrite( \
-
current_object_address, \
- static_cast<int>(current_address -
current_object_address)); \
-
} \
- if (!current_was_incremented)
{ \
-
current++; \
-
} \
-
break; \
} \
+ if (how == kFromCode)
{ \
+ Address location_of_branch_data =
reinterpret_cast<Address>(current); \
+
Assembler::deserialization_set_special_target_at( \
+
location_of_branch_data, \
+
Code::cast(HeapObject::FromAddress(current_object_address)), \
+
reinterpret_cast<Address>(new_object)); \
+ location_of_branch_data +=
Assembler::kSpecialTargetSize; \
+ current =
reinterpret_cast<Object**>(location_of_branch_data); \
+ current_was_incremented =
true; \
+ } else
{ \
+ *current =
new_object; \
+
} \
+
} \
+ if (emit_write_barrier && write_barrier_needed)
{ \
+ Address current_address =
reinterpret_cast<Address>(current); \
+
isolate->heap()->RecordWrite( \
+
current_object_address, \
+ static_cast<int>(current_address -
current_object_address)); \
+
} \
+ if (!current_was_incremented)
{ \
+
current++; \
+
} \
+
break; \
+ }
// This generates a case and a body for the new space (which has to do
extra
// write barrier handling) and handles the other spaces with 8 fall-through
@@ -1161,6 +1166,12 @@
kFromCode,
kStartOfObject,
0)
+ // Find a builtin and write a pointer to it to the current object.
+ CASE_STATEMENT(kBuiltin, kPlain, kStartOfObject, 0)
+ CASE_BODY(kBuiltin, kPlain, kStartOfObject, 0)
+ // Find a builtin and write a pointer to it in the current code
object.
+ CASE_STATEMENT(kBuiltin, kFromCode, kInnerPointer, 0)
+ CASE_BODY(kBuiltin, kFromCode, kInnerPointer, 0)
#undef CASE_STATEMENT
#undef CASE_BODY
@@ -1717,7 +1728,7 @@
int up_to_offset = static_cast<int>(up_to - object_start);
int to_skip = up_to_offset - bytes_processed_so_far_;
int bytes_to_output = to_skip;
- bytes_processed_so_far_ += to_skip;
+ bytes_processed_so_far_ += to_skip;
// This assert will fail if the reloc info gives us the
target_address_address
// locations in a non-ascending order. Luckily that doesn't happen.
ASSERT(to_skip >= 0);
@@ -1846,7 +1857,6 @@
return;
}
- // TODO(yangguo) wire up builtins.
// TODO(yangguo) wire up stubs from stub cache.
// TODO(yangguo) wire up script source.
// TODO(yangguo) wire up internalized strings
@@ -1854,6 +1864,14 @@
// TODO(yangguo) We cannot deal with different hash seeds yet.
ASSERT(!heap_object->IsHashTable());
+ if (heap_object->IsCode()) {
+ Code* code_object = Code::cast(heap_object);
+ if (code_object->kind() == Code::BUILTIN) {
+ SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
+ return;
+ }
+ }
+
if (address_mapper_.IsMapped(heap_object)) {
int space = SpaceOfObject(heap_object);
int address = address_mapper_.MappedTo(heap_object);
@@ -1871,6 +1889,27 @@
where_to_point);
serializer.Serialize();
}
+
+
+void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
+ WhereToPoint where_to_point, int
skip) {
+ if (skip != 0) {
+ sink_->Put(kSkip, "SkipFromSerializeBuiltin");
+ sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin");
+ }
+
+ ASSERT((how_to_code == kPlain && where_to_point == kStartOfObject) ||
+ (how_to_code == kFromCode && where_to_point == kInnerPointer));
+ int id = 0;
+ do { // Look for existing builtins in the list.
+ Code* b =
isolate()->builtins()->builtin(static_cast<Builtins::Name>(id));
+ if (builtin == b) break;
+ } while (++id < Builtins::builtin_count);
+ ASSERT(id < Builtins::builtin_count); // We must have found a one.
+
+ sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin");
+ sink_->PutInt(id, "builtin_index");
+}
Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) {
=======================================
--- /branches/bleeding_edge/src/serialize.h Thu Jul 10 10:28:05 2014 UTC
+++ /branches/bleeding_edge/src/serialize.h Mon Jul 14 11:22:03 2014 UTC
@@ -148,17 +148,18 @@
protected:
// Where the pointed-to object can be found:
enum Where {
- kNewObject = 0, // Object is next in snapshot.
+ kNewObject = 0, // Object is next in snapshot.
// 1-6 One per space.
- kRootArray = 0x9, // Object is found in root array.
- kPartialSnapshotCache = 0xa, // Object is in the cache.
- kExternalReference = 0xb, // Pointer to an external reference.
- kSkip = 0xc, // Skip n bytes.
- kNop = 0xd, // Does nothing, used to pad.
- // 0xe-0xf Free.
- kBackref = 0x10, // Object is described relative to end.
+ kRootArray = 0x9, // Object is found in root array.
+ kPartialSnapshotCache = 0xa, // Object is in the cache.
+ kExternalReference = 0xb, // Pointer to an external reference.
+ kSkip = 0xc, // Skip n bytes.
+ kBuiltin = 0xd, // Builtin code object.
+ // 0xe Free.
+ kNop = 0xf, // Does nothing, used to pad.
+ kBackref = 0x10, // Object is described relative to end.
// 0x11-0x16 One per space.
- kBackrefWithSkip = 0x18, // Object is described relative to end.
+ kBackrefWithSkip = 0x18, // Object is described relative to end.
// 0x19-0x1e One per space.
// 0x20-0x3f Used by misc. tags below.
kPointedToMask = 0x3f
@@ -566,14 +567,9 @@
static Object* Deserialize(Isolate* isolate, ScriptData* data);
- // The data header consists of int-sized entries:
- // [0] version hash
- // [1] length in bytes
- // [2..8] reservation sizes for spaces from NEW_SPACE to
PROPERTY_CELL_SPACE.
- static const int kHeaderSize = 9;
- static const int kVersionHashOffset = 0;
- static const int kPayloadLengthOffset = 1;
- static const int kReservationsOffset = 2;
+ private:
+ void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip);
};
=======================================
--- /branches/bleeding_edge/test/cctest/test-compiler.cc Tue Jul 8
14:13:50 2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-compiler.cc Mon Jul 14
11:22:03 2014 UTC
@@ -397,48 +397,6 @@
CHECK_EQ(fun1->code(), fun2->code());
}
}
-
-
-TEST(SerializeToplevel) {
- FLAG_serialize_toplevel = true;
- v8::HandleScope scope(CcTest::isolate());
- v8::Local<v8::Context> context = CcTest::NewContext(PRINT_EXTENSION);
- v8::Context::Scope context_scope(context);
-
- const char* source1 = "1 + 1";
- const char* source2 = "1 + 2"; // Use alternate string to verify
caching.
-
- Isolate* isolate = CcTest::i_isolate();
- Handle<String> source1_string = isolate->factory()
-
->NewStringFromUtf8(CStrVector(source1))
- .ToHandleChecked();
- Handle<String> source2_string = isolate->factory()
-
->NewStringFromUtf8(CStrVector(source2))
- .ToHandleChecked();
-
- ScriptData* cache = NULL;
-
- Handle<SharedFunctionInfo> orig =
- Compiler::CompileScript(source1_string, Handle<String>(), 0, 0,
false,
- Handle<Context>(isolate->native_context()),
NULL,
- &cache, PRODUCE_CACHED_DATA,
NOT_NATIVES_CODE);
-
- Handle<SharedFunctionInfo> info =
- Compiler::CompileScript(source2_string, Handle<String>(), 0, 0,
false,
- Handle<Context>(isolate->native_context()),
NULL,
- &cache, CONSUME_CACHED_DATA,
NOT_NATIVES_CODE);
-
- CHECK_NE(*orig, *info);
- Handle<JSFunction> fun =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(
- info, isolate->native_context());
- Handle<JSObject> global(isolate->context()->global_object());
- Handle<Object> result =
- Execution::Call(isolate, fun, global, 0, NULL).ToHandleChecked();
- CHECK_EQ(2, Handle<Smi>::cast(result)->value());
-
- delete cache;
-}
#ifdef ENABLE_DISASSEMBLER
=======================================
--- /branches/bleeding_edge/test/cctest/test-serialize.cc Thu Jul 10
10:28:05 2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-serialize.cc Mon Jul 14
11:22:03 2014 UTC
@@ -661,3 +661,62 @@
bool ArtificialFailure2 = false;
CHECK(ArtificialFailure2);
}
+
+
+int CountBuiltins() {
+ // Check that we have not deserialized any additional builtin.
+ HeapIterator iterator(CcTest::heap());
+ DisallowHeapAllocation no_allocation;
+ int counter = 0;
+ for (HeapObject* obj = iterator.next(); obj != NULL; obj =
iterator.next()) {
+ if (obj->IsCode() && Code::cast(obj)->kind() == Code::BUILTIN)
counter++;
+ }
+ return counter;
+}
+
+
+TEST(SerializeToplevel) {
+ FLAG_serialize_toplevel = true;
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> context = CcTest::NewContext(PRINT_EXTENSION);
+ v8::Context::Scope context_scope(context);
+
+ const char* source1 = "1 + 1";
+ const char* source2 = "1 + 2"; // Use alternate string to verify
caching.
+
+ Isolate* isolate = CcTest::i_isolate();
+ Handle<String> source1_string = isolate->factory()
+
->NewStringFromUtf8(CStrVector(source1))
+ .ToHandleChecked();
+
+ Handle<String> source2_string = isolate->factory()
+
->NewStringFromUtf8(CStrVector(source2))
+ .ToHandleChecked();
+
+ ScriptData* cache = NULL;
+
+ Handle<SharedFunctionInfo> orig =
+ Compiler::CompileScript(source1_string, Handle<String>(), 0, 0,
false,
+ Handle<Context>(isolate->native_context()),
NULL,
+ &cache, PRODUCE_CACHED_DATA,
NOT_NATIVES_CODE);
+
+ int builtins_count = CountBuiltins();
+
+ Handle<SharedFunctionInfo> info =
+ Compiler::CompileScript(source2_string, Handle<String>(), 0, 0,
false,
+ Handle<Context>(isolate->native_context()),
NULL,
+ &cache, CONSUME_CACHED_DATA,
NOT_NATIVES_CODE);
+
+ CHECK_NE(*orig, *info);
+ Handle<JSFunction> fun =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(
+ info, isolate->native_context());
+ Handle<JSObject> global(isolate->context()->global_object());
+ Handle<Object> result =
+ Execution::Call(isolate, fun, global, 0, NULL).ToHandleChecked();
+ CHECK_EQ(2, Handle<Smi>::cast(result)->value());
+
+ CHECK_EQ(builtins_count, CountBuiltins());
+
+ delete cache;
+}
--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.