Commit ed7e4554 authored by Camillo Bruni's avatar Camillo Bruni Committed by V8 LUCI CQ

[mjsunit][tools][d8] Full roundtrip tickprocessor test

- Add os.d8Path property
- Add os.name property
- Change tickprocssor test to use command line arguments for testing
  various configurations
- Change tickprocessor test to create a temporary v8.log and read it
  back in on linux only
- Rearrange code in tickprocessor.mjs to allow instantiating the
  CppEntriesProvider directly
- Drop complete symbol-list for tickprocessor-test-large.log for better
  code searching in V8

Change-Id: Ib56dd0a1ba5377282c84c4de6f17e2fd69ee8123
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2929120Reviewed-by: 's avatarPatrick Thier <pthier@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74892}
parent 98629925
......@@ -2800,6 +2800,24 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
Local<ObjectTemplate> Shell::CreateOSTemplate(Isolate* isolate) {
Local<ObjectTemplate> os_template = ObjectTemplate::New(isolate);
AddOSMethods(isolate, os_template);
#if V8_TARGET_OS_LINUX
const char os_name[] = "linux";
#elif V8_TARGET_OS_WIN
const char os_name[] = "windows";
#elif V8_TARGET_OS_MACOSX
const char os_name[] = "macos";
#elif V8_TARGET_OS_ANDROID
const char os_name[] = "android";
#else
const char os_name[] = "unknown";
#endif
os_template->Set(isolate, "name",
v8::String::NewFromUtf8Literal(isolate, os_name),
PropertyAttribute::ReadOnly);
os_template->Set(
isolate, "d8Path",
v8::String::NewFromUtf8(isolate, options.d8_path).ToLocalChecked(),
PropertyAttribute::ReadOnly);
return os_template;
}
......@@ -4117,6 +4135,7 @@ void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) {
bool Shell::SetOptions(int argc, char* argv[]) {
bool logfile_per_isolate = false;
bool no_always_opt = false;
options.d8_path = argv[0];
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--") == 0) {
argv[i] = nullptr;
......
......@@ -351,6 +351,7 @@ class ShellOptions {
bool specified_ = false;
};
DisallowReassignment<const char*> d8_path = {"d8-path", ""};
DisallowReassignment<bool> fuzzilli_coverage_statistics = {
"fuzzilli-coverage-statistics", false};
DisallowReassignment<bool> fuzzilli_enable_builtins_coverage = {
......@@ -541,29 +542,30 @@ class Shell : public i::AllStatic {
// milliseconds on the total running time of the program. Exceptions are
// thrown on timeouts or other errors or if the exit status of the program
// indicates an error.
//
static void System(const v8::FunctionCallbackInfo<v8::Value>& args);
// os.chdir(dir) changes directory to the given directory. Throws an
// exception/ on error.
//
static void ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
// os.setenv(variable, value) sets an environment variable. Repeated calls to
// this method leak memory due to the API of setenv in the standard C library.
//
static void SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
static void UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
// os.umask(alue) calls the umask system call and returns the old umask.
//
static void SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args);
// os.mkdirp(name, mask) creates a directory. The mask (if present) is anded
// with the current umask. Intermediate directories are created if necessary.
// An exception is not thrown if the directory already exists. Analogous to
// the "mkdir -p" command.
static void System(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
static void UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args);
static void MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
static MaybeLocal<Promise> HostImportModuleDynamically(
Local<Context> context, Local<ScriptOrModule> referrer,
Local<String> specifier, Local<FixedArray> import_assertions);
static void ModuleResolutionSuccessCallback(
const v8::FunctionCallbackInfo<v8::Value>& info);
static void ModuleResolutionFailureCallback(
......
......@@ -41,6 +41,10 @@ function arg_error(str) {
}
}
const kOsNameValues = ['linux', 'macos', 'windows', 'android', 'unknown'];
assertTrue(kOsNameValues.includes(os.name));
assertTrue(os.d8Path.length > 0);
function str_error(str) {
var e = new Object();
......
......@@ -2,49 +2,30 @@ Statistical profiling result from v8.log, (303 ticks, 0 unaccounted, 0 excluded)
[Shared libraries]:
ticks total nonlib name
9 3.0% /usr/local/google/home/cbruni/Documents/v8/v8/out/x64.release/d8
6 2.0% /usr/lib/x86_64-linux-gnu/libc-2.31.so
24 7.9% /usr/local/google/home/cbruni/Documents/v8/v8/out/x64.release/d8
10 3.3% /usr/lib/x86_64-linux-gnu/libc-2.31.so
4 1.3% /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
[JavaScript]:
ticks total nonlib name
102 33.7% 35.4% LazyCompile: *<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
25 8.3% 8.7% LazyCompile: *ics test/mjsunit/tools/tickprocessor-test.js:47:13
21 6.9% 7.3% LazyCompile: *loop test/mjsunit/tools/tickprocessor-test.js:10:14
102 33.7% 38.5% LazyCompile: *<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
25 8.3% 9.4% LazyCompile: *ics test/mjsunit/tools/tickprocessor-test.js:47:13
21 6.9% 7.9% LazyCompile: *loop test/mjsunit/tools/tickprocessor-test.js:10:14
[C++]:
ticks total nonlib name
99 32.7% 34.4% v8_Default_embedded_blob_code_data_
12 4.0% 4.2% __write
3 1.0% 1.0% fwrite
2 0.7% 0.7% v8::internal::RootScavengeVisitor::VisitRootPointer(v8::internal::Root, char const*, v8::internal::FullObjectSlot)
2 0.7% 0.7% __pthread_mutex_unlock_usercnt
2 0.7% 0.7% __libc_malloc
2 0.7% 0.7% _IO_file_xsputn
1 0.3% 0.3% v8::internal::compiler::TopLevelLiveRange::AddUseInterval(v8::internal::compiler::LifetimePosition, v8::internal::compiler::LifetimePosition, v8::internal::Zone*, bool)
1 0.3% 0.3% v8::internal::compiler::Scheduler::PrepareUses()
1 0.3% 0.3% v8::internal::compiler::CommonOperatorBuilder::CommonOperatorBuilder(v8::internal::Zone*)
1 0.3% 0.3% v8::internal::SpaceWithLinearArea::AdvanceAllocationObservers()
1 0.3% 0.3% v8::internal::SerializerDeserializer::Iterate(v8::internal::Isolate*, v8::internal::RootVisitor*)
1 0.3% 0.3% v8::internal::Log::MessageBuilder::AppendString(char const*, unsigned long, bool)
1 0.3% 0.3% v8::internal::LargeObjectSpace::SizeOfObjects()
1 0.3% 0.3% v8::internal::Heap::Scavenge()
1 0.3% 0.3% v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment)
1 0.3% 0.3% v8::internal::Heap::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment)
1 0.3% 0.3% v8::OutputStream::GetChunkSize()
1 0.3% 0.3% std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > std::__1::__pad_and_output<char, std::__1::char_traits<char> >(std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >, char const*, char const*, char const*, std::__1::ios_base&, char)
1 0.3% 0.3% std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > >::do_put(std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::ios_base&, char, long) const
1 0.3% 0.3% std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(unsigned long)
1 0.3% 0.3% int v8::internal::Deserializer::ReadSingleBytecodeData<v8::internal::SlotAccessorForHeapObject>(unsigned char, v8::internal::SlotAccessorForHeapObject)
1 0.3% 0.3% __pthread_cond_wait
1 0.3% 0.3% __pthread_cond_signal
1 0.3% 0.3% Cr_z_inflate_fast_chunk_
99 32.7% 37.4% v8_Default_embedded_blob_code_data_
12 4.0% 4.5% __write
3 1.0% 1.1% fwrite
2 0.7% 0.8% v8::internal::RootScavengeVisitor::VisitRootPointer(v8::internal::Root, char const*, v8::internal::FullObjectSlot)
1 0.3% 0.4% v8::internal::compiler::TopLevelLiveRange::AddUseInterval(v8::internal::compiler::LifetimePosition, v8::internal::compiler::LifetimePosition, v8::internal::Zone*, bool)
[Summary]:
ticks total nonlib name
148 48.8% 51.4% JavaScript
140 46.2% 48.6% C++
20 6.6% 6.9% GC
15 5.0% Shared libraries
148 48.8% 55.8% JavaScript
117 38.6% 44.2% C++
20 6.6% 7.5% GC
38 12.5% Shared libraries
[C++ entry points]:
ticks cpp total name
......@@ -69,17 +50,25 @@ Statistical profiling result from v8.log, (303 ticks, 0 unaccounted, 0 excluded)
25 8.3% LazyCompile: *ics test/mjsunit/tools/tickprocessor-test.js:47:13
25 100.0% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
24 7.9% /usr/local/google/home/cbruni/Documents/v8/v8/out/x64.release/d8
4 16.7% LazyCompile: ~ics test/mjsunit/tools/tickprocessor-test.js:47:13
4 100.0% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
3 12.5% v8::internal::Runtime_CompileForOnStackReplacement(int, unsigned long*, v8::internal::Isolate*)
2 66.7% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
1 33.3% LazyCompile: ~loop test/mjsunit/tools/tickprocessor-test.js:10:14
1 100.0% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
2 8.3% v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*)
2 100.0% LazyCompile: *<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
2 8.3% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
2 8.3% LazyCompile: ~read_megamorphic test/mjsunit/tools/tickprocessor-test.js:35:26
2 100.0% LazyCompile: ~ics test/mjsunit/tools/tickprocessor-test.js:47:13
2 100.0% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
21 6.9% LazyCompile: *loop test/mjsunit/tools/tickprocessor-test.js:10:14
21 100.0% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
12 4.0% __write
9 3.0% /usr/local/google/home/cbruni/Documents/v8/v8/out/x64.release/d8
4 44.4% LazyCompile: ~ics test/mjsunit/tools/tickprocessor-test.js:47:13
4 100.0% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
2 22.2% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
2 22.2% LazyCompile: ~read_megamorphic test/mjsunit/tools/tickprocessor-test.js:35:26
2 100.0% LazyCompile: ~ics test/mjsunit/tools/tickprocessor-test.js:47:13
2 100.0% Script: ~<anonymous> test/mjsunit/tools/tickprocessor-test.js:1:1
10 3.3% /usr/lib/x86_64-linux-gnu/libc-2.31.so
6 2.0% /usr/lib/x86_64-linux-gnu/libc-2.31.so
4 1.3% /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
......@@ -53,6 +53,6 @@ function ics() {
}
}
for (let i = 0; i < 100_000; i++) {
for (let i = 0; i < 10_000; i++) {
ics();
}
......@@ -25,9 +25,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --enable-os-system
// Resources: test/mjsunit/tools/tickprocessor-test-func-info.log
// Resources: test/mjsunit/tools/tickprocessor-test-func-info.log.symbols.json
// Resources: test/mjsunit/tools/tickprocessor-test-large.default
// Resources: test/mjsunit/tools/tickprocessor-test-large.js
// Resources: test/mjsunit/tools/tickprocessor-test-large.log
// Resources: test/mjsunit/tools/tickprocessor-test-large.log.symbols.json
// Resources: test/mjsunit/tools/tickprocessor-test.default
......@@ -40,23 +42,12 @@
// Resources: test/mjsunit/tools/tickprocessor-test.separate-baseline-handlers
// Resources: test/mjsunit/tools/tickprocessor-test.separate-bytecodes
// Resources: test/mjsunit/tools/tickprocessor-test.separate-ic
// Env: TEST_FILE_NAME
import {
TickProcessor, ArgumentsProcessor, UnixCppEntriesProvider,
MacCppEntriesProvider, WindowsCppEntriesProvider
MacCppEntriesProvider, WindowsCppEntriesProvider
} from "../../../tools/tickprocessor.mjs";
// TODO(cbruni): Remove after refactoring
export function readFile(fileName) {
try {
return read(fileName);
} catch (e) {
console.log(fileName + ': ' + (e.message || e));
throw e;
}
}
(function testArgumentsProcessor() {
var p_default = new ArgumentsProcessor([]);
assertTrue(p_default.parse());
......@@ -372,7 +363,7 @@ export function readFile(fileName) {
class CppEntriesProviderMock {
constructor(filename) {
this.isLoaded = false;
this.symbols = JSON.parse(readFile(filename));
this.symbols = JSON.parse(d8.file.read(filename));
}
parseVmSymbols(name, startAddr, endAddr, slideAddr, symbolAdder) {
if (this.isLoaded) return;
......@@ -392,17 +383,17 @@ class PrintMonitor {
this.expectedOut = this.loadExpectedOutput(outputOrFileName)
this.outputFile = outputOrFileName;
}
var expectedOut = this.expectedOut;
var outputPos = 0;
var diffs = this.diffs = [];
var realOut = this.realOut = [];
var unexpectedOut = this.unexpectedOut = null;
let expectedOut = this.expectedOut;
let outputPos = 0;
let diffs = this.diffs = [];
let realOut = this.realOut = [];
let unexpectedOut = this.unexpectedOut = null;
this.oldPrint = print;
print = function(str) {
var strSplit = str.split('\n');
for (var i = 0; i < strSplit.length; ++i) {
var s = strSplit[i];
const strSplit = str.split('\n');
for (let i = 0; i < strSplit.length; ++i) {
const s = strSplit[i];
realOut.push(s);
if (outputPos < expectedOut.length) {
if (expectedOut[outputPos] != s) {
......@@ -418,98 +409,95 @@ class PrintMonitor {
}
loadExpectedOutput(fileName) {
var output = readFile(fileName);
const output = d8.file.read(fileName);
return output.split('\n');
}
finish() {
print = this.oldPrint;
if (this.diffs.length > 0 || this.unexpectedOut != null) {
console.log("===== actual output: =====");
console.log(this.realOut.join('\n'));
console.log("===== expected output: =====");
if (this.outputFile) {
console.log("===== File: " + this.outputFile + " =====");
}
console.log(this.expectedOut.join('\n'));
if (this.diffs.length > 0) {
this.diffs.forEach(line => console.log(line))
assertEquals([], this.diffs);
}
assertNull(this.unexpectedOut);
if (this.diffs.length == 0 && this.unexpectedOut == null) return;
console.log("===== actual output: =====");
console.log(this.realOut.join('\n'));
console.log("===== expected output: =====");
if (this.outputFile) {
console.log("===== File: " + this.outputFile + " =====");
}
console.log(this.expectedOut.join('\n'));
if (this.diffs.length > 0) {
this.diffs.forEach(line => console.log(line))
assertEquals([], this.diffs);
}
assertNull(this.unexpectedOut);
}
}
function driveTickProcessorTest(
separateIc, separateBytecodes, separateBuiltins, separateStubs,
separateBaselineHandlers, ignoreUnknown, stateFilter, logInput,
refOutput, onlySummary) {
// TEST_FILE_NAME must be provided by test runner.
assertEquals('string', typeof TEST_FILE_NAME);
var pathLen = TEST_FILE_NAME.lastIndexOf('/');
if (pathLen == -1) {
pathLen = TEST_FILE_NAME.lastIndexOf('\\');
}
assertTrue(pathLen != -1);
const testsPath = TEST_FILE_NAME.substr(0, pathLen + 1);
const symbolsFile = testsPath + logInput + '.symbols.json';
const tp = new TickProcessor(new CppEntriesProviderMock(symbolsFile),
separateIc,
separateBytecodes,
separateBuiltins,
separateStubs,
separateBaselineHandlers,
TickProcessor.CALL_GRAPH_SIZE,
ignoreUnknown,
stateFilter,
"0",
"auto,auto",
null,
false,
false,
onlySummary);
const pm = new PrintMonitor(testsPath + refOutput);
tp.processLogFileInTest(testsPath + logInput);
tp.printStatistics();
pm.finish();
};
(function testProcessing() {
var testData = {
const testData = {
'Default': [
false, false, true, true, false, false, null,
'tickprocessor-test.log', 'tickprocessor-test.default', false],
'tickprocessor-test.log', 'tickprocessor-test.default',
['--separate-ic=false']],
'SeparateBytecodes': [
false, true, true, true, false, false, null,
'tickprocessor-test.log', 'tickprocessor-test.separate-bytecodes', false],
'tickprocessor-test.log', 'tickprocessor-test.separate-bytecodes',
['--separate-ic=false', '--separate-bytecodes']],
'SeparateBaselineHandlers': [
false, false, true, true, true, false, null,
'tickprocessor-test.log', 'tickprocessor-test.separate-baseline-handlers', false],
'tickprocessor-test.log', 'tickprocessor-test.separate-baseline-handlers',
['--separate-ic=false', '--separate-baseline-handlers']],
'SeparateIc': [
true, false, true, true, false, false, null,
'tickprocessor-test.log', 'tickprocessor-test.separate-ic', false],
'tickprocessor-test.log', 'tickprocessor-test.separate-ic',
['--separate-ic=true']],
'IgnoreUnknown': [
false, false, true, true, false, true, null,
'tickprocessor-test.log', 'tickprocessor-test.ignore-unknown', false],
'tickprocessor-test.log', 'tickprocessor-test.ignore-unknown',
['--separate-ic=false', '--ignore-unknown']],
'GcState': [
false, false, true, true, false, false, TickProcessor.VmStates.GC,
'tickprocessor-test.log', 'tickprocessor-test.gc-state', false],
'tickprocessor-test.log', 'tickprocessor-test.gc-state', ['-g']],
'OnlySummary': [
false, false, true, true, false, false, null,
'tickprocessor-test.log', 'tickprocessor-test.only-summary', true],
'tickprocessor-test.log', 'tickprocessor-test.only-summary',
['--separate-ic=false', '--only-summary']],
'FunctionInfo': [
false, false, true, true, false, false, null,
'tickprocessor-test-func-info.log', 'tickprocessor-test.func-info',
false],
['']
],
'DefaultLarge': [
false, false, true, true, false, false, null,
'tickprocessor-test-large.log', 'tickprocessor-test-large.default', false],
'tickprocessor-test-large.log', 'tickprocessor-test-large.default'],
};
for (var testName in testData) {
console.log('=== testProcessing-' + testName + ' ===');
driveTickProcessorTest(...testData[testName]);
testTickProcessor(...testData[testName]);
}
})();
function testTickProcessor(logInput, refOutput, args=[]) {
// /foo/bar/tickprocesser.mjs => /foo/bar/
const dir = import.meta.url.split("/").slice(0, -1).join('/') + '/';
const params = ArgumentsProcessor.process(args);
testExpectations(dir + logInput, dir + refOutput, params);
testEndToEnd(dir + 'tickprocessor-test-large.js', dir + refOutput, params);
}
function testExpectations(logInput, refOutput, params) {
const symbolsFile = logInput + '.symbols.json';
const cppEntries = new CppEntriesProviderMock(symbolsFile);
const tickProcessor = TickProcessor.fromParams(params, cppEntries);
const printMonitor = new PrintMonitor(refOutput);
tickProcessor.processLogFileInTest(logInput);
tickProcessor.printStatistics();
printMonitor.finish();
};
function testEndToEnd(sourceFile, ignoredRefOutput, params) {
// This test only works on linux.
if (!os?.system) return;
if (os.name !== 'linux' && os.name !== 'macos') return;
params.platform = os.name;
const tmpLogFile= `/var/tmp/${Date.now()}.v8.log`
const result = os.system(
os.d8Path, ['--prof', `--logfile=${tmpLogFile}`, sourceFile]);
const tickProcessor = TickProcessor.fromParams(params);
// We will not always get the same ticks due to timing on bots,
// hence we cannot properly compare output expectations.
// Let's just use a dummy file and only test whether we don't throw.
const printMonitor = new PrintMonitor(ignoredRefOutput);
tickProcessor.processLogFileInTest(tmpLogFile);
tickProcessor.printStatistics();
}
\ No newline at end of file
......@@ -25,41 +25,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import {
ArgumentsProcessor, TickProcessor, UnixCppEntriesProvider,
WindowsCppEntriesProvider, MacCppEntriesProvider
} from "./tickprocessor.mjs";
// Tick Processor's code flow.
const entriesProviders = {
'unix': UnixCppEntriesProvider,
'windows': WindowsCppEntriesProvider,
'mac': MacCppEntriesProvider
};
import { ArgumentsProcessor, TickProcessor } from "./tickprocessor.mjs";
const params = ArgumentsProcessor.process(arguments);
const tickProcessor = new TickProcessor(
new (entriesProviders[params.platform])(params.nm, params.objdump, params.targetRootFS,
params.apkEmbeddedLibrary),
params.separateIc,
params.separateBytecodes,
params.separateBuiltins,
params.separateStubs,
params.separateBaselineHandlers,
params.callGraphSize,
params.ignoreUnknown,
params.stateFilter,
params.distortion,
params.range,
params.sourceMap,
params.timedRange,
params.pairwiseTimedRange,
params.onlySummary,
params.runtimeTimerFilter,
params.preprocessJson);
const tickProcessor = TickProcessor.fromParams(params);
tickProcessor.processLogFile(params.logFileName);
if (params.serializeVMSymbols) {
tickProcessor.printVMSymbols();
} else {
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment