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

Side by Side Diff: src/compiler/wasm-compiler.cc

Issue 2619803004: [wasm] Add support for compiling WASM_INTERPRETER_ENTRY stubs (Closed)
Patch Set: Address comments 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/wasm-compiler.h" 5 #include "src/compiler/wasm-compiler.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/isolate-inl.h" 9 #include "src/isolate-inl.h"
10 10
(...skipping 18 matching lines...) Expand all
29 #include "src/compiler/zone-stats.h" 29 #include "src/compiler/zone-stats.h"
30 30
31 #include "src/code-factory.h" 31 #include "src/code-factory.h"
32 #include "src/code-stubs.h" 32 #include "src/code-stubs.h"
33 #include "src/factory.h" 33 #include "src/factory.h"
34 #include "src/log-inl.h" 34 #include "src/log-inl.h"
35 35
36 #include "src/wasm/function-body-decoder.h" 36 #include "src/wasm/function-body-decoder.h"
37 #include "src/wasm/wasm-limits.h" 37 #include "src/wasm/wasm-limits.h"
38 #include "src/wasm/wasm-module.h" 38 #include "src/wasm/wasm-module.h"
39 #include "src/wasm/wasm-objects.h"
39 #include "src/wasm/wasm-opcodes.h" 40 #include "src/wasm/wasm-opcodes.h"
40 #include "src/wasm/wasm-text.h" 41 #include "src/wasm/wasm-text.h"
41 42
42 // TODO(titzer): pull WASM_64 up to a common header. 43 // TODO(titzer): pull WASM_64 up to a common header.
43 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 44 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
44 #define WASM_64 1 45 #define WASM_64 1
45 #else 46 #else
46 #define WASM_64 0 47 #define WASM_64 0
47 #endif 48 #endif
48 49
(...skipping 14 matching lines...) Expand all
63 NodeProperties::MergeControlToEnd(g, jsgraph->common(), node); 64 NodeProperties::MergeControlToEnd(g, jsgraph->common(), node);
64 } else { 65 } else {
65 g->SetEnd(g->NewNode(jsgraph->common()->End(1), node)); 66 g->SetEnd(g->NewNode(jsgraph->common()->End(1), node));
66 } 67 }
67 } 68 }
68 69
69 Node* BuildCallToRuntime(Runtime::FunctionId f, JSGraph* jsgraph, 70 Node* BuildCallToRuntime(Runtime::FunctionId f, JSGraph* jsgraph,
70 Handle<Context> context, Node** parameters, 71 Handle<Context> context, Node** parameters,
71 int parameter_count, Node** effect_ptr, 72 int parameter_count, Node** effect_ptr,
72 Node* control) { 73 Node* control) {
73 // At the moment we only allow 2 parameters. If more parameters are needed,
74 // then the size of {inputs} below has to be increased accordingly.
75 DCHECK(parameter_count <= 2);
76 const Runtime::Function* fun = Runtime::FunctionForId(f); 74 const Runtime::Function* fun = Runtime::FunctionForId(f);
77 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( 75 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
78 jsgraph->zone(), f, fun->nargs, Operator::kNoProperties, 76 jsgraph->zone(), f, fun->nargs, Operator::kNoProperties,
79 CallDescriptor::kNoFlags); 77 CallDescriptor::kNoFlags);
80 // CEntryStubConstant nodes have to be created and cached in the main 78 // CEntryStubConstant nodes have to be created and cached in the main
81 // thread. At the moment this is only done for CEntryStubConstant(1). 79 // thread. At the moment this is only done for CEntryStubConstant(1).
82 DCHECK_EQ(1, fun->result_size); 80 DCHECK_EQ(1, fun->result_size);
83 Node* inputs[8]; 81 // At the moment we only allow 2 parameters. If more parameters are needed,
82 // increase this constant accordingly.
83 static const int kMaxParams = 3;
84 DCHECK_GE(kMaxParams, parameter_count);
85 Node* inputs[kMaxParams + 6];
84 int count = 0; 86 int count = 0;
85 inputs[count++] = jsgraph->CEntryStubConstant(fun->result_size); 87 inputs[count++] = jsgraph->CEntryStubConstant(fun->result_size);
86 for (int i = 0; i < parameter_count; i++) { 88 for (int i = 0; i < parameter_count; i++) {
87 inputs[count++] = parameters[i]; 89 inputs[count++] = parameters[i];
88 } 90 }
89 inputs[count++] = jsgraph->ExternalConstant( 91 inputs[count++] = jsgraph->ExternalConstant(
90 ExternalReference(f, jsgraph->isolate())); // ref 92 ExternalReference(f, jsgraph->isolate())); // ref
91 inputs[count++] = jsgraph->Int32Constant(fun->nargs); // arity 93 inputs[count++] = jsgraph->Int32Constant(fun->nargs); // arity
92 inputs[count++] = jsgraph->HeapConstant(context); // context 94 inputs[count++] = jsgraph->HeapConstant(context); // context
93 inputs[count++] = *effect_ptr; 95 inputs[count++] = *effect_ptr;
(...skipping 2811 matching lines...) Expand 10 before | Expand all | Expand 10 after
2905 2907
2906 // Convert the return value back. 2908 // Convert the return value back.
2907 Node* i32_zero = jsgraph()->Int32Constant(0); 2909 Node* i32_zero = jsgraph()->Int32Constant(0);
2908 Node* val = sig->return_count() == 0 2910 Node* val = sig->return_count() == 0
2909 ? i32_zero 2911 ? i32_zero
2910 : FromJS(call, HeapConstant(isolate->native_context()), 2912 : FromJS(call, HeapConstant(isolate->native_context()),
2911 sig->GetReturn()); 2913 sig->GetReturn());
2912 Return(val); 2914 Return(val);
2913 } 2915 }
2914 2916
2917 void WasmGraphBuilder::BuildWasmInterpreterEntry(
2918 uint32_t function_index, wasm::FunctionSig* sig,
2919 Handle<WasmInstanceObject> instance) {
2920 int wasm_count = static_cast<int>(sig->parameter_count());
2921 int param_count = jsgraph()->machine()->Is64()
2922 ? wasm_count
2923 : Int64Lowering::GetParameterCountAfterLowering(sig);
2924
2925 // Build the start and the parameter nodes.
2926 Node* start = Start(param_count + 3);
2927 *effect_ = start;
2928 *control_ = start;
2929
2930 // Compute size for the argument buffer.
2931 int args_size_bytes = 0;
2932 for (int i = 0; i < wasm_count; i++) {
2933 args_size_bytes += 1 << ElementSizeLog2Of(sig->GetParam(i));
2934 }
2935
2936 // The return value is also passed via this buffer:
2937 DCHECK_GE(1, sig->return_count());
2938 int return_size_bytes =
2939 sig->return_count() == 0 ? 0 : 1 << ElementSizeLog2Of(sig->GetReturn(0));
2940
2941 // Get a stack slot for the arguments.
2942 Node* arg_buffer = graph()->NewNode(jsgraph()->machine()->StackSlot(
2943 std::max(args_size_bytes, return_size_bytes)));
2944
2945 // Now store all our arguments to the buffer.
2946 int param_index = 0;
2947 int offset = 0;
2948 for (int i = 0; i < wasm_count; i++) {
2949 Node* param = Param(param_index++);
2950 bool is_i64_as_two_params =
2951 jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kWasmI64;
2952 MachineRepresentation param_rep =
2953 is_i64_as_two_params ? wasm::kWasmI32 : sig->GetParam(i);
2954 StoreRepresentation store_rep(param_rep, WriteBarrierKind::kNoWriteBarrier);
2955 *effect_ =
2956 graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
2957 Int32Constant(offset), param, *effect_, *control_);
2958 offset += 1 << ElementSizeLog2Of(param_rep);
2959 if (is_i64_as_two_params) {
titzer 2017/01/11 15:52:34 As discussed in person, you'll have to check the e
Clemens Hammacher 2017/01/11 16:56:10 Done.
2960 // Also store the upper half.
2961 param = Param(param_index++);
2962 StoreRepresentation store_rep(wasm::kWasmI32,
2963 WriteBarrierKind::kNoWriteBarrier);
2964 *effect_ =
2965 graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
2966 Int32Constant(offset), param, *effect_, *control_);
2967 offset += 1 << ElementSizeLog2Of(wasm::kWasmI32);
2968 }
2969 }
2970 DCHECK_EQ(param_count, param_index);
2971 DCHECK_EQ(args_size_bytes, offset);
2972
2973 Node* parameters[] = {
2974 jsgraph()->HeapConstant(instance), // wasm instance
2975 jsgraph()->SmiConstant(function_index), // function index
2976 arg_buffer, // argument buffer
titzer 2017/01/11 15:52:34 Can you add a TODO or other comment that we are pa
Clemens Hammacher 2017/01/11 16:56:10 I think IsSmi would actually return true, even tho
2977 };
2978 BuildCallToRuntime(Runtime::kWasmRunInterpreter, jsgraph(),
2979 jsgraph()->isolate()->native_context(), parameters,
2980 arraysize(parameters), effect_, *control_);
2981
2982 // Read back the return value.
2983 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
2984 sig->GetReturn() == wasm::kWasmI64) {
2985 MachineType load_rep = wasm::WasmOpcodes::MachineTypeFor(wasm::kWasmI32);
2986 Node* lower =
2987 graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
2988 Int32Constant(0), *effect_, *control_);
2989 Node* upper =
2990 graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
2991 Int32Constant(sizeof(int32_t)), *effect_, *control_);
2992 Return(upper, lower);
2993 } else {
2994 Node* val;
2995 if (sig->return_count() == 0) {
2996 val = Int32Constant(0);
2997 } else {
2998 MachineType load_rep =
2999 wasm::WasmOpcodes::MachineTypeFor(sig->GetReturn());
3000 val = graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
3001 Int32Constant(0), *effect_, *control_);
3002 }
3003 Return(val);
3004 }
3005 }
3006
2915 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { 3007 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
2916 DCHECK(module_ && module_->instance); 3008 DCHECK(module_ && module_->instance);
2917 if (offset == 0) { 3009 if (offset == 0) {
2918 if (!mem_buffer_) { 3010 if (!mem_buffer_) {
2919 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( 3011 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant(
2920 reinterpret_cast<uintptr_t>(module_->instance->mem_start), 3012 reinterpret_cast<uintptr_t>(module_->instance->mem_start),
2921 RelocInfo::WASM_MEMORY_REFERENCE); 3013 RelocInfo::WASM_MEMORY_REFERENCE);
2922 } 3014 }
2923 return mem_buffer_; 3015 return mem_buffer_;
2924 } else { 3016 } else {
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after
3486 } 3578 }
3487 RecordFunctionCompilation( 3579 RecordFunctionCompilation(
3488 CodeEventListener::FUNCTION_TAG, isolate, code, "wasm-to-js", index, 3580 CodeEventListener::FUNCTION_TAG, isolate, code, "wasm-to-js", index,
3489 {module_name->ToCString().get(), module_name->length()}, 3581 {module_name->ToCString().get(), module_name->length()},
3490 {function_name, function_name_size}); 3582 {function_name, function_name_size});
3491 } 3583 }
3492 3584
3493 return code; 3585 return code;
3494 } 3586 }
3495 3587
3588 Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
3589 wasm::FunctionSig* sig,
3590 Handle<WasmInstanceObject> instance) {
3591 //----------------------------------------------------------------------------
3592 // Create the Graph
3593 //----------------------------------------------------------------------------
3594 Zone zone(isolate->allocator(), ZONE_NAME);
3595 Graph graph(&zone);
3596 CommonOperatorBuilder common(&zone);
3597 MachineOperatorBuilder machine(&zone);
3598 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
3599
3600 Node* control = nullptr;
3601 Node* effect = nullptr;
3602
3603 WasmGraphBuilder builder(nullptr, &zone, &jsgraph, sig);
3604 builder.set_control_ptr(&control);
3605 builder.set_effect_ptr(&effect);
3606 builder.BuildWasmInterpreterEntry(func_index, sig, instance);
3607
3608 Handle<Code> code = Handle<Code>::null();
3609 {
3610 if (FLAG_trace_turbo_graph) { // Simple textual RPO.
3611 OFStream os(stdout);
3612 os << "-- Wasm to interpreter graph -- " << std::endl;
3613 os << AsRPO(graph);
3614 }
3615
3616 // Schedule and compile to machine code.
3617 CallDescriptor* incoming =
3618 wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig);
3619 if (machine.Is32()) {
3620 incoming = wasm::ModuleEnv::GetI32WasmCallDescriptor(&zone, incoming);
3621 }
3622 Code::Flags flags = Code::ComputeFlags(Code::WASM_INTERPRETER_ENTRY);
3623 EmbeddedVector<char, 32> debug_name;
3624 int name_len = SNPrintF(debug_name, "wasm-to-interpreter#%d", func_index);
3625 DCHECK(name_len > 0 && name_len < debug_name.length());
3626 debug_name.Truncate(name_len);
3627 DCHECK_EQ('\0', debug_name.start()[debug_name.length()]);
3628
3629 CompilationInfo info(debug_name, isolate, &zone, flags);
3630 code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
3631 #ifdef ENABLE_DISASSEMBLER
3632 if (FLAG_print_opt_code && !code.is_null()) {
3633 OFStream os(stdout);
3634 code->Disassemble(debug_name.start(), os);
3635 }
3636 #endif
3637
3638 if (isolate->logger()->is_logging_code_events() ||
3639 isolate->is_profiling()) {
3640 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code,
3641 "wasm-to-interpreter", func_index,
3642 wasm::WasmName("module"), debug_name);
3643 }
3644 }
3645
3646 Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(1, TENURED);
3647 Handle<WeakCell> weak_instance = isolate->factory()->NewWeakCell(instance);
3648 deopt_data->set(0, *weak_instance);
3649 code->set_deoptimization_data(*deopt_data);
3650
3651 return code;
3652 }
3653
3496 SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( 3654 SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
3497 double* decode_ms) { 3655 double* decode_ms) {
3498 base::ElapsedTimer decode_timer; 3656 base::ElapsedTimer decode_timer;
3499 if (FLAG_trace_wasm_decode_time) { 3657 if (FLAG_trace_wasm_decode_time) {
3500 decode_timer.Start(); 3658 decode_timer.Start();
3501 } 3659 }
3502 // Create a TF graph during decoding. 3660 // Create a TF graph during decoding.
3503 3661
3504 Graph* graph = jsgraph_->graph(); 3662 Graph* graph = jsgraph_->graph();
3505 CommonOperatorBuilder* common = jsgraph_->common(); 3663 CommonOperatorBuilder* common = jsgraph_->common();
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
3693 Smi::FromInt(instruction.instr_offset)); 3851 Smi::FromInt(instruction.instr_offset));
3694 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset, 3852 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset,
3695 Smi::FromInt(instruction.landing_offset)); 3853 Smi::FromInt(instruction.landing_offset));
3696 } 3854 }
3697 return fn_protected; 3855 return fn_protected;
3698 } 3856 }
3699 3857
3700 } // namespace compiler 3858 } // namespace compiler
3701 } // namespace internal 3859 } // namespace internal
3702 } // namespace v8 3860 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698