[turbofan] support for Int64 in CheckedLoad/CheckedStore on 64-bit platforms.
authortitzer <titzer@chromium.org>
Thu, 3 Sep 2015 10:45:35 +0000 (03:45 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 3 Sep 2015 10:45:54 +0000 (10:45 +0000)
This is to support WebAssembly 64-bit ints in the short term, since it
currently uses CheckedLoad/CheckedStore for accesses to the memory. In the
long run, we'll change this to be explicit bounds checks that throw on out
of bounds.

R=bmeurer@chromium.org
BUG=

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

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

14 files changed:
src/compiler/arm/code-generator-arm.cc
src/compiler/arm64/code-generator-arm64.cc
src/compiler/arm64/instruction-selector-arm64.cc
src/compiler/ia32/code-generator-ia32.cc
src/compiler/instruction-codes.h
src/compiler/mips/code-generator-mips.cc
src/compiler/mips64/code-generator-mips64.cc
src/compiler/mips64/instruction-selector-mips64.cc
src/compiler/ppc/code-generator-ppc.cc
src/compiler/ppc/instruction-selector-ppc.cc
src/compiler/x64/code-generator-x64.cc
src/compiler/x64/instruction-selector-x64.cc
src/compiler/x87/code-generator-x87.cc
test/cctest/compiler/test-run-machops.cc

index 08d7426..ead028c 100644 (file)
@@ -878,6 +878,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedStoreFloat64:
       ASSEMBLE_CHECKED_STORE_FLOAT(64);
       break;
+    case kCheckedLoadWord64:
+    case kCheckedStoreWord64:
+      UNREACHABLE();  // currently unsupported checked int64 load/store.
+      break;
   }
 }  // NOLINT(readability/fn_size)
 
index 1559c80..fa3a04e 100644 (file)
@@ -302,6 +302,20 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
   } while (0)
 
 
+#define ASSEMBLE_CHECKED_LOAD_INTEGER_64(asm_instr)          \
+  do {                                                       \
+    auto result = i.OutputRegister();                        \
+    auto buffer = i.InputRegister(0);                        \
+    auto offset = i.InputRegister32(1);                      \
+    auto length = i.InputOperand32(2);                       \
+    __ Cmp(offset, length);                                  \
+    auto ool = new (zone()) OutOfLineLoadZero(this, result); \
+    __ B(hs, ool->entry());                                  \
+    __ asm_instr(result, MemOperand(buffer, offset, UXTW));  \
+    __ Bind(ool->exit());                                    \
+  } while (0)
+
+
 #define ASSEMBLE_CHECKED_STORE_FLOAT(width)          \
   do {                                               \
     auto buffer = i.InputRegister(0);                \
@@ -330,6 +344,20 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
   } while (0)
 
 
+#define ASSEMBLE_CHECKED_STORE_INTEGER_64(asm_instr)       \
+  do {                                                     \
+    auto buffer = i.InputRegister(0);                      \
+    auto offset = i.InputRegister32(1);                    \
+    auto length = i.InputOperand32(2);                     \
+    auto value = i.InputRegister(3);                       \
+    __ Cmp(offset, length);                                \
+    Label done;                                            \
+    __ B(hs, &done);                                       \
+    __ asm_instr(value, MemOperand(buffer, offset, UXTW)); \
+    __ Bind(&done);                                        \
+  } while (0)
+
+
 #define ASSEMBLE_SHIFT(asm_instr, width)                                    \
   do {                                                                      \
     if (instr->InputAt(1)->IsRegister()) {                                  \
@@ -942,6 +970,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedLoadWord32:
       ASSEMBLE_CHECKED_LOAD_INTEGER(Ldr);
       break;
+    case kCheckedLoadWord64:
+      ASSEMBLE_CHECKED_LOAD_INTEGER_64(Ldr);
+      break;
     case kCheckedLoadFloat32:
       ASSEMBLE_CHECKED_LOAD_FLOAT(32);
       break;
@@ -957,6 +988,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedStoreWord32:
       ASSEMBLE_CHECKED_STORE_INTEGER(Str);
       break;
+    case kCheckedStoreWord64:
+      ASSEMBLE_CHECKED_STORE_INTEGER_64(Str);
+      break;
     case kCheckedStoreFloat32:
       ASSEMBLE_CHECKED_STORE_FLOAT(32);
       break;
index 76b1059..fbc7df2 100644 (file)
@@ -458,6 +458,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) {
     case kRepWord32:
       opcode = kCheckedLoadWord32;
       break;
+    case kRepWord64:
+      opcode = kCheckedLoadWord64;
+      break;
     case kRepFloat32:
       opcode = kCheckedLoadFloat32;
       break;
@@ -491,6 +494,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
     case kRepWord32:
       opcode = kCheckedStoreWord32;
       break;
+    case kRepWord64:
+      opcode = kCheckedStoreWord64;
+      break;
     case kRepFloat32:
       opcode = kCheckedStoreFloat32;
       break;
index f102ef5..c21cc2d 100644 (file)
@@ -954,6 +954,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
       __ cmp(esp, Operand::StaticVariable(stack_limit));
       break;
     }
+    case kCheckedLoadWord64:
+    case kCheckedStoreWord64:
+      UNREACHABLE();  // currently unsupported checked int64 load/store.
+      break;
   }
 }  // NOLINT(readability/fn_size)
 
