Skip to content

Commit e6bb7d0

Browse files
committed
[JSC] Do not check Cell / WebAssemblyGCObject types when incoming static type proves it
https://bugs.webkit.org/show_bug.cgi?id=297638 rdar://158734753 Reviewed by Justin Michaud. Now input types are propagated well, and we can easily remove unnecessary cell checks / WebAssemblyGCObject checks based on the proven types of the input value. This patch adds definitelyIsCellOrNull and definitelyIsWasmGCObjectOrNull, and using them to remove unnecessary checks in wasm RefTest / RefCast. * Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp: (JSC::Wasm::BBQJITImpl::BBQJIT::emitRefTestOrCast): * Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp: (JSC::Wasm::OMGIRGenerator::emitRefTestOrCast): * Source/JavaScriptCore/wasm/WasmTypeDefinition.cpp: (JSC::Wasm::Type::definitelyIsCellOrNull const): (JSC::Wasm::Type::definitelyIsWasmGCObjectOrNull const): * Source/JavaScriptCore/wasm/generateWasmOpsHeader.py: Canonical link: https://commits.webkit.org/298961@main
1 parent 4911982 commit e6bb7d0

File tree

4 files changed

+76
-17
lines changed

4 files changed

+76
-17
lines changed

Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,8 +2404,10 @@ void BBQJIT::emitRefTestOrCast(const TypedExpression& typedValue, GPRReg valueGP
24042404
doneCases.append(m_jit.jump());
24052405

24062406
checkObjectCase.link(m_jit);
2407-
failureCases.append(m_jit.branchIfNotCell(valueGPR, DoNotHaveTagRegisters));
2408-
failureCases.append(m_jit.branchIfNotType(valueGPR, JSType::WebAssemblyGCObjectType));
2407+
if (!typedValue.type().definitelyIsCellOrNull())
2408+
failureCases.append(m_jit.branchIfNotCell(valueGPR, DoNotHaveTagRegisters));
2409+
if (!typedValue.type().definitelyIsWasmGCObjectOrNull())
2410+
failureCases.append(m_jit.branchIfNotType(valueGPR, JSType::WebAssemblyGCObjectType));
24092411
break;
24102412
}
24112413
case Wasm::TypeKind::I31ref: {
@@ -2416,8 +2418,10 @@ void BBQJIT::emitRefTestOrCast(const TypedExpression& typedValue, GPRReg valueGP
24162418
}
24172419
case Wasm::TypeKind::Arrayref:
24182420
case Wasm::TypeKind::Structref: {
2419-
failureCases.append(m_jit.branchIfNotCell(valueGPR, DoNotHaveTagRegisters));
2420-
failureCases.append(m_jit.branchIfNotType(valueGPR, JSType::WebAssemblyGCObjectType));
2421+
if (!typedValue.type().definitelyIsCellOrNull())
2422+
failureCases.append(m_jit.branchIfNotCell(valueGPR, DoNotHaveTagRegisters));
2423+
if (!typedValue.type().definitelyIsWasmGCObjectOrNull())
2424+
failureCases.append(m_jit.branchIfNotType(valueGPR, JSType::WebAssemblyGCObjectType));
24212425
m_jit.emitLoadStructure(valueGPR, wasmScratchGPR);
24222426
m_jit.loadPtr(Address(wasmScratchGPR, WebAssemblyGCStructure::offsetOfRTT()), wasmScratchGPR);
24232427
failureCases.append(m_jit.branch8(CCallHelpers::NotEqual, Address(wasmScratchGPR, RTT::offsetOfKind()), TrustedImm32(static_cast<int32_t>(static_cast<TypeKind>(toHeapType) == Wasm::TypeKind::Arrayref ? RTTKind::Array : RTTKind::Struct))));
@@ -2432,9 +2436,10 @@ void BBQJIT::emitRefTestOrCast(const TypedExpression& typedValue, GPRReg valueGP
24322436
m_jit.loadPtr(Address(valueGPR, WebAssemblyFunctionBase::offsetOfRTT()), wasmScratchGPR);
24332437
else {
24342438
// The cell check is only needed for non-functions, as the typechecker does not allow non-Cell values for funcref casts.
2435-
// FIXME: We only need this check if reference has a type that could include non-cells.
2436-
failureCases.append(m_jit.branchIfNotCell(valueGPR, DoNotHaveTagRegisters));
2437-
failureCases.append(m_jit.branchIfNotType(valueGPR, JSType::WebAssemblyGCObjectType));
2439+
if (!typedValue.type().definitelyIsCellOrNull())
2440+
failureCases.append(m_jit.branchIfNotCell(valueGPR, DoNotHaveTagRegisters));
2441+
if (!typedValue.type().definitelyIsWasmGCObjectOrNull())
2442+
failureCases.append(m_jit.branchIfNotType(valueGPR, JSType::WebAssemblyGCObjectType));
24382443
m_jit.emitLoadStructure(valueGPR, wasmScratchGPR);
24392444
m_jit.loadPtr(Address(wasmScratchGPR, WebAssemblyGCStructure::offsetOfRTT()), wasmScratchGPR);
24402445
}

Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3697,9 +3697,12 @@ void OMGIRGenerator::emitRefTestOrCast(CastKind castKind, TypedExpression refere
36973697
endBlock->addPredecessor(m_currentBlock);
36983698

36993699
m_currentBlock = checkObject;
3700-
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, BitAnd, origin(), value, constant(pointerType(), JSValue::NotCellMask)), castFailure, falseBlock);
3701-
Value* jsType = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), value, safeCast<int32_t>(JSCell::typeInfoTypeOffset()));
3702-
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), jsType, constant(Int32, JSType::WebAssemblyGCObjectType)), castFailure, falseBlock);
3700+
if (!reference.type().definitelyIsCellOrNull())
3701+
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, BitAnd, origin(), value, constant(pointerType(), JSValue::NotCellMask)), castFailure, falseBlock);
3702+
if (!reference.type().definitelyIsWasmGCObjectOrNull()) {
3703+
Value* jsType = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), value, safeCast<int32_t>(JSCell::typeInfoTypeOffset()));
3704+
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), jsType, constant(Int32, JSType::WebAssemblyGCObjectType)), castFailure, falseBlock);
3705+
}
37033706
break;
37043707
}
37053708
case Wasm::TypeKind::I31ref: {
@@ -3711,9 +3714,12 @@ void OMGIRGenerator::emitRefTestOrCast(CastKind castKind, TypedExpression refere
37113714
}
37123715
case Wasm::TypeKind::Arrayref:
37133716
case Wasm::TypeKind::Structref: {
3714-
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, BitAnd, origin(), value, constant(pointerType(), JSValue::NotCellMask)), castFailure, falseBlock);
3715-
Value* jsType = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), value, safeCast<int32_t>(JSCell::typeInfoTypeOffset()));
3716-
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), jsType, constant(Int32, JSType::WebAssemblyGCObjectType)), castFailure, falseBlock);
3717+
if (!reference.type().definitelyIsCellOrNull())
3718+
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, BitAnd, origin(), value, constant(pointerType(), JSValue::NotCellMask)), castFailure, falseBlock);
3719+
if (!reference.type().definitelyIsWasmGCObjectOrNull()) {
3720+
Value* jsType = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), value, safeCast<int32_t>(JSCell::typeInfoTypeOffset()));
3721+
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), jsType, constant(Int32, JSType::WebAssemblyGCObjectType)), castFailure, falseBlock);
3722+
}
37173723
Value* rtt = emitLoadRTTFromObject(value);
37183724
emitCheckOrBranchForCast(castKind, emitNotRTTKind(rtt, static_cast<TypeKind>(toHeapType) == Wasm::TypeKind::Arrayref ? RTTKind::Array : RTTKind::Struct), castFailure, falseBlock);
37193725
break;
@@ -3730,10 +3736,12 @@ void OMGIRGenerator::emitRefTestOrCast(CastKind castKind, TypedExpression refere
37303736
rtt = emitLoadRTTFromFuncref(value);
37313737
else {
37323738
// The cell check is only needed for non-functions, as the typechecker does not allow non-Cell values for funcref casts.
3733-
// FIXME: We only need this check if reference has a type that could include non-cells.
3734-
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, BitAnd, origin(), value, constant(Int64, JSValue::NotCellMask)), castFailure, falseBlock);
3735-
Value* jsType = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), value, safeCast<int32_t>(JSCell::typeInfoTypeOffset()));
3736-
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), jsType, constant(Int32, JSType::WebAssemblyGCObjectType)), castFailure, falseBlock);
3739+
if (!reference.type().definitelyIsCellOrNull())
3740+
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, BitAnd, origin(), value, constant(Int64, JSValue::NotCellMask)), castFailure, falseBlock);
3741+
if (!reference.type().definitelyIsWasmGCObjectOrNull()) {
3742+
Value* jsType = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), value, safeCast<int32_t>(JSCell::typeInfoTypeOffset()));
3743+
emitCheckOrBranchForCast(castKind, m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), jsType, constant(Int32, JSType::WebAssemblyGCObjectType)), castFailure, falseBlock);
3744+
}
37373745
rtt = emitLoadRTTFromObject(value);
37383746
}
37393747

