Revision: 17789
Author:   [email protected]
Date:     Fri Nov 15 12:24:10 2013 UTC
Log:      ARM: Merge redundant entries in literal pool.

This patch also clean up 64-bits literals handling.

[email protected]

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

Patch from Rodolph Perfetta <[email protected]>.
http://code.google.com/p/v8/source/detail?r=17789

Modified:
 /branches/bleeding_edge/src/arm/assembler-arm.cc
 /branches/bleeding_edge/src/arm/assembler-arm.h
 /branches/bleeding_edge/src/assembler.h

=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.cc Tue Nov 5 13:19:14 2013 UTC +++ /branches/bleeding_edge/src/arm/assembler-arm.cc Fri Nov 15 12:24:10 2013 UTC
@@ -517,12 +517,13 @@
       recorded_ast_id_(TypeFeedbackId::None()),
       positions_recorder_(this) {
   reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
-  num_pending_reloc_info_ = 0;
+  num_pending_32_bit_reloc_info_ = 0;
   num_pending_64_bit_reloc_info_ = 0;
   next_buffer_check_ = 0;
   const_pool_blocked_nesting_ = 0;
   no_const_pool_before_ = 0;
-  first_const_pool_use_ = -1;
+  first_const_pool_32_use_ = -1;
+  first_const_pool_64_use_ = -1;
   last_bound_pos_ = 0;
   ClearRecordedAstId();
 }
@@ -536,7 +537,7 @@
 void Assembler::GetCode(CodeDesc* desc) {
   // Emit constant pool if necessary.
   CheckConstPool(true, false);
-  ASSERT(num_pending_reloc_info_ == 0);
+  ASSERT(num_pending_32_bit_reloc_info_ == 0);
   ASSERT(num_pending_64_bit_reloc_info_ == 0);

   // Set up code descriptor.
@@ -3149,14 +3150,19 @@
   // to relocate any emitted relocation entries.

   // Relocate pending relocation entries.
-  for (int i = 0; i < num_pending_reloc_info_; i++) {
-    RelocInfo& rinfo = pending_reloc_info_[i];
+  for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) {
+    RelocInfo& rinfo = pending_32_bit_reloc_info_[i];
     ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
            rinfo.rmode() != RelocInfo::POSITION);
     if (rinfo.rmode() != RelocInfo::JS_RETURN) {
       rinfo.set_pc(rinfo.pc() + pc_delta);
     }
   }
+  for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) {
+    RelocInfo& rinfo = pending_64_bit_reloc_info_[i];
+    ASSERT(rinfo.rmode() == RelocInfo::NONE64);
+    rinfo.set_pc(rinfo.pc() + pc_delta);
+  }
 }


@@ -3164,7 +3170,7 @@
   // No relocation info should be pending while using db. db is used
   // to write pure data with no pointers and the constant pool should
   // be emitted before using db.
-  ASSERT(num_pending_reloc_info_ == 0);
+  ASSERT(num_pending_32_bit_reloc_info_ == 0);
   ASSERT(num_pending_64_bit_reloc_info_ == 0);
   CheckBuffer();
   *reinterpret_cast<uint8_t*>(pc_) = data;
@@ -3176,7 +3182,7 @@
   // No relocation info should be pending while using dd. dd is used
   // to write pure data with no pointers and the constant pool should
   // be emitted before using dd.
-  ASSERT(num_pending_reloc_info_ == 0);
+  ASSERT(num_pending_32_bit_reloc_info_ == 0);
   ASSERT(num_pending_64_bit_reloc_info_ == 0);
   CheckBuffer();
   *reinterpret_cast<uint32_t*>(pc_) = data;
@@ -3246,15 +3252,19 @@


