Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Unified Diff: src/compiler/wasm-compiler.cc

Issue 2619803004: [wasm] Add support for compiling WASM_INTERPRETER_ENTRY stubs (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;

Powered by Google App Engine
This is Rietveld 408576698