Fix issues with Arm's use of embedded constant pools
authormbrandy <mbrandy@us.ibm.com>
Tue, 9 Jun 2015 16:00:11 +0000 (09:00 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 9 Jun 2015 16:00:25 +0000 (16:00 +0000)
- Introduce Assembler::DataAlign for table alignment in code object
- Fix several misuses of r8 (alias of the pool pointer register, pp)
- Fix calculation of pp in OSR/handler entry invocation
- Enable missing cases in deserializer
- Fix references to ool constant pools in comments.

R=rmcilroy@chromium.org, michael_dawson@ca.ibm.com
BUG=chromium:497180
LOG=N

Review URL: https://codereview.chromium.org/1155673005

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

18 files changed:
src/arm/assembler-arm-inl.h
src/arm/assembler-arm.cc
src/arm/assembler-arm.h
src/arm/builtins-arm.cc
src/arm/code-stubs-arm.cc
src/arm/frames-arm.h
src/arm/macro-assembler-arm.cc
src/arm64/assembler-arm64.h
src/assembler.cc
src/ia32/assembler-ia32.h
src/mips/assembler-mips.h
src/mips64/assembler-mips64.h
src/ppc/assembler-ppc-inl.h
src/ppc/assembler-ppc.cc
src/ppc/assembler-ppc.h
src/snapshot/serialize.cc
src/x64/assembler-x64.h
src/x87/assembler-x87.h

index 5e590a7d030d446e2bead4178b035eaf2b468ad8..28a323ab519b3d03b14719505fd6262da5e07915 100644 (file)
@@ -120,8 +120,9 @@ Address RelocInfo::target_address_address() {
                               || rmode_ == EXTERNAL_REFERENCE);
   if (FLAG_enable_embedded_constant_pool ||
       Assembler::IsMovW(Memory::int32_at(pc_))) {
-    // We return the PC for ool constant pool since this function is used by the
-    // serializer and expects the address to reside within the code object.
+    // We return the PC for embedded constant pool since this function is used
+    // by the serializer and expects the address to reside within the code
+    // object.
     return reinterpret_cast<Address>(pc_);
   } else {
     DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)));
index ed8664a9c5f32f10ddc131ad8973e2b79cc37347..b90ff1e05b6a383cbf40276af1e762b20ebd2635 100644 (file)
@@ -494,6 +494,7 @@ void Assembler::GetCode(CodeDesc* desc) {
 
 void Assembler::Align(int m) {
   DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
+  DCHECK((pc_offset() & (kInstrSize - 1)) == 0);
   while ((pc_offset() & (m - 1)) != 0) {
     nop();
   }
index 82d786fe512b2ba98844df9793ca89d3f361ef8b..879021df3b9755b7a954ed66e6a498f4b189467b 100644 (file)
@@ -792,6 +792,9 @@ class Assembler : public AssemblerBase {
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2 (>= 4).
   void Align(int m);
+  // Insert the smallest number of zero bytes possible to align the pc offset
+  // to a mulitple of m. m must be a power of 2 (>= 2).
+  void DataAlign(int m);
   // Aligns code to something that's optimal for a jump target for the platform.
   void CodeTargetAlign();
 
index 7ebef530f3ef787d8724d9d1fcfe05607e5d0345..2638033cdee6ca9477f63e528394fe17eec6e1ca 100644 (file)
@@ -1166,6 +1166,8 @@ void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
   __ ldr(r1, FieldMemOperand(r0, Code::kDeoptimizationDataOffset));
 
   { ConstantPoolUnavailableScope constant_pool_unavailable(masm);
+    __ add(r0, r0, Operand(Code::kHeaderSize - kHeapObjectTag));  // Code start
+
     if (FLAG_enable_embedded_constant_pool) {
       __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r0);
     }
@@ -1175,10 +1177,8 @@ void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
     __ ldr(r1, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(
         DeoptimizationInputData::kOsrPcOffsetIndex)));
 
-    // Compute the target address = code_obj + header_size + osr_offset
-    // <entry_addr> = <code_obj> + #header_size + <osr_offset>
-    __ add(r0, r0, Operand::SmiUntag(r1));
-    __ add(lr, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
+    // Compute the target address = code start + osr_offset
+    __ add(lr, r0, Operand::SmiUntag(r1));
 
     // And "return" to the OSR entry point of the function.
     __ Ret();
index 03e6862b5dffae96a3bcb25bc1558ebf9ad057bd..5adf6703143287f37a6137c558ecc33da917e60c 100644 (file)
@@ -1101,10 +1101,10 @@ void CEntryStub::Generate(MacroAssembler* masm) {
   __ ldr(r1, MemOperand(r1));
   __ mov(r2, Operand(pending_handler_offset_address));
   __ ldr(r2, MemOperand(r2));
+  __ add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));  // Code start
   if (FLAG_enable_embedded_constant_pool) {
     __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r1);
   }
-  __ add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ add(pc, r1, r2);
 }
 
