@@ -731,6 +731,32 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
731731 }
732732 }
733733
734+ struct ConstSlots {
735+ private( set) var values : [ UntypedValue ]
736+ private var indexByValue : [ UntypedValue : Int ]
737+ let stackLayout : StackLayout
738+
739+ init ( stackLayout: StackLayout ) {
740+ self . values = [ ]
741+ self . indexByValue = [ : ]
742+ self . stackLayout = stackLayout
743+ }
744+
745+ mutating func allocate( _ value: Value ) -> Int ? {
746+ let untyped = UntypedValue ( value)
747+ if let allocated = indexByValue [ untyped] {
748+ // NOTE: Share the same const slot for exactly the same bit pattern
749+ // values even having different types
750+ return allocated
751+ }
752+ guard values. count < stackLayout. constantSlotSize else { return nil }
753+ let constSlotIndex = values. count
754+ values. append ( untyped)
755+ indexByValue [ untyped] = constSlotIndex
756+ return constSlotIndex
757+ }
758+ }
759+
734760 let allocator : ISeqAllocator
735761 let funcTypeInterner : Interner < FunctionType >
736762 let module : Context
@@ -744,7 +770,7 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
744770 let functionIndex : FunctionIndex
745771 /// Whether a call to this function should be intercepted
746772 let intercepting : Bool
747- var constantSlots : [ UntypedValue ]
773+ var constantSlots : ConstSlots
748774
749775 init (
750776 allocator: ISeqAllocator ,
@@ -767,7 +793,7 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
767793 self . locals = Locals ( types: type. parameters + locals)
768794 self . functionIndex = functionIndex
769795 self . intercepting = intercepting
770- self . constantSlots = [ ]
796+ self . constantSlots = ConstSlots ( stackLayout : stackLayout )
771797
772798 do {
773799 let endLabel = self . iseqBuilder. allocLabel ( )
@@ -944,7 +970,7 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
944970 for (idx, instruction) in instructions. enumerated ( ) {
945971 buffer [ idx] = instruction
946972 }
947- let constants = allocator. allocateConstants ( self . constantSlots)
973+ let constants = allocator. allocateConstants ( self . constantSlots. values )
948974 return InstructionSequence (
949975 instructions: buffer,
950976 maxStackHeight: Int ( valueStack. stackRegBase) + valueStack. maxHeight,
@@ -1563,15 +1589,8 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
15631589 }
15641590 }
15651591
1566- private mutating func allocateConstSlot( _ type: ValueType , _ value: Value ) -> Int ? {
1567- guard constantSlots. count < stackLayout. constantSlotSize else { return nil }
1568- let constSlotIndex = constantSlots. count
1569- constantSlots. append ( UntypedValue ( value) )
1570- return constSlotIndex
1571- }
1572-
15731592 private mutating func visitConst( _ type: ValueType , _ value: Value ) {
1574- if let constSlotIndex = allocateConstSlot ( type , value) {
1593+ if let constSlotIndex = constantSlots . allocate ( value) {
15751594 valueStack. pushConst ( constSlotIndex, type: type)
15761595 return
15771596 }
0 commit comments