-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathload_results.py
More file actions
326 lines (272 loc) · 11.9 KB
/
load_results.py
File metadata and controls
326 lines (272 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
from globals import c_profiled_loc, c_alloc_type, c_deref_type, c_realloc_type, c_free_type, c_generic_type, c_source_loc
from processing import scope, print_scope_table, print_func_table
from iterate_ast import DerefInstance, FuncCallParamInstance, print_deref_table, print_funcCall_param_table
import pickle
class runtime_node:
def __init__(self, code: str, index: int, timestamp: int):
self.code = code
self.index = index
self.timestamp = timestamp
class alloc_node(runtime_node):
def __init__(self, code: str, index: int, timestamp: int, alloc_id: int):
super().__init__(code, index, timestamp)
self.alloc_id = alloc_id
def __str__(self):
return f'{self.code} at {self.index} with allocation[{self.alloc_id}]'
class deref_node(runtime_node):
def __init__(self, code: str, index: int, timestamp: int, alloc_id: int):
super().__init__(code, index, timestamp)
self.alloc_id = alloc_id
def __str__(self):
return f'{self.code} at {self.index} with allocation[{self.alloc_id}]'
class realloc_node(runtime_node):
def __init__(self, code: str, index: int, timestamp: int, dealloc_id: int, alloc_id: int):
super().__init__(code, index, timestamp)
self.dealloc_id = dealloc_id
self.alloc_id = alloc_id
def __str__(self):
return f'{self.code} at {self.index} with deallocation[{self.dealloc_id}] and allocation[{self.alloc_id}]'
class free_node(runtime_node):
def __init__(self, code: str, index: int, timestamp: int, dealloc_id: int):
super().__init__(code, index, timestamp)
self.dealloc_id = dealloc_id
def __str__(self):
return f'{self.code} at {self.index} with deallocation[{self.dealloc_id}]'
class generic_node(runtime_node):
def __init__(self, code: str, index: int, timestamp: int):
super().__init__(code, index, timestamp)
def __str__(self):
return f'{self.code} at {self.index}'
def print_runtime_result(rt: []):
for node in rt:
print(node)
def print_alloc_table(alloc_table: dict()):
print('------Allocation Table------')
for alloc_id in alloc_table:
print(f'alloc[{alloc_id}] = {alloc_table[alloc_id][:-1]}, {"Freed" if alloc_table[alloc_id][-1] else "Not Freed"}')
def load_allocation_table() -> dict():
result = dict()
# Open file
with open(c_profiled_loc + 'allocTable.cymp', 'r') as f:
for line in f:
fields = line.strip().split(',')
result[int(fields[0])] = (int(fields[1], 16), int(fields[2]), bool(int(fields[3])))
return result
def load_runtime_result() -> []:
result = []
# Open file
with open(c_profiled_loc + 'runtime.cymp', 'r') as f:
for line in f:
fields = line.strip().split(',')
instr = fields[0]
if instr in c_alloc_type:
if len(fields) != 4:
raise Exception(f'Invalid alloc instruction {instr}')
result.append(alloc_node(instr, int(fields[1]), fields[2], int(fields[3])))
elif instr in c_deref_type:
if len(fields) != 4:
raise Exception(f'Invalid deref instruction {instr}')
result.append(deref_node(instr, int(fields[1]), fields[2], int(fields[3])))
elif instr in c_realloc_type:
if len(fields) != 5:
raise Exception(f'Invalid realloc instruction {instr}')
result.append(realloc_node(instr, int(fields[1]), fields[2], int(fields[3]), int(fields[4])))
elif instr in c_free_type:
if len(fields) != 4:
raise Exception(f'Invalid free instruction {instr}')
result.append(free_node(instr, int(fields[1]), fields[2], int(fields[3])))
elif instr in c_generic_type: # code, index, timstamp
if len(fields) != 3:
raise Exception(f'Invalid generic instruction {instr}')
result.append(generic_node(instr, int(fields[1]), fields[2]))
else:
raise Exception(f'Invalid instruction {instr}')
return result
def import_all() -> (dict, [], dict, dict, dict, dict):
try:
alloc_table = load_allocation_table() # Dict
except:
raise Exception('Error loading allocation table')
try:
runtime_result = load_runtime_result() # List
except:
raise Exception('Error loading runtime result')
# Unpickle all tables
try:
with open(c_profiled_loc + 'call_table.pkl', 'rb') as f:
call_table = pickle.load(f)
except:
raise Exception('Error loading call table')
try:
with open(c_profiled_loc + 'deref_table.pkl', 'rb') as f:
deref_table = pickle.load(f)
except:
raise Exception('Error loading deref table')
try:
with open(c_profiled_loc + 'func_table.pkl', 'rb') as f:
func_table = pickle.load(f)
except:
raise Exception('Error loading func table')
try:
with open(c_profiled_loc + 'scope_table.pkl', 'rb') as f:
scope_table = pickle.load(f)
except:
raise Exception('Error loading scope table')
return alloc_table, runtime_result, call_table, scope_table, deref_table, func_table
def print_foreground(text, color_code):
foreground_color = f"\033[{color_code}m"
reset = "\033[0m"
print(f"{foreground_color}{text}{reset}", end="")
def print_highlighted(text, background_color_code):
background_color = f"\033[{background_color_code}m"
reset = "\033[0m"
print(f"{background_color}{text}{reset}", end="")
def print_highlighted_source(source: str, scope_table: dict):
# Build enter coords and exits coords
enter_coords = {scope_table[key].enter_coord : key for key in scope_table}
exit_coords = {scope_table[key].exit_coord : key for key in scope_table}
scope_frames = []
line, index = 1, 1
# Print line number
print_foreground(f'#{line}\t| ', 31)
# Variable to handle proper highlighting of closing braces
exiting_scope = False
for s in source:
# Printing current char
if exiting_scope:
print_foreground(s, 32 + len(scope_frames) + 1)
if s == '}':
exiting_scope = False
else:
if len(scope_frames) == 0:
print(s, end='')
else:
print_foreground(s, 32 + len(scope_frames))
# Increment counts
if s == '\n':
line += 1
index = 0
index += 1
# Check scope enter
if f'{line}:{index}' in enter_coords:
scope_frames.append(enter_coords[f'{line}:{index}'])
# Print scope name
print_highlighted(f'SCOPE({scope_frames[-1]})', 42)
# Check scope exit
if f'{line}:{index}' in exit_coords:
if scope_frames.pop() != exit_coords[f'{line}:{index}']:
raise Exception('Scope mismatch')
exiting_scope = True
# Print line number
if s == '\n':
print_foreground(f'#{line}\t| ', 31)
print()
def process_runtime_result(print_result=False, print_runtime=False, print_tracking=False, print_highlight_source=True) -> dict:
"""Iterates through the runtime result and returns a modified scope table"""
# Use import all
alloc_table, runtime_result, call_table, scope_table, deref_table, func_table = import_all()
if print_highlight_source:
# Load source
with open(c_source_loc + 'sample.c', 'r') as f:
source = f.read()
print_highlighted_source(source, scope_table)
if print_runtime:
print_runtime_result(runtime_result)
if print_result:
print_alloc_table(alloc_table)
print_scope_table(scope_table)
print_deref_table(deref_table)
print_func_table(func_table)
print_funcCall_param_table(call_table)
scope_frame = []
main_func = None
# Iterate through runtime result
for node in runtime_result:
# Scope enter
if node.code == 'SENT':
if main_func is None:
main_func = node.index
scope_frame.append(node.index)
# Add a new empty list to the current scope's runtime table
scope_table[node.index].runtime_table[len(scope_table[node.index].runtime_table)] = []
if print_tracking:
print(f'Entering scope {node.index}')
print(f'Scope frame: {scope_frame}')
# Scope exit
elif node.code == 'SEXT':
if scope_frame.pop() != node.index:
raise Exception(f'Scope frame exit mismatch at {node.index}')
if print_tracking:
print(f'Exiting scope {node.index}')
print(f'Scope frame: {scope_frame}')
# Handle function returns
elif node.code == 'RETN':
if main_func is None:
raise Exception(f'Returning outside of main function')
# If returning from a main function
if scope_frame[-1] == main_func:
if print_tracking:
print(f'Returning from main function')
return scope_table, alloc_table
else:
if print_tracking:
print(f'Returning from function {scope_frame[-1]}')
while scope_frame[-1] != main_func:
scope_frame.pop()
elif node.code == 'EXIT':
return scope_table, alloc_table
else: # Every type of operation except scope change
# Append node to runtime list of the latest entrance of the current scope
scope_table[scope_frame[-1]].runtime_table[len(scope_table[scope_frame[-1]].runtime_table)-1].append(node)
return scope_table, alloc_table
def print_scope_table_data(scope_table: dict, alloc_table: dict):
def interpret_scope(s: scope):
entrances = []
# Iterate over entrance
for i in range(len(s.runtime_table)):
curr_deref_amount = 0
curr_alloc_amound = 0
curr_free_amount = 0
curr_runtime_list = s.runtime_table[i]
deref_blocks = set()
alloc_blocks = set()
free_blocks = set()
# Iterate over runtime list
for node in curr_runtime_list:
if isinstance(node, deref_node):
deref_blocks.add(node.alloc_id)
elif isinstance(node, alloc_node):
alloc_blocks.add(node.alloc_id)
elif isinstance(node, realloc_node):
alloc_blocks.add(node.alloc_id)
free_blocks.add(node.dealloc_id)
elif isinstance(node, free_node):
free_blocks.add(node.dealloc_id)
# Iterate over blocks
for block_id in deref_blocks:
curr_deref_amount += alloc_table[block_id][1]
for block_id in alloc_blocks:
curr_alloc_amound += alloc_table[block_id][1]
for block_id in free_blocks:
curr_free_amount += alloc_table[block_id][1]
entrances.append((curr_deref_amount, curr_alloc_amound, curr_free_amount))
return entrances
for id in scope_table:
curr_scope = scope_table[id]
print(curr_scope)
stats = interpret_scope(curr_scope)
for i, s in enumerate(stats):
print(f'Entrance #{i}: ')
if s[0] > 0:
print(f'\t{s[0]} bytes dereferences', end='')
if s[1] > 0:
print(f'\t{s[1]} bytes allocations', end='')
if s[2] > 0:
print(f'\t{s[2]} bytes frees', end='')
if s[0] == 0 and s[1] == 0 and s[2] == 0:
print(f'\tNo memory action', end='')
print()
print()
if __name__ == '__main__':
resulting_scope_table, alloc_table = process_runtime_result(print_result=False, print_runtime=False, print_tracking=False)
print_scope_table_data(resulting_scope_table, alloc_table)