@@ -1348,11 +1348,11 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
     __ ldr(map_load_offset, MemOperand(map_load_offset));
     __ str(map, FieldMemOperand(map_load_offset, Cell::kValueOffset));
 
-    __ mov(r8, map);
+    __ mov(scratch, map);
     // |map_load_offset| points at the beginning of the cell. Calculate the
     // field containing the map.
     __ add(function, map_load_offset, Operand(Cell::kValueOffset - 1));
-    __ RecordWriteField(map_load_offset, Cell::kValueOffset, r8, function,
+    __ RecordWriteField(map_load_offset, Cell::kValueOffset, scratch, function,
                         kLRHasNotBeenSaved, kDontSaveFPRegs,
                         OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
   }
@@ -2434,7 +2434,7 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) {
   // this position in a symbol (see static asserts in type-feedback-vector.h).
   Label check_allocation_site;
   Register feedback_map = r5;
-  Register weak_value = r8;
+  Register weak_value = r6;
   __ ldr(weak_value, FieldMemOperand(r4, WeakCell::kValueOffset));
   __ cmp(r1, weak_value);
   __ b(eq, &done);
@@ -4495,7 +4495,7 @@ void LoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   Register slot = LoadWithVectorDescriptor::SlotRegister();          // r0
   Register feedback = r4;
   Register receiver_map = r5;
-  Register scratch1 = r8;
+  Register scratch1 = r6;
 
   __ add(feedback, vector, Operand::PointerOffsetFromSmiKey(slot));
   __ ldr(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize));
@@ -4552,7 +4552,7 @@ void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   Register slot = LoadWithVectorDescriptor::SlotRegister();          // r0
   Register feedback = r4;
   Register receiver_map = r5;
-  Register scratch1 = r8;
+  Register scratch1 = r6;
 
   __ add(feedback, vector, Operand::PointerOffsetFromSmiKey(slot));
   __ ldr(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize));
index ea621c965b47e9322b7f6d0ddcb0eefb10db9c20..b9ffdd0712a9c46120c25bafc86bbf274c6bec9e 100644 (file)
@@ -66,11 +66,23 @@ const int kNumDoubleCalleeSaved = 8;
 // TODO(regis): Only 8 registers may actually be sufficient. Revisit.
 const int kNumSafepointRegisters = 16;
 
+// The embedded constant pool pointer (r8/pp) is not included in the safepoint
+// since it is not tagged.  This register is preserved in the stack frame where
+// its value will be updated if GC code movement occurs.  Including it in the
+// safepoint (where it will not be relocated) would cause a stale value to be
+// restored.
+const RegList kConstantPointerRegMask =
+    FLAG_enable_embedded_constant_pool ? (1 << 8) : 0;
+const int kNumConstantPoolPointerReg =
+    FLAG_enable_embedded_constant_pool ? 1 : 0;
+
 // Define the list of registers actually saved at safepoints.
 // Note that the number of saved registers may be smaller than the reserved
 // space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
-const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
-const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
+const RegList kSafepointSavedRegisters =
+    kJSCallerSaved | (kCalleeSaved & ~kConstantPointerRegMask);
+const int kNumSafepointSavedRegisters =
+    kNumJSCallerSaved + kNumCalleeSaved - kNumConstantPoolPointerReg;
 
 // ----------------------------------------------------
 
index 61b59edf868c08b11cd80ef246550d679f2df753..c7452cf3b15c9c7cf016b4194f94757c008c9d01 100644 (file)
@@ -707,8 +707,12 @@ void MacroAssembler::PopFixedFrame(Register marker_reg) {
 
 // Push and pop all registers that can hold pointers.
 void MacroAssembler::PushSafepointRegisters() {
-  // Safepoints expect a block of contiguous register values starting with r0:
-  DCHECK(((1 << kNumSafepointSavedRegisters) - 1) == kSafepointSavedRegisters);
+  // Safepoints expect a block of contiguous register values starting with r0.
+  // except when FLAG_enable_embedded_constant_pool, which omits pp.
+  DCHECK(kSafepointSavedRegisters ==
+         (FLAG_enable_embedded_constant_pool
+              ? ((1 << (kNumSafepointSavedRegisters + 1)) - 1) & ~pp.bit()
+              : (1 << kNumSafepointSavedRegisters) - 1));
   // Safepoints expect a block of kNumSafepointRegisters values on the
   // stack, so adjust the stack for unsaved registers.
   const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
@@ -738,6 +742,10 @@ void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
   // The registers are pushed starting with the highest encoding,
   // which means that lowest encodings are closest to the stack pointer.
+  if (FLAG_enable_embedded_constant_pool && reg_code > pp.code()) {
+    // RegList omits pp.
+    reg_code -= 1;
+  }
   DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters);
   return reg_code;
 }
