Commit c9f59780 authored by titzer's avatar titzer Committed by Commit bot

[wasm] Fix arm64 frame alignment.

    In JavaScript code and stubs, JSSP mirrors the CSP but may be unaligned.
    But in WASM code only CSP is used, like native code, and it must be
    aligned.
    Calls into WASM from JS need to carefully align the C stack
    pointer (csp) and restore the previous JSSP, while calls from WASM
    to JS need to compute a new JSSP and restore their CSP after the
    call.

R=ahaas@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#35096}
parent 000d3389
...@@ -1355,6 +1355,14 @@ void MacroAssembler::AssertStackConsistency() { ...@@ -1355,6 +1355,14 @@ void MacroAssembler::AssertStackConsistency() {
} }
} }
void MacroAssembler::AssertCspAligned() {
if (emit_debug_code() && use_real_aborts()) {
// TODO(titzer): use a real assert for alignment check?
UseScratchRegisterScope scope(this);
Register temp = scope.AcquireX();
ldr(temp, MemOperand(csp));
}
}
void MacroAssembler::AssertFPCRState(Register fpcr) { void MacroAssembler::AssertFPCRState(Register fpcr) {
if (emit_debug_code()) { if (emit_debug_code()) {
......
...@@ -788,6 +788,9 @@ class MacroAssembler : public Assembler { ...@@ -788,6 +788,9 @@ class MacroAssembler : public Assembler {
// If emit_debug_code() is false, this emits no code. // If emit_debug_code() is false, this emits no code.
void AssertStackConsistency(); void AssertStackConsistency();
// Emits a runtime assert that the CSP is aligned.
void AssertCspAligned();
// Preserve the callee-saved registers (as defined by AAPCS64). // Preserve the callee-saved registers (as defined by AAPCS64).
// //
// Higher-numbered registers are pushed before lower-numbered registers, and // Higher-numbered registers are pushed before lower-numbered registers, and
......
...@@ -530,16 +530,20 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -530,16 +530,20 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Add(target, target, Code::kHeaderSize - kHeapObjectTag); __ Add(target, target, Code::kHeaderSize - kHeapObjectTag);
__ Call(target); __ Call(target);
} }
RecordCallPosition(instr);
// TODO(titzer): this is ugly. JSSP should be a caller-save register // TODO(titzer): this is ugly. JSSP should be a caller-save register
// in this case, but it is not possible to express in the register // in this case, but it is not possible to express in the register
// allocator. // allocator.
CallDescriptor::Flags flags = CallDescriptor::Flags flags(MiscField::decode(opcode));
static_cast<CallDescriptor::Flags>(MiscField::decode(opcode));
if (flags & CallDescriptor::kRestoreJSSP) { if (flags & CallDescriptor::kRestoreJSSP) {
__ mov(jssp, csp); __ Ldr(jssp, MemOperand(csp));
__ Mov(csp, jssp);
}
if (flags & CallDescriptor::kRestoreCSP) {
__ Mov(csp, jssp);
__ AssertCspAligned();
} }
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
RecordCallPosition(instr);
break; break;
} }
case kArchTailCallCodeObjectFromJSFunction: case kArchTailCallCodeObjectFromJSFunction:
...@@ -575,16 +579,20 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -575,16 +579,20 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
} }
__ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Call(x10); __ Call(x10);
RecordCallPosition(instr);
// TODO(titzer): this is ugly. JSSP should be a caller-save register // TODO(titzer): this is ugly. JSSP should be a caller-save register
// in this case, but it is not possible to express in the register // in this case, but it is not possible to express in the register
// allocator. // allocator.
CallDescriptor::Flags flags = CallDescriptor::Flags flags(MiscField::decode(opcode));
static_cast<CallDescriptor::Flags>(MiscField::decode(opcode));
if (flags & CallDescriptor::kRestoreJSSP) { if (flags & CallDescriptor::kRestoreJSSP) {
__ mov(jssp, csp); __ Ldr(jssp, MemOperand(csp));
__ Mov(csp, jssp);
}
if (flags & CallDescriptor::kRestoreCSP) {
__ Mov(csp, jssp);
__ AssertCspAligned();
} }
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
RecordCallPosition(instr);
break; break;
} }
case kArchTailCallJSFunctionFromJSFunction: case kArchTailCallJSFunctionFromJSFunction:
...@@ -967,26 +975,46 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -967,26 +975,46 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
// Pseudo instruction turned into cbz/cbnz in AssembleArchBranch. // Pseudo instruction turned into cbz/cbnz in AssembleArchBranch.
break; break;
case kArm64ClaimCSP: { case kArm64ClaimCSP: {
int count = i.InputInt32(0); int count = RoundUp(i.InputInt32(0), 2);
Register prev = __ StackPointer(); Register prev = __ StackPointer();
if (prev.Is(jssp)) { if (prev.Is(jssp)) {
__ AlignAndSetCSPForFrame(); // TODO(titzer): make this a macro-assembler method.
} // Align the CSP and store the previous JSSP on the stack.
if (count > 0) { UseScratchRegisterScope scope(masm());
__ Claim(count); Register tmp = scope.AcquireX();
int sp_alignment = __ ActivationFrameAlignment();
__ Sub(tmp, jssp, kPointerSize);
__ And(tmp, tmp, Operand(~static_cast<uint64_t>(sp_alignment - 1)));
__ Mov(csp, tmp);
__ Str(jssp, MemOperand(csp));
if (count > 0) {
__ SetStackPointer(csp);
__ Claim(count);
__ SetStackPointer(prev);
}
} else {
__ AssertCspAligned();
if (count > 0) {
__ Claim(count);
frame_access_state()->IncreaseSPDelta(count);
}
} }
__ SetStackPointer(prev);
frame_access_state()->IncreaseSPDelta(count);
break; break;
} }
case kArm64ClaimJSSP: { case kArm64ClaimJSSP: {
int count = i.InputInt32(0); int count = i.InputInt32(0);
if (csp.Is(__ StackPointer())) { if (csp.Is(__ StackPointer())) {
// No JSP is set up. Compute it from the CSP. // No JSSP is set up. Compute it from the CSP.
int even = RoundUp(count, 2); __ AssertCspAligned();
__ Sub(jssp, csp, count * kPointerSize); if (count > 0) {
__ Sub(csp, csp, even * kPointerSize); // Must always be aligned. int even = RoundUp(count, 2);
frame_access_state()->IncreaseSPDelta(even); __ Sub(jssp, csp, count * kPointerSize);
__ Sub(csp, csp, even * kPointerSize); // Must always be aligned.
frame_access_state()->IncreaseSPDelta(even);
} else {
__ Mov(jssp, csp);
}
} else { } else {
// JSSP is the current stack pointer, just use regular Claim(). // JSSP is the current stack pointer, just use regular Claim().
__ Claim(count); __ Claim(count);
...@@ -1467,6 +1495,10 @@ void CodeGenerator::AssembleDeoptimizerCall( ...@@ -1467,6 +1495,10 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() { void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (descriptor->UseNativeStack()) {
__ AssertCspAligned();
}
frame()->AlignFrame(16); frame()->AlignFrame(16);
int stack_shrink_slots = frame()->GetSpillSlotCount(); int stack_shrink_slots = frame()->GetSpillSlotCount();
if (frame()->needs_frame()) { if (frame()->needs_frame()) {
...@@ -1579,6 +1611,10 @@ void CodeGenerator::AssembleReturn() { ...@@ -1579,6 +1611,10 @@ void CodeGenerator::AssembleReturn() {
pop_count += (pop_count & 1); // align pop_count += (pop_count & 1); // align
} }
__ Drop(pop_count); __ Drop(pop_count);
if (descriptor->UseNativeStack()) {
__ AssertCspAligned();
}
__ Ret(); __ Ret();
} }
......
...@@ -1631,20 +1631,20 @@ void InstructionSelector::EmitPrepareArguments( ...@@ -1631,20 +1631,20 @@ void InstructionSelector::EmitPrepareArguments(
Node* node) { Node* node) {
Arm64OperandGenerator g(this); Arm64OperandGenerator g(this);
bool from_native_stack = linkage()->GetIncomingDescriptor()->UseNativeStack();
bool to_native_stack = descriptor->UseNativeStack(); bool to_native_stack = descriptor->UseNativeStack();
bool always_claim = to_native_stack != from_native_stack;
int claim_count = static_cast<int>(arguments->size()); int claim_count = static_cast<int>(arguments->size());
int slot = claim_count - 1; int slot = claim_count - 1;
if (to_native_stack) {
// Native stack must always be aligned to 16 (2 words).
claim_count = RoundUp(claim_count, 2);
}
// TODO(titzer): claim and poke probably take small immediates.
// Bump the stack pointer(s). // Bump the stack pointer(s).
if (claim_count > 0 || to_native_stack) { if (claim_count > 0 || always_claim) {
// TODO(titzer): claim and poke probably take small immediates.
// TODO(titzer): it would be better to bump the csp here only // TODO(titzer): it would be better to bump the csp here only
// and emit paired stores with increment for non c frames. // and emit paired stores with increment for non c frames.
ArchOpcode claim = to_native_stack ? kArm64ClaimCSP : kArm64ClaimJSSP; ArchOpcode claim = to_native_stack ? kArm64ClaimCSP : kArm64ClaimJSSP;
// Claim(0) isn't a nop if there is a mismatch between CSP and JSSP.
Emit(claim, g.NoOutput(), g.TempImmediate(claim_count)); Emit(claim, g.NoOutput(), g.TempImmediate(claim_count));
} }
......
...@@ -230,6 +230,11 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor( ...@@ -230,6 +230,11 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor(
// The target for C calls is always an address (i.e. machine pointer). // The target for C calls is always an address (i.e. machine pointer).
MachineType target_type = MachineType::Pointer(); MachineType target_type = MachineType::Pointer();
LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
CallDescriptor::Flags flags = CallDescriptor::kUseNativeStack;
if (set_initialize_root_flag) {
flags |= CallDescriptor::kInitializeRootRegister;
}
return new (zone) CallDescriptor( // -- return new (zone) CallDescriptor( // --
CallDescriptor::kCallAddress, // kind CallDescriptor::kCallAddress, // kind
target_type, // target MachineType target_type, // target MachineType
...@@ -240,10 +245,7 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor( ...@@ -240,10 +245,7 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor(
Operator::kNoProperties, // properties Operator::kNoProperties, // properties
kCalleeSaveRegisters, // callee-saved registers kCalleeSaveRegisters, // callee-saved registers
kCalleeSaveFPRegisters, // callee-saved fp regs kCalleeSaveFPRegisters, // callee-saved fp regs
set_initialize_root_flag ? // flags flags, "c-call");
CallDescriptor::kInitializeRootRegister
: CallDescriptor::kNoFlags,
"c-call");
} }
} // namespace compiler } // namespace compiler
......
...@@ -1543,13 +1543,15 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -1543,13 +1543,15 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
buffer.instruction_args.push_back(g.Label(handler)); buffer.instruction_args.push_back(g.Label(handler));
} }
// (arm64 only) caller uses JSSP but callee might destroy it. bool from_native_stack = linkage()->GetIncomingDescriptor()->UseNativeStack();
if (descriptor->UseNativeStack() && bool to_native_stack = descriptor->UseNativeStack();
!linkage()->GetIncomingDescriptor()->UseNativeStack()) { if (from_native_stack != to_native_stack) {
flags |= CallDescriptor::kRestoreJSSP; // (arm64 only) Mismatch in the use of stack pointers. One or the other
// has to be restored manually by the code generator.
flags |= to_native_stack ? CallDescriptor::kRestoreJSSP
: CallDescriptor::kRestoreCSP;
} }
// Select the appropriate opcode based on the call type. // Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop; InstructionCode opcode = kArchNop;
switch (descriptor->kind()) { switch (descriptor->kind()) {
......
...@@ -160,10 +160,11 @@ class CallDescriptor final : public ZoneObject { ...@@ -160,10 +160,11 @@ class CallDescriptor final : public ZoneObject {
kCanUseRoots = 1u << 6, kCanUseRoots = 1u << 6,
// (arm64 only) native stack should be used for arguments. // (arm64 only) native stack should be used for arguments.
kUseNativeStack = 1u << 7, kUseNativeStack = 1u << 7,
// (arm64 only) call instruction has to restore JSSP. // (arm64 only) call instruction has to restore JSSP or CSP.
kRestoreJSSP = 1u << 8, kRestoreJSSP = 1u << 8,
kRestoreCSP = 1u << 9,
// Causes the code generator to initialize the root register. // Causes the code generator to initialize the root register.
kInitializeRootRegister = 1u << 9, kInitializeRootRegister = 1u << 10,
kPatchableCallSiteWithNop = kPatchableCallSite | kNeedsNopAfterCall kPatchableCallSiteWithNop = kPatchableCallSite | kNeedsNopAfterCall
}; };
typedef base::Flags<Flag> Flags; typedef base::Flags<Flag> Flags;
......
...@@ -2461,6 +2461,12 @@ Handle<JSFunction> CompileJSToWasmWrapper( ...@@ -2461,6 +2461,12 @@ Handle<JSFunction> CompileJSToWasmWrapper(
CompilationInfo info(func_name, isolate, &zone, flags); CompilationInfo info(func_name, isolate, &zone, flags);
Handle<Code> code = Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr); Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_opt_code && !code.is_null()) {
OFStream os(stdout);
code->Disassemble(buffer.start(), os);
}
#endif
if (debugging) { if (debugging) {
buffer.Dispose(); buffer.Dispose();
} }
...@@ -2541,6 +2547,12 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module, ...@@ -2541,6 +2547,12 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
CompilationInfo info(func_name, isolate, &zone, flags); CompilationInfo info(func_name, isolate, &zone, flags);
code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr); code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_opt_code && !code.is_null()) {
OFStream os(stdout);
code->Disassemble(buffer.start(), os);
}
#endif
if (debugging) { if (debugging) {
buffer.Dispose(); buffer.Dispose();
} }
......
...@@ -66,11 +66,18 @@ uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig, ...@@ -66,11 +66,18 @@ uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig,
uint32_t AddJSSelector(TestingModule* module, FunctionSig* sig, int which) { uint32_t AddJSSelector(TestingModule* module, FunctionSig* sig, int which) {
const int kMaxParams = 8; const int kMaxParams = 11;
static const char* formals[kMaxParams] = { static const char* formals[kMaxParams] = {"",
"", "a", "a,b", "a,b,c", "a",
"a,b,c,d", "a,b,c,d,e", "a,b,c,d,e,f", "a,b,c,d,e,f,g", "a,b",
}; "a,b,c",
"a,b,c,d",
"a,b,c,d,e",
"a,b,c,d,e,f",
"a,b,c,d,e,f,g",
"a,b,c,d,e,f,g,h",
"a,b,c,d,e,f,g,h,i",
"a,b,c,d,e,f,g,h,i,j"};
CHECK_LT(which, static_cast<int>(sig->parameter_count())); CHECK_LT(which, static_cast<int>(sig->parameter_count()));
CHECK_LT(static_cast<int>(sig->parameter_count()), kMaxParams); CHECK_LT(static_cast<int>(sig->parameter_count()), kMaxParams);
...@@ -173,8 +180,6 @@ TEST(Run_I32Popcount_jswrapped) { ...@@ -173,8 +180,6 @@ TEST(Run_I32Popcount_jswrapped) {
} }
#if !V8_TARGET_ARCH_ARM64
// TODO(titzer): dynamic frame alignment on arm64
TEST(Run_CallJS_Add_jswrapped) { TEST(Run_CallJS_Add_jswrapped) {
TestSignatures sigs; TestSignatures sigs;
TestingModule module; TestingModule module;
...@@ -189,12 +194,9 @@ TEST(Run_CallJS_Add_jswrapped) { ...@@ -189,12 +194,9 @@ TEST(Run_CallJS_Add_jswrapped) {
EXPECT_CALL(199, jsfunc, 100, -1); EXPECT_CALL(199, jsfunc, 100, -1);
EXPECT_CALL(-666666801, jsfunc, -666666900, -1); EXPECT_CALL(-666666801, jsfunc, -666666900, -1);
} }
#endif
void RunJSSelectTest(int which) { void RunJSSelectTest(int which) {
#if !V8_TARGET_ARCH_ARM
// TODO(titzer): fix tests on arm and reenable
const int kMaxParams = 8; const int kMaxParams = 8;
PredictableInputValues inputs(0x100); PredictableInputValues inputs(0x100);
LocalType type = kAstF64; LocalType type = kAstF64;
...@@ -225,7 +227,6 @@ void RunJSSelectTest(int which) { ...@@ -225,7 +227,6 @@ void RunJSSelectTest(int which) {
double expected = inputs.arg_d(which); double expected = inputs.arg_d(which);
EXPECT_CALL(expected, jsfunc, 0.0, 0.0); EXPECT_CALL(expected, jsfunc, 0.0, 0.0);
} }
#endif
} }
...@@ -298,10 +299,11 @@ TEST(Run_WASMSelect_7) { RunWASMSelectTest(7); } ...@@ -298,10 +299,11 @@ TEST(Run_WASMSelect_7) { RunWASMSelectTest(7); }
void RunWASMSelectAlignTest(int num_args, int num_params) { void RunWASMSelectAlignTest(int num_args, int num_params) {
PredictableInputValues inputs(0x300); PredictableInputValues inputs(0x300);
Isolate* isolate = CcTest::InitIsolateOnce(); Isolate* isolate = CcTest::InitIsolateOnce();
const int kMaxParams = 4; const int kMaxParams = 10;
DCHECK_LE(num_args, kMaxParams); DCHECK_LE(num_args, kMaxParams);
LocalType type = kAstF64; LocalType type = kAstF64;
LocalType types[kMaxParams + 1] = {type, type, type, type, type}; LocalType types[kMaxParams + 1] = {type, type, type, type, type, type,
type, type, type, type, type};
FunctionSig sig(1, num_params, types); FunctionSig sig(1, num_params, types);
for (int which = 0; which < num_params; which++) { for (int which = 0; which < num_params; which++) {
...@@ -310,12 +312,16 @@ void RunWASMSelectAlignTest(int num_args, int num_params) { ...@@ -310,12 +312,16 @@ void RunWASMSelectAlignTest(int num_args, int num_params) {
BUILD(t, WASM_GET_LOCAL(which)); BUILD(t, WASM_GET_LOCAL(which));
Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd()); Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
Handle<Object> args[] = { Handle<Object> args[] = {isolate->factory()->NewNumber(inputs.arg_d(0)),
isolate->factory()->NewNumber(inputs.arg_d(0)), isolate->factory()->NewNumber(inputs.arg_d(1)),
isolate->factory()->NewNumber(inputs.arg_d(1)), isolate->factory()->NewNumber(inputs.arg_d(2)),
isolate->factory()->NewNumber(inputs.arg_d(2)), isolate->factory()->NewNumber(inputs.arg_d(3)),
isolate->factory()->NewNumber(inputs.arg_d(3)), isolate->factory()->NewNumber(inputs.arg_d(4)),
}; isolate->factory()->NewNumber(inputs.arg_d(5)),
isolate->factory()->NewNumber(inputs.arg_d(6)),
isolate->factory()->NewNumber(inputs.arg_d(7)),
isolate->factory()->NewNumber(inputs.arg_d(8)),
isolate->factory()->NewNumber(inputs.arg_d(9))};
double nan = std::numeric_limits<double>::quiet_NaN(); double nan = std::numeric_limits<double>::quiet_NaN();
double expected = which < num_args ? inputs.arg_d(which) : nan; double expected = which < num_args ? inputs.arg_d(which) : nan;
...@@ -353,16 +359,43 @@ TEST(Run_WASMSelectAlign_4) { ...@@ -353,16 +359,43 @@ TEST(Run_WASMSelectAlign_4) {
RunWASMSelectAlignTest(4, 4); RunWASMSelectAlignTest(4, 4);
} }
TEST(Run_WASMSelectAlign_7) {
RunWASMSelectAlignTest(7, 5);
RunWASMSelectAlignTest(7, 6);
RunWASMSelectAlignTest(7, 7);
}
TEST(Run_WASMSelectAlign_8) {
RunWASMSelectAlignTest(8, 5);
RunWASMSelectAlignTest(8, 6);
RunWASMSelectAlignTest(8, 7);
RunWASMSelectAlignTest(8, 8);
}
TEST(Run_WASMSelectAlign_9) {
RunWASMSelectAlignTest(9, 6);
RunWASMSelectAlignTest(9, 7);
RunWASMSelectAlignTest(9, 8);
RunWASMSelectAlignTest(9, 9);
}
TEST(Run_WASMSelectAlign_10) {
RunWASMSelectAlignTest(10, 7);
RunWASMSelectAlignTest(10, 8);
RunWASMSelectAlignTest(10, 9);
RunWASMSelectAlignTest(10, 10);
}
void RunJSSelectAlignTest(int num_args, int num_params) { void RunJSSelectAlignTest(int num_args, int num_params) {
PredictableInputValues inputs(0x400); PredictableInputValues inputs(0x400);
Isolate* isolate = CcTest::InitIsolateOnce(); Isolate* isolate = CcTest::InitIsolateOnce();
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
const int kMaxParams = 4; const int kMaxParams = 10;
CHECK_LE(num_args, kMaxParams); CHECK_LE(num_args, kMaxParams);
CHECK_LE(num_params, kMaxParams); CHECK_LE(num_params, kMaxParams);
LocalType type = kAstF64; LocalType type = kAstF64;
LocalType types[kMaxParams + 1] = {type, type, type, type, type}; LocalType types[kMaxParams + 1] = {type, type, type, type, type, type,
type, type, type, type, type};
FunctionSig sig(1, num_params, types); FunctionSig sig(1, num_params, types);
// Build the calling code. // Build the calling code.
...@@ -392,6 +425,12 @@ void RunJSSelectAlignTest(int num_args, int num_params) { ...@@ -392,6 +425,12 @@ void RunJSSelectAlignTest(int num_args, int num_params) {
factory->NewNumber(inputs.arg_d(1)), factory->NewNumber(inputs.arg_d(1)),
factory->NewNumber(inputs.arg_d(2)), factory->NewNumber(inputs.arg_d(2)),
factory->NewNumber(inputs.arg_d(3)), factory->NewNumber(inputs.arg_d(3)),
factory->NewNumber(inputs.arg_d(4)),
factory->NewNumber(inputs.arg_d(5)),
factory->NewNumber(inputs.arg_d(6)),
factory->NewNumber(inputs.arg_d(7)),
factory->NewNumber(inputs.arg_d(8)),
factory->NewNumber(inputs.arg_d(9)),
}; };
double nan = std::numeric_limits<double>::quiet_NaN(); double nan = std::numeric_limits<double>::quiet_NaN();
...@@ -406,29 +445,50 @@ TEST(Run_JSSelectAlign_0) { ...@@ -406,29 +445,50 @@ TEST(Run_JSSelectAlign_0) {
RunJSSelectAlignTest(0, 2); RunJSSelectAlignTest(0, 2);
} }
TEST(Run_JSSelectAlign_1) {
RunJSSelectAlignTest(1, 2);
RunJSSelectAlignTest(1, 3);
}
TEST(Run_JSSelectAlign_2) { TEST(Run_JSSelectAlign_2) {
RunJSSelectAlignTest(2, 3); RunJSSelectAlignTest(2, 3);
RunJSSelectAlignTest(2, 4); RunJSSelectAlignTest(2, 4);
} }
TEST(Run_JSSelectAlign_3) {
RunJSSelectAlignTest(3, 3);
RunJSSelectAlignTest(3, 4);
}
TEST(Run_JSSelectAlign_4) { TEST(Run_JSSelectAlign_4) {
RunJSSelectAlignTest(4, 3); RunJSSelectAlignTest(4, 3);
RunJSSelectAlignTest(4, 4); RunJSSelectAlignTest(4, 4);
} }
TEST(Run_JSSelectAlign_7) {
RunJSSelectAlignTest(7, 3);
RunJSSelectAlignTest(7, 4);
RunJSSelectAlignTest(7, 4);
RunJSSelectAlignTest(7, 4);
}
#if !V8_TARGET_ARCH_ARM64 TEST(Run_JSSelectAlign_8) {
// TODO(titzer): dynamic frame alignment on arm64 RunJSSelectAlignTest(8, 5);
TEST(Run_JSSelectAlign_1) { RunJSSelectAlignTest(8, 6);
RunJSSelectAlignTest(1, 2); RunJSSelectAlignTest(8, 7);
RunJSSelectAlignTest(1, 3); RunJSSelectAlignTest(8, 8);
} }
TEST(Run_JSSelectAlign_9) {
RunJSSelectAlignTest(9, 6);
RunJSSelectAlignTest(9, 7);
RunJSSelectAlignTest(9, 8);
RunJSSelectAlignTest(9, 9);
}
TEST(Run_JSSelectAlign_3) { TEST(Run_JSSelectAlign_10) {
RunJSSelectAlignTest(3, 3); RunJSSelectAlignTest(10, 7);
RunJSSelectAlignTest(3, 4); RunJSSelectAlignTest(10, 8);
RunJSSelectAlignTest(10, 9);
RunJSSelectAlignTest(10, 10);
} }
#endif
...@@ -19,7 +19,6 @@ using namespace v8::internal::compiler; ...@@ -19,7 +19,6 @@ using namespace v8::internal::compiler;
using namespace v8::internal::wasm; using namespace v8::internal::wasm;
#if !V8_TARGET_ARCH_ARM64
// TODO(titzer): fix arm64 frame alignment. // TODO(titzer): fix arm64 frame alignment.
namespace { namespace {
void TestModule(WasmModuleIndex* module, int32_t expected_result) { void TestModule(WasmModuleIndex* module, int32_t expected_result) {
...@@ -207,5 +206,3 @@ TEST(Run_WasmModule_Global) { ...@@ -207,5 +206,3 @@ TEST(Run_WasmModule_Global) {
TestModule(writer->WriteTo(&zone), 97); TestModule(writer->WriteTo(&zone), 97);
} }
#endif #endif
#endif // !V8_TARGET_ARCH_ARM64
...@@ -2680,9 +2680,6 @@ TEST(Run_Wasm_F64CopySign) { ...@@ -2680,9 +2680,6 @@ TEST(Run_Wasm_F64CopySign) {
} }
// TODO(tizer): Fix on arm and reenable.
#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
TEST(Run_Wasm_F32CopySign) { TEST(Run_Wasm_F32CopySign) {
WasmRunner<float> r(MachineType::Float32(), MachineType::Float32()); WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
...@@ -2692,10 +2689,6 @@ TEST(Run_Wasm_F32CopySign) { ...@@ -2692,10 +2689,6 @@ TEST(Run_Wasm_F32CopySign) {
} }
} }
#endif
void CompileCallIndirectMany(LocalType param) { void CompileCallIndirectMany(LocalType param) {
// Make sure we don't run out of registers when compiling indirect calls // Make sure we don't run out of registers when compiling indirect calls
// with many many parameters. // with many many parameters.
......
...@@ -266,8 +266,7 @@ ...@@ -266,8 +266,7 @@
'regress/regress-crbug-474297': [PASS, ['mode == debug', SLOW]], 'regress/regress-crbug-474297': [PASS, ['mode == debug', SLOW]],
'es6/tail-call-megatest*': [PASS, FAST_VARIANTS], 'es6/tail-call-megatest*': [PASS, FAST_VARIANTS],
# TODO(titzer): correct WASM adapter frame alignment on arm64 # TODO(titzer): ASM->WASM tests on these platforms
'wasm/*': [PASS, ['arch == arm64', SKIP]],
'wasm/asm-wasm': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]], 'wasm/asm-wasm': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]],
# TODO(branelson): Figure out why ignition + asm-wasm-stdlib fails. # TODO(branelson): Figure out why ignition + asm-wasm-stdlib fails.
'wasm/asm-wasm-stdlib': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el] or ignition == True', SKIP]], 'wasm/asm-wasm-stdlib': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el] or ignition == True', SKIP]],
...@@ -276,7 +275,7 @@ ...@@ -276,7 +275,7 @@
'wasm/asm-wasm-deopt': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]], 'wasm/asm-wasm-deopt': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]],
# TODO(branelson): Figure out why ignition + asm->wasm fails embenchen. # TODO(branelson): Figure out why ignition + asm->wasm fails embenchen.
'wasm/embenchen/*': [PASS, ['ignition == True', SKIP]], 'wasm/embenchen/*': [PASS, ['arch == arm64', SKIP], ['ignition == True', SKIP]],
# TODO(bradnelson) Fix and re-enable. # TODO(bradnelson) Fix and re-enable.
'wasm/embenchen/box2d': [SKIP], # hang 'wasm/embenchen/box2d': [SKIP], # hang
......
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