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 967398 : state = new_state;
41 967398 : locals = nullptr;
42 967398 : control = nullptr;
43 967398 : effect = nullptr;
44 967398 : instance_cache = {};
45 : }
46 : void SetNotMerged() {
47 140477 : 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 5138902 : : 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 498 : 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 844424 : : ControlBase(std::forward<Args>(args)...) {}
94 : };
95 :
96 : explicit WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder)
97 628435 : : builder_(builder) {}
98 :
99 628867 : 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 629382 : size_t size = sizeof(TFNode*) * env_count;
105 629382 : ssa_env->state = SsaEnv::kReached;
106 : ssa_env->locals =
107 : size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
108 629382 : : nullptr;
109 :
110 : // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the
111 : // instance parameter.
112 629324 : TFNode* start = builder_->Start(
113 1258648 : static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
114 628106 : ssa_env->effect = start;
115 628106 : 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 628106 : builder_->set_effect_ptr(&ssa_env->effect);
119 628106 : builder_->set_control_ptr(&ssa_env->control);
120 : // Initialize the instance parameter (index 0).
121 628106 : 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 1102037 : for (; index < decoder->sig_->parameter_count(); ++index) {
126 236382 : ssa_env->locals[index] = builder_->Param(index + 1);
127 : }
128 650210 : while (index < num_locals) {
129 : ValueType type = decoder->GetLocalType(index);
130 21196 : TFNode* node = DefaultValue(type);
131 1088045 : while (index < num_locals && decoder->GetLocalType(index) == type) {
132 : // Do a whole run of like-typed locals at a time.
133 354958 : ssa_env->locals[index++] = node;
134 : }
135 : }
136 : LoadContextIntoSsa(ssa_env);
137 : SetEnv(ssa_env);
138 628828 : }
139 :
140 : // Reload the instance cache entries into the Ssa Environment.
141 : void LoadContextIntoSsa(SsaEnv* ssa_env) {
142 775200 : if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache);
143 : }
144 :
145 : void StartFunctionBody(FullDecoder* decoder, Control* block) {}
146 :
147 618503 : 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 167220 : block->end_env = ssa_env_;
156 167220 : SetEnv(Steal(decoder->zone(), ssa_env_));
157 : }
158 :
159 9610 : void Loop(FullDecoder* decoder, Control* block) {
160 9610 : SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
161 9611 : block->end_env = finish_try_env;
162 : // The continue environment is the inner environment.
163 9611 : SetEnv(PrepareForLoop(decoder, finish_try_env));
164 9607 : ssa_env_->SetNotMerged();
165 9607 : if (!decoder->ok()) return;
166 : // Wrap input merge into phis.
167 9670 : 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 499 : void Try(FullDecoder* decoder, Control* block) {
174 499 : SsaEnv* outer_env = ssa_env_;
175 499 : 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 498 : block->end_env = outer_env;
183 498 : block->try_info = try_info;
184 498 : block->previous_catch = current_catch_;
185 498 : current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
186 498 : }
187 :
188 39130 : void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
189 39130 : TFNode* if_true = nullptr;
190 39130 : TFNode* if_false = nullptr;
191 78255 : BUILD(BranchNoHint, cond.node, &if_true, &if_false);
192 39136 : SsaEnv* end_env = ssa_env_;
193 39136 : SsaEnv* false_env = Split(decoder, ssa_env_);
194 39136 : false_env->control = if_false;
195 39136 : SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
196 39132 : true_env->control = if_true;
197 39132 : if_block->end_env = end_env;
198 39132 : if_block->false_env = false_env;
199 : SetEnv(true_env);
200 39132 : }
201 :
202 : void FallThruTo(FullDecoder* decoder, Control* c) {
203 : DCHECK(!c->is_loop());
204 32914 : MergeValuesInto(decoder, c, &c->end_merge);
205 : }
206 :
207 212450 : void PopControl(FullDecoder* decoder, Control* block) {
208 : // A loop just continues with the end environment. There is no merge.
209 212450 : if (block->is_loop()) return;
210 : // Any other block falls through to the parent block.
211 203249 : if (block->reachable()) FallThruTo(decoder, block);
212 203239 : if (block->is_onearmed_if()) {
213 : // Merge the else branch into the end merge.
214 20451 : SetEnv(block->false_env);
215 20451 : MergeValuesInto(decoder, block, &block->end_merge);
216 : }
217 : // Now continue with the merged environment.
218 203244 : 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 950769 : 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 3354248 : auto node = BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
231 1117802 : if (result) result->node = node;
232 : }
233 :
234 : void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
235 1950100 : result->node = builder_->Int32Constant(value);
236 : }
237 :
238 : void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
239 50917 : result->node = builder_->Int64Constant(value);
240 : }
241 :
242 : void F32Const(FullDecoder* decoder, Value* result, float value) {
243 118448 : result->node = builder_->Float32Constant(value);
244 : }
245 :
246 : void F64Const(FullDecoder* decoder, Value* result, double value) {
247 125403 : result->node = builder_->Float64Constant(value);
248 : }
249 :
250 : void RefNull(FullDecoder* decoder, Value* result) {
251 110 : result->node = builder_->RefNull();
252 : }
253 :
254 : void Drop(FullDecoder* decoder, const Value& value) {}
255 :
256 644633 : void DoReturn(FullDecoder* decoder, Vector<Value> values) {
257 644769 : TFNode** nodes = GetNodes(values);
258 1289568 : BUILD(Return, static_cast<uint32_t>(values.size()), nodes);
259 644341 : }
260 :
261 : void GetLocal(FullDecoder* decoder, Value* result,
262 : const LocalIndexImmediate<validate>& imm) {
263 606971 : if (!ssa_env_->locals) return; // unreachable
264 607049 : result->node = ssa_env_->locals[imm.index];
265 : }
266 :
267 : void SetLocal(FullDecoder* decoder, const Value& value,
268 : const LocalIndexImmediate<validate>& imm) {
269 356924 : if (!ssa_env_->locals) return; // unreachable
270 356925 : 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 98464 : result->node = value.node;
276 98464 : if (!ssa_env_->locals) return; // unreachable
277 98464 : ssa_env_->locals[imm.index] = value.node;
278 : }
279 :
280 : void GetGlobal(FullDecoder* decoder, Value* result,
281 : const GlobalIndexImmediate<validate>& imm) {
282 73197 : result->node = BUILD(GetGlobal, imm.index);
283 : }
284 :
285 : void SetGlobal(FullDecoder* decoder, const Value& value,
286 : const GlobalIndexImmediate<validate>& imm) {
287 35246 : 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 318494 : BUILD(Unreachable, decoder->position());
302 : }
303 :
304 854 : void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
305 : const Value& tval, Value* result) {
306 : TFNode* controls[2];
307 1709 : BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
308 1708 : TFNode* merge = BUILD(Merge, 2, controls);
309 858 : TFNode* vals[2] = {tval.node, fval.node};
310 1717 : TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
311 857 : result->node = phi;
312 857 : ssa_env_->control = merge;
313 857 : }
314 :
315 347240 : void BrOrRet(FullDecoder* decoder, uint32_t depth) {
316 694480 : if (depth == decoder->control_depth() - 1) {
317 254 : uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count());
318 : TFNode** values =
319 : ret_count == 0 ? nullptr
320 398 : : GetNodes(decoder->stack_value(ret_count), ret_count);
321 508 : BUILD(Return, ret_count, values);
322 : } else {
323 : Br(decoder, decoder->control_at(depth));
324 : }
325 347223 : }
326 :
327 : void Br(FullDecoder* decoder, Control* target) {
328 370044 : MergeValuesInto(decoder, target, target->br_merge());
329 : }
330 :
331 130872 : void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
332 130872 : SsaEnv* fenv = ssa_env_;
333 130872 : SsaEnv* tenv = Split(decoder, fenv);
334 130870 : fenv->SetNotMerged();
335 261742 : BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
336 130930 : SetEnv(tenv);
337 130930 : BrOrRet(decoder, depth);
338 130863 : SetEnv(fenv);
339 130863 : }
340 :
341 5318 : void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm,
342 : const Value& key) {
343 5318 : if (imm.table_count == 0) {
344 : // Only a default target. Do the equivalent of br.
345 920 : uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
346 460 : BrOrRet(decoder, target);
347 461 : return;
348 : }
349 :
350 4858 : SsaEnv* branch_env = ssa_env_;
351 : // Build branches to the various blocks based on the table.
352 9717 : TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
353 :
354 4860 : SsaEnv* copy = Steal(decoder->zone(), branch_env);
355 : SetEnv(copy);
356 4861 : BranchTableIterator<validate> iterator(decoder, imm);
357 435999 : while (iterator.has_next()) {
358 215570 : uint32_t i = iterator.cur_index();
359 215570 : uint32_t target = iterator.next();
360 215572 : SetEnv(Split(decoder, copy));
361 215572 : ssa_env_->control =
362 431144 : (i == imm.table_count) ? BUILD(IfDefault, sw) : BUILD(IfValue, i, sw);
363 215571 : BrOrRet(decoder, target);
364 : }
365 : DCHECK(decoder->ok());
366 : SetEnv(branch_env);
367 : }
368 :
369 18188 : void Else(FullDecoder* decoder, Control* if_block) {
370 18188 : if (if_block->reachable()) {
371 : // Merge the if branch into the end merge.
372 15055 : MergeValuesInto(decoder, if_block, &if_block->end_merge);
373 : }
374 18188 : SetEnv(if_block->false_env);
375 18188 : }
376 :
377 : void LoadMem(FullDecoder* decoder, LoadType type,
378 : const MemoryAccessImmediate<validate>& imm, const Value& index,
379 : Value* result) {
380 : result->node =
381 486283 : BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
382 97353 : 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 859271 : BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
389 143241 : value.node, decoder->position(), type.value_type());
390 : }
391 :
392 : void CurrentMemoryPages(FullDecoder* decoder, Value* result) {
393 982 : result->node = BUILD(CurrentMemoryPages);
394 : }
395 :
396 1307 : void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) {
397 2614 : result->node = BUILD(MemoryGrow, value.node);
398 : // Always reload the instance cache after growing memory.
399 1306 : LoadContextIntoSsa(ssa_env_);
400 1309 : }
401 :
402 : void CallDirect(FullDecoder* decoder,
403 : const CallFunctionImmediate<validate>& imm,
404 : const Value args[], Value returns[]) {
405 141083 : 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 147 : 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 3871 : 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 14448 : TFNode* input_nodes[] = {input0.node, input1.node};
454 28896 : result->node = BUILD(Simd8x16ShuffleOp, imm.shuffle, input_nodes);
455 : }
456 :
457 551 : void Throw(FullDecoder* decoder, const ExceptionIndexImmediate<validate>& imm,
458 : const Vector<Value>& value_args) {
459 : int count = value_args.length();
460 551 : ZoneVector<TFNode*> args(count, decoder->zone());
461 1124 : for (int i = 0; i < count; ++i) {
462 572 : args[i] = value_args[i].node;
463 : }
464 1656 : BUILD(Throw, imm.index, imm.exception, VectorOf(args));
465 551 : builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
466 552 : }
467 :
468 405 : void Rethrow(FullDecoder* decoder, const Value& exception) {
469 810 : BUILD(Rethrow, exception.node);
470 406 : builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
471 407 : }
472 :
473 328 : void BrOnException(FullDecoder* decoder, const Value& exception,
474 : const ExceptionIndexImmediate<validate>& imm,
475 : uint32_t depth, Vector<Value> values) {
476 328 : TFNode* if_match = nullptr;
477 328 : TFNode* if_no_match = nullptr;
478 :
479 : // Get the exception tag and see if it matches the expected one.
480 656 : TFNode* caught_tag = BUILD(GetExceptionTag, exception.node);
481 660 : TFNode* exception_tag = BUILD(LoadExceptionTagFromTable, imm.index);
482 660 : TFNode* compare = BUILD(ExceptionTagEqual, caught_tag, exception_tag);
483 656 : 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 329 : if_no_match_env->control = if_no_match;
487 329 : 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 329 : builder_->GetExceptionValues(exception.node, imm.exception);
496 748 : for (size_t i = 0, e = values.size(); i < e; ++i) {
497 209 : values[i].node = caught_values[i];
498 : }
499 330 : BrOrRet(decoder, depth);
500 :
501 : // If the tags don't match we fall-through here.
502 : SetEnv(if_no_match_env);
503 330 : }
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 32506 : void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
524 : const MemoryAccessImmediate<validate>& imm, Value* result) {
525 32645 : TFNode** inputs = GetNodes(args);
526 97885 : TFNode* node = BUILD(AtomicOp, opcode, inputs, imm.alignment, imm.offset,
527 : decoder->position());
528 32955 : if (result) result->node = node;
529 32955 : }
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 610 : return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
571 610 : ->try_info;
572 : }
573 :
574 682341 : TFNode** GetNodes(Value* values, size_t count) {
575 682341 : TFNode** nodes = builder_->Buffer(count);
576 1841956 : for (size_t i = 0; i < count; ++i) {
577 579677 : nodes[i] = values[i].node;
578 : }
579 682602 : return nodes;
580 : }
581 :
582 : TFNode** GetNodes(Vector<Value> values) {
583 682243 : 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 1575983 : ssa_env_ = env;
615 : // TODO(wasm): combine the control and effect pointers with instance cache.
616 1575983 : builder_->set_control_ptr(&env->control);
617 1575983 : builder_->set_effect_ptr(&env->effect);
618 1575983 : builder_->set_instance_cache(&env->instance_cache);
619 : }
620 :
621 3075979 : TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
622 3075979 : if (node == nullptr) return nullptr;
623 :
624 2969899 : const bool inside_try_scope = current_catch_ != kNullCatch;
625 :
626 2969899 : 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 610 : success_env->control = if_success;
636 :
637 610 : SsaEnv* exception_env = Split(decoder, success_env);
638 610 : exception_env->control = if_exception;
639 : TryInfo* try_info = current_try_info(decoder);
640 610 : 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 21194 : TFNode* DefaultValue(ValueType type) {
657 21194 : switch (type) {
658 : case kWasmI32:
659 10387 : return builder_->Int32Constant(0);
660 : case kWasmI64:
661 6712 : return builder_->Int64Constant(0);
662 : case kWasmF32:
663 476 : return builder_->Float32Constant(0);
664 : case kWasmF64:
665 1300 : return builder_->Float64Constant(0);
666 : case kWasmS128:
667 2177 : return builder_->S128Zero();
668 : case kWasmAnyRef:
669 : case kWasmAnyFunc:
670 : case kWasmExceptRef:
671 142 : return builder_->RefNull();
672 : default:
673 0 : UNREACHABLE();
674 : }
675 : }
676 :
677 438430 : void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge) {
678 : DCHECK(merge == &c->start_merge || merge == &c->end_merge);
679 :
680 438430 : SsaEnv* target = c->end_env;
681 438430 : const bool first = target->state == SsaEnv::kUnreachable;
682 438430 : Goto(decoder, ssa_env_, target);
683 :
684 438430 : if (merge->arity == 0) return;
685 :
686 : uint32_t avail =
687 17174 : decoder->stack_size() - decoder->control_at(0)->stack_depth;
688 : DCHECK_GE(avail, merge->arity);
689 17174 : uint32_t start = avail >= merge->arity ? 0 : merge->arity - avail;
690 : Value* stack_values = decoder->stack_value(merge->arity);
691 51724 : for (uint32_t i = start; i < merge->arity; ++i) {
692 17271 : 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 14072 : : builder_->CreateOrMergeIntoPhi(
698 7036 : ValueTypes::MachineRepresentationFor(old.type),
699 24307 : target->control, old.node, val.node);
700 : }
701 : }
702 :
703 439058 : void Goto(FullDecoder* decoder, SsaEnv* from, SsaEnv* to) {
704 : DCHECK_NOT_NULL(to);
705 439058 : switch (to->state) {
706 : case SsaEnv::kUnreachable: { // Overwrite destination.
707 190666 : to->state = SsaEnv::kReached;
708 190666 : to->locals = from->locals;
709 190666 : to->control = from->control;
710 190666 : to->effect = from->effect;
711 190666 : to->instance_cache = from->instance_cache;
712 : break;
713 : }
714 : case SsaEnv::kReached: { // Create a new merge.
715 34692 : to->state = SsaEnv::kMerged;
716 : // Merge control.
717 34692 : TFNode* controls[] = {to->control, from->control};
718 34692 : TFNode* merge = builder_->Merge(2, controls);
719 34697 : to->control = merge;
720 : // Merge effects.
721 34697 : if (from->effect != to->effect) {
722 22105 : TFNode* effects[] = {to->effect, from->effect, merge};
723 22105 : to->effect = builder_->EffectPhi(2, effects, merge);
724 : }
725 : // Merge SSA values.
726 720360 : 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 60532 : TFNode* vals[] = {a, b};
731 : to->locals[i] =
732 121064 : builder_->Phi(decoder->GetLocalType(i), 2, vals, merge);
733 : }
734 : }
735 : // Start a new merge from the instance cache.
736 34699 : builder_->NewInstanceCacheMerge(&to->instance_cache,
737 34699 : &from->instance_cache, merge);
738 : break;
739 : }
740 : case SsaEnv::kMerged: {
741 213700 : TFNode* merge = to->control;
742 : // Extend the existing merge control node.
743 213700 : builder_->AppendToMerge(merge, from->control);
744 : // Merge effects.
745 213698 : to->effect = builder_->CreateOrMergeIntoEffectPhi(merge, to->effect,
746 213702 : from->effect);
747 : // Merge locals.
748 772833 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
749 2236528 : to->locals[i] = builder_->CreateOrMergeIntoPhi(
750 559132 : ValueTypes::MachineRepresentationFor(decoder->GetLocalType(i)),
751 1677395 : merge, to->locals[i], from->locals[i]);
752 : }
753 : // Merge the instance caches.
754 213701 : builder_->MergeInstanceCacheInto(&to->instance_cache,
755 213701 : &from->instance_cache, merge);
756 : break;
757 : }
758 : default:
759 0 : UNREACHABLE();
760 : }
761 439062 : return from->Kill();
762 : }
763 :
764 9611 : SsaEnv* PrepareForLoop(FullDecoder* decoder, SsaEnv* env) {
765 9611 : env->state = SsaEnv::kMerged;
766 :
767 9611 : env->control = builder_->Loop(env->control);
768 9611 : env->effect = builder_->EffectPhi(1, &env->effect, env->control);
769 9613 : builder_->TerminateLoop(env->effect, env->control);
770 : // The '+ 1' here is to be able to set the instance cache as assigned.
771 9609 : BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
772 9609 : decoder, decoder->pc(), decoder->total_locals() + 1, decoder->zone());
773 9611 : if (decoder->failed()) return env;
774 9595 : if (assigned != nullptr) {
775 : // Only introduce phis for variables assigned in this loop.
776 9595 : int instance_cache_index = decoder->total_locals();
777 185670 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
778 176074 : if (!assigned->Contains(i)) continue;
779 73812 : env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
780 36907 : &env->locals[i], env->control);
781 : }
782 : // Introduce phis for instance cache pointers if necessary.
783 9596 : if (assigned->Contains(instance_cache_index)) {
784 4381 : builder_->PrepareInstanceCacheForLoop(&env->instance_cache,
785 4381 : env->control);
786 : }
787 :
788 9597 : SsaEnv* loop_body_env = Split(decoder, env);
789 19196 : builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
790 9598 : &(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 396603 : SsaEnv* Split(FullDecoder* decoder, SsaEnv* from) {
811 : DCHECK_NOT_NULL(from);
812 : SsaEnv* result =
813 : reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
814 396614 : size_t size = sizeof(TFNode*) * decoder->num_locals();
815 396614 : result->control = from->control;
816 396614 : result->effect = from->effect;
817 :
818 396614 : result->state = SsaEnv::kReached;
819 396614 : if (size > 0) {
820 287474 : result->locals = reinterpret_cast<TFNode**>(decoder->zone()->New(size));
821 287473 : memcpy(result->locals, from->locals, size);
822 : } else {
823 109140 : result->locals = nullptr;
824 : }
825 396613 : result->instance_cache = from->instance_cache;
826 :
827 396613 : return result;
828 : }
829 :
830 : // Create a copy of {from} that steals its state and leaves {from}
831 : // unreachable.
832 222241 : SsaEnv* Steal(Zone* zone, SsaEnv* from) {
833 : DCHECK_NOT_NULL(from);
834 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
835 222241 : result->state = SsaEnv::kReached;
836 222241 : result->locals = from->locals;
837 222241 : result->control = from->control;
838 222241 : result->effect = from->effect;
839 222241 : result->instance_cache = from->instance_cache;
840 : from->Kill(SsaEnv::kUnreachable);
841 222241 : 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 144870 : 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 144870 : int param_count = static_cast<int>(sig->parameter_count());
859 144870 : TFNode** arg_nodes = builder_->Buffer(param_count + 1);
860 144890 : TFNode** return_nodes = nullptr;
861 144890 : arg_nodes[0] = index_node;
862 749096 : for (int i = 0; i < param_count; ++i) {
863 302103 : arg_nodes[i + 1] = args[i].node;
864 : }
865 144890 : if (index_node) {
866 15517 : BUILD(CallIndirect, table_index, sig_index, arg_nodes, &return_nodes,
867 3870 : decoder->position());
868 : } else {
869 564023 : BUILD(CallDirect, sig_index, arg_nodes, &return_nodes,
870 141020 : decoder->position());
871 : }
872 144880 : int return_count = static_cast<int>(sig->return_count());
873 397542 : for (int i = 0; i < return_count; ++i) {
874 126331 : 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 144880 : LoadContextIntoSsa(ssa_env_);
879 144991 : }
880 :
881 218 : void DoReturnCall(FullDecoder* decoder, uint32_t table_index,
882 : TFNode* index_node, FunctionSig* sig, uint32_t sig_index,
883 : const Value args[]) {
884 218 : int arg_count = static_cast<int>(sig->parameter_count());
885 218 : TFNode** arg_nodes = builder_->Buffer(arg_count + 1);
886 218 : arg_nodes[0] = index_node;
887 1180 : for (int i = 0; i < arg_count; ++i) {
888 481 : arg_nodes[i + 1] = args[i].node;
889 : }
890 218 : if (index_node) {
891 284 : BUILD(ReturnCallIndirect, table_index, sig_index, arg_nodes,
892 71 : decoder->position());
893 : } else {
894 443 : BUILD(ReturnCall, sig_index, arg_nodes, decoder->position());
895 : }
896 218 : }
897 : };
898 :
899 : } // namespace
900 :
901 628730 : 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 1256351 : Zone zone(allocator, ZONE_NAME);
907 : WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
908 : &zone, module, enabled, detected, body, builder);
909 628435 : if (node_origins) {
910 8 : builder->AddBytecodePositionDecorator(node_origins, &decoder);
911 : }
912 628435 : decoder.Decode();
913 627534 : if (node_origins) {
914 8 : builder->RemoveBytecodePositionDecorator();
915 : }
916 1883613 : return decoder.toResult(nullptr);
917 : }
918 :
919 : #undef BUILD
920 :
921 : } // namespace wasm
922 : } // namespace internal
923 122004 : } // namespace v8
|