| // Copyright 2017 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| function inherits(childCtor, parentCtor) { |
| childCtor.prototype.__proto__ = parentCtor.prototype; |
| }; |
| |
| /** |
| * A thin wrapper around shell's 'read' function showing a file name on error. |
| */ |
| function readFile(fileName) { |
| try { |
| return read(fileName); |
| } catch (e) { |
| print(fileName + ': ' + (e.message || e)); |
| throw e; |
| } |
| } |
| |
| /** |
| * Parser for dynamic code optimization state. |
| */ |
| function parseState(s) { |
| switch (s) { |
| case "": return Profile.CodeState.COMPILED; |
| case "~": return Profile.CodeState.OPTIMIZABLE; |
| case "*": return Profile.CodeState.OPTIMIZED; |
| } |
| throw new Error("unknown code state: " + s); |
| } |
| |
| |
| function IcProcessor() { |
| var propertyICParser = [parseInt, parseInt, parseInt, null, null, parseInt, |
| null, null, null]; |
| LogReader.call(this, { |
| 'code-creation': { |
| parsers: [null, parseInt, parseInt, parseInt, parseInt, null, 'var-args'], |
| processor: this.processCodeCreation }, |
| 'code-move': { parsers: [parseInt, parseInt], |
| processor: this.processCodeMove }, |
| 'code-delete': { parsers: [parseInt], |
| processor: this.processCodeDelete }, |
| 'sfi-move': { parsers: [parseInt, parseInt], |
| processor: this.processFunctionMove }, |
| 'LoadIC': { |
| parsers : propertyICParser, |
| processor: this.processPropertyIC.bind(this, "LoadIC") }, |
| 'StoreIC': { |
| parsers : propertyICParser, |
| processor: this.processPropertyIC.bind(this, "StoreIC") }, |
| 'KeyedLoadIC': { |
| parsers : propertyICParser, |
| processor: this.processPropertyIC.bind(this, "KeyedLoadIC") }, |
| 'KeyedStoreIC': { |
| parsers : propertyICParser, |
| processor: this.processPropertyIC.bind(this, "KeyedStoreIC") }, |
| }); |
| this.deserializedEntriesNames_ = []; |
| this.profile_ = new Profile(); |
| |
| this.LoadIC = 0; |
| this.StoreIC = 0; |
| this.KeyedLoadIC = 0; |
| this.KeyedStoreIC = 0; |
| } |
| inherits(IcProcessor, LogReader); |
| |
| /** |
| * @override |
| */ |
| IcProcessor.prototype.printError = function(str) { |
| print(str); |
| }; |
| |
| IcProcessor.prototype.processString = function(string) { |
| var end = string.length; |
| var current = 0; |
| var next = 0; |
| var line; |
| var i = 0; |
| var entry; |
| while (current < end) { |
| next = string.indexOf("\n", current); |
| if (next === -1) break; |
| i++; |
| line = string.substring(current, next); |
| current = next + 1; |
| this.processLogLine(line); |
| } |
| } |
| |
| IcProcessor.prototype.processLogFile = function(fileName) { |
| this.collectEntries = true |
| this.lastLogFileName_ = fileName; |
| var line; |
| while (line = readline()) { |
| this.processLogLine(line); |
| } |
| print(); |
| print("====================="); |
| print("Load: " + this.LoadIC); |
| print("Store: " + this.StoreIC); |
| print("KeyedLoad: " + this.KeyedLoadIC); |
| print("KeyedStore: " + this.KeyedStoreIC); |
| }; |
| |
| IcProcessor.prototype.addEntry = function(entry) { |
| this.entries.push(entry); |
| } |
| |
| IcProcessor.prototype.processCodeCreation = function( |
| type, kind, timestamp, start, size, name, maybe_func) { |
| name = this.deserializedEntriesNames_[start] || name; |
| if (name.startsWith("onComplete")) { |
| console.log(name); |
| } |
| if (maybe_func.length) { |
| var funcAddr = parseInt(maybe_func[0]); |
| var state = parseState(maybe_func[1]); |
| this.profile_.addFuncCode(type, name, timestamp, start, size, funcAddr, state); |
| } else { |
| this.profile_.addCode(type, name, timestamp, start, size); |
| } |
| }; |
| |
| |
| IcProcessor.prototype.processCodeMove = function(from, to) { |
| this.profile_.moveCode(from, to); |
| }; |
| |
| |
| IcProcessor.prototype.processCodeDelete = function(start) { |
| this.profile_.deleteCode(start); |
| }; |
| |
| |
| IcProcessor.prototype.processFunctionMove = function(from, to) { |
| this.profile_.moveFunc(from, to); |
| }; |
| |
| IcProcessor.prototype.formatName = function(entry) { |
| if (!entry) return "<unknown>" |
| var name = entry.func.getName(); |
| var re = /(.*):[0-9]+:[0-9]+$/; |
| var array = re.exec(name); |
| if (!array) return name; |
| return entry.getState() + array[1]; |
| } |
| |
| IcProcessor.prototype.processPropertyIC = function ( |
| type, pc, line, column, old_state, new_state, map, name, modifier, |
| slow_reason) { |
| this[type]++; |
| var entry = this.profile_.findEntry(pc); |
| print(type + " (" + old_state + "->" + new_state + modifier + ") at " + |
| this.formatName(entry) + ":" + line + ":" + column + " " + name + |
| " (map 0x" + map.toString(16) + ")" + |
| (slow_reason ? " " + slow_reason : "")); |
| } |
| |
| |
| class ArgumentsProcessor extends BaseArgumentsProcessor { |
| getArgsDispatch() { |
| return { |
| '--range': ['range', 'auto,auto', |
| 'Specify the range limit as [start],[end]'], |
| '--source-map': ['sourceMap', null, |
| 'Specify the source map that should be used for output'] |
| }; |
| } |
| getDefaultResults() { |
| return { |
| logFileName: 'v8.log', |
| range: 'auto,auto', |
| }; |
| } |
| } |