@@ -30,6 +30,7 @@ class Evaluator(
3030
3131 private [this ] var stackDepth : Int = 0
3232 private [this ] val maxStack : Int = settings.maxStack
33+ private [sjsonnet] var flameGraphProfiler : FlameGraphProfiler = _
3334
3435 @ inline private [sjsonnet] final def checkStackDepth (pos : Position ): Unit = {
3536 stackDepth += 1
@@ -39,8 +40,24 @@ class Evaluator(
3940 Error .fail(" Max stack frames exceeded." , pos)
4041 }
4142
42- @ inline private [sjsonnet] final def decrementStackDepth (): Unit =
43+ @ inline private [sjsonnet] final def checkStackDepth (pos : Position , expr : Expr ): Unit = {
44+ stackDepth += 1
45+ if (flameGraphProfiler != null ) flameGraphProfiler.push(expr.exprErrorString)
46+ if (stackDepth > maxStack)
47+ Error .fail(" Max stack frames exceeded." , pos)
48+ }
49+
50+ @ inline private [sjsonnet] final def checkStackDepth (pos : Position , name : String ): Unit = {
51+ stackDepth += 1
52+ if (flameGraphProfiler != null ) flameGraphProfiler.push(name)
53+ if (stackDepth > maxStack)
54+ Error .fail(" Max stack frames exceeded." , pos)
55+ }
56+
57+ @ inline private [sjsonnet] final def decrementStackDepth (): Unit = {
4358 stackDepth -= 1
59+ if (flameGraphProfiler != null ) flameGraphProfiler.pop()
60+ }
4461
4562 def materialize (v : Val ): Value = Materializer .apply(v)
4663 val cachedImports : collection.mutable.HashMap [Path , Val ] =
@@ -230,7 +247,7 @@ class Evaluator(
230247 */
231248 protected def visitApply (e : Apply )(implicit scope : ValScope ): Val = {
232249 if (debugStats != null ) debugStats.functionCalls += 1
233- checkStackDepth(e.pos)
250+ checkStackDepth(e.pos, e )
234251 try {
235252 val lhs = visitExpr(e.value)
236253 implicit val tailstrictMode : TailstrictMode =
@@ -246,7 +263,7 @@ class Evaluator(
246263
247264 protected def visitApply0 (e : Apply0 )(implicit scope : ValScope ): Val = {
248265 if (debugStats != null ) debugStats.functionCalls += 1
249- checkStackDepth(e.pos)
266+ checkStackDepth(e.pos, e )
250267 try {
251268 val lhs = visitExpr(e.value)
252269 implicit val tailstrictMode : TailstrictMode =
@@ -261,7 +278,7 @@ class Evaluator(
261278
262279 protected def visitApply1 (e : Apply1 )(implicit scope : ValScope ): Val = {
263280 if (debugStats != null ) debugStats.functionCalls += 1
264- checkStackDepth(e.pos)
281+ checkStackDepth(e.pos, e )
265282 try {
266283 val lhs = visitExpr(e.value)
267284 implicit val tailstrictMode : TailstrictMode =
@@ -277,7 +294,7 @@ class Evaluator(
277294
278295 protected def visitApply2 (e : Apply2 )(implicit scope : ValScope ): Val = {
279296 if (debugStats != null ) debugStats.functionCalls += 1
280- checkStackDepth(e.pos)
297+ checkStackDepth(e.pos, e )
281298 try {
282299 val lhs = visitExpr(e.value)
283300 implicit val tailstrictMode : TailstrictMode =
@@ -295,7 +312,7 @@ class Evaluator(
295312
296313 protected def visitApply3 (e : Apply3 )(implicit scope : ValScope ): Val = {
297314 if (debugStats != null ) debugStats.functionCalls += 1
298- checkStackDepth(e.pos)
315+ checkStackDepth(e.pos, e )
299316 try {
300317 val lhs = visitExpr(e.value)
301318 implicit val tailstrictMode : TailstrictMode =
@@ -316,7 +333,7 @@ class Evaluator(
316333
317334 protected def visitApplyBuiltin0 (e : ApplyBuiltin0 ): Val = {
318335 if (debugStats != null ) debugStats.builtinCalls += 1
319- checkStackDepth(e.pos)
336+ checkStackDepth(e.pos, e )
320337 try {
321338 val result = e.func.evalRhs(this , e.pos)
322339 if (e.tailstrict) TailCall .resolve(result) else result
@@ -325,7 +342,7 @@ class Evaluator(
325342
326343 protected def visitApplyBuiltin1 (e : ApplyBuiltin1 )(implicit scope : ValScope ): Val = {
327344 if (debugStats != null ) debugStats.builtinCalls += 1
328- checkStackDepth(e.pos)
345+ checkStackDepth(e.pos, e )
329346 try {
330347 if (e.tailstrict) {
331348 TailCall .resolve(e.func.evalRhs(visitExpr(e.a1), this , e.pos))
@@ -337,7 +354,7 @@ class Evaluator(
337354
338355 protected def visitApplyBuiltin2 (e : ApplyBuiltin2 )(implicit scope : ValScope ): Val = {
339356 if (debugStats != null ) debugStats.builtinCalls += 1
340- checkStackDepth(e.pos)
357+ checkStackDepth(e.pos, e )
341358 try {
342359 if (e.tailstrict) {
343360 TailCall .resolve(e.func.evalRhs(visitExpr(e.a1), visitExpr(e.a2), this , e.pos))
@@ -349,7 +366,7 @@ class Evaluator(
349366
350367 protected def visitApplyBuiltin3 (e : ApplyBuiltin3 )(implicit scope : ValScope ): Val = {
351368 if (debugStats != null ) debugStats.builtinCalls += 1
352- checkStackDepth(e.pos)
369+ checkStackDepth(e.pos, e )
353370 try {
354371 if (e.tailstrict) {
355372 TailCall .resolve(
@@ -363,7 +380,7 @@ class Evaluator(
363380
364381 protected def visitApplyBuiltin4 (e : ApplyBuiltin4 )(implicit scope : ValScope ): Val = {
365382 if (debugStats != null ) debugStats.builtinCalls += 1
366- checkStackDepth(e.pos)
383+ checkStackDepth(e.pos, e )
367384 try {
368385 if (e.tailstrict) {
369386 TailCall .resolve(
@@ -391,7 +408,7 @@ class Evaluator(
391408
392409 protected def visitApplyBuiltin (e : ApplyBuiltin )(implicit scope : ValScope ): Val = {
393410 if (debugStats != null ) debugStats.builtinCalls += 1
394- checkStackDepth(e.pos)
411+ checkStackDepth(e.pos, e )
395412 try {
396413 val arr = new Array [Eval ](e.argExprs.length)
397414 var idx = 0
@@ -504,7 +521,7 @@ class Evaluator(
504521 cachedImports.getOrElseUpdate(
505522 p, {
506523 if (debugStats != null ) debugStats.importCalls += 1
507- checkStackDepth(e.pos)
524+ checkStackDepth(e.pos, e )
508525 try {
509526 val doc = resolver.parse(p, str) match {
510527 case Right ((expr, _)) => expr
@@ -732,7 +749,7 @@ class Evaluator(
732749 def evalRhs (vs : ValScope , es : EvalScope , fs : FileScope , pos : Position ): Val =
733750 visitExprWithTailCallSupport(rhs)(vs)
734751 override def evalDefault (expr : Expr , vs : ValScope , es : EvalScope ): Val = {
735- checkStackDepth(expr.pos)
752+ checkStackDepth(expr.pos, " default " )
736753 try visitExpr(expr)(vs)
737754 finally decrementStackDepth()
738755 }
@@ -923,9 +940,10 @@ class Evaluator(
923940 case Member .Field (offset, fieldName, plus, null , sep, rhs) =>
924941 val k = visitFieldName(fieldName, offset)
925942 if (k != null ) {
943+ val fieldKey = k
926944 val v = new Val .Obj .Member (plus, sep) {
927945 def invoke (self : Val .Obj , sup : Val .Obj , fs : FileScope , ev : EvalScope ): Val = {
928- checkStackDepth(rhs.pos)
946+ checkStackDepth(rhs.pos, fieldKey )
929947 try visitExpr(rhs)(makeNewScope(self, sup))
930948 finally decrementStackDepth()
931949 }
@@ -938,9 +956,10 @@ class Evaluator(
938956 case Member .Field (offset, fieldName, false , argSpec, sep, rhs) =>
939957 val k = visitFieldName(fieldName, offset)
940958 if (k != null ) {
959+ val fieldKey = k
941960 val v = new Val .Obj .Member (false , sep) {
942961 def invoke (self : Val .Obj , sup : Val .Obj , fs : FileScope , ev : EvalScope ): Val = {
943- checkStackDepth(rhs.pos)
962+ checkStackDepth(rhs.pos, fieldKey )
944963 try visitMethod(rhs, argSpec, offset)(makeNewScope(self, sup))
945964 finally decrementStackDepth()
946965 }
@@ -982,7 +1001,7 @@ class Evaluator(
9821001 k,
9831002 new Val .Obj .Member (e.plus, Visibility .Normal , deprecatedSkipAsserts = true ) {
9841003 def invoke (self : Val .Obj , sup : Val .Obj , fs : FileScope , ev : EvalScope ): Val = {
985- checkStackDepth(e.value.pos)
1004+ checkStackDepth(e.value.pos, " object comprehension " )
9861005 try {
9871006 lazy val newScope : ValScope = s.extend(newBindings, self, sup)
9881007 lazy val newBindings = visitBindings(binds, newScope)
0 commit comments