Chromium Code Reviews| Index: src/compiler/wasm-compiler.cc |
| diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc |
| index ed739e1adfb470cd7640644e728e326d98f925f3..ebe9b23b37d6f9b77673db5e78613355172eba8b 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" |
| @@ -2911,6 +2912,86 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target, |
| Return(val); |
| } |
| +void WasmGraphBuilder::BuildWasmToInterpreter( |
| + 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; |
| + |
| + auto build_runtime_call = [&](Runtime::FunctionId f) -> Node* { |
| + Node* parameters[] = { |
| + jsgraph()->SmiConstant(function_index), // function index |
| + jsgraph()->HeapConstant(instance), // wasm instance |
| + }; |
| + return BuildCallToRuntime( |
| + f, jsgraph(), jsgraph()->isolate()->native_context(), parameters, |
| + arraysize(parameters), effect_, *control_); |
| + }; |
| + |
| + // Get a buffer to store all parameters. |
| + Node* arg_buffer = build_runtime_call(Runtime::kGetWasmInterpreterBuffer); |
|
titzer
2017/01/10 19:00:51
I think we can put this buffer into the stack fram
titzer
2017/01/10 19:02:47
Actually, now that I think about it, we might be a
Clemens Hammacher
2017/01/11 15:05:29
Done: http://crrev.com/2624183002
Using a special
|
| + |
| + // 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 = 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); |
| + if (is_i64_as_two_params) { |
|
titzer
2017/01/10 19:00:51
I think this might be backward for big-endian plat
Clemens Hammacher
2017/01/11 15:05:29
According to AddParameterNodes (line 2811) and Bui
|
| + // 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); |
|
titzer
2017/01/10 19:00:51
sizeof(int32_t) is also fine.
Clemens Hammacher
2017/01/11 15:05:29
Yes, but this way it is the same expression as 7 l
|
| + } |
| + } |
| + DCHECK_EQ(param_count, param_index); |
| + |
| + build_runtime_call(Runtime::kWasmRunInterpreter); |
| + |
| + // 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(4), *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) { |
| @@ -3486,6 +3567,72 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target, |
| return code; |
| } |
| +Handle<Code> CompileWasmToInterpreter(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.BuildWasmToInterpreter(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_TO_INTERPRETER); |
| + 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; |