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 595359 : state = new_state;
41 595359 : locals = nullptr;
42 595359 : control = nullptr;
43 595359 : effect = nullptr;
44 595359 : instance_cache = {};
45 : }
46 : void SetNotMerged() {
47 35532 : 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 7634592 : : 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 520 : 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 1258036 : : ControlBase(std::forward<Args>(args)...) {}
94 : };
95 :
96 : explicit WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder)
97 503594 : : builder_(builder) {}
98 :
99 590934 : void StartFunction(FullDecoder* decoder) {
100 : SsaEnv* ssa_env =
101 503707 : reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
102 : uint32_t num_locals = decoder->num_locals();
103 : uint32_t env_count = num_locals;
104 503730 : size_t size = sizeof(TFNode*) * env_count;
105 503730 : ssa_env->state = SsaEnv::kReached;
106 : ssa_env->locals =
107 : size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
108 590957 : : 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 1201680 : static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
114 503651 : ssa_env->effect = start;
115 503651 : 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 503651 : builder_->set_effect_ptr(&ssa_env->effect);
119 503651 : builder_->set_control_ptr(&ssa_env->control);
120 : // Initialize the instance parameter (index 0).
121 503651 : 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 1899551 : for (; index < decoder->sig_->parameter_count(); ++index) {
126 194264 : ssa_env->locals[index] = builder_->Param(index + 1);
127 : }
128 524164 : while (index < num_locals) {
129 : ValueType type = decoder->GetLocalType(index);
130 20465 : TFNode* node = DefaultValue(type);
131 740962 : while (index < num_locals && decoder->GetLocalType(index) == type) {
132 : // Do a whole run of like-typed locals at a time.
133 349042 : ssa_env->locals[index++] = node;
134 : }
135 : }
136 : LoadContextIntoSsa(ssa_env);
137 : SetEnv(ssa_env);
138 503711 : }
139 :
140 : // Reload the instance cache entries into the Ssa Environment.
141 : void LoadContextIntoSsa(SsaEnv* ssa_env) {
142 537232 : if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache);
143 : }
144 :
145 : void StartFunctionBody(FullDecoder* decoder, Control* block) {}
146 :
147 496947 : void FinishFunction(FullDecoder*) { builder_->PatchInStackCheckIfNeeded(); }
148 :
149 : void OnFirstError(FullDecoder*) {}
150 :
151 : void NextInstruction(FullDecoder*, WasmOpcode) {}
152 :
153 118832 : void Block(FullDecoder* decoder, Control* block) {
154 : // The branch environment is the outer environment.
155 59416 : block->end_env = ssa_env_;
156 118832 : SetEnv(Steal(decoder->zone(), ssa_env_));
157 59415 : }
158 :
159 18180 : void Loop(FullDecoder* decoder, Control* block) {
160 18180 : SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
161 9090 : block->end_env = finish_try_env;
162 : // The continue environment is the inner environment.
163 9090 : SetEnv(PrepareForLoop(decoder, finish_try_env));
164 9089 : ssa_env_->SetNotMerged();
165 18178 : if (!decoder->ok()) return;
166 : // Wrap input merge into phis.
167 32 : for (uint32_t i = 0; i < block->start_merge.arity; ++i) {
168 : Value& val = block->start_merge[i];
169 32 : val.node = builder_->Phi(val.type, 1, &val.node, block->end_env->control);
170 : }
171 : }
172 :
173 1559 : void Try(FullDecoder* decoder, Control* block) {
174 519 : SsaEnv* outer_env = ssa_env_;
175 519 : 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 520 : catch_env->state = SsaEnv::kUnreachable;
179 520 : SsaEnv* try_env = Steal(decoder->zone(), outer_env);
180 : SetEnv(try_env);
181 : TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env);
182 520 : block->end_env = outer_env;
183 520 : block->try_info = try_info;
184 520 : block->previous_catch = current_catch_;
185 520 : current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
186 520 : }
187 :
188 56244 : void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
189 56244 : TFNode* if_true = nullptr;
190 56244 : TFNode* if_false = nullptr;
191 112488 : BUILD(BranchNoHint, cond.node, &if_true, &if_false);
192 56249 : SsaEnv* end_env = ssa_env_;
193 112493 : SsaEnv* false_env = Split(decoder, ssa_env_);
194 56244 : false_env->control = if_false;
195 112488 : SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
196 56245 : true_env->control = if_true;
197 56245 : if_block->end_env = end_env;
198 56245 : if_block->false_env = false_env;
199 : SetEnv(true_env);
200 56245 : }
201 :
202 32563 : void FallThruTo(FullDecoder* decoder, Control* c) {
203 : DCHECK(!c->is_loop());
204 65126 : MergeValuesInto(decoder, c, &c->end_merge);
205 : }
206 :
207 160719 : void PopControl(FullDecoder* decoder, Control* block) {
208 : // A loop just continues with the end environment. There is no merge.
209 358973 : if (block->is_loop()) return;
210 : // Any other block falls through to the parent block.
211 113753 : if (block->reachable()) FallThruTo(decoder, block);
212 113751 : if (block->is_onearmed_if()) {
213 : // Merge the else branch into the end merge.
214 38107 : SetEnv(block->false_env);
215 76214 : MergeValuesInto(decoder, block, &block->end_merge);
216 : }
217 : // Now continue with the merged environment.
218 113751 : 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 326410 : 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 2253465 : auto node = BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
231 751122 : if (result) result->node = node;
232 : }
233 :
234 : void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
235 1642277 : result->node = builder_->Int32Constant(value);
236 : }
237 :
238 : void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
239 20701 : result->node = builder_->Int64Constant(value);
240 : }
241 :
242 : void F32Const(FullDecoder* decoder, Value* result, float value) {
243 3203 : result->node = builder_->Float32Constant(value);
244 : }
245 :
246 : void F64Const(FullDecoder* decoder, Value* result, double value) {
247 9170 : result->node = builder_->Float64Constant(value);
248 : }
249 :
250 : void RefNull(FullDecoder* decoder, Value* result) {
251 80 : result->node = builder_->RefNull();
252 : }
253 :
254 : void Drop(FullDecoder* decoder, const Value& value) {}
255 :
256 540814 : void DoReturn(FullDecoder* decoder, Vector<Value> values) {
257 540894 : TFNode** nodes = GetNodes(values);
258 1081789 : BUILD(Return, static_cast<uint32_t>(values.size()), nodes);
259 540848 : }
260 :
261 : void GetLocal(FullDecoder* decoder, Value* result,
262 : const LocalIndexImmediate<validate>& imm) {
263 600067 : if (!ssa_env_->locals) return; // unreachable
264 600082 : result->node = ssa_env_->locals[imm.index];
265 : }
266 :
267 : void SetLocal(FullDecoder* decoder, const Value& value,
268 : const LocalIndexImmediate<validate>& imm) {
269 357212 : if (!ssa_env_->locals) return; // unreachable
270 357213 : 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 98399 : result->node = value.node;
276 98399 : if (!ssa_env_->locals) return; // unreachable
277 98399 : ssa_env_->locals[imm.index] = value.node;
278 : }
279 :
280 : void GetGlobal(FullDecoder* decoder, Value* result,
281 : const GlobalIndexImmediate<validate>& imm) {
282 72497 : result->node = BUILD(GetGlobal, imm.index);
283 : }
284 :
285 : void SetGlobal(FullDecoder* decoder, const Value& value,
286 : const GlobalIndexImmediate<validate>& imm) {
287 30892 : BUILD(SetGlobal, imm.index, value.node);
288 : }
289 :
290 : void GetTable(FullDecoder* decoder, const Value& index, Value* result,
291 : const TableIndexImmediate<validate>& imm) {
292 0 : 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 0 : BUILD(SetTable, imm.index, index.node, value.node, decoder->position());
298 : }
299 :
300 : void Unreachable(FullDecoder* decoder) {
301 4623 : BUILD(Unreachable, decoder->position());
302 : }
303 :
304 818 : void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
305 : const Value& tval, Value* result) {
306 : TFNode* controls[2];
307 1636 : BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
308 1640 : TFNode* merge = BUILD(Merge, 2, controls);
309 820 : TFNode* vals[2] = {tval.node, fval.node};
310 1640 : TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
311 819 : result->node = phi;
312 819 : ssa_env_->control = merge;
313 819 : }
314 :
315 242922 : void BrOrRet(FullDecoder* decoder, uint32_t depth) {
316 485580 : if (depth == decoder->control_depth() - 1) {
317 212 : uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count());
318 : TFNode** values =
319 : ret_count == 0 ? nullptr
320 344 : : GetNodes(decoder->stack_value(ret_count), ret_count);
321 424 : BUILD(Return, ret_count, values);
322 : } else {
323 : Br(decoder, decoder->control_at(depth));
324 : }
325 242796 : }
326 :
327 265316 : void Br(FullDecoder* decoder, Control* target) {
328 265316 : MergeValuesInto(decoder, target, target->br_merge());
329 : }
330 :
331 26443 : void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
332 26443 : SsaEnv* fenv = ssa_env_;
333 26443 : SsaEnv* tenv = Split(decoder, fenv);
334 26443 : fenv->SetNotMerged();
335 52886 : BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
336 26443 : SetEnv(tenv);
337 26443 : BrOrRet(decoder, depth);
338 26443 : SetEnv(fenv);
339 26443 : }
340 :
341 5303 : void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm,
342 : const Value& key) {
343 5303 : if (imm.table_count == 0) {
344 : // Only a default target. Do the equivalent of br.
345 5754 : uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
346 451 : BrOrRet(decoder, target);
347 5754 : return;
348 : }
349 :
350 4852 : SsaEnv* branch_env = ssa_env_;
351 : // Build branches to the various blocks based on the table.
352 9704 : TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
353 :
354 9704 : SsaEnv* copy = Steal(decoder->zone(), branch_env);
355 : SetEnv(copy);
356 4853 : BranchTableIterator<validate> iterator(decoder, imm);
357 220378 : while (iterator.has_next()) {
358 215526 : uint32_t i = iterator.cur_index();
359 215526 : uint32_t target = iterator.next();
360 215526 : SetEnv(Split(decoder, copy));
361 : ssa_env_->control =
362 431048 : (i == imm.table_count) ? BUILD(IfDefault, sw) : BUILD(IfValue, i, sw);
363 215525 : BrOrRet(decoder, target);
364 : }
365 : DCHECK(decoder->ok());
366 : SetEnv(branch_env);
367 : }
368 :
369 32569 : void Else(FullDecoder* decoder, Control* if_block) {
370 17834 : if (if_block->reachable()) {
371 : // Merge the if branch into the end merge.
372 29470 : MergeValuesInto(decoder, if_block, &if_block->end_merge);
373 : }
374 17834 : SetEnv(if_block->false_env);
375 17834 : }
376 :
377 : void LoadMem(FullDecoder* decoder, LoadType type,
378 : const MemoryAccessImmediate<validate>& imm, const Value& index,
379 : Value* result) {
380 : result->node =
381 471320 : BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
382 94262 : 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 864904 : BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
389 144163 : value.node, decoder->position(), type.value_type());
390 : }
391 :
392 : void CurrentMemoryPages(FullDecoder* decoder, Value* result) {
393 736 : result->node = BUILD(CurrentMemoryPages);
394 : }
395 :
396 1120 : void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) {
397 2240 : result->node = BUILD(MemoryGrow, value.node);
398 : // Always reload the instance cache after growing memory.
399 1120 : LoadContextIntoSsa(ssa_env_);
400 1120 : }
401 :
402 : void CallDirect(FullDecoder* decoder,
403 : const CallFunctionImmediate<validate>& imm,
404 : const Value args[], Value returns[]) {
405 29126 : DoCall(decoder, nullptr, imm.sig, imm.index, args, returns);
406 : }
407 :
408 0 : void ReturnCall(FullDecoder* decoder,
409 : const CallFunctionImmediate<validate>& imm,
410 : const Value args[]) {
411 0 : UNIMPLEMENTED();
412 : }
413 :
414 : void CallIndirect(FullDecoder* decoder, const Value& index,
415 : const CallIndirectImmediate<validate>& imm,
416 : const Value args[], Value returns[]) {
417 3285 : DoCall(decoder, index.node, imm.sig, imm.sig_index, args, returns);
418 : }
419 :
420 0 : void ReturnCallIndirect(FullDecoder* decoder, const Value& index,
421 : const CallIndirectImmediate<validate>& imm,
422 : const Value args[]) {
423 0 : UNIMPLEMENTED();
424 : }
425 :
426 4164 : void SimdOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
427 : Value* result) {
428 4164 : TFNode** inputs = GetNodes(args);
429 8328 : TFNode* node = BUILD(SimdOp, opcode, inputs);
430 4164 : if (result) result->node = node;
431 4164 : }
432 :
433 18676 : void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
434 : const SimdLaneImmediate<validate> imm, Vector<Value> inputs,
435 : Value* result) {
436 18676 : TFNode** nodes = GetNodes(inputs);
437 37352 : result->node = BUILD(SimdLaneOp, opcode, imm.lane, nodes);
438 18676 : }
439 :
440 : void SimdShiftOp(FullDecoder* decoder, WasmOpcode opcode,
441 : const SimdShiftImmediate<validate> imm, const Value& input,
442 : Value* result) {
443 1272 : TFNode* inputs[] = {input.node};
444 2544 : result->node = BUILD(SimdShiftOp, opcode, imm.shift, inputs);
445 : }
446 :
447 : void Simd8x16ShuffleOp(FullDecoder* decoder,
448 : const Simd8x16ShuffleImmediate<validate>& imm,
449 : const Value& input0, const Value& input1,
450 : Value* result) {
451 14544 : TFNode* input_nodes[] = {input0.node, input1.node};
452 29088 : result->node = BUILD(Simd8x16ShuffleOp, imm.shuffle, input_nodes);
453 : }
454 :
455 502 : void Throw(FullDecoder* decoder, const ExceptionIndexImmediate<validate>& imm,
456 766 : const Vector<Value>& value_args) {
457 : int count = value_args.length();
458 502 : ZoneVector<TFNode*> args(count, decoder->zone());
459 768 : for (int i = 0; i < count; ++i) {
460 528 : args[i] = value_args[i].node;
461 : }
462 1512 : BUILD(Throw, imm.index, imm.exception, VectorOf(args));
463 504 : builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
464 503 : }
465 :
466 423 : void Rethrow(FullDecoder* decoder, const Value& exception) {
467 846 : BUILD(Rethrow, exception.node);
468 424 : builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
469 423 : }
470 :
471 376 : void BrOnException(FullDecoder* decoder, const Value& exception,
472 : const ExceptionIndexImmediate<validate>& imm,
473 : uint32_t depth, Vector<Value> values) {
474 376 : TFNode* if_match = nullptr;
475 376 : TFNode* if_no_match = nullptr;
476 :
477 : // Get the exception tag and see if it matches the expected one.
478 752 : TFNode* caught_tag = BUILD(GetExceptionTag, exception.node);
479 752 : TFNode* exception_tag = BUILD(LoadExceptionTagFromTable, imm.index);
480 752 : TFNode* compare = BUILD(ExceptionTagEqual, caught_tag, exception_tag);
481 752 : BUILD(BranchNoHint, compare, &if_match, &if_no_match);
482 752 : SsaEnv* if_no_match_env = Split(decoder, ssa_env_);
483 752 : SsaEnv* if_match_env = Steal(decoder->zone(), ssa_env_);
484 376 : if_no_match_env->control = if_no_match;
485 376 : if_match_env->control = if_match;
486 :
487 : // If the tags match we extract the values from the exception object and
488 : // push them onto the operand stack using the passed {values} vector.
489 : SetEnv(if_match_env);
490 : // TODO(mstarzinger): Can't use BUILD() here, GetExceptionValues() returns
491 : // TFNode** rather than TFNode*. Fix to add landing pads.
492 : TFNode** caught_values =
493 376 : builder_->GetExceptionValues(exception.node, imm.exception);
494 623 : for (size_t i = 0, e = values.size(); i < e; ++i) {
495 496 : values[i].node = caught_values[i];
496 : }
497 375 : BrOrRet(decoder, depth);
498 :
499 : // If the tags don't match we fall-through here.
500 : SetEnv(if_no_match_env);
501 375 : }
502 :
503 : void Catch(FullDecoder* decoder, Control* block, Value* exception) {
504 : DCHECK(block->is_try_catch());
505 :
506 520 : current_catch_ = block->previous_catch; // Pop try scope.
507 :
508 : // The catch block is unreachable if no possible throws in the try block
509 : // exist. We only build a landing pad if some node in the try block can
510 : // (possibly) throw. Otherwise the catch environments remain empty.
511 520 : if (!block->try_info->might_throw()) {
512 8 : block->reachability = kSpecOnlyReachable;
513 : return;
514 : }
515 :
516 512 : SetEnv(block->try_info->catch_env);
517 : DCHECK_NOT_NULL(block->try_info->exception);
518 512 : exception->node = block->try_info->exception;
519 : }
520 :
521 32606 : void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
522 : const MemoryAccessImmediate<validate>& imm, Value* result) {
523 32660 : TFNode** inputs = GetNodes(args);
524 97952 : TFNode* node = BUILD(AtomicOp, opcode, inputs, imm.alignment, imm.offset,
525 : decoder->position());
526 32683 : if (result) result->node = node;
527 32683 : }
528 :
529 : void MemoryInit(FullDecoder* decoder,
530 : const MemoryInitImmediate<validate>& imm, const Value& dst,
531 : const Value& src, const Value& size) {
532 160 : BUILD(MemoryInit, imm.data_segment_index, dst.node, src.node, size.node,
533 40 : decoder->position());
534 : }
535 : void DataDrop(FullDecoder* decoder, const DataDropImmediate<validate>& imm) {
536 72 : BUILD(DataDrop, imm.index, decoder->position());
537 : }
538 : void MemoryCopy(FullDecoder* decoder,
539 : const MemoryCopyImmediate<validate>& imm, const Value& dst,
540 : const Value& src, const Value& size) {
541 72 : BUILD(MemoryCopy, dst.node, src.node, size.node, decoder->position());
542 : }
543 : void MemoryFill(FullDecoder* decoder,
544 : const MemoryIndexImmediate<validate>& imm, const Value& dst,
545 : const Value& value, const Value& size) {
546 72 : BUILD(MemoryFill, dst.node, value.node, size.node, decoder->position());
547 : }
548 : void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
549 : Vector<Value> args) {
550 125 : BUILD(TableInit, imm.table.index, imm.elem_segment_index, args[0].node,
551 31 : args[1].node, args[2].node, decoder->position());
552 : }
553 : void ElemDrop(FullDecoder* decoder, const ElemDropImmediate<validate>& imm) {
554 48 : BUILD(ElemDrop, imm.index, decoder->position());
555 : }
556 : void TableCopy(FullDecoder* decoder, const TableCopyImmediate<validate>& imm,
557 : Vector<Value> args) {
558 256 : BUILD(TableCopy, imm.table_src.index, imm.table_dst.index, args[0].node,
559 64 : args[1].node, args[2].node, decoder->position());
560 : }
561 :
562 : private:
563 : SsaEnv* ssa_env_;
564 : compiler::WasmGraphBuilder* builder_;
565 : uint32_t current_catch_ = kNullCatch;
566 :
567 : TryInfo* current_try_info(FullDecoder* decoder) {
568 648 : return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
569 648 : ->try_info;
570 : }
571 :
572 596387 : TFNode** GetNodes(Value* values, size_t count) {
573 596387 : TFNode** nodes = builder_->Buffer(count);
574 602710 : for (size_t i = 0; i < count; ++i) {
575 602710 : nodes[i] = values[i].node;
576 : }
577 596520 : return nodes;
578 : }
579 :
580 596260 : TFNode** GetNodes(Vector<Value> values) {
581 596260 : return GetNodes(values.start(), values.size());
582 : }
583 :
584 : void SetEnv(SsaEnv* env) {
585 : #if DEBUG
586 : if (FLAG_trace_wasm_decoder) {
587 : char state = 'X';
588 : if (env) {
589 : switch (env->state) {
590 : case SsaEnv::kReached:
591 : state = 'R';
592 : break;
593 : case SsaEnv::kUnreachable:
594 : state = 'U';
595 : break;
596 : case SsaEnv::kMerged:
597 : state = 'M';
598 : break;
599 : case SsaEnv::kControlEnd:
600 : state = 'E';
601 : break;
602 : }
603 : }
604 : PrintF("{set_env = %p, state = %c", static_cast<void*>(env), state);
605 : if (env && env->control) {
606 : PrintF(", control = ");
607 : compiler::WasmGraphBuilder::PrintDebugName(env->control);
608 : }
609 : PrintF("}\n");
610 : }
611 : #endif
612 1078698 : ssa_env_ = env;
613 : // TODO(wasm): combine the control and effect pointers with instance cache.
614 1078698 : builder_->set_control_ptr(&env->control);
615 1078698 : builder_->set_effect_ptr(&env->effect);
616 1078698 : builder_->set_instance_cache(&env->instance_cache);
617 : }
618 :
619 2107178 : TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
620 2105882 : if (node == nullptr) return nullptr;
621 :
622 2104362 : const bool inside_try_scope = current_catch_ != kNullCatch;
623 :
624 2104362 : if (!inside_try_scope) return node;
625 :
626 1272 : TFNode* if_success = nullptr;
627 1272 : TFNode* if_exception = nullptr;
628 1272 : if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
629 : return node;
630 : }
631 :
632 1296 : SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
633 646 : success_env->control = if_success;
634 :
635 646 : SsaEnv* exception_env = Split(decoder, success_env);
636 648 : exception_env->control = if_exception;
637 : TryInfo* try_info = current_try_info(decoder);
638 648 : Goto(decoder, exception_env, try_info->catch_env);
639 648 : TFNode* exception = try_info->exception;
640 648 : if (exception == nullptr) {
641 : DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
642 512 : try_info->exception = if_exception;
643 : } else {
644 : DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
645 : try_info->exception = builder_->CreateOrMergeIntoPhi(
646 : MachineRepresentation::kWord32, try_info->catch_env->control,
647 136 : try_info->exception, if_exception);
648 : }
649 :
650 : SetEnv(success_env);
651 648 : return node;
652 : }
653 :
654 20465 : TFNode* DefaultValue(ValueType type) {
655 20465 : switch (type) {
656 : case kWasmI32:
657 10165 : return builder_->Int32Constant(0);
658 : case kWasmI64:
659 6367 : return builder_->Int64Constant(0);
660 : case kWasmF32:
661 416 : return builder_->Float32Constant(0);
662 : case kWasmF64:
663 1241 : return builder_->Float64Constant(0);
664 : case kWasmS128:
665 2156 : return builder_->S128Zero();
666 : case kWasmAnyRef:
667 : case kWasmAnyFunc:
668 : case kWasmExceptRef:
669 120 : return builder_->RefNull();
670 : default:
671 0 : UNREACHABLE();
672 : }
673 : }
674 :
675 350715 : void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge) {
676 : DCHECK(merge == &c->start_merge || merge == &c->end_merge);
677 :
678 350715 : SsaEnv* target = c->end_env;
679 350715 : const bool first = target->state == SsaEnv::kUnreachable;
680 350715 : Goto(decoder, ssa_env_, target);
681 :
682 701449 : if (merge->arity == 0) return;
683 :
684 : uint32_t avail =
685 16751 : decoder->stack_size() - decoder->control_at(0)->stack_depth;
686 : DCHECK_GE(avail, merge->arity);
687 16751 : uint32_t start = avail >= merge->arity ? 0 : merge->arity - avail;
688 : Value* stack_values = decoder->stack_value(merge->arity);
689 16826 : for (uint32_t i = start; i < merge->arity; ++i) {
690 16823 : Value& val = stack_values[i];
691 : Value& old = (*merge)[i];
692 : DCHECK_NOT_NULL(val.node);
693 : DCHECK(val.type == old.type || val.type == kWasmVar);
694 : old.node = first ? val.node
695 : : builder_->CreateOrMergeIntoPhi(
696 : ValueTypes::MachineRepresentationFor(old.type),
697 16823 : target->control, old.node, val.node);
698 : }
699 : }
700 :
701 351371 : void Goto(FullDecoder* decoder, SsaEnv* from, SsaEnv* to) {
702 : DCHECK_NOT_NULL(to);
703 351371 : switch (to->state) {
704 : case SsaEnv::kUnreachable: { // Overwrite destination.
705 103373 : to->state = SsaEnv::kReached;
706 103373 : to->locals = from->locals;
707 103373 : to->control = from->control;
708 103373 : to->effect = from->effect;
709 103373 : to->instance_cache = from->instance_cache;
710 : break;
711 : }
712 : case SsaEnv::kReached: { // Create a new merge.
713 34469 : to->state = SsaEnv::kMerged;
714 : // Merge control.
715 34469 : TFNode* controls[] = {to->control, from->control};
716 34469 : TFNode* merge = builder_->Merge(2, controls);
717 34470 : to->control = merge;
718 : // Merge effects.
719 34470 : if (from->effect != to->effect) {
720 21966 : TFNode* effects[] = {to->effect, from->effect, merge};
721 21966 : to->effect = builder_->EffectPhi(2, effects, merge);
722 : }
723 : // Merge SSA values.
724 719808 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
725 685336 : TFNode* a = to->locals[i];
726 685336 : TFNode* b = from->locals[i];
727 685336 : if (a != b) {
728 60497 : TFNode* vals[] = {a, b};
729 : to->locals[i] =
730 120994 : builder_->Phi(decoder->GetLocalType(i), 2, vals, merge);
731 : }
732 : }
733 : // Start a new merge from the instance cache.
734 : builder_->NewInstanceCacheMerge(&to->instance_cache,
735 34472 : &from->instance_cache, merge);
736 : break;
737 : }
738 : case SsaEnv::kMerged: {
739 213529 : TFNode* merge = to->control;
740 : // Extend the existing merge control node.
741 213529 : builder_->AppendToMerge(merge, from->control);
742 : // Merge effects.
743 : to->effect = builder_->CreateOrMergeIntoEffectPhi(merge, to->effect,
744 213530 : from->effect);
745 : // Merge locals.
746 772355 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
747 : to->locals[i] = builder_->CreateOrMergeIntoPhi(
748 558826 : ValueTypes::MachineRepresentationFor(decoder->GetLocalType(i)),
749 1117652 : merge, to->locals[i], from->locals[i]);
750 : }
751 : // Merge the instance caches.
752 : builder_->MergeInstanceCacheInto(&to->instance_cache,
753 213529 : &from->instance_cache, merge);
754 : break;
755 : }
756 : default:
757 0 : UNREACHABLE();
758 : }
759 351373 : return from->Kill();
760 : }
761 :
762 27261 : SsaEnv* PrepareForLoop(FullDecoder* decoder, SsaEnv* env) {
763 9090 : env->state = SsaEnv::kMerged;
764 :
765 9090 : env->control = builder_->Loop(env->control);
766 9089 : env->effect = builder_->EffectPhi(1, &env->effect, env->control);
767 9091 : builder_->TerminateLoop(env->effect, env->control);
768 : // The '+ 1' here is to be able to set the instance cache as assigned.
769 : BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
770 27262 : decoder, decoder->pc(), decoder->total_locals() + 1, decoder->zone());
771 9090 : if (decoder->failed()) return env;
772 9082 : if (assigned != nullptr) {
773 : // Only introduce phis for variables assigned in this loop.
774 9082 : int instance_cache_index = decoder->total_locals();
775 184638 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
776 175556 : if (!assigned->Contains(i)) continue;
777 36742 : env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
778 73484 : &env->locals[i], env->control);
779 : }
780 : // Introduce phis for instance cache pointers if necessary.
781 9082 : if (assigned->Contains(instance_cache_index)) {
782 : builder_->PrepareInstanceCacheForLoop(&env->instance_cache,
783 4259 : env->control);
784 : }
785 :
786 9082 : SsaEnv* loop_body_env = Split(decoder, env);
787 : builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
788 18162 : &(loop_body_env->control));
789 : return loop_body_env;
790 : }
791 :
792 : // Conservatively introduce phis for all local variables.
793 0 : for (int i = decoder->num_locals() - 1; i >= 0; i--) {
794 0 : env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
795 0 : &env->locals[i], env->control);
796 : }
797 :
798 : // Conservatively introduce phis for instance cache.
799 0 : builder_->PrepareInstanceCacheForLoop(&env->instance_cache, env->control);
800 :
801 0 : SsaEnv* loop_body_env = Split(decoder, env);
802 : builder_->StackCheck(decoder->position(), &loop_body_env->effect,
803 0 : &loop_body_env->control);
804 : return loop_body_env;
805 : }
806 :
807 : // Create a complete copy of {from}.
808 613403 : SsaEnv* Split(FullDecoder* decoder, SsaEnv* from) {
809 : DCHECK_NOT_NULL(from);
810 : SsaEnv* result =
811 308836 : reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
812 308842 : size_t size = sizeof(TFNode*) * decoder->num_locals();
813 308842 : result->control = from->control;
814 308842 : result->effect = from->effect;
815 :
816 308842 : result->state = SsaEnv::kReached;
817 308842 : if (size > 0) {
818 304567 : result->locals = reinterpret_cast<TFNode**>(decoder->zone()->New(size));
819 304564 : memcpy(result->locals, from->locals, size);
820 : } else {
821 4275 : result->locals = nullptr;
822 : }
823 308839 : result->instance_cache = from->instance_cache;
824 :
825 308839 : return result;
826 : }
827 :
828 : // Create a copy of {from} that steals its state and leaves {from}
829 : // unreachable.
830 131145 : SsaEnv* Steal(Zone* zone, SsaEnv* from) {
831 : DCHECK_NOT_NULL(from);
832 131145 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
833 131144 : result->state = SsaEnv::kReached;
834 131144 : result->locals = from->locals;
835 131144 : result->control = from->control;
836 131144 : result->effect = from->effect;
837 131144 : result->instance_cache = from->instance_cache;
838 : from->Kill(SsaEnv::kUnreachable);
839 131144 : return result;
840 : }
841 :
842 : // Create an unreachable environment.
843 : SsaEnv* UnreachableEnv(Zone* zone) {
844 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
845 : result->state = SsaEnv::kUnreachable;
846 : result->control = nullptr;
847 : result->effect = nullptr;
848 : result->locals = nullptr;
849 : result->instance_cache = {};
850 : return result;
851 : }
852 :
853 64822 : void DoCall(FullDecoder* decoder, TFNode* index_node, FunctionSig* sig,
854 : uint32_t index, const Value args[], Value returns[]) {
855 32409 : int param_count = static_cast<int>(sig->parameter_count());
856 32409 : TFNode** arg_nodes = builder_->Buffer(param_count + 1);
857 32409 : TFNode** return_nodes = nullptr;
858 32409 : arg_nodes[0] = index_node;
859 103702 : for (int i = 0; i < param_count; ++i) {
860 71293 : arg_nodes[i + 1] = args[i].node;
861 : }
862 32409 : if (index_node) {
863 9855 : BUILD(CallIndirect, index, arg_nodes, &return_nodes, decoder->position());
864 : } else {
865 87370 : BUILD(CallDirect, index, arg_nodes, &return_nodes, decoder->position());
866 : }
867 32413 : int return_count = static_cast<int>(sig->return_count());
868 50447 : for (int i = 0; i < return_count; ++i) {
869 18034 : returns[i].node = return_nodes[i];
870 : }
871 : // The invoked function could have used grow_memory, so we need to
872 : // reload mem_size and mem_start.
873 32413 : LoadContextIntoSsa(ssa_env_);
874 32416 : }
875 : };
876 :
877 : } // namespace
878 :
879 503585 : DecodeResult BuildTFGraph(AccountingAllocator* allocator,
880 : const WasmFeatures& enabled,
881 : const wasm::WasmModule* module,
882 : compiler::WasmGraphBuilder* builder,
883 : WasmFeatures* detected, const FunctionBody& body,
884 : compiler::NodeOriginTable* node_origins) {
885 503585 : Zone zone(allocator, ZONE_NAME);
886 : WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
887 503606 : &zone, module, enabled, detected, body, builder);
888 503591 : if (node_origins) {
889 0 : builder->AddBytecodePositionDecorator(node_origins, &decoder);
890 : }
891 503591 : decoder.Decode();
892 503488 : if (node_origins) {
893 0 : builder->RemoveBytecodePositionDecorator();
894 : }
895 1510619 : return decoder.toResult(nullptr);
896 : }
897 :
898 : #undef BUILD
899 :
900 : } // namespace wasm
901 : } // namespace internal
902 178779 : } // namespace v8
|