⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialize.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
// Copyright 2006-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:////     * Redistributions of source code must retain the above copyright//       notice, this list of conditions and the following disclaimer.//     * Redistributions in binary form must reproduce the above//       copyright notice, this list of conditions and the following//       disclaimer in the documentation and/or other materials provided//       with the distribution.//     * Neither the name of Google Inc. nor the names of its//       contributors may be used to endorse or promote products derived//       from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include "v8.h"#include "accessors.h"#include "api.h"#include "execution.h"#include "global-handles.h"#include "ic-inl.h"#include "natives.h"#include "platform.h"#include "runtime.h"#include "serialize.h"#include "stub-cache.h"#include "v8threads.h"namespace v8 { namespace internal {// Encoding: a RelativeAddress must be able to fit in a pointer:// it is encoded as an Address with (from MS to LS bits):// 27 bits identifying a word in the space, in one of three formats:// - MAP and OLD spaces: 16 bits of page number, 11 bits of word offset in page// - NEW space:          27 bits of word offset// - LO space:           27 bits of page number// 3 bits to encode the AllocationSpace (special values for code in LO space)// 2 bits identifying this as a HeapObjectconst int kSpaceShift = kHeapObjectTagSize;const int kSpaceBits = kSpaceTagSize;const int kSpaceMask = kSpaceTagMask;// These value are used instead of space numbers when serializing/// deserializing.  They indicate an object that is in large object space, but// should be treated specially.// Make the pages executable on platforms that support it:const int kLOSpaceExecutable = LAST_SPACE + 1;// Reserve space for write barrier bits (for objects that can contain// references to new space):const int kLOSpacePointer = LAST_SPACE + 2;const int kOffsetShift = kSpaceShift + kSpaceBits;const int kOffsetBits = 11;const int kOffsetMask = (1 << kOffsetBits) - 1;const int kPageBits = 32 - (kOffsetBits + kSpaceBits + kHeapObjectTagSize);const int kPageShift = kOffsetShift + kOffsetBits;const int kPageMask = (1 << kPageBits) - 1;const int kPageAndOffsetShift = kOffsetShift;const int kPageAndOffsetBits = kPageBits + kOffsetBits;const int kPageAndOffsetMask = (1 << kPageAndOffsetBits) - 1;static inline AllocationSpace GetSpace(Address addr) {  const int encoded = reinterpret_cast<int>(addr);  int space_number = ((encoded >> kSpaceShift) & kSpaceMask);  if (space_number == kLOSpaceExecutable) space_number = LO_SPACE;  else if (space_number == kLOSpacePointer) space_number = LO_SPACE;  return static_cast<AllocationSpace>(space_number);}static inline bool IsLargeExecutableObject(Address addr) {  const int encoded = reinterpret_cast<int>(addr);  const int space_number = ((encoded >> kSpaceShift) & kSpaceMask);  if (space_number == kLOSpaceExecutable) return true;  return false;}static inline bool IsLargeFixedArray(Address addr) {  const int encoded = reinterpret_cast<int>(addr);  const int space_number = ((encoded >> kSpaceShift) & kSpaceMask);  if (space_number == kLOSpacePointer) return true;  return false;}static inline int PageIndex(Address addr) {  const int encoded = reinterpret_cast<int>(addr);  return (encoded >> kPageShift) & kPageMask;}static inline int PageOffset(Address addr) {  const int encoded = reinterpret_cast<int>(addr);  return ((encoded >> kOffsetShift) & kOffsetMask) << kObjectAlignmentBits;}static inline int NewSpaceOffset(Address addr) {  const int encoded = reinterpret_cast<int>(addr);  return ((encoded >> kPageAndOffsetShift) & kPageAndOffsetMask) <<      kObjectAlignmentBits;}static inline int LargeObjectIndex(Address addr) {  const int encoded = reinterpret_cast<int>(addr);  return (encoded >> kPageAndOffsetShift) & kPageAndOffsetMask;}// A RelativeAddress encodes a heap address that is independent of// the actual memory addresses in real heap. The general case (for the// OLD, CODE and MAP spaces) is as a (space id, page number, page offset)// triple. The NEW space has page number == 0, because there are no// pages. The LARGE_OBJECT space has page offset = 0, since there is// exactly one object per page.  RelativeAddresses are encodable as// Addresses, so that they can replace the map() pointers of// HeapObjects. The encoded Addresses are also encoded as HeapObjects// and allow for marking (is_marked() see mark(), clear_mark()...) as// used by the Mark-Compact collector.class RelativeAddress { public:  RelativeAddress(AllocationSpace space,                  int page_index,                  int page_offset)  : space_(space), page_index_(page_index), page_offset_(page_offset)  {    ASSERT(space <= LAST_SPACE && space >= 0);  }  // Return the encoding of 'this' as an Address. Decode with constructor.  Address Encode() const;  AllocationSpace space() const {    if (space_ == kLOSpaceExecutable) return LO_SPACE;    if (space_ == kLOSpacePointer) return LO_SPACE;    return static_cast<AllocationSpace>(space_);  }  int page_index() const { return page_index_; }  int page_offset() const { return page_offset_; }  bool in_paged_space() const {    return space_ == CODE_SPACE ||           space_ == OLD_POINTER_SPACE ||           space_ == OLD_DATA_SPACE ||           space_ == MAP_SPACE;  }  void next_address(int offset) { page_offset_ += offset; }  void next_page(int init_offset = 0) {    page_index_++;    page_offset_ = init_offset;  }#ifdef DEBUG  void Verify();#endif  void set_to_large_code_object() {    ASSERT(space_ == LO_SPACE);    space_ = kLOSpaceExecutable;  }  void set_to_large_fixed_array() {    ASSERT(space_ == LO_SPACE);    space_ = kLOSpacePointer;  } private:  int space_;  int page_index_;  int page_offset_;};Address RelativeAddress::Encode() const {  ASSERT(page_index_ >= 0);  int word_offset = 0;  int result = 0;  switch (space_) {    case MAP_SPACE:    case OLD_POINTER_SPACE:    case OLD_DATA_SPACE:    case CODE_SPACE:      ASSERT_EQ(0, page_index_ & ~kPageMask);      word_offset = page_offset_ >> kObjectAlignmentBits;      ASSERT_EQ(0, word_offset & ~kOffsetMask);      result = (page_index_ << kPageShift) | (word_offset << kOffsetShift);      break;    case NEW_SPACE:      ASSERT_EQ(0, page_index_);      word_offset = page_offset_ >> kObjectAlignmentBits;      ASSERT_EQ(0, word_offset & ~kPageAndOffsetMask);      result = word_offset << kPageAndOffsetShift;      break;    case LO_SPACE:    case kLOSpaceExecutable:    case kLOSpacePointer:      ASSERT_EQ(0, page_offset_);      ASSERT_EQ(0, page_index_ & ~kPageAndOffsetMask);      result = page_index_ << kPageAndOffsetShift;      break;  }  // OR in AllocationSpace and kHeapObjectTag  ASSERT_EQ(0, space_ & ~kSpaceMask);  result |= (space_ << kSpaceShift) | kHeapObjectTag;  return reinterpret_cast<Address>(result);}#ifdef DEBUGvoid RelativeAddress::Verify() {  ASSERT(page_offset_ >= 0 && page_index_ >= 0);  switch (space_) {    case MAP_SPACE:    case OLD_POINTER_SPACE:    case OLD_DATA_SPACE:    case CODE_SPACE:      ASSERT(Page::kObjectStartOffset <= page_offset_ &&             page_offset_ <= Page::kPageSize);      break;    case NEW_SPACE:      ASSERT(page_index_ == 0);      break;    case LO_SPACE:    case kLOSpaceExecutable:    case kLOSpacePointer:      ASSERT(page_offset_ == 0);      break;  }}#endifenum GCTreatment {  DataObject,     // Object that cannot contain a reference to new space.  PointerObject,  // Object that can contain a reference to new space.  CodeObject      // Object that contains executable code.};// A SimulatedHeapSpace simulates the allocation of objects in a page in// the heap. It uses linear allocation - that is, it doesn't simulate the// use of a free list. This simulated// allocation must exactly match that done by Heap.class SimulatedHeapSpace { public:  // The default constructor initializes to an invalid state.  SimulatedHeapSpace(): current_(LAST_SPACE, -1, -1) {}  // Sets 'this' to the first address in 'space' that would be  // returned by allocation in an empty heap.  void InitEmptyHeap(AllocationSpace space);  // Sets 'this' to the next address in 'space' that would be returned  // by allocation in the current heap. Intended only for testing  // serialization and deserialization in the current address space.  void InitCurrentHeap(AllocationSpace space);  // Returns the RelativeAddress where the next  // object of 'size' bytes will be allocated, and updates 'this' to  // point to the next free address beyond that object.  RelativeAddress Allocate(int size, GCTreatment special_gc_treatment); private:  RelativeAddress current_;};void SimulatedHeapSpace::InitEmptyHeap(AllocationSpace space) {  switch (space) {    case MAP_SPACE:    case OLD_POINTER_SPACE:    case OLD_DATA_SPACE:    case CODE_SPACE:      current_ = RelativeAddress(space, 0, Page::kObjectStartOffset);      break;    case NEW_SPACE:    case LO_SPACE:      current_ = RelativeAddress(space, 0, 0);      break;  }}void SimulatedHeapSpace::InitCurrentHeap(AllocationSpace space) {  switch (space) {    case MAP_SPACE:    case OLD_POINTER_SPACE:    case OLD_DATA_SPACE:    case CODE_SPACE: {      PagedSpace* ps;      if (space == MAP_SPACE) {        ps = Heap::map_space();      } else if (space == OLD_POINTER_SPACE) {        ps = Heap::old_pointer_space();      } else if (space == OLD_DATA_SPACE) {        ps = Heap::old_data_space();      } else {        ASSERT(space == CODE_SPACE);        ps = Heap::code_space();      }      Address top = ps->top();      Page* top_page = Page::FromAllocationTop(top);      int page_index = 0;      PageIterator it(ps, PageIterator::PAGES_IN_USE);      while (it.has_next()) {        if (it.next() == top_page) break;        page_index++;      }      current_ = RelativeAddress(space,                                 page_index,                                 top_page->Offset(top));      break;    }    case NEW_SPACE:      current_ = RelativeAddress(space,                                 0,                                 Heap::NewSpaceTop() - Heap::NewSpaceStart());      break;    case LO_SPACE:      int page_index = 0;      for (LargeObjectIterator it(Heap::lo_space()); it.has_next(); it.next()) {        page_index++;      }      current_ = RelativeAddress(space, page_index, 0);      break;  }}RelativeAddress SimulatedHeapSpace::Allocate(int size,                                             GCTreatment special_gc_treatment) {#ifdef DEBUG  current_.Verify();#endif  int alloc_size = OBJECT_SIZE_ALIGN(size);  if (current_.in_paged_space() &&      current_.page_offset() + alloc_size > Page::kPageSize) {    ASSERT(alloc_size <= Page::kMaxHeapObjectSize);    current_.next_page(Page::kObjectStartOffset);  }  RelativeAddress result = current_;  if (current_.space() == LO_SPACE) {    current_.next_page();    if (special_gc_treatment == CodeObject) {      result.set_to_large_code_object();    } else if (special_gc_treatment == PointerObject) {      result.set_to_large_fixed_array();    }  } else {    current_.next_address(alloc_size);  }#ifdef DEBUG  current_.Verify();  result.Verify();#endif  return result;}// -----------------------------------------------------------------------------// Coding of external references.// The encoding of an external reference. The type is in the high word.// The id is in the low word.static uint32_t EncodeExternal(TypeCode type, uint16_t id) {  return static_cast<uint32_t>(type) << 16 | id;}static int* GetInternalPointer(StatsCounter* counter) {  // All counters refer to dummy_counter, if deserializing happens without  // setting up counters.  static int dummy_counter = 0;  return counter->Enabled() ? counter->GetInternalPointer() : &dummy_counter;}// ExternalReferenceTable is a helper class that defines the relationship// between external references and their encodings. It is used to build// hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.class ExternalReferenceTable { public:  static ExternalReferenceTable* instance() {    if (!instance_) instance_ = new ExternalReferenceTable();    return instance_;  }  int size() const { return refs_.length(); }  Address address(int i) { return refs_[i].address; }  uint32_t code(int i) { return refs_[i].code; }  const char* name(int i) { return refs_[i].name; }  int max_id(int code) { return max_id_[code]; } private:  static ExternalReferenceTable* instance_;  ExternalReferenceTable();  struct ExternalReferenceEntry {    Address address;    uint32_t code;    const char* name;  };  void Add(Address address, TypeCode type, uint16_t id, const char* name) {    CHECK_NE(NULL, address);    ExternalReferenceEntry entry;    entry.address = address;    entry.code = EncodeExternal(type, id);    entry.name = name;    CHECK_NE(0, entry.code);    refs_.Add(entry);    if (id > max_id_[type]) max_id_[type] = id;  }  List<ExternalReferenceEntry> refs_;  int max_id_[kTypeCodeCount];};ExternalReferenceTable* ExternalReferenceTable::instance_ = NULL;ExternalReferenceTable::ExternalReferenceTable() : refs_(64) {  for (int type_code = 0; type_code < kTypeCodeCount; type_code++) {    max_id_[type_code] = 0;  }  // Define all entries in the table.  // Builtins#define DEF_ENTRY_C(name) \  Add(Builtins::c_function_address(Builtins::c_##name), \      C_BUILTIN, \      Builtins::c_##name, \      "Builtins::" #name);  BUILTIN_LIST_C(DEF_ENTRY_C)#undef DEF_ENTRY_C#define DEF_ENTRY_C(name) \  Add(Builtins::builtin_address(Builtins::name), \      BUILTIN, \      Builtins::name, \      "Builtins::" #name);#define DEF_ENTRY_A(name, kind, state) DEF_ENTRY_C(name)  BUILTIN_LIST_C(DEF_ENTRY_C)  BUILTIN_LIST_A(DEF_ENTRY_A)#undef DEF_ENTRY_C#undef DEF_ENTRY_A  // Runtime functions#define RUNTIME_ENTRY(name, nargs) \  Add(Runtime::FunctionForId(Runtime::k##name)->entry, \      RUNTIME_FUNCTION, \      Runtime::k##name, \      "Runtime::" #name);  RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY)#undef RUNTIME_ENTRY  // IC utilities#define IC_ENTRY(name) \  Add(IC::AddressFromUtilityId(IC::k##name), \      IC_UTILITY, \      IC::k##name, \      "IC::" #name);  IC_UTIL_LIST(IC_ENTRY)#undef IC_ENTRY  // Debug addresses  Add(Debug_Address(Debug::k_after_break_target_address).address(),      DEBUG_ADDRESS,      Debug::k_after_break_target_address << kDebugIdShift,      "Debug::after_break_target_address()");  Add(Debug_Address(Debug::k_debug_break_return_address).address(),      DEBUG_ADDRESS,      Debug::k_debug_break_return_address << kDebugIdShift,      "Debug::debug_break_return_address()");  const char* debug_register_format = "Debug::register_address(%i)";  size_t dr_format_length = strlen(debug_register_format);  for (int i = 0; i < kNumJSCallerSaved; ++i) {    Vector<char> name = Vector<char>::New(dr_format_length + 1);    OS::SNPrintF(name, debug_register_format, i);    Add(Debug_Address(Debug::k_register_address, i).address(),        DEBUG_ADDRESS,        Debug::k_register_address << kDebugIdShift | i,        name.start());  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -