copied patches for 0.12.x

This commit is contained in:
Igor Klopov 2016-08-11 20:55:24 +03:00
parent 4c3a6df890
commit 25dec4cd92
16 changed files with 4581 additions and 0 deletions

View File

@ -0,0 +1,211 @@
commit b324d0bb99045fcfe80397a978eb2ce29af4990f
Author: igorklopov <igor@klopov.com>
Date: Mon Aug 17 11:31:50 2015 +0400
U2
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 0e68ab8..92aca16 100644
--- node/deps/v8/src/code-stubs.cc
+++ node/deps/v8/src/code-stubs.cc
@@ -252,6 +252,172 @@ void CodeStub::PrintName(OStream& os) const { // NOLINT
}
+void CheckCodeStub(CodeStub* pstub, CodeStub::Major MajorKey, int MinorKey) {
+ if (pstub->MajorKey() != MajorKey) fprintf(stderr, "MajorKey %d != %d in %s\n", pstub->MajorKey(), MajorKey, pstub->MajorName(MajorKey, false));
+ if (pstub->MinorKey() != MinorKey) fprintf(stderr, "MinorKey %d != %d in %s\n", pstub->MinorKey(), MinorKey, pstub->MajorName(MajorKey, false));
+ // if (pstub->MajorKey() == MajorKey) fprintf(stderr, "correct MajorKey in %s\n", pstub->MajorName(MajorKey, false));
+ // if (pstub->MinorKey() == MinorKey) fprintf(stderr, "correct MinorKey in %s\n", pstub->MajorName(MajorKey, false));
+}
+
+
+void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
+ DispatchedCall call) {
+ CodeStub::Major MajorKey = MajorKeyFromKey(key);
+ int MinorKey = MinorKeyFromKey(key);
+ switch (MajorKey) {
+ case CEntry: {
+ // int result = (save_doubles_ == kSaveFPRegs) ? 1 : 0;
+ int result_size = (MinorKey & 0x02) ? 2 : 1;
+ // return result | ((result_size_ == 1) ? 0 : 2);
+ SaveFPRegsMode save_doubles = (MinorKey & 0x01) ? kSaveFPRegs : kDontSaveFPRegs;
+ CEntryStub stub(isolate, result_size, save_doubles);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case CallConstruct: {
+ // int MinorKey() const { return flags_; }
+ CallConstructorFlags flags = (CallConstructorFlags) MinorKey;
+ CallConstructStub stub(isolate, flags);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case FastNewContext: {
+ // int NotMissMinorKey() const V8_OVERRIDE { return slots_; }
+ int slots = MinorKey;
+ FastNewContextStub stub(isolate, slots);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case FastNewClosure: {
+ // class StrictModeBits: public BitField<bool, 0, 1> {};
+ StrictMode strict_mode = (StrictMode) (MinorKey & 0x01);
+ // class IsGeneratorBits: public BitField<bool, 1, 1> {};
+ bool is_generator = MinorKey & 0x02;
+ FastNewClosureStub stub(isolate, strict_mode, is_generator);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case RecordWrite: {
+ #if V8_TARGET_ARCH_IA32
+ // class ObjectBits: public BitField<int, 0, 3> {};
+ Register object = Register::from_code(MinorKey & 0x07);
+ // class ValueBits: public BitField<int, 3, 3> {};
+ Register value = Register::from_code((MinorKey >> 3) & 0x07);
+ // class AddressBits: public BitField<int, 6, 3> {};
+ Register address = Register::from_code((MinorKey >> 6) & 0x07);
+ // class RememberedSetActionBits: public BitField<RememberedSetAction, 9, 1> {};
+ RememberedSetAction remembered_set_action = (RememberedSetAction) ((MinorKey >> 9) & 0x01);
+ // class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 10, 1> {};
+ SaveFPRegsMode fp_mode = (SaveFPRegsMode) ((MinorKey >> 10) & 0x01);
+ RecordWriteStub stub(isolate, object, value, address, remembered_set_action, fp_mode);
+ #endif
+ #if V8_TARGET_ARCH_X64
+ // class ObjectBits: public BitField<int, 0, 4> {};
+ Register object = Register::from_code(MinorKey & 0x0F);
+ // class ValueBits: public BitField<int, 4, 4> {};
+ Register value = Register::from_code((MinorKey >> 4) & 0x0F);
+ // class AddressBits: public BitField<int, 8, 4> {};
+ Register address = Register::from_code((MinorKey >> 8) & 0x0F);
+ // class RememberedSetActionBits: public BitField<RememberedSetAction, 12, 1> {};
+ RememberedSetAction remembered_set_action = (RememberedSetAction) ((MinorKey >> 12) & 0x01);
+ // class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 13, 1> {};
+ SaveFPRegsMode fp_mode = (SaveFPRegsMode) ((MinorKey >> 13) & 0x01);
+ RecordWriteStub stub(isolate, object, value, address, remembered_set_action, fp_mode);
+ #endif
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case ToNumber: {
+ ToNumberStub stub(isolate);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case ArgumentsAccess: {
+ // int MinorKey() const { return type_; }
+ ArgumentsAccessStub::Type type = (ArgumentsAccessStub::Type) MinorKey;
+ ArgumentsAccessStub stub(isolate, type);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case FastCloneShallowArray: {
+ // class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
+ AllocationSiteMode allocation_site_mode = (AllocationSiteMode) (MinorKey & 0x01);
+ FastCloneShallowArrayStub stub(isolate, allocation_site_mode);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case StoreArrayLiteralElement: {
+ StoreArrayLiteralElementStub stub(isolate);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case CallFunction: {
+ // class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
+ CallFunctionFlags flags = (CallFunctionFlags) (MinorKey & 0x03);
+ // class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
+ unsigned argc = MinorKey >> 2;
+ CallFunctionStub stub(isolate, argc, flags);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case Instanceof: {
+ // int MinorKey() const { return static_cast<int>(flags_); }
+ InstanceofStub::Flags flags = (InstanceofStub::Flags) MinorKey;
+ InstanceofStub stub(isolate, flags);
+ CodeStub* pstub = &stub;
+ CheckCodeStub(pstub, MajorKey, MinorKey);
+ call(pstub, value_out);
+ break;
+ }
+ case NUMBER_OF_IDS:
+ UNREACHABLE();
+ case NoCache:
+ *value_out = NULL;
+ break;
+ default: {
+ fprintf(stderr, "unhandled MajorKey: %s (%d)\n", MajorName(MajorKey, false), MajorKey);
+ UNREACHABLE();
+ }
+ }
+}
+
+
+void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
+ Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
+ // Code stubs with special cache cannot be recreated from stub key.
+ *code_out = stub->UseSpecialCache() ? Handle<Code>() : stub->GetCode();
+}
+
+
+MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
+ HandleScope scope(isolate);
+ Handle<Code> code;
+ void** value_out = reinterpret_cast<void**>(&code);
+ Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
+ return scope.CloseAndEscape(code);
+}
+
+
// static
void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
// Generate the uninitialized versions of the stub.
diff --git a/src/code-stubs.h b/src/code-stubs.h
index c1d051b..9cc12df 100644
--- node/deps/v8/src/code-stubs.h
+++ node/deps/v8/src/code-stubs.h
@@ -179,6 +179,8 @@ class CodeStub BASE_EMBEDDED {
// Lookup the code in the (possibly custom) cache.
bool FindCodeInCache(Code** code_out);
+ static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
+
// Returns information for computing the number key.
virtual Major MajorKey() const = 0;
virtual int MinorKey() const = 0;
@@ -242,6 +244,14 @@ class CodeStub BASE_EMBEDDED {
// If a stub uses a special cache override this.
virtual bool UseSpecialCache() { return false; }
+ // We use this dispatch to statically instantiate the correct code stub for
+ // the given stub key and call the passed function with that code stub.
+ typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
+ static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
+ DispatchedCall call);
+
+ static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
+
STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
class MinorKeyBits: public BitField<uint32_t,

View File

@ -0,0 +1,484 @@
commit a49ac519c8df83c52ed67e3860c51ccad80e037a
Author: yangguo@chromium.org <yangguo@chromium.org>
Date: Wed Sep 17 12:50:17 2014 +0000
Serialize code stubs using stub key.
Also add some tracing to the code serializer.
R=mvstanton@chromium.org
Review URL: https://codereview.chromium.org/556243005
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24002 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 4208e62..792fda9 100644
--- node/deps/v8/src/flag-definitions.h
+++ node/deps/v8/src/flag-definitions.h
@@ -428,6 +428,7 @@ DEFINE_BOOL(trace_stub_failures, false,
"trace deoptimization of generated code stubs")
DEFINE_BOOL(serialize_toplevel, false, "enable caching of toplevel scripts")
+DEFINE_BOOL(trace_code_serializer, false, "trace code serializer")
// compiler.cc
DEFINE_INT(min_preparse_length, 1024,
diff --git a/src/serialize.cc b/src/serialize.cc
index 1a19ab0..9447fc8 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -8,6 +8,7 @@
#include "src/api.h"
#include "src/base/platform/platform.h"
#include "src/bootstrapper.h"
+#include "src/code-stubs.h"
#include "src/deoptimizer.h"
#include "src/execution.h"
#include "src/global-handles.h"
@@ -872,7 +873,7 @@ void Deserializer::ReadChunk(Object** current,
} else if (where == kAttachedReference) { \
DCHECK(deserializing_user_code()); \
int index = source_->GetInt(); \
- new_object = attached_objects_->at(index); \
+ new_object = *attached_objects_->at(index); \
emit_write_barrier = isolate->heap()->InNewSpace(new_object); \
} else { \
DCHECK(where == kBackrefWithSkip); \
@@ -1125,6 +1126,10 @@ void Deserializer::ReadChunk(Object** current,
// the current object.
CASE_STATEMENT(kAttachedReference, kPlain, kStartOfObject, 0)
CASE_BODY(kAttachedReference, kPlain, kStartOfObject, 0)
+ CASE_STATEMENT(kAttachedReference, kPlain, kInnerPointer, 0)
+ CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0)
+ CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0)
+ CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0)
#undef CASE_STATEMENT
#undef CASE_BODY
@@ -1311,12 +1316,12 @@ int Serializer::RootIndex(HeapObject* heap_object, HowToCode from) {
// location into a later object. We can encode the location as an offset from
// the start of the deserialized objects or as an offset backwards from the
// current allocation pointer.
-void Serializer::SerializeReferenceToPreviousObject(
- int space,
- int address,
- HowToCode how_to_code,
- WhereToPoint where_to_point,
- int skip) {
+void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object,
+ HowToCode how_to_code,
+ WhereToPoint where_to_point,
+ int skip) {
+ int space = SpaceOfObject(heap_object);
+ int address = address_mapper_.MappedTo(heap_object);
int offset = CurrentAllocationAddress(space) - address;
// Shift out the bits that are always 0.
offset >>= kObjectAlignmentBits;
@@ -1347,12 +1352,7 @@ void StartupSerializer::SerializeObject(
}
if (address_mapper_.IsMapped(heap_object)) {
- int space = SpaceOfObject(heap_object);
- int address = address_mapper_.MappedTo(heap_object);
- SerializeReferenceToPreviousObject(space,
- address,
- how_to_code,
- where_to_point,
+ SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
skip);
} else {
if (skip != 0) {
@@ -1455,12 +1455,7 @@ void PartialSerializer::SerializeObject(
DCHECK(!heap_object->IsInternalizedString());
if (address_mapper_.IsMapped(heap_object)) {
- int space = SpaceOfObject(heap_object);
- int address = address_mapper_.MappedTo(heap_object);
- SerializeReferenceToPreviousObject(space,
- address,
- how_to_code,
- where_to_point,
+ SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
skip);
} else {
if (skip != 0) {
@@ -1782,17 +1777,32 @@ void Serializer::InitializeCodeAddressMap() {
ScriptData* CodeSerializer::Serialize(Isolate* isolate,
Handle<SharedFunctionInfo> info,
Handle<String> source) {
+ base::ElapsedTimer timer;
+ if (FLAG_profile_deserialization) timer.Start();
+
// Serialize code object.
List<byte> payload;
ListSnapshotSink list_sink(&payload);
- CodeSerializer cs(isolate, &list_sink, *source);
+ DebugSnapshotSink debug_sink(&list_sink);
+ SnapshotByteSink* sink = FLAG_trace_code_serializer
+ ? static_cast<SnapshotByteSink*>(&debug_sink)
+ : static_cast<SnapshotByteSink*>(&list_sink);
+ CodeSerializer cs(isolate, sink, *source);
DisallowHeapAllocation no_gc;
Object** location = Handle<Object>::cast(info).location();
cs.VisitPointer(location);
cs.Pad();
SerializedCodeData data(&payload, &cs);
- return data.GetScriptData();
+ ScriptData* script_data = data.GetScriptData();
+
+ if (FLAG_profile_deserialization) {
+ double ms = timer.Elapsed().InMillisecondsF();
+ int length = script_data->length();
+ PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms);
+ }
+
+ return script_data;
}
@@ -1813,16 +1823,13 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
return;
}
- // TODO(yangguo) wire up stubs from stub cache.
// TODO(yangguo) wire up global object.
// TODO(yangguo) We cannot deal with different hash seeds yet.
DCHECK(!heap_object->IsHashTable());
if (address_mapper_.IsMapped(heap_object)) {
- int space = SpaceOfObject(heap_object);
- int address = address_mapper_.MappedTo(heap_object);
- SerializeReferenceToPreviousObject(space, address, how_to_code,
- where_to_point, skip);
+ SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
+ skip);
return;
}
@@ -1832,7 +1839,11 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
return;
}
- // TODO(yangguo) figure out whether other code kinds can be handled smarter.
+ if (code_object->IsCodeStubOrIC()) {
+ SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
+ return;
+ }
+ code_object->ClearInlineCaches();
}
if (heap_object == source_) {
@@ -1840,6 +1851,14 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
return;
}
+ SerializeHeapObject(heap_object, how_to_code, where_to_point, skip);
+}
+
+
+void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
+ HowToCode how_to_code,
+ WhereToPoint where_to_point,
+ int skip) {
if (heap_object->IsScript()) {
// The wrapper cache uses a Foreign object to point to a global handle.
// However, the object visitor expects foreign objects to point to external
@@ -1851,6 +1870,13 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
sink_->Put(kSkip, "SkipFromSerializeObject");
sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
}
+
+ if (FLAG_trace_code_serializer) {
+ PrintF("Encoding heap object: ");
+ heap_object->ShortPrint();
+ PrintF("\n");
+ }
+
// Object has not yet been serialized. Serialize it here.
ObjectSerializer serializer(this, heap_object, sink_, how_to_code,
where_to_point);
@@ -1870,11 +1896,62 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
int builtin_index = builtin->builtin_index();
DCHECK_LT(builtin_index, Builtins::builtin_count);
DCHECK_LE(0, builtin_index);
+
+ if (FLAG_trace_code_serializer) {
+ PrintF("Encoding builtin: %s\n",
+ isolate()->builtins()->name(builtin_index));
+ }
+
sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin");
sink_->PutInt(builtin_index, "builtin_index");
}
+void CodeSerializer::SerializeCodeStub(Code* code, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip) {
+ DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
+ (how_to_code == kPlain && where_to_point == kInnerPointer) ||
+ (how_to_code == kFromCode && where_to_point == kInnerPointer));
+ uint32_t stub_key = code->stub_key();
+
+ if (CodeStub::MajorKeyFromKey(stub_key) == CodeStub::NoCacheKey()) {
+ if (FLAG_trace_code_serializer) {
+ PrintF("Encoding uncacheable code stub as heap object\n");
+ }
+ SerializeHeapObject(code, how_to_code, where_to_point, skip);
+ return;
+ }
+
+ if (skip != 0) {
+ sink_->Put(kSkip, "SkipFromSerializeCodeStub");
+ sink_->PutInt(skip, "SkipDistanceFromSerializeCodeStub");
+ }
+
+ int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex;
+
+ if (FLAG_trace_code_serializer) {
+ PrintF("Encoding code stub %s as %d\n",
+ CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false),
+ index);
+ }
+
+ sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub");
+ sink_->PutInt(index, "CodeStub key");
+}
+
+
+int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
+ // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2).
+ int index = 0;
+ while (index < stub_keys_.length()) {
+ if (stub_keys_[index] == stub_key) return index;
+ index++;
+ }
+ stub_keys_.Add(stub_key);
+ return index;
+}
+
+
void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
WhereToPoint where_to_point,
int skip) {
@@ -1883,6 +1960,10 @@ void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject");
}
+ if (FLAG_trace_code_serializer) {
+ PrintF("Encoding source object\n");
+ }
+
DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex");
@@ -1894,22 +1975,36 @@ Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate,
Handle<String> source) {
base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start();
- SerializedCodeData scd(data, *source);
- SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
- Deserializer deserializer(&payload);
- STATIC_ASSERT(NEW_SPACE == 0);
- for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
- deserializer.set_reservation(i, scd.GetReservation(i));
- }
-
- // Prepare and register list of attached objects.
- Vector<Object*> attached_objects = Vector<Object*>::New(1);
- attached_objects[kSourceObjectIndex] = *source;
- deserializer.SetAttachedObjects(&attached_objects);
Object* root;
- deserializer.DeserializePartial(isolate, &root);
- deserializer.FlushICacheForNewCodeObjects();
+
+ {
+ HandleScope scope(isolate);
+
+ SerializedCodeData scd(data, *source);
+ SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
+ Deserializer deserializer(&payload);
+ STATIC_ASSERT(NEW_SPACE == 0);
+ for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
+ deserializer.set_reservation(i, scd.GetReservation(i));
+ }
+
+ // Prepare and register list of attached objects.
+ Vector<const uint32_t> code_stub_keys = scd.CodeStubKeys();
+ Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
+ code_stub_keys.length() + kCodeStubsBaseIndex);
+ attached_objects[kSourceObjectIndex] = source;
+ for (int i = 0; i < code_stub_keys.length(); i++) {
+ attached_objects[i + kCodeStubsBaseIndex] =
+ CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
+ }
+ deserializer.SetAttachedObjects(&attached_objects);
+
+ // Deserialize.
+ deserializer.DeserializePartial(isolate, &root);
+ deserializer.FlushICacheForNewCodeObjects();
+ }
+
if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF();
int length = data->length();
@@ -1922,18 +2017,35 @@ Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate,
SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
: owns_script_data_(true) {
DisallowHeapAllocation no_gc;
- int data_length = payload->length() + kHeaderEntries * kIntSize;
+ List<uint32_t>* stub_keys = cs->stub_keys();
+
+ // Calculate sizes.
+ int num_stub_keys = stub_keys->length();
+ int stub_keys_size = stub_keys->length() * kInt32Size;
+ int data_length = kHeaderSize + stub_keys_size + payload->length();
+
+ // Allocate backing store and create result data.
byte* data = NewArray<byte>(data_length);
DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment));
- CopyBytes(data + kHeaderEntries * kIntSize, payload->begin(),
- static_cast<size_t>(payload->length()));
script_data_ = new ScriptData(data, data_length);
script_data_->AcquireDataOwnership();
+
+ // Set header values.
SetHeaderValue(kCheckSumOffset, CheckSum(cs->source()));
+ SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
+ SetHeaderValue(kPayloadLengthOffset, payload->length());
STATIC_ASSERT(NEW_SPACE == 0);
for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i));
}
+
+ // Copy code stub keys.
+ CopyBytes(data + kHeaderSize, reinterpret_cast<byte*>(stub_keys->begin()),
+ stub_keys_size);
+
+ // Copy serialized data.
+ CopyBytes(data + kHeaderSize + stub_keys_size, payload->begin(),
+ static_cast<size_t>(payload->length()));
}
diff --git a/src/serialize.h b/src/serialize.h
index 066d75f..71b274b 100644
--- node/deps/v8/src/serialize.h
+++ node/deps/v8/src/serialize.h
@@ -257,7 +257,7 @@ class Deserializer: public SerializerDeserializer {
// Serialized user code reference certain objects that are provided in a list
// By calling this method, we assume that we are deserializing user code.
- void SetAttachedObjects(Vector<Object*>* attached_objects) {
+ void SetAttachedObjects(Vector<Handle<Object> >* attached_objects) {
attached_objects_ = attached_objects;
}
@@ -308,7 +308,7 @@ class Deserializer: public SerializerDeserializer {
Isolate* isolate_;
// Objects from the attached object descriptions in the serialized user code.
- Vector<Object*>* attached_objects_;
+ Vector<Handle<Object> >* attached_objects_;
SnapshotByteSource* source_;
// This is the address of the next object that will be allocated in each
@@ -459,12 +459,10 @@ class Serializer : public SerializerDeserializer {
HowToCode how_to_code,
WhereToPoint where_to_point,
int skip) = 0;
- void SerializeReferenceToPreviousObject(
- int space,
- int address,
- HowToCode how_to_code,
- WhereToPoint where_to_point,
- int skip);
+ void SerializeReferenceToPreviousObject(HeapObject* heap_object,
+ HowToCode how_to_code,
+ WhereToPoint where_to_point,
+ int skip);
void InitializeAllocators();
// This will return the space for an object.
static int SpaceOfObject(HeapObject* object);
@@ -594,20 +592,29 @@ class CodeSerializer : public Serializer {
Handle<String> source);
static const int kSourceObjectIndex = 0;
+ static const int kCodeStubsBaseIndex = 1;
String* source() {
DCHECK(!AllowHeapAllocation::IsAllowed());
return source_;
}
+ List<uint32_t>* stub_keys() { return &stub_keys_; }
+
private:
void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
WhereToPoint where_to_point, int skip);
+ void SerializeCodeStub(Code* code, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip);
void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
int skip);
+ void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip);
+ int AddCodeStubKey(uint32_t stub_key);
DisallowHeapAllocation no_gc_;
String* source_;
+ List<uint32_t> stub_keys_;
DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
};
@@ -638,12 +645,22 @@ class SerializedCodeData {
return result;
}
+ Vector<const uint32_t> CodeStubKeys() const {
+ return Vector<const uint32_t>(
+ reinterpret_cast<const uint32_t*>(script_data_->data() + kHeaderSize),
+ GetHeaderValue(kNumCodeStubKeysOffset));
+ }
+
const byte* Payload() const {
- return script_data_->data() + kHeaderEntries * kIntSize;
+ int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size;
+ return script_data_->data() + kHeaderSize + code_stubs_size;
}
int PayloadLength() const {
- return script_data_->length() - kHeaderEntries * kIntSize;
+ int payload_length = GetHeaderValue(kPayloadLengthOffset);
+ DCHECK_EQ(script_data_->data() + script_data_->length(),
+ Payload() + payload_length);
+ return payload_length;
}
int GetReservation(int space) const {
@@ -666,10 +683,21 @@ class SerializedCodeData {
// The data header consists of int-sized entries:
// [0] version hash
- // [1..7] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
+ // [1] number of code stub keys
+ // [2] payload length
+ // [3..9] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
static const int kCheckSumOffset = 0;
- static const int kReservationsOffset = 1;
- static const int kHeaderEntries = 8;
+ static const int kNumCodeStubKeysOffset = 1;
+ static const int kPayloadLengthOffset = 2;
+ static const int kReservationsOffset = 3;
+
+ static const int kNumSpaces = PROPERTY_CELL_SPACE - NEW_SPACE + 1;
+ static const int kHeaderEntries = kReservationsOffset + kNumSpaces;
+ static const int kHeaderSize = kHeaderEntries * kIntSize;
+
+ // Following the header, we store, in sequential order
+ // - code stub keys
+ // - serialization payload
ScriptData* script_data_;
bool owns_script_data_;

View File

@ -0,0 +1,739 @@
commit 1257f35c21c9aeb054ae57a0087c50d91f625c24
Author: yangguo@chromium.org <yangguo@chromium.org>
Date: Thu Sep 25 07:32:13 2014 +0000
Support large objects in the serializer/deserializer.
R=hpayer@chromium.org, mvstanton@chromium.org
Review URL: https://codereview.chromium.org/581223004
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24204 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 3d0c2f0..78c45b0 100644
--- node/deps/v8/src/heap/heap.cc
+++ node/deps/v8/src/heap/heap.cc
@@ -923,9 +923,12 @@ void Heap::ReserveSpace(int* sizes, Address* locations_out) {
static const int kThreshold = 20;
while (gc_performed && counter++ < kThreshold) {
gc_performed = false;
- DCHECK(NEW_SPACE == FIRST_PAGED_SPACE - 1);
- for (int space = NEW_SPACE; space <= LAST_PAGED_SPACE; space++) {
- if (sizes[space] != 0) {
+ for (int space = NEW_SPACE; space < Serializer::kNumberOfSpaces; space++) {
+ if (sizes[space] == 0) continue;
+ bool perform_gc = false;
+ if (space == LO_SPACE) {
+ perform_gc = !lo_space()->CanAllocateSize(sizes[space]);
+ } else {
AllocationResult allocation;
if (space == NEW_SPACE) {
allocation = new_space()->AllocateRaw(sizes[space]);
@@ -933,23 +936,27 @@ void Heap::ReserveSpace(int* sizes, Address* locations_out) {
allocation = paged_space(space)->AllocateRaw(sizes[space]);
}
FreeListNode* node;
- if (!allocation.To(&node)) {
- if (space == NEW_SPACE) {
- Heap::CollectGarbage(NEW_SPACE,
- "failed to reserve space in the new space");
- } else {
- AbortIncrementalMarkingAndCollectGarbage(
- this, static_cast<AllocationSpace>(space),
- "failed to reserve space in paged space");
- }
- gc_performed = true;
- break;
- } else {
+ if (allocation.To(&node)) {
// Mark with a free list node, in case we have a GC before
// deserializing.
node->set_size(this, sizes[space]);
+ DCHECK(space < Serializer::kNumberOfPreallocatedSpaces);
locations_out[space] = node->address();
+ } else {
+ perform_gc = true;
+ }
+ }
+ if (perform_gc) {
+ if (space == NEW_SPACE) {
+ Heap::CollectGarbage(NEW_SPACE,
+ "failed to reserve space in the new space");
+ } else {
+ AbortIncrementalMarkingAndCollectGarbage(
+ this, static_cast<AllocationSpace>(space),
+ "failed to reserve space in paged or large object space");
}
+ gc_performed = true;
+ break; // Abort for-loop over spaces and retry.
}
}
}
diff --git a/src/heap/heap.h b/src/heap/heap.h
index 956b859..87b939a 100644
--- node/deps/v8/src/heap/heap.h
+++ node/deps/v8/src/heap/heap.h
@@ -2021,6 +2021,7 @@ class Heap {
int gc_callbacks_depth_;
friend class AlwaysAllocateScope;
+ friend class Deserializer;
friend class Factory;
friend class GCCallbacksScope;
friend class GCTracer;
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
index f8d340f..ae4048f 100644
--- node/deps/v8/src/heap/spaces.cc
+++ node/deps/v8/src/heap/spaces.cc
@@ -2840,9 +2840,7 @@ AllocationResult LargeObjectSpace::AllocateRaw(int object_size,
return AllocationResult::Retry(identity());
}
- if (Size() + object_size > max_capacity_) {
- return AllocationResult::Retry(identity());
- }
+ if (!CanAllocateSize(object_size)) return AllocationResult::Retry(identity());
LargePage* page = heap()->isolate()->memory_allocator()->AllocateLargePage(
object_size, this, executable);
diff --git a/src/heap/spaces.h b/src/heap/spaces.h
index 9ecb3c4..1a89449 100644
--- node/deps/v8/src/heap/spaces.h
+++ node/deps/v8/src/heap/spaces.h
@@ -2728,6 +2728,8 @@ class LargeObjectSpace : public Space {
MUST_USE_RESULT AllocationResult
AllocateRaw(int object_size, Executability executable);
+ bool CanAllocateSize(int size) { return Size() + size <= max_capacity_; }
+
// Available bytes for objects in this space.
inline intptr_t Available();
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index b4a4018..eacd098 100644
--- node/deps/v8/src/mksnapshot.cc
+++ node/deps/v8/src/mksnapshot.cc
@@ -84,10 +84,10 @@ class SnapshotWriter {
i::List<i::byte> startup_blob;
i::ListSnapshotSink sink(&startup_blob);
- int spaces[] = {
- i::NEW_SPACE, i::OLD_POINTER_SPACE, i::OLD_DATA_SPACE, i::CODE_SPACE,
- i::MAP_SPACE, i::CELL_SPACE, i::PROPERTY_CELL_SPACE
- };
+ int spaces[] = {i::NEW_SPACE, i::OLD_POINTER_SPACE,
+ i::OLD_DATA_SPACE, i::CODE_SPACE,
+ i::MAP_SPACE, i::CELL_SPACE,
+ i::PROPERTY_CELL_SPACE, i::LO_SPACE};
i::byte* snapshot_bytes = snapshot_data.begin();
sink.PutBlob(snapshot_bytes, snapshot_data.length(), "snapshot");
@@ -197,6 +197,7 @@ class SnapshotWriter {
WriteSizeVar(ser, prefix, "map", i::MAP_SPACE);
WriteSizeVar(ser, prefix, "cell", i::CELL_SPACE);
WriteSizeVar(ser, prefix, "property_cell", i::PROPERTY_CELL_SPACE);
+ WriteSizeVar(ser, prefix, "lo", i::LO_SPACE);
fprintf(fp_, "\n");
}
diff --git a/src/serialize.cc b/src/serialize.cc
index 843f976..894a1be 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -596,8 +596,9 @@ Deserializer::Deserializer(SnapshotByteSource* source)
: isolate_(NULL),
attached_objects_(NULL),
source_(source),
- external_reference_decoder_(NULL) {
- for (int i = 0; i < LAST_SPACE + 1; i++) {
+ external_reference_decoder_(NULL),
+ deserialized_large_objects_(0) {
+ for (int i = 0; i < kNumberOfSpaces; i++) {
reservations_[i] = kUninitializedReservation;
}
}
@@ -615,7 +616,7 @@ void Deserializer::FlushICacheForNewCodeObjects() {
void Deserializer::Deserialize(Isolate* isolate) {
isolate_ = isolate;
DCHECK(isolate_ != NULL);
- isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
+ isolate_->heap()->ReserveSpace(reservations_, high_water_);
// No active threads.
DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
// No active handles.
@@ -662,7 +663,8 @@ void Deserializer::DeserializePartial(Isolate* isolate, Object** root) {
for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
DCHECK(reservations_[i] != kUninitializedReservation);
}
- isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
+ Heap* heap = isolate->heap();
+ heap->ReserveSpace(reservations_, high_water_);
if (external_reference_decoder_ == NULL) {
external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
}
@@ -798,11 +800,40 @@ void Deserializer::ReadObject(int space_number,
*write_back = obj;
#ifdef DEBUG
- bool is_codespace = (space_number == CODE_SPACE);
- DCHECK(obj->IsCode() == is_codespace);
+ if (obj->IsCode()) {
+ DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE);
+ } else {
+ DCHECK(space_number != CODE_SPACE);
+ }
#endif
}
+
+// We know the space requirements before deserialization and can
+// pre-allocate that reserved space. During deserialization, all we need
+// to do is to bump up the pointer for each space in the reserved
+// space. This is also used for fixing back references.
+// Since multiple large objects cannot be folded into one large object
+// space allocation, we have to do an actual allocation when deserializing
+// each large object. Instead of tracking offset for back references, we
+// reference large objects by index.
+Address Deserializer::Allocate(int space_index, int size) {
+ if (space_index == LO_SPACE) {
+ AlwaysAllocateScope scope(isolate_);
+ LargeObjectSpace* lo_space = isolate_->heap()->lo_space();
+ Executability exec = static_cast<Executability>(source_->GetInt());
+ AllocationResult result = lo_space->AllocateRaw(size, exec);
+ HeapObject* obj = HeapObject::cast(result.ToObjectChecked());
+ deserialized_large_objects_.Add(obj);
+ return obj->address();
+ } else {
+ DCHECK(space_index < kNumberOfPreallocatedSpaces);
+ Address address = high_water_[space_index];
+ high_water_[space_index] = address + size;
+ return address;
+ }
+}
+
void Deserializer::ReadChunk(Object** current,
Object** limit,
int source_space,
@@ -925,15 +956,16 @@ void Deserializer::ReadChunk(Object** current,
// 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
// cases and one body.
-#define ALL_SPACES(where, how, within) \
- CASE_STATEMENT(where, how, within, NEW_SPACE) \
- CASE_BODY(where, how, within, NEW_SPACE) \
- CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \
- CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \
- CASE_STATEMENT(where, how, within, CODE_SPACE) \
- CASE_STATEMENT(where, how, within, CELL_SPACE) \
- CASE_STATEMENT(where, how, within, PROPERTY_CELL_SPACE) \
- CASE_STATEMENT(where, how, within, MAP_SPACE) \
+#define ALL_SPACES(where, how, within) \
+ CASE_STATEMENT(where, how, within, NEW_SPACE) \
+ CASE_BODY(where, how, within, NEW_SPACE) \
+ CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \
+ CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \
+ CASE_STATEMENT(where, how, within, CODE_SPACE) \
+ CASE_STATEMENT(where, how, within, MAP_SPACE) \
+ CASE_STATEMENT(where, how, within, CELL_SPACE) \
+ CASE_STATEMENT(where, how, within, PROPERTY_CELL_SPACE) \
+ CASE_STATEMENT(where, how, within, LO_SPACE) \
CASE_BODY(where, how, within, kAnyOldSpace)
#define FOUR_CASES(byte_code) \
@@ -1184,12 +1216,11 @@ Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
sink_(sink),
external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
root_index_wave_front_(0),
- code_address_map_(NULL) {
+ code_address_map_(NULL),
+ seen_large_objects_index_(0) {
// The serializer is meant to be used only to generate initial heap images
// from a context in which there is only one isolate.
- for (int i = 0; i <= LAST_SPACE; i++) {
- fullness_[i] = 0;
- }
+ for (int i = 0; i < kNumberOfSpaces; i++) fullness_[i] = 0;
}
@@ -1324,10 +1355,7 @@ void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object,
WhereToPoint where_to_point,
int skip) {
int space = SpaceOfObject(heap_object);
- int address = address_mapper_.MappedTo(heap_object);
- int offset = CurrentAllocationAddress(space) - address;
- // Shift out the bits that are always 0.
- offset >>= kObjectAlignmentBits;
+
if (skip == 0) {
sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer");
} else {
@@ -1335,7 +1363,17 @@ void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object,
"BackRefSerWithSkip");
sink_->PutInt(skip, "BackRefSkipDistance");
}
- sink_->PutInt(offset, "offset");
+
+ if (space == LO_SPACE) {
+ int index = address_mapper_.MappedTo(heap_object);
+ sink_->PutInt(index, "large object index");
+ } else {
+ int address = address_mapper_.MappedTo(heap_object);
+ int offset = CurrentAllocationAddress(space) - address;
+ // Shift out the bits that are always 0.
+ offset >>= kObjectAlignmentBits;
+ sink_->PutInt(offset, "offset");
+ }
}
@@ -1494,8 +1532,18 @@ void Serializer::ObjectSerializer::Serialize() {
}
// Mark this object as already serialized.
- int offset = serializer_->Allocate(space, size);
- serializer_->address_mapper()->AddMapping(object_, offset);
+ if (space == LO_SPACE) {
+ if (object_->IsCode()) {
+ sink_->PutInt(EXECUTABLE, "executable large object");
+ } else {
+ sink_->PutInt(NOT_EXECUTABLE, "not executable large object");
+ }
+ int index = serializer_->AllocateLargeObject(size);
+ serializer_->address_mapper()->AddMapping(object_, index);
+ } else {
+ int offset = serializer_->Allocate(space, size);
+ serializer_->address_mapper()->AddMapping(object_, offset);
+ }
// Serialize the map (first word of the object).
serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject, 0);
@@ -1747,8 +1795,14 @@ int Serializer::SpaceOfObject(HeapObject* object) {
}
+int Serializer::AllocateLargeObject(int size) {
+ fullness_[LO_SPACE] += size;
+ return seen_large_objects_index_++;
+}
+
+
int Serializer::Allocate(int space, int size) {
- CHECK(space >= 0 && space < kNumberOfSpaces);
+ CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
int allocation_address = fullness_[space];
fullness_[space] = allocation_address + size;
return allocation_address;
@@ -1840,11 +1894,11 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
if (heap_object->IsCode()) {
Code* code_object = Code::cast(heap_object);
+ DCHECK(!code_object->is_optimized_code());
if (code_object->kind() == Code::BUILTIN) {
SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
return;
- }
- if (code_object->IsCodeStubOrIC()) {
+ } else if (code_object->IsCodeStubOrIC()) {
SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
return;
}
@@ -1991,7 +2045,7 @@ Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate,
SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
Deserializer deserializer(&payload);
STATIC_ASSERT(NEW_SPACE == 0);
- for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
+ for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
deserializer.set_reservation(i, scd.GetReservation(i));
}
@@ -2041,7 +2095,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
SetHeaderValue(kPayloadLengthOffset, payload->length());
STATIC_ASSERT(NEW_SPACE == 0);
- for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
+ for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) {
SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i));
}
diff --git a/src/serialize.h b/src/serialize.h
index 71b274b..7831536 100644
--- node/deps/v8/src/serialize.h
+++ node/deps/v8/src/serialize.h
@@ -148,11 +148,15 @@ class SerializerDeserializer: public ObjectVisitor {
static int nop() { return kNop; }
+ // No reservation for large object space necessary.
+ static const int kNumberOfPreallocatedSpaces = LO_SPACE;
+ static const int kNumberOfSpaces = INVALID_SPACE;
+
protected:
// Where the pointed-to object can be found:
enum Where {
kNewObject = 0, // Object is next in snapshot.
- // 1-6 One per space.
+ // 1-7 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.
@@ -161,9 +165,9 @@ class SerializerDeserializer: public ObjectVisitor {
kAttachedReference = 0xe, // Object is described in an attached list.
kNop = 0xf, // Does nothing, used to pad.
kBackref = 0x10, // Object is described relative to end.
- // 0x11-0x16 One per space.
+ // 0x11-0x17 One per space.
kBackrefWithSkip = 0x18, // Object is described relative to end.
- // 0x19-0x1e One per space.
+ // 0x19-0x1f One per space.
// 0x20-0x3f Used by misc. tags below.
kPointedToMask = 0x3f
};
@@ -225,11 +229,11 @@ class SerializerDeserializer: public ObjectVisitor {
return byte_code & 0x1f;
}
- static const int kNumberOfSpaces = LO_SPACE;
static const int kAnyOldSpace = -1;
// A bitmask for getting the space out of an instruction.
static const int kSpaceMask = 7;
+ STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
};
@@ -249,7 +253,7 @@ class Deserializer: public SerializerDeserializer {
void set_reservation(int space_number, int reservation) {
DCHECK(space_number >= 0);
- DCHECK(space_number <= LAST_SPACE);
+ DCHECK(space_number < kNumberOfSpaces);
reservations_[space_number] = reservation;
}
@@ -282,24 +286,18 @@ class Deserializer: public SerializerDeserializer {
void ReadChunk(
Object** start, Object** end, int space, Address object_address);
void ReadObject(int space_number, Object** write_back);
+ Address Allocate(int space_index, int size);
// Special handling for serialized code like hooking up internalized strings.
HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj);
Object* ProcessBackRefInSerializedCode(Object* obj);
- // This routine both allocates a new object, and also keeps
- // track of where objects have been allocated so that we can
- // fix back references when deserializing.
- Address Allocate(int space_index, int size) {
- Address address = high_water_[space_index];
- high_water_[space_index] = address + size;
- return address;
- }
-
// This returns the address of an object that has been described in the
// snapshot as being offset bytes back in a particular space.
HeapObject* GetAddressFromEnd(int space) {
int offset = source_->GetInt();
+ if (space == LO_SPACE) return deserialized_large_objects_[offset];
+ DCHECK(space < kNumberOfPreallocatedSpaces);
offset <<= kObjectAlignmentBits;
return HeapObject::FromAddress(high_water_[space] - offset);
}
@@ -313,13 +311,15 @@ class Deserializer: public SerializerDeserializer {
SnapshotByteSource* source_;
// This is the address of the next object that will be allocated in each
// space. It is used to calculate the addresses of back-references.
- Address high_water_[LAST_SPACE + 1];
+ Address high_water_[kNumberOfPreallocatedSpaces];
- int reservations_[LAST_SPACE + 1];
+ int reservations_[kNumberOfSpaces];
static const intptr_t kUninitializedReservation = -1;
ExternalReferenceDecoder* external_reference_decoder_;
+ List<HeapObject*> deserialized_large_objects_;
+
DISALLOW_COPY_AND_ASSIGN(Deserializer);
};
@@ -466,6 +466,7 @@ class Serializer : public SerializerDeserializer {
void InitializeAllocators();
// This will return the space for an object.
static int SpaceOfObject(HeapObject* object);
+ int AllocateLargeObject(int size);
int Allocate(int space, int size);
int EncodeExternalReference(Address addr) {
return external_reference_encoder_->Encode(addr);
@@ -480,7 +481,7 @@ class Serializer : public SerializerDeserializer {
Isolate* isolate_;
// Keep track of the fullness of each space in order to generate
// relative addresses for back references.
- int fullness_[LAST_SPACE + 1];
+ int fullness_[kNumberOfSpaces];
SnapshotByteSink* sink_;
ExternalReferenceEncoder* external_reference_encoder_;
@@ -497,6 +498,8 @@ class Serializer : public SerializerDeserializer {
private:
CodeAddressMap* code_address_map_;
+ // We map serialized large objects to indexes for back-referencing.
+ int seen_large_objects_index_;
DISALLOW_COPY_AND_ASSIGN(Serializer);
};
@@ -691,8 +694,8 @@ class SerializedCodeData {
static const int kPayloadLengthOffset = 2;
static const int kReservationsOffset = 3;
- static const int kNumSpaces = PROPERTY_CELL_SPACE - NEW_SPACE + 1;
- static const int kHeaderEntries = kReservationsOffset + kNumSpaces;
+ static const int kHeaderEntries =
+ kReservationsOffset + SerializerDeserializer::kNumberOfSpaces;
static const int kHeaderSize = kHeaderEntries * kIntSize;
// Following the header, we store, in sequential order
diff --git a/src/snapshot-common.cc b/src/snapshot-common.cc
index a2d5213..4e90ce1 100644
--- node/deps/v8/src/snapshot-common.cc
+++ node/deps/v8/src/snapshot-common.cc
@@ -21,8 +21,8 @@ void Snapshot::ReserveSpaceForLinkedInSnapshot(Deserializer* deserializer) {
deserializer->set_reservation(CODE_SPACE, code_space_used_);
deserializer->set_reservation(MAP_SPACE, map_space_used_);
deserializer->set_reservation(CELL_SPACE, cell_space_used_);
- deserializer->set_reservation(PROPERTY_CELL_SPACE,
- property_cell_space_used_);
+ deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_space_used_);
+ deserializer->set_reservation(LO_SPACE, lo_space_used_);
}
@@ -67,6 +67,7 @@ Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
deserializer.set_reservation(CELL_SPACE, context_cell_space_used_);
deserializer.set_reservation(PROPERTY_CELL_SPACE,
context_property_cell_space_used_);
+ deserializer.set_reservation(LO_SPACE, context_lo_space_used_);
deserializer.DeserializePartial(isolate, &root);
CHECK(root->IsContext());
return Handle<Context>(Context::cast(root));
diff --git a/src/snapshot-empty.cc b/src/snapshot-empty.cc
index 65207bf..e8673e5 100644
--- node/deps/v8/src/snapshot-empty.cc
+++ node/deps/v8/src/snapshot-empty.cc
@@ -27,6 +27,7 @@ const int Snapshot::code_space_used_ = 0;
const int Snapshot::map_space_used_ = 0;
const int Snapshot::cell_space_used_ = 0;
const int Snapshot::property_cell_space_used_ = 0;
+const int Snapshot::lo_space_used_ = 0;
const int Snapshot::context_new_space_used_ = 0;
const int Snapshot::context_pointer_space_used_ = 0;
@@ -35,5 +36,5 @@ const int Snapshot::context_code_space_used_ = 0;
const int Snapshot::context_map_space_used_ = 0;
const int Snapshot::context_cell_space_used_ = 0;
const int Snapshot::context_property_cell_space_used_ = 0;
-
+const int Snapshot::context_lo_space_used_ = 0;
} } // namespace v8::internal
diff --git a/src/snapshot-external.cc b/src/snapshot-external.cc
index ee1a8f4..9b8bc1b 100644
--- node/deps/v8/src/snapshot-external.cc
+++ node/deps/v8/src/snapshot-external.cc
@@ -25,6 +25,7 @@ struct SnapshotImpl {
int map_space_used;
int cell_space_used;
int property_cell_space_used;
+ int lo_space_used;
const byte* context_data;
int context_size;
@@ -35,6 +36,7 @@ struct SnapshotImpl {
int context_map_space_used;
int context_cell_space_used;
int context_property_cell_space_used;
+ int context_lo_space_used;
};
@@ -66,6 +68,7 @@ bool Snapshot::Initialize(Isolate* isolate) {
deserializer.set_reservation(CELL_SPACE, snapshot_impl_->cell_space_used);
deserializer.set_reservation(PROPERTY_CELL_SPACE,
snapshot_impl_->property_cell_space_used);
+ deserializer.set_reservation(LO_SPACE, snapshot_impl_->lo_space_used);
bool success = V8::Initialize(&deserializer);
if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF();
@@ -97,6 +100,7 @@ Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
deserializer.set_reservation(PROPERTY_CELL_SPACE,
snapshot_impl_->
context_property_cell_space_used);
+ deserializer.set_reservation(LO_SPACE, snapshot_impl_->context_lo_space_used);
Object* root;
deserializer.DeserializePartial(isolate, &root);
CHECK(root->IsContext());
@@ -123,6 +127,7 @@ void SetSnapshotFromFile(StartupData* snapshot_blob) {
snapshot_impl_->map_space_used = source.GetInt();
snapshot_impl_->cell_space_used = source.GetInt();
snapshot_impl_->property_cell_space_used = source.GetInt();
+ snapshot_impl_->lo_space_used = source.GetInt();
success &= source.GetBlob(&snapshot_impl_->context_data,
&snapshot_impl_->context_size);
diff --git a/src/snapshot-source-sink.cc b/src/snapshot-source-sink.cc
index 44f8706..29bad33 100644
--- node/deps/v8/src/snapshot-source-sink.cc
+++ node/deps/v8/src/snapshot-source-sink.cc
@@ -39,15 +39,17 @@ void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) {
- DCHECK(integer < 1 << 22);
+ DCHECK(integer < 1 << 30);
integer <<= 2;
int bytes = 1;
if (integer > 0xff) bytes = 2;
if (integer > 0xffff) bytes = 3;
- integer |= bytes;
+ if (integer > 0xffffff) bytes = 4;
+ integer |= (bytes - 1);
Put(static_cast<int>(integer & 0xff), "IntPart1");
if (bytes > 1) Put(static_cast<int>((integer >> 8) & 0xff), "IntPart2");
if (bytes > 2) Put(static_cast<int>((integer >> 16) & 0xff), "IntPart3");
+ if (bytes > 3) Put(static_cast<int>((integer >> 24) & 0xff), "IntPart4");
}
void SnapshotByteSink::PutRaw(byte* data, int number_of_bytes,
diff --git a/src/snapshot-source-sink.h b/src/snapshot-source-sink.h
index 3c64bca..c1a31b5 100644
--- node/deps/v8/src/snapshot-source-sink.h
+++ node/deps/v8/src/snapshot-source-sink.h
@@ -39,7 +39,7 @@ class SnapshotByteSource FINAL {
// This way of variable-length encoding integers does not suffer from branch
// mispredictions.
uint32_t answer = GetUnalignedInt();
- int bytes = answer & 3;
+ int bytes = (answer & 3) + 1;
Advance(bytes);
uint32_t mask = 0xffffffffu;
mask >>= 32 - (bytes << 3);
diff --git a/src/snapshot.h b/src/snapshot.h
index 3d752a7..590ecf1 100644
--- node/deps/v8/src/snapshot.h
+++ node/deps/v8/src/snapshot.h
@@ -48,6 +48,7 @@ class Snapshot {
static const int map_space_used_;
static const int cell_space_used_;
static const int property_cell_space_used_;
+ static const int lo_space_used_;
static const int context_new_space_used_;
static const int context_pointer_space_used_;
static const int context_data_space_used_;
@@ -55,6 +56,7 @@ class Snapshot {
static const int context_map_space_used_;
static const int context_cell_space_used_;
static const int context_property_cell_space_used_;
+ static const int context_lo_space_used_;
static const int size_;
static const int raw_size_;
static const int context_size_;
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index c277011..ed9419d 100644
--- node/deps/v8/test/cctest/test-serialize.cc
+++ node/deps/v8/test/cctest/test-serialize.cc
@@ -137,14 +137,10 @@ class FileByteSink : public SnapshotByteSink {
virtual int Position() {
return ftell(fp_);
}
- void WriteSpaceUsed(
- int new_space_used,
- int pointer_space_used,
- int data_space_used,
- int code_space_used,
- int map_space_used,
- int cell_space_used,
- int property_cell_space_used);
+ void WriteSpaceUsed(int new_space_used, int pointer_space_used,
+ int data_space_used, int code_space_used,
+ int map_space_used, int cell_space_used,
+ int property_cell_space_used, int lo_space_used);
private:
FILE* fp_;
@@ -152,14 +148,11 @@ class FileByteSink : public SnapshotByteSink {
};
-void FileByteSink::WriteSpaceUsed(
- int new_space_used,
- int pointer_space_used,
- int data_space_used,
- int code_space_used,
- int map_space_used,
- int cell_space_used,
- int property_cell_space_used) {
+void FileByteSink::WriteSpaceUsed(int new_space_used, int pointer_space_used,
+ int data_space_used, int code_space_used,
+ int map_space_used, int cell_space_used,
+ int property_cell_space_used,
+ int lo_space_used) {
int file_name_length = StrLength(file_name_) + 10;
Vector<char> name = Vector<char>::New(file_name_length + 1);
SNPrintF(name, "%s.size", file_name_);
@@ -172,6 +165,7 @@ void FileByteSink::WriteSpaceUsed(
fprintf(fp, "map %d\n", map_space_used);
fprintf(fp, "cell %d\n", cell_space_used);
fprintf(fp, "property cell %d\n", property_cell_space_used);
+ fprintf(fp, "lo %d\n", lo_space_used);
fclose(fp);
}
@@ -181,14 +175,14 @@ static bool WriteToFile(Isolate* isolate, const char* snapshot_file) {
StartupSerializer ser(isolate, &file);
ser.Serialize();
- file.WriteSpaceUsed(
- ser.CurrentAllocationAddress(NEW_SPACE),
- ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
- ser.CurrentAllocationAddress(OLD_DATA_SPACE),
- ser.CurrentAllocationAddress(CODE_SPACE),
- ser.CurrentAllocationAddress(MAP_SPACE),
- ser.CurrentAllocationAddress(CELL_SPACE),
- ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
+ file.WriteSpaceUsed(ser.CurrentAllocationAddress(NEW_SPACE),
+ ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
+ ser.CurrentAllocationAddress(OLD_DATA_SPACE),
+ ser.CurrentAllocationAddress(CODE_SPACE),
+ ser.CurrentAllocationAddress(MAP_SPACE),
+ ser.CurrentAllocationAddress(CELL_SPACE),
+ ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE),
+ ser.CurrentAllocationAddress(LO_SPACE));
return true;
}
@@ -246,7 +240,7 @@ static void ReserveSpaceForSnapshot(Deserializer* deserializer,
FILE* fp = v8::base::OS::FOpen(name.start(), "r");
name.Dispose();
int new_size, pointer_size, data_size, code_size, map_size, cell_size,
- property_cell_size;
+ property_cell_size, lo_size;
#ifdef _MSC_VER
// Avoid warning about unsafe fscanf from MSVC.
// Please note that this is only fine if %c and %s are not being used.
@@ -259,6 +253,7 @@ static void ReserveSpaceForSnapshot(Deserializer* deserializer,
CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
+ CHECK_EQ(1, fscanf(fp, "lo %d\n", &lo_size));
#ifdef _MSC_VER
#undef fscanf
#endif
@@ -270,6 +265,7 @@ static void ReserveSpaceForSnapshot(Deserializer* deserializer,
deserializer->set_reservation(MAP_SPACE, map_size);
deserializer->set_reservation(CELL_SPACE, cell_size);
deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_size);
+ deserializer->set_reservation(LO_SPACE, lo_size);
}

View File

@ -0,0 +1,88 @@
commit 667f15a1047eeadf4cbadbb50dafe6541745cdc3
Author: yangguo@chromium.org <yangguo@chromium.org>
Date: Mon Sep 29 07:14:05 2014 +0000
Fix serializing ICs.
R=mvstanton@chromium.org
Review URL: https://codereview.chromium.org/587213002
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24262 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/serialize.cc b/src/serialize.cc
index 894a1be..a2dde9b 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -1894,15 +1894,26 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
if (heap_object->IsCode()) {
Code* code_object = Code::cast(heap_object);
- DCHECK(!code_object->is_optimized_code());
- if (code_object->kind() == Code::BUILTIN) {
- SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
- return;
- } else if (code_object->IsCodeStubOrIC()) {
- SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
- return;
+ switch (code_object->kind()) {
+ case Code::OPTIMIZED_FUNCTION: // No optimized code compiled yet.
+ case Code::HANDLER: // No handlers patched in yet.
+ case Code::REGEXP: // No regexp literals initialized yet.
+ case Code::NUMBER_OF_KINDS: // Pseudo enum value.
+ CHECK(false);
+ case Code::BUILTIN:
+ SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
+ return;
+ case Code::STUB:
+ SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
+ return;
+#define IC_KIND_CASE(KIND) case Code::KIND:
+ IC_KIND_LIST(IC_KIND_CASE)
+#undef IC_KIND_CASE
+ // TODO(yangguo): add special handling to canonicalize ICs.
+ case Code::FUNCTION:
+ SerializeHeapObject(code_object, how_to_code, where_to_point, skip);
+ return;
}
- code_object->ClearInlineCaches();
}
if (heap_object == source_) {
@@ -1967,20 +1978,13 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
}
-void CodeSerializer::SerializeCodeStub(Code* code, HowToCode how_to_code,
+void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code,
WhereToPoint where_to_point, int skip) {
DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
(how_to_code == kPlain && where_to_point == kInnerPointer) ||
(how_to_code == kFromCode && where_to_point == kInnerPointer));
- uint32_t stub_key = code->stub_key();
-
- if (CodeStub::MajorKeyFromKey(stub_key) == CodeStub::NoCacheKey()) {
- if (FLAG_trace_code_serializer) {
- PrintF("Encoding uncacheable code stub as heap object\n");
- }
- SerializeHeapObject(code, how_to_code, where_to_point, skip);
- return;
- }
+ uint32_t stub_key = stub->stub_key();
+ DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache);
if (skip != 0) {
sink_->Put(kSkip, "SkipFromSerializeCodeStub");
diff --git a/src/serialize.h b/src/serialize.h
index 7831536..b6ad82c 100644
--- node/deps/v8/src/serialize.h
+++ node/deps/v8/src/serialize.h
@@ -607,7 +607,7 @@ class CodeSerializer : public Serializer {
private:
void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
WhereToPoint where_to_point, int skip);
- void SerializeCodeStub(Code* code, HowToCode how_to_code,
+ void SerializeCodeStub(Code* stub, HowToCode how_to_code,
WhereToPoint where_to_point, int skip);
void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
int skip);

View File

@ -0,0 +1,238 @@
commit ad24cdae728fc34b23e74a22543702de3ae477d1
Author: yangguo@chromium.org <yangguo@chromium.org>
Date: Mon Sep 29 07:53:22 2014 +0000
Do not serialize non-lazy compiled function literals.
... and some small refactorings.
R=mvstanton@chromium.org
Review URL: https://codereview.chromium.org/594513002
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24266 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/serialize.cc b/src/serialize.cc
index a2dde9b..9d59b6f 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -1846,7 +1846,7 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
SnapshotByteSink* sink = FLAG_trace_code_serializer
? static_cast<SnapshotByteSink*>(&debug_sink)
: static_cast<SnapshotByteSink*>(&list_sink);
- CodeSerializer cs(isolate, sink, *source);
+ CodeSerializer cs(isolate, sink, *source, info->code());
DisallowHeapAllocation no_gc;
Object** location = Handle<Object>::cast(info).location();
cs.VisitPointer(location);
@@ -1867,31 +1867,25 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
WhereToPoint where_to_point, int skip) {
- CHECK(o->IsHeapObject());
HeapObject* heap_object = HeapObject::cast(o);
- // The code-caches link to context-specific code objects, which
- // the startup and context serializes cannot currently handle.
- DCHECK(!heap_object->IsMap() ||
- Map::cast(heap_object)->code_cache() ==
- heap_object->GetHeap()->empty_fixed_array());
-
int root_index;
if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
return;
}
- // TODO(yangguo) wire up global object.
- // TODO(yangguo) We cannot deal with different hash seeds yet.
- DCHECK(!heap_object->IsHashTable());
-
if (address_mapper_.IsMapped(heap_object)) {
SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
skip);
return;
}
+ if (skip != 0) {
+ sink_->Put(kSkip, "SkipFromSerializeObject");
+ sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
+ }
+
if (heap_object->IsCode()) {
Code* code_object = Code::cast(heap_object);
switch (code_object->kind()) {
@@ -1901,34 +1895,42 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
case Code::NUMBER_OF_KINDS: // Pseudo enum value.
CHECK(false);
case Code::BUILTIN:
- SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
+ SerializeBuiltin(code_object, how_to_code, where_to_point);
return;
case Code::STUB:
- SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
+ SerializeCodeStub(code_object, how_to_code, where_to_point);
return;
#define IC_KIND_CASE(KIND) case Code::KIND:
IC_KIND_LIST(IC_KIND_CASE)
#undef IC_KIND_CASE
+ SerializeHeapObject(code_object, how_to_code, where_to_point);
+ return;
// TODO(yangguo): add special handling to canonicalize ICs.
case Code::FUNCTION:
- SerializeHeapObject(code_object, how_to_code, where_to_point, skip);
+ SerializeHeapObject(code_object, how_to_code, where_to_point);
return;
}
}
if (heap_object == source_) {
- SerializeSourceObject(how_to_code, where_to_point, skip);
+ SerializeSourceObject(how_to_code, where_to_point);
return;
}
- SerializeHeapObject(heap_object, how_to_code, where_to_point, skip);
+ // Past this point we should not see any (context-specific) maps anymore.
+ CHECK(!heap_object->IsMap());
+ // There should be no references to the global object embedded.
+ CHECK(!heap_object->IsJSGlobalProxy() && !heap_object->IsGlobalObject());
+ // There should be no hash table embedded. They would require rehashing.
+ CHECK(!heap_object->IsHashTable());
+
+ SerializeHeapObject(heap_object, how_to_code, where_to_point);
}
void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
HowToCode how_to_code,
- WhereToPoint where_to_point,
- int skip) {
+ WhereToPoint where_to_point) {
if (heap_object->IsScript()) {
// The wrapper cache uses a Foreign object to point to a global handle.
// However, the object visitor expects foreign objects to point to external
@@ -1936,11 +1946,6 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
Script::cast(heap_object)->ClearWrapperCache();
}
- if (skip != 0) {
- sink_->Put(kSkip, "SkipFromSerializeObject");
- sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
- }
-
if (FLAG_trace_code_serializer) {
PrintF("Encoding heap object: ");
heap_object->ShortPrint();
@@ -1955,12 +1960,7 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
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");
- }
-
+ WhereToPoint where_to_point) {
DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
(how_to_code == kPlain && where_to_point == kInnerPointer) ||
(how_to_code == kFromCode && where_to_point == kInnerPointer));
@@ -1979,18 +1979,13 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code,
- WhereToPoint where_to_point, int skip) {
+ WhereToPoint where_to_point) {
DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
(how_to_code == kPlain && where_to_point == kInnerPointer) ||
(how_to_code == kFromCode && where_to_point == kInnerPointer));
uint32_t stub_key = stub->stub_key();
DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache);
- if (skip != 0) {
- sink_->Put(kSkip, "SkipFromSerializeCodeStub");
- sink_->PutInt(skip, "SkipDistanceFromSerializeCodeStub");
- }
-
int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex;
if (FLAG_trace_code_serializer) {
@@ -2017,16 +2012,8 @@ int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
- WhereToPoint where_to_point,
- int skip) {
- if (skip != 0) {
- sink_->Put(kSkip, "SkipFromSerializeSourceObject");
- sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject");
- }
-
- if (FLAG_trace_code_serializer) {
- PrintF("Encoding source object\n");
- }
+ WhereToPoint where_to_point) {
+ if (FLAG_trace_code_serializer) PrintF("Encoding source object\n");
DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
diff --git a/src/serialize.h b/src/serialize.h
index b6ad82c..616f8f1 100644
--- node/deps/v8/src/serialize.h
+++ node/deps/v8/src/serialize.h
@@ -577,19 +577,10 @@ class StartupSerializer : public Serializer {
class CodeSerializer : public Serializer {
public:
- CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source)
- : Serializer(isolate, sink), source_(source) {
- set_root_index_wave_front(Heap::kStrongRootListLength);
- InitializeCodeAddressMap();
- }
-
static ScriptData* Serialize(Isolate* isolate,
Handle<SharedFunctionInfo> info,
Handle<String> source);
- virtual void SerializeObject(Object* o, HowToCode how_to_code,
- WhereToPoint where_to_point, int skip);
-
static Handle<SharedFunctionInfo> Deserialize(Isolate* isolate,
ScriptData* data,
Handle<String> source);
@@ -605,18 +596,29 @@ class CodeSerializer : public Serializer {
List<uint32_t>* stub_keys() { return &stub_keys_; }
private:
+ CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source,
+ Code* main_code)
+ : Serializer(isolate, sink), source_(source), main_code_(main_code) {
+ set_root_index_wave_front(Heap::kStrongRootListLength);
+ InitializeCodeAddressMap();
+ }
+
+ virtual void SerializeObject(Object* o, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip);
+
void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
- WhereToPoint where_to_point, int skip);
+ WhereToPoint where_to_point);
void SerializeCodeStub(Code* stub, HowToCode how_to_code,
- WhereToPoint where_to_point, int skip);
- void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
- int skip);
+ WhereToPoint where_to_point);
+ void SerializeSourceObject(HowToCode how_to_code,
+ WhereToPoint where_to_point);
void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code,
- WhereToPoint where_to_point, int skip);
+ WhereToPoint where_to_point);
int AddCodeStubKey(uint32_t stub_key);
DisallowHeapAllocation no_gc_;
String* source_;
+ Code* main_code_;
List<uint32_t> stub_keys_;
DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
};

View File

@ -0,0 +1,53 @@
commit 6ca8f782aac4df7530d9fd460ec0fabd46628e1d
Author: yangguo@chromium.org <yangguo@chromium.org>
Date: Fri Oct 10 10:51:34 2014 +0000
Reset code age when serializing code objects.
R=mvstanton@chromium.org
Review URL: https://codereview.chromium.org/642283002
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24523 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/objects.cc b/src/objects.cc
index 9f25145..3eedfe9 100644
--- node/deps/v8/src/objects.cc
+++ node/deps/v8/src/objects.cc
@@ -10463,6 +10463,12 @@ static Code::Age EffectiveAge(Code::Age age) {
}
+void Code::MakeYoung() {
+ byte* sequence = FindCodeAgeSequence();
+ if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, GetIsolate());
+}
+
+
void Code::MakeOlder(MarkingParity current_parity) {
byte* sequence = FindCodeAgeSequence();
if (sequence != NULL) {
diff --git a/src/objects.h b/src/objects.h
index bcbea12..1faae86 100644
--- node/deps/v8/src/objects.h
+++ node/deps/v8/src/objects.h
@@ -5310,6 +5310,7 @@ class Code: public HeapObject {
// compilation stub.
static void MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate);
static void MarkCodeAsExecuted(byte* sequence, Isolate* isolate);
+ void MakeYoung();
void MakeOlder(MarkingParity);
static bool IsYoungSequence(Isolate* isolate, byte* sequence);
bool IsOld();
diff --git a/src/serialize.cc b/src/serialize.cc
index 0cc629d..c287219 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -1991,6 +1991,7 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
return;
// TODO(yangguo): add special handling to canonicalize ICs.
case Code::FUNCTION:
+ code_object->MakeYoung();
SerializeHeapObject(code_object, how_to_code, where_to_point);
return;
}

View File

@ -0,0 +1,38 @@
commit 33dc53f9cc709862de641d32c9a412cf7cfce953
Author: yangguo@chromium.org <yangguo@chromium.org>
Date: Mon Oct 13 07:50:21 2014 +0000
Always include full reloc info to stubs for serialization.
R=mvstanton@chromium.org
Review URL: https://codereview.chromium.org/641643006
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24543 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 80fff3f..63488dc 100644
--- node/deps/v8/src/code-stubs-hydrogen.cc
+++ node/deps/v8/src/code-stubs-hydrogen.cc
@@ -233,6 +233,8 @@ Handle<Code> HydrogenCodeStub::GenerateLightweightMissCode(
// Generate the code for the stub.
masm.set_generating_stub(true);
+ // TODO(yangguo): remove this once we can serialize IC stubs.
+ masm.enable_serializer();
NoCurrentFrameScope scope(&masm);
GenerateLightweightMiss(&masm, miss);
}
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 357324b..9832650 100644
--- node/deps/v8/src/code-stubs.cc
+++ node/deps/v8/src/code-stubs.cc
@@ -111,6 +111,8 @@ Handle<Code> PlatformCodeStub::GenerateCode() {
// Generate the code for the stub.
masm.set_generating_stub(true);
+ // TODO(yangguo): remove this once we can serialize IC stubs.
+ masm.enable_serializer();
NoCurrentFrameScope scope(&masm);
Generate(&masm);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
commit d7acb9148b6407526c257eceaec16c358655a3d5
Author: jkummerow@chromium.org <jkummerow@chromium.org>
Date: Wed Oct 15 14:27:26 2014 +0000
Fix compilation after r24639
TBR=yangguo@chromium.org
Review URL: https://codereview.chromium.org/661473002
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24642 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/serialize.cc b/src/serialize.cc
index 4c9675e..b980940 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -1918,7 +1918,7 @@ uint32_t Serializer::Allocate(int space, int size) {
DCHECK(size > 0 && size < Page::kMaxRegularHeapObjectSize);
uint32_t new_chunk_size = pending_chunk_[space] + size;
uint32_t allocation;
- if (new_chunk_size > Page::kMaxRegularHeapObjectSize) {
+ if (new_chunk_size > static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize)) {
// The new chunk size would not fit onto a single page. Complete the
// current chunk and start a new one.
completed_chunks_[space].Add(pending_chunk_[space]);

View File

@ -0,0 +1,26 @@
commit 2577d6c261da26d6fbc97669a3ef8f4b61027c7e
Author: sigurds@chromium.org <sigurds@chromium.org>
Date: Wed Oct 15 14:42:32 2014 +0000
Fix compilation after r24639
TBR=yangguo@chromium.org
Review URL: https://codereview.chromium.org/653353003
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24643 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/serialize.h b/src/serialize.h
index 6e1f651..482bc34 100644
--- node/deps/v8/src/serialize.h
+++ node/deps/v8/src/serialize.h
@@ -263,7 +263,8 @@ class Deserializer: public SerializerDeserializer {
void AddReservation(int space, uint32_t chunk) {
DCHECK(space >= 0);
DCHECK(space < kNumberOfSpaces);
- DCHECK(space == LO_SPACE || chunk < Page::kMaxRegularHeapObjectSize);
+ DCHECK(space == LO_SPACE ||
+ chunk < static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c);
}

View File

@ -0,0 +1,29 @@
commit 8949d5f58002c5d058064e9047a6247119e725bf
Author: jkummerow@chromium.org <jkummerow@chromium.org>
Date: Wed Oct 15 15:04:09 2014 +0000
Fix compilation some more after r24639
Third time's a charm...
TBR=yangguo@chromium.org
Review URL: https://codereview.chromium.org/655223003
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24644 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/serialize.cc b/src/serialize.cc
index b980940..4933a19 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -2213,7 +2213,9 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) {
Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i);
for (int j = 0; j < chunks.length(); j++) {
- DCHECK(i == LO_SPACE || chunks[j] < Page::kMaxRegularHeapObjectSize);
+ DCHECK(i == LO_SPACE ||
+ chunks[j] <
+ static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
uint32_t chunk = ChunkSizeBits::encode(chunks[j]) |
IsLastChunkBits::encode(j == chunks.length() - 1);
reservations.Add(chunk);

View File

@ -0,0 +1,177 @@
commit 7753ace1354ac231374da0446a5057b6b40780db
Author: yangguo@chromium.org <yangguo@chromium.org>
Date: Thu Oct 23 08:25:42 2014 +0000
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
diff --git a/src/objects.cc b/src/objects.cc
index 2685a5c..371931c 100644
--- node/deps/v8/src/objects.cc
+++ node/deps/v8/src/objects.cc
@@ -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);
diff --git a/src/objects.h b/src/objects.h
index 7e509e7..b2b64c2 100644
--- node/deps/v8/src/objects.h
+++ node/deps/v8/src/objects.h
@@ -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:
diff --git a/src/serialize.cc b/src/serialize.cc
index 5e6de03..95336fb 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -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());
diff --git a/src/serialize.h b/src/serialize.h
index 47a244f..df6723c 100644
--- node/deps/v8/src/serialize.h
+++ node/deps/v8/src/serialize.h
@@ -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));
Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c);
}
@@ -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> {};

View File

@ -0,0 +1,217 @@
commit 3a3d5e741a4329641fa45f7293220e8dfd7a8f15
Author: yangguo@chromium.org <yangguo@chromium.org>
Date: Fri Oct 31 14:43:21 2014 +0000
Break allocations in the code serializer into correct chunk sizes.
This change has been inspired by Slava Chigrin <vchigrin@yandex-team.ru> (https://codereview.chromium.org/689663002/)
R=mvstanton@chromium.org, vchigrin@yandex-team.ru
Review URL: https://codereview.chromium.org/686103004
Cr-Commit-Position: refs/heads/master@{#25039}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25039 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 94c8937..93e00d2 100644
--- node/deps/v8/src/heap/heap.cc
+++ node/deps/v8/src/heap/heap.cc
@@ -939,6 +939,8 @@ bool Heap::ReserveSpace(Reservation* reservations) {
for (auto& chunk : *reservation) {
AllocationResult allocation;
int size = chunk.size;
+ DCHECK_LE(size, MemoryAllocator::PageAreaSize(
+ static_cast<AllocationSpace>(space)));
if (space == NEW_SPACE) {
allocation = new_space()->AllocateRaw(size);
} else {
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
index 85281aa..430f31d 100644
--- node/deps/v8/src/heap/spaces.cc
+++ node/deps/v8/src/heap/spaces.cc
@@ -892,19 +892,15 @@ void MemoryChunk::IncrementLiveBytesFromMutator(Address address, int by) {
// -----------------------------------------------------------------------------
// PagedSpace implementation
-PagedSpace::PagedSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id,
+PagedSpace::PagedSpace(Heap* heap, intptr_t max_capacity, AllocationSpace space,
Executability executable)
- : Space(heap, id, executable),
+ : Space(heap, space, executable),
free_list_(this),
swept_precisely_(true),
unswept_free_bytes_(0),
end_of_unswept_pages_(NULL),
emergency_memory_(NULL) {
- if (id == CODE_SPACE) {
- area_size_ = heap->isolate()->memory_allocator()->CodePageAreaSize();
- } else {
- area_size_ = Page::kPageSize - Page::kObjectStartOffset;
- }
+ area_size_ = MemoryAllocator::PageAreaSize(space);
max_capacity_ =
(RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) * AreaSize();
accounting_stats_.Clear();
diff --git a/src/heap/spaces.h b/src/heap/spaces.h
index 5be9c3a..1944464 100644
--- node/deps/v8/src/heap/spaces.h
+++ node/deps/v8/src/heap/spaces.h
@@ -1104,6 +1104,12 @@ class MemoryAllocator {
return CodePageAreaEndOffset() - CodePageAreaStartOffset();
}
+ static int PageAreaSize(AllocationSpace space) {
+ DCHECK_NE(LO_SPACE, space);
+ return (space == CODE_SPACE) ? CodePageAreaSize()
+ : Page::kMaxRegularHeapObjectSize;
+ }
+
MUST_USE_RESULT bool CommitExecutableMemory(base::VirtualMemory* vm,
Address start, size_t commit_size,
size_t reserved_size);
diff --git a/src/serialize.cc b/src/serialize.cc
index 86045d3..df62adb 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -1258,10 +1258,15 @@ Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
root_index_map_(isolate),
code_address_map_(NULL),
+ large_objects_total_size_(0),
seen_large_objects_index_(0) {
// The serializer is meant to be used only to generate initial heap images
// from a context in which there is only one isolate.
- for (int i = 0; i < kNumberOfSpaces; i++) pending_chunk_[i] = 0;
+ for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
+ pending_chunk_[i] = 0;
+ max_chunk_size_[i] = static_cast<uint32_t>(
+ MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i)));
+ }
}
@@ -1336,8 +1341,7 @@ void Serializer::VisitPointers(Object** start, Object** end) {
void Serializer::FinalizeAllocation() {
- DCHECK_EQ(0, completed_chunks_[LO_SPACE].length()); // Not yet finalized.
- for (int i = 0; i < kNumberOfSpaces; i++) {
+ for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
// Complete the last pending chunk and if there are no completed chunks,
// make sure there is at least one empty chunk.
if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) {
@@ -1906,17 +1910,17 @@ AllocationSpace Serializer::SpaceOfObject(HeapObject* object) {
uint32_t Serializer::AllocateLargeObject(int size) {
// Large objects are allocated one-by-one when deserializing. We do not
// have to keep track of multiple chunks.
- pending_chunk_[LO_SPACE] += size;
+ large_objects_total_size_ += size;
return seen_large_objects_index_++;
}
uint32_t Serializer::Allocate(int space, int size) {
CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
- DCHECK(size > 0 && size <= Page::kMaxRegularHeapObjectSize);
+ DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space)));
uint32_t new_chunk_size = pending_chunk_[space] + size;
uint32_t allocation;
- if (new_chunk_size > static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize)) {
+ if (new_chunk_size > max_chunk_size(space)) {
// The new chunk size would not fit onto a single page. Complete the
// current chunk and start a new one.
completed_chunks_[space].Add(pending_chunk_[space]);
@@ -1929,15 +1933,6 @@ BackReference Serializer::Allocate(AllocationSpace space, int size) {
}
-int Serializer::SpaceAreaSize(int space) {
- if (space == CODE_SPACE) {
- return isolate_->memory_allocator()->CodePageAreaSize();
- } else {
- return Page::kPageSize - Page::kObjectStartOffset;
- }
-}
-
-
void Serializer::Pad() {
// The non-branching GetInt will read up to 3 bytes too far, so we need
// to pad the snapshot to make sure we don't read over the end.
@@ -2273,9 +2268,6 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) {
Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i);
for (int j = 0; j < chunks.length(); j++) {
- DCHECK(i == LO_SPACE ||
- chunks[j] <=
- static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
uint32_t chunk = ChunkSizeBits::encode(chunks[j]) |
IsLastChunkBits::encode(j == chunks.length() - 1);
reservations.Add(chunk);
diff --git a/src/serialize.h b/src/serialize.h
index 2aa55ea..9c56118 100644
--- node/deps/v8/src/serialize.h
+++ node/deps/v8/src/serialize.h
@@ -404,8 +404,6 @@ class Deserializer: public SerializerDeserializer {
void AddReservation(int space, uint32_t chunk) {
DCHECK(space >= 0);
DCHECK(space < kNumberOfSpaces);
- DCHECK(space == LO_SPACE ||
- chunk <= static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c);
}
@@ -498,9 +496,12 @@ class Serializer : public SerializerDeserializer {
void FinalizeAllocation();
Vector<const uint32_t> FinalAllocationChunks(int space) const {
- DCHECK_EQ(1, completed_chunks_[LO_SPACE].length()); // Already finalized.
- DCHECK_EQ(0, pending_chunk_[space]); // No pending chunks.
- return completed_chunks_[space].ToConstVector();
+ if (space == LO_SPACE) {
+ return Vector<const uint32_t>(&large_objects_total_size_, 1);
+ } else {
+ DCHECK_EQ(0, pending_chunk_[space]); // No pending chunks.
+ return completed_chunks_[space].ToConstVector();
+ }
}
Isolate* isolate() const { return isolate_; }
@@ -496,20 +496,25 @@
return external_reference_encoder_->Encode(addr);
}
- int SpaceAreaSize(int space);
-
// Some roots should not be serialized, because their actual value depends on
// absolute addresses and they are reset after deserialization, anyway.
bool ShouldBeSkipped(Object** current);
+ uint32_t max_chunk_size(int space) const {
+ DCHECK_LE(0, space);
+ DCHECK_LT(space, kNumberOfSpaces);
+ return max_chunk_size_[space];
+ }
+
Isolate* isolate_;
// Objects from the same space are put into chunks for bulk-allocation
// when deserializing. We have to make sure that each chunk fits into a
// page. So we track the chunk size in pending_chunk_ of a space, but
// when it exceeds a page, we complete the current chunk and start a new one.
- uint32_t pending_chunk_[kNumberOfSpaces];
- List<uint32_t> completed_chunks_[kNumberOfSpaces];
+ uint32_t pending_chunk_[kNumberOfPreallocatedSpaces];
+ List<uint32_t> completed_chunks_[kNumberOfPreallocatedSpaces];
+ uint32_t max_chunk_size_[kNumberOfPreallocatedSpaces];
SnapshotByteSink* sink_;
ExternalReferenceEncoder* external_reference_encoder_;
@@ -529,6 +534,7 @@
CodeAddressMap* code_address_map_;
// We map serialized large objects to indexes for back-referencing.
uint32_t seen_large_objects_index_;
+ uint32_t large_objects_total_size_;
DISALLOW_COPY_AND_ASSIGN(Serializer);
};

View File

@ -0,0 +1,117 @@
commit c64b47f55237a78b6d74baa1503e7218b94811e4
Author: yangguo <yangguo@chromium.org>
Date: Thu Nov 20 08:20:48 2014 -0800
When optimizing deserialized code, make sure IC state is preserved.
R=jkummerow@chromium.org
Review URL: https://codereview.chromium.org/737373003
Cr-Commit-Position: refs/heads/master@{#25444}
diff --git a/src/compiler.cc b/src/compiler.cc
index 3b612c1..33d88d7 100644
--- node/deps/v8/src/compiler.cc
+++ node/deps/v8/src/compiler.cc
@@ -384,13 +384,21 @@
if (FLAG_hydrogen_stats) {
timer.Start();
}
- CompilationInfoWithZone unoptimized(info()->shared_info());
+ Handle<SharedFunctionInfo> shared = info()->shared_info();
+ CompilationInfoWithZone unoptimized(shared);
// Note that we use the same AST that we will use for generating the
// optimized code.
unoptimized.SetFunction(info()->function());
unoptimized.PrepareForCompilation(info()->scope());
unoptimized.SetContext(info()->context());
if (should_recompile) unoptimized.EnableDeoptimizationSupport();
+ // If the current code has reloc info for serialization, also include
+ // reloc info for serialization for the new code, so that deopt support
+ // can be added without losing IC state.
+ if (shared->code()->kind() == Code::FUNCTION &&
+ shared->code()->has_reloc_info_for_serialization()) {
+ unoptimized.PrepareForSerializing();
+ }
bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
if (should_recompile) {
if (!succeeded) return SetLastStatus(FAILED);
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 535dcd2..0d7363e 100644
--- node/deps/v8/src/flag-definitions.h
+++ node/deps/v8/src/flag-definitions.h
@@ -427,7 +427,8 @@
DEFINE_BOOL(trace_stub_failures, false,
"trace deoptimization of generated code stubs")
-DEFINE_BOOL(serialize_toplevel, false, "enable caching of toplevel scripts")
+DEFINE_BOOL(serialize_toplevel, true, "enable caching of toplevel scripts")
+DEFINE_BOOL(serialize_inner, true, "enable caching of inner functions")
DEFINE_BOOL(trace_code_serializer, false, "trace code serializer")
// compiler.cc
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index e32c59f..cb8f4aa 100644
--- node/deps/v8/src/full-codegen.cc
+++ node/deps/v8/src/full-codegen.cc
@@ -321,6 +321,7 @@
cgen.PopulateDeoptimizationData(code);
cgen.PopulateTypeFeedbackInfo(code);
code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
+ code->set_has_reloc_info_for_serialization(info->will_serialize());
code->set_handler_table(*cgen.handler_table());
code->set_compiled_optimizable(info->IsOptimizable());
code->set_allow_osr_at_loop_nesting_level(0);
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 3dd6fed..108f9f6 100644
--- node/deps/v8/src/objects-inl.h
+++ node/deps/v8/src/objects-inl.h
@@ -4794,6 +4794,21 @@
}
+bool Code::has_reloc_info_for_serialization() {
+ DCHECK_EQ(FUNCTION, kind());
+ byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
+ return FullCodeFlagsHasRelocInfoForSerialization::decode(flags);
+}
+
+
+void Code::set_has_reloc_info_for_serialization(bool value) {
+ DCHECK_EQ(FUNCTION, kind());
+ byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
+ flags = FullCodeFlagsHasRelocInfoForSerialization::update(flags, value);
+ WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
+}
+
+
int Code::allow_osr_at_loop_nesting_level() {
DCHECK_EQ(FUNCTION, kind());
int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
diff --git a/src/objects.h b/src/objects.h
index 678dcb2..9569de9 100644
--- node/deps/v8/src/objects.h
+++ node/deps/v8/src/objects.h
@@ -5597,6 +5597,12 @@
inline bool is_compiled_optimizable();
inline void set_compiled_optimizable(bool value);
+ // [has_reloc_info_for_serialization]: For FUNCTION kind, tells if its
+ // reloc info includes runtime and external references to support
+ // serialization/deserialization.
+ inline bool has_reloc_info_for_serialization();
+ inline void set_has_reloc_info_for_serialization(bool value);
+
// [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
// how long the function has been marked for OSR and therefore which
// level of loop nesting we are willing to do on-stack replacement
@@ -5873,6 +5879,8 @@
public BitField<bool, 0, 1> {}; // NOLINT
class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
+ class FullCodeFlagsHasRelocInfoForSerialization
+ : public BitField<bool, 3, 1> {};
static const int kProfilerTicksOffset = kFullCodeFlags + 1;

1060
patches/node.v0.12.15.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,21 @@
{
"v0.12.5": [
"backport.R00000.patch",
"backport.R24002.patch",
"backport.R24204.patch",
"backport.R24262.patch",
"backport.R24266.patch",
"backport.R24523.patch",
"backport.R24543.patch",
"backport.R24639.patch",
"backport.R24642.patch",
"backport.R24643.patch",
"backport.R24644.patch",
"backport.R24824.patch",
"backport.R25039.patch",
"backport.R25444.patch",
"node.v0.12.15.patch"
],
"v4.4.7": [
"backport.R32768.v8=4.5.patch",
"node.v4.4.7.patch"