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#if !V8_ENABLE_WEBASSEMBLY
6#error This header should only be included if WebAssembly is enabled.
7#endif  // !V8_ENABLE_WEBASSEMBLY
8
9#ifndef V8_WASM_FUNCTION_COMPILER_H_
10#define V8_WASM_FUNCTION_COMPILER_H_
11
12#include <memory>
13
14#include "src/codegen/assembler.h"
15#include "src/codegen/code-desc.h"
16#include "src/trap-handler/trap-handler.h"
17#include "src/wasm/compilation-environment.h"
18#include "src/wasm/function-body-decoder.h"
19#include "src/wasm/wasm-limits.h"
20#include "src/wasm/wasm-module.h"
21#include "src/wasm/wasm-tier.h"
22
23namespace v8 {
24namespace internal {
25
26class Counters;
27class TurbofanCompilationJob;
28
29namespace wasm {
30
31class NativeModule;
32class WasmCode;
33class WasmEngine;
34struct WasmFunction;
35
36struct WasmCompilationResult {
37 public:
38  MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(WasmCompilationResult);
39
40  enum Kind : int8_t {
41    kFunction,
42    kWasmToJsWrapper,
43  };
44
45  bool succeeded() const { return code_desc.buffer != nullptr; }
46  bool failed() const { return !succeeded(); }
47  operator bool() const { return succeeded(); }
48
49  CodeDesc code_desc;
50  std::unique_ptr<AssemblerBuffer> instr_buffer;
51  uint32_t frame_slot_count = 0;
52  uint32_t tagged_parameter_slots = 0;
53  base::OwnedVector<byte> source_positions;
54  base::OwnedVector<byte> protected_instructions_data;
55  int func_index = kAnonymousFuncIndex;
56  ExecutionTier requested_tier;
57  ExecutionTier result_tier;
58  Kind kind = kFunction;
59  ForDebugging for_debugging = kNoDebugging;
60  int feedback_vector_slots = 0;
61};
62
63class V8_EXPORT_PRIVATE WasmCompilationUnit final {
64 public:
65  static ExecutionTier GetBaselineExecutionTier(const WasmModule*);
66
67  WasmCompilationUnit(int index, ExecutionTier tier, ForDebugging for_debugging)
68      : func_index_(index), tier_(tier), for_debugging_(for_debugging) {}
69
70  WasmCompilationResult ExecuteCompilation(CompilationEnv*,
71                                           const WireBytesStorage*, Counters*,
72                                           WasmFeatures* detected);
73
74  ExecutionTier tier() const { return tier_; }
75  ForDebugging for_debugging() const { return for_debugging_; }
76  int func_index() const { return func_index_; }
77
78  static void CompileWasmFunction(Isolate*, NativeModule*,
79                                  WasmFeatures* detected, const WasmFunction*,
80                                  ExecutionTier);
81
82 private:
83  WasmCompilationResult ExecuteFunctionCompilation(CompilationEnv*,
84                                                   const WireBytesStorage*,
85                                                   Counters*,
86                                                   WasmFeatures* detected);
87
88  WasmCompilationResult ExecuteImportWrapperCompilation(CompilationEnv*);
89
90  int func_index_;
91  ExecutionTier tier_;
92  ForDebugging for_debugging_;
93};
94
95// {WasmCompilationUnit} should be trivially copyable and small enough so we can
96// efficiently pass it by value.
97ASSERT_TRIVIALLY_COPYABLE(WasmCompilationUnit);
98STATIC_ASSERT(sizeof(WasmCompilationUnit) <= 2 * kSystemPointerSize);
99
100class V8_EXPORT_PRIVATE JSToWasmWrapperCompilationUnit final {
101 public:
102  // A flag to mark whether the compilation unit can skip the compilation
103  // and return the builtin (generic) wrapper, when available.
104  enum AllowGeneric : bool { kAllowGeneric = true, kDontAllowGeneric = false };
105
106  JSToWasmWrapperCompilationUnit(Isolate* isolate, const FunctionSig* sig,
107                                 const wasm::WasmModule* module, bool is_import,
108                                 const WasmFeatures& enabled_features,
109                                 AllowGeneric allow_generic);
110  ~JSToWasmWrapperCompilationUnit();
111
112  Isolate* isolate() const { return isolate_; }
113
114  void Execute();
115  Handle<Code> Finalize();
116
117  bool is_import() const { return is_import_; }
118  const FunctionSig* sig() const { return sig_; }
119
120  // Run a compilation unit synchronously.
121  static Handle<Code> CompileJSToWasmWrapper(Isolate* isolate,
122                                             const FunctionSig* sig,
123                                             const WasmModule* module,
124                                             bool is_import);
125
126  // Run a compilation unit synchronously, but ask for the specific
127  // wrapper.
128  static Handle<Code> CompileSpecificJSToWasmWrapper(Isolate* isolate,
129                                                     const FunctionSig* sig,
130                                                     const WasmModule* module);
131
132 private:
133  // Wrapper compilation is bound to an isolate. Concurrent accesses to the
134  // isolate (during the "Execute" phase) must be audited carefully, i.e. we
135  // should only access immutable information (like the root table). The isolate
136  // is guaranteed to be alive when this unit executes.
137  Isolate* isolate_;
138  bool is_import_;
139  const FunctionSig* sig_;
140  bool use_generic_wrapper_;
141  std::unique_ptr<TurbofanCompilationJob> job_;
142};
143
144}  // namespace wasm
145}  // namespace internal
146}  // namespace v8
147
148#endif  // V8_WASM_FUNCTION_COMPILER_H_
149