Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / v8 / src / serialize.h
index 9e3cc88..71b274b 100644 (file)
@@ -5,7 +5,11 @@
 #ifndef V8_SERIALIZE_H_
 #define V8_SERIALIZE_H_
 
+#include "src/compiler.h"
 #include "src/hashmap.h"
+#include "src/heap-profiler.h"
+#include "src/isolate.h"
+#include "src/snapshot-source-sink.h"
 
 namespace v8 {
 namespace internal {
@@ -13,17 +17,16 @@ namespace internal {
 // A TypeCode is used to distinguish different kinds of external reference.
 // It is a single bit to make testing for types easy.
 enum TypeCode {
-  UNCLASSIFIED,        // One-of-a-kind references.
+  UNCLASSIFIED,  // One-of-a-kind references.
+  C_BUILTIN,
   BUILTIN,
   RUNTIME_FUNCTION,
   IC_UTILITY,
   STATS_COUNTER,
   TOP_ADDRESS,
-  C_BUILTIN,
-  EXTENSION,
   ACCESSOR,
-  RUNTIME_ENTRY,
   STUB_CACHE_TABLE,
+  RUNTIME_ENTRY,
   LAZY_DEOPTIMIZATION
 };
 
@@ -77,8 +80,12 @@ class ExternalReferenceTable {
   // For other types of references, the caller will figure out the address.
   void Add(Address address, TypeCode type, uint16_t id, const char* name);
 
+  void Add(Address address, const char* name) {
+    Add(address, UNCLASSIFIED, ++max_id_[UNCLASSIFIED], name);
+  }
+
   List<ExternalReferenceEntry> refs_;
-  int max_id_[kTypeCodeCount];
+  uint16_t max_id_[kTypeCodeCount];
 };
 
 
@@ -119,7 +126,7 @@ class ExternalReferenceDecoder {
 
   Address* Lookup(uint32_t key) const {
     int type = key >> kReferenceTypeShift;
-    ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount);
+    DCHECK(kFirstTypeCode <= type && type < kTypeCodeCount);
     int id = key & kReferenceIdMask;
     return &encodings_[type][id];
   }
@@ -132,49 +139,6 @@ class ExternalReferenceDecoder {
 };
 
 
-class SnapshotByteSource {
- public:
-  SnapshotByteSource(const byte* array, int length)
-    : data_(array), length_(length), position_(0) { }
-
-  bool HasMore() { return position_ < length_; }
-
-  int Get() {
-    ASSERT(position_ < length_);
-    return data_[position_++];
-  }
-
-  int32_t GetUnalignedInt() {
-#if defined(V8_HOST_CAN_READ_UNALIGNED) &&  __BYTE_ORDER == __LITTLE_ENDIAN
-    int32_t answer;
-    ASSERT(position_ + sizeof(answer) <= length_ + 0u);
-    answer = *reinterpret_cast<const int32_t*>(data_ + position_);
-#else
-    int32_t answer = data_[position_];
-    answer |= data_[position_ + 1] << 8;
-    answer |= data_[position_ + 2] << 16;
-    answer |= data_[position_ + 3] << 24;
-#endif
-    return answer;
-  }
-
-  void Advance(int by) { position_ += by; }
-
-  inline void CopyRaw(byte* to, int number_of_bytes);
-
-  inline int GetInt();
-
-  bool AtEOF();
-
-  int position() { return position_; }
-
- private:
-  const byte* data_;
-  int length_;
-  int position_;
-};
-
-
 // The Serializer/Deserializer class is a common superclass for Serializer and
 // Deserializer which is used to store common constants and methods used by
 // both.
@@ -187,17 +151,18 @@ class SerializerDeserializer: public ObjectVisitor {
  protected:
   // Where the pointed-to object can be found:
   enum Where {
-    kNewObject = 0,                 // Object is next in snapshot.
+    kNewObject = 0,  // Object is next in snapshot.
     // 1-6                             One per space.
-    kRootArray = 0x9,               // Object is found in root array.
-    kPartialSnapshotCache = 0xa,    // Object is in the cache.
-    kExternalReference = 0xb,       // Pointer to an external reference.
-    kSkip = 0xc,                    // Skip n bytes.
-    kNop = 0xd,                     // Does nothing, used to pad.
-    // 0xe-0xf                         Free.
-    kBackref = 0x10,                // Object is described relative to end.
+    kRootArray = 0x9,             // Object is found in root array.
+    kPartialSnapshotCache = 0xa,  // Object is in the cache.
+    kExternalReference = 0xb,     // Pointer to an external reference.
+    kSkip = 0xc,                  // Skip n bytes.
+    kBuiltin = 0xd,               // Builtin code object.
+    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.
-    kBackrefWithSkip = 0x18,        // Object is described relative to end.
+    kBackrefWithSkip = 0x18,  // Object is described relative to end.
     // 0x19-0x1e                       One per space.
     // 0x20-0x3f                       Used by misc. tags below.
     kPointedToMask = 0x3f
@@ -246,11 +211,11 @@ class SerializerDeserializer: public ObjectVisitor {
   // 0x73-0x7f            Repeat last word (subtract 0x72 to get the count).
   static const int kMaxRepeats = 0x7f - 0x72;
   static int CodeForRepeats(int repeats) {
-    ASSERT(repeats >= 1 && repeats <= kMaxRepeats);
+    DCHECK(repeats >= 1 && repeats <= kMaxRepeats);
     return 0x72 + repeats;
   }
   static int RepeatsForCode(int byte_code) {
-    ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f);
+    DCHECK(byte_code >= kConstantRepeat && byte_code <= 0x7f);
     return byte_code - 0x72;
   }
   static const int kRootArrayConstants = 0xa0;
@@ -268,26 +233,6 @@ class SerializerDeserializer: public ObjectVisitor {
 };
 
 
-int SnapshotByteSource::GetInt() {
-  // This way of variable-length encoding integers does not suffer from branch
-  // mispredictions.
-  uint32_t answer = GetUnalignedInt();
-  int bytes = answer & 3;
-  Advance(bytes);
-  uint32_t mask = 0xffffffffu;
-  mask >>= 32 - (bytes << 3);
-  answer &= mask;
-  answer >>= 2;
-  return answer;
-}
-
-
-void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
-  MemCopy(to, data_ + position_, number_of_bytes);
-  position_ += number_of_bytes;
-}
-
-
 // A Deserializer reads a snapshot and reconstructs the Object graph it defines.
 class Deserializer: public SerializerDeserializer {
  public:
@@ -303,11 +248,21 @@ class Deserializer: public SerializerDeserializer {
   void DeserializePartial(Isolate* isolate, Object** root);
 
   void set_reservation(int space_number, int reservation) {
-    ASSERT(space_number >= 0);
-    ASSERT(space_number <= LAST_SPACE);
+    DCHECK(space_number >= 0);
+    DCHECK(space_number <= LAST_SPACE);
     reservations_[space_number] = reservation;
   }
 
+  void FlushICacheForNewCodeObjects();
+
+  // 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<Handle<Object> >* attached_objects) {
+    attached_objects_ = attached_objects;
+  }
+
+  bool deserializing_user_code() { return attached_objects_ != NULL; }
+
  private:
   virtual void VisitPointers(Object** start, Object** end);
 
@@ -328,16 +283,16 @@ class Deserializer: public SerializerDeserializer {
       Object** start, Object** end, int space, Address object_address);
   void ReadObject(int space_number, Object** write_back);
 
+  // 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;
-    HeapProfiler* profiler = isolate_->heap_profiler();
-    if (profiler->is_tracking_allocations()) {
-      profiler->AllocationEvent(address, size);
-    }
     return address;
   }
 
@@ -349,11 +304,12 @@ class Deserializer: public SerializerDeserializer {
     return HeapObject::FromAddress(high_water_[space] - offset);
   }
 
-  void FlushICacheForNewCodeObjects();
-
   // Cached current isolate.
   Isolate* isolate_;
 
+  // Objects from the attached object descriptions in the serialized user code.
+  Vector<Handle<Object> >* attached_objects_;
+
   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.
@@ -368,18 +324,6 @@ class Deserializer: public SerializerDeserializer {
 };
 
 
-class SnapshotByteSink {
- public:
-  virtual ~SnapshotByteSink() { }
-  virtual void Put(int byte, const char* description) = 0;
-  virtual void PutSection(int byte, const char* description) {
-    Put(byte, description);
-  }
-  void PutInt(uintptr_t integer, const char* description);
-  virtual int Position() = 0;
-};
-
-
 // Mapping objects to their location after deserialization.
 // This is used during building, but not at runtime by V8.
 class SerializationAddressMapper {
@@ -397,13 +341,13 @@ class SerializationAddressMapper {
   }
 
   int MappedTo(HeapObject* obj) {
-    ASSERT(IsMapped(obj));
+    DCHECK(IsMapped(obj));
     return static_cast<int>(reinterpret_cast<intptr_t>(
         serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
   }
 
   void AddMapping(HeapObject* obj, int to) {
-    ASSERT(!IsMapped(obj));
+    DCHECK(!IsMapped(obj));
     HashMap::Entry* entry =
         serialization_map_->Lookup(Key(obj), Hash(obj), true);
     entry->value = Value(to);
@@ -439,7 +383,7 @@ class Serializer : public SerializerDeserializer {
   // You can call this after serialization to find out how much space was used
   // in each space.
   int CurrentAllocationAddress(int space) const {
-    ASSERT(space < kNumberOfSpaces);
+    DCHECK(space < kNumberOfSpaces);
     return fullness_[space];
   }
 
@@ -458,7 +402,7 @@ class Serializer : public SerializerDeserializer {
   int RootIndex(HeapObject* heap_object, HowToCode from);
   intptr_t root_index_wave_front() { return root_index_wave_front_; }
   void set_root_index_wave_front(intptr_t value) {
-    ASSERT(value >= root_index_wave_front_);
+    DCHECK(value >= root_index_wave_front_);
     root_index_wave_front_ = value;
   }
 
@@ -486,8 +430,8 @@ class Serializer : public SerializerDeserializer {
     void VisitCell(RelocInfo* rinfo);
     void VisitRuntimeEntry(RelocInfo* reloc);
     // Used for seralizing the external strings that hold the natives source.
-    void VisitExternalAsciiString(
-        v8::String::ExternalAsciiStringResource** resource);
+    void VisitExternalOneByteString(
+        v8::String::ExternalOneByteStringResource** resource);
     // We can't serialize a heap with external two byte strings.
     void VisitExternalTwoByteString(
         v8::String::ExternalStringResource** resource) {
@@ -515,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);
@@ -584,7 +526,7 @@ class PartialSerializer : public Serializer {
     // allow them to be part of the partial snapshot because they contain a
     // unique ID, and deserializing several partial snapshots containing script
     // would cause dupes.
-    ASSERT(!o->IsScript());
+    DCHECK(!o->IsScript());
     return o->IsName() || o->IsSharedFunctionInfo() ||
            o->IsHeapNumber() || o->IsCode() ||
            o->IsScopeInfo() ||
@@ -624,9 +566,142 @@ class StartupSerializer : public Serializer {
     SerializeWeakReferences();
     Pad();
   }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StartupSerializer);
+};
+
+
+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);
+
+  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);
 };
 
 
+// Wrapper around ScriptData to provide code-serializer-specific functionality.
+class SerializedCodeData {
+ public:
+  // Used by when consuming.
+  explicit SerializedCodeData(ScriptData* data, String* source)
+      : script_data_(data), owns_script_data_(false) {
+    DisallowHeapAllocation no_gc;
+    CHECK(IsSane(source));
+  }
+
+  // Used when producing.
+  SerializedCodeData(List<byte>* payload, CodeSerializer* cs);
+
+  ~SerializedCodeData() {
+    if (owns_script_data_) delete script_data_;
+  }
+
+  // Return ScriptData object and relinquish ownership over it to the caller.
+  ScriptData* GetScriptData() {
+    ScriptData* result = script_data_;
+    script_data_ = NULL;
+    DCHECK(owns_script_data_);
+    owns_script_data_ = false;
+    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 {
+    int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size;
+    return script_data_->data() + kHeaderSize + code_stubs_size;
+  }
+
+  int PayloadLength() const {
+    int payload_length = GetHeaderValue(kPayloadLengthOffset);
+    DCHECK_EQ(script_data_->data() + script_data_->length(),
+              Payload() + payload_length);
+    return payload_length;
+  }
+
+  int GetReservation(int space) const {
+    return GetHeaderValue(kReservationsOffset + space);
+  }
+
+ private:
+  void SetHeaderValue(int offset, int value) {
+    reinterpret_cast<int*>(const_cast<byte*>(script_data_->data()))[offset] =
+        value;
+  }
+
+  int GetHeaderValue(int offset) const {
+    return reinterpret_cast<const int*>(script_data_->data())[offset];
+  }
+
+  bool IsSane(String* source);
+
+  int CheckSum(String* source);
+
+  // 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.
+  static const int kCheckSumOffset = 0;
+  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_;
+};
 } }  // namespace v8::internal
 
 #endif  // V8_SERIALIZE_H_