Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_COMPILER_WASM_COMPILER_H_
6 : #define V8_COMPILER_WASM_COMPILER_H_
7 :
8 : #include <memory>
9 :
10 : // Clients of this interface shouldn't depend on lots of compiler internals.
11 : // Do not include anything from src/compiler here!
12 : #include "src/compilation-info.h"
13 : #include "src/compiler.h"
14 : #include "src/trap-handler/trap-handler.h"
15 : #include "src/wasm/function-body-decoder.h"
16 : #include "src/wasm/wasm-module.h"
17 : #include "src/wasm/wasm-opcodes.h"
18 : #include "src/wasm/wasm-result.h"
19 : #include "src/zone/zone.h"
20 :
21 : namespace v8 {
22 : namespace internal {
23 :
24 : namespace compiler {
25 : // Forward declarations for some compiler data structures.
26 : class Node;
27 : class JSGraph;
28 : class Graph;
29 : class Operator;
30 : class SourcePositionTable;
31 : } // namespace compiler
32 :
33 : namespace wasm {
34 : // Forward declarations for some WASM data structures.
35 : struct ModuleBytesEnv;
36 : struct ModuleEnv;
37 : struct WasmFunction;
38 : struct WasmModule;
39 : class ErrorThrower;
40 : struct DecodeStruct;
41 :
42 : // Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
43 : typedef compiler::Node TFNode;
44 : typedef compiler::JSGraph TFGraph;
45 : } // namespace wasm
46 :
47 : namespace compiler {
48 142506 : class WasmCompilationUnit final {
49 : public:
50 : WasmCompilationUnit(Isolate* isolate, wasm::ModuleBytesEnv* module_env,
51 : const wasm::WasmFunction* function);
52 : WasmCompilationUnit(Isolate* isolate, wasm::ModuleEnv* module_env,
53 : wasm::FunctionBody body, wasm::WasmName name, int index);
54 :
55 : Zone* graph_zone() { return graph_zone_.get(); }
56 : int func_index() const { return func_index_; }
57 :
58 : void InitializeHandles();
59 : void ExecuteCompilation();
60 : Handle<Code> FinishCompilation(wasm::ErrorThrower* thrower);
61 :
62 : static Handle<Code> CompileWasmFunction(wasm::ErrorThrower* thrower,
63 : Isolate* isolate,
64 : wasm::ModuleBytesEnv* module_env,
65 : const wasm::WasmFunction* function);
66 :
67 : private:
68 : SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
69 :
70 : Isolate* isolate_;
71 : wasm::ModuleEnv* module_env_;
72 : wasm::FunctionBody func_body_;
73 : wasm::WasmName func_name_;
74 : // The graph zone is deallocated at the end of ExecuteCompilation.
75 : std::unique_ptr<Zone> graph_zone_;
76 : JSGraph* jsgraph_;
77 : Zone compilation_zone_;
78 : CompilationInfo info_;
79 : std::unique_ptr<CompilationJob> job_;
80 : int func_index_;
81 : wasm::Result<wasm::DecodeStruct*> graph_construction_result_;
82 : bool ok_ = true;
83 : #if DEBUG
84 : bool handles_initialized_ = false;
85 : #endif // DEBUG
86 : ZoneVector<trap_handler::ProtectedInstructionData>
87 : protected_instructions_; // Instructions that are protected by the signal
88 : // handler.
89 :
90 : DISALLOW_COPY_AND_ASSIGN(WasmCompilationUnit);
91 : };
92 :
93 : // Wraps a JS function, producing a code object that can be called from WASM.
94 : Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
95 : wasm::FunctionSig* sig, uint32_t index,
96 : Handle<String> module_name,
97 : MaybeHandle<String> import_name,
98 : wasm::ModuleOrigin origin);
99 :
100 : // Wraps a given wasm code object, producing a code object.
101 : Handle<Code> CompileJSToWasmWrapper(Isolate* isolate,
102 : const wasm::WasmModule* module,
103 : Handle<Code> wasm_code, uint32_t index);
104 :
105 : // Compiles a stub that redirects a call to a wasm function to the wasm
106 : // interpreter. It's ABI compatible with the compiled wasm function.
107 : Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
108 : wasm::FunctionSig* sig,
109 : Handle<WasmInstanceObject> instance);
110 :
111 : // Abstracts details of building TurboFan graph nodes for WASM to separate
112 : // the WASM decoder from the internal details of TurboFan.
113 : class WasmTrapHelper;
114 : typedef ZoneVector<Node*> NodeVector;
115 : class WasmGraphBuilder {
116 : public:
117 : WasmGraphBuilder(
118 : wasm::ModuleEnv* module_env, Zone* z, JSGraph* g, wasm::FunctionSig* sig,
119 : compiler::SourcePositionTable* source_position_table = nullptr);
120 :
121 462295 : Node** Buffer(size_t count) {
122 462295 : if (count > cur_bufsize_) {
123 1088 : size_t new_size = count + cur_bufsize_ + 5;
124 : cur_buffer_ =
125 1088 : reinterpret_cast<Node**>(zone_->New(new_size * sizeof(Node*)));
126 1088 : cur_bufsize_ = new_size;
127 : }
128 462295 : return cur_buffer_;
129 : }
130 :
131 : //-----------------------------------------------------------------------
132 : // Operations independent of {control} or {effect}.
133 : //-----------------------------------------------------------------------
134 : Node* Error();
135 : Node* Start(unsigned params);
136 : Node* Param(unsigned index);
137 : Node* Loop(Node* entry);
138 : Node* Terminate(Node* effect, Node* control);
139 : Node* Merge(unsigned count, Node** controls);
140 : Node* Phi(wasm::ValueType type, unsigned count, Node** vals, Node* control);
141 : Node* EffectPhi(unsigned count, Node** effects, Node* control);
142 : Node* NumberConstant(int32_t value);
143 : Node* Uint32Constant(uint32_t value);
144 : Node* Int32Constant(int32_t value);
145 : Node* Int64Constant(int64_t value);
146 : Node* Float32Constant(float value);
147 : Node* Float64Constant(double value);
148 : Node* HeapConstant(Handle<HeapObject> value);
149 : Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
150 : wasm::WasmCodePosition position = wasm::kNoCodePosition);
151 : Node* Unop(wasm::WasmOpcode opcode, Node* input,
152 : wasm::WasmCodePosition position = wasm::kNoCodePosition);
153 : Node* GrowMemory(Node* input);
154 : Node* Throw(Node* input);
155 : Node* Catch(Node* input, wasm::WasmCodePosition position);
156 : unsigned InputCount(Node* node);
157 : bool IsPhiWithMerge(Node* phi, Node* merge);
158 : bool ThrowsException(Node* node, Node** if_success, Node** if_exception);
159 : void AppendToMerge(Node* merge, Node* from);
160 : void AppendToPhi(Node* phi, Node* from);
161 :
162 : void StackCheck(wasm::WasmCodePosition position, Node** effect = nullptr,
163 : Node** control = nullptr);
164 :
165 : //-----------------------------------------------------------------------
166 : // Operations that read and/or write {control} and {effect}.
167 : //-----------------------------------------------------------------------
168 : Node* BranchNoHint(Node* cond, Node** true_node, Node** false_node);
169 : Node* BranchExpectTrue(Node* cond, Node** true_node, Node** false_node);
170 : Node* BranchExpectFalse(Node* cond, Node** true_node, Node** false_node);
171 :
172 : Node* TrapIfTrue(wasm::TrapReason reason, Node* cond,
173 : wasm::WasmCodePosition position);
174 : Node* TrapIfFalse(wasm::TrapReason reason, Node* cond,
175 : wasm::WasmCodePosition position);
176 : Node* TrapIfEq32(wasm::TrapReason reason, Node* node, int32_t val,
177 : wasm::WasmCodePosition position);
178 : Node* ZeroCheck32(wasm::TrapReason reason, Node* node,
179 : wasm::WasmCodePosition position);
180 : Node* TrapIfEq64(wasm::TrapReason reason, Node* node, int64_t val,
181 : wasm::WasmCodePosition position);
182 : Node* ZeroCheck64(wasm::TrapReason reason, Node* node,
183 : wasm::WasmCodePosition position);
184 :
185 : Node* Switch(unsigned count, Node* key);
186 : Node* IfValue(int32_t value, Node* sw);
187 : Node* IfDefault(Node* sw);
188 : Node* Return(unsigned count, Node** nodes);
189 : template <typename... Nodes>
190 : Node* Return(Node* fst, Nodes*... more) {
191 67566 : Node* arr[] = {fst, more...};
192 67566 : return Return(arraysize(arr), arr);
193 : }
194 : Node* ReturnVoid();
195 : Node* Unreachable(wasm::WasmCodePosition position);
196 :
197 : Node* CallDirect(uint32_t index, Node** args, Node*** rets,
198 : wasm::WasmCodePosition position);
199 : Node* CallIndirect(uint32_t index, Node** args, Node*** rets,
200 : wasm::WasmCodePosition position);
201 :
202 : void BuildJSToWasmWrapper(Handle<Code> wasm_code, wasm::FunctionSig* sig);
203 : void BuildWasmToJSWrapper(Handle<JSReceiver> target, wasm::FunctionSig* sig);
204 : void BuildWasmInterpreterEntry(uint32_t func_index, wasm::FunctionSig* sig,
205 : Handle<WasmInstanceObject> instance);
206 :
207 : Node* ToJS(Node* node, wasm::ValueType type);
208 : Node* FromJS(Node* node, Node* context, wasm::ValueType type);
209 : Node* Invert(Node* node);
210 : void EnsureFunctionTableNodes();
211 :
212 : //-----------------------------------------------------------------------
213 : // Operations that concern the linear memory.
214 : //-----------------------------------------------------------------------
215 : Node* CurrentMemoryPages();
216 : Node* GetGlobal(uint32_t index);
217 : Node* SetGlobal(uint32_t index, Node* val);
218 : Node* LoadMem(wasm::ValueType type, MachineType memtype, Node* index,
219 : uint32_t offset, uint32_t alignment,
220 : wasm::WasmCodePosition position);
221 : Node* StoreMem(MachineType type, Node* index, uint32_t offset,
222 : uint32_t alignment, Node* val,
223 : wasm::WasmCodePosition position);
224 :
225 : static void PrintDebugName(Node* node);
226 :
227 16600 : Node* Control() { return *control_; }
228 16600 : Node* Effect() { return *effect_; }
229 :
230 743735 : void set_control_ptr(Node** control) { this->control_ = control; }
231 :
232 743735 : void set_effect_ptr(Node** effect) { this->effect_ = effect; }
233 :
234 : wasm::FunctionSig* GetFunctionSignature() { return sig_; }
235 :
236 : void Int64LoweringForTesting();
237 :
238 : void SimdScalarLoweringForTesting();
239 :
240 : void SetSourcePosition(Node* node, wasm::WasmCodePosition position);
241 :
242 : Node* S128Zero();
243 : Node* S1x4Zero();
244 : Node* S1x8Zero();
245 : Node* S1x16Zero();
246 :
247 : Node* SimdOp(wasm::WasmOpcode opcode, const NodeVector& inputs);
248 :
249 : Node* SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane,
250 : const NodeVector& inputs);
251 :
252 : Node* SimdShiftOp(wasm::WasmOpcode opcode, uint8_t shift,
253 : const NodeVector& inputs);
254 :
255 : Node* SimdConcatOp(uint8_t bytes, const NodeVector& inputs);
256 :
257 : bool has_simd() const { return has_simd_; }
258 :
259 : wasm::ModuleEnv* module_env() const { return module_; }
260 :
261 : private:
262 : static const int kDefaultBufferSize = 16;
263 : friend class WasmTrapHelper;
264 :
265 : Zone* zone_;
266 : JSGraph* jsgraph_;
267 : wasm::ModuleEnv* module_ = nullptr;
268 : Node* mem_buffer_ = nullptr;
269 : Node* mem_size_ = nullptr;
270 : NodeVector signature_tables_;
271 : NodeVector function_tables_;
272 : NodeVector function_table_sizes_;
273 : Node** control_ = nullptr;
274 : Node** effect_ = nullptr;
275 : Node** cur_buffer_;
276 : size_t cur_bufsize_;
277 : Node* def_buffer_[kDefaultBufferSize];
278 : bool has_simd_ = false;
279 :
280 : wasm::FunctionSig* sig_;
281 : SetOncePointer<const Operator> allocate_heap_number_operator_;
282 :
283 : compiler::SourcePositionTable* source_position_table_ = nullptr;
284 :
285 : // Internal helper methods.
286 : JSGraph* jsgraph() { return jsgraph_; }
287 : Graph* graph();
288 :
289 : Node* String(const char* string);
290 : Node* MemSize();
291 : Node* MemBuffer(uint32_t offset);
292 : void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset,
293 : wasm::WasmCodePosition position);
294 :
295 : Node* BuildChangeEndianness(Node* node, MachineType type,
296 : wasm::ValueType wasmtype = wasm::kWasmStmt);
297 :
298 : Node* MaskShiftCount32(Node* node);
299 : Node* MaskShiftCount64(Node* node);
300 :
301 : Node* BuildCCall(MachineSignature* sig, Node** args);
302 : Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
303 : wasm::WasmCodePosition position);
304 :
305 : Node* BuildF32CopySign(Node* left, Node* right);
306 : Node* BuildF64CopySign(Node* left, Node* right);
307 : Node* BuildI32SConvertF32(Node* input, wasm::WasmCodePosition position);
308 : Node* BuildI32SConvertF64(Node* input, wasm::WasmCodePosition position);
309 : Node* BuildI32UConvertF32(Node* input, wasm::WasmCodePosition position);
310 : Node* BuildI32UConvertF64(Node* input, wasm::WasmCodePosition position);
311 : Node* BuildI32Ctz(Node* input);
312 : Node* BuildI32Popcnt(Node* input);
313 : Node* BuildI64Ctz(Node* input);
314 : Node* BuildI64Popcnt(Node* input);
315 : Node* BuildBitCountingCall(Node* input, ExternalReference ref,
316 : MachineRepresentation input_type);
317 :
318 : Node* BuildCFuncInstruction(ExternalReference ref, MachineType type,
319 : Node* input0, Node* input1 = nullptr);
320 : Node* BuildF32Trunc(Node* input);
321 : Node* BuildF32Floor(Node* input);
322 : Node* BuildF32Ceil(Node* input);
323 : Node* BuildF32NearestInt(Node* input);
324 : Node* BuildF64Trunc(Node* input);
325 : Node* BuildF64Floor(Node* input);
326 : Node* BuildF64Ceil(Node* input);
327 : Node* BuildF64NearestInt(Node* input);
328 : Node* BuildI32Rol(Node* left, Node* right);
329 : Node* BuildI64Rol(Node* left, Node* right);
330 :
331 : Node* BuildF64Acos(Node* input);
332 : Node* BuildF64Asin(Node* input);
333 : Node* BuildF64Pow(Node* left, Node* right);
334 : Node* BuildF64Mod(Node* left, Node* right);
335 :
336 : Node* BuildIntToFloatConversionInstruction(
337 : Node* input, ExternalReference ref,
338 : MachineRepresentation parameter_representation,
339 : const MachineType result_type);
340 : Node* BuildF32SConvertI64(Node* input);
341 : Node* BuildF32UConvertI64(Node* input);
342 : Node* BuildF64SConvertI64(Node* input);
343 : Node* BuildF64UConvertI64(Node* input);
344 :
345 : Node* BuildFloatToIntConversionInstruction(
346 : Node* input, ExternalReference ref,
347 : MachineRepresentation parameter_representation,
348 : const MachineType result_type, wasm::WasmCodePosition position);
349 : Node* BuildI64SConvertF32(Node* input, wasm::WasmCodePosition position);
350 : Node* BuildI64UConvertF32(Node* input, wasm::WasmCodePosition position);
351 : Node* BuildI64SConvertF64(Node* input, wasm::WasmCodePosition position);
352 : Node* BuildI64UConvertF64(Node* input, wasm::WasmCodePosition position);
353 :
354 : Node* BuildI32DivS(Node* left, Node* right, wasm::WasmCodePosition position);
355 : Node* BuildI32RemS(Node* left, Node* right, wasm::WasmCodePosition position);
356 : Node* BuildI32DivU(Node* left, Node* right, wasm::WasmCodePosition position);
357 : Node* BuildI32RemU(Node* left, Node* right, wasm::WasmCodePosition position);
358 :
359 : Node* BuildI64DivS(Node* left, Node* right, wasm::WasmCodePosition position);
360 : Node* BuildI64RemS(Node* left, Node* right, wasm::WasmCodePosition position);
361 : Node* BuildI64DivU(Node* left, Node* right, wasm::WasmCodePosition position);
362 : Node* BuildI64RemU(Node* left, Node* right, wasm::WasmCodePosition position);
363 : Node* BuildDiv64Call(Node* left, Node* right, ExternalReference ref,
364 : MachineType result_type, int trap_zero,
365 : wasm::WasmCodePosition position);
366 :
367 : Node* BuildJavaScriptToNumber(Node* node, Node* context);
368 :
369 : Node* BuildChangeInt32ToTagged(Node* value);
370 : Node* BuildChangeFloat64ToTagged(Node* value);
371 : Node* BuildChangeTaggedToFloat64(Node* value);
372 :
373 : Node* BuildChangeInt32ToSmi(Node* value);
374 : Node* BuildChangeSmiToInt32(Node* value);
375 : Node* BuildChangeUint32ToSmi(Node* value);
376 : Node* BuildChangeSmiToFloat64(Node* value);
377 : Node* BuildTestNotSmi(Node* value);
378 : Node* BuildSmiShiftBitsConstant();
379 :
380 : Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control);
381 : Node* BuildLoadHeapNumberValue(Node* value, Node* control);
382 : Node* BuildHeapNumberValueIndexConstant();
383 :
384 : // Asm.js specific functionality.
385 : Node* BuildI32AsmjsSConvertF32(Node* input);
386 : Node* BuildI32AsmjsSConvertF64(Node* input);
387 : Node* BuildI32AsmjsUConvertF32(Node* input);
388 : Node* BuildI32AsmjsUConvertF64(Node* input);
389 : Node* BuildI32AsmjsDivS(Node* left, Node* right);
390 : Node* BuildI32AsmjsRemS(Node* left, Node* right);
391 : Node* BuildI32AsmjsDivU(Node* left, Node* right);
392 : Node* BuildI32AsmjsRemU(Node* left, Node* right);
393 : Node* BuildAsmjsLoadMem(MachineType type, Node* index);
394 : Node* BuildAsmjsStoreMem(MachineType type, Node* index, Node* val);
395 :
396 199692 : Node** Realloc(Node** buffer, size_t old_count, size_t new_count) {
397 199692 : Node** buf = Buffer(new_count);
398 199698 : if (buf != buffer) memcpy(buf, buffer, old_count * sizeof(Node*));
399 199698 : return buf;
400 : }
401 :
402 : int AddParameterNodes(Node** args, int pos, int param_count,
403 : wasm::FunctionSig* sig);
404 : };
405 : } // namespace compiler
406 : } // namespace internal
407 : } // namespace v8
408 :
409 : #endif // V8_COMPILER_WASM_COMPILER_H_
|