Skip to content

Commit deee314

Browse files
committed
Python/Ruby: Optimize join-order in TypeTracker::[small]step
1 parent 05f3934 commit deee314

File tree

2 files changed

+320
-20
lines changed

2 files changed

+320
-20
lines changed

python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll

Lines changed: 160 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,74 @@ private module Cached {
224224

225225
private import Cached
226226

227+
pragma[nomagic]
228+
private predicate stepNoCallProj(TypeTrackingNode nodeFrom, StepSummary summary) {
229+
stepNoCall(nodeFrom, _, summary)
230+
}
231+
232+
bindingset[nodeFrom, t]
233+
pragma[inline_late]
234+
pragma[noopt]
235+
private TypeTracker stepNoCallInlineLate(
236+
TypeTracker t, TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo
237+
) {
238+
exists(StepSummary summary |
239+
stepNoCallProj(nodeFrom, summary) and
240+
result = t.append(summary) and
241+
stepNoCall(nodeFrom, nodeTo, summary)
242+
)
243+
}
244+
245+
pragma[nomagic]
246+
private predicate stepCallProj(TypeTrackingNode nodeFrom, StepSummary summary) {
247+
stepCall(nodeFrom, _, summary)
248+
}
249+
250+
bindingset[nodeFrom, t]
251+
pragma[inline_late]
252+
pragma[noopt]
253+
private TypeTracker stepCallInlineLate(
254+
TypeTracker t, TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo
255+
) {
256+
exists(StepSummary summary |
257+
stepCallProj(nodeFrom, summary) and
258+
result = t.append(summary) and
259+
stepCall(nodeFrom, nodeTo, summary)
260+
)
261+
}
262+
263+
pragma[nomagic]
264+
private predicate smallstepNoCallProj(Node nodeFrom, StepSummary summary) {
265+
smallstepNoCall(nodeFrom, _, summary)
266+
}
267+
268+
bindingset[nodeFrom, t]
269+
pragma[inline_late]
270+
pragma[noopt]
271+
private TypeTracker smallstepNoCallInlineLate(TypeTracker t, Node nodeFrom, Node nodeTo) {
272+
exists(StepSummary summary |
273+
smallstepNoCallProj(nodeFrom, summary) and
274+
result = t.append(summary) and
275+
smallstepNoCall(nodeFrom, nodeTo, summary)
276+
)
277+
}
278+
279+
pragma[nomagic]
280+
private predicate smallstepCallProj(Node nodeFrom, StepSummary summary) {
281+
smallstepCall(nodeFrom, _, summary)
282+
}
283+
284+
bindingset[nodeFrom, t]
285+
pragma[inline_late]
286+
pragma[noopt]
287+
private TypeTracker smallstepCallInlineLate(TypeTracker t, Node nodeFrom, Node nodeTo) {
288+
exists(StepSummary summary |
289+
smallstepCallProj(nodeFrom, summary) and
290+
result = t.append(summary) and
291+
smallstepCall(nodeFrom, nodeTo, summary)
292+
)
293+
}
294+
227295
/**
228296
* Holds if `nodeFrom` is being written to the `content` of the object in `nodeTo`.
229297
*
@@ -296,6 +364,24 @@ class StepSummary extends TStepSummary {
296364

297365
/** Provides predicates for updating step summaries (`StepSummary`s). */
298366
module StepSummary {
367+
/**
368+
* Gets the summary that corresponds to having taken a forwards
369+
* inter-procedural step from `nodeFrom` to `nodeTo`.
370+
*
371+
* This predicate should normally not be used; consider using `step`
372+
* instead.
373+
*/
374+
predicate stepCall = Cached::stepCall/3;
375+
376+
/**
377+
* Gets the summary that corresponds to having taken a forwards
378+
* intra-procedural step from `nodeFrom` to `nodeTo`.
379+
*
380+
* This predicate should normally not be used; consider using `step`
381+
* instead.
382+
*/
383+
predicate stepNoCall = Cached::stepNoCall/3;
384+
299385
/**
300386
* Gets the summary that corresponds to having taken a forwards
301387
* heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
@@ -313,6 +399,24 @@ module StepSummary {
313399
stepCall(nodeFrom, nodeTo, summary)
314400
}
315401

402+
/**
403+
* Gets the summary that corresponds to having taken a forwards
404+
* inter-procedural step from `nodeFrom` to `nodeTo`.
405+
*
406+
* This predicate should normally not be used; consider using `step`
407+
* instead.
408+
*/
409+
predicate smallstepNoCall = Cached::smallstepNoCall/3;
410+
411+
/**
412+
* Gets the summary that corresponds to having taken a forwards
413+
* intra-procedural step from `nodeFrom` to `nodeTo`.
414+
*
415+
* This predicate should normally not be used; consider using `step`
416+
* instead.
417+
*/
418+
predicate smallstepCall = Cached::smallstepCall/3;
419+
316420
/**
317421
* Gets the summary that corresponds to having taken a forwards
318422
* local, heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
@@ -425,16 +529,66 @@ class TypeTracker extends TTypeTracker {
425529
*/
426530
TypeTracker continue() { content = noContent() and result = this }
427531

532+
/**
533+
* Gets the summary that corresponds to having taken a forwards
534+
* intra-procedural step from `nodeFrom` to `nodeTo`.
535+
*
536+
* This predicate should normally not be used; consider using `step`
537+
* instead.
538+
*/
539+
pragma[inline]
540+
TypeTracker stepNoCall(TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo) {
541+
result = stepNoCallInlineLate(this, nodeFrom, nodeTo)
542+
}
543+
544+
/**
545+
* Gets the summary that corresponds to having taken a forwards
546+
* inter-procedural step from `nodeFrom` to `nodeTo`.
547+
*
548+
* This predicate should normally not be used; consider using `step`
549+
* instead.
550+
*/
551+
pragma[inline]
552+
TypeTracker stepCall(TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo) {
553+
result = stepCallInlineLate(this, nodeFrom, nodeTo)
554+
}
555+
428556
/**
429557
* Gets the summary that corresponds to having taken a forwards
430558
* heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
431559
*/
432560
pragma[inline]
433561
TypeTracker step(TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo) {
434-
exists(StepSummary summary |
435-
StepSummary::step(nodeFrom, pragma[only_bind_out](nodeTo), pragma[only_bind_into](summary)) and
436-
result = this.append(pragma[only_bind_into](summary))
437-
)
562+
result = this.stepNoCall(nodeFrom, nodeTo)
563+
or
564+
result = this.stepCall(nodeFrom, nodeTo)
565+
}
566+
567+
/**
568+
* Gets the summary that corresponds to having taken a forwards
569+
* intra-procedural step from `nodeFrom` to `nodeTo`.
570+
*
571+
* This predicate should normally not be used; consider using `step`
572+
* instead.
573+
*/
574+
pragma[inline]
575+
TypeTracker smallstepNoCall(Node nodeFrom, Node nodeTo) {
576+
result = smallstepNoCallInlineLate(this, nodeFrom, nodeTo)
577+
or
578+
simpleLocalFlowStep(nodeFrom, nodeTo) and
579+
result = this
580+
}
581+
582+
/**
583+
* Gets the summary that corresponds to having taken a forwards
584+
* inter-procedural step from `nodeFrom` to `nodeTo`.
585+
*
586+
* This predicate should normally not be used; consider using `step`
587+
* instead.
588+
*/
589+
pragma[inline]
590+
TypeTracker smallstepCall(Node nodeFrom, Node nodeTo) {
591+
result = smallstepCallInlineLate(this, nodeFrom, nodeTo)
438592
}
439593

440594
/**
@@ -463,13 +617,9 @@ class TypeTracker extends TTypeTracker {
463617
*/
464618
pragma[inline]
465619
TypeTracker smallstep(Node nodeFrom, Node nodeTo) {
466-
exists(StepSummary summary |
467-
StepSummary::smallstep(nodeFrom, nodeTo, summary) and
468-
result = this.append(summary)
469-
)
620+
result = this.smallstepNoCall(nodeFrom, nodeTo)
470621
or
471-
simpleLocalFlowStep(nodeFrom, nodeTo) and
472-
result = this
622+
result = this.smallstepCall(nodeFrom, nodeTo)
473623
}
474624
}
475625

0 commit comments

Comments
 (0)