diff options
Diffstat (limited to '')
-rw-r--r-- | js/src/wasm/WasmOpIter.cpp | 863 |
1 files changed, 863 insertions, 0 deletions
diff --git a/js/src/wasm/WasmOpIter.cpp b/js/src/wasm/WasmOpIter.cpp new file mode 100644 index 0000000000..91e2e17a70 --- /dev/null +++ b/js/src/wasm/WasmOpIter.cpp @@ -0,0 +1,863 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * + * Copyright 2015 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wasm/WasmOpIter.h" + +#include "jit/AtomicOp.h" + +using namespace js; +using namespace js::jit; +using namespace js::wasm; + +#ifdef ENABLE_WASM_GC +# ifndef ENABLE_WASM_FUNCTION_REFERENCES +# error "GC types require the function-references feature" +# endif +#endif + +#ifdef DEBUG + +# ifdef ENABLE_WASM_FUNCTION_REFERENCES +# define WASM_FUNCTION_REFERENCES_OP(code) return code +# else +# define WASM_FUNCTION_REFERENCES_OP(code) break +# endif +# ifdef ENABLE_WASM_GC +# define WASM_GC_OP(code) return code +# else +# define WASM_GC_OP(code) break +# endif +# ifdef ENABLE_WASM_SIMD +# define WASM_SIMD_OP(code) return code +# else +# define WASM_SIMD_OP(code) break +# endif + +OpKind wasm::Classify(OpBytes op) { + switch (Op(op.b0)) { + case Op::Block: + return OpKind::Block; + case Op::Loop: + return OpKind::Loop; + case Op::Unreachable: + return OpKind::Unreachable; + case Op::Drop: + return OpKind::Drop; + case Op::I32Const: + return OpKind::I32; + case Op::I64Const: + return OpKind::I64; + case Op::F32Const: + return OpKind::F32; + case Op::F64Const: + return OpKind::F64; + case Op::Br: + return OpKind::Br; + case Op::BrIf: + return OpKind::BrIf; + case Op::BrTable: + return OpKind::BrTable; + case Op::Nop: + return OpKind::Nop; + case Op::I32Clz: + case Op::I32Ctz: + case Op::I32Popcnt: + case Op::I64Clz: + case Op::I64Ctz: + case Op::I64Popcnt: + case Op::F32Abs: + case Op::F32Neg: + case Op::F32Ceil: + case Op::F32Floor: + case Op::F32Trunc: + case Op::F32Nearest: + case Op::F32Sqrt: + case Op::F64Abs: + case Op::F64Neg: + case Op::F64Ceil: + case Op::F64Floor: + case Op::F64Trunc: + case Op::F64Nearest: + case Op::F64Sqrt: + return OpKind::Unary; + case Op::I32Add: + case Op::I32Sub: + case Op::I32Mul: + case Op::I32DivS: + case Op::I32DivU: + case Op::I32RemS: + case Op::I32RemU: + case Op::I32And: + case Op::I32Or: + case Op::I32Xor: + case Op::I32Shl: + case Op::I32ShrS: + case Op::I32ShrU: + case Op::I32Rotl: + case Op::I32Rotr: + case Op::I64Add: + case Op::I64Sub: + case Op::I64Mul: + case Op::I64DivS: + case Op::I64DivU: + case Op::I64RemS: + case Op::I64RemU: + case Op::I64And: + case Op::I64Or: + case Op::I64Xor: + case Op::I64Shl: + case Op::I64ShrS: + case Op::I64ShrU: + case Op::I64Rotl: + case Op::I64Rotr: + case Op::F32Add: + case Op::F32Sub: + case Op::F32Mul: + case Op::F32Div: + case Op::F32Min: + case Op::F32Max: + case Op::F32CopySign: + case Op::F64Add: + case Op::F64Sub: + case Op::F64Mul: + case Op::F64Div: + case Op::F64Min: + case Op::F64Max: + case Op::F64CopySign: + return OpKind::Binary; + case Op::I32Eq: + case Op::I32Ne: + case Op::I32LtS: + case Op::I32LtU: + case Op::I32LeS: + case Op::I32LeU: + case Op::I32GtS: + case Op::I32GtU: + case Op::I32GeS: + case Op::I32GeU: + case Op::I64Eq: + case Op::I64Ne: + case Op::I64LtS: + case Op::I64LtU: + case Op::I64LeS: + case Op::I64LeU: + case Op::I64GtS: + case Op::I64GtU: + case Op::I64GeS: + case Op::I64GeU: + case Op::F32Eq: + case Op::F32Ne: + case Op::F32Lt: + case Op::F32Le: + case Op::F32Gt: + case Op::F32Ge: + case Op::F64Eq: + case Op::F64Ne: + case Op::F64Lt: + case Op::F64Le: + case Op::F64Gt: + case Op::F64Ge: + return OpKind::Comparison; + case Op::I32Eqz: + case Op::I32WrapI64: + case Op::I32TruncF32S: + case Op::I32TruncF32U: + case Op::I32ReinterpretF32: + case Op::I32TruncF64S: + case Op::I32TruncF64U: + case Op::I64ExtendI32S: + case Op::I64ExtendI32U: + case Op::I64TruncF32S: + case Op::I64TruncF32U: + case Op::I64TruncF64S: + case Op::I64TruncF64U: + case Op::I64ReinterpretF64: + case Op::I64Eqz: + case Op::F32ConvertI32S: + case Op::F32ConvertI32U: + case Op::F32ReinterpretI32: + case Op::F32ConvertI64S: + case Op::F32ConvertI64U: + case Op::F32DemoteF64: + case Op::F64ConvertI32S: + case Op::F64ConvertI32U: + case Op::F64ConvertI64S: + case Op::F64ConvertI64U: + case Op::F64ReinterpretI64: + case Op::F64PromoteF32: + case Op::I32Extend8S: + case Op::I32Extend16S: + case Op::I64Extend8S: + case Op::I64Extend16S: + case Op::I64Extend32S: + return OpKind::Conversion; + case Op::I32Load8S: + case Op::I32Load8U: + case Op::I32Load16S: + case Op::I32Load16U: + case Op::I64Load8S: + case Op::I64Load8U: + case Op::I64Load16S: + case Op::I64Load16U: + case Op::I64Load32S: + case Op::I64Load32U: + case Op::I32Load: + case Op::I64Load: + case Op::F32Load: + case Op::F64Load: + return OpKind::Load; + case Op::I32Store8: + case Op::I32Store16: + case Op::I64Store8: + case Op::I64Store16: + case Op::I64Store32: + case Op::I32Store: + case Op::I64Store: + case Op::F32Store: + case Op::F64Store: + return OpKind::Store; + case Op::SelectNumeric: + case Op::SelectTyped: + return OpKind::Select; + case Op::LocalGet: + return OpKind::GetLocal; + case Op::LocalSet: + return OpKind::SetLocal; + case Op::LocalTee: + return OpKind::TeeLocal; + case Op::GlobalGet: + return OpKind::GetGlobal; + case Op::GlobalSet: + return OpKind::SetGlobal; + case Op::TableGet: + return OpKind::TableGet; + case Op::TableSet: + return OpKind::TableSet; + case Op::Call: + return OpKind::Call; + case Op::CallIndirect: + return OpKind::CallIndirect; + case Op::CallRef: + WASM_FUNCTION_REFERENCES_OP(OpKind::CallRef); + case Op::Return: + case Op::Limit: + // Accept Limit, for use in decoding the end of a function after the body. + return OpKind::Return; + case Op::If: + return OpKind::If; + case Op::Else: + return OpKind::Else; + case Op::End: + return OpKind::End; + case Op::Catch: + return OpKind::Catch; + case Op::CatchAll: + return OpKind::CatchAll; + case Op::Delegate: + return OpKind::Delegate; + case Op::Throw: + return OpKind::Throw; + case Op::Rethrow: + return OpKind::Rethrow; + case Op::Try: + return OpKind::Try; + case Op::MemorySize: + return OpKind::MemorySize; + case Op::MemoryGrow: + return OpKind::MemoryGrow; + case Op::RefNull: + return OpKind::RefNull; + case Op::RefIsNull: + return OpKind::Conversion; + case Op::RefFunc: + return OpKind::RefFunc; + case Op::RefAsNonNull: + WASM_FUNCTION_REFERENCES_OP(OpKind::RefAsNonNull); + case Op::BrOnNull: + WASM_FUNCTION_REFERENCES_OP(OpKind::BrOnNull); + case Op::BrOnNonNull: + WASM_FUNCTION_REFERENCES_OP(OpKind::BrOnNonNull); + case Op::RefEq: + WASM_GC_OP(OpKind::Comparison); + case Op::GcPrefix: { + switch (GcOp(op.b1)) { + case GcOp::Limit: + // Reject Limit for GcPrefix encoding + break; + case GcOp::StructNew: + WASM_GC_OP(OpKind::StructNew); + case GcOp::StructNewDefault: + WASM_GC_OP(OpKind::StructNewDefault); + case GcOp::StructGet: + case GcOp::StructGetS: + case GcOp::StructGetU: + WASM_GC_OP(OpKind::StructGet); + case GcOp::StructSet: + WASM_GC_OP(OpKind::StructSet); + case GcOp::ArrayNew: + WASM_GC_OP(OpKind::ArrayNew); + case GcOp::ArrayNewFixed: + WASM_GC_OP(OpKind::ArrayNewFixed); + case GcOp::ArrayNewDefault: + WASM_GC_OP(OpKind::ArrayNewDefault); + case GcOp::ArrayNewData: + case GcOp::ArrayInitFromElemStaticV5: + case GcOp::ArrayNewElem: + WASM_GC_OP(OpKind::ArrayNewData); + case GcOp::ArrayGet: + case GcOp::ArrayGetS: + case GcOp::ArrayGetU: + WASM_GC_OP(OpKind::ArrayGet); + case GcOp::ArraySet: + WASM_GC_OP(OpKind::ArraySet); + case GcOp::ArrayLenWithTypeIndex: + case GcOp::ArrayLen: + WASM_GC_OP(OpKind::ArrayLen); + case GcOp::ArrayCopy: + WASM_GC_OP(OpKind::ArrayCopy); + case GcOp::RefTestV5: + WASM_GC_OP(OpKind::RefTestV5); + case GcOp::RefCastV5: + WASM_GC_OP(OpKind::RefCastV5); + case GcOp::RefTest: + case GcOp::RefTestNull: + WASM_GC_OP(OpKind::RefTest); + case GcOp::RefCast: + case GcOp::RefCastNull: + WASM_GC_OP(OpKind::RefCast); + case GcOp::BrOnCast: + WASM_GC_OP(OpKind::BrOnCast); + case GcOp::BrOnCastV5: + case GcOp::BrOnCastHeapV5: + case GcOp::BrOnCastHeapNullV5: + WASM_GC_OP(OpKind::BrOnCastV5); + case GcOp::BrOnCastFailV5: + case GcOp::BrOnCastFailHeapV5: + case GcOp::BrOnCastFailHeapNullV5: + WASM_GC_OP(OpKind::BrOnCastFailV5); + case GcOp::RefAsStructV5: + WASM_GC_OP(OpKind::Conversion); + case GcOp::BrOnNonStructV5: + WASM_GC_OP(OpKind::BrOnNonStructV5); + case GcOp::ExternInternalize: + WASM_GC_OP(OpKind::RefConversion); + case GcOp::ExternExternalize: + WASM_GC_OP(OpKind::RefConversion); + } + break; + } + case Op::SimdPrefix: { + switch (SimdOp(op.b1)) { + case SimdOp::MozPMADDUBSW: + case SimdOp::Limit: + // Reject Limit and reserved codes for SimdPrefix encoding + break; + case SimdOp::I8x16ExtractLaneS: + case SimdOp::I8x16ExtractLaneU: + case SimdOp::I16x8ExtractLaneS: + case SimdOp::I16x8ExtractLaneU: + case SimdOp::I32x4ExtractLane: + case SimdOp::I64x2ExtractLane: + case SimdOp::F32x4ExtractLane: + case SimdOp::F64x2ExtractLane: + WASM_SIMD_OP(OpKind::ExtractLane); + case SimdOp::I8x16Splat: + case SimdOp::I16x8Splat: + case SimdOp::I32x4Splat: + case SimdOp::I64x2Splat: + case SimdOp::F32x4Splat: + case SimdOp::F64x2Splat: + case SimdOp::V128AnyTrue: + case SimdOp::I8x16AllTrue: + case SimdOp::I16x8AllTrue: + case SimdOp::I32x4AllTrue: + case SimdOp::I64x2AllTrue: + case SimdOp::I8x16Bitmask: + case SimdOp::I16x8Bitmask: + case SimdOp::I32x4Bitmask: + case SimdOp::I64x2Bitmask: + WASM_SIMD_OP(OpKind::Conversion); + case SimdOp::I8x16ReplaceLane: + case SimdOp::I16x8ReplaceLane: + case SimdOp::I32x4ReplaceLane: + case SimdOp::I64x2ReplaceLane: + case SimdOp::F32x4ReplaceLane: + case SimdOp::F64x2ReplaceLane: + WASM_SIMD_OP(OpKind::ReplaceLane); + case SimdOp::I8x16Eq: + case SimdOp::I8x16Ne: + case SimdOp::I8x16LtS: + case SimdOp::I8x16LtU: + case SimdOp::I8x16GtS: + case SimdOp::I8x16GtU: + case SimdOp::I8x16LeS: + case SimdOp::I8x16LeU: + case SimdOp::I8x16GeS: + case SimdOp::I8x16GeU: + case SimdOp::I16x8Eq: + case SimdOp::I16x8Ne: + case SimdOp::I16x8LtS: + case SimdOp::I16x8LtU: + case SimdOp::I16x8GtS: + case SimdOp::I16x8GtU: + case SimdOp::I16x8LeS: + case SimdOp::I16x8LeU: + case SimdOp::I16x8GeS: + case SimdOp::I16x8GeU: + case SimdOp::I32x4Eq: + case SimdOp::I32x4Ne: + case SimdOp::I32x4LtS: + case SimdOp::I32x4LtU: + case SimdOp::I32x4GtS: + case SimdOp::I32x4GtU: + case SimdOp::I32x4LeS: + case SimdOp::I32x4LeU: + case SimdOp::I32x4GeS: + case SimdOp::I32x4GeU: + case SimdOp::I64x2Eq: + case SimdOp::I64x2Ne: + case SimdOp::I64x2LtS: + case SimdOp::I64x2GtS: + case SimdOp::I64x2LeS: + case SimdOp::I64x2GeS: + case SimdOp::F32x4Eq: + case SimdOp::F32x4Ne: + case SimdOp::F32x4Lt: + case SimdOp::F32x4Gt: + case SimdOp::F32x4Le: + case SimdOp::F32x4Ge: + case SimdOp::F64x2Eq: + case SimdOp::F64x2Ne: + case SimdOp::F64x2Lt: + case SimdOp::F64x2Gt: + case SimdOp::F64x2Le: + case SimdOp::F64x2Ge: + case SimdOp::V128And: + case SimdOp::V128Or: + case SimdOp::V128Xor: + case SimdOp::V128AndNot: + case SimdOp::I8x16AvgrU: + case SimdOp::I16x8AvgrU: + case SimdOp::I8x16Add: + case SimdOp::I8x16AddSatS: + case SimdOp::I8x16AddSatU: + case SimdOp::I8x16Sub: + case SimdOp::I8x16SubSatS: + case SimdOp::I8x16SubSatU: + case SimdOp::I8x16MinS: + case SimdOp::I8x16MaxS: + case SimdOp::I8x16MinU: + case SimdOp::I8x16MaxU: + case SimdOp::I16x8Add: + case SimdOp::I16x8AddSatS: + case SimdOp::I16x8AddSatU: + case SimdOp::I16x8Sub: + case SimdOp::I16x8SubSatS: + case SimdOp::I16x8SubSatU: + case SimdOp::I16x8Mul: + case SimdOp::I16x8MinS: + case SimdOp::I16x8MaxS: + case SimdOp::I16x8MinU: + case SimdOp::I16x8MaxU: + case SimdOp::I32x4Add: + case SimdOp::I32x4Sub: + case SimdOp::I32x4Mul: + case SimdOp::I32x4MinS: + case SimdOp::I32x4MaxS: + case SimdOp::I32x4MinU: + case SimdOp::I32x4MaxU: + case SimdOp::I64x2Add: + case SimdOp::I64x2Sub: + case SimdOp::I64x2Mul: + case SimdOp::F32x4Add: + case SimdOp::F32x4Sub: + case SimdOp::F32x4Mul: + case SimdOp::F32x4Div: + case SimdOp::F32x4Min: + case SimdOp::F32x4Max: + case SimdOp::F64x2Add: + case SimdOp::F64x2Sub: + case SimdOp::F64x2Mul: + case SimdOp::F64x2Div: + case SimdOp::F64x2Min: + case SimdOp::F64x2Max: + case SimdOp::I8x16NarrowI16x8S: + case SimdOp::I8x16NarrowI16x8U: + case SimdOp::I16x8NarrowI32x4S: + case SimdOp::I16x8NarrowI32x4U: + case SimdOp::I8x16Swizzle: + case SimdOp::F32x4PMin: + case SimdOp::F32x4PMax: + case SimdOp::F64x2PMin: + case SimdOp::F64x2PMax: + case SimdOp::I32x4DotI16x8S: + case SimdOp::I16x8ExtmulLowI8x16S: + case SimdOp::I16x8ExtmulHighI8x16S: + case SimdOp::I16x8ExtmulLowI8x16U: + case SimdOp::I16x8ExtmulHighI8x16U: + case SimdOp::I32x4ExtmulLowI16x8S: + case SimdOp::I32x4ExtmulHighI16x8S: + case SimdOp::I32x4ExtmulLowI16x8U: + case SimdOp::I32x4ExtmulHighI16x8U: + case SimdOp::I64x2ExtmulLowI32x4S: + case SimdOp::I64x2ExtmulHighI32x4S: + case SimdOp::I64x2ExtmulLowI32x4U: + case SimdOp::I64x2ExtmulHighI32x4U: + case SimdOp::I16x8Q15MulrSatS: + case SimdOp::F32x4RelaxedMin: + case SimdOp::F32x4RelaxedMax: + case SimdOp::F64x2RelaxedMin: + case SimdOp::F64x2RelaxedMax: + case SimdOp::I8x16RelaxedSwizzle: + case SimdOp::I16x8RelaxedQ15MulrS: + case SimdOp::I16x8DotI8x16I7x16S: + WASM_SIMD_OP(OpKind::Binary); + case SimdOp::I8x16Neg: + case SimdOp::I16x8Neg: + case SimdOp::I16x8ExtendLowI8x16S: + case SimdOp::I16x8ExtendHighI8x16S: + case SimdOp::I16x8ExtendLowI8x16U: + case SimdOp::I16x8ExtendHighI8x16U: + case SimdOp::I32x4Neg: + case SimdOp::I32x4ExtendLowI16x8S: + case SimdOp::I32x4ExtendHighI16x8S: + case SimdOp::I32x4ExtendLowI16x8U: + case SimdOp::I32x4ExtendHighI16x8U: + case SimdOp::I32x4TruncSatF32x4S: + case SimdOp::I32x4TruncSatF32x4U: + case SimdOp::I64x2Neg: + case SimdOp::I64x2ExtendLowI32x4S: + case SimdOp::I64x2ExtendHighI32x4S: + case SimdOp::I64x2ExtendLowI32x4U: + case SimdOp::I64x2ExtendHighI32x4U: + case SimdOp::F32x4Abs: + case SimdOp::F32x4Neg: + case SimdOp::F32x4Sqrt: + case SimdOp::F32x4ConvertI32x4S: + case SimdOp::F32x4ConvertI32x4U: + case SimdOp::F64x2Abs: + case SimdOp::F64x2Neg: + case SimdOp::F64x2Sqrt: + case SimdOp::V128Not: + case SimdOp::I8x16Popcnt: + case SimdOp::I8x16Abs: + case SimdOp::I16x8Abs: + case SimdOp::I32x4Abs: + case SimdOp::I64x2Abs: + case SimdOp::F32x4Ceil: + case SimdOp::F32x4Floor: + case SimdOp::F32x4Trunc: + case SimdOp::F32x4Nearest: + case SimdOp::F64x2Ceil: + case SimdOp::F64x2Floor: + case SimdOp::F64x2Trunc: + case SimdOp::F64x2Nearest: + case SimdOp::F32x4DemoteF64x2Zero: + case SimdOp::F64x2PromoteLowF32x4: + case SimdOp::F64x2ConvertLowI32x4S: + case SimdOp::F64x2ConvertLowI32x4U: + case SimdOp::I32x4TruncSatF64x2SZero: + case SimdOp::I32x4TruncSatF64x2UZero: + case SimdOp::I16x8ExtaddPairwiseI8x16S: + case SimdOp::I16x8ExtaddPairwiseI8x16U: + case SimdOp::I32x4ExtaddPairwiseI16x8S: + case SimdOp::I32x4ExtaddPairwiseI16x8U: + case SimdOp::I32x4RelaxedTruncF32x4S: + case SimdOp::I32x4RelaxedTruncF32x4U: + case SimdOp::I32x4RelaxedTruncF64x2SZero: + case SimdOp::I32x4RelaxedTruncF64x2UZero: + WASM_SIMD_OP(OpKind::Unary); + case SimdOp::I8x16Shl: + case SimdOp::I8x16ShrS: + case SimdOp::I8x16ShrU: + case SimdOp::I16x8Shl: + case SimdOp::I16x8ShrS: + case SimdOp::I16x8ShrU: + case SimdOp::I32x4Shl: + case SimdOp::I32x4ShrS: + case SimdOp::I32x4ShrU: + case SimdOp::I64x2Shl: + case SimdOp::I64x2ShrS: + case SimdOp::I64x2ShrU: + WASM_SIMD_OP(OpKind::VectorShift); + case SimdOp::V128Bitselect: + WASM_SIMD_OP(OpKind::Ternary); + case SimdOp::I8x16Shuffle: + WASM_SIMD_OP(OpKind::VectorShuffle); + case SimdOp::V128Const: + WASM_SIMD_OP(OpKind::V128); + case SimdOp::V128Load: + case SimdOp::V128Load8Splat: + case SimdOp::V128Load16Splat: + case SimdOp::V128Load32Splat: + case SimdOp::V128Load64Splat: + case SimdOp::V128Load8x8S: + case SimdOp::V128Load8x8U: + case SimdOp::V128Load16x4S: + case SimdOp::V128Load16x4U: + case SimdOp::V128Load32x2S: + case SimdOp::V128Load32x2U: + case SimdOp::V128Load32Zero: + case SimdOp::V128Load64Zero: + WASM_SIMD_OP(OpKind::Load); + case SimdOp::V128Store: + WASM_SIMD_OP(OpKind::Store); + case SimdOp::V128Load8Lane: + case SimdOp::V128Load16Lane: + case SimdOp::V128Load32Lane: + case SimdOp::V128Load64Lane: + WASM_SIMD_OP(OpKind::LoadLane); + case SimdOp::V128Store8Lane: + case SimdOp::V128Store16Lane: + case SimdOp::V128Store32Lane: + case SimdOp::V128Store64Lane: + WASM_SIMD_OP(OpKind::StoreLane); + case SimdOp::F32x4RelaxedFma: + case SimdOp::F32x4RelaxedFnma: + case SimdOp::F64x2RelaxedFma: + case SimdOp::F64x2RelaxedFnma: + case SimdOp::I8x16RelaxedLaneSelect: + case SimdOp::I16x8RelaxedLaneSelect: + case SimdOp::I32x4RelaxedLaneSelect: + case SimdOp::I64x2RelaxedLaneSelect: + case SimdOp::I32x4DotI8x16I7x16AddS: + WASM_SIMD_OP(OpKind::Ternary); + } + break; + } + case Op::MiscPrefix: { + switch (MiscOp(op.b1)) { + case MiscOp::Limit: + // Reject Limit for MiscPrefix encoding + break; + case MiscOp::I32TruncSatF32S: + case MiscOp::I32TruncSatF32U: + case MiscOp::I32TruncSatF64S: + case MiscOp::I32TruncSatF64U: + case MiscOp::I64TruncSatF32S: + case MiscOp::I64TruncSatF32U: + case MiscOp::I64TruncSatF64S: + case MiscOp::I64TruncSatF64U: + return OpKind::Conversion; + case MiscOp::MemoryCopy: + case MiscOp::TableCopy: + return OpKind::MemOrTableCopy; + case MiscOp::DataDrop: + case MiscOp::ElemDrop: + return OpKind::DataOrElemDrop; + case MiscOp::MemoryFill: + return OpKind::MemFill; + case MiscOp::MemoryInit: + case MiscOp::TableInit: + return OpKind::MemOrTableInit; + case MiscOp::TableFill: + return OpKind::TableFill; + case MiscOp::MemoryDiscard: + return OpKind::MemDiscard; + case MiscOp::TableGrow: + return OpKind::TableGrow; + case MiscOp::TableSize: + return OpKind::TableSize; + } + break; + } + case Op::ThreadPrefix: { + switch (ThreadOp(op.b1)) { + case ThreadOp::Limit: + // Reject Limit for ThreadPrefix encoding + break; + case ThreadOp::Wake: + return OpKind::Wake; + case ThreadOp::I32Wait: + case ThreadOp::I64Wait: + return OpKind::Wait; + case ThreadOp::Fence: + return OpKind::Fence; + case ThreadOp::I32AtomicLoad: + case ThreadOp::I64AtomicLoad: + case ThreadOp::I32AtomicLoad8U: + case ThreadOp::I32AtomicLoad16U: + case ThreadOp::I64AtomicLoad8U: + case ThreadOp::I64AtomicLoad16U: + case ThreadOp::I64AtomicLoad32U: + return OpKind::AtomicLoad; + case ThreadOp::I32AtomicStore: + case ThreadOp::I64AtomicStore: + case ThreadOp::I32AtomicStore8U: + case ThreadOp::I32AtomicStore16U: + case ThreadOp::I64AtomicStore8U: + case ThreadOp::I64AtomicStore16U: + case ThreadOp::I64AtomicStore32U: + return OpKind::AtomicStore; + case ThreadOp::I32AtomicAdd: + case ThreadOp::I64AtomicAdd: + case ThreadOp::I32AtomicAdd8U: + case ThreadOp::I32AtomicAdd16U: + case ThreadOp::I64AtomicAdd8U: + case ThreadOp::I64AtomicAdd16U: + case ThreadOp::I64AtomicAdd32U: + case ThreadOp::I32AtomicSub: + case ThreadOp::I64AtomicSub: + case ThreadOp::I32AtomicSub8U: + case ThreadOp::I32AtomicSub16U: + case ThreadOp::I64AtomicSub8U: + case ThreadOp::I64AtomicSub16U: + case ThreadOp::I64AtomicSub32U: + case ThreadOp::I32AtomicAnd: + case ThreadOp::I64AtomicAnd: + case ThreadOp::I32AtomicAnd8U: + case ThreadOp::I32AtomicAnd16U: + case ThreadOp::I64AtomicAnd8U: + case ThreadOp::I64AtomicAnd16U: + case ThreadOp::I64AtomicAnd32U: + case ThreadOp::I32AtomicOr: + case ThreadOp::I64AtomicOr: + case ThreadOp::I32AtomicOr8U: + case ThreadOp::I32AtomicOr16U: + case ThreadOp::I64AtomicOr8U: + case ThreadOp::I64AtomicOr16U: + case ThreadOp::I64AtomicOr32U: + case ThreadOp::I32AtomicXor: + case ThreadOp::I64AtomicXor: + case ThreadOp::I32AtomicXor8U: + case ThreadOp::I32AtomicXor16U: + case ThreadOp::I64AtomicXor8U: + case ThreadOp::I64AtomicXor16U: + case ThreadOp::I64AtomicXor32U: + case ThreadOp::I32AtomicXchg: + case ThreadOp::I64AtomicXchg: + case ThreadOp::I32AtomicXchg8U: + case ThreadOp::I32AtomicXchg16U: + case ThreadOp::I64AtomicXchg8U: + case ThreadOp::I64AtomicXchg16U: + case ThreadOp::I64AtomicXchg32U: + return OpKind::AtomicBinOp; + case ThreadOp::I32AtomicCmpXchg: + case ThreadOp::I64AtomicCmpXchg: + case ThreadOp::I32AtomicCmpXchg8U: + case ThreadOp::I32AtomicCmpXchg16U: + case ThreadOp::I64AtomicCmpXchg8U: + case ThreadOp::I64AtomicCmpXchg16U: + case ThreadOp::I64AtomicCmpXchg32U: + return OpKind::AtomicCompareExchange; + default: + break; + } + break; + } + case Op::MozPrefix: { + switch (MozOp(op.b1)) { + case MozOp::Limit: + // Reject Limit for the MozPrefix encoding + break; + case MozOp::TeeGlobal: + return OpKind::TeeGlobal; + case MozOp::I32BitNot: + case MozOp::I32Abs: + case MozOp::I32Neg: + return OpKind::Unary; + case MozOp::I32Min: + case MozOp::I32Max: + case MozOp::F64Mod: + case MozOp::F64Pow: + case MozOp::F64Atan2: + return OpKind::Binary; + case MozOp::F64SinNative: + case MozOp::F64SinFdlibm: + case MozOp::F64CosNative: + case MozOp::F64CosFdlibm: + case MozOp::F64TanNative: + case MozOp::F64TanFdlibm: + case MozOp::F64Asin: + case MozOp::F64Acos: + case MozOp::F64Atan: + case MozOp::F64Exp: + case MozOp::F64Log: + return OpKind::Unary; + case MozOp::I32TeeStore8: + case MozOp::I32TeeStore16: + case MozOp::I64TeeStore8: + case MozOp::I64TeeStore16: + case MozOp::I64TeeStore32: + case MozOp::I32TeeStore: + case MozOp::I64TeeStore: + case MozOp::F32TeeStore: + case MozOp::F64TeeStore: + case MozOp::F32TeeStoreF64: + case MozOp::F64TeeStoreF32: + return OpKind::TeeStore; + case MozOp::OldCallDirect: + return OpKind::OldCallDirect; + case MozOp::OldCallIndirect: + return OpKind::OldCallIndirect; + case MozOp::Intrinsic: + return OpKind::Intrinsic; + } + break; + } + case Op::FirstPrefix: + break; + } + MOZ_CRASH("unimplemented opcode"); +} + +# undef WASM_GC_OP +# undef WASM_REF_OP + +#endif // DEBUG + +bool UnsetLocalsState::init(const ValTypeVector& locals, size_t numParams) { + MOZ_ASSERT(setLocalsStack_.empty()); + + // Find the first and total count of non-defaultable locals. + size_t firstNonDefaultable = UINT32_MAX; + size_t countNonDefaultable = 0; + for (size_t i = numParams; i < locals.length(); i++) { + if (!locals[i].isDefaultable()) { + firstNonDefaultable = std::min(i, firstNonDefaultable); + countNonDefaultable++; + } + } + firstNonDefaultLocal_ = firstNonDefaultable; + if (countNonDefaultable == 0) { + // No locals to track, saving CPU cycles. + MOZ_ASSERT(firstNonDefaultable == UINT32_MAX); + return true; + } + + // setLocalsStack_ cannot be deeper than amount of non-defaultable locals. + if (!setLocalsStack_.reserve(countNonDefaultable)) { + return false; + } + + // Allocate a bitmap for locals starting at the first non-defaultable local. + size_t bitmapSize = + ((locals.length() - firstNonDefaultable) + (WordBits - 1)) / WordBits; + if (!unsetLocals_.resize(bitmapSize)) { + return false; + } + memset(unsetLocals_.begin(), 0, bitmapSize * WordSize); + for (size_t i = firstNonDefaultable; i < locals.length(); i++) { + if (!locals[i].isDefaultable()) { + size_t localUnsetIndex = i - firstNonDefaultable; + unsetLocals_[localUnsetIndex / WordBits] |= + 1 << (localUnsetIndex % WordBits); + } + } + return true; +} |