Skip to content

Commit 7b455be

Browse files
committed
Added stats options for memory info, stack depths and frame sizes
1 parent e6dcfaf commit 7b455be

File tree

7 files changed

+193
-14
lines changed

7 files changed

+193
-14
lines changed

.idea/runConfigurations/picoc_basic_c__memory_.xml

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

c-tests/memory.c

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
int a = 0;
2+
int b;
3+
char arr1[100];
4+
5+
6+
long long func() {
7+
char c = 0;
8+
char arr3[300];
9+
arr1[0] = 1;
10+
return c;
11+
}
12+
13+
14+
int main(void) {
15+
a = 1;
16+
b = 2;
17+
int c = 0;
18+
int d = 1;
19+
char e;
20+
e = 1;
21+
22+
func();
23+
24+
short arr2[100];
25+
26+
return c + d - e;
27+
}

interpreter.h

+1
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ struct Picoc_Struct {
539539
int CollectFullExpressions;
540540
int PrintStats;
541541
int PrintExpressions;
542+
int PrintMemory;
542543
};
543544

544545
/* table.c */

picoc.c

+16-2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ int main(int argc, char **argv)
6969
}
7070
CollectStats = true;
7171
pc.CollectStats = true;
72+
if (StatsType >= 0x1000) {
73+
pc.PrintMemory = true;
74+
StatsType -= 0x1000;
75+
}
7276
if (StatsType >= 0x100) {
7377
pc.PrintExpressions = true;
7478
StatsType -= 0x100;
@@ -112,9 +116,13 @@ int main(int argc, char **argv)
112116
* 0x8: Print number of assignments to each basic variable type, in CSV format (one row, no header row)
113117
* 0x9: Print summary of expressions encountered during execution and their counts
114118
* 0xa: Print full list of expressions encountered during execution
119+
* 0xb: Print summary information about expression chains
120+
* 0xc: Print information about stack depths and frame sizes
121+
* 0xd: Print information about stack depths and frame sizes in CSV format
115122
*
116-
* Add 0x010 to each type to also print token information to stderr in real-time as they are parsed.
117-
* Add 0x100 to each type to also print expressions information to stderr in real-time as they are executed.
123+
* Add 0x0010 to each type to also print token information to stderr in real-time as they are parsed.
124+
* Add 0x0100 to each type to also print expressions information to stderr in real-time as they are executed.
125+
* Add 0x1000 to each type to also print memory information to stderr in real-time as it is allocated.
118126
*/
119127

120128
if (CollectStats) {
@@ -155,6 +163,12 @@ int main(int argc, char **argv)
155163
case 0x0b:
156164
stats_print_expression_chains_summary();
157165
break;
166+
case 0x0c:
167+
stats_print_stack_info();
168+
break;
169+
case 0x0d:
170+
stats_print_stack_info_csv();
171+
break;
158172
default:
159173
break;
160174
}

stats.c

+131-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define NUM_OPERATORS 45
1313
#define NUM_EXPRESSION_TYPES 4
1414
#define EXPRESSION_CHAIN_STACK_SIZE 100
15+
#define MAX_STACK_FRAMES 100
1516

1617
struct LexTokenStat {
1718
const char* name;
@@ -274,6 +275,13 @@ const char *OperatorSymbols[NUM_OPERATORS] = {
274275
")"
275276
};
276277

278+
struct StackFrameStats {
279+
unsigned int LvalueAllocation;
280+
unsigned int TotalAllocation;
281+
unsigned int CumulativeLvalueAllocation;
282+
unsigned int CumulativeTotalAllocation;
283+
};
284+
277285

278286
void stats_print_expression(enum ExpressionType Type, enum LexToken Op, enum BaseType TopType, enum BaseType BottomType);
279287
void stats_traverse_expressions_tree(struct ExpressionChainItem *Node);
@@ -298,9 +306,14 @@ struct ExpressionChainNode *CurrentExpression = NULL;
298306
struct ExpressionChainItem ExpressionChainsRoot = {{0}};
299307
struct ExpressionChainItem *ExpressionChainTreePosition = NULL;
300308
union ExpressionHash ExpressionChainStack[EXPRESSION_CHAIN_STACK_SIZE];
301-
int ExpressionChainStackTop = 0;
302-
int TotalExpressions = 0;
303-
int TotalExpressionChains = 0;
309+
unsigned int ExpressionChainStackTop = 0;
310+
unsigned int TotalExpressions = 0;
311+
unsigned int TotalExpressionChains = 0;
312+
struct StackFrameStats StackFrameAllocations[MAX_STACK_FRAMES] = {{0}};
313+
unsigned int MaxStackFrameLvalueAllocation = 0;
314+
unsigned int MaxStackFrameTotalAllocation = 0;
315+
unsigned int MaxCumulativeLvalueAllocation = 0;
316+
unsigned int MaxCumulativeTotalAllocation = 0;
304317

305318

306319
void stats_log_statement(enum LexToken token, struct ParseState *parser)
@@ -634,8 +647,20 @@ void stats_log_stack_frame_add(struct ParseState *parser, const char *funcName)
634647
if (StackFramesDepth > StackFramesMaxDepth) {
635648
StackFramesMaxDepth = StackFramesDepth;
636649
}
637-
if (parser->pc->PrintStats) {
638-
fprintf(stderr, "Adding stack frame for '%s()' (current depth %u, max %u) at %s:%d:%d\n",
650+
651+
StackFrameAllocations[StackFramesDepth].TotalAllocation = 0;
652+
StackFrameAllocations[StackFramesDepth].LvalueAllocation = 0;
653+
StackFrameAllocations[StackFramesDepth].CumulativeTotalAllocation = StackFrameAllocations[StackFramesDepth - 1].CumulativeTotalAllocation;
654+
StackFrameAllocations[StackFramesDepth].CumulativeLvalueAllocation = StackFrameAllocations[StackFramesDepth - 1].CumulativeLvalueAllocation;
655+
656+
if (parser->pc->PrintStats || parser->pc->PrintMemory) {
657+
fprintf(stderr, "\n");
658+
for (int i = 0; i < StackFramesDepth - 1; i++)
659+
fprintf(stderr, " ");
660+
fprintf(stderr, "***\n");
661+
for (int i = 0; i < StackFramesDepth - 1; i++)
662+
fprintf(stderr, " ");
663+
fprintf(stderr, "Adding stack frame for '%s()' (new depth %u, max depth %u) at %s:%d:%d\n",
639664
funcName, StackFramesDepth, StackFramesMaxDepth, parser->FileName, parser->Line, parser->CharacterPos);
640665
}
641666
}
@@ -646,9 +671,87 @@ void stats_log_stack_frame_pop(struct ParseState *parser)
646671
{
647672
if (parser->pc->CollectStats) {
648673
StackFramesDepth--;
649-
if (parser->pc->PrintStats) {
650-
fprintf(stderr, "Popping stack frame (current depth %u, max %u) at %s:%d:%d\n",
674+
if (parser->pc->PrintStats || parser->pc->PrintMemory) {
675+
for (int i = 0; i < StackFramesDepth; i++)
676+
fprintf(stderr, " ");
677+
fprintf(stderr, "Popping stack frame (new depth %u, max depth %u) at %s:%d:%d\n",
651678
StackFramesDepth, StackFramesMaxDepth, parser->FileName, parser->Line, parser->CharacterPos);
679+
for (int i = 0; i < StackFramesDepth; i++)
680+
fprintf(stderr, " ");
681+
fprintf(stderr, "***\n\n");
682+
}
683+
}
684+
}
685+
686+
687+
void stats_log_stack_allocation(struct ParseState *parser, int Size, int IsLValue)
688+
{
689+
if (parser->pc->CollectStats && (parser->Mode == RunModeRun) && (strcmp(parser->FileName, "startup") != 0)) {
690+
691+
StackFrameAllocations[StackFramesDepth].TotalAllocation += Size;
692+
if (StackFrameAllocations[StackFramesDepth].TotalAllocation > MaxStackFrameTotalAllocation)
693+
MaxStackFrameTotalAllocation = StackFrameAllocations[StackFramesDepth].TotalAllocation;
694+
695+
StackFrameAllocations[StackFramesDepth].CumulativeTotalAllocation += Size;
696+
if (StackFrameAllocations[StackFramesDepth].CumulativeTotalAllocation > MaxCumulativeTotalAllocation)
697+
MaxCumulativeTotalAllocation = StackFrameAllocations[StackFramesDepth].CumulativeTotalAllocation;
698+
699+
if (IsLValue) {
700+
StackFrameAllocations[StackFramesDepth].LvalueAllocation += Size;
701+
if (StackFrameAllocations[StackFramesDepth].LvalueAllocation > MaxStackFrameLvalueAllocation)
702+
MaxStackFrameLvalueAllocation = StackFrameAllocations[StackFramesDepth].LvalueAllocation;
703+
704+
StackFrameAllocations[StackFramesDepth].CumulativeLvalueAllocation += Size;
705+
if (StackFrameAllocations[StackFramesDepth].CumulativeLvalueAllocation > MaxCumulativeLvalueAllocation)
706+
MaxCumulativeLvalueAllocation = StackFrameAllocations[StackFramesDepth].CumulativeLvalueAllocation;
707+
}
708+
709+
if (parser->pc->PrintMemory) {
710+
for (int i = 0; i < StackFramesDepth; i++)
711+
fprintf(stderr, " ");
712+
fprintf(stderr, "%s:%d:%d Allocated %d bytes on stack (total %d/%d) %s\n",
713+
parser->FileName, parser->Line, parser->CharacterPos, Size,
714+
StackFrameAllocations[StackFramesDepth].TotalAllocation,
715+
StackFrameAllocations[StackFramesDepth].CumulativeTotalAllocation,
716+
IsLValue ? "(lvalue)" : "");
717+
}
718+
}
719+
}
720+
721+
722+
void stats_log_stack_pop(struct ParseState *parser, struct Value *Var)
723+
{
724+
if (parser->pc->CollectStats && (parser->Mode == RunModeRun) && (strcmp(parser->FileName, "startup") != 0)) {
725+
int Size = Var->Typ->Sizeof;
726+
727+
StackFrameAllocations[StackFramesDepth].TotalAllocation -= Size;
728+
StackFrameAllocations[StackFramesDepth].CumulativeTotalAllocation -= Size;
729+
if (Var->IsLValue) {
730+
StackFrameAllocations[StackFramesDepth].LvalueAllocation -= Size;
731+
StackFrameAllocations[StackFramesDepth].CumulativeLvalueAllocation -= Size;
732+
}
733+
734+
if (parser->pc->PrintMemory) {
735+
for (int i = 0; i < StackFramesDepth; i++)
736+
fprintf(stderr, " ");
737+
fprintf(stderr, "%s:%d:%d Popped %d bytes off stack (total %d/%d) %s\n",
738+
parser->FileName, parser->Line, parser->CharacterPos, Size,
739+
StackFrameAllocations[StackFramesDepth].TotalAllocation,
740+
StackFrameAllocations[StackFramesDepth].CumulativeTotalAllocation,
741+
Var->IsLValue ? "(lvalue)" : "");
742+
}
743+
}
744+
}
745+
746+
747+
void stats_log_variable_definition(struct ParseState *parser, char *Ident, struct ValueType *Typ)
748+
{
749+
if (parser->pc->CollectStats) {
750+
if (parser->pc->PrintMemory) {
751+
for (int i = 0; i < StackFramesDepth; i++)
752+
fprintf(stderr, " ");
753+
fprintf(stderr, "%s:%d:%d Defining variable '%s' of size %d bytes...\n",
754+
parser->FileName, parser->Line, parser->CharacterPos, Ident, Typ->Sizeof);
652755
}
653756
}
654757
}
@@ -914,3 +1017,24 @@ void stats_print_expression_chains(void)
9141017

9151018
printf("\n");
9161019
}
1020+
1021+
1022+
void stats_print_stack_info(void)
1023+
{
1024+
printf("Maximum stack frame depth: %d\n", StackFramesMaxDepth);
1025+
printf("Maximum individual stack frame size: %d bytes\n", MaxStackFrameTotalAllocation);
1026+
printf("Maximum cumulative stack frame size: %d bytes\n", MaxCumulativeTotalAllocation);
1027+
printf("Maximum individual stack frame size (lvalues only): %d bytes\n", MaxStackFrameLvalueAllocation);
1028+
printf("Maximum cumulative stack frame size (lvalues only): %d bytes\n", MaxCumulativeLvalueAllocation);
1029+
}
1030+
1031+
1032+
void stats_print_stack_info_csv(void)
1033+
{
1034+
printf("%d,%d,%d,%d,%d\n",
1035+
StackFramesMaxDepth,
1036+
MaxStackFrameTotalAllocation,
1037+
MaxCumulativeTotalAllocation,
1038+
MaxStackFrameLvalueAllocation,
1039+
MaxCumulativeLvalueAllocation);
1040+
}

stats.h

+5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ void stats_log_expression_stack_collapse(struct ParseState *parser);
4343
void stats_log_expression_evaluation(struct ParseState *parser, enum ExpressionType Type, enum LexToken Op, struct Value *BottomValue, struct Value *TopValue);
4444
void stats_log_stack_frame_add(struct ParseState *parser, const char *funcName);
4545
void stats_log_stack_frame_pop(struct ParseState *parser);
46+
void stats_log_stack_allocation(struct ParseState *parser, int Size, int IsLValue);
47+
void stats_log_stack_pop(struct ParseState *parser, struct Value *Var);
48+
void stats_log_variable_definition(struct ParseState *parser, char *Ident, struct ValueType *Typ);
4649
void stats_print_tokens(int all);
4750
void stats_print_tokens_csv(void);
4851
void stats_print_tokens_csv_runmode(enum RunMode runMode);
@@ -56,5 +59,7 @@ void stats_print_assignments_csv(void);
5659
void stats_print_expressions_summary(void);
5760
void stats_print_expression_chains_summary(void);
5861
void stats_print_expression_chains(void);
62+
void stats_print_stack_info(void);
63+
void stats_print_stack_info_csv(void);
5964

6065
#endif //PICOC_STATS_H

variable.c

+12-4
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ struct Value *VariableAllocValueAndData(Picoc *pc, struct ParseState *Parser,
109109

110110
NewValue->OutOfScope = false;
111111

112+
if (!OnHeap && !IsLValue)
113+
stats_log_stack_allocation(Parser, DataSize, IsLValue);
114+
112115
return NewValue;
113116
}
114117

@@ -122,6 +125,9 @@ struct Value *VariableAllocValueFromType(Picoc *pc, struct ParseState *Parser,
122125
assert(Size >= 0 || Typ == &pc->VoidType);
123126
NewValue->Typ = Typ;
124127

128+
if (!OnHeap)
129+
stats_log_stack_allocation(Parser, Typ->Sizeof, IsLValue);
130+
125131
return NewValue;
126132
}
127133

@@ -294,6 +300,8 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
294300
struct Table * currentTable = (pc->TopStackFrame == NULL) ?
295301
&(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
296302

303+
stats_log_variable_definition(Parser, Ident, Typ);
304+
297305
#ifdef DEBUG_VAR_SCOPE
298306
if (Parser) fprintf(stderr, "def %s %x (%s:%d:%d)\n", Ident, ScopeID,
299307
Parser->FileName, Parser->Line, Parser->CharacterPos);
@@ -454,10 +462,10 @@ void VariableStackPop(struct ParseState *Parser, struct Value *Var)
454462
if (Var->Val != NULL)
455463
HeapFreeMem(Parser->pc, Var->Val);
456464
Success = HeapPopStack(Parser->pc, Var, sizeof(struct Value)); /* free from heap */
457-
} else if (Var->ValOnStack)
458-
Success = HeapPopStack(Parser->pc, Var,
459-
sizeof(struct Value)+TypeSizeValue(Var, false)); /* free from stack */
460-
else
465+
} else if (Var->ValOnStack) {
466+
Success = HeapPopStack(Parser->pc, Var, sizeof(struct Value) + TypeSizeValue(Var, false)); /* free from stack */
467+
stats_log_stack_pop(Parser, Var);
468+
} else
461469
Success = HeapPopStack(Parser->pc, Var, sizeof(struct Value)); /* value isn't our problem */
462470

463471
if (!Success)

0 commit comments

Comments
 (0)