Serializer: serialize internal references via object visitor.
authoryangguo <yangguo@chromium.org>
Wed, 18 Mar 2015 13:38:32 +0000 (06:38 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 18 Mar 2015 13:38:45 +0000 (13:38 +0000)
Review URL: https://codereview.chromium.org/1005183006

Cr-Commit-Position: refs/heads/master@{#27275}

16 files changed:
src/arm/assembler-arm-inl.h
src/arm/assembler-arm.h
src/arm64/assembler-arm64-inl.h
src/arm64/assembler-arm64.h
src/assembler.cc
src/assembler.h
src/heap/objects-visiting-inl.h
src/heap/objects-visiting.h
src/ia32/assembler-ia32-inl.h
src/ia32/assembler-ia32.h
src/objects.h
src/serialize.cc
src/serialize.h
src/x64/assembler-x64-inl.h
src/x64/assembler-x64.h
test/cctest/test-serialize.cc

index 0be6f921e40684ccb584c05c76bc3a28bfb5a7c1..f5076c26ce14e1dd35bb1d94b6cf798479c52d9c 100644 (file)
@@ -121,7 +121,7 @@ Address RelocInfo::target_address_address() {
   if (FLAG_enable_ool_constant_pool ||
       Assembler::IsMovW(Memory::int32_at(pc_))) {
     // We return the PC for ool constant pool since this function is used by the
-    // serializerer and expects the address to reside within the code object.
+    // serializer and expects the address to reside within the code object.
     return reinterpret_cast<Address>(pc_);
   } else {
     DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)));
@@ -196,9 +196,9 @@ Address RelocInfo::target_internal_reference() {
 }
 
 
-void RelocInfo::set_target_internal_reference(Address target) {
+Address RelocInfo::target_internal_reference_address() {
   DCHECK(rmode_ == INTERNAL_REFERENCE);
-  Memory::Address_at(pc_) = target;
+  return reinterpret_cast<Address>(pc_);
 }
 
 
@@ -310,11 +310,14 @@ Object** RelocInfo::call_object_address() {
 
 
 void RelocInfo::WipeOut() {
-  DCHECK(IsEmbeddedObject(rmode_) ||
-         IsCodeTarget(rmode_) ||
-         IsRuntimeEntry(rmode_) ||
-         IsExternalReference(rmode_));
-  Assembler::set_target_address_at(pc_, host_, NULL);
+  DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
+         IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
+         IsInternalReference(rmode_));
+  if (IsInternalReference(rmode_)) {
+    Memory::Address_at(pc_) = NULL;
+  } else {
+    Assembler::set_target_address_at(pc_, host_, NULL);
+  }
 }
 
 
@@ -345,6 +348,8 @@ void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
     visitor->VisitCell(this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     visitor->VisitExternalReference(this);
+  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
+    visitor->VisitInternalReference(this);
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     visitor->VisitCodeAgeSequence(this);
   } else if (((RelocInfo::IsJSReturn(mode) &&
@@ -370,6 +375,8 @@ void RelocInfo::Visit(Heap* heap) {
     StaticVisitor::VisitCell(heap, this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     StaticVisitor::VisitExternalReference(this);
+  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
+    StaticVisitor::VisitInternalReference(this);
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     StaticVisitor::VisitCodeAgeSequence(heap, this);
   } else if (heap->isolate()->debug()->has_break_points() &&
@@ -546,6 +553,12 @@ void Assembler::deserialization_set_special_target_at(
 }
 
 
+void Assembler::deserialization_set_target_internal_reference_at(
+    Address pc, Address target) {
+  Memory::Address_at(pc) = target;
+}
+
+
 bool Assembler::is_constant_pool_load(Address pc) {
   if (CpuFeatures::IsSupported(ARMv7)) {
     return !Assembler::IsMovW(Memory::int32_at(pc)) ||
index fc143e17414e1b497e81c0029a9fda6fca3e4219..272ec9d44825af6ca456128a32f06c1791b93a7d 100644 (file)
@@ -795,6 +795,10 @@ class Assembler : public AssemblerBase {
   inline static void deserialization_set_special_target_at(
       Address constant_pool_entry, Code* code, Address target);
 
+  // This sets the internal reference at the pc.
+  inline static void deserialization_set_target_internal_reference_at(
+      Address pc, Address target);
+
   // Here we are patching the address in the constant pool, not the actual call
   // instruction.  The address in the constant pool is the same size as a
   // pointer.
index d9d919c438df89e61ac01dae4a995a6acfdeb0fe..2d2b7e6dd3344eb3eb8a814ec094ca1cd2a4af10 100644 (file)
@@ -654,6 +654,12 @@ void Assembler::deserialization_set_special_target_at(
 }
 
 
+void Assembler::deserialization_set_target_internal_reference_at(
+    Address pc, Address target) {
+  UNIMPLEMENTED();  // ARM64 does not use internal references.
+}
+
+
 void Assembler::set_target_address_at(Address pc,
                                       ConstantPoolArray* constant_pool,
                                       Address target,
@@ -741,13 +747,15 @@ Address RelocInfo::target_external_reference() {
 
 Address RelocInfo::target_internal_reference() {
   DCHECK(rmode_ == INTERNAL_REFERENCE);
-  return Memory::Address_at(pc_);
+  UNIMPLEMENTED();  // ARM64 does not use internal references.
+  return NULL;
 }
 
 
-void RelocInfo::set_target_internal_reference(Address target) {
+Address RelocInfo::target_internal_reference_address() {
   DCHECK(rmode_ == INTERNAL_REFERENCE);
-  Memory::Address_at(pc_) = target;
+  UNIMPLEMENTED();  // ARM64 does not use internal references.
+  return NULL;
 }
 
 
@@ -838,11 +846,14 @@ void RelocInfo::set_call_address(Address target) {
 
 
 void RelocInfo::WipeOut() {
-  DCHECK(IsEmbeddedObject(rmode_) ||
-         IsCodeTarget(rmode_) ||
-         IsRuntimeEntry(rmode_) ||
-         IsExternalReference(rmode_));
-  Assembler::set_target_address_at(pc_, host_, NULL);
+  DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
+         IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
+         IsInternalReference(rmode_));
+  if (IsInternalReference(rmode_)) {
+    UNIMPLEMENTED();  // ARM64 does not use internal references.
+  } else {
+    Assembler::set_target_address_at(pc_, host_, NULL);
+  }
 }
 
 
@@ -874,6 +885,8 @@ void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
     visitor->VisitCell(this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     visitor->VisitExternalReference(this);
+  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
+    UNIMPLEMENTED();  // ARM64 does not use internal references.
   } else if (((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
@@ -897,6 +910,8 @@ void RelocInfo::Visit(Heap* heap) {
     StaticVisitor::VisitCell(heap, this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     StaticVisitor::VisitExternalReference(this);
+  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
+    UNIMPLEMENTED();  // ARM64 does not use internal references.
   } else if (heap->isolate()->debug()->has_break_points() &&
              ((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
index 23662ad7a0f276d6d0cb2f6c9847a3a75646f2cb..64103e3a6b8e95b35d7c9a114d94ed2596acc074 100644 (file)
@@ -901,6 +901,10 @@ class Assembler : public AssemblerBase {
   inline static void deserialization_set_special_target_at(
       Address constant_pool_entry, Code* code, Address target);
 
+  // This sets the internal reference at the pc.
+  inline static void deserialization_set_target_internal_reference_at(
+      Address pc, Address target);
+
   // All addresses in the constant pool are the same size as pointers.
   static const int kSpecialTargetSize = kPointerSize;
 
index 3494f697a771ad7f533660db76cb42310ebe9510..d3f541a33f10db64ddfd389066f5a9b7503b7524 100644 (file)
@@ -911,14 +911,21 @@ void RelocInfo::Verify(Isolate* isolate) {
       CHECK(code->address() == HeapObject::cast(found)->address());
       break;
     }
+    case INTERNAL_REFERENCE:
+    case INTERNAL_REFERENCE_ENCODED: {
+      Address target = target_internal_reference();
+      Address pc = target_internal_reference_address();
+      Code* code = Code::cast(isolate->FindCodeObject(pc));
+      CHECK(target >= code->instruction_start());
+      CHECK(target <= code->instruction_end());
+      break;
+    }
     case RUNTIME_ENTRY:
     case JS_RETURN:
     case COMMENT:
     case POSITION:
     case STATEMENT_POSITION:
     case EXTERNAL_REFERENCE:
-    case INTERNAL_REFERENCE:
-    case INTERNAL_REFERENCE_ENCODED:
     case DEOPT_REASON:
     case CONST_POOL:
     case VENEER_POOL:
index 07859b3f8bec81525952ea1d86b1a106aa2959f5..691cae510ea53f5191d164d03765388922008878 100644 (file)
@@ -581,10 +581,13 @@ class RelocInfo {
   // applies to; can only be called if rmode_ is EXTERNAL_REFERENCE.
   INLINE(Address target_external_reference());
 
-  // Read/modify the reference in the instruction this relocation
+  // Read the reference in the instruction this relocation
   // applies to; can only be called if rmode_ is INTERNAL_REFERENCE.
   INLINE(Address target_internal_reference());
-  INLINE(void set_target_internal_reference(Address target));
+
+  // Return the reference address this relocation applies to;
+  // can only be called if rmode_ is INTERNAL_REFERENCE.
+  INLINE(Address target_internal_reference_address());
 
   // Read/modify the address of a call instruction. This is used to relocate
   // the break points where straight-line code is patched with a call
index b4240d2a491e44be26f4e8fbb6bda132953e8bc1..872b2dd30c814da322199aa643ad5fe17cbceee2 100644 (file)
@@ -842,6 +842,8 @@ void Code::CodeIterateBody(ObjectVisitor* v) {
                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                   RelocInfo::ModeMask(RelocInfo::CELL) |
                   RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
+                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
+                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
                   RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
                   RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
@@ -869,6 +871,8 @@ void Code::CodeIterateBody(Heap* heap) {
                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                   RelocInfo::ModeMask(RelocInfo::CELL) |
                   RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
+                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
+                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
                   RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
                   RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
index 30005ec622ace5c0fff41e1d80d67bd0a165c8d4..2bc90457acdbb63bb70fcd5a0d7b362b7c25acb6 100644 (file)
@@ -413,6 +413,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
   INLINE(static void VisitCodeTarget(Heap* heap, RelocInfo* rinfo));
   INLINE(static void VisitCodeAgeSequence(Heap* heap, RelocInfo* rinfo));
   INLINE(static void VisitExternalReference(RelocInfo* rinfo)) {}
+  INLINE(static void VisitInternalReference(RelocInfo* rinfo)) {}
   INLINE(static void VisitRuntimeEntry(RelocInfo* rinfo)) {}
   // Skip the weak next code link in a code object.
   INLINE(static void VisitNextCodeLink(Heap* heap, Object** slot)) {}
index 521ab4fab4e9f367c91496ff75fff4129b2299d4..20e3cc935fceb33345a385d8d0edb6925e99661d 100644 (file)
@@ -166,9 +166,9 @@ Address RelocInfo::target_internal_reference() {
 }
 
 
-void RelocInfo::set_target_internal_reference(Address target) {
+Address RelocInfo::target_internal_reference_address() {
   DCHECK(rmode_ == INTERNAL_REFERENCE);
-  Memory::Address_at(pc_) = target;
+  return reinterpret_cast<Address>(pc_);
 }
 
 
@@ -280,7 +280,8 @@ Object** RelocInfo::call_object_address() {
 
 
 void RelocInfo::WipeOut() {
-  if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_)) {
+  if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
+      IsInternalReference(rmode_)) {
     Memory::Address_at(pc_) = NULL;
   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     // Effectively write zero into the relocation.
@@ -312,7 +313,8 @@ void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
     visitor->VisitCell(this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     visitor->VisitExternalReference(this);
-    CpuFeatures::FlushICache(pc_, sizeof(Address));
+  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
+    visitor->VisitInternalReference(this);
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     visitor->VisitCodeAgeSequence(this);
   } else if (((RelocInfo::IsJSReturn(mode) &&
@@ -339,7 +341,8 @@ void RelocInfo::Visit(Heap* heap) {
     StaticVisitor::VisitCell(heap, this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     StaticVisitor::VisitExternalReference(this);
-    CpuFeatures::FlushICache(pc_, sizeof(Address));
+  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
+    StaticVisitor::VisitInternalReference(this);
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     StaticVisitor::VisitCodeAgeSequence(heap, this);
   } else if (heap->isolate()->debug()->has_break_points() &&
@@ -528,6 +531,12 @@ void Assembler::emit_near_disp(Label* L) {
 }
 
 
+void Assembler::deserialization_set_target_internal_reference_at(
+    Address pc, Address target) {
+  Memory::Address_at(pc) = target;
+}
+
+
 void Operand::set_modrm(int mod, Register rm) {
   DCHECK((mod & -4) == 0);
   buf_[0] = mod << 6 | rm.code();
index 7edcf527f2ee03aeb2d70be2ccbb31752f7f7fcb..656333ed4e7289210465d9e9268f3fbf7a1ac422 100644 (file)
@@ -547,6 +547,10 @@ class Assembler : public AssemblerBase {
     set_target_address_at(instruction_payload, code, target);
   }
 
+  // This sets the internal reference at the pc.
+  inline static void deserialization_set_target_internal_reference_at(
+      Address pc, Address target);
+
   static const int kSpecialTargetSize = kPointerSize;
 
   // Distance between the address of the code target in the call instruction
index 3f6f50be72768f31fb27014a5d56b37ec46c6aa8..f70d868344b022881fe17aa32290d63712bb018b 100644 (file)
@@ -10946,9 +10946,12 @@ class ObjectVisitor BASE_EMBEDDED {
   // Visits an external reference embedded into a code object.
   virtual void VisitExternalReference(RelocInfo* rinfo);
 
-  // Visits an external reference. The value may be modified on return.
+  // Visits an external reference.
   virtual void VisitExternalReference(Address* p) {}
 
+  // Visits an (encoded) internal reference.
+  virtual void VisitInternalReference(RelocInfo* rinfo) {}
+
   // Visits a handle that has an embedder-assigned class ID.
   virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
 
index b846c445c9f5d8e6b2c2ec93077c06c5f0273525..784992d92b869972834c954f211b5d635510294c 100644 (file)
@@ -780,25 +780,13 @@ void Deserializer::ReadObject(int space_number, Object** write_back) {
 #ifdef DEBUG
   if (obj->IsCode()) {
     DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE);
+#ifdef VERIFY_HEAP
+    obj->ObjectVerify();
+#endif  // VERIFY_HEAP
   } else {
     DCHECK(space_number != CODE_SPACE);
   }
-#endif
-
-  if (obj->IsCode()) {
-    // Turn internal references encoded as offsets back to absolute addresses.
-    Code* code = Code::cast(obj);
-    Address entry = code->entry();
-    int mode_mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
-                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
-    for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
-      RelocInfo* rinfo = it.rinfo();
-      intptr_t offset =
-          reinterpret_cast<intptr_t>(rinfo->target_internal_reference());
-      DCHECK(0 <= offset && offset <= code->instruction_size());
-      rinfo->set_target_internal_reference(entry + offset);
-    }
-  }
+#endif  // DEBUG
 }
 
 
@@ -1172,6 +1160,21 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
         break;
       }
 
+      case kInternalReference: {
+        // Internal reference address is not encoded via skip, but by offset
+        // from code entry.
+        int pc_offset = source_.GetInt();
+        int target_offset = source_.GetInt();
+        Code* code =
+            Code::cast(HeapObject::FromAddress(current_object_address));
+        DCHECK(0 <= pc_offset && pc_offset <= code->instruction_size());
+        DCHECK(0 <= target_offset && target_offset <= code->instruction_size());
+        Address pc = code->entry() + pc_offset;
+        Address target = code->entry() + target_offset;
+        Assembler::deserialization_set_target_internal_reference_at(pc, target);
+        break;
+      }
+
       case kNativesStringResource: {
         DCHECK(!isolate_->heap()->deserialization_complete());
         int index = source_.Get();
@@ -1859,6 +1862,28 @@ void Serializer::ObjectSerializer::VisitExternalReference(RelocInfo* rinfo) {
 }
 
 
+void Serializer::ObjectSerializer::VisitInternalReference(RelocInfo* rinfo) {
+  // We can only reference to internal references of code that has been output.
+  DCHECK(is_code_object_ && code_has_been_output_);
+  // We do not use skip from last patched pc to find the pc to patch, since
+  // target_address_address may not return addresses in ascending order when
+  // used for internal references. External references may be stored at the
+  // end of the code in the constant pool, whereas internal references are
+  // inline. That would cause the skip to be negative. Instead, we store the
+  // offset from code entry.
+  Address entry = Code::cast(object_)->entry();
+  intptr_t pc_offset = rinfo->target_internal_reference_address() - entry;
+  intptr_t target_offset = rinfo->target_internal_reference() - entry;
+  DCHECK(0 <= pc_offset &&
+         pc_offset <= Code::cast(object_)->instruction_size());
+  DCHECK(0 <= target_offset &&
+         target_offset <= Code::cast(object_)->instruction_size());
+  sink_->Put(kInternalReference, "InternalRef");
+  sink_->PutInt(static_cast<uintptr_t>(pc_offset), "internal ref address");
+  sink_->PutInt(static_cast<uintptr_t>(target_offset), "internal ref value");
+}
+
+
 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) {
   int skip = OutputRawData(rinfo->target_address_address(),
                            kCanReturnSkipInsteadOfSkipping);
@@ -1934,7 +1959,6 @@ Address Serializer::ObjectSerializer::PrepareCode() {
   Code* code = serializer_->CopyCode(original);
   // Code age headers are not serializable.
   code->MakeYoung(serializer_->isolate());
-  Address entry = original->entry();
   int mode_mask = RelocInfo::kCodeTargetMask |
                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                   RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
@@ -1943,15 +1967,7 @@ Address Serializer::ObjectSerializer::PrepareCode() {
                   RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
   for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
     RelocInfo* rinfo = it.rinfo();
-    RelocInfo::Mode rmode = rinfo->rmode();
-    if (RelocInfo::IsInternalReference(rmode) ||
-        RelocInfo::IsInternalReferenceEncoded(rmode)) {
-      // Convert internal references to relative offsets.
-      Address target = rinfo->target_internal_reference();
-      intptr_t offset = target - entry;
-      DCHECK(0 <= offset && offset <= original->instruction_size());
-      rinfo->set_target_internal_reference(reinterpret_cast<Address>(offset));
-    } else if (!(FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool())) {
+    if (!(FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool())) {
       rinfo->WipeOut();
     }
   }
@@ -1974,14 +1990,13 @@ int Serializer::ObjectSerializer::OutputRawData(
   // locations in a non-ascending order.  Luckily that doesn't happen.
   DCHECK(to_skip >= 0);
   bool outputting_code = false;
-  if (to_skip != 0 && code_object_ && !code_has_been_output_) {
+  if (to_skip != 0 && is_code_object_ && !code_has_been_output_) {
     // Output the code all at once and fix later.
     bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_;
     outputting_code = true;
     code_has_been_output_ = true;
   }
-  if (bytes_to_output != 0 &&
-      (!code_object_ || outputting_code)) {
+  if (bytes_to_output != 0 && (!is_code_object_ || outputting_code)) {
 #define RAW_CASE(index)                                                        \
     if (!outputting_code && bytes_to_output == index * kPointerSize &&         \
         index * kPointerSize == to_skip) {                                     \
@@ -1996,9 +2011,9 @@ int Serializer::ObjectSerializer::OutputRawData(
       sink_->PutInt(bytes_to_output, "length");
     }
 
-    if (code_object_) object_start = PrepareCode();
+    if (is_code_object_) object_start = PrepareCode();
 
-    const char* description = code_object_ ? "Code" : "Byte";
+    const char* description = is_code_object_ ? "Code" : "Byte";
 #ifdef MEMORY_SANITIZER
     // Object sizes are usually rounded up with uninitialized padding space.
     MSAN_MEMORY_IS_INITIALIZED(object_start + base, bytes_to_output);
@@ -2322,7 +2337,6 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
     isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(),
                                        *result, NULL, name);
   }
-
   return scope.CloseAndEscape(result);
 }
 
index f344e5ae5769de5759f8db5d1c07e92334440ee5..74c5e6d4588c9b473b317ade82b49ee0c9860601 100644 (file)
@@ -348,6 +348,9 @@ class SerializerDeserializer: public ObjectVisitor {
   };
 
   // Misc.
+
+  // 0x48, 0x88 and 0xc8 are unused.
+
   // Raw data to be copied from the snapshot.  This byte code does not advance
   // the current pointer, which is used for code objects, where we write the
   // entire code in one memcpy, then fix up stuff with kSkip and other byte
@@ -357,6 +360,9 @@ class SerializerDeserializer: public ObjectVisitor {
   // These autoadvance the current pointer.
   static const int kOnePointerRawData = 0x21;
 
+  // Internal reference encoded as offsets of pc and target from code entry.
+  static const int kInternalReference = 0x08;
+
   static const int kVariableRepeat = 0x60;
   // 0x61-0x6f   Repeat last word
   static const int kFixedRepeat = 0x61;
@@ -611,23 +617,21 @@ class Serializer : public SerializerDeserializer {
  protected:
   class ObjectSerializer : public ObjectVisitor {
    public:
-    ObjectSerializer(Serializer* serializer,
-                     Object* o,
-                     SnapshotByteSink* sink,
-                     HowToCode how_to_code,
-                     WhereToPoint where_to_point)
-      : serializer_(serializer),
-        object_(HeapObject::cast(o)),
-        sink_(sink),
-        reference_representation_(how_to_code + where_to_point),
-        bytes_processed_so_far_(0),
-        code_object_(o->IsCode()),
-        code_has_been_output_(false) { }
+    ObjectSerializer(Serializer* serializer, Object* o, SnapshotByteSink* sink,
+                     HowToCode how_to_code, WhereToPoint where_to_point)
+        : serializer_(serializer),
+          object_(HeapObject::cast(o)),
+          sink_(sink),
+          reference_representation_(how_to_code + where_to_point),
+          bytes_processed_so_far_(0),
+          is_code_object_(o->IsCode()),
+          code_has_been_output_(false) {}
     void Serialize();
     void VisitPointers(Object** start, Object** end);
     void VisitEmbeddedPointer(RelocInfo* target);
     void VisitExternalReference(Address* p);
     void VisitExternalReference(RelocInfo* rinfo);
+    void VisitInternalReference(RelocInfo* rinfo);
     void VisitCodeTarget(RelocInfo* target);
     void VisitCodeEntry(Address entry_address);
     void VisitCell(RelocInfo* rinfo);
@@ -660,7 +664,7 @@ class Serializer : public SerializerDeserializer {
     SnapshotByteSink* sink_;
     int reference_representation_;
     int bytes_processed_so_far_;
-    bool code_object_;
+    bool is_code_object_;
     bool code_has_been_output_;
   };
 
index e8f90c6aca5c39c2f7983a5c17be787e600886fd..de30c0a3b339e6fef78920f16aa74ffe188edee8 100644 (file)
@@ -265,6 +265,12 @@ void Assembler::set_target_address_at(Address pc,
 }
 
 
+void Assembler::deserialization_set_target_internal_reference_at(
+    Address pc, Address target) {
+  Memory::Address_at(pc) = target;
+}
+
+
 Address Assembler::target_address_from_return_address(Address pc) {
   return pc - kCallTargetAddressOffset;
 }
@@ -378,9 +384,9 @@ Address RelocInfo::target_internal_reference() {
 }
 
 
-void RelocInfo::set_target_internal_reference(Address target) {
+Address RelocInfo::target_internal_reference_address() {
   DCHECK(rmode_ == INTERNAL_REFERENCE);
-  Memory::Address_at(pc_) = target;
+  return reinterpret_cast<Address>(pc_);
 }
 
 
@@ -450,7 +456,8 @@ void RelocInfo::set_target_cell(Cell* cell,
 
 
 void RelocInfo::WipeOut() {
-  if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_)) {
+  if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
+      IsInternalReference(rmode_)) {
     Memory::Address_at(pc_) = NULL;
   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     // Effectively write zero into the relocation.
@@ -554,7 +561,8 @@ void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
     visitor->VisitCell(this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     visitor->VisitExternalReference(this);
-    CpuFeatures::FlushICache(pc_, sizeof(Address));
+  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
+    visitor->VisitInternalReference(this);
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     visitor->VisitCodeAgeSequence(this);
   } else if (((RelocInfo::IsJSReturn(mode) &&
@@ -581,7 +589,8 @@ void RelocInfo::Visit(Heap* heap) {
     StaticVisitor::VisitCell(heap, this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     StaticVisitor::VisitExternalReference(this);
-    CpuFeatures::FlushICache(pc_, sizeof(Address));
+  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
+    StaticVisitor::VisitInternalReference(this);
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
     StaticVisitor::VisitCodeAgeSequence(heap, this);
   } else if (heap->isolate()->debug()->has_break_points() &&
index bf3572dc548c3e2ee99867471a5a89840294c8ca..56c99fd43f4a6bc915bfecaa4b67b7152e4b0fa4 100644 (file)
@@ -570,6 +570,10 @@ class Assembler : public AssemblerBase {
     set_target_address_at(instruction_payload, code, target);
   }
 
+  // This sets the internal reference at the pc.
+  inline static void deserialization_set_target_internal_reference_at(
+      Address instruction, Address target);
+
   static inline RelocInfo::Mode RelocInfoNone() {
     if (kPointerSize == kInt64Size) {
       return RelocInfo::NONE64;
index b124974e0c3a113acc92435095a3251bef50e23c..9fadddf4c27a199564430b786307cc4f4a3aee77 100644 (file)
@@ -1484,6 +1484,9 @@ TEST(SerializeWithHarmonyScoping) {
 
 
 TEST(SerializeInternalReference) {
+#ifdef V8_TARGET_ARCH_ARM64
+  return;
+#endif  // V8_TARGET_ARCH_ARM64
   // Disable experimental natives that are loaded after deserialization.
   FLAG_turbo_deoptimization = false;
   FLAG_context_specialization = false;
@@ -1502,10 +1505,10 @@ TEST(SerializeInternalReference) {
       "      case 2:"
       "      case 3: j = 2; break;"
       "      case 4:"
-      "      case 5: j = 3; break;"
+      "      case 5: j = foo(3) + 1; break;"
       "      default: j = 0; break;"
       "    }"
-      "    return j|0;"
+      "    return j + 10;"
       "  }"
       "  return { foo: foo };"
       "})(this, {}, undefined).foo;"
@@ -1525,8 +1528,24 @@ TEST(SerializeInternalReference) {
     v8::Context::Scope c_scope(context);
     v8::Handle<v8::Function> foo =
         v8::Handle<v8::Function>::Cast(CompileRun("foo"));
+
+    // There are at least 6 internal references.
+    int mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
+               RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
+    RelocIterator it(v8::Utils::OpenHandle(*foo)->code(), mask);
+    for (int i = 0; i < 6; ++i) {
+      CHECK(!it.done());
+      it.next();
+    }
+
     CHECK(v8::Utils::OpenHandle(*foo)->code()->is_turbofanned());
-    CHECK_EQ(3, CompileRun("foo(4)")->ToInt32(isolate)->Int32Value());
+    CHECK_EQ(11, CompileRun("foo(0)")->ToInt32(isolate)->Int32Value());
+    CHECK_EQ(11, CompileRun("foo(1)")->ToInt32(isolate)->Int32Value());
+    CHECK_EQ(12, CompileRun("foo(2)")->ToInt32(isolate)->Int32Value());
+    CHECK_EQ(12, CompileRun("foo(3)")->ToInt32(isolate)->Int32Value());
+    CHECK_EQ(23, CompileRun("foo(4)")->ToInt32(isolate)->Int32Value());
+    CHECK_EQ(23, CompileRun("foo(5)")->ToInt32(isolate)->Int32Value());
+    CHECK_EQ(10, CompileRun("foo(6)")->ToInt32(isolate)->Int32Value());
   }
   isolate->Dispose();
 }