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

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

Issue 2619803004: [wasm] Add support for compiling WASM_INTERPRETER_ENTRY stubs (Closed)
Patch Set: Change void* to uint8_t* 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
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2826 matching lines...) Expand 10 before | Expand all | Expand 10 after
2920 2922
2921 // Convert the return value back. 2923 // Convert the return value back.
2922 Node* i32_zero = jsgraph()->Int32Constant(0); 2924 Node* i32_zero = jsgraph()->Int32Constant(0);
2923 Node* val = sig->return_count() == 0 2925 Node* val = sig->return_count() == 0
2924 ? i32_zero 2926 ? i32_zero
2925 : FromJS(call, HeapConstant(isolate->native_context()), 2927 : FromJS(call, HeapConstant(isolate->native_context()),
2926 sig->GetReturn()); 2928 sig->GetReturn());
2927 Return(val); 2929 Return(val);
2928 } 2930 }
2929 2931
2932 void WasmGraphBuilder::BuildWasmInterpreterEntry(
2933 uint32_t function_index, wasm::FunctionSig* sig,
2934 Handle<WasmInstanceObject> instance) {
2935 int wasm_count = static_cast<int>(sig->parameter_count());
2936 int param_count = jsgraph()->machine()->Is64()
2937 ? wasm_count
2938 : Int64Lowering::GetParameterCountAfterLowering(sig);
2939
2940 // Build the start and the parameter nodes.
2941 Node* start = Start(param_count + 3);
2942 *effect_ = start;
2943 *control_ = start;
2944
2945 // Compute size for the argument buffer.
2946 int args_size_bytes = 0;
2947 for (int i = 0; i < wasm_count; i++) {
2948 args_size_bytes += 1 << ElementSizeLog2Of(sig->GetParam(i));
2949 }
2950
2951 // The return value is also passed via this buffer:
2952 DCHECK_GE(1, sig->return_count());
2953 int return_size_bytes =
2954 sig->return_count() == 0 ? 0 : 1 << ElementSizeLog2Of(sig->GetReturn(0));
2955
2956 // Get a stack slot for the arguments.
2957 Node* arg_buffer = graph()->NewNode(jsgraph()->machine()->StackSlot(
2958 std::max(args_size_bytes, return_size_bytes)));
2959
2960 // Now store all our arguments to the buffer.
2961 int param_index = 0;
2962 int offset = 0;
2963 for (int i = 0; i < wasm_count; i++) {
2964 Node* param = Param(param_index++);
2965 bool is_i64_as_two_params =
2966 jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kWasmI64;
2967 MachineRepresentation param_rep =
2968 is_i64_as_two_params ? wasm::kWasmI32 : sig->GetParam(i);
2969 StoreRepresentation store_rep(param_rep, WriteBarrierKind::kNoWriteBarrier);
2970 *effect_ =
2971 graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
2972 Int32Constant(offset), param, *effect_, *control_);
2973 offset += 1 << ElementSizeLog2Of(param_rep);
2974 // TODO(clemensh): Respect endianess here. Might need to swap upper and
2975 // lower word.
2976 if (is_i64_as_two_params) {
2977 // Also store the upper half.
2978 param = Param(param_index++);
2979 StoreRepresentation store_rep(wasm::kWasmI32,
2980 WriteBarrierKind::kNoWriteBarrier);
2981 *effect_ =
2982 graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
2983 Int32Constant(offset), param, *effect_, *control_);
2984 offset += 1 << ElementSizeLog2Of(wasm::kWasmI32);
2985 }
2986 }
2987 DCHECK_EQ(param_count, param_index);
2988 DCHECK_EQ(args_size_bytes, offset);
2989
2990 // We are passing the raw arg_buffer here. To the GC and other parts, it looks
2991 // like a Smi (lowest bit not set). In the runtime function however, don't
2992 // call Smi::value on it, but just cast it to a byte pointer.
2993 Node* parameters[] = {
2994 jsgraph()->HeapConstant(instance), // wasm instance
2995 jsgraph()->SmiConstant(function_index), // function index
2996 arg_buffer, // argument buffer
2997 };
2998 BuildCallToRuntime(Runtime::kWasmRunInterpreter, jsgraph(),
2999 jsgraph()->isolate()->native_context(), parameters,
3000 arraysize(parameters), effect_, *control_);
3001
3002 // Read back the return value.
3003 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
3004 sig->GetReturn() == wasm::kWasmI64) {
3005 MachineType load_rep = wasm::WasmOpcodes::MachineTypeFor(wasm::kWasmI32);
3006 Node* lower =
3007 graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
3008 Int32Constant(0), *effect_, *control_);
3009 Node* upper =
3010 graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
3011 Int32Constant(sizeof(int32_t)), *effect_, *control_);
3012 Return(upper, lower);
3013 } else {
3014 Node* val;
3015 if (sig->return_count() == 0) {
3016 val = Int32Constant(0);
3017 } else {
3018 MachineType load_rep =
3019 wasm::WasmOpcodes::MachineTypeFor(sig->GetReturn());
3020 val = graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
3021 Int32Constant(0), *effect_, *control_);
3022 }
3023 Return(val);
3024 }
3025 }
3026
2930 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { 3027 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
2931 DCHECK(module_ && module_->instance); 3028 DCHECK(module_ && module_->instance);
2932 if (offset == 0) { 3029 if (offset == 0) {
2933 if (!mem_buffer_) { 3030 if (!mem_buffer_) {
2934 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( 3031 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant(
2935 reinterpret_cast<uintptr_t>(module_->instance->mem_start), 3032 reinterpret_cast<uintptr_t>(module_->instance->mem_start),
2936 RelocInfo::WASM_MEMORY_REFERENCE); 3033 RelocInfo::WASM_MEMORY_REFERENCE);
2937 } 3034 }
2938 return mem_buffer_; 3035 return mem_buffer_;
2939 } else { 3036 } else {
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after
3501 } 3598 }
3502 RecordFunctionCompilation( 3599 RecordFunctionCompilation(
3503 CodeEventListener::FUNCTION_TAG, isolate, code, "wasm-to-js", index, 3600 CodeEventListener::FUNCTION_TAG, isolate, code, "wasm-to-js", index,
3504 {module_name->ToCString().get(), module_name->length()}, 3601 {module_name->ToCString().get(), module_name->length()},
3505 {function_name, function_name_size}); 3602 {function_name, function_name_size});
3506 } 3603 }
3507 3604
3508 return code; 3605 return code;
3509 } 3606 }
3510 3607
3608 Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
3609 wasm::FunctionSig* sig,
3610 Handle<WasmInstanceObject> instance) {
3611 //----------------------------------------------------------------------------
3612 // Create the Graph
3613 //----------------------------------------------------------------------------
3614 Zone zone(isolate->allocator(), ZONE_NAME);
3615 Graph graph(&zone);
3616 CommonOperatorBuilder common(&zone);
3617 MachineOperatorBuilder machine(&zone);
3618 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
3619
3620 Node* control = nullptr;
3621 Node* effect = nullptr;
3622
3623 WasmGraphBuilder builder(nullptr, &zone, &jsgraph, sig);
3624 builder.set_control_ptr(&control);
3625 builder.set_effect_ptr(&effect);
3626 builder.BuildWasmInterpreterEntry(func_index, sig, instance);
3627
3628 Handle<Code> code = Handle<Code>::null();
3629 {
3630 if (FLAG_trace_turbo_graph) { // Simple textual RPO.
3631 OFStream os(stdout);
3632 os << "-- Wasm to interpreter graph -- " << std::endl;
3633 os << AsRPO(graph);
3634 }
3635
3636 // Schedule and compile to machine code.
3637 CallDescriptor* incoming =
3638 wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig);
3639 if (machine.Is32()) {
3640 incoming = wasm::ModuleEnv::GetI32WasmCallDescriptor(&zone, incoming);
3641 }
3642 Code::Flags flags = Code::ComputeFlags(Code::WASM_INTERPRETER_ENTRY);
3643 EmbeddedVector<char, 32> debug_name;
3644 int name_len = SNPrintF(debug_name, "wasm-to-interpreter#%d", func_index);
3645 DCHECK(name_len > 0 && name_len < debug_name.length());
3646 debug_name.Truncate(name_len);
3647 DCHECK_EQ('\0', debug_name.start()[debug_name.length()]);
3648
3649 CompilationInfo info(debug_name, isolate, &zone, flags);
3650 code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
3651 #ifdef ENABLE_DISASSEMBLER
3652 if (FLAG_print_opt_code && !code.is_null()) {
3653 OFStream os(stdout);
3654 code->Disassemble(debug_name.start(), os);
3655 }
3656 #endif
3657
3658 if (isolate->logger()->is_logging_code_events() ||
3659 isolate->is_profiling()) {
3660 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code,
3661 "wasm-to-interpreter", func_index,
3662 wasm::WasmName("module"), debug_name);
3663 }
3664 }
3665
3666 Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(1, TENURED);
3667 Handle<WeakCell> weak_instance = isolate->factory()->NewWeakCell(instance);
3668 deopt_data->set(0, *weak_instance);
3669 code->set_deoptimization_data(*deopt_data);
3670
3671 return code;
3672 }
3673
3511 SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( 3674 SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
3512 double* decode_ms) { 3675 double* decode_ms) {
3513 base::ElapsedTimer decode_timer; 3676 base::ElapsedTimer decode_timer;
3514 if (FLAG_trace_wasm_decode_time) { 3677 if (FLAG_trace_wasm_decode_time) {
3515 decode_timer.Start(); 3678 decode_timer.Start();
3516 } 3679 }
3517 // Create a TF graph during decoding. 3680 // Create a TF graph during decoding.
3518 3681
3519 Graph* graph = jsgraph_->graph(); 3682 Graph* graph = jsgraph_->graph();
3520 CommonOperatorBuilder* common = jsgraph_->common(); 3683 CommonOperatorBuilder* common = jsgraph_->common();
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
3708 Smi::FromInt(instruction.instr_offset)); 3871 Smi::FromInt(instruction.instr_offset));
3709 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset, 3872 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset,
3710 Smi::FromInt(instruction.landing_offset)); 3873 Smi::FromInt(instruction.landing_offset));
3711 } 3874 }
3712 return fn_protected; 3875 return fn_protected;
3713 } 3876 }
3714 3877
3715 } // namespace compiler 3878 } // namespace compiler
3716 } // namespace internal 3879 } // namespace internal
3717 } // namespace v8 3880 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698