[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:
titzer 2015-09-03 03:45:35 -07:00 committed by Commit bot
parent 92e85aed10
commit 963d664581
14 changed files with 147 additions and 1 deletions

View 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)

View 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;

View 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;

View 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)

View 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)

View 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;
}
}

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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)

View 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