diff options
Diffstat (limited to 'deps/v8/test/cctest/wasm')
-rw-r--r-- | deps/v8/test/cctest/wasm/test-gc.cc | 714 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-jump-table-assembler.cc | 8 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-liftoff-inspection.cc | 255 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc | 22 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-exceptions.cc | 318 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-memory64.cc | 44 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-module.cc | 35 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-simd-scalar-lowering.cc | 6 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-simd.cc | 234 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-streaming-compilation.cc | 22 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc | 8 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-wasm-serialization.cc | 18 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-wasm-stack.cc | 6 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/wasm-run-utils.cc | 1 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/wasm-run-utils.h | 8 |
15 files changed, 1047 insertions, 652 deletions
diff --git a/deps/v8/test/cctest/wasm/test-gc.cc b/deps/v8/test/cctest/wasm/test-gc.cc index 44d3b03076..dd1dfea0f1 100644 --- a/deps/v8/test/cctest/wasm/test-gc.cc +++ b/deps/v8/test/cctest/wasm/test-gc.cc @@ -204,7 +204,6 @@ ValueType optref(uint32_t type_index) { WASM_COMPILED_EXEC_TEST(WasmBasicStruct) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte type_index = tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)}); @@ -277,7 +276,6 @@ WASM_COMPILED_EXEC_TEST(WasmBasicStruct) { // struct refs types in globals and if-results. WASM_COMPILED_EXEC_TEST(WasmRefAsNonNull) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte type_index = tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)}); ValueType kRefTypes[] = {ref(type_index)}; @@ -308,7 +306,6 @@ WASM_COMPILED_EXEC_TEST(WasmRefAsNonNull) { WASM_COMPILED_EXEC_TEST(WasmBrOnNull) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte type_index = tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)}); ValueType kRefTypes[] = {ref(type_index)}; @@ -346,86 +343,77 @@ WASM_COMPILED_EXEC_TEST(WasmBrOnNull) { WASM_COMPILED_EXEC_TEST(BrOnCast) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; + ValueType kDataRefNull = ValueType::Ref(HeapType::kData, kNullable); const byte type_index = tester.DefineStruct({F(kWasmI32, true)}); + const byte other_type_index = tester.DefineStruct({F(kWasmF32, true)}); const byte rtt_index = - tester.AddGlobal(ValueType::Rtt(type_index, 1), false, + tester.AddGlobal(ValueType::Rtt(type_index, 0), false, WasmInitExpr::RttCanon( static_cast<HeapType::Representation>(type_index))); const byte kTestStruct = tester.DefineFunction( - tester.sigs.i_v(), {kWasmI32, kWasmEqRef}, - {WASM_BLOCK(WASM_LOCAL_SET(0, WASM_I32V(111)), - // Pipe a struct through a local so it's statically typed - // as eqref. - WASM_LOCAL_SET( - 1, WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(1), - WASM_GLOBAL_GET(rtt_index))), - WASM_LOCAL_GET(1), - // The struct is not an i31, so this branch isn't taken. - WASM_BR_ON_CAST(0, WASM_RTT_CANON(kI31RefCode)), - WASM_LOCAL_SET(0, WASM_I32V(222)), // Final result. - // This branch is taken. - WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)), - // Not executed due to the branch. - WASM_DROP, WASM_LOCAL_SET(0, WASM_I32V(333))), - WASM_LOCAL_GET(0), kExprEnd}); - - const byte kTestI31 = tester.DefineFunction( - tester.sigs.i_v(), {kWasmI32, kWasmEqRef}, - {WASM_BLOCK(WASM_LOCAL_SET(0, WASM_I32V(111)), - // Pipe an i31ref through a local so it's statically typed - // as eqref. - WASM_LOCAL_SET(1, WASM_I31_NEW(WASM_I32V(42))), - WASM_LOCAL_GET(1), - // The i31 is not a struct, so this branch isn't taken. - WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)), - WASM_LOCAL_SET(0, WASM_I32V(222)), // Final result. - // This branch is taken. - WASM_BR_ON_CAST(0, WASM_RTT_CANON(kI31RefCode)), - // Not executed due to the branch. - WASM_DROP, WASM_LOCAL_SET(0, WASM_I32V(333))), - WASM_LOCAL_GET(0), kExprEnd}); + tester.sigs.i_v(), {kWasmI32, kDataRefNull}, + {WASM_BLOCK_R(ValueType::Ref(type_index, kNullable), + WASM_LOCAL_SET(0, WASM_I32V(111)), + // Pipe a struct through a local so it's statically typed + // as dataref. + WASM_LOCAL_SET(1, WASM_STRUCT_NEW_WITH_RTT( + other_type_index, WASM_F32(1.0), + WASM_RTT_CANON(other_type_index))), + WASM_LOCAL_GET(1), + // The type check fails, so this branch isn't taken. + WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)), WASM_DROP, + + WASM_LOCAL_SET(0, WASM_I32V(221)), // (Final result) - 1 + WASM_LOCAL_SET(1, WASM_STRUCT_NEW_WITH_RTT( + type_index, WASM_I32V(1), + WASM_GLOBAL_GET(rtt_index))), + WASM_LOCAL_GET(1), + // This branch is taken. + WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)), + WASM_GLOBAL_GET(rtt_index), WASM_GC_OP(kExprRefCast), + + // Not executed due to the branch. + WASM_LOCAL_SET(0, WASM_I32V(333))), + WASM_GC_OP(kExprStructGet), type_index, 0, WASM_LOCAL_GET(0), + kExprI32Add, kExprEnd}); const byte kTestNull = tester.DefineFunction( - tester.sigs.i_v(), {kWasmI32, kWasmEqRef}, - {WASM_BLOCK(WASM_LOCAL_SET(0, WASM_I32V(111)), - WASM_LOCAL_GET(1), // Put a nullref onto the value stack. - // Neither of these branches is taken for nullref. - WASM_BR_ON_CAST(0, WASM_RTT_CANON(kI31RefCode)), - WASM_LOCAL_SET(0, WASM_I32V(222)), - WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)), WASM_DROP, - WASM_LOCAL_SET(0, WASM_I32V(333))), // Final result. - WASM_LOCAL_GET(0), kExprEnd}); + tester.sigs.i_v(), {kWasmI32, kDataRefNull}, + {WASM_BLOCK_R(ValueType::Ref(type_index, kNullable), + WASM_LOCAL_SET(0, WASM_I32V(111)), + WASM_LOCAL_GET(1), // Put a nullref onto the value stack. + // Not taken for nullref. + WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)), + WASM_RTT_CANON(type_index), WASM_GC_OP(kExprRefCast), + + WASM_LOCAL_SET(0, WASM_I32V(222))), // Final result. + WASM_DROP, WASM_LOCAL_GET(0), kExprEnd}); const byte kTypedAfterBranch = tester.DefineFunction( - tester.sigs.i_v(), {kWasmI32, kWasmEqRef}, + tester.sigs.i_v(), {kWasmI32, kDataRefNull}, {WASM_LOCAL_SET(1, WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_GLOBAL_GET(rtt_index))), - WASM_BLOCK(WASM_LOCAL_SET( + WASM_BLOCK_I( + // The inner block should take the early branch with a struct + // on the stack. + WASM_BLOCK_R(ValueType::Ref(type_index, kNonNullable), + WASM_LOCAL_GET(1), + WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)), + // Returning 123 is the unreachable failure case. + WASM_I32V(123), WASM_BR(1)), // The outer block catches the struct left behind by the inner block // and reads its field. - 0, - WASM_STRUCT_GET( - type_index, 0, - // The inner block should take the early branch with a struct - // on the stack. - WASM_BLOCK_R(ValueType::Ref(type_index, kNonNullable), - WASM_LOCAL_GET(1), - WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)), - // Returning 123 is the unreachable failure case. - WASM_LOCAL_SET(0, WASM_I32V(123)), WASM_BR(1))))), - WASM_LOCAL_GET(0), kExprEnd}); + WASM_GC_OP(kExprStructGet), type_index, 0), + kExprEnd}); tester.CompileModule(); tester.CheckResult(kTestStruct, 222); - tester.CheckResult(kTestI31, 222); - tester.CheckResult(kTestNull, 333); + tester.CheckResult(kTestNull, 222); tester.CheckResult(kTypedAfterBranch, 42); } WASM_COMPILED_EXEC_TEST(WasmRefEq) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; byte type_index = tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)}); ValueType kRefTypes[] = {ref(type_index)}; ValueType kOptRefType = optref(type_index); @@ -465,7 +453,6 @@ WASM_COMPILED_EXEC_TEST(WasmRefEq) { WASM_COMPILED_EXEC_TEST(WasmPackedStructU) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte type_index = tester.DefineStruct( {F(kWasmI8, true), F(kWasmI16, true), F(kWasmI32, true)}); @@ -503,7 +490,6 @@ WASM_COMPILED_EXEC_TEST(WasmPackedStructU) { WASM_COMPILED_EXEC_TEST(WasmPackedStructS) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte type_index = tester.DefineStruct( {F(kWasmI8, true), F(kWasmI16, true), F(kWasmI32, true)}); @@ -621,7 +607,6 @@ TEST(WasmLetInstruction) { WASM_COMPILED_EXEC_TEST(WasmBasicArray) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte type_index = tester.DefineArray(wasm::kWasmI32, true); ValueType kRefTypes[] = {ref(type_index)}; @@ -697,7 +682,6 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) { WASM_COMPILED_EXEC_TEST(WasmPackedArrayU) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte array_index = tester.DefineArray(kWasmI8, true); ValueType array_type = optref(array_index); @@ -733,7 +717,6 @@ WASM_COMPILED_EXEC_TEST(WasmPackedArrayU) { WASM_COMPILED_EXEC_TEST(WasmPackedArrayS) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte array_index = tester.DefineArray(kWasmI16, true); ValueType array_type = optref(array_index); @@ -769,7 +752,6 @@ WASM_COMPILED_EXEC_TEST(WasmPackedArrayS) { WASM_COMPILED_EXEC_TEST(NewDefault) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte struct_type = tester.DefineStruct( {F(wasm::kWasmI32, true), F(wasm::kWasmF64, true), F(optref(0), true)}); const byte array_type = tester.DefineArray(wasm::kWasmI32, true); @@ -801,17 +783,18 @@ WASM_COMPILED_EXEC_TEST(NewDefault) { tester.CheckResult(allocate_array, 0); } -TEST(BasicRTT) { - WasmGCTester tester; +WASM_COMPILED_EXEC_TEST(BasicRtt) { + WasmGCTester tester(execution_tier); + const byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)}); const byte subtype_index = tester.DefineStruct({F(wasm::kWasmI32, true), F(wasm::kWasmI32, true)}); - ValueType kRttTypes[] = {ValueType::Rtt(type_index, 1)}; + + ValueType kRttTypes[] = {ValueType::Rtt(type_index, 0)}; FunctionSig sig_t_v(1, 0, kRttTypes); - ValueType kRttSubtypes[] = { - ValueType::Rtt(static_cast<HeapType>(subtype_index), 2)}; + ValueType kRttSubtypes[] = {ValueType::Rtt(subtype_index, 1)}; FunctionSig sig_t2_v(1, 0, kRttSubtypes); - ValueType kRttTypesDeeper[] = {ValueType::Rtt(type_index, 2)}; + ValueType kRttTypesDeeper[] = {ValueType::Rtt(type_index, 1)}; FunctionSig sig_t3_v(1, 0, kRttTypesDeeper); ValueType kRefTypes[] = {ref(type_index)}; FunctionSig sig_q_v(1, 0, kRefTypes); @@ -821,43 +804,34 @@ TEST(BasicRTT) { const byte kRttSub = tester.DefineFunction( &sig_t2_v, {}, {WASM_RTT_SUB(subtype_index, WASM_RTT_CANON(type_index)), kExprEnd}); - const byte kRttSubGeneric = tester.DefineFunction( - &sig_t3_v, {}, - {WASM_RTT_SUB(type_index, WASM_RTT_CANON(kEqRefCode)), kExprEnd}); const byte kStructWithRtt = tester.DefineFunction( &sig_q_v, {}, {WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_RTT_CANON(type_index)), kExprEnd}); + const int kFieldIndex = 1; - const int kStructIndexCode = 1; // Shifted in 'let' block. - const int kRttIndexCode = 0; // Let-bound, hence first local. + const int kStructIndexCode = 0; // This implements the following function: // var local_struct: type0; - // let (local_rtt = rtt.sub(rtt.canon(type0), type1) in { - // local_struct = new type1 with rtt 'local_rtt'; - // return (ref.test local_struct local_rtt) + - // ((ref.cast local_struct local_rtt)[field0]); + // local_struct = new type1 with rtt 'kRttSub()'; + // return (ref.test local_struct kRttSub()) + + // ((ref.cast local_struct kRttSub())[field0]); // } // The expected return value is 1+42 = 43. const byte kRefCast = tester.DefineFunction( tester.sigs.i_v(), {optref(type_index)}, - {WASM_LET_1_I( - WASM_RTT(2, subtype_index), - WASM_RTT_SUB(subtype_index, WASM_RTT_CANON(type_index)), - WASM_LOCAL_SET(kStructIndexCode, - WASM_STRUCT_NEW_WITH_RTT( - subtype_index, WASM_I32V(11), WASM_I32V(42), - WASM_LOCAL_GET(kRttIndexCode))), - WASM_I32_ADD( - WASM_REF_TEST(type_index, subtype_index, - WASM_LOCAL_GET(kStructIndexCode), - WASM_LOCAL_GET(kRttIndexCode)), - WASM_STRUCT_GET(subtype_index, kFieldIndex, - WASM_REF_CAST(type_index, subtype_index, - WASM_LOCAL_GET(kStructIndexCode), - WASM_LOCAL_GET(kRttIndexCode)))), - kExprEnd)}); + {WASM_LOCAL_SET( + kStructIndexCode, + WASM_STRUCT_NEW_WITH_RTT(subtype_index, WASM_I32V(11), WASM_I32V(42), + WASM_CALL_FUNCTION0(kRttSub))), + WASM_I32_ADD( + WASM_REF_TEST(WASM_LOCAL_GET(kStructIndexCode), + WASM_CALL_FUNCTION0(kRttSub)), + WASM_STRUCT_GET(subtype_index, kFieldIndex, + WASM_REF_CAST(WASM_LOCAL_GET(kStructIndexCode), + WASM_CALL_FUNCTION0(kRttSub)))), + kExprEnd}); tester.CompileModule(); @@ -875,7 +849,6 @@ TEST(BasicRTT) { tester.GetResultObject(kRttSub).ToHandleChecked(); CHECK(subref_result->IsMap()); Handle<Map> submap = Handle<Map>::cast(subref_result); - CHECK_EQ(*map, submap->wasm_type_info().parent()); CHECK_EQ(reinterpret_cast<Address>( tester.instance()->module()->struct_type(subtype_index)), submap->wasm_type_info().foreign_address()); @@ -883,12 +856,6 @@ TEST(BasicRTT) { tester.GetResultObject(kRttSub).ToHandleChecked(); CHECK(subref_result.is_identical_to(subref_result_canonicalized)); - Handle<Object> sub_generic_1 = - tester.GetResultObject(kRttSubGeneric).ToHandleChecked(); - Handle<Object> sub_generic_2 = - tester.GetResultObject(kRttSubGeneric).ToHandleChecked(); - CHECK(sub_generic_1.is_identical_to(sub_generic_2)); - Handle<Object> s = tester.GetResultObject(kStructWithRtt).ToHandleChecked(); CHECK(s->IsWasmStruct()); CHECK_EQ(Handle<WasmStruct>::cast(s)->map(), *map); @@ -896,84 +863,85 @@ TEST(BasicRTT) { tester.CheckResult(kRefCast, 43); } -WASM_COMPILED_EXEC_TEST(AnyRefRtt) { +WASM_EXEC_TEST(NoDepthRtt) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; - - ValueType any_rtt_0_type = ValueType::Rtt(HeapType::kAny, 0); - FunctionSig sig_any_canon(1, 0, &any_rtt_0_type); - byte kAnyRttCanon = tester.DefineFunction( - &sig_any_canon, {}, {WASM_RTT_CANON(kAnyRefCode), kExprEnd}); - - ValueType any_rtt_1_type = ValueType::Rtt(HeapType::kAny, 1); - FunctionSig sig_any_sub(1, 0, &any_rtt_1_type); - byte kAnyRttSub = tester.DefineFunction( - &sig_any_sub, {}, - {WASM_RTT_SUB(kAnyRefCode, WASM_RTT_CANON(kAnyRefCode)), kExprEnd}); - - ValueType func_rtt_1_type = ValueType::Rtt(HeapType::kFunc, 1); - FunctionSig sig_func_sub(1, 0, &func_rtt_1_type); - byte kFuncRttSub = tester.DefineFunction( - &sig_func_sub, {}, - {WASM_RTT_SUB(kFuncRefCode, WASM_RTT_CANON(kAnyRefCode)), kExprEnd}); - - ValueType eq_rtt_1_type = ValueType::Rtt(HeapType::kEq, 1); - FunctionSig sig_eq_sub(1, 0, &eq_rtt_1_type); - byte kEqRttSub = tester.DefineFunction( - &sig_eq_sub, {}, - {WASM_RTT_SUB(kEqRefCode, WASM_RTT_CANON(kAnyRefCode)), kExprEnd}); - const byte type_index = tester.DefineArray(kWasmI32, true); - ValueType array_rtt_type = ValueType::Rtt(type_index, 1); - FunctionSig sig_array_canon(1, 0, &array_rtt_type); - byte kArrayRttCanon = tester.DefineFunction( - &sig_array_canon, {}, {WASM_RTT_CANON(type_index), kExprEnd}); - - byte kCheckArrayAgainstAny = tester.DefineFunction( - tester.sigs.i_v(), {kWasmAnyRef}, - {WASM_LOCAL_SET(0, WASM_ARRAY_NEW_DEFAULT(type_index, WASM_I32V(5), - WASM_RTT_CANON(type_index))), - WASM_REF_TEST(kAnyRefCode, type_index, WASM_LOCAL_GET(0), - WASM_RTT_CANON(type_index)), + const byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)}); + const byte subtype_index = + tester.DefineStruct({F(wasm::kWasmI32, true), F(wasm::kWasmI32, true)}); + const byte empty_struct_index = tester.DefineStruct({}); + + ValueType kRttSubtypeNoDepth = ValueType::Rtt(subtype_index); + FunctionSig sig_t2_v_nd(1, 0, &kRttSubtypeNoDepth); + + const byte kRttSubtypeCanon = tester.DefineFunction( + &sig_t2_v_nd, {}, {WASM_RTT_CANON(subtype_index), kExprEnd}); + const byte kRttSubtypeSub = tester.DefineFunction( + &sig_t2_v_nd, {}, + {WASM_RTT_SUB(subtype_index, WASM_RTT_CANON(type_index)), kExprEnd}); + + const byte kTestCanon = tester.DefineFunction( + tester.sigs.i_v(), {optref(type_index)}, + {WASM_LOCAL_SET(0, WASM_STRUCT_NEW_WITH_RTT( + subtype_index, WASM_I32V(11), WASM_I32V(42), + WASM_RTT_CANON(subtype_index))), + WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeCanon)), kExprEnd}); - byte kCheckAnyAgainstAny = tester.DefineFunction( - tester.sigs.i_v(), {kWasmAnyRef}, - {WASM_LOCAL_SET(0, WASM_ARRAY_NEW_DEFAULT(type_index, WASM_I32V(5), - WASM_RTT_CANON(type_index))), - WASM_REF_TEST(kAnyRefCode, kAnyRefCode, WASM_LOCAL_GET(0), - WASM_RTT_CANON(kAnyRefCode)), + const byte kTestSub = tester.DefineFunction( + tester.sigs.i_v(), {optref(type_index)}, + {WASM_LOCAL_SET( + 0, WASM_STRUCT_NEW_WITH_RTT( + subtype_index, WASM_I32V(11), WASM_I32V(42), + WASM_RTT_SUB(subtype_index, WASM_RTT_CANON(type_index)))), + WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeSub)), kExprEnd}); - tester.CompileModule(); + const byte kTestSubVsEmpty = tester.DefineFunction( + tester.sigs.i_v(), {optref(type_index)}, + {WASM_LOCAL_SET(0, WASM_STRUCT_NEW_WITH_RTT( + subtype_index, WASM_I32V(11), WASM_I32V(42), + WASM_RTT_SUB(subtype_index, + WASM_RTT_CANON(empty_struct_index)))), + WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeSub)), + kExprEnd}); - // Check (rtt.canon any). - Handle<Object> result_any_canon = - tester.GetResultObject(kAnyRttCanon).ToHandleChecked(); - CHECK(result_any_canon->IsMap()); - Handle<Map> any_map = Handle<Map>::cast(result_any_canon); - CHECK_EQ(any_map->wasm_type_info().parent(), - tester.isolate()->root(RootIndex::kNullMap)); - CHECK_EQ(any_map->wasm_type_info().supertypes().length(), 0); - - for (byte func_index : {kArrayRttCanon, kAnyRttSub, kFuncRttSub, kEqRttSub}) { - Handle<Object> result = - tester.GetResultObject(func_index).ToHandleChecked(); - CHECK(result->IsMap()); - Handle<Map> map = Handle<Map>::cast(result); - // Its parent should be (rtt.canon any). - CHECK_EQ(map->wasm_type_info().parent(), *any_map); - CHECK_EQ(map->wasm_type_info().supertypes().get(0), *any_map); - CHECK_EQ(map->wasm_type_info().supertypes().length(), 1); - } + const byte kTestSubVsCanon = tester.DefineFunction( + tester.sigs.i_v(), {optref(type_index)}, + {WASM_LOCAL_SET(0, WASM_STRUCT_NEW_WITH_RTT( + subtype_index, WASM_I32V(11), WASM_I32V(42), + WASM_RTT_CANON(subtype_index))), + WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeSub)), + kExprEnd}); - tester.CheckResult(kCheckArrayAgainstAny, 1); - tester.CheckResult(kCheckAnyAgainstAny, 1); + const byte kTestCanonVsSub = tester.DefineFunction( + tester.sigs.i_v(), {optref(type_index)}, + {WASM_LOCAL_SET( + 0, WASM_STRUCT_NEW_WITH_RTT( + subtype_index, WASM_I32V(11), WASM_I32V(42), + WASM_RTT_SUB(subtype_index, WASM_RTT_CANON(type_index)))), + WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeCanon)), + kExprEnd}); + + const byte kTestSuperVsSub = tester.DefineFunction( + tester.sigs.i_v(), {optref(type_index)}, + {WASM_LOCAL_SET(0, WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), + WASM_RTT_CANON(type_index))), + WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeCanon)), + kExprEnd}); + + tester.CompileModule(); + + tester.CheckResult(kTestCanon, 1); + tester.CheckResult(kTestSub, 1); + tester.CheckResult(kTestSubVsEmpty, 0); + tester.CheckResult(kTestSubVsCanon, 0); + tester.CheckResult(kTestCanonVsSub, 0); + tester.CheckResult(kTestSuperVsSub, 0); } WASM_COMPILED_EXEC_TEST(ArrayNewMap) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte type_index = tester.DefineArray(kWasmI32, true); @@ -985,7 +953,7 @@ WASM_COMPILED_EXEC_TEST(ArrayNewMap) { WASM_RTT_CANON(type_index)), kExprEnd}); - ValueType rtt_type = ValueType::Rtt(type_index, 1); + ValueType rtt_type = ValueType::Rtt(type_index, 0); FunctionSig rtt_canon_sig(1, 0, &rtt_type); const byte kRttCanon = tester.DefineFunction( &rtt_canon_sig, {}, {WASM_RTT_CANON(type_index), kExprEnd}); @@ -1000,8 +968,8 @@ WASM_COMPILED_EXEC_TEST(ArrayNewMap) { CHECK_EQ(Handle<WasmArray>::cast(result)->map(), *map); } -TEST(FunctionRefs) { - WasmGCTester tester; +WASM_COMPILED_EXEC_TEST(FunctionRefs) { + WasmGCTester tester(execution_tier); const byte func_index = tester.DefineFunction(tester.sigs.i_v(), {}, {WASM_I32V(42), kExprEnd}); const byte sig_index = 0; @@ -1012,26 +980,18 @@ TEST(FunctionRefs) { tester.AddGlobal(ValueType::Ref(sig_index, kNullable), false, WasmInitExpr::RefFuncConst(func_index)); - ValueType func_type = ValueType::Ref(sig_index, kNonNullable); + ValueType func_type = ValueType::Ref(sig_index, kNullable); FunctionSig sig_func(1, 0, &func_type); - ValueType rtt1 = ValueType::Rtt(sig_index, 1); - FunctionSig sig_rtt1(1, 0, &rtt1); + ValueType rtt0 = ValueType::Rtt(sig_index, 0); + FunctionSig sig_rtt0(1, 0, &rtt0); const byte rtt_canon = tester.DefineFunction( - &sig_rtt1, {}, {WASM_RTT_CANON(sig_index), kExprEnd}); - - ValueType rtt2 = ValueType::Rtt(sig_index, 2); - FunctionSig sig_rtt2(1, 0, &rtt2); - const byte rtt_sub = tester.DefineFunction( - &sig_rtt2, {}, - {WASM_RTT_SUB(sig_index, WASM_RTT_CANON(kFuncRefCode)), kExprEnd}); + &sig_rtt0, {}, {WASM_RTT_CANON(sig_index), kExprEnd}); const byte cast = tester.DefineFunction( &sig_func, {kWasmFuncRef}, {WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)), - WASM_REF_CAST(kFuncRefCode, sig_index, WASM_LOCAL_GET(0), - WASM_RTT_CANON(sig_index)), - kExprEnd}); + WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(sig_index)), kExprEnd}); const byte cast_reference = tester.DefineFunction( &sig_func, {}, {WASM_REF_FUNC(sig_index), kExprEnd}); @@ -1039,8 +999,19 @@ TEST(FunctionRefs) { const byte test = tester.DefineFunction( tester.sigs.i_v(), {kWasmFuncRef}, {WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)), - WASM_REF_TEST(kFuncRefCode, other_sig_index, WASM_LOCAL_GET(0), - WASM_RTT_CANON(other_sig_index)), + WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_RTT_CANON(sig_index)), kExprEnd}); + + const byte test_fail_1 = tester.DefineFunction( + tester.sigs.i_v(), {kWasmFuncRef}, + {WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)), + WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_RTT_CANON(other_sig_index)), + kExprEnd}); + + const byte test_fail_2 = tester.DefineFunction( + tester.sigs.i_v(), {kWasmFuncRef}, + {WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)), + WASM_REF_TEST(WASM_LOCAL_GET(0), + WASM_RTT_SUB(sig_index, WASM_RTT_CANON(sig_index))), kExprEnd}); tester.CompileModule(); @@ -1051,11 +1022,6 @@ TEST(FunctionRefs) { Handle<Map> map_canon = Handle<Map>::cast(result_canon); CHECK(map_canon->IsJSFunctionMap()); - Handle<Object> result_sub = tester.GetResultObject(rtt_sub).ToHandleChecked(); - CHECK(result_sub->IsMap()); - Handle<Map> map_sub = Handle<Map>::cast(result_sub); - CHECK(map_sub->IsJSFunctionMap()); - Handle<Object> result_cast = tester.GetResultObject(cast).ToHandleChecked(); CHECK(result_cast->IsJSFunction()); Handle<JSFunction> cast_function = Handle<JSFunction>::cast(result_cast); @@ -1069,11 +1035,13 @@ TEST(FunctionRefs) { CHECK_EQ(cast_function->code().raw_instruction_start(), cast_function_reference->code().raw_instruction_start()); - tester.CheckResult(test, 0); + tester.CheckResult(test, 1); + tester.CheckResult(test_fail_1, 0); + tester.CheckResult(test_fail_2, 0); } -TEST(CallRef) { - WasmGCTester tester; +WASM_COMPILED_EXEC_TEST(CallRef) { + WasmGCTester tester(execution_tier); byte callee = tester.DefineFunction( tester.sigs.i_ii(), {}, {WASM_I32_ADD(WASM_LOCAL_GET(0), WASM_LOCAL_GET(1)), kExprEnd}); @@ -1093,29 +1061,154 @@ TEST(CallRef) { WASM_COMPILED_EXEC_TEST(RefTestCastNull) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)}); const byte kRefTestNull = tester.DefineFunction( tester.sigs.i_v(), {}, - {WASM_REF_TEST(type_index, type_index, WASM_REF_NULL(type_index), - WASM_RTT_CANON(type_index)), + {WASM_REF_TEST(WASM_REF_NULL(type_index), WASM_RTT_CANON(type_index)), kExprEnd}); const byte kRefCastNull = tester.DefineFunction( - tester.sigs.i_i(), // Argument and return value ignored - {}, - {WASM_REF_CAST(type_index, type_index, WASM_REF_NULL(type_index), - WASM_RTT_CANON(type_index)), - kExprDrop, WASM_I32V(0), kExprEnd}); + tester.sigs.i_v(), {}, + {WASM_REF_IS_NULL(WASM_REF_CAST(WASM_REF_NULL(type_index), + WASM_RTT_CANON(type_index))), + kExprEnd}); tester.CompileModule(); tester.CheckResult(kRefTestNull, 0); - tester.CheckHasThrown(kRefCastNull, 0); + tester.CheckResult(kRefCastNull, 1); +} + +WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) { + WasmGCTester tester(execution_tier); + + byte array_index = tester.DefineArray(kWasmI32, true); + byte function_index = + tester.DefineFunction(tester.sigs.v_v(), {}, {kExprEnd}); + byte sig_index = 1; + + // This is just so func_index counts as "declared". + tester.AddGlobal(ValueType::Ref(sig_index, kNullable), false, + WasmInitExpr::RefFuncConst(function_index)); + + byte kDataCheckNull = tester.DefineFunction( + tester.sigs.i_v(), {}, + {WASM_REF_IS_DATA(WASM_REF_NULL(kAnyRefCode)), kExprEnd}); + byte kFuncCheckNull = tester.DefineFunction( + tester.sigs.i_v(), {}, + {WASM_REF_IS_FUNC(WASM_REF_NULL(kAnyRefCode)), kExprEnd}); + byte kI31CheckNull = tester.DefineFunction( + tester.sigs.i_v(), {}, + {WASM_REF_IS_I31(WASM_REF_NULL(kAnyRefCode)), kExprEnd}); + + byte kDataCastNull = + tester.DefineFunction(tester.sigs.i_v(), {}, + {WASM_REF_AS_DATA(WASM_REF_NULL(kAnyRefCode)), + WASM_DROP, WASM_I32V(1), kExprEnd}); + byte kFuncCastNull = + tester.DefineFunction(tester.sigs.i_v(), {}, + {WASM_REF_AS_FUNC(WASM_REF_NULL(kAnyRefCode)), + WASM_DROP, WASM_I32V(1), kExprEnd}); + byte kI31CastNull = + tester.DefineFunction(tester.sigs.i_v(), {}, + {WASM_REF_AS_I31(WASM_REF_NULL(kAnyRefCode)), + WASM_DROP, WASM_I32V(1), kExprEnd}); + +#define TYPE_CHECK(type, value) \ + tester.DefineFunction(tester.sigs.i_v(), {kWasmAnyRef}, \ + {WASM_LOCAL_SET(0, WASM_SEQ(value)), \ + WASM_REF_IS_##type(WASM_LOCAL_GET(0)), kExprEnd}) + + byte kDataCheckSuccess = + TYPE_CHECK(DATA, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10), + WASM_RTT_CANON(array_index))); + byte kDataCheckFailure = TYPE_CHECK(DATA, WASM_I31_NEW(WASM_I32V(42))); + byte kFuncCheckSuccess = TYPE_CHECK(FUNC, WASM_REF_FUNC(function_index)); + byte kFuncCheckFailure = + TYPE_CHECK(FUNC, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10), + WASM_RTT_CANON(array_index))); + byte kI31CheckSuccess = TYPE_CHECK(I31, WASM_I31_NEW(WASM_I32V(42))); + byte kI31CheckFailure = + TYPE_CHECK(I31, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10), + WASM_RTT_CANON(array_index))); +#undef TYPE_CHECK + +#define TYPE_CAST(type, value) \ + tester.DefineFunction(tester.sigs.i_v(), {kWasmAnyRef}, \ + {WASM_LOCAL_SET(0, WASM_SEQ(value)), \ + WASM_REF_AS_##type(WASM_LOCAL_GET(0)), WASM_DROP, \ + WASM_I32V(1), kExprEnd}) + + byte kDataCastSuccess = + TYPE_CAST(DATA, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10), + WASM_RTT_CANON(array_index))); + byte kDataCastFailure = TYPE_CAST(DATA, WASM_I31_NEW(WASM_I32V(42))); + byte kFuncCastSuccess = TYPE_CAST(FUNC, WASM_REF_FUNC(function_index)); + byte kFuncCastFailure = + TYPE_CAST(FUNC, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10), + WASM_RTT_CANON(array_index))); + byte kI31CastSuccess = TYPE_CAST(I31, WASM_I31_NEW(WASM_I32V(42))); + byte kI31CastFailure = + TYPE_CAST(I31, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10), + WASM_RTT_CANON(array_index))); +#undef TYPE_CAST + +// If the branch is not taken, we return 0. If it is taken, then the respective +// type check should succeed, and we return 1. +#define BR_ON(TYPE, type, value) \ + tester.DefineFunction( \ + tester.sigs.i_v(), {kWasmAnyRef}, \ + {WASM_LOCAL_SET(0, WASM_SEQ(value)), \ + WASM_REF_IS_##TYPE(WASM_BLOCK_R( \ + kWasm##type##Ref, WASM_BR_ON_##TYPE(0, WASM_LOCAL_GET(0)), \ + WASM_RETURN(WASM_I32V(0)))), \ + kExprEnd}) + + byte kBrOnDataTaken = + BR_ON(DATA, Data, + WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10), + WASM_RTT_CANON(array_index))); + byte kBrOnDataNotTaken = BR_ON(DATA, Data, WASM_REF_FUNC(function_index)); + byte kBrOnFuncTaken = BR_ON(FUNC, Func, WASM_REF_FUNC(function_index)); + byte kBrOnFuncNotTaken = BR_ON(FUNC, Func, WASM_I31_NEW(WASM_I32V(42))); + byte kBrOnI31Taken = BR_ON(I31, I31, WASM_I31_NEW(WASM_I32V(42))); + byte kBrOnI31NotTaken = + BR_ON(I31, I31, + WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10), + WASM_RTT_CANON(array_index))); +#undef BR_ON + + tester.CompileModule(); + + tester.CheckResult(kDataCheckNull, 0); + tester.CheckHasThrown(kDataCastNull); + tester.CheckResult(kDataCheckSuccess, 1); + tester.CheckResult(kDataCheckFailure, 0); + tester.CheckResult(kDataCastSuccess, 1); + tester.CheckHasThrown(kDataCastFailure); + tester.CheckResult(kBrOnDataTaken, 1); + tester.CheckResult(kBrOnDataNotTaken, 0); + + tester.CheckResult(kFuncCheckNull, 0); + tester.CheckHasThrown(kFuncCastNull); + tester.CheckResult(kFuncCheckSuccess, 1); + tester.CheckResult(kFuncCheckFailure, 0); + tester.CheckResult(kFuncCastSuccess, 1); + tester.CheckHasThrown(kFuncCastFailure); + tester.CheckResult(kBrOnFuncTaken, 1); + tester.CheckResult(kBrOnFuncNotTaken, 0); + + tester.CheckResult(kI31CheckNull, 0); + tester.CheckHasThrown(kI31CastNull); + tester.CheckResult(kI31CheckSuccess, 1); + tester.CheckResult(kI31CheckFailure, 0); + tester.CheckResult(kI31CastSuccess, 1); + tester.CheckHasThrown(kI31CastFailure); + tester.CheckResult(kBrOnI31Taken, 1); + tester.CheckResult(kBrOnI31NotTaken, 0); } WASM_COMPILED_EXEC_TEST(BasicI31) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte kSigned = tester.DefineFunction( tester.sigs.i_i(), {}, {WASM_I31_GET_S(WASM_I31_NEW(WASM_LOCAL_GET(0))), kExprEnd}); @@ -1133,89 +1226,30 @@ WASM_COMPILED_EXEC_TEST(BasicI31) { tester.CheckResult(kUnsigned, 0x7FFFFFFF, 0x7FFFFFFF); } -WASM_COMPILED_EXEC_TEST(I31Casts) { - WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; - const byte struct_type = tester.DefineStruct({F(wasm::kWasmI32, true)}); - const byte i31_rtt = - tester.AddGlobal(ValueType::Rtt(HeapType::kI31, 1), false, - WasmInitExpr::RttCanon(HeapType::kI31)); - const byte struct_rtt = - tester.AddGlobal(ValueType::Rtt(struct_type, 1), false, - WasmInitExpr::RttCanon( - static_cast<HeapType::Representation>(struct_type))); - // Adds the result of a successful typecheck to the untagged value, i.e. - // should return 1 + 42 = 43. - const byte kTestAndCastSuccess = tester.DefineFunction( - tester.sigs.i_v(), {kWasmEqRef}, - {WASM_LOCAL_SET(0, WASM_I31_NEW(WASM_I32V(42))), - WASM_I32_ADD(WASM_REF_TEST(kEqRefCode, kI31RefCode, WASM_LOCAL_GET(0), - WASM_GLOBAL_GET(i31_rtt)), - WASM_I31_GET_S(WASM_REF_CAST(kEqRefCode, kI31RefCode, - WASM_LOCAL_GET(0), - WASM_GLOBAL_GET(i31_rtt)))), - kExprEnd}); - // Adds the results of two unsuccessful type checks (an i31ref is not a - // struct, nor the other way round). - const byte kTestFalse = tester.DefineFunction( - tester.sigs.i_v(), {}, - {WASM_I32_ADD( - WASM_REF_TEST(kEqRefCode, kI31RefCode, - WASM_STRUCT_NEW_WITH_RTT(struct_type, WASM_I32V(42), - WASM_GLOBAL_GET(struct_rtt)), - WASM_GLOBAL_GET(i31_rtt)), - WASM_REF_TEST(kEqRefCode, struct_type, WASM_I31_NEW(WASM_I32V(23)), - WASM_GLOBAL_GET(struct_rtt))), - kExprEnd}); - // Tries to cast an i31ref to a struct, which should trap. - const byte kCastI31ToStruct = tester.DefineFunction( - tester.sigs.i_i(), // Argument and return value ignored - {}, - {WASM_STRUCT_GET( - struct_type, 0, - WASM_REF_CAST(kEqRefCode, struct_type, WASM_I31_NEW(WASM_I32V(42)), - WASM_GLOBAL_GET(struct_rtt))), - kExprEnd}); - // Tries to cast a struct to i31ref, which should trap. - const byte kCastStructToI31 = tester.DefineFunction( - tester.sigs.i_i(), // Argument and return value ignored - {}, - {WASM_I31_GET_S( - WASM_REF_CAST(kEqRefCode, kI31RefCode, - WASM_STRUCT_NEW_WITH_RTT(struct_type, WASM_I32V(42), - WASM_GLOBAL_GET(struct_rtt)), - WASM_GLOBAL_GET(i31_rtt))), - kExprEnd}); - tester.CompileModule(); - tester.CheckResult(kTestAndCastSuccess, 43); - tester.CheckResult(kTestFalse, 0); - tester.CheckHasThrown(kCastI31ToStruct, 0); - tester.CheckHasThrown(kCastStructToI31, 0); -} - // This flushed out a few bugs, so it serves as a regression test. It can also // be modified (made to run longer) to measure performance of casts. WASM_COMPILED_EXEC_TEST(CastsBenchmark) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte SuperType = tester.DefineStruct({F(wasm::kWasmI32, true)}); const byte SubType = tester.DefineStruct({F(wasm::kWasmI32, true), F(wasm::kWasmI32, true)}); - const byte ListType = tester.DefineArray(wasm::kWasmEqRef, true); + + ValueType kDataRefNull = ValueType::Ref(HeapType::kData, kNullable); + const byte ListType = tester.DefineArray(kDataRefNull, true); const byte List = tester.AddGlobal(ValueType::Ref(ListType, kNullable), true, WasmInitExpr::RefNullConst( static_cast<HeapType::Representation>(ListType))); const byte RttSuper = tester.AddGlobal( - ValueType::Rtt(SuperType, 1), false, + ValueType::Rtt(SuperType, 0), false, WasmInitExpr::RttCanon(static_cast<HeapType::Representation>(SuperType))); const byte RttSub = tester.AddGlobal( - ValueType::Rtt(SubType, 2), false, + ValueType::Rtt(SubType, 1), false, WasmInitExpr::RttSub(static_cast<HeapType::Representation>(SubType), WasmInitExpr::GlobalGet(RttSuper))); const byte RttList = tester.AddGlobal( - ValueType::Rtt(ListType, 1), false, + ValueType::Rtt(ListType, 0), false, WasmInitExpr::RttCanon(static_cast<HeapType::Representation>(ListType))); const uint32_t kListLength = 1024; @@ -1273,7 +1307,6 @@ WASM_COMPILED_EXEC_TEST(CastsBenchmark) { WASM_STRUCT_GET( SuperType, 0, WASM_REF_CAST( - kEqRefCode, SuperType, WASM_ARRAY_GET( ListType, WASM_LOCAL_GET(list), WASM_I32_AND(WASM_LOCAL_GET(i), @@ -1296,7 +1329,6 @@ WASM_COMPILED_EXEC_TEST(CastsBenchmark) { WASM_COMPILED_EXEC_TEST(GlobalInitReferencingGlobal) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; const byte from = tester.AddGlobal(kWasmI32, false, WasmInitExpr(42)); const byte to = tester.AddGlobal(kWasmI32, false, WasmInitExpr::GlobalGet(from)); @@ -1311,7 +1343,6 @@ WASM_COMPILED_EXEC_TEST(GlobalInitReferencingGlobal) { WASM_COMPILED_EXEC_TEST(IndirectNullSetManually) { WasmGCTester tester(execution_tier); - FLAG_experimental_liftoff_extern_ref = true; byte sig_index = tester.DefineSignature(tester.sigs.i_i()); tester.DefineTable(ValueType::Ref(sig_index, kNullable), 1, 1); byte func_index = tester.DefineFunction( @@ -1325,74 +1356,71 @@ WASM_COMPILED_EXEC_TEST(IndirectNullSetManually) { tester.CheckHasThrown(func_index, 42); } -TEST(JsAccess) { - for (ValueType supertype : {kWasmEqRef, kWasmAnyRef}) { - WasmGCTester tester; - const byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)}); - ValueType kRefType = ref(type_index); - ValueType kSupertypeToI[] = {kWasmI32, supertype}; - FunctionSig sig_t_v(1, 0, &kRefType); - FunctionSig sig_super_v(1, 0, &supertype); - FunctionSig sig_i_super(1, 1, kSupertypeToI); - - tester.DefineExportedFunction( - "disallowed", &sig_t_v, - {WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), - WASM_RTT_CANON(type_index)), - kExprEnd}); - // Same code, different signature. - tester.DefineExportedFunction( - "producer", &sig_super_v, - {WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), - WASM_RTT_CANON(type_index)), - kExprEnd}); - tester.DefineExportedFunction( - "consumer", &sig_i_super, - {WASM_STRUCT_GET( - type_index, 0, - WASM_REF_CAST(supertype.value_type_code(), type_index, - WASM_LOCAL_GET(0), WASM_RTT_CANON(type_index))), - kExprEnd}); - - tester.CompileModule(); - Isolate* isolate = tester.isolate(); - TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); - MaybeHandle<Object> maybe_result = - tester.CallExportedFunction("disallowed", 0, nullptr); - CHECK(maybe_result.is_null()); - CHECK(try_catch.HasCaught()); - try_catch.Reset(); - isolate->clear_pending_exception(); - - maybe_result = tester.CallExportedFunction("producer", 0, nullptr); - if (maybe_result.is_null()) { - FATAL("Calling 'producer' failed: %s", - *v8::String::Utf8Value(reinterpret_cast<v8::Isolate*>(isolate), - try_catch.Message()->Get())); - } - { - Handle<Object> args[] = {maybe_result.ToHandleChecked()}; - maybe_result = tester.CallExportedFunction("consumer", 1, args); - } - if (maybe_result.is_null()) { - FATAL("Calling 'consumer' failed: %s", - *v8::String::Utf8Value(reinterpret_cast<v8::Isolate*>(isolate), - try_catch.Message()->Get())); - } - Handle<Object> result = maybe_result.ToHandleChecked(); - CHECK(result->IsSmi()); - CHECK_EQ(42, Smi::cast(*result).value()); - // Calling {consumer} with any other object (e.g. the Smi we just got as - // {result}) should trap. - { - Handle<Object> args[] = {result}; - maybe_result = tester.CallExportedFunction("consumer", 1, args); - } - CHECK(maybe_result.is_null()); - CHECK(try_catch.HasCaught()); - try_catch.Reset(); - isolate->clear_pending_exception(); +WASM_COMPILED_EXEC_TEST(JsAccess) { + WasmGCTester tester(execution_tier); + const byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)}); + ValueType kRefType = ref(type_index); + ValueType kSupertypeToI[] = {kWasmI32, kWasmDataRef}; + FunctionSig sig_t_v(1, 0, &kRefType); + FunctionSig sig_super_v(1, 0, &kWasmDataRef); + FunctionSig sig_i_super(1, 1, kSupertypeToI); + + tester.DefineExportedFunction( + "disallowed", &sig_t_v, + {WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), + WASM_RTT_CANON(type_index)), + kExprEnd}); + // Same code, different signature. + tester.DefineExportedFunction( + "producer", &sig_super_v, + {WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), + WASM_RTT_CANON(type_index)), + kExprEnd}); + tester.DefineExportedFunction( + "consumer", &sig_i_super, + {WASM_STRUCT_GET( + type_index, 0, + WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(type_index))), + kExprEnd}); + + tester.CompileModule(); + Isolate* isolate = tester.isolate(); + TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); + MaybeHandle<Object> maybe_result = + tester.CallExportedFunction("disallowed", 0, nullptr); + CHECK(maybe_result.is_null()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + isolate->clear_pending_exception(); + + maybe_result = tester.CallExportedFunction("producer", 0, nullptr); + if (maybe_result.is_null()) { + FATAL("Calling 'producer' failed: %s", + *v8::String::Utf8Value(reinterpret_cast<v8::Isolate*>(isolate), + try_catch.Message()->Get())); + } + { + Handle<Object> args[] = {maybe_result.ToHandleChecked()}; + maybe_result = tester.CallExportedFunction("consumer", 1, args); + } + if (maybe_result.is_null()) { + FATAL("Calling 'consumer' failed: %s", + *v8::String::Utf8Value(reinterpret_cast<v8::Isolate*>(isolate), + try_catch.Message()->Get())); + } + Handle<Object> result = maybe_result.ToHandleChecked(); + CHECK(result->IsSmi()); + CHECK_EQ(42, Smi::cast(*result).value()); + // Calling {consumer} with any other object (e.g. the Smi we just got as + // {result}) should trap. + { + Handle<Object> args[] = {result}; + maybe_result = tester.CallExportedFunction("consumer", 1, args); } + CHECK(maybe_result.is_null()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + isolate->clear_pending_exception(); } } // namespace test_gc diff --git a/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc b/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc index 6b888511d9..bfe88180d1 100644 --- a/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc +++ b/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc @@ -144,6 +144,11 @@ void CompileJumpTableThunk(Address thunk, Address jump_target) { __ lw(scratch, MemOperand(scratch, 0)); __ Branch(&exit, ne, scratch, Operand(zero_reg)); __ Jump(jump_target, RelocInfo::NONE); +#elif V8_TARGET_ARCH_RISCV64 + __ li(scratch, Operand(stop_bit_address, RelocInfo::NONE)); + __ Lw(scratch, MemOperand(scratch, 0)); + __ Branch(&exit, ne, scratch, Operand(zero_reg)); + __ Jump(jump_target, RelocInfo::NONE); #else #error Unsupported architecture #endif @@ -232,7 +237,8 @@ TEST(JumpTablePatchingStress) { constexpr int kNumberOfPatcherThreads = 3; STATIC_ASSERT(kAssemblerBufferSize >= kJumpTableSize); - auto buffer = AllocateAssemblerBuffer(kAssemblerBufferSize); + auto buffer = AllocateAssemblerBuffer(kAssemblerBufferSize, nullptr, + VirtualMemory::kMapAsJittable); byte* thunk_slot_buffer = buffer->start() + kBufferSlotStartOffset; std::bitset<kAvailableBufferSlots> used_thunk_slots; diff --git a/deps/v8/test/cctest/wasm/test-liftoff-inspection.cc b/deps/v8/test/cctest/wasm/test-liftoff-inspection.cc index c3444b9ae6..f5847d1fb1 100644 --- a/deps/v8/test/cctest/wasm/test-liftoff-inspection.cc +++ b/deps/v8/test/cctest/wasm/test-liftoff-inspection.cc @@ -20,15 +20,16 @@ class LiftoffCompileEnvironment { : isolate_(CcTest::InitIsolateOnce()), handle_scope_(isolate_), zone_(isolate_->allocator(), ZONE_NAME), - module_builder_(&zone_, nullptr, TestExecutionTier::kLiftoff, - kRuntimeExceptionSupport, kNoLowerSimd) { + wasm_runner_(nullptr, TestExecutionTier::kLiftoff, 0, + kRuntimeExceptionSupport, kNoLowerSimd) { // Add a table of length 1, for indirect calls. - module_builder_.AddIndirectFunctionTable(nullptr, 1); + wasm_runner_.builder().AddIndirectFunctionTable(nullptr, 1); + // Set tiered down such that we generate debugging code. + wasm_runner_.builder().SetTieredDown(); } struct TestFunction { - OwnedVector<uint8_t> body_bytes; - WasmFunction* function; + WasmCode* code; FunctionBody body; }; @@ -39,17 +40,15 @@ class LiftoffCompileEnvironment { auto test_func = AddFunction(return_types, param_types, raw_function_bytes); // Now compile the function with Liftoff two times. - CompilationEnv env = module_builder_.CreateCompilationEnv(); + CompilationEnv env = wasm_runner_.builder().CreateCompilationEnv(); WasmFeatures detected1; WasmFeatures detected2; - WasmCompilationResult result1 = - ExecuteLiftoffCompilation(isolate_->allocator(), &env, test_func.body, - test_func.function->func_index, kNoDebugging, - isolate_->counters(), &detected1); - WasmCompilationResult result2 = - ExecuteLiftoffCompilation(isolate_->allocator(), &env, test_func.body, - test_func.function->func_index, kNoDebugging, - isolate_->counters(), &detected2); + WasmCompilationResult result1 = ExecuteLiftoffCompilation( + isolate_->allocator(), &env, test_func.body, test_func.code->index(), + kNoDebugging, isolate_->counters(), &detected1); + WasmCompilationResult result2 = ExecuteLiftoffCompilation( + isolate_->allocator(), &env, test_func.body, test_func.code->index(), + kNoDebugging, isolate_->counters(), &detected2); CHECK(result1.succeeded()); CHECK(result2.succeeded()); @@ -70,20 +69,20 @@ class LiftoffCompileEnvironment { std::vector<int> breakpoints = {}) { auto test_func = AddFunction(return_types, param_types, raw_function_bytes); - CompilationEnv env = module_builder_.CreateCompilationEnv(); + CompilationEnv env = wasm_runner_.builder().CreateCompilationEnv(); WasmFeatures detected; std::unique_ptr<DebugSideTable> debug_side_table_via_compilation; - ExecuteLiftoffCompilation(CcTest::i_isolate()->allocator(), &env, - test_func.body, 0, kForDebugging, nullptr, - &detected, VectorOf(breakpoints), - &debug_side_table_via_compilation); + auto result = ExecuteLiftoffCompilation( + CcTest::i_isolate()->allocator(), &env, test_func.body, 0, + kForDebugging, nullptr, &detected, VectorOf(breakpoints), + &debug_side_table_via_compilation); + CHECK(result.succeeded()); // If there are no breakpoint, then {ExecuteLiftoffCompilation} should // provide the same debug side table. if (breakpoints.empty()) { std::unique_ptr<DebugSideTable> debug_side_table = - GenerateLiftoffDebugSideTable(CcTest::i_isolate()->allocator(), &env, - test_func.body, 0); + GenerateLiftoffDebugSideTable(test_func.code); CheckTableEquals(*debug_side_table, *debug_side_table_via_compilation); } @@ -94,6 +93,7 @@ class LiftoffCompileEnvironment { static void CheckTableEquals(const DebugSideTable& a, const DebugSideTable& b) { CHECK_EQ(a.num_locals(), b.num_locals()); + CHECK_EQ(a.entries().size(), b.entries().size()); CHECK(std::equal(a.entries().begin(), a.entries().end(), b.entries().begin(), b.entries().end(), &CheckEntryEquals)); @@ -102,42 +102,11 @@ class LiftoffCompileEnvironment { static bool CheckEntryEquals(const DebugSideTable::Entry& a, const DebugSideTable::Entry& b) { CHECK_EQ(a.pc_offset(), b.pc_offset()); - CHECK(std::equal(a.values().begin(), a.values().end(), b.values().begin(), - b.values().end(), &CheckValueEquals)); + CHECK_EQ(a.stack_height(), b.stack_height()); + CHECK_EQ(a.changed_values(), b.changed_values()); return true; } - static bool CheckValueEquals(const DebugSideTable::Entry::Value& a, - const DebugSideTable::Entry::Value& b) { - CHECK_EQ(a.type, b.type); - CHECK_EQ(a.kind, b.kind); - switch (a.kind) { - case DebugSideTable::Entry::kConstant: - CHECK_EQ(a.i32_const, b.i32_const); - break; - case DebugSideTable::Entry::kRegister: - CHECK_EQ(a.reg_code, b.reg_code); - break; - case DebugSideTable::Entry::kStack: - CHECK_EQ(a.stack_offset, b.stack_offset); - break; - } - return true; - } - - OwnedVector<uint8_t> GenerateFunctionBody( - std::initializer_list<uint8_t> raw_function_bytes) { - // Build the function bytes by prepending the locals decl and appending an - // "end" opcode. - OwnedVector<uint8_t> function_bytes = - OwnedVector<uint8_t>::New(raw_function_bytes.size() + 2); - function_bytes[0] = WASM_NO_LOCALS; - std::copy(raw_function_bytes.begin(), raw_function_bytes.end(), - &function_bytes[1]); - function_bytes[raw_function_bytes.size() + 1] = WASM_END; - return function_bytes; - } - FunctionSig* AddSig(std::initializer_list<ValueType> return_types, std::initializer_list<ValueType> param_types) { ValueType* storage = @@ -147,66 +116,81 @@ class LiftoffCompileEnvironment { storage + return_types.size()); FunctionSig* sig = zone_.New<FunctionSig>(return_types.size(), param_types.size(), storage); - module_builder_.AddSignature(sig); return sig; } TestFunction AddFunction(std::initializer_list<ValueType> return_types, std::initializer_list<ValueType> param_types, - std::initializer_list<uint8_t> raw_function_bytes) { - OwnedVector<uint8_t> function_bytes = - GenerateFunctionBody(raw_function_bytes); + std::initializer_list<uint8_t> function_bytes) { FunctionSig* sig = AddSig(return_types, param_types); - int func_index = - module_builder_.AddFunction(sig, "f", TestingModuleBuilder::kWasm); - WasmFunction* function = module_builder_.GetFunctionAt(func_index); - function->code = {module_builder_.AddBytes(function_bytes.as_vector()), - static_cast<uint32_t>(function_bytes.size())}; - FunctionBody body{function->sig, 0, function_bytes.begin(), - function_bytes.end()}; - return {std::move(function_bytes), function, body}; + // Compile the function so we can get the WasmCode* which is later used to + // generate the debug side table lazily. + auto& func_compiler = wasm_runner_.NewFunction(sig, "f"); + func_compiler.Build(function_bytes.begin(), function_bytes.end()); + + WasmCode* code = + wasm_runner_.builder().GetFunctionCode(func_compiler.function_index()); + + // Get the wire bytes created by the function compiler (including locals + // declaration and the trailing "end" opcode). + NativeModule* native_module = code->native_module(); + auto* function = &native_module->module()->functions[code->index()]; + Vector<const uint8_t> function_wire_bytes = + native_module->wire_bytes().SubVector(function->code.offset(), + function->code.end_offset()); + + FunctionBody body{sig, 0, function_wire_bytes.begin(), + function_wire_bytes.end()}; + return {code, body}; } Isolate* isolate_; HandleScope handle_scope_; Zone zone_; - TestingModuleBuilder module_builder_; + // wasm_runner_ is used to build actual code objects needed to request lazy + // generation of debug side tables. + WasmRunnerBase wasm_runner_; + WasmCodeRefScope code_ref_scope_; }; struct DebugSideTableEntry { - std::vector<DebugSideTable::Entry::Value> values; + int stack_height; + std::vector<DebugSideTable::Entry::Value> changed_values; // Construct via vector or implicitly via initializer list. - explicit DebugSideTableEntry(std::vector<DebugSideTable::Entry::Value> values) - : values(std::move(values)) {} + DebugSideTableEntry(int stack_height, + std::vector<DebugSideTable::Entry::Value> changed_values) + : stack_height(stack_height), changed_values(std::move(changed_values)) {} + DebugSideTableEntry( - std::initializer_list<DebugSideTable::Entry::Value> values) - : values(values) {} + int stack_height, + std::initializer_list<DebugSideTable::Entry::Value> changed_values) + : stack_height(stack_height), changed_values(changed_values) {} bool operator==(const DebugSideTableEntry& other) const { - if (values.size() != other.values.size()) return false; - for (size_t i = 0; i < values.size(); ++i) { - if (values[i].type != other.values[i].type) return false; - if (values[i].kind != other.values[i].kind) return false; - // Stack offsets and register codes are platform dependent, so only check - // constants here. - if (values[i].kind == DebugSideTable::Entry::kConstant && - values[i].i32_const != other.values[i].i32_const) { - return false; - } - } - return true; + return stack_height == other.stack_height && + std::equal(changed_values.begin(), changed_values.end(), + other.changed_values.begin(), other.changed_values.end(), + CheckValueEquals); + } + + // Check for equality, but ignore exact register and stack offset. + static bool CheckValueEquals(const DebugSideTable::Entry::Value& a, + const DebugSideTable::Entry::Value& b) { + return a.index == b.index && a.kind == b.kind && a.kind == b.kind && + (a.storage != DebugSideTable::Entry::kConstant || + a.i32_const == b.i32_const); } }; // Debug builds will print the vector of DebugSideTableEntry. #ifdef DEBUG std::ostream& operator<<(std::ostream& out, const DebugSideTableEntry& entry) { - out << "{"; + out << "stack height " << entry.stack_height << ", changed: {"; const char* comma = ""; - for (auto& v : entry.values) { - out << comma << v.type.name() << " "; - switch (v.kind) { + for (auto& v : entry.changed_values) { + out << comma << v.index << ":" << name(v.kind) << " "; + switch (v.storage) { case DebugSideTable::Entry::kConstant: out << "const:" << v.i32_const; break; @@ -229,23 +213,27 @@ std::ostream& operator<<(std::ostream& out, #endif // DEBUG // Named constructors to make the tests more readable. -DebugSideTable::Entry::Value Constant(ValueType type, int32_t constant) { +DebugSideTable::Entry::Value Constant(int index, ValueKind kind, + int32_t constant) { DebugSideTable::Entry::Value value; - value.type = type; - value.kind = DebugSideTable::Entry::kConstant; + value.index = index; + value.kind = kind; + value.storage = DebugSideTable::Entry::kConstant; value.i32_const = constant; return value; } -DebugSideTable::Entry::Value Register(ValueType type) { +DebugSideTable::Entry::Value Register(int index, ValueKind kind) { DebugSideTable::Entry::Value value; - value.type = type; - value.kind = DebugSideTable::Entry::kRegister; + value.index = index; + value.kind = kind; + value.storage = DebugSideTable::Entry::kRegister; return value; } -DebugSideTable::Entry::Value Stack(ValueType type) { +DebugSideTable::Entry::Value Stack(int index, ValueKind kind) { DebugSideTable::Entry::Value value; - value.type = type; - value.kind = DebugSideTable::Entry::kStack; + value.index = index; + value.kind = kind; + value.storage = DebugSideTable::Entry::kStack; return value; } @@ -253,10 +241,10 @@ void CheckDebugSideTable(std::vector<DebugSideTableEntry> expected_entries, const wasm::DebugSideTable* debug_side_table) { std::vector<DebugSideTableEntry> entries; for (auto& entry : debug_side_table->entries()) { - auto values = entry.values(); - entries.push_back( - DebugSideTableEntry{std::vector<DebugSideTable::Entry::Value>{ - values.begin(), values.end()}}); + entries.emplace_back( + entry.stack_height(), + std::vector<DebugSideTable::Entry::Value>{ + entry.changed_values().begin(), entry.changed_values().end()}); } CHECK_EQ(expected_entries, entries); } @@ -308,9 +296,9 @@ TEST(Liftoff_debug_side_table_simple) { CheckDebugSideTable( { // function entry, locals in registers. - {Register(kWasmI32), Register(kWasmI32)}, - // OOL stack check, locals spilled, stack empty. - {Stack(kWasmI32), Stack(kWasmI32)}, + {2, {Register(0, kI32), Register(1, kI32)}}, + // OOL stack check, locals spilled, stack still empty. + {2, {Stack(0, kI32), Stack(1, kI32)}}, }, debug_side_table.get()); } @@ -324,11 +312,11 @@ TEST(Liftoff_debug_side_table_call) { CheckDebugSideTable( { // function entry, local in register. - {Register(kWasmI32)}, + {1, {Register(0, kI32)}}, // call, local spilled, stack empty. - {Stack(kWasmI32)}, - // OOL stack check, local spilled, stack empty. - {Stack(kWasmI32)}, + {1, {Stack(0, kI32)}}, + // OOL stack check, local spilled as before, stack empty. + {1, {}}, }, debug_side_table.get()); } @@ -344,11 +332,11 @@ TEST(Liftoff_debug_side_table_call_const) { CheckDebugSideTable( { // function entry, local in register. - {Register(kWasmI32)}, + {1, {Register(0, kI32)}}, // call, local is kConst. - {Constant(kWasmI32, kConst)}, + {1, {Constant(0, kI32, kConst)}}, // OOL stack check, local spilled. - {Stack(kWasmI32)}, + {1, {Stack(0, kI32)}}, }, debug_side_table.get()); } @@ -363,15 +351,15 @@ TEST(Liftoff_debug_side_table_indirect_call) { CheckDebugSideTable( { // function entry, local in register. - {Register(kWasmI32)}, + {1, {Register(0, kI32)}}, // indirect call, local spilled, stack empty. - {Stack(kWasmI32)}, - // OOL stack check, local spilled, stack empty. - {Stack(kWasmI32)}, - // OOL trap (invalid index), local spilled, stack has {kConst}. - {Stack(kWasmI32), Constant(kWasmI32, kConst)}, - // OOL trap (sig mismatch), local spilled, stack has {kConst}. - {Stack(kWasmI32), Constant(kWasmI32, kConst)}, + {1, {Stack(0, kI32)}}, + // OOL stack check, local still spilled. + {1, {}}, + // OOL trap (invalid index), local still spilled, stack has {kConst}. + {2, {Constant(1, kI32, kConst)}}, + // OOL trap (sig mismatch), stack unmodified. + {2, {}}, }, debug_side_table.get()); } @@ -385,11 +373,11 @@ TEST(Liftoff_debug_side_table_loop) { CheckDebugSideTable( { // function entry, local in register. - {Register(kWasmI32)}, + {1, {Register(0, kI32)}}, // OOL stack check, local spilled, stack empty. - {Stack(kWasmI32)}, - // OOL loop stack check, local spilled, stack has {kConst}. - {Stack(kWasmI32), Constant(kWasmI32, kConst)}, + {1, {Stack(0, kI32)}}, + // OOL loop stack check, local still spilled, stack has {kConst}. + {2, {Constant(1, kI32, kConst)}}, }, debug_side_table.get()); } @@ -402,13 +390,13 @@ TEST(Liftoff_debug_side_table_trap) { CheckDebugSideTable( { // function entry, locals in registers. - {Register(kWasmI32), Register(kWasmI32)}, + {2, {Register(0, kI32), Register(1, kI32)}}, // OOL stack check, local spilled, stack empty. - {Stack(kWasmI32), Stack(kWasmI32)}, - // OOL trap (div by zero), locals spilled, stack empty. - {Stack(kWasmI32), Stack(kWasmI32)}, - // OOL trap (result unrepresentable), locals spilled, stack empty. - {Stack(kWasmI32), Stack(kWasmI32)}, + {2, {Stack(0, kI32), Stack(1, kI32)}}, + // OOL trap (div by zero), stack as before. + {2, {}}, + // OOL trap (unrepresentable), stack as before. + {2, {}}, }, debug_side_table.get()); } @@ -426,12 +414,11 @@ TEST(Liftoff_breakpoint_simple) { CheckDebugSideTable( { // First break point, locals in registers. - {Register(kWasmI32), Register(kWasmI32)}, - // Second break point, locals and two stack values in registers. - {Register(kWasmI32), Register(kWasmI32), Register(kWasmI32), - Register(kWasmI32)}, + {2, {Register(0, kI32), Register(1, kI32)}}, + // Second break point, locals unchanged, two register stack values. + {4, {Register(2, kI32), Register(3, kI32)}}, // OOL stack check, locals spilled, stack empty. - {Stack(kWasmI32), Stack(kWasmI32)}, + {2, {Stack(0, kI32), Stack(1, kI32)}}, }, debug_side_table.get()); } diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc b/deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc index 9b391dd0d0..b00f0714c2 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc @@ -46,7 +46,6 @@ void CheckMemoryEqualsFollowedByZeroes(TestingModuleBuilder* builder, } // namespace WASM_EXEC_TEST(MemoryInit) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); const byte data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; @@ -83,7 +82,6 @@ WASM_EXEC_TEST(MemoryInit) { } WASM_EXEC_TEST(MemoryInitOutOfBoundsData) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); const byte data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; @@ -105,7 +103,6 @@ WASM_EXEC_TEST(MemoryInitOutOfBoundsData) { } WASM_EXEC_TEST(MemoryInitOutOfBounds) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); const byte data[kWasmPageSize] = {}; @@ -137,7 +134,6 @@ WASM_EXEC_TEST(MemoryInitOutOfBounds) { } WASM_EXEC_TEST(MemoryCopy) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); byte* mem = r.builder().AddMemory(kWasmPageSize); BUILD( @@ -166,7 +162,6 @@ WASM_EXEC_TEST(MemoryCopy) { } WASM_EXEC_TEST(MemoryCopyOverlapping) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); byte* mem = r.builder().AddMemory(kWasmPageSize); BUILD( @@ -189,7 +184,6 @@ WASM_EXEC_TEST(MemoryCopyOverlapping) { } WASM_EXEC_TEST(MemoryCopyOutOfBoundsData) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); byte* mem = r.builder().AddMemory(kWasmPageSize); BUILD( @@ -218,7 +212,6 @@ WASM_EXEC_TEST(MemoryCopyOutOfBoundsData) { } WASM_EXEC_TEST(MemoryCopyOutOfBounds) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); BUILD( @@ -248,7 +241,6 @@ WASM_EXEC_TEST(MemoryCopyOutOfBounds) { } WASM_EXEC_TEST(MemoryFill) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); BUILD( @@ -272,7 +264,6 @@ WASM_EXEC_TEST(MemoryFill) { } WASM_EXEC_TEST(MemoryFillValueWrapsToByte) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); BUILD( @@ -286,7 +277,6 @@ WASM_EXEC_TEST(MemoryFillValueWrapsToByte) { } WASM_EXEC_TEST(MemoryFillOutOfBoundsData) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); BUILD( @@ -299,7 +289,6 @@ WASM_EXEC_TEST(MemoryFillOutOfBoundsData) { } WASM_EXEC_TEST(MemoryFillOutOfBounds) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); BUILD( @@ -322,7 +311,6 @@ WASM_EXEC_TEST(MemoryFillOutOfBounds) { } WASM_EXEC_TEST(DataDropTwice) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); const byte data[] = {0}; @@ -334,7 +322,6 @@ WASM_EXEC_TEST(DataDropTwice) { } WASM_EXEC_TEST(DataDropThenMemoryInit) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t> r(execution_tier); r.builder().AddMemory(kWasmPageSize); const byte data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; @@ -348,7 +335,6 @@ WASM_EXEC_TEST(DataDropThenMemoryInit) { void TestTableCopyInbounds(TestExecutionTier execution_tier, int table_dst, int table_src) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); const uint32_t kTableSize = 5; // Add 10 function tables, even though we only test one table. @@ -411,7 +397,6 @@ void CheckTableCall(Isolate* isolate, Handle<WasmTableObject> table, } // namespace void TestTableInitElems(TestExecutionTier execution_tier, int table_index) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); Isolate* isolate = CcTest::InitIsolateOnce(); HandleScope scope(isolate); TestSignatures sigs; @@ -489,7 +474,6 @@ WASM_COMPILED_EXEC_TEST(TableInitElems9) { } void TestTableInitOob(TestExecutionTier execution_tier, int table_index) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); Isolate* isolate = CcTest::InitIsolateOnce(); HandleScope scope(isolate); TestSignatures sigs; @@ -569,7 +553,6 @@ WASM_COMPILED_EXEC_TEST(TableInitOob9) { void TestTableCopyElems(TestExecutionTier execution_tier, int table_dst, int table_src) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); Isolate* isolate = CcTest::InitIsolateOnce(); HandleScope scope(isolate); TestSignatures sigs; @@ -651,7 +634,6 @@ WASM_COMPILED_EXEC_TEST(TableCopyElemsFrom6To6) { void TestTableCopyCalls(TestExecutionTier execution_tier, int table_dst, int table_src) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); Isolate* isolate = CcTest::InitIsolateOnce(); HandleScope scope(isolate); TestSignatures sigs; @@ -726,7 +708,6 @@ WASM_COMPILED_EXEC_TEST(TableCopyCallsTo6From6) { void TestTableCopyOobWrites(TestExecutionTier execution_tier, int table_dst, int table_src) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); Isolate* isolate = CcTest::InitIsolateOnce(); HandleScope scope(isolate); TestSignatures sigs; @@ -802,7 +783,6 @@ WASM_COMPILED_EXEC_TEST(TableCopyOobWritesFrom6To6) { void TestTableCopyOob1(TestExecutionTier execution_tier, int table_dst, int table_src) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier); const uint32_t kTableSize = 5; @@ -860,7 +840,6 @@ WASM_COMPILED_EXEC_TEST(TableCopyOob1From6To6) { } WASM_COMPILED_EXEC_TEST(ElemDropTwice) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t> r(execution_tier); r.builder().AddIndirectFunctionTable(nullptr, 1); r.builder().AddPassiveElementSegment({}); @@ -871,7 +850,6 @@ WASM_COMPILED_EXEC_TEST(ElemDropTwice) { } WASM_COMPILED_EXEC_TEST(ElemDropThenTableInit) { - EXPERIMENTAL_FLAG_SCOPE(bulk_memory); WasmRunner<uint32_t, uint32_t> r(execution_tier); r.builder().AddIndirectFunctionTable(nullptr, 1); r.builder().AddPassiveElementSegment({}); diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-exceptions.cc b/deps/v8/test/cctest/wasm/test-run-wasm-exceptions.cc index 83b446cc49..e55547911b 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-exceptions.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-exceptions.cc @@ -12,7 +12,7 @@ namespace internal { namespace wasm { namespace test_run_wasm_exceptions { -WASM_COMPILED_EXEC_TEST(TryCatchThrow) { +WASM_EXEC_TEST(TryCatchThrow) { TestSignatures sigs; EXPERIMENTAL_FLAG_SCOPE(eh); WasmRunner<uint32_t, uint32_t> r(execution_tier); @@ -27,12 +27,265 @@ WASM_COMPILED_EXEC_TEST(TryCatchThrow) { WASM_THROW(except))), WASM_STMTS(WASM_I32V(kResult0)), except)); - // Need to call through JS to allow for creation of stack traces. - r.CheckCallViaJS(kResult0, 0); - r.CheckCallViaJS(kResult1, 1); + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + } +} + +WASM_EXEC_TEST(TryCatchThrowWithValue) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + WasmRunner<uint32_t, uint32_t> r(execution_tier); + uint32_t except = r.builder().AddException(sigs.v_i()); + constexpr uint32_t kResult0 = 23; + constexpr uint32_t kResult1 = 42; + + // Build the main test function. + BUILD(r, WASM_TRY_CATCH_T( + kWasmI32, + WASM_STMTS(WASM_I32V(kResult1), + WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), + WASM_I32V(kResult0), WASM_THROW(except))), + WASM_STMTS(kExprNop), except)); + + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + } +} + +WASM_EXEC_TEST(TryMultiCatchThrow) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + WasmRunner<uint32_t, uint32_t> r(execution_tier); + uint32_t except1 = r.builder().AddException(sigs.v_v()); + uint32_t except2 = r.builder().AddException(sigs.v_v()); + constexpr uint32_t kResult0 = 23; + constexpr uint32_t kResult1 = 42; + constexpr uint32_t kResult2 = 51; + + // Build the main test function. + BUILD( + r, kExprTry, static_cast<byte>((kWasmI32).value_type_code()), + WASM_STMTS(WASM_I32V(kResult2), + WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), WASM_THROW(except1)), + WASM_IF(WASM_I32_EQ(WASM_LOCAL_GET(0), WASM_I32V(1)), + WASM_THROW(except2))), + kExprCatch, except1, WASM_STMTS(WASM_I32V(kResult0)), kExprCatch, except2, + WASM_STMTS(WASM_I32V(kResult1)), kExprEnd); + + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + r.CheckCallViaJS(kResult2, 2); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + CHECK_EQ(kResult2, r.CallInterpreter(2)); + } +} + +WASM_EXEC_TEST(TryCatchAllThrow) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + WasmRunner<uint32_t, uint32_t> r(execution_tier); + uint32_t except1 = r.builder().AddException(sigs.v_v()); + uint32_t except2 = r.builder().AddException(sigs.v_v()); + constexpr uint32_t kResult0 = 23; + constexpr uint32_t kResult1 = 42; + constexpr uint32_t kResult2 = 51; + + // Build the main test function. + BUILD( + r, kExprTry, static_cast<byte>((kWasmI32).value_type_code()), + WASM_STMTS(WASM_I32V(kResult2), + WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), WASM_THROW(except1)), + WASM_IF(WASM_I32_EQ(WASM_LOCAL_GET(0), WASM_I32V(1)), + WASM_THROW(except2))), + kExprCatch, except1, WASM_STMTS(WASM_I32V(kResult0)), kExprCatchAll, + WASM_STMTS(WASM_I32V(kResult1)), kExprEnd); + + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + r.CheckCallViaJS(kResult2, 2); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + CHECK_EQ(kResult2, r.CallInterpreter(2)); + } +} + +WASM_EXEC_TEST(TryImplicitRethrow) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + WasmRunner<uint32_t, uint32_t> r(execution_tier); + uint32_t except1 = r.builder().AddException(sigs.v_v()); + uint32_t except2 = r.builder().AddException(sigs.v_v()); + constexpr uint32_t kResult0 = 23; + constexpr uint32_t kResult1 = 42; + constexpr uint32_t kResult2 = 51; + + // Build the main test function. + BUILD(r, + WASM_TRY_CATCH_T( + kWasmI32, + WASM_TRY_CATCH_T(kWasmI32, + WASM_STMTS(WASM_I32V(kResult1), + WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), + WASM_THROW(except2))), + WASM_STMTS(WASM_I32V(kResult2)), except1), + WASM_I32V(kResult0), except2)); + + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + } +} + +WASM_EXEC_TEST(TryDelegate) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + WasmRunner<uint32_t, uint32_t> r(execution_tier); + uint32_t except = r.builder().AddException(sigs.v_v()); + constexpr uint32_t kResult0 = 23; + constexpr uint32_t kResult1 = 42; + + // Build the main test function. + BUILD(r, + WASM_TRY_CATCH_T(kWasmI32, + WASM_TRY_DELEGATE_T( + kWasmI32, + WASM_STMTS(WASM_I32V(kResult1), + WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), + WASM_THROW(except))), + 0), + WASM_I32V(kResult0), except)); + + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + } } -WASM_COMPILED_EXEC_TEST(TryCatchCallDirect) { +WASM_EXEC_TEST(TryUnwind) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + WasmRunner<uint32_t, uint32_t> r(execution_tier); + uint32_t except = r.builder().AddException(sigs.v_v()); + constexpr uint32_t kResult0 = 23; + constexpr uint32_t kResult1 = 42; + + // Build the main test function. + BUILD(r, WASM_TRY_CATCH_T( + kWasmI32, + WASM_TRY_UNWIND_T( + kWasmI32, + WASM_TRY_DELEGATE_T( + kWasmI32, + WASM_STMTS(WASM_I32V(kResult1), + WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), + WASM_THROW(except))), + 0), + kExprNop), + WASM_I32V(kResult0), except)); + + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + } +} + +WASM_EXEC_TEST(TryCatchRethrow) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + WasmRunner<uint32_t, uint32_t> r(execution_tier); + uint32_t except1 = r.builder().AddException(sigs.v_v()); + uint32_t except2 = r.builder().AddException(sigs.v_v()); + constexpr uint32_t kResult0 = 23; + constexpr uint32_t kResult1 = 42; + constexpr uint32_t kUnreachable = 51; + + // Build the main test function. + BUILD(r, + WASM_TRY_CATCH_CATCH_T( + kWasmI32, + WASM_TRY_CATCH_T( + kWasmI32, WASM_THROW(except2), + WASM_TRY_CATCH_T( + kWasmI32, WASM_THROW(except1), + WASM_STMTS(WASM_I32V(kUnreachable), + WASM_IF_ELSE(WASM_I32_EQZ(WASM_LOCAL_GET(0)), + WASM_RETHROW(1), WASM_RETHROW(2))), + except1), + except2), + except1, WASM_I32V(kResult0), except2, WASM_I32V(kResult1))); + + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + } +} + +WASM_EXEC_TEST(TryDelegateToCaller) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + WasmRunner<uint32_t, uint32_t> r(execution_tier); + uint32_t except = r.builder().AddException(sigs.v_v()); + constexpr uint32_t kResult0 = 23; + constexpr uint32_t kResult1 = 42; + + // Build the main test function. + BUILD(r, + WASM_TRY_CATCH_T(kWasmI32, + WASM_TRY_DELEGATE_T( + kWasmI32, + WASM_STMTS(WASM_I32V(kResult1), + WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), + WASM_THROW(except))), + 1), + WASM_I32V(kResult0), except)); + + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + constexpr int64_t trap = 0xDEADBEEF; + r.CheckCallViaJS(trap, 0); + r.CheckCallViaJS(kResult1, 1); + } else { + constexpr int stopped = 0; + CHECK_EQ(stopped, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + } +} + +WASM_EXEC_TEST(TryCatchCallDirect) { TestSignatures sigs; EXPERIMENTAL_FLAG_SCOPE(eh); WasmRunner<uint32_t, uint32_t> r(execution_tier); @@ -55,12 +308,17 @@ WASM_COMPILED_EXEC_TEST(TryCatchCallDirect) { WASM_DROP))), WASM_STMTS(WASM_I32V(kResult0)), except)); - // Need to call through JS to allow for creation of stack traces. - r.CheckCallViaJS(kResult0, 0); - r.CheckCallViaJS(kResult1, 1); + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + } } -WASM_COMPILED_EXEC_TEST(TryCatchCallIndirect) { +WASM_EXEC_TEST(TryCatchCallIndirect) { TestSignatures sigs; EXPERIMENTAL_FLAG_SCOPE(eh); WasmRunner<uint32_t, uint32_t> r(execution_tier); @@ -92,9 +350,14 @@ WASM_COMPILED_EXEC_TEST(TryCatchCallIndirect) { WASM_DROP))), WASM_STMTS(WASM_I32V(kResult0)), except)); - // Need to call through JS to allow for creation of stack traces. - r.CheckCallViaJS(kResult0, 0); - r.CheckCallViaJS(kResult1, 1); + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJS(kResult0, 0); + r.CheckCallViaJS(kResult1, 1); + } else { + CHECK_EQ(kResult0, r.CallInterpreter(0)); + CHECK_EQ(kResult1, r.CallInterpreter(1)); + } } WASM_COMPILED_EXEC_TEST(TryCatchCallExternal) { @@ -152,32 +415,51 @@ void TestTrapNotCaught(byte* code, size_t code_size, WASM_DROP), WASM_STMTS(WASM_I32V(kResultCaught)))); - // Need to call through JS to allow for creation of stack traces. - r.CheckCallViaJSTraps(); + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJSTraps(); + } else { + r.CallInterpreter(); + } } } // namespace -WASM_COMPILED_EXEC_TEST(TryCatchTrapUnreachable) { +WASM_EXEC_TEST(TryCatchTrapUnreachable) { byte code[] = {WASM_UNREACHABLE}; TestTrapNotCaught(code, arraysize(code), execution_tier); } -WASM_COMPILED_EXEC_TEST(TryCatchTrapMemOutOfBounds) { +WASM_EXEC_TEST(TryCatchTrapMemOutOfBounds) { byte code[] = {WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(-1))}; TestTrapNotCaught(code, arraysize(code), execution_tier); } -WASM_COMPILED_EXEC_TEST(TryCatchTrapDivByZero) { +WASM_EXEC_TEST(TryCatchTrapDivByZero) { byte code[] = {WASM_I32_DIVS(WASM_LOCAL_GET(0), WASM_I32V_1(0))}; TestTrapNotCaught(code, arraysize(code), execution_tier); } -WASM_COMPILED_EXEC_TEST(TryCatchTrapRemByZero) { +WASM_EXEC_TEST(TryCatchTrapRemByZero) { byte code[] = {WASM_I32_REMS(WASM_LOCAL_GET(0), WASM_I32V_1(0))}; TestTrapNotCaught(code, arraysize(code), execution_tier); } +TEST(Regress1180457) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + WasmRunner<uint32_t> r(TestExecutionTier::kInterpreter); + constexpr uint32_t kResult0 = 23; + constexpr uint32_t kUnreachable = 42; + BUILD(r, WASM_TRY_CATCH_ALL_T( + kWasmI32, + WASM_TRY_DELEGATE_T( + kWasmI32, WASM_STMTS(WASM_I32V(kResult0), WASM_BR(0)), 0), + WASM_I32V(kUnreachable))); + + CHECK_EQ(kResult0, r.CallInterpreter()); +} + } // namespace test_run_wasm_exceptions } // namespace wasm } // namespace internal diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-memory64.cc b/deps/v8/test/cctest/wasm/test-run-wasm-memory64.cc index 1dcccca67f..71bb77f6ad 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-memory64.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-memory64.cc @@ -7,6 +7,7 @@ #include "test/cctest/wasm/wasm-run-utils.h" #include "test/common/wasm/test-signatures.h" #include "test/common/wasm/wasm-macro-gen.h" +#include "test/common/wasm/wasm-module-runner.h" namespace v8 { namespace internal { @@ -54,6 +55,49 @@ WASM_EXEC_TEST(Load) { // TODO(clemensb): Test atomic instructions. +WASM_EXEC_TEST(InitExpression) { + EXPERIMENTAL_FLAG_SCOPE(memory64); + Isolate* isolate = CcTest::InitIsolateOnce(); + HandleScope scope(isolate); + + ErrorThrower thrower(isolate, "TestMemory64InitExpression"); + + const byte data[] = { + WASM_MODULE_HEADER, // + SECTION(Memory, // + ENTRY_COUNT(1), // + kMemory64WithMaximum, // type + 1, // initial size + 2), // maximum size + SECTION(Data, // + ENTRY_COUNT(1), // + 0, // linear memory index + WASM_I64V_3(0xFFFF), kExprEnd, // destination offset + U32V_1(1), // source size + 'c') // data bytes + }; + + testing::CompileAndInstantiateForTesting( + isolate, &thrower, ModuleWireBytes(data, data + arraysize(data))); + if (thrower.error()) { + thrower.Reify()->Print(); + FATAL("compile or instantiate error"); + } +} + +WASM_EXEC_TEST(MemorySize) { + // TODO(clemensb): Implement memory64 in the interpreter. + if (execution_tier == TestExecutionTier::kInterpreter) return; + + Memory64Runner<uint64_t> r(execution_tier); + constexpr int kNumPages = 13; + r.builder().AddMemoryElems<uint8_t>(kNumPages * kWasmPageSize); + + BUILD(r, WASM_MEMORY_SIZE); + + CHECK_EQ(kNumPages, r.Call()); +} + } // namespace wasm } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-module.cc b/deps/v8/test/cctest/wasm/test-run-wasm-module.cc index 9a6e85f431..a9f5dd6b26 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-module.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-module.cc @@ -904,41 +904,6 @@ TEST(EmptyMemoryEmptyDataSegment) { Cleanup(); } -TEST(MemoryWithOOBEmptyDataSegment) { - { - FlagScope<bool> no_bulk_memory( - &v8::internal::FLAG_experimental_wasm_bulk_memory, false); - Isolate* isolate = CcTest::InitIsolateOnce(); - HandleScope scope(isolate); - testing::SetupIsolateForWasmModule(isolate); - - ErrorThrower thrower(isolate, "Run_WasmModule_InitDataAtTheUpperLimit"); - - const byte data[] = { - WASM_MODULE_HEADER, // -- - kMemorySectionCode, // -- - U32V_1(4), // section size - ENTRY_COUNT(1), // -- - kWithMaximum, // -- - 1, // initial size - 1, // maximum size - kDataSectionCode, // -- - U32V_1(9), // section size - ENTRY_COUNT(1), // -- - 0, // linear memory index - WASM_I32V_4(0x2468ACE), // destination offset - kExprEnd, - U32V_1(0), // source size - }; - - CompileAndInstantiateForTesting( - isolate, &thrower, ModuleWireBytes(data, data + arraysize(data))); - // It should not be possible to instantiate this module. - CHECK(thrower.error()); - } - Cleanup(); -} - #undef EMIT_CODE_WITH_END } // namespace test_run_wasm_module diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-simd-scalar-lowering.cc b/deps/v8/test/cctest/wasm/test-run-wasm-simd-scalar-lowering.cc index 11db27f72c..4c5309aae5 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-simd-scalar-lowering.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-simd-scalar-lowering.cc @@ -224,7 +224,7 @@ WASM_SIMD_TEST(AnyTrue_DifferentShapes) { WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); BUILD(r, WASM_SIMD_I32x4_SPLAT(WASM_LOCAL_GET(0)), - WASM_SIMD_OP(kExprV8x16AnyTrue)); + WASM_SIMD_OP(kExprV128AnyTrue)); CHECK_EQ(0, r.Call(0x00000000)); } @@ -233,7 +233,7 @@ WASM_SIMD_TEST(AnyTrue_DifferentShapes) { WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); BUILD(r, WASM_SIMD_I32x4_SPLAT(WASM_LOCAL_GET(0)), - WASM_SIMD_OP(kExprV16x8AnyTrue)); + WASM_SIMD_OP(kExprV128AnyTrue)); CHECK_EQ(1, r.Call(0x000000FF)); } @@ -243,7 +243,7 @@ WASM_SIMD_TEST(AnyTrue_DifferentShapes) { WasmRunner<int32_t, float> r(execution_tier, lower_simd); BUILD(r, WASM_SIMD_F32x4_SPLAT(WASM_LOCAL_GET(0)), - WASM_SIMD_OP(kExprV8x16AnyTrue)); + WASM_SIMD_OP(kExprV128AnyTrue)); CHECK_EQ(0, r.Call(0x00000000)); } diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc b/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc index c6be948954..fa9299f27b 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc @@ -17,6 +17,7 @@ #include "src/base/macros.h" #include "src/base/memory.h" #include "src/base/overflowing-math.h" +#include "src/base/safe_conversions.h" #include "src/base/utils/random-number-generator.h" #include "src/codegen/assembler-inl.h" #include "src/codegen/cpu-features.h" @@ -800,26 +801,22 @@ WASM_SIMD_TEST_NO_LOWERING(I8x16SignSelect) { } WASM_SIMD_TEST_NO_LOWERING(I16x8SignSelect) { - std::array<int16_t, kSimd128Size / 2> selection = {0x8000, 0, -1, 0, - 0x8000, 0, -1, 0}; - std::array<int8_t, kSimd128Size> mask; - memcpy(mask.data(), selection.data(), kSimd128Size); + std::array<int8_t, kSimd128Size> mask = {0, 0x80, 0, 0, -1, -1, 0, 0, + 0, 0x80, 0, 0, -1, -1, 0, 0}; RunSignSelect<int16_t>(execution_tier, lower_simd, kExprI16x8SignSelect, kExprI16x8Splat, mask); } WASM_SIMD_TEST_NO_LOWERING(I32x4SignSelect) { - std::array<int32_t, kSimd128Size / 4> selection = {0x80000000, 0, -1, 0}; - std::array<int8_t, kSimd128Size> mask; - memcpy(mask.data(), selection.data(), kSimd128Size); + std::array<int8_t, kSimd128Size> mask = {0, 0, 0, 0x80, 0, 0, 0, 0, + -1, -1, -1, -1, 0, 0, 0, 0}; RunSignSelect<int32_t>(execution_tier, lower_simd, kExprI32x4SignSelect, kExprI32x4Splat, mask); } WASM_SIMD_TEST_NO_LOWERING(I64x2SignSelect) { - std::array<int64_t, kSimd128Size / 8> selection = {0x8000000000000000, 0}; - std::array<int8_t, kSimd128Size> mask; - memcpy(mask.data(), selection.data(), kSimd128Size); + std::array<int8_t, kSimd128Size> mask = {0, 0, 0, 0, 0, 0, 0, 0x80, + 0, 0, 0, 0, 0, 0, 0, 0}; RunSignSelect<int64_t>(execution_tier, lower_simd, kExprI64x2SignSelect, kExprI64x2Splat, mask); } @@ -954,6 +951,10 @@ WASM_SIMD_TEST(I64x2Neg) { base::NegateWithWraparound); } +WASM_SIMD_TEST_NO_LOWERING(I64x2Abs) { + RunI64x2UnOpTest(execution_tier, lower_simd, kExprI64x2Abs, std::abs); +} + void RunI64x2ShiftOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, Int64ShiftOp expected_op) { // Intentionally shift by 64, should be no-op. @@ -1003,7 +1004,6 @@ WASM_SIMD_TEST(I64x2ShrU) { void RunI64x2BinOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, Int64BinOp expected_op) { - FLAG_SCOPE(wasm_simd_post_mvp); WasmRunner<int32_t, int64_t, int64_t> r(execution_tier, lower_simd); // Global to hold output. int64_t* g = r.builder().AddGlobal<int64_t>(kWasmS128); @@ -1038,15 +1038,29 @@ WASM_SIMD_TEST(I64x2Sub) { base::SubWithWraparound); } -#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X || \ - V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS64 || \ - V8_TARGET_ARCH_MIPS WASM_SIMD_TEST_NO_LOWERING(I64x2Eq) { RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2Eq, Equal); } -#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X || - // V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS64 || - // V8_TARGET_ARCH_MIPS + +WASM_SIMD_TEST_NO_LOWERING(I64x2Ne) { + RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2Ne, NotEqual); +} + +WASM_SIMD_TEST_NO_LOWERING(I64x2LtS) { + RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2LtS, Less); +} + +WASM_SIMD_TEST_NO_LOWERING(I64x2LeS) { + RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2LeS, LessEqual); +} + +WASM_SIMD_TEST_NO_LOWERING(I64x2GtS) { + RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2GtS, Greater); +} + +WASM_SIMD_TEST_NO_LOWERING(I64x2GeS) { + RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2GeS, GreaterEqual); +} WASM_SIMD_TEST(F64x2Splat) { WasmRunner<int32_t, double> r(execution_tier, lower_simd); @@ -1282,6 +1296,115 @@ WASM_SIMD_TEST(F64x2NearestInt) { true); } +template <typename SrcType> +void RunF64x2ConvertLowI32x4Test(TestExecutionTier execution_tier, + LowerSimd lower_simd, WasmOpcode opcode) { + WasmRunner<int32_t, SrcType> r(execution_tier, lower_simd); + double* g = r.builder().template AddGlobal<double>(kWasmS128); + // TODO(zhin): set top lanes to 0 to assert conversion happens on low lanes. + BUILD( + r, + WASM_GLOBAL_SET( + 0, WASM_SIMD_UNOP(opcode, WASM_SIMD_I32x4_SPLAT(WASM_LOCAL_GET(0)))), + WASM_ONE); + + for (SrcType x : compiler::ValueHelper::GetVector<SrcType>()) { + r.Call(x); + double expected = static_cast<double>(x); + for (int i = 0; i < 2; i++) { + double actual = ReadLittleEndianValue<double>(&g[i]); + CheckDoubleResult(x, x, expected, actual, true); + } + } +} + +WASM_SIMD_TEST_NO_LOWERING(F64x2ConvertLowI32x4S) { + RunF64x2ConvertLowI32x4Test<int32_t>(execution_tier, lower_simd, + kExprF64x2ConvertLowI32x4S); +} + +WASM_SIMD_TEST_NO_LOWERING(F64x2ConvertLowI32x4U) { + RunF64x2ConvertLowI32x4Test<uint32_t>(execution_tier, lower_simd, + kExprF64x2ConvertLowI32x4U); +} + +template <typename SrcType> +void RunI32x4TruncSatF64x2Test(TestExecutionTier execution_tier, + LowerSimd lower_simd, WasmOpcode opcode) { + WasmRunner<int32_t, double> r(execution_tier, lower_simd); + SrcType* g = r.builder().AddGlobal<SrcType>(kWasmS128); + BUILD( + r, + WASM_GLOBAL_SET( + 0, WASM_SIMD_UNOP(opcode, WASM_SIMD_F64x2_SPLAT(WASM_LOCAL_GET(0)))), + WASM_ONE); + + FOR_FLOAT64_INPUTS(x) { + r.Call(x); + SrcType expected = base::saturated_cast<SrcType>(x); + for (int i = 0; i < 2; i++) { + SrcType actual = ReadLittleEndianValue<SrcType>(&g[i]); + CHECK_EQ(expected, actual); + } + // Top lanes are zero-ed. + for (int i = 2; i < 4; i++) { + CHECK_EQ(0, ReadLittleEndianValue<SrcType>(&g[i])); + } + } +} + +WASM_SIMD_TEST_NO_LOWERING(I32x4TruncSatF64x2SZero) { + RunI32x4TruncSatF64x2Test<int32_t>(execution_tier, lower_simd, + kExprI32x4TruncSatF64x2SZero); +} + +WASM_SIMD_TEST_NO_LOWERING(I32x4TruncSatF64x2UZero) { + RunI32x4TruncSatF64x2Test<uint32_t>(execution_tier, lower_simd, + kExprI32x4TruncSatF64x2UZero); +} + +WASM_SIMD_TEST_NO_LOWERING(F32x4DemoteF64x2Zero) { + WasmRunner<int32_t, double> r(execution_tier, lower_simd); + float* g = r.builder().AddGlobal<float>(kWasmS128); + BUILD(r, + WASM_GLOBAL_SET( + 0, WASM_SIMD_UNOP(kExprF32x4DemoteF64x2Zero, + WASM_SIMD_F64x2_SPLAT(WASM_LOCAL_GET(0)))), + WASM_ONE); + + FOR_FLOAT64_INPUTS(x) { + r.Call(x); + float expected = DoubleToFloat32(x); + for (int i = 0; i < 2; i++) { + float actual = ReadLittleEndianValue<float>(&g[i]); + CheckFloatResult(x, x, expected, actual, true); + } + for (int i = 2; i < 4; i++) { + float actual = ReadLittleEndianValue<float>(&g[i]); + CheckFloatResult(x, x, 0, actual, true); + } + } +} + +WASM_SIMD_TEST_NO_LOWERING(F64x2PromoteLowF32x4) { + WasmRunner<int32_t, float> r(execution_tier, lower_simd); + double* g = r.builder().AddGlobal<double>(kWasmS128); + BUILD(r, + WASM_GLOBAL_SET( + 0, WASM_SIMD_UNOP(kExprF64x2PromoteLowF32x4, + WASM_SIMD_F32x4_SPLAT(WASM_LOCAL_GET(0)))), + WASM_ONE); + + FOR_FLOAT32_INPUTS(x) { + r.Call(x); + double expected = static_cast<double>(x); + for (int i = 0; i < 2; i++) { + double actual = ReadLittleEndianValue<double>(&g[i]); + CheckDoubleResult(x, x, expected, actual, true); + } + } +} + void RunF64x2BinOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, DoubleBinOp expected_op) { WasmRunner<int32_t, double, double> r(execution_tier, lower_simd); @@ -1804,18 +1927,14 @@ WASM_SIMD_TEST(I32x4ConvertI16x8) { } } -// TODO(v8:10972) Prototyping i64x2 convert from i32x4. // Tests both signed and unsigned conversion from I32x4 (unpacking). -#if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32 || \ - V8_TARGET_ARCH_ARM WASM_SIMD_TEST_NO_LOWERING(I64x2ConvertI32x4) { - FLAG_SCOPE(wasm_simd_post_mvp); WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); // Create four output vectors to hold signed and unsigned results. int64_t* g0 = r.builder().AddGlobal<int64_t>(kWasmS128); int64_t* g1 = r.builder().AddGlobal<int64_t>(kWasmS128); - int64_t* g2 = r.builder().AddGlobal<int64_t>(kWasmS128); - int64_t* g3 = r.builder().AddGlobal<int64_t>(kWasmS128); + uint64_t* g2 = r.builder().AddGlobal<uint64_t>(kWasmS128); + uint64_t* g3 = r.builder().AddGlobal<uint64_t>(kWasmS128); // Build fn to splat test value, perform conversions, and write the results. byte value = 0; byte temp1 = r.AllocateLocal(kWasmS128); @@ -1833,17 +1952,16 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2ConvertI32x4) { FOR_INT32_INPUTS(x) { r.Call(x); int64_t expected_signed = static_cast<int64_t>(x); - int64_t expected_unsigned = static_cast<int64_t>(static_cast<uint32_t>(x)); + uint64_t expected_unsigned = + static_cast<uint64_t>(static_cast<uint32_t>(x)); for (int i = 0; i < 2; i++) { CHECK_EQ(expected_signed, ReadLittleEndianValue<int64_t>(&g0[i])); CHECK_EQ(expected_signed, ReadLittleEndianValue<int64_t>(&g1[i])); - CHECK_EQ(expected_unsigned, ReadLittleEndianValue<int64_t>(&g2[i])); - CHECK_EQ(expected_unsigned, ReadLittleEndianValue<int64_t>(&g3[i])); + CHECK_EQ(expected_unsigned, ReadLittleEndianValue<uint64_t>(&g2[i])); + CHECK_EQ(expected_unsigned, ReadLittleEndianValue<uint64_t>(&g3[i])); } } } -#endif // V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32 || - // V8_TARGET_ARCH_ARM void RunI32x4UnOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, Int32UnOp expected_op) { @@ -1880,14 +1998,10 @@ WASM_SIMD_TEST(S128Not) { [](int32_t x) { return ~x; }); } -#if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X64 || \ - V8_TARGET_ARCH_IA32 -// TODO(v8:11086) Prototype i32x4.extadd_pairwise_i16x8_{s,u} template <typename Narrow, typename Wide> void RunExtAddPairwiseTest(TestExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode ext_add_pairwise, WasmOpcode splat) { - FLAG_SCOPE(wasm_simd_post_mvp); constexpr int num_lanes = kSimd128Size / sizeof(Wide); WasmRunner<int32_t, Narrow> r(execution_tier, lower_simd); Wide* g = r.builder().template AddGlobal<Wide>(kWasmS128); @@ -1930,8 +2044,6 @@ WASM_SIMD_TEST_NO_LOWERING(I16x8ExtAddPairwiseI8x16U) { kExprI16x8ExtAddPairwiseI8x16U, kExprI8x16Splat); } -#endif // V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X64 || - // V8_TARGET_ARCH_IA32 void RunI32x4BinOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, Int32BinOp expected_op) { @@ -2157,8 +2269,8 @@ WASM_SIMD_TEST(I16x8ConvertI32x4) { FOR_INT32_INPUTS(x) { r.Call(x); - int16_t expected_signed = Saturate<int16_t>(x); - int16_t expected_unsigned = Saturate<uint16_t>(x); + int16_t expected_signed = base::saturated_cast<int16_t>(x); + int16_t expected_unsigned = base::saturated_cast<uint16_t>(x); for (int i = 0; i < 8; i++) { CHECK_EQ(expected_signed, ReadLittleEndianValue<int16_t>(&g0[i])); CHECK_EQ(expected_unsigned, ReadLittleEndianValue<int16_t>(&g1[i])); @@ -2325,7 +2437,6 @@ WASM_SIMD_TEST(I16x8RoundingAverageU) { } WASM_SIMD_TEST_NO_LOWERING(I16x8Q15MulRSatS) { - FLAG_SCOPE(wasm_simd_post_mvp); RunI16x8BinOpTest<int16_t>(execution_tier, lower_simd, kExprI16x8Q15MulRSatS, SaturateRoundingQMul<int16_t>); } @@ -2542,10 +2653,7 @@ WASM_SIMD_TEST(I8x16Abs) { RunI8x16UnOpTest(execution_tier, lower_simd, kExprI8x16Abs, Abs); } -#if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM -// TODO(v8:11002) Prototype i8x16.popcnt. WASM_SIMD_TEST_NO_LOWERING(I8x16Popcnt) { - FLAG_SCOPE(wasm_simd_post_mvp); WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); // Global to hold output. int8_t* g = r.builder().AddGlobal<int8_t>(kWasmS128); @@ -2565,14 +2673,13 @@ WASM_SIMD_TEST_NO_LOWERING(I8x16Popcnt) { } } } -#endif // V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM // Tests both signed and unsigned conversion from I16x8 (packing). WASM_SIMD_TEST(I8x16ConvertI16x8) { WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); // Create output vectors to hold signed and unsigned results. - int8_t* g0 = r.builder().AddGlobal<int8_t>(kWasmS128); - int8_t* g1 = r.builder().AddGlobal<int8_t>(kWasmS128); + int8_t* g_s = r.builder().AddGlobal<int8_t>(kWasmS128); + uint8_t* g_u = r.builder().AddGlobal<uint8_t>(kWasmS128); // Build fn to splat test value, perform conversions, and write the results. byte value = 0; byte temp1 = r.AllocateLocal(kWasmS128); @@ -2587,11 +2694,11 @@ WASM_SIMD_TEST(I8x16ConvertI16x8) { FOR_INT16_INPUTS(x) { r.Call(x); - int8_t expected_signed = Saturate<int8_t>(x); - int8_t expected_unsigned = Saturate<uint8_t>(x); + int8_t expected_signed = base::saturated_cast<int8_t>(x); + uint8_t expected_unsigned = base::saturated_cast<uint8_t>(x); for (int i = 0; i < 16; i++) { - CHECK_EQ(expected_signed, ReadLittleEndianValue<int8_t>(&g0[i])); - CHECK_EQ(expected_unsigned, ReadLittleEndianValue<int8_t>(&g1[i])); + CHECK_EQ(expected_signed, ReadLittleEndianValue<int8_t>(&g_s[i])); + CHECK_EQ(expected_unsigned, ReadLittleEndianValue<uint8_t>(&g_u[i])); } } } @@ -3271,14 +3378,14 @@ WASM_SIMD_TEST(S8x16MultiShuffleFuzz) { byte reduced = r.AllocateLocal(kWasmI32); \ BUILD(r, WASM_LOCAL_SET(zero, WASM_SIMD_I##format##_SPLAT(int_type(0))), \ WASM_LOCAL_SET( \ - reduced, WASM_SIMD_UNOP(kExprV##format##AnyTrue, \ + reduced, WASM_SIMD_UNOP(kExprV128AnyTrue, \ WASM_SIMD_BINOP(kExprI##format##Eq, \ WASM_LOCAL_GET(zero), \ WASM_LOCAL_GET(zero)))), \ WASM_IF(WASM_I32_EQ(WASM_LOCAL_GET(reduced), WASM_ZERO), \ WASM_RETURN1(WASM_ZERO)), \ WASM_LOCAL_SET( \ - reduced, WASM_SIMD_UNOP(kExprV##format##AnyTrue, \ + reduced, WASM_SIMD_UNOP(kExprV128AnyTrue, \ WASM_SIMD_BINOP(kExprI##format##Ne, \ WASM_LOCAL_GET(zero), \ WASM_LOCAL_GET(zero)))), \ @@ -3302,14 +3409,14 @@ WASM_SIMD_TEST(S8x16MultiShuffleFuzz) { WASM_SIMD_I##format##_REPLACE_LANE( \ lanes - 1, WASM_LOCAL_GET(zero), int_type(1))), \ WASM_LOCAL_SET( \ - reduced, WASM_SIMD_UNOP(kExprV##format##AnyTrue, \ + reduced, WASM_SIMD_UNOP(kExprV128AnyTrue, \ WASM_SIMD_BINOP(kExprI##format##Eq, \ WASM_LOCAL_GET(one_one), \ WASM_LOCAL_GET(zero)))), \ WASM_IF(WASM_I32_EQ(WASM_LOCAL_GET(reduced), WASM_ZERO), \ WASM_RETURN1(WASM_ZERO)), \ WASM_LOCAL_SET( \ - reduced, WASM_SIMD_UNOP(kExprV##format##AnyTrue, \ + reduced, WASM_SIMD_UNOP(kExprV128AnyTrue, \ WASM_SIMD_BINOP(kExprI##format##Ne, \ WASM_LOCAL_GET(one_one), \ WASM_LOCAL_GET(zero)))), \ @@ -3333,6 +3440,7 @@ WASM_SIMD_TEST(S8x16MultiShuffleFuzz) { CHECK_EQ(1, r.Call()); \ } +WASM_SIMD_BOOL_REDUCTION_TEST(64x2, 2, WASM_I64V) WASM_SIMD_BOOL_REDUCTION_TEST(32x4, 4, WASM_I32V) WASM_SIMD_BOOL_REDUCTION_TEST(16x8, 8, WASM_I32V) WASM_SIMD_BOOL_REDUCTION_TEST(8x16, 16, WASM_I32V) @@ -3590,7 +3698,7 @@ WASM_SIMD_TEST(SimdF32x4SetGlobal) { CHECK_EQ(GetScalar(global, 3), 65.0f); } -#if V8_TARGET_ARCH_ARM64 +#if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32 // TODO(v8:11168): Prototyping prefetch. WASM_SIMD_TEST(SimdPrefetch) { FLAG_SCOPE(wasm_simd_post_mvp); @@ -3642,7 +3750,7 @@ WASM_SIMD_TEST(SimdPrefetch) { } } } -#endif // V8_TARGET_ARCH_ARM64 +#endif // V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32 WASM_SIMD_TEST(SimdLoadStoreLoad) { WasmRunner<int32_t> r(execution_tier, lower_simd); @@ -3995,13 +4103,9 @@ WASM_SIMD_TEST(S128Load64Zero) { RunLoadZeroTest<int64_t>(execution_tier, lower_simd, kExprS128Load64Zero); } -#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM64 || \ - V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_S390X || V8_TARGET_ARCH_MIPS64 -// TODO(v8:10975): Prototyping load lane and store lane. template <typename T> void RunLoadLaneTest(TestExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode load_op, WasmOpcode splat_op) { - FLAG_SCOPE(wasm_simd_post_mvp); WasmOpcode const_op = splat_op == kExprI64x2Splat ? kExprI64Const : kExprI32Const; @@ -4100,12 +4204,6 @@ WASM_SIMD_TEST_NO_LOWERING(S128Load64Lane) { template <typename T> void RunStoreLaneTest(TestExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode store_op, WasmOpcode splat_op) { - FLAG_SCOPE(wasm_simd_post_mvp); - if (execution_tier == TestExecutionTier::kLiftoff) { - // Not yet implemented. - return; - } - constexpr int lanes = kSimd128Size / sizeof(T); constexpr int mem_index = 16; // Store to mem index 16 (bytes). constexpr int splat_value = 33; @@ -4196,9 +4294,6 @@ WASM_SIMD_TEST_NO_LOWERING(S128Store64Lane) { kExprI64x2Splat); } -#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM64 || - // V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_S390X || V8_TARGET_ARCH_MIPS64 - #define WASM_SIMD_ANYTRUE_TEST(format, lanes, max, param_type) \ WASM_SIMD_TEST(S##format##AnyTrue) { \ FLAG_SCOPE(wasm_simd_post_mvp); \ @@ -4208,7 +4303,7 @@ WASM_SIMD_TEST_NO_LOWERING(S128Store64Lane) { BUILD( \ r, \ WASM_LOCAL_SET(simd, WASM_SIMD_I##format##_SPLAT(WASM_LOCAL_GET(0))), \ - WASM_SIMD_UNOP(kExprV##format##AnyTrue, WASM_LOCAL_GET(simd))); \ + WASM_SIMD_UNOP(kExprV128AnyTrue, WASM_LOCAL_GET(simd))); \ CHECK_EQ(1, r.Call(max)); \ CHECK_EQ(1, r.Call(5)); \ CHECK_EQ(0, r.Call(0)); \ @@ -4220,11 +4315,11 @@ WASM_SIMD_ANYTRUE_TEST(8x16, 16, 0xff, int32_t) // Special any true test cases that splats a -0.0 double into a i64x2. // This is specifically to ensure that our implementation correct handles that // 0.0 and -0.0 will be different in an anytrue (IEEE753 says they are equals). -WASM_SIMD_TEST(V32x4AnytrueWithNegativeZero) { +WASM_SIMD_TEST(V128AnytrueWithNegativeZero) { WasmRunner<int32_t, int64_t> r(execution_tier, lower_simd); byte simd = r.AllocateLocal(kWasmS128); BUILD(r, WASM_LOCAL_SET(simd, WASM_SIMD_I64x2_SPLAT(WASM_LOCAL_GET(0))), - WASM_SIMD_UNOP(kExprV32x4AnyTrue, WASM_LOCAL_GET(simd))); + WASM_SIMD_UNOP(kExprV128AnyTrue, WASM_LOCAL_GET(simd))); CHECK_EQ(1, r.Call(0x8000000000000000)); CHECK_EQ(0, r.Call(0x0000000000000000)); } @@ -4243,6 +4338,7 @@ WASM_SIMD_TEST(V32x4AnytrueWithNegativeZero) { CHECK_EQ(1, r.Call(0x1)); \ CHECK_EQ(0, r.Call(0)); \ } +WASM_SIMD_ALLTRUE_TEST(64x2, 2, 0xffffffffffffffff, int64_t) WASM_SIMD_ALLTRUE_TEST(32x4, 4, 0xffffffff, int32_t) WASM_SIMD_ALLTRUE_TEST(16x8, 8, 0xffff, int32_t) WASM_SIMD_ALLTRUE_TEST(8x16, 16, 0xff, int32_t) diff --git a/deps/v8/test/cctest/wasm/test-streaming-compilation.cc b/deps/v8/test/cctest/wasm/test-streaming-compilation.cc index 863256818a..92ad205070 100644 --- a/deps/v8/test/cctest/wasm/test-streaming-compilation.cc +++ b/deps/v8/test/cctest/wasm/test-streaming-compilation.cc @@ -1372,6 +1372,28 @@ STREAM_TEST(TestProfilingMidStreaming) { cpu_profiler->Dispose(); } +STREAM_TEST(TierDownWithError) { + // https://crbug.com/1160031 + StreamTester tester(isolate); + Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + Zone* zone = tester.zone(); + + ZoneBuffer buffer(zone); + { + TestSignatures sigs; + WasmModuleBuilder builder(zone); + // Type error at i32.add. + builder.AddFunction(sigs.v_v())->Emit(kExprI32Add); + builder.WriteTo(&buffer); + } + + i_isolate->wasm_engine()->TierDownAllModulesPerIsolate(i_isolate); + + tester.OnBytesReceived(buffer.begin(), buffer.size()); + tester.FinishStream(); + tester.RunCompilerTasks(); +} + #undef STREAM_TEST } // namespace wasm diff --git a/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc b/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc index 2d7b4024d7..156bfb55ac 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc @@ -179,16 +179,16 @@ struct WasmValWrapper { #ifdef DEBUG std::ostream& operator<<(std::ostream& out, const WasmValWrapper& wrapper) { switch (wrapper.val.type().kind()) { - case ValueType::kI32: + case kI32: out << "i32: " << wrapper.val.to<int32_t>(); break; - case ValueType::kI64: + case kI64: out << "i64: " << wrapper.val.to<int64_t>(); break; - case ValueType::kF32: + case kF32: out << "f32: " << wrapper.val.to<float>(); break; - case ValueType::kF64: + case kF64: out << "f64: " << wrapper.val.to<double>(); break; default: diff --git a/deps/v8/test/cctest/wasm/test-wasm-serialization.cc b/deps/v8/test/cctest/wasm/test-wasm-serialization.cc index 2a0f441eb7..e23a549ddd 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-serialization.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-serialization.cc @@ -61,14 +61,6 @@ class WasmSerializationTest { memset(const_cast<uint8_t*>(wire_bytes_.data()), 0, wire_bytes_.size() / 2); } - void InvalidateNumFunctions() { - Address num_functions_slot = - reinterpret_cast<Address>(serialized_bytes_.data()) + - WasmSerializer::kHeaderSize; - CHECK_EQ(1, base::ReadUnalignedValue<uint32_t>(num_functions_slot)); - base::WriteUnalignedValue<uint32_t>(num_functions_slot, 0); - } - MaybeHandle<WasmModuleObject> Deserialize( Vector<const char> source_url = {}) { return DeserializeNativeModule(CcTest::i_isolate(), @@ -239,16 +231,6 @@ TEST(DeserializeNoSerializedData) { test.CollectGarbage(); } -TEST(DeserializeInvalidNumFunctions) { - WasmSerializationTest test; - { - HandleScope scope(CcTest::i_isolate()); - test.InvalidateNumFunctions(); - CHECK(test.Deserialize().is_null()); - } - test.CollectGarbage(); -} - TEST(DeserializeWireBytesAndSerializedDataInvalid) { WasmSerializationTest test; { diff --git a/deps/v8/test/cctest/wasm/test-wasm-stack.cc b/deps/v8/test/cctest/wasm/test-wasm-stack.cc index 7ef79a6350..9faab4479e 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-stack.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-stack.cc @@ -196,11 +196,11 @@ WASM_COMPILED_EXEC_TEST(CollectDetailedWasmStack_WasmUrl) { Handle<FixedArray> stack_trace_object = isolate->GetDetailedStackTrace(Handle<JSObject>::cast(exception)); CHECK(!stack_trace_object.is_null()); - Handle<StackTraceFrame> stack_frame = Handle<StackTraceFrame>::cast( - handle(stack_trace_object->get(0), isolate)); + Handle<StackFrameInfo> stack_frame( + StackFrameInfo::cast(stack_trace_object->get(0)), isolate); MaybeHandle<String> maybe_stack_trace_str = - SerializeStackTraceFrame(isolate, stack_frame); + SerializeStackFrameInfo(isolate, stack_frame); CHECK(!maybe_stack_trace_str.is_null()); Handle<String> stack_trace_str = maybe_stack_trace_str.ToHandleChecked(); diff --git a/deps/v8/test/cctest/wasm/wasm-run-utils.cc b/deps/v8/test/cctest/wasm/wasm-run-utils.cc index 2657d7e9a7..82f7824315 100644 --- a/deps/v8/test/cctest/wasm/wasm-run-utils.cc +++ b/deps/v8/test/cctest/wasm/wasm-run-utils.cc @@ -335,6 +335,7 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() { auto native_module = isolate_->wasm_engine()->NewNativeModule( isolate_, enabled_features_, test_module_, code_size_estimate); native_module->SetWireBytes(OwnedVector<const uint8_t>()); + native_module->compilation_state()->set_compilation_id(0); constexpr Vector<const char> kNoSourceUrl{"", 0}; Handle<Script> script = isolate_->wasm_engine()->GetOrCreateScript( isolate_, native_module, kNoSourceUrl); diff --git a/deps/v8/test/cctest/wasm/wasm-run-utils.h b/deps/v8/test/cctest/wasm/wasm-run-utils.h index eeb29acf81..f873390283 100644 --- a/deps/v8/test/cctest/wasm/wasm-run-utils.h +++ b/deps/v8/test/cctest/wasm/wasm-run-utils.h @@ -233,12 +233,16 @@ class TestingModuleBuilder { void SetExecutable() { native_module_->SetExecutable(true); } - void TierDown() { + void SetTieredDown() { native_module_->SetTieringState(kTieredDown); - native_module_->RecompileForTiering(); execution_tier_ = TestExecutionTier::kLiftoff; } + void TierDown() { + SetTieredDown(); + native_module_->RecompileForTiering(); + } + CompilationEnv CreateCompilationEnv(); ExecutionTier execution_tier() const { |