Skip to content

Commit 56048ac

Browse files
committed
[Runtime+IRGen] Fix existential offset for multiple protocol witnesses
1 parent 8b3aaf5 commit 56048ac

File tree

4 files changed

+57
-14
lines changed

4 files changed

+57
-14
lines changed

lib/IRGen/TypeLayout.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ class LayoutStringBuilder {
364364
uint64_t op = (static_cast<uint64_t>(refCounting.kind) << 56) | skip;
365365
B.addInt64(op);
366366
refCountBytes += sizeof(uint64_t);
367-
skip = 0;
367+
skip = refCounting.size - getFixedBufferSize(IGM).getValue();
368368
break;
369369
}
370370

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ static void existentialDestroyBranchless(const Metadata *metadata,
684684
uint8_t *addr) {
685685
OpaqueValue *object = (OpaqueValue *)(addr + addrOffset);
686686
auto* type = getExistentialTypeMetadata(object);
687-
addrOffset += sizeof(uintptr_t) * (NumWords_ValueBuffer + 2);
687+
addrOffset += sizeof(uintptr_t) * NumWords_ValueBuffer;
688688
if (type->getValueWitnesses()->isValueInline()) {
689689
type->vw_destroy(object);
690690
} else {
@@ -918,12 +918,9 @@ static void existentialInitWithCopyBranchless(const Metadata *metadata,
918918
uint8_t *src) {
919919
uintptr_t _addrOffset = addrOffset;
920920
auto *type = getExistentialTypeMetadata((OpaqueValue*)(src + _addrOffset));
921-
auto *witness = *(void**)(src + _addrOffset + ((NumWords_ValueBuffer + 1) * sizeof(uintptr_t)));
922-
memcpy(dest + _addrOffset + (NumWords_ValueBuffer * sizeof(uintptr_t)), &type, sizeof(uintptr_t));
923-
memcpy(dest + _addrOffset + ((NumWords_ValueBuffer + 1) * sizeof(uintptr_t)), &witness, sizeof(uintptr_t));
924921
auto *destObject = (ValueBuffer *)(dest + _addrOffset);
925922
auto *srcObject = (ValueBuffer *)(src + _addrOffset);
926-
addrOffset = _addrOffset + (sizeof(uintptr_t) * (2 + NumWords_ValueBuffer));
923+
addrOffset = _addrOffset + (sizeof(uintptr_t) * NumWords_ValueBuffer);
927924
type->vw_initializeBufferWithCopyOfBuffer(destObject, srcObject);
928925
}
929926

@@ -1062,12 +1059,9 @@ static void existentialInitWithTake(const Metadata *metadata,
10621059
uint8_t *src) {
10631060
uintptr_t _addrOffset = addrOffset;
10641061
auto* type = getExistentialTypeMetadata((OpaqueValue*)(src + addrOffset));
1065-
auto *witness = *(void**)(src + _addrOffset + ((NumWords_ValueBuffer + 1) * sizeof(uintptr_t)));
10661062
auto *destObject = (OpaqueValue *)(dest + _addrOffset);
10671063
auto *srcObject = (OpaqueValue *)(src + _addrOffset);
1068-
memcpy(dest + _addrOffset + (NumWords_ValueBuffer * sizeof(uintptr_t)), &type, sizeof(uintptr_t));
1069-
memcpy(dest + _addrOffset + ((NumWords_ValueBuffer + 1) * sizeof(uintptr_t)), &witness, sizeof(uintptr_t));
1070-
addrOffset = _addrOffset + (sizeof(uintptr_t) * (2 + NumWords_ValueBuffer));
1064+
addrOffset = _addrOffset + (sizeof(uintptr_t) * NumWords_ValueBuffer);
10711065
if (SWIFT_UNLIKELY(!type->getValueWitnesses()->isBitwiseTakable())) {
10721066
type->vw_initializeWithTake(destObject, srcObject);
10731067
}
@@ -1317,12 +1311,9 @@ static void existentialAssignWithCopy(const Metadata *metadata,
13171311
uint8_t *src) {
13181312
uintptr_t _addrOffset = addrOffset;
13191313
auto *type = getExistentialTypeMetadata((OpaqueValue*)(src + _addrOffset));
1320-
auto *witness = *(void**)(src + _addrOffset + ((NumWords_ValueBuffer + 1) * sizeof(uintptr_t)));
1321-
memcpy(dest + _addrOffset + (NumWords_ValueBuffer * sizeof(uintptr_t)), &type, sizeof(uintptr_t));
1322-
memcpy(dest + _addrOffset + ((NumWords_ValueBuffer + 1) * sizeof(uintptr_t)), &witness, sizeof(uintptr_t));
13231314
auto *destObject = (OpaqueValue *)(dest + _addrOffset);
13241315
auto *srcObject = (OpaqueValue *)(src + _addrOffset);
1325-
addrOffset = _addrOffset + (sizeof(uintptr_t) * (2 + NumWords_ValueBuffer));
1316+
addrOffset = _addrOffset + (sizeof(uintptr_t) * NumWords_ValueBuffer);
13261317
if (type->getValueWitnesses()->isValueInline()) {
13271318
type->vw_assignWithCopy(destObject, srcObject);
13281319
} else {

test/Interpreter/Inputs/layout_string_witnesses_types.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,21 @@ public enum Repro {
264264
}
265265
}
266266

267+
public protocol A {}
268+
public protocol B {}
269+
public protocol C {}
270+
271+
public struct MultiProtocolExistentialWrapper {
272+
let x: Int = 0
273+
let y: any (A&B&C)
274+
let z: AnyObject
275+
276+
public init(y: any (A&B&C), z: AnyObject) {
277+
self.y = y
278+
self.z = z
279+
}
280+
}
281+
267282
#if os(macOS)
268283
import Foundation
269284

test/Interpreter/layout_string_witnesses_static.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,43 @@ func testExistentialStructBox() {
293293

294294
testExistentialStructBox()
295295

296+
class ClassWithABC: A, B, C {
297+
deinit {
298+
print("ClassWithABC deinitialized!")
299+
}
300+
}
301+
302+
func testMultiProtocolExistential() {
303+
let ptr = UnsafeMutablePointer<MultiProtocolExistentialWrapper>.allocate(capacity: 1)
304+
305+
do {
306+
let x = ClassWithABC()
307+
testInit(ptr, to: MultiProtocolExistentialWrapper(y: x, z: SimpleClass(x: 23)))
308+
}
309+
310+
do {
311+
let y = ClassWithABC()
312+
313+
// CHECK: Before deinit
314+
print("Before deinit")
315+
316+
// CHECK-NEXT: ClassWithABC deinitialized!
317+
// CHECK-NEXT: SimpleClass deinitialized!
318+
testAssign(ptr, from: MultiProtocolExistentialWrapper(y: y, z: SimpleClass(x: 32)))
319+
}
320+
321+
// CHECK-NEXT: Before deinit
322+
print("Before deinit")
323+
324+
// CHECK-NEXT: ClassWithABC deinitialized!
325+
// CHECK-NEXT: SimpleClass deinitialized!
326+
testDestroy(ptr)
327+
328+
ptr.deallocate()
329+
}
330+
331+
testMultiProtocolExistential()
332+
296333
class ClassWithSomeClassProtocol: SomeClassProtocol {
297334
deinit {
298335
print("ClassWithSomeClassProtocol deinitialized!")

0 commit comments

Comments
 (0)