blob: 95e6e50f9ceaed8af6d10455fc59eba67983bdf9 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001# Copyright 2008 the V8 project authors. All rights reserved.
ager@chromium.orgc27e4e72008-09-04 13:52:27 +00002# Redistribution and use in source and binary forms, with or without
3# modification, are permitted provided that the following conditions are
4# met:
5#
6# * Redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer.
8# * Redistributions in binary form must reproduce the above
9# copyright notice, this list of conditions and the following
10# disclaimer in the documentation and/or other materials provided
11# with the distribution.
12# * Neither the name of Google Inc. nor the names of its
13# contributors may be used to endorse or promote products derived
14# from this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
ager@chromium.org381abbb2009-02-25 13:23:22 +000028import csv, splaytree, sys, re
29from operator import itemgetter
30import getopt, os, string
ager@chromium.orgc27e4e72008-09-04 13:52:27 +000031
32class CodeEntry(object):
33
34 def __init__(self, start_addr, name):
35 self.start_addr = start_addr
36 self.tick_count = 0
37 self.name = name
ager@chromium.org381abbb2009-02-25 13:23:22 +000038 self.stacks = {}
ager@chromium.orgc27e4e72008-09-04 13:52:27 +000039
ager@chromium.org381abbb2009-02-25 13:23:22 +000040 def Tick(self, pc, stack):
ager@chromium.orgc27e4e72008-09-04 13:52:27 +000041 self.tick_count += 1
ager@chromium.org381abbb2009-02-25 13:23:22 +000042 if len(stack) > 0:
43 stack.insert(0, self.ToString())
44 stack_key = tuple(stack)
45 self.stacks[stack_key] = self.stacks.setdefault(stack_key, 0) + 1
ager@chromium.orgc27e4e72008-09-04 13:52:27 +000046
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000047 def RegionTicks(self):
48 return None
49
ager@chromium.orgc27e4e72008-09-04 13:52:27 +000050 def SetStartAddress(self, start_addr):
51 self.start_addr = start_addr
52
53 def ToString(self):
54 return self.name
55
56 def IsSharedLibraryEntry(self):
57 return False
58
ager@chromium.org381abbb2009-02-25 13:23:22 +000059 def IsICEntry(self):
60 return False
61
ager@chromium.orgc27e4e72008-09-04 13:52:27 +000062
63class SharedLibraryEntry(CodeEntry):
64
65 def __init__(self, start_addr, name):
66 CodeEntry.__init__(self, start_addr, name)
67
68 def IsSharedLibraryEntry(self):
69 return True
70
71
72class JSCodeEntry(CodeEntry):
73
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000074 def __init__(self, start_addr, name, type, size, assembler):
ager@chromium.orgc27e4e72008-09-04 13:52:27 +000075 CodeEntry.__init__(self, start_addr, name)
76 self.type = type
77 self.size = size
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000078 self.assembler = assembler
79 self.region_ticks = None
ager@chromium.org381abbb2009-02-25 13:23:22 +000080 self.builtin_ic_re = re.compile('^(Keyed)?(Call|Load|Store)IC_')
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000081
ager@chromium.org381abbb2009-02-25 13:23:22 +000082 def Tick(self, pc, stack):
83 super(JSCodeEntry, self).Tick(pc, stack)
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000084 if not pc is None:
85 offset = pc - self.start_addr
86 seen = []
87 narrowest = None
88 narrowest_width = None
89 for region in self.Regions():
90 if region.Contains(offset):
91 if (not region.name in seen):
92 seen.append(region.name)
93 if narrowest is None or region.Width() < narrowest.Width():
94 narrowest = region
95 if len(seen) == 0:
96 return
97 if self.region_ticks is None:
98 self.region_ticks = {}
99 for name in seen:
100 if not name in self.region_ticks:
101 self.region_ticks[name] = [0, 0]
102 self.region_ticks[name][0] += 1
103 if name == narrowest.name:
104 self.region_ticks[name][1] += 1
105
106 def RegionTicks(self):
107 return self.region_ticks
108
109 def Regions(self):
110 if self.assembler:
111 return self.assembler.regions
112 else:
113 return []
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000114
115 def ToString(self):
ager@chromium.org7c537e22008-10-16 08:43:32 +0000116 name = self.name
iposva@chromium.org245aa852009-02-10 00:49:54 +0000117 if name == '':
118 name = '<anonymous>'
119 elif name.startswith(' '):
120 name = '<anonymous>' + name
ager@chromium.org7c537e22008-10-16 08:43:32 +0000121 return self.type + ': ' + name
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000122
ager@chromium.org381abbb2009-02-25 13:23:22 +0000123 def IsICEntry(self):
124 return self.type in ('CallIC', 'LoadIC', 'StoreIC') or \
125 (self.type == 'Builtin' and self.builtin_ic_re.match(self.name))
126
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000127
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000128class CodeRegion(object):
129
130 def __init__(self, start_offset, name):
131 self.start_offset = start_offset
132 self.name = name
133 self.end_offset = None
134
135 def Contains(self, pc):
136 return (self.start_offset <= pc) and (pc <= self.end_offset)
137
138 def Width(self):
139 return self.end_offset - self.start_offset
140
141
142class Assembler(object):
143
144 def __init__(self):
145 # Mapping from region ids to open regions
146 self.pending_regions = {}
147 self.regions = []
148
149
ager@chromium.org71daaf62009-04-01 07:22:49 +0000150class FunctionEnumerator(object):
151
152 def __init__(self):
153 self.known_funcs = {}
154 self.next_func_id = 0
155
156 def GetFunctionId(self, name):
157 if not self.known_funcs.has_key(name):
158 self.known_funcs[name] = self.next_func_id
159 self.next_func_id += 1
160 return self.known_funcs[name]
161
162 def GetKnownFunctions(self):
163 known_funcs_items = self.known_funcs.items();
164 known_funcs_items.sort(key = itemgetter(1))
165 result = []
166 for func, id_not_used in known_funcs_items:
167 result.append(func)
168 return result
169
170
ager@chromium.org41826e72009-03-30 13:30:57 +0000171VMStates = { 'JS': 0, 'GC': 1, 'COMPILER': 2, 'OTHER': 3, 'EXTERNAL' : 4 }
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000172
173
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000174class TickProcessor(object):
175
176 def __init__(self):
177 self.log_file = ''
178 self.deleted_code = []
179 self.vm_extent = {}
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000180 # Map from assembler ids to the pending assembler objects
181 self.pending_assemblers = {}
182 # Map from code addresses the have been allocated but not yet officially
183 # created to their assemblers.
184 self.assemblers = {}
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000185 self.js_entries = splaytree.SplayTree()
186 self.cpp_entries = splaytree.SplayTree()
187 self.total_number_of_ticks = 0
188 self.number_of_library_ticks = 0
189 self.unaccounted_number_of_ticks = 0
190 self.excluded_number_of_ticks = 0
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000191 self.number_of_gc_ticks = 0
ager@chromium.org381abbb2009-02-25 13:23:22 +0000192 # Flag indicating whether to ignore unaccounted ticks in the report
193 self.ignore_unknown = False
ager@chromium.org71daaf62009-04-01 07:22:49 +0000194 self.func_enum = FunctionEnumerator()
195 self.packed_stacks = []
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000196
ager@chromium.org71daaf62009-04-01 07:22:49 +0000197 def ProcessLogfile(self, filename, included_state = None, ignore_unknown = False, separate_ic = False, call_graph_json = False):
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000198 self.log_file = filename
199 self.included_state = included_state
ager@chromium.org381abbb2009-02-25 13:23:22 +0000200 self.ignore_unknown = ignore_unknown
201 self.separate_ic = separate_ic
ager@chromium.org71daaf62009-04-01 07:22:49 +0000202 self.call_graph_json = call_graph_json
ager@chromium.org381abbb2009-02-25 13:23:22 +0000203
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000204 try:
205 logfile = open(filename, 'rb')
206 except IOError:
207 sys.exit("Could not open logfile: " + filename)
208 try:
ager@chromium.org71daaf62009-04-01 07:22:49 +0000209 try:
210 logreader = csv.reader(logfile)
211 row_num = 1
212 for row in logreader:
213 row_num += 1
214 if row[0] == 'tick':
215 self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3]), self.PreprocessStack(row[4:]))
216 elif row[0] == 'code-creation':
217 self.ProcessCodeCreation(row[1], int(row[2], 16), int(row[3]), row[4])
218 elif row[0] == 'code-move':
219 self.ProcessCodeMove(int(row[1], 16), int(row[2], 16))
220 elif row[0] == 'code-delete':
221 self.ProcessCodeDelete(int(row[1], 16))
222 elif row[0] == 'shared-library':
223 self.AddSharedLibraryEntry(row[1], int(row[2], 16), int(row[3], 16))
224 self.ParseVMSymbols(row[1], int(row[2], 16), int(row[3], 16))
225 elif row[0] == 'begin-code-region':
226 self.ProcessBeginCodeRegion(int(row[1], 16), int(row[2], 16), int(row[3], 16), row[4])
227 elif row[0] == 'end-code-region':
228 self.ProcessEndCodeRegion(int(row[1], 16), int(row[2], 16), int(row[3], 16))
229 elif row[0] == 'code-allocate':
230 self.ProcessCodeAllocate(int(row[1], 16), int(row[2], 16))
231 except csv.Error:
232 print("parse error in line " + str(row_num))
233 raise
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000234 finally:
235 logfile.close()
236
237 def AddSharedLibraryEntry(self, filename, start, end):
238 # Mark the pages used by this library.
239 i = start
240 while i < end:
241 page = i >> 12
242 self.vm_extent[page] = 1
243 i += 4096
244 # Add the library to the entries so that ticks for which we do not
245 # have symbol information is reported as belonging to the library.
246 self.cpp_entries.Insert(start, SharedLibraryEntry(start, filename))
247
248 def ParseVMSymbols(self, filename, start, end):
249 return
250
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000251 def ProcessCodeAllocate(self, addr, assem):
252 if assem in self.pending_assemblers:
253 assembler = self.pending_assemblers.pop(assem)
254 self.assemblers[addr] = assembler
255
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000256 def ProcessCodeCreation(self, type, addr, size, name):
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000257 if addr in self.assemblers:
258 assembler = self.assemblers.pop(addr)
259 else:
260 assembler = None
261 self.js_entries.Insert(addr, JSCodeEntry(addr, name, type, size, assembler))
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000262
263 def ProcessCodeMove(self, from_addr, to_addr):
264 try:
265 removed_node = self.js_entries.Remove(from_addr)
266 removed_node.value.SetStartAddress(to_addr);
267 self.js_entries.Insert(to_addr, removed_node.value)
ager@chromium.org41826e72009-03-30 13:30:57 +0000268 except splaytree.KeyNotFoundError:
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000269 print('Code move event for unknown code: 0x%x' % from_addr)
270
271 def ProcessCodeDelete(self, from_addr):
272 try:
273 removed_node = self.js_entries.Remove(from_addr)
274 self.deleted_code.append(removed_node.value)
ager@chromium.org41826e72009-03-30 13:30:57 +0000275 except splaytree.KeyNotFoundError:
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000276 print('Code delete event for unknown code: 0x%x' % from_addr)
277
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000278 def ProcessBeginCodeRegion(self, id, assm, start, name):
279 if not assm in self.pending_assemblers:
280 self.pending_assemblers[assm] = Assembler()
281 assembler = self.pending_assemblers[assm]
282 assembler.pending_regions[id] = CodeRegion(start, name)
283
284 def ProcessEndCodeRegion(self, id, assm, end):
285 assm = self.pending_assemblers[assm]
286 region = assm.pending_regions.pop(id)
287 region.end_offset = end
288 assm.regions.append(region)
289
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000290 def IncludeTick(self, pc, sp, state):
291 return (self.included_state is None) or (self.included_state == state)
292
ager@chromium.org381abbb2009-02-25 13:23:22 +0000293 def FindEntry(self, pc):
294 page = pc >> 12
295 if page in self.vm_extent:
296 entry = self.cpp_entries.FindGreatestsLessThan(pc)
297 if entry != None:
298 return entry.value
299 else:
300 return entry
301 max = self.js_entries.FindMax()
302 min = self.js_entries.FindMin()
303 if max != None and pc < (max.key + max.value.size) and pc > min.key:
304 return self.js_entries.FindGreatestsLessThan(pc).value
305 return None
306
307 def PreprocessStack(self, stack):
308 # remove all non-addresses (e.g. 'overflow') and convert to int
309 result = []
310 for frame in stack:
311 if frame.startswith('0x'):
312 result.append(int(frame, 16))
313 return result
314
315 def ProcessStack(self, stack):
316 result = []
317 for frame in stack:
318 entry = self.FindEntry(frame)
319 if entry != None:
320 result.append(entry.ToString())
321 return result
322
323 def ProcessTick(self, pc, sp, state, stack):
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000324 if state == VMStates['GC']:
325 self.number_of_gc_ticks += 1
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000326 if not self.IncludeTick(pc, sp, state):
327 self.excluded_number_of_ticks += 1;
328 return
329 self.total_number_of_ticks += 1
ager@chromium.org381abbb2009-02-25 13:23:22 +0000330 entry = self.FindEntry(pc)
331 if entry == None:
332 self.unaccounted_number_of_ticks += 1
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000333 return
ager@chromium.org381abbb2009-02-25 13:23:22 +0000334 if entry.IsSharedLibraryEntry():
335 self.number_of_library_ticks += 1
336 if entry.IsICEntry() and not self.separate_ic:
337 if len(stack) > 0:
338 caller_pc = stack.pop(0)
339 self.total_number_of_ticks -= 1
340 self.ProcessTick(caller_pc, sp, state, stack)
341 else:
342 self.unaccounted_number_of_ticks += 1
343 else:
344 entry.Tick(pc, self.ProcessStack(stack))
ager@chromium.org71daaf62009-04-01 07:22:49 +0000345 if self.call_graph_json:
346 self.AddToPackedStacks(pc, stack)
347
348 def AddToPackedStacks(self, pc, stack):
349 full_stack = stack
350 full_stack.insert(0, pc)
351 func_names = self.ProcessStack(full_stack)
352 func_ids = []
353 for func in func_names:
354 func_ids.append(self.func_enum.GetFunctionId(func))
355 self.packed_stacks.append(func_ids)
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000356
357 def PrintResults(self):
ager@chromium.org71daaf62009-04-01 07:22:49 +0000358 if not self.call_graph_json:
359 self.PrintStatistics()
360 else:
361 self.PrintCallGraphJSON()
362
363 def PrintStatistics(self):
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000364 print('Statistical profiling result from %s, (%d ticks, %d unaccounted, %d excluded).' %
365 (self.log_file,
366 self.total_number_of_ticks,
367 self.unaccounted_number_of_ticks,
368 self.excluded_number_of_ticks))
369 if self.total_number_of_ticks > 0:
370 js_entries = self.js_entries.ExportValueList()
371 js_entries.extend(self.deleted_code)
372 cpp_entries = self.cpp_entries.ExportValueList()
ager@chromium.org381abbb2009-02-25 13:23:22 +0000373 # Print the unknown ticks percentage if they are not ignored.
374 if not self.ignore_unknown and self.unaccounted_number_of_ticks > 0:
375 self.PrintHeader('Unknown')
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000376 self.PrintCounter(self.unaccounted_number_of_ticks)
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000377 # Print the library ticks.
378 self.PrintHeader('Shared libraries')
379 self.PrintEntries(cpp_entries, lambda e:e.IsSharedLibraryEntry())
380 # Print the JavaScript ticks.
381 self.PrintHeader('JavaScript')
382 self.PrintEntries(js_entries, lambda e:not e.IsSharedLibraryEntry())
383 # Print the C++ ticks.
384 self.PrintHeader('C++')
385 self.PrintEntries(cpp_entries, lambda e:not e.IsSharedLibraryEntry())
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000386 # Print the GC ticks.
387 self.PrintHeader('GC')
388 self.PrintCounter(self.number_of_gc_ticks)
ager@chromium.org381abbb2009-02-25 13:23:22 +0000389 # Print call profile.
390 print('\n [Call profile]:')
391 print(' total call path')
392 js_entries.extend(cpp_entries)
393 self.PrintCallProfile(js_entries)
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000394
395 def PrintHeader(self, header_title):
396 print('\n [%s]:' % header_title)
ager@chromium.org381abbb2009-02-25 13:23:22 +0000397 print(' ticks total nonlib name')
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000398
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000399 def PrintCounter(self, ticks_count):
400 percentage = ticks_count * 100.0 / self.total_number_of_ticks
401 print(' %(ticks)5d %(total)5.1f%%' % {
402 'ticks' : ticks_count,
403 'total' : percentage,
404 })
405
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000406 def PrintEntries(self, entries, condition):
ager@chromium.org381abbb2009-02-25 13:23:22 +0000407 # If ignoring unaccounted ticks don't include these in percentage
408 # calculations
409 number_of_accounted_ticks = self.total_number_of_ticks
410 if self.ignore_unknown:
411 number_of_accounted_ticks -= self.unaccounted_number_of_ticks
412
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000413 number_of_non_library_ticks = number_of_accounted_ticks - self.number_of_library_ticks
414 entries.sort(key=lambda e:e.tick_count, reverse=True)
415 for entry in entries:
416 if entry.tick_count > 0 and condition(entry):
417 total_percentage = entry.tick_count * 100.0 / number_of_accounted_ticks
418 if entry.IsSharedLibraryEntry():
419 non_library_percentage = 0
420 else:
421 non_library_percentage = entry.tick_count * 100.0 / number_of_non_library_ticks
ager@chromium.org381abbb2009-02-25 13:23:22 +0000422 print(' %(ticks)5d %(total)5.1f%% %(nonlib)6.1f%% %(name)s' % {
423 'ticks' : entry.tick_count,
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000424 'total' : total_percentage,
425 'nonlib' : non_library_percentage,
426 'name' : entry.ToString()
427 })
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000428 region_ticks = entry.RegionTicks()
429 if not region_ticks is None:
430 items = region_ticks.items()
431 items.sort(key=lambda e: e[1][1], reverse=True)
432 for (name, ticks) in items:
433 print(' flat cum')
434 print(' %(flat)5.1f%% %(accum)5.1f%% %(name)s' % {
435 'flat' : ticks[1] * 100.0 / entry.tick_count,
436 'accum' : ticks[0] * 100.0 / entry.tick_count,
437 'name': name
438 })
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000439
ager@chromium.org381abbb2009-02-25 13:23:22 +0000440 def PrintCallProfile(self, entries):
441 all_stacks = {}
442 total_stacks = 0
443 for entry in entries:
444 all_stacks.update(entry.stacks)
445 for count in entry.stacks.itervalues():
446 total_stacks += count
447 all_stacks_items = all_stacks.items();
448 all_stacks_items.sort(key = itemgetter(1), reverse=True)
449 missing_percentage = (self.total_number_of_ticks - total_stacks) * 100.0 / self.total_number_of_ticks
450 print(' %(ticks)5d %(total)5.1f%% <no call path information>' % {
451 'ticks' : self.total_number_of_ticks - total_stacks,
452 'total' : missing_percentage
453 })
454 for stack, count in all_stacks_items:
455 total_percentage = count * 100.0 / self.total_number_of_ticks
456 print(' %(ticks)5d %(total)5.1f%% %(call_path)s' % {
457 'ticks' : count,
458 'total' : total_percentage,
459 'call_path' : stack[0] + ' <- ' + stack[1]
460 })
461
ager@chromium.org71daaf62009-04-01 07:22:49 +0000462 def PrintCallGraphJSON(self):
463 print('\nvar __profile_funcs = ["' +
464 '",\n"'.join(self.func_enum.GetKnownFunctions()) +
465 '"];')
466 print('var __profile_ticks = [')
467 str_packed_stacks = []
468 for stack in self.packed_stacks:
469 str_packed_stacks.append('[' + ','.join(map(str, stack)) + ']')
470 print(',\n'.join(str_packed_stacks))
471 print('];')
ager@chromium.org381abbb2009-02-25 13:23:22 +0000472
473class CmdLineProcessor(object):
474
475 def __init__(self):
ager@chromium.org41826e72009-03-30 13:30:57 +0000476 self.options = ["js",
477 "gc",
478 "compiler",
479 "other",
480 "external",
481 "ignore-unknown",
ager@chromium.org71daaf62009-04-01 07:22:49 +0000482 "separate-ic",
483 "call-graph-json"]
ager@chromium.org381abbb2009-02-25 13:23:22 +0000484 # default values
485 self.state = None
486 self.ignore_unknown = False
487 self.log_file = None
488 self.separate_ic = False
ager@chromium.org71daaf62009-04-01 07:22:49 +0000489 self.call_graph_json = False
ager@chromium.org381abbb2009-02-25 13:23:22 +0000490
491 def ProcessArguments(self):
492 try:
ager@chromium.org41826e72009-03-30 13:30:57 +0000493 opts, args = getopt.getopt(sys.argv[1:], "jgcoe", self.options)
ager@chromium.org381abbb2009-02-25 13:23:22 +0000494 except getopt.GetoptError:
495 self.PrintUsageAndExit()
496 for key, value in opts:
497 if key in ("-j", "--js"):
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000498 self.state = VMStates['JS']
ager@chromium.org381abbb2009-02-25 13:23:22 +0000499 if key in ("-g", "--gc"):
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000500 self.state = VMStates['GC']
ager@chromium.org381abbb2009-02-25 13:23:22 +0000501 if key in ("-c", "--compiler"):
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000502 self.state = VMStates['COMPILER']
ager@chromium.org381abbb2009-02-25 13:23:22 +0000503 if key in ("-o", "--other"):
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000504 self.state = VMStates['OTHER']
ager@chromium.org41826e72009-03-30 13:30:57 +0000505 if key in ("-e", "--external"):
506 self.state = VMStates['EXTERNAL']
ager@chromium.org381abbb2009-02-25 13:23:22 +0000507 if key in ("--ignore-unknown"):
508 self.ignore_unknown = True
509 if key in ("--separate-ic"):
510 self.separate_ic = True
ager@chromium.org71daaf62009-04-01 07:22:49 +0000511 if key in ("--call-graph-json"):
512 self.call_graph_json = True
ager@chromium.org381abbb2009-02-25 13:23:22 +0000513 self.ProcessRequiredArgs(args)
514
515 def ProcessRequiredArgs(self, args):
516 return
517
518 def GetRequiredArgsNames(self):
519 return
520
521 def PrintUsageAndExit(self):
522 print('Usage: %(script_name)s --{%(opts)s} %(req_opts)s' % {
523 'script_name': os.path.basename(sys.argv[0]),
524 'opts': string.join(self.options, ','),
525 'req_opts': self.GetRequiredArgsNames()
526 })
527 sys.exit(2)
528
529 def RunLogfileProcessing(self, tick_processor):
ager@chromium.org71daaf62009-04-01 07:22:49 +0000530 tick_processor.ProcessLogfile(self.log_file, self.state, self.ignore_unknown,
531 self.separate_ic, self.call_graph_json)
ager@chromium.org381abbb2009-02-25 13:23:22 +0000532
533
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000534if __name__ == '__main__':
535 sys.exit('You probably want to run windows-tick-processor.py or linux-tick-processor.py.')