[wasm] Backoff implementation for F64Trunc using std::trunc.

R=titzer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#33670}
This commit is contained in:
ahaas 2016-02-02 02:57:58 -08:00 committed by Commit bot
parent 7feaf896bb
commit 3f4163cd24
8 changed files with 90 additions and 15 deletions

View File

@ -34,6 +34,7 @@
#include "src/assembler.h"
#include <math.h>
#include <cmath>
#include "src/api.h"
#include "src/base/cpu.h"
@ -1131,6 +1132,12 @@ ExternalReference ExternalReference::compute_output_frames_function(
Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
}
static void trunc64_wrapper(double* param) { *param = trunc(*param); }
ExternalReference ExternalReference::trunc64_wrapper_function(
Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(trunc64_wrapper)));
}
ExternalReference ExternalReference::log_enter_external_function(
Isolate* isolate) {

View File

@ -913,6 +913,8 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference new_deoptimizer_function(Isolate* isolate);
static ExternalReference compute_output_frames_function(Isolate* isolate);
static ExternalReference trunc64_wrapper_function(Isolate* isolate);
// Log support.
static ExternalReference log_enter_external_function(Isolate* isolate);
static ExternalReference log_leave_external_function(Isolate* isolate);

View File

@ -795,13 +795,9 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
}
}
case wasm::kExprF64Trunc: {
if (m->Float64RoundTruncate().IsSupported()) {
op = m->Float64RoundTruncate().op();
break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input);
op = m->Float64RoundTruncate().op();
break;
}
case wasm::kExprF64NearestInt: {
if (m->Float64RoundTiesEven().IsSupported()) {
@ -1436,6 +1432,60 @@ Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
return Unop(wasm::kExprF32ReinterpretI32, result);
}
Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
// 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
// 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
// the C function we collect the return value from the stack slot.
Node* stack_slot_param = graph()->NewNode(
jsgraph()->machine()->StackSlot(MachineRepresentation::kFloat64));
const Operator* store_op = jsgraph()->machine()->Store(
StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier));
*effect_ =
graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
input, *effect_, *control_);
Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1);
sig_builder.AddParam(MachineType::Pointer());
Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(
ExternalReference::trunc64_wrapper_function(jsgraph()->isolate())));
Node* args[] = {function, stack_slot_param};
BuildCCall(sig_builder.Build(), args);
const Operator* load_op = jsgraph()->machine()->Load(MachineType::Float64());
Node* load =
graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0),
*effect_, *control_);
*effect_ = load;
return load;
}
Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) {
const size_t params = sig->parameter_count();
const size_t extra = 2; // effect and control inputs.
const size_t count = 1 + params + extra;
// Reallocate the buffer to make space for extra inputs.
args = Realloc(args, count);
// Add effect and control inputs.
args[params + 1] = *effect_;
args[params + 2] = *control_;
CallDescriptor* desc =
Linkage::GetSimplifiedCDescriptor(jsgraph()->zone(), sig);
const Operator* op = jsgraph()->common()->Call(desc);
Node* call = graph()->NewNode(op, static_cast<int>(count), args);
*effect_ = call;
return call;
}
Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) {
const size_t params = sig->parameter_count();

View File

@ -159,6 +159,7 @@ class WasmGraphBuilder {
Node* MemBuffer(uint32_t offset);
void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset);
Node* BuildCCall(MachineSignature* sig, Node** args);
Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args);
Node* BuildF32Neg(Node* input);
Node* BuildF64Neg(Node* input);
@ -177,6 +178,7 @@ class WasmGraphBuilder {
Node* BuildI64Ctz(Node* input);
Node* BuildI64Popcnt(Node* input);
Node* BuildF32Trunc(Node* input);
Node* BuildF64Trunc(Node* input);
Node** Realloc(Node** buffer, size_t count) {
Node** buf = Buffer(count);

View File

@ -264,6 +264,7 @@ CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone,
// The target for WASM calls is always a code object.
MachineType target_type = MachineType::AnyTagged();
LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
return new (zone) CallDescriptor( // --
CallDescriptor::kCallCodeObject, // kind
target_type, // target MachineType

View File

@ -119,6 +119,8 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"InvokeFunctionCallback");
Add(ExternalReference::invoke_accessor_getter_callback(isolate).address(),
"InvokeAccessorGetterCallback");
Add(ExternalReference::trunc64_wrapper_function(isolate).address(),
"trunc64_wrapper");
Add(ExternalReference::log_enter_external_function(isolate).address(),
"Logger::EnterExternal");
Add(ExternalReference::log_leave_external_function(isolate).address(),

View File

@ -5588,6 +5588,19 @@ TEST(RunCallCFunction8) {
}
#endif // USE_SIMULATOR
TEST(RunCallExternalReferenceF64Trunc) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
Node* stack_slot = m.StackSlot(MachineRepresentation::kFloat64);
m.Store(MachineRepresentation::kFloat64, stack_slot, m.Parameter(0),
WriteBarrierKind::kNoWriteBarrier);
Node* function = m.ExternalConstant(
ExternalReference::trunc64_wrapper_function(m.isolate()));
m.CallCFunction1(MachineType::Pointer(), MachineType::Pointer(), function,
stack_slot);
m.Return(m.Load(MachineType::Float64(), stack_slot));
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), m.Call(*i)); }
}
#if V8_TARGET_ARCH_64_BIT
// TODO(titzer): run int64 tests on all platforms when supported.
TEST(RunCheckedLoadInt64) {

View File

@ -3006,14 +3006,6 @@ TEST(Run_Wasm_F64Ceil) {
}
TEST(Run_Wasm_F64Trunc) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); }
}
TEST(Run_Wasm_F64NearestInt) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0)));
@ -3023,6 +3015,12 @@ TEST(Run_Wasm_F64NearestInt) {
#endif
TEST(Run_Wasm_F64Trunc) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); }
}
TEST(Run_Wasm_F32Min) {
WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());