void Assembler::RecordRelocInfoConstantPoolEntryHelper(const RelocInfo& rinfo) {
-  ASSERT(num_pending_reloc_info_ < kMaxNumPendingRelocInfo);
-  if (num_pending_reloc_info_ == 0) {
-    first_const_pool_use_ = pc_offset();
-  }
-  pending_reloc_info_[num_pending_reloc_info_++] = rinfo;
   if (rinfo.rmode() == RelocInfo::NONE64) {
-    ++num_pending_64_bit_reloc_info_;
+    ASSERT(num_pending_64_bit_reloc_info_ < kMaxNumPending64RelocInfo);
+    if (num_pending_64_bit_reloc_info_ == 0) {
+      first_const_pool_64_use_ = pc_offset();
+    }
+    pending_64_bit_reloc_info_[num_pending_64_bit_reloc_info_++] = rinfo;
+  } else {
+    ASSERT(num_pending_32_bit_reloc_info_ < kMaxNumPending32RelocInfo);
+    if (num_pending_32_bit_reloc_info_ == 0) {
+      first_const_pool_32_use_ = pc_offset();
+    }
+    pending_32_bit_reloc_info_[num_pending_32_bit_reloc_info_++] = rinfo;
   }
-  ASSERT(num_pending_64_bit_reloc_info_ <= num_pending_reloc_info_);
   // Make sure the constant pool is not emitted in place of the next
   // instruction for which we just recorded relocation info.
   BlockConstPoolFor(1);
@@ -3264,12 +3274,15 @@
 void Assembler::BlockConstPoolFor(int instructions) {
   int pc_limit = pc_offset() + instructions * kInstrSize;
   if (no_const_pool_before_ < pc_limit) {
- // If there are some pending entries, the constant pool cannot be blocked
-    // further than constant pool instruction's reach.
-    ASSERT((num_pending_reloc_info_ == 0) ||
-           (pc_limit - first_const_pool_use_ < kMaxDistToIntPool));
-    // TODO(jfb) Also check 64-bit entries are in range (requires splitting
-    //           them up from 32-bit entries).
+    // Max pool start (if we need a jump and an alignment).
+#ifdef DEBUG
+    int start = pc_limit + kInstrSize + 2 * kPointerSize;
+    ASSERT((num_pending_32_bit_reloc_info_ == 0) ||
+           (start - first_const_pool_32_use_ +
+ num_pending_64_bit_reloc_info_ * kDoubleSize < kMaxDistToIntPool));
+    ASSERT((num_pending_64_bit_reloc_info_ == 0) ||
+           (start - first_const_pool_64_use_ < kMaxDistToFPPool));
+#endif
     no_const_pool_before_ = pc_limit;
   }

@@ -3290,8 +3303,8 @@
   }

   // There is nothing to do if there are no pending constant pool entries.
-  if (num_pending_reloc_info_ == 0)  {
-    ASSERT(num_pending_64_bit_reloc_info_ == 0);
+  if ((num_pending_32_bit_reloc_info_ == 0) &&
+      (num_pending_64_bit_reloc_info_ == 0)) {
     // Calculate the offset of the next check.
     next_buffer_check_ = pc_offset() + kCheckPoolInterval;
     return;
@@ -3300,24 +3313,18 @@
// Check that the code buffer is large enough before emitting the constant
   // pool (include the jump over the pool and the constant pool marker and
   // the gap to the relocation information).
- // Note 64-bit values are wider, and the first one needs to be 64-bit aligned.
   int jump_instr = require_jump ? kInstrSize : 0;
   int size_up_to_marker = jump_instr + kInstrSize;
-  int size_after_marker = num_pending_reloc_info_ * kPointerSize;
+  int size_after_marker = num_pending_32_bit_reloc_info_ * kPointerSize;
   bool has_fp_values = (num_pending_64_bit_reloc_info_ > 0);
-  // 64-bit values must be 64-bit aligned.
-  // We'll start emitting at PC: branch+marker, then 32-bit values, then
-  // 64-bit values which might need to be aligned.
-  bool require_64_bit_align = has_fp_values &&
-      (((uintptr_t)pc_ + size_up_to_marker + size_after_marker) & 0x3);
-  if (require_64_bit_align) {
-    size_after_marker += kInstrSize;
+  bool require_64_bit_align = false;
+  if (has_fp_values) {
+    require_64_bit_align = (((uintptr_t)pc_ + size_up_to_marker) & 0x7);
+    if (require_64_bit_align) {
+      size_after_marker += kInstrSize;
+    }
+    size_after_marker += num_pending_64_bit_reloc_info_ * kDoubleSize;
   }
-  // num_pending_reloc_info_ also contains 64-bit entries, the above code
-  // therefore already counted half of the size for 64-bit entries. Add the
-  // remaining size.
-  STATIC_ASSERT(kPointerSize == kDoubleSize / 2);
-  size_after_marker += num_pending_64_bit_reloc_info_ * (kDoubleSize / 2);

   int size = size_up_to_marker + size_after_marker;

@@ -3330,19 +3337,25 @@
// * the instruction doesn't require a jump after itself to jump over the
   //    constant pool, and we're getting close to running out of range.
   if (!force_emit) {
-    ASSERT((first_const_pool_use_ >= 0) && (num_pending_reloc_info_ > 0));
-    int dist = pc_offset() + size - first_const_pool_use_;
+ ASSERT((first_const_pool_32_use_ >= 0) || (first_const_pool_64_use_ >= 0));
+    bool need_emit = false;
     if (has_fp_values) {
-      if ((dist < kMaxDistToFPPool - kCheckPoolInterval) &&
-          (require_jump || (dist < kMaxDistToFPPool / 2))) {
-        return;
-      }
-    } else {
-      if ((dist < kMaxDistToIntPool - kCheckPoolInterval) &&
-          (require_jump || (dist < kMaxDistToIntPool / 2))) {
-        return;
+      int dist64 = pc_offset() +
+                   size -
+                   num_pending_32_bit_reloc_info_ * kPointerSize -
+                   first_const_pool_64_use_;
+      if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
+          (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) {
+        need_emit = true;
       }
     }
+    int dist32 =
+      pc_offset() + size - first_const_pool_32_use_;
+    if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) ||
+        (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) {
+      need_emit = true;
+    }
+    if (!need_emit) return;
   }

   int needed_space = size + kGap;
@@ -3371,15 +3384,10 @@

     // Emit 64-bit constant pool entries first: their range is smaller than
     // 32-bit entries.
-    for (int i = 0; i < num_pending_reloc_info_; i++) {
-      RelocInfo& rinfo = pending_reloc_info_[i];
+    for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) {
+      RelocInfo& rinfo = pending_64_bit_reloc_info_[i];

-      if (rinfo.rmode() != RelocInfo::NONE64) {
-        // 32-bit values emitted later.
-        continue;
-      }
-
-      ASSERT(!((uintptr_t)pc_ & 0x3));  // Check 64-bit alignment.
+      ASSERT(!((uintptr_t)pc_ & 0x7));  // Check 64-bit alignment.

       Instr instr = instr_at(rinfo.pc());
// Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0.
@@ -3388,54 +3396,86 @@

       int delta = pc_ - rinfo.pc() - kPcLoadDelta;
       ASSERT(is_uint10(delta));
+
+      bool found = false;
+      uint64_t value = rinfo.raw_data64();
+      for (int j = 0; j < i; j++) {
+        RelocInfo& rinfo2 = pending_64_bit_reloc_info_[j];
+        if (value == rinfo2.raw_data64()) {
+          found = true;
+          ASSERT(rinfo2.rmode() == RelocInfo::NONE64);
+          Instr instr2 = instr_at(rinfo2.pc());
+          ASSERT(IsVldrDPcImmediateOffset(instr2));
+          delta = GetVldrDRegisterImmediateOffset(instr2);
+          delta += rinfo2.pc() - rinfo.pc();
+          break;
+        }
+      }

instr_at_put(rinfo.pc(), SetVldrDRegisterImmediateOffset(instr, delta));

-      const double double_data = rinfo.data64();
-      uint64_t uint_data = 0;
-      OS::MemCopy(&uint_data, &double_data, sizeof(double_data));
-      emit(uint_data & 0xFFFFFFFF);
-      emit(uint_data >> 32);
+      if (!found) {
+        uint64_t uint_data = rinfo.raw_data64();
+        emit(uint_data & 0xFFFFFFFF);
+        emit(uint_data >> 32);
+      }
     }

     // Emit 32-bit constant pool entries.
-    for (int i = 0; i < num_pending_reloc_info_; i++) {
-      RelocInfo& rinfo = pending_reloc_info_[i];
+    for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) {
+      RelocInfo& rinfo = pending_32_bit_reloc_info_[i];
       ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
              rinfo.rmode() != RelocInfo::POSITION &&
              rinfo.rmode() != RelocInfo::STATEMENT_POSITION &&
-             rinfo.rmode() != RelocInfo::CONST_POOL);
-
-      if (rinfo.rmode() == RelocInfo::NONE64) {
-        // 64-bit values emitted earlier.
-        continue;
-      }
+             rinfo.rmode() != RelocInfo::CONST_POOL &&
+             rinfo.rmode() != RelocInfo::NONE64);

       Instr instr = instr_at(rinfo.pc());

       // 64-bit loads shouldn't get here.
       ASSERT(!IsVldrDPcImmediateOffset(instr));

-      int delta = pc_ - rinfo.pc() - kPcLoadDelta;
-      // 0 is the smallest delta:
-      //   ldr rd, [pc, #0]
-      //   constant pool marker
-      //   data
-
       if (IsLdrPcImmediateOffset(instr) &&
           GetLdrRegisterImmediateOffset(instr) == 0) {
+        int delta = pc_ - rinfo.pc() - kPcLoadDelta;
         ASSERT(is_uint12(delta));
+        // 0 is the smallest delta:
+        //   ldr rd, [pc, #0]
+        //   constant pool marker
+        //   data
+
+        bool found = false;
+        if (!Serializer::enabled() && (rinfo.rmode() >= RelocInfo::CELL)) {
+          for (int j = 0; j < i; j++) {
+            RelocInfo& rinfo2 = pending_32_bit_reloc_info_[j];
+
+            if ((rinfo2.data() == rinfo.data()) &&
+                (rinfo2.rmode() == rinfo.rmode())) {
+              Instr instr2 = instr_at(rinfo2.pc());
+              if (IsLdrPcImmediateOffset(instr2)) {
+                delta = GetLdrRegisterImmediateOffset(instr2);
+                delta += rinfo2.pc() - rinfo.pc();
+                found = true;
+                break;
+              }
+            }
+          }
+        }
+
instr_at_put(rinfo.pc(), SetLdrRegisterImmediateOffset(instr, delta));
-        emit(rinfo.data());
+
+        if (!found) {
+          emit(rinfo.data());
+        }
       } else {
         ASSERT(IsMovW(instr));
-        emit(rinfo.data());
       }
     }

-    num_pending_reloc_info_ = 0;
+    num_pending_32_bit_reloc_info_ = 0;
     num_pending_64_bit_reloc_info_ = 0;
-    first_const_pool_use_ = -1;
+    first_const_pool_32_use_ = -1;
+    first_const_pool_64_use_ = -1;

     RecordComment("]");

=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.h Thu Nov 7 08:23:09 2013 UTC +++ /branches/bleeding_edge/src/arm/assembler-arm.h Fri Nov 15 12:24:10 2013 UTC
@@ -1443,7 +1443,8 @@
   static const int kMaxDistToIntPool = 4*KB;
   static const int kMaxDistToFPPool = 1*KB;
   // All relocations could be integer, it therefore acts as the limit.
-  static const int kMaxNumPendingRelocInfo = kMaxDistToIntPool/kInstrSize;
+ static const int kMaxNumPending32RelocInfo = kMaxDistToIntPool/kInstrSize;
+  static const int kMaxNumPending64RelocInfo = kMaxDistToFPPool/kInstrSize;

// Postpone the generation of the constant pool for the specified number of
   // instructions.
@@ -1481,11 +1482,16 @@
   // StartBlockConstPool to have an effect.
   void EndBlockConstPool() {
     if (--const_pool_blocked_nesting_ == 0) {
+#ifdef DEBUG
+      // Max pool start (if we need a jump and an alignment).
+      int start = pc_offset() + kInstrSize + 2 * kPointerSize;
       // Check the constant pool hasn't been blocked for too long.
-      ASSERT((num_pending_reloc_info_ == 0) ||
-             (pc_offset() < (first_const_pool_use_ + kMaxDistToIntPool)));
+      ASSERT((num_pending_32_bit_reloc_info_ == 0) ||
+             (start + num_pending_64_bit_reloc_info_ * kDoubleSize <
+              (first_const_pool_32_use_ + kMaxDistToIntPool)));
       ASSERT((num_pending_64_bit_reloc_info_ == 0) ||
-             (pc_offset() < (first_const_pool_use_ + kMaxDistToFPPool)));
+             (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
+#endif
       // Two cases:
       //  * no_const_pool_before_ >= next_buffer_check_ and the emission is
       //    still blocked
@@ -1534,7 +1540,8 @@

   // Keep track of the first instruction requiring a constant pool entry
   // since the previous constant pool was emitted.
-  int first_const_pool_use_;
+  int first_const_pool_32_use_;
+  int first_const_pool_64_use_;

   // Relocation info generation
   // Each relocation is encoded as a variable size value
@@ -1548,12 +1555,12 @@
// If every instruction in a long sequence is accessing the pool, we need one
   // pending relocation entry per instruction.

-  // the buffer of pending relocation info
-  RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo];
-  // number of pending reloc info entries in the buffer
-  int num_pending_reloc_info_;
- // Number of pending reloc info entries included above which also happen to
-  // be 64-bit.
+  // The buffers of pending relocation info.
+  RelocInfo pending_32_bit_reloc_info_[kMaxNumPending32RelocInfo];
+  RelocInfo pending_64_bit_reloc_info_[kMaxNumPending64RelocInfo];
+  // Number of pending reloc info entries in the 32 bits buffer.
+  int num_pending_32_bit_reloc_info_;
+  // Number of pending reloc info entries in the 64 bits buffer.
   int num_pending_64_bit_reloc_info_;

   // The bound position, before this we cannot do instruction elimination.
=======================================
--- /branches/bleeding_edge/src/assembler.h     Mon Nov 11 18:00:52 2013 UTC
+++ /branches/bleeding_edge/src/assembler.h     Fri Nov 15 12:24:10 2013 UTC
@@ -372,6 +372,9 @@
   Mode rmode() const {  return rmode_; }
   intptr_t data() const { return data_; }
   double data64() const { return data64_; }
+  uint64_t raw_data64() {
+    return BitCast<uint64_t>(data64_);
+  }
   Code* host() const { return host_; }

   // Apply a relocation by delta bytes

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to