Commit 963d6645 authored by titzer's avatar titzer Committed by Commit bot

[turbofan] support for Int64 in CheckedLoad/CheckedStore on 64-bit platforms.

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}
parent 92e85aed
...@@ -878,6 +878,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -878,6 +878,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedStoreFloat64: case kCheckedStoreFloat64:
ASSEMBLE_CHECKED_STORE_FLOAT(64); ASSEMBLE_CHECKED_STORE_FLOAT(64);
break; break;
case kCheckedLoadWord64:
case kCheckedStoreWord64:
UNREACHABLE(); // currently unsupported checked int64 load/store.
break;
} }
} // NOLINT(readability/fn_size) } // NOLINT(readability/fn_size)
......
...@@ -302,6 +302,20 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { ...@@ -302,6 +302,20 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
} while (0) } 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) \ #define ASSEMBLE_CHECKED_STORE_FLOAT(width) \
do { \ do { \
auto buffer = i.InputRegister(0); \ auto buffer = i.InputRegister(0); \
...@@ -330,6 +344,20 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { ...@@ -330,6 +344,20 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
} while (0) } 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) \ #define ASSEMBLE_SHIFT(asm_instr, width) \
do { \ do { \
if (instr->InputAt(1)->IsRegister()) { \ if (instr->InputAt(1)->IsRegister()) { \
...@@ -942,6 +970,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -942,6 +970,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedLoadWord32: case kCheckedLoadWord32:
ASSEMBLE_CHECKED_LOAD_INTEGER(Ldr); ASSEMBLE_CHECKED_LOAD_INTEGER(Ldr);
break; break;
case kCheckedLoadWord64:
ASSEMBLE_CHECKED_LOAD_INTEGER_64(Ldr);
break;
case kCheckedLoadFloat32: case kCheckedLoadFloat32:
ASSEMBLE_CHECKED_LOAD_FLOAT(32); ASSEMBLE_CHECKED_LOAD_FLOAT(32);
break; break;
...@@ -957,6 +988,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -957,6 +988,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedStoreWord32: case kCheckedStoreWord32:
ASSEMBLE_CHECKED_STORE_INTEGER(Str); ASSEMBLE_CHECKED_STORE_INTEGER(Str);
break; break;
case kCheckedStoreWord64:
ASSEMBLE_CHECKED_STORE_INTEGER_64(Str);
break;
case kCheckedStoreFloat32: case kCheckedStoreFloat32:
ASSEMBLE_CHECKED_STORE_FLOAT(32); ASSEMBLE_CHECKED_STORE_FLOAT(32);
break; break;
......
...@@ -458,6 +458,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) { ...@@ -458,6 +458,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) {
case kRepWord32: case kRepWord32:
opcode = kCheckedLoadWord32; opcode = kCheckedLoadWord32;
break; break;
case kRepWord64:
opcode = kCheckedLoadWord64;
break;
case kRepFloat32: case kRepFloat32:
opcode = kCheckedLoadFloat32; opcode = kCheckedLoadFloat32;
break; break;
...@@ -491,6 +494,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) { ...@@ -491,6 +494,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
case kRepWord32: case kRepWord32:
opcode = kCheckedStoreWord32; opcode = kCheckedStoreWord32;
break; break;
case kRepWord64:
opcode = kCheckedStoreWord64;
break;
case kRepFloat32: case kRepFloat32:
opcode = kCheckedStoreFloat32; opcode = kCheckedStoreFloat32;
break; break;
......
...@@ -954,6 +954,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -954,6 +954,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ cmp(esp, Operand::StaticVariable(stack_limit)); __ cmp(esp, Operand::StaticVariable(stack_limit));
break; break;
} }
case kCheckedLoadWord64:
case kCheckedStoreWord64:
UNREACHABLE(); // currently unsupported checked int64 load/store.
break;
} }
} // NOLINT(readability/fn_size) } // NOLINT(readability/fn_size)
......
...@@ -56,11 +56,13 @@ namespace compiler { ...@@ -56,11 +56,13 @@ namespace compiler {
V(CheckedLoadInt16) \ V(CheckedLoadInt16) \
V(CheckedLoadUint16) \ V(CheckedLoadUint16) \
V(CheckedLoadWord32) \ V(CheckedLoadWord32) \
V(CheckedLoadWord64) \
V(CheckedLoadFloat32) \ V(CheckedLoadFloat32) \
V(CheckedLoadFloat64) \ V(CheckedLoadFloat64) \
V(CheckedStoreWord8) \ V(CheckedStoreWord8) \
V(CheckedStoreWord16) \ V(CheckedStoreWord16) \
V(CheckedStoreWord32) \ V(CheckedStoreWord32) \
V(CheckedStoreWord64) \
V(CheckedStoreFloat32) \ V(CheckedStoreFloat32) \
V(CheckedStoreFloat64) \ V(CheckedStoreFloat64) \
TARGET_ARCH_OPCODE_LIST(V) TARGET_ARCH_OPCODE_LIST(V)
......
...@@ -858,6 +858,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -858,6 +858,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedStoreFloat64: case kCheckedStoreFloat64:
ASSEMBLE_CHECKED_STORE_FLOAT(Double, sdc1); ASSEMBLE_CHECKED_STORE_FLOAT(Double, sdc1);
break; break;
case kCheckedLoadWord64:
case kCheckedStoreWord64:
UNREACHABLE(); // currently unsupported checked int64 load/store.
break;
} }
} }
......
...@@ -906,6 +906,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -906,6 +906,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedLoadWord32: case kCheckedLoadWord32:
ASSEMBLE_CHECKED_LOAD_INTEGER(lw); ASSEMBLE_CHECKED_LOAD_INTEGER(lw);
break; break;
case kCheckedLoadWord64:
ASSEMBLE_CHECKED_LOAD_INTEGER(ld);
break;
case kCheckedLoadFloat32: case kCheckedLoadFloat32:
ASSEMBLE_CHECKED_LOAD_FLOAT(Single, lwc1); ASSEMBLE_CHECKED_LOAD_FLOAT(Single, lwc1);
break; break;
...@@ -921,6 +924,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -921,6 +924,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedStoreWord32: case kCheckedStoreWord32:
ASSEMBLE_CHECKED_STORE_INTEGER(sw); ASSEMBLE_CHECKED_STORE_INTEGER(sw);
break; break;
case kCheckedStoreWord64:
ASSEMBLE_CHECKED_STORE_INTEGER(sd);
break;
case kCheckedStoreFloat32: case kCheckedStoreFloat32:
ASSEMBLE_CHECKED_STORE_FLOAT(Single, swc1); ASSEMBLE_CHECKED_STORE_FLOAT(Single, swc1);
break; break;
......
...@@ -841,6 +841,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) { ...@@ -841,6 +841,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) {
case kRepWord32: case kRepWord32:
opcode = kCheckedLoadWord32; opcode = kCheckedLoadWord32;
break; break;
case kRepWord64:
opcode = kCheckedLoadWord64;
break;
case kRepFloat32: case kRepFloat32:
opcode = kCheckedLoadFloat32; opcode = kCheckedLoadFloat32;
break; break;
...@@ -885,6 +888,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) { ...@@ -885,6 +888,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
case kRepWord32: case kRepWord32:
opcode = kCheckedStoreWord32; opcode = kCheckedStoreWord32;
break; break;
case kRepWord64:
opcode = kCheckedStoreWord64;
break;
case kRepFloat32: case kRepFloat32:
opcode = kCheckedStoreFloat32; opcode = kCheckedStoreFloat32;
break; break;
......
...@@ -1142,6 +1142,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -1142,6 +1142,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedLoadWord32: case kCheckedLoadWord32:
ASSEMBLE_CHECKED_LOAD_INTEGER(lwa, lwax); ASSEMBLE_CHECKED_LOAD_INTEGER(lwa, lwax);
break; break;
case kCheckedLoadWord64:
#if V8_TARGET_ARCH_PPC64
ASSEMBLE_CHECKED_LOAD_INTEGER(ld, ldx);
#else
UNREACHABLE();
#endif
break;
case kCheckedLoadFloat32: case kCheckedLoadFloat32:
ASSEMBLE_CHECKED_LOAD_FLOAT(lfs, lfsx, 32); ASSEMBLE_CHECKED_LOAD_FLOAT(lfs, lfsx, 32);
break; break;
...@@ -1157,6 +1164,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -1157,6 +1164,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedStoreWord32: case kCheckedStoreWord32:
ASSEMBLE_CHECKED_STORE_INTEGER(stw, stwx); ASSEMBLE_CHECKED_STORE_INTEGER(stw, stwx);
break; break;
case kCheckedStoreWord64:
#if V8_TARGET_ARCH_PPC64
ASSEMBLE_CHECKED_STORE_INTEGER(std, stdx);
#else
UNREACHABLE();
#endif
break;
case kCheckedStoreFloat32: case kCheckedStoreFloat32:
ASSEMBLE_CHECKED_STORE_FLOAT32(); ASSEMBLE_CHECKED_STORE_FLOAT32();
break; break;
......
...@@ -282,6 +282,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) { ...@@ -282,6 +282,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) {
case kRepWord32: case kRepWord32:
opcode = kCheckedLoadWord32; opcode = kCheckedLoadWord32;
break; break;
case kRepWord64:
opcode = kCheckedLoadWord64;
break;
case kRepFloat32: case kRepFloat32:
opcode = kCheckedLoadFloat32; opcode = kCheckedLoadFloat32;
break; break;
...@@ -317,6 +320,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) { ...@@ -317,6 +320,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
case kRepWord32: case kRepWord32:
opcode = kCheckedStoreWord32; opcode = kCheckedStoreWord32;
break; break;
case kRepWord64:
opcode = kCheckedStoreWord64;
break;
case kRepFloat32: case kRepFloat32:
opcode = kCheckedStoreFloat32; opcode = kCheckedStoreFloat32;
break; break;
......
...@@ -1271,6 +1271,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -1271,6 +1271,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedLoadWord32: case kCheckedLoadWord32:
ASSEMBLE_CHECKED_LOAD_INTEGER(movl); ASSEMBLE_CHECKED_LOAD_INTEGER(movl);
break; break;
case kCheckedLoadWord64:
ASSEMBLE_CHECKED_LOAD_INTEGER(movq);
break;
case kCheckedLoadFloat32: case kCheckedLoadFloat32:
ASSEMBLE_CHECKED_LOAD_FLOAT(movss); ASSEMBLE_CHECKED_LOAD_FLOAT(movss);
break; break;
...@@ -1286,6 +1289,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -1286,6 +1289,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedStoreWord32: case kCheckedStoreWord32:
ASSEMBLE_CHECKED_STORE_INTEGER(movl); ASSEMBLE_CHECKED_STORE_INTEGER(movl);
break; break;
case kCheckedStoreWord64:
ASSEMBLE_CHECKED_STORE_INTEGER(movq);
break;
case kCheckedStoreFloat32: case kCheckedStoreFloat32:
ASSEMBLE_CHECKED_STORE_FLOAT(movss); ASSEMBLE_CHECKED_STORE_FLOAT(movss);
break; break;
......
...@@ -233,6 +233,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) { ...@@ -233,6 +233,9 @@ void InstructionSelector::VisitCheckedLoad(Node* node) {
case kRepWord32: case kRepWord32:
opcode = kCheckedLoadWord32; opcode = kCheckedLoadWord32;
break; break;
case kRepWord64:
opcode = kCheckedLoadWord64;
break;
case kRepFloat32: case kRepFloat32:
opcode = kCheckedLoadFloat32; opcode = kCheckedLoadFloat32;
break; break;
...@@ -280,6 +283,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) { ...@@ -280,6 +283,9 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
case kRepWord32: case kRepWord32:
opcode = kCheckedStoreWord32; opcode = kCheckedStoreWord32;
break; break;
case kRepWord64:
opcode = kCheckedStoreWord64;
break;
case kRepFloat32: case kRepFloat32:
opcode = kCheckedStoreFloat32; opcode = kCheckedStoreFloat32;
break; break;
......
...@@ -1224,6 +1224,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -1224,6 +1224,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ cmp(esp, Operand::StaticVariable(stack_limit)); __ cmp(esp, Operand::StaticVariable(stack_limit));
break; break;
} }
case kCheckedLoadWord64:
case kCheckedStoreWord64:
UNREACHABLE(); // currently unsupported checked int64 load/store.
break;
} }
} // NOLINT(readability/fn_size) } // NOLINT(readability/fn_size)
......
...@@ -5277,5 +5277,49 @@ TEST(RunCallCFunction8) { ...@@ -5277,5 +5277,49 @@ TEST(RunCallCFunction8) {
CHECK_EQ(x * 8, m.Call(x)); CHECK_EQ(x * 8, m.Call(x));
} }
} }
#endif // USE_SIMULATOR #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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment