| // 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', | |
| }; | |
| } | |
| } |