index 7346648a9b02aed4e8150d7359f7c8c5ce898be7..5fab081d4b41b52ca802c99d3cbf6cb3349048c0 100644 (file)
@@ -851,6 +851,9 @@ class Assembler : public AssemblerBase {
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2 (>= 4).
   void Align(int m);
+  // Insert the smallest number of zero bytes possible to align the pc offset
+  // to a mulitple of m. m must be a power of 2 (>= 2).
+  void DataAlign(int m);
 
   inline void Unreachable();
 
index 90d08bb6821177d179fbc0c161c5e7eae448a698..acce223582e75fb98cbe220947d2760211d15c07 100644 (file)
@@ -1814,7 +1814,7 @@ int ConstantPoolBuilder::Emit(Assembler* assm) {
 
   if (!emitted) {
     // Mark start of constant pool.  Align if necessary.
-    if (!empty) assm->Align(kDoubleSize);
+    if (!empty) assm->DataAlign(kDoubleSize);
     assm->bind(&emitted_label_);
     if (!empty) {
       // Emit in groups based on access and type.
@@ -1822,7 +1822,7 @@ int ConstantPoolBuilder::Emit(Assembler* assm) {
       EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::DOUBLE);
       EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::INTPTR);
       if (info_[ConstantPoolEntry::DOUBLE].overflow()) {
-        assm->Align(kDoubleSize);
+        assm->DataAlign(kDoubleSize);
         EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
                   ConstantPoolEntry::DOUBLE);
       }
@@ -1871,5 +1871,13 @@ void Assembler::RecordDebugBreakSlot() {
   EnsureSpace ensure_space(this);
   RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
 }
+
+
+void Assembler::DataAlign(int m) {
+  DCHECK(m >= 2 && base::bits::IsPowerOfTwo32(m));
+  while ((pc_offset() & (m - 1)) != 0) {
+    db(0);
+  }
+}
 }  // namespace internal
 }  // namespace v8
