@@ -127,8 +127,13 @@ static bool EvalContextClassPut(EvalContext *ctx, const char *ns, const char *na
127127static const char * EvalContextCurrentNamespace (const EvalContext * ctx );
128128static ClassRef IDRefQualify (const EvalContext * ctx , const char * id );
129129
130- static EventFrame * EventFrameCreate (char * type , const char * name , const char * source , SourceOffset offset );
130+ static EventFrame * EventFrameCreate (char * type , const char * name , const char * source , SourceOffset offset , char * id );
131131static void EventFrameDestroy (EventFrame * event );
132+
133+ static char * BundleGetCallStackID (const Bundle * bp );
134+ static char * PromiseGetCallStackID (const Promise * pp );
135+ static char * FunctionGetCallStackID (const FnCall * fp );
136+
132137static EventFrame * BundleToEventFrame (const Bundle * bp );
133138static EventFrame * PromiseToEventFrame (const Promise * pp );
134139static EventFrame * FunctionToEventFrame (const FnCall * fp );
@@ -346,6 +351,20 @@ static StackFrame *LastStackFrameByType(const EvalContext *ctx, StackFrameType t
346351 return NULL ;
347352}
348353
354+ static StackFrame * LastStackFrameByEvent (const EvalContext * ctx )
355+ {
356+ for (size_t i = 0 ; i < SeqLength (ctx -> stack ); i ++ )
357+ {
358+ StackFrame * frame = LastStackFrame (ctx , i );
359+ if (frame -> event != NULL )
360+ {
361+ return frame ;
362+ }
363+ }
364+
365+ return NULL ;
366+ }
367+
349368static LogLevel AdjustLogLevel (LogLevel base , LogLevel adjust )
350369{
351370 if (adjust == -1 )
@@ -1436,7 +1455,22 @@ void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, cons
14361455 assert (ctx != NULL );
14371456 assert (!LastStackFrame (ctx , 0 ) || LastStackFrame (ctx , 0 )-> type == STACK_FRAME_TYPE_PROMISE_ITERATION );
14381457
1439- EvalContextStackPushFrame (ctx , StackFrameNewBundle (owner , inherits_previous , ctx -> profiling ));
1458+ StackFrame * prev_frame = LastStackFrameByEvent (ctx );
1459+ StackFrame * frame = StackFrameNewBundle (owner , inherits_previous , ctx -> profiling );
1460+
1461+ EventFrame * pushed_event = frame -> event ;
1462+ EvalContextStackPushFrame (ctx , frame );
1463+ if (pushed_event != NULL )
1464+ {
1465+ if (prev_frame == NULL || prev_frame -> event == NULL )
1466+ {
1467+ pushed_event -> stacktrace = SafeStringDuplicate (pushed_event -> id );
1468+ }
1469+ else
1470+ {
1471+ pushed_event -> stacktrace = StringFormat ("%s;%s" , prev_frame -> event -> stacktrace , pushed_event -> id );
1472+ }
1473+ }
14401474
14411475 if (RlistLen (args ) > 0 )
14421476 {
@@ -1516,9 +1550,22 @@ void EvalContextStackPushPromiseFrame(EvalContext *ctx, const Promise *owner)
15161550
15171551 EvalContextVariableClearMatch (ctx );
15181552
1553+ StackFrame * prev_frame = LastStackFrameByEvent (ctx );
15191554 StackFrame * frame = StackFrameNewPromise (owner , ctx -> profiling );
15201555
15211556 EvalContextStackPushFrame (ctx , frame );
1557+ EventFrame * pushed_event = frame -> event ;
1558+ if (pushed_event != NULL )
1559+ {
1560+ if (prev_frame == NULL || prev_frame -> event == NULL )
1561+ {
1562+ pushed_event -> stacktrace = SafeStringDuplicate (pushed_event -> id );
1563+ }
1564+ else
1565+ {
1566+ pushed_event -> stacktrace = StringFormat ("%s;%s" , prev_frame -> event -> stacktrace , pushed_event -> id );
1567+ }
1568+ }
15221569
15231570 // create an empty table
15241571 frame -> data .promise .vars = VariableTableNew ();
@@ -3891,7 +3938,7 @@ void EvalContextSetProfiling(EvalContext *ctx, bool profiling)
38913938 ctx -> profiling = profiling ;
38923939}
38933940
3894- static EventFrame * EventFrameCreate (char * type , const char * name , const char * source , SourceOffset offset )
3941+ static EventFrame * EventFrameCreate (char * type , const char * name , const char * source , SourceOffset offset , char * id )
38953942{
38963943 EventFrame * event = (EventFrame * ) xmalloc (sizeof (EventFrame ));
38973944
@@ -3900,7 +3947,8 @@ static EventFrame *EventFrameCreate(char *type, const char *name, const char *so
39003947 event -> filename = GetAbsolutePath (source );
39013948 event -> elapsed = 0 ;
39023949 event -> offset = offset ;
3903- event -> id = StringFormat ("%s_%s_%s_%ld_%ld" , type , name , source , offset .start , offset .line );
3950+ event -> id = id ;
3951+ event -> stacktrace = "" ;
39043952
39053953 return event ;
39063954}
@@ -3926,6 +3974,7 @@ static JsonElement *EventToJson(EventFrame *event)
39263974 JsonObjectAppendString (json_event , "filename" , event -> filename );
39273975 JsonObjectAppendString (json_event , "id" , event -> id );
39283976 JsonObjectAppendInteger64 (json_event , "elapsed" , event -> elapsed );
3977+ JsonObjectAppendString (json_event , "callstack" , event -> stacktrace );
39293978
39303979 JsonElement * offset = JsonObjectCreate (4 );
39313980 JsonObjectAppendInteger (offset , "start" , event -> offset .start );
@@ -3941,19 +3990,19 @@ static JsonElement *EventToJson(EventFrame *event)
39413990static EventFrame * BundleToEventFrame (const Bundle * bp )
39423991{
39433992 assert (bp != NULL );
3944- return EventFrameCreate ("bundle" , bp -> name , bp -> source_path , bp -> offset );
3993+ return EventFrameCreate ("bundle" , bp -> name , bp -> source_path , bp -> offset , BundleGetCallStackID ( bp ) );
39453994}
39463995
39473996static EventFrame * PromiseToEventFrame (const Promise * pp )
39483997{
39493998 assert (pp != NULL );
3950- return EventFrameCreate ("promise" , PromiseGetPromiseType (pp ), PromiseGetBundle (pp )-> source_path , pp -> offset );
3999+ return EventFrameCreate ("promise" , PromiseGetPromiseType (pp ), PromiseGetBundle (pp )-> source_path , pp -> offset , PromiseGetCallStackID ( pp ) );
39514000}
39524001
39534002static EventFrame * FunctionToEventFrame (const FnCall * fp )
39544003{
39554004 assert (fp != NULL );
3956- return EventFrameCreate ("function" , fp -> name , PromiseGetBundle (fp -> caller )-> source_path , fp -> caller -> offset );
4005+ return EventFrameCreate ("function" , fp -> name , PromiseGetBundle (fp -> caller )-> source_path , fp -> caller -> offset , FunctionGetCallStackID ( fp ) );
39574006}
39584007
39594008void EvalContextAddFunctionEvent (EvalContext * ctx , const FnCall * fp , int64_t start )
@@ -3982,31 +4031,6 @@ void EvalContextProfilingStart(EvalContext *ctx)
39824031 ctx -> profiler .elapsed = EvalContextEventStart ();
39834032}
39844033
3985- static HashMap * SumEventFrames (Seq * events )
3986- {
3987- HashMap * map = HashMapNew ((MapHashFn ) StringHash , (MapKeyEqualFn ) StringEqual , NULL , NULL , 10 );
3988-
3989- size_t length = SeqLength (events );
3990- EventFrame * curr ;
3991- EventFrame * prev ;
3992- MapKeyValue * mkv ;
3993- for (int i = 0 ; i < length ; i ++ )
3994- {
3995- curr = SeqAt (events , i );
3996- mkv = HashMapGet (map , curr -> id );
3997-
3998- if (mkv == NULL )
3999- {
4000- HashMapInsert (map , curr -> id , curr );
4001- continue ;
4002- }
4003- prev = mkv -> value ;
4004- prev -> elapsed += curr -> elapsed ;
4005- }
4006-
4007- return map ;
4008- }
4009-
40104034void EvalContextProfilingEnd (EvalContext * ctx , const Policy * policy )
40114035{
40124036 assert (ctx != NULL );
@@ -4022,19 +4046,16 @@ void EvalContextProfilingEnd(EvalContext *ctx, const Policy *policy)
40224046
40234047 ctx -> profiler .elapsed = end - start ;
40244048
4025- HashMap * map = SumEventFrames (ctx -> profiler .events );
40264049 JsonElement * profiling = JsonObjectCreate (2 );
40274050
40284051 JsonElement * json_policy = PolicyToJson (policy );
40294052 JsonObjectAppendObject (profiling , "policy" , json_policy );
40304053
40314054 JsonElement * events = JsonArrayCreate (10 );
40324055 {
4033- HashMapIterator iter = HashMapIteratorInit (map );
4034- MapKeyValue * mkv ;
4035- while ((mkv = HashMapIteratorNext (& iter )) != NULL )
4056+ for (size_t i = 0 ; i < SeqLength (ctx -> profiler .events ); i ++ )
40364057 {
4037- EventFrame * event = mkv -> value ;
4058+ EventFrame * event = SeqAt ( ctx -> profiler . events , i ) ;
40384059 JsonArrayAppendObject (events , EventToJson (event ));
40394060 }
40404061 }
@@ -4047,3 +4068,22 @@ void EvalContextProfilingEnd(EvalContext *ctx, const Policy *policy)
40474068
40484069 JsonDestroy (profiling );
40494070}
4071+
4072+
4073+ static char * BundleGetCallStackID (const Bundle * bp )
4074+ {
4075+ assert (bp != NULL );
4076+ return StringFormat ("bundle_%s_%s:%s_%s:%ld_%ld-%ld" , bp -> type , bp -> ns , bp -> name , bp -> source_path , bp -> offset .line , bp -> offset .start , bp -> offset .end );
4077+ }
4078+
4079+ static char * PromiseGetCallStackID (const Promise * pp )
4080+ {
4081+ assert (pp != NULL );
4082+ return StringFormat ("promise_%s_%ld_%ld-%ld" , PromiseGetPromiseType (pp ), pp -> offset .line , pp -> offset .start , pp -> offset .end );
4083+ }
4084+
4085+ static char * FunctionGetCallStackID (const FnCall * fp )
4086+ {
4087+ assert (fp != NULL );
4088+ return StringFormat ("function_%s_%ld_%ld-%ld" , fp -> name , fp -> caller -> offset .line , fp -> caller -> offset .start , fp -> caller -> offset .end );
4089+ }
0 commit comments