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 800514 : state = new_state;
41 800514 : locals = nullptr;
42 800514 : control = nullptr;
43 800514 : effect = nullptr;
44 800514 : instance_cache = {};
45 : }
46 : void SetNotMerged() {
47 42165 : 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 13264585 : : 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 502 : 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 2510630 : : ControlBase(std::forward<Args>(args)...) {}
94 : };
95 :
96 : explicit WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder)
97 1067446 : : builder_(builder) {}
98 :
99 1193305 : void StartFunction(FullDecoder* decoder) {
100 : SsaEnv* ssa_env =
101 1067540 : reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
102 : uint32_t num_locals = decoder->num_locals();
103 : uint32_t env_count = num_locals;
104 1067642 : size_t size = sizeof(TFNode*) * env_count;
105 1067642 : ssa_env->state = SsaEnv::kReached;
106 : ssa_env->locals =
107 : size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
108 1193407 : : nullptr;
109 :
110 : // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the
111 : // instance parameter.
112 : TFNode* start = builder_->Start(
113 2385359 : static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
114 1067498 : ssa_env->effect = start;
115 1067498 : 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 1067498 : builder_->set_effect_ptr(&ssa_env->effect);
119 1067498 : builder_->set_control_ptr(&ssa_env->control);
120 : // Initialize the instance parameter (index 0).
121 1067498 : 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 3702945 : for (; index < decoder->sig_->parameter_count(); ++index) {
126 250219 : ssa_env->locals[index] = builder_->Param(index + 1);
127 : }
128 1108279 : while (index < num_locals) {
129 : ValueType type = decoder->GetLocalType(index);
130 40743 : TFNode* node = DefaultValue(type);
131 1086128 : while (index < num_locals && decoder->GetLocalType(index) == type) {
132 : // Do a whole run of like-typed locals at a time.
133 501145 : ssa_env->locals[index++] = node;
134 : }
135 : }
136 : LoadContextIntoSsa(ssa_env);
137 : SetEnv(ssa_env);
138 1067507 : }
139 :
140 : // Reload the instance cache entries into the Ssa Environment.
141 : void LoadContextIntoSsa(SsaEnv* ssa_env) {
142 1108320 : if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache);
143 : }
144 :
145 : void StartFunctionBody(FullDecoder* decoder, Control* block) {}
146 :
147 1060701 : void FinishFunction(FullDecoder*) { builder_->PatchInStackCheckIfNeeded(); }
148 :
149 : void OnFirstError(FullDecoder*) {}
150 :
151 : void NextInstruction(FullDecoder*, WasmOpcode) {}
152 :
153 195416 : void Block(FullDecoder* decoder, Control* block) {
154 : // The branch environment is the outer environment.
155 97708 : block->end_env = ssa_env_;
156 195416 : SetEnv(Steal(decoder->zone(), ssa_env_));
157 97708 : }
158 :
159 21348 : void Loop(FullDecoder* decoder, Control* block) {
160 21348 : SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
161 10675 : block->end_env = finish_try_env;
162 : // The continue environment is the inner environment.
163 10675 : SetEnv(PrepareForLoop(decoder, finish_try_env));
164 10677 : ssa_env_->SetNotMerged();
165 21354 : if (!decoder->ok()) return;
166 : // Wrap input merge into phis.
167 36 : for (uint32_t i = 0; i < block->start_merge.arity; ++i) {
168 : Value& val = block->start_merge[i];
169 36 : val.node = builder_->Phi(val.type, 1, &val.node, block->end_env->control);
170 : }
171 : }
172 :
173 1510 : void Try(FullDecoder* decoder, Control* block) {
174 504 : SsaEnv* outer_env = ssa_env_;
175 504 : 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 504 : catch_env->state = SsaEnv::kUnreachable;
179 504 : SsaEnv* try_env = Steal(decoder->zone(), outer_env);
180 : SetEnv(try_env);
181 : TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env);
182 502 : block->end_env = outer_env;
183 502 : block->try_info = try_info;
184 502 : block->previous_catch = current_catch_;
185 502 : current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
186 502 : }
187 :
188 78755 : void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
189 78755 : TFNode* if_true = nullptr;
190 78755 : TFNode* if_false = nullptr;
191 157510 : BUILD(BranchNoHint, cond.node, &if_true, &if_false);
192 78760 : SsaEnv* end_env = ssa_env_;
193 157520 : SsaEnv* false_env = Split(decoder, ssa_env_);
194 78760 : false_env->control = if_false;
195 157520 : SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
196 78759 : true_env->control = if_true;
197 78759 : if_block->end_env = end_env;
198 78759 : if_block->false_env = false_env;
199 : SetEnv(true_env);
200 78759 : }
201 :
202 38274 : void FallThruTo(FullDecoder* decoder, Control* c) {
203 : DCHECK(!c->is_loop());
204 76548 : MergeValuesInto(decoder, c, &c->end_merge);
205 : }
206 :
207 242452 : void PopControl(FullDecoder* decoder, Control* block) {
208 : // A loop just continues with the end environment. There is no merge.
209 544704 : if (block->is_loop()) return;
210 : // Any other block falls through to the parent block.
211 174587 : if (block->reachable()) FallThruTo(decoder, block);
212 174591 : if (block->is_onearmed_if()) {
213 : // Merge the else branch into the end merge.
214 57397 : SetEnv(block->false_env);
215 114794 : MergeValuesInto(decoder, block, &block->end_merge);
216 : }
217 : // Now continue with the merged environment.
218 174590 : 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 377178 : 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 4058420 : auto node = BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
231 1352807 : if (result) result->node = node;
232 : }
233 :
234 : void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
235 3048088 : result->node = builder_->Int32Constant(value);
236 : }
237 :
238 : void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
239 24881 : result->node = builder_->Int64Constant(value);
240 : }
241 :
242 : void F32Const(FullDecoder* decoder, Value* result, float value) {
243 3978 : result->node = builder_->Float32Constant(value);
244 : }
245 :
246 : void F64Const(FullDecoder* decoder, Value* result, double value) {
247 11786 : result->node = builder_->Float64Constant(value);
248 : }
249 :
250 : void RefNull(FullDecoder* decoder, Value* result) {
251 45 : result->node = builder_->RefNull();
252 : }
253 :
254 : void Drop(FullDecoder* decoder, const Value& value) {}
255 :
256 1134917 : void DoReturn(FullDecoder* decoder, Vector<Value> values) {
257 1135031 : TFNode** nodes = GetNodes(values);
258 2270042 : BUILD(Return, static_cast<uint32_t>(values.size()), nodes);
259 1134985 : }
260 :
261 : void GetLocal(FullDecoder* decoder, Value* result,
262 : const LocalIndexImmediate<validate>& imm) {
263 853883 : if (!ssa_env_->locals) return; // unreachable
264 853880 : result->node = ssa_env_->locals[imm.index];
265 : }
266 :
267 : void SetLocal(FullDecoder* decoder, const Value& value,
268 : const LocalIndexImmediate<validate>& imm) {
269 512163 : if (!ssa_env_->locals) return; // unreachable
270 512167 : 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 115521 : result->node = value.node;
276 115521 : if (!ssa_env_->locals) return; // unreachable
277 115521 : ssa_env_->locals[imm.index] = value.node;
278 : }
279 :
280 : void GetGlobal(FullDecoder* decoder, Value* result,
281 : const GlobalIndexImmediate<validate>& imm) {
282 127348 : result->node = BUILD(GetGlobal, imm.index);
283 : }
284 :
285 : void SetGlobal(FullDecoder* decoder, const Value& value,
286 : const GlobalIndexImmediate<validate>& imm) {
287 45440 : BUILD(SetGlobal, imm.index, value.node);
288 : }
289 :
290 : void Unreachable(FullDecoder* decoder) {
291 5382 : BUILD(Unreachable, decoder->position());
292 : }
293 :
294 943 : void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
295 : const Value& tval, Value* result) {
296 : TFNode* controls[2];
297 1886 : BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
298 1892 : TFNode* merge = BUILD(Merge, 2, controls);
299 948 : TFNode* vals[2] = {tval.node, fval.node};
300 1896 : TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
301 948 : result->node = phi;
302 948 : ssa_env_->control = merge;
303 948 : }
304 :
305 298060 : void BrOrRet(FullDecoder* decoder, uint32_t depth) {
306 595768 : if (depth == decoder->control_depth() - 1) {
307 266 : uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count());
308 : TFNode** values =
309 : ret_count == 0 ? nullptr
310 442 : : GetNodes(decoder->stack_value(ret_count), ret_count);
311 532 : BUILD(Return, ret_count, values);
312 : } else {
313 : Br(decoder, decoder->control_at(depth));
314 : }
315 297894 : }
316 :
317 324607 : void Br(FullDecoder* decoder, Control* target) {
318 324607 : MergeValuesInto(decoder, target, target->br_merge());
319 : }
320 :
321 31488 : void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
322 31488 : SsaEnv* fenv = ssa_env_;
323 31488 : SsaEnv* tenv = Split(decoder, fenv);
324 31488 : fenv->SetNotMerged();
325 62974 : BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
326 31488 : SetEnv(tenv);
327 31488 : BrOrRet(decoder, depth);
328 31490 : SetEnv(fenv);
329 31490 : }
330 :
331 11742 : void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm,
332 : const Value& key) {
333 11742 : if (imm.table_count == 0) {
334 : // Only a default target. Do the equivalent of br.
335 12266 : uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
336 525 : BrOrRet(decoder, target);
337 12267 : return;
338 : }
339 :
340 11217 : SsaEnv* branch_env = ssa_env_;
341 : // Build branches to the various blocks based on the table.
342 22434 : TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
343 :
344 22432 : SsaEnv* copy = Steal(decoder->zone(), branch_env);
345 : SetEnv(copy);
346 11216 : BranchTableIterator<validate> iterator(decoder, imm);
347 276672 : while (iterator.has_next()) {
348 265455 : uint32_t i = iterator.cur_index();
349 265455 : uint32_t target = iterator.next();
350 265455 : SetEnv(Split(decoder, copy));
351 : ssa_env_->control =
352 530902 : (i == imm.table_count) ? BUILD(IfDefault, sw) : BUILD(IfValue, i, sw);
353 265454 : BrOrRet(decoder, target);
354 : }
355 : DCHECK(decoder->ok());
356 : SetEnv(branch_env);
357 : }
358 :
359 38489 : void Else(FullDecoder* decoder, Control* if_block) {
360 21073 : if (if_block->reachable()) {
361 : // Merge the if branch into the end merge.
362 34832 : MergeValuesInto(decoder, if_block, &if_block->end_merge);
363 : }
364 21073 : SetEnv(if_block->false_env);
365 21073 : }
366 :
367 : void LoadMem(FullDecoder* decoder, LoadType type,
368 : const MemoryAccessImmediate<validate>& imm, const Value& index,
369 : Value* result) {
370 : result->node =
371 992805 : BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
372 198560 : imm.offset, imm.alignment, decoder->position());
373 : }
374 :
375 : void StoreMem(FullDecoder* decoder, StoreType type,
376 : const MemoryAccessImmediate<validate>& imm, const Value& index,
377 : const Value& value) {
378 1547581 : BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
379 257933 : value.node, decoder->position(), type.value_type());
380 : }
381 :
382 : void CurrentMemoryPages(FullDecoder* decoder, Value* result) {
383 828 : result->node = BUILD(CurrentMemoryPages);
384 : }
385 :
386 1280 : void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) {
387 2560 : result->node = BUILD(MemoryGrow, value.node);
388 : // Always reload the instance cache after growing memory.
389 1280 : LoadContextIntoSsa(ssa_env_);
390 1280 : }
391 :
392 : void CallDirect(FullDecoder* decoder,
393 : const CallFunctionImmediate<validate>& imm,
394 : const Value args[], Value returns[]) {
395 35540 : DoCall(decoder, nullptr, imm.sig, imm.index, args, returns);
396 : }
397 :
398 : void CallIndirect(FullDecoder* decoder, const Value& index,
399 : const CallIndirectImmediate<validate>& imm,
400 : const Value args[], Value returns[]) {
401 3969 : DoCall(decoder, index.node, imm.sig, imm.sig_index, args, returns);
402 : }
403 :
404 7685 : void SimdOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
405 : Value* result) {
406 7685 : TFNode** inputs = GetNodes(args);
407 15370 : TFNode* node = BUILD(SimdOp, opcode, inputs);
408 7685 : if (result) result->node = node;
409 7685 : }
410 :
411 34880 : void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
412 : const SimdLaneImmediate<validate> imm, Vector<Value> inputs,
413 : Value* result) {
414 34880 : TFNode** nodes = GetNodes(inputs);
415 69760 : result->node = BUILD(SimdLaneOp, opcode, imm.lane, nodes);
416 34880 : }
417 :
418 : void SimdShiftOp(FullDecoder* decoder, WasmOpcode opcode,
419 : const SimdShiftImmediate<validate> imm, const Value& input,
420 : Value* result) {
421 2385 : TFNode* inputs[] = {input.node};
422 4770 : result->node = BUILD(SimdShiftOp, opcode, imm.shift, inputs);
423 : }
424 :
425 : void Simd8x16ShuffleOp(FullDecoder* decoder,
426 : const Simd8x16ShuffleImmediate<validate>& imm,
427 : const Value& input0, const Value& input1,
428 : Value* result) {
429 33780 : TFNode* input_nodes[] = {input0.node, input1.node};
430 67560 : result->node = BUILD(Simd8x16ShuffleOp, imm.shuffle, input_nodes);
431 : }
432 :
433 538 : void Throw(FullDecoder* decoder, const ExceptionIndexImmediate<validate>& imm,
434 835 : const Vector<Value>& value_args) {
435 : int count = value_args.length();
436 538 : ZoneVector<TFNode*> args(count, decoder->zone());
437 835 : for (int i = 0; i < count; ++i) {
438 594 : args[i] = value_args[i].node;
439 : }
440 1614 : BUILD(Throw, imm.index, imm.exception, VectorOf(args));
441 539 : builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
442 540 : }
443 :
444 477 : void Rethrow(FullDecoder* decoder, const Value& exception) {
445 954 : BUILD(Rethrow, exception.node);
446 477 : builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
447 477 : }
448 :
449 423 : void BrOnException(FullDecoder* decoder, const Value& exception,
450 : const ExceptionIndexImmediate<validate>& imm,
451 : uint32_t depth, Vector<Value> values) {
452 423 : TFNode* if_match = nullptr;
453 423 : TFNode* if_no_match = nullptr;
454 :
455 : // Get the exception tag and see if it matches the expected one.
456 846 : TFNode* caught_tag = BUILD(GetExceptionTag, exception.node);
457 846 : TFNode* exception_tag = BUILD(LoadExceptionTagFromTable, imm.index);
458 846 : TFNode* compare = BUILD(ExceptionTagEqual, caught_tag, exception_tag);
459 846 : BUILD(BranchNoHint, compare, &if_match, &if_no_match);
460 846 : SsaEnv* if_no_match_env = Split(decoder, ssa_env_);
461 846 : SsaEnv* if_match_env = Steal(decoder->zone(), ssa_env_);
462 423 : if_no_match_env->control = if_no_match;
463 423 : if_match_env->control = if_match;
464 :
465 : // If the tags match we extract the values from the exception object and
466 : // push them onto the operand stack using the passed {values} vector.
467 : SetEnv(if_match_env);
468 : // TODO(mstarzinger): Can't use BUILD() here, GetExceptionValues() returns
469 : // TFNode** rather than TFNode*. Fix to add landing pads.
470 : TFNode** caught_values =
471 423 : builder_->GetExceptionValues(exception.node, imm.exception);
472 702 : for (size_t i = 0, e = values.size(); i < e; ++i) {
473 558 : values[i].node = caught_values[i];
474 : }
475 423 : BrOrRet(decoder, depth);
476 :
477 : // If the tags don't match we fall-through here.
478 : SetEnv(if_no_match_env);
479 423 : }
480 :
481 : void Catch(FullDecoder* decoder, Control* block, Value* exception) {
482 : DCHECK(block->is_try_catch());
483 :
484 504 : current_catch_ = block->previous_catch; // Pop try scope.
485 :
486 : // The catch block is unreachable if no possible throws in the try block
487 : // exist. We only build a landing pad if some node in the try block can
488 : // (possibly) throw. Otherwise the catch environments remain empty.
489 504 : if (!block->try_info->might_throw()) {
490 9 : block->reachability = kSpecOnlyReachable;
491 : return;
492 : }
493 :
494 495 : SetEnv(block->try_info->catch_env);
495 : DCHECK_NOT_NULL(block->try_info->exception);
496 495 : exception->node = block->try_info->exception;
497 : }
498 :
499 33530 : void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
500 : const MemoryAccessImmediate<validate>& imm, Value* result) {
501 33543 : TFNode** inputs = GetNodes(args);
502 100619 : TFNode* node = BUILD(AtomicOp, opcode, inputs, imm.alignment, imm.offset,
503 : decoder->position());
504 33576 : if (result) result->node = node;
505 33576 : }
506 :
507 : void MemoryInit(FullDecoder* decoder,
508 : const MemoryInitImmediate<validate>& imm, const Value& dst,
509 : const Value& src, const Value& size) {
510 180 : BUILD(MemoryInit, imm.data_segment_index, dst.node, src.node, size.node,
511 45 : decoder->position());
512 : }
513 : void MemoryDrop(FullDecoder* decoder,
514 : const MemoryDropImmediate<validate>& imm) {
515 81 : BUILD(MemoryDrop, imm.index, decoder->position());
516 : }
517 : void MemoryCopy(FullDecoder* decoder,
518 : const MemoryIndexImmediate<validate>& imm, const Value& dst,
519 : const Value& src, const Value& size) {
520 81 : BUILD(MemoryCopy, dst.node, src.node, size.node, decoder->position());
521 : }
522 : void MemoryFill(FullDecoder* decoder,
523 : const MemoryIndexImmediate<validate>& imm, const Value& dst,
524 : const Value& value, const Value& size) {
525 81 : BUILD(MemoryFill, dst.node, value.node, size.node, decoder->position());
526 : }
527 : void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
528 : Vector<Value> args) {
529 36 : BUILD(TableInit, imm.table.index, imm.elem_segment_index, args[0].node,
530 9 : args[1].node, args[2].node, decoder->position());
531 : }
532 : void TableDrop(FullDecoder* decoder,
533 : const TableDropImmediate<validate>& imm) {
534 54 : BUILD(TableDrop, imm.index, decoder->position());
535 : }
536 : void TableCopy(FullDecoder* decoder, const TableIndexImmediate<validate>& imm,
537 : Vector<Value> args) {
538 288 : BUILD(TableCopy, imm.index, args[0].node, args[1].node, args[2].node,
539 72 : decoder->position());
540 : }
541 :
542 : private:
543 : SsaEnv* ssa_env_;
544 : compiler::WasmGraphBuilder* builder_;
545 : uint32_t current_catch_ = kNullCatch;
546 :
547 : TryInfo* current_try_info(FullDecoder* decoder) {
548 648 : return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
549 648 : ->try_info;
550 : }
551 :
552 1211168 : TFNode** GetNodes(Value* values, size_t count) {
553 1211168 : TFNode** nodes = builder_->Buffer(count);
554 1217860 : for (size_t i = 0; i < count; ++i) {
555 1217860 : nodes[i] = values[i].node;
556 : }
557 1211305 : return nodes;
558 : }
559 :
560 1211012 : TFNode** GetNodes(Vector<Value> values) {
561 1211012 : return GetNodes(values.start(), values.size());
562 : }
563 :
564 : void SetEnv(SsaEnv* env) {
565 : #if DEBUG
566 : if (FLAG_trace_wasm_decoder) {
567 : char state = 'X';
568 : if (env) {
569 : switch (env->state) {
570 : case SsaEnv::kReached:
571 : state = 'R';
572 : break;
573 : case SsaEnv::kUnreachable:
574 : state = 'U';
575 : break;
576 : case SsaEnv::kMerged:
577 : state = 'M';
578 : break;
579 : case SsaEnv::kControlEnd:
580 : state = 'E';
581 : break;
582 : }
583 : }
584 : PrintF("{set_env = %p, state = %c", static_cast<void*>(env), state);
585 : if (env && env->control) {
586 : PrintF(", control = ");
587 : compiler::WasmGraphBuilder::PrintDebugName(env->control);
588 : }
589 : PrintF("}\n");
590 : }
591 : #endif
592 1861063 : ssa_env_ = env;
593 : // TODO(wasm): combine the control and effect pointers with instance cache.
594 1861063 : builder_->set_control_ptr(&env->control);
595 1861063 : builder_->set_effect_ptr(&env->effect);
596 1861063 : builder_->set_instance_cache(&env->instance_cache);
597 : }
598 :
599 3705693 : TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
600 3704397 : if (node == nullptr) return nullptr;
601 :
602 3702634 : const bool inside_try_scope = current_catch_ != kNullCatch;
603 :
604 3702634 : if (!inside_try_scope) return node;
605 :
606 1187 : TFNode* if_success = nullptr;
607 1187 : TFNode* if_exception = nullptr;
608 1187 : if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
609 : return node;
610 : }
611 :
612 1296 : SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
613 648 : success_env->control = if_success;
614 :
615 648 : SsaEnv* exception_env = Split(decoder, success_env);
616 648 : exception_env->control = if_exception;
617 : TryInfo* try_info = current_try_info(decoder);
618 648 : Goto(decoder, exception_env, try_info->catch_env);
619 647 : TFNode* exception = try_info->exception;
620 647 : if (exception == nullptr) {
621 : DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
622 494 : try_info->exception = if_exception;
623 : } else {
624 : DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
625 : try_info->exception = builder_->CreateOrMergeIntoPhi(
626 : MachineRepresentation::kWord32, try_info->catch_env->control,
627 153 : try_info->exception, if_exception);
628 : }
629 :
630 : SetEnv(success_env);
631 647 : return node;
632 : }
633 :
634 40742 : TFNode* DefaultValue(ValueType type) {
635 40742 : switch (type) {
636 : case kWasmI32:
637 19552 : return builder_->Int32Constant(0);
638 : case kWasmI64:
639 14929 : return builder_->Int64Constant(0);
640 : case kWasmF32:
641 587 : return builder_->Float32Constant(0);
642 : case kWasmF64:
643 1582 : return builder_->Float64Constant(0);
644 : case kWasmS128:
645 3993 : return builder_->S128Zero();
646 : case kWasmAnyRef:
647 : case kWasmExceptRef:
648 99 : return builder_->RefNull();
649 : default:
650 0 : UNREACHABLE();
651 : }
652 : }
653 :
654 437684 : void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge) {
655 : DCHECK(merge == &c->start_merge || merge == &c->end_merge);
656 :
657 437684 : SsaEnv* target = c->end_env;
658 437684 : const bool first = target->state == SsaEnv::kUnreachable;
659 437684 : Goto(decoder, ssa_env_, target);
660 :
661 875391 : if (merge->arity == 0) return;
662 :
663 : uint32_t avail =
664 19990 : decoder->stack_size() - decoder->control_at(0)->stack_depth;
665 : DCHECK_GE(avail, merge->arity);
666 19990 : uint32_t start = avail >= merge->arity ? 0 : merge->arity - avail;
667 : Value* stack_values = decoder->stack_value(merge->arity);
668 20096 : for (uint32_t i = start; i < merge->arity; ++i) {
669 20093 : Value& val = stack_values[i];
670 : Value& old = (*merge)[i];
671 : DCHECK_NOT_NULL(val.node);
672 : DCHECK(val.type == old.type || val.type == kWasmVar);
673 : old.node = first ? val.node
674 : : builder_->CreateOrMergeIntoPhi(
675 : ValueTypes::MachineRepresentationFor(old.type),
676 20093 : target->control, old.node, val.node);
677 : }
678 : }
679 :
680 438343 : void Goto(FullDecoder* decoder, SsaEnv* from, SsaEnv* to) {
681 : DCHECK_NOT_NULL(to);
682 438343 : switch (to->state) {
683 : case SsaEnv::kUnreachable: { // Overwrite destination.
684 149802 : to->state = SsaEnv::kReached;
685 149802 : to->locals = from->locals;
686 149802 : to->control = from->control;
687 149802 : to->effect = from->effect;
688 149802 : to->instance_cache = from->instance_cache;
689 : break;
690 : }
691 : case SsaEnv::kReached: { // Create a new merge.
692 46261 : to->state = SsaEnv::kMerged;
693 : // Merge control.
694 46261 : TFNode* controls[] = {to->control, from->control};
695 46261 : TFNode* merge = builder_->Merge(2, controls);
696 46264 : to->control = merge;
697 : // Merge effects.
698 46264 : if (from->effect != to->effect) {
699 25558 : TFNode* effects[] = {to->effect, from->effect, merge};
700 25558 : to->effect = builder_->EffectPhi(2, effects, merge);
701 : }
702 : // Merge SSA values.
703 857179 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
704 810913 : TFNode* a = to->locals[i];
705 810913 : TFNode* b = from->locals[i];
706 810913 : if (a != b) {
707 71235 : TFNode* vals[] = {a, b};
708 : to->locals[i] =
709 142470 : builder_->Phi(decoder->GetLocalType(i), 2, vals, merge);
710 : }
711 : }
712 : // Start a new merge from the instance cache.
713 : builder_->NewInstanceCacheMerge(&to->instance_cache,
714 46266 : &from->instance_cache, merge);
715 : break;
716 : }
717 : case SsaEnv::kMerged: {
718 242280 : TFNode* merge = to->control;
719 : // Extend the existing merge control node.
720 242280 : builder_->AppendToMerge(merge, from->control);
721 : // Merge effects.
722 : to->effect = builder_->CreateOrMergeIntoEffectPhi(merge, to->effect,
723 242280 : from->effect);
724 : // Merge locals.
725 888061 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
726 : to->locals[i] = builder_->CreateOrMergeIntoPhi(
727 645778 : ValueTypes::MachineRepresentationFor(decoder->GetLocalType(i)),
728 1291556 : merge, to->locals[i], from->locals[i]);
729 : }
730 : // Merge the instance caches.
731 : builder_->MergeInstanceCacheInto(&to->instance_cache,
732 242283 : &from->instance_cache, merge);
733 : break;
734 : }
735 : default:
736 0 : UNREACHABLE();
737 : }
738 438348 : return from->Kill();
739 : }
740 :
741 32014 : SsaEnv* PrepareForLoop(FullDecoder* decoder, SsaEnv* env) {
742 10675 : env->state = SsaEnv::kMerged;
743 :
744 10675 : env->control = builder_->Loop(env->control);
745 10675 : env->effect = builder_->EffectPhi(1, &env->effect, env->control);
746 10676 : builder_->TerminateLoop(env->effect, env->control);
747 : // The '+ 1' here is to be able to set the instance cache as assigned.
748 : BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
749 32016 : decoder, decoder->pc(), decoder->total_locals() + 1, decoder->zone());
750 10678 : if (decoder->failed()) return env;
751 10668 : if (assigned != nullptr) {
752 : // Only introduce phis for variables assigned in this loop.
753 10668 : int instance_cache_index = decoder->total_locals();
754 215828 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
755 205161 : if (!assigned->Contains(i)) continue;
756 43095 : env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
757 86190 : &env->locals[i], env->control);
758 : }
759 : // Introduce phis for instance cache pointers if necessary.
760 10667 : if (assigned->Contains(instance_cache_index)) {
761 : builder_->PrepareInstanceCacheForLoop(&env->instance_cache,
762 4911 : env->control);
763 : }
764 :
765 10667 : SsaEnv* loop_body_env = Split(decoder, env);
766 : builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
767 21330 : &(loop_body_env->control));
768 : return loop_body_env;
769 : }
770 :
771 : // Conservatively introduce phis for all local variables.
772 0 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
773 0 : env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
774 0 : &env->locals[i], env->control);
775 : }
776 :
777 : // Conservatively introduce phis for instance cache.
778 0 : builder_->PrepareInstanceCacheForLoop(&env->instance_cache, env->control);
779 :
780 0 : SsaEnv* loop_body_env = Split(decoder, env);
781 : builder_->StackCheck(decoder->position(), &loop_body_env->effect,
782 0 : &loop_body_env->control);
783 : return loop_body_env;
784 : }
785 :
786 : // Create a complete copy of {from}.
787 771047 : SsaEnv* Split(FullDecoder* decoder, SsaEnv* from) {
788 : DCHECK_NOT_NULL(from);
789 : SsaEnv* result =
790 387939 : reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
791 387940 : size_t size = sizeof(TFNode*) * decoder->num_locals();
792 387940 : result->control = from->control;
793 387940 : result->effect = from->effect;
794 :
795 387940 : result->state = SsaEnv::kReached;
796 : result->locals =
797 : size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
798 771048 : : nullptr;
799 387944 : memcpy(result->locals, from->locals, size);
800 387944 : result->instance_cache = from->instance_cache;
801 :
802 387944 : return result;
803 : }
804 :
805 : // Create a copy of {from} that steals its state and leaves {from}
806 : // unreachable.
807 199933 : SsaEnv* Steal(Zone* zone, SsaEnv* from) {
808 : DCHECK_NOT_NULL(from);
809 199933 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
810 199931 : result->state = SsaEnv::kReached;
811 199931 : result->locals = from->locals;
812 199931 : result->control = from->control;
813 199931 : result->effect = from->effect;
814 199931 : result->instance_cache = from->instance_cache;
815 : from->Kill(SsaEnv::kUnreachable);
816 199931 : return result;
817 : }
818 :
819 : // Create an unreachable environment.
820 : SsaEnv* UnreachableEnv(Zone* zone) {
821 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
822 : result->state = SsaEnv::kUnreachable;
823 : result->control = nullptr;
824 : result->effect = nullptr;
825 : result->locals = nullptr;
826 : result->instance_cache = {};
827 : return result;
828 : }
829 :
830 79002 : void DoCall(FullDecoder* decoder, TFNode* index_node, FunctionSig* sig,
831 : uint32_t index, const Value args[], Value returns[]) {
832 39498 : int param_count = static_cast<int>(sig->parameter_count());
833 39498 : TFNode** arg_nodes = builder_->Buffer(param_count + 1);
834 39504 : TFNode** return_nodes = nullptr;
835 39504 : arg_nodes[0] = index_node;
836 142426 : for (int i = 0; i < param_count; ++i) {
837 102922 : arg_nodes[i + 1] = args[i].node;
838 : }
839 39504 : if (index_node) {
840 11904 : BUILD(CallIndirect, index, arg_nodes, &return_nodes, decoder->position());
841 : } else {
842 106604 : BUILD(CallDirect, index, arg_nodes, &return_nodes, decoder->position());
843 : }
844 39504 : int return_count = static_cast<int>(sig->return_count());
845 63202 : for (int i = 0; i < return_count; ++i) {
846 23698 : returns[i].node = return_nodes[i];
847 : }
848 : // The invoked function could have used grow_memory, so we need to
849 : // reload mem_size and mem_start.
850 39504 : LoadContextIntoSsa(ssa_env_);
851 39516 : }
852 : };
853 :
854 : } // namespace
855 :
856 1067464 : DecodeResult BuildTFGraph(AccountingAllocator* allocator,
857 : const WasmFeatures& enabled,
858 : const wasm::WasmModule* module,
859 : compiler::WasmGraphBuilder* builder,
860 : WasmFeatures* detected, const FunctionBody& body,
861 : compiler::NodeOriginTable* node_origins) {
862 1067464 : Zone zone(allocator, ZONE_NAME);
863 : WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
864 1067456 : &zone, module, enabled, detected, body, builder);
865 1067439 : if (node_origins) {
866 0 : builder->AddBytecodePositionDecorator(node_origins, &decoder);
867 : }
868 1067439 : decoder.Decode();
869 1067296 : if (node_origins) {
870 0 : builder->RemoveBytecodePositionDecorator();
871 : }
872 3202070 : return decoder.toResult(nullptr);
873 : }
874 :
875 : #undef BUILD
876 :
877 : } // namespace wasm
878 : } // namespace internal
879 183867 : } // namespace v8
|