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