📄 serialize.cc.svn-base
字号:
// Stat counters#define COUNTER_ENTRY(name, caption) \ Add(reinterpret_cast<Address>(GetInternalPointer(&Counters::name)), \ STATS_COUNTER, \ Counters::k_##name, \ "Counters::" #name); STATS_COUNTER_LIST_1(COUNTER_ENTRY) STATS_COUNTER_LIST_2(COUNTER_ENTRY)#undef COUNTER_ENTRY // Top addresses const char* top_address_format = "Top::get_address_from_id(%i)"; size_t top_format_length = strlen(top_address_format); for (uint16_t i = 0; i < Top::k_top_address_count; ++i) { Vector<char> name = Vector<char>::New(top_format_length + 1); const char* chars = name.start(); OS::SNPrintF(name, top_address_format, i); Add(Top::get_address_from_id((Top::AddressId)i), TOP_ADDRESS, i, chars); } // Extensions Add(FUNCTION_ADDR(GCExtension::GC), EXTENSION, 1, "GCExtension::GC"); Add(FUNCTION_ADDR(PrintExtension::Print), EXTENSION, 2, "PrintExtension::Print"); Add(FUNCTION_ADDR(LoadExtension::Load), EXTENSION, 3, "LoadExtension::Load"); Add(FUNCTION_ADDR(QuitExtension::Quit), EXTENSION, 4, "QuitExtension::Quit"); // Accessors#define ACCESSOR_DESCRIPTOR_DECLARATION(name) \ Add((Address)&Accessors::name, \ ACCESSOR, \ Accessors::k##name, \ "Accessors::" #name); ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)#undef ACCESSOR_DESCRIPTOR_DECLARATION // Stub cache tables Add(SCTableReference::keyReference(StubCache::kPrimary).address(), STUB_CACHE_TABLE, 1, "StubCache::primary_->key"); Add(SCTableReference::valueReference(StubCache::kPrimary).address(), STUB_CACHE_TABLE, 2, "StubCache::primary_->value"); Add(SCTableReference::keyReference(StubCache::kSecondary).address(), STUB_CACHE_TABLE, 3, "StubCache::secondary_->key"); Add(SCTableReference::valueReference(StubCache::kSecondary).address(), STUB_CACHE_TABLE, 4, "StubCache::secondary_->value"); // Runtime entries Add(FUNCTION_ADDR(Runtime::PerformGC), RUNTIME_ENTRY, 1, "Runtime::PerformGC"); // Miscellaneous Add(ExternalReference::builtin_passed_function().address(), UNCLASSIFIED, 1, "Builtins::builtin_passed_function"); Add(ExternalReference::the_hole_value_location().address(), UNCLASSIFIED, 2, "Factory::the_hole_value().location()"); Add(ExternalReference::address_of_stack_guard_limit().address(), UNCLASSIFIED, 3, "StackGuard::address_of_limit()"); Add(ExternalReference::debug_break().address(), UNCLASSIFIED, 4, "Debug::Break()"); Add(ExternalReference::new_space_start().address(), UNCLASSIFIED, 5, "Heap::NewSpaceStart()"); Add(ExternalReference::new_space_allocation_limit_address().address(), UNCLASSIFIED, 6, "Heap::NewSpaceAllocationLimitAddress()"); Add(ExternalReference::new_space_allocation_top_address().address(), UNCLASSIFIED, 7, "Heap::NewSpaceAllocationTopAddress()"); Add(ExternalReference::debug_step_in_fp_address().address(), UNCLASSIFIED, 8, "Debug::step_in_fp_addr()");}ExternalReferenceEncoder::ExternalReferenceEncoder() : encodings_(Match) { ExternalReferenceTable* external_references = ExternalReferenceTable::instance(); for (int i = 0; i < external_references->size(); ++i) { Put(external_references->address(i), i); }}uint32_t ExternalReferenceEncoder::Encode(Address key) const { int index = IndexOf(key); return index >=0 ? ExternalReferenceTable::instance()->code(index) : 0;}const char* ExternalReferenceEncoder::NameOfAddress(Address key) const { int index = IndexOf(key); return index >=0 ? ExternalReferenceTable::instance()->name(index) : NULL;}int ExternalReferenceEncoder::IndexOf(Address key) const { if (key == NULL) return -1; HashMap::Entry* entry = const_cast<HashMap &>(encodings_).Lookup(key, Hash(key), false); return entry == NULL ? -1 : reinterpret_cast<int>(entry->value);}void ExternalReferenceEncoder::Put(Address key, int index) { HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true); entry->value = reinterpret_cast<void *>(index);}ExternalReferenceDecoder::ExternalReferenceDecoder() : encodings_(NewArray<Address*>(kTypeCodeCount)) { ExternalReferenceTable* external_references = ExternalReferenceTable::instance(); for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) { int max = external_references->max_id(type) + 1; encodings_[type] = NewArray<Address>(max + 1); } for (int i = 0; i < external_references->size(); ++i) { Put(external_references->code(i), external_references->address(i)); }}ExternalReferenceDecoder::~ExternalReferenceDecoder() { for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) { DeleteArray(encodings_[type]); } DeleteArray(encodings_);}//------------------------------------------------------------------------------// Implementation of Serializer// Helper class to write the bytes of the serialized heap.class SnapshotWriter { public: SnapshotWriter() { len_ = 0; max_ = 8 << 10; // 8K initial size str_ = NewArray<char>(max_); } ~SnapshotWriter() { DeleteArray(str_); } void GetString(char** str, int* len) { *str = NewArray<char>(len_); memcpy(*str, str_, len_); *len = len_; } void Reserve(int bytes, int pos); void PutC(char c) { InsertC(c, len_); } void PutInt(int i) { InsertInt(i, len_); } void PutBytes(const byte* a, int size) { InsertBytes(a, len_, size); } void PutString(const char* s) { InsertString(s, len_); } int InsertC(char c, int pos) { Reserve(1, pos); str_[pos] = c; len_++; return pos + 1; } int InsertInt(int i, int pos) { return InsertBytes(reinterpret_cast<byte*>(&i), pos, sizeof(i)); } int InsertBytes(const byte* a, int pos, int size) { Reserve(size, pos); memcpy(&str_[pos], a, size); len_ += size; return pos + size; } int InsertString(const char* s, int pos); int length() { return len_; } Address position() { return reinterpret_cast<Address>(&str_[len_]); } private: char* str_; // the snapshot int len_; // the curent length of str_ int max_; // the allocated size of str_};void SnapshotWriter::Reserve(int bytes, int pos) { CHECK(0 <= pos && pos <= len_); while (len_ + bytes >= max_) { max_ *= 2; char* old = str_; str_ = NewArray<char>(max_); memcpy(str_, old, len_); DeleteArray(old); } if (pos < len_) { char* old = str_; str_ = NewArray<char>(max_); memcpy(str_, old, pos); memcpy(str_ + pos + bytes, old + pos, len_ - pos); DeleteArray(old); }}int SnapshotWriter::InsertString(const char* s, int pos) { int size = strlen(s); pos = InsertC('[', pos); pos = InsertInt(size, pos); pos = InsertC(']', pos); return InsertBytes(reinterpret_cast<const byte*>(s), pos, size);}class ReferenceUpdater: public ObjectVisitor { public: ReferenceUpdater(HeapObject* obj, Serializer* serializer) : obj_address_(obj->address()), serializer_(serializer), reference_encoder_(serializer->reference_encoder_), offsets_(8), addresses_(8) { } virtual void VisitPointers(Object** start, Object** end) { for (Object** p = start; p < end; ++p) { if ((*p)->IsHeapObject()) { offsets_.Add(reinterpret_cast<Address>(p) - obj_address_); Address a = serializer_->GetSavedAddress(HeapObject::cast(*p)); addresses_.Add(a); } } } virtual void VisitExternalReferences(Address* start, Address* end) { for (Address* p = start; p < end; ++p) { uint32_t code = reference_encoder_->Encode(*p); CHECK(*p == NULL ? code == 0 : code != 0); offsets_.Add(reinterpret_cast<Address>(p) - obj_address_); addresses_.Add(reinterpret_cast<Address>(code)); } } virtual void VisitRuntimeEntry(RelocInfo* rinfo) { Address target = rinfo->target_address(); uint32_t encoding = reference_encoder_->Encode(target); CHECK(target == NULL ? encoding == 0 : encoding != 0); offsets_.Add(reinterpret_cast<Address>(rinfo->pc()) - obj_address_); addresses_.Add(reinterpret_cast<Address>(encoding)); } void Update(Address start_address) { for (int i = 0; i < offsets_.length(); i++) { Address* p = reinterpret_cast<Address*>(start_address + offsets_[i]); *p = addresses_[i]; } } private: Address obj_address_; Serializer* serializer_; ExternalReferenceEncoder* reference_encoder_; List<int> offsets_; List<Address> addresses_;};// Helper functions for a map of encoded heap object addresses.static uint32_t HeapObjectHash(HeapObject* key) { return reinterpret_cast<uint32_t>(key) >> 2;}static bool MatchHeapObject(void* key1, void* key2) { return key1 == key2;}Serializer::Serializer() : global_handles_(4), saved_addresses_(MatchHeapObject) { root_ = true; roots_ = 0; objects_ = 0; reference_encoder_ = NULL; writer_ = new SnapshotWriter(); for (int i = 0; i <= LAST_SPACE; i++) { allocator_[i] = new SimulatedHeapSpace(); }}Serializer::~Serializer() { for (int i = 0; i <= LAST_SPACE; i++) { delete allocator_[i]; } if (reference_encoder_) delete reference_encoder_; delete writer_;}bool Serializer::serialization_enabled_ = true;#ifdef DEBUGstatic const int kMaxTagLength = 32;void Serializer::Synchronize(const char* tag) { if (FLAG_debug_serialization) { int length = strlen(tag); ASSERT(length <= kMaxTagLength); writer_->PutC('S'); writer_->PutInt(length); writer_->PutBytes(reinterpret_cast<const byte*>(tag), length); }}#endifvoid Serializer::InitializeAllocators() { for (int i = 0; i <= LAST_SPACE; i++) { allocator_[i]->InitEmptyHeap(static_cast<AllocationSpace>(i)); }}bool Serializer::IsVisited(HeapObject *obj) { HashMap::Entry* entry = saved_addresses_.Lookup(obj, HeapObjectHash(obj), false); return entry != NULL;}Address Serializer::GetSavedAddress(HeapObject *obj) { HashMap::Entry* entry = saved_addresses_.Lookup(obj, HeapObjectHash(obj), false); ASSERT(entry != NULL); return reinterpret_cast<Address>(entry->value);}void Serializer::SaveAddress(HeapObject* obj, Address addr) { HashMap::Entry* entry = saved_addresses_.Lookup(obj, HeapObjectHash(obj), true); entry->value = addr;}void Serializer::Serialize() { // No active threads. CHECK_EQ(NULL, ThreadState::FirstInUse()); // No active or weak handles. CHECK(HandleScopeImplementer::instance()->Blocks()->is_empty()); CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles()); // We need a counter function during serialization to resolve the // references to counters in the code on the heap. CHECK(StatsTable::HasCounterFunction()); CHECK(enabled()); InitializeAllocators(); reference_encoder_ = new ExternalReferenceEncoder(); PutHeader(); Heap::IterateRoots(this); PutLog(); PutContextStack(); disable();}void Serializer::Finalize(char** str, int* len) { writer_->GetString(str, len);}// Serialize objects by writing them into the stream.void Serializer::VisitPointers(Object** start, Object** end) { bool root = root_; root_ = false; for (Object** p = start; p < end; ++p) { bool serialized; Address a = Encode(*p, &serialized); if (root) { roots_++; // If the object was not just serialized, // write its encoded address instead. if (!serialized) PutEncodedAddress(a); } } root_ = root;}class GlobalHandlesRetriever: public ObjectVisitor { public: explicit GlobalHandlesRetriever(List<Object**>* handles) : global_handles_(handles) {} virtual void VisitPointers(Object** start, Object** end) { for (; start != end; ++start) { global_handles_->Add(start); } } private: List<Object**>* global_handles_;};void Serializer::PutFlags() { writer_->PutC('F'); List<char*>* argv = FlagList::argv(); writer_->PutInt(argv->length()); writer_->PutC('['); for (int i = 0; i < argv->length(); i++) { if (i > 0) writer_->PutC('|'); writer_->PutString((*argv)[i]); DeleteArray((*argv)[i]); } writer_->PutC(']'); flags_end_ = writer_->length(); delete argv;}void Serializer::PutHeader() { PutFlags(); writer_->PutC('D');#ifdef DEBUG writer_->PutC(FLAG_debug_serialization ? '1' : '0');#else writer_->PutC('0');#endif // Write sizes of paged memory spaces. Allocate extra space for the old // and code spaces, because objects in new space will be promoted to them. writer_->PutC('S'); writer_->PutC('['); writer_->PutInt(Heap::old_pointer_space()->Size() + Heap::new_space()->Size()); writer_->PutC('|'); writer_->PutInt(Heap::old_data_space()->Size() + Heap::new_space()->Size()); writer_->PutC('|'); writer_->PutInt(Heap::code_space()->Size() + Heap::new_space()->Size()); writer_->PutC('|'); writer_->PutInt(Heap::map_space()->Size()); writer_->PutC(']'); // Write global handles. writer_->PutC('G'); writer_->PutC('['); GlobalHandlesRetriever ghr(&global_handles_); GlobalHandles::IterateRoots(&ghr); for (int i = 0; i < global_handles_.length(); i++) { writer_->PutC('N'); } writer_->PutC(']');}void Serializer::PutLog() {#ifdef ENABLE_LOGGING_AND_PROFILING if (FLAG_log_code) { Logger::TearDown(); int pos = writer_->InsertC('L', flags_end_); bool exists; Vector<const char> log = ReadFile(FLAG_logfile, &exists); writer_->InsertString(log.start(), pos); log.Dispose(); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -