| Index: src/compiler/wasm-compiler.cc
|
| diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
|
| index ec99c6d95bd9df63d731957471fc0d4e2da500d1..1573c026f69b3b3a8cc3862f2a6f19109f23787c 100644
|
| --- a/src/compiler/wasm-compiler.cc
|
| +++ b/src/compiler/wasm-compiler.cc
|
| @@ -36,6 +36,7 @@
|
| #include "src/wasm/function-body-decoder.h"
|
| #include "src/wasm/wasm-limits.h"
|
| #include "src/wasm/wasm-module.h"
|
| +#include "src/wasm/wasm-objects.h"
|
| #include "src/wasm/wasm-opcodes.h"
|
| #include "src/wasm/wasm-text.h"
|
|
|
| @@ -70,9 +71,6 @@ Node* BuildCallToRuntime(Runtime::FunctionId f, JSGraph* jsgraph,
|
| Handle<Context> context, Node** parameters,
|
| int parameter_count, Node** effect_ptr,
|
| Node* control) {
|
| - // At the moment we only allow 2 parameters. If more parameters are needed,
|
| - // then the size of {inputs} below has to be increased accordingly.
|
| - DCHECK(parameter_count <= 2);
|
| const Runtime::Function* fun = Runtime::FunctionForId(f);
|
| CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
|
| jsgraph->zone(), f, fun->nargs, Operator::kNoProperties,
|
| @@ -80,7 +78,11 @@ Node* BuildCallToRuntime(Runtime::FunctionId f, JSGraph* jsgraph,
|
| // CEntryStubConstant nodes have to be created and cached in the main
|
| // thread. At the moment this is only done for CEntryStubConstant(1).
|
| DCHECK_EQ(1, fun->result_size);
|
| - Node* inputs[8];
|
| + // At the moment we only allow 2 parameters. If more parameters are needed,
|
| + // increase this constant accordingly.
|
| + static const int kMaxParams = 3;
|
| + DCHECK_GE(kMaxParams, parameter_count);
|
| + Node* inputs[kMaxParams + 6];
|
| int count = 0;
|
| inputs[count++] = jsgraph->CEntryStubConstant(fun->result_size);
|
| for (int i = 0; i < parameter_count; i++) {
|
| @@ -2927,6 +2929,101 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target,
|
| Return(val);
|
| }
|
|
|
| +void WasmGraphBuilder::BuildWasmInterpreterEntry(
|
| + uint32_t function_index, wasm::FunctionSig* sig,
|
| + Handle<WasmInstanceObject> instance) {
|
| + int wasm_count = static_cast<int>(sig->parameter_count());
|
| + int param_count = jsgraph()->machine()->Is64()
|
| + ? wasm_count
|
| + : Int64Lowering::GetParameterCountAfterLowering(sig);
|
| +
|
| + // Build the start and the parameter nodes.
|
| + Node* start = Start(param_count + 3);
|
| + *effect_ = start;
|
| + *control_ = start;
|
| +
|
| + // Compute size for the argument buffer.
|
| + int args_size_bytes = 0;
|
| + for (int i = 0; i < wasm_count; i++) {
|
| + args_size_bytes += 1 << ElementSizeLog2Of(sig->GetParam(i));
|
| + }
|
| +
|
| + // The return value is also passed via this buffer:
|
| + DCHECK_GE(1, sig->return_count());
|
| + int return_size_bytes =
|
| + sig->return_count() == 0 ? 0 : 1 << ElementSizeLog2Of(sig->GetReturn(0));
|
| +
|
| + // Get a stack slot for the arguments.
|
| + Node* arg_buffer = graph()->NewNode(jsgraph()->machine()->StackSlot(
|
| + std::max(args_size_bytes, return_size_bytes)));
|
| +
|
| + // Now store all our arguments to the buffer.
|
| + int param_index = 0;
|
| + int offset = 0;
|
| + for (int i = 0; i < wasm_count; i++) {
|
| + Node* param = Param(param_index++);
|
| + bool is_i64_as_two_params =
|
| + jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kWasmI64;
|
| + MachineRepresentation param_rep =
|
| + is_i64_as_two_params ? wasm::kWasmI32 : sig->GetParam(i);
|
| + StoreRepresentation store_rep(param_rep, WriteBarrierKind::kNoWriteBarrier);
|
| + *effect_ =
|
| + graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
|
| + Int32Constant(offset), param, *effect_, *control_);
|
| + offset += 1 << ElementSizeLog2Of(param_rep);
|
| + // TODO(clemensh): Respect endianess here. Might need to swap upper and
|
| + // lower word.
|
| + if (is_i64_as_two_params) {
|
| + // Also store the upper half.
|
| + param = Param(param_index++);
|
| + StoreRepresentation store_rep(wasm::kWasmI32,
|
| + WriteBarrierKind::kNoWriteBarrier);
|
| + *effect_ =
|
| + graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
|
| + Int32Constant(offset), param, *effect_, *control_);
|
| + offset += 1 << ElementSizeLog2Of(wasm::kWasmI32);
|
| + }
|
| + }
|
| + DCHECK_EQ(param_count, param_index);
|
| + DCHECK_EQ(args_size_bytes, offset);
|
| +
|
| + // We are passing the raw arg_buffer here. To the GC and other parts, it looks
|
| + // like a Smi (lowest bit not set). In the runtime function however, don't
|
| + // call Smi::value on it, but just cast it to a byte pointer.
|
| + Node* parameters[] = {
|
| + jsgraph()->HeapConstant(instance), // wasm instance
|
| + jsgraph()->SmiConstant(function_index), // function index
|
| + arg_buffer, // argument buffer
|
| + };
|
| + BuildCallToRuntime(Runtime::kWasmRunInterpreter, jsgraph(),
|
| + jsgraph()->isolate()->native_context(), parameters,
|
| + arraysize(parameters), effect_, *control_);
|
| +
|
| + // Read back the return value.
|
| + if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
|
| + sig->GetReturn() == wasm::kWasmI64) {
|
| + MachineType load_rep = wasm::WasmOpcodes::MachineTypeFor(wasm::kWasmI32);
|
| + Node* lower =
|
| + graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
|
| + Int32Constant(0), *effect_, *control_);
|
| + Node* upper =
|
| + graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
|
| + Int32Constant(sizeof(int32_t)), *effect_, *control_);
|
| + Return(upper, lower);
|
| + } else {
|
| + Node* val;
|
| + if (sig->return_count() == 0) {
|
| + val = Int32Constant(0);
|
| + } else {
|
| + MachineType load_rep =
|
| + wasm::WasmOpcodes::MachineTypeFor(sig->GetReturn());
|
| + val = graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
|
| + Int32Constant(0), *effect_, *control_);
|
| + }
|
| + Return(val);
|
| + }
|
| +}
|
| +
|
| Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
|
| DCHECK(module_ && module_->instance);
|
| if (offset == 0) {
|
| @@ -3508,6 +3605,72 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
|
| return code;
|
| }
|
|
|
| +Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
|
| + wasm::FunctionSig* sig,
|
| + Handle<WasmInstanceObject> instance) {
|
| + //----------------------------------------------------------------------------
|
| + // Create the Graph
|
| + //----------------------------------------------------------------------------
|
| + Zone zone(isolate->allocator(), ZONE_NAME);
|
| + Graph graph(&zone);
|
| + CommonOperatorBuilder common(&zone);
|
| + MachineOperatorBuilder machine(&zone);
|
| + JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
|
| +
|
| + Node* control = nullptr;
|
| + Node* effect = nullptr;
|
| +
|
| + WasmGraphBuilder builder(nullptr, &zone, &jsgraph, sig);
|
| + builder.set_control_ptr(&control);
|
| + builder.set_effect_ptr(&effect);
|
| + builder.BuildWasmInterpreterEntry(func_index, sig, instance);
|
| +
|
| + Handle<Code> code = Handle<Code>::null();
|
| + {
|
| + if (FLAG_trace_turbo_graph) { // Simple textual RPO.
|
| + OFStream os(stdout);
|
| + os << "-- Wasm to interpreter graph -- " << std::endl;
|
| + os << AsRPO(graph);
|
| + }
|
| +
|
| + // Schedule and compile to machine code.
|
| + CallDescriptor* incoming =
|
| + wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig);
|
| + if (machine.Is32()) {
|
| + incoming = wasm::ModuleEnv::GetI32WasmCallDescriptor(&zone, incoming);
|
| + }
|
| + Code::Flags flags = Code::ComputeFlags(Code::WASM_INTERPRETER_ENTRY);
|
| + EmbeddedVector<char, 32> debug_name;
|
| + int name_len = SNPrintF(debug_name, "wasm-to-interpreter#%d", func_index);
|
| + DCHECK(name_len > 0 && name_len < debug_name.length());
|
| + debug_name.Truncate(name_len);
|
| + DCHECK_EQ('\0', debug_name.start()[debug_name.length()]);
|
| +
|
| + CompilationInfo info(debug_name, isolate, &zone, flags);
|
| + code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
|
| +#ifdef ENABLE_DISASSEMBLER
|
| + if (FLAG_print_opt_code && !code.is_null()) {
|
| + OFStream os(stdout);
|
| + code->Disassemble(debug_name.start(), os);
|
| + }
|
| +#endif
|
| +
|
| + if (isolate->logger()->is_logging_code_events() ||
|
| + isolate->is_profiling()) {
|
| + RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code,
|
| + "wasm-to-interpreter", func_index,
|
| + wasm::WasmName("module"), debug_name);
|
| + }
|
| + }
|
| +
|
| + Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(1, TENURED);
|
| + Handle<WeakCell> weak_instance = isolate->factory()->NewWeakCell(instance);
|
| + deopt_data->set(0, *weak_instance);
|
| + code->set_deoptimization_data(*deopt_data);
|
| +
|
| + return code;
|
| +}
|
| +
|
| SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
|
| double* decode_ms) {
|
| base::ElapsedTimer decode_timer;
|
|
|