Make sure the constant pool size is as promised.
authoryangguo <yangguo@chromium.org>
Fri, 3 Jul 2015 10:32:27 +0000 (03:32 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 3 Jul 2015 10:32:37 +0000 (10:32 +0000)
LOG=N
R=bmeurer@chromium.org
BUG=chromium:506443

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

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

src/arm/assembler-arm.cc
src/assembler.cc
src/disassembler.cc
test/mjsunit/regress/regress-crbug-506443.js [new file with mode: 0644]

index b90ff1e..74c682a 100644 (file)
@@ -3734,18 +3734,19 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
   // the gap to the relocation information).
   int jump_instr = require_jump ? kInstrSize : 0;
   int size_up_to_marker = jump_instr + kInstrSize;
-  int size_after_marker = num_pending_32_bit_constants_ * kPointerSize;
+  int estimated_size_after_marker =
+      num_pending_32_bit_constants_ * kPointerSize;
   bool has_fp_values = (num_pending_64_bit_constants_ > 0);
   bool require_64_bit_align = false;
   if (has_fp_values) {
-    require_64_bit_align = (((uintptr_t)pc_ + size_up_to_marker) & 0x7);
+    require_64_bit_align = IsAligned(
+        reinterpret_cast<intptr_t>(pc_ + size_up_to_marker), kDoubleAlignment);
     if (require_64_bit_align) {
-      size_after_marker += kInstrSize;
+      estimated_size_after_marker += kInstrSize;
     }
-    size_after_marker += num_pending_64_bit_constants_ * kDoubleSize;
+    estimated_size_after_marker += num_pending_64_bit_constants_ * kDoubleSize;
   }
-
-  int size = size_up_to_marker + size_after_marker;
+  int estimated_size = size_up_to_marker + estimated_size_after_marker;
 
   // We emit a constant pool when:
   //  * requested to do so by parameter force_emit (e.g. after each function).
@@ -3759,7 +3760,7 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
     DCHECK((first_const_pool_32_use_ >= 0) || (first_const_pool_64_use_ >= 0));
     bool need_emit = false;
     if (has_fp_values) {
-      int dist64 = pc_offset() + size -
+      int dist64 = pc_offset() + estimated_size -
                    num_pending_32_bit_constants_ * kPointerSize -
                    first_const_pool_64_use_;
       if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
@@ -3767,8 +3768,7 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
         need_emit = true;
       }
     }
-    int dist32 =
-      pc_offset() + size - first_const_pool_32_use_;
+    int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_;
     if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) ||
         (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) {
       need_emit = true;
@@ -3776,6 +3776,37 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
     if (!need_emit) return;
   }
 
+  // Deduplicate constants.
+  int size_after_marker = estimated_size_after_marker;
+  for (int i = 0; i < num_pending_64_bit_constants_; i++) {
+    ConstantPoolEntry& entry = pending_64_bit_constants_[i];
+    DCHECK(!entry.is_merged());
+    for (int j = 0; j < i; j++) {
+      if (entry.value64() == pending_64_bit_constants_[j].value64()) {
+        DCHECK(!pending_64_bit_constants_[j].is_merged());
+        entry.set_merged_index(j);
+        size_after_marker -= kDoubleSize;
+        break;
+      }
+    }
+  }
+
+  for (int i = 0; i < num_pending_32_bit_constants_; i++) {
+    ConstantPoolEntry& entry = pending_32_bit_constants_[i];
+    DCHECK(!entry.is_merged());
+    if (!entry.sharing_ok()) continue;
+    for (int j = 0; j < i; j++) {
+      if (entry.value() == pending_32_bit_constants_[j].value()) {
+        DCHECK(!pending_32_bit_constants_[j].is_merged());
+        entry.set_merged_index(j);
+        size_after_marker -= kPointerSize;
+        break;
+      }
+    }
+  }
+
+  int size = size_up_to_marker + size_after_marker;
+
   int needed_space = size + kGap;
   while (buffer_space() <= needed_space) GrowBuffer();
 
@@ -3785,6 +3816,9 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
     RecordComment("[ Constant Pool");
     RecordConstPool(size);
 
