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/graph-builder-interface.h"
6 :
7 : #include "src/compiler/wasm-compiler.h"
8 : #include "src/flags.h"
9 : #include "src/handles.h"
10 : #include "src/objects-inl.h"
11 : #include "src/ostreams.h"
12 : #include "src/wasm/decoder.h"
13 : #include "src/wasm/function-body-decoder-impl.h"
14 : #include "src/wasm/function-body-decoder.h"
15 : #include "src/wasm/wasm-limits.h"
16 : #include "src/wasm/wasm-linkage.h"
17 : #include "src/wasm/wasm-module.h"
18 : #include "src/wasm/wasm-opcodes.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 : namespace wasm {
23 :
24 : namespace {
25 :
26 : // An SsaEnv environment carries the current local variable renaming
27 : // as well as the current effect and control dependency in the TF graph.
28 : // It maintains a control state that tracks whether the environment
29 : // is reachable, has reached a control end, or has been merged.
30 : struct SsaEnv {
31 : enum State { kControlEnd, kUnreachable, kReached, kMerged };
32 :
33 : State state;
34 : TFNode* control;
35 : TFNode* effect;
36 : compiler::WasmInstanceCacheNodes instance_cache;
37 : TFNode** locals;
38 :
39 : void Kill(State new_state = kControlEnd) {
40 959152 : state = new_state;
41 959152 : locals = nullptr;
42 959152 : control = nullptr;
43 959152 : effect = nullptr;
44 959152 : instance_cache = {};
45 : }
46 : void SetNotMerged() {
47 140530 : if (state == kMerged) state = kReached;
48 : }
49 : };
50 :
51 : #define BUILD(func, ...) \
52 : ([&] { \
53 : DCHECK(decoder->ok()); \
54 : return CheckForException(decoder, builder_->func(__VA_ARGS__)); \
55 : })()
56 :
57 : constexpr uint32_t kNullCatch = static_cast<uint32_t>(-1);
58 :
59 : class WasmGraphBuildingInterface {
60 : public:
61 : static constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
62 : using FullDecoder = WasmFullDecoder<validate, WasmGraphBuildingInterface>;
63 :
64 : struct Value : public ValueBase {
65 : TFNode* node = nullptr;
66 :
67 : template <typename... Args>
68 : explicit Value(Args&&... args) V8_NOEXCEPT
69 5026831 : : ValueBase(std::forward<Args>(args)...) {}
70 : };
71 :
72 : struct TryInfo : public ZoneObject {
73 : SsaEnv* catch_env;
74 : TFNode* exception = nullptr;
75 :
76 : bool might_throw() const { return exception != nullptr; }
77 :
78 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TryInfo);
79 :
80 499 : explicit TryInfo(SsaEnv* c) : catch_env(c) {}
81 : };
82 :
83 : struct Control : public ControlBase<Value> {
84 : SsaEnv* end_env = nullptr; // end environment for the construct.
85 : SsaEnv* false_env = nullptr; // false environment (only for if).
86 : TryInfo* try_info = nullptr; // information about try statements.
87 : int32_t previous_catch = -1; // previous Control with a catch.
88 :
89 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Control);
90 :
91 : template <typename... Args>
92 : explicit Control(Args&&... args) V8_NOEXCEPT
93 835274 : : ControlBase(std::forward<Args>(args)...) {}
94 : };
95 :
96 : explicit WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder)
97 619247 : : builder_(builder) {}
98 :
99 619613 : void StartFunction(FullDecoder* decoder) {
100 : SsaEnv* ssa_env =
101 : reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
102 : uint32_t num_locals = decoder->num_locals();
103 : uint32_t env_count = num_locals;
104 620561 : size_t size = sizeof(TFNode*) * env_count;
105 620561 : ssa_env->state = SsaEnv::kReached;
106 : ssa_env->locals =
107 : size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
108 620561 : : nullptr;
109 :
110 : // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the
111 : // instance parameter.
112 620492 : TFNode* start = builder_->Start(
113 1240984 : static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
114 619068 : ssa_env->effect = start;
115 619068 : ssa_env->control = start;
116 : // Initialize effect and control before initializing the locals default
117 : // values (which might require instance loads) or loading the context.
118 619068 : builder_->set_effect_ptr(&ssa_env->effect);
119 619068 : builder_->set_control_ptr(&ssa_env->control);
120 : // Initialize the instance parameter (index 0).
121 619068 : builder_->set_instance_node(builder_->Param(kWasmInstanceParameterIndex));
122 : // Initialize local variables. Parameters are shifted by 1 because of the
123 : // the instance parameter.
124 : uint32_t index = 0;
125 1022337 : for (; index < decoder->sig_->parameter_count(); ++index) {
126 201235 : ssa_env->locals[index] = builder_->Param(index + 1);
127 : }
128 640902 : while (index < num_locals) {
129 : ValueType type = decoder->GetLocalType(index);
130 21210 : TFNode* node = DefaultValue(type);
131 1089670 : while (index < num_locals && decoder->GetLocalType(index) == type) {
132 : // Do a whole run of like-typed locals at a time.
133 355484 : ssa_env->locals[index++] = node;
134 : }
135 : }
136 : LoadContextIntoSsa(ssa_env);
137 : SetEnv(ssa_env);
138 619330 : }
139 :
140 : // Reload the instance cache entries into the Ssa Environment.
141 : void LoadContextIntoSsa(SsaEnv* ssa_env) {
142 765982 : if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache);
143 : }
144 :
145 : void StartFunctionBody(FullDecoder* decoder, Control* block) {}
146 :
147 608652 : void FinishFunction(FullDecoder*) { builder_->PatchInStackCheckIfNeeded(); }
148 :
149 : void OnFirstError(FullDecoder*) {}
150 :
151 : void NextInstruction(FullDecoder*, WasmOpcode) {}
152 :
153 : void Block(FullDecoder* decoder, Control* block) {
154 : // The branch environment is the outer environment.
155 167257 : block->end_env = ssa_env_;
156 167257 : SetEnv(Steal(decoder->zone(), ssa_env_));
157 : }
158 :
159 9603 : void Loop(FullDecoder* decoder, Control* block) {
160 9603 : SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
161 9600 : block->end_env = finish_try_env;
162 : // The continue environment is the inner environment.
163 9600 : SetEnv(PrepareForLoop(decoder, finish_try_env));
164 9598 : ssa_env_->SetNotMerged();
165 9598 : if (!decoder->ok()) return;
166 : // Wrap input merge into phis.
167 9661 : for (uint32_t i = 0; i < block->start_merge.arity; ++i) {
168 : Value& val = block->start_merge[i];
169 38 : val.node = builder_->Phi(val.type, 1, &val.node, block->end_env->control);
170 : }
171 : }
172 :
173 500 : void Try(FullDecoder* decoder, Control* block) {
174 500 : SsaEnv* outer_env = ssa_env_;
175 500 : SsaEnv* catch_env = Split(decoder, outer_env);
176 : // Mark catch environment as unreachable, since only accessable
177 : // through catch unwinding (i.e. landing pads).
178 499 : catch_env->state = SsaEnv::kUnreachable;
179 499 : SsaEnv* try_env = Steal(decoder->zone(), outer_env);
180 : SetEnv(try_env);
181 : TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env);
182 499 : block->end_env = outer_env;
183 499 : block->try_info = try_info;
184 499 : block->previous_catch = current_catch_;
185 499 : current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
186 499 : }
187 :
188 39149 : void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
189 39149 : TFNode* if_true = nullptr;
190 39149 : TFNode* if_false = nullptr;
191 78297 : BUILD(BranchNoHint, cond.node, &if_true, &if_false);
192 39150 : SsaEnv* end_env = ssa_env_;
193 39150 : SsaEnv* false_env = Split(decoder, ssa_env_);
194 39148 : false_env->control = if_false;
195 39148 : SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
196 39147 : true_env->control = if_true;
197 39147 : if_block->end_env = end_env;
198 39147 : if_block->false_env = false_env;
199 : SetEnv(true_env);
200 39147 : }
201 :
202 : void FallThruTo(FullDecoder* decoder, Control* c) {
203 : DCHECK(!c->is_loop());
204 32907 : MergeValuesInto(decoder, c, &c->end_merge);
205 : }
206 :
207 212482 : void PopControl(FullDecoder* decoder, Control* block) {
208 : // A loop just continues with the end environment. There is no merge.
209 212482 : if (block->is_loop()) return;
210 : // Any other block falls through to the parent block.
211 203301 : if (block->reachable()) FallThruTo(decoder, block);
212 203296 : if (block->is_onearmed_if()) {
213 : // Merge the else branch into the end merge.
214 20456 : SetEnv(block->false_env);
215 20456 : MergeValuesInto(decoder, block, &block->end_merge);
216 : }
217 : // Now continue with the merged environment.
218 203294 : SetEnv(block->end_env);
219 : }
220 :
221 : void EndControl(FullDecoder* decoder, Control* block) { ssa_env_->Kill(); }
222 :
223 : void UnOp(FullDecoder* decoder, WasmOpcode opcode, const Value& value,
224 : Value* result) {
225 902405 : result->node = BUILD(Unop, opcode, value.node, decoder->position());
226 : }
227 :
228 : void BinOp(FullDecoder* decoder, WasmOpcode opcode, const Value& lhs,
229 : const Value& rhs, Value* result) {
230 3304899 : auto node = BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
231 1101558 : if (result) result->node = node;
232 : }
233 :
234 : void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
235 1925430 : result->node = builder_->Int32Constant(value);
236 : }
237 :
238 : void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
239 42904 : result->node = builder_->Int64Constant(value);
240 : }
241 :
242 : void F32Const(FullDecoder* decoder, Value* result, float value) {
243 118495 : result->node = builder_->Float32Constant(value);
244 : }
245 :
246 : void F64Const(FullDecoder* decoder, Value* result, double value) {
247 125483 : result->node = builder_->Float64Constant(value);
248 : }
249 :
250 : void RefNull(FullDecoder* decoder, Value* result) {
251 106 : result->node = builder_->RefNull();
252 : }
253 :
254 : void Drop(FullDecoder* decoder, const Value& value) {}
255 :
256 635081 : void DoReturn(FullDecoder* decoder, Vector<Value> values) {
257 635299 : TFNode** nodes = GetNodes(values);
258 1270636 : BUILD(Return, static_cast<uint32_t>(values.size()), nodes);
259 634404 : }
260 :
261 : void GetLocal(FullDecoder* decoder, Value* result,
262 : const LocalIndexImmediate<validate>& imm) {
263 573769 : if (!ssa_env_->locals) return; // unreachable
264 573813 : result->node = ssa_env_->locals[imm.index];
265 : }
266 :
267 : void SetLocal(FullDecoder* decoder, const Value& value,
268 : const LocalIndexImmediate<validate>& imm) {
269 356821 : if (!ssa_env_->locals) return; // unreachable
270 356829 : ssa_env_->locals[imm.index] = value.node;
271 : }
272 :
273 : void TeeLocal(FullDecoder* decoder, const Value& value, Value* result,
274 : const LocalIndexImmediate<validate>& imm) {
275 98470 : result->node = value.node;
276 98470 : if (!ssa_env_->locals) return; // unreachable
277 98470 : ssa_env_->locals[imm.index] = value.node;
278 : }
279 :
280 : void GetGlobal(FullDecoder* decoder, Value* result,
281 : const GlobalIndexImmediate<validate>& imm) {
282 74154 : result->node = BUILD(GetGlobal, imm.index);
283 : }
284 :
285 : void SetGlobal(FullDecoder* decoder, const Value& value,
286 : const GlobalIndexImmediate<validate>& imm) {
287 35244 : BUILD(SetGlobal, imm.index, value.node);
288 : }
289 :
290 : void GetTable(FullDecoder* decoder, const Value& index, Value* result,
291 : const TableIndexImmediate<validate>& imm) {
292 195 : result->node = BUILD(GetTable, imm.index, index.node, decoder->position());
293 : }
294 :
295 : void SetTable(FullDecoder* decoder, const Value& index, const Value& value,
296 : const TableIndexImmediate<validate>& imm) {
297 132 : BUILD(SetTable, imm.index, index.node, value.node, decoder->position());
298 : }
299 :
300 : void Unreachable(FullDecoder* decoder) {
301 318646 : BUILD(Unreachable, decoder->position());
302 : }
303 :
304 853 : void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
305 : const Value& tval, Value* result) {
306 : TFNode* controls[2];
307 1708 : BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
308 1714 : TFNode* merge = BUILD(Merge, 2, controls);
309 859 : TFNode* vals[2] = {tval.node, fval.node};
310 1718 : TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
311 857 : result->node = phi;
312 857 : ssa_env_->control = merge;
313 857 : }
314 :
315 347282 : void BrOrRet(FullDecoder* decoder, uint32_t depth) {
316 694564 : if (depth == decoder->control_depth() - 1) {
317 255 : uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count());
318 : TFNode** values =
319 : ret_count == 0 ? nullptr
320 399 : : GetNodes(decoder->stack_value(ret_count), ret_count);
321 510 : BUILD(Return, ret_count, values);
322 : } else {
323 : Br(decoder, decoder->control_at(depth));
324 : }
325 347279 : }
326 :
327 : void Br(FullDecoder* decoder, Control* target) {
328 370070 : MergeValuesInto(decoder, target, target->br_merge());
329 : }
330 :
331 130933 : void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
332 130933 : SsaEnv* fenv = ssa_env_;
333 130933 : SsaEnv* tenv = Split(decoder, fenv);
334 130932 : fenv->SetNotMerged();
335 261866 : BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
336 130992 : SetEnv(tenv);
337 130992 : BrOrRet(decoder, depth);
338 130919 : SetEnv(fenv);
339 130919 : }
340 :
341 5316 : void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm,
342 : const Value& key) {
343 5316 : if (imm.table_count == 0) {
344 : // Only a default target. Do the equivalent of br.
345 916 : uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
346 458 : BrOrRet(decoder, target);
347 457 : return;
348 : }
349 :
350 4858 : SsaEnv* branch_env = ssa_env_;
351 : // Build branches to the various blocks based on the table.
352 9716 : TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
353 :
354 4858 : SsaEnv* copy = Steal(decoder->zone(), branch_env);
355 : SetEnv(copy);
356 4863 : BranchTableIterator<validate> iterator(decoder, imm);
357 436011 : while (iterator.has_next()) {
358 215578 : uint32_t i = iterator.cur_index();
359 215578 : uint32_t target = iterator.next();
360 215575 : SetEnv(Split(decoder, copy));
361 215571 : ssa_env_->control =
362 431140 : (i == imm.table_count) ? BUILD(IfDefault, sw) : BUILD(IfValue, i, sw);
363 215577 : BrOrRet(decoder, target);
364 : }
365 : DCHECK(decoder->ok());
366 : SetEnv(branch_env);
367 : }
368 :
369 18191 : void Else(FullDecoder* decoder, Control* if_block) {
370 18191 : if (if_block->reachable()) {
371 : // Merge the if branch into the end merge.
372 15060 : MergeValuesInto(decoder, if_block, &if_block->end_merge);
373 : }
374 18191 : SetEnv(if_block->false_env);
375 18191 : }
376 :
377 : void LoadMem(FullDecoder* decoder, LoadType type,
378 : const MemoryAccessImmediate<validate>& imm, const Value& index,
379 : Value* result) {
380 : result->node =
381 486663 : BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
382 97397 : imm.offset, imm.alignment, decoder->position());
383 : }
384 :
385 : void StoreMem(FullDecoder* decoder, StoreType type,
386 : const MemoryAccessImmediate<validate>& imm, const Value& index,
387 : const Value& value) {
388 758064 : BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
389 126354 : value.node, decoder->position(), type.value_type());
390 : }
391 :
392 : void CurrentMemoryPages(FullDecoder* decoder, Value* result) {
393 976 : result->node = BUILD(CurrentMemoryPages);
394 : }
395 :
396 1308 : void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) {
397 2616 : result->node = BUILD(MemoryGrow, value.node);
398 : // Always reload the instance cache after growing memory.
399 1307 : LoadContextIntoSsa(ssa_env_);
400 1308 : }
401 :
402 : void CallDirect(FullDecoder* decoder,
403 : const CallFunctionImmediate<validate>& imm,
404 : const Value args[], Value returns[]) {
405 141138 : DoCall(decoder, 0, nullptr, imm.sig, imm.index, args, returns);
406 : }
407 :
408 : void ReturnCall(FullDecoder* decoder,
409 : const CallFunctionImmediate<validate>& imm,
410 : const Value args[]) {
411 148 : DoReturnCall(decoder, 0, nullptr, imm.sig, imm.index, args);
412 : }
413 :
414 : void CallIndirect(FullDecoder* decoder, const Value& index,
415 : const CallIndirectImmediate<validate>& imm,
416 : const Value args[], Value returns[]) {
417 : DoCall(decoder, imm.table_index, index.node, imm.sig, imm.sig_index, args,
418 3853 : returns);
419 : }
420 :
421 : void ReturnCallIndirect(FullDecoder* decoder, const Value& index,
422 : const CallIndirectImmediate<validate>& imm,
423 : const Value args[]) {
424 : DoReturnCall(decoder, imm.table_index, index.node, imm.sig, imm.sig_index,
425 71 : args);
426 : }
427 :
428 4320 : void SimdOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
429 : Value* result) {
430 4320 : TFNode** inputs = GetNodes(args);
431 8640 : TFNode* node = BUILD(SimdOp, opcode, inputs);
432 4320 : if (result) result->node = node;
433 4320 : }
434 :
435 784 : void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
436 : const SimdLaneImmediate<validate> imm, Vector<Value> inputs,
437 : Value* result) {
438 784 : TFNode** nodes = GetNodes(inputs);
439 1568 : result->node = BUILD(SimdLaneOp, opcode, imm.lane, nodes);
440 784 : }
441 :
442 : void SimdShiftOp(FullDecoder* decoder, WasmOpcode opcode,
443 : const SimdShiftImmediate<validate> imm, const Value& input,
444 : Value* result) {
445 1272 : TFNode* inputs[] = {input.node};
446 2544 : result->node = BUILD(SimdShiftOp, opcode, imm.shift, inputs);
447 : }
448 :
449 : void Simd8x16ShuffleOp(FullDecoder* decoder,
450 : const Simd8x16ShuffleImmediate<validate>& imm,
451 : const Value& input0, const Value& input1,
452 : Value* result) {
453 14928 : TFNode* input_nodes[] = {input0.node, input1.node};
454 29856 : result->node = BUILD(Simd8x16ShuffleOp, imm.shuffle, input_nodes);
455 : }
456 :
457 548 : void Throw(FullDecoder* decoder, const ExceptionIndexImmediate<validate>& imm,
458 : const Vector<Value>& value_args) {
459 : int count = value_args.length();
460 548 : ZoneVector<TFNode*> args(count, decoder->zone());
461 1121 : for (int i = 0; i < count; ++i) {
462 572 : args[i] = value_args[i].node;
463 : }
464 1643 : BUILD(Throw, imm.index, imm.exception, VectorOf(args));
465 548 : builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
466 548 : }
467 :
468 404 : void Rethrow(FullDecoder* decoder, const Value& exception) {
469 808 : BUILD(Rethrow, exception.node);
470 406 : builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
471 407 : }
472 :
473 326 : void BrOnException(FullDecoder* decoder, const Value& exception,
474 : const ExceptionIndexImmediate<validate>& imm,
475 : uint32_t depth, Vector<Value> values) {
476 326 : TFNode* if_match = nullptr;
477 326 : TFNode* if_no_match = nullptr;
478 :
479 : // Get the exception tag and see if it matches the expected one.
480 652 : TFNode* caught_tag = BUILD(GetExceptionTag, exception.node);
481 656 : TFNode* exception_tag = BUILD(LoadExceptionTagFromTable, imm.index);
482 660 : TFNode* compare = BUILD(ExceptionTagEqual, caught_tag, exception_tag);
483 660 : BUILD(BranchNoHint, compare, &if_match, &if_no_match);
484 330 : SsaEnv* if_no_match_env = Split(decoder, ssa_env_);
485 329 : SsaEnv* if_match_env = Steal(decoder->zone(), ssa_env_);
486 328 : if_no_match_env->control = if_no_match;
487 328 : if_match_env->control = if_match;
488 :
489 : // If the tags match we extract the values from the exception object and
490 : // push them onto the operand stack using the passed {values} vector.
491 : SetEnv(if_match_env);
492 : // TODO(mstarzinger): Can't use BUILD() here, GetExceptionValues() returns
493 : // TFNode** rather than TFNode*. Fix to add landing pads.
494 : TFNode** caught_values =
495 328 : builder_->GetExceptionValues(exception.node, imm.exception);
496 744 : for (size_t i = 0, e = values.size(); i < e; ++i) {
497 208 : values[i].node = caught_values[i];
498 : }
499 328 : BrOrRet(decoder, depth);
500 :
501 : // If the tags don't match we fall-through here.
502 : SetEnv(if_no_match_env);
503 329 : }
504 :
505 : void Catch(FullDecoder* decoder, Control* block, Value* exception) {
506 : DCHECK(block->is_try_catch());
507 :
508 499 : current_catch_ = block->previous_catch; // Pop try scope.
509 :
510 : // The catch block is unreachable if no possible throws in the try block
511 : // exist. We only build a landing pad if some node in the try block can
512 : // (possibly) throw. Otherwise the catch environments remain empty.
513 499 : if (!block->try_info->might_throw()) {
514 11 : block->reachability = kSpecOnlyReachable;
515 : return;
516 : }
517 :
518 488 : SetEnv(block->try_info->catch_env);
519 : DCHECK_NOT_NULL(block->try_info->exception);
520 488 : exception->node = block->try_info->exception;
521 : }
522 :
523 24134 : void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
524 : const MemoryAccessImmediate<validate>& imm, Value* result) {
525 24220 : TFNode** inputs = GetNodes(args);
526 72644 : TFNode* node = BUILD(AtomicOp, opcode, inputs, imm.alignment, imm.offset,
527 : decoder->position());
528 24404 : if (result) result->node = node;
529 24404 : }
530 :
531 : void MemoryInit(FullDecoder* decoder,
532 : const MemoryInitImmediate<validate>& imm, const Value& dst,
533 : const Value& src, const Value& size) {
534 304 : BUILD(MemoryInit, imm.data_segment_index, dst.node, src.node, size.node,
535 76 : decoder->position());
536 : }
537 : void DataDrop(FullDecoder* decoder, const DataDropImmediate<validate>& imm) {
538 147 : BUILD(DataDrop, imm.index, decoder->position());
539 : }
540 : void MemoryCopy(FullDecoder* decoder,
541 : const MemoryCopyImmediate<validate>& imm, const Value& dst,
542 : const Value& src, const Value& size) {
543 129 : BUILD(MemoryCopy, dst.node, src.node, size.node, decoder->position());
544 : }
545 : void MemoryFill(FullDecoder* decoder,
546 : const MemoryIndexImmediate<validate>& imm, const Value& dst,
547 : const Value& value, const Value& size) {
548 129 : BUILD(MemoryFill, dst.node, value.node, size.node, decoder->position());
549 : }
550 : void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
551 : Vector<Value> args) {
552 96 : BUILD(TableInit, imm.table.index, imm.elem_segment_index, args[0].node,
553 24 : args[1].node, args[2].node, decoder->position());
554 : }
555 : void ElemDrop(FullDecoder* decoder, const ElemDropImmediate<validate>& imm) {
556 81 : BUILD(ElemDrop, imm.index, decoder->position());
557 : }
558 : void TableCopy(FullDecoder* decoder, const TableCopyImmediate<validate>& imm,
559 : Vector<Value> args) {
560 204 : BUILD(TableCopy, imm.table_src.index, imm.table_dst.index, args[0].node,
561 51 : args[1].node, args[2].node, decoder->position());
562 : }
563 :
564 : private:
565 : SsaEnv* ssa_env_;
566 : compiler::WasmGraphBuilder* builder_;
567 : uint32_t current_catch_ = kNullCatch;
568 :
569 : TryInfo* current_try_info(FullDecoder* decoder) {
570 608 : return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
571 608 : ->try_info;
572 : }
573 :
574 664411 : TFNode** GetNodes(Value* values, size_t count) {
575 664411 : TFNode** nodes = builder_->Buffer(count);
576 1791904 : for (size_t i = 0; i < count; ++i) {
577 563588 : nodes[i] = values[i].node;
578 : }
579 664728 : return nodes;
580 : }
581 :
582 : TFNode** GetNodes(Vector<Value> values) {
583 664319 : return GetNodes(values.start(), values.size());
584 : }
585 :
586 : void SetEnv(SsaEnv* env) {
587 : #if DEBUG
588 : if (FLAG_trace_wasm_decoder) {
589 : char state = 'X';
590 : if (env) {
591 : switch (env->state) {
592 : case SsaEnv::kReached:
593 : state = 'R';
594 : break;
595 : case SsaEnv::kUnreachable:
596 : state = 'U';
597 : break;
598 : case SsaEnv::kMerged:
599 : state = 'M';
600 : break;
601 : case SsaEnv::kControlEnd:
602 : state = 'E';
603 : break;
604 : }
605 : }
606 : PrintF("{set_env = %p, state = %c", static_cast<void*>(env), state);
607 : if (env && env->control) {
608 : PrintF(", control = ");
609 : compiler::WasmGraphBuilder::PrintDebugName(env->control);
610 : }
611 : PrintF("}\n");
612 : }
613 : #endif
614 1566707 : ssa_env_ = env;
615 : // TODO(wasm): combine the control and effect pointers with instance cache.
616 1566707 : builder_->set_control_ptr(&env->control);
617 1566707 : builder_->set_effect_ptr(&env->effect);
618 1566707 : builder_->set_instance_cache(&env->instance_cache);
619 : }
620 :
621 3009505 : TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
622 3009505 : if (node == nullptr) return nullptr;
623 :
624 2903352 : const bool inside_try_scope = current_catch_ != kNullCatch;
625 :
626 2903352 : if (!inside_try_scope) return node;
627 :
628 1194 : TFNode* if_success = nullptr;
629 1194 : TFNode* if_exception = nullptr;
630 1194 : if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
631 : return node;
632 : }
633 :
634 610 : SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
635 609 : success_env->control = if_success;
636 :
637 609 : SsaEnv* exception_env = Split(decoder, success_env);
638 608 : exception_env->control = if_exception;
639 : TryInfo* try_info = current_try_info(decoder);
640 608 : Goto(decoder, exception_env, try_info->catch_env);
641 610 : TFNode* exception = try_info->exception;
642 610 : if (exception == nullptr) {
643 : DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
644 489 : try_info->exception = if_exception;
645 : } else {
646 : DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
647 242 : try_info->exception = builder_->CreateOrMergeIntoPhi(
648 121 : MachineRepresentation::kWord32, try_info->catch_env->control,
649 121 : try_info->exception, if_exception);
650 : }
651 :
652 : SetEnv(success_env);
653 610 : return node;
654 : }
655 :
656 21210 : TFNode* DefaultValue(ValueType type) {
657 21210 : switch (type) {
658 : case kWasmI32:
659 10399 : return builder_->Int32Constant(0);
660 : case kWasmI64:
661 6715 : return builder_->Int64Constant(0);
662 : case kWasmF32:
663 477 : return builder_->Float32Constant(0);
664 : case kWasmF64:
665 1300 : return builder_->Float64Constant(0);
666 : case kWasmS128:
667 2178 : return builder_->S128Zero();
668 : case kWasmAnyRef:
669 : case kWasmAnyFunc:
670 : case kWasmExceptRef:
671 141 : return builder_->RefNull();
672 : default:
673 0 : UNREACHABLE();
674 : }
675 : }
676 :
677 438471 : void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge) {
678 : DCHECK(merge == &c->start_merge || merge == &c->end_merge);
679 :
680 438471 : SsaEnv* target = c->end_env;
681 438471 : const bool first = target->state == SsaEnv::kUnreachable;
682 438471 : Goto(decoder, ssa_env_, target);
683 :
684 438460 : if (merge->arity == 0) return;
685 :
686 : uint32_t avail =
687 17183 : decoder->stack_size() - decoder->control_at(0)->stack_depth;
688 : DCHECK_GE(avail, merge->arity);
689 17183 : uint32_t start = avail >= merge->arity ? 0 : merge->arity - avail;
690 : Value* stack_values = decoder->stack_value(merge->arity);
691 51745 : for (uint32_t i = start; i < merge->arity; ++i) {
692 17279 : Value& val = stack_values[i];
693 : Value& old = (*merge)[i];
694 : DCHECK_NOT_NULL(val.node);
695 : DCHECK(val.type == old.type || val.type == kWasmVar);
696 : old.node = first ? val.node
697 14070 : : builder_->CreateOrMergeIntoPhi(
698 7035 : ValueTypes::MachineRepresentationFor(old.type),
699 24314 : target->control, old.node, val.node);
700 : }
701 : }
702 :
703 439099 : void Goto(FullDecoder* decoder, SsaEnv* from, SsaEnv* to) {
704 : DCHECK_NOT_NULL(to);
705 439099 : switch (to->state) {
706 : case SsaEnv::kUnreachable: { // Overwrite destination.
707 190731 : to->state = SsaEnv::kReached;
708 190731 : to->locals = from->locals;
709 190731 : to->control = from->control;
710 190731 : to->effect = from->effect;
711 190731 : to->instance_cache = from->instance_cache;
712 : break;
713 : }
714 : case SsaEnv::kReached: { // Create a new merge.
715 34697 : to->state = SsaEnv::kMerged;
716 : // Merge control.
717 34697 : TFNode* controls[] = {to->control, from->control};
718 34697 : TFNode* merge = builder_->Merge(2, controls);
719 34694 : to->control = merge;
720 : // Merge effects.
721 34694 : if (from->effect != to->effect) {
722 22106 : TFNode* effects[] = {to->effect, from->effect, merge};
723 22106 : to->effect = builder_->EffectPhi(2, effects, merge);
724 : }
725 : // Merge SSA values.
726 720356 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
727 685661 : TFNode* a = to->locals[i];
728 685661 : TFNode* b = from->locals[i];
729 685661 : if (a != b) {
730 60534 : TFNode* vals[] = {a, b};
731 : to->locals[i] =
732 121068 : builder_->Phi(decoder->GetLocalType(i), 2, vals, merge);
733 : }
734 : }
735 : // Start a new merge from the instance cache.
736 34695 : builder_->NewInstanceCacheMerge(&to->instance_cache,
737 34695 : &from->instance_cache, merge);
738 : break;
739 : }
740 : case SsaEnv::kMerged: {
741 213671 : TFNode* merge = to->control;
742 : // Extend the existing merge control node.
743 213671 : builder_->AppendToMerge(merge, from->control);
744 : // Merge effects.
745 213671 : to->effect = builder_->CreateOrMergeIntoEffectPhi(merge, to->effect,
746 213670 : from->effect);
747 : // Merge locals.
748 772789 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
749 2236456 : to->locals[i] = builder_->CreateOrMergeIntoPhi(
750 559114 : ValueTypes::MachineRepresentationFor(decoder->GetLocalType(i)),
751 1677347 : merge, to->locals[i], from->locals[i]);
752 : }
753 : // Merge the instance caches.
754 213675 : builder_->MergeInstanceCacheInto(&to->instance_cache,
755 213675 : &from->instance_cache, merge);
756 : break;
757 : }
758 : default:
759 0 : UNREACHABLE();
760 : }
761 439098 : return from->Kill();
762 : }
763 :
764 9600 : SsaEnv* PrepareForLoop(FullDecoder* decoder, SsaEnv* env) {
765 9600 : env->state = SsaEnv::kMerged;
766 :
767 9600 : env->control = builder_->Loop(env->control);
768 9603 : env->effect = builder_->EffectPhi(1, &env->effect, env->control);
769 9604 : builder_->TerminateLoop(env->effect, env->control);
770 : // The '+ 1' here is to be able to set the instance cache as assigned.
771 9601 : BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
772 9601 : decoder, decoder->pc(), decoder->total_locals() + 1, decoder->zone());
773 9603 : if (decoder->failed()) return env;
774 9588 : if (assigned != nullptr) {
775 : // Only introduce phis for variables assigned in this loop.
776 9588 : int instance_cache_index = decoder->total_locals();
777 185655 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
778 176066 : if (!assigned->Contains(i)) continue;
779 73802 : env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
780 36902 : &env->locals[i], env->control);
781 : }
782 : // Introduce phis for instance cache pointers if necessary.
783 9589 : if (assigned->Contains(instance_cache_index)) {
784 4384 : builder_->PrepareInstanceCacheForLoop(&env->instance_cache,
785 4384 : env->control);
786 : }
787 :
788 9589 : SsaEnv* loop_body_env = Split(decoder, env);
789 19178 : builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
790 9589 : &(loop_body_env->control));
791 : return loop_body_env;
792 : }
793 :
794 : // Conservatively introduce phis for all local variables.
795 0 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
796 0 : env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
797 0 : &env->locals[i], env->control);
798 : }
799 :
800 : // Conservatively introduce phis for instance cache.
801 0 : builder_->PrepareInstanceCacheForLoop(&env->instance_cache, env->control);
802 :
803 0 : SsaEnv* loop_body_env = Split(decoder, env);
804 0 : builder_->StackCheck(decoder->position(), &loop_body_env->effect,
805 0 : &loop_body_env->control);
806 : return loop_body_env;
807 : }
808 :
809 : // Create a complete copy of {from}.
810 396669 : SsaEnv* Split(FullDecoder* decoder, SsaEnv* from) {
811 : DCHECK_NOT_NULL(from);
812 : SsaEnv* result =
813 : reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
814 396686 : size_t size = sizeof(TFNode*) * decoder->num_locals();
815 396686 : result->control = from->control;
816 396686 : result->effect = from->effect;
817 :
818 396686 : result->state = SsaEnv::kReached;
819 396686 : if (size > 0) {
820 287464 : result->locals = reinterpret_cast<TFNode**>(decoder->zone()->New(size));
821 287464 : memcpy(result->locals, from->locals, size);
822 : } else {
823 109222 : result->locals = nullptr;
824 : }
825 396686 : result->instance_cache = from->instance_cache;
826 :
827 396686 : return result;
828 : }
829 :
830 : // Create a copy of {from} that steals its state and leaves {from}
831 : // unreachable.
832 222274 : SsaEnv* Steal(Zone* zone, SsaEnv* from) {
833 : DCHECK_NOT_NULL(from);
834 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
835 222274 : result->state = SsaEnv::kReached;
836 222274 : result->locals = from->locals;
837 222274 : result->control = from->control;
838 222274 : result->effect = from->effect;
839 222274 : result->instance_cache = from->instance_cache;
840 : from->Kill(SsaEnv::kUnreachable);
841 222274 : return result;
842 : }
843 :
844 : // Create an unreachable environment.
845 : SsaEnv* UnreachableEnv(Zone* zone) {
846 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
847 : result->state = SsaEnv::kUnreachable;
848 : result->control = nullptr;
849 : result->effect = nullptr;
850 : result->locals = nullptr;
851 : result->instance_cache = {};
852 : return result;
853 : }
854 :
855 144930 : void DoCall(FullDecoder* decoder, uint32_t table_index, TFNode* index_node,
856 : FunctionSig* sig, uint32_t sig_index, const Value args[],
857 : Value returns[]) {
858 144930 : int param_count = static_cast<int>(sig->parameter_count());
859 144930 : TFNode** arg_nodes = builder_->Buffer(param_count + 1);
860 144957 : TFNode** return_nodes = nullptr;
861 144957 : arg_nodes[0] = index_node;
862 749483 : for (int i = 0; i < param_count; ++i) {
863 302263 : arg_nodes[i + 1] = args[i].node;
864 : }
865 144957 : if (index_node) {
866 15444 : BUILD(CallIndirect, table_index, sig_index, arg_nodes, &return_nodes,
867 3854 : decoder->position());
868 : } else {
869 564404 : BUILD(CallDirect, sig_index, arg_nodes, &return_nodes,
870 141103 : decoder->position());
871 : }
872 144983 : int return_count = static_cast<int>(sig->return_count());
873 397925 : for (int i = 0; i < return_count; ++i) {
874 126471 : returns[i].node = return_nodes[i];
875 : }
876 : // The invoked function could have used grow_memory, so we need to
877 : // reload mem_size and mem_start.
878 144983 : LoadContextIntoSsa(ssa_env_);
879 145075 : }
880 :
881 219 : void DoReturnCall(FullDecoder* decoder, uint32_t table_index,
882 : TFNode* index_node, FunctionSig* sig, uint32_t sig_index,
883 : const Value args[]) {
884 219 : int arg_count = static_cast<int>(sig->parameter_count());
885 219 : TFNode** arg_nodes = builder_->Buffer(arg_count + 1);
886 219 : arg_nodes[0] = index_node;
887 1185 : for (int i = 0; i < arg_count; ++i) {
888 483 : arg_nodes[i + 1] = args[i].node;
889 : }
890 219 : if (index_node) {
891 284 : BUILD(ReturnCallIndirect, table_index, sig_index, arg_nodes,
892 71 : decoder->position());
893 : } else {
894 444 : BUILD(ReturnCall, sig_index, arg_nodes, decoder->position());
895 : }
896 219 : }
897 : };
898 :
899 : } // namespace
900 :
901 619407 : DecodeResult BuildTFGraph(AccountingAllocator* allocator,
902 : const WasmFeatures& enabled, const WasmModule* module,
903 : compiler::WasmGraphBuilder* builder,
904 : WasmFeatures* detected, const FunctionBody& body,
905 : compiler::NodeOriginTable* node_origins) {
906 1237778 : Zone zone(allocator, ZONE_NAME);
907 : WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
908 : &zone, module, enabled, detected, body, builder);
909 619247 : if (node_origins) {
910 8 : builder->AddBytecodePositionDecorator(node_origins, &decoder);
911 : }
912 619247 : decoder.Decode();
913 617935 : if (node_origins) {
914 8 : builder->RemoveBytecodePositionDecorator();
915 : }
916 1855180 : return decoder.toResult(nullptr);
917 : }
918 :
919 : #undef BUILD
920 :
921 : } // namespace wasm
922 : } // namespace internal
923 122036 : } // namespace v8
|