[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}
This commit is contained in:
parent
92e85aed10
commit
963d664581
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user