5 #include "src/compiler/wasm-compiler.h" 9 #include "src/assembler-inl.h" 10 #include "src/assembler.h" 11 #include "src/base/optional.h" 12 #include "src/base/platform/elapsed-timer.h" 13 #include "src/base/platform/platform.h" 14 #include "src/base/v8-fallthrough.h" 15 #include "src/builtins/builtins.h" 16 #include "src/code-factory.h" 17 #include "src/compiler/backend/code-generator.h" 18 #include "src/compiler/backend/instruction-selector.h" 19 #include "src/compiler/common-operator.h" 20 #include "src/compiler/compiler-source-position-table.h" 21 #include "src/compiler/diamond.h" 22 #include "src/compiler/graph-visualizer.h" 23 #include "src/compiler/graph.h" 24 #include "src/compiler/int64-lowering.h" 25 #include "src/compiler/js-graph.h" 26 #include "src/compiler/js-operator.h" 27 #include "src/compiler/linkage.h" 28 #include "src/compiler/machine-operator.h" 29 #include "src/compiler/node-matchers.h" 30 #include "src/compiler/node-origin-table.h" 31 #include "src/compiler/pipeline.h" 32 #include "src/compiler/simd-scalar-lowering.h" 33 #include "src/compiler/zone-stats.h" 34 #include "src/counters.h" 35 #include "src/heap/factory.h" 36 #include "src/isolate-inl.h" 37 #include "src/log-inl.h" 38 #include "src/optimized-compilation-info.h" 39 #include "src/tracing/trace-event.h" 40 #include "src/trap-handler/trap-handler.h" 41 #include "src/wasm/function-body-decoder.h" 42 #include "src/wasm/function-compiler.h" 43 #include "src/wasm/graph-builder-interface.h" 44 #include "src/wasm/jump-table-assembler.h" 45 #include "src/wasm/memory-tracing.h" 46 #include "src/wasm/object-access.h" 47 #include "src/wasm/wasm-code-manager.h" 48 #include "src/wasm/wasm-limits.h" 49 #include "src/wasm/wasm-linkage.h" 50 #include "src/wasm/wasm-module.h" 51 #include "src/wasm/wasm-objects-inl.h" 52 #include "src/wasm/wasm-opcodes.h" 53 #include "src/wasm/wasm-text.h" 62 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 68 #define FATAL_UNSUPPORTED_OPCODE(opcode) \ 69 FATAL("Unsupported opcode 0x%x:%s", (opcode), \ 70 wasm::WasmOpcodes::OpcodeName(opcode)); 72 MachineType assert_size(
int expected_size, MachineType type) {
73 DCHECK_EQ(expected_size, ElementSizeInBytes(type.representation()));
77 #define WASM_INSTANCE_OBJECT_SIZE(name) \ 78 (WasmInstanceObject::k##name##OffsetEnd - \ 79 WasmInstanceObject::k##name##Offset + 1) // NOLINT(whitespace/indent) 81 #define WASM_INSTANCE_OBJECT_OFFSET(name) \ 82 wasm::ObjectAccess::ToTagged(WasmInstanceObject::k##name##Offset) 84 #define LOAD_RAW(base_pointer, byte_offset, type) \ 85 SetEffect(graph()->NewNode(mcgraph()->machine()->Load(type), base_pointer, \ 86 mcgraph()->Int32Constant(byte_offset), Effect(), \ 89 #define LOAD_INSTANCE_FIELD(name, type) \ 90 LOAD_RAW(instance_node_.get(), WASM_INSTANCE_OBJECT_OFFSET(name), \ 91 assert_size(WASM_INSTANCE_OBJECT_SIZE(name), type)) 93 #define LOAD_TAGGED_POINTER(base_pointer, byte_offset) \ 94 LOAD_RAW(base_pointer, byte_offset, MachineType::TaggedPointer()) 96 #define LOAD_TAGGED_ANY(base_pointer, byte_offset) \ 97 LOAD_RAW(base_pointer, byte_offset, MachineType::AnyTagged()) 99 #define LOAD_FIXED_ARRAY_SLOT(array_node, index, type) \ 100 LOAD_RAW(array_node, \ 101 wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(index), type) 103 #define LOAD_FIXED_ARRAY_SLOT_SMI(array_node, index) \ 104 LOAD_FIXED_ARRAY_SLOT(array_node, index, MachineType::TaggedSigned()) 106 #define LOAD_FIXED_ARRAY_SLOT_PTR(array_node, index) \ 107 LOAD_FIXED_ARRAY_SLOT(array_node, index, MachineType::TaggedPointer()) 109 #define LOAD_FIXED_ARRAY_SLOT_ANY(array_node, index) \ 110 LOAD_FIXED_ARRAY_SLOT(array_node, index, MachineType::AnyTagged()) 113 #define STORE_FIXED_ARRAY_SLOT_SMI(array_node, index, value) \ 114 SetEffect(graph()->NewNode( \ 115 mcgraph()->machine()->Store(StoreRepresentation( \ 116 MachineRepresentation::kTaggedSigned, kNoWriteBarrier)), \ 118 mcgraph()->Int32Constant( \ 119 wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(index)), \ 120 value, Effect(), Control())) 123 #define STORE_FIXED_ARRAY_SLOT_ANY(array_node, index, value) \ 124 SetEffect(graph()->NewNode( \ 125 mcgraph()->machine()->Store(StoreRepresentation( \ 126 MachineRepresentation::kTagged, kFullWriteBarrier)), \ 128 mcgraph()->Int32Constant( \ 129 wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(index)), \ 130 value, Effect(), Control())) 132 void MergeControlToEnd(MachineGraph* mcgraph, Node* node) {
133 Graph* g = mcgraph->graph();
135 NodeProperties::MergeControlToEnd(g, mcgraph->common(), node);
137 g->SetEnd(g->NewNode(mcgraph->common()->End(1), node));
141 bool ContainsSimd(wasm::FunctionSig* sig) {
142 for (
auto type : sig->all()) {
143 if (type == wasm::kWasmS128)
return true;
148 bool ContainsInt64(wasm::FunctionSig* sig) {
149 for (
auto type : sig->all()) {
150 if (type == wasm::kWasmI64)
return true;
156 WasmGraphBuilder::WasmGraphBuilder(
157 wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
158 wasm::FunctionSig* sig,
159 compiler::SourcePositionTable* source_position_table)
163 cur_buffer_(def_buffer_),
164 cur_bufsize_(kDefaultBufferSize),
165 has_simd_(ContainsSimd(sig)),
166 untrusted_code_mitigations_(FLAG_untrusted_code_mitigations),
168 source_position_table_(source_position_table) {
169 DCHECK_IMPLIES(use_trap_handler(), trap_handler::IsTrapHandlerEnabled());
170 DCHECK_NOT_NULL(mcgraph_);
173 Node* WasmGraphBuilder::Error() {
return mcgraph()->Dead(); }
175 Node* WasmGraphBuilder::Start(
unsigned params) {
176 Node* start = graph()->NewNode(mcgraph()->common()->Start(params));
177 graph()->SetStart(start);
181 Node* WasmGraphBuilder::Param(
unsigned index) {
182 return graph()->NewNode(mcgraph()->common()->Parameter(index),
186 Node* WasmGraphBuilder::Loop(Node* entry) {
187 return graph()->NewNode(mcgraph()->common()->Loop(1), entry);
190 Node* WasmGraphBuilder::TerminateLoop(Node* effect, Node* control) {
192 graph()->NewNode(mcgraph()->common()->Terminate(), effect, control);
193 MergeControlToEnd(mcgraph(), terminate);
197 Node* WasmGraphBuilder::TerminateThrow(Node* effect, Node* control) {
199 graph()->NewNode(mcgraph()->common()->Throw(), effect, control);
200 MergeControlToEnd(mcgraph(), terminate);
204 bool WasmGraphBuilder::IsPhiWithMerge(Node* phi, Node* merge) {
205 return phi && IrOpcode::IsPhiOpcode(phi->opcode()) &&
206 NodeProperties::GetControlInput(phi) == merge;
209 bool WasmGraphBuilder::ThrowsException(Node* node, Node** if_success,
210 Node** if_exception) {
211 if (node->op()->HasProperty(compiler::Operator::kNoThrow)) {
215 *if_success = graph()->NewNode(mcgraph()->common()->IfSuccess(), node);
217 graph()->NewNode(mcgraph()->common()->IfException(), node, node);
222 void WasmGraphBuilder::AppendToMerge(Node* merge, Node* from) {
223 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode()));
224 merge->AppendInput(mcgraph()->zone(), from);
225 int new_size = merge->InputCount();
226 NodeProperties::ChangeOp(
227 merge, mcgraph()->common()->ResizeMergeOrPhi(merge->op(), new_size));
230 void WasmGraphBuilder::AppendToPhi(Node* phi, Node* from) {
231 DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
232 int new_size = phi->InputCount();
233 phi->InsertInput(mcgraph()->zone(), phi->InputCount() - 1, from);
234 NodeProperties::ChangeOp(
235 phi, mcgraph()->common()->ResizeMergeOrPhi(phi->op(), new_size));
238 Node* WasmGraphBuilder::Merge(
unsigned count, Node** controls) {
239 return graph()->NewNode(mcgraph()->common()->Merge(count), count, controls);
242 Node* WasmGraphBuilder::Phi(wasm::ValueType type,
unsigned count, Node** vals,
244 DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
245 Node** buf = Realloc(vals, count, count + 1);
246 buf[count] = control;
247 return graph()->NewNode(
248 mcgraph()->common()->Phi(wasm::ValueTypes::MachineRepresentationFor(type),
253 Node* WasmGraphBuilder::EffectPhi(
unsigned count, Node** effects,
255 DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
256 Node** buf = Realloc(effects, count, count + 1);
257 buf[count] = control;
258 return graph()->NewNode(mcgraph()->common()->EffectPhi(count), count + 1,
262 Node* WasmGraphBuilder::RefNull() {
263 return LOAD_INSTANCE_FIELD(NullValue, MachineType::TaggedPointer());
266 Node* WasmGraphBuilder::NoContextConstant() {
268 return mcgraph()->IntPtrConstant(0);
271 Node* WasmGraphBuilder::Uint32Constant(
uint32_t value) {
272 return mcgraph()->Uint32Constant(value);
275 Node* WasmGraphBuilder::Int32Constant(int32_t value) {
276 return mcgraph()->Int32Constant(value);
279 Node* WasmGraphBuilder::Int64Constant(
int64_t value) {
280 return mcgraph()->Int64Constant(value);
283 Node* WasmGraphBuilder::IntPtrConstant(intptr_t value) {
284 return mcgraph()->IntPtrConstant(value);
287 void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
288 Node** effect, Node** control) {
289 DCHECK_NOT_NULL(env_);
290 if (FLAG_wasm_no_stack_checks || !env_->runtime_exception_support) {
293 if (effect ==
nullptr) effect = effect_;
294 if (control ==
nullptr) control = control_;
300 Node* limit_address = graph()->NewNode(
301 mcgraph()->machine()->Load(MachineType::Pointer()), instance_node_.get(),
302 mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(StackLimitAddress)),
304 Node* limit = graph()->NewNode(
305 mcgraph()->machine()->Load(MachineType::Pointer()), limit_address,
306 mcgraph()->IntPtrConstant(0), limit_address, *control);
308 Node* pointer = graph()->NewNode(mcgraph()->machine()->LoadStackPointer());
311 graph()->NewNode(mcgraph()->machine()->UintLessThan(), limit, pointer);
313 Diamond stack_check(graph(), mcgraph()->common(), check, BranchHint::kTrue);
314 stack_check.Chain(*control);
316 if (stack_check_call_operator_ ==
nullptr) {
319 auto call_descriptor = Linkage::GetStubCallDescriptor(
321 NoContextDescriptor{},
323 CallDescriptor::kNoFlags,
324 Operator::kNoProperties,
325 StubCallMode::kCallWasmRuntimeStub);
328 stack_check_code_node_.set(mcgraph()->RelocatableIntPtrConstant(
329 wasm::WasmCode::kWasmStackGuard, RelocInfo::WASM_STUB_CALL));
330 stack_check_call_operator_ = mcgraph()->common()->Call(call_descriptor);
333 Node* call = graph()->NewNode(stack_check_call_operator_.get(),
334 stack_check_code_node_.get(), *effect,
335 stack_check.if_false);
337 SetSourcePosition(call, position);
339 Node* ephi = stack_check.EffectPhi(*effect, call);
341 *control = stack_check.merge;
345 void WasmGraphBuilder::PatchInStackCheckIfNeeded() {
346 if (!needs_stack_check_)
return;
348 Node* start = graph()->start();
350 Node* dummy = graph()->NewNode(mcgraph()->common()->Dead());
351 Node* control = dummy;
352 Node* effect = dummy;
355 StackCheck(0, &effect, &control);
358 if (effect == dummy)
return;
362 NodeProperties::ReplaceUses(start, start, effect, control);
363 NodeProperties::ReplaceUses(dummy,
nullptr, start, start);
366 Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
367 wasm::WasmCodePosition position) {
369 MachineOperatorBuilder* m = mcgraph()->machine();
371 case wasm::kExprI32Add:
374 case wasm::kExprI32Sub:
377 case wasm::kExprI32Mul:
380 case wasm::kExprI32DivS:
381 return BuildI32DivS(left, right, position);
382 case wasm::kExprI32DivU:
383 return BuildI32DivU(left, right, position);
384 case wasm::kExprI32RemS:
385 return BuildI32RemS(left, right, position);
386 case wasm::kExprI32RemU:
387 return BuildI32RemU(left, right, position);
388 case wasm::kExprI32And:
391 case wasm::kExprI32Ior:
394 case wasm::kExprI32Xor:
397 case wasm::kExprI32Shl:
399 right = MaskShiftCount32(right);
401 case wasm::kExprI32ShrU:
403 right = MaskShiftCount32(right);
405 case wasm::kExprI32ShrS:
407 right = MaskShiftCount32(right);
409 case wasm::kExprI32Ror:
411 right = MaskShiftCount32(right);
413 case wasm::kExprI32Rol:
414 right = MaskShiftCount32(right);
415 return BuildI32Rol(left, right);
416 case wasm::kExprI32Eq:
417 op = m->Word32Equal();
419 case wasm::kExprI32Ne:
420 return Invert(Binop(wasm::kExprI32Eq, left, right));
421 case wasm::kExprI32LtS:
422 op = m->Int32LessThan();
424 case wasm::kExprI32LeS:
425 op = m->Int32LessThanOrEqual();
427 case wasm::kExprI32LtU:
428 op = m->Uint32LessThan();
430 case wasm::kExprI32LeU:
431 op = m->Uint32LessThanOrEqual();
433 case wasm::kExprI32GtS:
434 op = m->Int32LessThan();
435 std::swap(left, right);
437 case wasm::kExprI32GeS:
438 op = m->Int32LessThanOrEqual();
439 std::swap(left, right);
441 case wasm::kExprI32GtU:
442 op = m->Uint32LessThan();
443 std::swap(left, right);
445 case wasm::kExprI32GeU:
446 op = m->Uint32LessThanOrEqual();
447 std::swap(left, right);
449 case wasm::kExprI64And:
452 case wasm::kExprI64Add:
455 case wasm::kExprI64Sub:
458 case wasm::kExprI64Mul:
461 case wasm::kExprI64DivS:
462 return BuildI64DivS(left, right, position);
463 case wasm::kExprI64DivU:
464 return BuildI64DivU(left, right, position);
465 case wasm::kExprI64RemS:
466 return BuildI64RemS(left, right, position);
467 case wasm::kExprI64RemU:
468 return BuildI64RemU(left, right, position);
469 case wasm::kExprI64Ior:
472 case wasm::kExprI64Xor:
475 case wasm::kExprI64Shl:
477 right = MaskShiftCount64(right);
479 case wasm::kExprI64ShrU:
481 right = MaskShiftCount64(right);
483 case wasm::kExprI64ShrS:
485 right = MaskShiftCount64(right);
487 case wasm::kExprI64Eq:
488 op = m->Word64Equal();
490 case wasm::kExprI64Ne:
491 return Invert(Binop(wasm::kExprI64Eq, left, right));
492 case wasm::kExprI64LtS:
493 op = m->Int64LessThan();
495 case wasm::kExprI64LeS:
496 op = m->Int64LessThanOrEqual();
498 case wasm::kExprI64LtU:
499 op = m->Uint64LessThan();
501 case wasm::kExprI64LeU:
502 op = m->Uint64LessThanOrEqual();
504 case wasm::kExprI64GtS:
505 op = m->Int64LessThan();
506 std::swap(left, right);
508 case wasm::kExprI64GeS:
509 op = m->Int64LessThanOrEqual();
510 std::swap(left, right);
512 case wasm::kExprI64GtU:
513 op = m->Uint64LessThan();
514 std::swap(left, right);
516 case wasm::kExprI64GeU:
517 op = m->Uint64LessThanOrEqual();
518 std::swap(left, right);
520 case wasm::kExprI64Ror:
522 right = MaskShiftCount64(right);
524 case wasm::kExprI64Rol:
525 return BuildI64Rol(left, right);
526 case wasm::kExprF32CopySign:
527 return BuildF32CopySign(left, right);
528 case wasm::kExprF64CopySign:
529 return BuildF64CopySign(left, right);
530 case wasm::kExprF32Add:
531 op = m->Float32Add();
533 case wasm::kExprF32Sub:
534 op = m->Float32Sub();
536 case wasm::kExprF32Mul:
537 op = m->Float32Mul();
539 case wasm::kExprF32Div:
540 op = m->Float32Div();
542 case wasm::kExprF32Eq:
543 op = m->Float32Equal();
545 case wasm::kExprF32Ne:
546 return Invert(Binop(wasm::kExprF32Eq, left, right));
547 case wasm::kExprF32Lt:
548 op = m->Float32LessThan();
550 case wasm::kExprF32Ge:
551 op = m->Float32LessThanOrEqual();
552 std::swap(left, right);
554 case wasm::kExprF32Gt:
555 op = m->Float32LessThan();
556 std::swap(left, right);
558 case wasm::kExprF32Le:
559 op = m->Float32LessThanOrEqual();
561 case wasm::kExprF64Add:
562 op = m->Float64Add();
564 case wasm::kExprF64Sub:
565 op = m->Float64Sub();
567 case wasm::kExprF64Mul:
568 op = m->Float64Mul();
570 case wasm::kExprF64Div:
571 op = m->Float64Div();
573 case wasm::kExprF64Eq:
574 op = m->Float64Equal();
576 case wasm::kExprF64Ne:
577 return Invert(Binop(wasm::kExprF64Eq, left, right));
578 case wasm::kExprF64Lt:
579 op = m->Float64LessThan();
581 case wasm::kExprF64Le:
582 op = m->Float64LessThanOrEqual();
584 case wasm::kExprF64Gt:
585 op = m->Float64LessThan();
586 std::swap(left, right);
588 case wasm::kExprF64Ge:
589 op = m->Float64LessThanOrEqual();
590 std::swap(left, right);
592 case wasm::kExprF32Min:
593 op = m->Float32Min();
595 case wasm::kExprF64Min:
596 op = m->Float64Min();
598 case wasm::kExprF32Max:
599 op = m->Float32Max();
601 case wasm::kExprF64Max:
602 op = m->Float64Max();
604 case wasm::kExprF64Pow:
605 return BuildF64Pow(left, right);
606 case wasm::kExprF64Atan2:
607 op = m->Float64Atan2();
609 case wasm::kExprF64Mod:
610 return BuildF64Mod(left, right);
611 case wasm::kExprI32AsmjsDivS:
612 return BuildI32AsmjsDivS(left, right);
613 case wasm::kExprI32AsmjsDivU:
614 return BuildI32AsmjsDivU(left, right);
615 case wasm::kExprI32AsmjsRemS:
616 return BuildI32AsmjsRemS(left, right);
617 case wasm::kExprI32AsmjsRemU:
618 return BuildI32AsmjsRemU(left, right);
619 case wasm::kExprI32AsmjsStoreMem8:
620 return BuildAsmjsStoreMem(MachineType::Int8(), left, right);
621 case wasm::kExprI32AsmjsStoreMem16:
622 return BuildAsmjsStoreMem(MachineType::Int16(), left, right);
623 case wasm::kExprI32AsmjsStoreMem:
624 return BuildAsmjsStoreMem(MachineType::Int32(), left, right);
625 case wasm::kExprF32AsmjsStoreMem:
626 return BuildAsmjsStoreMem(MachineType::Float32(), left, right);
627 case wasm::kExprF64AsmjsStoreMem:
628 return BuildAsmjsStoreMem(MachineType::Float64(), left, right);
630 FATAL_UNSUPPORTED_OPCODE(opcode);
632 return graph()->NewNode(op, left, right);
635 Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input,
636 wasm::WasmCodePosition position) {
638 MachineOperatorBuilder* m = mcgraph()->machine();
640 case wasm::kExprI32Eqz:
641 op = m->Word32Equal();
642 return graph()->NewNode(op, input, mcgraph()->Int32Constant(0));
643 case wasm::kExprF32Abs:
644 op = m->Float32Abs();
646 case wasm::kExprF32Neg: {
647 op = m->Float32Neg();
650 case wasm::kExprF32Sqrt:
651 op = m->Float32Sqrt();
653 case wasm::kExprF64Abs:
654 op = m->Float64Abs();
656 case wasm::kExprF64Neg: {
657 op = m->Float64Neg();
660 case wasm::kExprF64Sqrt:
661 op = m->Float64Sqrt();
663 case wasm::kExprI32SConvertF32:
664 case wasm::kExprI32UConvertF32:
665 case wasm::kExprI32SConvertF64:
666 case wasm::kExprI32UConvertF64:
667 case wasm::kExprI32SConvertSatF64:
668 case wasm::kExprI32UConvertSatF64:
669 case wasm::kExprI32SConvertSatF32:
670 case wasm::kExprI32UConvertSatF32:
671 return BuildIntConvertFloat(input, position, opcode);
672 case wasm::kExprI32AsmjsSConvertF64:
673 return BuildI32AsmjsSConvertF64(input);
674 case wasm::kExprI32AsmjsUConvertF64:
675 return BuildI32AsmjsUConvertF64(input);
676 case wasm::kExprF32ConvertF64:
677 op = m->TruncateFloat64ToFloat32();
679 case wasm::kExprF64SConvertI32:
680 op = m->ChangeInt32ToFloat64();
682 case wasm::kExprF64UConvertI32:
683 op = m->ChangeUint32ToFloat64();
685 case wasm::kExprF32SConvertI32:
686 op = m->RoundInt32ToFloat32();
688 case wasm::kExprF32UConvertI32:
689 op = m->RoundUint32ToFloat32();
691 case wasm::kExprI32AsmjsSConvertF32:
692 return BuildI32AsmjsSConvertF32(input);
693 case wasm::kExprI32AsmjsUConvertF32:
694 return BuildI32AsmjsUConvertF32(input);
695 case wasm::kExprF64ConvertF32:
696 op = m->ChangeFloat32ToFloat64();
698 case wasm::kExprF32ReinterpretI32:
699 op = m->BitcastInt32ToFloat32();
701 case wasm::kExprI32ReinterpretF32:
702 op = m->BitcastFloat32ToInt32();
704 case wasm::kExprI32Clz:
707 case wasm::kExprI32Ctz: {
708 if (m->Word32Ctz().IsSupported()) {
709 op = m->Word32Ctz().op();
711 }
else if (m->Word32ReverseBits().IsSupported()) {
712 Node* reversed = graph()->NewNode(m->Word32ReverseBits().op(), input);
713 Node* result = graph()->NewNode(m->Word32Clz(), reversed);
716 return BuildI32Ctz(input);
719 case wasm::kExprI32Popcnt: {
720 if (m->Word32Popcnt().IsSupported()) {
721 op = m->Word32Popcnt().op();
724 return BuildI32Popcnt(input);
727 case wasm::kExprF32Floor: {
728 if (!m->Float32RoundDown().IsSupported())
return BuildF32Floor(input);
729 op = m->Float32RoundDown().op();
732 case wasm::kExprF32Ceil: {
733 if (!m->Float32RoundUp().IsSupported())
return BuildF32Ceil(input);
734 op = m->Float32RoundUp().op();
737 case wasm::kExprF32Trunc: {
738 if (!m->Float32RoundTruncate().IsSupported())
return BuildF32Trunc(input);
739 op = m->Float32RoundTruncate().op();
742 case wasm::kExprF32NearestInt: {
743 if (!m->Float32RoundTiesEven().IsSupported())
744 return BuildF32NearestInt(input);
745 op = m->Float32RoundTiesEven().op();
748 case wasm::kExprF64Floor: {
749 if (!m->Float64RoundDown().IsSupported())
return BuildF64Floor(input);
750 op = m->Float64RoundDown().op();
753 case wasm::kExprF64Ceil: {
754 if (!m->Float64RoundUp().IsSupported())
return BuildF64Ceil(input);
755 op = m->Float64RoundUp().op();
758 case wasm::kExprF64Trunc: {
759 if (!m->Float64RoundTruncate().IsSupported())
return BuildF64Trunc(input);
760 op = m->Float64RoundTruncate().op();
763 case wasm::kExprF64NearestInt: {
764 if (!m->Float64RoundTiesEven().IsSupported())
765 return BuildF64NearestInt(input);
766 op = m->Float64RoundTiesEven().op();
769 case wasm::kExprF64Acos: {
770 return BuildF64Acos(input);
772 case wasm::kExprF64Asin: {
773 return BuildF64Asin(input);
775 case wasm::kExprF64Atan:
776 op = m->Float64Atan();
778 case wasm::kExprF64Cos: {
779 op = m->Float64Cos();
782 case wasm::kExprF64Sin: {
783 op = m->Float64Sin();
786 case wasm::kExprF64Tan: {
787 op = m->Float64Tan();
790 case wasm::kExprF64Exp: {
791 op = m->Float64Exp();
794 case wasm::kExprF64Log:
795 op = m->Float64Log();
797 case wasm::kExprI32ConvertI64:
798 op = m->TruncateInt64ToInt32();
800 case wasm::kExprI64SConvertI32:
801 op = m->ChangeInt32ToInt64();
803 case wasm::kExprI64UConvertI32:
804 op = m->ChangeUint32ToUint64();
806 case wasm::kExprF64ReinterpretI64:
807 op = m->BitcastInt64ToFloat64();
809 case wasm::kExprI64ReinterpretF64:
810 op = m->BitcastFloat64ToInt64();
812 case wasm::kExprI64Clz:
815 case wasm::kExprI64Ctz: {
816 OptionalOperator ctz64 = m->Word64Ctz();
817 if (ctz64.IsSupported()) {
820 }
else if (m->Is32() && m->Word32Ctz().IsSupported()) {
821 op = ctz64.placeholder();
823 }
else if (m->Word64ReverseBits().IsSupported()) {
824 Node* reversed = graph()->NewNode(m->Word64ReverseBits().op(), input);
825 Node* result = graph()->NewNode(m->Word64Clz(), reversed);
828 return BuildI64Ctz(input);
831 case wasm::kExprI64Popcnt: {
832 OptionalOperator popcnt64 = m->Word64Popcnt();
833 if (popcnt64.IsSupported()) {
835 }
else if (m->Is32() && m->Word32Popcnt().IsSupported()) {
836 op = popcnt64.placeholder();
838 return BuildI64Popcnt(input);
842 case wasm::kExprI64Eqz:
843 op = m->Word64Equal();
844 return graph()->NewNode(op, input, mcgraph()->Int64Constant(0));
845 case wasm::kExprF32SConvertI64:
847 return BuildF32SConvertI64(input);
849 op = m->RoundInt64ToFloat32();
851 case wasm::kExprF32UConvertI64:
853 return BuildF32UConvertI64(input);
855 op = m->RoundUint64ToFloat32();
857 case wasm::kExprF64SConvertI64:
859 return BuildF64SConvertI64(input);
861 op = m->RoundInt64ToFloat64();
863 case wasm::kExprF64UConvertI64:
865 return BuildF64UConvertI64(input);
867 op = m->RoundUint64ToFloat64();
869 case wasm::kExprI32SExtendI8:
870 op = m->SignExtendWord8ToInt32();
872 case wasm::kExprI32SExtendI16:
873 op = m->SignExtendWord16ToInt32();
875 case wasm::kExprI64SExtendI8:
876 op = m->SignExtendWord8ToInt64();
878 case wasm::kExprI64SExtendI16:
879 op = m->SignExtendWord16ToInt64();
881 case wasm::kExprI64SExtendI32:
882 op = m->SignExtendWord32ToInt64();
884 case wasm::kExprI64SConvertF32:
885 case wasm::kExprI64UConvertF32:
886 case wasm::kExprI64SConvertF64:
887 case wasm::kExprI64UConvertF64:
888 case wasm::kExprI64SConvertSatF32:
889 case wasm::kExprI64UConvertSatF32:
890 case wasm::kExprI64SConvertSatF64:
891 case wasm::kExprI64UConvertSatF64:
892 return mcgraph()->machine()->Is32()
893 ? BuildCcallConvertFloat(input, position, opcode)
894 : BuildIntConvertFloat(input, position, opcode);
895 case wasm::kExprRefIsNull:
896 return graph()->NewNode(m->WordEqual(), input, RefNull());
897 case wasm::kExprI32AsmjsLoadMem8S:
898 return BuildAsmjsLoadMem(MachineType::Int8(), input);
899 case wasm::kExprI32AsmjsLoadMem8U:
900 return BuildAsmjsLoadMem(MachineType::Uint8(), input);
901 case wasm::kExprI32AsmjsLoadMem16S:
902 return BuildAsmjsLoadMem(MachineType::Int16(), input);
903 case wasm::kExprI32AsmjsLoadMem16U:
904 return BuildAsmjsLoadMem(MachineType::Uint16(), input);
905 case wasm::kExprI32AsmjsLoadMem:
906 return BuildAsmjsLoadMem(MachineType::Int32(), input);
907 case wasm::kExprF32AsmjsLoadMem:
908 return BuildAsmjsLoadMem(MachineType::Float32(), input);
909 case wasm::kExprF64AsmjsLoadMem:
910 return BuildAsmjsLoadMem(MachineType::Float64(), input);
912 FATAL_UNSUPPORTED_OPCODE(opcode);
914 return graph()->NewNode(op, input);
917 Node* WasmGraphBuilder::Float32Constant(
float value) {
918 return mcgraph()->Float32Constant(value);
921 Node* WasmGraphBuilder::Float64Constant(
double value) {
922 return mcgraph()->Float64Constant(value);
926 Node* Branch(MachineGraph* mcgraph, Node* cond, Node** true_node,
927 Node** false_node, Node* control, BranchHint hint) {
928 DCHECK_NOT_NULL(cond);
929 DCHECK_NOT_NULL(control);
931 mcgraph->graph()->NewNode(mcgraph->common()->Branch(hint), cond, control);
932 *true_node = mcgraph->graph()->NewNode(mcgraph->common()->IfTrue(), branch);
933 *false_node = mcgraph->graph()->NewNode(mcgraph->common()->IfFalse(), branch);
938 Node* WasmGraphBuilder::BranchNoHint(Node* cond, Node** true_node,
940 return Branch(mcgraph(), cond, true_node, false_node, Control(),
944 Node* WasmGraphBuilder::BranchExpectTrue(Node* cond, Node** true_node,
946 return Branch(mcgraph(), cond, true_node, false_node, Control(),
950 Node* WasmGraphBuilder::BranchExpectFalse(Node* cond, Node** true_node,
952 return Branch(mcgraph(), cond, true_node, false_node, Control(),
956 TrapId WasmGraphBuilder::GetTrapIdForTrap(wasm::TrapReason reason) {
959 if (!env_ || !env_->runtime_exception_support) {
963 return TrapId::kInvalid;
967 #define TRAPREASON_TO_TRAPID(name) \ 968 case wasm::k##name: \ 970 static_cast<int>(TrapId::k##name) == wasm::WasmCode::kThrowWasm##name, \ 971 "trap id mismatch"); \ 972 return TrapId::k##name; 973 FOREACH_WASM_TRAPREASON(TRAPREASON_TO_TRAPID)
974 #undef TRAPREASON_TO_TRAPID 980 Node* WasmGraphBuilder::TrapIfTrue(wasm::TrapReason reason, Node* cond,
981 wasm::WasmCodePosition position) {
982 TrapId trap_id = GetTrapIdForTrap(reason);
983 Node* node = SetControl(graph()->NewNode(mcgraph()->common()->TrapIf(trap_id),
984 cond, Effect(), Control()));
985 SetSourcePosition(node, position);
989 Node* WasmGraphBuilder::TrapIfFalse(wasm::TrapReason reason, Node* cond,
990 wasm::WasmCodePosition position) {
991 TrapId trap_id = GetTrapIdForTrap(reason);
992 Node* node = SetControl(graph()->NewNode(
993 mcgraph()->common()->TrapUnless(trap_id), cond, Effect(), Control()));
994 SetSourcePosition(node, position);
999 Node* WasmGraphBuilder::TrapIfEq32(wasm::TrapReason reason, Node* node,
1001 wasm::WasmCodePosition position) {
1002 Int32Matcher m(node);
1003 if (m.HasValue() && !m.Is(val))
return graph()->start();
1005 return TrapIfFalse(reason, node, position);
1007 return TrapIfTrue(reason,
1008 graph()->NewNode(mcgraph()->machine()->Word32Equal(),
1009 node, mcgraph()->Int32Constant(val)),
1015 Node* WasmGraphBuilder::ZeroCheck32(wasm::TrapReason reason, Node* node,
1016 wasm::WasmCodePosition position) {
1017 return TrapIfEq32(reason, node, 0, position);
1021 Node* WasmGraphBuilder::TrapIfEq64(wasm::TrapReason reason, Node* node,
1023 wasm::WasmCodePosition position) {
1024 Int64Matcher m(node);
1025 if (m.HasValue() && !m.Is(val))
return graph()->start();
1026 return TrapIfTrue(reason,
1027 graph()->NewNode(mcgraph()->machine()->Word64Equal(), node,
1028 mcgraph()->Int64Constant(val)),
1033 Node* WasmGraphBuilder::ZeroCheck64(wasm::TrapReason reason, Node* node,
1034 wasm::WasmCodePosition position) {
1035 return TrapIfEq64(reason, node, 0, position);
1038 Node* WasmGraphBuilder::Switch(
unsigned count, Node* key) {
1039 return graph()->NewNode(mcgraph()->common()->Switch(count), key, Control());
1042 Node* WasmGraphBuilder::IfValue(int32_t value, Node* sw) {
1043 DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
1044 return graph()->NewNode(mcgraph()->common()->IfValue(value), sw);
1047 Node* WasmGraphBuilder::IfDefault(Node* sw) {
1048 DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
1049 return graph()->NewNode(mcgraph()->common()->IfDefault(), sw);
1052 Node* WasmGraphBuilder::Return(
unsigned count, Node** vals) {
1053 static const int kStackAllocatedNodeBufferSize = 8;
1054 Node* stack_buffer[kStackAllocatedNodeBufferSize];
1055 std::vector<Node*> heap_buffer;
1057 Node** buf = stack_buffer;
1058 if (count + 3 > kStackAllocatedNodeBufferSize) {
1059 heap_buffer.resize(count + 3);
1060 buf = heap_buffer.data();
1063 buf[0] = mcgraph()->Int32Constant(0);
1064 memcpy(buf + 1, vals,
sizeof(
void*) * count);
1065 buf[count + 1] = Effect();
1066 buf[count + 2] = Control();
1068 graph()->NewNode(mcgraph()->common()->Return(count), count + 3, buf);
1070 MergeControlToEnd(mcgraph(), ret);
1074 Node* WasmGraphBuilder::ReturnVoid() {
return Return(0,
nullptr); }
1076 Node* WasmGraphBuilder::Unreachable(wasm::WasmCodePosition position) {
1077 TrapIfFalse(wasm::TrapReason::kTrapUnreachable, Int32Constant(0), position);
1082 Node* WasmGraphBuilder::MaskShiftCount32(Node* node) {
1083 static const int32_t kMask32 = 0x1F;
1084 if (!mcgraph()->machine()->Word32ShiftIsSafe()) {
1086 Int32Matcher match(node);
1087 if (match.HasValue()) {
1088 int32_t masked = (match.Value() & kMask32);
1089 if (match.Value() != masked) node = mcgraph()->Int32Constant(masked);
1091 node = graph()->NewNode(mcgraph()->machine()->Word32And(), node,
1092 mcgraph()->Int32Constant(kMask32));
1098 Node* WasmGraphBuilder::MaskShiftCount64(Node* node) {
1099 static const int64_t kMask64 = 0x3F;
1100 if (!mcgraph()->machine()->Word32ShiftIsSafe()) {
1102 Int64Matcher match(node);
1103 if (match.HasValue()) {
1104 int64_t masked = (match.Value() & kMask64);
1105 if (match.Value() != masked) node = mcgraph()->Int64Constant(masked);
1107 node = graph()->NewNode(mcgraph()->machine()->Word64And(), node,
1108 mcgraph()->Int64Constant(kMask64));
1114 static bool ReverseBytesSupported(MachineOperatorBuilder* m,
1115 size_t size_in_bytes) {
1116 switch (size_in_bytes) {
1128 Node* WasmGraphBuilder::BuildChangeEndiannessStore(
1129 Node* node, MachineRepresentation mem_rep, wasm::ValueType wasmtype) {
1132 MachineOperatorBuilder* m = mcgraph()->machine();
1133 int valueSizeInBytes = wasm::ValueTypes::ElementSizeInBytes(wasmtype);
1134 int valueSizeInBits = 8 * valueSizeInBytes;
1135 bool isFloat =
false;
1138 case wasm::kWasmF64:
1139 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
1142 case wasm::kWasmI64:
1143 result = mcgraph()->Int64Constant(0);
1145 case wasm::kWasmF32:
1146 value = graph()->NewNode(m->BitcastFloat32ToInt32(), node);
1149 case wasm::kWasmI32:
1150 result = mcgraph()->Int32Constant(0);
1152 case wasm::kWasmS128:
1153 DCHECK(ReverseBytesSupported(m, valueSizeInBytes));
1160 if (mem_rep == MachineRepresentation::kWord8) {
1164 if (wasmtype == wasm::kWasmI64 && mem_rep < MachineRepresentation::kWord64) {
1167 value = graph()->NewNode(m->TruncateInt64ToInt32(), value);
1168 valueSizeInBytes = wasm::ValueTypes::ElementSizeInBytes(wasm::kWasmI32);
1169 valueSizeInBits = 8 * valueSizeInBytes;
1170 if (mem_rep == MachineRepresentation::kWord16) {
1172 graph()->NewNode(m->Word32Shl(), value, mcgraph()->Int32Constant(16));
1174 }
else if (wasmtype == wasm::kWasmI32 &&
1175 mem_rep == MachineRepresentation::kWord16) {
1177 graph()->NewNode(m->Word32Shl(), value, mcgraph()->Int32Constant(16));
1183 if (ReverseBytesSupported(m, valueSizeInBytes)) {
1184 switch (valueSizeInBytes) {
1186 result = graph()->NewNode(m->Word32ReverseBytes(), value);
1189 result = graph()->NewNode(m->Word64ReverseBytes(), value);
1192 Node* byte_reversed_lanes[4];
1193 for (
int lane = 0; lane < 4; lane++) {
1194 byte_reversed_lanes[lane] = graph()->NewNode(
1195 m->Word32ReverseBytes(),
1196 graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
1202 graph()->NewNode(mcgraph()->machine()->S128And(), value, value);
1204 for (
int lane = 0; lane < 4; lane++) {
1206 graph()->NewNode(mcgraph()->machine()->I32x4ReplaceLane(3 - lane),
1207 result, byte_reversed_lanes[lane]);
1217 for (
i = 0, shiftCount = valueSizeInBits - 8;
i < valueSizeInBits / 2;
1218 i += 8, shiftCount -= 16) {
1224 DCHECK_LT(0, shiftCount);
1225 DCHECK_EQ(0, (shiftCount + 8) % 16);
1227 if (valueSizeInBits > 32) {
1228 shiftLower = graph()->NewNode(m->Word64Shl(), value,
1229 mcgraph()->Int64Constant(shiftCount));
1230 shiftHigher = graph()->NewNode(m->Word64Shr(), value,
1231 mcgraph()->Int64Constant(shiftCount));
1232 lowerByte = graph()->NewNode(
1233 m->Word64And(), shiftLower,
1234 mcgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
1235 << (valueSizeInBits - 8 -
i)));
1236 higherByte = graph()->NewNode(
1237 m->Word64And(), shiftHigher,
1238 mcgraph()->Int64Constant(static_cast<uint64_t>(0xFF) <<
i));
1239 result = graph()->NewNode(m->Word64Or(), result, lowerByte);
1240 result = graph()->NewNode(m->Word64Or(), result, higherByte);
1242 shiftLower = graph()->NewNode(m->Word32Shl(), value,
1243 mcgraph()->Int32Constant(shiftCount));
1244 shiftHigher = graph()->NewNode(m->Word32Shr(), value,
1245 mcgraph()->Int32Constant(shiftCount));
1246 lowerByte = graph()->NewNode(
1247 m->Word32And(), shiftLower,
1248 mcgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
1249 << (valueSizeInBits - 8 -
i)));
1250 higherByte = graph()->NewNode(
1251 m->Word32And(), shiftHigher,
1252 mcgraph()->Int32Constant(static_cast<uint32_t>(0xFF) <<
i));
1253 result = graph()->NewNode(m->Word32Or(), result, lowerByte);
1254 result = graph()->NewNode(m->Word32Or(), result, higherByte);
1261 case wasm::kWasmF64:
1262 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
1264 case wasm::kWasmF32:
1265 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
1276 Node* WasmGraphBuilder::BuildChangeEndiannessLoad(Node* node,
1277 MachineType memtype,
1278 wasm::ValueType wasmtype) {
1281 MachineOperatorBuilder* m = mcgraph()->machine();
1282 int valueSizeInBytes = ElementSizeInBytes(memtype.representation());
1283 int valueSizeInBits = 8 * valueSizeInBytes;
1284 bool isFloat =
false;
1286 switch (memtype.representation()) {
1287 case MachineRepresentation::kFloat64:
1288 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
1291 case MachineRepresentation::kWord64:
1292 result = mcgraph()->Int64Constant(0);
1294 case MachineRepresentation::kFloat32:
1295 value = graph()->NewNode(m->BitcastFloat32ToInt32(), node);
1298 case MachineRepresentation::kWord32:
1299 case MachineRepresentation::kWord16:
1300 result = mcgraph()->Int32Constant(0);
1302 case MachineRepresentation::kWord8:
1306 case MachineRepresentation::kSimd128:
1307 DCHECK(ReverseBytesSupported(m, valueSizeInBytes));
1317 if (ReverseBytesSupported(m, valueSizeInBytes < 4 ? 4 : valueSizeInBytes)) {
1318 switch (valueSizeInBytes) {
1321 graph()->NewNode(m->Word32ReverseBytes(),
1322 graph()->NewNode(m->Word32Shl(), value,
1323 mcgraph()->Int32Constant(16)));
1326 result = graph()->NewNode(m->Word32ReverseBytes(), value);
1329 result = graph()->NewNode(m->Word64ReverseBytes(), value);
1332 Node* byte_reversed_lanes[4];
1333 for (
int lane = 0; lane < 4; lane++) {
1334 byte_reversed_lanes[lane] = graph()->NewNode(
1335 m->Word32ReverseBytes(),
1336 graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
1342 graph()->NewNode(mcgraph()->machine()->S128And(), value, value);
1344 for (
int lane = 0; lane < 4; lane++) {
1346 graph()->NewNode(mcgraph()->machine()->I32x4ReplaceLane(3 - lane),
1347 result, byte_reversed_lanes[lane]);
1356 for (
i = 0, shiftCount = valueSizeInBits - 8;
i < valueSizeInBits / 2;
1357 i += 8, shiftCount -= 16) {
1363 DCHECK_LT(0, shiftCount);
1364 DCHECK_EQ(0, (shiftCount + 8) % 16);
1366 if (valueSizeInBits > 32) {
1367 shiftLower = graph()->NewNode(m->Word64Shl(), value,
1368 mcgraph()->Int64Constant(shiftCount));
1369 shiftHigher = graph()->NewNode(m->Word64Shr(), value,
1370 mcgraph()->Int64Constant(shiftCount));
1371 lowerByte = graph()->NewNode(
1372 m->Word64And(), shiftLower,
1373 mcgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
1374 << (valueSizeInBits - 8 -
i)));
1375 higherByte = graph()->NewNode(
1376 m->Word64And(), shiftHigher,
1377 mcgraph()->Int64Constant(static_cast<uint64_t>(0xFF) <<
i));
1378 result = graph()->NewNode(m->Word64Or(), result, lowerByte);
1379 result = graph()->NewNode(m->Word64Or(), result, higherByte);
1381 shiftLower = graph()->NewNode(m->Word32Shl(), value,
1382 mcgraph()->Int32Constant(shiftCount));
1383 shiftHigher = graph()->NewNode(m->Word32Shr(), value,
1384 mcgraph()->Int32Constant(shiftCount));
1385 lowerByte = graph()->NewNode(
1386 m->Word32And(), shiftLower,
1387 mcgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
1388 << (valueSizeInBits - 8 -
i)));
1389 higherByte = graph()->NewNode(
1390 m->Word32And(), shiftHigher,
1391 mcgraph()->Int32Constant(static_cast<uint32_t>(0xFF) <<
i));
1392 result = graph()->NewNode(m->Word32Or(), result, lowerByte);
1393 result = graph()->NewNode(m->Word32Or(), result, higherByte);
1399 switch (memtype.representation()) {
1400 case MachineRepresentation::kFloat64:
1401 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
1403 case MachineRepresentation::kFloat32:
1404 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
1413 if (memtype.IsSigned()) {
1415 if (valueSizeInBits < 32) {
1416 Node* shiftBitCount;
1420 if (wasmtype == wasm::kWasmI64) {
1421 shiftBitCount = mcgraph()->Int32Constant(64 - valueSizeInBits);
1422 result = graph()->NewNode(
1424 graph()->NewNode(m->Word64Shl(),
1425 graph()->NewNode(m->ChangeInt32ToInt64(), result),
1428 }
else if (wasmtype == wasm::kWasmI32) {
1429 shiftBitCount = mcgraph()->Int32Constant(32 - valueSizeInBits);
1430 result = graph()->NewNode(
1432 graph()->NewNode(m->Word32Shl(), result, shiftBitCount),
1441 Node* WasmGraphBuilder::BuildF32CopySign(Node* left, Node* right) {
1442 Node* result = Unop(
1443 wasm::kExprF32ReinterpretI32,
1444 Binop(wasm::kExprI32Ior,
1445 Binop(wasm::kExprI32And, Unop(wasm::kExprI32ReinterpretF32, left),
1446 mcgraph()->Int32Constant(0x7FFFFFFF)),
1447 Binop(wasm::kExprI32And, Unop(wasm::kExprI32ReinterpretF32, right),
1448 mcgraph()->Int32Constant(0x80000000))));
1453 Node* WasmGraphBuilder::BuildF64CopySign(Node* left, Node* right) {
1455 Node* result = Unop(
1456 wasm::kExprF64ReinterpretI64,
1457 Binop(wasm::kExprI64Ior,
1458 Binop(wasm::kExprI64And, Unop(wasm::kExprI64ReinterpretF64, left),
1459 mcgraph()->Int64Constant(0x7FFFFFFFFFFFFFFF)),
1460 Binop(wasm::kExprI64And, Unop(wasm::kExprI64ReinterpretF64, right),
1461 mcgraph()->Int64Constant(0x8000000000000000))));
1465 MachineOperatorBuilder* m = mcgraph()->machine();
1467 Node* high_word_left = graph()->NewNode(m->Float64ExtractHighWord32(), left);
1468 Node* high_word_right =
1469 graph()->NewNode(m->Float64ExtractHighWord32(), right);
1471 Node* new_high_word = Binop(wasm::kExprI32Ior,
1472 Binop(wasm::kExprI32And, high_word_left,
1473 mcgraph()->Int32Constant(0x7FFFFFFF)),
1474 Binop(wasm::kExprI32And, high_word_right,
1475 mcgraph()->Int32Constant(0x80000000)));
1477 return graph()->NewNode(m->Float64InsertHighWord32(), left, new_high_word);
1483 MachineType IntConvertType(wasm::WasmOpcode opcode) {
1485 case wasm::kExprI32SConvertF32:
1486 case wasm::kExprI32SConvertF64:
1487 case wasm::kExprI32SConvertSatF32:
1488 case wasm::kExprI32SConvertSatF64:
1489 return MachineType::Int32();
1490 case wasm::kExprI32UConvertF32:
1491 case wasm::kExprI32UConvertF64:
1492 case wasm::kExprI32UConvertSatF32:
1493 case wasm::kExprI32UConvertSatF64:
1494 return MachineType::Uint32();
1495 case wasm::kExprI64SConvertF32:
1496 case wasm::kExprI64SConvertF64:
1497 case wasm::kExprI64SConvertSatF32:
1498 case wasm::kExprI64SConvertSatF64:
1499 return MachineType::Int64();
1500 case wasm::kExprI64UConvertF32:
1501 case wasm::kExprI64UConvertF64:
1502 case wasm::kExprI64UConvertSatF32:
1503 case wasm::kExprI64UConvertSatF64:
1504 return MachineType::Uint64();
1510 MachineType FloatConvertType(wasm::WasmOpcode opcode) {
1512 case wasm::kExprI32SConvertF32:
1513 case wasm::kExprI32UConvertF32:
1514 case wasm::kExprI32SConvertSatF32:
1515 case wasm::kExprI64SConvertF32:
1516 case wasm::kExprI64UConvertF32:
1517 case wasm::kExprI32UConvertSatF32:
1518 case wasm::kExprI64SConvertSatF32:
1519 case wasm::kExprI64UConvertSatF32:
1520 return MachineType::Float32();
1521 case wasm::kExprI32SConvertF64:
1522 case wasm::kExprI32UConvertF64:
1523 case wasm::kExprI64SConvertF64:
1524 case wasm::kExprI64UConvertF64:
1525 case wasm::kExprI32SConvertSatF64:
1526 case wasm::kExprI32UConvertSatF64:
1527 case wasm::kExprI64SConvertSatF64:
1528 case wasm::kExprI64UConvertSatF64:
1529 return MachineType::Float64();
1535 const Operator* ConvertOp(WasmGraphBuilder* builder, wasm::WasmOpcode opcode) {
1537 case wasm::kExprI32SConvertF32:
1538 case wasm::kExprI32SConvertSatF32:
1539 return builder->mcgraph()->machine()->TruncateFloat32ToInt32();
1540 case wasm::kExprI32UConvertF32:
1541 case wasm::kExprI32UConvertSatF32:
1542 return builder->mcgraph()->machine()->TruncateFloat32ToUint32();
1543 case wasm::kExprI32SConvertF64:
1544 case wasm::kExprI32SConvertSatF64:
1545 return builder->mcgraph()->machine()->ChangeFloat64ToInt32();
1546 case wasm::kExprI32UConvertF64:
1547 case wasm::kExprI32UConvertSatF64:
1548 return builder->mcgraph()->machine()->TruncateFloat64ToUint32();
1549 case wasm::kExprI64SConvertF32:
1550 case wasm::kExprI64SConvertSatF32:
1551 return builder->mcgraph()->machine()->TryTruncateFloat32ToInt64();
1552 case wasm::kExprI64UConvertF32:
1553 case wasm::kExprI64UConvertSatF32:
1554 return builder->mcgraph()->machine()->TryTruncateFloat32ToUint64();
1555 case wasm::kExprI64SConvertF64:
1556 case wasm::kExprI64SConvertSatF64:
1557 return builder->mcgraph()->machine()->TryTruncateFloat64ToInt64();
1558 case wasm::kExprI64UConvertF64:
1559 case wasm::kExprI64UConvertSatF64:
1560 return builder->mcgraph()->machine()->TryTruncateFloat64ToUint64();
1566 wasm::WasmOpcode ConvertBackOp(wasm::WasmOpcode opcode) {
1568 case wasm::kExprI32SConvertF32:
1569 case wasm::kExprI32SConvertSatF32:
1570 return wasm::kExprF32SConvertI32;
1571 case wasm::kExprI32UConvertF32:
1572 case wasm::kExprI32UConvertSatF32:
1573 return wasm::kExprF32UConvertI32;
1574 case wasm::kExprI32SConvertF64:
1575 case wasm::kExprI32SConvertSatF64:
1576 return wasm::kExprF64SConvertI32;
1577 case wasm::kExprI32UConvertF64:
1578 case wasm::kExprI32UConvertSatF64:
1579 return wasm::kExprF64UConvertI32;
1585 bool IsTrappingConvertOp(wasm::WasmOpcode opcode) {
1587 case wasm::kExprI32SConvertF32:
1588 case wasm::kExprI32UConvertF32:
1589 case wasm::kExprI32SConvertF64:
1590 case wasm::kExprI32UConvertF64:
1591 case wasm::kExprI64SConvertF32:
1592 case wasm::kExprI64UConvertF32:
1593 case wasm::kExprI64SConvertF64:
1594 case wasm::kExprI64UConvertF64:
1596 case wasm::kExprI32SConvertSatF64:
1597 case wasm::kExprI32UConvertSatF64:
1598 case wasm::kExprI32SConvertSatF32:
1599 case wasm::kExprI32UConvertSatF32:
1600 case wasm::kExprI64SConvertSatF32:
1601 case wasm::kExprI64UConvertSatF32:
1602 case wasm::kExprI64SConvertSatF64:
1603 case wasm::kExprI64UConvertSatF64:
1610 Node* Zero(WasmGraphBuilder* builder,
const MachineType& ty) {
1611 switch (ty.representation()) {
1612 case MachineRepresentation::kWord32:
1613 return builder->Int32Constant(0);
1614 case MachineRepresentation::kWord64:
1615 return builder->Int64Constant(0);
1616 case MachineRepresentation::kFloat32:
1617 return builder->Float32Constant(0.0);
1618 case MachineRepresentation::kFloat64:
1619 return builder->Float64Constant(0.0);
1625 Node* Min(WasmGraphBuilder* builder,
const MachineType& ty) {
1626 switch (ty.semantic()) {
1627 case MachineSemantic::kInt32:
1628 return builder->Int32Constant(std::numeric_limits<int32_t>::min());
1629 case MachineSemantic::kUint32:
1630 return builder->Int32Constant(std::numeric_limits<uint32_t>::min());
1631 case MachineSemantic::kInt64:
1632 return builder->Int64Constant(std::numeric_limits<int64_t>::min());
1633 case MachineSemantic::kUint64:
1634 return builder->Int64Constant(std::numeric_limits<uint64_t>::min());
1640 Node* Max(WasmGraphBuilder* builder,
const MachineType& ty) {
1641 switch (ty.semantic()) {
1642 case MachineSemantic::kInt32:
1643 return builder->Int32Constant(std::numeric_limits<int32_t>::max());
1644 case MachineSemantic::kUint32:
1645 return builder->Int32Constant(std::numeric_limits<uint32_t>::max());
1646 case MachineSemantic::kInt64:
1647 return builder->Int64Constant(std::numeric_limits<int64_t>::max());
1648 case MachineSemantic::kUint64:
1649 return builder->Int64Constant(std::numeric_limits<uint64_t>::max());
1655 wasm::WasmOpcode TruncOp(
const MachineType& ty) {
1656 switch (ty.representation()) {
1657 case MachineRepresentation::kFloat32:
1658 return wasm::kExprF32Trunc;
1659 case MachineRepresentation::kFloat64:
1660 return wasm::kExprF64Trunc;
1666 wasm::WasmOpcode NeOp(
const MachineType& ty) {
1667 switch (ty.representation()) {
1668 case MachineRepresentation::kFloat32:
1669 return wasm::kExprF32Ne;
1670 case MachineRepresentation::kFloat64:
1671 return wasm::kExprF64Ne;
1677 wasm::WasmOpcode LtOp(
const MachineType& ty) {
1678 switch (ty.representation()) {
1679 case MachineRepresentation::kFloat32:
1680 return wasm::kExprF32Lt;
1681 case MachineRepresentation::kFloat64:
1682 return wasm::kExprF64Lt;
1688 Node* ConvertTrapTest(WasmGraphBuilder* builder, wasm::WasmOpcode opcode,
1689 const MachineType& int_ty,
const MachineType& float_ty,
1690 Node* trunc, Node* converted_value) {
1691 if (int_ty.representation() == MachineRepresentation::kWord32) {
1692 Node* check = builder->Unop(ConvertBackOp(opcode), converted_value);
1693 return builder->Binop(NeOp(float_ty), trunc, check);
1695 return builder->graph()->NewNode(builder->mcgraph()->common()->Projection(1),
1696 trunc, builder->graph()->start());
1699 Node* ConvertSaturateTest(WasmGraphBuilder* builder, wasm::WasmOpcode opcode,
1700 const MachineType& int_ty,
1701 const MachineType& float_ty, Node* trunc,
1702 Node* converted_value) {
1703 Node* test = ConvertTrapTest(builder, opcode, int_ty, float_ty, trunc,
1705 if (int_ty.representation() == MachineRepresentation::kWord64) {
1706 test = builder->Binop(wasm::kExprI64Eq, test, builder->Int64Constant(0));
1713 Node* WasmGraphBuilder::BuildIntConvertFloat(Node* input,
1714 wasm::WasmCodePosition position,
1715 wasm::WasmOpcode opcode) {
1716 const MachineType int_ty = IntConvertType(opcode);
1717 const MachineType float_ty = FloatConvertType(opcode);
1718 const Operator* conv_op = ConvertOp(
this, opcode);
1719 Node* trunc =
nullptr;
1720 Node* converted_value =
nullptr;
1721 const bool is_int32 =
1722 int_ty.representation() == MachineRepresentation::kWord32;
1724 trunc = Unop(TruncOp(float_ty), input);
1725 converted_value = graph()->NewNode(conv_op, trunc);
1727 trunc = graph()->NewNode(conv_op, input);
1728 converted_value = graph()->NewNode(mcgraph()->common()->Projection(0),
1729 trunc, graph()->start());
1731 if (IsTrappingConvertOp(opcode)) {
1733 ConvertTrapTest(
this, opcode, int_ty, float_ty, trunc, converted_value);
1735 TrapIfTrue(wasm::kTrapFloatUnrepresentable, test, position);
1737 ZeroCheck64(wasm::kTrapFloatUnrepresentable, test, position);
1739 return converted_value;
1741 Node* test = ConvertSaturateTest(
this, opcode, int_ty, float_ty, trunc,
1743 Diamond tl_d(graph(), mcgraph()->common(), test, BranchHint::kFalse);
1744 tl_d.Chain(Control());
1745 Node* nan_test = Binop(NeOp(float_ty), input, input);
1746 Diamond nan_d(graph(), mcgraph()->common(), nan_test, BranchHint::kFalse);
1747 nan_d.Nest(tl_d,
true);
1748 Node* neg_test = Binop(LtOp(float_ty), input, Zero(
this, float_ty));
1749 Diamond sat_d(graph(), mcgraph()->common(), neg_test, BranchHint::kNone);
1750 sat_d.Nest(nan_d,
false);
1752 sat_d.Phi(int_ty.representation(), Min(
this, int_ty), Max(
this, int_ty));
1754 nan_d.Phi(int_ty.representation(), Zero(
this, int_ty), sat_val);
1755 return tl_d.Phi(int_ty.representation(), nan_val, converted_value);
1758 Node* WasmGraphBuilder::BuildI32AsmjsSConvertF32(Node* input) {
1759 MachineOperatorBuilder* m = mcgraph()->machine();
1761 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
1762 return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
1765 Node* WasmGraphBuilder::BuildI32AsmjsSConvertF64(Node* input) {
1766 MachineOperatorBuilder* m = mcgraph()->machine();
1768 return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
1771 Node* WasmGraphBuilder::BuildI32AsmjsUConvertF32(Node* input) {
1772 MachineOperatorBuilder* m = mcgraph()->machine();
1774 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
1775 return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
1778 Node* WasmGraphBuilder::BuildI32AsmjsUConvertF64(Node* input) {
1779 MachineOperatorBuilder* m = mcgraph()->machine();
1781 return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
1784 Node* WasmGraphBuilder::BuildBitCountingCall(Node* input, ExternalReference ref,
1785 MachineRepresentation input_type) {
1786 Node* stack_slot_param =
1787 graph()->NewNode(mcgraph()->machine()->StackSlot(input_type));
1789 const Operator* store_op = mcgraph()->machine()->Store(
1790 StoreRepresentation(input_type, kNoWriteBarrier));
1791 SetEffect(graph()->NewNode(store_op, stack_slot_param,
1792 mcgraph()->Int32Constant(0), input, Effect(),
1795 MachineType sig_types[] = {MachineType::Int32(), MachineType::Pointer()};
1796 MachineSignature sig(1, 1, sig_types);
1798 Node*
function = graph()->NewNode(mcgraph()->common()->ExternalConstant(ref));
1800 return BuildCCall(&sig,
function, stack_slot_param);
1803 Node* WasmGraphBuilder::BuildI32Ctz(Node* input) {
1804 return BuildBitCountingCall(input, ExternalReference::wasm_word32_ctz(),
1805 MachineRepresentation::kWord32);
1808 Node* WasmGraphBuilder::BuildI64Ctz(Node* input) {
1809 return Unop(wasm::kExprI64UConvertI32,
1810 BuildBitCountingCall(input, ExternalReference::wasm_word64_ctz(),
1811 MachineRepresentation::kWord64));
1814 Node* WasmGraphBuilder::BuildI32Popcnt(Node* input) {
1815 return BuildBitCountingCall(input, ExternalReference::wasm_word32_popcnt(),
1816 MachineRepresentation::kWord32);
1819 Node* WasmGraphBuilder::BuildI64Popcnt(Node* input) {
1821 wasm::kExprI64UConvertI32,
1822 BuildBitCountingCall(input, ExternalReference::wasm_word64_popcnt(),
1823 MachineRepresentation::kWord64));
1826 Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
1827 MachineType type = MachineType::Float32();
1828 ExternalReference ref = ExternalReference::wasm_f32_trunc();
1830 return BuildCFuncInstruction(ref, type, input);
1833 Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
1834 MachineType type = MachineType::Float32();
1835 ExternalReference ref = ExternalReference::wasm_f32_floor();
1836 return BuildCFuncInstruction(ref, type, input);
1839 Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
1840 MachineType type = MachineType::Float32();
1841 ExternalReference ref = ExternalReference::wasm_f32_ceil();
1842 return BuildCFuncInstruction(ref, type, input);
1845 Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
1846 MachineType type = MachineType::Float32();
1847 ExternalReference ref = ExternalReference::wasm_f32_nearest_int();
1848 return BuildCFuncInstruction(ref, type, input);
1851 Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
1852 MachineType type = MachineType::Float64();
1853 ExternalReference ref = ExternalReference::wasm_f64_trunc();
1854 return BuildCFuncInstruction(ref, type, input);
1857 Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
1858 MachineType type = MachineType::Float64();
1859 ExternalReference ref = ExternalReference::wasm_f64_floor();
1860 return BuildCFuncInstruction(ref, type, input);
1863 Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
1864 MachineType type = MachineType::Float64();
1865 ExternalReference ref = ExternalReference::wasm_f64_ceil();
1866 return BuildCFuncInstruction(ref, type, input);
1869 Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
1870 MachineType type = MachineType::Float64();
1871 ExternalReference ref = ExternalReference::wasm_f64_nearest_int();
1872 return BuildCFuncInstruction(ref, type, input);
1875 Node* WasmGraphBuilder::BuildF64Acos(Node* input) {
1876 MachineType type = MachineType::Float64();
1877 ExternalReference ref = ExternalReference::f64_acos_wrapper_function();
1878 return BuildCFuncInstruction(ref, type, input);
1881 Node* WasmGraphBuilder::BuildF64Asin(Node* input) {
1882 MachineType type = MachineType::Float64();
1883 ExternalReference ref = ExternalReference::f64_asin_wrapper_function();
1884 return BuildCFuncInstruction(ref, type, input);
1887 Node* WasmGraphBuilder::BuildF64Pow(Node* left, Node* right) {
1888 MachineType type = MachineType::Float64();
1889 ExternalReference ref = ExternalReference::wasm_float64_pow();
1890 return BuildCFuncInstruction(ref, type, left, right);
1893 Node* WasmGraphBuilder::BuildF64Mod(Node* left, Node* right) {
1894 MachineType type = MachineType::Float64();
1895 ExternalReference ref = ExternalReference::f64_mod_wrapper_function();
1896 return BuildCFuncInstruction(ref, type, left, right);
1899 Node* WasmGraphBuilder::BuildCFuncInstruction(ExternalReference ref,
1900 MachineType type, Node* input0,
1909 const int type_size = ElementSizeInBytes(type.representation());
1910 const int stack_slot_bytes = (input1 ==
nullptr ? 1 : 2) * type_size;
1912 graph()->NewNode(mcgraph()->machine()->StackSlot(stack_slot_bytes));
1914 const Operator* store_op = mcgraph()->machine()->Store(
1915 StoreRepresentation(type.representation(), kNoWriteBarrier));
1916 SetEffect(graph()->NewNode(store_op, stack_slot, mcgraph()->Int32Constant(0),
1917 input0, Effect(), Control()));
1919 Node*
function = graph()->NewNode(mcgraph()->common()->ExternalConstant(ref));
1921 if (input1 !=
nullptr) {
1922 SetEffect(graph()->NewNode(store_op, stack_slot,
1923 mcgraph()->Int32Constant(type_size), input1,
1924 Effect(), Control()));
1927 MachineType sig_types[] = {MachineType::Pointer()};
1928 MachineSignature sig(0, 1, sig_types);
1929 BuildCCall(&sig,
function, stack_slot);
1931 return SetEffect(graph()->NewNode(mcgraph()->machine()->Load(type),
1932 stack_slot, mcgraph()->Int32Constant(0),
1933 Effect(), Control()));
1936 Node* WasmGraphBuilder::BuildF32SConvertI64(Node* input) {
1938 return BuildIntToFloatConversionInstruction(
1939 input, ExternalReference::wasm_int64_to_float32(),
1940 MachineRepresentation::kWord64, MachineType::Float32());
1942 Node* WasmGraphBuilder::BuildF32UConvertI64(Node* input) {
1944 return BuildIntToFloatConversionInstruction(
1945 input, ExternalReference::wasm_uint64_to_float32(),
1946 MachineRepresentation::kWord64, MachineType::Float32());
1948 Node* WasmGraphBuilder::BuildF64SConvertI64(Node* input) {
1949 return BuildIntToFloatConversionInstruction(
1950 input, ExternalReference::wasm_int64_to_float64(),
1951 MachineRepresentation::kWord64, MachineType::Float64());
1953 Node* WasmGraphBuilder::BuildF64UConvertI64(Node* input) {
1954 return BuildIntToFloatConversionInstruction(
1955 input, ExternalReference::wasm_uint64_to_float64(),
1956 MachineRepresentation::kWord64, MachineType::Float64());
1959 Node* WasmGraphBuilder::BuildIntToFloatConversionInstruction(
1960 Node* input, ExternalReference ref,
1961 MachineRepresentation parameter_representation,
1962 const MachineType result_type) {
1963 int stack_slot_size =
1964 std::max(ElementSizeInBytes(parameter_representation),
1965 ElementSizeInBytes(result_type.representation()));
1967 graph()->NewNode(mcgraph()->machine()->StackSlot(stack_slot_size));
1968 const Operator* store_op = mcgraph()->machine()->Store(
1969 StoreRepresentation(parameter_representation, kNoWriteBarrier));
1970 SetEffect(graph()->NewNode(store_op, stack_slot, mcgraph()->Int32Constant(0),
1971 input, Effect(), Control()));
1972 MachineType sig_types[] = {MachineType::Pointer()};
1973 MachineSignature sig(0, 1, sig_types);
1974 Node*
function = graph()->NewNode(mcgraph()->common()->ExternalConstant(ref));
1975 BuildCCall(&sig,
function, stack_slot);
1976 return SetEffect(graph()->NewNode(mcgraph()->machine()->Load(result_type),
1977 stack_slot, mcgraph()->Int32Constant(0),
1978 Effect(), Control()));
1983 ExternalReference convert_ccall_ref(WasmGraphBuilder* builder,
1984 wasm::WasmOpcode opcode) {
1986 case wasm::kExprI64SConvertF32:
1987 case wasm::kExprI64SConvertSatF32:
1988 return ExternalReference::wasm_float32_to_int64();
1989 case wasm::kExprI64UConvertF32:
1990 case wasm::kExprI64UConvertSatF32:
1991 return ExternalReference::wasm_float32_to_uint64();
1992 case wasm::kExprI64SConvertF64:
1993 case wasm::kExprI64SConvertSatF64:
1994 return ExternalReference::wasm_float64_to_int64();
1995 case wasm::kExprI64UConvertF64:
1996 case wasm::kExprI64UConvertSatF64:
1997 return ExternalReference::wasm_float64_to_uint64();
2005 Node* WasmGraphBuilder::BuildCcallConvertFloat(Node* input,
2006 wasm::WasmCodePosition position,
2007 wasm::WasmOpcode opcode) {
2008 const MachineType int_ty = IntConvertType(opcode);
2009 const MachineType float_ty = FloatConvertType(opcode);
2010 ExternalReference call_ref = convert_ccall_ref(
this, opcode);
2011 int stack_slot_size = std::max(ElementSizeInBytes(int_ty.representation()),
2012 ElementSizeInBytes(float_ty.representation()));
2014 graph()->NewNode(mcgraph()->machine()->StackSlot(stack_slot_size));
2015 const Operator* store_op = mcgraph()->machine()->Store(
2016 StoreRepresentation(float_ty.representation(), kNoWriteBarrier));
2017 SetEffect(graph()->NewNode(store_op, stack_slot, Int32Constant(0), input,
2018 Effect(), Control()));
2019 MachineType sig_types[] = {MachineType::Int32(), MachineType::Pointer()};
2020 MachineSignature sig(1, 1, sig_types);
2022 graph()->NewNode(mcgraph()->common()->ExternalConstant(call_ref));
2023 Node* overflow = BuildCCall(&sig,
function, stack_slot);
2024 if (IsTrappingConvertOp(opcode)) {
2025 ZeroCheck32(wasm::kTrapFloatUnrepresentable, overflow, position);
2026 return SetEffect(graph()->NewNode(mcgraph()->machine()->Load(int_ty),
2027 stack_slot, Int32Constant(0), Effect(),
2030 Node* test = Binop(wasm::kExprI32Eq, overflow, Int32Constant(0), position);
2031 Diamond tl_d(graph(), mcgraph()->common(), test, BranchHint::kFalse);
2032 tl_d.Chain(Control());
2033 Node* nan_test = Binop(NeOp(float_ty), input, input);
2034 Diamond nan_d(graph(), mcgraph()->common(), nan_test, BranchHint::kFalse);
2035 nan_d.Nest(tl_d,
true);
2036 Node* neg_test = Binop(LtOp(float_ty), input, Zero(
this, float_ty));
2037 Diamond sat_d(graph(), mcgraph()->common(), neg_test, BranchHint::kNone);
2038 sat_d.Nest(nan_d,
false);
2040 sat_d.Phi(int_ty.representation(), Min(
this, int_ty), Max(
this, int_ty));
2042 SetEffect(graph()->NewNode(mcgraph()->machine()->Load(int_ty), stack_slot,
2043 Int32Constant(0), Effect(), Control()));
2045 nan_d.Phi(int_ty.representation(), Zero(
this, int_ty), sat_val);
2046 return tl_d.Phi(int_ty.representation(), nan_val, load);
2049 Node* WasmGraphBuilder::MemoryGrow(Node* input) {
2050 needs_stack_check_ =
true;
2052 WasmMemoryGrowDescriptor interface_descriptor;
2053 auto call_descriptor = Linkage::GetStubCallDescriptor(
2055 interface_descriptor,
2056 interface_descriptor.GetStackParameterCount(),
2057 CallDescriptor::kNoFlags,
2058 Operator::kNoProperties,
2059 StubCallMode::kCallWasmRuntimeStub);
2062 Node* call_target = mcgraph()->RelocatableIntPtrConstant(
2063 wasm::WasmCode::kWasmMemoryGrow, RelocInfo::WASM_STUB_CALL);
2065 SetControl(graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
2066 call_target, input, Effect(), Control())));
2073 constexpr
uint32_t kBytesPerExceptionValuesArrayElement = 2;
2075 size_t ComputeEncodedElementSize(wasm::ValueType type) {
2077 static_cast<size_t>(wasm::ValueTypes::ElementSizeInBytes(type));
2078 DCHECK_EQ(byte_size % kBytesPerExceptionValuesArrayElement, 0);
2079 DCHECK_LE(1, byte_size / kBytesPerExceptionValuesArrayElement);
2080 return byte_size / kBytesPerExceptionValuesArrayElement;
2087 uint32_t WasmGraphBuilder::GetExceptionEncodedSize(
2088 const wasm::WasmException* exception)
const {
2089 const wasm::WasmExceptionSig* sig = exception->sig;
2091 for (
size_t i = 0;
i < sig->parameter_count(); ++
i) {
2092 switch (sig->GetParam(
i)) {
2093 case wasm::kWasmI32:
2094 case wasm::kWasmF32:
2095 DCHECK_EQ(2, ComputeEncodedElementSize(sig->GetParam(
i)));
2098 case wasm::kWasmI64:
2099 case wasm::kWasmF64:
2100 DCHECK_EQ(4, ComputeEncodedElementSize(sig->GetParam(
i)));
2103 case wasm::kWasmS128:
2107 case wasm::kWasmAnyRef:
2114 return encoded_size;
2117 Node* WasmGraphBuilder::Throw(
uint32_t exception_index,
2118 const wasm::WasmException* exception,
2119 const Vector<Node*> values) {
2120 needs_stack_check_ =
true;
2121 uint32_t encoded_size = GetExceptionEncodedSize(exception);
2122 Node* create_parameters[] = {
2123 LoadExceptionTagFromTable(exception_index),
2124 BuildChangeUint31ToSmi(Uint32Constant(encoded_size))};
2126 BuildCallToRuntime(Runtime::kWasmThrowCreate, create_parameters,
2127 arraysize(create_parameters));
2128 Node* values_array =
2129 BuildCallToRuntime(Runtime::kWasmExceptionGetValues, &except_obj, 1);
2131 const wasm::WasmExceptionSig* sig = exception->sig;
2132 MachineOperatorBuilder* m = mcgraph()->machine();
2133 for (
size_t i = 0;
i < sig->parameter_count(); ++
i) {
2134 Node* value = values[
i];
2135 switch (sig->GetParam(
i)) {
2136 case wasm::kWasmF32:
2137 value = graph()->NewNode(m->BitcastFloat32ToInt32(), value);
2139 case wasm::kWasmI32:
2140 BuildEncodeException32BitValue(values_array, &index, value);
2142 case wasm::kWasmF64:
2143 value = graph()->NewNode(m->BitcastFloat64ToInt64(), value);
2145 case wasm::kWasmI64: {
2146 Node* upper32 = graph()->NewNode(
2147 m->TruncateInt64ToInt32(),
2148 Binop(wasm::kExprI64ShrU, value, Int64Constant(32)));
2149 BuildEncodeException32BitValue(values_array, &index, upper32);
2150 Node* lower32 = graph()->NewNode(m->TruncateInt64ToInt32(), value);
2151 BuildEncodeException32BitValue(values_array, &index, lower32);
2154 case wasm::kWasmAnyRef:
2155 STORE_FIXED_ARRAY_SLOT_ANY(values_array, index, value);
2162 DCHECK_EQ(encoded_size, index);
2163 WasmThrowDescriptor interface_descriptor;
2164 auto call_descriptor = Linkage::GetStubCallDescriptor(
2165 mcgraph()->zone(), interface_descriptor,
2166 interface_descriptor.GetStackParameterCount(), CallDescriptor::kNoFlags,
2167 Operator::kNoProperties, StubCallMode::kCallWasmRuntimeStub);
2168 Node* call_target = mcgraph()->RelocatableIntPtrConstant(
2169 wasm::WasmCode::kWasmThrow, RelocInfo::WASM_STUB_CALL);
2170 return SetEffect(SetControl(
2171 graph()->NewNode(mcgraph()->common()->Call(call_descriptor), call_target,
2172 except_obj, Effect(), Control())));
2175 void WasmGraphBuilder::BuildEncodeException32BitValue(Node* values_array,
2178 MachineOperatorBuilder* machine = mcgraph()->machine();
2179 Node* upper_halfword_as_smi = BuildChangeUint31ToSmi(
2180 graph()->NewNode(machine->Word32Shr(), value, Int32Constant(16)));
2181 STORE_FIXED_ARRAY_SLOT_SMI(values_array, *index, upper_halfword_as_smi);
2183 Node* lower_halfword_as_smi = BuildChangeUint31ToSmi(
2184 graph()->NewNode(machine->Word32And(), value, Int32Constant(0xFFFFu)));
2185 STORE_FIXED_ARRAY_SLOT_SMI(values_array, *index, lower_halfword_as_smi);
2189 Node* WasmGraphBuilder::BuildDecodeException32BitValue(Node* values_array,
2191 MachineOperatorBuilder* machine = mcgraph()->machine();
2193 BuildChangeSmiToInt32(LOAD_FIXED_ARRAY_SLOT_SMI(values_array, *index));
2195 upper = graph()->NewNode(machine->Word32Shl(), upper, Int32Constant(16));
2197 BuildChangeSmiToInt32(LOAD_FIXED_ARRAY_SLOT_SMI(values_array, *index));
2199 Node* value = graph()->NewNode(machine->Word32Or(), upper, lower);
2203 Node* WasmGraphBuilder::BuildDecodeException64BitValue(Node* values_array,
2205 Node* upper = Binop(wasm::kExprI64Shl,
2206 Unop(wasm::kExprI64UConvertI32,
2207 BuildDecodeException32BitValue(values_array, index)),
2209 Node* lower = Unop(wasm::kExprI64UConvertI32,
2210 BuildDecodeException32BitValue(values_array, index));
2211 return Binop(wasm::kExprI64Ior, upper, lower);
2214 Node* WasmGraphBuilder::Rethrow(Node* except_obj) {
2215 needs_stack_check_ =
true;
2216 WasmThrowDescriptor interface_descriptor;
2217 auto call_descriptor = Linkage::GetStubCallDescriptor(
2218 mcgraph()->zone(), interface_descriptor,
2219 interface_descriptor.GetStackParameterCount(), CallDescriptor::kNoFlags,
2220 Operator::kNoProperties, StubCallMode::kCallWasmRuntimeStub);
2221 Node* call_target = mcgraph()->RelocatableIntPtrConstant(
2222 wasm::WasmCode::kWasmThrow, RelocInfo::WASM_STUB_CALL);
2223 return SetEffect(SetControl(
2224 graph()->NewNode(mcgraph()->common()->Call(call_descriptor), call_target,
2225 except_obj, Effect(), Control())));
2228 Node* WasmGraphBuilder::ExceptionTagEqual(Node* caught_tag,
2229 Node* expected_tag) {
2230 MachineOperatorBuilder* machine = mcgraph()->machine();
2231 return graph()->NewNode(machine->WordEqual(), caught_tag, expected_tag);
2234 Node* WasmGraphBuilder::LoadExceptionTagFromTable(
uint32_t exception_index) {
2235 Node* exceptions_table =
2236 LOAD_INSTANCE_FIELD(ExceptionsTable, MachineType::TaggedPointer());
2237 Node* tag = LOAD_FIXED_ARRAY_SLOT_PTR(exceptions_table, exception_index);
2241 Node* WasmGraphBuilder::GetExceptionTag(Node* except_obj) {
2242 needs_stack_check_ =
true;
2243 return BuildCallToRuntime(Runtime::kWasmExceptionGetTag, &except_obj, 1);
2246 Node** WasmGraphBuilder::GetExceptionValues(
2247 Node* except_obj,
const wasm::WasmException* exception) {
2248 Node* values_array =
2249 BuildCallToRuntime(Runtime::kWasmExceptionGetValues, &except_obj, 1);
2251 const wasm::WasmExceptionSig* sig = exception->sig;
2252 Node** values = Buffer(sig->parameter_count());
2253 for (
size_t i = 0;
i < sig->parameter_count(); ++
i) {
2255 switch (sig->GetParam(
i)) {
2256 case wasm::kWasmI32:
2257 value = BuildDecodeException32BitValue(values_array, &index);
2259 case wasm::kWasmI64:
2260 value = BuildDecodeException64BitValue(values_array, &index);
2262 case wasm::kWasmF32: {
2263 value = Unop(wasm::kExprF32ReinterpretI32,
2264 BuildDecodeException32BitValue(values_array, &index));
2267 case wasm::kWasmF64: {
2268 value = Unop(wasm::kExprF64ReinterpretI64,
2269 BuildDecodeException64BitValue(values_array, &index));
2272 case wasm::kWasmAnyRef:
2273 value = LOAD_FIXED_ARRAY_SLOT_ANY(values_array, index);
2281 DCHECK_EQ(index, GetExceptionEncodedSize(exception));
2285 Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right,
2286 wasm::WasmCodePosition position) {
2287 MachineOperatorBuilder* m = mcgraph()->machine();
2288 ZeroCheck32(wasm::kTrapDivByZero, right, position);
2289 Node* before = Control();
2291 Node* denom_is_not_m1;
2293 graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(-1)),
2294 &denom_is_m1, &denom_is_not_m1);
2295 SetControl(denom_is_m1);
2296 TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt, position);
2297 if (Control() != denom_is_m1) {
2298 SetControl(graph()->NewNode(mcgraph()->common()->Merge(2), denom_is_not_m1,
2303 return graph()->NewNode(m->Int32Div(), left, right, Control());
2306 Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right,
2307 wasm::WasmCodePosition position) {
2308 MachineOperatorBuilder* m = mcgraph()->machine();
2310 ZeroCheck32(wasm::kTrapRemByZero, right, position);
2313 graph(), mcgraph()->common(),
2314 graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(-1)),
2315 BranchHint::kFalse);
2318 return d.Phi(MachineRepresentation::kWord32, mcgraph()->Int32Constant(0),
2319 graph()->NewNode(m->Int32Mod(), left, right, d.if_false));
2322 Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right,
2323 wasm::WasmCodePosition position) {
2324 MachineOperatorBuilder* m = mcgraph()->machine();
2325 return graph()->NewNode(m->Uint32Div(), left, right,
2326 ZeroCheck32(wasm::kTrapDivByZero, right, position));
2329 Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right,
2330 wasm::WasmCodePosition position) {
2331 MachineOperatorBuilder* m = mcgraph()->machine();
2332 return graph()->NewNode(m->Uint32Mod(), left, right,
2333 ZeroCheck32(wasm::kTrapRemByZero, right, position));
2336 Node* WasmGraphBuilder::BuildI32AsmjsDivS(Node* left, Node* right) {
2337 MachineOperatorBuilder* m = mcgraph()->machine();
2339 Int32Matcher mr(right);
2340 if (mr.HasValue()) {
2341 if (mr.Value() == 0) {
2342 return mcgraph()->Int32Constant(0);
2343 }
else if (mr.Value() == -1) {
2345 return graph()->NewNode(m->Int32Sub(), mcgraph()->Int32Constant(0), left);
2347 return graph()->NewNode(m->Int32Div(), left, right, Control());
2351 if (m->Int32DivIsSafe()) {
2353 return graph()->NewNode(m->Int32Div(), left, right, graph()->start());
2358 graph(), mcgraph()->common(),
2359 graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(0)),
2360 BranchHint::kFalse);
2364 graph(), mcgraph()->common(),
2365 graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(-1)),
2366 BranchHint::kFalse);
2368 Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false);
2370 graph()->NewNode(m->Int32Sub(), mcgraph()->Int32Constant(0), left);
2373 MachineRepresentation::kWord32, neg,
2374 z.Phi(MachineRepresentation::kWord32, mcgraph()->Int32Constant(0), div));
2377 Node* WasmGraphBuilder::BuildI32AsmjsRemS(Node* left, Node* right) {
2378 CommonOperatorBuilder* c = mcgraph()->common();
2379 MachineOperatorBuilder* m = mcgraph()->machine();
2380 Node*
const zero = mcgraph()->Int32Constant(0);
2382 Int32Matcher mr(right);
2383 if (mr.HasValue()) {
2384 if (mr.Value() == 0 || mr.Value() == -1) {
2387 return graph()->NewNode(m->Int32Mod(), left, right, Control());
2410 Node*
const minus_one = mcgraph()->Int32Constant(-1);
2412 const Operator*
const merge_op = c->Merge(2);
2413 const Operator*
const phi_op = c->Phi(MachineRepresentation::kWord32, 2);
2415 Node* check0 = graph()->NewNode(m->Int32LessThan(), zero, right);
2417 graph()->NewNode(c->Branch(BranchHint::kTrue), check0, graph()->start());
2419 Node* if_true0 = graph()->NewNode(c->IfTrue(), branch0);
2422 Node* msk = graph()->NewNode(m->Int32Add(), right, minus_one);
2424 Node* check1 = graph()->NewNode(m->Word32And(), right, msk);
2425 Node* branch1 = graph()->NewNode(c->Branch(), check1, if_true0);
2427 Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
2428 Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
2430 Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
2433 Node* check2 = graph()->NewNode(m->Int32LessThan(), left, zero);
2435 graph()->NewNode(c->Branch(BranchHint::kFalse), check2, if_false1);
2437 Node* if_true2 = graph()->NewNode(c->IfTrue(), branch2);
2438 Node* true2 = graph()->NewNode(
2439 m->Int32Sub(), zero,
2440 graph()->NewNode(m->Word32And(),
2441 graph()->NewNode(m->Int32Sub(), zero, left), msk));
2443 Node* if_false2 = graph()->NewNode(c->IfFalse(), branch2);
2444 Node* false2 = graph()->NewNode(m->Word32And(), left, msk);
2446 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
2447 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
2450 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
2451 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
2454 Node* if_false0 = graph()->NewNode(c->IfFalse(), branch0);
2457 Node* check1 = graph()->NewNode(m->Int32LessThan(), right, minus_one);
2459 graph()->NewNode(c->Branch(BranchHint::kTrue), check1, if_false0);
2461 Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
2462 Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
2464 Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
2465 Node* false1 = zero;
2467 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
2468 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
2471 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
2472 return graph()->NewNode(phi_op, true0, false0, merge0);
2475 Node* WasmGraphBuilder::BuildI32AsmjsDivU(Node* left, Node* right) {
2476 MachineOperatorBuilder* m = mcgraph()->machine();
2478 if (m->Uint32DivIsSafe()) {
2480 return graph()->NewNode(m->Uint32Div(), left, right, graph()->start());
2485 graph(), mcgraph()->common(),
2486 graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(0)),
2487 BranchHint::kFalse);
2489 return z.Phi(MachineRepresentation::kWord32, mcgraph()->Int32Constant(0),
2490 graph()->NewNode(mcgraph()->machine()->Uint32Div(), left, right,
2494 Node* WasmGraphBuilder::BuildI32AsmjsRemU(Node* left, Node* right) {
2495 MachineOperatorBuilder* m = mcgraph()->machine();
2499 graph(), mcgraph()->common(),
2500 graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(0)),
2501 BranchHint::kFalse);
2503 Node* rem = graph()->NewNode(mcgraph()->machine()->Uint32Mod(), left, right,
2505 return z.Phi(MachineRepresentation::kWord32, mcgraph()->Int32Constant(0),
2509 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right,
2510 wasm::WasmCodePosition position) {
2511 if (mcgraph()->machine()->Is32()) {
2512 return BuildDiv64Call(left, right, ExternalReference::wasm_int64_div(),
2513 MachineType::Int64(), wasm::kTrapDivByZero, position);
2515 ZeroCheck64(wasm::kTrapDivByZero, right, position);
2516 Node* before = Control();
2518 Node* denom_is_not_m1;
2519 BranchExpectFalse(graph()->NewNode(mcgraph()->machine()->Word64Equal(), right,
2520 mcgraph()->Int64Constant(-1)),
2521 &denom_is_m1, &denom_is_not_m1);
2522 SetControl(denom_is_m1);
2523 TrapIfEq64(wasm::kTrapDivUnrepresentable, left,
2524 std::numeric_limits<int64_t>::min(), position);
2525 if (Control() != denom_is_m1) {
2526 SetControl(graph()->NewNode(mcgraph()->common()->Merge(2), denom_is_not_m1,
2531 return graph()->NewNode(mcgraph()->machine()->Int64Div(), left, right,
2535 Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right,
2536 wasm::WasmCodePosition position) {
2537 if (mcgraph()->machine()->Is32()) {
2538 return BuildDiv64Call(left, right, ExternalReference::wasm_int64_mod(),
2539 MachineType::Int64(), wasm::kTrapRemByZero, position);
2541 ZeroCheck64(wasm::kTrapRemByZero, right, position);
2542 Diamond d(mcgraph()->graph(), mcgraph()->common(),
2543 graph()->NewNode(mcgraph()->machine()->Word64Equal(), right,
2544 mcgraph()->Int64Constant(-1)));
2548 Node* rem = graph()->NewNode(mcgraph()->machine()->Int64Mod(), left, right,
2551 return d.Phi(MachineRepresentation::kWord64, mcgraph()->Int64Constant(0),
2555 Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right,
2556 wasm::WasmCodePosition position) {
2557 if (mcgraph()->machine()->Is32()) {
2558 return BuildDiv64Call(left, right, ExternalReference::wasm_uint64_div(),
2559 MachineType::Int64(), wasm::kTrapDivByZero, position);
2561 return graph()->NewNode(mcgraph()->machine()->Uint64Div(), left, right,
2562 ZeroCheck64(wasm::kTrapDivByZero, right, position));
2564 Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right,
2565 wasm::WasmCodePosition position) {
2566 if (mcgraph()->machine()->Is32()) {
2567 return BuildDiv64Call(left, right, ExternalReference::wasm_uint64_mod(),
2568 MachineType::Int64(), wasm::kTrapRemByZero, position);
2570 return graph()->NewNode(mcgraph()->machine()->Uint64Mod(), left, right,
2571 ZeroCheck64(wasm::kTrapRemByZero, right, position));
2574 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right,
2575 ExternalReference ref,
2576 MachineType result_type,
2577 wasm::TrapReason trap_zero,
2578 wasm::WasmCodePosition position) {
2580 graph()->NewNode(mcgraph()->machine()->StackSlot(2 *
sizeof(
double)));
2582 const Operator* store_op = mcgraph()->machine()->Store(
2583 StoreRepresentation(MachineRepresentation::kWord64, kNoWriteBarrier));
2584 SetEffect(graph()->NewNode(store_op, stack_slot, mcgraph()->Int32Constant(0),
2585 left, Effect(), Control()));
2586 SetEffect(graph()->NewNode(store_op, stack_slot,
2587 mcgraph()->Int32Constant(
sizeof(
double)), right,
2588 Effect(), Control()));
2590 MachineType sig_types[] = {MachineType::Int32(), MachineType::Pointer()};
2591 MachineSignature sig(1, 1, sig_types);
2593 Node*
function = graph()->NewNode(mcgraph()->common()->ExternalConstant(ref));
2594 Node* call = BuildCCall(&sig,
function, stack_slot);
2596 ZeroCheck32(trap_zero, call, position);
2597 TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1, position);
2598 return SetEffect(graph()->NewNode(mcgraph()->machine()->Load(result_type),
2599 stack_slot, mcgraph()->Int32Constant(0),
2600 Effect(), Control()));
2603 template <
typename... Args>
2604 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node*
function,
2606 DCHECK_LE(sig->return_count(), 1);
2607 DCHECK_EQ(
sizeof...(args), sig->parameter_count());
2608 Node*
const call_args[] = {
function, args..., Effect(), Control()};
2610 auto call_descriptor =
2611 Linkage::GetSimplifiedCDescriptor(mcgraph()->zone(), sig);
2613 const Operator* op = mcgraph()->common()->Call(call_descriptor);
2614 return SetEffect(graph()->NewNode(op, arraysize(call_args), call_args));
2617 Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args,
2619 wasm::WasmCodePosition position,
2620 Node* instance_node,
2621 UseRetpoline use_retpoline) {
2622 if (instance_node ==
nullptr) {
2623 DCHECK_NOT_NULL(instance_node_);
2624 instance_node = instance_node_.get();
2626 needs_stack_check_ =
true;
2627 const size_t params = sig->parameter_count();
2628 const size_t extra = 3;
2629 const size_t count = 1 + params + extra;
2632 args = Realloc(args, 1 + params, count);
2635 memmove(&args[2], &args[1], params *
sizeof(Node*));
2636 args[1] = instance_node;
2639 args[params + 2] = Effect();
2640 args[params + 3] = Control();
2642 auto call_descriptor =
2643 GetWasmCallDescriptor(mcgraph()->zone(), sig, use_retpoline);
2644 const Operator* op = mcgraph()->common()->Call(call_descriptor);
2645 Node* call = SetEffect(graph()->NewNode(op, static_cast<int>(count), args));
2646 DCHECK(position == wasm::kNoCodePosition || position > 0);
2647 if (position > 0) SetSourcePosition(call, position);
2649 size_t ret_count = sig->return_count();
2650 if (ret_count == 0)
return call;
2652 *rets = Buffer(ret_count);
2653 if (ret_count == 1) {
2658 for (
size_t i = 0;
i < ret_count;
i++) {
2659 (*rets)[
i] = graph()->NewNode(mcgraph()->common()->Projection(
i), call,
2666 Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig, Node** args,
2668 wasm::WasmCodePosition position,
2671 Node* imported_function_refs =
2672 LOAD_INSTANCE_FIELD(ImportedFunctionRefs, MachineType::TaggedPointer());
2674 LOAD_FIXED_ARRAY_SLOT_PTR(imported_function_refs, func_index);
2677 Node* imported_targets =
2678 LOAD_INSTANCE_FIELD(ImportedFunctionTargets, MachineType::Pointer());
2679 Node* target_node = SetEffect(graph()->NewNode(
2680 mcgraph()->machine()->Load(MachineType::Pointer()), imported_targets,
2681 mcgraph()->Int32Constant(func_index * kPointerSize), Effect(),
2683 args[0] = target_node;
2684 return BuildWasmCall(sig, args, rets, position, ref_node,
2685 untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline);
2688 Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig, Node** args,
2690 wasm::WasmCodePosition position,
2693 Node* imported_function_refs =
2694 LOAD_INSTANCE_FIELD(ImportedFunctionRefs, MachineType::TaggedPointer());
2696 Node* imported_instances_data = graph()->NewNode(
2697 mcgraph()->machine()->IntAdd(), imported_function_refs,
2698 mcgraph()->IntPtrConstant(
2699 wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(0)));
2700 Node* func_index_times_pointersize = graph()->NewNode(
2701 mcgraph()->machine()->IntMul(), Uint32ToUintptr(func_index),
2702 mcgraph()->Int32Constant(kPointerSize));
2703 Node* ref_node = SetEffect(
2704 graph()->NewNode(mcgraph()->machine()->Load(MachineType::TaggedPointer()),
2705 imported_instances_data, func_index_times_pointersize,
2706 Effect(), Control()));
2710 Node* imported_targets =
2711 LOAD_INSTANCE_FIELD(ImportedFunctionTargets, MachineType::Pointer());
2712 Node* target_node = SetEffect(graph()->NewNode(
2713 mcgraph()->machine()->Load(MachineType::Pointer()), imported_targets,
2714 func_index_times_pointersize, Effect(), Control()));
2715 args[0] = target_node;
2716 return BuildWasmCall(sig, args, rets, position, ref_node,
2717 untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline);
2720 Node* WasmGraphBuilder::CallDirect(
uint32_t index, Node** args, Node*** rets,
2721 wasm::WasmCodePosition position) {
2722 DCHECK_NULL(args[0]);
2723 wasm::FunctionSig* sig = env_->module->functions[index].sig;
2725 if (env_ && index < env_->module->num_imported_functions) {
2727 return BuildImportCall(sig, args, rets, position, index);
2732 Address code =
static_cast<Address
>(index);
2733 args[0] = mcgraph()->RelocatableIntPtrConstant(code, RelocInfo::WASM_CALL);
2735 return BuildWasmCall(sig, args, rets, position,
nullptr, kNoRetpoline);
2738 Node* WasmGraphBuilder::CallIndirect(
uint32_t sig_index, Node** args,
2740 wasm::WasmCodePosition position) {
2741 DCHECK_NOT_NULL(args[0]);
2742 DCHECK_NOT_NULL(env_);
2745 wasm::FunctionSig* sig = env_->module->signatures[sig_index];
2748 LOAD_INSTANCE_FIELD(IndirectFunctionTableSize, MachineType::Uint32());
2750 MachineOperatorBuilder* machine = mcgraph()->machine();
2751 Node* key = args[0];
2754 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, ift_size);
2755 TrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position);
2758 if (untrusted_code_mitigations_) {
2761 graph()->NewNode(machine->Word32Xor(), key, Int32Constant(-1));
2762 Node* masked_diff = graph()->NewNode(
2763 machine->Word32And(),
2764 graph()->NewNode(machine->Int32Sub(), key, ift_size), neg_key);
2766 graph()->NewNode(machine->Word32Sar(), masked_diff, Int32Constant(31));
2767 key = graph()->NewNode(machine->Word32And(), key, mask);
2772 LOAD_INSTANCE_FIELD(IndirectFunctionTableSigIds, MachineType::Pointer());
2774 int32_t expected_sig_id = env_->module->signature_ids[sig_index];
2775 Node* scaled_key = Uint32ToUintptr(
2776 graph()->NewNode(machine->Word32Shl(), key, Int32Constant(2)));
2779 SetEffect(graph()->NewNode(machine->Load(MachineType::Int32()),
2780 ift_sig_ids, scaled_key, Effect(), Control()));
2781 Node* sig_match = graph()->NewNode(machine->WordEqual(), loaded_sig,
2782 Int32Constant(expected_sig_id));
2784 TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position);
2787 LOAD_INSTANCE_FIELD(IndirectFunctionTableTargets, MachineType::Pointer());
2788 Node* ift_instances = LOAD_INSTANCE_FIELD(IndirectFunctionTableRefs,
2789 MachineType::TaggedPointer());
2791 scaled_key = graph()->NewNode(machine->Word32Shl(), key,
2792 Int32Constant(kPointerSizeLog2));
2795 SetEffect(graph()->NewNode(machine->Load(MachineType::Pointer()),
2796 ift_targets, scaled_key, Effect(), Control()));
2798 Node* target_instance = SetEffect(graph()->NewNode(
2799 machine->Load(MachineType::TaggedPointer()),
2800 graph()->NewNode(machine->IntAdd(), ift_instances, scaled_key),
2801 Int32Constant(wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(0)),
2802 Effect(), Control()));
2806 return BuildWasmCall(sig, args, rets, position, target_instance,
2807 untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline);
2810 Node* WasmGraphBuilder::BuildI32Rol(Node* left, Node* right) {
2813 Int32Matcher m(right);
2815 return Binop(wasm::kExprI32Ror, left,
2816 mcgraph()->Int32Constant(32 - m.Value()));
2818 return Binop(wasm::kExprI32Ror, left,
2819 Binop(wasm::kExprI32Sub, mcgraph()->Int32Constant(32), right));
2823 Node* WasmGraphBuilder::BuildI64Rol(Node* left, Node* right) {
2826 Int64Matcher m(right);
2828 return Binop(wasm::kExprI64Ror, left,
2829 mcgraph()->Int64Constant(64 - m.Value()));
2831 return Binop(wasm::kExprI64Ror, left,
2832 Binop(wasm::kExprI64Sub, mcgraph()->Int64Constant(64), right));
2836 Node* WasmGraphBuilder::Invert(Node* node) {
2837 return Unop(wasm::kExprI32Eqz, node);
2840 bool CanCover(Node* value, IrOpcode::Value opcode) {
2841 if (value->opcode() != opcode)
return false;
2843 for (Edge
const edge : value->use_edges()) {
2844 if (NodeProperties::IsControlEdge(edge))
continue;
2845 if (NodeProperties::IsEffectEdge(edge))
continue;
2846 DCHECK(NodeProperties::IsValueEdge(edge));
2847 if (!first)
return false;
2853 Node* WasmGraphBuilder::BuildChangeInt32ToIntPtr(Node* value) {
2854 if (mcgraph()->machine()->Is64()) {
2855 value = graph()->NewNode(mcgraph()->machine()->ChangeInt32ToInt64(), value);
2860 Node* WasmGraphBuilder::BuildChangeInt32ToSmi(Node* value) {
2861 value = BuildChangeInt32ToIntPtr(value);
2862 return graph()->NewNode(mcgraph()->machine()->WordShl(), value,
2863 BuildSmiShiftBitsConstant());
2866 Node* WasmGraphBuilder::BuildChangeUint31ToSmi(Node* value) {
2867 return graph()->NewNode(mcgraph()->machine()->WordShl(),
2868 Uint32ToUintptr(value), BuildSmiShiftBitsConstant());
2871 Node* WasmGraphBuilder::BuildSmiShiftBitsConstant() {
2872 return mcgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
2875 Node* WasmGraphBuilder::BuildChangeSmiToInt32(Node* value) {
2876 value = graph()->NewNode(mcgraph()->machine()->WordSar(), value,
2877 BuildSmiShiftBitsConstant());
2878 if (mcgraph()->machine()->Is64()) {
2880 graph()->NewNode(mcgraph()->machine()->TruncateInt64ToInt32(), value);
2885 void WasmGraphBuilder::InitInstanceCache(
2886 WasmInstanceCacheNodes* instance_cache) {
2887 DCHECK_NOT_NULL(instance_node_);
2890 instance_cache->mem_start = SetEffect(graph()->NewNode(
2891 mcgraph()->machine()->Load(MachineType::UintPtr()), instance_node_.get(),
2892 mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(MemoryStart)),
2893 Effect(), Control()));
2896 instance_cache->mem_size = SetEffect(graph()->NewNode(
2897 mcgraph()->machine()->Load(MachineType::UintPtr()), instance_node_.get(),
2898 mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(MemorySize)),
2899 Effect(), Control()));
2901 if (untrusted_code_mitigations_) {
2903 instance_cache->mem_mask =
2904 LOAD_INSTANCE_FIELD(MemoryMask, MachineType::UintPtr());
2907 instance_cache->mem_mask =
nullptr;
2911 void WasmGraphBuilder::PrepareInstanceCacheForLoop(
2912 WasmInstanceCacheNodes* instance_cache, Node* control) {
2913 #define INTRODUCE_PHI(field, rep) \ 2914 instance_cache->field = graph()->NewNode(mcgraph()->common()->Phi(rep, 1), \ 2915 instance_cache->field, control); 2917 INTRODUCE_PHI(mem_start, MachineType::PointerRepresentation());
2918 INTRODUCE_PHI(mem_size, MachineType::PointerRepresentation());
2919 if (untrusted_code_mitigations_) {
2920 INTRODUCE_PHI(mem_mask, MachineType::PointerRepresentation());
2923 #undef INTRODUCE_PHI 2926 void WasmGraphBuilder::NewInstanceCacheMerge(WasmInstanceCacheNodes* to,
2927 WasmInstanceCacheNodes* from,
2929 #define INTRODUCE_PHI(field, rep) \ 2930 if (to->field != from->field) { \ 2931 Node* vals[] = {to->field, from->field, merge}; \ 2932 to->field = graph()->NewNode(mcgraph()->common()->Phi(rep, 2), 3, vals); \ 2935 INTRODUCE_PHI(mem_start, MachineType::PointerRepresentation());
2936 INTRODUCE_PHI(mem_size, MachineRepresentation::kWord32);
2937 if (untrusted_code_mitigations_) {
2938 INTRODUCE_PHI(mem_mask, MachineRepresentation::kWord32);
2941 #undef INTRODUCE_PHI 2944 void WasmGraphBuilder::MergeInstanceCacheInto(WasmInstanceCacheNodes* to,
2945 WasmInstanceCacheNodes* from,
2947 to->mem_size = CreateOrMergeIntoPhi(MachineType::PointerRepresentation(),
2948 merge, to->mem_size, from->mem_size);
2949 to->mem_start = CreateOrMergeIntoPhi(MachineType::PointerRepresentation(),
2950 merge, to->mem_start, from->mem_start);
2951 if (untrusted_code_mitigations_) {
2952 to->mem_mask = CreateOrMergeIntoPhi(MachineType::PointerRepresentation(),
2953 merge, to->mem_mask, from->mem_mask);
2957 Node* WasmGraphBuilder::CreateOrMergeIntoPhi(MachineRepresentation rep,
2958 Node* merge, Node* tnode,
2960 if (IsPhiWithMerge(tnode, merge)) {
2961 AppendToPhi(tnode, fnode);
2962 }
else if (tnode != fnode) {
2963 uint32_t count = merge->InputCount();
2965 Node** vals = Buffer(count + 1);
2966 for (
uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
2967 vals[count - 1] = fnode;
2968 vals[count] = merge;
2969 return graph()->NewNode(mcgraph()->common()->Phi(rep, count), count + 1,
2975 Node* WasmGraphBuilder::CreateOrMergeIntoEffectPhi(Node* merge, Node* tnode,
2977 if (IsPhiWithMerge(tnode, merge)) {
2978 AppendToPhi(tnode, fnode);
2979 }
else if (tnode != fnode) {
2980 uint32_t count = merge->InputCount();
2981 Node** effects = Buffer(count);
2982 for (
uint32_t j = 0; j < count - 1; j++) {
2985 effects[count - 1] = fnode;
2986 tnode = EffectPhi(count, effects, merge);
2991 void WasmGraphBuilder::GetGlobalBaseAndOffset(MachineType mem_type,
2992 const wasm::WasmGlobal& global,
2994 Node** offset_node) {
2995 DCHECK_NOT_NULL(instance_node_);
2996 if (global.mutability && global.imported) {
2997 if (imported_mutable_globals_ ==
nullptr) {
2999 imported_mutable_globals_ = graph()->NewNode(
3000 mcgraph()->machine()->Load(MachineType::UintPtr()),
3001 instance_node_.get(),
3002 mcgraph()->Int32Constant(
3003 WASM_INSTANCE_OBJECT_OFFSET(ImportedMutableGlobals)),
3004 graph()->start(), graph()->start());
3006 *base_node = SetEffect(graph()->NewNode(
3007 mcgraph()->machine()->Load(MachineType::UintPtr()),
3008 imported_mutable_globals_.get(),
3009 mcgraph()->Int32Constant(global.index *
sizeof(Address)), Effect(),
3011 *offset_node = mcgraph()->Int32Constant(0);
3013 if (globals_start_ ==
nullptr) {
3023 globals_start_ = graph()->NewNode(
3024 mcgraph()->machine()->Load(MachineType::UintPtr()),
3025 instance_node_.get(),
3026 mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(GlobalsStart)),
3027 graph()->start(), graph()->start());
3029 *base_node = globals_start_.get();
3030 *offset_node = mcgraph()->Int32Constant(global.offset);
3032 if (mem_type == MachineType::Simd128() && global.offset != 0) {
3034 *base_node = graph()->NewNode(mcgraph()->machine()->IntAdd(), *base_node,
3036 *offset_node = mcgraph()->Int32Constant(0);
3041 Node* WasmGraphBuilder::MemBuffer(
uint32_t offset) {
3042 DCHECK_NOT_NULL(instance_cache_);
3043 Node* mem_start = instance_cache_->mem_start;
3044 DCHECK_NOT_NULL(mem_start);
3045 if (offset == 0)
return mem_start;
3046 return graph()->NewNode(mcgraph()->machine()->IntAdd(), mem_start,
3047 mcgraph()->IntPtrConstant(offset));
3050 Node* WasmGraphBuilder::CurrentMemoryPages() {
3052 DCHECK_EQ(wasm::kWasmOrigin, env_->module->origin);
3053 DCHECK_NOT_NULL(instance_cache_);
3054 Node* mem_size = instance_cache_->mem_size;
3055 DCHECK_NOT_NULL(mem_size);
3057 graph()->NewNode(mcgraph()->machine()->WordShr(), mem_size,
3058 mcgraph()->Int32Constant(wasm::kWasmPageSizeLog2));
3059 if (mcgraph()->machine()->Is64()) {
3061 graph()->NewNode(mcgraph()->machine()->TruncateInt64ToInt32(), result);
3066 Node* WasmGraphBuilder::BuildLoadBuiltinFromInstance(
int builtin_index) {
3067 DCHECK(Builtins::IsBuiltinId(builtin_index));
3068 Node* isolate_root = LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer());
3069 return LOAD_TAGGED_POINTER(isolate_root,
3070 IsolateData::builtin_slot_offset(builtin_index));
3075 Node* WasmGraphBuilder::BuildCallToRuntimeWithContext(Runtime::FunctionId f,
3078 int parameter_count) {
3079 const Runtime::Function* fun = Runtime::FunctionForId(f);
3080 auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
3081 mcgraph()->zone(), f, fun->nargs, Operator::kNoProperties,
3082 CallDescriptor::kNoFlags);
3085 DCHECK_EQ(1, fun->result_size);
3087 LOAD_INSTANCE_FIELD(CEntryStub, MachineType::TaggedPointer());
3090 static const int kMaxParams = 4;
3091 DCHECK_GE(kMaxParams, parameter_count);
3092 Node* inputs[kMaxParams + 6];
3094 inputs[count++] = centry_stub;
3095 for (
int i = 0;
i < parameter_count;
i++) {
3096 inputs[count++] = parameters[
i];
3099 mcgraph()->ExternalConstant(ExternalReference::Create(f));
3100 inputs[count++] = mcgraph()->Int32Constant(fun->nargs);
3101 inputs[count++] = js_context;
3102 inputs[count++] = Effect();
3103 inputs[count++] = Control();
3105 return SetEffect(mcgraph()->graph()->NewNode(
3106 mcgraph()->common()->Call(call_descriptor), count, inputs));
3109 Node* WasmGraphBuilder::BuildCallToRuntime(Runtime::FunctionId f,
3111 int parameter_count) {
3112 return BuildCallToRuntimeWithContext(f, NoContextConstant(), parameters,
3116 Node* WasmGraphBuilder::GetGlobal(
uint32_t index) {
3117 MachineType mem_type =
3118 wasm::ValueTypes::MachineTypeFor(env_->module->globals[index].type);
3119 Node* base =
nullptr;
3120 Node* offset =
nullptr;
3121 GetGlobalBaseAndOffset(mem_type, env_->module->globals[index], &base,
3123 Node* load = SetEffect(graph()->NewNode(mcgraph()->machine()->Load(mem_type),
3124 base, offset, Effect(), Control()));
3125 #if defined(V8_TARGET_BIG_ENDIAN) 3126 load = BuildChangeEndiannessLoad(load, mem_type,
3127 env_->module->globals[index].type);
3132 Node* WasmGraphBuilder::SetGlobal(
uint32_t index, Node* val) {
3133 MachineType mem_type =
3134 wasm::ValueTypes::MachineTypeFor(env_->module->globals[index].type);
3135 Node* base =
nullptr;
3136 Node* offset =
nullptr;
3137 GetGlobalBaseAndOffset(mem_type, env_->module->globals[index], &base,
3139 const Operator* op = mcgraph()->machine()->Store(
3140 StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
3141 #if defined(V8_TARGET_BIG_ENDIAN) 3142 val = BuildChangeEndiannessStore(val, mem_type.representation(),
3143 env_->module->globals[index].type);
3146 graph()->NewNode(op, base, offset, val, Effect(), Control()));
3149 Node* WasmGraphBuilder::CheckBoundsAndAlignment(
3150 uint8_t access_size, Node* index,
uint32_t offset,
3151 wasm::WasmCodePosition position) {
3155 BoundsCheckMem(access_size, index, offset, position, kNeedsBoundsCheck);
3156 Node* effective_address =
3157 graph()->NewNode(mcgraph()->machine()->IntAdd(), MemBuffer(offset),
3158 Uint32ToUintptr(index));
3163 graph()->NewNode(mcgraph()->machine()->WordAnd(), effective_address,
3164 IntPtrConstant(access_size - 1));
3165 TrapIfFalse(wasm::kTrapUnalignedAccess,
3166 graph()->NewNode(mcgraph()->machine()->Word32Equal(), cond,
3167 mcgraph()->Int32Constant(0)),
3172 Node* WasmGraphBuilder::BoundsCheckMem(uint8_t access_size, Node* index,
3174 wasm::WasmCodePosition position,
3175 EnforceBoundsCheck enforce_check) {
3176 DCHECK_LE(1, access_size);
3177 index = Uint32ToUintptr(index);
3178 if (FLAG_wasm_no_bounds_checks)
return index;
3180 if (use_trap_handler() && enforce_check == kCanOmitBoundsCheck) {
3184 const bool statically_oob = access_size > env_->max_memory_size ||
3185 offset > env_->max_memory_size - access_size;
3186 if (statically_oob) {
3188 TrapIfEq32(wasm::kTrapMemOutOfBounds, Int32Constant(0), 0, position);
3189 return mcgraph()->IntPtrConstant(0);
3191 uint64_t end_offset = uint64_t{offset} + access_size - 1u;
3192 Node* end_offset_node = IntPtrConstant(end_offset);
3203 auto m = mcgraph()->machine();
3204 Node* mem_size = instance_cache_->mem_size;
3205 if (end_offset >= env_->min_memory_size) {
3208 Node* cond = graph()->NewNode(m->UintLessThan(), end_offset_node, mem_size);
3209 TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
3213 UintPtrMatcher match(index);
3214 if (match.HasValue()) {
3216 if (index_val < env_->min_memory_size - end_offset) {
3225 Node* effective_size =
3226 graph()->NewNode(m->IntSub(), mem_size, end_offset_node);
3229 Node* cond = graph()->NewNode(m->UintLessThan(), index, effective_size);
3230 TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
3232 if (untrusted_code_mitigations_) {
3234 Node* mem_mask = instance_cache_->mem_mask;
3235 DCHECK_NOT_NULL(mem_mask);
3236 index = graph()->NewNode(m->WordAnd(), index, mem_mask);
3241 const Operator* WasmGraphBuilder::GetSafeLoadOperator(
int offset,
3242 wasm::ValueType type) {
3243 int alignment = offset % (wasm::ValueTypes::ElementSizeInBytes(type));
3244 MachineType mach_type = wasm::ValueTypes::MachineTypeFor(type);
3245 if (alignment == 0 || mcgraph()->machine()->UnalignedLoadSupported(
3246 wasm::ValueTypes::MachineRepresentationFor(type))) {
3247 return mcgraph()->machine()->Load(mach_type);
3249 return mcgraph()->machine()->UnalignedLoad(mach_type);
3252 const Operator* WasmGraphBuilder::GetSafeStoreOperator(
int offset,
3253 wasm::ValueType type) {
3254 int alignment = offset % (wasm::ValueTypes::ElementSizeInBytes(type));
3255 MachineRepresentation rep = wasm::ValueTypes::MachineRepresentationFor(type);
3256 if (alignment == 0 || mcgraph()->machine()->UnalignedStoreSupported(rep)) {
3257 StoreRepresentation store_rep(rep, WriteBarrierKind::kNoWriteBarrier);
3258 return mcgraph()->machine()->Store(store_rep);
3260 UnalignedStoreRepresentation store_rep(rep);
3261 return mcgraph()->machine()->UnalignedStore(store_rep);
3264 Node* WasmGraphBuilder::TraceMemoryOperation(
bool is_store,
3265 MachineRepresentation rep,
3267 wasm::WasmCodePosition position) {
3269 Node* info = graph()->NewNode(
3270 mcgraph()->machine()->StackSlot(
sizeof(wasm::MemoryTracingInfo), kAlign));
3272 Node* address = graph()->NewNode(mcgraph()->machine()->Int32Add(),
3273 Int32Constant(offset), index);
3274 auto store = [&](
int offset, MachineRepresentation rep, Node* data) {
3275 SetEffect(graph()->NewNode(
3276 mcgraph()->machine()->Store(StoreRepresentation(rep, kNoWriteBarrier)),
3277 info, mcgraph()->Int32Constant(offset), data, Effect(), Control()));
3280 store(offsetof(wasm::MemoryTracingInfo, address),
3281 MachineRepresentation::kWord32, address);
3282 store(offsetof(wasm::MemoryTracingInfo, is_store),
3283 MachineRepresentation::kWord8,
3284 mcgraph()->Int32Constant(is_store ? 1 : 0));
3285 store(offsetof(wasm::MemoryTracingInfo, mem_rep),
3286 MachineRepresentation::kWord8,
3287 mcgraph()->Int32Constant(static_cast<int>(rep)));
3289 Node* call = BuildCallToRuntime(Runtime::kWasmTraceMemory, &info, 1);
3290 SetSourcePosition(call, position);
3294 Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype,
3297 wasm::WasmCodePosition position) {
3302 index = BoundsCheckMem(wasm::ValueTypes::MemSize(memtype), index, offset,
3303 position, kCanOmitBoundsCheck);
3305 if (memtype.representation() == MachineRepresentation::kWord8 ||
3306 mcgraph()->machine()->UnalignedLoadSupported(memtype.representation())) {
3307 if (use_trap_handler()) {
3308 load = graph()->NewNode(mcgraph()->machine()->ProtectedLoad(memtype),
3309 MemBuffer(offset), index, Effect(), Control());
3310 SetSourcePosition(load, position);
3312 load = graph()->NewNode(mcgraph()->machine()->Load(memtype),
3313 MemBuffer(offset), index, Effect(), Control());
3317 DCHECK(!use_trap_handler());
3318 load = graph()->NewNode(mcgraph()->machine()->UnalignedLoad(memtype),
3319 MemBuffer(offset), index, Effect(), Control());
3324 #if defined(V8_TARGET_BIG_ENDIAN) 3325 load = BuildChangeEndiannessLoad(load, memtype, type);
3328 if (type == wasm::kWasmI64 &&
3329 ElementSizeInBytes(memtype.representation()) < 8) {
3331 if (memtype.IsSigned()) {
3333 load = graph()->NewNode(mcgraph()->machine()->ChangeInt32ToInt64(), load);
3337 graph()->NewNode(mcgraph()->machine()->ChangeUint32ToUint64(), load);
3341 if (FLAG_trace_wasm_memory) {
3342 TraceMemoryOperation(
false, memtype.representation(), index, offset,
3349 Node* WasmGraphBuilder::StoreMem(MachineRepresentation mem_rep, Node* index,
3351 wasm::WasmCodePosition position,
3352 wasm::ValueType type) {
3355 index = BoundsCheckMem(i::ElementSizeInBytes(mem_rep), index, offset,
3356 position, kCanOmitBoundsCheck);
3358 #if defined(V8_TARGET_BIG_ENDIAN) 3359 val = BuildChangeEndiannessStore(val, mem_rep, type);
3362 if (mem_rep == MachineRepresentation::kWord8 ||
3363 mcgraph()->machine()->UnalignedStoreSupported(mem_rep)) {
3364 if (use_trap_handler()) {
3366 graph()->NewNode(mcgraph()->machine()->ProtectedStore(mem_rep),
3367 MemBuffer(offset), index, val, Effect(), Control());
3368 SetSourcePosition(store, position);
3370 StoreRepresentation rep(mem_rep, kNoWriteBarrier);
3372 graph()->NewNode(mcgraph()->machine()->Store(rep), MemBuffer(offset),
3373 index, val, Effect(), Control());
3377 DCHECK(!use_trap_handler());
3378 UnalignedStoreRepresentation rep(mem_rep);
3380 graph()->NewNode(mcgraph()->machine()->UnalignedStore(rep),
3381 MemBuffer(offset), index, val, Effect(), Control());
3386 if (FLAG_trace_wasm_memory) {
3387 TraceMemoryOperation(
true, mem_rep, index, offset, position);
3394 Node* GetAsmJsOOBValue(MachineRepresentation rep, MachineGraph* mcgraph) {
3396 case MachineRepresentation::kWord8:
3397 case MachineRepresentation::kWord16:
3398 case MachineRepresentation::kWord32:
3399 return mcgraph->Int32Constant(0);
3400 case MachineRepresentation::kWord64:
3401 return mcgraph->Int64Constant(0);
3402 case MachineRepresentation::kFloat32:
3403 return mcgraph->Float32Constant(std::numeric_limits<float>::quiet_NaN());
3404 case MachineRepresentation::kFloat64:
3405 return mcgraph->Float64Constant(std::numeric_limits<double>::quiet_NaN());
3412 Node* WasmGraphBuilder::BuildAsmjsLoadMem(MachineType type, Node* index) {
3413 DCHECK_NOT_NULL(instance_cache_);
3414 Node* mem_start = instance_cache_->mem_start;
3415 Node* mem_size = instance_cache_->mem_size;
3416 DCHECK_NOT_NULL(mem_start);
3417 DCHECK_NOT_NULL(mem_size);
3425 index = Uint32ToUintptr(index);
3426 Diamond bounds_check(
3427 graph(), mcgraph()->common(),
3428 graph()->NewNode(mcgraph()->machine()->UintLessThan(), index, mem_size),
3430 bounds_check.Chain(Control());
3432 if (untrusted_code_mitigations_) {
3434 Node* mem_mask = instance_cache_->mem_mask;
3435 DCHECK_NOT_NULL(mem_mask);
3436 index = graph()->NewNode(mcgraph()->machine()->WordAnd(), index, mem_mask);
3439 Node* load = graph()->NewNode(mcgraph()->machine()->Load(type), mem_start,
3440 index, Effect(), bounds_check.if_true);
3441 SetEffect(bounds_check.EffectPhi(load, Effect()));
3442 SetControl(bounds_check.merge);
3443 return bounds_check.Phi(type.representation(), load,
3444 GetAsmJsOOBValue(type.representation(), mcgraph()));
3447 Node* WasmGraphBuilder::Uint32ToUintptr(Node* node) {
3448 if (mcgraph()->machine()->Is32())
return node;
3450 Uint32Matcher matcher(node);
3451 if (matcher.HasValue()) {
3453 return mcgraph()->IntPtrConstant(bit_cast<intptr_t>(value));
3455 return graph()->NewNode(mcgraph()->machine()->ChangeUint32ToUint64(), node);
3458 Node* WasmGraphBuilder::BuildAsmjsStoreMem(MachineType type, Node* index,
3460 DCHECK_NOT_NULL(instance_cache_);
3461 Node* mem_start = instance_cache_->mem_start;
3462 Node* mem_size = instance_cache_->mem_size;
3463 DCHECK_NOT_NULL(mem_start);
3464 DCHECK_NOT_NULL(mem_size);
3470 Diamond bounds_check(
3471 graph(), mcgraph()->common(),
3472 graph()->NewNode(mcgraph()->machine()->Uint32LessThan(), index, mem_size),
3474 bounds_check.Chain(Control());
3476 if (untrusted_code_mitigations_) {
3478 Node* mem_mask = instance_cache_->mem_mask;
3479 DCHECK_NOT_NULL(mem_mask);
3481 graph()->NewNode(mcgraph()->machine()->Word32And(), index, mem_mask);
3484 index = Uint32ToUintptr(index);
3485 const Operator* store_op = mcgraph()->machine()->Store(StoreRepresentation(
3486 type.representation(), WriteBarrierKind::kNoWriteBarrier));
3487 Node* store = graph()->NewNode(store_op, mem_start, index, val, Effect(),
3488 bounds_check.if_true);
3489 SetEffect(bounds_check.EffectPhi(store, Effect()));
3490 SetControl(bounds_check.merge);
3494 void WasmGraphBuilder::PrintDebugName(Node* node) {
3495 PrintF(
"#%d:%s", node->id(), node->op()->mnemonic());
3498 Graph* WasmGraphBuilder::graph() {
return mcgraph()->graph(); }
3501 Signature<MachineRepresentation>* CreateMachineSignature(
3502 Zone* zone, wasm::FunctionSig* sig) {
3503 Signature<MachineRepresentation>::Builder builder(zone, sig->return_count(),
3504 sig->parameter_count());
3505 for (
auto ret : sig->returns()) {
3506 builder.AddReturn(wasm::ValueTypes::MachineRepresentationFor(ret));
3509 for (
auto param : sig->parameters()) {
3510 builder.AddParam(wasm::ValueTypes::MachineRepresentationFor(param));
3512 return builder.Build();
3516 void WasmGraphBuilder::LowerInt64() {
3517 if (mcgraph()->machine()->Is64())
return;
3518 Int64Lowering r(mcgraph()->graph(), mcgraph()->machine(), mcgraph()->common(),
3520 CreateMachineSignature(mcgraph()->zone(), sig_));
3524 void WasmGraphBuilder::SimdScalarLoweringForTesting() {
3525 SimdScalarLowering(mcgraph(), CreateMachineSignature(mcgraph()->zone(), sig_))
3529 void WasmGraphBuilder::SetSourcePosition(Node* node,
3530 wasm::WasmCodePosition position) {
3531 DCHECK_NE(position, wasm::kNoCodePosition);
3532 if (source_position_table_)
3533 source_position_table_->SetSourcePosition(node, SourcePosition(position));
3536 Node* WasmGraphBuilder::S128Zero() {
3538 return graph()->NewNode(mcgraph()->machine()->S128Zero());
3541 Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node*
const* inputs) {
3544 case wasm::kExprF32x4Splat:
3545 return graph()->NewNode(mcgraph()->machine()->F32x4Splat(), inputs[0]);
3546 case wasm::kExprF32x4SConvertI32x4:
3547 return graph()->NewNode(mcgraph()->machine()->F32x4SConvertI32x4(),
3549 case wasm::kExprF32x4UConvertI32x4:
3550 return graph()->NewNode(mcgraph()->machine()->F32x4UConvertI32x4(),
3552 case wasm::kExprF32x4Abs:
3553 return graph()->NewNode(mcgraph()->machine()->F32x4Abs(), inputs[0]);
3554 case wasm::kExprF32x4Neg:
3555 return graph()->NewNode(mcgraph()->machine()->F32x4Neg(), inputs[0]);
3556 case wasm::kExprF32x4RecipApprox:
3557 return graph()->NewNode(mcgraph()->machine()->F32x4RecipApprox(),
3559 case wasm::kExprF32x4RecipSqrtApprox:
3560 return graph()->NewNode(mcgraph()->machine()->F32x4RecipSqrtApprox(),
3562 case wasm::kExprF32x4Add:
3563 return graph()->NewNode(mcgraph()->machine()->F32x4Add(), inputs[0],
3565 case wasm::kExprF32x4AddHoriz:
3566 return graph()->NewNode(mcgraph()->machine()->F32x4AddHoriz(), inputs[0],
3568 case wasm::kExprF32x4Sub:
3569 return graph()->NewNode(mcgraph()->machine()->F32x4Sub(), inputs[0],
3571 case wasm::kExprF32x4Mul:
3572 return graph()->NewNode(mcgraph()->machine()->F32x4Mul(), inputs[0],
3574 case wasm::kExprF32x4Min:
3575 return graph()->NewNode(mcgraph()->machine()->F32x4Min(), inputs[0],
3577 case wasm::kExprF32x4Max:
3578 return graph()->NewNode(mcgraph()->machine()->F32x4Max(), inputs[0],
3580 case wasm::kExprF32x4Eq:
3581 return graph()->NewNode(mcgraph()->machine()->F32x4Eq(), inputs[0],
3583 case wasm::kExprF32x4Ne:
3584 return graph()->NewNode(mcgraph()->machine()->F32x4Ne(), inputs[0],
3586 case wasm::kExprF32x4Lt:
3587 return graph()->NewNode(mcgraph()->machine()->F32x4Lt(), inputs[0],
3589 case wasm::kExprF32x4Le:
3590 return graph()->NewNode(mcgraph()->machine()->F32x4Le(), inputs[0],
3592 case wasm::kExprF32x4Gt:
3593 return graph()->NewNode(mcgraph()->machine()->F32x4Lt(), inputs[1],
3595 case wasm::kExprF32x4Ge:
3596 return graph()->NewNode(mcgraph()->machine()->F32x4Le(), inputs[1],
3598 case wasm::kExprI32x4Splat:
3599 return graph()->NewNode(mcgraph()->machine()->I32x4Splat(), inputs[0]);
3600 case wasm::kExprI32x4SConvertF32x4:
3601 return graph()->NewNode(mcgraph()->machine()->I32x4SConvertF32x4(),
3603 case wasm::kExprI32x4UConvertF32x4:
3604 return graph()->NewNode(mcgraph()->machine()->I32x4UConvertF32x4(),
3606 case wasm::kExprI32x4SConvertI16x8Low:
3607 return graph()->NewNode(mcgraph()->machine()->I32x4SConvertI16x8Low(),
3609 case wasm::kExprI32x4SConvertI16x8High:
3610 return graph()->NewNode(mcgraph()->machine()->I32x4SConvertI16x8High(),
3612 case wasm::kExprI32x4Neg:
3613 return graph()->NewNode(mcgraph()->machine()->I32x4Neg(), inputs[0]);
3614 case wasm::kExprI32x4Add:
3615 return graph()->NewNode(mcgraph()->machine()->I32x4Add(), inputs[0],
3617 case wasm::kExprI32x4AddHoriz:
3618 return graph()->NewNode(mcgraph()->machine()->I32x4AddHoriz(), inputs[0],
3620 case wasm::kExprI32x4Sub:
3621 return graph()->NewNode(mcgraph()->machine()->I32x4Sub(), inputs[0],
3623 case wasm::kExprI32x4Mul:
3624 return graph()->NewNode(mcgraph()->machine()->I32x4Mul(), inputs[0],
3626 case wasm::kExprI32x4MinS:
3627 return graph()->NewNode(mcgraph()->machine()->I32x4MinS(), inputs[0],
3629 case wasm::kExprI32x4MaxS:
3630 return graph()->NewNode(mcgraph()->machine()->I32x4MaxS(), inputs[0],
3632 case wasm::kExprI32x4Eq:
3633 return graph()->NewNode(mcgraph()->machine()->I32x4Eq(), inputs[0],
3635 case wasm::kExprI32x4Ne:
3636 return graph()->NewNode(mcgraph()->machine()->I32x4Ne(), inputs[0],
3638 case wasm::kExprI32x4LtS:
3639 return graph()->NewNode(mcgraph()->machine()->I32x4GtS(), inputs[1],
3641 case wasm::kExprI32x4LeS:
3642 return graph()->NewNode(mcgraph()->machine()->I32x4GeS(), inputs[1],
3644 case wasm::kExprI32x4GtS:
3645 return graph()->NewNode(mcgraph()->machine()->I32x4GtS(), inputs[0],
3647 case wasm::kExprI32x4GeS:
3648 return graph()->NewNode(mcgraph()->machine()->I32x4GeS(), inputs[0],
3650 case wasm::kExprI32x4UConvertI16x8Low:
3651 return graph()->NewNode(mcgraph()->machine()->I32x4UConvertI16x8Low(),
3653 case wasm::kExprI32x4UConvertI16x8High:
3654 return graph()->NewNode(mcgraph()->machine()->I32x4UConvertI16x8High(),
3656 case wasm::kExprI32x4MinU:
3657 return graph()->NewNode(mcgraph()->machine()->I32x4MinU(), inputs[0],
3659 case wasm::kExprI32x4MaxU:
3660 return graph()->NewNode(mcgraph()->machine()->I32x4MaxU(), inputs[0],
3662 case wasm::kExprI32x4LtU:
3663 return graph()->NewNode(mcgraph()->machine()->I32x4GtU(), inputs[1],
3665 case wasm::kExprI32x4LeU:
3666 return graph()->NewNode(mcgraph()->machine()->I32x4GeU(), inputs[1],
3668 case wasm::kExprI32x4GtU:
3669 return graph()->NewNode(mcgraph()->machine()->I32x4GtU(), inputs[0],
3671 case wasm::kExprI32x4GeU:
3672 return graph()->NewNode(mcgraph()->machine()->I32x4GeU(), inputs[0],
3674 case wasm::kExprI16x8Splat:
3675 return graph()->NewNode(mcgraph()->machine()->I16x8Splat(), inputs[0]);
3676 case wasm::kExprI16x8SConvertI8x16Low:
3677 return graph()->NewNode(mcgraph()->machine()->I16x8SConvertI8x16Low(),
3679 case wasm::kExprI16x8SConvertI8x16High:
3680 return graph()->NewNode(mcgraph()->machine()->I16x8SConvertI8x16High(),
3682 case wasm::kExprI16x8Neg:
3683 return graph()->NewNode(mcgraph()->machine()->I16x8Neg(), inputs[0]);
3684 case wasm::kExprI16x8SConvertI32x4:
3685 return graph()->NewNode(mcgraph()->machine()->I16x8SConvertI32x4(),
3686 inputs[0], inputs[1]);
3687 case wasm::kExprI16x8Add:
3688 return graph()->NewNode(mcgraph()->machine()->I16x8Add(), inputs[0],
3690 case wasm::kExprI16x8AddSaturateS:
3691 return graph()->NewNode(mcgraph()->machine()->I16x8AddSaturateS(),
3692 inputs[0], inputs[1]);
3693 case wasm::kExprI16x8AddHoriz:
3694 return graph()->NewNode(mcgraph()->machine()->I16x8AddHoriz(), inputs[0],
3696 case wasm::kExprI16x8Sub:
3697 return graph()->NewNode(mcgraph()->machine()->I16x8Sub(), inputs[0],
3699 case wasm::kExprI16x8SubSaturateS:
3700 return graph()->NewNode(mcgraph()->machine()->I16x8SubSaturateS(),
3701 inputs[0], inputs[1]);
3702 case wasm::kExprI16x8Mul:
3703 return graph()->NewNode(mcgraph()->machine()->I16x8Mul(), inputs[0],
3705 case wasm::kExprI16x8MinS:
3706 return graph()->NewNode(mcgraph()->machine()->I16x8MinS(), inputs[0],
3708 case wasm::kExprI16x8MaxS:
3709 return graph()->NewNode(mcgraph()->machine()->I16x8MaxS(), inputs[0],
3711 case wasm::kExprI16x8Eq:
3712 return graph()->NewNode(mcgraph()->machine()->I16x8Eq(), inputs[0],
3714 case wasm::kExprI16x8Ne:
3715 return graph()->NewNode(mcgraph()->machine()->I16x8Ne(), inputs[0],
3717 case wasm::kExprI16x8LtS:
3718 return graph()->NewNode(mcgraph()->machine()->I16x8GtS(), inputs[1],
3720 case wasm::kExprI16x8LeS:
3721 return graph()->NewNode(mcgraph()->machine()->I16x8GeS(), inputs[1],
3723 case wasm::kExprI16x8GtS:
3724 return graph()->NewNode(mcgraph()->machine()->I16x8GtS(), inputs[0],
3726 case wasm::kExprI16x8GeS:
3727 return graph()->NewNode(mcgraph()->machine()->I16x8GeS(), inputs[0],
3729 case wasm::kExprI16x8UConvertI8x16Low:
3730 return graph()->NewNode(mcgraph()->machine()->I16x8UConvertI8x16Low(),
3732 case wasm::kExprI16x8UConvertI8x16High:
3733 return graph()->NewNode(mcgraph()->machine()->I16x8UConvertI8x16High(),
3735 case wasm::kExprI16x8UConvertI32x4:
3736 return graph()->NewNode(mcgraph()->machine()->I16x8UConvertI32x4(),
3737 inputs[0], inputs[1]);
3738 case wasm::kExprI16x8AddSaturateU:
3739 return graph()->NewNode(mcgraph()->machine()->I16x8AddSaturateU(),
3740 inputs[0], inputs[1]);
3741 case wasm::kExprI16x8SubSaturateU:
3742 return graph()->NewNode(mcgraph()->machine()->I16x8SubSaturateU(),
3743 inputs[0], inputs[1]);
3744 case wasm::kExprI16x8MinU:
3745 return graph()->NewNode(mcgraph()->machine()->I16x8MinU(), inputs[0],
3747 case wasm::kExprI16x8MaxU:
3748 return graph()->NewNode(mcgraph()->machine()->I16x8MaxU(), inputs[0],
3750 case wasm::kExprI16x8LtU:
3751 return graph()->NewNode(mcgraph()->machine()->I16x8GtU(), inputs[1],
3753 case wasm::kExprI16x8LeU:
3754 return graph()->NewNode(mcgraph()->machine()->I16x8GeU(), inputs[1],
3756 case wasm::kExprI16x8GtU:
3757 return graph()->NewNode(mcgraph()->machine()->I16x8GtU(), inputs[0],
3759 case wasm::kExprI16x8GeU:
3760 return graph()->NewNode(mcgraph()->machine()->I16x8GeU(), inputs[0],
3762 case wasm::kExprI8x16Splat:
3763 return graph()->NewNode(mcgraph()->machine()->I8x16Splat(), inputs[0]);
3764 case wasm::kExprI8x16Neg:
3765 return graph()->NewNode(mcgraph()->machine()->I8x16Neg(), inputs[0]);
3766 case wasm::kExprI8x16SConvertI16x8:
3767 return graph()->NewNode(mcgraph()->machine()->I8x16SConvertI16x8(),
3768 inputs[0], inputs[1]);
3769 case wasm::kExprI8x16Add:
3770 return graph()->NewNode(mcgraph()->machine()->I8x16Add(), inputs[0],
3772 case wasm::kExprI8x16AddSaturateS:
3773 return graph()->NewNode(mcgraph()->machine()->I8x16AddSaturateS(),
3774 inputs[0], inputs[1]);
3775 case wasm::kExprI8x16Sub:
3776 return graph()->NewNode(mcgraph()->machine()->I8x16Sub(), inputs[0],
3778 case wasm::kExprI8x16SubSaturateS:
3779 return graph()->NewNode(mcgraph()->machine()->I8x16SubSaturateS(),
3780 inputs[0], inputs[1]);
3781 case wasm::kExprI8x16Mul:
3782 return graph()->NewNode(mcgraph()->machine()->I8x16Mul(), inputs[0],
3784 case wasm::kExprI8x16MinS:
3785 return graph()->NewNode(mcgraph()->machine()->I8x16MinS(), inputs[0],
3787 case wasm::kExprI8x16MaxS:
3788 return graph()->NewNode(mcgraph()->machine()->I8x16MaxS(), inputs[0],
3790 case wasm::kExprI8x16Eq:
3791 return graph()->NewNode(mcgraph()->machine()->I8x16Eq(), inputs[0],
3793 case wasm::kExprI8x16Ne:
3794 return graph()->NewNode(mcgraph()->machine()->I8x16Ne(), inputs[0],
3796 case wasm::kExprI8x16LtS:
3797 return graph()->NewNode(mcgraph()->machine()->I8x16GtS(), inputs[1],
3799 case wasm::kExprI8x16LeS:
3800 return graph()->NewNode(mcgraph()->machine()->I8x16GeS(), inputs[1],
3802 case wasm::kExprI8x16GtS:
3803 return graph()->NewNode(mcgraph()->machine()->I8x16GtS(), inputs[0],
3805 case wasm::kExprI8x16GeS:
3806 return graph()->NewNode(mcgraph()->machine()->I8x16GeS(), inputs[0],
3808 case wasm::kExprI8x16UConvertI16x8:
3809 return graph()->NewNode(mcgraph()->machine()->I8x16UConvertI16x8(),
3810 inputs[0], inputs[1]);
3811 case wasm::kExprI8x16AddSaturateU:
3812 return graph()->NewNode(mcgraph()->machine()->I8x16AddSaturateU(),
3813 inputs[0], inputs[1]);
3814 case wasm::kExprI8x16SubSaturateU:
3815 return graph()->NewNode(mcgraph()->machine()->I8x16SubSaturateU(),
3816 inputs[0], inputs[1]);
3817 case wasm::kExprI8x16MinU:
3818 return graph()->NewNode(mcgraph()->machine()->I8x16MinU(), inputs[0],
3820 case wasm::kExprI8x16MaxU:
3821 return graph()->NewNode(mcgraph()->machine()->I8x16MaxU(), inputs[0],
3823 case wasm::kExprI8x16LtU:
3824 return graph()->NewNode(mcgraph()->machine()->I8x16GtU(), inputs[1],
3826 case wasm::kExprI8x16LeU:
3827 return graph()->NewNode(mcgraph()->machine()->I8x16GeU(), inputs[1],
3829 case wasm::kExprI8x16GtU:
3830 return graph()->NewNode(mcgraph()->machine()->I8x16GtU(), inputs[0],
3832 case wasm::kExprI8x16GeU:
3833 return graph()->NewNode(mcgraph()->machine()->I8x16GeU(), inputs[0],
3835 case wasm::kExprS128And:
3836 return graph()->NewNode(mcgraph()->machine()->S128And(), inputs[0],
3838 case wasm::kExprS128Or:
3839 return graph()->NewNode(mcgraph()->machine()->S128Or(), inputs[0],
3841 case wasm::kExprS128Xor:
3842 return graph()->NewNode(mcgraph()->machine()->S128Xor(), inputs[0],
3844 case wasm::kExprS128Not:
3845 return graph()->NewNode(mcgraph()->machine()->S128Not(), inputs[0]);
3846 case wasm::kExprS128Select:
3847 return graph()->NewNode(mcgraph()->machine()->S128Select(), inputs[0],
3848 inputs[1], inputs[2]);
3849 case wasm::kExprS1x4AnyTrue:
3850 return graph()->NewNode(mcgraph()->machine()->S1x4AnyTrue(), inputs[0]);
3851 case wasm::kExprS1x4AllTrue:
3852 return graph()->NewNode(mcgraph()->machine()->S1x4AllTrue(), inputs[0]);
3853 case wasm::kExprS1x8AnyTrue:
3854 return graph()->NewNode(mcgraph()->machine()->S1x8AnyTrue(), inputs[0]);
3855 case wasm::kExprS1x8AllTrue:
3856 return graph()->NewNode(mcgraph()->machine()->S1x8AllTrue(), inputs[0]);
3857 case wasm::kExprS1x16AnyTrue:
3858 return graph()->NewNode(mcgraph()->machine()->S1x16AnyTrue(), inputs[0]);
3859 case wasm::kExprS1x16AllTrue:
3860 return graph()->NewNode(mcgraph()->machine()->S1x16AllTrue(), inputs[0]);
3862 FATAL_UNSUPPORTED_OPCODE(opcode);
3866 Node* WasmGraphBuilder::SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane,
3867 Node*
const* inputs) {
3870 case wasm::kExprF32x4ExtractLane:
3871 return graph()->NewNode(mcgraph()->machine()->F32x4ExtractLane(lane),
3873 case wasm::kExprF32x4ReplaceLane:
3874 return graph()->NewNode(mcgraph()->machine()->F32x4ReplaceLane(lane),
3875 inputs[0], inputs[1]);
3876 case wasm::kExprI32x4ExtractLane:
3877 return graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
3879 case wasm::kExprI32x4ReplaceLane:
3880 return graph()->NewNode(mcgraph()->machine()->I32x4ReplaceLane(lane),
3881 inputs[0], inputs[1]);
3882 case wasm::kExprI16x8ExtractLane:
3883 return graph()->NewNode(mcgraph()->machine()->I16x8ExtractLane(lane),
3885 case wasm::kExprI16x8ReplaceLane:
3886 return graph()->NewNode(mcgraph()->machine()->I16x8ReplaceLane(lane),
3887 inputs[0], inputs[1]);
3888 case wasm::kExprI8x16ExtractLane:
3889 return graph()->NewNode(mcgraph()->machine()->I8x16ExtractLane(lane),
3891 case wasm::kExprI8x16ReplaceLane:
3892 return graph()->NewNode(mcgraph()->machine()->I8x16ReplaceLane(lane),
3893 inputs[0], inputs[1]);
3895 FATAL_UNSUPPORTED_OPCODE(opcode);
3899 Node* WasmGraphBuilder::SimdShiftOp(wasm::WasmOpcode opcode, uint8_t shift,
3900 Node*
const* inputs) {
3903 case wasm::kExprI32x4Shl:
3904 return graph()->NewNode(mcgraph()->machine()->I32x4Shl(shift), inputs[0]);
3905 case wasm::kExprI32x4ShrS:
3906 return graph()->NewNode(mcgraph()->machine()->I32x4ShrS(shift),
3908 case wasm::kExprI32x4ShrU:
3909 return graph()->NewNode(mcgraph()->machine()->I32x4ShrU(shift),
3911 case wasm::kExprI16x8Shl:
3912 return graph()->NewNode(mcgraph()->machine()->I16x8Shl(shift), inputs[0]);
3913 case wasm::kExprI16x8ShrS:
3914 return graph()->NewNode(mcgraph()->machine()->I16x8ShrS(shift),
3916 case wasm::kExprI16x8ShrU:
3917 return graph()->NewNode(mcgraph()->machine()->I16x8ShrU(shift),
3919 case wasm::kExprI8x16Shl:
3920 return graph()->NewNode(mcgraph()->machine()->I8x16Shl(shift), inputs[0]);
3921 case wasm::kExprI8x16ShrS:
3922 return graph()->NewNode(mcgraph()->machine()->I8x16ShrS(shift),
3924 case wasm::kExprI8x16ShrU:
3925 return graph()->NewNode(mcgraph()->machine()->I8x16ShrU(shift),
3928 FATAL_UNSUPPORTED_OPCODE(opcode);
3932 Node* WasmGraphBuilder::Simd8x16ShuffleOp(
const uint8_t shuffle[16],
3933 Node*
const* inputs) {
3935 return graph()->NewNode(mcgraph()->machine()->S8x16Shuffle(shuffle),
3936 inputs[0], inputs[1]);
3939 #define ATOMIC_BINOP_LIST(V) \ 3940 V(I32AtomicAdd, Add, Uint32, Word32) \ 3941 V(I64AtomicAdd, Add, Uint64, Word64) \ 3942 V(I32AtomicAdd8U, Add, Uint8, Word32) \ 3943 V(I32AtomicAdd16U, Add, Uint16, Word32) \ 3944 V(I64AtomicAdd8U, Add, Uint8, Word64) \ 3945 V(I64AtomicAdd16U, Add, Uint16, Word64) \ 3946 V(I64AtomicAdd32U, Add, Uint32, Word64) \ 3947 V(I32AtomicSub, Sub, Uint32, Word32) \ 3948 V(I64AtomicSub, Sub, Uint64, Word64) \ 3949 V(I32AtomicSub8U, Sub, Uint8, Word32) \ 3950 V(I32AtomicSub16U, Sub, Uint16, Word32) \ 3951 V(I64AtomicSub8U, Sub, Uint8, Word64) \ 3952 V(I64AtomicSub16U, Sub, Uint16, Word64) \ 3953 V(I64AtomicSub32U, Sub, Uint32, Word64) \ 3954 V(I32AtomicAnd, And, Uint32, Word32) \ 3955 V(I64AtomicAnd, And, Uint64, Word64) \ 3956 V(I32AtomicAnd8U, And, Uint8, Word32) \ 3957 V(I64AtomicAnd16U, And, Uint16, Word64) \ 3958 V(I32AtomicAnd16U, And, Uint16, Word32) \ 3959 V(I64AtomicAnd8U, And, Uint8, Word64) \ 3960 V(I64AtomicAnd32U, And, Uint32, Word64) \ 3961 V(I32AtomicOr, Or, Uint32, Word32) \ 3962 V(I64AtomicOr, Or, Uint64, Word64) \ 3963 V(I32AtomicOr8U, Or, Uint8, Word32) \ 3964 V(I32AtomicOr16U, Or, Uint16, Word32) \ 3965 V(I64AtomicOr8U, Or, Uint8, Word64) \ 3966 V(I64AtomicOr16U, Or, Uint16, Word64) \ 3967 V(I64AtomicOr32U, Or, Uint32, Word64) \ 3968 V(I32AtomicXor, Xor, Uint32, Word32) \ 3969 V(I64AtomicXor, Xor, Uint64, Word64) \ 3970 V(I32AtomicXor8U, Xor, Uint8, Word32) \ 3971 V(I32AtomicXor16U, Xor, Uint16, Word32) \ 3972 V(I64AtomicXor8U, Xor, Uint8, Word64) \ 3973 V(I64AtomicXor16U, Xor, Uint16, Word64) \ 3974 V(I64AtomicXor32U, Xor, Uint32, Word64) \ 3975 V(I32AtomicExchange, Exchange, Uint32, Word32) \ 3976 V(I64AtomicExchange, Exchange, Uint64, Word64) \ 3977 V(I32AtomicExchange8U, Exchange, Uint8, Word32) \ 3978 V(I32AtomicExchange16U, Exchange, Uint16, Word32) \ 3979 V(I64AtomicExchange8U, Exchange, Uint8, Word64) \ 3980 V(I64AtomicExchange16U, Exchange, Uint16, Word64) \ 3981 V(I64AtomicExchange32U, Exchange, Uint32, Word64) 3983 #define ATOMIC_CMP_EXCHG_LIST(V) \ 3984 V(I32AtomicCompareExchange, Uint32, Word32) \ 3985 V(I64AtomicCompareExchange, Uint64, Word64) \ 3986 V(I32AtomicCompareExchange8U, Uint8, Word32) \ 3987 V(I32AtomicCompareExchange16U, Uint16, Word32) \ 3988 V(I64AtomicCompareExchange8U, Uint8, Word64) \ 3989 V(I64AtomicCompareExchange16U, Uint16, Word64) \ 3990 V(I64AtomicCompareExchange32U, Uint32, Word64) 3992 #define ATOMIC_LOAD_LIST(V) \ 3993 V(I32AtomicLoad, Uint32, Word32) \ 3994 V(I64AtomicLoad, Uint64, Word64) \ 3995 V(I32AtomicLoad8U, Uint8, Word32) \ 3996 V(I32AtomicLoad16U, Uint16, Word32) \ 3997 V(I64AtomicLoad8U, Uint8, Word64) \ 3998 V(I64AtomicLoad16U, Uint16, Word64) \ 3999 V(I64AtomicLoad32U, Uint32, Word64) 4001 #define ATOMIC_STORE_LIST(V) \ 4002 V(I32AtomicStore, Uint32, kWord32, Word32) \ 4003 V(I64AtomicStore, Uint64, kWord64, Word64) \ 4004 V(I32AtomicStore8U, Uint8, kWord8, Word32) \ 4005 V(I32AtomicStore16U, Uint16, kWord16, Word32) \ 4006 V(I64AtomicStore8U, Uint8, kWord8, Word64) \ 4007 V(I64AtomicStore16U, Uint16, kWord16, Word64) \ 4008 V(I64AtomicStore32U, Uint32, kWord32, Word64) 4010 Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node*
const* inputs,
4012 wasm::WasmCodePosition position) {
4015 #define BUILD_ATOMIC_BINOP(Name, Operation, Type, Prefix) \ 4016 case wasm::kExpr##Name: { \ 4017 Node* index = CheckBoundsAndAlignment( \ 4018 wasm::ValueTypes::MemSize(MachineType::Type()), inputs[0], offset, \ 4020 node = graph()->NewNode( \ 4021 mcgraph()->machine()->Prefix##Atomic##Operation(MachineType::Type()), \ 4022 MemBuffer(offset), index, inputs[1], Effect(), Control()); \ 4025 ATOMIC_BINOP_LIST(BUILD_ATOMIC_BINOP)
4026 #undef BUILD_ATOMIC_BINOP 4028 #define BUILD_ATOMIC_CMP_EXCHG(Name, Type, Prefix) \ 4029 case wasm::kExpr##Name: { \ 4030 Node* index = CheckBoundsAndAlignment( \ 4031 wasm::ValueTypes::MemSize(MachineType::Type()), inputs[0], offset, \ 4033 node = graph()->NewNode( \ 4034 mcgraph()->machine()->Prefix##AtomicCompareExchange( \ 4035 MachineType::Type()), \ 4036 MemBuffer(offset), index, inputs[1], inputs[2], Effect(), Control()); \ 4039 ATOMIC_CMP_EXCHG_LIST(BUILD_ATOMIC_CMP_EXCHG)
4040 #undef BUILD_ATOMIC_CMP_EXCHG 4042 #define BUILD_ATOMIC_LOAD_OP(Name, Type, Prefix) \ 4043 case wasm::kExpr##Name: { \ 4044 Node* index = CheckBoundsAndAlignment( \ 4045 wasm::ValueTypes::MemSize(MachineType::Type()), inputs[0], offset, \ 4047 node = graph()->NewNode( \ 4048 mcgraph()->machine()->Prefix##AtomicLoad(MachineType::Type()), \ 4049 MemBuffer(offset), index, Effect(), Control()); \ 4052 ATOMIC_LOAD_LIST(BUILD_ATOMIC_LOAD_OP)
4053 #undef BUILD_ATOMIC_LOAD_OP 4055 #define BUILD_ATOMIC_STORE_OP(Name, Type, Rep, Prefix) \ 4056 case wasm::kExpr##Name: { \ 4057 Node* index = CheckBoundsAndAlignment( \ 4058 wasm::ValueTypes::MemSize(MachineType::Type()), inputs[0], offset, \ 4060 node = graph()->NewNode( \ 4061 mcgraph()->machine()->Prefix##AtomicStore(MachineRepresentation::Rep), \ 4062 MemBuffer(offset), index, inputs[1], Effect(), Control()); \ 4065 ATOMIC_STORE_LIST(BUILD_ATOMIC_STORE_OP)
4066 #undef BUILD_ATOMIC_STORE_OP 4067 case wasm::kExprAtomicWake: {
4068 Node* index = CheckBoundsAndAlignment(
4069 wasm::ValueTypes::MemSize(MachineType::Uint32()), inputs[0], offset,
4072 Node* address = graph()->NewNode(mcgraph()->machine()->Int32Add(),
4073 Uint32Constant(offset), index);
4074 WasmAtomicWakeDescriptor interface_descriptor;
4075 auto call_descriptor = Linkage::GetStubCallDescriptor(
4076 mcgraph()->zone(), interface_descriptor,
4077 interface_descriptor.GetStackParameterCount(),
4078 CallDescriptor::kNoFlags, Operator::kNoProperties,
4079 StubCallMode::kCallWasmRuntimeStub);
4080 Node* call_target = mcgraph()->RelocatableIntPtrConstant(
4081 wasm::WasmCode::kWasmAtomicWake, RelocInfo::WASM_STUB_CALL);
4082 node = graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
4083 call_target, address, inputs[1], Effect(),
4088 case wasm::kExprI32AtomicWait: {
4089 Node* index = CheckBoundsAndAlignment(
4090 wasm::ValueTypes::MemSize(MachineType::Uint32()), inputs[0], offset,
4093 Node* address = graph()->NewNode(mcgraph()->machine()->Int32Add(),
4094 Uint32Constant(offset), index);
4096 if (mcgraph()->machine()->Is32()) {
4097 timeout = BuildF64SConvertI64(inputs[2]);
4099 timeout = graph()->NewNode(mcgraph()->machine()->RoundInt64ToFloat64(),
4102 WasmI32AtomicWaitDescriptor interface_descriptor;
4103 auto call_descriptor = Linkage::GetStubCallDescriptor(
4104 mcgraph()->zone(), interface_descriptor,
4105 interface_descriptor.GetStackParameterCount(),
4106 CallDescriptor::kNoFlags, Operator::kNoProperties,
4107 StubCallMode::kCallWasmRuntimeStub);
4108 Node* call_target = mcgraph()->RelocatableIntPtrConstant(
4109 wasm::WasmCode::kWasmI32AtomicWait, RelocInfo::WASM_STUB_CALL);
4110 node = graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
4111 call_target, address, inputs[1], timeout,
4112 Effect(), Control());
4117 FATAL_UNSUPPORTED_OPCODE(opcode);
4119 return SetEffect(node);
4122 #undef ATOMIC_BINOP_LIST 4123 #undef ATOMIC_CMP_EXCHG_LIST 4124 #undef ATOMIC_LOAD_LIST 4125 #undef ATOMIC_STORE_LIST 4130 : origins_(origins), decoder_(decoder) {}
4132 void Decorate(
Node* node)
final {
4133 origins_->SetNodeOrigin(
4134 node,
NodeOrigin(
"wasm graph creation",
"n/a",
4135 NodeOrigin::kWasmBytecode, decoder_->position()));
4143 void WasmGraphBuilder::AddBytecodePositionDecorator(
4145 DCHECK_NULL(decorator_);
4146 decorator_ =
new (graph()->zone())
WasmDecorator(node_origins, decoder);
4147 graph()->AddDecorator(decorator_);
4150 void WasmGraphBuilder::RemoveBytecodePositionDecorator() {
4151 DCHECK_NOT_NULL(decorator_);
4152 graph()->RemoveDecorator(decorator_);
4153 decorator_ =
nullptr;
4157 bool must_record_function_compilation(Isolate* isolate) {
4158 return isolate->logger()->is_listening_to_code_events() ||
4159 isolate->is_profiling();
4163 void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
4164 Isolate* isolate, Handle<Code> code,
4165 const
char* format, ...) {
4166 DCHECK(must_record_function_compilation(isolate));
4168 ScopedVector<char> buffer(128);
4170 va_start(arguments, format);
4171 int len = VSNPrintF(buffer, format, arguments);
4174 Handle<String> name_str =
4175 isolate->factory()->NewStringFromAsciiChecked(buffer.start());
4176 PROFILE(isolate, CodeCreateEvent(tag, AbstractCode::cast(*code), *name_str));
4179 class WasmWrapperGraphBuilder :
public WasmGraphBuilder {
4181 WasmWrapperGraphBuilder(Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* sig,
4182 compiler::SourcePositionTable* spt,
4183 StubCallMode stub_mode)
4184 : WasmGraphBuilder(nullptr, zone, jsgraph, sig, spt),
4185 isolate_(jsgraph->isolate()),
4187 stub_mode_(stub_mode) {}
4189 Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control) {
4190 MachineOperatorBuilder* machine = mcgraph()->machine();
4191 CommonOperatorBuilder* common = mcgraph()->common();
4192 Node* target = (stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
4193 ? mcgraph()->RelocatableIntPtrConstant(
4194 wasm::WasmCode::kWasmAllocateHeapNumber,
4195 RelocInfo::WASM_STUB_CALL)
4196 : jsgraph()->HeapConstant(
4197 BUILTIN_CODE(isolate_, AllocateHeapNumber));
4198 if (!allocate_heap_number_operator_.is_set()) {
4199 auto call_descriptor = Linkage::GetStubCallDescriptor(
4200 mcgraph()->zone(), AllocateHeapNumberDescriptor(), 0,
4201 CallDescriptor::kNoFlags, Operator::kNoThrow, stub_mode_);
4202 allocate_heap_number_operator_.set(common->Call(call_descriptor));
4204 Node* heap_number = graph()->NewNode(allocate_heap_number_operator_.get(),
4205 target, Effect(), control);
4207 graph()->NewNode(machine->Store(StoreRepresentation(
4208 MachineRepresentation::kFloat64, kNoWriteBarrier)),
4209 heap_number, BuildHeapNumberValueIndexConstant(),
4210 value, heap_number, control));
4214 Node* BuildChangeSmiToFloat64(Node* value) {
4215 return graph()->NewNode(mcgraph()->machine()->ChangeInt32ToFloat64(),
4216 BuildChangeSmiToInt32(value));
4219 Node* BuildTestHeapObject(Node* value) {
4220 return graph()->NewNode(mcgraph()->machine()->WordAnd(), value,
4221 mcgraph()->IntPtrConstant(kHeapObjectTag));
4224 Node* BuildLoadHeapNumberValue(Node* value) {
4225 return SetEffect(graph()->NewNode(
4226 mcgraph()->machine()->Load(MachineType::Float64()), value,
4227 BuildHeapNumberValueIndexConstant(), Effect(), Control()));
4230 Node* BuildHeapNumberValueIndexConstant() {
4231 return mcgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
4234 Node* BuildChangeInt32ToTagged(Node* value) {
4235 MachineOperatorBuilder* machine = mcgraph()->machine();
4236 CommonOperatorBuilder* common = mcgraph()->common();
4238 if (SmiValuesAre32Bits()) {
4239 return BuildChangeInt32ToSmi(value);
4241 DCHECK(SmiValuesAre31Bits());
4243 Node* effect = Effect();
4244 Node* control = Control();
4245 Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value,
4248 Node* ovf = graph()->NewNode(common->Projection(1), add, graph()->start());
4250 graph()->NewNode(common->Branch(BranchHint::kFalse), ovf, control);
4252 Node* if_true = graph()->NewNode(common->IfTrue(), branch);
4253 Node* vtrue = BuildAllocateHeapNumberWithValue(
4254 graph()->NewNode(machine->ChangeInt32ToFloat64(), value), if_true);
4255 Node* etrue = Effect();
4257 Node* if_false = graph()->NewNode(common->IfFalse(), branch);
4258 Node* vfalse = graph()->NewNode(common->Projection(0), add, if_false);
4259 vfalse = BuildChangeInt32ToIntPtr(vfalse);
4262 SetControl(graph()->NewNode(common->Merge(2), if_true, if_false));
4263 SetEffect(graph()->NewNode(common->EffectPhi(2), etrue, effect, merge));
4264 return graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2),
4265 vtrue, vfalse, merge);
4268 Node* BuildChangeFloat64ToTagged(Node* value) {
4269 MachineOperatorBuilder* machine = mcgraph()->machine();
4270 CommonOperatorBuilder* common = mcgraph()->common();
4283 Node* effect = Effect();
4284 Node* control = Control();
4285 Node* value32 = graph()->NewNode(machine->RoundFloat64ToInt32(), value);
4286 Node* check_i32 = graph()->NewNode(
4287 machine->Float64Equal(), value,
4288 graph()->NewNode(machine->ChangeInt32ToFloat64(), value32));
4289 Node* branch_i32 = graph()->NewNode(common->Branch(), check_i32, control);
4291 Node* if_i32 = graph()->NewNode(common->IfTrue(), branch_i32);
4292 Node* if_not_i32 = graph()->NewNode(common->IfFalse(), branch_i32);
4295 Node* check_zero = graph()->NewNode(machine->Word32Equal(), value32,
4296 mcgraph()->Int32Constant(0));
4297 Node* branch_zero = graph()->NewNode(common->Branch(BranchHint::kFalse),
4298 check_zero, if_i32);
4300 Node* if_zero = graph()->NewNode(common->IfTrue(), branch_zero);
4301 Node* if_not_zero = graph()->NewNode(common->IfFalse(), branch_zero);
4304 Node* check_negative = graph()->NewNode(
4305 machine->Int32LessThan(),
4306 graph()->NewNode(machine->Float64ExtractHighWord32(), value),
4307 mcgraph()->Int32Constant(0));
4308 Node* branch_negative = graph()->NewNode(common->Branch(BranchHint::kFalse),
4309 check_negative, if_zero);
4311 Node* if_negative = graph()->NewNode(common->IfTrue(), branch_negative);
4312 Node* if_not_negative =
4313 graph()->NewNode(common->IfFalse(), branch_negative);
4317 graph()->NewNode(common->Merge(2), if_not_zero, if_not_negative);
4318 Node* if_box = graph()->NewNode(common->Merge(2), if_not_i32, if_negative);
4324 if (SmiValuesAre32Bits()) {
4325 vsmi = BuildChangeInt32ToSmi(value32);
4327 DCHECK(SmiValuesAre31Bits());
4328 Node* smi_tag = graph()->NewNode(machine->Int32AddWithOverflow(), value32,
4332 graph()->NewNode(common->Projection(1), smi_tag, if_smi);
4333 Node* branch_ovf = graph()->NewNode(common->Branch(BranchHint::kFalse),
4336 Node* if_ovf = graph()->NewNode(common->IfTrue(), branch_ovf);
4337 if_box = graph()->NewNode(common->Merge(2), if_ovf, if_box);
4339 if_smi = graph()->NewNode(common->IfFalse(), branch_ovf);
4340 vsmi = graph()->NewNode(common->Projection(0), smi_tag, if_smi);
4341 vsmi = BuildChangeInt32ToIntPtr(vsmi);
4345 Node* vbox = BuildAllocateHeapNumberWithValue(value, if_box);
4346 Node* ebox = Effect();
4349 SetControl(graph()->NewNode(common->Merge(2), if_smi, if_box));
4350 SetEffect(graph()->NewNode(common->EffectPhi(2), effect, ebox, merge));
4351 return graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2),
4355 int AddArgumentNodes(Node** args,
int pos,
int param_count,
4356 wasm::FunctionSig* sig) {
4358 for (
int i = 0;
i < param_count; ++
i) {
4361 args[pos++] = ToJS(param, sig->GetParam(
i));
4366 Node* BuildJavaScriptToNumber(Node* node, Node* js_context) {
4367 auto call_descriptor = Linkage::GetStubCallDescriptor(
4368 mcgraph()->zone(), TypeConversionDescriptor{}, 0,
4369 CallDescriptor::kNoFlags, Operator::kNoProperties, stub_mode_);
4371 (stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
4372 ? mcgraph()->RelocatableIntPtrConstant(
4373 wasm::WasmCode::kWasmToNumber, RelocInfo::WASM_STUB_CALL)
4374 : jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, ToNumber));
4376 Node* result = SetEffect(
4377 graph()->NewNode(mcgraph()->common()->Call(call_descriptor), stub_code,
4378 node, js_context, Effect(), Control()));
4380 SetSourcePosition(result, 1);
4385 Node* BuildChangeTaggedToFloat64(Node* value) {
4386 MachineOperatorBuilder* machine = mcgraph()->machine();
4387 CommonOperatorBuilder* common = mcgraph()->common();
4396 Node* check_heap_object = BuildTestHeapObject(value);
4397 Diamond is_heap_object(graph(), common, check_heap_object,
4398 BranchHint::kFalse);
4399 is_heap_object.Chain(Control());
4401 SetControl(is_heap_object.if_true);
4402 Node* orig_effect = Effect();
4404 Node* undefined_node =
4405 LOAD_INSTANCE_FIELD(UndefinedValue, MachineType::TaggedPointer());
4406 Node* check_undefined =
4407 graph()->NewNode(machine->WordEqual(), value, undefined_node);
4408 Node* effect_tagged = Effect();
4410 Diamond is_undefined(graph(), common, check_undefined, BranchHint::kFalse);
4411 is_undefined.Nest(is_heap_object,
true);
4413 SetControl(is_undefined.if_false);
4414 Node* vheap_number = BuildLoadHeapNumberValue(value);
4415 Node* effect_undefined = Effect();
4417 SetControl(is_undefined.merge);
4419 mcgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
4420 Node* vtagged = is_undefined.Phi(MachineRepresentation::kFloat64,
4421 vundefined, vheap_number);
4423 effect_tagged = is_undefined.EffectPhi(effect_tagged, effect_undefined);
4426 Node* vfrom_smi = BuildChangeSmiToFloat64(value);
4428 SetControl(is_heap_object.merge);
4429 SetEffect(is_heap_object.EffectPhi(effect_tagged, orig_effect));
4430 return is_heap_object.Phi(MachineRepresentation::kFloat64, vtagged,
4434 Node* ToJS(Node* node, wasm::ValueType type) {
4436 case wasm::kWasmI32:
4437 return BuildChangeInt32ToTagged(node);
4438 case wasm::kWasmS128:
4439 case wasm::kWasmI64:
4441 case wasm::kWasmF32:
4442 node = graph()->NewNode(mcgraph()->machine()->ChangeFloat32ToFloat64(),
4444 return BuildChangeFloat64ToTagged(node);
4445 case wasm::kWasmF64:
4446 return BuildChangeFloat64ToTagged(node);
4447 case wasm::kWasmAnyRef:
4454 Node* FromJS(Node* node, Node* js_context, wasm::ValueType type) {
4455 DCHECK_NE(wasm::kWasmStmt, type);
4458 if (type == wasm::kWasmAnyRef) {
4463 Node* num = BuildJavaScriptToNumber(node, js_context);
4466 num = BuildChangeTaggedToFloat64(num);
4469 case wasm::kWasmI32: {
4470 num = graph()->NewNode(mcgraph()->machine()->TruncateFloat64ToWord32(),
4474 case wasm::kWasmS128:
4475 case wasm::kWasmI64:
4477 case wasm::kWasmF32:
4478 num = graph()->NewNode(mcgraph()->machine()->TruncateFloat64ToFloat32(),
4481 case wasm::kWasmF64:
4489 void BuildModifyThreadInWasmFlag(
bool new_value) {
4490 if (!trap_handler::IsTrapHandlerEnabled())
return;
4491 Node* isolate_root =
4492 LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer());
4494 Node* thread_in_wasm_flag_address =
4495 LOAD_RAW(isolate_root, Isolate::thread_in_wasm_flag_address_offset(),
4496 MachineType::Pointer());
4498 SetEffect(graph()->NewNode(
4499 mcgraph()->machine()->Store(StoreRepresentation(
4500 MachineRepresentation::kWord32, kNoWriteBarrier)),
4501 thread_in_wasm_flag_address, mcgraph()->Int32Constant(0),
4502 mcgraph()->Int32Constant(new_value ? 1 : 0), Effect(), Control()));
4505 Node* BuildLoadFunctionDataFromExportedFunction(Node* closure) {
4506 Node* shared = SetEffect(graph()->NewNode(
4507 jsgraph()->machine()->Load(MachineType::AnyTagged()), closure,
4508 jsgraph()->Int32Constant(
4509 wasm::ObjectAccess::SharedFunctionInfoOffsetInTaggedJSFunction()),
4510 Effect(), Control()));
4511 return SetEffect(graph()->NewNode(
4512 jsgraph()->machine()->Load(MachineType::AnyTagged()), shared,
4513 jsgraph()->Int32Constant(SharedFunctionInfo::kFunctionDataOffset -
4515 Effect(), Control()));
4518 Node* BuildLoadInstanceFromExportedFunctionData(Node* function_data) {
4519 return SetEffect(graph()->NewNode(
4520 jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
4521 jsgraph()->Int32Constant(WasmExportedFunctionData::kInstanceOffset -
4523 Effect(), Control()));
4526 Node* BuildLoadFunctionIndexFromExportedFunctionData(Node* function_data) {
4527 Node* function_index_smi = SetEffect(graph()->NewNode(
4528 jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
4529 jsgraph()->Int32Constant(
4530 WasmExportedFunctionData::kFunctionIndexOffset - kHeapObjectTag),
4531 Effect(), Control()));
4532 Node* function_index = BuildChangeSmiToInt32(function_index_smi);
4533 return function_index;
4536 Node* BuildLoadJumpTableOffsetFromExportedFunctionData(Node* function_data) {
4537 Node* jump_table_offset_smi = SetEffect(graph()->NewNode(
4538 jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
4539 jsgraph()->Int32Constant(
4540 WasmExportedFunctionData::kJumpTableOffsetOffset - kHeapObjectTag),
4541 Effect(), Control()));
4542 Node* jump_table_offset = BuildChangeSmiToInt32(jump_table_offset_smi);
4543 return jump_table_offset;
4546 void BuildJSToWasmWrapper(
bool is_import) {
4547 const int wasm_count =
static_cast<int>(sig_->parameter_count());
4550 SetEffect(SetControl(Start(wasm_count + 5)));
4554 graph()->NewNode(jsgraph()->common()->Parameter(
4555 Linkage::kJSCallClosureParamIndex,
"%closure"),
4557 Node* js_context = graph()->NewNode(
4558 mcgraph()->common()->Parameter(
4559 Linkage::GetJSCallContextParamIndex(wasm_count + 1),
"%context"),
4566 Node* function_data = BuildLoadFunctionDataFromExportedFunction(js_closure);
4568 BuildLoadInstanceFromExportedFunctionData(function_data));
4570 if (!wasm::IsJSCompatibleSignature(sig_)) {
4574 BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, js_context,
4576 Return(jsgraph()->SmiConstant(0));
4580 const int args_count = wasm_count + 1;
4581 Node** args = Buffer(args_count);
4585 for (
int i = 0;
i < wasm_count; ++
i) {
4586 Node* param = Param(
i + 1);
4587 Node* wasm_param = FromJS(param, js_context, sig_->GetParam(
i));
4588 args[
i + 1] = wasm_param;
4592 BuildModifyThreadInWasmFlag(
true);
4597 Node* function_index =
4598 BuildLoadFunctionIndexFromExportedFunctionData(function_data);
4599 BuildImportCall(sig_, args, &rets, wasm::kNoCodePosition, function_index);
4603 Node* jump_table_start =
4604 LOAD_INSTANCE_FIELD(JumpTableStart, MachineType::Pointer());
4605 Node* jump_table_offset =
4606 BuildLoadJumpTableOffsetFromExportedFunctionData(function_data);
4607 Node* jump_table_slot = graph()->NewNode(
4608 mcgraph()->machine()->IntAdd(), jump_table_start, jump_table_offset);
4609 args[0] = jump_table_slot;
4611 BuildWasmCall(sig_, args, &rets, wasm::kNoCodePosition,
nullptr,
4616 BuildModifyThreadInWasmFlag(
false);
4618 Node* jsval = sig_->return_count() == 0 ? jsgraph()->UndefinedConstant()
4619 : ToJS(rets[0], sig_->GetReturn());
4623 bool BuildWasmImportCallWrapper(WasmImportCallKind kind) {
4624 int wasm_count =
static_cast<int>(sig_->parameter_count());
4627 SetEffect(SetControl(Start(wasm_count + 4)));
4629 instance_node_.set(Param(wasm::kWasmInstanceParameterIndex));
4631 Node* native_context =
4632 LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer());
4634 if (kind == WasmImportCallKind::kRuntimeTypeError) {
4638 BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError,
4639 native_context,
nullptr, 0);
4647 Node* callable_node = Param(wasm_count + 1);
4649 Node* undefined_node =
4650 LOAD_INSTANCE_FIELD(UndefinedValue, MachineType::TaggedPointer());
4652 Node* call =
nullptr;
4653 bool sloppy_receiver =
true;
4655 BuildModifyThreadInWasmFlag(
false);
4661 case WasmImportCallKind::kJSFunctionArityMatch:
4662 sloppy_receiver =
false;
4664 case WasmImportCallKind::kJSFunctionArityMatchSloppy: {
4665 Node** args = Buffer(wasm_count + 9);
4667 Node* function_context = SetEffect(graph()->NewNode(
4668 mcgraph()->machine()->Load(MachineType::TaggedPointer()),
4670 mcgraph()->Int32Constant(
4671 wasm::ObjectAccess::ContextOffsetInTaggedJSFunction()),
4672 Effect(), Control()));
4673 args[pos++] = callable_node;
4675 if (sloppy_receiver) {
4676 Node* global_proxy = LOAD_FIXED_ARRAY_SLOT_PTR(
4677 native_context, Context::GLOBAL_PROXY_INDEX);
4678 args[pos++] = global_proxy;
4680 args[pos++] = undefined_node;
4683 auto call_descriptor = Linkage::GetJSCallDescriptor(
4684 graph()->zone(),
false, wasm_count + 1, CallDescriptor::kNoFlags);
4687 pos = AddArgumentNodes(args, pos, wasm_count, sig_);
4689 args[pos++] = undefined_node;
4690 args[pos++] = mcgraph()->Int32Constant(wasm_count);
4691 args[pos++] = function_context;
4692 args[pos++] = Effect();
4693 args[pos++] = Control();
4695 call = graph()->NewNode(mcgraph()->common()->Call(call_descriptor), pos,
4702 case WasmImportCallKind::kJSFunctionArityMismatch:
4703 sloppy_receiver =
false;
4705 case WasmImportCallKind::kJSFunctionArityMismatchSloppy: {
4706 Node** args = Buffer(wasm_count + 9);
4708 Node* function_context = SetEffect(graph()->NewNode(
4709 mcgraph()->machine()->Load(MachineType::TaggedPointer()),
4711 mcgraph()->Int32Constant(
4712 wasm::ObjectAccess::ContextOffsetInTaggedJSFunction()),
4713 Effect(), Control()));
4715 BuildLoadBuiltinFromInstance(Builtins::kArgumentsAdaptorTrampoline);
4716 args[pos++] = callable_node;
4717 args[pos++] = undefined_node;
4718 args[pos++] = mcgraph()->Int32Constant(wasm_count);
4721 Node* shared_function_info = SetEffect(graph()->NewNode(
4722 mcgraph()->machine()->Load(MachineType::TaggedPointer()),
4724 mcgraph()->Int32Constant(
4725 wasm::ObjectAccess::
4726 SharedFunctionInfoOffsetInTaggedJSFunction()),
4727 Effect(), Control()));
4728 Node* formal_param_count = SetEffect(graph()->NewNode(
4729 mcgraph()->machine()->Load(MachineType::Uint16()),
4730 shared_function_info,
4731 mcgraph()->Int32Constant(
4732 wasm::ObjectAccess::
4733 FormalParameterCountOffsetInSharedFunctionInfo()),
4734 Effect(), Control()));
4735 args[pos++] = formal_param_count;
4738 if (sloppy_receiver) {
4739 Node* global_proxy = LOAD_FIXED_ARRAY_SLOT_PTR(
4740 native_context, Context::GLOBAL_PROXY_INDEX);
4741 args[pos++] = global_proxy;
4743 args[pos++] = undefined_node;
4746 #ifdef V8_TARGET_ARCH_IA32 4749 CallDescriptor::Flags flags = CallDescriptor::kAllowCallThroughSlot;
4751 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
4753 auto call_descriptor = Linkage::GetStubCallDescriptor(
4754 mcgraph()->zone(), ArgumentsAdaptorDescriptor{}, 1 + wasm_count,
4755 flags, Operator::kNoProperties);
4758 pos = AddArgumentNodes(args, pos, wasm_count, sig_);
4759 args[pos++] = function_context;
4760 args[pos++] = Effect();
4761 args[pos++] = Control();
4762 call = graph()->NewNode(mcgraph()->common()->Call(call_descriptor), pos,
4769 case WasmImportCallKind::kUseCallBuiltin: {
4770 Node** args = Buffer(wasm_count + 9);
4772 args[pos++] = mcgraph()->RelocatableIntPtrConstant(
4773 wasm::WasmCode::kWasmCallJavaScript, RelocInfo::WASM_STUB_CALL);
4774 args[pos++] = callable_node;
4775 args[pos++] = mcgraph()->Int32Constant(wasm_count);
4776 args[pos++] = undefined_node;
4778 auto call_descriptor = Linkage::GetStubCallDescriptor(
4779 graph()->zone(), CallTrampolineDescriptor{}, wasm_count + 1,
4780 CallDescriptor::kNoFlags, Operator::kNoProperties,
4781 StubCallMode::kCallWasmRuntimeStub);
4784 pos = AddArgumentNodes(args, pos, wasm_count, sig_);
4791 args[pos++] = native_context;
4792 args[pos++] = Effect();
4793 args[pos++] = Control();
4795 call = graph()->NewNode(mcgraph()->common()->Call(call_descriptor), pos,
4802 DCHECK_NOT_NULL(call);
4805 SetSourcePosition(call, 0);
4808 Node* val = sig_->return_count() == 0
4809 ? mcgraph()->Int32Constant(0)
4810 : FromJS(call, native_context, sig_->GetReturn());
4812 BuildModifyThreadInWasmFlag(
true);
4818 void BuildWasmInterpreterEntry(
uint32_t func_index) {
4819 int param_count =
static_cast<int>(sig_->parameter_count());
4822 SetEffect(SetControl(Start(param_count + 3)));
4825 instance_node_.set(Param(wasm::kWasmInstanceParameterIndex));
4828 int args_size_bytes = 0;
4829 for (wasm::ValueType type : sig_->parameters()) {
4830 args_size_bytes += wasm::ValueTypes::ElementSizeInBytes(type);
4834 DCHECK_GE(wasm::kV8MaxWasmFunctionReturns, sig_->return_count());
4836 DCHECK_EQ(1, wasm::kV8MaxWasmFunctionReturns);
4837 int return_size_bytes =
4838 sig_->return_count() == 0
4840 : wasm::ValueTypes::ElementSizeInBytes(sig_->GetReturn());
4844 args_size_bytes == 0 && return_size_bytes == 0
4845 ? mcgraph()->IntPtrConstant(0)
4846 : graph()->NewNode(mcgraph()->machine()->StackSlot(
4847 std::max(args_size_bytes, return_size_bytes), 8));
4852 for (
int i = 0;
i < param_count; ++
i) {
4853 wasm::ValueType type = sig_->GetParam(
i);
4855 SetEffect(graph()->NewNode(GetSafeStoreOperator(offset, type), arg_buffer,
4856 Int32Constant(offset), Param(
i + 1), Effect(),
4858 offset += wasm::ValueTypes::ElementSizeInBytes(type);
4860 DCHECK_EQ(args_size_bytes, offset);
4865 Node* parameters[] = {jsgraph()->SmiConstant(func_index), arg_buffer};
4866 BuildCallToRuntime(Runtime::kWasmRunInterpreter, parameters,
4867 arraysize(parameters));
4870 if (sig_->return_count() == 0) {
4871 Return(Int32Constant(0));
4874 DCHECK_EQ(1, sig_->return_count());
4875 MachineType load_rep =
4876 wasm::ValueTypes::MachineTypeFor(sig_->GetReturn());
4877 Node* val = SetEffect(
4878 graph()->NewNode(mcgraph()->machine()->Load(load_rep), arg_buffer,
4879 Int32Constant(0), Effect(), Control()));
4883 if (ContainsInt64(sig_)) LowerInt64();
4886 void BuildCWasmEntry() {
4888 SetEffect(SetControl(Start(CWasmEntryParameters::kNumParameters + 5)));
4891 Node* code_entry = Param(CWasmEntryParameters::kCodeEntry + 1);
4892 Node* object_ref_node = Param(CWasmEntryParameters::kObjectRef + 1);
4893 Node* arg_buffer = Param(CWasmEntryParameters::kArgumentsBuffer + 1);
4895 int wasm_arg_count =
static_cast<int>(sig_->parameter_count());
4898 Node** args = Buffer(arg_count);
4901 args[pos++] = code_entry;
4902 args[pos++] = object_ref_node;
4905 for (wasm::ValueType type : sig_->parameters()) {
4906 Node* arg_load = SetEffect(
4907 graph()->NewNode(GetSafeLoadOperator(offset, type), arg_buffer,
4908 Int32Constant(offset), Effect(), Control()));
4909 args[pos++] = arg_load;
4910 offset += wasm::ValueTypes::ElementSizeInBytes(type);
4913 args[pos++] = Effect();
4914 args[pos++] = Control();
4915 DCHECK_EQ(arg_count, pos);
4918 auto call_descriptor = GetWasmCallDescriptor(mcgraph()->zone(), sig_);
4920 Node* call = SetEffect(graph()->NewNode(
4921 mcgraph()->common()->Call(call_descriptor), arg_count, args));
4924 DCHECK_GE(1, sig_->return_count());
4925 if (sig_->return_count() == 1) {
4926 StoreRepresentation store_rep(
4927 wasm::ValueTypes::MachineRepresentationFor(sig_->GetReturn()),
4929 SetEffect(graph()->NewNode(mcgraph()->machine()->Store(store_rep),
4930 arg_buffer, Int32Constant(0), call, Effect(),
4933 Return(jsgraph()->SmiConstant(0));
4935 if (mcgraph()->machine()->Is32() && ContainsInt64(sig_)) {
4936 MachineRepresentation sig_reps[] = {
4937 MachineRepresentation::kWord32,
4938 MachineRepresentation::kTagged,
4939 MachineRepresentation::kTagged,
4940 MachineRepresentation::kTagged
4942 Signature<MachineRepresentation> c_entry_sig(1, 2, sig_reps);
4943 Int64Lowering r(mcgraph()->graph(), mcgraph()->machine(),
4944 mcgraph()->common(), mcgraph()->zone(), &c_entry_sig);
4949 JSGraph* jsgraph() {
return jsgraph_; }
4952 Isolate*
const isolate_;
4954 StubCallMode stub_mode_;
4955 SetOncePointer<const Operator> allocate_heap_number_operator_;
4958 void AppendSignature(
char* buffer,
size_t max_name_len,
4959 wasm::FunctionSig* sig) {
4960 size_t name_len = strlen(buffer);
4961 auto append_name_char = [&](
char c) {
4962 if (name_len + 1 < max_name_len) buffer[name_len++] = c;
4964 for (wasm::ValueType t : sig->parameters()) {
4965 append_name_char(wasm::ValueTypes::ShortNameOf(t));
4967 append_name_char(
':');
4968 for (wasm::ValueType t : sig->returns()) {
4969 append_name_char(wasm::ValueTypes::ShortNameOf(t));
4971 buffer[name_len] =
'\0';
4976 MaybeHandle<Code> CompileJSToWasmWrapper(Isolate* isolate,
4977 wasm::FunctionSig* sig,
4979 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT(
"v8.wasm"),
4980 "CompileJSToWasmWrapper");
4984 Zone zone(isolate->allocator(), ZONE_NAME);
4986 CommonOperatorBuilder common(&zone);
4987 MachineOperatorBuilder machine(
4988 &zone, MachineType::PointerRepresentation(),
4989 InstructionSelector::SupportedMachineOperatorFlags(),
4990 InstructionSelector::AlignmentRequirements());
4991 JSGraph jsgraph(isolate, &graph, &common,
nullptr,
nullptr, &machine);
4993 Node* control =
nullptr;
4994 Node* effect =
nullptr;
4996 WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig,
nullptr,
4997 StubCallMode::kCallOnHeapBuiltin);
4998 builder.set_control_ptr(&control);
4999 builder.set_effect_ptr(&effect);
5000 builder.BuildJSToWasmWrapper(is_import);
5005 static constexpr
size_t kMaxNameLen = 128;
5006 char debug_name[kMaxNameLen] =
"js_to_wasm:";
5007 AppendSignature(debug_name, kMaxNameLen, sig);
5010 int params =
static_cast<int>(sig->parameter_count());
5011 CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
5012 &zone,
false, params + 1, CallDescriptor::kNoFlags);
5014 MaybeHandle<Code> maybe_code = Pipeline::GenerateCodeForWasmHeapStub(
5015 isolate, incoming, &graph, Code::JS_TO_WASM_FUNCTION, debug_name,
5016 WasmAssemblerOptions());
5018 if (!maybe_code.ToHandle(&code)) {
5021 #ifdef ENABLE_DISASSEMBLER 5022 if (FLAG_print_opt_code) {
5023 CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
5024 OFStream os(tracing_scope.file());
5025 code->Disassemble(debug_name, os);
5029 if (must_record_function_compilation(isolate)) {
5030 RecordFunctionCompilation(CodeEventListener::STUB_TAG, isolate, code,
"%s",
5037 WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> target,
5038 wasm::FunctionSig* expected_sig) {
5039 if (WasmExportedFunction::IsWasmExportedFunction(*target)) {
5040 auto imported_function = WasmExportedFunction::cast(*target);
5041 wasm::FunctionSig* imported_sig =
5042 imported_function->instance()
5044 ->functions[imported_function->function_index()]
5046 if (*imported_sig != *expected_sig) {
5047 return WasmImportCallKind::kLinkError;
5049 return WasmImportCallKind::kWasmToWasm;
5052 if (!wasm::IsJSCompatibleSignature(expected_sig)) {
5053 return WasmImportCallKind::kRuntimeTypeError;
5057 if (target->IsJSFunction()) {
5058 Handle<JSFunction>
function = Handle<JSFunction>::cast(target);
5059 SharedFunctionInfo* shared =
function->shared();
5062 #define COMPARE_SIG_FOR_BUILTIN(name) \ 5064 wasm::FunctionSig* sig = wasm::WasmOpcodes::Signature(wasm::kExpr##name); \ 5065 if (!sig) sig = wasm::WasmOpcodes::AsmjsSignature(wasm::kExpr##name); \ 5066 DCHECK_NOT_NULL(sig); \ 5067 if (*expected_sig == *sig) return WasmImportCallKind::k##name; \ 5069 #define COMPARE_SIG_FOR_BUILTIN_F64(name) \ 5070 case Builtins::kMath##name: \ 5071 COMPARE_SIG_FOR_BUILTIN(F64##name); \ 5073 #define COMPARE_SIG_FOR_BUILTIN_F32_F64(name) \ 5074 case Builtins::kMath##name: \ 5075 COMPARE_SIG_FOR_BUILTIN(F64##name); \ 5076 COMPARE_SIG_FOR_BUILTIN(F32##name); \ 5079 if (FLAG_wasm_math_intrinsics && shared->HasBuiltinId()) {
5080 switch (shared->builtin_id()) {
5081 COMPARE_SIG_FOR_BUILTIN_F64(Acos);
5082 COMPARE_SIG_FOR_BUILTIN_F64(Asin);
5083 COMPARE_SIG_FOR_BUILTIN_F64(Atan);
5084 COMPARE_SIG_FOR_BUILTIN_F64(Cos);
5085 COMPARE_SIG_FOR_BUILTIN_F64(Sin);
5086 COMPARE_SIG_FOR_BUILTIN_F64(Tan);
5087 COMPARE_SIG_FOR_BUILTIN_F64(Exp);
5088 COMPARE_SIG_FOR_BUILTIN_F64(Log);
5089 COMPARE_SIG_FOR_BUILTIN_F64(Atan2);
5094 COMPARE_SIG_FOR_BUILTIN_F32_F64(Min);
5095 COMPARE_SIG_FOR_BUILTIN_F32_F64(Max);
5096 COMPARE_SIG_FOR_BUILTIN_F32_F64(Abs);
5097 COMPARE_SIG_FOR_BUILTIN_F32_F64(Ceil);
5098 COMPARE_SIG_FOR_BUILTIN_F32_F64(Floor);
5099 COMPARE_SIG_FOR_BUILTIN_F32_F64(Sqrt);
5100 case Builtins::kMathFround:
5101 COMPARE_SIG_FOR_BUILTIN(F32ConvertF64);
5108 #undef COMPARE_SIG_FOR_BUILTIN 5109 #undef COMPARE_SIG_FOR_BUILTIN_F64 5110 #undef COMPARE_SIG_FOR_BUILTIN_F32_F64 5112 if (IsClassConstructor(shared->kind())) {
5114 return WasmImportCallKind::kUseCallBuiltin;
5116 bool sloppy = is_sloppy(shared->language_mode()) && !shared->native();
5117 if (shared->internal_formal_parameter_count() ==
5118 expected_sig->parameter_count()) {
5119 return sloppy ? WasmImportCallKind::kJSFunctionArityMatchSloppy
5120 : WasmImportCallKind::kJSFunctionArityMatch;
5122 return sloppy ? WasmImportCallKind::kJSFunctionArityMismatchSloppy
5123 : WasmImportCallKind::kJSFunctionArityMismatch;
5126 return WasmImportCallKind::kUseCallBuiltin;
5129 wasm::WasmOpcode GetMathIntrinsicOpcode(WasmImportCallKind kind,
5130 const char** name_ptr) {
5131 #define CASE(name) \ 5132 case WasmImportCallKind::k##name: \ 5133 *name_ptr = "WasmMathIntrinsic:" #name; \ 5134 return wasm::kExpr##name 5158 CASE(F32ConvertF64);
5161 return wasm::kExprUnreachable;
5166 wasm::WasmCode* CompileWasmMathIntrinsic(Isolate* isolate,
5167 wasm::NativeModule* native_module,
5168 WasmImportCallKind kind,
5169 wasm::FunctionSig* sig) {
5170 DCHECK_EQ(1, sig->return_count());
5172 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT(
"v8.wasm"),
5173 "CompileWasmMathIntrinsic");
5175 Zone zone(isolate->allocator(), ZONE_NAME);
5179 SourcePositionTable* source_positions =
nullptr;
5180 MachineGraph* mcgraph =
new (&zone) MachineGraph(
5181 new (&zone) Graph(&zone),
new (&zone) CommonOperatorBuilder(&zone),
5182 new (&zone) MachineOperatorBuilder(
5183 &zone, MachineType::PointerRepresentation(),
5184 InstructionSelector::SupportedMachineOperatorFlags(),
5185 InstructionSelector::AlignmentRequirements()));
5187 wasm::CompilationEnv env(
5188 native_module->module(), wasm::UseTrapHandler::kNoTrapHandler,
5189 wasm::RuntimeExceptionSupport::kNoRuntimeExceptionSupport,
5190 wasm::LowerSimd::kNoLowerSimd);
5192 WasmGraphBuilder builder(&env, mcgraph->zone(), mcgraph, sig,
5196 Node* start = builder.Start(static_cast<int>(sig->parameter_count() + 1 + 1));
5197 Node* effect = start;
5198 Node* control = start;
5199 builder.set_effect_ptr(&effect);
5200 builder.set_control_ptr(&control);
5201 builder.set_instance_node(builder.Param(wasm::kWasmInstanceParameterIndex));
5204 Node* result =
nullptr;
5205 const char* debug_name =
"WasmMathIntrinsic";
5206 auto opcode = GetMathIntrinsicOpcode(kind, &debug_name);
5207 switch (sig->parameter_count()) {
5209 result = builder.Unop(opcode, builder.Param(1));
5212 result = builder.Binop(opcode, builder.Param(1), builder.Param(2));
5219 builder.Return(result);
5222 auto call_descriptor = GetWasmCallDescriptor(&zone, sig);
5223 if (mcgraph->machine()->Is32()) {
5224 call_descriptor = GetI32WasmCallDescriptor(&zone, call_descriptor);
5227 wasm::WasmCode* wasm_code = Pipeline::GenerateCodeForWasmNativeStub(
5228 isolate->wasm_engine(), call_descriptor, mcgraph, Code::WASM_FUNCTION,
5229 wasm::WasmCode::kFunction, debug_name, AssemblerOptions::Default(isolate),
5230 native_module, source_positions);
5231 CHECK_NOT_NULL(wasm_code);
5237 wasm::WasmCode* CompileWasmImportCallWrapper(Isolate* isolate,
5238 wasm::NativeModule* native_module,
5239 WasmImportCallKind kind,
5240 wasm::FunctionSig* sig,
5241 bool source_positions) {
5242 DCHECK_NE(WasmImportCallKind::kLinkError, kind);
5243 DCHECK_NE(WasmImportCallKind::kWasmToWasm, kind);
5246 if (FLAG_wasm_math_intrinsics &&
5247 kind >= WasmImportCallKind::kFirstMathIntrinsic &&
5248 kind <= WasmImportCallKind::kLastMathIntrinsic) {
5249 return CompileWasmMathIntrinsic(isolate, native_module, kind, sig);
5252 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT(
"v8.wasm"),
5253 "CompileWasmImportCallWrapper");
5257 Zone zone(isolate->allocator(), ZONE_NAME);
5259 CommonOperatorBuilder common(&zone);
5260 MachineOperatorBuilder machine(
5261 &zone, MachineType::PointerRepresentation(),
5262 InstructionSelector::SupportedMachineOperatorFlags(),
5263 InstructionSelector::AlignmentRequirements());
5264 JSGraph jsgraph(isolate, &graph, &common,
nullptr,
nullptr, &machine);
5266 Node* control =
nullptr;
5267 Node* effect =
nullptr;
5269 SourcePositionTable* source_position_table =
5270 source_positions ?
new (&zone) SourcePositionTable(&graph) :
nullptr;
5272 WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig, source_position_table,
5273 StubCallMode::kCallWasmRuntimeStub);
5274 builder.set_control_ptr(&control);
5275 builder.set_effect_ptr(&effect);
5276 builder.BuildWasmImportCallWrapper(kind);
5278 const char* func_name =
"wasm-to-js";
5281 CallDescriptor* incoming =
5282 GetWasmCallDescriptor(&zone, sig, WasmGraphBuilder::kNoRetpoline,
5283 WasmGraphBuilder::kExtraCallableParam);
5284 if (machine.Is32()) {
5285 incoming = GetI32WasmCallDescriptor(&zone, incoming);
5287 wasm::WasmCode* wasm_code = Pipeline::GenerateCodeForWasmNativeStub(
5288 isolate->wasm_engine(), incoming, &jsgraph, Code::WASM_TO_JS_FUNCTION,
5289 wasm::WasmCode::kWasmToJsWrapper, func_name,
5290 AssemblerOptions::Default(isolate), native_module, source_position_table);
5291 CHECK_NOT_NULL(wasm_code);
5296 wasm::WasmCode* CompileWasmInterpreterEntry(Isolate* isolate,
5297 wasm::NativeModule* native_module,
5299 wasm::FunctionSig* sig) {
5303 Zone zone(isolate->allocator(), ZONE_NAME);
5305 CommonOperatorBuilder common(&zone);
5306 MachineOperatorBuilder machine(
5307 &zone, MachineType::PointerRepresentation(),
5308 InstructionSelector::SupportedMachineOperatorFlags(),
5309 InstructionSelector::AlignmentRequirements());
5310 JSGraph jsgraph(isolate, &graph, &common,
nullptr,
nullptr, &machine);
5312 Node* control =
nullptr;
5313 Node* effect =
nullptr;
5315 WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig,
nullptr,
5316 StubCallMode::kCallWasmRuntimeStub);
5317 builder.set_control_ptr(&control);
5318 builder.set_effect_ptr(&effect);
5319 builder.BuildWasmInterpreterEntry(func_index);
5322 CallDescriptor* incoming = GetWasmCallDescriptor(&zone, sig);
5323 if (machine.Is32()) {
5324 incoming = GetI32WasmCallDescriptor(&zone, incoming);
5327 EmbeddedVector<char, 32> func_name;
5329 SNPrintF(func_name,
"wasm-interpreter-entry#%d", func_index));
5331 wasm::WasmCode* wasm_code = Pipeline::GenerateCodeForWasmNativeStub(
5332 isolate->wasm_engine(), incoming, &jsgraph, Code::WASM_INTERPRETER_ENTRY,
5333 wasm::WasmCode::kInterpreterEntry, func_name.start(),
5334 AssemblerOptions::Default(isolate), native_module);
5335 CHECK_NOT_NULL(wasm_code);
5340 MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
5341 Zone zone(isolate->allocator(), ZONE_NAME);
5343 CommonOperatorBuilder common(&zone);
5344 MachineOperatorBuilder machine(
5345 &zone, MachineType::PointerRepresentation(),
5346 InstructionSelector::SupportedMachineOperatorFlags(),
5347 InstructionSelector::AlignmentRequirements());
5348 JSGraph jsgraph(isolate, &graph, &common,
nullptr,
nullptr, &machine);
5350 Node* control =
nullptr;
5351 Node* effect =
nullptr;
5353 WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig,
nullptr,
5354 StubCallMode::kCallOnHeapBuiltin);
5355 builder.set_control_ptr(&control);
5356 builder.set_effect_ptr(&effect);
5357 builder.BuildCWasmEntry();
5360 CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
5361 &zone,
false, CWasmEntryParameters::kNumParameters + 1,
5362 CallDescriptor::kNoFlags);
5365 static constexpr
size_t kMaxNameLen = 128;
5366 char debug_name[kMaxNameLen] =
"c-wasm-entry:";
5367 AppendSignature(debug_name, kMaxNameLen, sig);
5369 MaybeHandle<Code> maybe_code = Pipeline::GenerateCodeForWasmHeapStub(
5370 isolate, incoming, &graph, Code::C_WASM_ENTRY, debug_name,
5371 AssemblerOptions::Default(isolate));
5373 if (!maybe_code.ToHandle(&code)) {
5376 #ifdef ENABLE_DISASSEMBLER 5377 if (FLAG_print_opt_code) {
5378 CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
5379 OFStream os(tracing_scope.file());
5380 code->Disassemble(debug_name, os);
5387 TurbofanWasmCompilationUnit::TurbofanWasmCompilationUnit(
5388 wasm::WasmCompilationUnit* wasm_unit)
5389 : wasm_unit_(wasm_unit) {}
5392 TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() =
default;
5394 bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
5395 wasm::CompilationEnv* env,
const wasm::FunctionBody& func_body,
5396 wasm::WasmFeatures* detected,
double* decode_ms, MachineGraph* mcgraph,
5397 NodeOriginTable* node_origins, SourcePositionTable* source_positions) {
5398 base::ElapsedTimer decode_timer;
5399 if (FLAG_trace_wasm_decode_time) {
5400 decode_timer.Start();
5404 WasmGraphBuilder builder(env, mcgraph->zone(), mcgraph, func_body.sig,
5406 wasm::VoidResult graph_construction_result = wasm::BuildTFGraph(
5407 wasm_unit_->wasm_engine_->allocator(),
5408 wasm_unit_->native_module_->enabled_features(), env->module, &builder,
5409 detected, func_body, node_origins);
5410 if (graph_construction_result.failed()) {
5411 if (FLAG_trace_wasm_compiler) {
5412 StdoutStream{} <<
"Compilation failed: " 5413 << graph_construction_result.error_msg() << std::endl;
5415 wasm_unit_->native_module()->compilation_state()->SetError(
5416 wasm_unit_->func_index_, std::move(graph_construction_result));
5420 builder.LowerInt64();
5422 if (builder.has_simd() &&
5423 (!CpuFeatures::SupportsWasmSimd128() || env->lower_simd)) {
5424 SimdScalarLowering(mcgraph,
5425 CreateMachineSignature(mcgraph->zone(), func_body.sig))
5429 if (wasm_unit_->func_index_ >= FLAG_trace_wasm_ast_start &&
5430 wasm_unit_->func_index_ < FLAG_trace_wasm_ast_end) {
5431 PrintRawWasmCode(wasm_unit_->wasm_engine_->allocator(), func_body,
5432 env->module, wasm::kPrintLocals);
5434 if (FLAG_trace_wasm_decode_time) {
5435 *decode_ms = decode_timer.Elapsed().InMillisecondsF();
5441 Vector<const char> GetDebugName(Zone* zone,
int index) {
5443 constexpr
int kBufferLength = 24;
5445 EmbeddedVector<char, kBufferLength> name_vector;
5446 int name_len = SNPrintF(name_vector,
"wasm-function#%d", index);
5447 DCHECK(name_len > 0 && name_len < name_vector.length());
5449 char* index_name = zone->NewArray<
char>(name_len);
5450 memcpy(index_name, name_vector.start(), name_len);
5451 return Vector<const char>(index_name, name_len);
5455 void TurbofanWasmCompilationUnit::ExecuteCompilation(
5456 wasm::CompilationEnv* env,
const wasm::FunctionBody& func_body,
5457 Counters* counters, wasm::WasmFeatures* detected) {
5458 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT(
"v8.wasm"),
5459 "ExecuteTurbofanCompilation");
5460 double decode_ms = 0;
5461 size_t node_count = 0;
5463 Zone zone(wasm_unit_->wasm_engine_->allocator(), ZONE_NAME);
5464 MachineGraph* mcgraph =
new (&zone) MachineGraph(
5465 new (&zone) Graph(&zone),
new (&zone) CommonOperatorBuilder(&zone),
5466 new (&zone) MachineOperatorBuilder(
5467 &zone, MachineType::PointerRepresentation(),
5468 InstructionSelector::SupportedMachineOperatorFlags(),
5469 InstructionSelector::AlignmentRequirements()));
5471 OptimizedCompilationInfo info(GetDebugName(&zone, wasm_unit_->func_index_),
5472 &zone, Code::WASM_FUNCTION);
5473 if (env->runtime_exception_support) {
5474 info.SetWasmRuntimeExceptionSupport();
5477 if (info.trace_turbo_json_enabled()) {
5479 tcf << AsC1VCompilation(&info);
5482 NodeOriginTable* node_origins = info.trace_turbo_json_enabled()
5484 NodeOriginTable(mcgraph->graph())
5486 SourcePositionTable* source_positions =
5487 new (mcgraph->zone()) SourcePositionTable(mcgraph->graph());
5488 if (!BuildGraphForWasmFunction(env, func_body, detected, &decode_ms, mcgraph,
5489 node_origins, source_positions)) {
5495 node_origins->AddDecorator();
5498 base::ElapsedTimer pipeline_timer;
5499 if (FLAG_trace_wasm_decode_time) {
5500 node_count = mcgraph->graph()->NodeCount();
5501 pipeline_timer.Start();
5505 auto call_descriptor = GetWasmCallDescriptor(&zone, func_body.sig);
5506 if (mcgraph->machine()->Is32()) {
5507 call_descriptor = GetI32WasmCallDescriptor(&zone, call_descriptor);
5510 if (wasm::WasmCode* wasm_code = Pipeline::GenerateCodeForWasmFunction(
5511 &info, wasm_unit_->wasm_engine_, mcgraph, call_descriptor,
5512 source_positions, node_origins, func_body, wasm_unit_->native_module_,
5513 wasm_unit_->func_index_)) {
5514 wasm_unit_->SetResult(wasm_code, counters);
5516 if (FLAG_trace_wasm_decode_time) {
5517 double pipeline_ms = pipeline_timer.Elapsed().InMillisecondsF();
5519 "wasm-compilation phase 1 ok: %u bytes, %0.3f ms decode, %zu nodes, " 5520 "%0.3f ms pipeline\n",
5521 static_cast<unsigned>(func_body.end - func_body.start), decode_ms,
5522 node_count, pipeline_ms);
5525 counters->wasm_compile_function_peak_memory_bytes()->AddSample(
5526 static_cast<int>(mcgraph->graph()->zone()->allocation_size()));
5531 class LinkageLocationAllocator {
5533 template <
size_t kNumGpRegs,
size_t kNumFpRegs>
5534 constexpr LinkageLocationAllocator(
const Register (&gp)[kNumGpRegs],
5535 const DoubleRegister (&fp)[kNumFpRegs])
5536 : allocator_(wasm::LinkageAllocator(gp, fp)) {}
5538 LinkageLocation Next(MachineRepresentation rep) {
5539 MachineType type = MachineType::TypeForRepresentation(rep);
5540 if (IsFloatingPoint(rep)) {
5541 if (allocator_.CanAllocateFP(rep)) {
5542 int reg_code = allocator_.NextFpReg(rep);
5543 return LinkageLocation::ForRegister(reg_code, type);
5545 }
else if (allocator_.CanAllocateGP()) {
5546 int reg_code = allocator_.NextGpReg();
5547 return LinkageLocation::ForRegister(reg_code, type);
5550 int index = -1 - allocator_.NextStackSlot(rep);
5551 return LinkageLocation::ForCallerFrameSlot(index, type);
5554 void SetStackOffset(
int offset) { allocator_.SetStackOffset(offset); }
5555 int NumStackSlots()
const {
return allocator_.NumStackSlots(); }
5558 wasm::LinkageAllocator allocator_;
5563 CallDescriptor* GetWasmCallDescriptor(
5564 Zone* zone, wasm::FunctionSig* fsig,
5565 WasmGraphBuilder::UseRetpoline use_retpoline,
5566 WasmGraphBuilder::ExtraCallableParam extra_callable_param) {
5569 int extra_params = extra_callable_param ? 2 : 1;
5570 LocationSignature::Builder locations(zone, fsig->return_count(),
5571 fsig->parameter_count() + extra_params);
5574 LinkageLocationAllocator params(wasm::kGpParamRegisters,
5575 wasm::kFpParamRegisters);
5578 locations.AddParam(params.Next(MachineRepresentation::kTaggedPointer));
5580 const int parameter_count =
static_cast<int>(fsig->parameter_count());
5581 for (
int i = 0;
i < parameter_count;
i++) {
5582 MachineRepresentation param =
5583 wasm::ValueTypes::MachineRepresentationFor(fsig->GetParam(
i));
5584 auto l = params.Next(param);
5585 locations.AddParam(l);
5590 if (extra_callable_param) {
5591 locations.AddParam(LinkageLocation::ForRegister(
5592 kJSFunctionRegister.code(), MachineType::TaggedPointer()));
5596 LinkageLocationAllocator rets(wasm::kGpReturnRegisters,
5597 wasm::kFpReturnRegisters);
5599 int parameter_slots = params.NumStackSlots();
5600 if (kPadArguments) parameter_slots = RoundUp(parameter_slots, 2);
5602 rets.SetStackOffset(parameter_slots);
5604 const int return_count =
static_cast<int>(locations.return_count_);
5605 for (
int i = 0;
i < return_count;
i++) {
5606 MachineRepresentation ret =
5607 wasm::ValueTypes::MachineRepresentationFor(fsig->GetReturn(
i));
5608 auto l = rets.Next(ret);
5609 locations.AddReturn(l);
5612 const RegList kCalleeSaveRegisters = 0;
5613 const RegList kCalleeSaveFPRegisters = 0;
5616 MachineType target_type = MachineType::Pointer();
5617 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
5619 CallDescriptor::Kind kind = extra_callable_param
5620 ? CallDescriptor::kCallWasmImportWrapper
5621 : CallDescriptor::kCallWasmFunction;
5623 CallDescriptor::Flags flags =
5624 use_retpoline ? CallDescriptor::kRetpoline : CallDescriptor::kNoFlags;
5625 return new (zone) CallDescriptor(
5631 compiler::Operator::kNoProperties,
5632 kCalleeSaveRegisters,
5633 kCalleeSaveFPRegisters,
5637 rets.NumStackSlots() - parameter_slots);
5641 CallDescriptor* ReplaceTypeInCallDescriptorWith(
5642 Zone* zone, CallDescriptor* call_descriptor,
size_t num_replacements,
5643 MachineType input_type, MachineRepresentation output_type) {
5644 size_t parameter_count = call_descriptor->ParameterCount();
5645 size_t return_count = call_descriptor->ReturnCount();
5647 if (call_descriptor->GetParameterType(
i) == input_type) {
5648 parameter_count += num_replacements - 1;
5651 for (
size_t i = 0;
i < call_descriptor->ReturnCount();
i++) {
5652 if (call_descriptor->GetReturnType(
i) == input_type) {
5653 return_count += num_replacements - 1;
5656 if (parameter_count == call_descriptor->ParameterCount() &&
5657 return_count == call_descriptor->ReturnCount()) {
5658 return call_descriptor;
5661 LocationSignature::Builder locations(zone, return_count, parameter_count);
5663 LinkageLocationAllocator params(wasm::kGpParamRegisters,
5664 wasm::kFpParamRegisters);
5666 if (call_descriptor->GetParameterType(
i) == input_type) {
5667 for (
size_t j = 0; j < num_replacements; j++) {
5668 locations.AddParam(params.Next(output_type));
5672 params.Next(call_descriptor->GetParameterType(
i).representation()));
5676 LinkageLocationAllocator rets(wasm::kGpReturnRegisters,
5677 wasm::kFpReturnRegisters);
5678 rets.SetStackOffset(params.NumStackSlots());
5679 for (
size_t i = 0;
i < call_descriptor->ReturnCount();
i++) {
5680 if (call_descriptor->GetReturnType(
i) == input_type) {
5681 for (
size_t j = 0; j < num_replacements; j++) {
5682 locations.AddReturn(rets.Next(output_type));
5685 locations.AddReturn(
5686 rets.Next(call_descriptor->GetReturnType(
i).representation()));
5690 return new (zone) CallDescriptor(
5691 call_descriptor->kind(),
5692 call_descriptor->GetInputType(0),
5693 call_descriptor->GetInputLocation(0),
5695 params.NumStackSlots(),
5696 call_descriptor->properties(),
5697 call_descriptor->CalleeSavedRegisters(),
5698 call_descriptor->CalleeSavedFPRegisters(),
5699 call_descriptor->flags(),
5700 call_descriptor->debug_name(),
5701 call_descriptor->AllocatableRegisters(),
5702 rets.NumStackSlots() - params.NumStackSlots());
5706 CallDescriptor* GetI32WasmCallDescriptor(Zone* zone,
5707 CallDescriptor* call_descriptor) {
5708 return ReplaceTypeInCallDescriptorWith(zone, call_descriptor, 2,
5709 MachineType::Int64(),
5710 MachineRepresentation::kWord32);
5713 CallDescriptor* GetI32WasmCallDescriptorForSimd(
5714 Zone* zone, CallDescriptor* call_descriptor) {
5715 return ReplaceTypeInCallDescriptorWith(zone, call_descriptor, 4,
5716 MachineType::Simd128(),
5717 MachineRepresentation::kWord32);
5720 AssemblerOptions WasmAssemblerOptions() {
5721 AssemblerOptions options;
5722 options.record_reloc_info_for_serialization =
true;
5723 options.enable_root_array_delta_access =
false;
5728 #undef FATAL_UNSUPPORTED_OPCODE 5729 #undef WASM_INSTANCE_OBJECT_SIZE 5730 #undef WASM_INSTANCE_OBJECT_OFFSET 5732 #undef LOAD_INSTANCE_FIELD 5733 #undef LOAD_TAGGED_POINTER 5734 #undef LOAD_TAGGED_ANY 5735 #undef LOAD_FIXED_ARRAY_SLOT 5736 #undef LOAD_FIXED_ARRAY_SLOT_SMI 5737 #undef LOAD_FIXED_ARRAY_SLOT_PTR 5738 #undef LOAD_FIXED_ARRAY_SLOT_ANY 5739 #undef STORE_FIXED_ARRAY_SLOT_SMI 5740 #undef STORE_FIXED_ARRAY_SLOT_ANY