Source/JavaScriptCore/wasm/WasmTypeDefinition.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,48 @@ void TypeInformation::tryCleanup()
11761176
} while (changed);
11771177
}
11781178

1179+
bool Type::definitelyIsCellOrNull() const
1180+
{
1181+
if (!isRefType(*this))
1182+
return false;
1183+
1184+
if (typeIndexIsType(index)) {
1185+
switch (static_cast<TypeKind>(index)) {
1186+
case TypeKind::Funcref:
1187+
case TypeKind::Arrayref:
1188+
case TypeKind::Structref:
1189+
case TypeKind::Exn:
1190+
return true;
1191+
default:
1192+
return false;
1193+
}
1194+
}
1195+
return true;
1196+
}
1197+
1198+
bool Type::definitelyIsWasmGCObjectOrNull() const
1199+
{
1200+
if (!isRefType(*this))
1201+
return false;
1202+
1203+
if (typeIndexIsType(index)) {
1204+
switch (static_cast<TypeKind>(index)) {
1205+
case TypeKind::Arrayref:
1206+
case TypeKind::Structref:
1207+
return true;
1208+
default:
1209+
return false;
1210+
}
1211+
}
1212+
1213+
const TypeDefinition& def = TypeInformation::get(index).expand();
1214+
if (def.is<Wasm::StructType>())
1215+
return true;
1216+
if (def.is<Wasm::ArrayType>())
1217+
return true;
1218+
return false;
1219+
}
1220+
11791221
} } // namespace JSC::Wasm
11801222

11811223
WTF_ALLOW_UNSAFE_BUFFER_USAGE_END

Source/JavaScriptCore/wasm/generateWasmOpsHeader.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,10 @@ def atomicMemoryLog2AlignmentGenerator(filter):
276276
return kind == TypeKind::RefNull || kind == TypeKind::Externref || kind == TypeKind::Funcref;
277277
}
278278
279+
// Saying conservatively.
280+
bool definitelyIsCellOrNull() const;
281+
bool definitelyIsWasmGCObjectOrNull() const;
282+
279283
void dump(PrintStream& out) const;
280284
Width width() const;
281285

0 commit comments

Comments
 (0)