Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit b621ffb

Browse files
committed
Start to use object.destroy + GC.addrOf
1 parent 78508ef commit b621ffb

1 file changed

Lines changed: 39 additions & 27 deletions

File tree

src/core/memory.d

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -944,8 +944,8 @@ performs the following actions in sequence:
944944
$(UL
945945
$(LI
946946
Calls `.object.destroy(x)` (if `x` is a class or interface object) or
947-
`typeid(*x).destroy(x)` (if `x` is pointer to a struct) to destroy the referred entity.
948-
Arrays of structs call `typeid(*x).destroy(x)` for each element.
947+
`(*x).__xdtor()` (if `x` is pointer to a struct and a custom destructor exists) to destroy the referred entity.
948+
Arrays of structs with a custom destructor call `x.__xdtor()` for each element in the array.
949949
)
950950
$(LI
951951
Frees the memory allocated for `x`. If `x` is a reference to a class
@@ -968,34 +968,48 @@ See_Also: $(REF destroy, object), $(REF free, core,GC)
968968
*/
969969
void __delete(T)(ref T x) @system
970970
{
971+
static void _destructRecurse(S)(ref S s)
972+
if (is(S == struct))
973+
{
974+
static if (__traits(hasMember, S, "__xdtor") &&
975+
// Bugzilla 14746: Check that it's the exact member of S.
976+
__traits(isSame, S, __traits(parent, s.__xdtor)))
977+
s.__xdtor();
978+
}
979+
971980
// See also: https://github.com/dlang/dmd/blob/v2.078.0/src/dmd/e2ir.d#L3886
972981
static if (is(T == interface))
973982
{
974-
(cast(Object) x).destroy;
983+
.object.destroy(x);
975984
}
976985
else static if (is(T == class))
977986
{
978-
(cast(Object) x).destroy;
987+
.object.destroy(x);
979988
}
980989
else static if (is(T == U*, U))
981990
{
982991
static if (is(U == struct))
983-
typeid(U).destroy(x);
992+
_destructRecurse(*x);
984993
}
985994
else static if (is(T : E[], E))
986995
{
987996
static if (is(E == struct))
988997
{
989998
foreach (ref e; x)
990-
typeid(E).destroy(&e);
999+
_destructRecurse(e);
9911000
}
9921001
}
9931002
else
9941003
{
9951004
static assert(0, "It is not possible to delete: `" ~ T.stringof ~ "`");
9961005
}
9971006

998-
static if (is(T == interface) || is(T == class) || is(T == U2*, U2) || is(T : E2[], E2))
1007+
static if (is(T == interface) || is(T == class))
1008+
{
1009+
GC.free(cast(void*) x);
1010+
x = null;
1011+
}
1012+
else static if (is(T == U2*, U2) || is(T : E2[], E2))
9991013
{
10001014
GC.free(&x);
10011015
x = null;
@@ -1018,11 +1032,14 @@ unittest
10181032
B a = b;
10191033
b.test = 10;
10201034

1035+
assert(GC.addrOf(cast(void*) b) != null);
10211036
__delete(b);
10221037
assert(b is null);
10231038
assert(dtorCalled);
1039+
assert(GC.addrOf(cast(void*) b) == null);
10241040
// but be careful, a still points to it
10251041
assert(a !is null);
1042+
assert(GC.addrOf(cast(void*) a) !is null);
10261043
}
10271044

10281045
/// Deleting interfaces
@@ -1049,9 +1066,11 @@ unittest
10491066
A a = new B();
10501067
a.quack();
10511068

1069+
assert(GC.addrOf(cast(void*) a) != null);
10521070
__delete(a);
10531071
assert(a is null);
10541072
assert(dtorCalled);
1073+
assert(GC.addrOf(cast(void*) a) == null);
10551074
}
10561075

10571076
/// Deleting structs
@@ -1067,39 +1086,27 @@ unittest
10671086
}
10681087
}
10691088
auto a = new A("foo");
1070-
__delete(a);
10711089

1090+
assert(GC.addrOf(cast(void*) a) != null);
1091+
__delete(a);
10721092
assert(a is null);
10731093
assert(dtorCalled);
1094+
assert(GC.addrOf(cast(void*) a) == null);
10741095
}
10751096

10761097
/// Deleting arrays
10771098
unittest
10781099
{
10791100
int[] a = [1, 2, 3];
10801101
auto b = a;
1081-
__delete(b);
1082-
assert(b is null);
1083-
}
10841102

1085-
/// Deleting pointers
1086-
unittest
1087-
{
1088-
bool dtorCalled;
1089-
class A
1090-
{
1091-
string test;
1092-
~this()
1093-
{
1094-
dtorCalled = true;
1095-
}
1096-
}
1097-
A a = new A();
1098-
a.test = "exists";
1099-
auto b = &a;
1103+
assert(GC.addrOf(b.ptr) != null);
11001104
__delete(b);
11011105
assert(b is null);
1102-
assert(!dtorCalled);
1106+
assert(GC.addrOf(b.ptr) == null);
1107+
// but be careful, a still points to it
1108+
assert(a !is null);
1109+
assert(GC.addrOf(a.ptr) !is null);
11031110
}
11041111

11051112
/// Deleting arrays of structs
@@ -1115,17 +1122,22 @@ unittest
11151122
}
11161123
}
11171124
auto arr = [A(1), A(2), A(3)];
1125+
1126+
assert(GC.addrOf(arr.ptr) != null);
11181127
__delete(arr);
11191128
assert(dtorCalled == 3);
1129+
assert(GC.addrOf(arr.ptr) == null);
11201130
}
11211131

11221132
// Deleting raw memory
11231133
unittest
11241134
{
11251135
import core.memory : GC;
11261136
auto a = GC.malloc(5);
1137+
assert(GC.addrOf(cast(void*) a) != null);
11271138
__delete(a);
11281139
assert(a is null);
1140+
assert(GC.addrOf(cast(void*) a) == null);
11291141
}
11301142

11311143
// __delete returns with no effect if x is null

0 commit comments

Comments
 (0)