Arm codegen could emit const pool in the middle of jump table.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 10 Dec 2008 08:37:58 +0000 (08:37 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 10 Dec 2008 08:37:58 +0000 (08:37 +0000)
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@956 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/assembler-arm.h
src/codegen-arm.cc
src/constants-arm.h
src/macro-assembler-arm.cc
src/macro-assembler-arm.h
test/mjsunit/switch.js

index 1aebc42..bd70066 100644 (file)
@@ -672,6 +672,14 @@ class Assembler : public Malloced {
   // Patch branch instruction at pos to branch to given branch target pos
   void target_at_put(int pos, int target_pos);
 
+  // Check if is time to emit a constant pool for pending reloc info entries
+  void CheckConstPool(bool force_emit, bool require_jump);
+
+  // Block the emission of the constant pool before pc_offset
+  void BlockConstPoolBefore(int pc_offset) {
+    if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
+  }
+
  private:
   // Code buffer:
   // The buffer into which code and relocation info are generated.
@@ -769,14 +777,6 @@ class Assembler : public Malloced {
 
   // Record reloc info for current pc_
   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
-
-  // Check if is time to emit a constant pool for pending reloc info entries
-  void CheckConstPool(bool force_emit, bool require_jump);
-
-  // Block the emission of the constant pool before pc_offset
-  void BlockConstPoolBefore(int pc_offset) {
-    if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
-  }
 };
 
 } }  // namespace v8::internal
index 494257a..712a989 100644 (file)
@@ -1347,15 +1347,7 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
   __ b(ne, fail_label);
   __ cmp(r0, Operand(Smi::FromInt(range)));
   __ b(ge, fail_label);
-  __ add(pc, pc, Operand(r0, LSL, 2 - kSmiTagSize));
-  // One extra instruction offsets the table, so the table's start address is
-  // the pc-register at the above add.
-  __ stop("Unreachable: Switch table alignment");
-
-  // Table containing branch operations.
-  for (int i = 0; i < range; i++) {
-    __ b(case_targets[i]);
-  }
+  __ SmiJumpTable(r0, case_targets);
 
   GenerateFastCaseSwitchCases(node, case_labels);
 }
index 46ddb15..f553963 100644 (file)
@@ -129,6 +129,7 @@ class Instr {
  public:
   enum {
     kInstrSize = 4,
+    kInstrSizeLog2 = 2,
     kPCReadOffset = 8
   };
 
index 7016145..5cbeae9 100644 (file)
@@ -176,6 +176,20 @@ void MacroAssembler::Ret() {
 }
 
 
+void MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) {
+  // Empty the const pool.
+  CheckConstPool(true, true);
+  add(pc, pc, Operand(index,
+                      LSL,
+                      assembler::arm::Instr::kInstrSizeLog2 - kSmiTagSize));
+  BlockConstPoolBefore(pc_offset() + (targets.length() + 1) * sizeof(Instr));
+  nop();  // Jump table alignment.
+  for (int i = 0; i < targets.length(); i++) {
+    b(targets[i]);
+  }
+}
+
+
 // Will clobber 4 registers: object, offset, scratch, ip.  The
 // register 'object' contains a heap object pointer.  The heap object
 // tag is shifted away.
index 7cc843f..b2edf3e 100644 (file)
@@ -87,7 +87,8 @@ class MacroAssembler: public Assembler {
   void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
   void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
   void Ret();
-
+  // Jumps to the label at the index given by the Smi in "index".
+  void SmiJumpTable(Register index, Vector<Label*> targets);
 
   // Sets the remembered set bit for [address+offset], where address is the
   // address of the heap object 'object'.  The address must be in the first 8K
index 821a4f3..e2b14d1 100644 (file)
@@ -267,3 +267,23 @@ assertEquals("default", f7(1<<30), "0-1-switch.maxsmi++");
 assertEquals("default", f7(-(1<<30)-1), "0-1-switch.minsmi--");
 assertEquals("A", f7((170/16)-(170%16/16)), "0-1-switch.heapnum");
 
+
+function makeVeryLong(length) {
+  var res = "function() {\n" +
+            "  var res = 0;\n" + 
+            "  for (var i = 0; i <= " + length + "; i++) {\n" +
+            "    switch(i) {\n";
+  for (var i = 0; i < length; i++) {
+    res += "    case " + i + ": res += 2; break;\n";
+  }
+  res += "    default: res += 1;\n" +
+         "    }\n" +
+         "  }\n" +
+         "  return res;\n" +
+         "}";
+  return eval(res);
+}
+var verylong_size = 1000;
+var verylong = makeVeryLong(verylong_size);
+
+assertEquals(verylong_size * 2 + 1, verylong());
\ No newline at end of file