v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
wasm-in-js-inlining-reducer-inl.h
Go to the documentation of this file.
1// Copyright 2024 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#ifndef V8_COMPILER_TURBOSHAFT_WASM_IN_JS_INLINING_REDUCER_INL_H_
6#define V8_COMPILER_TURBOSHAFT_WASM_IN_JS_INLINING_REDUCER_INL_H_
7
8#if !V8_ENABLE_WEBASSEMBLY
9#error This header should only be included if WebAssembly is enabled.
10#endif // !V8_ENABLE_WEBASSEMBLY
11
21#include "src/wasm/decoder.h"
28
30
31#define TRACE(x) \
32 do { \
33 if (v8_flags.trace_turbo_inlining) { \
34 StdoutStream() << x << std::endl; \
35 } \
36 } while (false)
37
38template <class Next>
39class WasmInJSInliningReducer : public Next {
40 public:
41 TURBOSHAFT_REDUCER_BOILERPLATE(WasmInJSInlining)
42
44 OptionalV<turboshaft::FrameState> frame_state,
45 base::Vector<const OpIndex> arguments,
46 const TSCallDescriptor* descriptor, OpEffects effects) {
47 if (!descriptor->js_wasm_call_parameters) {
48 // Regular call, nothing to do with Wasm or inlining. Proceed untouched...
49 return Next::ReduceCall(callee, frame_state, arguments, descriptor,
50 effects);
51 }
52
53 // We shouldn't have attached `JSWasmCallParameters` at this call, unless
54 // we have TS Wasm-in-JS inlining enabled.
55 CHECK(v8_flags.turboshaft_wasm_in_js_inlining);
56
57 const wasm::WasmModule* module =
58 descriptor->js_wasm_call_parameters->module();
59 wasm::NativeModule* native_module =
60 descriptor->js_wasm_call_parameters->native_module();
61 uint32_t func_idx = descriptor->js_wasm_call_parameters->function_index();
62
64 TryInlineWasmCall(module, native_module, func_idx, arguments);
65 if (result.valid()) {
66 return result;
67 } else {
68 // The JS-to-Wasm wrapper was already inlined by the earlier TurboFan
69 // phase, specifically `JSInliner::ReduceJSWasmCall`. However, it did
70 // not toggle the thread-in-Wasm flag, since we don't want to set it
71 // in the inline case above.
72 // For the non-inline case, we need to toggle the flag now.
73 // TODO(dlehmann,353475584): Reuse the code from
74 // `WasmGraphBuilderBase::BuildModifyThreadInWasmFlag`, but that
75 // requires a different assembler stack...
76 OpIndex isolate_root = __ LoadRootRegister();
77 V<WordPtr> thread_in_wasm_flag_address =
78 __ Load(isolate_root, LoadOp::Kind::RawAligned().Immutable(),
79 MemoryRepresentation::UintPtr(),
80 Isolate::thread_in_wasm_flag_address_offset());
81 __ Store(thread_in_wasm_flag_address, __ Word32Constant(1),
82 LoadOp::Kind::RawAligned(), MemoryRepresentation::Int32(),
83 compiler::kNoWriteBarrier);
84
85 result =
86 Next::ReduceCall(callee, frame_state, arguments, descriptor, effects);
87
88 __ Store(thread_in_wasm_flag_address, __ Word32Constant(0),
89 LoadOp::Kind::RawAligned(), MemoryRepresentation::Int32(),
90 compiler::kNoWriteBarrier);
91
92 return result;
93 }
94 }
95
96 private:
98 wasm::NativeModule* native_module, uint32_t func_idx,
100};
101
121using wasm::ValueType;
122using wasm::WasmOpcode;
123
124template <class Assembler>
126 public:
130 struct Value : public wasm::ValueBase<ValidationTag> {
132 template <typename... Args>
133 explicit Value(Args&&... args) V8_NOEXCEPT
134 : ValueBase(std::forward<Args>(args)...) {}
135 };
136 // TODO(dlehmann,353475584): Introduce a proper `Control` struct/class, once
137 // we want to support control-flow in the inlinee.
139 static constexpr bool kUsesPoppedArgs = false;
140
143 V<WasmTrustedInstanceData> trusted_instance_data)
144 : asm_(assembler),
145 locals_(assembler.phase_zone()),
146 arguments_(arguments),
147 trusted_instance_data_(trusted_instance_data) {}
148
149 V<Any> Result() { return result_; }
150
152
153 void Bailout(FullDecoder* decoder) {
154 decoder->errorf("unsupported operation: %s",
155 decoder->SafeOpcodeNameAt(decoder->pc()));
156 }
157
158 void StartFunction(FullDecoder* decoder) {
159 locals_.resize(decoder->num_locals());
160
161 // Initialize the function parameters, which are part of the local space.
162 CHECK_LE(arguments_.size(), locals_.size());
163 std::copy(arguments_.begin(), arguments_.end(), locals_.begin());
164
165 // Initialize the non-parameter locals.
166 uint32_t index = static_cast<uint32_t>(decoder->sig_->parameter_count());
167 CHECK_EQ(index, arguments_.size());
168 while (index < decoder->num_locals()) {
169 ValueType type = decoder->local_type(index);
170 OpIndex op;
171 if (!type.is_defaultable()) {
172 DCHECK(type.is_reference());
173 op = __ RootConstant(RootIndex::kOptimizedOut);
174 } else {
175 op = DefaultValue(type);
176 }
177 while (index < decoder->num_locals() &&
178 decoder->local_type(index) == type) {
179 locals_[index++] = op;
180 }
181 }
182 }
183 void StartFunctionBody(FullDecoder* decoder, Control* block) {}
184 void FinishFunction(FullDecoder* decoder) {}
185
187 // TODO(dlehmann,353475584): Copied from Turboshaft graph builder, still
188 // need to understand what the inlining ID is / where to get it.
189 // __ SetCurrentOrigin(
190 // WasmPositionToOpIndex(decoder->position(), inlining_id_));
191 }
192
194 // This is just for testing bailouts in Liftoff, here it's just a nop.
195 }
196
197 void TraceInstruction(FullDecoder* decoder, uint32_t markid) {
198 Bailout(decoder);
199 }
200
201 void UnOp(FullDecoder* decoder, WasmOpcode opcode, const Value& value,
202 Value* result) {
203 result->op = UnOpImpl(decoder, opcode, value.op, value.type);
204 }
205 void BinOp(FullDecoder* decoder, WasmOpcode opcode, const Value& lhs,
206 const Value& rhs, Value* result) {
207 result->op = BinOpImpl(decoder, opcode, lhs.op, rhs.op);
208 }
209
211 ValueType input_type /* for ref.is_null only*/) {
212 switch (opcode) {
213 case wasm::kExprI32Eqz:
214 return __ Word32Equal(arg, 0);
215 case wasm::kExprF32Abs:
216 return __ Float32Abs(arg);
217 case wasm::kExprF32Neg:
218 return __ Float32Negate(arg);
219 case wasm::kExprF32Sqrt:
220 return __ Float32Sqrt(arg);
221 case wasm::kExprF64Abs:
222 return __ Float64Abs(arg);
223 case wasm::kExprF64Neg:
224 return __ Float64Negate(arg);
225 case wasm::kExprF64Sqrt:
226 return __ Float64Sqrt(arg);
227 case wasm::kExprF64SConvertI32:
228 return __ ChangeInt32ToFloat64(arg);
229 case wasm::kExprF64UConvertI32:
230 return __ ChangeUint32ToFloat64(arg);
231 case wasm::kExprF32SConvertI32:
232 return __ ChangeInt32ToFloat32(arg);
233 case wasm::kExprF32UConvertI32:
234 return __ ChangeUint32ToFloat32(arg);
235 case wasm::kExprF32ConvertF64:
236 return __ TruncateFloat64ToFloat32(arg);
237 case wasm::kExprF64ConvertF32:
238 return __ ChangeFloat32ToFloat64(arg);
239 case wasm::kExprF32ReinterpretI32:
240 return __ BitcastWord32ToFloat32(arg);
241 case wasm::kExprI32ReinterpretF32:
242 return __ BitcastFloat32ToWord32(arg);
243 case wasm::kExprI32Clz:
244 return __ Word32CountLeadingZeros(arg);
245 case wasm::kExprI32SExtendI8:
246 return __ Word32SignExtend8(arg);
247 case wasm::kExprI32SExtendI16:
248 return __ Word32SignExtend16(arg);
249 case wasm::kExprRefIsNull:
250 return __ IsNull(arg, input_type);
251 case wasm::kExprRefAsNonNull:
252 // We abuse ref.as_non_null opcode (which is ordinarily a binary op and
253 // not otherwise used in this switch) as a sentinel for the negation of
254 // ref.is_null. See `function-body-decoder-impl.h`
255 return __ Word32Equal(__ IsNull(arg, input_type), 0);
256
257 // We currently don't support operations that:
258 // - could trap,
259 // - call a builtin,
260 // - need the instance,
261 // - require later Int64Lowering (which is currently only compatible with
262 // the Wasm pipeline),
263 // - are actually asm.js opcodes and not spec'ed in Wasm.
264 case wasm::kExprI32ConvertI64:
265 case wasm::kExprI64SConvertI32:
266 case wasm::kExprI64UConvertI32:
267 case wasm::kExprF64ReinterpretI64:
268 case wasm::kExprI64ReinterpretF64:
269 case wasm::kExprI64Clz:
270 case wasm::kExprI64Eqz:
271 case wasm::kExprI64SExtendI8:
272 case wasm::kExprI64SExtendI16:
273 case wasm::kExprI64SExtendI32:
274 case wasm::kExprI32SConvertF32:
275 case wasm::kExprI32UConvertF32:
276 case wasm::kExprI32SConvertF64:
277 case wasm::kExprI32UConvertF64:
278 case wasm::kExprI64SConvertF32:
279 case wasm::kExprI64UConvertF32:
280 case wasm::kExprI64SConvertF64:
281 case wasm::kExprI64UConvertF64:
282 case wasm::kExprI32SConvertSatF32:
283 case wasm::kExprI32UConvertSatF32:
284 case wasm::kExprI32SConvertSatF64:
285 case wasm::kExprI32UConvertSatF64:
286 case wasm::kExprI64SConvertSatF32:
287 case wasm::kExprI64UConvertSatF32:
288 case wasm::kExprI64SConvertSatF64:
289 case wasm::kExprI64UConvertSatF64:
290 case wasm::kExprI32Ctz:
291 case wasm::kExprI32Popcnt:
292 case wasm::kExprF32Floor:
293 case wasm::kExprF32Ceil:
294 case wasm::kExprF32Trunc:
295 case wasm::kExprF32NearestInt:
296 case wasm::kExprF64Floor:
297 case wasm::kExprF64Ceil:
298 case wasm::kExprF64Trunc:
299 case wasm::kExprF64NearestInt:
300 case wasm::kExprI64Ctz:
301 case wasm::kExprI64Popcnt:
302 case wasm::kExprF32SConvertI64:
303 case wasm::kExprF32UConvertI64:
304 case wasm::kExprF64SConvertI64:
305 case wasm::kExprF64UConvertI64:
306
307 // TODO(dlehmann): Fix arm64 no-ptr-compression builds, see relevant
308 // earlier CL https://crrev.com/c/4311941/1..4.
309 case wasm::kExprAnyConvertExtern:
310 case wasm::kExprExternConvertAny:
311
312 // asm.js:
313 case wasm::kExprF64Acos:
314 case wasm::kExprF64Asin:
315 case wasm::kExprF64Atan:
316 case wasm::kExprF64Cos:
317 case wasm::kExprF64Sin:
318 case wasm::kExprF64Tan:
319 case wasm::kExprF64Exp:
320 case wasm::kExprF64Log:
321 case wasm::kExprI32AsmjsLoadMem8S:
322 case wasm::kExprI32AsmjsLoadMem8U:
323 case wasm::kExprI32AsmjsLoadMem16S:
324 case wasm::kExprI32AsmjsLoadMem16U:
325 case wasm::kExprI32AsmjsLoadMem:
326 case wasm::kExprF32AsmjsLoadMem:
327 case wasm::kExprF64AsmjsLoadMem:
328 case wasm::kExprI32AsmjsSConvertF32:
329 case wasm::kExprI32AsmjsUConvertF32:
330 case wasm::kExprI32AsmjsSConvertF64:
331 case wasm::kExprI32AsmjsUConvertF64:
332 // Not supported, but we are aware of it. Bailout below.
333 break;
334
335 default:
336 // Fuzzers should alert us when we forget ops, but it's not security
337 // critical, so we just bailout below as well.
338 DCHECK_WITH_MSG(false, "unhandled unary op");
339 }
340
341 Bailout(decoder);
342 return OpIndex::Invalid();
343 }
344
346 OpIndex rhs) {
347 switch (opcode) {
348 case wasm::kExprI32Add:
349 return __ Word32Add(lhs, rhs);
350 case wasm::kExprI32Sub:
351 return __ Word32Sub(lhs, rhs);
352 case wasm::kExprI32Mul:
353 return __ Word32Mul(lhs, rhs);
354 case wasm::kExprI32And:
355 return __ Word32BitwiseAnd(lhs, rhs);
356 case wasm::kExprI32Ior:
357 return __ Word32BitwiseOr(lhs, rhs);
358 case wasm::kExprI32Xor:
359 return __ Word32BitwiseXor(lhs, rhs);
360 case wasm::kExprI32Shl:
361 // If possible, the bitwise-and gets optimized away later.
362 return __ Word32ShiftLeft(lhs, __ Word32BitwiseAnd(rhs, 0x1f));
363 case wasm::kExprI32ShrS:
364 return __ Word32ShiftRightArithmetic(lhs,
365 __ Word32BitwiseAnd(rhs, 0x1f));
366 case wasm::kExprI32ShrU:
367 return __ Word32ShiftRightLogical(lhs, __ Word32BitwiseAnd(rhs, 0x1f));
368 case wasm::kExprI32Ror:
369 return __ Word32RotateRight(lhs, __ Word32BitwiseAnd(rhs, 0x1f));
370 case wasm::kExprI32Rol:
371 if (SupportedOperations::word32_rol()) {
372 return __ Word32RotateLeft(lhs, __ Word32BitwiseAnd(rhs, 0x1f));
373 } else {
374 return __ Word32RotateRight(
375 lhs, __ Word32Sub(32, __ Word32BitwiseAnd(rhs, 0x1f)));
376 }
377 case wasm::kExprI32Eq:
378 return __ Word32Equal(lhs, rhs);
379 case wasm::kExprI32Ne:
380 return __ Word32Equal(__ Word32Equal(lhs, rhs), 0);
381 case wasm::kExprI32LtS:
382 return __ Int32LessThan(lhs, rhs);
383 case wasm::kExprI32LeS:
384 return __ Int32LessThanOrEqual(lhs, rhs);
385 case wasm::kExprI32LtU:
386 return __ Uint32LessThan(lhs, rhs);
387 case wasm::kExprI32LeU:
388 return __ Uint32LessThanOrEqual(lhs, rhs);
389 case wasm::kExprI32GtS:
390 return __ Int32LessThan(rhs, lhs);
391 case wasm::kExprI32GeS:
392 return __ Int32LessThanOrEqual(rhs, lhs);
393 case wasm::kExprI32GtU:
394 return __ Uint32LessThan(rhs, lhs);
395 case wasm::kExprI32GeU:
396 return __ Uint32LessThanOrEqual(rhs, lhs);
397
398 case wasm::kExprF32CopySign: {
399 V<Word32> lhs_without_sign =
400 __ Word32BitwiseAnd(__ BitcastFloat32ToWord32(lhs), 0x7fffffff);
401 V<Word32> rhs_sign =
402 __ Word32BitwiseAnd(__ BitcastFloat32ToWord32(rhs), 0x80000000);
403 return __ BitcastWord32ToFloat32(
404 __ Word32BitwiseOr(lhs_without_sign, rhs_sign));
405 }
406 case wasm::kExprF32Add:
407 return __ Float32Add(lhs, rhs);
408 case wasm::kExprF32Sub:
409 return __ Float32Sub(lhs, rhs);
410 case wasm::kExprF32Mul:
411 return __ Float32Mul(lhs, rhs);
412 case wasm::kExprF32Div:
413 return __ Float32Div(lhs, rhs);
414 case wasm::kExprF32Eq:
415 return __ Float32Equal(lhs, rhs);
416 case wasm::kExprF32Ne:
417 return __ Word32Equal(__ Float32Equal(lhs, rhs), 0);
418 case wasm::kExprF32Lt:
419 return __ Float32LessThan(lhs, rhs);
420 case wasm::kExprF32Le:
421 return __ Float32LessThanOrEqual(lhs, rhs);
422 case wasm::kExprF32Gt:
423 return __ Float32LessThan(rhs, lhs);
424 case wasm::kExprF32Ge:
425 return __ Float32LessThanOrEqual(rhs, lhs);
426 case wasm::kExprF32Min:
427 return __ Float32Min(rhs, lhs);
428 case wasm::kExprF32Max:
429 return __ Float32Max(rhs, lhs);
430 case wasm::kExprF64Add:
431 return __ Float64Add(lhs, rhs);
432 case wasm::kExprF64Sub:
433 return __ Float64Sub(lhs, rhs);
434 case wasm::kExprF64Mul:
435 return __ Float64Mul(lhs, rhs);
436 case wasm::kExprF64Div:
437 return __ Float64Div(lhs, rhs);
438 case wasm::kExprF64Eq:
439 return __ Float64Equal(lhs, rhs);
440 case wasm::kExprF64Ne:
441 return __ Word32Equal(__ Float64Equal(lhs, rhs), 0);
442 case wasm::kExprF64Lt:
443 return __ Float64LessThan(lhs, rhs);
444 case wasm::kExprF64Le:
445 return __ Float64LessThanOrEqual(lhs, rhs);
446 case wasm::kExprF64Gt:
447 return __ Float64LessThan(rhs, lhs);
448 case wasm::kExprF64Ge:
449 return __ Float64LessThanOrEqual(rhs, lhs);
450 case wasm::kExprF64Min:
451 return __ Float64Min(lhs, rhs);
452 case wasm::kExprF64Max:
453 return __ Float64Max(lhs, rhs);
454 case wasm::kExprRefEq:
455 return __ TaggedEqual(lhs, rhs);
456
457 // We currently don't support operations that:
458 // - could trap,
459 // - call a builtin,
460 // - need the instance,
461 // - require later Int64Lowering (which is currently only compatible with
462 // the Wasm pipeline),
463 // - are actually asm.js opcodes and not spec'ed in Wasm.
464 case wasm::kExprI64Add:
465 case wasm::kExprI64Sub:
466 case wasm::kExprI64Mul:
467 case wasm::kExprI64And:
468 case wasm::kExprI64Ior:
469 case wasm::kExprI64Xor:
470 case wasm::kExprI64Shl:
471 case wasm::kExprI64ShrS:
472 case wasm::kExprI64ShrU:
473 case wasm::kExprI64Ror:
474 case wasm::kExprI64Rol:
475 case wasm::kExprI64Eq:
476 case wasm::kExprI64Ne:
477 case wasm::kExprI64LtS:
478 case wasm::kExprI64LeS:
479 case wasm::kExprI64LtU:
480 case wasm::kExprI64LeU:
481 case wasm::kExprI64GtS:
482 case wasm::kExprI64GeS:
483 case wasm::kExprI64GtU:
484 case wasm::kExprI64GeU:
485
486 case wasm::kExprF64CopySign:
487
488 case wasm::kExprI32DivS:
489 case wasm::kExprI32DivU:
490 case wasm::kExprI32RemS:
491 case wasm::kExprI32RemU:
492 case wasm::kExprI64DivS:
493 case wasm::kExprI64DivU:
494 case wasm::kExprI64RemS:
495 case wasm::kExprI64RemU:
496
497 // asm.js:
498 case wasm::kExprF64Atan2:
499 case wasm::kExprF64Pow:
500 case wasm::kExprF64Mod:
501 case wasm::kExprI32AsmjsDivS:
502 case wasm::kExprI32AsmjsDivU:
503 case wasm::kExprI32AsmjsRemS:
504 case wasm::kExprI32AsmjsRemU:
505 case wasm::kExprI32AsmjsStoreMem8:
506 case wasm::kExprI32AsmjsStoreMem16:
507 case wasm::kExprI32AsmjsStoreMem:
508 case wasm::kExprF32AsmjsStoreMem:
509 case wasm::kExprF64AsmjsStoreMem:
510 // Not supported, but we are aware of it. Bailout below.
511 break;
512
513 default:
514 // Fuzzers should alert us when we forget ops, but it's not security
515 // critical, so we just bailout below as well.
516 DCHECK_WITH_MSG(false, "unhandled binary op");
517 }
518
519 Bailout(decoder);
520 return OpIndex::Invalid();
521 }
522
523 void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
524 result->op = __ Word32Constant(value);
525 }
526
527 void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
528 // TODO(dlehmann,353475584): Support i64 ops.
529 Bailout(decoder);
530 }
531
532 void F32Const(FullDecoder* decoder, Value* result, float value) {
533 result->op = __ Float32Constant(value);
534 }
535
536 void F64Const(FullDecoder* decoder, Value* result, double value) {
537 result->op = __ Float64Constant(value);
538 }
539
540 void S128Const(FullDecoder* decoder, const Simd128Immediate& imm,
541 Value* result) {
542 Bailout(decoder);
543 }
544
545 void RefNull(FullDecoder* decoder, ValueType type, Value* result) {
546 Bailout(decoder);
547 }
548
549 void RefFunc(FullDecoder* decoder, uint32_t function_index, Value* result) {
550 Bailout(decoder);
551 }
552
553 void RefAsNonNull(FullDecoder* decoder, const Value& arg, Value* result) {
554 Bailout(decoder);
555 }
556
557 void Drop(FullDecoder* decoder) {}
558
560 const IndexImmediate& imm) {
561 result->op = locals_[imm.index];
562 }
563
564 void LocalSet(FullDecoder* decoder, const Value& value,
565 const IndexImmediate& imm) {
566 locals_[imm.index] = value.op;
567 }
568
569 void LocalTee(FullDecoder* decoder, const Value& value, Value* result,
570 const IndexImmediate& imm) {
571 locals_[imm.index] = result->op = value.op;
572 }
573
575 const GlobalIndexImmediate& imm) {
576 bool shared = decoder->module_->globals[imm.index].shared;
577 if (shared) {
578 return Bailout(decoder);
579 }
581 }
582
583 void GlobalSet(FullDecoder* decoder, const Value& value,
584 const GlobalIndexImmediate& imm) {
585 bool shared = decoder->module_->globals[imm.index].shared;
586 if (shared) {
587 return Bailout(decoder);
588 }
590 }
591
592 // TODO(dlehmann,353475584): Support control-flow in the inlinee.
593
594 void Block(FullDecoder* decoder, Control* block) { Bailout(decoder); }
595 void Loop(FullDecoder* decoder, Control* block) { Bailout(decoder); }
596 void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
597 Bailout(decoder);
598 }
599 void Else(FullDecoder* decoder, Control* if_block) { Bailout(decoder); }
600 void BrOrRet(FullDecoder* decoder, uint32_t depth, uint32_t drop_values = 0) {
601 Bailout(decoder);
602 }
603 void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
604 Bailout(decoder);
605 }
606 void BrTable(FullDecoder* decoder, const BranchTableImmediate& imm,
607 const Value& key) {
608 Bailout(decoder);
609 }
610
611 void FallThruTo(FullDecoder* decoder, Control* block) { Bailout(decoder); }
612 void PopControl(FullDecoder* decoder, Control* block) { Bailout(decoder); }
613 void DoReturn(FullDecoder* decoder, uint32_t drop_values) {
614 size_t return_count = decoder->sig_->return_count();
615
616 if (return_count == 1) {
617 result_ =
618 decoder
619 ->stack_value(static_cast<uint32_t>(return_count + drop_values))
620 ->op;
621 } else if (return_count == 0) {
622 Isolate* isolate = __ data() -> isolate();
623 DCHECK_NOT_NULL(isolate);
624 result_ = __ HeapConstant(isolate->factory()->undefined_value());
625 } else {
626 // We currently don't support wrapper inlining with multi-value returns,
627 // so this should never be hit.
628 UNREACHABLE();
629 }
630 }
631 void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
632 const Value& tval, Value* result) {
633 Bailout(decoder);
634 }
635
636 // TODO(dlehmann,353475584): Support exceptions in the inlinee.
637
638 void Try(FullDecoder* decoder, Control* block) { Bailout(decoder); }
639 void Throw(FullDecoder* decoder, const TagIndexImmediate& imm,
640 const Value arg_values[]) {
641 Bailout(decoder);
642 }
643 void Rethrow(FullDecoder* decoder, Control* block) { Bailout(decoder); }
645 Control* block, base::Vector<Value> values) {
646 Bailout(decoder);
647 }
648 void Delegate(FullDecoder* decoder, uint32_t depth, Control* block) {
649 Bailout(decoder);
650 }
651
652 void CatchAll(FullDecoder* decoder, Control* block) { Bailout(decoder); }
653 void TryTable(FullDecoder* decoder, Control* block) { Bailout(decoder); }
654 void CatchCase(FullDecoder* decoder, Control* block,
655 const wasm::CatchCase& catch_case,
656 base::Vector<Value> values) {
657 Bailout(decoder);
658 }
659 void ThrowRef(FullDecoder* decoder, Value* value) { Bailout(decoder); }
660
661 void EffectHandlerTable(FullDecoder* decoder, Control* block) {
662 Bailout(decoder);
663 }
664
665 // TODO(dlehmann,353475584): Support traps in the inlinee.
666
667 void Trap(FullDecoder* decoder, wasm::TrapReason reason) { Bailout(decoder); }
668 void AssertNullTypecheck(FullDecoder* decoder, const Value& obj,
669 Value* result) {
670 Bailout(decoder);
671 }
672
673 void AssertNotNullTypecheck(FullDecoder* decoder, const Value& obj,
674 Value* result) {
675 Bailout(decoder);
676 }
678 OpIndex index, OpIndex num_waiters_to_wake, Value* result) {
679 Bailout(decoder);
680 }
681 void AtomicWait(FullDecoder* decoder, WasmOpcode opcode,
682 const MemoryAccessImmediate& imm, OpIndex index,
683 OpIndex expected, V<Word64> timeout, Value* result) {
684 Bailout(decoder);
685 }
686 void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, const Value args[],
687 const size_t argc, const MemoryAccessImmediate& imm,
688 Value* result) {
689 Bailout(decoder);
690 }
691 void AtomicFence(FullDecoder* decoder) { Bailout(decoder); }
692
693 void MemoryInit(FullDecoder* decoder, const MemoryInitImmediate& imm,
694 const Value& dst, const Value& src, const Value& size) {
695 Bailout(decoder);
696 }
697 void MemoryCopy(FullDecoder* decoder, const MemoryCopyImmediate& imm,
698 const Value& dst, const Value& src, const Value& size) {
699 Bailout(decoder);
700 }
701 void MemoryFill(FullDecoder* decoder, const MemoryIndexImmediate& imm,
702 const Value& dst, const Value& value, const Value& size) {
703 Bailout(decoder);
704 }
705 void DataDrop(FullDecoder* decoder, const IndexImmediate& imm) {
706 Bailout(decoder);
707 }
708
709 void TableGet(FullDecoder* decoder, const Value& index, Value* result,
710 const TableIndexImmediate& imm) {
711 Bailout(decoder);
712 }
713 void TableSet(FullDecoder* decoder, const Value& index, const Value& value,
714 const TableIndexImmediate& imm) {
715 Bailout(decoder);
716 }
717 void TableInit(FullDecoder* decoder, const TableInitImmediate& imm,
718 const Value& dst_val, const Value& src_val,
719 const Value& size_val) {
720 Bailout(decoder);
721 }
722 void TableCopy(FullDecoder* decoder, const TableCopyImmediate& imm,
723 const Value& dst_val, const Value& src_val,
724 const Value& size_val) {
725 Bailout(decoder);
726 }
727 void TableGrow(FullDecoder* decoder, const TableIndexImmediate& imm,
728 const Value& value, const Value& delta, Value* result) {
729 Bailout(decoder);
730 }
731 void TableFill(FullDecoder* decoder, const TableIndexImmediate& imm,
732 const Value& start, const Value& value, const Value& count) {
733 Bailout(decoder);
734 }
735 void TableSize(FullDecoder* decoder, const TableIndexImmediate& imm,
736 Value* result) {
737 Bailout(decoder);
738 }
739
740 void ElemDrop(FullDecoder* decoder, const IndexImmediate& imm) {
741 Bailout(decoder);
742 }
743
744 void StructNew(FullDecoder* decoder, const StructIndexImmediate& imm,
745 const Value& descriptor, const Value args[], Value* result) {
746 Bailout(decoder);
747 }
749 const Value& descriptor, Value* result) {
750 Bailout(decoder);
751 }
752 void StructGet(FullDecoder* decoder, const Value& struct_object,
753 const FieldImmediate& field, bool is_signed, Value* result) {
754 Bailout(decoder);
755 }
756 void StructSet(FullDecoder* decoder, const Value& struct_object,
757 const FieldImmediate& field, const Value& field_value) {
758 Bailout(decoder);
759 }
760 void ArrayNew(FullDecoder* decoder, const ArrayIndexImmediate& imm,
761 const Value& length, const Value& initial_value,
762 Value* result) {
763 Bailout(decoder);
764 }
766 const Value& length, Value* result) {
767 // TODO(dlehmann): This will pull in/cause a lot of code duplication wrt.
768 // the Wasm pipeline / `TurboshaftGraphBuildingInterface`.
769 // How to reduce duplication best? Common superclass? But both will have
770 // different Assemblers (reducer stacks), so I will have to templatize that.
771 Bailout(decoder);
772 }
773 void ArrayGet(FullDecoder* decoder, const Value& array_obj,
774 const ArrayIndexImmediate& imm, const Value& index,
775 bool is_signed, Value* result) {
776 Bailout(decoder);
777 }
778 void ArraySet(FullDecoder* decoder, const Value& array_obj,
779 const ArrayIndexImmediate& imm, const Value& index,
780 const Value& value) {
781 Bailout(decoder);
782 }
783 void ArrayLen(FullDecoder* decoder, const Value& array_obj, Value* result) {
784 Bailout(decoder);
785 }
786 void ArrayCopy(FullDecoder* decoder, const Value& dst, const Value& dst_index,
787 const Value& src, const Value& src_index,
788 const ArrayIndexImmediate& src_imm, const Value& length) {
789 Bailout(decoder);
790 }
792 const Value& array, const Value& index, const Value& value,
793 const Value& length) {
794 Bailout(decoder);
795 }
796 void ArrayNewFixed(FullDecoder* decoder, const ArrayIndexImmediate& array_imm,
797 const IndexImmediate& length_imm, const Value elements[],
798 Value* result) {
799 Bailout(decoder);
800 }
802 const ArrayIndexImmediate& array_imm,
803 const IndexImmediate& segment_imm, const Value& offset,
804 const Value& length, Value* result) {
805 Bailout(decoder);
806 }
808 const ArrayIndexImmediate& array_imm,
809 const IndexImmediate& segment_imm, const Value& array,
810 const Value& array_index, const Value& segment_offset,
811 const Value& length) {
812 Bailout(decoder);
813 }
814
815 void RefI31(FullDecoder* decoder, const Value& input, Value* result) {
816 Bailout(decoder);
817 }
818 void I31GetS(FullDecoder* decoder, const Value& input, Value* result) {
819 Bailout(decoder);
820 }
821
822 void I31GetU(FullDecoder* decoder, const Value& input, Value* result) {
823 Bailout(decoder);
824 }
825
826 void RefGetDesc(FullDecoder* decoder, const Value& ref, Value* desc) {
827 Bailout(decoder);
828 }
829
830 void RefTest(FullDecoder* decoder, wasm::HeapType target_type,
831 const Value& object, Value* result, bool null_succeeds) {
832 Bailout(decoder);
833 }
834 void RefTestAbstract(FullDecoder* decoder, const Value& object,
836 Bailout(decoder);
837 }
838 void RefCast(FullDecoder* decoder, const Value& object, Value* result) {
839 Bailout(decoder);
840 }
841 void RefCastDesc(FullDecoder* decoder, const Value& object,
842 const Value& descriptor, Value* result) {
843 Bailout(decoder);
844 }
845 void RefCastAbstract(FullDecoder* decoder, const Value& object,
847 Bailout(decoder);
848 }
849 void LoadMem(FullDecoder* decoder, wasm::LoadType type,
850 const MemoryAccessImmediate& imm, const Value& index,
851 Value* result) {
852 Bailout(decoder);
853 }
856 const MemoryAccessImmediate& imm, const Value& index,
857 Value* result) {
858 Bailout(decoder);
859 }
860 void LoadLane(FullDecoder* decoder, wasm::LoadType type, const Value& value,
861 const Value& index, const MemoryAccessImmediate& imm,
862 const uint8_t laneidx, Value* result) {
863 Bailout(decoder);
864 }
865
867 const MemoryAccessImmediate& imm, const Value& index,
868 const Value& value) {
869 Bailout(decoder);
870 }
871
873 const MemoryAccessImmediate& imm, const Value& index,
874 const Value& value, const uint8_t laneidx) {
875 Bailout(decoder);
876 }
877
879 Value* result) {
880 Bailout(decoder);
881 }
882
883 void MemoryGrow(FullDecoder* decoder, const MemoryIndexImmediate& imm,
884 const Value& value, Value* result) {
885 Bailout(decoder);
886 }
887
888 // TODO(dlehmann,353475584): Support non-leaf functions as the inlinee (i.e.,
889 // calls).
890
892 const Value args[], Value returns[]) {
893 Bailout(decoder);
894 }
896 const Value args[]) {
897 Bailout(decoder);
898 }
899 void CallIndirect(FullDecoder* decoder, const Value& index,
900 const CallIndirectImmediate& imm, const Value args[],
901 Value returns[]) {
902 Bailout(decoder);
903 }
904 void ReturnCallIndirect(FullDecoder* decoder, const Value& index,
905 const CallIndirectImmediate& imm,
906 const Value args[]) {
907 Bailout(decoder);
908 }
909 void CallRef(FullDecoder* decoder, const Value& func_ref,
910 const wasm::FunctionSig* sig, const Value args[],
911 Value returns[]) {
912 Bailout(decoder);
913 }
914
915 void ReturnCallRef(FullDecoder* decoder, const Value& func_ref,
916 const wasm::FunctionSig* sig, const Value args[]) {
917 Bailout(decoder);
918 }
919
920 void BrOnNull(FullDecoder* decoder, const Value& ref_object, uint32_t depth,
921 bool pass_null_along_branch, Value* result_on_fallthrough) {
922 Bailout(decoder);
923 }
924
925 void BrOnNonNull(FullDecoder* decoder, const Value& ref_object, Value* result,
926 uint32_t depth, bool /* drop_null_on_fallthrough */) {
927 Bailout(decoder);
928 }
929
930 void BrOnCast(FullDecoder* decoder, wasm::HeapType target_type,
931 const Value& object, Value* value_on_branch, uint32_t br_depth,
932 bool null_succeeds) {
933 Bailout(decoder);
934 }
935 void BrOnCastDesc(FullDecoder* decoder, wasm::HeapType target_type,
936 const Value& object, const Value& descriptor,
937 Value* value_on_branch, uint32_t br_depth,
938 bool null_succeeds) {
939 Bailout(decoder);
940 }
941 void BrOnCastAbstract(FullDecoder* decoder, const Value& object,
942 wasm::HeapType type, Value* value_on_branch,
943 uint32_t br_depth, bool null_succeeds) {
944 Bailout(decoder);
945 }
946 void BrOnCastFail(FullDecoder* decoder, wasm::HeapType target_type,
947 const Value& object, Value* value_on_fallthrough,
948 uint32_t br_depth, bool null_succeeds) {
949 Bailout(decoder);
950 }
951 void BrOnCastDescFail(FullDecoder* decoder, wasm::HeapType target_type,
952 const Value& object, const Value& descriptor,
953 Value* value_on_fallthrough, uint32_t br_depth,
954 bool null_succeeds) {
955 Bailout(decoder);
956 }
957 void BrOnCastFailAbstract(FullDecoder* decoder, const Value& object,
958 wasm::HeapType type, Value* value_on_fallthrough,
959 uint32_t br_depth, bool null_succeeds) {
960 Bailout(decoder);
961 }
962
963 // SIMD:
964
965 void SimdOp(FullDecoder* decoder, WasmOpcode opcode, const Value* args,
966 Value* result) {
967 Bailout(decoder);
968 }
969 void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
970 const SimdLaneImmediate& imm,
972 Bailout(decoder);
973 }
975 const Value& input0, const Value& input1,
976 Value* result) {
977 Bailout(decoder);
978 }
979
980 // String stuff:
981
983 const unibrow::Utf8Variant variant, const Value& offset,
984 const Value& size, Value* result) {
985 Bailout(decoder);
986 }
988 const unibrow::Utf8Variant variant,
989 const Value& array, const Value& start,
990 const Value& end, Value* result) {
991 Bailout(decoder);
992 }
994 const Value& offset, const Value& size, Value* result) {
995 Bailout(decoder);
996 }
997 void StringNewWtf16Array(FullDecoder* decoder, const Value& array,
998 const Value& start, const Value& end,
999 Value* result) {
1000 Bailout(decoder);
1001 }
1003 Value* result) {
1004 Bailout(decoder);
1005 }
1007 const unibrow::Utf8Variant variant, const Value& str,
1008 Value* result) {
1009 Bailout(decoder);
1010 }
1011 void StringMeasureWtf16(FullDecoder* decoder, const Value& str,
1012 Value* result) {
1013 Bailout(decoder);
1014 }
1016 const MemoryIndexImmediate& memory,
1017 const unibrow::Utf8Variant variant, const Value& str,
1018 const Value& offset, Value* result) {
1019 Bailout(decoder);
1020 }
1022 const unibrow::Utf8Variant variant,
1023 const Value& str, const Value& array,
1024 const Value& start, Value* result) {
1025 Bailout(decoder);
1026 }
1028 const Value& str, const Value& offset, Value* result) {
1029 Bailout(decoder);
1030 }
1031 void StringEncodeWtf16Array(FullDecoder* decoder, const Value& str,
1032 const Value& array, const Value& start,
1033 Value* result) {
1034 Bailout(decoder);
1035 }
1036 void StringConcat(FullDecoder* decoder, const Value& head, const Value& tail,
1037 Value* result) {
1038 Bailout(decoder);
1039 }
1040 void StringEq(FullDecoder* decoder, const Value& a, const Value& b,
1041 Value* result) {
1042 Bailout(decoder);
1043 }
1044 void StringIsUSVSequence(FullDecoder* decoder, const Value& str,
1045 Value* result) {
1046 Bailout(decoder);
1047 }
1048 void StringAsWtf8(FullDecoder* decoder, const Value& str, Value* result) {
1049 Bailout(decoder);
1050 }
1051 void StringViewWtf8Advance(FullDecoder* decoder, const Value& view,
1052 const Value& pos, const Value& bytes,
1053 Value* result) {
1054 Bailout(decoder);
1055 }
1057 const MemoryIndexImmediate& memory,
1058 const unibrow::Utf8Variant variant,
1059 const Value& view, const Value& addr,
1060 const Value& pos, const Value& bytes,
1061 Value* next_pos, Value* bytes_written) {
1062 Bailout(decoder);
1063 }
1064 void StringViewWtf8Slice(FullDecoder* decoder, const Value& view,
1065 const Value& start, const Value& end,
1066 Value* result) {
1067 Bailout(decoder);
1068 }
1069 void StringAsWtf16(FullDecoder* decoder, const Value& str, Value* result) {
1070 Bailout(decoder);
1071 }
1073 const Value& pos, Value* result) {
1074 Bailout(decoder);
1075 }
1077 const MemoryIndexImmediate& imm, const Value& view,
1078 const Value& offset, const Value& pos,
1079 const Value& codeunits, Value* result) {
1080 Bailout(decoder);
1081 }
1082 void StringViewWtf16Slice(FullDecoder* decoder, const Value& view,
1083 const Value& start, const Value& end,
1084 Value* result) {
1085 Bailout(decoder);
1086 }
1087 void StringAsIter(FullDecoder* decoder, const Value& str, Value* result) {
1088 Bailout(decoder);
1089 }
1090
1091 void StringViewIterNext(FullDecoder* decoder, const Value& view,
1092 Value* result) {
1093 Bailout(decoder);
1094 }
1095 void StringViewIterAdvance(FullDecoder* decoder, const Value& view,
1096 const Value& codepoints, Value* result) {
1097 Bailout(decoder);
1098 }
1099 void StringViewIterRewind(FullDecoder* decoder, const Value& view,
1100 const Value& codepoints, Value* result) {
1101 Bailout(decoder);
1102 }
1103 void StringViewIterSlice(FullDecoder* decoder, const Value& view,
1104 const Value& codepoints, Value* result) {
1105 Bailout(decoder);
1106 }
1107 void StringCompare(FullDecoder* decoder, const Value& lhs, const Value& rhs,
1108 Value* result) {
1109 Bailout(decoder);
1110 }
1111 void StringFromCodePoint(FullDecoder* decoder, const Value& code_point,
1112 Value* result) {
1113 Bailout(decoder);
1114 }
1115 void StringHash(FullDecoder* decoder, const Value& string, Value* result) {
1116 Bailout(decoder);
1117 }
1118
1119 void Forward(FullDecoder* decoder, const Value& from, Value* to) {
1120 Bailout(decoder);
1121 }
1122
1123 private:
1124 // TODO(dlehmann): copied from `TurboshaftGraphBuildingInterface`, DRY.
1126 switch (type.kind()) {
1127 case wasm::kI8:
1128 case wasm::kI16:
1129 case wasm::kI32:
1130 return __ Word32Constant(int32_t{0});
1131 case wasm::kI64:
1132 return __ Word64Constant(int64_t{0});
1133 case wasm::kF16:
1134 case wasm::kF32:
1135 return __ Float32Constant(0.0f);
1136 case wasm::kF64:
1137 return __ Float64Constant(0.0);
1138 case wasm::kRefNull:
1139 return __ Null(type);
1140 case wasm::kS128: {
1141 uint8_t value[kSimd128Size] = {};
1142 return __ Simd128Constant(value);
1143 }
1144 case wasm::kVoid:
1145 case wasm::kRef:
1146 case wasm::kBottom:
1147 case wasm::kTop:
1148 UNREACHABLE();
1149 }
1150 }
1151
1152 Assembler& Asm() { return asm_; }
1154
1155 // Since we don't have support for blocks and control-flow yet, this is
1156 // essentially a stripped-down version of `ssa_env_` from
1157 // `TurboshaftGraphBuildingInterface`.
1159
1160 // The arguments passed to the to-be-inlined function, _excluding_ the
1161 // Wasm instance.
1164
1165 // Populated only after decoding finished successfully, i.e., didn't bail out.
1167};
1168
1169template <class Next>
1171 const wasm::WasmModule* module, wasm::NativeModule* native_module,
1172 uint32_t func_idx, base::Vector<const OpIndex> arguments) {
1173 const wasm::WasmFunction& func = module->functions[func_idx];
1174
1175 TRACE("Considering wasm function ["
1176 << func_idx << "] "
1177 << JSInliner::WasmFunctionNameForTrace(native_module, func_idx)
1178 << " of module " << module << " for inlining");
1179
1180 if (wasm::is_asmjs_module(module)) {
1181 TRACE("- not inlining: asm.js-in-JS inlining is not supported");
1182 return OpIndex::Invalid();
1183 }
1184
1185 if (func_idx < module->num_imported_functions) {
1186 TRACE("- not inlining: call to an imported function");
1187 return OpIndex::Invalid();
1188 }
1189 DCHECK_LT(func_idx - module->num_imported_functions,
1190 module->num_declared_functions);
1191
1192 // TODO(42204563): Support shared-everything proposal (at some point, or
1193 // possibly never).
1194 bool is_shared = module->type(func.sig_index).is_shared;
1195 if (is_shared) {
1196 TRACE("- not inlining: shared everything is not supported");
1197 return OpIndex::Invalid();
1198 }
1199
1200 base::Vector<const uint8_t> module_bytes = native_module->wire_bytes();
1201 const uint8_t* start = module_bytes.begin() + func.code.offset();
1202 const uint8_t* end = module_bytes.begin() + func.code.end_offset();
1203
1204 wasm::FunctionBody func_body{func.sig, func.code.offset(), start, end,
1205 is_shared};
1206
1207 auto env = wasm::CompilationEnv::ForModule(native_module);
1208 wasm::WasmDetectedFeatures detected{};
1209
1210 // JS-to-Wasm wrapper inlining doesn't support multi-value at the moment,
1211 // so we should never reach here with more than 1 return value.
1212 DCHECK_LE(func.sig->return_count(), 1);
1213 base::Vector<const OpIndex> arguments_without_instance =
1214 arguments.SubVectorFrom(1);
1215 V<WasmTrustedInstanceData> trusted_instance_data =
1217
1218 Block* inlinee_body_and_rest = __ NewBlock();
1219 __ Goto(inlinee_body_and_rest);
1220
1221 // First pass: Decode Wasm body to see if we could inline or would bail out.
1222 // Emit into an unreachable block. We are not interested in the operations at
1223 // this point, only in the decoder status afterwards.
1224 Block* unreachable = __ NewBlock();
1225 __ Bind(unreachable);
1226
1228 using Decoder =
1230 Decoder can_inline_decoder(Asm().phase_zone(), env.module,
1231 env.enabled_features, &detected, func_body, Asm(),
1232 arguments_without_instance, trusted_instance_data);
1233 DCHECK(env.module->function_was_validated(func_idx));
1234 can_inline_decoder.Decode();
1235
1236 // The function was already validated, so decoding can only fail if we bailed
1237 // out due to an unsupported instruction.
1238 if (!can_inline_decoder.ok()) {
1239 TRACE("- not inlining: " << can_inline_decoder.error().message());
1240 __ Bind(inlinee_body_and_rest);
1241 return OpIndex::Invalid();
1242 }
1243
1244 // Second pass: Actually emit the inlinee instructions now.
1245 __ Bind(inlinee_body_and_rest);
1246 Decoder emitting_decoder(Asm().phase_zone(), env.module, env.enabled_features,
1247 &detected, func_body, Asm(),
1248 arguments_without_instance, trusted_instance_data);
1249 emitting_decoder.Decode();
1250 DCHECK(emitting_decoder.ok());
1251 DCHECK(emitting_decoder.interface().Result().valid());
1252 TRACE("- inlining");
1253 return emitting_decoder.interface().Result();
1254}
1255
1256} // namespace v8::internal::compiler::turboshaft
1257
1259
1260#endif // V8_COMPILER_TURBOSHAFT_WASM_IN_JS_INLINING_REDUCER_INL_H_
#define REDUCE(operation)
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
SourcePosition pos
Vector< T > SubVectorFrom(size_t from) const
Definition vector.h:46
constexpr T * begin() const
Definition vector.h:96
virtual void Decode(Instruction *instr)
static constexpr OpIndex Invalid()
Definition index.h:88
V< Any > TryInlineWasmCall(const wasm::WasmModule *module, wasm::NativeModule *native_module, uint32_t func_idx, base::Vector< const OpIndex > arguments)
void StringViewIterSlice(FullDecoder *decoder, const Value &view, const Value &codepoints, Value *result)
void StringViewWtf8Slice(FullDecoder *decoder, const Value &view, const Value &start, const Value &end, Value *result)
void GlobalSet(FullDecoder *decoder, const Value &value, const GlobalIndexImmediate &imm)
void StringViewWtf8Advance(FullDecoder *decoder, const Value &view, const Value &pos, const Value &bytes, Value *result)
void StructSet(FullDecoder *decoder, const Value &struct_object, const FieldImmediate &field, const Value &field_value)
void CallRef(FullDecoder *decoder, const Value &func_ref, const wasm::FunctionSig *sig, const Value args[], Value returns[])
void StringAsIter(FullDecoder *decoder, const Value &str, Value *result)
void I31GetU(FullDecoder *decoder, const Value &input, Value *result)
void AssertNullTypecheck(FullDecoder *decoder, const Value &obj, Value *result)
void ElemDrop(FullDecoder *decoder, const IndexImmediate &imm)
void BrOrRet(FullDecoder *decoder, uint32_t depth, uint32_t drop_values=0)
void CatchCase(FullDecoder *decoder, Control *block, const wasm::CatchCase &catch_case, base::Vector< Value > values)
void Select(FullDecoder *decoder, const Value &cond, const Value &fval, const Value &tval, Value *result)
void ArrayLen(FullDecoder *decoder, const Value &array_obj, Value *result)
void ArraySet(FullDecoder *decoder, const Value &array_obj, const ArrayIndexImmediate &imm, const Value &index, const Value &value)
void BrOnCastDesc(FullDecoder *decoder, wasm::HeapType target_type, const Value &object, const Value &descriptor, Value *value_on_branch, uint32_t br_depth, bool null_succeeds)
void RefCastAbstract(FullDecoder *decoder, const Value &object, wasm::HeapType type, Value *result, bool null_succeeds)
void StringNewWtf16Array(FullDecoder *decoder, const Value &array, const Value &start, const Value &end, Value *result)
void I64Const(FullDecoder *decoder, Value *result, int64_t value)
void If(FullDecoder *decoder, const Value &cond, Control *if_block)
void BrOnCastFail(FullDecoder *decoder, wasm::HeapType target_type, const Value &object, Value *value_on_fallthrough, uint32_t br_depth, bool null_succeeds)
void Throw(FullDecoder *decoder, const TagIndexImmediate &imm, const Value arg_values[])
void LocalGet(FullDecoder *decoder, Value *result, const IndexImmediate &imm)
void LocalTee(FullDecoder *decoder, const Value &value, Value *result, const IndexImmediate &imm)
void StringMeasureWtf16(FullDecoder *decoder, const Value &str, Value *result)
void AssertNotNullTypecheck(FullDecoder *decoder, const Value &obj, Value *result)
void TableSet(FullDecoder *decoder, const Value &index, const Value &value, const TableIndexImmediate &imm)
void StringViewIterNext(FullDecoder *decoder, const Value &view, Value *result)
void SimdOp(FullDecoder *decoder, WasmOpcode opcode, const Value *args, Value *result)
void CallIndirect(FullDecoder *decoder, const Value &index, const CallIndirectImmediate &imm, const Value args[], Value returns[])
void ArrayGet(FullDecoder *decoder, const Value &array_obj, const ArrayIndexImmediate &imm, const Value &index, bool is_signed, Value *result)
void BrOnCastAbstract(FullDecoder *decoder, const Value &object, wasm::HeapType type, Value *value_on_branch, uint32_t br_depth, bool null_succeeds)
void StringConcat(FullDecoder *decoder, const Value &head, const Value &tail, Value *result)
void ArrayInitSegment(FullDecoder *decoder, const ArrayIndexImmediate &array_imm, const IndexImmediate &segment_imm, const Value &array, const Value &array_index, const Value &segment_offset, const Value &length)
void AtomicNotify(FullDecoder *decoder, const MemoryAccessImmediate &imm, OpIndex index, OpIndex num_waiters_to_wake, Value *result)
void CurrentMemoryPages(FullDecoder *decoder, const MemoryIndexImmediate &imm, Value *result)
void SimdLaneOp(FullDecoder *decoder, WasmOpcode opcode, const SimdLaneImmediate &imm, base::Vector< const Value > inputs, Value *result)
void LoadMem(FullDecoder *decoder, wasm::LoadType type, const MemoryAccessImmediate &imm, const Value &index, Value *result)
void TableSize(FullDecoder *decoder, const TableIndexImmediate &imm, Value *result)
void Delegate(FullDecoder *decoder, uint32_t depth, Control *block)
void StoreLane(FullDecoder *decoder, wasm::StoreType type, const MemoryAccessImmediate &imm, const Value &index, const Value &value, const uint8_t laneidx)
void RefTestAbstract(FullDecoder *decoder, const Value &object, wasm::HeapType type, Value *result, bool null_succeeds)
void StructNew(FullDecoder *decoder, const StructIndexImmediate &imm, const Value &descriptor, const Value args[], Value *result)
void ArrayNewDefault(FullDecoder *decoder, const ArrayIndexImmediate &imm, const Value &length, Value *result)
void TableGrow(FullDecoder *decoder, const TableIndexImmediate &imm, const Value &value, const Value &delta, Value *result)
void ReturnCall(FullDecoder *decoder, const CallFunctionImmediate &imm, const Value args[])
void CallDirect(FullDecoder *decoder, const CallFunctionImmediate &imm, const Value args[], Value returns[])
void StructNewDefault(FullDecoder *decoder, const StructIndexImmediate &imm, const Value &descriptor, Value *result)
void MemoryFill(FullDecoder *decoder, const MemoryIndexImmediate &imm, const Value &dst, const Value &value, const Value &size)
void StringNewWtf16(FullDecoder *decoder, const MemoryIndexImmediate &imm, const Value &offset, const Value &size, Value *result)
void ArrayNew(FullDecoder *decoder, const ArrayIndexImmediate &imm, const Value &length, const Value &initial_value, Value *result)
void StringViewWtf16GetCodeUnit(FullDecoder *decoder, const Value &view, const Value &pos, Value *result)
void MemoryInit(FullDecoder *decoder, const MemoryInitImmediate &imm, const Value &dst, const Value &src, const Value &size)
void StringEncodeWtf16Array(FullDecoder *decoder, const Value &str, const Value &array, const Value &start, Value *result)
void LoadLane(FullDecoder *decoder, wasm::LoadType type, const Value &value, const Value &index, const MemoryAccessImmediate &imm, const uint8_t laneidx, Value *result)
void MemoryGrow(FullDecoder *decoder, const MemoryIndexImmediate &imm, const Value &value, Value *result)
void RefCastDesc(FullDecoder *decoder, const Value &object, const Value &descriptor, Value *result)
void TableGet(FullDecoder *decoder, const Value &index, Value *result, const TableIndexImmediate &imm)
void StringMeasureWtf8(FullDecoder *decoder, const unibrow::Utf8Variant variant, const Value &str, Value *result)
void ReturnCallRef(FullDecoder *decoder, const Value &func_ref, const wasm::FunctionSig *sig, const Value args[])
OpIndex UnOpImpl(FullDecoder *decoder, WasmOpcode opcode, OpIndex arg, ValueType input_type)
void StoreMem(FullDecoder *decoder, wasm::StoreType type, const MemoryAccessImmediate &imm, const Value &index, const Value &value)
void TableInit(FullDecoder *decoder, const TableInitImmediate &imm, const Value &dst_val, const Value &src_val, const Value &size_val)
void StringCompare(FullDecoder *decoder, const Value &lhs, const Value &rhs, Value *result)
void StringViewWtf16Slice(FullDecoder *decoder, const Value &view, const Value &start, const Value &end, Value *result)
void BrOnCastFailAbstract(FullDecoder *decoder, const Value &object, wasm::HeapType type, Value *value_on_fallthrough, uint32_t br_depth, bool null_succeeds)
void StringNewWtf8(FullDecoder *decoder, const MemoryIndexImmediate &imm, const unibrow::Utf8Variant variant, const Value &offset, const Value &size, Value *result)
void RefAsNonNull(FullDecoder *decoder, const Value &arg, Value *result)
void DataDrop(FullDecoder *decoder, const IndexImmediate &imm)
void StringAsWtf16(FullDecoder *decoder, const Value &str, Value *result)
void I32Const(FullDecoder *decoder, Value *result, int32_t value)
void StringEncodeWtf8(FullDecoder *decoder, const MemoryIndexImmediate &memory, const unibrow::Utf8Variant variant, const Value &str, const Value &offset, Value *result)
void BrIf(FullDecoder *decoder, const Value &cond, uint32_t depth)
void ArrayNewFixed(FullDecoder *decoder, const ArrayIndexImmediate &array_imm, const IndexImmediate &length_imm, const Value elements[], Value *result)
void StringEq(FullDecoder *decoder, const Value &a, const Value &b, Value *result)
void AtomicOp(FullDecoder *decoder, WasmOpcode opcode, const Value args[], const size_t argc, const MemoryAccessImmediate &imm, Value *result)
OpIndex BinOpImpl(FullDecoder *decoder, WasmOpcode opcode, OpIndex lhs, OpIndex rhs)
void BrOnNonNull(FullDecoder *decoder, const Value &ref_object, Value *result, uint32_t depth, bool)
void BrOnCastDescFail(FullDecoder *decoder, wasm::HeapType target_type, const Value &object, const Value &descriptor, Value *value_on_fallthrough, uint32_t br_depth, bool null_succeeds)
void StringIsUSVSequence(FullDecoder *decoder, const Value &str, Value *result)
void RefGetDesc(FullDecoder *decoder, const Value &ref, Value *desc)
void StringEncodeWtf8Array(FullDecoder *decoder, const unibrow::Utf8Variant variant, const Value &str, const Value &array, const Value &start, Value *result)
void F64Const(FullDecoder *decoder, Value *result, double value)
void BrTable(FullDecoder *decoder, const BranchTableImmediate &imm, const Value &key)
void BinOp(FullDecoder *decoder, WasmOpcode opcode, const Value &lhs, const Value &rhs, Value *result)
void LoadTransform(FullDecoder *decoder, wasm::LoadType type, wasm::LoadTransformationKind transform, const MemoryAccessImmediate &imm, const Value &index, Value *result)
void StringHash(FullDecoder *decoder, const Value &string, Value *result)
void RefNull(FullDecoder *decoder, ValueType type, Value *result)
void ReturnCallIndirect(FullDecoder *decoder, const Value &index, const CallIndirectImmediate &imm, const Value args[])
void RefFunc(FullDecoder *decoder, uint32_t function_index, Value *result)
void ArrayFill(FullDecoder *decoder, ArrayIndexImmediate &imm, const Value &array, const Value &index, const Value &value, const Value &length)
void RefI31(FullDecoder *decoder, const Value &input, Value *result)
WasmInJsInliningInterface(Assembler &assembler, base::Vector< const OpIndex > arguments, V< WasmTrustedInstanceData > trusted_instance_data)
void F32Const(FullDecoder *decoder, Value *result, float value)
void StringConst(FullDecoder *decoder, const StringConstImmediate &imm, Value *result)
void AtomicWait(FullDecoder *decoder, WasmOpcode opcode, const MemoryAccessImmediate &imm, OpIndex index, OpIndex expected, V< Word64 > timeout, Value *result)
void BrOnNull(FullDecoder *decoder, const Value &ref_object, uint32_t depth, bool pass_null_along_branch, Value *result_on_fallthrough)
void GlobalGet(FullDecoder *decoder, Value *result, const GlobalIndexImmediate &imm)
void TableFill(FullDecoder *decoder, const TableIndexImmediate &imm, const Value &start, const Value &value, const Value &count)
void BrOnCast(FullDecoder *decoder, wasm::HeapType target_type, const Value &object, Value *value_on_branch, uint32_t br_depth, bool null_succeeds)
void StringNewWtf8Array(FullDecoder *decoder, const unibrow::Utf8Variant variant, const Value &array, const Value &start, const Value &end, Value *result)
void StringViewWtf16Encode(FullDecoder *decoder, const MemoryIndexImmediate &imm, const Value &view, const Value &offset, const Value &pos, const Value &codeunits, Value *result)
void StringViewIterAdvance(FullDecoder *decoder, const Value &view, const Value &codepoints, Value *result)
void Simd8x16ShuffleOp(FullDecoder *decoder, const Simd128Immediate &imm, const Value &input0, const Value &input1, Value *result)
void LocalSet(FullDecoder *decoder, const Value &value, const IndexImmediate &imm)
void StringFromCodePoint(FullDecoder *decoder, const Value &code_point, Value *result)
void CatchException(FullDecoder *decoder, const TagIndexImmediate &imm, Control *block, base::Vector< Value > values)
void ArrayNewSegment(FullDecoder *decoder, const ArrayIndexImmediate &array_imm, const IndexImmediate &segment_imm, const Value &offset, const Value &length, Value *result)
void Forward(FullDecoder *decoder, const Value &from, Value *to)
void StringEncodeWtf16(FullDecoder *decoder, const MemoryIndexImmediate &imm, const Value &str, const Value &offset, Value *result)
void I31GetS(FullDecoder *decoder, const Value &input, Value *result)
void RefTest(FullDecoder *decoder, wasm::HeapType target_type, const Value &object, Value *result, bool null_succeeds)
void StructGet(FullDecoder *decoder, const Value &struct_object, const FieldImmediate &field, bool is_signed, Value *result)
void MemoryCopy(FullDecoder *decoder, const MemoryCopyImmediate &imm, const Value &dst, const Value &src, const Value &size)
void StringViewIterRewind(FullDecoder *decoder, const Value &view, const Value &codepoints, Value *result)
void S128Const(FullDecoder *decoder, const Simd128Immediate &imm, Value *result)
void TableCopy(FullDecoder *decoder, const TableCopyImmediate &imm, const Value &dst_val, const Value &src_val, const Value &size_val)
void StringAsWtf8(FullDecoder *decoder, const Value &str, Value *result)
void ArrayCopy(FullDecoder *decoder, const Value &dst, const Value &dst_index, const Value &src, const Value &src_index, const ArrayIndexImmediate &src_imm, const Value &length)
void StringViewWtf8Encode(FullDecoder *decoder, const MemoryIndexImmediate &memory, const unibrow::Utf8Variant variant, const Value &view, const Value &addr, const Value &pos, const Value &bytes, Value *next_pos, Value *bytes_written)
void UnOp(FullDecoder *decoder, WasmOpcode opcode, const Value &value, Value *result)
void RefCast(FullDecoder *decoder, const Value &object, Value *result)
void V8_NOINLINE V8_PRESERVE_MOST errorf(const char *format, Args... args)
Definition decoder.h:342
const uint8_t * pc() const
Definition decoder.h:408
base::Vector< const uint8_t > wire_bytes() const
ValueType local_type(uint32_t index) const
const char * SafeOpcodeNameAt(const uint8_t *pc)
#define TURBOSHAFT_REDUCER_BOILERPLATE(Name)
Definition assembler.h:823
int start
int end
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
Isolate * isolate
int32_t offset
ZoneVector< RpoNumber > & result
#define TRACE(...)
bool null_succeeds
Utf8Variant
Definition unicode.h:145
TNode< Float64T > Float64Add(TNode< Float64T > a, TNode< Float64T > b)
constexpr int kWasmInstanceDataParameterIndex
bool is_asmjs_module(const WasmModule *module)
constexpr int kSimd128Size
Definition globals.h:706
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
V8_EXPORT_PRIVATE FlagValues v8_flags
JSArrayBuffer::IsDetachableBit is_shared
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
bool is_signed(Condition cond)
const size_t segment_offset
#define V8_NOEXCEPT
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_WITH_MSG(condition, msg)
Definition logging.h:182
#define CHECK_LE(lhs, rhs)
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
static CompilationEnv ForModule(const NativeModule *native_module)
ValueBase(const uint8_t *pc, ValueType type)