Commit 23943d0e authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Provide backoff implementations for the Fxx rounding instructions

If the architecture does not provide rounding instructions, then C
implementations of these rounding instructions are called. The C
implementations from math.h are used, function pointers are registered
as external references so that they can be call from the simulator.

R=titzer@chromium.org

BUG=575379

LOG=Y

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

Cr-Commit-Position: refs/heads/master@{#33677}
parent d77d6577
...@@ -122,7 +122,6 @@ void FastAccessorBuilder::CheckNotZeroOrJump(ValueId value_id, ...@@ -122,7 +122,6 @@ void FastAccessorBuilder::CheckNotZeroOrJump(ValueId value_id,
FromApi(this)->CheckNotZeroOrJump(value_id, label_id); FromApi(this)->CheckNotZeroOrJump(value_id, label_id);
} }
FastAccessorBuilder::ValueId FastAccessorBuilder::Call( FastAccessorBuilder::ValueId FastAccessorBuilder::Call(
v8::FunctionCallback callback, ValueId value_id) { v8::FunctionCallback callback, ValueId value_id) {
return FromApi(this)->Call(callback, value_id); return FromApi(this)->Call(callback, value_id);
......
...@@ -1132,11 +1132,66 @@ ExternalReference ExternalReference::compute_output_frames_function( ...@@ -1132,11 +1132,66 @@ ExternalReference ExternalReference::compute_output_frames_function(
Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames))); Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
} }
static void trunc64_wrapper(double* param) { *param = trunc(*param); } static void f32_trunc_wrapper(float* param) { *param = truncf(*param); }
ExternalReference ExternalReference::trunc64_wrapper_function( ExternalReference ExternalReference::f32_trunc_wrapper_function(
Isolate* isolate) { Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(trunc64_wrapper))); return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f32_trunc_wrapper)));
}
static void f32_floor_wrapper(float* param) { *param = floorf(*param); }
ExternalReference ExternalReference::f32_floor_wrapper_function(
Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f32_floor_wrapper)));
}
static void f32_ceil_wrapper(float* param) { *param = ceilf(*param); }
ExternalReference ExternalReference::f32_ceil_wrapper_function(
Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f32_ceil_wrapper)));
}
static void f32_nearest_int_wrapper(float* param) {
*param = nearbyintf(*param);
}
ExternalReference ExternalReference::f32_nearest_int_wrapper_function(
Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(f32_nearest_int_wrapper)));
}
static void f64_trunc_wrapper(double* param) { *param = trunc(*param); }
ExternalReference ExternalReference::f64_trunc_wrapper_function(
Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_trunc_wrapper)));
}
static void f64_floor_wrapper(double* param) { *param = floor(*param); }
ExternalReference ExternalReference::f64_floor_wrapper_function(
Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_floor_wrapper)));
}
static void f64_ceil_wrapper(double* param) { *param = ceil(*param); }
ExternalReference ExternalReference::f64_ceil_wrapper_function(
Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_ceil_wrapper)));
}
static void f64_nearest_int_wrapper(double* param) {
*param = nearbyint(*param);
}
ExternalReference ExternalReference::f64_nearest_int_wrapper_function(
Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(f64_nearest_int_wrapper)));
} }
ExternalReference ExternalReference::log_enter_external_function( ExternalReference ExternalReference::log_enter_external_function(
......
...@@ -913,7 +913,14 @@ class ExternalReference BASE_EMBEDDED { ...@@ -913,7 +913,14 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference new_deoptimizer_function(Isolate* isolate); static ExternalReference new_deoptimizer_function(Isolate* isolate);
static ExternalReference compute_output_frames_function(Isolate* isolate); static ExternalReference compute_output_frames_function(Isolate* isolate);
static ExternalReference trunc64_wrapper_function(Isolate* isolate); static ExternalReference f32_trunc_wrapper_function(Isolate* isolate);
static ExternalReference f32_floor_wrapper_function(Isolate* isolate);
static ExternalReference f32_ceil_wrapper_function(Isolate* isolate);
static ExternalReference f32_nearest_int_wrapper_function(Isolate* isolate);
static ExternalReference f64_trunc_wrapper_function(Isolate* isolate);
static ExternalReference f64_floor_wrapper_function(Isolate* isolate);
static ExternalReference f64_ceil_wrapper_function(Isolate* isolate);
static ExternalReference f64_nearest_int_wrapper_function(Isolate* isolate);
// Log support. // Log support.
static ExternalReference log_enter_external_function(Isolate* isolate); static ExternalReference log_enter_external_function(Isolate* isolate);
......
...@@ -167,7 +167,6 @@ void FastAccessorAssembler::CheckNotZeroOrJump(ValueId value_id, ...@@ -167,7 +167,6 @@ void FastAccessorAssembler::CheckNotZeroOrJump(ValueId value_id,
assembler_->Bind(&pass); assembler_->Bind(&pass);
} }
FastAccessorAssembler::ValueId FastAccessorAssembler::Call( FastAccessorAssembler::ValueId FastAccessorAssembler::Call(
FunctionCallback callback_function, ValueId arg) { FunctionCallback callback_function, ValueId arg) {
CHECK_EQ(kBuilding, state_); CHECK_EQ(kBuilding, state_);
...@@ -209,7 +208,6 @@ FastAccessorAssembler::ValueId FastAccessorAssembler::Call( ...@@ -209,7 +208,6 @@ FastAccessorAssembler::ValueId FastAccessorAssembler::Call(
return FromRaw(call); return FromRaw(call);
} }
MaybeHandle<Code> FastAccessorAssembler::Build() { MaybeHandle<Code> FastAccessorAssembler::Build() {
CHECK_EQ(kBuilding, state_); CHECK_EQ(kBuilding, state_);
......
...@@ -742,57 +742,35 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) { ...@@ -742,57 +742,35 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
} }
} }
case wasm::kExprF32Floor: { case wasm::kExprF32Floor: {
if (m->Float32RoundDown().IsSupported()) { if (!m->Float32RoundDown().IsSupported()) return BuildF32Floor(input);
op = m->Float32RoundDown().op(); op = m->Float32RoundDown().op();
break; break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
} }
case wasm::kExprF32Ceil: { case wasm::kExprF32Ceil: {
if (m->Float32RoundUp().IsSupported()) { if (!m->Float32RoundUp().IsSupported()) return BuildF32Ceil(input);
op = m->Float32RoundUp().op(); op = m->Float32RoundUp().op();
break; break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
} }
case wasm::kExprF32Trunc: { case wasm::kExprF32Trunc: {
if (m->Float32RoundTruncate().IsSupported()) { if (!m->Float32RoundTruncate().IsSupported()) return BuildF32Trunc(input);
op = m->Float32RoundTruncate().op(); op = m->Float32RoundTruncate().op();
} else {
return BuildF32Trunc(input);
}
break; break;
} }
case wasm::kExprF32NearestInt: { case wasm::kExprF32NearestInt: {
if (m->Float32RoundTiesEven().IsSupported()) { if (!m->Float32RoundTiesEven().IsSupported())
op = m->Float32RoundTiesEven().op(); return BuildF32NearestInt(input);
break; op = m->Float32RoundTiesEven().op();
} else { break;
op = UnsupportedOpcode(opcode);
break;
}
} }
case wasm::kExprF64Floor: { case wasm::kExprF64Floor: {
if (m->Float64RoundDown().IsSupported()) { if (!m->Float64RoundDown().IsSupported()) return BuildF64Floor(input);
op = m->Float64RoundDown().op(); op = m->Float64RoundDown().op();
break; break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
} }
case wasm::kExprF64Ceil: { case wasm::kExprF64Ceil: {
if (m->Float64RoundUp().IsSupported()) { if (!m->Float64RoundUp().IsSupported()) return BuildF64Ceil(input);
op = m->Float64RoundUp().op(); op = m->Float64RoundUp().op();
break; break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
} }
case wasm::kExprF64Trunc: { case wasm::kExprF64Trunc: {
if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input); if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input);
...@@ -800,13 +778,10 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) { ...@@ -800,13 +778,10 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
break; break;
} }
case wasm::kExprF64NearestInt: { case wasm::kExprF64NearestInt: {
if (m->Float64RoundTiesEven().IsSupported()) { if (!m->Float64RoundTiesEven().IsSupported())
op = m->Float64RoundTiesEven().op(); return BuildF64NearestInt(input);
break; op = m->Float64RoundTiesEven().op();
} else { break;
op = UnsupportedOpcode(opcode);
break;
}
} }
#if WASM_64 #if WASM_64
...@@ -1365,99 +1340,89 @@ Node* WasmGraphBuilder::BuildI64Popcnt(Node* input) { ...@@ -1365,99 +1340,89 @@ Node* WasmGraphBuilder::BuildI64Popcnt(Node* input) {
return result; return result;
} }
Node* WasmGraphBuilder::BuildF32Trunc(Node* input) { Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
// int32_t int_input = bitftoi(input); MachineType type = MachineType::Float32();
// int32_t exponent = int_input & 0x7f800000; ExternalReference ref =
// if (exponent >= ((23 + 127) << 23)) { ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate());
// if (input != input) { return BuildRoundingInstruction(input, ref, type);
// return bititof(int_input | (1 << 22)); }
// }
// return input; Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
// } MachineType type = MachineType::Float32();
// int32_t sign = int_input & 0x80000000; ExternalReference ref =
// if (exponent < (127 << 23)) { ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate());
// return bititof(sign); return BuildRoundingInstruction(input, ref, type);
// } }
// int32_t mantissa = int_input & 0x007fffff;
// int32_t shift = (127 + 23) - (exponent >> 23); Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
// int32_t new_mantissa = (mantissa >> shift) << shift; MachineType type = MachineType::Float32();
// int32_t result = new_mantissa | exponent | sign; ExternalReference ref =
// return bititof(result); ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate());
return BuildRoundingInstruction(input, ref, type);
Node* int_input = Unop(wasm::kExprI32ReinterpretF32, input); }
Node* exponent =
Binop(wasm::kExprI32And, int_input, jsgraph()->Int32Constant(0x7f800000)); Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
MachineType type = MachineType::Float32();
Node* sign = ExternalReference ref =
Binop(wasm::kExprI32And, int_input, jsgraph()->Int32Constant(0x80000000)); ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate());
return BuildRoundingInstruction(input, ref, type);
Node* result_out_of_range = int_input;
Node* result_nan =
Binop(wasm::kExprI32Ior, int_input, jsgraph()->Int32Constant(1 << 22));
Node* result_zero = sign;
Node* mantissa =
Binop(wasm::kExprI32And, int_input, jsgraph()->Int32Constant(0x007fffff));
Node* shift =
Binop(wasm::kExprI32Sub, jsgraph()->Int32Constant(23 + 127),
Binop(wasm::kExprI32ShrU, exponent, jsgraph()->Int32Constant(23)));
Node* new_mantissa = Binop(wasm::kExprI32Shl,
Binop(wasm::kExprI32ShrU, mantissa, shift), shift);
Node* result_truncate =
Binop(wasm::kExprI32Ior, Binop(wasm::kExprI32Ior, new_mantissa, exponent),
sign);
Diamond is_zero(
graph(), jsgraph()->common(),
Binop(wasm::kExprI32LtU, exponent, jsgraph()->Int32Constant(127 << 23)));
Node* result_within_range =
is_zero.Phi(wasm::kAstI32, result_zero, result_truncate);
Diamond input_nan(graph(), jsgraph()->common(),
Binop(wasm::kExprF32Ne, input, input));
Node* result_exponent_geq_23 =
input_nan.Phi(wasm::kAstI32, result_nan, result_out_of_range);
Diamond exponent_geq_23(graph(), jsgraph()->common(),
Binop(wasm::kExprI32GeU, exponent,
jsgraph()->Int32Constant((23 + 127) << 23)));
Node* result = exponent_geq_23.Phi(wasm::kAstI32, result_exponent_geq_23,
result_within_range);
return Unop(wasm::kExprF32ReinterpretI32, result);
} }
Node* WasmGraphBuilder::BuildF64Trunc(Node* input) { Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
MachineType type = MachineType::Float64();
ExternalReference ref =
ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate());
return BuildRoundingInstruction(input, ref, type);
}
Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
MachineType type = MachineType::Float64();
ExternalReference ref =
ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate());
return BuildRoundingInstruction(input, ref, type);
}
Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
MachineType type = MachineType::Float64();
ExternalReference ref =
ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate());
return BuildRoundingInstruction(input, ref, type);
}
Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
MachineType type = MachineType::Float64();
ExternalReference ref =
ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate());
return BuildRoundingInstruction(input, ref, type);
}
Node* WasmGraphBuilder::BuildRoundingInstruction(Node* input,
ExternalReference ref,
MachineType type) {
// We do truncation by calling a C function which calculates the truncation // We do truncation by calling a C function which calculates the truncation
// for us. The input is passed to the C function as a double* to avoid double // for us. The input is passed to the C function as a double* to avoid double
// parameters. For this we reserve a slot on the stack, store the parameter in // parameters. For this we reserve a slot on the stack, store the parameter in
// that slot, pass a pointer to the slot to the C function, and after calling // that slot, pass a pointer to the slot to the C function, and after calling
// the C function we collect the return value from the stack slot. // the C function we collect the return value from the stack slot.
Node* stack_slot_param = graph()->NewNode( Node* stack_slot_param =
jsgraph()->machine()->StackSlot(MachineRepresentation::kFloat64)); graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation()));
const Operator* store_op = jsgraph()->machine()->Store( const Operator* store_op = jsgraph()->machine()->Store(
StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier)); StoreRepresentation(type.representation(), kNoWriteBarrier));
*effect_ = *effect_ =
graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
input, *effect_, *control_); input, *effect_, *control_);
Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1); Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1);
sig_builder.AddParam(MachineType::Pointer()); sig_builder.AddParam(MachineType::Pointer());
Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant( Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
ExternalReference::trunc64_wrapper_function(jsgraph()->isolate())));
Node* args[] = {function, stack_slot_param}; Node* args[] = {function, stack_slot_param};
BuildCCall(sig_builder.Build(), args); BuildCCall(sig_builder.Build(), args);
const Operator* load_op = jsgraph()->machine()->Load(MachineType::Float64()); const Operator* load_op = jsgraph()->machine()->Load(type);
Node* load = Node* load =
graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0), graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0),
......
...@@ -177,8 +177,16 @@ class WasmGraphBuilder { ...@@ -177,8 +177,16 @@ class WasmGraphBuilder {
Node* BuildI32Popcnt(Node* input); Node* BuildI32Popcnt(Node* input);
Node* BuildI64Ctz(Node* input); Node* BuildI64Ctz(Node* input);
Node* BuildI64Popcnt(Node* input); Node* BuildI64Popcnt(Node* input);
Node* BuildRoundingInstruction(Node* input, ExternalReference ref,
MachineType type);
Node* BuildF32Trunc(Node* input); Node* BuildF32Trunc(Node* input);
Node* BuildF32Floor(Node* input);
Node* BuildF32Ceil(Node* input);
Node* BuildF32NearestInt(Node* input);
Node* BuildF64Trunc(Node* input); Node* BuildF64Trunc(Node* input);
Node* BuildF64Floor(Node* input);
Node* BuildF64Ceil(Node* input);
Node* BuildF64NearestInt(Node* input);
Node** Realloc(Node** buffer, size_t count) { Node** Realloc(Node** buffer, size_t count) {
Node** buf = Buffer(count); Node** buf = Buffer(count);
......
...@@ -119,8 +119,22 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) { ...@@ -119,8 +119,22 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"InvokeFunctionCallback"); "InvokeFunctionCallback");
Add(ExternalReference::invoke_accessor_getter_callback(isolate).address(), Add(ExternalReference::invoke_accessor_getter_callback(isolate).address(),
"InvokeAccessorGetterCallback"); "InvokeAccessorGetterCallback");
Add(ExternalReference::trunc64_wrapper_function(isolate).address(), Add(ExternalReference::f32_trunc_wrapper_function(isolate).address(),
"trunc64_wrapper"); "f32_trunc_wrapper");
Add(ExternalReference::f32_floor_wrapper_function(isolate).address(),
"f32_floor_wrapper");
Add(ExternalReference::f32_ceil_wrapper_function(isolate).address(),
"f32_ceil_wrapper");
Add(ExternalReference::f32_nearest_int_wrapper_function(isolate).address(),
"f32_nearest_int_wrapper");
Add(ExternalReference::f64_trunc_wrapper_function(isolate).address(),
"f64_trunc_wrapper");
Add(ExternalReference::f64_floor_wrapper_function(isolate).address(),
"f64_floor_wrapper");
Add(ExternalReference::f64_ceil_wrapper_function(isolate).address(),
"f64_ceil_wrapper");
Add(ExternalReference::f64_nearest_int_wrapper_function(isolate).address(),
"f64_nearest_int_wrapper");
Add(ExternalReference::log_enter_external_function(isolate).address(), Add(ExternalReference::log_enter_external_function(isolate).address(),
"Logger::EnterExternal"); "Logger::EnterExternal");
Add(ExternalReference::log_leave_external_function(isolate).address(), Add(ExternalReference::log_leave_external_function(isolate).address(),
......
...@@ -40,6 +40,8 @@ class RawMachineAssemblerTester : public HandleAndZoneScope, ...@@ -40,6 +40,8 @@ class RawMachineAssemblerTester : public HandleAndZoneScope,
MachineType::PointerRepresentation(), MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags()) {} InstructionSelector::SupportedMachineOperatorFlags()) {}
virtual ~RawMachineAssemblerTester() {}
void CheckNumber(double expected, Object* number) { void CheckNumber(double expected, Object* number) {
CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number)); CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
} }
...@@ -86,6 +88,7 @@ class BufferedRawMachineAssemblerTester ...@@ -86,6 +88,7 @@ class BufferedRawMachineAssemblerTester
: BufferedRawMachineAssemblerTester(ComputeParameterCount(p0, p1, p2, p3), : BufferedRawMachineAssemblerTester(ComputeParameterCount(p0, p1, p2, p3),
p0, p1, p2, p3) {} p0, p1, p2, p3) {}
virtual byte* Generate() { return RawMachineAssemblerTester::Generate(); }
// The BufferedRawMachineAssemblerTester does not pass parameters directly // The BufferedRawMachineAssemblerTester does not pass parameters directly
// to the constructed IR graph. Instead it passes a pointer to the parameter // to the constructed IR graph. Instead it passes a pointer to the parameter
...@@ -245,6 +248,8 @@ class BufferedRawMachineAssemblerTester<void> ...@@ -245,6 +248,8 @@ class BufferedRawMachineAssemblerTester<void>
: Load(p3, RawMachineAssembler::Parameter(3)); : Load(p3, RawMachineAssembler::Parameter(3));
} }
virtual byte* Generate() { return RawMachineAssemblerTester::Generate(); }
// The BufferedRawMachineAssemblerTester does not pass parameters directly // The BufferedRawMachineAssemblerTester does not pass parameters directly
// to the constructed IR graph. Instead it passes a pointer to the parameter // to the constructed IR graph. Instead it passes a pointer to the parameter
// to the IR graph, and adds Load nodes to the IR graph to load the // to the IR graph, and adds Load nodes to the IR graph to load the
...@@ -523,7 +528,8 @@ class BinopGen { ...@@ -523,7 +528,8 @@ class BinopGen {
// and run the generated code to ensure it produces the correct results. // and run the generated code to ensure it produces the correct results.
class Int32BinopInputShapeTester { class Int32BinopInputShapeTester {
public: public:
explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g) : gen(g) {} explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g)
: gen(g), input_a(0), input_b(0) {}
void TestAllInputShapes(); void TestAllInputShapes();
......
...@@ -5588,17 +5588,77 @@ TEST(RunCallCFunction8) { ...@@ -5588,17 +5588,77 @@ TEST(RunCallCFunction8) {
} }
#endif // USE_SIMULATOR #endif // USE_SIMULATOR
template <typename T>
void TestExternalReferenceFunction(
BufferedRawMachineAssemblerTester<int32_t>* m, ExternalReference ref,
T (*comparison)(T)) {
T parameter;
Node* function = m->ExternalConstant(ref);
m->CallCFunction1(MachineType::Pointer(), MachineType::Pointer(), function,
m->PointerConstant(&parameter));
m->Return(m->Int32Constant(4356));
FOR_FLOAT64_INPUTS(i) {
parameter = *i;
m->Call();
CheckDoubleEq(comparison(*i), parameter);
}
}
TEST(RunCallExternalReferenceF32Trunc) {
BufferedRawMachineAssemblerTester<int32_t> m;
ExternalReference ref =
ExternalReference::f32_trunc_wrapper_function(m.isolate());
TestExternalReferenceFunction<float>(&m, ref, truncf);
}
TEST(RunCallExternalReferenceF32Floor) {
BufferedRawMachineAssemblerTester<int32_t> m;
ExternalReference ref =
ExternalReference::f32_floor_wrapper_function(m.isolate());
TestExternalReferenceFunction<float>(&m, ref, floorf);
}
TEST(RunCallExternalReferenceF32Ceil) {
BufferedRawMachineAssemblerTester<int32_t> m;
ExternalReference ref =
ExternalReference::f32_ceil_wrapper_function(m.isolate());
TestExternalReferenceFunction<float>(&m, ref, ceilf);
}
TEST(RunCallExternalReferenceF32RoundTiesEven) {
BufferedRawMachineAssemblerTester<int32_t> m;
ExternalReference ref =
ExternalReference::f32_nearest_int_wrapper_function(m.isolate());
TestExternalReferenceFunction<float>(&m, ref, nearbyintf);
}
TEST(RunCallExternalReferenceF64Trunc) { TEST(RunCallExternalReferenceF64Trunc) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64()); BufferedRawMachineAssemblerTester<int32_t> m;
Node* stack_slot = m.StackSlot(MachineRepresentation::kFloat64); ExternalReference ref =
m.Store(MachineRepresentation::kFloat64, stack_slot, m.Parameter(0), ExternalReference::f64_trunc_wrapper_function(m.isolate());
WriteBarrierKind::kNoWriteBarrier); TestExternalReferenceFunction<double>(&m, ref, trunc);
Node* function = m.ExternalConstant( }
ExternalReference::trunc64_wrapper_function(m.isolate()));
m.CallCFunction1(MachineType::Pointer(), MachineType::Pointer(), function, TEST(RunCallExternalReferenceF64Floor) {
stack_slot); BufferedRawMachineAssemblerTester<int32_t> m;
m.Return(m.Load(MachineType::Float64(), stack_slot)); ExternalReference ref =
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), m.Call(*i)); } ExternalReference::f64_floor_wrapper_function(m.isolate());
TestExternalReferenceFunction<double>(&m, ref, floor);
}
TEST(RunCallExternalReferenceF64Ceil) {
BufferedRawMachineAssemblerTester<int32_t> m;
ExternalReference ref =
ExternalReference::f64_ceil_wrapper_function(m.isolate());
TestExternalReferenceFunction<double>(&m, ref, ceil);
}
TEST(RunCallExternalReferenceF64RoundTiesEven) {
BufferedRawMachineAssemblerTester<int32_t> m;
ExternalReference ref =
ExternalReference::f64_nearest_int_wrapper_function(m.isolate());
TestExternalReferenceFunction<double>(&m, ref, nearbyint);
} }
#if V8_TARGET_ARCH_64_BIT #if V8_TARGET_ARCH_64_BIT
......
...@@ -287,7 +287,6 @@ TEST(FastAccessorLoad) { ...@@ -287,7 +287,6 @@ TEST(FastAccessorLoad) {
ExpectString("loadval()", "Hello"); ExpectString("loadval()", "Hello");
} }
void ApiCallbackInt(const v8::FunctionCallbackInfo<v8::Value>& info) { void ApiCallbackInt(const v8::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(12345); info.GetReturnValue().Set(12345);
} }
...@@ -298,14 +297,12 @@ void ApiCallbackString(const v8::FunctionCallbackInfo<v8::Value>& info) { ...@@ -298,14 +297,12 @@ void ApiCallbackString(const v8::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(v8_str(kApiCallbackStringValue)); info.GetReturnValue().Set(v8_str(kApiCallbackStringValue));
} }
void ApiCallbackParam(const v8::FunctionCallbackInfo<v8::Value>& info) { void ApiCallbackParam(const v8::FunctionCallbackInfo<v8::Value>& info) {
CHECK_EQ(1, info.Length()); CHECK_EQ(1, info.Length());
CHECK(info[0]->IsNumber()); CHECK(info[0]->IsNumber());
info.GetReturnValue().Set(info[0]); info.GetReturnValue().Set(info[0]);
} }
// "Fast" accessor, callback to embedder // "Fast" accessor, callback to embedder
TEST(FastAccessorCallback) { TEST(FastAccessorCallback) {
LocalContext env; LocalContext env;
......
...@@ -2955,41 +2955,34 @@ TEST(Run_Wasm_CallIndirect_NoTable) { ...@@ -2955,41 +2955,34 @@ TEST(Run_Wasm_CallIndirect_NoTable) {
CHECK_TRAP(r.Call(2)); CHECK_TRAP(r.Call(2));
} }
TEST(Run_Wasm_F32Trunc) {
WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) { CheckFloatEq(trunc(*i), r.Call(*i)); }
}
// TODO(titzer): Fix for nosee4 and re-enable.
#if 0
TEST(Run_Wasm_F32Floor) { TEST(Run_Wasm_F32Floor) {
WasmRunner<float> r(MachineType::Float32()); WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0))); BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) { CheckFloatEq(floor(*i), r.Call(*i)); } FOR_FLOAT32_INPUTS(i) { CheckFloatEq(floorf(*i), r.Call(*i)); }
} }
TEST(Run_Wasm_F32Ceil) { TEST(Run_Wasm_F32Ceil) {
WasmRunner<float> r(MachineType::Float32()); WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0))); BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) { CheckFloatEq(ceil(*i), r.Call(*i)); } FOR_FLOAT32_INPUTS(i) { CheckFloatEq(ceilf(*i), r.Call(*i)); }
} }
TEST(Run_Wasm_F32Trunc) {
WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) { CheckFloatEq(truncf(*i), r.Call(*i)); }
}
TEST(Run_Wasm_F32NearestInt) { TEST(Run_Wasm_F32NearestInt) {
WasmRunner<float> r(MachineType::Float32()); WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0))); BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyint(*i), r.Call(*i)); } FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyintf(*i), r.Call(*i)); }
} }
TEST(Run_Wasm_F64Floor) { TEST(Run_Wasm_F64Floor) {
WasmRunner<double> r(MachineType::Float64()); WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0))); BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0)));
...@@ -2997,7 +2990,6 @@ TEST(Run_Wasm_F64Floor) { ...@@ -2997,7 +2990,6 @@ TEST(Run_Wasm_F64Floor) {
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(floor(*i), r.Call(*i)); } FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(floor(*i), r.Call(*i)); }
} }
TEST(Run_Wasm_F64Ceil) { TEST(Run_Wasm_F64Ceil) {
WasmRunner<double> r(MachineType::Float64()); WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0))); BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0)));
...@@ -3005,21 +2997,18 @@ TEST(Run_Wasm_F64Ceil) { ...@@ -3005,21 +2997,18 @@ TEST(Run_Wasm_F64Ceil) {
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(ceil(*i), r.Call(*i)); } FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(ceil(*i), r.Call(*i)); }
} }
TEST(Run_Wasm_F64Trunc) {
TEST(Run_Wasm_F64NearestInt) {
WasmRunner<double> r(MachineType::Float64()); WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0))); BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(nearbyint(*i), r.Call(*i)); } FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); }
} }
#endif TEST(Run_Wasm_F64NearestInt) {
TEST(Run_Wasm_F64Trunc) {
WasmRunner<double> r(MachineType::Float64()); WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0))); BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); } FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(nearbyint(*i), r.Call(*i)); }
} }
TEST(Run_Wasm_F32Min) { TEST(Run_Wasm_F32Min) {
......
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