Line data Source code
1 : // Copyright 2018 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/wasm/function-compiler.h"
6 :
7 : #include "src/compiler/wasm-compiler.h"
8 : #include "src/counters.h"
9 : #include "src/macro-assembler-inl.h"
10 : #include "src/wasm/baseline/liftoff-compiler.h"
11 : #include "src/wasm/wasm-code-manager.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 : namespace wasm {
16 :
17 : namespace {
18 :
19 : const char* GetExecutionTierAsString(ExecutionTier tier) {
20 : switch (tier) {
21 : case ExecutionTier::kBaseline:
22 : return "liftoff";
23 : case ExecutionTier::kOptimized:
24 : return "turbofan";
25 : case ExecutionTier::kInterpreter:
26 : return "interpreter";
27 : }
28 : UNREACHABLE();
29 : }
30 :
31 : } // namespace
32 :
33 : // static
34 168271 : ExecutionTier WasmCompilationUnit::GetDefaultExecutionTier(
35 : const WasmModule* module) {
36 168231 : return FLAG_liftoff && module->origin == kWasmOrigin
37 : ? ExecutionTier::kBaseline
38 336542 : : ExecutionTier::kOptimized;
39 : }
40 :
41 1755349 : WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine, int index,
42 : ExecutionTier tier)
43 1755349 : : wasm_engine_(wasm_engine), func_index_(index), tier_(tier) {
44 1755349 : if (V8_UNLIKELY(FLAG_wasm_tier_mask_for_testing) && index < 32 &&
45 : (FLAG_wasm_tier_mask_for_testing & (1 << index))) {
46 : tier = ExecutionTier::kOptimized;
47 : }
48 1755349 : SwitchTier(tier);
49 1755350 : }
50 :
51 : // Declared here such that {LiftoffCompilationUnit} and
52 : // {TurbofanWasmCompilationUnit} can be opaque in the header file.
53 : WasmCompilationUnit::~WasmCompilationUnit() = default;
54 :
55 1754487 : void WasmCompilationUnit::ExecuteCompilation(
56 : CompilationEnv* env, NativeModule* native_module,
57 : const std::shared_ptr<WireBytesStorage>& wire_bytes_storage,
58 : Counters* counters, WasmFeatures* detected) {
59 1754487 : auto* func = &env->module->functions[func_index_];
60 1754487 : Vector<const uint8_t> code = wire_bytes_storage->GetCode(func->code);
61 : wasm::FunctionBody func_body{func->sig, func->code.offset(), code.start(),
62 1754459 : code.end()};
63 :
64 1754459 : auto size_histogram = SELECT_WASM_COUNTER(counters, env->module->origin, wasm,
65 : function_size_bytes);
66 1754459 : size_histogram->AddSample(static_cast<int>(func_body.end - func_body.start));
67 1754453 : auto timed_histogram = SELECT_WASM_COUNTER(counters, env->module->origin,
68 : wasm_compile, function_time);
69 : TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);
70 :
71 : if (FLAG_trace_wasm_compiler) {
72 : PrintF("Compiling wasm function %d with %s\n\n", func_index_,
73 : GetExecutionTierAsString(tier_));
74 : }
75 :
76 1754453 : switch (tier_) {
77 : case ExecutionTier::kBaseline:
78 711937 : if (liftoff_unit_->ExecuteCompilation(env, native_module, func_body,
79 : counters, detected)) {
80 : break;
81 : }
82 : // Otherwise, fall back to turbofan.
83 24502 : SwitchTier(ExecutionTier::kOptimized);
84 : // TODO(wasm): We could actually stop or remove the tiering unit for this
85 : // function to avoid compiling it twice with TurboFan.
86 : V8_FALLTHROUGH;
87 : case ExecutionTier::kOptimized:
88 : turbofan_unit_->ExecuteCompilation(env, native_module, func_body,
89 1067030 : counters, detected);
90 1067035 : break;
91 : case ExecutionTier::kInterpreter:
92 0 : UNREACHABLE(); // TODO(titzer): compile interpreter entry stub.
93 : }
94 1754503 : }
95 :
96 1779850 : void WasmCompilationUnit::SwitchTier(ExecutionTier new_tier) {
97 : // This method is being called in the constructor, where neither
98 : // {liftoff_unit_} nor {turbofan_unit_} are set, or to switch tier from
99 : // kLiftoff to kTurbofan, in which case {liftoff_unit_} is already set.
100 1779850 : tier_ = new_tier;
101 1779850 : switch (new_tier) {
102 : case ExecutionTier::kBaseline:
103 : DCHECK(!turbofan_unit_);
104 : DCHECK(!liftoff_unit_);
105 712206 : liftoff_unit_.reset(new LiftoffCompilationUnit(this));
106 : return;
107 : case ExecutionTier::kOptimized:
108 : DCHECK(!turbofan_unit_);
109 : liftoff_unit_.reset();
110 1067642 : turbofan_unit_.reset(new compiler::TurbofanWasmCompilationUnit(this));
111 : return;
112 : case ExecutionTier::kInterpreter:
113 0 : UNREACHABLE(); // TODO(titzer): allow compiling interpreter entry stub.
114 : }
115 0 : UNREACHABLE();
116 : }
117 :
118 : // static
119 145833 : void WasmCompilationUnit::CompileWasmFunction(Isolate* isolate,
120 : NativeModule* native_module,
121 : WasmFeatures* detected,
122 : const WasmFunction* function,
123 : ExecutionTier tier) {
124 : ModuleWireBytes wire_bytes(native_module->wire_bytes());
125 : FunctionBody function_body{function->sig, function->code.offset(),
126 : wire_bytes.start() + function->code.offset(),
127 : wire_bytes.start() + function->code.end_offset()};
128 :
129 291666 : WasmCompilationUnit unit(isolate->wasm_engine(), function->func_index, tier);
130 145833 : CompilationEnv env = native_module->CreateCompilationEnv();
131 : unit.ExecuteCompilation(
132 : &env, native_module,
133 : native_module->compilation_state()->GetWireBytesStorage(),
134 291666 : isolate->counters(), detected);
135 145833 : }
136 :
137 3495200 : void WasmCompilationUnit::SetResult(WasmCode* code, Counters* counters) {
138 : DCHECK_NULL(result_);
139 1747600 : result_ = code;
140 1747600 : code->native_module()->PublishCode(code);
141 :
142 : counters->wasm_generated_code_size()->Increment(
143 1747764 : static_cast<int>(code->instructions().size()));
144 : counters->wasm_reloc_size()->Increment(
145 1747764 : static_cast<int>(code->reloc_info().size()));
146 1747760 : }
147 :
148 : } // namespace wasm
149 : } // namespace internal
150 183867 : } // namespace v8
|