Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/signature.h"
6 :
7 : #include "src/base/platform/elapsed-timer.h"
8 : #include "src/flags.h"
9 : #include "src/handles.h"
10 : #include "src/objects-inl.h"
11 : #include "src/zone/zone-containers.h"
12 :
13 : #include "src/wasm/decoder.h"
14 : #include "src/wasm/function-body-decoder-impl.h"
15 : #include "src/wasm/function-body-decoder.h"
16 : #include "src/wasm/wasm-limits.h"
17 : #include "src/wasm/wasm-module.h"
18 : #include "src/wasm/wasm-opcodes.h"
19 :
20 : #include "src/ostreams.h"
21 :
22 : #include "src/compiler/wasm-compiler.h"
23 :
24 : namespace v8 {
25 : namespace internal {
26 : namespace wasm {
27 :
28 : namespace {
29 :
30 : template <typename T>
31 : Vector<T> vec2vec(ZoneVector<T>& vec) {
32 140 : return Vector<T>(vec.data(), vec.size());
33 : }
34 :
35 : // An SsaEnv environment carries the current local variable renaming
36 : // as well as the current effect and control dependency in the TF graph.
37 : // It maintains a control state that tracks whether the environment
38 : // is reachable, has reached a control end, or has been merged.
39 : struct SsaEnv {
40 : enum State { kControlEnd, kUnreachable, kReached, kMerged };
41 :
42 : State state;
43 : TFNode* control;
44 : TFNode* effect;
45 : TFNode* mem_size;
46 : TFNode* mem_start;
47 : TFNode** locals;
48 :
49 2865827 : bool go() { return state >= kReached; }
50 : void Kill(State new_state = kControlEnd) {
51 1691442 : state = new_state;
52 1691442 : locals = nullptr;
53 1691442 : control = nullptr;
54 1691442 : effect = nullptr;
55 1691442 : mem_size = nullptr;
56 1691442 : mem_start = nullptr;
57 : }
58 : void SetNotMerged() {
59 175112 : if (state == kMerged) state = kReached;
60 : }
61 : };
62 :
63 : #define BUILD(func, ...) \
64 : ([&] { \
65 : DCHECK(ssa_env_->go()); \
66 : DCHECK(decoder->ok()); \
67 : return CheckForException(decoder, builder_->func(__VA_ARGS__)); \
68 : })()
69 :
70 : constexpr uint32_t kNullCatch = static_cast<uint32_t>(-1);
71 :
72 : class WasmGraphBuildingInterface {
73 : public:
74 : static constexpr wasm::Decoder::ValidateFlag validate =
75 : wasm::Decoder::kValidate;
76 : using Decoder = WasmFullDecoder<validate, WasmGraphBuildingInterface>;
77 :
78 : struct Value : public ValueWithNamedConstructors<Value> {
79 : TFNode* node;
80 : };
81 :
82 : struct TryInfo : public ZoneObject {
83 : SsaEnv* catch_env;
84 : TFNode* exception;
85 :
86 70 : explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {}
87 : };
88 :
89 : struct Control : public ControlWithNamedConstructors<Control, Value> {
90 : SsaEnv* end_env; // end environment for the construct.
91 : SsaEnv* false_env; // false environment (only for if).
92 : TryInfo* try_info; // information used for compiling try statements.
93 : int32_t previous_catch; // previous Control (on the stack) with a catch.
94 : };
95 :
96 234351 : explicit WasmGraphBuildingInterface(TFBuilder* builder) : builder_(builder) {}
97 :
98 468877 : void StartFunction(Decoder* decoder) {
99 : SsaEnv* ssa_env =
100 234441 : reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
101 : uint32_t num_locals = decoder->NumLocals();
102 : // The '+ 2' here is to accommodate for mem_size and mem_start nodes.
103 234456 : uint32_t env_count = num_locals + 2;
104 234456 : size_t size = sizeof(TFNode*) * env_count;
105 234456 : ssa_env->state = SsaEnv::kReached;
106 : ssa_env->locals =
107 : size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
108 468892 : : nullptr;
109 :
110 : // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the
111 : // wasm_context parameter.
112 : TFNode* start = builder_->Start(
113 654877 : static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
114 : // Initialize the wasm_context (the paramater at index 0).
115 : builder_->set_wasm_context(
116 234443 : builder_->Param(compiler::kWasmContextParameterIndex));
117 : // Initialize local variables. Parameters are shifted by 1 because of the
118 : // the wasm_context.
119 : uint32_t index = 0;
120 1075239 : for (; index < decoder->sig_->parameter_count(); ++index) {
121 186023 : ssa_env->locals[index] = builder_->Param(index + 1);
122 : }
123 244685 : while (index < num_locals) {
124 : ValueType type = decoder->GetLocalType(index);
125 10287 : TFNode* node = DefaultValue(type);
126 113516 : while (index < num_locals && decoder->GetLocalType(index) == type) {
127 : // Do a whole run of like-typed locals at a time.
128 45194 : ssa_env->locals[index++] = node;
129 : }
130 : }
131 234398 : ssa_env->effect = start;
132 234398 : ssa_env->control = start;
133 : // Initialize effect and control before loading the context.
134 234398 : builder_->set_effect_ptr(&ssa_env->effect);
135 234398 : builder_->set_control_ptr(&ssa_env->control);
136 : // Always load mem_size and mem_start from the WasmContext into the ssa.
137 234398 : LoadContextIntoSsa(ssa_env);
138 : SetEnv(ssa_env);
139 234442 : }
140 :
141 : // Reload the wasm context variables from the WasmContext structure attached
142 : // to the memory object into the Ssa Environment. This does not automatically
143 : // set the mem_size_ and mem_start_ pointers in WasmGraphBuilder.
144 822597 : void LoadContextIntoSsa(SsaEnv* ssa_env) {
145 1233917 : if (!ssa_env || !ssa_env->go()) return;
146 : DCHECK_NOT_NULL(builder_->Effect());
147 : DCHECK_NOT_NULL(builder_->Control());
148 411338 : ssa_env->mem_size = builder_->LoadMemSize();
149 411316 : ssa_env->mem_start = builder_->LoadMemStart();
150 : }
151 :
152 468424 : void StartFunctionBody(Decoder* decoder, Control* block) {
153 234212 : SsaEnv* break_env = ssa_env_;
154 234212 : SetEnv(Steal(decoder->zone(), break_env));
155 234228 : block->end_env = break_env;
156 234228 : }
157 :
158 : void FinishFunction(Decoder* decoder) {
159 228618 : builder_->PatchInStackCheckIfNeeded();
160 : }
161 :
162 : void OnFirstError(Decoder* decoder) {}
163 :
164 483294 : void Block(Decoder* decoder, Control* block) {
165 : // The break environment is the outer environment.
166 241647 : block->end_env = ssa_env_;
167 483294 : SetEnv(Steal(decoder->zone(), ssa_env_));
168 241645 : }
169 :
170 23246 : void Loop(Decoder* decoder, Control* block) {
171 23246 : SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
172 11623 : block->end_env = finish_try_env;
173 : // The continue environment is the inner environment.
174 11623 : SetEnv(PrepareForLoop(decoder, finish_try_env));
175 11624 : ssa_env_->SetNotMerged();
176 11624 : }
177 :
178 210 : void Try(Decoder* decoder, Control* block) {
179 70 : SsaEnv* outer_env = ssa_env_;
180 70 : SsaEnv* catch_env = Split(decoder, outer_env);
181 : // Mark catch environment as unreachable, since only accessable
182 : // through catch unwinding (i.e. landing pads).
183 70 : catch_env->state = SsaEnv::kUnreachable;
184 70 : SsaEnv* try_env = Steal(decoder->zone(), outer_env);
185 : SetEnv(try_env);
186 : TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env);
187 70 : block->end_env = outer_env;
188 70 : block->try_info = try_info;
189 70 : block->previous_catch = current_catch_;
190 70 : current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
191 70 : }
192 :
193 62057 : void If(Decoder* decoder, const Value& cond, Control* if_block) {
194 62057 : TFNode* if_true = nullptr;
195 62057 : TFNode* if_false = nullptr;
196 186171 : if (ssa_env_->go()) BUILD(BranchNoHint, cond.node, &if_true, &if_false);
197 62060 : SsaEnv* end_env = ssa_env_;
198 124120 : SsaEnv* false_env = Split(decoder, ssa_env_);
199 62060 : false_env->control = if_false;
200 124120 : SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
201 62055 : true_env->control = if_true;
202 62055 : if_block->end_env = end_env;
203 62055 : if_block->false_env = false_env;
204 : SetEnv(true_env);
205 62055 : }
206 :
207 : void FallThruTo(Decoder* decoder, Control* c) {
208 : DCHECK(!c->is_loop());
209 135591 : MergeValuesInto(decoder, c);
210 : }
211 :
212 542063 : void PopControl(Decoder* decoder, Control* block) {
213 1084126 : if (!block->is_loop()) SetEnv(block->end_env);
214 542063 : if (block->is_onearmed_if()) {
215 38193 : Goto(decoder, block->false_env, block->end_env);
216 : }
217 542063 : }
218 :
219 : void EndControl(Decoder* decoder, Control* block) { ssa_env_->Kill(); }
220 :
221 : void UnOp(Decoder* decoder, WasmOpcode opcode, FunctionSig* sig,
222 : const Value& value, Value* result) {
223 1101566 : result->node = BUILD(Unop, opcode, value.node, decoder->position());
224 : }
225 :
226 : void BinOp(Decoder* decoder, WasmOpcode opcode, FunctionSig* sig,
227 : const Value& lhs, const Value& rhs, Value* result) {
228 : result->node =
229 2905520 : BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
230 : }
231 :
232 : void I32Const(Decoder* decoder, Value* result, int32_t value) {
233 967330 : result->node = builder_->Int32Constant(value);
234 : }
235 :
236 : void I64Const(Decoder* decoder, Value* result, int64_t value) {
237 46084 : result->node = builder_->Int64Constant(value);
238 : }
239 :
240 : void F32Const(Decoder* decoder, Value* result, float value) {
241 146674 : result->node = builder_->Float32Constant(value);
242 : }
243 :
244 : void F64Const(Decoder* decoder, Value* result, double value) {
245 157475 : result->node = builder_->Float64Constant(value);
246 : }
247 :
248 : void Drop(Decoder* decoder, const Value& value) {}
249 :
250 288483 : void DoReturn(Decoder* decoder, Vector<Value> values, bool implicit) {
251 288483 : if (implicit) {
252 : DCHECK_EQ(1, decoder->control_depth());
253 151574 : SetEnv(decoder->control_at(0)->end_env);
254 : }
255 288483 : size_t num_values = values.size();
256 288499 : TFNode** buffer = GetNodes(values);
257 433460 : for (size_t i = 0; i < num_values; ++i) {
258 289922 : buffer[i] = values[i].node;
259 : }
260 576996 : BUILD(Return, static_cast<unsigned>(values.size()), buffer);
261 288477 : }
262 :
263 : void GetLocal(Decoder* decoder, Value* result,
264 : const LocalIndexOperand<validate>& operand) {
265 567861 : if (!ssa_env_->locals) return; // unreachable
266 567847 : result->node = ssa_env_->locals[operand.index];
267 : }
268 :
269 : void SetLocal(Decoder* decoder, const Value& value,
270 : const LocalIndexOperand<validate>& operand) {
271 48441 : if (!ssa_env_->locals) return; // unreachable
272 48443 : ssa_env_->locals[operand.index] = value.node;
273 : }
274 :
275 : void TeeLocal(Decoder* decoder, const Value& value, Value* result,
276 : const LocalIndexOperand<validate>& operand) {
277 131961 : result->node = value.node;
278 131961 : if (!ssa_env_->locals) return; // unreachable
279 131961 : ssa_env_->locals[operand.index] = value.node;
280 : }
281 :
282 : void GetGlobal(Decoder* decoder, Value* result,
283 : const GlobalIndexOperand<validate>& operand) {
284 39322 : result->node = BUILD(GetGlobal, operand.index);
285 : }
286 :
287 : void SetGlobal(Decoder* decoder, const Value& value,
288 : const GlobalIndexOperand<validate>& operand) {
289 23892 : BUILD(SetGlobal, operand.index, value.node);
290 : }
291 :
292 : void Unreachable(Decoder* decoder) {
293 389997 : BUILD(Unreachable, decoder->position());
294 : }
295 :
296 398 : void Select(Decoder* decoder, const Value& cond, const Value& fval,
297 : const Value& tval, Value* result) {
298 : TFNode* controls[2];
299 797 : BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
300 800 : TFNode* merge = BUILD(Merge, 2, controls);
301 397 : TFNode* vals[2] = {tval.node, fval.node};
302 797 : TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
303 400 : result->node = phi;
304 400 : ssa_env_->control = merge;
305 400 : }
306 :
307 492372 : void BreakTo(Decoder* decoder, Control* target) {
308 492372 : if (target->is_loop()) {
309 11146 : Goto(decoder, ssa_env_, target->end_env);
310 : } else {
311 481226 : MergeValuesInto(decoder, target);
312 : }
313 492369 : }
314 :
315 163490 : void BrIf(Decoder* decoder, const Value& cond, Control* target) {
316 163490 : SsaEnv* fenv = ssa_env_;
317 163490 : SsaEnv* tenv = Split(decoder, fenv);
318 163488 : fenv->SetNotMerged();
319 326976 : BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
320 163491 : ssa_env_ = tenv;
321 163491 : BreakTo(decoder, target);
322 163486 : ssa_env_ = fenv;
323 163486 : }
324 :
325 13610 : void BrTable(Decoder* decoder, const BranchTableOperand<validate>& operand,
326 : const Value& key) {
327 13610 : if (operand.table_count == 0) {
328 : // Only a default target. Do the equivalent of br.
329 14146 : uint32_t target = BranchTableIterator<validate>(decoder, operand).next();
330 1072 : BreakTo(decoder, decoder->control_at(target));
331 14146 : return;
332 : }
333 :
334 13074 : SsaEnv* break_env = ssa_env_;
335 : // Build branches to the various blocks based on the table.
336 26148 : TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
337 :
338 26148 : SsaEnv* copy = Steal(decoder->zone(), break_env);
339 13075 : ssa_env_ = copy;
340 13075 : BranchTableIterator<validate> iterator(decoder, operand);
341 310844 : while (iterator.has_next()) {
342 297770 : uint32_t i = iterator.cur_index();
343 297770 : uint32_t target = iterator.next();
344 297770 : ssa_env_ = Split(decoder, copy);
345 634761 : ssa_env_->control = (i == operand.table_count) ? BUILD(IfDefault, sw)
346 880235 : : BUILD(IfValue, i, sw);
347 595538 : BreakTo(decoder, decoder->control_at(target));
348 : }
349 : DCHECK(decoder->ok());
350 13074 : ssa_env_ = break_env;
351 : }
352 :
353 : void Else(Decoder* decoder, Control* if_block) {
354 : SetEnv(if_block->false_env);
355 : }
356 :
357 : void LoadMem(Decoder* decoder, ValueType type, MachineType mem_type,
358 : const MemoryAccessOperand<validate>& operand, const Value& index,
359 : Value* result) {
360 132323 : result->node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
361 33081 : operand.alignment, decoder->position());
362 : }
363 :
364 : void StoreMem(Decoder* decoder, ValueType type, MachineType mem_type,
365 : const MemoryAccessOperand<validate>& operand,
366 : const Value& index, const Value& value) {
367 58251 : BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
368 14567 : value.node, decoder->position(), type);
369 : }
370 :
371 : void CurrentMemoryPages(Decoder* decoder, Value* result) {
372 1136 : result->node = BUILD(CurrentMemoryPages);
373 : }
374 :
375 1106 : void GrowMemory(Decoder* decoder, const Value& value, Value* result) {
376 2212 : result->node = BUILD(GrowMemory, value.node);
377 : // Reload mem_size and mem_start after growing memory.
378 1106 : LoadContextIntoSsa(ssa_env_);
379 1106 : }
380 :
381 : void CallDirect(Decoder* decoder,
382 : const CallFunctionOperand<validate>& operand,
383 : const Value args[], Value returns[]) {
384 172532 : DoCall(decoder, nullptr, operand, args, returns, false);
385 : }
386 :
387 : void CallIndirect(Decoder* decoder, const Value& index,
388 : const CallIndirectOperand<validate>& operand,
389 : const Value args[], Value returns[]) {
390 3290 : DoCall(decoder, index.node, operand, args, returns, true);
391 : }
392 :
393 2694 : void SimdOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
394 : Value* result) {
395 2694 : TFNode** inputs = GetNodes(args);
396 5388 : TFNode* node = BUILD(SimdOp, opcode, inputs);
397 2694 : if (result) result->node = node;
398 2694 : }
399 :
400 12654 : void SimdLaneOp(Decoder* decoder, WasmOpcode opcode,
401 : const SimdLaneOperand<validate> operand, Vector<Value> inputs,
402 : Value* result) {
403 12654 : TFNode** nodes = GetNodes(inputs);
404 25308 : result->node = BUILD(SimdLaneOp, opcode, operand.lane, nodes);
405 12654 : }
406 :
407 : void SimdShiftOp(Decoder* decoder, WasmOpcode opcode,
408 : const SimdShiftOperand<validate> operand, const Value& input,
409 : Value* result) {
410 72 : TFNode* inputs[] = {input.node};
411 144 : result->node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
412 : }
413 :
414 : void Simd8x16ShuffleOp(Decoder* decoder,
415 : const Simd8x16ShuffleOperand<validate>& operand,
416 : const Value& input0, const Value& input1,
417 : Value* result) {
418 0 : TFNode* input_nodes[] = {input0.node, input1.node};
419 0 : result->node = BUILD(Simd8x16ShuffleOp, operand.shuffle, input_nodes);
420 : }
421 :
422 : TFNode* GetExceptionTag(Decoder* decoder,
423 : const ExceptionIndexOperand<validate>& operand) {
424 : // TODO(kschimpf): Need to get runtime exception tag values. This
425 : // code only handles non-imported/exported exceptions.
426 : return BUILD(Int32Constant, operand.index);
427 : }
428 :
429 140 : void Throw(Decoder* decoder, const ExceptionIndexOperand<validate>& operand,
430 380 : Control* block, const Vector<Value>& value_args) {
431 : int count = value_args.length();
432 140 : ZoneVector<TFNode*> args(count, decoder->zone());
433 100 : for (int i = 0; i < count; ++i) {
434 200 : args[i] = value_args[i].node;
435 : }
436 420 : BUILD(Throw, operand.index, operand.exception, vec2vec(args));
437 140 : Unreachable(decoder);
438 : EndControl(decoder, block);
439 140 : }
440 :
441 70 : void CatchException(Decoder* decoder,
442 : const ExceptionIndexOperand<validate>& operand,
443 70 : Control* block, Vector<Value> values) {
444 : DCHECK(block->is_try_catch());
445 70 : current_catch_ = block->previous_catch;
446 70 : SsaEnv* catch_env = block->try_info->catch_env;
447 : SetEnv(catch_env);
448 :
449 70 : TFNode* compare_i32 = nullptr;
450 70 : if (block->try_info->exception == nullptr) {
451 : // Catch not applicable, no possible throws in the try
452 : // block. Create dummy code so that body of catch still
453 : // compiles. Note: This only happens because the current
454 : // implementation only builds a landing pad if some node in the
455 : // try block can (possibly) throw.
456 : //
457 : // TODO(kschimpf): Always generate a landing pad for a try block.
458 0 : compare_i32 = BUILD(Int32Constant, 0);
459 : } else {
460 : // Get the exception and see if wanted exception.
461 140 : TFNode* caught_tag = BUILD(GetExceptionRuntimeId);
462 : TFNode* exception_tag =
463 140 : BUILD(ConvertExceptionTagToRuntimeId, operand.index);
464 140 : compare_i32 = BUILD(Binop, kExprI32Eq, caught_tag, exception_tag);
465 : }
466 :
467 70 : TFNode* if_catch = nullptr;
468 70 : TFNode* if_no_catch = nullptr;
469 140 : BUILD(BranchNoHint, compare_i32, &if_catch, &if_no_catch);
470 :
471 140 : SsaEnv* if_no_catch_env = Split(decoder, ssa_env_);
472 70 : if_no_catch_env->control = if_no_catch;
473 140 : SsaEnv* if_catch_env = Steal(decoder->zone(), ssa_env_);
474 70 : if_catch_env->control = if_catch;
475 :
476 : // TODO(kschimpf): Generalize to allow more catches. Will force
477 : // moving no_catch code to END opcode.
478 : SetEnv(if_no_catch_env);
479 140 : BUILD(Rethrow);
480 70 : Unreachable(decoder);
481 : EndControl(decoder, block);
482 :
483 : SetEnv(if_catch_env);
484 :
485 70 : if (block->try_info->exception == nullptr) {
486 : // No caught value, make up filler nodes so that catch block still
487 : // compiles.
488 0 : for (Value& value : values) {
489 0 : value.node = DefaultValue(value.type);
490 : }
491 : } else {
492 : // TODO(kschimpf): Can't use BUILD() here, GetExceptionValues() returns
493 : // TFNode** rather than TFNode*. Fix to add landing pads.
494 70 : TFNode** caught_values = builder_->GetExceptionValues(operand.exception);
495 40 : for (size_t i = 0, e = values.size(); i < e; ++i) {
496 40 : values[i].node = caught_values[i];
497 : }
498 : }
499 70 : }
500 :
501 512 : void AtomicOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
502 : const MemoryAccessOperand<validate>& operand, Value* result) {
503 512 : TFNode** inputs = GetNodes(args);
504 1536 : TFNode* node = BUILD(AtomicOp, opcode, inputs, operand.alignment,
505 : operand.offset, decoder->position());
506 512 : if (result) result->node = node;
507 512 : }
508 :
509 : private:
510 : SsaEnv* ssa_env_;
511 : TFBuilder* builder_;
512 : uint32_t current_catch_ = kNullCatch;
513 :
514 : TryInfo* current_try_info(Decoder* decoder) {
515 90 : return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
516 90 : ->try_info;
517 : }
518 :
519 304325 : TFNode** GetNodes(Value* values, size_t count) {
520 304325 : TFNode** nodes = builder_->Buffer(count);
521 162608 : for (size_t i = 0; i < count; ++i) {
522 162608 : nodes[i] = values[i].node;
523 : }
524 304356 : return nodes;
525 : }
526 :
527 304343 : TFNode** GetNodes(Vector<Value> values) {
528 304343 : return GetNodes(values.start(), values.size());
529 : }
530 :
531 : void SetEnv(SsaEnv* env) {
532 : #if DEBUG
533 : if (FLAG_trace_wasm_decoder) {
534 : char state = 'X';
535 : if (env) {
536 : switch (env->state) {
537 : case SsaEnv::kReached:
538 : state = 'R';
539 : break;
540 : case SsaEnv::kUnreachable:
541 : state = 'U';
542 : break;
543 : case SsaEnv::kMerged:
544 : state = 'M';
545 : break;
546 : case SsaEnv::kControlEnd:
547 : state = 'E';
548 : break;
549 : }
550 : }
551 : PrintF("{set_env = %p, state = %c", static_cast<void*>(env), state);
552 : if (env && env->control) {
553 : PrintF(", control = ");
554 : compiler::WasmGraphBuilder::PrintDebugName(env->control);
555 : }
556 : PrintF("}\n");
557 : }
558 : #endif
559 1414418 : ssa_env_ = env;
560 : // TODO(wasm): Create a WasmEnv class with control, effect, mem_size and
561 : // mem_start. SsaEnv can inherit from it. This way WasmEnv can be passed
562 : // directly to WasmGraphBuilder instead of always copying four pointers.
563 1414418 : builder_->set_control_ptr(&env->control);
564 1414418 : builder_->set_effect_ptr(&env->effect);
565 1414418 : builder_->set_mem_size(&env->mem_size);
566 1414418 : builder_->set_mem_start(&env->mem_start);
567 : }
568 :
569 2389176 : TFNode* CheckForException(Decoder* decoder, TFNode* node) {
570 2388996 : if (node == nullptr) return nullptr;
571 :
572 2259056 : const bool inside_try_scope = current_catch_ != kNullCatch;
573 :
574 2259056 : if (!inside_try_scope) return node;
575 :
576 190 : TFNode* if_success = nullptr;
577 190 : TFNode* if_exception = nullptr;
578 190 : if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
579 : return node;
580 : }
581 :
582 180 : SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
583 90 : success_env->control = if_success;
584 :
585 90 : SsaEnv* exception_env = Split(decoder, success_env);
586 90 : exception_env->control = if_exception;
587 : TryInfo* try_info = current_try_info(decoder);
588 90 : Goto(decoder, exception_env, try_info->catch_env);
589 90 : TFNode* exception = try_info->exception;
590 90 : if (exception == nullptr) {
591 : DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
592 70 : try_info->exception = if_exception;
593 : } else {
594 : DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
595 : try_info->exception =
596 : CreateOrMergeIntoPhi(kWasmI32, try_info->catch_env->control,
597 20 : try_info->exception, if_exception);
598 : }
599 :
600 : SetEnv(success_env);
601 90 : return node;
602 : }
603 :
604 10284 : TFNode* DefaultValue(ValueType type) {
605 10284 : switch (type) {
606 : case kWasmI32:
607 6081 : return builder_->Int32Constant(0);
608 : case kWasmI64:
609 689 : return builder_->Int64Constant(0);
610 : case kWasmF32:
611 678 : return builder_->Float32Constant(0);
612 : case kWasmF64:
613 1840 : return builder_->Float64Constant(0);
614 : case kWasmS128:
615 996 : return builder_->S128Zero();
616 : default:
617 0 : UNREACHABLE();
618 : }
619 : }
620 :
621 616752 : void MergeValuesInto(Decoder* decoder, Control* c) {
622 1850158 : if (!ssa_env_->go()) return;
623 :
624 616781 : SsaEnv* target = c->end_env;
625 616781 : const bool first = target->state == SsaEnv::kUnreachable;
626 616781 : Goto(decoder, ssa_env_, target);
627 :
628 : uint32_t avail =
629 616610 : decoder->stack_size() - decoder->control_at(0)->stack_depth;
630 616610 : uint32_t start = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
631 702162 : for (uint32_t i = start; i < c->merge.arity; ++i) {
632 : auto& val = decoder->GetMergeValueFromStack(c, i);
633 : auto& old = c->merge[i];
634 : DCHECK_NOT_NULL(val.node);
635 : DCHECK(val.type == old.type || val.type == kWasmVar);
636 : old.node = first ? val.node
637 : : CreateOrMergeIntoPhi(old.type, target->control,
638 85479 : old.node, val.node);
639 : }
640 : }
641 :
642 666098 : void Goto(Decoder* decoder, SsaEnv* from, SsaEnv* to) {
643 : DCHECK_NOT_NULL(to);
644 666098 : if (!from->go()) return;
645 665978 : switch (to->state) {
646 : case SsaEnv::kUnreachable: { // Overwrite destination.
647 345213 : to->state = SsaEnv::kReached;
648 345213 : to->locals = from->locals;
649 345213 : to->control = from->control;
650 345213 : to->effect = from->effect;
651 345213 : to->mem_size = from->mem_size;
652 345213 : to->mem_start = from->mem_start;
653 345213 : break;
654 : }
655 : case SsaEnv::kReached: { // Create a new merge.
656 51205 : to->state = SsaEnv::kMerged;
657 : // Merge control.
658 51205 : TFNode* controls[] = {to->control, from->control};
659 51205 : TFNode* merge = builder_->Merge(2, controls);
660 51203 : to->control = merge;
661 : // Merge effects.
662 51203 : if (from->effect != to->effect) {
663 28100 : TFNode* effects[] = {to->effect, from->effect, merge};
664 28100 : to->effect = builder_->EffectPhi(2, effects, merge);
665 : }
666 : // Merge SSA values.
667 980474 : for (int i = decoder->NumLocals() - 1; i >= 0; i--) {
668 929271 : TFNode* a = to->locals[i];
669 929271 : TFNode* b = from->locals[i];
670 929271 : if (a != b) {
671 81292 : TFNode* vals[] = {a, b};
672 : to->locals[i] =
673 162584 : builder_->Phi(decoder->GetLocalType(i), 2, vals, merge);
674 : }
675 : }
676 : // Merge mem_size and mem_start.
677 51203 : if (to->mem_size != from->mem_size) {
678 16545 : TFNode* vals[] = {to->mem_size, from->mem_size};
679 : to->mem_size =
680 16545 : builder_->Phi(MachineRepresentation::kWord32, 2, vals, merge);
681 : }
682 51203 : if (to->mem_start != from->mem_start) {
683 16545 : TFNode* vals[] = {to->mem_start, from->mem_start};
684 : to->mem_start = builder_->Phi(MachineType::PointerRepresentation(), 2,
685 16545 : vals, merge);
686 : }
687 : break;
688 : }
689 : case SsaEnv::kMerged: {
690 269560 : TFNode* merge = to->control;
691 : // Extend the existing merge.
692 269560 : builder_->AppendToMerge(merge, from->control);
693 : // Merge effects.
694 269559 : if (builder_->IsPhiWithMerge(to->effect, merge)) {
695 17649 : builder_->AppendToPhi(to->effect, from->effect);
696 251912 : } else if (to->effect != from->effect) {
697 164 : uint32_t count = builder_->InputCount(merge);
698 164 : TFNode** effects = builder_->Buffer(count);
699 643 : for (uint32_t j = 0; j < count - 1; j++) {
700 479 : effects[j] = to->effect;
701 : }
702 164 : effects[count - 1] = from->effect;
703 164 : to->effect = builder_->EffectPhi(count, effects, merge);
704 : }
705 : // Merge locals.
706 999942 : for (int i = decoder->NumLocals() - 1; i >= 0; i--) {
707 : to->locals[i] = CreateOrMergeIntoPhi(decoder->GetLocalType(i), merge,
708 1460760 : to->locals[i], from->locals[i]);
709 : }
710 : // Merge mem_size and mem_start.
711 : to->mem_size =
712 : CreateOrMergeIntoPhi(MachineRepresentation::kWord32, merge,
713 269562 : to->mem_size, from->mem_size);
714 : to->mem_start =
715 : CreateOrMergeIntoPhi(MachineType::PointerRepresentation(), merge,
716 269562 : to->mem_start, from->mem_start);
717 269561 : break;
718 : }
719 : default:
720 0 : UNREACHABLE();
721 : }
722 : return from->Kill();
723 : }
724 :
725 1277456 : TFNode* CreateOrMergeIntoPhi(ValueType type, TFNode* merge, TFNode* tnode,
726 : TFNode* fnode) {
727 1277456 : if (builder_->IsPhiWithMerge(tnode, merge)) {
728 126706 : builder_->AppendToPhi(tnode, fnode);
729 1150752 : } else if (tnode != fnode) {
730 16633 : uint32_t count = builder_->InputCount(merge);
731 16633 : TFNode** vals = builder_->Buffer(count);
732 34377 : for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
733 16634 : vals[count - 1] = fnode;
734 16634 : return builder_->Phi(type, count, vals, merge);
735 : }
736 : return tnode;
737 : }
738 :
739 34867 : SsaEnv* PrepareForLoop(Decoder* decoder, SsaEnv* env) {
740 11622 : if (!env->go()) return Split(decoder, env);
741 11622 : env->state = SsaEnv::kMerged;
742 :
743 11622 : env->control = builder_->Loop(env->control);
744 11622 : env->effect = builder_->EffectPhi(1, &env->effect, env->control);
745 11622 : builder_->Terminate(env->effect, env->control);
746 : // The '+ 2' here is to be able to set mem_size and mem_start as assigned.
747 : BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
748 34868 : decoder, decoder->pc(), decoder->total_locals() + 2, decoder->zone());
749 11625 : if (decoder->failed()) return env;
750 11620 : if (assigned != nullptr) {
751 : // Only introduce phis for variables assigned in this loop.
752 11620 : int mem_size_index = decoder->total_locals();
753 11620 : int mem_start_index = decoder->total_locals() + 1;
754 245715 : for (int i = decoder->NumLocals() - 1; i >= 0; i--) {
755 234094 : if (!assigned->Contains(i)) continue;
756 : env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
757 98786 : &env->locals[i], env->control);
758 : }
759 : // Introduce phis for mem_size and mem_start if necessary.
760 11621 : if (assigned->Contains(mem_size_index)) {
761 : env->mem_size = builder_->Phi(MachineRepresentation::kWord32, 1,
762 5350 : &env->mem_size, env->control);
763 : }
764 11621 : if (assigned->Contains(mem_start_index)) {
765 : env->mem_start = builder_->Phi(MachineType::PointerRepresentation(), 1,
766 5350 : &env->mem_start, env->control);
767 : }
768 :
769 11621 : SsaEnv* loop_body_env = Split(decoder, env);
770 : builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
771 23242 : &(loop_body_env->control));
772 : return loop_body_env;
773 : }
774 :
775 : // Conservatively introduce phis for all local variables.
776 0 : for (int i = decoder->NumLocals() - 1; i >= 0; i--) {
777 : env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
778 0 : &env->locals[i], env->control);
779 : }
780 :
781 : // Conservatively introduce phis for mem_size and mem_start.
782 : env->mem_size = builder_->Phi(MachineRepresentation::kWord32, 1,
783 0 : &env->mem_size, env->control);
784 : env->mem_start = builder_->Phi(MachineType::PointerRepresentation(), 1,
785 0 : &env->mem_start, env->control);
786 :
787 0 : SsaEnv* loop_body_env = Split(decoder, env);
788 : builder_->StackCheck(decoder->position(), &loop_body_env->effect,
789 0 : &loop_body_env->control);
790 : return loop_body_env;
791 : }
792 :
793 : // Create a complete copy of the {from}.
794 1605505 : SsaEnv* Split(Decoder* decoder, SsaEnv* from) {
795 : DCHECK_NOT_NULL(from);
796 : SsaEnv* result =
797 535171 : reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
798 : // The '+ 2' here is to accommodate for mem_size and mem_start nodes.
799 535167 : size_t size = sizeof(TFNode*) * (decoder->NumLocals() + 2);
800 535167 : result->control = from->control;
801 535167 : result->effect = from->effect;
802 :
803 535167 : if (from->go()) {
804 535167 : result->state = SsaEnv::kReached;
805 : result->locals =
806 : size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
807 1070334 : : nullptr;
808 535169 : memcpy(result->locals, from->locals, size);
809 535169 : result->mem_size = from->mem_size;
810 535169 : result->mem_start = from->mem_start;
811 : } else {
812 0 : result->state = SsaEnv::kUnreachable;
813 0 : result->locals = nullptr;
814 0 : result->mem_size = nullptr;
815 0 : result->mem_start = nullptr;
816 : }
817 :
818 535169 : return result;
819 : }
820 :
821 : // Create a copy of {from} that steals its state and leaves {from}
822 : // unreachable.
823 562819 : SsaEnv* Steal(Zone* zone, SsaEnv* from) {
824 : DCHECK_NOT_NULL(from);
825 562819 : if (!from->go()) return UnreachableEnv(zone);
826 562819 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
827 562845 : result->state = SsaEnv::kReached;
828 562845 : result->locals = from->locals;
829 562845 : result->control = from->control;
830 562845 : result->effect = from->effect;
831 562845 : result->mem_size = from->mem_size;
832 562845 : result->mem_start = from->mem_start;
833 : from->Kill(SsaEnv::kUnreachable);
834 : return result;
835 : }
836 :
837 : // Create an unreachable environment.
838 0 : SsaEnv* UnreachableEnv(Zone* zone) {
839 0 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
840 0 : result->state = SsaEnv::kUnreachable;
841 0 : result->control = nullptr;
842 0 : result->effect = nullptr;
843 0 : result->locals = nullptr;
844 0 : result->mem_size = nullptr;
845 0 : result->mem_start = nullptr;
846 0 : return result;
847 : }
848 :
849 : template <typename Operand>
850 351644 : void DoCall(WasmFullDecoder<validate, WasmGraphBuildingInterface>* decoder,
851 : TFNode* index_node, const Operand& operand, const Value args[],
852 : Value returns[], bool is_indirect) {
853 351635 : int param_count = static_cast<int>(operand.sig->parameter_count());
854 175819 : TFNode** arg_nodes = builder_->Buffer(param_count + 1);
855 175825 : TFNode** return_nodes = nullptr;
856 175825 : arg_nodes[0] = index_node;
857 393875 : for (int i = 0; i < param_count; ++i) {
858 393875 : arg_nodes[i + 1] = args[i].node;
859 : }
860 175825 : if (is_indirect) {
861 3290 : builder_->CallIndirect(operand.index, arg_nodes, &return_nodes,
862 : decoder->position());
863 : } else {
864 172535 : builder_->CallDirect(operand.index, arg_nodes, &return_nodes,
865 : decoder->position());
866 : }
867 351632 : int return_count = static_cast<int>(operand.sig->return_count());
868 155041 : for (int i = 0; i < return_count; ++i) {
869 155041 : 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 175816 : LoadContextIntoSsa(ssa_env_);
874 175826 : }
875 : };
876 :
877 : } // namespace
878 :
879 20521 : bool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start,
880 : const byte* end) {
881 : Decoder decoder(start, end);
882 20521 : if (WasmDecoder<Decoder::kValidate>::DecodeLocals(&decoder, nullptr,
883 20521 : &decls->type_list)) {
884 : DCHECK(decoder.ok());
885 20490 : decls->encoded_size = decoder.pc_offset();
886 20490 : return true;
887 : }
888 : return false;
889 : }
890 :
891 20432 : BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
892 : BodyLocalDecls* decls)
893 20432 : : Decoder(start, end) {
894 20432 : if (decls != nullptr) {
895 20429 : if (DecodeLocalDecls(decls, start, end)) {
896 20399 : pc_ += decls->encoded_size;
897 20399 : if (pc_ > end_) pc_ = end_;
898 : }
899 : }
900 20432 : }
901 :
902 171110 : DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
903 : const wasm::WasmModule* module,
904 : FunctionBody& body) {
905 171110 : Zone zone(allocator, ZONE_NAME);
906 : WasmFullDecoder<Decoder::kValidate, EmptyInterface> decoder(&zone, module,
907 : body);
908 171110 : decoder.Decode();
909 513330 : return decoder.toResult(nullptr);
910 : }
911 :
912 157413 : DecodeResult VerifyWasmCodeWithStats(AccountingAllocator* allocator,
913 : const wasm::WasmModule* module,
914 : FunctionBody& body, bool is_wasm,
915 : Counters* counters) {
916 157413 : CHECK_LE(0, body.end - body.start);
917 : auto time_counter = is_wasm ? counters->wasm_decode_wasm_function_time()
918 157413 : : counters->wasm_decode_asm_function_time();
919 : TimedHistogramScope wasm_decode_function_time_scope(time_counter);
920 472239 : return VerifyWasmCode(allocator, module, body);
921 : }
922 :
923 234381 : DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
924 : FunctionBody& body) {
925 234381 : Zone zone(allocator, ZONE_NAME);
926 : WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
927 234351 : &zone, builder->module(), body, builder);
928 234351 : decoder.Decode();
929 702688 : return decoder.toResult(nullptr);
930 : }
931 :
932 214306 : unsigned OpcodeLength(const byte* pc, const byte* end) {
933 : Decoder decoder(pc, end);
934 428612 : return WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, pc);
935 : }
936 :
937 179323 : std::pair<uint32_t, uint32_t> StackEffect(const WasmModule* module,
938 : FunctionSig* sig, const byte* pc,
939 : const byte* end) {
940 : WasmDecoder<Decoder::kNoValidate> decoder(module, sig, pc, end);
941 358646 : return decoder.StackEffect(pc);
942 : }
943 :
944 0 : void PrintRawWasmCode(const byte* start, const byte* end) {
945 0 : AccountingAllocator allocator;
946 0 : PrintRawWasmCode(&allocator, FunctionBodyForTesting(start, end), nullptr);
947 0 : }
948 :
949 : namespace {
950 0 : const char* RawOpcodeName(WasmOpcode opcode) {
951 0 : switch (opcode) {
952 : #define DECLARE_NAME_CASE(name, opcode, sig) \
953 : case kExpr##name: \
954 : return "kExpr" #name;
955 0 : FOREACH_OPCODE(DECLARE_NAME_CASE)
956 : #undef DECLARE_NAME_CASE
957 : default:
958 : break;
959 : }
960 0 : return "Unknown";
961 : }
962 : } // namespace
963 :
964 0 : bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
965 : const wasm::WasmModule* module) {
966 0 : OFStream os(stdout);
967 0 : Zone zone(allocator, ZONE_NAME);
968 : WasmDecoder<Decoder::kNoValidate> decoder(module, body.sig, body.start,
969 0 : body.end);
970 : int line_nr = 0;
971 :
972 : // Print the function signature.
973 0 : if (body.sig) {
974 0 : os << "// signature: " << *body.sig << std::endl;
975 : ++line_nr;
976 : }
977 :
978 : // Print the local declarations.
979 : BodyLocalDecls decls(&zone);
980 0 : BytecodeIterator i(body.start, body.end, &decls);
981 0 : if (body.start != i.pc() && !FLAG_wasm_code_fuzzer_gen_test) {
982 0 : os << "// locals: ";
983 0 : if (!decls.type_list.empty()) {
984 0 : ValueType type = decls.type_list[0];
985 : uint32_t count = 0;
986 0 : for (size_t pos = 0; pos < decls.type_list.size(); ++pos) {
987 0 : if (decls.type_list[pos] == type) {
988 0 : ++count;
989 : } else {
990 0 : os << " " << count << " " << WasmOpcodes::TypeName(type);
991 0 : type = decls.type_list[pos];
992 : count = 1;
993 : }
994 : }
995 : }
996 : os << std::endl;
997 : ++line_nr;
998 :
999 0 : for (const byte* locals = body.start; locals < i.pc(); locals++) {
1000 0 : os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
1001 : }
1002 : os << std::endl;
1003 : ++line_nr;
1004 : }
1005 :
1006 0 : os << "// body: " << std::endl;
1007 : ++line_nr;
1008 : unsigned control_depth = 0;
1009 0 : for (; i.has_next(); i.next()) {
1010 : unsigned length =
1011 0 : WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, i.pc());
1012 :
1013 0 : WasmOpcode opcode = i.current();
1014 0 : if (opcode == kExprElse) control_depth--;
1015 :
1016 0 : int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
1017 :
1018 : // 64 whitespaces
1019 : const char* padding =
1020 : " ";
1021 0 : os.write(padding, num_whitespaces);
1022 :
1023 0 : os << RawOpcodeName(opcode) << ",";
1024 :
1025 0 : for (unsigned j = 1; j < length; ++j) {
1026 0 : os << " 0x" << AsHex(i.pc()[j], 2) << ",";
1027 : }
1028 :
1029 0 : switch (opcode) {
1030 : case kExprElse:
1031 0 : os << " // @" << i.pc_offset();
1032 0 : control_depth++;
1033 0 : break;
1034 : case kExprLoop:
1035 : case kExprIf:
1036 : case kExprBlock:
1037 : case kExprTry: {
1038 0 : BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
1039 0 : os << " // @" << i.pc_offset();
1040 0 : for (unsigned i = 0; i < operand.out_arity(); i++) {
1041 0 : os << " " << WasmOpcodes::TypeName(operand.out_type(i));
1042 : }
1043 0 : control_depth++;
1044 : break;
1045 : }
1046 : case kExprEnd:
1047 0 : os << " // @" << i.pc_offset();
1048 0 : control_depth--;
1049 0 : break;
1050 : case kExprBr: {
1051 0 : BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
1052 0 : os << " // depth=" << operand.depth;
1053 : break;
1054 : }
1055 : case kExprBrIf: {
1056 0 : BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
1057 0 : os << " // depth=" << operand.depth;
1058 : break;
1059 : }
1060 : case kExprBrTable: {
1061 0 : BranchTableOperand<Decoder::kNoValidate> operand(&i, i.pc());
1062 0 : os << " // entries=" << operand.table_count;
1063 : break;
1064 : }
1065 : case kExprCallIndirect: {
1066 0 : CallIndirectOperand<Decoder::kNoValidate> operand(&i, i.pc());
1067 0 : os << " // sig #" << operand.index;
1068 0 : if (decoder.Complete(i.pc(), operand)) {
1069 0 : os << ": " << *operand.sig;
1070 : }
1071 : break;
1072 : }
1073 : case kExprCallFunction: {
1074 0 : CallFunctionOperand<Decoder::kNoValidate> operand(&i, i.pc());
1075 0 : os << " // function #" << operand.index;
1076 0 : if (decoder.Complete(i.pc(), operand)) {
1077 0 : os << ": " << *operand.sig;
1078 : }
1079 : break;
1080 : }
1081 : default:
1082 : break;
1083 : }
1084 : os << std::endl;
1085 : ++line_nr;
1086 : }
1087 :
1088 0 : return decoder.ok();
1089 : }
1090 :
1091 78 : BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
1092 : const byte* start, const byte* end) {
1093 : Decoder decoder(start, end);
1094 : return WasmDecoder<Decoder::kValidate>::AnalyzeLoopAssignment(
1095 156 : &decoder, start, static_cast<uint32_t>(num_locals), zone);
1096 : }
1097 :
1098 : #undef BUILD
1099 :
1100 : } // namespace wasm
1101 : } // namespace internal
1102 : } // namespace v8
|