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