1
1
// This file is a part of Julia. License is MIT: https://julialang.org/license
2
2
3
3
// Assumptions for pinning:
4
- // * args need to be pinned
5
- // * JL_ROOTING_ARGUMENT and JL_ROOTED_ARGUMENT will propagate pinning state as well.
6
4
// * The checker may not consider alias for derived pointers in some cases.
7
5
// * if f(x) returns a derived pointer from x, a = f(x); b = f(x); PTR_PIN(a); The checker will NOT find b as pinned.
8
6
// * a = x->y; b = x->y; PTR_PIN(a); The checker will find b as pinned.
@@ -49,7 +47,7 @@ static const Stmt *getStmtForDiagnostics(const ExplodedNode *N)
49
47
}
50
48
51
49
// Turn on/off the log here
52
- #define DEBUG_LOG 1
50
+ #define DEBUG_LOG 0
53
51
54
52
class GCChecker
55
53
: public Checker<
@@ -175,6 +173,9 @@ class GCChecker
175
173
} else if (parent.isPinned ()) {
176
174
// If parent is pinned, the child is not pinned.
177
175
return getNotPinned (parent);
176
+ } else if (parent.isMoved ()) {
177
+ // If parent is moved, the child is not pinned.
178
+ return getNotPinned (parent);
178
179
} else {
179
180
// For other cases, the children have the same state as the parent.
180
181
return parent;
@@ -200,19 +201,20 @@ class GCChecker
200
201
const ParmVarDecl *PVD) {
201
202
bool isFunctionSafepoint = !isFDAnnotatedNotSafepoint (FD);
202
203
bool maybeUnrooted = declHasAnnotation (PVD, " julia_maybe_unrooted" );
203
- bool maybeUnpinned = declHasAnnotation (PVD, " julia_maybe_unpinned" );
204
- if (!isFunctionSafepoint || maybeUnrooted || maybeUnpinned) {
204
+ if (!isFunctionSafepoint || maybeUnrooted) {
205
205
ValueState VS = getAllocated ();
206
206
VS.PVD = PVD;
207
207
VS.FD = FD;
208
208
return VS;
209
209
}
210
210
bool require_tpin = declHasAnnotation (PVD, " julia_require_tpin" );
211
+ bool require_pin = declHasAnnotation (PVD, " julia_require_pin" );
211
212
if (require_tpin) {
212
213
return getRooted (nullptr , ValueState::TransitivelyPinned, -1 );
213
- } else {
214
- // Assume arguments are pinned
214
+ } else if (require_pin) {
215
215
return getRooted (nullptr , ValueState::Pinned, -1 );
216
+ } else {
217
+ return getRooted (nullptr , ValueState::NotPinned, -1 );
216
218
}
217
219
}
218
220
};
@@ -345,6 +347,7 @@ class GCChecker
345
347
void validateValue (const GCChecker::ValueState* VS, CheckerContext &C, SymbolRef Sym, const char *message) const ;
346
348
void validateValueRootnessOnly (const GCChecker::ValueState* VS, CheckerContext &C, SymbolRef Sym, const char *message) const ;
347
349
void validateValue (const GCChecker::ValueState* VS, CheckerContext &C, SymbolRef Sym, const char *message, SourceRange range) const ;
350
+ void validateValueRootnessOnly (const GCChecker::ValueState* VS, CheckerContext &C, SymbolRef Sym, const char *message, SourceRange range) const ;
348
351
int validateValueInner (const GCChecker::ValueState* VS) const ;
349
352
GCChecker::ValueState getRootedFromRegion (const MemRegion *Region, const PinState *PS, int Depth) const ;
350
353
template <typename T>
@@ -481,6 +484,15 @@ static const VarRegion *walk_back_to_global_VR(const MemRegion *Region) {
481
484
#define FREED 1
482
485
#define MOVED 2
483
486
487
+ void GCChecker::validateValueRootnessOnly (const ValueState* VS, CheckerContext &C, SymbolRef Sym, const char *message, SourceRange range) const {
488
+ int v = validateValueInner (VS);
489
+ if (v == FREED) {
490
+ GCChecker::report_value_error (C, Sym, (std::string (message) + " GCed" ).c_str (), range);
491
+ } else if (v == MOVED) {
492
+ // We don't care if it is moved
493
+ }
494
+ }
495
+
484
496
void GCChecker::validateValue (const ValueState* VS, CheckerContext &C, SymbolRef Sym, const char *message, SourceRange range) const {
485
497
int v = validateValueInner (VS);
486
498
if (v == FREED) {
@@ -1139,10 +1151,10 @@ bool GCChecker::processPotentialSafepoint(const CallEvent &Call,
1139
1151
// Symbolically move all unpinned values.
1140
1152
GCValueMapTy AMap2 = State->get <GCValueMap>();
1141
1153
for (auto I = AMap2.begin (), E = AMap2.end (); I != E; ++I) {
1154
+ logWithDump (" - check Sym" , I.getKey ());
1142
1155
if (RetSym == I.getKey ())
1143
1156
continue ;
1144
1157
if (I.getData ().isNotPinned ()) {
1145
- logWithDump (" - move unpinned values, Sym" , I.getKey ());
1146
1158
logWithDump (" - move unpinned values, VS" , I.getData ());
1147
1159
auto NewVS = ValueState::getMoved (I.getData ());
1148
1160
State = State->set <GCValueMap>(I.getKey (), NewVS);
@@ -1195,9 +1207,9 @@ bool GCChecker::processArgumentRooting(const CallEvent &Call, CheckerContext &C,
1195
1207
const ValueState *CurrentVState = State->get <GCValueMap>(RootedSymbol);
1196
1208
ValueState NewVState = *OldVState;
1197
1209
// If the old state is pinned, the new state is not pinned.
1198
- if (OldVState->isPinned () && ((CurrentVState && !CurrentVState->isPinnedByAnyway ()) || !CurrentVState)) {
1199
- NewVState = ValueState::getNotPinned (*OldVState);
1200
- }
1210
+ // if (OldVState->isPinned() && ((CurrentVState && !CurrentVState->isPinnedByAnyway()) || !CurrentVState)) {
1211
+ // NewVState = ValueState::getNotPinned(*OldVState);
1212
+ // }
1201
1213
logWithDump (" - Rooted set to" , NewVState);
1202
1214
State = State->set <GCValueMap>(RootedSymbol, NewVState);
1203
1215
return true ;
@@ -1633,23 +1645,16 @@ void GCChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
1633
1645
range);
1634
1646
}
1635
1647
}
1636
- if (ValState->isNotPinned ()) {
1637
- bool MaybeUnpinned = false ;
1638
- if (FD) {
1639
- if (idx < FD->getNumParams ()) {
1640
- MaybeUnpinned =
1641
- declHasAnnotation (FD->getParamDecl (idx), " julia_maybe_unpinned" );
1642
- }
1643
- }
1644
- if (!MaybeUnpinned && isCalleeSafepoint) {
1645
- report_value_error (C, Sym, " Passing non-pinned value as argument to function that may GC" , range);
1646
- }
1647
- }
1648
1648
if (FD && idx < FD->getNumParams () && declHasAnnotation (FD->getParamDecl (idx), " julia_require_tpin" )) {
1649
1649
if (!ValState->isTransitivelyPinned ()) {
1650
1650
report_value_error (C, Sym, " Passing non-tpinned argument to function that requires a tpin argument." );
1651
1651
}
1652
1652
}
1653
+ if (FD && idx < FD->getNumParams () && declHasAnnotation (FD->getParamDecl (idx), " julia_require_pin" )) {
1654
+ if (!ValState->isPinnedByAnyway ()) {
1655
+ report_value_error (C, Sym, " Passing non-pinned argument to function that requires a pin argument." );
1656
+ }
1657
+ }
1653
1658
}
1654
1659
}
1655
1660
@@ -1810,6 +1815,7 @@ bool GCChecker::evalCall(const CallEvent &Call, CheckerContext &C) const {
1810
1815
}
1811
1816
1812
1817
const ValueState *OldVS = C.getState ()->get <GCValueMap>(Sym);
1818
+ logWithDump (" - PTR_PIN OldVS" , OldVS);
1813
1819
if (OldVS && OldVS->isMoved ()) {
1814
1820
report_error (C, " Attempt to PIN a value that is already moved." );
1815
1821
return true ;
0 commit comments