index a9db281..88471e6 100644 (file)
@@ -56,11 +56,13 @@ namespace compiler {
   V(CheckedLoadInt16)         \
   V(CheckedLoadUint16)        \
   V(CheckedLoadWord32)        \
+  V(CheckedLoadWord64)        \
   V(CheckedLoadFloat32)       \
   V(CheckedLoadFloat64)       \
   V(CheckedStoreWord8)        \
   V(CheckedStoreWord16)       \
   V(CheckedStoreWord32)       \
+  V(CheckedStoreWord64)       \
   V(CheckedStoreFloat32)      \
   V(CheckedStoreFloat64)      \
   TARGET_ARCH_OPCODE_LIST(V)
index cdd8bdb..be74193 100644 (file)
@@ -858,6 +858,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedStoreFloat64:
       ASSEMBLE_CHECKED_STORE_FLOAT(Double, sdc1);
       break;
+    case kCheckedLoadWord64:
+    case kCheckedStoreWord64:
+      UNREACHABLE();  // currently unsupported checked int64 load/store.
+      break;
   }
 }
 
index 670bd67..bcfa56a 100644 (file)
@@ -906,6 +906,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedLoadWord32:
       ASSEMBLE_CHECKED_LOAD_INTEGER(lw);
       break;
+    case kCheckedLoadWord64:
+      ASSEMBLE_CHECKED_LOAD_INTEGER(ld);
+      break;
     case kCheckedLoadFloat32:
       ASSEMBLE_CHECKED_LOAD_FLOAT(Single, lwc1);
       break;
@@ -921,6 +924,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedStoreWord32:
       ASSEMBLE_CHECKED_STORE_INTEGER(sw);
       break;
+    case kCheckedStoreWord64:
+      ASSEMBLE_CHECKED_STORE_INTEGER(sd);
+      break;
     case kCheckedStoreFloat32:
       ASSEMBLE_CHECKED_STORE_FLOAT(Single, swc1);
       break;
