OLD | NEW |
(Empty) | |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // 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 |
| 28 // Load implementations from <project root>/tools. |
| 29 // Files: tools/splaytree.js tools/codemap.js tools/csvparser.js |
| 30 // Files: tools/consarray.js tools/profile.js tools/profile_view.js |
| 31 // Files: tools/logreader.js tools/tickprocessor.js |
| 32 // Env: TEST_FILE_NAME |
| 33 |
| 34 (function testArgumentsProcessor() { |
| 35 var p_default = new ArgumentsProcessor([]); |
| 36 assertTrue(p_default.parse()); |
| 37 assertEquals(ArgumentsProcessor.DEFAULTS, p_default.result()); |
| 38 |
| 39 var p_logFile = new ArgumentsProcessor(['logfile.log']); |
| 40 assertTrue(p_logFile.parse()); |
| 41 assertEquals('logfile.log', p_logFile.result().logFileName); |
| 42 |
| 43 var p_platformAndLog = new ArgumentsProcessor(['--windows', 'winlog.log']); |
| 44 assertTrue(p_platformAndLog.parse()); |
| 45 assertEquals('windows', p_platformAndLog.result().platform); |
| 46 assertEquals('winlog.log', p_platformAndLog.result().logFileName); |
| 47 |
| 48 var p_flags = new ArgumentsProcessor(['--gc', '--separate-ic']); |
| 49 assertTrue(p_flags.parse()); |
| 50 assertEquals(TickProcessor.VmStates.GC, p_flags.result().stateFilter); |
| 51 assertTrue(p_flags.result().separateIc); |
| 52 |
| 53 var p_nmAndLog = new ArgumentsProcessor(['--nm=mn', 'nmlog.log']); |
| 54 assertTrue(p_nmAndLog.parse()); |
| 55 assertEquals('mn', p_nmAndLog.result().nm); |
| 56 assertEquals('nmlog.log', p_nmAndLog.result().logFileName); |
| 57 |
| 58 var p_bad = new ArgumentsProcessor(['--unknown', 'badlog.log']); |
| 59 assertFalse(p_bad.parse()); |
| 60 })(); |
| 61 |
| 62 |
| 63 (function testUnixCppEntriesProvider() { |
| 64 var oldLoadSymbols = UnixCppEntriesProvider.prototype.loadSymbols; |
| 65 |
| 66 // shell executable |
| 67 UnixCppEntriesProvider.prototype.loadSymbols = function(libName) { |
| 68 this.symbols = [[ |
| 69 ' U operator delete[](void*)@@GLIBCXX_3.4', |
| 70 '08049790 T _init', |
| 71 '08049f50 T _start', |
| 72 '08139150 t v8::internal::Runtime_StringReplaceRegExpWithString(v8::intern
al::Arguments)', |
| 73 '08139ca0 T v8::internal::Runtime::GetElementOrCharAt(v8::internal::Handle
<v8::internal::Object>, unsigned int)', |
| 74 '0813a0b0 t v8::internal::Runtime_DebugGetPropertyDetails(v8::internal::Ar
guments)', |
| 75 '08181d30 W v8::internal::RegExpMacroAssemblerIrregexp::stack_limit_slack(
)', |
| 76 ' w __gmon_start__', |
| 77 '081f08a0 B stdout' |
| 78 ].join('\n'), '']; |
| 79 }; |
| 80 |
| 81 var shell_prov = new UnixCppEntriesProvider(); |
| 82 var shell_syms = []; |
| 83 shell_prov.parseVmSymbols('shell', 0x08048000, 0x081ee000, |
| 84 function (name, start, end) { |
| 85 shell_syms.push(Array.prototype.slice.apply(arguments, [0])); |
| 86 }); |
| 87 assertEquals( |
| 88 [['_init', 0x08049790, 0x08049f50], |
| 89 ['_start', 0x08049f50, 0x08139150], |
| 90 ['v8::internal::Runtime_StringReplaceRegExpWithString(v8::internal::Argum
ents)', 0x08139150, 0x08139ca0], |
| 91 ['v8::internal::Runtime::GetElementOrCharAt(v8::internal::Handle<v8::inte
rnal::Object>, unsigned int)', 0x08139ca0, 0x0813a0b0], |
| 92 ['v8::internal::Runtime_DebugGetPropertyDetails(v8::internal::Arguments)'
, 0x0813a0b0, 0x08181d30], |
| 93 ['v8::internal::RegExpMacroAssemblerIrregexp::stack_limit_slack()', 0x081
81d30, 0x081ee000]], |
| 94 shell_syms); |
| 95 |
| 96 // libc library |
| 97 UnixCppEntriesProvider.prototype.loadSymbols = function(libName) { |
| 98 this.symbols = [[ |
| 99 '000162a0 T __libc_init_first', |
| 100 '0002a5f0 T __isnan', |
| 101 '0002a5f0 W isnan', |
| 102 '0002aaa0 W scalblnf', |
| 103 '0002aaa0 W scalbnf', |
| 104 '0011a340 T __libc_thread_freeres', |
| 105 '00128860 R _itoa_lower_digits'].join('\n'), '']; |
| 106 }; |
| 107 var libc_prov = new UnixCppEntriesProvider(); |
| 108 var libc_syms = []; |
| 109 libc_prov.parseVmSymbols('libc', 0xf7c5c000, 0xf7da5000, |
| 110 function (name, start, end) { |
| 111 libc_syms.push(Array.prototype.slice.apply(arguments, [0])); |
| 112 }); |
| 113 assertEquals( |
| 114 [['__libc_init_first', 0xf7c5c000 + 0x000162a0, 0xf7c5c000 + 0x0002a5f0], |
| 115 ['isnan', 0xf7c5c000 + 0x0002a5f0, 0xf7c5c000 + 0x0002aaa0], |
| 116 ['scalbnf', 0xf7c5c000 + 0x0002aaa0, 0xf7c5c000 + 0x0011a340], |
| 117 ['__libc_thread_freeres', 0xf7c5c000 + 0x0011a340, 0xf7da5000]], |
| 118 libc_syms); |
| 119 |
| 120 UnixCppEntriesProvider.prototype.loadSymbols = oldLoadSymbols; |
| 121 })(); |
| 122 |
| 123 |
| 124 (function testWindowsCppEntriesProvider() { |
| 125 var oldLoadSymbols = WindowsCppEntriesProvider.prototype.loadSymbols; |
| 126 |
| 127 WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) { |
| 128 this.symbols = [ |
| 129 ' Start Length Name Class', |
| 130 ' 0001:00000000 000ac902H .text CODE', |
| 131 ' 0001:000ac910 000005e2H .text$yc CODE', |
| 132 ' Address Publics by Value Rva+Base Lib:Object
', |
| 133 ' 0000:00000000 __except_list 00000000 <absolute>', |
| 134 ' 0001:00000000 ?ReadFile@@YA?AV?$Handle@VString@v8@@@v8@@PBD@Z 0040
1000 f shell.obj', |
| 135 ' 0001:000000a0 ?Print@@YA?AV?$Handle@VValue@v8@@@v8@@ABVArguments@2
@@Z 004010a0 f shell.obj', |
| 136 ' 0001:00001230 ??1UTF8Buffer@internal@v8@@QAE@XZ 00402230 f v8_sn
apshot:scanner.obj', |
| 137 ' 0001:00001230 ??1Utf8Value@String@v8@@QAE@XZ 00402230 f v8_snaps
hot:api.obj', |
| 138 ' 0001:000954ba __fclose_nolock 004964ba f LIBCMT:fclos
e.obj', |
| 139 ' 0002:00000000 __imp__SetThreadPriority@8 004af000 kernel32:KER
NEL32.dll', |
| 140 ' 0003:00000418 ?in_use_list_@PreallocatedStorage@internal@v8@@0V123
@A 00544418 v8_snapshot:allocation.obj', |
| 141 ' Static symbols', |
| 142 ' 0001:00000b70 ?DefaultFatalErrorHandler@v8@@YAXPBD0@Z 00401b70 f
v8_snapshot:api.obj', |
| 143 ' 0001:000010b0 ?EnsureInitialized@v8@@YAXPBD@Z 004020b0 f v8_snap
shot:api.obj', |
| 144 ' 0001:000ad17b ??__Fnomem@?5???2@YAPAXI@Z@YAXXZ 004ae17b f LIBCMT
:new.obj' |
| 145 ].join('\r\n'); |
| 146 }; |
| 147 var shell_prov = new WindowsCppEntriesProvider(); |
| 148 var shell_syms = []; |
| 149 shell_prov.parseVmSymbols('shell.exe', 0x00400000, 0x0057c000, |
| 150 function (name, start, end) { |
| 151 shell_syms.push(Array.prototype.slice.apply(arguments, [0])); |
| 152 }); |
| 153 assertEquals( |
| 154 [['ReadFile', 0x00401000, 0x004010a0], |
| 155 ['Print', 0x004010a0, 0x00402230], |
| 156 ['v8::String::?1Utf8Value', 0x00402230, 0x004964ba], |
| 157 ['v8::DefaultFatalErrorHandler', 0x00401b70, 0x004020b0], |
| 158 ['v8::EnsureInitialized', 0x004020b0, 0x0057c000]], |
| 159 shell_syms); |
| 160 |
| 161 WindowsCppEntriesProvider.prototype.loadSymbols = oldLoadSymbols; |
| 162 })(); |
| 163 |
| 164 |
| 165 function CppEntriesProviderMock() { |
| 166 }; |
| 167 |
| 168 |
| 169 CppEntriesProviderMock.prototype.parseVmSymbols = function( |
| 170 name, startAddr, endAddr, symbolAdder) { |
| 171 var symbols = { |
| 172 'shell': |
| 173 [['v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::St
ring*, v8::internal::LookupResult*)', 0x080f8800, 0x080f8d90], |
| 174 ['v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::inte
rnal::String*>::FindEntry(v8::internal::String*)', 0x080f8210, 0x080f8800], |
| 175 ['v8::internal::Runtime_Math_exp(v8::internal::Arguments)', 0x08123b20,
0x08123b80]], |
| 176 '/lib32/libm-2.7.so': |
| 177 [['exp', startAddr + 0x00009e80, startAddr + 0x00009f30], |
| 178 ['fegetexcept', startAddr + 0x000061e0, startAddr + 0x00008b10]], |
| 179 'ffffe000-fffff000': []}; |
| 180 assertTrue(name in symbols); |
| 181 var syms = symbols[name]; |
| 182 for (var i = 0; i < syms.length; ++i) { |
| 183 symbolAdder.apply(null, syms[i]); |
| 184 } |
| 185 }; |
| 186 |
| 187 |
| 188 function PrintMonitor(outputOrFileName) { |
| 189 var expectedOut = typeof outputOrFileName == 'string' ? |
| 190 this.loadExpectedOutput(outputOrFileName) : outputOrFileName; |
| 191 var outputPos = 0; |
| 192 var diffs = this.diffs = []; |
| 193 var realOut = this.realOut = []; |
| 194 |
| 195 this.oldPrint = print; |
| 196 print = function(str) { |
| 197 var strSplit = str.split('\n'); |
| 198 for (var i = 0; i < strSplit.length; ++i) { |
| 199 s = strSplit[i]; |
| 200 realOut.push(s); |
| 201 assertTrue(outputPos < expectedOut.length, |
| 202 'unexpected output: "' + s + '"'); |
| 203 if (expectedOut[outputPos] != s) { |
| 204 diffs.push('line ' + outputPos + ': expected <' + |
| 205 expectedOut[outputPos] + '> found <' + s + '>\n'); |
| 206 } |
| 207 outputPos++; |
| 208 } |
| 209 }; |
| 210 }; |
| 211 |
| 212 |
| 213 PrintMonitor.prototype.loadExpectedOutput = function(fileName) { |
| 214 var output = readFile(fileName); |
| 215 return output.split('\n'); |
| 216 }; |
| 217 |
| 218 |
| 219 PrintMonitor.prototype.finish = function() { |
| 220 print = this.oldPrint; |
| 221 if (this.diffs.length > 0) { |
| 222 print(this.realOut.join('\n')); |
| 223 assertEquals([], this.diffs); |
| 224 } |
| 225 }; |
| 226 |
| 227 |
| 228 function driveTickProcessorTest( |
| 229 separateIc, ignoreUnknown, stateFilter, logInput, refOutput) { |
| 230 // TEST_FILE_NAME must be provided by test runner. |
| 231 assertEquals('string', typeof TEST_FILE_NAME); |
| 232 var pathLen = TEST_FILE_NAME.lastIndexOf('/'); |
| 233 if (pathLen == -1) { |
| 234 pathLen = TEST_FILE_NAME.lastIndexOf('\\'); |
| 235 } |
| 236 assertTrue(pathLen != -1); |
| 237 var testsPath = TEST_FILE_NAME.substr(0, pathLen + 1); |
| 238 var tp = new TickProcessor( |
| 239 new CppEntriesProviderMock(), separateIc, ignoreUnknown, stateFilter); |
| 240 var pm = new PrintMonitor(testsPath + refOutput); |
| 241 tp.processLogFile(testsPath + logInput); |
| 242 // Hack file name to avoid dealing with platform specifics. |
| 243 tp.lastLogFileName_ = 'v8.log'; |
| 244 tp.printStatistics(); |
| 245 pm.finish(); |
| 246 }; |
| 247 |
| 248 |
| 249 (function testProcessing() { |
| 250 var testData = { |
| 251 'Default': [ |
| 252 false, false, null, |
| 253 'tickprocessor-test.log', 'tickprocessor-test.default'], |
| 254 'SeparateIc': [ |
| 255 true, false, null, |
| 256 'tickprocessor-test.log', 'tickprocessor-test.separate-ic'], |
| 257 'IgnoreUnknown': [ |
| 258 false, true, null, |
| 259 'tickprocessor-test.log', 'tickprocessor-test.ignore-unknown'], |
| 260 'GcState': [ |
| 261 false, false, TickProcessor.VmStates.GC, |
| 262 'tickprocessor-test.log', 'tickprocessor-test.gc-state'] |
| 263 }; |
| 264 for (var testName in testData) { |
| 265 print('=== testProcessing-' + testName + ' ==='); |
| 266 driveTickProcessorTest.apply(null, testData[testName]); |
| 267 } |
| 268 })(); |
OLD | NEW |