| Index: src/compiler/wasm-compiler.cc
|
| diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
|
| index 0a13f98d8593f32e8990752d7d1a64451314ae6d..6a50324e1e14b8b82927441359d429217b9c6707 100644
|
| --- a/src/compiler/wasm-compiler.cc
|
| +++ b/src/compiler/wasm-compiler.cc
|
| @@ -2493,6 +2493,107 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function,
|
| MergeControlToEnd(jsgraph(), ret);
|
| }
|
|
|
| +void WasmGraphBuilder::BuildWasmToInterpreter(uint32_t function_index,
|
| + wasm::FunctionSig* sig,
|
| + Handle<JSObject> wasm_obj) {
|
| + 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;
|
| +
|
| + auto build_runtime_call = [&](Runtime::FunctionId f) -> Node* {
|
| + const Runtime::Function* fun = Runtime::FunctionForId(f);
|
| + CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
|
| + jsgraph()->zone(), f, fun->nargs, Operator::kNoProperties,
|
| + CallDescriptor::kNoFlags);
|
| + DCHECK_EQ(1, fun->result_size);
|
| + DCHECK_EQ(2, fun->nargs);
|
| + Node* inputs[] = {
|
| + jsgraph()->CEntryStubConstant(fun->result_size), // C entry
|
| + jsgraph()->SmiConstant(function_index), // function index
|
| + jsgraph()->HeapConstant(wasm_obj), // wasm object
|
| + jsgraph()->ExternalConstant(
|
| + ExternalReference(f, jsgraph()->isolate())), // ref
|
| + jsgraph()->Int32Constant(fun->nargs), // arity
|
| + HeapConstant(jsgraph()->isolate()->native_context()), // context
|
| + *effect_,
|
| + *control_};
|
| + Node* call = *control_ = *effect_ =
|
| + graph()->NewNode(jsgraph()->common()->Call(desc),
|
| + static_cast<int>(arraysize(inputs)), inputs);
|
| + *control_ = call;
|
| + *effect_ = call;
|
| + return call;
|
| + };
|
| +
|
| + // Get a buffer to store all parameters.
|
| + Node* arg_buffer = build_runtime_call(Runtime::kGetWasmInterpreterBuffer);
|
| +
|
| + // Now store all our parameters to the buffer.
|
| + int param_index = 0;
|
| + int offset = 0;
|
| + for (int i = 0; i < wasm_count; i++) {
|
| + Node* param =
|
| + graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start);
|
| + bool is_lower_half_i64 =
|
| + jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64;
|
| + MachineRepresentation param_rep =
|
| + is_lower_half_i64 ? wasm::kAstI32 : 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);
|
| + if (is_lower_half_i64) {
|
| + // Also store the upper half.
|
| + param = graph()->NewNode(jsgraph()->common()->Parameter(param_index++),
|
| + start);
|
| + StoreRepresentation store_rep(wasm::kAstI32,
|
| + WriteBarrierKind::kNoWriteBarrier);
|
| + *effect_ =
|
| + graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
|
| + Int32Constant(offset), param, *effect_, *control_);
|
| + offset += 1 << ElementSizeLog2Of(wasm::kAstI32);
|
| + }
|
| + }
|
| + DCHECK_EQ(param_count, param_index);
|
| +
|
| + build_runtime_call(Runtime::kWasmRunInterpreter);
|
| +
|
| + // Convert the return value back.
|
| + Node* ret;
|
| + if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
|
| + sig->GetReturn() == wasm::kAstI64) {
|
| + LoadRepresentation load_rep(wasm::kAstI32, MachineSemantic::kNone);
|
| + 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(4), *effect_, *control_);
|
| + ret = graph()->NewNode(jsgraph()->common()->Return(), upper, lower,
|
| + *effect_, *control_);
|
| + } else {
|
| + Node* val;
|
| + if (sig->return_count() == 0) {
|
| + val = Int32Constant(0);
|
| + } else {
|
| + LoadRepresentation load_rep(sig->GetReturn(), MachineSemantic::kNone);
|
| + val = graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
|
| + Int32Constant(0), *effect_, *control_);
|
| + }
|
| + ret = graph()->NewNode(jsgraph()->common()->Return(), val, *effect_,
|
| + *control_);
|
| + }
|
| +
|
| + MergeControlToEnd(jsgraph(), ret);
|
| +}
|
| +
|
| Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
|
| DCHECK(module_ && module_->instance);
|
| if (offset == 0) {
|
| @@ -3099,6 +3200,67 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate,
|
| return code;
|
| }
|
|
|
| +Handle<Code> CompileWasmToInterpreter(Isolate* isolate, uint32_t func_index,
|
| + wasm::FunctionSig* sig,
|
| + Handle<JSObject> wasm_obj) {
|
| + //----------------------------------------------------------------------------
|
| + // Create the Graph
|
| + //----------------------------------------------------------------------------
|
| + Zone zone(isolate->allocator());
|
| + 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(&zone, &jsgraph, sig);
|
| + builder.set_control_ptr(&control);
|
| + builder.set_effect_ptr(&effect);
|
| + builder.BuildWasmToInterpreter(func_index, sig, wasm_obj);
|
| +
|
| + 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_TO_INTERPRETER);
|
| + char buf[32];
|
| + int buf_len =
|
| + SNPrintF(ArrayVector(buf), "wasm-to-interpreter#%d", func_index);
|
| + DCHECK(buf_len > 0 && buf_len < sizeof(buf));
|
| + Vector<const char> debug_name(buf, buf_len);
|
| +
|
| + 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(buf, os);
|
| + }
|
| +#endif
|
| +
|
| + RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info, buf,
|
| + func_index, debug_name);
|
| + }
|
| +
|
| + Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(1);
|
| + deopt_data->set(0, *wasm_obj);
|
| + code->set_deoptimization_data(*deopt_data);
|
| +
|
| + return code;
|
| +}
|
| +
|
| SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
|
| double* decode_ms) {
|
| base::ElapsedTimer decode_timer;
|
|
|