index 0d701916992cb865085daf5bcbe3802bd8979bf8..e77ef28ce738ec45bbf25f9759df463ee2b63cca 100644 (file)
@@ -607,6 +607,9 @@ class Assembler : public AssemblerBase {
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2.
   void Align(int m);
+  // Insert the smallest number of zero bytes possible to align the pc offset
+  // to a mulitple of m. m must be a power of 2 (>= 2).
+  void DataAlign(int m);
   void Nop(int bytes = 1);
   // Aligns code to something that's optimal for a jump target for the platform.
   void CodeTargetAlign();
index c116c13bcddfc746f8c2473fa4ce98e3ea6dd0e4..96d5073b942e9cd9818283c326740c838af04751 100644 (file)
@@ -606,6 +606,9 @@ class Assembler : public AssemblerBase {
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2 (>= 4).
   void Align(int m);
+  // Insert the smallest number of zero bytes possible to align the pc offset
+  // to a mulitple of m. m must be a power of 2 (>= 2).
+  void DataAlign(int m);
   // Aligns code to something that's optimal for a jump target for the platform.
   void CodeTargetAlign();
 
index 7bada88cf8583e920033ad2cc2a9de1f8f421462..f7a1f5e1ef3e1fdaf27beb54560eecccb7d3e236 100644 (file)
@@ -597,6 +597,9 @@ class Assembler : public AssemblerBase {
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2 (>= 4).
   void Align(int m);
+  // Insert the smallest number of zero bytes possible to align the pc offset
+  // to a mulitple of m. m must be a power of 2 (>= 2).
+  void DataAlign(int m);
   // Aligns code to something that's optimal for a jump target for the platform.
   void CodeTargetAlign();
 
index 14b5503a17349a7cde1d9efd9e74525121b8df4e..0e759efec16b475538a4ce7dffe409bbe8914bfe 100644 (file)
@@ -96,8 +96,9 @@ Address RelocInfo::target_address_address() {
 
   if (FLAG_enable_embedded_constant_pool &&
       Assembler::IsConstantPoolLoadStart(pc_)) {
-    // We return the PC for ool constant pool since this function is used by the
-    // serializer and expects the address to reside within the code object.
+    // We return the PC for embedded constant pool since this function is used
+    // by the serializer and expects the address to reside within the code
+    // object.
     return reinterpret_cast<Address>(pc_);
   }
 
index cce578e9f6cde0c2519afdf5d72311a2b64668ce..38c7fd82b7bbe096725621d39a531f973491ed80 100644 (file)
@@ -244,17 +244,9 @@ void Assembler::GetCode(CodeDesc* desc) {
 
 
 void Assembler::Align(int m) {
-#if V8_TARGET_ARCH_PPC64
-  DCHECK(m >= 4 && base::bits::IsPowerOfTwo64(m));
-#else
   DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
-#endif
-  // First ensure instruction alignment
-  while (pc_offset() & (kInstrSize - 1)) {
-    db(0);
-  }
-  // Then pad to requested alignedment with nops
-  while (pc_offset() & (m - 1)) {
+  DCHECK((pc_offset() & (kInstrSize - 1)) == 0);
+  while ((pc_offset() & (m - 1)) != 0) {
     nop();
   }
 }
index fb56852bb5b5c254d82662f910f0b1c5265f90dc..e8a654fe6457022332381d5de2d48e66c076f866 100644 (file)
@@ -736,6 +736,9 @@ class Assembler : public AssemblerBase {
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2 (>= 4).
   void Align(int m);
+  // Insert the smallest number of zero bytes possible to align the pc offset
+  // to a mulitple of m. m must be a power of 2 (>= 2).
+  void DataAlign(int m);
   // Aligns code to something that's optimal for a jump target for the platform.
   void CodeTargetAlign();
 
index ace8225b8246caf958f3bf335b2c33c423e19576..9f8189266a36c9086dc7c163788ca520f0272d81 100644 (file)
@@ -1006,15 +1006,15 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space,
       ALL_SPACES(kBackref, kPlain, kStartOfObject)
       ALL_SPACES(kBackrefWithSkip, kPlain, kStartOfObject)
 #if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) || \
-    defined(V8_TARGET_ARCH_PPC)
+    defined(V8_TARGET_ARCH_PPC) || V8_EMBEDDED_CONSTANT_POOL
       // Deserialize a new object from pointer found in code and write
       // a pointer to it to the current object. Required only for MIPS, PPC or
-      // ARM with ool constant pool, and omitted on the other architectures
+      // ARM with embedded constant pool, and omitted on the other architectures
       // because it is fully unrolled and would cause bloat.
       ALL_SPACES(kNewObject, kFromCode, kStartOfObject)
       // Find a recently deserialized code object using its offset from the
       // current allocation point and write a pointer to it to the current
-      // object. Required only for MIPS, PPC or ARM with ool constant pool.
+      // object. Required only for MIPS, PPC or ARM with embedded constant pool.
       ALL_SPACES(kBackref, kFromCode, kStartOfObject)
       ALL_SPACES(kBackrefWithSkip, kFromCode, kStartOfObject)
 #endif
@@ -1031,7 +1031,7 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space,
       CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0)
       CASE_BODY(kRootArray, kPlain, kStartOfObject, 0)
 #if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) || \
-    defined(V8_TARGET_ARCH_PPC)
+    defined(V8_TARGET_ARCH_PPC) || V8_EMBEDDED_CONSTANT_POOL
       // Find an object in the roots array and write a pointer to it to in code.
       CASE_STATEMENT(kRootArray, kFromCode, kStartOfObject, 0)
       CASE_BODY(kRootArray, kFromCode, kStartOfObject, 0)
index cb52541b5690ffbeb4e36ad282d7282a1429be57..15c531960f337ac094ebd24c08bcdac8a34c2535 100644 (file)
@@ -704,6 +704,9 @@ class Assembler : public AssemblerBase {
   // possible to align the pc offset to a multiple
   // of m, where m must be a power of 2.
   void Align(int m);
+  // Insert the smallest number of zero bytes possible to align the pc offset
+  // to a mulitple of m. m must be a power of 2 (>= 2).
+  void DataAlign(int m);
   void Nop(int bytes = 1);
   // Aligns code to something that's optimal for a jump target for the platform.
   void CodeTargetAlign();
index ea05ab975f03c02eb37a195606d6c7c8ae46c12b..ededc2aadc53d2fa00cab4fccad672db2647dfcf 100644 (file)
@@ -590,6 +590,9 @@ class Assembler : public AssemblerBase {
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2.
   void Align(int m);
+  // Insert the smallest number of zero bytes possible to align the pc offset
+  // to a mulitple of m. m must be a power of 2 (>= 2).
+  void DataAlign(int m);
   void Nop(int bytes = 1);
   // Aligns code to something that's optimal for a jump target for the platform.
   void CodeTargetAlign();