index 33d6f58..838b263 100644 (file)
@@ -841,6 +841,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) {
     case kRepWord32:
       opcode = kCheckedLoadWord32;
       break;
+    case kRepWord64:
+      opcode = kCheckedLoadWord64;
+      break;
     case kRepFloat32:
       opcode = kCheckedLoadFloat32;
       break;
@@ -885,6 +888,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
     case kRepWord32:
       opcode = kCheckedStoreWord32;
       break;
+    case kRepWord64:
+      opcode = kCheckedStoreWord64;
+      break;
     case kRepFloat32:
       opcode = kCheckedStoreFloat32;
       break;
index 83b857e..3d99b06 100644 (file)
@@ -1142,6 +1142,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedLoadWord32:
       ASSEMBLE_CHECKED_LOAD_INTEGER(lwa, lwax);
       break;
+    case kCheckedLoadWord64:
+#if V8_TARGET_ARCH_PPC64
+      ASSEMBLE_CHECKED_LOAD_INTEGER(ld, ldx);
+#else
+      UNREACHABLE();
+#endif
+      break;
     case kCheckedLoadFloat32:
       ASSEMBLE_CHECKED_LOAD_FLOAT(lfs, lfsx, 32);
       break;
@@ -1157,6 +1164,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedStoreWord32:
       ASSEMBLE_CHECKED_STORE_INTEGER(stw, stwx);
       break;
+    case kCheckedStoreWord64:
+#if V8_TARGET_ARCH_PPC64
+      ASSEMBLE_CHECKED_STORE_INTEGER(std, stdx);
+#else
+      UNREACHABLE();
+#endif
+      break;
     case kCheckedStoreFloat32:
       ASSEMBLE_CHECKED_STORE_FLOAT32();
       break;
index 197dcc1..d8543a3 100644 (file)
@@ -282,6 +282,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) {
     case kRepWord32:
       opcode = kCheckedLoadWord32;
       break;
+    case kRepWord64:
+      opcode = kCheckedLoadWord64;
+      break;
     case kRepFloat32:
       opcode = kCheckedLoadFloat32;
       break;
@@ -317,6 +320,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
     case kRepWord32:
       opcode = kCheckedStoreWord32;
       break;
+    case kRepWord64:
+      opcode = kCheckedStoreWord64;
+      break;
     case kRepFloat32:
       opcode = kCheckedStoreFloat32;
       break;
index 55f8088..5626080 100644 (file)
@@ -1271,6 +1271,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedLoadWord32:
       ASSEMBLE_CHECKED_LOAD_INTEGER(movl);
       break;
+    case kCheckedLoadWord64:
+      ASSEMBLE_CHECKED_LOAD_INTEGER(movq);
+      break;
     case kCheckedLoadFloat32:
       ASSEMBLE_CHECKED_LOAD_FLOAT(movss);
       break;
@@ -1286,6 +1289,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kCheckedStoreWord32:
       ASSEMBLE_CHECKED_STORE_INTEGER(movl);
       break;
+    case kCheckedStoreWord64:
+      ASSEMBLE_CHECKED_STORE_INTEGER(movq);
+      break;
     case kCheckedStoreFloat32:
       ASSEMBLE_CHECKED_STORE_FLOAT(movss);
       break;
index 0bcd526..fa63138 100644 (file)
@@ -233,6 +233,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) {
     case kRepWord32:
       opcode = kCheckedLoadWord32;
       break;
+    case kRepWord64:
+      opcode = kCheckedLoadWord64;
+      break;
     case kRepFloat32:
       opcode = kCheckedLoadFloat32;
       break;
@@ -280,6 +283,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
     case kRepWord32:
       opcode = kCheckedStoreWord32;
       break;
+    case kRepWord64:
+      opcode = kCheckedStoreWord64;
+      break;
     case kRepFloat32:
       opcode = kCheckedStoreFloat32;
       break;
index e174e70..596b7ab 100644 (file)
@@ -1224,6 +1224,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
       __ cmp(esp, Operand::StaticVariable(stack_limit));
       break;
     }
+    case kCheckedLoadWord64:
+    case kCheckedStoreWord64:
+      UNREACHABLE();  // currently unsupported checked int64 load/store.
+      break;
   }
 }  // NOLINT(readability/fn_size)
 
index 8b14dab..2206181 100644 (file)
@@ -5277,5 +5277,49 @@ TEST(RunCallCFunction8) {
     CHECK_EQ(x * 8, m.Call(x));
   }
 }
-
 #endif  // USE_SIMULATOR
+
+#if V8_TARGET_ARCH_64_BIT
+TEST(RunCheckedLoadInt64) {
+  int64_t buffer[] = {0x66bbccddeeff0011LL, 0x1122334455667788LL};
+  RawMachineAssemblerTester<int64_t> m(kMachInt32);
+  Node* base = m.PointerConstant(buffer);
+  Node* index = m.Parameter(0);
+  Node* length = m.Int32Constant(16);
+  Node* load =
+      m.NewNode(m.machine()->CheckedLoad(kMachInt64), base, index, length);
+  m.Return(load);
+
+  CHECK_EQ(buffer[0], m.Call(0));
+  CHECK_EQ(buffer[1], m.Call(8));
+  CHECK_EQ(0, m.Call(16));
+}
+
+
+TEST(RunCheckedStoreInt64) {
+  const int64_t write = 0x5566778899aabbLL;
+  const int64_t before = 0x33bbccddeeff0011LL;
+  int64_t buffer[] = {before, before};
+  RawMachineAssemblerTester<int32_t> m(kMachInt32);
+  Node* base = m.PointerConstant(buffer);
+  Node* index = m.Parameter(0);
+  Node* length = m.Int32Constant(16);
+  Node* value = m.Int64Constant(write);
+  Node* store = m.NewNode(m.machine()->CheckedStore(kMachInt64), base, index,
+                          length, value);
+  USE(store);
+  m.Return(m.Int32Constant(11));
+
+  CHECK_EQ(11, m.Call(16));
+  CHECK_EQ(before, buffer[0]);
+  CHECK_EQ(before, buffer[1]);
+
+  CHECK_EQ(11, m.Call(0));
+  CHECK_EQ(write, buffer[0]);
+  CHECK_EQ(before, buffer[1]);
+
+  CHECK_EQ(11, m.Call(8));
+  CHECK_EQ(write, buffer[0]);
+  CHECK_EQ(write, buffer[1]);
+}
+#endif