+    Label size_check;
+    bind(&size_check);
+
     // Emit jump over constant pool if necessary.
     Label after_pool;
     if (require_jump) {
@@ -3805,8 +3839,6 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
     for (int i = 0; i < num_pending_64_bit_constants_; i++) {
       ConstantPoolEntry& entry = pending_64_bit_constants_[i];
 
-      DCHECK(!((uintptr_t)pc_ & 0x7));  // Check 64-bit alignment.
-
       Instr instr = instr_at(entry.position());
       // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0.
       DCHECK((IsVldrDPcImmediateOffset(instr) &&
@@ -3815,24 +3847,19 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
       int delta = pc_offset() - entry.position() - kPcLoadDelta;
       DCHECK(is_uint10(delta));
 
-      bool found = false;
-      uint64_t value = entry.value64();
-      for (int j = 0; j < i; j++) {
-        ConstantPoolEntry& entry2 = pending_64_bit_constants_[j];
-        if (value == entry2.value64()) {
-          found = true;
-          Instr instr2 = instr_at(entry2.position());
-          DCHECK(IsVldrDPcImmediateOffset(instr2));
-          delta = GetVldrDRegisterImmediateOffset(instr2);
-          delta += entry2.position() - entry.position();
-          break;
-        }
+      if (entry.is_merged()) {
+        ConstantPoolEntry& merged =
+            pending_64_bit_constants_[entry.merged_index()];
+        DCHECK(entry.value64() == merged.value64());
+        Instr merged_instr = instr_at(merged.position());
+        DCHECK(IsVldrDPcImmediateOffset(merged_instr));
+        delta = GetVldrDRegisterImmediateOffset(merged_instr);
+        delta += merged.position() - entry.position();
       }
-
       instr_at_put(entry.position(),
                    SetVldrDRegisterImmediateOffset(instr, delta));
-
-      if (!found) {
+      if (!entry.is_merged()) {
+        DCHECK(IsAligned(reinterpret_cast<intptr_t>(pc_), kDoubleAlignment));
         dq(entry.value64());
       }
     }
@@ -3844,41 +3871,31 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
 
       // 64-bit loads shouldn't get here.
       DCHECK(!IsVldrDPcImmediateOffset(instr));
+      DCHECK(!IsMovW(instr));
+      DCHECK(IsLdrPcImmediateOffset(instr) &&
+             GetLdrRegisterImmediateOffset(instr) == 0);
 
-      if (IsLdrPcImmediateOffset(instr) &&
-          GetLdrRegisterImmediateOffset(instr) == 0) {
-        int delta = pc_offset() - entry.position() - kPcLoadDelta;
-        DCHECK(is_uint12(delta));
-        // 0 is the smallest delta:
-        //   ldr rd, [pc, #0]
-        //   constant pool marker
-        //   data
-
-        bool found = false;
-        if (entry.sharing_ok()) {
-          for (int j = 0; j < i; j++) {
-            ConstantPoolEntry& entry2 = pending_32_bit_constants_[j];
-
-            if (entry2.value() == entry.value()) {
-              Instr instr2 = instr_at(entry2.position());
-              if (IsLdrPcImmediateOffset(instr2)) {
-                delta = GetLdrRegisterImmediateOffset(instr2);
-                delta += entry2.position() - entry.position();
-                found = true;
-                break;
-              }
-            }
-          }
-        }
-
-        instr_at_put(entry.position(),
-                     SetLdrRegisterImmediateOffset(instr, delta));
-
-        if (!found) {
-          emit(entry.value());
-        }
-      } else {
-        DCHECK(IsMovW(instr));
+      int delta = pc_offset() - entry.position() - kPcLoadDelta;
+      DCHECK(is_uint12(delta));
+      // 0 is the smallest delta:
+      //   ldr rd, [pc, #0]
+      //   constant pool marker
+      //   data
+
+      if (entry.is_merged()) {
+        DCHECK(entry.sharing_ok());
+        ConstantPoolEntry& merged =
+            pending_32_bit_constants_[entry.merged_index()];
+        DCHECK(entry.value() == merged.value());
+        Instr merged_instr = instr_at(merged.position());
+        DCHECK(IsLdrPcImmediateOffset(merged_instr));
+        delta = GetLdrRegisterImmediateOffset(merged_instr);
+        delta += merged.position() - entry.position();
+      }
+      instr_at_put(entry.position(),
+                   SetLdrRegisterImmediateOffset(instr, delta));
+      if (!entry.is_merged()) {
+        emit(entry.value());
       }
     }
 
@@ -3889,6 +3906,8 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
 
     RecordComment("]");
 
+    DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check));
+
     if (after_pool.is_linked()) {
       bind(&after_pool);
     }
index acce223..91577c6 100644 (file)
@@ -881,6 +881,8 @@ void RelocInfo::Print(Isolate* isolate, std::ostream& os) {  // NOLINT
     if (id != Deoptimizer::kNotDeoptimizationEntry) {
       os << "  (deoptimization bailout " << id << ")";
     }
+  } else if (IsConstPool(rmode_)) {
+    os << " (size " << static_cast<int>(data_) << ")";
   }
 
   os << "\n";
index 9ec2f42..47e506d 100644 (file)
@@ -100,8 +100,8 @@ static int DecodeIt(Isolate* isolate, std::ostream* os,
       int num_const = d.ConstantPoolSizeAt(pc);
       if (num_const >= 0) {
         SNPrintF(decode_buffer,
-                 "%08x       constant pool begin",
-                 *reinterpret_cast<int32_t*>(pc));
+                 "%08x       constant pool begin (num_const = %d)",
+                 *reinterpret_cast<int32_t*>(pc), num_const);
         constants = num_const;
         pc += 4;
       } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc &&
diff --git a/test/mjsunit/regress/regress-crbug-506443.js b/test/mjsunit/regress/regress-crbug-506443.js
new file mode 100644 (file)
index 0000000..13cbac6
--- /dev/null
@@ -0,0 +1,89 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+assertSame = function assertSame() {
+  if (found === expected) {
+    if (1 / expected) return;
+  } else if ((expected !== expected) && (found !== found)) {
+    return;
+  };
+};
+assertEquals = function assertEquals() {
+  if (expected) {;
+  }
+};
+assertArrayEquals = function assertArrayEquals() {
+  var start = "";
+  if (name_opt) {
+    start = name_opt + " - ";
+  };
+  if (expected.length == found.length) {
+    for (var i = 0; i < expected.length; ++i) {;
+    }
+  }
+};
+assertPropertiesEqual = function assertPropertiesEqual() {
+  if (found) {;
+  }
+};
+assertToStringEquals = function assertToStringEquals() {
+  if (found) {;
+  }
+};
+assertTrue = function assertTrue() {;
+};
+assertFalse = function assertFalse() {;
+};
+assertUnreachable = function assertUnreachable() {
+  var message = "Fail" + "ure: unreachable";
+  if (name_opt) {
+    message += " - " + name_opt;
+  }
+};
+OptimizationStatus = function() {}
+assertUnoptimized = function assertUnoptimized() {;
+}
+assertOptimized = function assertOptimized() {;
+}
+triggerAssertFalse = function() {}
+var __v_2 = {};
+var __v_3 = {};
+var __v_4 = {};
+var __v_5 = {};
+var __v_6 = 1073741823;
+var __v_7 = {};
+var __v_8 = {};
+var __v_9 = {};
+var __v_10 = {};
+var __v_11 = 2147483648;
+var __v_12 = 1073741823;
+var __v_13 = {};
+var __v_14 = {};
+var __v_15 = -2147483648;
+var __v_16 = {};
+var __v_17 = {};
+var __v_19 = {};
+var __v_20 = {};
+var __v_21 = {};
+var __v_22 = {};
+var __v_23 = {};
+var __v_24 = {};
+try {
+  (function() {
+    var Debug = %GetDebugContext().Debug;
+
+    function __f_0() {}
+    for (var __v_0 = 0; __v_0 < 3; __v_0++) {
+      var __v_2 = function() {
+        a = 1;
+      }
+      Debug.setListener(__f_0);
+      if (__v_0 < 2) Debug.setBreakPoint(__v_2);
+    }
+  })();
+} catch (e) {
+  print();
+}