From 9b0cd8c4bba267ccebba51ba3fe388ef33e90327 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Thu, 1 Oct 2026 18:54:09 -0500 Subject: [PATCH] Skip checked enum inits in cycle() hot path The generated checked initializers for raw representable enums are too big to be inlined into the large `cycle()` function. Since the only values used in `cycle()` are raw values generated from cases in the first place, and these enums have raw case values that match the enum tag, it's safe to bitcast from the raw value to the enum type instead. This change adds a function to convert a raw value to an enum case, asserting in debug mode if the constructed case is invalid. --- .../_StringProcessing/Engine/InstPayload.swift | 8 +++----- .../_StringProcessing/Engine/Instruction.swift | 6 +++--- Sources/_StringProcessing/Utility/Misc.swift | 16 +++++++++++++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Sources/_StringProcessing/Engine/InstPayload.swift b/Sources/_StringProcessing/Engine/InstPayload.swift index 550fa4915..0a4df998c 100644 --- a/Sources/_StringProcessing/Engine/InstPayload.swift +++ b/Sources/_StringProcessing/Engine/InstPayload.swift @@ -552,7 +552,7 @@ struct QuantifyPayload: RawRepresentable { } var builtinCC: _CharacterClassModel.Representation { - _CharacterClassModel.Representation(rawValue: self.rawValue & 0xFF)! + _uncheckedRawEnum(self.rawValue & 0xFF) } var builtinIsInverted: Bool { (self.rawValue >> 9) & 1 == 1 @@ -596,8 +596,7 @@ struct CharacterClassPayload: RawRepresentable { self.rawValue & CharacterClassPayload.scalarBit != 0 } var cc: _CharacterClassModel.Representation { - _CharacterClassModel.Representation.init( - rawValue: self.rawValue & CharacterClassPayload.ccMask).unsafelyUnwrapped + _uncheckedRawEnum(self.rawValue & CharacterClassPayload.ccMask) } } @@ -636,8 +635,7 @@ struct AssertionPayload: RawRepresentable { } var kind: DSLTree.Atom.Assertion { - return .init( - rawValue: self.rawValue & AssertionPayload.assertionKindMask).unsafelyUnwrapped + _uncheckedRawEnum(self.rawValue & AssertionPayload.assertionKindMask) } var anchorsMatchNewlines: Bool { self.rawValue & AssertionPayload.anchorBit != 0 } var usesSimpleUnicodeBoundaries: Bool { diff --git a/Sources/_StringProcessing/Engine/Instruction.swift b/Sources/_StringProcessing/Engine/Instruction.swift index 80bfd9b05..66416106d 100644 --- a/Sources/_StringProcessing/Engine/Instruction.swift +++ b/Sources/_StringProcessing/Engine/Instruction.swift @@ -279,9 +279,9 @@ extension Instruction { var opcode: OpCode { get { - OpCode( - rawValue: (rawValue & _opcodeMask) &>> 56 - ).unsafelyUnwrapped + // Every instruction is built from a real case, with the payload inside 56 bits, + // so the opcode byte is always a valid case index. + _uncheckedRawEnum(rawValue &>> 56) } set { assert(newValue != .invalid, "consider hoisting this") diff --git a/Sources/_StringProcessing/Utility/Misc.swift b/Sources/_StringProcessing/Utility/Misc.swift index d63370b55..749288672 100644 --- a/Sources/_StringProcessing/Utility/Misc.swift +++ b/Sources/_StringProcessing/Utility/Misc.swift @@ -76,4 +76,18 @@ extension String { } } - +/// Converts a raw value into a single-byte enum without going through +/// its checked initializer. +/// +/// - Precondition: `rawValue` is the raw value of a case of `T`, and `T` is +/// a no-payload enum laid out as a single byte. +@inline(__always) +//@unsafe +internal func _uncheckedRawEnum( + _ rawValue: UInt64, as _: T.Type = T.self +) -> T where T.RawValue == UInt64 { + let result = unsafeBitCast(UInt8(truncatingIfNeeded: rawValue), to: T.self) + assert(result.rawValue == rawValue, + "\(T.self) is no longer laid out as its contiguous case index") + return result +}