1// Copyright 2017 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5function inherits(childCtor, parentCtor) { 6 childCtor.prototype.__proto__ = parentCtor.prototype; 7}; 8 9/** 10 * A thin wrapper around shell's 'read' function showing a file name on error. 11 */ 12function readFile(fileName) { 13 try { 14 return read(fileName); 15 } catch (e) { 16 print(fileName + ': ' + (e.message || e)); 17 throw e; 18 } 19} 20 21/** 22 * Parser for dynamic code optimization state. 23 */ 24function parseState(s) { 25 switch (s) { 26 case "": return Profile.CodeState.COMPILED; 27 case "~": return Profile.CodeState.OPTIMIZABLE; 28 case "*": return Profile.CodeState.OPTIMIZED; 29 } 30 throw new Error("unknown code state: " + s); 31} 32 33 34function IcProcessor() { 35 var propertyICParser = [parseInt, parseInt, parseInt, parseString, 36 parseString, parseInt, parseString, parseString, parseString]; 37 LogReader.call(this, { 38 'code-creation': { 39 parsers: [parseString, parseInt, parseInt, parseInt, parseInt, 40 parseString, parseVarArgs], 41 processor: this.processCodeCreation }, 42 'code-move': { parsers: [parseInt, parseInt], 43 processor: this.processCodeMove }, 44 'code-delete': { parsers: [parseInt], 45 processor: this.processCodeDelete }, 46 'sfi-move': { parsers: [parseInt, parseInt], 47 processor: this.processFunctionMove }, 48 'LoadIC': { 49 parsers : propertyICParser, 50 processor: this.processPropertyIC.bind(this, "LoadIC") }, 51 'StoreIC': { 52 parsers : propertyICParser, 53 processor: this.processPropertyIC.bind(this, "StoreIC") }, 54 'KeyedLoadIC': { 55 parsers : propertyICParser, 56 processor: this.processPropertyIC.bind(this, "KeyedLoadIC") }, 57 'KeyedStoreIC': { 58 parsers : propertyICParser, 59 processor: this.processPropertyIC.bind(this, "KeyedStoreIC") }, 60 'StoreInArrayLiteralIC': { 61 parsers : propertyICParser, 62 processor: this.processPropertyIC.bind(this, "StoreInArrayLiteralIC") }, 63 }); 64 this.profile_ = new Profile(); 65 66 this.LoadIC = 0; 67 this.StoreIC = 0; 68 this.KeyedLoadIC = 0; 69 this.KeyedStoreIC = 0; 70 this.StoreInArrayLiteralIC = 0; 71} 72inherits(IcProcessor, LogReader); 73 74/** 75 * @override 76 */ 77IcProcessor.prototype.printError = function(str) { 78 print(str); 79}; 80 81IcProcessor.prototype.processString = function(string) { 82 var end = string.length; 83 var current = 0; 84 var next = 0; 85 var line; 86 var i = 0; 87 var entry; 88 while (current < end) { 89 next = string.indexOf("\n", current); 90 if (next === -1) break; 91 i++; 92 line = string.substring(current, next); 93 current = next + 1; 94 this.processLogLine(line); 95 } 96} 97 98IcProcessor.prototype.processLogFile = function(fileName) { 99 this.collectEntries = true 100 this.lastLogFileName_ = fileName; 101 var line; 102 while (line = readline()) { 103 this.processLogLine(line); 104 } 105 print(); 106 print("====================="); 107 print("Load: " + this.LoadIC); 108 print("Store: " + this.StoreIC); 109 print("KeyedLoad: " + this.KeyedLoadIC); 110 print("KeyedStore: " + this.KeyedStoreIC); 111 print("StoreInArrayLiteral: " + this.StoreInArrayLiteralIC); 112}; 113 114IcProcessor.prototype.addEntry = function(entry) { 115 this.entries.push(entry); 116} 117 118IcProcessor.prototype.processCodeCreation = function( 119 type, kind, timestamp, start, size, name, maybe_func) { 120 if (maybe_func.length) { 121 var funcAddr = parseInt(maybe_func[0]); 122 var state = parseState(maybe_func[1]); 123 this.profile_.addFuncCode(type, name, timestamp, start, size, funcAddr, state); 124 } else { 125 this.profile_.addCode(type, name, timestamp, start, size); 126 } 127}; 128 129 130IcProcessor.prototype.processCodeMove = function(from, to) { 131 this.profile_.moveCode(from, to); 132}; 133 134 135IcProcessor.prototype.processCodeDelete = function(start) { 136 this.profile_.deleteCode(start); 137}; 138 139 140IcProcessor.prototype.processFunctionMove = function(from, to) { 141 this.profile_.moveFunc(from, to); 142}; 143 144IcProcessor.prototype.formatName = function(entry) { 145 if (!entry) return "<unknown>" 146 var name = entry.func.getName(); 147 var re = /(.*):[0-9]+:[0-9]+$/; 148 var array = re.exec(name); 149 if (!array) return name; 150 return entry.getState() + array[1]; 151} 152 153IcProcessor.prototype.processPropertyIC = function ( 154 type, pc, line, column, old_state, new_state, map, name, modifier, 155 slow_reason) { 156 this[type]++; 157 var entry = this.profile_.findEntry(pc); 158 print(type + " (" + old_state + "->" + new_state + modifier + ") at " + 159 this.formatName(entry) + ":" + line + ":" + column + " " + name + 160 " (map 0x" + map.toString(16) + ")" + 161 (slow_reason ? " " + slow_reason : "")); 162} 163 164 165class ArgumentsProcessor extends BaseArgumentsProcessor { 166 getArgsDispatch() { 167 return { 168 '--range': ['range', 'auto,auto', 169 'Specify the range limit as [start],[end]'], 170 '--source-map': ['sourceMap', null, 171 'Specify the source map that should be used for output'] 172 }; 173 } 174 getDefaultResults() { 175 return { 176 logFileName: 'v8.log', 177 range: 'auto,auto', 178 }; 179 } 180} 181