diff options
author | Ben Murdoch <benm@google.com> | 2016-08-08 18:44:38 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2016-08-08 18:53:09 +0100 |
commit | bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8 (patch) | |
tree | f29dbc902638cd0978d68e11ca4210b4d42ad94b /tools | |
parent | c760da5ef600c88c80b92873880fa8d221642e06 (diff) | |
download | v8-bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8.tar.gz |
Merge V8 5.2.361.47
https://chromium.googlesource.com/v8/v8/+/5.2.361.47
Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
Diffstat (limited to 'tools')
43 files changed, 3812 insertions, 2693 deletions
diff --git a/tools/blink_tests/TestExpectationsIgnition b/tools/blink_tests/TestExpectationsIgnition new file mode 100644 index 00000000..f2c912d2 --- /dev/null +++ b/tools/blink_tests/TestExpectationsIgnition @@ -0,0 +1,4 @@ +# Failures due to eager compilation, crbug/608287. +[ Linux ] inspector/sources/debugger-frameworks/frameworks-jquery.html [ Failure ] +[ Linux ] inspector-protocol/heap-profiler/heap-snapshot-with-active-dom-object.html [ Failure ] +[ Linux ] inspector-protocol/heap-profiler/heap-snapshot-with-detached-dom-tree.html [ Failure ] diff --git a/tools/callstats.html b/tools/callstats.html new file mode 100644 index 00000000..da85494f --- /dev/null +++ b/tools/callstats.html @@ -0,0 +1,1481 @@ +<html> +<!-- +Copyright 2016 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. +--> + +<head> + <meta charset="UTF-8"> + <style> + body { + font-family: arial; + } + + table { + display: table; + border-spacing: 0px; + } + + tr { + border-spacing: 0px; + padding: 10px; + } + + td, + th { + padding: 3px 10px 3px 5px; + } + + .inline { + display: inline-block; + vertical-align: top; + } + + h2, + h3 { + margin-bottom: 0px; + } + + .hidden { + display: none; + } + + .view { + display: table; + } + + .column { + display: table-cell; + border-right: 1px black dotted; + min-width: 200px; + } + + .column .header { + padding: 0 10px 0 10px + } + + #column { + display: none; + } + + .list { + width: 100%; + } + + select { + width: 100% + } + + .list tbody { + cursor: pointer; + } + + .list tr:nth-child(even) { + background-color: #EFEFEF; + } + + .list tr:nth-child(even).selected { + background-color: #DDD; + } + + .list tr.child { + display: none; + } + + .list tr.child.visible { + display: table-row; + } + + .list .child .name { + padding-left: 20px; + } + + .list .parent td { + border-top: 1px solid #AAA; + } + + .list .total { + font-weight: bold + } + + .list tr.parent { + background-color: #FFF; + } + + .list tr.parent.selected { + background-color: #DDD; + } + + tr.selected { + background-color: #DDD; + } + + .list .position { + text-align: right; + display: none; + } + + .list div.toggle { + cursor: pointer; + } + + #column_0 .position { + display: table-cell; + } + + #column_0 .name { + display: table-cell; + } + + .list .name { + display: none; + white-space: nowrap; + } + + .value { + text-align: right; + } + + .selectedVersion { + font-weight: bold; + } + + #baseline { + width: auto; + } + + .compareSelector { + padding-bottom: 20px; + } + + .pageDetailTable tbody { + cursor: pointer + } + + .pageDetailTable tfoot td { + border-top: 1px grey solid; + } + + #popover { + position: absolute; + transform: translateY(-50%) translateX(40px); + box-shadow: -2px 10px 44px -10px #000; + border-radius: 5px; + z-index: 1; + background-color: #FFF; + display: none; + white-space: nowrap; + } + + #popover table { + position: relative; + z-index: 1; + text-align: right; + margin: 10px; + } + #popover td { + padding: 3px 0px 3px 5px; + white-space: nowrap; + } + + .popoverArrow { + background-color: #FFF; + position: absolute; + width: 30px; + height: 30px; + transform: translateY(-50%)rotate(45deg); + top: 50%; + left: -10px; + z-index: 0; + } + + #popover .name { + padding: 5px; + font-weight: bold; + text-align: center; + } + + #popover table .compare { + display: none + } + + #popover table.compare .compare { + display: table-cell; + } + + #popover .compare .time, + #popover .compare .version { + padding-left: 10px; + } + </style> + <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> + <script type="text/javascript"> + "use strict" + google.charts.load('current', {packages: ['corechart']}); + + // Did anybody say monkeypatching? + if (!NodeList.prototype.forEach) { + NodeList.prototype.forEach = function(func) { + for (var i = 0; i < this.length; i++) { + func(this[i]); + } + } + } + + var versions; + var selectedPage; + var baselineVersion; + var selectedEntry; + + function initialize() { + var original = $("column"); + var view = document.createElement('div'); + view.id = 'view'; + var i = 0; + versions.forEach((version) => { + if (!version.enabled) return; + // add column + var column = original.cloneNode(true); + column.id = "column_" + i; + // Fill in all versions + var select = column.querySelector(".version"); + select.id = "selectVersion_" + i; + // add all select options + versions.forEach((version) => { + if (!version.enabled) return; + var option = document.createElement("option"); + option.textContent = version.name; + option.version = version; + select.appendChild(option); + }); + // Fill in all page versions + select = column.querySelector(".pageVersion"); + select.id = "select_" + i; + // add all pages + versions.forEach((version) => { + if (!version.enabled) return; + var optgroup = document.createElement("optgroup"); + optgroup.label = version.name; + optgroup.version = version; + version.pages.forEach((page) => { + var option = document.createElement("option"); + option.textContent = page.name; + option.page = page; + optgroup.appendChild(option); + }); + select.appendChild(optgroup); + }); + view.appendChild(column); + i++; + }); + var oldView = $('view'); + oldView.parentNode.replaceChild(view, oldView); + + var select = $('baseline'); + removeAllChildren(select); + select.appendChild(document.createElement('option')); + versions.forEach((version) => { + var option = document.createElement("option"); + option.textContent = version.name; + option.version = version; + select.appendChild(option); + }); + + var versionSelectorList = $('results').querySelector('.versionSelector ul'); + removeAllChildren(versionSelectorList); + versions.forEach((version) => { + var li = document.createElement('li'); + var checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.checked = version.enabled; + checkbox.version = version; + checkbox.addEventListener('click', handleToggleVersionEnable); + li.appendChild(checkbox); + li.appendChild(document.createTextNode(version.name)); + versionSelectorList.appendChild(li); + }); + $('results').querySelectorAll('#results > .hidden').forEach((node) => { + toggleCssClass(node, 'hidden', false); + }); + } + + function showPage(firstPage) { + var changeSelectedEntry = selectedEntry !== undefined + && selectedEntry.page === selectedPage; + selectedPage = firstPage; + selectedPage.sort(); + showPageInColumn(firstPage, 0); + // Show the other versions of this page in the following columns. + var pageVersions = versions.pageVersions(firstPage.name); + var index = 1; + pageVersions.forEach((page) => { + if (page !== firstPage) { + showPageInColumn(page, index); + index++; + } + }); + if (changeSelectedEntry) { + showEntryDetail(selectedPage.getEntry(selectedEntry)); + } else { + showImpactList(selectedPage); + } + } + + function showPageInColumn(page, columnIndex) { + page.sort(); + var showDiff = (baselineVersion === undefined && columnIndex !== 0) || + (baselineVersion !== undefined && page.version !== baselineVersion); + var diffStatus = (td, a, b) => {}; + if (showDiff) { + if (baselineVersion !== undefined) { + diffStatus = (td, a, b) => { + if (a == 0) return; + td.style.color = a < 0 ? '#FF0000' : '#00BB00'; + }; + } else { + diffStatus = (td, a, b) => { + if (a == b) return; + var color; + var ratio = a / b; + if (ratio > 1) { + ratio = Math.min(Math.round((ratio - 1) * 255 * 10), 200); + color = '#' + ratio.toString(16) + "0000"; + } else { + ratio = Math.min(Math.round((1 - ratio) * 255 * 10), 200); + color = '#00' + ratio.toString(16) + "00"; + } + td.style.color = color; + } + } + } + + var column = $('column_' + columnIndex); + var select = $('select_' + columnIndex); + // Find the matching option + selectOption(select, (i, option) => { + return option.page == page + }); + var table = column.querySelector("table"); + var oldTbody = table.querySelector('tbody'); + var tbody = document.createElement('tbody'); + var referencePage = selectedPage; + page.forEachSorted(selectedPage, (parentEntry, entry, referenceEntry) => { + // Filter out entries that do not exist in the first column for the default + // view. + if (baselineVersion === undefined && referenceEntry && + referenceEntry.time == 0) { + return; + } + var tr = document.createElement('tr'); + tbody.appendChild(tr); + tr.entry = entry; + tr.parentEntry = parentEntry; + tr.className = parentEntry === undefined ? 'parent' : 'child'; + // Don't show entries that do not exist on the current page or if we + // compare against the current page + if (entry !== undefined && page.version !== baselineVersion) { + // If we show a diff, use the baselineVersion as the referenceEntry + if (baselineVersion !== undefined) { + var baselineEntry = baselineVersion.getEntry(entry); + if (baselineEntry !== undefined) referenceEntry = baselineEntry + } + if (!parentEntry) { + var node = td(tr, '<div class="toggle">►</div>', 'position'); + node.firstChild.addEventListener('click', handleToggleGroup); + } else { + td(tr, entry.position == 0 ? '' : entry.position, 'position'); + } + td(tr, entry.name, 'name ' + entry.cssClass()); + diffStatus( + td(tr, ms(entry.time), 'value time'), + entry.time, referenceEntry.time); + diffStatus( + td(tr, percent(entry.timePercent), 'value time'), + entry.time, referenceEntry.time); + diffStatus( + td(tr, count(entry.count), 'value count'), + entry.count, referenceEntry.count); + } else if (baselineVersion !== undefined && referenceEntry + && page.version !== baselineVersion) { + // Show comparison of entry that does not exist on the current page. + tr.entry = referenceEntry; + td(tr, '-', 'position'); + td(tr, referenceEntry.name, 'name'); + diffStatus( + td(tr, ms(referenceEntry.time), 'value time'), + referenceEntry.time, 0); + diffStatus( + td(tr, percent(referenceEntry.timePercent), 'value time'), + referenceEntry.timePercent, 0); + diffStatus( + td(tr, count(referenceEntry.count), 'value count'), + referenceEntry.count, 0); + } else { + // Display empty entry / baseline entry + var showBaselineEntry = entry !== undefined; + if (showBaselineEntry) { + if (!parentEntry) { + var node = td(tr, '<div class="toggle">►</div>', 'position'); + node.firstChild.addEventListener('click', handleToggleGroup); + } else { + td(tr, entry.position == 0 ? '' : entry.position, 'position'); + } + td(tr, entry.name, 'name'); + td(tr, ms(entry.time, false), 'value time'); + td(tr, percent(entry.timePercent, false), 'value time'); + td(tr, count(entry.count, false), 'value count'); + } else { + td(tr, '-', 'position'); + td(tr, '-', 'name'); + td(tr, '-', 'value time'); + td(tr, '-', 'value time'); + td(tr, '-', 'value count'); + } + } + }); + table.replaceChild(tbody, oldTbody); + var versionSelect = column.querySelector('select.version'); + selectOption(versionSelect, (index, option) => { + return option.version == page.version + }); + } + + function selectEntry(entry, updateSelectedPage) { + if (updateSelectedPage) { + entry = selectedPage.version.getEntry(entry); + } + var rowIndex; + var needsPageSwitch = updateSelectedPage && entry.page != selectedPage; + // If clicked in the detail row change the first column to that page. + if (needsPageSwitch) showPage(entry.page); + var childNodes = $('column_0').querySelector('.list tbody').childNodes; + for (var i = 0; i < childNodes.length; i++) { + if (childNodes[i].entry.name == entry.name) { + rowIndex = i; + break; + } + } + var firstEntry = childNodes[rowIndex].entry; + if (rowIndex) { + if (firstEntry.parent) showGroup(firstEntry.parent); + } + // Deselect all + $('view').querySelectorAll('.list tbody tr').forEach((tr) => { + toggleCssClass(tr, 'selected', false); + }); + // Select the entry row + $('view').querySelectorAll("tbody").forEach((body) => { + var row = body.childNodes[rowIndex]; + if (!row) return; + toggleCssClass(row, 'selected', row.entry && row.entry.name == + firstEntry.name); + }); + if (updateSelectedPage) { + entry = selectedEntry.page.version.getEntry(entry); + } + selectedEntry = entry; + showEntryDetail(entry); + } + + function showEntryDetail(entry) { + var table, tbody, entries; + table = $('detailView').querySelector('.versionDetailTable'); + tbody = document.createElement('tbody'); + if (entry !== undefined) { + $('detailView').querySelector('.versionDetail h3 span').innerHTML = + entry.name; + entries = versions.pageVersions(entry.page.name).map( + (page) => { + return page.get(entry.name) + }); + entries.sort((a, b) => { + return a.time - b.time + }); + entries.forEach((pageEntry) => { + if (pageEntry === undefined) return; + var tr = document.createElement('tr'); + if (pageEntry == entry) tr.className += 'selected'; + tr.entry = pageEntry; + td(tr, pageEntry.page.version.name, 'version'); + td(tr, pageEntry.position, 'value position'); + td(tr, ms(pageEntry.time), 'value time'); + td(tr, percent(pageEntry.timePercent), 'value time'); + td(tr, count(pageEntry.count), 'value count'); + tbody.appendChild(tr); + }); + } + table.replaceChild(tbody, table.querySelector('tbody')); + + table = $('detailView').querySelector('.pageDetailTable'); + tbody = document.createElement('tbody'); + if (entry !== undefined) { + var version = entry.page.version; + $('detailView').querySelector('.pageDetail h3 span').innerHTML = + version.name; + entries = version.pages.map( + (page) => { + return page.get(entry.name) + }); + entries.sort((a, b) => { + var cmp = b.timePercent - a.timePercent; + if (cmp.toFixed(1) == 0) return b.time - a.time; + return cmp + }); + entries.forEach((pageEntry) => { + if (pageEntry === undefined) return; + var tr = document.createElement('tr'); + if (pageEntry === entry) tr.className += 'selected'; + tr.entry = pageEntry; + td(tr, pageEntry.page.name, 'name'); + td(tr, pageEntry.position, 'value position'); + td(tr, ms(pageEntry.time), 'value time'); + td(tr, percent(pageEntry.timePercent), 'value time'); + td(tr, count(pageEntry.count), 'value count'); + tbody.appendChild(tr); + }); + // show the total for all pages + var tds = table.querySelectorAll('tfoot td'); + tds[2].innerHTML = ms(entry.getTimeImpact()); + // Only show the percentage total if we are in diff mode: + tds[3].innerHTML = percent(entry.getTimePercentImpact()); + tds[4].innerHTML = count(entry.getCountImpact()); + } + table.replaceChild(tbody, table.querySelector('tbody')); + showImpactList(entry.page); + showPageGraphs(entry.page); + } + + function showImpactList(page) { + var impactView = $('detailView').querySelector('.impactView'); + impactView.querySelector('h3 span').innerHTML = page.version.name; + + var table = impactView.querySelector('table'); + var tbody = document.createElement('tbody'); + var version = page.version; + var entries = version.allEntries(); + if (selectedEntry !== undefined && selectedEntry.isGroup) { + impactView.querySelector('h3 span').innerHTML += " " + selectedEntry.name; + entries = entries.filter((entry) => { + return entry.name == selectedEntry.name || + (entry.parent && entry.parent.name == selectedEntry.name) + }); + } + var isCompareView = baselineVersion !== undefined; + entries = entries.filter((entry) => { + if (isCompareView) { + var impact = entry.getTimeImpact(); + return impact < -1 || 1 < impact + } + return entry.getTimePercentImpact() > 0.1; + }); + entries.sort((a, b) => { + var cmp = b.getTimePercentImpact() - a.getTimePercentImpact(); + if (isCompareView || cmp.toFixed(1) == 0) { + return b.getTimeImpact() - a.getTimeImpact(); + } + return cmp + }); + entries.forEach((entry) => { + var tr = document.createElement('tr'); + tr.entry = entry; + td(tr, entry.name, 'name'); + td(tr, ms(entry.getTimeImpact()), 'value time'); + var percentImpact = entry.getTimePercentImpact(); + td(tr, percentImpact > 1000 ? '-' : percent(percentImpact), 'value time'); + var topPages = entry.getPagesByPercentImpact().slice(0, 3) + .map((each) => { + return each.name + ' (' + percent(each.getEntry(entry).timePercent) + + ')' + }); + td(tr, topPages.join(', '), 'name'); + tbody.appendChild(tr); + }); + table.replaceChild(tbody, table.querySelector('tbody')); + } + + var selectedGroup; + function showPageGraphs(page) { + var groups = page.groups.filter(each => each.name != page.total.name); + if (selectedGroup == undefined) { + selectedGroup = groups[0]; + } else { + groups = groups.filter(each => each.name != selectedGroup.name); + groups.unshift(selectedGroup); + } + var dataTable = new google.visualization.DataTable(); + dataTable.addColumn('string', 'Name'); + groups.forEach(group => { + var column = dataTable.addColumn('number', group.name); + dataTable.setColumnProperty(column, 'group', group); + }); + // Calculate the average row + var row = ['Average']; + groups.forEach((group) => { + row.push(group.getTimeImpact()); + }); + dataTable.addRow(row); + // Sort the pages by the selected group. + var pages = page.version.pages.slice(); + pages.sort((a, b) => { + return b.getEntry(selectedGroup).timePercent - a.getEntry(selectedGroup).timePercent; + }); + // Calculate the entries for the pages + pages.forEach((page) => { + row = [page.name]; + groups.forEach((group) => { + row.push(page.getEntry(group).time); + }); + dataTable.addRow(row); + }); + + var height = 1000/27*page.version.pages.length; + var options = { + title: 'Page Comparison for Version ' + page.version.name, + isStacked: 'percent', + height: height , + hAxis: { + title: '% Time', + minValue: 0, + }, + vAxis: { + } + }; + var chart = new google.visualization.BarChart($('pageGraphs')); + chart.draw(dataTable, options); + google.visualization.events.addListener(chart, 'select', selectHandler); + function selectHandler() { + var column = chart.getSelection()[0].column; + if (column === undefined) return; + selectedGroup = dataTable.getColumnProperty(column, 'group'); + showPageGraphs(selectedEntry.page); + } + } + + function showGroup(entry) { + toggleGroup(entry, true); + } + + function toggleGroup(group, show) { + $('view').querySelectorAll(".child").forEach((tr) => { + var entry = tr.parentEntry; + if (!entry) return; + if (entry.name !== group.name) return; + toggleCssClass(tr, 'visible', show); + }); + } + + function showPopover(entry) { + var popover = $('popover'); + popover.querySelector('td.name').innerHTML = entry.name; + popover.querySelector('td.page').innerHTML = entry.page.name; + setPopoverDetail(popover, entry, ''); + popover.querySelector('table').className = ""; + if (baselineVersion !== undefined) { + entry = baselineVersion.getEntry(entry); + setPopoverDetail(popover, entry, '.compare'); + popover.querySelector('table').className = "compare"; + } + } + + function setPopoverDetail(popover, entry, prefix) { + var node = (name) => popover.querySelector(prefix + name); + if (entry == undefined) { + node('.version').innerHTML = baselineVersion.name; + node('.time').innerHTML = '-'; + node('.timeVariance').innerHTML = '-'; + node('.percent').innerHTML = '-'; + node('.percentVariance').innerHTML = '-'; + node('.count').innerHTML = '-'; + node('.countVariance').innerHTML = '-'; + node('.timeImpact').innerHTML = '-'; + node('.timePercentImpact').innerHTML = '-'; + } else { + node('.version').innerHTML = entry.page.version.name; + node('.time').innerHTML = ms(entry._time, false); + node('.timeVariance').innerHTML + = percent(entry.timeVariancePercent, false); + node('.percent').innerHTML = percent(entry.timePercent, false); + node('.percentVariance').innerHTML + = percent(entry.timePercentVariancePercent, false); + node('.count').innerHTML = count(entry._count, false); + node('.countVariance').innerHTML + = percent(entry.timeVariancePercent, false); + node('.timeImpact').innerHTML + = ms(entry.getTimeImpact(false), false); + node('.timePercentImpact').innerHTML + = percent(entry.getTimeImpactVariancePercent(false), false); + } + } + + // =========================================================================== + // Helpers + function $(id) { + return document.getElementById(id) + } + + function removeAllChildren(node) { + while (node.firstChild) { + node.removeChild(node.firstChild); + } + } + + function selectOption(select, match) { + var options = select.options; + for (var i = 0; i < options.length; i++) { + if (match(i, options[i])) { + select.selectedIndex = i; + return; + } + } + } + + function td(tr, content, className) { + var td = document.createElement("td"); + td.innerHTML = content; + td.className = className + tr.appendChild(td); + return td + } + + function nodeIndex(node) { + var children = node.parentNode.childNodes, + i = 0; + for (; i < children.length; i++) { + if (children[i] == node) { + return i; + } + } + return -1; + } + + function toggleCssClass(node, cssClass, toggleState) { + var index = -1; + var classes; + if (node.className != undefined) { + classes = node.className.split(' '); + index = classes.indexOf(cssClass); + } + if (index == -1) { + if (toggleState === false) return; + node.className += ' ' + cssClass; + return; + } + if (toggleState === true) return; + classes.splice(index, 1); + node.className = classes.join(' '); + } + + function diffSign(value, digits, unit, showDiff) { + if (showDiff === false || baselineVersion == undefined) { + return value.toFixed(digits) + unit; + } + return (value >= 0 ? '+' : '') + value.toFixed(digits) + unit + 'Δ'; + } + + function ms(value, showDiff) { + return diffSign(value, 1, 'ms', showDiff); + } + + function count(value, showDiff) { + return diffSign(value, 0, '#', showDiff); + } + + function percent(value, showDiff) { + return diffSign(value, 1, '%', showDiff); + } + + // ========================================================================= + // EventHandlers + function handleBodyLoad() { + $('uploadInput').focus(); + } + + function handleLoadFile() { + var files = document.getElementById("uploadInput").files; + var file = files[0]; + var reader = new FileReader(); + + reader.onload = function(evt) { + versions = Versions.fromJSON(JSON.parse(this.result)); + initialize() + showPage(versions.versions[0].pages[0]); + } + reader.readAsText(file); + } + + function handleToggleGroup(event) { + var group = event.target.parentNode.parentNode.entry; + toggleGroup(selectedPage.get(group.name)); + } + + function handleSelectPage(select, event) { + var option = select.options[select.selectedIndex]; + if (select.id == "select_0") { + showPage(option.page); + } else { + var columnIndex = select.id.split('_')[1]; + showPageInColumn(option.page, columnIndex); + } + } + + function handleSelectVersion(select, event) { + var option = select.options[select.selectedIndex]; + var version = option.version; + if (select.id == "selectVersion_0") { + var page = version.get(selectedPage.name); + showPage(page); + } else { + var columnIndex = select.id.split('_')[1]; + var pageSelect = $('select_' + columnIndex); + var page = pageSelect.options[select.selectedIndex].page; + page = version.get(page.name); + showPageInColumn(page, columnIndex); + } + } + + function handleSelectDetailRow(table, event) { + if (event.target.tagName != 'TD') return; + var tr = event.target.parentNode; + if (tr.tagName != 'TR') return; + if (tr.entry === undefined) return; + selectEntry(tr.entry, true); + } + + function handleSelectRow(table, event, fromDetail) { + if (event.target.tagName != 'TD') return; + var tr = event.target.parentNode; + if (tr.tagName != 'TR') return; + if (tr.entry === undefined) return; + selectEntry(tr.entry, false); + } + + function handleSelectBaseline(select, event) { + var option = select.options[select.selectedIndex]; + baselineVersion = option.version + showPage(selectedPage); + if (selectedEntry === undefined) return; + selectEntry(selectedEntry, true); + } + + function handleUpdatePopover(event) { + var popover = $('popover'); + popover.style.left = event.pageX + 'px'; + popover.style.top = event.pageY + 'px'; + popover.style.display = event.shiftKey ? 'block' : 'none'; + var target = event.target; + while (target.entry === undefined) { + target = target.parentNode; + if (!target) return; + } + showPopover(target.entry); + } + + function handleToggleVersionEnable(event) { + var version = this.version; + if (version === undefined) return; + version.enabled = this.checked; + initialize(); + var page = selectedPage; + if (page === undefined || !page.version.enabled) { + page = versions.getEnabledPage(page.name); + } + showPage(page); + } + + // =========================================================================== + + class Versions { + constructor() { + this.versions = []; + } + add(version) { + this.versions.push(version) + } + pageVersions(name) { + var result = []; + this.versions.forEach((version) => { + if (!version.enabled) return; + var page = version.get(name); + if (page !== undefined) result.push(page); + }); + return result; + } + get length() { + return this.versions.length + } + get(index) { + return this.versions[index] + }; + forEach(f) { + this.versions.forEach(f); + } + sort() { + this.versions.sort((a, b) => { + if (a.name > b.name) return 1; + if (a.name < b.name) return -1; + return 0 + }) + } + getEnabledPage(name) { + for (var i = 0; i < this.versions.length; i++) { + var version = this.versions[i]; + if (!version.enabled) continue; + var page = version.get(name); + if (page !== undefined) return page; + } + } + } + Versions.fromJSON = function(json) { + var versions = new Versions(); + for (var version in json) { + versions.add(Version.fromJSON(version, json[version])); + } + versions.sort(); + return versions; + } + + class Version { + constructor(name) { + this.name = name; + this.enabled = true; + this.pages = []; + } + add(page) { + this.pages.push(page); + } + indexOf(name) { + for (var i = 0; i < this.pages.length; i++) { + if (this.pages[i].name == name) return i; + } + return -1; + } + get(name) { + var index = this.indexOf(name); + if (0 <= index) return this.pages[index]; + return undefined + } + get length() { + return this.versions.length + } + getEntry(entry) { + if (entry === undefined) return undefined; + var page = this.get(entry.page.name); + if (page === undefined) return undefined; + return page.get(entry.name); + } + forEachEntry(fun) { + this.pages.forEach((page) => { + page.forEach(fun); + }); + } + allEntries() { + var map = new Map(); + this.forEachEntry((group, entry) => { + if (!map.has(entry.name)) map.set(entry.name, entry); + }); + return Array.from(map.values()); + } + getTotalValue(name, property) { + if (name === undefined) name = this.pages[0].total.name; + var sum = 0; + this.pages.forEach((page) => { + var entry = page.get(name); + if (entry !== undefined) sum += entry[property]; + }); + return sum; + } + getTotalTime(name, showDiff) { + return this.getTotalValue(name, showDiff === false ? '_time' : 'time'); + } + getTotalTimePercent(name, showDiff) { + if (baselineVersion === undefined) { + // Return the overall average percent of the given entry name. + return this.getTotalValue(name, 'time') / + this.getTotalTime('Group-Total') * 100; + } + // Otherwise return the difference to the sum of the baseline version. + var baselineValue = baselineVersion.getTotalTime(name, false); + return this.getTotalValue(name, '_time') / baselineValue * 100; + } + getTotalTimeVariance(name, showDiff) { + // Calculate the overall error for a given entry name + var sum = 0; + this.pages.forEach((page) => { + var entry = page.get(name); + if (entry === undefined) return; + sum += entry.timeVariance * entry.timeVariance; + }); + return Math.sqrt(sum); + } + getTotalTimeVariancePercent(name, showDiff) { + return this.getTotalTimeVariance(name, showDiff) / + this.getTotalTime(name, showDiff) * 100; + } + getTotalCount(name, showDiff) { + return this.getTotalValue(name, showDiff === false ? '_count' : 'count'); + } + getPagesByPercentImpact(name) { + var sortedPages = + this.pages.filter((each) => { + return each.get(name) !== undefined + }); + sortedPages.sort((a, b) => { + return b.get(name).timePercent - a.get(name).timePercent; + }); + return sortedPages; + } + sort() { + this.pages.sort((a, b) => { + if (a.name > b.name) return 1; + if (a.name < b.name) return -1; + return 0 + }) + } + } + Version.fromJSON = function(name, data) { + var version = new Version(name); + for (var page in data) { + version.add(Page.fromJSON(version, page, data[page])); + } + version.sort(); + return version; + } + + + class Page { + constructor(version, name) { + this.name = name; + this.total = new GroupedEntry('Total', /.*Total.*/); + this.unclassified = new UnclassifiedEntry(this) + this.groups = [ + this.total, + new GroupedEntry('IC', /.*IC.*/), + new GroupedEntry('Optimize', + /StackGuard|.*Optimize.*|.*Deoptimize.*|Recompile.*/), + new GroupedEntry('Compile', /.*Compile.*|Parse.*/), + new GroupedEntry('Callback', /.*Callback$/), + new GroupedEntry('API', /.*API.*/), + new GroupedEntry('GC', /GC|AllocateInTargetSpace/), + new GroupedEntry('JavaScript', /JS_Execution/), + this.unclassified + ]; + this.entryDict = new Map(); + this.groups.forEach((entry) => { + entry.page = this; + this.entryDict.set(entry.name, entry); + }); + this.version = version; + } + add(entry) { + entry.page = this; + this.entryDict.set(entry.name, entry); + var added = false; + this.groups.forEach((group) => { + if (!added) added = group.add(entry); + }); + if (added) return; + this.unclassified.push(entry); + } + get(name) { + return this.entryDict.get(name) + } + getEntry(entry) { + if (entry === undefined) return undefined; + return this.get(entry.name); + } + get length() { + return this.versions.length + } + forEachSorted(referencePage, func) { + // Iterate over all the entries in the order they appear on the reference page. + referencePage.forEach((parent, referenceEntry) => { + var entry; + if (parent) parent = this.entryDict.get(parent.name); + if (referenceEntry) entry = this.entryDict.get(referenceEntry.name); + func(parent, entry, referenceEntry); + }); + } + forEach(fun) { + this.forEachGroup((group) => { + fun(undefined, group); + group.forEach((entry) => { + fun(group, entry) + }); + }); + } + forEachGroup(fun) { + this.groups.forEach(fun) + } + sort() { + this.groups.sort((a, b) => { + return b.time - a.time; + }); + this.groups.forEach((group) => { + group.sort() + }); + } + } + Page.fromJSON = function(version, name, data) { + if (name.indexOf('www.') == 0) { + name = name.substring(4); + } + var page = new Page(version, name); + for (var i = 0; i < data.length; i++) { + page.add(Entry.fromJSON(i, data[data.length - i - 1])); + } + page.sort(); + return page + } + + + class Entry { + constructor(position, name, time, timeVariance, timeVariancePercent, + count, + countVariance, countVariancePercent) { + this.position = position; + this.name = name; + this._time = time; + this._timeVariance = timeVariance; + this._timeVariancePercent = timeVariancePercent; + this._count = count; + this.countVariance = countVariance; + this.countVariancePercent = countVariancePercent; + this.page = undefined; + this.parent = undefined; + } + getCompareWithBaseline(value, property) { + if (baselineVersion == undefined) return value; + var baselineEntry = baselineVersion.getEntry(this); + if (!baselineEntry) return value; + if (baselineVersion === this.page.version) return value; + return value - baselineEntry[property]; + } + cssClass() { + return '' + } + get time() { + return this.getCompareWithBaseline(this._time, '_time'); + } + get count() { + return this.getCompareWithBaseline(this._count, '_count'); + } + get timePercent() { + var value = this._time / this.page.total._time * 100; + if (baselineVersion == undefined) return value; + var baselineEntry = baselineVersion.getEntry(this); + if (!baselineEntry) return value; + if (baselineVersion === this.page.version) return value; + return (this._time - baselineEntry._time) / this.page.total._time * + 100; + } + get timePercentVariancePercent() { + // Get the absolute values for the percentages + return this.timeVariance / this.page.total._time * 100; + } + getTimeImpact(showDiff) { + return this.page.version.getTotalTime(this.name, showDiff); + } + getTimeImpactVariancePercent(showDiff) { + return this.page.version.getTotalTimeVariancePercent(this.name, showDiff); + } + getTimePercentImpact(showDiff) { + return this.page.version.getTotalTimePercent(this.name, showDiff); + } + getCountImpact(showDiff) { + return this.page.version.getTotalCount(this.name, showDiff); + } + getPagesByPercentImpact() { + return this.page.version.getPagesByPercentImpact(this.name); + } + get isGroup() { + return false + } + get timeVariance() { + return this._timeVariance + } + get timeVariancePercent() { + return this._timeVariancePercent + } + } + Entry.fromJSON = function(position, data) { + return new Entry(position, ...data); + } + + + class GroupedEntry extends Entry { + constructor(name, regexp) { + super(0, 'Group-' + name, 0, 0, 0, 0, 0, 0); + this.regexp = regexp; + this.entries = []; + } + add(entry) { + if (!entry.name.match(this.regexp)) return false; + this._time += entry.time; + this._count += entry.count; + // TODO: sum up variance + this.entries.push(entry); + entry.parent = this; + return true; + } + forEach(fun) { + if (baselineVersion === undefined) { + this.entries.forEach(fun); + return; + } + // If we have a baslineVersion to compare against show also all entries from the + // other group. + var tmpEntries = baselineVersion.getEntry(this) + .entries.filter((entry) => { + return this.page.get(entry.name) == undefined + }); + + // The compared entries are sorted by absolute impact. + tmpEntries = tmpEntries.map((entry) => { + var tmpEntry = new Entry(0, entry.name, 0, 0, 0, 0, 0, 0); + tmpEntry.page = this.page; + return tmpEntry; + }); + tmpEntries = tmpEntries.concat(this.entries); + tmpEntries.sort((a, b) => { + return a.time - b.time + }); + tmpEntries.forEach(fun); + } + sort() { + this.entries.sort((a, b) => { + return b.time - a.time; + }); + } + cssClass() { + if (this.page.total == this) return 'total'; + return ''; + } + get isGroup() { + return true + } + getVarianceForProperty(property) { + var sum = 0; + this.entries.forEach((entry) => { + sum += entry[property + 'Variance'] * entry[property + + 'Variance']; + }); + return Math.sqrt(sum); + } + get timeVariancePercent() { + if (this._time == 0) return 0; + return this.getVarianceForProperty('time') / this._time * 100 + } + get timeVariance() { + return this.getVarianceForProperty('time') + } + } + + class UnclassifiedEntry extends GroupedEntry { + constructor(page) { + super('Runtime'); + this.page = page; + this._time = undefined; + this._count = undefined; + } + add(entry) { + this.entries.push(entry); + entry.parent = this; + return true; + } + forEachPageGroup(fun) { + this.page.forEachGroup((group) => { + if (group == this) return; + if (group == this.page.total) return; + fun(group); + }); + } + get time() { + if (this._time === undefined) { + this._time = this.page.total._time; + this.forEachPageGroup((group) => { + this._time -= group._time; + }); + } + return this.getCompareWithBaseline(this._time, '_time'); + } + get count() { + if (this._count === undefined) { + this._count = this.page.total._count; + this.forEachPageGroup((group) => { + this._count -= group._count; + }); + } + return this.getCompareWithBaseline(this._count, '_count'); + } + } + </script> +</head> + +<body onmousemove="handleUpdatePopover(event)" onload="handleBodyLoad()"> + <h1>Runtime Stats Komparator</h1> + + <div id="results"> + <div class="inline"> + <h2>Data</h2> + <form name="fileForm"> + <p> + <input id="uploadInput" type="file" name="files" onchange="handleLoadFile();" accept=".json"> + </p> + </form> + </div> + + <div class="inline hidden"> + <h2>Result</h2> + <div class="compareSelector inline"> + Compare against: <select id="baseline" onchange="handleSelectBaseline(this, event)"></select><br/> + <span style="color: #060">Green</span> the selected version above performs + better on this measurement. + </div> + <div class="versionSelector inline"> + Select Versions: + <ul></ul> + </div> + </div> + <div id="view"> + </div> + + <div id="detailView" class="hidden"> + <h2></h2> + <div class="versionDetail inline"> + <h3>Version Comparison for <span></span></h3> + <table class="versionDetailTable" onclick="handleSelectDetailRow(this, event);"> + <thead> + <tr> + <th class="version">Version </th> + <th class="position">Pos. </th> + <th class="value time">Time▴ </th> + <th class="value time">Percent </th> + <th class="value count">Count </th> + </tr> + </thead> + <tbody></tbody> + </table> + </div> + <div class="pageDetail inline"> + <h3>Page Comparison for <span></span></h3> + <table class="pageDetailTable" onclick="handleSelectDetailRow(this, event);"> + <thead> + <tr> + <th class="page">Page </th> + <th class="position">Pos. </th> + <th class="value time">Time </th> + <th class="value time">Percent▾ </th> + <th class="value count">Count </th> + </tr> + </thead> + <tfoot> + <tr> + <td class="page">Total:</td> + <td class="position"></td> + <td class="value time"></td> + <td class="value time"></td> + <td class="value count"></td> + </tr> + </tfoot> + <tbody></tbody> + </table> + </div> + <div class="impactView inline"> + <h3>Impact list for <span></span></h3> + <table class="pageDetailTable" onclick="handleSelectDetailRow(this, event);"> + <thead> + <tr> + <th class="page">Name </th> + <th class="value time">Time </th> + <th class="value time">Percent▾ </th> + <th class="">Top Pages</th> + </tr> + </thead> + <tbody></tbody> + </table> + </div> + </div> + <div id="pageGraphs" class="hidden"> + </div> + + <div id="column" class="column"> + <div class="header"> + <select class="version" onchange="handleSelectVersion(this, event);"></select> + <select class="pageVersion" onchange="handleSelectPage(this, event);"></select> + </div> + <table class="list" onclick="handleSelectRow(this, event);"> + <thead> + <tr> + <th class="position">Pos. </th> + <th class="name">Name </th> + <th class="value time">Time </th> + <th class="value time">Percent </th> + <th class="value count">Count </th> + </tr> + </thead> + <tbody></tbody> + </table> + </div> + </div> + + <div class="inline"> + <h2>Usage</h2> + <ol> + <li>Install scipy, e.g. <code>sudo aptitude install python-scipy</code> + <li>Build chrome with the <a href="https://codereview.chromium.org/1923893002">extended runtime callstats</a>.</li> + <li>Run <code>callstats.py</code> with a web-page-replay archive: + <pre>$V8_DIR/tools/callstats.py run \ + --replay-bin=$CHROME_SRC/third_party/webpagereplay/replay.py \ + --replay-wpr=$INPUT_DIR/top25.wpr \ + --js-flags="" \ + --with-chrome=$CHROME_SRC/out/Release/chrome \ + --sites-file=$INPUT_DIR/top25.json</pre> + </li> + <li>Move results file to a subdirectory: <code>mkdir $VERSION_DIR; mv *.txt $VERSION_DIR</code></li> + <li>Repeat from step 1 with a different configuration (e.g. <code>--js-flags="--nolazy"</code>).</li> + <li>Create the final results file: <code>./callstats.py json $VERSION_DIR1 $VERSION_DIR2 > result.json</code></li> + <li>Use <code>results.json</code> on this site.</code> + </ol> + </div> + + <div id="popover"> + <div class="popoverArrow"></div> + <table> + <tr> + <td class="name" colspan="6"></td> + </tr> + <tr> + <td>Page:</td> + <td class="page name" colspan="6"></td> + </tr> + <tr> + <td>Version:</td> + <td class="version name" colspan="3"></td> + <td class="compare version name" colspan="3"></td> + </tr> + <tr> + <td>Time:</td> + <td class="time"></td><td>±</td><td class="timeVariance"></td> + <td class="compare time"></td><td class="compare"> ± </td><td class="compare timeVariance"></td> + </tr> + <tr> + <td>Percent:</td> + <td class="percent"></td><td>±</td><td class="percentVariance"></td> + <td class="compare percent"></td><td class="compare"> ± </td><td class="compare percentVariance"></td> + </tr> + <tr> + <td>Count:</td> + <td class="count"></td><td>±</td><td class="countVariance"></td> + <td class="compare count"></td><td class="compare"> ± </td><td class="compare countVariance"></td> + </tr> + <tr> + <td>Overall Impact:</td> + <td class="timeImpact"></td><td>±</td><td class="timePercentImpact"></td> + <td class="compare timeImpact"></td><td class="compare"> ± </td><td class="compare timePercentImpact"></td> + </tr> + </table> + </div> + +</body> + +</html> diff --git a/tools/callstats.py b/tools/callstats.py new file mode 100755 index 00000000..90446184 --- /dev/null +++ b/tools/callstats.py @@ -0,0 +1,556 @@ +#!/usr/bin/env python +# Copyright 2016 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. +''' +Usage: runtime-call-stats.py [-h] <command> ... + +Optional arguments: + -h, --help show this help message and exit + +Commands: + run run chrome with --runtime-call-stats and generate logs + stats process logs and print statistics + json process logs from several versions and generate JSON + help help information + +For each command, you can try ./runtime-call-stats.py help command. +''' + +import argparse +import json +import os +import re +import shutil +import subprocess +import sys +import tempfile + +import numpy +import scipy +import scipy.stats +from math import sqrt + + +# Run benchmarks. + +def print_command(cmd_args): + def fix_for_printing(arg): + m = re.match(r'^--([^=]+)=(.*)$', arg) + if m and (' ' in m.group(2) or m.group(2).startswith('-')): + arg = "--{}='{}'".format(m.group(1), m.group(2)) + elif ' ' in arg: + arg = "'{}'".format(arg) + return arg + print " ".join(map(fix_for_printing, cmd_args)) + + +def start_replay_server(args, sites): + with tempfile.NamedTemporaryFile(prefix='callstats-inject-', suffix='.js', + mode='wt', delete=False) as f: + injection = f.name + generate_injection(f, sites, args.refresh) + cmd_args = [ + args.replay_bin, + "--port=4080", + "--ssl_port=4443", + "--no-dns_forwarding", + "--use_closest_match", + "--no-diff_unknown_requests", + "--inject_scripts=deterministic.js,{}".format(injection), + args.replay_wpr, + ] + print "=" * 80 + print_command(cmd_args) + with open(os.devnull, 'w') as null: + server = subprocess.Popen(cmd_args, stdout=null, stderr=null) + print "RUNNING REPLAY SERVER: %s with PID=%s" % (args.replay_bin, server.pid) + print "=" * 80 + return {'process': server, 'injection': injection} + + +def stop_replay_server(server): + print("SHUTTING DOWN REPLAY SERVER %s" % server['process'].pid) + server['process'].terminate() + os.remove(server['injection']) + + +def generate_injection(f, sites, refreshes=0): + print >> f, """\ +(function() { + let s = window.sessionStorage.getItem("refreshCounter"); + let refreshTotal = """, refreshes, """; + let refreshCounter = s ? parseInt(s) : refreshTotal; + let refreshId = refreshTotal - refreshCounter; + if (refreshCounter > 0) { + window.sessionStorage.setItem("refreshCounter", refreshCounter-1); + } + + function match(url, item) { + if ('regexp' in item) return url.match(item.regexp) !== null; + let url_wanted = item.url; + // Allow automatic redirections from http to https. + if (url_wanted.startsWith("http://") && url.startsWith("https://")) { + url_wanted = "https://" + url_wanted.substr(7); + } + return url.startsWith(url_wanted); + }; + + function onLoad(e) { + let url = e.target.URL; + for (let item of sites) { + if (!match(url, item)) continue; + let timeout = 'timeline' in item ? 2500 * item.timeline + : 'timeout' in item ? 1000 * (item.timeout - 3) + : 10000; + console.log("Setting time out of " + timeout + " for: " + url); + window.setTimeout(function() { + console.log("Time is out for: " + url); + let msg = "STATS: (" + refreshId + ") " + url; + %GetAndResetRuntimeCallStats(1, msg); + if (refreshCounter > 0) { + console.log("Refresh counter is " + refreshCounter + ", refreshing: " + url); + window.location.reload(); + } + }, timeout); + return; + } + console.log("Ignoring: " + url); + }; + + let sites = + """, json.dumps(sites), """; + + console.log("Event listenner added for: " + window.location.href); + window.addEventListener("load", onLoad); +})();""" + + +def run_site(site, domain, args, timeout=None): + print "="*80 + print "RUNNING DOMAIN %s" % domain + print "="*80 + result_template = "{domain}#{count}.txt" if args.repeat else "{domain}.txt" + count = 0 + if timeout is None: timeout = args.timeout + if args.replay_wpr: + timeout *= 1 + args.refresh + timeout += 1 + while count == 0 or args.repeat is not None and count < args.repeat: + count += 1 + result = result_template.format(domain=domain, count=count) + retries = 0 + while args.retries is None or retries < args.retries: + retries += 1 + try: + if args.user_data_dir: + user_data_dir = args.user_data_dir + else: + user_data_dir = tempfile.mkdtemp(prefix="chr_") + js_flags = "--runtime-call-stats" + if args.replay_wpr: js_flags += " --allow-natives-syntax" + if args.js_flags: js_flags += " " + args.js_flags + chrome_flags = [ + "--no-default-browser-check", + "--disable-translate", + "--js-flags={}".format(js_flags), + "--no-first-run", + "--user-data-dir={}".format(user_data_dir), + ] + if args.replay_wpr: + chrome_flags += [ + "--host-resolver-rules=MAP *:80 localhost:4080, " \ + "MAP *:443 localhost:4443, " \ + "EXCLUDE localhost", + "--ignore-certificate-errors", + "--disable-seccomp-sandbox", + "--disable-web-security", + "--reduce-security-for-testing", + "--allow-insecure-localhost", + ] + else: + chrome_flags += [ + "--single-process", + ] + if args.chrome_flags: + chrome_flags += args.chrome_flags.split() + cmd_args = [ + "timeout", str(timeout), + args.with_chrome + ] + chrome_flags + [ site ] + print "- " * 40 + print_command(cmd_args) + print "- " * 40 + with open(result, "wt") as f: + status = subprocess.call(cmd_args, stdout=f) + # 124 means timeout killed chrome, 0 means the user was bored first! + # If none of these two happened, then chrome apparently crashed, so + # it must be called again. + if status != 124 and status != 0: + print("CHROME CRASHED, REPEATING RUN"); + continue + # If the stats file is empty, chrome must be called again. + if os.path.isfile(result) and os.path.getsize(result) > 0: + if args.print_url: + with open(result, "at") as f: + print >> f + print >> f, "URL: {}".format(site) + break + if retries <= 6: timeout += 2 ** (retries-1) + print("EMPTY RESULT, REPEATING RUN"); + finally: + if not args.user_data_dir: + shutil.rmtree(user_data_dir) + + +def read_sites_file(args): + try: + sites = [] + try: + with open(args.sites_file, "rt") as f: + for item in json.load(f): + if 'timeout' not in item: + # This is more-or-less arbitrary. + item['timeout'] = int(2.5 * item['timeline'] + 3) + if item['timeout'] > args.timeout: item['timeout'] = args.timeout + sites.append(item) + except ValueError: + with open(args.sites_file, "rt") as f: + for line in f: + line = line.strip() + if not line or line.startswith('#'): continue + sites.append({'url': line, 'timeout': args.timeout}) + return sites + except IOError as e: + args.error("Cannot read from {}. {}.".format(args.sites_file, e.strerror)) + sys.exit(1) + + +def do_run(args): + # Determine the websites to benchmark. + if args.sites_file: + sites = read_sites_file(args) + else: + sites = [{'url': site, 'timeout': args.timeout} for site in args.sites] + # Disambiguate domains, if needed. + L = [] + domains = {} + for item in sites: + site = item['url'] + m = re.match(r'^(https?://)?([^/]+)(/.*)?$', site) + if not m: + args.error("Invalid URL {}.".format(site)) + continue + domain = m.group(2) + entry = [site, domain, None, item['timeout']] + if domain not in domains: + domains[domain] = entry + else: + if not isinstance(domains[domain], int): + domains[domain][2] = 1 + domains[domain] = 1 + domains[domain] += 1 + entry[2] = domains[domain] + L.append(entry) + replay_server = start_replay_server(args, sites) if args.replay_wpr else None + try: + # Run them. + for site, domain, count, timeout in L: + if count is not None: domain = "{}%{}".format(domain, count) + print site, domain, timeout + run_site(site, domain, args, timeout) + finally: + if replay_server: + stop_replay_server(replay_server) + + +# Calculate statistics. + +def statistics(data): + N = len(data) + average = numpy.average(data) + median = numpy.median(data) + low = numpy.min(data) + high= numpy.max(data) + if N > 1: + # evaluate sample variance by setting delta degrees of freedom (ddof) to + # 1. The degree used in calculations is N - ddof + stddev = numpy.std(data, ddof=1) + # Get the endpoints of the range that contains 95% of the distribution + t_bounds = scipy.stats.t.interval(0.95, N-1) + #assert abs(t_bounds[0] + t_bounds[1]) < 1e-6 + # sum mean to the confidence interval + ci = { + 'abs': t_bounds[1] * stddev / sqrt(N), + 'low': average + t_bounds[0] * stddev / sqrt(N), + 'high': average + t_bounds[1] * stddev / sqrt(N) + } + else: + stddev = 0 + ci = { 'abs': 0, 'low': average, 'high': average } + if abs(stddev) > 0.0001 and abs(average) > 0.0001: + ci['perc'] = t_bounds[1] * stddev / sqrt(N) / average * 100 + else: + ci['perc'] = 0 + return { 'samples': N, 'average': average, 'median': median, + 'stddev': stddev, 'min': low, 'max': high, 'ci': ci } + + +def read_stats(path, S): + with open(path, "rt") as f: + # Process the whole file and sum repeating entries. + D = { 'Sum': {'time': 0, 'count': 0} } + for line in f: + line = line.strip() + # Discard headers and footers. + if not line: continue + if line.startswith("Runtime Function"): continue + if line.startswith("===="): continue + if line.startswith("----"): continue + if line.startswith("URL:"): continue + if line.startswith("STATS:"): continue + # We have a regular line. + fields = line.split() + key = fields[0] + time = float(fields[1].replace("ms", "")) + count = int(fields[3]) + if key not in D: D[key] = { 'time': 0, 'count': 0 } + D[key]['time'] += time + D[key]['count'] += count + # We calculate the sum, if it's not the "total" line. + if key != "Total": + D['Sum']['time'] += time + D['Sum']['count'] += count + # Append the sums as single entries to S. + for key in D: + if key not in S: S[key] = { 'time_list': [], 'count_list': [] } + S[key]['time_list'].append(D[key]['time']) + S[key]['count_list'].append(D[key]['count']) + + +def print_stats(S, args): + # Sort by ascending/descending time average, then by ascending/descending + # count average, then by ascending name. + def sort_asc_func(item): + return (item[1]['time_stat']['average'], + item[1]['count_stat']['average'], + item[0]) + def sort_desc_func(item): + return (-item[1]['time_stat']['average'], + -item[1]['count_stat']['average'], + item[0]) + # Sorting order is in the commend-line arguments. + sort_func = sort_asc_func if args.sort == "asc" else sort_desc_func + # Possibly limit how many elements to print. + L = [item for item in sorted(S.items(), key=sort_func) + if item[0] not in ["Total", "Sum"]] + N = len(L) + if args.limit == 0: + low, high = 0, N + elif args.sort == "desc": + low, high = 0, args.limit + else: + low, high = N-args.limit, N + # How to print entries. + def print_entry(key, value): + def stats(s, units=""): + conf = "{:0.1f}({:0.2f}%)".format(s['ci']['abs'], s['ci']['perc']) + return "{:8.1f}{} +/- {:15s}".format(s['average'], units, conf) + print "{:>50s} {} {}".format( + key, + stats(value['time_stat'], units="ms"), + stats(value['count_stat']) + ) + # Print and calculate partial sums, if necessary. + for i in range(low, high): + print_entry(*L[i]) + if args.totals and args.limit != 0: + if i == low: + partial = { 'time_list': [0] * len(L[i][1]['time_list']), + 'count_list': [0] * len(L[i][1]['count_list']) } + assert len(partial['time_list']) == len(L[i][1]['time_list']) + assert len(partial['count_list']) == len(L[i][1]['count_list']) + for j, v in enumerate(L[i][1]['time_list']): + partial['time_list'][j] += v + for j, v in enumerate(L[i][1]['count_list']): + partial['count_list'][j] += v + # Print totals, if necessary. + if args.totals: + print '-' * 80 + if args.limit != 0: + partial['time_stat'] = statistics(partial['time_list']) + partial['count_stat'] = statistics(partial['count_list']) + print_entry("Partial", partial) + print_entry("Sum", S["Sum"]) + print_entry("Total", S["Total"]) + + +def do_stats(args): + T = {} + for path in args.logfiles: + filename = os.path.basename(path) + m = re.match(r'^([^#]+)(#.*)?$', filename) + domain = m.group(1) + if domain not in T: T[domain] = {} + read_stats(path, T[domain]) + for i, domain in enumerate(sorted(T)): + if len(T) > 1: + if i > 0: print + print "{}:".format(domain) + print '=' * 80 + S = T[domain] + for key in S: + S[key]['time_stat'] = statistics(S[key]['time_list']) + S[key]['count_stat'] = statistics(S[key]['count_list']) + print_stats(S, args) + + +# Generate JSON file. + +def do_json(args): + J = {} + for path in args.logdirs: + if os.path.isdir(path): + for root, dirs, files in os.walk(path): + version = os.path.basename(root) + if version not in J: J[version] = {} + for filename in files: + if filename.endswith(".txt"): + m = re.match(r'^([^#]+)(#.*)?\.txt$', filename) + domain = m.group(1) + if domain not in J[version]: J[version][domain] = {} + read_stats(os.path.join(root, filename), J[version][domain]) + for version, T in J.items(): + for domain, S in T.items(): + A = [] + for name, value in S.items(): + # We don't want the calculated sum in the JSON file. + if name == "Sum": continue + entry = [name] + for x in ['time_list', 'count_list']: + s = statistics(S[name][x]) + entry.append(round(s['average'], 1)) + entry.append(round(s['ci']['abs'], 1)) + entry.append(round(s['ci']['perc'], 2)) + A.append(entry) + T[domain] = A + print json.dumps(J, separators=(',', ':')) + + +# Help. + +def do_help(parser, subparsers, args): + if args.help_cmd: + if args.help_cmd in subparsers: + subparsers[args.help_cmd].print_help() + else: + args.error("Unknown command '{}'".format(args.help_cmd)) + else: + parser.print_help() + + +# Main program, parse command line and execute. + +def coexist(*l): + given = sum(1 for x in l if x) + return given == 0 or given == len(l) + +def main(): + parser = argparse.ArgumentParser() + subparser_adder = parser.add_subparsers(title="commands", dest="command", + metavar="<command>") + subparsers = {} + # Command: run. + subparsers["run"] = subparser_adder.add_parser( + "run", help="run --help") + subparsers["run"].set_defaults( + func=do_run, error=subparsers["run"].error) + subparsers["run"].add_argument( + "--chrome-flags", type=str, default="", + help="specify additional chrome flags") + subparsers["run"].add_argument( + "--js-flags", type=str, default="", + help="specify additional V8 flags") + subparsers["run"].add_argument( + "--no-url", dest="print_url", action="store_false", default=True, + help="do not include url in statistics file") + subparsers["run"].add_argument( + "-n", "--repeat", type=int, metavar="<num>", + help="specify iterations for each website (default: once)") + subparsers["run"].add_argument( + "-k", "--refresh", type=int, metavar="<num>", default=0, + help="specify refreshes for each iteration (default: 0)") + subparsers["run"].add_argument( + "--replay-wpr", type=str, metavar="<path>", + help="use the specified web page replay (.wpr) archive") + subparsers["run"].add_argument( + "--replay-bin", type=str, metavar="<path>", + help="specify the replay.py script typically located in " \ + "$CHROMIUM/src/third_party/webpagereplay/replay.py") + subparsers["run"].add_argument( + "-r", "--retries", type=int, metavar="<num>", + help="specify retries if website is down (default: forever)") + subparsers["run"].add_argument( + "-f", "--sites-file", type=str, metavar="<path>", + help="specify file containing benchmark websites") + subparsers["run"].add_argument( + "-t", "--timeout", type=int, metavar="<seconds>", default=60, + help="specify seconds before chrome is killed") + subparsers["run"].add_argument( + "-u", "--user-data-dir", type=str, metavar="<path>", + help="specify user data dir (default is temporary)") + subparsers["run"].add_argument( + "-c", "--with-chrome", type=str, metavar="<path>", + default="/usr/bin/google-chrome", + help="specify chrome executable to use") + subparsers["run"].add_argument( + "sites", type=str, metavar="<URL>", nargs="*", + help="specify benchmark website") + # Command: stats. + subparsers["stats"] = subparser_adder.add_parser( + "stats", help="stats --help") + subparsers["stats"].set_defaults( + func=do_stats, error=subparsers["stats"].error) + subparsers["stats"].add_argument( + "-l", "--limit", type=int, metavar="<num>", default=0, + help="limit how many items to print (default: none)") + subparsers["stats"].add_argument( + "-s", "--sort", choices=["asc", "desc"], default="asc", + help="specify sorting order (default: ascending)") + subparsers["stats"].add_argument( + "-n", "--no-total", dest="totals", action="store_false", default=True, + help="do not print totals") + subparsers["stats"].add_argument( + "logfiles", type=str, metavar="<logfile>", nargs="*", + help="specify log files to parse") + # Command: json. + subparsers["json"] = subparser_adder.add_parser( + "json", help="json --help") + subparsers["json"].set_defaults( + func=do_json, error=subparsers["json"].error) + subparsers["json"].add_argument( + "logdirs", type=str, metavar="<logdir>", nargs="*", + help="specify directories with log files to parse") + # Command: help. + subparsers["help"] = subparser_adder.add_parser( + "help", help="help information") + subparsers["help"].set_defaults( + func=lambda args: do_help(parser, subparsers, args), + error=subparsers["help"].error) + subparsers["help"].add_argument( + "help_cmd", type=str, metavar="<command>", nargs="?", + help="command for which to display help") + # Execute the command. + args = parser.parse_args() + setattr(args, 'script_path', os.path.dirname(sys.argv[0])) + if args.command == "run" and coexist(args.sites_file, args.sites): + args.error("use either option --sites-file or site URLs") + sys.exit(1) + elif args.command == "run" and not coexist(args.replay_wpr, args.replay_bin): + args.error("options --replay-wpr and --replay-bin must be used together") + sys.exit(1) + else: + args.func(args) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/check-static-initializers.gyp b/tools/check-static-initializers.gyp index 547a6c87..cfeacfc8 100644 --- a/tools/check-static-initializers.gyp +++ b/tools/check-static-initializers.gyp @@ -13,8 +13,8 @@ '../src/d8.gyp:d8_run', ], 'includes': [ - '../build/features.gypi', - '../build/isolate.gypi', + '../gypfiles/features.gypi', + '../gypfiles/isolate.gypi', ], 'sources': [ 'check-static-initializers.isolate', diff --git a/tools/codemap.js b/tools/codemap.js index fa6c36b5..30cdc21d 100644 --- a/tools/codemap.js +++ b/tools/codemap.js @@ -246,6 +246,14 @@ CodeMap.prototype.getAllStaticEntries = function() { /** + * Returns an array of pairs of all static code entries and their addresses. + */ +CodeMap.prototype.getAllStaticEntriesWithAddresses = function() { + return this.statics_.exportKeysAndValues(); +}; + + +/** * Returns an array of all libraries entries. */ CodeMap.prototype.getAllLibrariesEntries = function() { diff --git a/tools/dump-cpp.py b/tools/dump-cpp.py new file mode 100644 index 00000000..b7bb32e9 --- /dev/null +++ b/tools/dump-cpp.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# Copyright 2016 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. + +# This script executes dumpcpp.js, collects all dumped C++ symbols, +# and merges them back into v8 log. + +import os +import platform +import re +import subprocess +import sys + +def is_file_executable(fPath): + return os.path.isfile(fPath) and os.access(fPath, os.X_OK) + +if __name__ == '__main__': + JS_FILES = ['splaytree.js', 'codemap.js', 'csvparser.js', 'consarray.js', + 'profile.js', 'logreader.js', 'tickprocessor.js', 'SourceMap.js', + 'dumpcpp.js'] + tools_path = os.path.dirname(os.path.realpath(__file__)) + on_windows = platform.system() == 'Windows' + JS_FILES = [os.path.join(tools_path, f) for f in JS_FILES] + + args = [] + log_file = 'v8.log' + debug = False + for arg in sys.argv[1:]: + if arg == '--debug': + debug = True + continue + args.append(arg) + if not arg.startswith('-'): + log_file = arg + + if on_windows: + args.append('--windows') + + with open(log_file, 'r') as f: + lines = f.readlines() + + d8_line = re.search(',\"(.*d8)', ''.join(lines)) + if d8_line: + d8_exec = d8_line.group(1) + if not is_file_executable(d8_exec): + print 'd8 binary path found in {} is not executable.'.format(log_file) + sys.exit(-1) + else: + print 'No d8 binary path found in {}.'.format(log_file) + sys.exit(-1) + + args = [d8_exec] + JS_FILES + ['--'] + args + + with open(log_file) as f: + sp = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + stdin=f) + out, err = sp.communicate() + if debug: + print err + if sp.returncode != 0: + print out + exit(-1) + + if on_windows and out: + out = re.sub('\r+\n', '\n', out) + + is_written = not bool(out) + with open(log_file, 'w') as f: + for line in lines: + if not is_written and line.startswith('tick'): + f.write(out) + is_written = True + f.write(line) diff --git a/tools/dumpcpp.js b/tools/dumpcpp.js new file mode 100644 index 00000000..28885e0c --- /dev/null +++ b/tools/dumpcpp.js @@ -0,0 +1,100 @@ +// Copyright 2016 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. + +// Dump C++ symbols of shared library if possible + +function processArguments(args) { + var processor = new ArgumentsProcessor(args); + if (processor.parse()) { + return processor.result(); + } else { + processor.printUsageAndExit(); + } +} + +function initSourceMapSupport() { + // Pull dev tools source maps into our name space. + SourceMap = WebInspector.SourceMap; + + // Overwrite the load function to load scripts synchronously. + SourceMap.load = function(sourceMapURL) { + var content = readFile(sourceMapURL); + var sourceMapObject = (JSON.parse(content)); + return new SourceMap(sourceMapURL, sourceMapObject); + }; +} + +var entriesProviders = { + 'unix': UnixCppEntriesProvider, + 'windows': WindowsCppEntriesProvider, + 'mac': MacCppEntriesProvider +}; + +var params = processArguments(arguments); +var sourceMap = null; +if (params.sourceMap) { + initSourceMapSupport(); + sourceMap = SourceMap.load(params.sourceMap); +} + +function CppProcessor(cppEntriesProvider, timedRange, pairwiseTimedRange) { + LogReader.call(this, { + 'shared-library': { parsers: [null, parseInt, parseInt], + processor: this.processSharedLibrary } + }, timedRange, pairwiseTimedRange); + + this.cppEntriesProvider_ = cppEntriesProvider; + this.codeMap_ = new CodeMap(); + this.lastLogFileName_ = null; +} +inherits(CppProcessor, LogReader); + +/** + * @override + */ +CppProcessor.prototype.printError = function(str) { + print(str); +}; + +CppProcessor.prototype.processLogFile = function(fileName) { + this.lastLogFileName_ = fileName; + var line; + while (line = readline()) { + this.processLogLine(line); + } +}; + +CppProcessor.prototype.processLogFileInTest = function(fileName) { + // Hack file name to avoid dealing with platform specifics. + this.lastLogFileName_ = 'v8.log'; + var contents = readFile(fileName); + this.processLogChunk(contents); +}; + +CppProcessor.prototype.processSharedLibrary = function( + name, startAddr, endAddr) { + var self = this; + var libFuncs = this.cppEntriesProvider_.parseVmSymbols( + name, startAddr, endAddr, function(fName, fStart, fEnd) { + var entry = new CodeMap.CodeEntry(fEnd - fStart, fName, 'CPP'); + self.codeMap_.addStaticCode(fStart, entry); + }); +}; + +CppProcessor.prototype.dumpCppSymbols = function() { + var staticEntries = this.codeMap_.getAllStaticEntriesWithAddresses(); + var total = staticEntries.length; + for (var i = 0; i < total; ++i) { + var entry = staticEntries[i]; + var printValues = ['cpp', '0x' + entry[0].toString(16), entry[1].size, + '"' + entry[1].name + '"']; + print(printValues.join(',')); + } +}; + +var cppProcessor = new CppProcessor( + new (entriesProviders[params.platform])(params.nm, params.targetRootFS), + params.timedRange, params.pairwiseTimedRange); +cppProcessor.processLogFile(params.logFileName); +cppProcessor.dumpCppSymbols(); diff --git a/tools/eval_gc_nvp.py b/tools/eval_gc_nvp.py index fcb6d8b9..25afe8e4 100755 --- a/tools/eval_gc_nvp.py +++ b/tools/eval_gc_nvp.py @@ -10,7 +10,7 @@ from argparse import ArgumentParser from copy import deepcopy from gc_nvp_common import split_nvp -from math import log +from math import ceil,log from sys import stdin @@ -74,11 +74,12 @@ class Histogram: class Category: - def __init__(self, key, histogram, csv): + def __init__(self, key, histogram, csv, percentiles): self.key = key self.values = [] self.histogram = histogram self.csv = csv + self.percentiles = percentiles def process_entry(self, entry): if self.key in entry: @@ -100,6 +101,16 @@ class Category: def empty(self): return len(self.values) == 0 + def _compute_percentiles(self): + ret = [] + if len(self.values) == 0: + return ret + sorted_values = sorted(self.values) + for percentile in self.percentiles: + index = int(ceil((len(self.values) - 1) * percentile / 100)) + ret.append(" {0}%: {1}".format(percentile, sorted_values[index])) + return ret + def __str__(self): if self.csv: ret = [self.key] @@ -118,6 +129,8 @@ class Category: ret.append(" avg: {0}".format(self.avg())) if self.histogram: ret.append(str(self.histogram)) + if self.percentiles: + ret.append("\n".join(self._compute_percentiles())) return "\n".join(ret) def __repr__(self): @@ -160,6 +173,9 @@ def main(): help="rank keys by metric (default: no)") parser.add_argument('--csv', dest='csv', action='store_true', help='provide output as csv') + parser.add_argument('--percentiles', dest='percentiles', + type=str, default="", + help='comma separated list of percentiles') args = parser.parse_args() histogram = None @@ -171,7 +187,14 @@ def main(): bucket_trait = LinearBucket(args.linear_histogram_granularity) histogram = Histogram(bucket_trait, not args.histogram_omit_empty) - categories = [ Category(key, deepcopy(histogram), args.csv) + percentiles = [] + for percentile in args.percentiles.split(','): + try: + percentiles.append(float(percentile)) + except ValueError: + pass + + categories = [ Category(key, deepcopy(histogram), args.csv, percentiles) for key in args.keys ] while True: diff --git a/tools/eval_gc_time.sh b/tools/eval_gc_time.sh index ceb4db54..140165da 100755 --- a/tools/eval_gc_time.sh +++ b/tools/eval_gc_time.sh @@ -17,6 +17,7 @@ print_usage_and_die() { echo " -c|--csv provide csv output" echo " -f|--file FILE profile input in a file" echo " (default: stdin)" + echo " -p|--percentiles comma separated percentiles" exit 1 } @@ -25,6 +26,7 @@ RANK_MODE=max TOP_LEVEL=no CSV="" LOGFILE=/dev/stdin +PERCENTILES="" while [[ $# -ge 1 ]] do @@ -60,6 +62,10 @@ do LOGFILE=$2 shift ;; + -p|--percentiles) + PERCENTILES="--percentiles=$2" + shift + ;; *) break ;; @@ -98,7 +104,6 @@ INTERESTING_OLD_GEN_KEYS="\ evacuate.clean_up \ evacuate.copy \ evacuate.update_pointers \ - evacuate.update_pointers.between_evacuated \ evacuate.update_pointers.to_evacuated \ evacuate.update_pointers.to_new \ evacuate.update_pointers.weak \ @@ -145,6 +150,7 @@ case $OP in --no-histogram \ --rank $RANK_MODE \ $CSV \ + $PERCENTILES \ ${INTERESTING_NEW_GEN_KEYS} ;; old-gen-rank) @@ -153,6 +159,7 @@ case $OP in --no-histogram \ --rank $RANK_MODE \ $CSV \ + $PERCENTILES \ ${INTERESTING_OLD_GEN_KEYS} ;; *) diff --git a/tools/gcmole/gcmole.lua b/tools/gcmole/gcmole.lua index 82ea4e02..f16ad8fd 100644 --- a/tools/gcmole/gcmole.lua +++ b/tools/gcmole/gcmole.lua @@ -185,7 +185,7 @@ end local function ParseGYPFile() local gyp = "" - local gyp_files = { "tools/gyp/v8.gyp", "test/cctest/cctest.gyp" } + local gyp_files = { "src/v8.gyp", "test/cctest/cctest.gyp" } for i = 1, #gyp_files do local f = assert(io.open(gyp_files[i]), "failed to open GYP file") local t = f:read('*a') diff --git a/tools/gcmole/run-gcmole.isolate b/tools/gcmole/run-gcmole.isolate index df6e9a26..39990dee 100644 --- a/tools/gcmole/run-gcmole.isolate +++ b/tools/gcmole/run-gcmole.isolate @@ -12,7 +12,6 @@ 'parallel.py', 'run-gcmole.py', # The following contains all relevant source and gyp files. - '../gyp/v8.gyp', '../../base/', '../../include/', '../../src/', diff --git a/tools/gcmole/run_gcmole.gyp b/tools/gcmole/run_gcmole.gyp index 9d13f760..7d206bf4 100644 --- a/tools/gcmole/run_gcmole.gyp +++ b/tools/gcmole/run_gcmole.gyp @@ -10,8 +10,8 @@ 'target_name': 'run_gcmole_run', 'type': 'none', 'includes': [ - '../../build/features.gypi', - '../../build/isolate.gypi', + '../../gypfiles/features.gypi', + '../../gypfiles/isolate.gypi', ], 'sources': [ 'run-gcmole.isolate', diff --git a/tools/gen-postmortem-metadata.py b/tools/gen-postmortem-metadata.py index a0afc06a..55f915d3 100644 --- a/tools/gen-postmortem-metadata.py +++ b/tools/gen-postmortem-metadata.py @@ -92,6 +92,8 @@ consts_misc = [ 'value': 'DescriptorArray::kFirstIndex' }, { 'name': 'prop_type_field', 'value': 'DATA' }, + { 'name': 'prop_type_const_field', + 'value': 'DATA_CONSTANT' }, { 'name': 'prop_type_mask', 'value': 'PropertyDetails::TypeField::kMask' }, { 'name': 'prop_index_mask', diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp deleted file mode 100644 index b09fd1f2..00000000 --- a/tools/gyp/v8.gyp +++ /dev/null @@ -1,2281 +0,0 @@ -# Copyright 2012 the V8 project authors. All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'variables': { - 'icu_use_data_file_flag%': 0, - 'v8_code': 1, - 'v8_random_seed%': 314159265, - 'v8_vector_stores%': 0, - 'embed_script%': "", - 'warmup_script%': "", - 'v8_extra_library_files%': [], - 'v8_experimental_extra_library_files%': [], - 'mksnapshot_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)', - }, - 'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'], - 'targets': [ - { - 'target_name': 'v8', - 'dependencies_traverse': 1, - 'dependencies': ['v8_maybe_snapshot'], - 'conditions': [ - ['want_separate_host_toolset==1', { - 'toolsets': ['host', 'target'], - }, { - 'toolsets': ['target'], - }], - ['component=="shared_library"', { - 'type': '<(component)', - 'sources': [ - # Note: on non-Windows we still build this file so that gyp - # has some sources to link into the component. - '../../src/v8dll-main.cc', - ], - 'include_dirs': [ - '../..', - ], - 'defines': [ - 'V8_SHARED', - 'BUILDING_V8_SHARED', - ], - 'direct_dependent_settings': { - 'defines': [ - 'V8_SHARED', - 'USING_V8_SHARED', - ], - }, - 'target_conditions': [ - ['OS=="android" and _toolset=="target"', { - 'libraries': [ - '-llog', - ], - 'include_dirs': [ - 'src/common/android/include', - ], - }], - ], - 'conditions': [ - ['OS=="mac"', { - 'xcode_settings': { - 'OTHER_LDFLAGS': ['-dynamiclib', '-all_load'] - }, - }], - ['soname_version!=""', { - 'product_extension': 'so.<(soname_version)', - }], - ], - }, - { - 'type': 'none', - }], - ], - 'direct_dependent_settings': { - 'include_dirs': [ - '../../include', - ], - }, - }, - { - # This rule delegates to either v8_snapshot, v8_nosnapshot, or - # v8_external_snapshot, depending on the current variables. - # The intention is to make the 'calling' rules a bit simpler. - 'target_name': 'v8_maybe_snapshot', - 'type': 'none', - 'conditions': [ - ['v8_use_snapshot!="true"', { - # The dependency on v8_base should come from a transitive - # dependency however the Android toolchain requires libv8_base.a - # to appear before libv8_snapshot.a so it's listed explicitly. - 'dependencies': ['v8_base', 'v8_nosnapshot'], - }], - ['v8_use_snapshot=="true" and v8_use_external_startup_data==0', { - # The dependency on v8_base should come from a transitive - # dependency however the Android toolchain requires libv8_base.a - # to appear before libv8_snapshot.a so it's listed explicitly. - 'dependencies': ['v8_base', 'v8_snapshot'], - }], - ['v8_use_snapshot=="true" and v8_use_external_startup_data==1 and want_separate_host_toolset==0', { - 'dependencies': ['v8_base', 'v8_external_snapshot'], - 'inputs': ['<(PRODUCT_DIR)/snapshot_blob.bin'], - 'conditions': [ - ['v8_separate_ignition_snapshot==1', { - 'inputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition.bin'], - }], - ] - }], - ['v8_use_snapshot=="true" and v8_use_external_startup_data==1 and want_separate_host_toolset==1', { - 'dependencies': ['v8_base', 'v8_external_snapshot'], - 'target_conditions': [ - ['_toolset=="host"', { - 'inputs': ['<(PRODUCT_DIR)/snapshot_blob_host.bin'], - }, { - 'inputs': ['<(PRODUCT_DIR)/snapshot_blob.bin'], - }], - ], - 'conditions': [ - ['v8_separate_ignition_snapshot==1', { - 'target_conditions': [ - ['_toolset=="host"', { - 'inputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition_host.bin'], - }, { - 'inputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition.bin'], - }], - ], - }], - ], - }], - ['want_separate_host_toolset==1', { - 'toolsets': ['host', 'target'], - }, { - 'toolsets': ['target'], - }], - ] - }, - { - 'target_name': 'v8_snapshot', - 'type': 'static_library', - 'conditions': [ - ['want_separate_host_toolset==1', { - 'toolsets': ['host', 'target'], - 'dependencies': [ - 'mksnapshot#host', - 'js2c#host', - ], - }, { - 'toolsets': ['target'], - 'dependencies': [ - 'mksnapshot', - 'js2c', - ], - }], - ['component=="shared_library"', { - 'defines': [ - 'V8_SHARED', - 'BUILDING_V8_SHARED', - ], - 'direct_dependent_settings': { - 'defines': [ - 'V8_SHARED', - 'USING_V8_SHARED', - ], - }, - }], - ], - 'dependencies': [ - 'v8_base', - ], - 'include_dirs+': [ - '../..', - ], - 'sources': [ - '<(SHARED_INTERMEDIATE_DIR)/libraries.cc', - '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc', - '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc', - '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc', - '<(INTERMEDIATE_DIR)/snapshot.cc', - ], - 'actions': [ - { - 'action_name': 'run_mksnapshot', - 'inputs': [ - '<(mksnapshot_exec)', - '<(embed_script)', - '<(warmup_script)', - ], - 'outputs': [ - '<(INTERMEDIATE_DIR)/snapshot.cc', - ], - 'variables': { - 'mksnapshot_flags': [], - 'conditions': [ - ['v8_random_seed!=0', { - 'mksnapshot_flags': ['--random-seed', '<(v8_random_seed)'], - }], - ['v8_vector_stores!=0', { - 'mksnapshot_flags': ['--vector-stores'], - }], - ], - }, - 'action': [ - '<(mksnapshot_exec)', - '<@(mksnapshot_flags)', - '--startup_src', '<@(INTERMEDIATE_DIR)/snapshot.cc', - '<(embed_script)', - '<(warmup_script)', - ], - }, - ], - }, - { - 'target_name': 'v8_nosnapshot', - 'type': 'static_library', - 'dependencies': [ - 'v8_base', - ], - 'include_dirs+': [ - '../..', - ], - 'sources': [ - '<(SHARED_INTERMEDIATE_DIR)/libraries.cc', - '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc', - '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc', - '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc', - '../../src/snapshot/snapshot-empty.cc', - ], - 'conditions': [ - ['want_separate_host_toolset==1', { - 'toolsets': ['host', 'target'], - 'dependencies': ['js2c#host'], - }, { - 'toolsets': ['target'], - 'dependencies': ['js2c'], - }], - ['component=="shared_library"', { - 'defines': [ - 'BUILDING_V8_SHARED', - 'V8_SHARED', - ], - }], - ] - }, - { - 'target_name': 'v8_external_snapshot', - 'type': 'static_library', - 'conditions': [ - [ 'v8_use_external_startup_data==1', { - 'conditions': [ - ['want_separate_host_toolset==1', { - 'toolsets': ['host', 'target'], - 'dependencies': [ - 'mksnapshot#host', - 'js2c#host', - 'natives_blob', - ]}, { - 'toolsets': ['target'], - 'dependencies': [ - 'mksnapshot', - 'js2c', - 'natives_blob', - ], - }], - ['component=="shared_library"', { - 'defines': [ - 'V8_SHARED', - 'BUILDING_V8_SHARED', - ], - 'direct_dependent_settings': { - 'defines': [ - 'V8_SHARED', - 'USING_V8_SHARED', - ], - }, - }], - # Extra snapshot blob for ignition. - ['v8_separate_ignition_snapshot==1', { - # This is concatenated to the other actions list of - # v8_external_snapshot. - 'actions': [ - { - 'action_name': 'run_mksnapshot (ignition)', - 'inputs': ['<(mksnapshot_exec)'], - 'variables': { - # TODO: Extract common mksnapshot_flags to a separate - # variable. - 'mksnapshot_flags_ignition': [ - '--ignition', - ], - 'conditions': [ - ['v8_random_seed!=0', { - 'mksnapshot_flags_ignition': ['--random-seed', '<(v8_random_seed)'], - }], - ['v8_vector_stores!=0', { - 'mksnapshot_flags_ignition': ['--vector-stores'], - }], - ], - }, - 'conditions': [ - ['want_separate_host_toolset==1', { - 'target_conditions': [ - ['_toolset=="host"', { - 'outputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition_host.bin'], - 'action': [ - '<(mksnapshot_exec)', - '<@(mksnapshot_flags_ignition)', - '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_ignition_host.bin', - '<(embed_script)', - '<(warmup_script)', - ], - }, { - 'outputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition.bin'], - 'action': [ - '<(mksnapshot_exec)', - '<@(mksnapshot_flags_ignition)', - '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_ignition.bin', - '<(embed_script)', - '<(warmup_script)', - ], - }], - ], - }, { - 'outputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition.bin'], - 'action': [ - '<(mksnapshot_exec)', - '<@(mksnapshot_flags_ignition)', - '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_ignition.bin', - '<(embed_script)', - '<(warmup_script)', - ], - }], - ], - }, - ], - }], - ], - 'dependencies': [ - 'v8_base', - ], - 'include_dirs+': [ - '../..', - ], - 'sources': [ - '../../src/snapshot/natives-external.cc', - '../../src/snapshot/snapshot-external.cc', - ], - 'actions': [ - { - 'action_name': 'run_mksnapshot (external)', - 'inputs': ['<(mksnapshot_exec)'], - 'variables': { - 'mksnapshot_flags': [], - 'conditions': [ - ['v8_random_seed!=0', { - 'mksnapshot_flags': ['--random-seed', '<(v8_random_seed)'], - }], - ['v8_vector_stores!=0', { - 'mksnapshot_flags': ['--vector-stores'], - }], - ], - }, - 'conditions': [ - ['want_separate_host_toolset==1', { - 'target_conditions': [ - ['_toolset=="host"', { - 'outputs': ['<(PRODUCT_DIR)/snapshot_blob_host.bin'], - 'action': [ - '<(mksnapshot_exec)', - '<@(mksnapshot_flags)', - '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_host.bin', - '<(embed_script)', - '<(warmup_script)', - ], - }, { - 'outputs': ['<(PRODUCT_DIR)/snapshot_blob.bin'], - 'action': [ - '<(mksnapshot_exec)', - '<@(mksnapshot_flags)', - '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob.bin', - '<(embed_script)', - '<(warmup_script)', - ], - }], - ], - }, { - 'outputs': ['<(PRODUCT_DIR)/snapshot_blob.bin'], - 'action': [ - '<(mksnapshot_exec)', - '<@(mksnapshot_flags)', - '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob.bin', - '<(embed_script)', - '<(warmup_script)', - ], - }], - ], - }, - ], - }], - ], - }, - { - 'target_name': 'v8_base', - 'type': 'static_library', - 'dependencies': [ - 'v8_libbase', - ], - 'variables': { - 'optimize': 'max', - }, - 'include_dirs+': [ - '../..', - # To be able to find base/trace_event/common/trace_event_common.h - '../../..', - ], - 'defines': [ - # TODO(jochen): Remove again after this is globally turned on. - 'V8_IMMINENT_DEPRECATION_WARNINGS', - ], - 'sources': [ ### gcmole(all) ### - '../../include/v8-debug.h', - '../../include/v8-experimental.h', - '../../include/v8-platform.h', - '../../include/v8-profiler.h', - '../../include/v8-testing.h', - '../../include/v8-util.h', - '../../include/v8-version.h', - '../../include/v8.h', - '../../include/v8config.h', - '../../src/accessors.cc', - '../../src/accessors.h', - '../../src/address-map.cc', - '../../src/address-map.h', - '../../src/allocation.cc', - '../../src/allocation.h', - '../../src/allocation-site-scopes.cc', - '../../src/allocation-site-scopes.h', - '../../src/api-experimental.cc', - '../../src/api-experimental.h', - '../../src/api.cc', - '../../src/api.h', - '../../src/api-arguments.cc', - '../../src/api-arguments.h', - '../../src/api-natives.cc', - '../../src/api-natives.h', - '../../src/arguments.cc', - '../../src/arguments.h', - '../../src/assembler.cc', - '../../src/assembler.h', - '../../src/assert-scope.h', - '../../src/assert-scope.cc', - '../../src/ast/ast-expression-rewriter.cc', - '../../src/ast/ast-expression-rewriter.h', - '../../src/ast/ast-expression-visitor.cc', - '../../src/ast/ast-expression-visitor.h', - '../../src/ast/ast-literal-reindexer.cc', - '../../src/ast/ast-literal-reindexer.h', - '../../src/ast/ast-numbering.cc', - '../../src/ast/ast-numbering.h', - '../../src/ast/ast-value-factory.cc', - '../../src/ast/ast-value-factory.h', - '../../src/ast/ast.cc', - '../../src/ast/ast.h', - '../../src/ast/modules.cc', - '../../src/ast/modules.h', - '../../src/ast/prettyprinter.cc', - '../../src/ast/prettyprinter.h', - '../../src/ast/scopeinfo.cc', - '../../src/ast/scopeinfo.h', - '../../src/ast/scopes.cc', - '../../src/ast/scopes.h', - '../../src/ast/variables.cc', - '../../src/ast/variables.h', - '../../src/atomic-utils.h', - '../../src/background-parsing-task.cc', - '../../src/background-parsing-task.h', - '../../src/bailout-reason.cc', - '../../src/bailout-reason.h', - '../../src/basic-block-profiler.cc', - '../../src/basic-block-profiler.h', - '../../src/bignum-dtoa.cc', - '../../src/bignum-dtoa.h', - '../../src/bignum.cc', - '../../src/bignum.h', - '../../src/bit-vector.cc', - '../../src/bit-vector.h', - '../../src/bootstrapper.cc', - '../../src/bootstrapper.h', - '../../src/builtins.cc', - '../../src/builtins.h', - '../../src/cached-powers.cc', - '../../src/cached-powers.h', - '../../src/cancelable-task.cc', - '../../src/cancelable-task.h', - '../../src/char-predicates.cc', - '../../src/char-predicates-inl.h', - '../../src/char-predicates.h', - '../../src/checks.h', - '../../src/code-factory.cc', - '../../src/code-factory.h', - '../../src/code-stubs.cc', - '../../src/code-stubs.h', - '../../src/code-stubs-hydrogen.cc', - '../../src/codegen.cc', - '../../src/codegen.h', - '../../src/collector.h', - '../../src/compilation-cache.cc', - '../../src/compilation-cache.h', - '../../src/compilation-dependencies.cc', - '../../src/compilation-dependencies.h', - '../../src/compilation-statistics.cc', - '../../src/compilation-statistics.h', - '../../src/compiler/access-builder.cc', - '../../src/compiler/access-builder.h', - '../../src/compiler/access-info.cc', - '../../src/compiler/access-info.h', - '../../src/compiler/all-nodes.cc', - '../../src/compiler/all-nodes.h', - '../../src/compiler/ast-graph-builder.cc', - '../../src/compiler/ast-graph-builder.h', - '../../src/compiler/ast-loop-assignment-analyzer.cc', - '../../src/compiler/ast-loop-assignment-analyzer.h', - '../../src/compiler/basic-block-instrumentor.cc', - '../../src/compiler/basic-block-instrumentor.h', - '../../src/compiler/branch-elimination.cc', - '../../src/compiler/branch-elimination.h', - '../../src/compiler/bytecode-branch-analysis.cc', - '../../src/compiler/bytecode-branch-analysis.h', - '../../src/compiler/bytecode-graph-builder.cc', - '../../src/compiler/bytecode-graph-builder.h', - '../../src/compiler/change-lowering.cc', - '../../src/compiler/change-lowering.h', - '../../src/compiler/c-linkage.cc', - '../../src/compiler/coalesced-live-ranges.cc', - '../../src/compiler/coalesced-live-ranges.h', - '../../src/compiler/code-generator-impl.h', - '../../src/compiler/code-generator.cc', - '../../src/compiler/code-generator.h', - '../../src/compiler/code-stub-assembler.cc', - '../../src/compiler/code-stub-assembler.h', - '../../src/compiler/common-node-cache.cc', - '../../src/compiler/common-node-cache.h', - '../../src/compiler/common-operator-reducer.cc', - '../../src/compiler/common-operator-reducer.h', - '../../src/compiler/common-operator.cc', - '../../src/compiler/common-operator.h', - '../../src/compiler/control-builders.cc', - '../../src/compiler/control-builders.h', - '../../src/compiler/control-equivalence.cc', - '../../src/compiler/control-equivalence.h', - '../../src/compiler/control-flow-optimizer.cc', - '../../src/compiler/control-flow-optimizer.h', - '../../src/compiler/dead-code-elimination.cc', - '../../src/compiler/dead-code-elimination.h', - '../../src/compiler/diamond.h', - '../../src/compiler/escape-analysis.cc', - '../../src/compiler/escape-analysis.h', - "../../src/compiler/escape-analysis-reducer.cc", - "../../src/compiler/escape-analysis-reducer.h", - '../../src/compiler/frame.cc', - '../../src/compiler/frame.h', - '../../src/compiler/frame-elider.cc', - '../../src/compiler/frame-elider.h', - "../../src/compiler/frame-states.cc", - "../../src/compiler/frame-states.h", - '../../src/compiler/gap-resolver.cc', - '../../src/compiler/gap-resolver.h', - '../../src/compiler/graph-reducer.cc', - '../../src/compiler/graph-reducer.h', - '../../src/compiler/graph-replay.cc', - '../../src/compiler/graph-replay.h', - '../../src/compiler/graph-trimmer.cc', - '../../src/compiler/graph-trimmer.h', - '../../src/compiler/graph-visualizer.cc', - '../../src/compiler/graph-visualizer.h', - '../../src/compiler/graph.cc', - '../../src/compiler/graph.h', - '../../src/compiler/greedy-allocator.cc', - '../../src/compiler/greedy-allocator.h', - '../../src/compiler/instruction-codes.h', - '../../src/compiler/instruction-selector-impl.h', - '../../src/compiler/instruction-selector.cc', - '../../src/compiler/instruction-selector.h', - '../../src/compiler/instruction-scheduler.cc', - '../../src/compiler/instruction-scheduler.h', - '../../src/compiler/instruction.cc', - '../../src/compiler/instruction.h', - '../../src/compiler/int64-lowering.cc', - '../../src/compiler/int64-lowering.h', - '../../src/compiler/js-builtin-reducer.cc', - '../../src/compiler/js-builtin-reducer.h', - '../../src/compiler/js-call-reducer.cc', - '../../src/compiler/js-call-reducer.h', - '../../src/compiler/js-context-specialization.cc', - '../../src/compiler/js-context-specialization.h', - '../../src/compiler/js-create-lowering.cc', - '../../src/compiler/js-create-lowering.h', - '../../src/compiler/js-frame-specialization.cc', - '../../src/compiler/js-frame-specialization.h', - '../../src/compiler/js-generic-lowering.cc', - '../../src/compiler/js-generic-lowering.h', - '../../src/compiler/js-global-object-specialization.cc', - '../../src/compiler/js-global-object-specialization.h', - '../../src/compiler/js-graph.cc', - '../../src/compiler/js-graph.h', - '../../src/compiler/js-inlining.cc', - '../../src/compiler/js-inlining.h', - '../../src/compiler/js-inlining-heuristic.cc', - '../../src/compiler/js-inlining-heuristic.h', - '../../src/compiler/js-intrinsic-lowering.cc', - '../../src/compiler/js-intrinsic-lowering.h', - '../../src/compiler/js-native-context-specialization.cc', - '../../src/compiler/js-native-context-specialization.h', - '../../src/compiler/js-operator.cc', - '../../src/compiler/js-operator.h', - '../../src/compiler/js-typed-lowering.cc', - '../../src/compiler/js-typed-lowering.h', - '../../src/compiler/jump-threading.cc', - '../../src/compiler/jump-threading.h', - '../../src/compiler/linkage.cc', - '../../src/compiler/linkage.h', - '../../src/compiler/liveness-analyzer.cc', - '../../src/compiler/liveness-analyzer.h', - '../../src/compiler/live-range-separator.cc', - '../../src/compiler/live-range-separator.h', - '../../src/compiler/load-elimination.cc', - '../../src/compiler/load-elimination.h', - '../../src/compiler/loop-analysis.cc', - '../../src/compiler/loop-analysis.h', - '../../src/compiler/loop-peeling.cc', - '../../src/compiler/loop-peeling.h', - '../../src/compiler/machine-operator-reducer.cc', - '../../src/compiler/machine-operator-reducer.h', - '../../src/compiler/machine-operator.cc', - '../../src/compiler/machine-operator.h', - '../../src/compiler/move-optimizer.cc', - '../../src/compiler/move-optimizer.h', - '../../src/compiler/node-aux-data.h', - '../../src/compiler/node-cache.cc', - '../../src/compiler/node-cache.h', - '../../src/compiler/node-marker.cc', - '../../src/compiler/node-marker.h', - '../../src/compiler/node-matchers.cc', - '../../src/compiler/node-matchers.h', - '../../src/compiler/node-properties.cc', - '../../src/compiler/node-properties.h', - '../../src/compiler/node.cc', - '../../src/compiler/node.h', - '../../src/compiler/opcodes.cc', - '../../src/compiler/opcodes.h', - '../../src/compiler/operator-properties.cc', - '../../src/compiler/operator-properties.h', - '../../src/compiler/operator.cc', - '../../src/compiler/operator.h', - '../../src/compiler/osr.cc', - '../../src/compiler/osr.h', - '../../src/compiler/pipeline.cc', - '../../src/compiler/pipeline.h', - '../../src/compiler/pipeline-statistics.cc', - '../../src/compiler/pipeline-statistics.h', - '../../src/compiler/raw-machine-assembler.cc', - '../../src/compiler/raw-machine-assembler.h', - '../../src/compiler/register-allocator.cc', - '../../src/compiler/register-allocator.h', - '../../src/compiler/register-allocator-verifier.cc', - '../../src/compiler/register-allocator-verifier.h', - '../../src/compiler/representation-change.cc', - '../../src/compiler/representation-change.h', - '../../src/compiler/schedule.cc', - '../../src/compiler/schedule.h', - '../../src/compiler/scheduler.cc', - '../../src/compiler/scheduler.h', - '../../src/compiler/select-lowering.cc', - '../../src/compiler/select-lowering.h', - '../../src/compiler/simplified-lowering.cc', - '../../src/compiler/simplified-lowering.h', - '../../src/compiler/simplified-operator-reducer.cc', - '../../src/compiler/simplified-operator-reducer.h', - '../../src/compiler/simplified-operator.cc', - '../../src/compiler/simplified-operator.h', - '../../src/compiler/source-position.cc', - '../../src/compiler/source-position.h', - '../../src/compiler/state-values-utils.cc', - '../../src/compiler/state-values-utils.h', - '../../src/compiler/tail-call-optimization.cc', - '../../src/compiler/tail-call-optimization.h', - '../../src/compiler/type-hint-analyzer.cc', - '../../src/compiler/type-hint-analyzer.h', - '../../src/compiler/type-hints.cc', - '../../src/compiler/type-hints.h', - '../../src/compiler/typer.cc', - '../../src/compiler/typer.h', - '../../src/compiler/value-numbering-reducer.cc', - '../../src/compiler/value-numbering-reducer.h', - '../../src/compiler/verifier.cc', - '../../src/compiler/verifier.h', - '../../src/compiler/wasm-compiler.cc', - '../../src/compiler/wasm-compiler.h', - '../../src/compiler/wasm-linkage.cc', - '../../src/compiler/zone-pool.cc', - '../../src/compiler/zone-pool.h', - '../../src/compiler.cc', - '../../src/compiler.h', - '../../src/context-measure.cc', - '../../src/context-measure.h', - '../../src/contexts-inl.h', - '../../src/contexts.cc', - '../../src/contexts.h', - '../../src/conversions-inl.h', - '../../src/conversions.cc', - '../../src/conversions.h', - '../../src/counters.cc', - '../../src/counters.h', - '../../src/crankshaft/compilation-phase.cc', - '../../src/crankshaft/compilation-phase.h', - '../../src/crankshaft/hydrogen-alias-analysis.h', - '../../src/crankshaft/hydrogen-bce.cc', - '../../src/crankshaft/hydrogen-bce.h', - '../../src/crankshaft/hydrogen-canonicalize.cc', - '../../src/crankshaft/hydrogen-canonicalize.h', - '../../src/crankshaft/hydrogen-check-elimination.cc', - '../../src/crankshaft/hydrogen-check-elimination.h', - '../../src/crankshaft/hydrogen-dce.cc', - '../../src/crankshaft/hydrogen-dce.h', - '../../src/crankshaft/hydrogen-dehoist.cc', - '../../src/crankshaft/hydrogen-dehoist.h', - '../../src/crankshaft/hydrogen-environment-liveness.cc', - '../../src/crankshaft/hydrogen-environment-liveness.h', - '../../src/crankshaft/hydrogen-escape-analysis.cc', - '../../src/crankshaft/hydrogen-escape-analysis.h', - '../../src/crankshaft/hydrogen-flow-engine.h', - '../../src/crankshaft/hydrogen-gvn.cc', - '../../src/crankshaft/hydrogen-gvn.h', - '../../src/crankshaft/hydrogen-infer-representation.cc', - '../../src/crankshaft/hydrogen-infer-representation.h', - '../../src/crankshaft/hydrogen-infer-types.cc', - '../../src/crankshaft/hydrogen-infer-types.h', - '../../src/crankshaft/hydrogen-instructions.cc', - '../../src/crankshaft/hydrogen-instructions.h', - '../../src/crankshaft/hydrogen-load-elimination.cc', - '../../src/crankshaft/hydrogen-load-elimination.h', - '../../src/crankshaft/hydrogen-mark-deoptimize.cc', - '../../src/crankshaft/hydrogen-mark-deoptimize.h', - '../../src/crankshaft/hydrogen-mark-unreachable.cc', - '../../src/crankshaft/hydrogen-mark-unreachable.h', - '../../src/crankshaft/hydrogen-osr.cc', - '../../src/crankshaft/hydrogen-osr.h', - '../../src/crankshaft/hydrogen-range-analysis.cc', - '../../src/crankshaft/hydrogen-range-analysis.h', - '../../src/crankshaft/hydrogen-redundant-phi.cc', - '../../src/crankshaft/hydrogen-redundant-phi.h', - '../../src/crankshaft/hydrogen-removable-simulates.cc', - '../../src/crankshaft/hydrogen-removable-simulates.h', - '../../src/crankshaft/hydrogen-representation-changes.cc', - '../../src/crankshaft/hydrogen-representation-changes.h', - '../../src/crankshaft/hydrogen-sce.cc', - '../../src/crankshaft/hydrogen-sce.h', - '../../src/crankshaft/hydrogen-store-elimination.cc', - '../../src/crankshaft/hydrogen-store-elimination.h', - '../../src/crankshaft/hydrogen-types.cc', - '../../src/crankshaft/hydrogen-types.h', - '../../src/crankshaft/hydrogen-uint32-analysis.cc', - '../../src/crankshaft/hydrogen-uint32-analysis.h', - '../../src/crankshaft/hydrogen.cc', - '../../src/crankshaft/hydrogen.h', - '../../src/crankshaft/lithium-allocator-inl.h', - '../../src/crankshaft/lithium-allocator.cc', - '../../src/crankshaft/lithium-allocator.h', - '../../src/crankshaft/lithium-codegen.cc', - '../../src/crankshaft/lithium-codegen.h', - '../../src/crankshaft/lithium.cc', - '../../src/crankshaft/lithium.h', - '../../src/crankshaft/lithium-inl.h', - '../../src/crankshaft/typing.cc', - '../../src/crankshaft/typing.h', - '../../src/crankshaft/unique.h', - '../../src/date.cc', - '../../src/date.h', - '../../src/dateparser-inl.h', - '../../src/dateparser.cc', - '../../src/dateparser.h', - '../../src/debug/debug-evaluate.cc', - '../../src/debug/debug-evaluate.h', - '../../src/debug/debug-frames.cc', - '../../src/debug/debug-frames.h', - '../../src/debug/debug-scopes.cc', - '../../src/debug/debug-scopes.h', - '../../src/debug/debug.cc', - '../../src/debug/debug.h', - '../../src/debug/liveedit.cc', - '../../src/debug/liveedit.h', - '../../src/deoptimizer.cc', - '../../src/deoptimizer.h', - '../../src/disasm.h', - '../../src/disassembler.cc', - '../../src/disassembler.h', - '../../src/diy-fp.cc', - '../../src/diy-fp.h', - '../../src/double.h', - '../../src/dtoa.cc', - '../../src/dtoa.h', - '../../src/effects.h', - '../../src/elements-kind.cc', - '../../src/elements-kind.h', - '../../src/elements.cc', - '../../src/elements.h', - '../../src/execution.cc', - '../../src/execution.h', - '../../src/extensions/externalize-string-extension.cc', - '../../src/extensions/externalize-string-extension.h', - '../../src/extensions/free-buffer-extension.cc', - '../../src/extensions/free-buffer-extension.h', - '../../src/extensions/gc-extension.cc', - '../../src/extensions/gc-extension.h', - '../../src/extensions/statistics-extension.cc', - '../../src/extensions/statistics-extension.h', - '../../src/extensions/trigger-failure-extension.cc', - '../../src/extensions/trigger-failure-extension.h', - '../../src/external-reference-table.cc', - '../../src/external-reference-table.h', - '../../src/factory.cc', - '../../src/factory.h', - '../../src/fast-accessor-assembler.cc', - '../../src/fast-accessor-assembler.h', - '../../src/fast-dtoa.cc', - '../../src/fast-dtoa.h', - '../../src/field-index.h', - '../../src/field-index-inl.h', - '../../src/field-type.cc', - '../../src/field-type.h', - '../../src/fixed-dtoa.cc', - '../../src/fixed-dtoa.h', - '../../src/flag-definitions.h', - '../../src/flags.cc', - '../../src/flags.h', - '../../src/frames-inl.h', - '../../src/frames.cc', - '../../src/frames.h', - '../../src/full-codegen/full-codegen.cc', - '../../src/full-codegen/full-codegen.h', - '../../src/futex-emulation.cc', - '../../src/futex-emulation.h', - '../../src/gdb-jit.cc', - '../../src/gdb-jit.h', - '../../src/global-handles.cc', - '../../src/global-handles.h', - '../../src/globals.h', - '../../src/handles-inl.h', - '../../src/handles.cc', - '../../src/handles.h', - '../../src/hashmap.h', - '../../src/heap-symbols.h', - '../../src/heap/array-buffer-tracker.cc', - '../../src/heap/array-buffer-tracker.h', - '../../src/heap/memory-reducer.cc', - '../../src/heap/memory-reducer.h', - '../../src/heap/gc-idle-time-handler.cc', - '../../src/heap/gc-idle-time-handler.h', - '../../src/heap/gc-tracer.cc', - '../../src/heap/gc-tracer.h', - '../../src/heap/heap-inl.h', - '../../src/heap/heap.cc', - '../../src/heap/heap.h', - '../../src/heap/incremental-marking-inl.h', - '../../src/heap/incremental-marking-job.cc', - '../../src/heap/incremental-marking-job.h', - '../../src/heap/incremental-marking.cc', - '../../src/heap/incremental-marking.h', - '../../src/heap/mark-compact-inl.h', - '../../src/heap/mark-compact.cc', - '../../src/heap/mark-compact.h', - '../../src/heap/object-stats.cc', - '../../src/heap/object-stats.h', - '../../src/heap/objects-visiting-inl.h', - '../../src/heap/objects-visiting.cc', - '../../src/heap/objects-visiting.h', - '../../src/heap/page-parallel-job.h', - '../../src/heap/remembered-set.cc', - '../../src/heap/remembered-set.h', - '../../src/heap/scavenge-job.h', - '../../src/heap/scavenge-job.cc', - '../../src/heap/scavenger-inl.h', - '../../src/heap/scavenger.cc', - '../../src/heap/scavenger.h', - '../../src/heap/slot-set.h', - '../../src/heap/spaces-inl.h', - '../../src/heap/spaces.cc', - '../../src/heap/spaces.h', - '../../src/heap/store-buffer.cc', - '../../src/heap/store-buffer.h', - '../../src/i18n.cc', - '../../src/i18n.h', - '../../src/icu_util.cc', - '../../src/icu_util.h', - '../../src/ic/access-compiler.cc', - '../../src/ic/access-compiler.h', - '../../src/ic/call-optimization.cc', - '../../src/ic/call-optimization.h', - '../../src/ic/handler-compiler.cc', - '../../src/ic/handler-compiler.h', - '../../src/ic/ic-inl.h', - '../../src/ic/ic-state.cc', - '../../src/ic/ic-state.h', - '../../src/ic/ic.cc', - '../../src/ic/ic.h', - '../../src/ic/ic-compiler.cc', - '../../src/ic/ic-compiler.h', - '../../src/identity-map.cc', - '../../src/identity-map.h', - '../../src/interface-descriptors.cc', - '../../src/interface-descriptors.h', - '../../src/interpreter/bytecodes.cc', - '../../src/interpreter/bytecodes.h', - '../../src/interpreter/bytecode-array-builder.cc', - '../../src/interpreter/bytecode-array-builder.h', - '../../src/interpreter/bytecode-array-iterator.cc', - '../../src/interpreter/bytecode-array-iterator.h', - '../../src/interpreter/bytecode-register-allocator.cc', - '../../src/interpreter/bytecode-register-allocator.h', - '../../src/interpreter/bytecode-generator.cc', - '../../src/interpreter/bytecode-generator.h', - '../../src/interpreter/bytecode-traits.h', - '../../src/interpreter/constant-array-builder.cc', - '../../src/interpreter/constant-array-builder.h', - '../../src/interpreter/control-flow-builders.cc', - '../../src/interpreter/control-flow-builders.h', - '../../src/interpreter/handler-table-builder.cc', - '../../src/interpreter/handler-table-builder.h', - '../../src/interpreter/interpreter.cc', - '../../src/interpreter/interpreter.h', - '../../src/interpreter/interpreter-assembler.cc', - '../../src/interpreter/interpreter-assembler.h', - '../../src/interpreter/interpreter-intrinsics.cc', - '../../src/interpreter/interpreter-intrinsics.h', - '../../src/interpreter/source-position-table.cc', - '../../src/interpreter/source-position-table.h', - '../../src/isolate-inl.h', - '../../src/isolate.cc', - '../../src/isolate.h', - '../../src/json-parser.h', - '../../src/json-stringifier.h', - '../../src/keys.h', - '../../src/keys.cc', - '../../src/layout-descriptor-inl.h', - '../../src/layout-descriptor.cc', - '../../src/layout-descriptor.h', - '../../src/list-inl.h', - '../../src/list.h', - '../../src/locked-queue-inl.h', - '../../src/locked-queue.h', - '../../src/log-inl.h', - '../../src/log-utils.cc', - '../../src/log-utils.h', - '../../src/log.cc', - '../../src/log.h', - '../../src/lookup.cc', - '../../src/lookup.h', - '../../src/macro-assembler.h', - '../../src/machine-type.cc', - '../../src/machine-type.h', - '../../src/messages.cc', - '../../src/messages.h', - '../../src/msan.h', - '../../src/objects-body-descriptors-inl.h', - '../../src/objects-body-descriptors.h', - '../../src/objects-debug.cc', - '../../src/objects-inl.h', - '../../src/objects-printer.cc', - '../../src/objects.cc', - '../../src/objects.h', - '../../src/optimizing-compile-dispatcher.cc', - '../../src/optimizing-compile-dispatcher.h', - '../../src/ostreams.cc', - '../../src/ostreams.h', - '../../src/parsing/expression-classifier.h', - '../../src/parsing/func-name-inferrer.cc', - '../../src/parsing/func-name-inferrer.h', - '../../src/parsing/parameter-initializer-rewriter.cc', - '../../src/parsing/parameter-initializer-rewriter.h', - '../../src/parsing/parser-base.h', - '../../src/parsing/parser.cc', - '../../src/parsing/parser.h', - '../../src/parsing/pattern-rewriter.cc', - '../../src/parsing/preparse-data-format.h', - '../../src/parsing/preparse-data.cc', - '../../src/parsing/preparse-data.h', - '../../src/parsing/preparser.cc', - '../../src/parsing/preparser.h', - '../../src/parsing/rewriter.cc', - '../../src/parsing/rewriter.h', - '../../src/parsing/scanner-character-streams.cc', - '../../src/parsing/scanner-character-streams.h', - '../../src/parsing/scanner.cc', - '../../src/parsing/scanner.h', - '../../src/parsing/token.cc', - '../../src/parsing/token.h', - '../../src/pending-compilation-error-handler.cc', - '../../src/pending-compilation-error-handler.h', - '../../src/perf-jit.cc', - '../../src/perf-jit.h', - '../../src/profiler/allocation-tracker.cc', - '../../src/profiler/allocation-tracker.h', - '../../src/profiler/circular-queue-inl.h', - '../../src/profiler/circular-queue.h', - '../../src/profiler/cpu-profiler-inl.h', - '../../src/profiler/cpu-profiler.cc', - '../../src/profiler/cpu-profiler.h', - '../../src/profiler/heap-profiler.cc', - '../../src/profiler/heap-profiler.h', - '../../src/profiler/heap-snapshot-generator-inl.h', - '../../src/profiler/heap-snapshot-generator.cc', - '../../src/profiler/heap-snapshot-generator.h', - '../../src/profiler/profile-generator-inl.h', - '../../src/profiler/profile-generator.cc', - '../../src/profiler/profile-generator.h', - '../../src/profiler/sampler.cc', - '../../src/profiler/sampler.h', - '../../src/profiler/sampling-heap-profiler.cc', - '../../src/profiler/sampling-heap-profiler.h', - '../../src/profiler/strings-storage.cc', - '../../src/profiler/strings-storage.h', - '../../src/profiler/unbound-queue-inl.h', - '../../src/profiler/unbound-queue.h', - '../../src/property-descriptor.cc', - '../../src/property-descriptor.h', - '../../src/property-details.h', - '../../src/property.cc', - '../../src/property.h', - '../../src/prototype.h', - '../../src/regexp/bytecodes-irregexp.h', - '../../src/regexp/interpreter-irregexp.cc', - '../../src/regexp/interpreter-irregexp.h', - '../../src/regexp/jsregexp-inl.h', - '../../src/regexp/jsregexp.cc', - '../../src/regexp/jsregexp.h', - '../../src/regexp/regexp-ast.cc', - '../../src/regexp/regexp-ast.h', - '../../src/regexp/regexp-macro-assembler-irregexp-inl.h', - '../../src/regexp/regexp-macro-assembler-irregexp.cc', - '../../src/regexp/regexp-macro-assembler-irregexp.h', - '../../src/regexp/regexp-macro-assembler-tracer.cc', - '../../src/regexp/regexp-macro-assembler-tracer.h', - '../../src/regexp/regexp-macro-assembler.cc', - '../../src/regexp/regexp-macro-assembler.h', - '../../src/regexp/regexp-parser.cc', - '../../src/regexp/regexp-parser.h', - '../../src/regexp/regexp-stack.cc', - '../../src/regexp/regexp-stack.h', - '../../src/register-configuration.cc', - '../../src/register-configuration.h', - '../../src/runtime-profiler.cc', - '../../src/runtime-profiler.h', - '../../src/runtime/runtime-array.cc', - '../../src/runtime/runtime-atomics.cc', - '../../src/runtime/runtime-classes.cc', - '../../src/runtime/runtime-collections.cc', - '../../src/runtime/runtime-compiler.cc', - '../../src/runtime/runtime-date.cc', - '../../src/runtime/runtime-debug.cc', - '../../src/runtime/runtime-forin.cc', - '../../src/runtime/runtime-function.cc', - '../../src/runtime/runtime-futex.cc', - '../../src/runtime/runtime-generator.cc', - '../../src/runtime/runtime-i18n.cc', - '../../src/runtime/runtime-internal.cc', - '../../src/runtime/runtime-interpreter.cc', - '../../src/runtime/runtime-json.cc', - '../../src/runtime/runtime-literals.cc', - '../../src/runtime/runtime-liveedit.cc', - '../../src/runtime/runtime-maths.cc', - '../../src/runtime/runtime-numbers.cc', - '../../src/runtime/runtime-object.cc', - '../../src/runtime/runtime-observe.cc', - '../../src/runtime/runtime-operators.cc', - '../../src/runtime/runtime-proxy.cc', - '../../src/runtime/runtime-regexp.cc', - '../../src/runtime/runtime-scopes.cc', - '../../src/runtime/runtime-simd.cc', - '../../src/runtime/runtime-strings.cc', - '../../src/runtime/runtime-symbol.cc', - '../../src/runtime/runtime-test.cc', - '../../src/runtime/runtime-typedarray.cc', - '../../src/runtime/runtime-uri.cc', - '../../src/runtime/runtime-utils.h', - '../../src/runtime/runtime.cc', - '../../src/runtime/runtime.h', - '../../src/safepoint-table.cc', - '../../src/safepoint-table.h', - '../../src/signature.h', - '../../src/simulator.h', - '../../src/small-pointer-list.h', - '../../src/snapshot/code-serializer.cc', - '../../src/snapshot/code-serializer.h', - '../../src/snapshot/deserializer.cc', - '../../src/snapshot/deserializer.h', - '../../src/snapshot/natives.h', - '../../src/snapshot/natives-common.cc', - '../../src/snapshot/partial-serializer.cc', - '../../src/snapshot/partial-serializer.h', - '../../src/snapshot/serializer.cc', - '../../src/snapshot/serializer.h', - '../../src/snapshot/serializer-common.cc', - '../../src/snapshot/serializer-common.h', - '../../src/snapshot/snapshot.h', - '../../src/snapshot/snapshot-common.cc', - '../../src/snapshot/snapshot-source-sink.cc', - '../../src/snapshot/snapshot-source-sink.h', - '../../src/snapshot/startup-serializer.cc', - '../../src/snapshot/startup-serializer.h', - '../../src/source-position.h', - '../../src/splay-tree.h', - '../../src/splay-tree-inl.h', - '../../src/startup-data-util.cc', - '../../src/startup-data-util.h', - '../../src/string-builder.cc', - '../../src/string-builder.h', - '../../src/string-search.h', - '../../src/string-stream.cc', - '../../src/string-stream.h', - '../../src/strtod.cc', - '../../src/strtod.h', - '../../src/ic/stub-cache.cc', - '../../src/ic/stub-cache.h', - '../../src/tracing/trace-event.cc', - '../../src/tracing/trace-event.h', - '../../src/transitions-inl.h', - '../../src/transitions.cc', - '../../src/transitions.h', - '../../src/type-cache.cc', - '../../src/type-cache.h', - '../../src/type-feedback-vector-inl.h', - '../../src/type-feedback-vector.cc', - '../../src/type-feedback-vector.h', - '../../src/type-info.cc', - '../../src/type-info.h', - '../../src/types.cc', - '../../src/types.h', - '../../src/typing-asm.cc', - '../../src/typing-asm.h', - '../../src/typing-reset.cc', - '../../src/typing-reset.h', - '../../src/unicode-inl.h', - '../../src/unicode.cc', - '../../src/unicode.h', - '../../src/unicode-cache-inl.h', - '../../src/unicode-cache.h', - '../../src/unicode-decoder.cc', - '../../src/unicode-decoder.h', - '../../src/utils-inl.h', - '../../src/utils.cc', - '../../src/utils.h', - '../../src/v8.cc', - '../../src/v8.h', - '../../src/v8memory.h', - '../../src/v8threads.cc', - '../../src/v8threads.h', - '../../src/vector.h', - '../../src/version.cc', - '../../src/version.h', - '../../src/vm-state-inl.h', - '../../src/vm-state.h', - '../../src/wasm/asm-wasm-builder.cc', - '../../src/wasm/asm-wasm-builder.h', - '../../src/wasm/ast-decoder.cc', - '../../src/wasm/ast-decoder.h', - '../../src/wasm/decoder.h', - '../../src/wasm/encoder.cc', - '../../src/wasm/encoder.h', - '../../src/wasm/module-decoder.cc', - '../../src/wasm/module-decoder.h', - '../../src/wasm/wasm-js.cc', - '../../src/wasm/wasm-js.h', - '../../src/wasm/wasm-macro-gen.h', - '../../src/wasm/wasm-module.cc', - '../../src/wasm/wasm-module.h', - '../../src/wasm/wasm-opcodes.cc', - '../../src/wasm/wasm-opcodes.h', - '../../src/wasm/wasm-result.cc', - '../../src/wasm/wasm-result.h', - '../../src/zone.cc', - '../../src/zone.h', - '../../src/zone-allocator.h', - '../../src/zone-containers.h', - '../../src/third_party/fdlibm/fdlibm.cc', - '../../src/third_party/fdlibm/fdlibm.h', - ], - 'conditions': [ - ['want_separate_host_toolset==1', { - 'toolsets': ['host', 'target'], - }, { - 'toolsets': ['target'], - }], - ['v8_target_arch=="arm"', { - 'sources': [ ### gcmole(arch:arm) ### - '../../src/arm/assembler-arm-inl.h', - '../../src/arm/assembler-arm.cc', - '../../src/arm/assembler-arm.h', - '../../src/arm/builtins-arm.cc', - '../../src/arm/code-stubs-arm.cc', - '../../src/arm/code-stubs-arm.h', - '../../src/arm/codegen-arm.cc', - '../../src/arm/codegen-arm.h', - '../../src/arm/constants-arm.h', - '../../src/arm/constants-arm.cc', - '../../src/arm/cpu-arm.cc', - '../../src/arm/deoptimizer-arm.cc', - '../../src/arm/disasm-arm.cc', - '../../src/arm/frames-arm.cc', - '../../src/arm/frames-arm.h', - '../../src/arm/interface-descriptors-arm.cc', - '../../src/arm/interface-descriptors-arm.h', - '../../src/arm/macro-assembler-arm.cc', - '../../src/arm/macro-assembler-arm.h', - '../../src/arm/simulator-arm.cc', - '../../src/arm/simulator-arm.h', - '../../src/compiler/arm/code-generator-arm.cc', - '../../src/compiler/arm/instruction-codes-arm.h', - '../../src/compiler/arm/instruction-scheduler-arm.cc', - '../../src/compiler/arm/instruction-selector-arm.cc', - '../../src/crankshaft/arm/lithium-arm.cc', - '../../src/crankshaft/arm/lithium-arm.h', - '../../src/crankshaft/arm/lithium-codegen-arm.cc', - '../../src/crankshaft/arm/lithium-codegen-arm.h', - '../../src/crankshaft/arm/lithium-gap-resolver-arm.cc', - '../../src/crankshaft/arm/lithium-gap-resolver-arm.h', - '../../src/debug/arm/debug-arm.cc', - '../../src/full-codegen/arm/full-codegen-arm.cc', - '../../src/ic/arm/access-compiler-arm.cc', - '../../src/ic/arm/handler-compiler-arm.cc', - '../../src/ic/arm/ic-arm.cc', - '../../src/ic/arm/ic-compiler-arm.cc', - '../../src/ic/arm/stub-cache-arm.cc', - '../../src/regexp/arm/regexp-macro-assembler-arm.cc', - '../../src/regexp/arm/regexp-macro-assembler-arm.h', - ], - }], - ['v8_target_arch=="arm64"', { - 'sources': [ ### gcmole(arch:arm64) ### - '../../src/arm64/assembler-arm64.cc', - '../../src/arm64/assembler-arm64.h', - '../../src/arm64/assembler-arm64-inl.h', - '../../src/arm64/builtins-arm64.cc', - '../../src/arm64/codegen-arm64.cc', - '../../src/arm64/codegen-arm64.h', - '../../src/arm64/code-stubs-arm64.cc', - '../../src/arm64/code-stubs-arm64.h', - '../../src/arm64/constants-arm64.h', - '../../src/arm64/cpu-arm64.cc', - '../../src/arm64/decoder-arm64.cc', - '../../src/arm64/decoder-arm64.h', - '../../src/arm64/decoder-arm64-inl.h', - '../../src/arm64/deoptimizer-arm64.cc', - '../../src/arm64/disasm-arm64.cc', - '../../src/arm64/disasm-arm64.h', - '../../src/arm64/frames-arm64.cc', - '../../src/arm64/frames-arm64.h', - '../../src/arm64/instructions-arm64.cc', - '../../src/arm64/instructions-arm64.h', - '../../src/arm64/instrument-arm64.cc', - '../../src/arm64/instrument-arm64.h', - '../../src/arm64/interface-descriptors-arm64.cc', - '../../src/arm64/interface-descriptors-arm64.h', - '../../src/arm64/macro-assembler-arm64.cc', - '../../src/arm64/macro-assembler-arm64.h', - '../../src/arm64/macro-assembler-arm64-inl.h', - '../../src/arm64/simulator-arm64.cc', - '../../src/arm64/simulator-arm64.h', - '../../src/arm64/utils-arm64.cc', - '../../src/arm64/utils-arm64.h', - '../../src/compiler/arm64/code-generator-arm64.cc', - '../../src/compiler/arm64/instruction-codes-arm64.h', - '../../src/compiler/arm64/instruction-scheduler-arm64.cc', - '../../src/compiler/arm64/instruction-selector-arm64.cc', - '../../src/crankshaft/arm64/delayed-masm-arm64.cc', - '../../src/crankshaft/arm64/delayed-masm-arm64.h', - '../../src/crankshaft/arm64/delayed-masm-arm64-inl.h', - '../../src/crankshaft/arm64/lithium-arm64.cc', - '../../src/crankshaft/arm64/lithium-arm64.h', - '../../src/crankshaft/arm64/lithium-codegen-arm64.cc', - '../../src/crankshaft/arm64/lithium-codegen-arm64.h', - '../../src/crankshaft/arm64/lithium-gap-resolver-arm64.cc', - '../../src/crankshaft/arm64/lithium-gap-resolver-arm64.h', - '../../src/debug/arm64/debug-arm64.cc', - '../../src/full-codegen/arm64/full-codegen-arm64.cc', - '../../src/ic/arm64/access-compiler-arm64.cc', - '../../src/ic/arm64/handler-compiler-arm64.cc', - '../../src/ic/arm64/ic-arm64.cc', - '../../src/ic/arm64/ic-compiler-arm64.cc', - '../../src/ic/arm64/stub-cache-arm64.cc', - '../../src/regexp/arm64/regexp-macro-assembler-arm64.cc', - '../../src/regexp/arm64/regexp-macro-assembler-arm64.h', - ], - }], - ['v8_target_arch=="ia32"', { - 'sources': [ ### gcmole(arch:ia32) ### - '../../src/ia32/assembler-ia32-inl.h', - '../../src/ia32/assembler-ia32.cc', - '../../src/ia32/assembler-ia32.h', - '../../src/ia32/builtins-ia32.cc', - '../../src/ia32/code-stubs-ia32.cc', - '../../src/ia32/code-stubs-ia32.h', - '../../src/ia32/codegen-ia32.cc', - '../../src/ia32/codegen-ia32.h', - '../../src/ia32/cpu-ia32.cc', - '../../src/ia32/deoptimizer-ia32.cc', - '../../src/ia32/disasm-ia32.cc', - '../../src/ia32/frames-ia32.cc', - '../../src/ia32/frames-ia32.h', - '../../src/ia32/interface-descriptors-ia32.cc', - '../../src/ia32/macro-assembler-ia32.cc', - '../../src/ia32/macro-assembler-ia32.h', - '../../src/compiler/ia32/code-generator-ia32.cc', - '../../src/compiler/ia32/instruction-codes-ia32.h', - '../../src/compiler/ia32/instruction-scheduler-ia32.cc', - '../../src/compiler/ia32/instruction-selector-ia32.cc', - '../../src/crankshaft/ia32/lithium-codegen-ia32.cc', - '../../src/crankshaft/ia32/lithium-codegen-ia32.h', - '../../src/crankshaft/ia32/lithium-gap-resolver-ia32.cc', - '../../src/crankshaft/ia32/lithium-gap-resolver-ia32.h', - '../../src/crankshaft/ia32/lithium-ia32.cc', - '../../src/crankshaft/ia32/lithium-ia32.h', - '../../src/debug/ia32/debug-ia32.cc', - '../../src/full-codegen/ia32/full-codegen-ia32.cc', - '../../src/ic/ia32/access-compiler-ia32.cc', - '../../src/ic/ia32/handler-compiler-ia32.cc', - '../../src/ic/ia32/ic-ia32.cc', - '../../src/ic/ia32/ic-compiler-ia32.cc', - '../../src/ic/ia32/stub-cache-ia32.cc', - '../../src/regexp/ia32/regexp-macro-assembler-ia32.cc', - '../../src/regexp/ia32/regexp-macro-assembler-ia32.h', - ], - }], - ['v8_target_arch=="x87"', { - 'sources': [ ### gcmole(arch:x87) ### - '../../src/x87/assembler-x87-inl.h', - '../../src/x87/assembler-x87.cc', - '../../src/x87/assembler-x87.h', - '../../src/x87/builtins-x87.cc', - '../../src/x87/code-stubs-x87.cc', - '../../src/x87/code-stubs-x87.h', - '../../src/x87/codegen-x87.cc', - '../../src/x87/codegen-x87.h', - '../../src/x87/cpu-x87.cc', - '../../src/x87/deoptimizer-x87.cc', - '../../src/x87/disasm-x87.cc', - '../../src/x87/frames-x87.cc', - '../../src/x87/frames-x87.h', - '../../src/x87/interface-descriptors-x87.cc', - '../../src/x87/macro-assembler-x87.cc', - '../../src/x87/macro-assembler-x87.h', - '../../src/compiler/x87/code-generator-x87.cc', - '../../src/compiler/x87/instruction-codes-x87.h', - '../../src/compiler/x87/instruction-scheduler-x87.cc', - '../../src/compiler/x87/instruction-selector-x87.cc', - '../../src/crankshaft/x87/lithium-codegen-x87.cc', - '../../src/crankshaft/x87/lithium-codegen-x87.h', - '../../src/crankshaft/x87/lithium-gap-resolver-x87.cc', - '../../src/crankshaft/x87/lithium-gap-resolver-x87.h', - '../../src/crankshaft/x87/lithium-x87.cc', - '../../src/crankshaft/x87/lithium-x87.h', - '../../src/debug/x87/debug-x87.cc', - '../../src/full-codegen/x87/full-codegen-x87.cc', - '../../src/ic/x87/access-compiler-x87.cc', - '../../src/ic/x87/handler-compiler-x87.cc', - '../../src/ic/x87/ic-x87.cc', - '../../src/ic/x87/ic-compiler-x87.cc', - '../../src/ic/x87/stub-cache-x87.cc', - '../../src/regexp/x87/regexp-macro-assembler-x87.cc', - '../../src/regexp/x87/regexp-macro-assembler-x87.h', - ], - }], - ['v8_target_arch=="mips" or v8_target_arch=="mipsel"', { - 'sources': [ ### gcmole(arch:mipsel) ### - '../../src/mips/assembler-mips.cc', - '../../src/mips/assembler-mips.h', - '../../src/mips/assembler-mips-inl.h', - '../../src/mips/builtins-mips.cc', - '../../src/mips/codegen-mips.cc', - '../../src/mips/codegen-mips.h', - '../../src/mips/code-stubs-mips.cc', - '../../src/mips/code-stubs-mips.h', - '../../src/mips/constants-mips.cc', - '../../src/mips/constants-mips.h', - '../../src/mips/cpu-mips.cc', - '../../src/mips/deoptimizer-mips.cc', - '../../src/mips/disasm-mips.cc', - '../../src/mips/frames-mips.cc', - '../../src/mips/frames-mips.h', - '../../src/mips/interface-descriptors-mips.cc', - '../../src/mips/macro-assembler-mips.cc', - '../../src/mips/macro-assembler-mips.h', - '../../src/mips/simulator-mips.cc', - '../../src/mips/simulator-mips.h', - '../../src/compiler/mips/code-generator-mips.cc', - '../../src/compiler/mips/instruction-codes-mips.h', - '../../src/compiler/mips/instruction-scheduler-mips.cc', - '../../src/compiler/mips/instruction-selector-mips.cc', - '../../src/crankshaft/mips/lithium-codegen-mips.cc', - '../../src/crankshaft/mips/lithium-codegen-mips.h', - '../../src/crankshaft/mips/lithium-gap-resolver-mips.cc', - '../../src/crankshaft/mips/lithium-gap-resolver-mips.h', - '../../src/crankshaft/mips/lithium-mips.cc', - '../../src/crankshaft/mips/lithium-mips.h', - '../../src/full-codegen/mips/full-codegen-mips.cc', - '../../src/debug/mips/debug-mips.cc', - '../../src/ic/mips/access-compiler-mips.cc', - '../../src/ic/mips/handler-compiler-mips.cc', - '../../src/ic/mips/ic-mips.cc', - '../../src/ic/mips/ic-compiler-mips.cc', - '../../src/ic/mips/stub-cache-mips.cc', - '../../src/regexp/mips/regexp-macro-assembler-mips.cc', - '../../src/regexp/mips/regexp-macro-assembler-mips.h', - ], - }], - ['v8_target_arch=="mips64" or v8_target_arch=="mips64el"', { - 'sources': [ ### gcmole(arch:mips64el) ### - '../../src/mips64/assembler-mips64.cc', - '../../src/mips64/assembler-mips64.h', - '../../src/mips64/assembler-mips64-inl.h', - '../../src/mips64/builtins-mips64.cc', - '../../src/mips64/codegen-mips64.cc', - '../../src/mips64/codegen-mips64.h', - '../../src/mips64/code-stubs-mips64.cc', - '../../src/mips64/code-stubs-mips64.h', - '../../src/mips64/constants-mips64.cc', - '../../src/mips64/constants-mips64.h', - '../../src/mips64/cpu-mips64.cc', - '../../src/mips64/deoptimizer-mips64.cc', - '../../src/mips64/disasm-mips64.cc', - '../../src/mips64/frames-mips64.cc', - '../../src/mips64/frames-mips64.h', - '../../src/mips64/interface-descriptors-mips64.cc', - '../../src/mips64/macro-assembler-mips64.cc', - '../../src/mips64/macro-assembler-mips64.h', - '../../src/mips64/simulator-mips64.cc', - '../../src/mips64/simulator-mips64.h', - '../../src/compiler/mips64/code-generator-mips64.cc', - '../../src/compiler/mips64/instruction-codes-mips64.h', - '../../src/compiler/mips64/instruction-scheduler-mips64.cc', - '../../src/compiler/mips64/instruction-selector-mips64.cc', - '../../src/crankshaft/mips64/lithium-codegen-mips64.cc', - '../../src/crankshaft/mips64/lithium-codegen-mips64.h', - '../../src/crankshaft/mips64/lithium-gap-resolver-mips64.cc', - '../../src/crankshaft/mips64/lithium-gap-resolver-mips64.h', - '../../src/crankshaft/mips64/lithium-mips64.cc', - '../../src/crankshaft/mips64/lithium-mips64.h', - '../../src/debug/mips64/debug-mips64.cc', - '../../src/full-codegen/mips64/full-codegen-mips64.cc', - '../../src/ic/mips64/access-compiler-mips64.cc', - '../../src/ic/mips64/handler-compiler-mips64.cc', - '../../src/ic/mips64/ic-mips64.cc', - '../../src/ic/mips64/ic-compiler-mips64.cc', - '../../src/ic/mips64/stub-cache-mips64.cc', - '../../src/regexp/mips64/regexp-macro-assembler-mips64.cc', - '../../src/regexp/mips64/regexp-macro-assembler-mips64.h', - ], - }], - ['v8_target_arch=="x64" or v8_target_arch=="x32"', { - 'sources': [ ### gcmole(arch:x64) ### - '../../src/crankshaft/x64/lithium-codegen-x64.cc', - '../../src/crankshaft/x64/lithium-codegen-x64.h', - '../../src/crankshaft/x64/lithium-gap-resolver-x64.cc', - '../../src/crankshaft/x64/lithium-gap-resolver-x64.h', - '../../src/crankshaft/x64/lithium-x64.cc', - '../../src/crankshaft/x64/lithium-x64.h', - '../../src/x64/assembler-x64-inl.h', - '../../src/x64/assembler-x64.cc', - '../../src/x64/assembler-x64.h', - '../../src/x64/builtins-x64.cc', - '../../src/x64/code-stubs-x64.cc', - '../../src/x64/code-stubs-x64.h', - '../../src/x64/codegen-x64.cc', - '../../src/x64/codegen-x64.h', - '../../src/x64/cpu-x64.cc', - '../../src/x64/deoptimizer-x64.cc', - '../../src/x64/disasm-x64.cc', - '../../src/x64/frames-x64.cc', - '../../src/x64/frames-x64.h', - '../../src/x64/interface-descriptors-x64.cc', - '../../src/x64/macro-assembler-x64.cc', - '../../src/x64/macro-assembler-x64.h', - '../../src/debug/x64/debug-x64.cc', - '../../src/full-codegen/x64/full-codegen-x64.cc', - '../../src/ic/x64/access-compiler-x64.cc', - '../../src/ic/x64/handler-compiler-x64.cc', - '../../src/ic/x64/ic-x64.cc', - '../../src/ic/x64/ic-compiler-x64.cc', - '../../src/ic/x64/stub-cache-x64.cc', - '../../src/regexp/x64/regexp-macro-assembler-x64.cc', - '../../src/regexp/x64/regexp-macro-assembler-x64.h', - ], - }], - ['v8_target_arch=="x64"', { - 'sources': [ - '../../src/compiler/x64/code-generator-x64.cc', - '../../src/compiler/x64/instruction-codes-x64.h', - '../../src/compiler/x64/instruction-scheduler-x64.cc', - '../../src/compiler/x64/instruction-selector-x64.cc', - ], - }], - ['v8_target_arch=="ppc" or v8_target_arch=="ppc64"', { - 'sources': [ ### gcmole(arch:ppc) ### - '../../src/compiler/ppc/code-generator-ppc.cc', - '../../src/compiler/ppc/instruction-codes-ppc.h', - '../../src/compiler/ppc/instruction-scheduler-ppc.cc', - '../../src/compiler/ppc/instruction-selector-ppc.cc', - '../../src/crankshaft/ppc/lithium-ppc.cc', - '../../src/crankshaft/ppc/lithium-ppc.h', - '../../src/crankshaft/ppc/lithium-codegen-ppc.cc', - '../../src/crankshaft/ppc/lithium-codegen-ppc.h', - '../../src/crankshaft/ppc/lithium-gap-resolver-ppc.cc', - '../../src/crankshaft/ppc/lithium-gap-resolver-ppc.h', - '../../src/debug/ppc/debug-ppc.cc', - '../../src/full-codegen/ppc/full-codegen-ppc.cc', - '../../src/ic/ppc/access-compiler-ppc.cc', - '../../src/ic/ppc/handler-compiler-ppc.cc', - '../../src/ic/ppc/ic-ppc.cc', - '../../src/ic/ppc/ic-compiler-ppc.cc', - '../../src/ic/ppc/stub-cache-ppc.cc', - '../../src/ppc/assembler-ppc-inl.h', - '../../src/ppc/assembler-ppc.cc', - '../../src/ppc/assembler-ppc.h', - '../../src/ppc/builtins-ppc.cc', - '../../src/ppc/code-stubs-ppc.cc', - '../../src/ppc/code-stubs-ppc.h', - '../../src/ppc/codegen-ppc.cc', - '../../src/ppc/codegen-ppc.h', - '../../src/ppc/constants-ppc.h', - '../../src/ppc/constants-ppc.cc', - '../../src/ppc/cpu-ppc.cc', - '../../src/ppc/deoptimizer-ppc.cc', - '../../src/ppc/disasm-ppc.cc', - '../../src/ppc/frames-ppc.cc', - '../../src/ppc/frames-ppc.h', - '../../src/ppc/interface-descriptors-ppc.cc', - '../../src/ppc/macro-assembler-ppc.cc', - '../../src/ppc/macro-assembler-ppc.h', - '../../src/ppc/simulator-ppc.cc', - '../../src/ppc/simulator-ppc.h', - '../../src/regexp/ppc/regexp-macro-assembler-ppc.cc', - '../../src/regexp/ppc/regexp-macro-assembler-ppc.h', - ], - }], - ['v8_target_arch=="s390" or v8_target_arch=="s390x"', { - 'sources': [ ### gcmole(arch:s390) ### - '../../src/compiler/s390/code-generator-s390.cc', - '../../src/compiler/s390/instruction-codes-s390.h', - '../../src/compiler/s390/instruction-scheduler-s390.cc', - '../../src/compiler/s390/instruction-selector-s390.cc', - '../../src/crankshaft/s390/lithium-codegen-s390.cc', - '../../src/crankshaft/s390/lithium-codegen-s390.h', - '../../src/crankshaft/s390/lithium-gap-resolver-s390.cc', - '../../src/crankshaft/s390/lithium-gap-resolver-s390.h', - '../../src/crankshaft/s390/lithium-s390.cc', - '../../src/crankshaft/s390/lithium-s390.h', - '../../src/debug/s390/debug-s390.cc', - '../../src/full-codegen/s390/full-codegen-s390.cc', - '../../src/ic/s390/access-compiler-s390.cc', - '../../src/ic/s390/handler-compiler-s390.cc', - '../../src/ic/s390/ic-compiler-s390.cc', - '../../src/ic/s390/ic-s390.cc', - '../../src/ic/s390/stub-cache-s390.cc', - '../../src/regexp/s390/regexp-macro-assembler-s390.cc', - '../../src/regexp/s390/regexp-macro-assembler-s390.h', - '../../src/s390/assembler-s390.cc', - '../../src/s390/assembler-s390.h', - '../../src/s390/assembler-s390-inl.h', - '../../src/s390/builtins-s390.cc', - '../../src/s390/codegen-s390.cc', - '../../src/s390/codegen-s390.h', - '../../src/s390/code-stubs-s390.cc', - '../../src/s390/code-stubs-s390.h', - '../../src/s390/constants-s390.cc', - '../../src/s390/constants-s390.h', - '../../src/s390/cpu-s390.cc', - '../../src/s390/deoptimizer-s390.cc', - '../../src/s390/disasm-s390.cc', - '../../src/s390/frames-s390.cc', - '../../src/s390/frames-s390.h', - '../../src/s390/interface-descriptors-s390.cc', - '../../src/s390/macro-assembler-s390.cc', - '../../src/s390/macro-assembler-s390.h', - '../../src/s390/simulator-s390.cc', - '../../src/s390/simulator-s390.h', - ], - }], - ['OS=="win"', { - 'variables': { - 'gyp_generators': '<!(echo $GYP_GENERATORS)', - }, - 'msvs_disabled_warnings': [4351, 4355, 4800], - # When building Official, the .lib is too large and exceeds the 2G - # limit. This breaks it into multiple pieces to avoid the limit. - # See http://crbug.com/485155. - 'msvs_shard': 4, - }], - ['component=="shared_library"', { - 'defines': [ - 'BUILDING_V8_SHARED', - 'V8_SHARED', - ], - }], - ['v8_postmortem_support=="true"', { - 'sources': [ - '<(SHARED_INTERMEDIATE_DIR)/debug-support.cc', - ] - }], - ['v8_enable_i18n_support==1', { - 'dependencies': [ - '<(icu_gyp_path):icui18n', - '<(icu_gyp_path):icuuc', - ] - }, { # v8_enable_i18n_support==0 - 'sources!': [ - '../../src/i18n.cc', - '../../src/i18n.h', - ], - }], - ['OS=="win" and v8_enable_i18n_support==1', { - 'dependencies': [ - '<(icu_gyp_path):icudata', - ], - }], - ['icu_use_data_file_flag==1', { - 'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE'], - }, { # else icu_use_data_file_flag !=1 - 'conditions': [ - ['OS=="win"', { - 'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_SHARED'], - }, { - 'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC'], - }], - ], - }], - ], - }, - { - 'target_name': 'v8_libbase', - 'type': 'static_library', - 'variables': { - 'optimize': 'max', - }, - 'include_dirs+': [ - '../..', - ], - 'sources': [ - '../../src/base/accounting-allocator.cc', - '../../src/base/accounting-allocator.h', - '../../src/base/adapters.h', - '../../src/base/atomicops.h', - '../../src/base/atomicops_internals_arm64_gcc.h', - '../../src/base/atomicops_internals_arm_gcc.h', - '../../src/base/atomicops_internals_atomicword_compat.h', - '../../src/base/atomicops_internals_mac.h', - '../../src/base/atomicops_internals_mips_gcc.h', - '../../src/base/atomicops_internals_mips64_gcc.h', - '../../src/base/atomicops_internals_portable.h', - '../../src/base/atomicops_internals_ppc_gcc.h', - '../../src/base/atomicops_internals_s390_gcc.h', - '../../src/base/atomicops_internals_tsan.h', - '../../src/base/atomicops_internals_x86_gcc.cc', - '../../src/base/atomicops_internals_x86_gcc.h', - '../../src/base/atomicops_internals_x86_msvc.h', - '../../src/base/bits.cc', - '../../src/base/bits.h', - '../../src/base/build_config.h', - '../../src/base/compiler-specific.h', - '../../src/base/cpu.cc', - '../../src/base/cpu.h', - '../../src/base/division-by-constant.cc', - '../../src/base/division-by-constant.h', - '../../src/base/flags.h', - '../../src/base/functional.cc', - '../../src/base/functional.h', - '../../src/base/iterator.h', - '../../src/base/lazy-instance.h', - '../../src/base/logging.cc', - '../../src/base/logging.h', - '../../src/base/macros.h', - '../../src/base/once.cc', - '../../src/base/once.h', - '../../src/base/platform/elapsed-timer.h', - '../../src/base/platform/time.cc', - '../../src/base/platform/time.h', - '../../src/base/platform/condition-variable.cc', - '../../src/base/platform/condition-variable.h', - '../../src/base/platform/mutex.cc', - '../../src/base/platform/mutex.h', - '../../src/base/platform/platform.h', - '../../src/base/platform/semaphore.cc', - '../../src/base/platform/semaphore.h', - '../../src/base/safe_conversions.h', - '../../src/base/safe_conversions_impl.h', - '../../src/base/safe_math.h', - '../../src/base/safe_math_impl.h', - '../../src/base/smart-pointers.h', - '../../src/base/sys-info.cc', - '../../src/base/sys-info.h', - '../../src/base/utils/random-number-generator.cc', - '../../src/base/utils/random-number-generator.h', - ], - 'conditions': [ - ['want_separate_host_toolset==1', { - 'toolsets': ['host', 'target'], - }, { - 'toolsets': ['target'], - }], - ['OS=="linux"', { - 'conditions': [ - ['nacl_target_arch=="none"', { - 'link_settings': { - 'libraries': [ - '-ldl', - '-lrt' - ], - }, - }, { - 'defines': [ - 'V8_LIBRT_NOT_AVAILABLE=1', - ], - }], - ], - 'sources': [ - '../../src/base/platform/platform-linux.cc', - '../../src/base/platform/platform-posix.cc' - ], - } - ], - ['OS=="android"', { - 'sources': [ - '../../src/base/platform/platform-posix.cc' - ], - 'link_settings': { - 'target_conditions': [ - ['_toolset=="host"', { - # Only include libdl and librt on host builds because they - # are included by default on Android target builds, and we - # don't want to re-include them here since this will change - # library order and break (see crbug.com/469973). - 'libraries': [ - '-ldl', - '-lrt' - ] - }] - ] - }, - 'conditions': [ - ['host_os=="mac"', { - 'target_conditions': [ - ['_toolset=="host"', { - 'sources': [ - '../../src/base/platform/platform-macos.cc' - ] - }, { - 'sources': [ - '../../src/base/platform/platform-linux.cc' - ] - }], - ], - }, { - 'sources': [ - '../../src/base/platform/platform-linux.cc' - ] - }], - ], - }, - ], - ['OS=="qnx"', { - 'link_settings': { - 'target_conditions': [ - ['_toolset=="host" and host_os=="linux"', { - 'libraries': [ - '-lrt' - ], - }], - ['_toolset=="target"', { - 'libraries': [ - '-lbacktrace' - ], - }], - ], - }, - 'sources': [ - '../../src/base/platform/platform-posix.cc', - '../../src/base/qnx-math.h', - ], - 'target_conditions': [ - ['_toolset=="host" and host_os=="linux"', { - 'sources': [ - '../../src/base/platform/platform-linux.cc' - ], - }], - ['_toolset=="host" and host_os=="mac"', { - 'sources': [ - '../../src/base/platform/platform-macos.cc' - ], - }], - ['_toolset=="target"', { - 'sources': [ - '../../src/base/platform/platform-qnx.cc' - ], - }], - ], - }, - ], - ['OS=="freebsd"', { - 'link_settings': { - 'libraries': [ - '-L/usr/local/lib -lexecinfo', - ]}, - 'sources': [ - '../../src/base/platform/platform-freebsd.cc', - '../../src/base/platform/platform-posix.cc' - ], - } - ], - ['OS=="openbsd"', { - 'link_settings': { - 'libraries': [ - '-L/usr/local/lib -lexecinfo', - ]}, - 'sources': [ - '../../src/base/platform/platform-openbsd.cc', - '../../src/base/platform/platform-posix.cc' - ], - } - ], - ['OS=="netbsd"', { - 'link_settings': { - 'libraries': [ - '-L/usr/pkg/lib -Wl,-R/usr/pkg/lib -lexecinfo', - ]}, - 'sources': [ - '../../src/base/platform/platform-openbsd.cc', - '../../src/base/platform/platform-posix.cc' - ], - } - ], - ['OS=="aix"', { - 'sources': [ - '../../src/base/platform/platform-aix.cc', - '../../src/base/platform/platform-posix.cc' - ]}, - ], - ['OS=="solaris"', { - 'link_settings': { - 'libraries': [ - '-lnsl -lrt', - ]}, - 'sources': [ - '../../src/base/platform/platform-solaris.cc', - '../../src/base/platform/platform-posix.cc' - ], - } - ], - ['OS=="mac"', { - 'sources': [ - '../../src/base/platform/platform-macos.cc', - '../../src/base/platform/platform-posix.cc' - ]}, - ], - ['OS=="win"', { - 'defines': [ - '_CRT_RAND_S' # for rand_s() - ], - 'variables': { - 'gyp_generators': '<!(echo $GYP_GENERATORS)', - }, - 'conditions': [ - ['gyp_generators=="make"', { - 'variables': { - 'build_env': '<!(uname -o)', - }, - 'conditions': [ - ['build_env=="Cygwin"', { - 'sources': [ - '../../src/base/platform/platform-cygwin.cc', - '../../src/base/platform/platform-posix.cc' - ], - }, { - 'sources': [ - '../../src/base/platform/platform-win32.cc', - '../../src/base/win32-headers.h', - ], - }], - ], - 'link_settings': { - 'libraries': [ '-lwinmm', '-lws2_32' ], - }, - }, { - 'sources': [ - '../../src/base/platform/platform-win32.cc', - '../../src/base/win32-headers.h', - ], - 'msvs_disabled_warnings': [4351, 4355, 4800], - 'link_settings': { - 'libraries': [ '-lwinmm.lib', '-lws2_32.lib' ], - }, - }], - ], - }], - ], - }, - { - 'target_name': 'v8_libplatform', - 'type': 'static_library', - 'variables': { - 'optimize': 'max', - }, - 'dependencies': [ - 'v8_libbase', - ], - 'include_dirs+': [ - '../..', - ], - 'sources': [ - '../../include/libplatform/libplatform.h', - '../../src/libplatform/default-platform.cc', - '../../src/libplatform/default-platform.h', - '../../src/libplatform/task-queue.cc', - '../../src/libplatform/task-queue.h', - '../../src/libplatform/worker-thread.cc', - '../../src/libplatform/worker-thread.h', - ], - 'conditions': [ - ['want_separate_host_toolset==1', { - 'toolsets': ['host', 'target'], - }, { - 'toolsets': ['target'], - }], - ], - 'direct_dependent_settings': { - 'include_dirs': [ - '../../include', - ], - }, - }, - { - 'target_name': 'natives_blob', - 'type': 'none', - 'conditions': [ - [ 'v8_use_external_startup_data==1', { - 'conditions': [ - ['want_separate_host_toolset==1', { - 'dependencies': ['js2c#host'], - }, { - 'dependencies': ['js2c'], - }], - ], - 'actions': [{ - 'action_name': 'concatenate_natives_blob', - 'inputs': [ - '../../tools/concatenate-files.py', - '<(SHARED_INTERMEDIATE_DIR)/libraries.bin', - '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental.bin', - '<(SHARED_INTERMEDIATE_DIR)/libraries-extras.bin', - '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental-extras.bin', - ], - 'conditions': [ - ['want_separate_host_toolset==1', { - 'target_conditions': [ - ['_toolset=="host"', { - 'outputs': [ - '<(PRODUCT_DIR)/natives_blob_host.bin', - ], - 'action': [ - 'python', '<@(_inputs)', '<(PRODUCT_DIR)/natives_blob_host.bin' - ], - }, { - 'outputs': [ - '<(PRODUCT_DIR)/natives_blob.bin', - ], - 'action': [ - 'python', '<@(_inputs)', '<(PRODUCT_DIR)/natives_blob.bin' - ], - }], - ], - }, { - 'outputs': [ - '<(PRODUCT_DIR)/natives_blob.bin', - ], - 'action': [ - 'python', '<@(_inputs)', '<(PRODUCT_DIR)/natives_blob.bin' - ], - }], - ], - }], - }], - ['want_separate_host_toolset==1', { - 'toolsets': ['host', 'target'], - }, { - 'toolsets': ['target'], - }], - ] - }, - { - 'target_name': 'js2c', - 'type': 'none', - 'conditions': [ - ['want_separate_host_toolset==1', { - 'toolsets': ['host'], - }, { - 'toolsets': ['target'], - }], - ['v8_enable_i18n_support==1', { - 'variables': { - 'i18n_library_files': [ - '../../src/js/i18n.js', - ], - }, - }, { - 'variables': { - 'i18n_library_files': [], - }, - }], - ], - 'variables': { - 'library_files': [ - '../../src/js/macros.py', - '../../src/messages.h', - '../../src/js/prologue.js', - '../../src/js/runtime.js', - '../../src/js/v8natives.js', - '../../src/js/symbol.js', - '../../src/js/array.js', - '../../src/js/string.js', - '../../src/js/uri.js', - '../../src/js/math.js', - '../../src/third_party/fdlibm/fdlibm.js', - '../../src/js/regexp.js', - '../../src/js/arraybuffer.js', - '../../src/js/typedarray.js', - '../../src/js/iterator-prototype.js', - '../../src/js/generator.js', - '../../src/js/object-observe.js', - '../../src/js/collection.js', - '../../src/js/weak-collection.js', - '../../src/js/collection-iterator.js', - '../../src/js/promise.js', - '../../src/js/messages.js', - '../../src/js/json.js', - '../../src/js/array-iterator.js', - '../../src/js/string-iterator.js', - '../../src/js/templates.js', - '../../src/js/spread.js', - '../../src/js/proxy.js', - '../../src/debug/mirrors.js', - '../../src/debug/debug.js', - '../../src/debug/liveedit.js', - ], - 'experimental_library_files': [ - '../../src/js/macros.py', - '../../src/messages.h', - '../../src/js/generator.js', - '../../src/js/harmony-atomics.js', - '../../src/js/harmony-regexp-exec.js', - '../../src/js/harmony-object-observe.js', - '../../src/js/harmony-sharedarraybuffer.js', - '../../src/js/harmony-simd.js', - '../../src/js/harmony-species.js', - '../../src/js/harmony-unicode-regexps.js', - '../../src/js/harmony-string-padding.js', - '../../src/js/promise-extra.js', - ], - 'libraries_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries.bin', - 'libraries_experimental_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental.bin', - 'libraries_extras_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-extras.bin', - 'libraries_experimental_extras_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental-extras.bin', - }, - 'actions': [ - { - 'action_name': 'js2c', - 'inputs': [ - '../../tools/js2c.py', - '<@(library_files)', - '<@(i18n_library_files)' - ], - 'outputs': ['<(SHARED_INTERMEDIATE_DIR)/libraries.cc'], - 'action': [ - 'python', - '../../tools/js2c.py', - '<(SHARED_INTERMEDIATE_DIR)/libraries.cc', - 'CORE', - '<@(library_files)', - '<@(i18n_library_files)' - ], - }, - { - 'action_name': 'js2c_bin', - 'inputs': [ - '../../tools/js2c.py', - '<@(library_files)', - '<@(i18n_library_files)' - ], - 'outputs': ['<@(libraries_bin_file)'], - 'action': [ - 'python', - '../../tools/js2c.py', - '<(SHARED_INTERMEDIATE_DIR)/libraries.cc', - 'CORE', - '<@(library_files)', - '<@(i18n_library_files)', - '--startup_blob', '<@(libraries_bin_file)', - '--nojs', - ], - }, - { - 'action_name': 'js2c_experimental', - 'inputs': [ - '../../tools/js2c.py', - '<@(experimental_library_files)', - ], - 'outputs': ['<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc'], - 'action': [ - 'python', - '../../tools/js2c.py', - '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc', - 'EXPERIMENTAL', - '<@(experimental_library_files)' - ], - }, - { - 'action_name': 'js2c_experimental_bin', - 'inputs': [ - '../../tools/js2c.py', - '<@(experimental_library_files)', - ], - 'outputs': ['<@(libraries_experimental_bin_file)'], - 'action': [ - 'python', - '../../tools/js2c.py', - '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc', - 'EXPERIMENTAL', - '<@(experimental_library_files)', - '--startup_blob', '<@(libraries_experimental_bin_file)', - '--nojs', - ], - }, - { - 'action_name': 'js2c_extras', - 'inputs': [ - '../../tools/js2c.py', - '<@(v8_extra_library_files)', - ], - 'outputs': ['<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc'], - 'action': [ - 'python', - '../../tools/js2c.py', - '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc', - 'EXTRAS', - '<@(v8_extra_library_files)', - ], - }, - { - 'action_name': 'js2c_extras_bin', - 'inputs': [ - '../../tools/js2c.py', - '<@(v8_extra_library_files)', - ], - 'outputs': ['<@(libraries_extras_bin_file)'], - 'action': [ - 'python', - '../../tools/js2c.py', - '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc', - 'EXTRAS', - '<@(v8_extra_library_files)', - '--startup_blob', '<@(libraries_extras_bin_file)', - '--nojs', - ], - }, - { - 'action_name': 'js2c_experimental_extras', - 'inputs': [ - '../../tools/js2c.py', - '<@(v8_experimental_extra_library_files)', - ], - 'outputs': [ - '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc', - ], - 'action': [ - 'python', - '../../tools/js2c.py', - '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc', - 'EXPERIMENTAL_EXTRAS', - '<@(v8_experimental_extra_library_files)', - ], - }, - { - 'action_name': 'js2c_experimental_extras_bin', - 'inputs': [ - '../../tools/js2c.py', - '<@(v8_experimental_extra_library_files)', - ], - 'outputs': ['<@(libraries_experimental_extras_bin_file)'], - 'action': [ - 'python', - '../../tools/js2c.py', - '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc', - 'EXPERIMENTAL_EXTRAS', - '<@(v8_experimental_extra_library_files)', - '--startup_blob', '<@(libraries_experimental_extras_bin_file)', - '--nojs', - ], - }, - ], - }, - { - 'target_name': 'postmortem-metadata', - 'type': 'none', - 'variables': { - 'heapobject_files': [ - '../../src/objects.h', - '../../src/objects-inl.h', - ], - }, - 'actions': [ - { - 'action_name': 'gen-postmortem-metadata', - 'inputs': [ - '../../tools/gen-postmortem-metadata.py', - '<@(heapobject_files)', - ], - 'outputs': [ - '<(SHARED_INTERMEDIATE_DIR)/debug-support.cc', - ], - 'action': [ - 'python', - '../../tools/gen-postmortem-metadata.py', - '<@(_outputs)', - '<@(heapobject_files)' - ] - } - ] - }, - { - 'target_name': 'mksnapshot', - 'type': 'executable', - 'dependencies': ['v8_base', 'v8_nosnapshot', 'v8_libplatform'], - 'include_dirs+': [ - '../..', - ], - 'sources': [ - '../../src/snapshot/mksnapshot.cc', - ], - 'conditions': [ - ['v8_enable_i18n_support==1', { - 'dependencies': [ - '<(icu_gyp_path):icui18n', - '<(icu_gyp_path):icuuc', - ] - }], - ['want_separate_host_toolset==1', { - 'toolsets': ['host'], - }, { - 'toolsets': ['target'], - }], - ], - }, - ], -} diff --git a/tools/ic-explorer.html b/tools/ic-explorer.html index 43b486a5..ad1737a6 100644 --- a/tools/ic-explorer.html +++ b/tools/ic-explorer.html @@ -1,338 +1,350 @@ <html> - <head> -<style> - .entry-details { - } - .entry-details TD { - } - .details { - width: 2em; - border: 1px black dotted; - } - .count { - text-align: right; - width: 5em; - font-family: monospace; - } - .percentage { - text-align: right; - width: 5em; - font-family: monospace; - } - .key { - padding-left: 1em; - } - .drilldown-group-title { - font-weight: bold; - padding: 0.5em 0 0.2em 0; - } -</style> - <script> -"use strict" -var entries = []; +<!-- +Copyright 2016 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. +--> -class Entry { - constructor(id, line) { - this.id = id; - this.line = line; - var parts = line.split(" "); - if (parts.length < 6) return - this.isValid = false; - if (parts[0][0] !== "[") return; - if (parts[1] === "patching") return; - this.type = parts[0].substr(1); - this.category = "Other"; - if (this.type.indexOf("Store") !== -1) { - this.category = "Store"; - } else if (this.type.indexOf("Load") !== -1) { - this.category = "Load"; +<head> + <style> + .entry-details {} + + .entry-details TD {} + + .details { + width: 2em; + border: 1px black dotted; + } + + .count { + text-align: right; + width: 5em; + font-family: monospace; + } + + .percentage { + text-align: right; + width: 5em; + font-family: monospace; + } + + .key { + padding-left: 1em; } - if (this.type.length == 0) return; - if (this.type.indexOf('BinaryOpIC(') === 0) { - this.type = "BinaryOpIC"; - var split = parts[0].split('('); - this.state = "(" + split[1] + " => " + parts[2]; - var offset = this.parsePositionAndFile(parts, 6); - if (offset == -1) return - if (this.file === undefined) return - this.file = this.file.slice(0,-1); - } else { - var offset = this.parsePositionAndFile(parts, 2); - if (offset == -1) return - this.state = parts[++offset]; - if (this.type !== "CompareIC") { - // if there is no address we have a smi key - var address = parts[++offset]; - if (address !== undefined && address.indexOf("0x") === 0) { - this.key = parts.slice(++offset).join(" "); + + .drilldown-group-title { + font-weight: bold; + padding: 0.5em 0 0.2em 0; + } + </style> + <script> + "use strict" + var entries = []; + + class Entry { + constructor(id, line) { + this.id = id; + this.line = line; + var parts = line.split(" "); + if (parts.length < 6) return + this.isValid = false; + if (parts[0][0] !== "[") return; + if (parts[1] === "patching") return; + this.type = parts[0].substr(1); + this.category = "Other"; + if (this.type.indexOf("Store") !== -1) { + this.category = "Store"; + } else if (this.type.indexOf("Load") !== -1) { + this.category = "Load"; + } + if (this.type.length == 0) return; + if (this.type.indexOf('BinaryOpIC(') === 0) { + this.type = "BinaryOpIC"; + var split = parts[0].split('('); + this.state = "(" + split[1] + " => " + parts[2]; + var offset = this.parsePositionAndFile(parts, 6); + if (offset == -1) return + if (this.file === undefined) return + this.file = this.file.slice(0, -1); } else { - this.key = address; + var offset = this.parsePositionAndFile(parts, 2); + if (offset == -1) return + this.state = parts[++offset]; + if (this.type !== "CompareIC") { + // if there is no address we have a smi key + var address = parts[++offset]; + if (address !== undefined && address.indexOf("0x") === 0) { + this.key = parts.slice(++offset).join(" "); + } else { + this.key = address; + } + } } + this.filePosition = this.file + " " + this.position; + if (this.key) { + var isStringKey = false + if (this.key.indexOf("<String[") === 0) { + isStringKey = true; + this.key = "\"" + this.key.slice(this.key.indexOf(']') + 3); + } else if (this.key.indexOf("<") === 0) { + this.key = this.key.slice(1); + } + if (this.key.endsWith(">]")) { + this.key = this.key.slice(0, -2); + } else if (this.key.endsWith("]")) { + this.key = this.key.slice(0, -1); + } + if (isStringKey) { + this.key = this.key + "\""; + } + } + this.isValid = true; } - } - this.filePosition = this.file + " " + this.position; - if (this.key) { - var isStringKey = false - if (this.key.indexOf("<String[") === 0) { - isStringKey = true; - this.key = "\"" + this.key.slice(this.key.indexOf(']')+3); - } else if (this.key.indexOf("<") === 0) { - this.key = this.key.slice(1); - } - if (this.key.endsWith(">]")) { - this.key = this.key.slice(0, -2); - } else if (this.key.endsWith("]")) { - this.key = this.key.slice(0, -1); - } - if (isStringKey) { - this.key = this.key + "\""; + + parsePositionAndFile(parts, start) { + // find the position of 'at' in the parts array. + var offset = start; + for (var i = start + 1; i < parts.length; i++) { + offset++; + if (parts[i] == 'at') break; + } + if (parts[offset] !== 'at') return -1; + this.position = parts.slice(start, offset).join(' '); + offset += 1; + this.isNative = parts[offset] == "native" + offset += this.isNative ? 1 : 0; + this.file = parts[offset]; + return offset; } } - this.isValid = true; - } - - parsePositionAndFile(parts, start) { - // find the position of 'at' in the parts array. - var offset = start; - for (var i = start+1; i<parts.length; i++) { - offset++; - if (parts[i] == 'at') break; - } - if (parts[offset] !== 'at') return -1; - this.position = parts.slice(start, offset).join(' '); - offset += 1; - this.isNative = parts[offset] == "native" - offset += this.isNative ? 1 : 0; - this.file = parts[offset]; - return offset; - } -} -function loadFile() { - var files = document.getElementById("uploadInput").files; + function loadFile() { + var files = document.getElementById("uploadInput").files; - var file = files[0]; - var reader = new FileReader(); + var file = files[0]; + var reader = new FileReader(); - reader.onload = function(evt) { - entries = []; - var end = this.result.length; - var current = 0; - var next = 0; - var line; - var i = 0; - var entry; - while (current < end) { - next = this.result.indexOf("\n", current); - if (next === -1) break; - i++; - - line = this.result.substring(current, next); - current = next+1; - entry = new Entry(i, line); - if (entry.isValid) entries.push(entry); + reader.onload = function(evt) { + entries = []; + var end = this.result.length; + var current = 0; + var next = 0; + var line; + var i = 0; + var entry; + while (current < end) { + next = this.result.indexOf("\n", current); + if (next === -1) break; + i++; + + line = this.result.substring(current, next); + current = next + 1; + entry = new Entry(i, line); + if (entry.isValid) entries.push(entry); + } + + document.getElementById("count").innerHTML = i; + updateTable(); + } + reader.readAsText(file); + initGroupKeySelect(); } - - document.getElementById("count").innerHTML = i; - updateTable(); - } - reader.readAsText(file); - initGroupKeySelect(); -} -var properties = ['type', 'category', 'file', 'filePosition', 'state' , 'key', 'isNative'] + var properties = ['type', 'category', 'file', 'filePosition', 'state', + 'key', 'isNative' + ] -class Group { - constructor(property, key, entry) { - this.property = property; - this.key = key; - this.count = 1; - this.entries = [entry]; - this.percentage = undefined; - this.groups = undefined; - } - - add(entry) { - this.count ++; - this.entries.push(entry) - } - - createSubGroups() { - this.groups = {}; - for (var i=0; i<properties.length; i++) { - var subProperty = properties[i]; - if (this.property == subProperty) continue; - this.groups[subProperty] = groupBy(this.entries, subProperty); - } - } -} + class Group { + constructor(property, key, entry) { + this.property = property; + this.key = key; + this.count = 1; + this.entries = [entry]; + this.percentage = undefined; + this.groups = undefined; + } + + add(entry) { + this.count++; + this.entries.push(entry) + } -function groupBy(entries, property) { - var accumulator = {}; - accumulator.__proto__ = null; - var length = entries.length; - for (var i = 0; i < length; i++) { - var entry = entries[i]; - var key = entry[property]; - if (accumulator[key] == undefined) { - accumulator[key] = new Group(property, key, entry) - } else { - var group = accumulator[key]; - if (group.entries == undefined) console.log([group, entry]); - group.add(entry) + createSubGroups() { + this.groups = {}; + for (var i = 0; i < properties.length; i++) { + var subProperty = properties[i]; + if (this.property == subProperty) continue; + this.groups[subProperty] = groupBy(this.entries, subProperty); + } + } } - } - var result = [] - for (var key in accumulator) { - var group = accumulator[key]; - group.percentage = Math.round(group.count / length * 100 * 100) / 100; - result.push(group); - } - result.sort((a,b) => { return b.count - a.count }); - return result; -} + function groupBy(entries, property) { + var accumulator = {}; + accumulator.__proto__ = null; + var length = entries.length; + for (var i = 0; i < length; i++) { + var entry = entries[i]; + var key = entry[property]; + if (accumulator[key] == undefined) { + accumulator[key] = new Group(property, key, entry) + } else { + var group = accumulator[key]; + if (group.entries == undefined) console.log([group, entry]); + group.add(entry) + } + } + var result = [] + for (var key in accumulator) { + var group = accumulator[key]; + group.percentage = Math.round(group.count / length * 100 * 100) / 100; + result.push(group); + } + result.sort((a, b) => { + return b.count - a.count + }); + return result; + } -function updateTable() { - var select = document.getElementById("group-key"); - var key = select.options[select.selectedIndex].text; - console.log(key); - var tableBody = document.getElementById("table-body"); - removeAllChildren(tableBody); - var groups = groupBy(entries, key, true); - display(groups, tableBody); -} -function selecedOption(node) { - return node.options[node.selectedIndex] -} + function updateTable() { + var select = document.getElementById("group-key"); + var key = select.options[select.selectedIndex].text; + console.log(key); + var tableBody = document.getElementById("table-body"); + removeAllChildren(tableBody); + var groups = groupBy(entries, key, true); + display(groups, tableBody); + } -function removeAllChildren(node) { - while (node.firstChild) { - node.removeChild(node.firstChild); - } -} + function selecedOption(node) { + return node.options[node.selectedIndex] + } -function display(entries, parent) { - var fragment = document.createDocumentFragment(); + function removeAllChildren(node) { + while (node.firstChild) { + node.removeChild(node.firstChild); + } + } - function td(tr, content, className) { - var td = document.createElement("td"); - td.innerHTML = content; - td.className = className - tr.appendChild(td); - return td - } - var max = Math.min(1000, entries.length) - for (var i = 0; i<max; i++) { - var entry = entries[i]; - var tr = document.createElement("tr"); - tr.entry = entry; - td(tr, '<span onclick="toggleDetails(this)">details</a>', 'details'); - td(tr, entry.percentage +"%", 'percentage'); - td(tr, entry.count, 'count'); - td(tr, entry.key, 'key'); - fragment.appendChild(tr); - } - var omitted = entries.length - max; - if (omitted > 0) { - var tr = document.createElement("tr"); - var td = td(tr, 'Omitted ' + omitted + " entries."); - td.colSpan = 4; - fragment.appendChild(tr); - } - parent.appendChild(fragment); -} + function display(entries, parent) { + var fragment = document.createDocumentFragment(); -function displayDrilldown(entry, previousSibling) { - var tr = document.createElement('tr'); - tr.className = "entry-details"; - tr.style.display = "none"; - // indent by one td. - tr.appendChild(document.createElement("td")); - var td = document.createElement("td"); - td.colSpan = 3; - for (var key in entry.groups) { - td.appendChild(displayDrilldownGroup(entry, key)); - } - tr.appendChild(td); - // Append the new TR after previousSibling. - previousSibling.parentNode.insertBefore(tr, previousSibling.nextSibling) -} + function td(tr, content, className) { + var td = document.createElement("td"); + td.innerHTML = content; + td.className = className + tr.appendChild(td); + return td + } + var max = Math.min(1000, entries.length) + for (var i = 0; i < max; i++) { + var entry = entries[i]; + var tr = document.createElement("tr"); + tr.entry = entry; + td(tr, '<span onclick="toggleDetails(this)">details</a>', 'details'); + td(tr, entry.percentage + "%", 'percentage'); + td(tr, entry.count, 'count'); + td(tr, entry.key, 'key'); + fragment.appendChild(tr); + } + var omitted = entries.length - max; + if (omitted > 0) { + var tr = document.createElement("tr"); + var td = td(tr, 'Omitted ' + omitted + " entries."); + td.colSpan = 4; + fragment.appendChild(tr); + } + parent.appendChild(fragment); + } -function displayDrilldownGroup(entry, key) { - var max = 20; - var group = entry.groups[key]; - var div = document.createElement("div") - div.className = 'drilldown-group-title' - div.innerHTML = key + ' [top ' + max + ']'; - var table = document.createElement("table"); - display(group.slice(0, max), table, false) - div.appendChild(table); - return div; -} + function displayDrilldown(entry, previousSibling) { + var tr = document.createElement('tr'); + tr.className = "entry-details"; + tr.style.display = "none"; + // indent by one td. + tr.appendChild(document.createElement("td")); + var td = document.createElement("td"); + td.colSpan = 3; + for (var key in entry.groups) { + td.appendChild(displayDrilldownGroup(entry, key)); + } + tr.appendChild(td); + // Append the new TR after previousSibling. + previousSibling.parentNode.insertBefore(tr, previousSibling.nextSibling) + } -function toggleDetails(node) { - var tr = node.parentNode.parentNode; - var entry = tr.entry; + function displayDrilldownGroup(entry, key) { + var max = 20; + var group = entry.groups[key]; + var div = document.createElement("div") + div.className = 'drilldown-group-title' + div.innerHTML = key + ' [top ' + max + ']'; + var table = document.createElement("table"); + display(group.slice(0, max), table, false) + div.appendChild(table); + return div; + } - // Create subgroup in-place if the don't exist yet. - if (entry.groups === undefined) { - entry.createSubGroups(); - displayDrilldown(entry, tr); - } - var details = tr.nextSibling; - var display = details.style.display; - if (display != "none") { - display = "none"; - }else { - display = "table-row" - }; - details.style.display = display; -} + function toggleDetails(node) { + var tr = node.parentNode.parentNode; + var entry = tr.entry; -function initGroupKeySelect() { - var select = document.getElementById("group-key"); - for (var i in properties) { - var option = document.createElement("option"); - option.text = properties[i]; - select.add(option); - } -} + // Create subgroup in-place if the don't exist yet. + if (entry.groups === undefined) { + entry.createSubGroups(); + displayDrilldown(entry, tr); + } + var details = tr.nextSibling; + var display = details.style.display; + if (display != "none") { + display = "none"; + } else { + display = "table-row" + }; + details.style.display = display; + } + function initGroupKeySelect() { + var select = document.getElementById("group-key"); + for (var i in properties) { + var option = document.createElement("option"); + option.text = properties[i]; + select.add(option); + } + } </script> - </head> - <body> - <h1> +</head> + +<body> + <h1> <span style="color: #00FF00">I</span> <span style="color: #FF00FF">C</span> <span style="color: #00FFFF">E</span> - </h1> - Your IC-Explorer. - <h2>Usage</h2> - Run your script with <code>--trace_ic</code> and upload on this page:<br/> - <code>/path/to/d8 --trace_ic your_script.js > trace.txt</code> - <h2>Data</h2> - <form name="fileForm"> - <p> - <input id="uploadInput" type="file" name="files" onchange="loadFile();" > - trace entries: <span id="count">0</span> - </p> - </form> - <h2>Result</h2> + </h1> Your IC-Explorer. + <h2>Usage</h2> Run your script with <code>--trace_ic</code> and upload on this page:<br/> + <code>/path/to/d8 --trace_ic your_script.js > trace.txt</code> + <h2>Data</h2> + <form name="fileForm"> <p> + <input id="uploadInput" type="file" name="files" onchange="loadFile();"> trace + entries: <span id="count">0</span> + </p> + </form> + <h2>Result</h2> + <p> Group-Key: <select id="group-key" onchange="updateTable()"></select> - </p> - <p> - <table id="table" width="100%"> - <tbody id="table-body"> - </tbody> - </table> - </p> - </body> + </p> + <p> + <table id="table" width="100%"> + <tbody id="table-body"> + </tbody> + </table> + </p> +</body> + </html> diff --git a/tools/ignition/bytecode_dispatches_report.py b/tools/ignition/bytecode_dispatches_report.py new file mode 100755 index 00000000..1c140141 --- /dev/null +++ b/tools/ignition/bytecode_dispatches_report.py @@ -0,0 +1,258 @@ +#! /usr/bin/python +# +# Copyright 2016 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. +# + +import argparse +import heapq +import json +from matplotlib import colors +from matplotlib import pyplot +import numpy +import struct + + +__DESCRIPTION = """ +Process v8.ignition_dispatches_counters.json and list top counters, +or plot a dispatch heatmap. + +Please note that those handlers that may not or will never dispatch +(e.g. Return or Throw) do not show up in the results. +""" + + +__HELP_EPILOGUE = """ +examples: + # Print the hottest bytecodes in descending order, reading from + # default filename v8.ignition_dispatches_counters.json (default mode) + $ tools/ignition/bytecode_dispatches_report.py + + # Print the hottest 15 bytecode dispatch pairs reading from data.json + $ tools/ignition/bytecode_dispatches_report.py -t -n 15 data.json + + # Save heatmap to default filename v8.ignition_dispatches_counters.svg + $ tools/ignition/bytecode_dispatches_report.py -p + + # Save heatmap to filename data.svg + $ tools/ignition/bytecode_dispatches_report.py -p -o data.svg + + # Open the heatmap in an interactive viewer + $ tools/ignition/bytecode_dispatches_report.py -p -i + + # Display the top 5 sources and destinations of dispatches to/from LdaZero + $ tools/ignition/bytecode_dispatches_report.py -f LdaZero -n 5 +""" + +__COUNTER_BITS = struct.calcsize("P") * 8 # Size in bits of a pointer +__COUNTER_MAX = 2**__COUNTER_BITS - 1 + + +def warn_if_counter_may_have_saturated(dispatches_table): + for source, counters_from_source in dispatches_table.items(): + for destination, counter in counters_from_source.items(): + if counter == __COUNTER_MAX: + print "WARNING: {} -> {} may have saturated.".format(source, + destination) + + +def find_top_bytecode_dispatch_pairs(dispatches_table, top_count): + def flattened_counters_generator(): + for source, counters_from_source in dispatches_table.items(): + for destination, counter in counters_from_source.items(): + yield source, destination, counter + + return heapq.nlargest(top_count, flattened_counters_generator(), + key=lambda x: x[2]) + + +def print_top_bytecode_dispatch_pairs(dispatches_table, top_count): + top_bytecode_dispatch_pairs = ( + find_top_bytecode_dispatch_pairs(dispatches_table, top_count)) + print "Top {} bytecode dispatch pairs:".format(top_count) + for source, destination, counter in top_bytecode_dispatch_pairs: + print "{:>12d}\t{} -> {}".format(counter, source, destination) + + +def find_top_bytecodes(dispatches_table): + top_bytecodes = [] + for bytecode, counters_from_bytecode in dispatches_table.items(): + top_bytecodes.append((bytecode, sum(counters_from_bytecode.values()))) + top_bytecodes.sort(key=lambda x: x[1], reverse=True) + return top_bytecodes + + +def print_top_bytecodes(dispatches_table): + top_bytecodes = find_top_bytecodes(dispatches_table) + print "Top bytecodes:" + for bytecode, counter in top_bytecodes: + print "{:>12d}\t{}".format(counter, bytecode) + + +def find_top_dispatch_sources(dispatches_table, destination, top_count): + def source_counters_generator(): + for source, table_row in dispatches_table.items(): + if destination in table_row: + yield source, table_row[destination] + + return heapq.nlargest(top_count, source_counters_generator(), + key=lambda x: x[1]) + + +def print_top_dispatch_sources_and_destinations(dispatches_table, bytecode, + top_count): + top_sources = find_top_dispatch_sources(dispatches_table, bytecode, top_count) + top_destinations = heapq.nlargest(top_count, + dispatches_table[bytecode].items(), + key=lambda x: x[1]) + + print "Top sources of dispatches to {}:".format(bytecode) + for source_name, counter in top_sources: + print "{:>12d}\t{}".format(counter, source_name) + + print "\nTop destinations of dispatches from {}:".format(bytecode) + for destination_name, counter in top_destinations: + print "{:>12d}\t{}".format(counter, destination_name) + + +def build_counters_matrix(dispatches_table): + labels = sorted(dispatches_table.keys()) + + counters_matrix = numpy.empty([len(labels), len(labels)], dtype=int) + for from_index, from_name in enumerate(labels): + current_row = dispatches_table[from_name]; + for to_index, to_name in enumerate(labels): + counters_matrix[from_index, to_index] = current_row.get(to_name, 0) + + # Reverse y axis for a nicer appearance + xlabels = labels + ylabels = list(reversed(xlabels)) + counters_matrix = numpy.flipud(counters_matrix) + + return counters_matrix, xlabels, ylabels + + +def plot_dispatches_table(dispatches_table, figure, axis): + counters_matrix, xlabels, ylabels = build_counters_matrix(dispatches_table) + + image = axis.pcolor( + counters_matrix, + cmap="jet", + norm=colors.LogNorm(), + edgecolor="grey", + linestyle="dotted", + linewidth=0.5 + ) + + axis.xaxis.set( + ticks=numpy.arange(0.5, len(xlabels)), + label="From bytecode handler" + ) + axis.xaxis.tick_top() + axis.set_xlim(0, len(xlabels)) + axis.set_xticklabels(xlabels, rotation="vertical") + + axis.yaxis.set( + ticks=numpy.arange(0.5, len(ylabels)), + label="To bytecode handler", + ticklabels=ylabels + ) + axis.set_ylim(0, len(ylabels)) + + figure.colorbar( + image, + ax=axis, + fraction=0.01, + pad=0.01 + ) + + +def parse_command_line(): + command_line_parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=__DESCRIPTION, + epilog=__HELP_EPILOGUE + ) + command_line_parser.add_argument( + "--plot-size", "-s", + metavar="N", + default=30, + help="shorter side in inches of the output plot (default 30)" + ) + command_line_parser.add_argument( + "--plot", "-p", + action="store_true", + help="plot dispatch pairs heatmap" + ) + command_line_parser.add_argument( + "--interactive", "-i", + action="store_true", + help="open the heatmap in an interactive viewer, instead of writing to file" + ) + command_line_parser.add_argument( + "--top-bytecode-dispatch-pairs", "-t", + action="store_true", + help="print the top bytecode dispatch pairs" + ) + command_line_parser.add_argument( + "--top-entries-count", "-n", + metavar="N", + type=int, + default=10, + help="print N top entries when running with -t or -f (default 10)" + ) + command_line_parser.add_argument( + "--top-dispatches-for-bytecode", "-f", + metavar="<bytecode name>", + help="print top dispatch sources and destinations to the specified bytecode" + ) + command_line_parser.add_argument( + "--output-filename", "-o", + metavar="<output filename>", + default="v8.ignition_dispatches_table.svg", + help=("file to save the plot file to. File type is deduced from the " + "extension. PDF, SVG, PNG supported") + ) + command_line_parser.add_argument( + "input_filename", + metavar="<input filename>", + default="v8.ignition_dispatches_table.json", + nargs='?', + help="Ignition counters JSON file" + ) + + return command_line_parser.parse_args() + + +def main(): + program_options = parse_command_line() + + with open(program_options.input_filename) as stream: + dispatches_table = json.load(stream) + + warn_if_counter_may_have_saturated(dispatches_table) + + if program_options.plot: + figure, axis = pyplot.subplots() + plot_dispatches_table(dispatches_table, figure, axis) + + if program_options.interactive: + pyplot.show() + else: + figure.set_size_inches(program_options.plot_size, + program_options.plot_size) + pyplot.savefig(program_options.output_filename) + elif program_options.top_bytecode_dispatch_pairs: + print_top_bytecode_dispatch_pairs( + dispatches_table, program_options.top_entries_count) + elif program_options.top_dispatches_for_bytecode: + print_top_dispatch_sources_and_destinations( + dispatches_table, program_options.top_dispatches_for_bytecode, + program_options.top_entries_count) + else: + print_top_bytecodes(dispatches_table) + + +if __name__ == "__main__": + main() diff --git a/tools/ignition/bytecode_dispatches_report_test.py b/tools/ignition/bytecode_dispatches_report_test.py new file mode 100644 index 00000000..523dac29 --- /dev/null +++ b/tools/ignition/bytecode_dispatches_report_test.py @@ -0,0 +1,54 @@ +# Copyright 2016 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. + +import bytecode_dispatches_report as bdr +import unittest + + +class BytecodeDispatchesReportTest(unittest.TestCase): + def test_find_top_counters(self): + top_counters = bdr.find_top_bytecode_dispatch_pairs({ + "a": {"a": 10, "b": 8, "c": 99}, + "b": {"a": 1, "b": 4, "c": 1}, + "c": {"a": 42, "b": 3, "c": 7}}, 5) + self.assertListEqual(top_counters, [ + ('a', 'c', 99), + ('c', 'a', 42), + ('a', 'a', 10), + ('a', 'b', 8), + ('c', 'c', 7)]) + + def test_build_counters_matrix(self): + counters_matrix, xlabels, ylabels = bdr.build_counters_matrix({ + "a": {"a": 10, "b": 8, "c": 7}, + "b": {"a": 1, "c": 4}, + "c": {"a": 42, "b": 12, "c": 99}}) + self.assertTrue((counters_matrix == [[42, 12, 99], + [ 1, 0, 4], + [10, 8, 7]]).all()) + self.assertListEqual(xlabels, ['a', 'b', 'c']) + self.assertListEqual(ylabels, ['c', 'b', 'a']) + + def test_find_top_bytecodes(self): + top_dispatch_sources = bdr.find_top_bytecodes({ + "a": {"a": 10, "b": 8, "c": 7}, + "b": {"a": 1, "c": 4}, + "c": {"a": 42, "b": 12, "c": 99} + }) + self.assertListEqual(top_dispatch_sources, [ + ('c', 153), + ('a', 25), + ('b', 5) + ]) + + def test_find_top_dispatch_sources(self): + top_dispatch_sources = bdr.find_top_dispatch_sources({ + "a": {"a": 10, "b": 8, "c": 7}, + "b": {"a": 1, "c": 4}, + "c": {"a": 42, "b": 12, "c": 99} + }, "b", 10) + self.assertListEqual(top_dispatch_sources, [ + ("c", 12), + ("a", 8) + ]) diff --git a/tools/ignition/linux_perf_bytecode_annotate.py b/tools/ignition/linux_perf_bytecode_annotate.py new file mode 100755 index 00000000..6681190d --- /dev/null +++ b/tools/ignition/linux_perf_bytecode_annotate.py @@ -0,0 +1,174 @@ +#! /usr/bin/python2 +# +# Copyright 2016 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. +# + +import argparse +import collections +import os +import subprocess +import sys + + +__DESCRIPTION = """ +Processes a perf.data sample file and annotates the hottest instructions in a +given bytecode handler. +""" + + +__HELP_EPILOGUE = """ +Note: + This tool uses the disassembly of interpreter's bytecode handler codegen + from out/<arch>.debug/d8. you should ensure that this binary is in-sync with + the version used to generate the perf profile. + + Also, the tool depends on the symbol offsets from perf samples being accurate. + As such, you should use the ":pp" suffix for events. + +Examples: + EVENT_TYPE=cycles:pp tools/run-perf.sh out/x64.release/d8 + tools/ignition/linux_perf_bytecode_annotate.py Add +""" + + +def bytecode_offset_generator(perf_stream, bytecode_name): + skip_until_end_of_chain = False + bytecode_symbol = "BytecodeHandler:" + bytecode_name; + + for line in perf_stream: + # Lines starting with a "#" are comments, skip them. + if line[0] == "#": + continue + line = line.strip() + + # Empty line signals the end of the callchain. + if not line: + skip_until_end_of_chain = False + continue + + if skip_until_end_of_chain: + continue + + symbol_and_offset = line.split(" ", 1)[1] + + if symbol_and_offset.startswith("BytecodeHandler:"): + skip_until_end_of_chain = True + + if symbol_and_offset.startswith(bytecode_symbol): + yield int(symbol_and_offset.split("+", 1)[1], 16) + + +def bytecode_offset_counts(bytecode_offsets): + offset_counts = collections.defaultdict(int) + for offset in bytecode_offsets: + offset_counts[offset] += 1 + return offset_counts + + +def bytecode_disassembly_generator(ignition_codegen, bytecode_name): + name_string = "name = " + bytecode_name + for line in ignition_codegen: + if line.startswith(name_string): + break + + # Found the bytecode disassembly. + for line in ignition_codegen: + line = line.strip() + # Blank line marks the end of the bytecode's disassembly. + if not line: + return + + # Only yield disassembly output. + if not line.startswith("0x"): + continue + + yield line + + +def print_disassembly_annotation(offset_counts, bytecode_disassembly): + total = sum(offset_counts.values()) + offsets = sorted(offset_counts, reverse=True) + def next_offset(): + return offsets.pop() if offsets else -1 + + current_offset = next_offset() + print current_offset; + + for line in bytecode_disassembly: + disassembly_offset = int(line.split()[1]) + if disassembly_offset == current_offset: + count = offset_counts[current_offset] + percentage = 100.0 * count / total + print "{:>8d} ({:>5.1f}%) ".format(count, percentage), + current_offset = next_offset() + else: + print " ", + print line + + if offsets: + print ("WARNING: Offsets not empty. Output is most likely invalid due to " + "a mismatch between perf output and debug d8 binary.") + + +def parse_command_line(): + command_line_parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=__DESCRIPTION, + epilog=__HELP_EPILOGUE) + + command_line_parser.add_argument( + "--arch", "-a", + help="The architecture (default: x64)", + default="x64", + ) + command_line_parser.add_argument( + "--input", "-i", + help="perf sample file to process (default: perf.data)", + default="perf.data", + metavar="<perf filename>", + dest="perf_filename" + ) + command_line_parser.add_argument( + "--output", "-o", + help="output file name (stdout if omitted)", + type=argparse.FileType("wt"), + default=sys.stdout, + metavar="<output filename>", + dest="output_stream" + ) + command_line_parser.add_argument( + "bytecode_name", + metavar="<bytecode name>", + nargs="?", + help="The bytecode handler to annotate" + ) + + return command_line_parser.parse_args() + + +def main(): + program_options = parse_command_line() + perf = subprocess.Popen(["perf", "script", "-f", "ip,sym,symoff", + "-i", program_options.perf_filename], + stdout=subprocess.PIPE) + + v8_root_path = os.path.dirname(__file__) + "/../../" + d8_path = "{}/out/{}.debug/d8".format(v8_root_path, program_options.arch) + d8_codegen = subprocess.Popen([d8_path, "--ignition", + "--trace-ignition-codegen", "-e", "1"], + stdout=subprocess.PIPE) + + bytecode_offsets = bytecode_offset_generator( + perf.stdout, program_options.bytecode_name) + offset_counts = bytecode_offset_counts(bytecode_offsets) + + bytecode_disassembly = bytecode_disassembly_generator( + d8_codegen.stdout, program_options.bytecode_name) + + print_disassembly_annotation(offset_counts, bytecode_disassembly) + + +if __name__ == "__main__": + main() diff --git a/tools/ignition/linux_perf_bytecode_annotate_test.py b/tools/ignition/linux_perf_bytecode_annotate_test.py new file mode 100644 index 00000000..15abbeda --- /dev/null +++ b/tools/ignition/linux_perf_bytecode_annotate_test.py @@ -0,0 +1,85 @@ +# Copyright 2016 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. + +import StringIO +import unittest +import linux_perf_bytecode_annotate as bytecode_annotate + + +PERF_SCRIPT_OUTPUT = """ +# This line is a comment +# This should be ignored too +# +# cdefab01 aRandomSymbol::Name(to, be, ignored) + + 00000000 firstSymbol + 00000123 secondSymbol + + 01234567 foo + abcdef76 BytecodeHandler:bar+0x12 + 76543210 baz + abcdef76 BytecodeHandler:bar+0x16 + 76543210 baz + + 01234567 foo + abcdef76 BytecodeHandler:foo+0x1 + 76543210 baz + abcdef76 BytecodeHandler:bar+0x2 + 76543210 bar + + abcdef76 BytecodeHandler:bar+0x19 + + abcdef76 BytecodeHandler:bar+0x12 + + abcdef76 BytecodeHandler:bar+0x12 +""" + + +D8_CODEGEN_OUTPUT = """ +kind = BYTECODE_HANDLER +name = foo +compiler = turbofan +Instructions (size = 3) +0x3101394a3c0 0 55 push rbp +0x3101394a3c1 1 ffe3 jmp rbx + +kind = BYTECODE_HANDLER +name = bar +compiler = turbofan +Instructions (size = 5) +0x3101394b3c0 0 55 push rbp +0x3101394b3c1 1 4883c428 REX.W addq rsp,0x28 +# Unexpected comment +0x3101394b3c5 5 ffe3 jmp rbx + +kind = BYTECODE_HANDLER +name = baz +compiler = turbofan +Instructions (size = 5) +0x3101394c3c0 0 55 push rbp +0x3101394c3c1 1 4883c428 REX.W addq rsp,0x28 +0x3101394c3c5 5 ffe3 jmp rbx +""" + + +class LinuxPerfBytecodeAnnotateTest(unittest.TestCase): + + def test_bytecode_offset_generator(self): + perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT) + offsets = list( + bytecode_annotate.bytecode_offset_generator(perf_stream, "bar")) + self.assertListEqual(offsets, [18, 25, 18, 18]) + + def test_bytecode_disassembly_generator(self): + codegen_stream = StringIO.StringIO(D8_CODEGEN_OUTPUT) + disassembly = list( + bytecode_annotate.bytecode_disassembly_generator(codegen_stream, "bar")) + self.assertListEqual(disassembly, [ + "0x3101394b3c0 0 55 push rbp", + "0x3101394b3c1 1 4883c428 REX.W addq rsp,0x28", + "0x3101394b3c5 5 ffe3 jmp rbx"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/ignition/linux_perf_report.py b/tools/ignition/linux_perf_report.py new file mode 100755 index 00000000..fbf562c2 --- /dev/null +++ b/tools/ignition/linux_perf_report.py @@ -0,0 +1,222 @@ +#! /usr/bin/python2 +# +# Copyright 2016 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. +# + +import argparse +import collections +import re +import subprocess +import sys + + +__DESCRIPTION = """ +Processes a perf.data sample file and reports the hottest Ignition bytecodes, +or write an input file for flamegraph.pl. +""" + + +__HELP_EPILOGUE = """ +examples: + # Get a flamegraph for Ignition bytecode handlers on Octane benchmark, + # without considering the time spent compiling JS code, entry trampoline + # samples and other non-Ignition samples. + # + $ tools/run-perf.sh out/x64.release/d8 \\ + --ignition --noturbo --nocrankshaft run.js + $ tools/ignition/linux_perf_report.py --flamegraph -o out.collapsed + $ flamegraph.pl --colors js out.collapsed > out.svg + + # Same as above, but show all samples, including time spent compiling JS code, + # entry trampoline samples and other samples. + $ # ... + $ tools/ignition/linux_perf_report.py \\ + --flamegraph --show-all -o out.collapsed + $ # ... + + # Same as above, but show full function signatures in the flamegraph. + $ # ... + $ tools/ignition/linux_perf_report.py \\ + --flamegraph --show-full-signatures -o out.collapsed + $ # ... + + # See the hottest bytecodes on Octane benchmark, by number of samples. + # + $ tools/run-perf.sh out/x64.release/d8 \\ + --ignition --noturbo --nocrankshaft octane/run.js + $ tools/ignition/linux_perf_report.py +""" + + +COMPILER_SYMBOLS_RE = re.compile( + r"v8::internal::(?:\(anonymous namespace\)::)?Compile|v8::internal::Parser") + + +def strip_function_parameters(symbol): + if symbol[-1] != ')': return symbol + pos = 1 + parenthesis_count = 0 + for c in reversed(symbol): + if c == ')': + parenthesis_count += 1 + elif c == '(': + parenthesis_count -= 1 + if parenthesis_count == 0: + break + else: + pos += 1 + return symbol[:-pos] + + +def collapsed_callchains_generator(perf_stream, show_all=False, + show_full_signatures=False): + current_chain = [] + skip_until_end_of_chain = False + compiler_symbol_in_chain = False + + for line in perf_stream: + # Lines starting with a "#" are comments, skip them. + if line[0] == "#": + continue + + line = line.strip() + + # Empty line signals the end of the callchain. + if not line: + if not skip_until_end_of_chain and current_chain and show_all: + current_chain.append("[other]") + yield current_chain + # Reset parser status. + current_chain = [] + skip_until_end_of_chain = False + compiler_symbol_in_chain = False + continue + + if skip_until_end_of_chain: + continue + + symbol = line.split(" ", 1)[1] + if not show_full_signatures: + symbol = strip_function_parameters(symbol) + current_chain.append(symbol) + + if symbol.startswith("BytecodeHandler:"): + yield current_chain + skip_until_end_of_chain = True + elif symbol == "Stub:CEntryStub" and compiler_symbol_in_chain: + if show_all: + current_chain[-1] = "[compiler]" + yield current_chain + skip_until_end_of_chain = True + elif COMPILER_SYMBOLS_RE.match(symbol): + compiler_symbol_in_chain = True + elif symbol == "Builtin:InterpreterEntryTrampoline": + if len(current_chain) == 1: + yield ["[entry trampoline]"] + else: + # If we see an InterpreterEntryTrampoline which is not at the top of the + # chain and doesn't have a BytecodeHandler above it, then we have + # skipped the top BytecodeHandler due to the top-level stub not building + # a frame. File the chain in the [misattributed] bucket. + current_chain[-1] = "[misattributed]" + yield current_chain + skip_until_end_of_chain = True + + +def calculate_samples_count_per_callchain(callchains): + chain_counters = collections.defaultdict(int) + for callchain in callchains: + key = ";".join(reversed(callchain)) + chain_counters[key] += 1 + return chain_counters.items() + + +def calculate_samples_count_per_handler(callchains): + def strip_handler_prefix_if_any(handler): + return handler if handler[0] == "[" else handler.split(":", 1)[1] + + handler_counters = collections.defaultdict(int) + for callchain in callchains: + handler = strip_handler_prefix_if_any(callchain[-1]) + handler_counters[handler] += 1 + return handler_counters.items() + + +def write_flamegraph_input_file(output_stream, callchains): + for callchain, count in calculate_samples_count_per_callchain(callchains): + output_stream.write("{}; {}\n".format(callchain, count)) + + +def write_handlers_report(output_stream, callchains): + handler_counters = calculate_samples_count_per_handler(callchains) + samples_num = sum(counter for _, counter in handler_counters) + # Sort by decreasing number of samples + handler_counters.sort(key=lambda entry: entry[1], reverse=True) + for bytecode_name, count in handler_counters: + output_stream.write( + "{}\t{}\t{:.3f}%\n".format(bytecode_name, count, + 100. * count / samples_num)) + + +def parse_command_line(): + command_line_parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=__DESCRIPTION, + epilog=__HELP_EPILOGUE) + + command_line_parser.add_argument( + "perf_filename", + help="perf sample file to process (default: perf.data)", + nargs="?", + default="perf.data", + metavar="<perf filename>" + ) + command_line_parser.add_argument( + "--flamegraph", "-f", + help="output an input file for flamegraph.pl, not a report", + action="store_true", + dest="output_flamegraph" + ) + command_line_parser.add_argument( + "--show-all", "-a", + help="show samples outside Ignition bytecode handlers", + action="store_true" + ) + command_line_parser.add_argument( + "--show-full-signatures", "-s", + help="show full signatures instead of function names", + action="store_true" + ) + command_line_parser.add_argument( + "--output", "-o", + help="output file name (stdout if omitted)", + type=argparse.FileType('wt'), + default=sys.stdout, + metavar="<output filename>", + dest="output_stream" + ) + + return command_line_parser.parse_args() + + +def main(): + program_options = parse_command_line() + + perf = subprocess.Popen(["perf", "script", "-f", "ip,sym", + "-i", program_options.perf_filename], + stdout=subprocess.PIPE) + + callchains = collapsed_callchains_generator( + perf.stdout, program_options.show_all, + program_options.show_full_signatures) + + if program_options.output_flamegraph: + write_flamegraph_input_file(program_options.output_stream, callchains) + else: + write_handlers_report(program_options.output_stream, callchains) + + +if __name__ == "__main__": + main() diff --git a/tools/ignition/linux_perf_report_test.py b/tools/ignition/linux_perf_report_test.py new file mode 100644 index 00000000..d9cef75d --- /dev/null +++ b/tools/ignition/linux_perf_report_test.py @@ -0,0 +1,147 @@ +# Copyright 2016 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. + +import linux_perf_report as ipr +import StringIO +import unittest + + +PERF_SCRIPT_OUTPUT = """ +# This line is a comment +# This should be ignored too +# +# cdefab01 aRandomSymbol::Name(to, be, ignored) + + 00000000 firstSymbol + 00000123 secondSymbol + + 01234567 foo + abcdef76 BytecodeHandler:bar + 76543210 baz + +# Indentation shouldn't matter (neither should this line) + + 01234567 foo + abcdef76 BytecodeHandler:bar + 76543210 baz + + 01234567 beep + abcdef76 BytecodeHandler:bar + 76543210 baz + + 01234567 hello + abcdef76 v8::internal::Compiler + 00000000 Stub:CEntryStub + 76543210 world + 11111111 BytecodeHandler:nope + + 00000000 Lost + 11111111 Builtin:InterpreterEntryTrampoline + 22222222 bar + + 11111111 Builtin:InterpreterEntryTrampoline + 22222222 bar +""" + + +class LinuxPerfReportTest(unittest.TestCase): + def test_collapsed_callchains_generator(self): + perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT) + callchains = list(ipr.collapsed_callchains_generator(perf_stream)) + self.assertListEqual(callchains, [ + ["foo", "BytecodeHandler:bar"], + ["foo", "BytecodeHandler:bar"], + ["beep", "BytecodeHandler:bar"], + ["[entry trampoline]"], + ]) + + def test_collapsed_callchains_generator_show_other(self): + perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT) + callchains = list(ipr.collapsed_callchains_generator(perf_stream, + show_all=True)) + self.assertListEqual(callchains, [ + ['firstSymbol', 'secondSymbol', '[other]'], + ["foo", "BytecodeHandler:bar"], + ["foo", "BytecodeHandler:bar"], + ["beep", "BytecodeHandler:bar"], + ["hello", "v8::internal::Compiler", "[compiler]"], + ["Lost", "[misattributed]"], + ["[entry trampoline]"], + ]) + + def test_calculate_samples_count_per_callchain(self): + counters = ipr.calculate_samples_count_per_callchain([ + ["foo", "BytecodeHandler:bar"], + ["foo", "BytecodeHandler:bar"], + ["beep", "BytecodeHandler:bar"], + ["hello", "v8::internal::Compiler", "[compiler]"], + ]) + self.assertItemsEqual(counters, [ + ('BytecodeHandler:bar;foo', 2), + ('BytecodeHandler:bar;beep', 1), + ('[compiler];v8::internal::Compiler;hello', 1), + ]) + + def test_calculate_samples_count_per_callchain(self): + counters = ipr.calculate_samples_count_per_callchain([ + ["foo", "BytecodeHandler:bar"], + ["foo", "BytecodeHandler:bar"], + ["beep", "BytecodeHandler:bar"], + ]) + self.assertItemsEqual(counters, [ + ('BytecodeHandler:bar;foo', 2), + ('BytecodeHandler:bar;beep', 1), + ]) + + def test_calculate_samples_count_per_handler_show_compile(self): + counters = ipr.calculate_samples_count_per_handler([ + ["foo", "BytecodeHandler:bar"], + ["foo", "BytecodeHandler:bar"], + ["beep", "BytecodeHandler:bar"], + ["hello", "v8::internal::Compiler", "[compiler]"], + ]) + self.assertItemsEqual(counters, [ + ("bar", 3), + ("[compiler]", 1) + ]) + + def test_calculate_samples_count_per_handler_(self): + counters = ipr.calculate_samples_count_per_handler([ + ["foo", "BytecodeHandler:bar"], + ["foo", "BytecodeHandler:bar"], + ["beep", "BytecodeHandler:bar"], + ]) + self.assertItemsEqual(counters, [("bar", 3)]) + + def test_multiple_handlers(self): + perf_stream = StringIO.StringIO(""" + 0000 foo(bar) + 1234 BytecodeHandler:first + 5678 a::random::call<to>(something, else) + 9abc BytecodeHandler:second + def0 otherIrrelevant(stuff) + 1111 entrypoint + """) + callchains = list(ipr.collapsed_callchains_generator(perf_stream, False)) + self.assertListEqual(callchains, [ + ["foo", "BytecodeHandler:first"], + ]) + + def test_compiler_symbols_regex(self): + compiler_symbols = [ + "v8::internal::Parser", + "v8::internal::(anonymous namespace)::Compile", + "v8::internal::Compiler::foo", + ] + for compiler_symbol in compiler_symbols: + self.assertTrue(ipr.COMPILER_SYMBOLS_RE.match(compiler_symbol)) + + def test_strip_function_parameters(self): + def should_match(signature, name): + self.assertEqual(ipr.strip_function_parameters(signature), name) + + should_match("foo(bar)", "foo"), + should_match("Foo(foomatic::(anonymous)::bar(baz))", "Foo"), + should_match("v8::(anonymous ns)::bar<thing(with, parentheses)>(baz, poe)", + "v8::(anonymous ns)::bar<thing(with, parentheses)>") diff --git a/tools/jsfunfuzz/jsfunfuzz.gyp b/tools/jsfunfuzz/jsfunfuzz.gyp index fb0e5f49..8938e445 100644 --- a/tools/jsfunfuzz/jsfunfuzz.gyp +++ b/tools/jsfunfuzz/jsfunfuzz.gyp @@ -13,8 +13,8 @@ '../../src/d8.gyp:d8_run', ], 'includes': [ - '../../build/features.gypi', - '../../build/isolate.gypi', + '../../gypfiles/features.gypi', + '../../gypfiles/isolate.gypi', ], 'sources': [ 'jsfunfuzz.isolate', diff --git a/tools/mingw-generate-makefiles.sh b/tools/mingw-generate-makefiles.sh index 32af52d3..67715fc1 100755 --- a/tools/mingw-generate-makefiles.sh +++ b/tools/mingw-generate-makefiles.sh @@ -27,7 +27,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Monkey-patch GYP. -cat > build/gyp/gyp.mingw << EOF +cat > tools/gyp/gyp.mingw << EOF #!/usr/bin/env python # Copyright (c) 2009 Google Inc. All rights reserved. @@ -74,11 +74,11 @@ EOF find out -name '*.mk' -or -name 'Makefile*' -exec rm {} \; # Generate fresh Makefiles. -mv build/gyp/gyp build/gyp/gyp.original -mv build/gyp/gyp.mingw build/gyp/gyp +mv tools/gyp/gyp tools/gyp/gyp.original +mv tools/gyp/gyp.mingw tools/gyp/gyp make out/Makefile.ia32 -mv build/gyp/gyp build/gyp/gyp.mingw -mv build/gyp/gyp.original build/gyp/gyp +mv tools/gyp/gyp tools/gyp/gyp.mingw +mv tools/gyp/gyp.original tools/gyp/gyp # Patch generated Makefiles: replace most backslashes with forward slashes, # fix library names in linker flags. diff --git a/tools/parser-shell.gyp b/tools/parser-shell.gyp index 77ed1eb2..4ef1a82d 100644 --- a/tools/parser-shell.gyp +++ b/tools/parser-shell.gyp @@ -30,14 +30,14 @@ 'v8_code': 1, 'v8_enable_i18n_support%': 1, }, - 'includes': ['../build/toolchain.gypi', '../build/features.gypi'], + 'includes': ['../gypfiles/toolchain.gypi', '../gypfiles/features.gypi'], 'targets': [ { 'target_name': 'parser-shell', 'type': 'executable', 'dependencies': [ - '../tools/gyp/v8.gyp:v8', - '../tools/gyp/v8.gyp:v8_libplatform', + '../src/v8.gyp:v8', + '../src/v8.gyp:v8_libplatform', ], 'conditions': [ ['v8_enable_i18n_support==1', { @@ -50,10 +50,6 @@ 'include_dirs+': [ '..', ], - 'defines': [ - # TODO(jochen): Remove again after this is globally turned on. - 'V8_IMMINENT_DEPRECATION_WARNINGS', - ], 'sources': [ 'parser-shell.cc', 'shell-utils.h', diff --git a/tools/perf-to-html.py b/tools/perf-to-html.py index 63faeb1d..7ec9c50f 100755 --- a/tools/perf-to-html.py +++ b/tools/perf-to-html.py @@ -115,8 +115,8 @@ class Benchmark: self.name_ = name self.tests_ = {} for test in data: - # strip off "<name>/" prefix - test_name = test.split("/")[1] + # strip off "<name>/" prefix, allowing for subsequent "/"s + test_name = test.split("/", 1)[1] self.appendResult(test_name, data[test]) # tests is a dictionary of Results diff --git a/tools/release/auto_roll.py b/tools/release/auto_roll.py index b71cac5a..243b029b 100755 --- a/tools/release/auto_roll.py +++ b/tools/release/auto_roll.py @@ -18,7 +18,9 @@ https://github.com/v8/v8/wiki/Triaging%20issues Please close rolling in case of a roll revert: https://v8-roll.appspot.com/ -This only works with a Google account.""") +This only works with a Google account. + +CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel""") class Preparation(Step): MESSAGE = "Preparation." diff --git a/tools/release/create_release.py b/tools/release/create_release.py index 7477ea14..14d44b4b 100755 --- a/tools/release/create_release.py +++ b/tools/release/create_release.py @@ -223,6 +223,27 @@ class CommitBranch(Step): os.remove(self.Config("CHANGELOG_ENTRY_FILE")) +class FixBrokenTag(Step): + MESSAGE = "Check for a missing tag and fix that instead." + + def RunStep(self): + commit = None + try: + commit = self.GitLog( + n=1, format="%H", + grep=self["commit_title"], + branch="origin/%s" % self["version"], + ) + except GitFailedException: + # In the normal case, the remote doesn't exist yet and git will fail. + pass + if commit: + print "Found %s. Trying to repair tag and bail out." % self["version"] + self.Git("tag %s %s" % (self["version"], commit)) + self.Git("push origin refs/tags/%s" % self["version"]) + return True + + class PushBranch(Step): MESSAGE = "Push changes." @@ -303,6 +324,7 @@ class CreateRelease(ScriptsBase): SetVersion, EnableMergeWatchlist, CommitBranch, + FixBrokenTag, PushBranch, TagRevision, CleanUp, diff --git a/tools/release/test_scripts.py b/tools/release/test_scripts.py index 05457c92..417f739f 100644 --- a/tools/release/test_scripts.py +++ b/tools/release/test_scripts.py @@ -970,6 +970,8 @@ Performance and stability improvements on all platforms.""" cb=self.WriteFakeWatchlistsFile), Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], "", cb=CheckVersionCommit), + Cmd("git log -1 --format=%H --grep=\"Version 3.22.5\" origin/3.22.5", + ""), Cmd("git push origin " "refs/heads/work-branch:refs/pending/heads/3.22.5 " "push_hash:refs/pending-tags/heads/3.22.5 " @@ -1041,6 +1043,8 @@ Please close rolling in case of a roll revert: https://v8-roll.appspot.com/ This only works with a Google account. +CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel + TBR=reviewer@chromium.org""" # Snippet from the original DEPS file. diff --git a/tools/run-deopt-fuzzer.gyp b/tools/run-deopt-fuzzer.gyp index 73f0aaf7..9eb6b538 100644 --- a/tools/run-deopt-fuzzer.gyp +++ b/tools/run-deopt-fuzzer.gyp @@ -13,8 +13,8 @@ '../src/d8.gyp:d8_run', ], 'includes': [ - '../build/features.gypi', - '../build/isolate.gypi', + '../gypfiles/features.gypi', + '../gypfiles/isolate.gypi', ], 'sources': [ 'run-deopt-fuzzer.isolate', diff --git a/tools/run-deopt-fuzzer.py b/tools/run-deopt-fuzzer.py index 970aa8e6..928c71b7 100755 --- a/tools/run-deopt-fuzzer.py +++ b/tools/run-deopt-fuzzer.py @@ -399,6 +399,7 @@ def Execute(arch, mode, args, options, suites, workspace): "gc_stress": False, "gcov_coverage": False, "ignition": False, + "ignition_turbofan": False, "isolates": options.isolates, "mode": mode, "no_i18n": False, diff --git a/tools/run-perf.sh b/tools/run-perf.sh index 24053b40..03123fdb 100755 --- a/tools/run-perf.sh +++ b/tools/run-perf.sh @@ -13,6 +13,7 @@ SAMPLE_EVERY_N_CYCLES=10000 SAMPLE_RATE_CONFIG_FILE="/proc/sys/kernel/perf_event_max_sample_rate" KERNEL_MAP_CONFIG_FILE="/proc/sys/kernel/kptr_restrict" CALL_GRAPH_METHOD="fp" # dwarf does not play nice with JITted objects. +EVENT_TYPE=${EVENT_TYPE:=cycles:u} ########## Usage @@ -46,7 +47,7 @@ fi echo "Running..." perf record -R \ - -e cycles:u \ + -e $EVENT_TYPE \ -c $SAMPLE_EVERY_N_CYCLES \ --call-graph $CALL_GRAPH_METHOD \ -i $@ --perf_basic_prof diff --git a/tools/run-tests.py b/tools/run-tests.py index a380c97a..b1c71dd0 100755 --- a/tools/run-tests.py +++ b/tools/run-tests.py @@ -105,6 +105,7 @@ TIMEOUT_DEFAULT = 60 VARIANTS = ["default", "stress", "turbofan"] EXHAUSTIVE_VARIANTS = VARIANTS + [ + "ignition", "nocrankshaft", "turbofan_opt", ] @@ -194,6 +195,8 @@ SLOW_ARCHS = ["android_arm", "mips64el", "nacl_ia32", "nacl_x64", + "s390", + "s390x", "x87", "arm64"] @@ -253,6 +256,9 @@ def BuildOptions(): default="") result.add_option("--ignition", help="Skip tests which don't run in ignition", default=False, action="store_true") + result.add_option("--ignition-turbofan", + help="Skip tests which don't run in ignition_turbofan", + default=False, action="store_true") result.add_option("--isolates", help="Whether to test isolates", default=False, action="store_true") result.add_option("-j", help="The number of parallel tasks to run", @@ -335,7 +341,7 @@ def BuildOptions(): result.add_option("--time", help="Print timing information after running", default=False, action="store_true") result.add_option("-t", "--timeout", help="Timeout in seconds", - default= -1, type="int") + default=TIMEOUT_DEFAULT, type="int") result.add_option("--tsan", help="Regard test expectations for TSAN", default=False, action="store_true") @@ -378,6 +384,10 @@ def BuildbotToV8Mode(config): def SetupEnvironment(options): """Setup additional environment variables.""" + + # Many tests assume an English interface. + os.environ['LANG'] = 'en_US.UTF-8' + symbolizer = 'external_symbolizer_path=%s' % ( os.path.join( BASE_DIR, 'third_party', 'llvm-build', 'Release+Asserts', 'bin', @@ -591,6 +601,11 @@ def Main(): return 1 SetupEnvironment(options) + if options.swarming: + # Swarming doesn't print how isolated commands are called. Lets make this + # less cryptic by printing it ourselves. + print ' '.join(sys.argv) + exit_code = 0 if not options.no_presubmit: print ">>> running presubmit tests" @@ -663,19 +678,16 @@ def Execute(arch, mode, args, options, suites): # Populate context object. mode_flags = MODES[mode]["flags"] - timeout = options.timeout - if timeout == -1: - # Simulators are slow, therefore allow a longer default timeout. - if arch in SLOW_ARCHS: - timeout = 2 * TIMEOUT_DEFAULT; - else: - timeout = TIMEOUT_DEFAULT; - timeout *= MODES[mode]["timeout_scalefactor"] + # Simulators are slow, therefore allow a longer timeout. + if arch in SLOW_ARCHS: + options.timeout *= 2 + + options.timeout *= MODES[mode]["timeout_scalefactor"] if options.predictable: # Predictable mode is slower. - timeout *= 2 + options.timeout *= 2 # TODO(machenbach): Remove temporary verbose output on windows after # debugging driver-hung-up on XP. @@ -685,7 +697,8 @@ def Execute(arch, mode, args, options, suites): ) ctx = context.Context(arch, MODES[mode]["execution_mode"], shell_dir, mode_flags, verbose_output, - timeout, options.isolates, + options.timeout, + options.isolates, options.command_prefix, options.extra_flags, options.no_i18n, @@ -711,6 +724,7 @@ def Execute(arch, mode, args, options, suites): "gc_stress": options.gc_stress, "gcov_coverage": options.gcov_coverage, "ignition": options.ignition, + "ignition_turbofan": options.ignition_turbofan, "isolates": options.isolates, "mode": MODES[mode]["status_mode"], "no_i18n": options.no_i18n, diff --git a/tools/run-valgrind.gyp b/tools/run-valgrind.gyp index d06be933..02dd26d2 100644 --- a/tools/run-valgrind.gyp +++ b/tools/run-valgrind.gyp @@ -13,8 +13,8 @@ '../src/d8.gyp:d8_run', ], 'includes': [ - '../build/features.gypi', - '../build/isolate.gypi', + '../gypfiles/features.gypi', + '../gypfiles/isolate.gypi', ], 'sources': [ 'run-valgrind.isolate', diff --git a/tools/run_perf.py b/tools/run_perf.py index db4245f4..1dd03bd5 100755 --- a/tools/run_perf.py +++ b/tools/run_perf.py @@ -612,6 +612,21 @@ class Platform(object): class DesktopPlatform(Platform): def __init__(self, options): super(DesktopPlatform, self).__init__(options) + self.command_prefix = [] + + if options.prioritize or options.affinitize != None: + self.command_prefix = ["schedtool"] + if options.prioritize: + self.command_prefix += ["-n", "-20"] + if options.affinitize != None: + # schedtool expects a bit pattern when setting affinity, where each + # bit set to '1' corresponds to a core where the process may run on. + # First bit corresponds to CPU 0. Since the 'affinitize' parameter is + # a core number, we need to map to said bit pattern. + cpu = int(options.affinitize) + core = 1 << cpu + self.command_prefix += ["-a", ("0x%x" % core)] + self.command_prefix += ["-e"] def PreExecution(self): pass @@ -627,15 +642,18 @@ class DesktopPlatform(Platform): suffix = ' - without patch' if no_patch else '' shell_dir = self.shell_dir_no_patch if no_patch else self.shell_dir title = ">>> %%s (#%d)%s:" % ((count + 1), suffix) + command = self.command_prefix + runnable.GetCommand(shell_dir, + self.extra_flags) try: output = commands.Execute( - runnable.GetCommand(shell_dir, self.extra_flags), - timeout=runnable.timeout, + command, + timeout=runnable.timeout, ) except OSError as e: # pragma: no cover print title % "OSError" print e return "" + print title % "Stdout" print output.stdout if output.stderr: # pragma: no cover @@ -788,6 +806,107 @@ class AndroidPlatform(Platform): # pragma: no cover stdout = "" return stdout +class CustomMachineConfiguration: + def __init__(self, disable_aslr = False, governor = None): + self.aslr_backup = None + self.governor_backup = None + self.disable_aslr = disable_aslr + self.governor = governor + + def __enter__(self): + if self.disable_aslr: + self.aslr_backup = CustomMachineConfiguration.GetASLR() + CustomMachineConfiguration.SetASLR(0) + if self.governor != None: + self.governor_backup = CustomMachineConfiguration.GetCPUGovernor() + CustomMachineConfiguration.SetCPUGovernor(self.governor) + return self + + def __exit__(self, type, value, traceback): + if self.aslr_backup != None: + CustomMachineConfiguration.SetASLR(self.aslr_backup) + if self.governor_backup != None: + CustomMachineConfiguration.SetCPUGovernor(self.governor_backup) + + @staticmethod + def GetASLR(): + try: + with open("/proc/sys/kernel/randomize_va_space", "r") as f: + return int(f.readline().strip()) + except Exception as e: + print "Failed to get current ASLR settings." + raise e + + @staticmethod + def SetASLR(value): + try: + with open("/proc/sys/kernel/randomize_va_space", "w") as f: + f.write(str(value)) + except Exception as e: + print "Failed to update ASLR to %s." % value + print "Are we running under sudo?" + raise e + + new_value = CustomMachineConfiguration.GetASLR() + if value != new_value: + raise Exception("Present value is %s" % new_value) + + @staticmethod + def GetCPUCoresRange(): + try: + with open("/sys/devices/system/cpu/present", "r") as f: + indexes = f.readline() + first, last = map(int, indexes.split("-")) + return range(first, last + 1) + except Exception as e: + print "Failed to retrieve number of CPUs." + raise e + + @staticmethod + def GetCPUPathForId(cpu_index): + ret = "/sys/devices/system/cpu/cpu" + ret += str(cpu_index) + ret += "/cpufreq/scaling_governor" + return ret + + @staticmethod + def GetCPUGovernor(): + try: + cpu_indices = CustomMachineConfiguration.GetCPUCoresRange() + ret = None + for cpu_index in cpu_indices: + cpu_device = CustomMachineConfiguration.GetCPUPathForId(cpu_index) + with open(cpu_device, "r") as f: + # We assume the governors of all CPUs are set to the same value + val = f.readline().strip() + if ret == None: + ret = val + elif ret != val: + raise Exception("CPU cores have differing governor settings") + return ret + except Exception as e: + print "Failed to get the current CPU governor." + print "Is the CPU governor disabled? Check BIOS." + raise e + + @staticmethod + def SetCPUGovernor(value): + try: + cpu_indices = CustomMachineConfiguration.GetCPUCoresRange() + for cpu_index in cpu_indices: + cpu_device = CustomMachineConfiguration.GetCPUPathForId(cpu_index) + with open(cpu_device, "w") as f: + f.write(value) + + except Exception as e: + print "Failed to change CPU governor to %s." % value + print "Are we running under sudo?" + raise e + + cur_value = CustomMachineConfiguration.GetCPUGovernor() + if cur_value != value: + raise Exception("Could not set CPU governor. Present value is %s" + % cur_value ) # TODO: Implement results_processor. def Main(args): @@ -822,6 +941,27 @@ def Main(args): help="JavaScript engine binary. By default, d8 under " "architecture-specific build dir. " "Not supported in conjunction with outdir-no-patch.") + parser.add_option("--prioritize", + help="Raise the priority to nice -20 for the benchmarking " + "process.Requires Linux, schedtool, and sudo privileges.", + default=False, action="store_true") + parser.add_option("--affinitize", + help="Run benchmarking process on the specified core. " + "For example: " + "--affinitize=0 will run the benchmark process on core 0. " + "--affinitize=3 will run the benchmark process on core 3. " + "Requires Linux, schedtool, and sudo privileges.", + default=None) + parser.add_option("--noaslr", + help="Disable ASLR for the duration of the benchmarked " + "process. Requires Linux and sudo privileges.", + default=False, action="store_true") + parser.add_option("--cpu-governor", + help="Set cpu governor to specified policy for the " + "duration of the benchmarked process. Typical options: " + "'powersave' for more stable results, or 'performance' " + "for shorter completion time of suite, with potentially " + "more noise in results.") (options, args) = parser.parse_args(args) @@ -872,56 +1012,60 @@ def Main(args): else: options.shell_dir_no_patch = None + prev_aslr = None + prev_cpu_gov = None platform = Platform.GetPlatform(options) results = Results() results_no_patch = Results() - for path in args: - path = os.path.abspath(path) + with CustomMachineConfiguration(governor = options.cpu_governor, + disable_aslr = options.noaslr) as conf: + for path in args: + path = os.path.abspath(path) - if not os.path.exists(path): # pragma: no cover - results.errors.append("Configuration file %s does not exist." % path) - continue + if not os.path.exists(path): # pragma: no cover + results.errors.append("Configuration file %s does not exist." % path) + continue - with open(path) as f: - suite = json.loads(f.read()) + with open(path) as f: + suite = json.loads(f.read()) - # If no name is given, default to the file name without .json. - suite.setdefault("name", os.path.splitext(os.path.basename(path))[0]) + # If no name is given, default to the file name without .json. + suite.setdefault("name", os.path.splitext(os.path.basename(path))[0]) - # Setup things common to one test suite. - platform.PreExecution() + # Setup things common to one test suite. + platform.PreExecution() - # Build the graph/trace tree structure. - default_parent = DefaultSentinel(default_binary_name) - root = BuildGraphConfigs(suite, options.arch, default_parent) + # Build the graph/trace tree structure. + default_parent = DefaultSentinel(default_binary_name) + root = BuildGraphConfigs(suite, options.arch, default_parent) - # Callback to be called on each node on traversal. - def NodeCB(node): - platform.PreTests(node, path) + # Callback to be called on each node on traversal. + def NodeCB(node): + platform.PreTests(node, path) - # Traverse graph/trace tree and interate over all runnables. - for runnable in FlattenRunnables(root, NodeCB): - print ">>> Running suite: %s" % "/".join(runnable.graphs) + # Traverse graph/trace tree and interate over all runnables. + for runnable in FlattenRunnables(root, NodeCB): + print ">>> Running suite: %s" % "/".join(runnable.graphs) - def Runner(): - """Output generator that reruns several times.""" - for i in xrange(0, max(1, runnable.run_count)): - # TODO(machenbach): Allow timeout per arch like with run_count per - # arch. - yield platform.Run(runnable, i) + def Runner(): + """Output generator that reruns several times.""" + for i in xrange(0, max(1, runnable.run_count)): + # TODO(machenbach): Allow timeout per arch like with run_count per + # arch. + yield platform.Run(runnable, i) - # Let runnable iterate over all runs and handle output. - result, result_no_patch = runnable.Run( + # Let runnable iterate over all runs and handle output. + result, result_no_patch = runnable.Run( Runner, trybot=options.shell_dir_no_patch) - results += result - results_no_patch += result_no_patch - platform.PostExecution() - - if options.json_test_results: - results.WriteToFile(options.json_test_results) - else: # pragma: no cover - print results + results += result + results_no_patch += result_no_patch + platform.PostExecution() + + if options.json_test_results: + results.WriteToFile(options.json_test_results) + else: # pragma: no cover + print results if options.json_test_results_no_patch: results_no_patch.WriteToFile(options.json_test_results_no_patch) diff --git a/tools/testrunner/local/execution.py b/tools/testrunner/local/execution.py index e0aec0bb..f3d11a8b 100644 --- a/tools/testrunner/local/execution.py +++ b/tools/testrunner/local/execution.py @@ -248,7 +248,6 @@ class Runner(object): self.total += 1 def _ProcessTestNormal(self, test, result, pool): - self.indicator.AboutToRun(test) test.output = result[1] test.duration = result[2] has_unexpected_output = test.suite.HasUnexpectedOutput(test) @@ -285,7 +284,6 @@ class Runner(object): if test.run == 1 and result[1].HasTimedOut(): # If we get a timeout in the first run, we are already in an # unpredictable state. Just report it as a failure and don't rerun. - self.indicator.AboutToRun(test) test.output = result[1] self.remaining -= 1 self.failed.append(test) @@ -294,16 +292,13 @@ class Runner(object): # From the second run on, check for different allocations. If a # difference is found, call the indicator twice to report both tests. # All runs of each test are counted as one for the statistic. - self.indicator.AboutToRun(test) self.remaining -= 1 self.failed.append(test) self.indicator.HasRun(test, True) - self.indicator.AboutToRun(test) test.output = result[1] self.indicator.HasRun(test, True) elif test.run >= 3: # No difference on the third run -> report a success. - self.indicator.AboutToRun(test) self.remaining -= 1 self.succeeded += 1 test.output = result[1] diff --git a/tools/testrunner/local/progress.py b/tools/testrunner/local/progress.py index 4e1be3e4..33e27e15 100644 --- a/tools/testrunner/local/progress.py +++ b/tools/testrunner/local/progress.py @@ -34,6 +34,7 @@ import time from . import execution from . import junit_output +from . import statusfile ABS_PATH_PREFIX = os.getcwd() + os.sep @@ -53,9 +54,6 @@ class ProgressIndicator(object): def Done(self): pass - def AboutToRun(self, test): - pass - def HasRun(self, test, has_unexpected_output): pass @@ -146,10 +144,6 @@ class SimpleProgressIndicator(ProgressIndicator): class VerboseProgressIndicator(SimpleProgressIndicator): - def AboutToRun(self, test): - print 'Starting %s...' % test.GetLabel() - sys.stdout.flush() - def HasRun(self, test, has_unexpected_output): if has_unexpected_output: if test.output.HasCrashed(): @@ -200,10 +194,8 @@ class CompactProgressIndicator(ProgressIndicator): self.PrintProgress('Done') print "" # Line break. - def AboutToRun(self, test): - self.PrintProgress(test.GetLabel()) - def HasRun(self, test, has_unexpected_output): + self.PrintProgress(test.GetLabel()) if has_unexpected_output: self.ClearLine(self.last_status_length) self.PrintFailureHeader(test) @@ -329,6 +321,12 @@ class JsonTestProgressIndicator(ProgressIndicator): # Buildbot might start out with an empty file. complete_results = json.loads(f.read() or "[]") + duration_mean = None + if self.tests: + # Get duration mean. + duration_mean = ( + sum(t.duration for t in self.tests) / float(len(self.tests))) + # Sort tests by duration. timed_tests = [t for t in self.tests if t.duration is not None] timed_tests.sort(lambda a, b: cmp(b.duration, a.duration)) @@ -338,6 +336,7 @@ class JsonTestProgressIndicator(ProgressIndicator): "flags": test.flags, "command": self._EscapeCommand(test).replace(ABS_PATH_PREFIX, ""), "duration": test.duration, + "marked_slow": statusfile.IsSlow(test.outcomes), } for test in timed_tests[:20] ] @@ -346,6 +345,8 @@ class JsonTestProgressIndicator(ProgressIndicator): "mode": self.mode, "results": self.results, "slowest_tests": slowest_tests, + "duration_mean": duration_mean, + "test_total": len(self.tests), }) with open(self.json_test_results, "w") as f: diff --git a/tools/testrunner/local/statusfile.py b/tools/testrunner/local/statusfile.py index 7e96cc37..fde62379 100644 --- a/tools/testrunner/local/statusfile.py +++ b/tools/testrunner/local/statusfile.py @@ -36,6 +36,7 @@ TIMEOUT = "TIMEOUT" CRASH = "CRASH" SLOW = "SLOW" FAST_VARIANTS = "FAST_VARIANTS" +NO_IGNITION = "NO_IGNITION" NO_VARIANTS = "NO_VARIANTS" # These are just for the status files and are mapped below in DEFS: FAIL_OK = "FAIL_OK" @@ -46,7 +47,8 @@ ALWAYS = "ALWAYS" KEYWORDS = {} for key in [SKIP, FAIL, PASS, OKAY, TIMEOUT, CRASH, SLOW, FAIL_OK, - FAST_VARIANTS, NO_VARIANTS, PASS_OR_FAIL, FAIL_SLOPPY, ALWAYS]: + FAST_VARIANTS, NO_IGNITION, NO_VARIANTS, PASS_OR_FAIL, FAIL_SLOPPY, + ALWAYS]: KEYWORDS[key] = key DEFS = {FAIL_OK: [FAIL, OKAY], @@ -70,6 +72,10 @@ def IsSlow(outcomes): return SLOW in outcomes +def NoIgnitionVariant(outcomes): + return NO_IGNITION in outcomes + + def OnlyStandardVariant(outcomes): return NO_VARIANTS in outcomes diff --git a/tools/testrunner/local/testsuite.py b/tools/testrunner/local/testsuite.py index f43d008b..8e8b4769 100644 --- a/tools/testrunner/local/testsuite.py +++ b/tools/testrunner/local/testsuite.py @@ -41,7 +41,8 @@ ALL_VARIANT_FLAGS = { "turbofan": [["--turbo"]], "turbofan_opt": [["--turbo", "--always-opt"]], "nocrankshaft": [["--nocrankshaft"]], - "ignition": [["--ignition", "--turbo"]], + "ignition": [["--ignition"]], + "ignition_turbofan": [["--ignition", "--turbo", "--turbo-from-bytecode"]], "preparser": [["--min-preparse-length=0"]], } @@ -51,14 +52,17 @@ FAST_VARIANT_FLAGS = { "stress": [["--stress-opt"]], "turbofan": [["--turbo"]], "nocrankshaft": [["--nocrankshaft"]], - "ignition": [["--ignition", "--turbo"]], + "ignition": [["--ignition"]], + "ignition_turbofan": [["--ignition", "--turbo", "--turbo-from-bytecode"]], "preparser": [["--min-preparse-length=0"]], } ALL_VARIANTS = set(["default", "stress", "turbofan", "turbofan_opt", - "nocrankshaft", "ignition", "preparser"]) + "nocrankshaft", "ignition", "ignition_turbofan", + "preparser"]) FAST_VARIANTS = set(["default", "turbofan"]) STANDARD_VARIANT = set(["default"]) +IGNITION_VARIANT = set(["ignition"]) class VariantGenerator(object): @@ -69,12 +73,15 @@ class VariantGenerator(object): self.standard_variant = STANDARD_VARIANT & variants def FilterVariantsByTest(self, testcase): - if testcase.outcomes and statusfile.OnlyStandardVariant( - testcase.outcomes): - return self.standard_variant - if testcase.outcomes and statusfile.OnlyFastVariants(testcase.outcomes): - return self.fast_variants - return self.all_variants + result = self.all_variants + if testcase.outcomes: + if statusfile.OnlyStandardVariant(testcase.outcomes): + return self.standard_variant + if statusfile.OnlyFastVariants(testcase.outcomes): + result = self.fast_variants + if statusfile.NoIgnitionVariant(testcase.outcomes): + result = result - IGNITION_VARIANT + return result def GetFlagSets(self, testcase, variant): if testcase.outcomes and statusfile.OnlyFastVariants(testcase.outcomes): diff --git a/tools/testrunner/network/network_execution.py b/tools/testrunner/network/network_execution.py index c842aba5..a9544017 100644 --- a/tools/testrunner/network/network_execution.py +++ b/tools/testrunner/network/network_execution.py @@ -203,7 +203,6 @@ class NetworkedRunner(execution.Runner): [constants.INFORM_DURATION, perf_key, test.duration, self.context.arch, self.context.mode], self.local_socket) - self.indicator.AboutToRun(test) has_unexpected_output = test.suite.HasUnexpectedOutput(test) if has_unexpected_output: self.failed.append(test) diff --git a/tools/tickprocessor.js b/tools/tickprocessor.js index ba7401a2..5534355f 100644 --- a/tools/tickprocessor.js +++ b/tools/tickprocessor.js @@ -83,7 +83,7 @@ function TickProcessor( pairwiseTimedRange, onlySummary) { LogReader.call(this, { - 'shared-library': { parsers: [null, parseInt, parseInt], + 'shared-library': { parsers: [null, parseInt, parseInt, parseInt], processor: this.processSharedLibrary }, 'code-creation': { parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'], @@ -242,13 +242,13 @@ TickProcessor.prototype.processLogFileInTest = function(fileName) { TickProcessor.prototype.processSharedLibrary = function( - name, startAddr, endAddr) { - var entry = this.profile_.addLibrary(name, startAddr, endAddr); + name, startAddr, endAddr, aslrSlide) { + var entry = this.profile_.addLibrary(name, startAddr, endAddr, aslrSlide); this.setCodeType(entry.getName(), 'SHARED_LIB'); var self = this; var libFuncs = this.cppEntriesProvider_.parseVmSymbols( - name, startAddr, endAddr, function(fName, fStart, fEnd) { + name, startAddr, endAddr, aslrSlide, function(fName, fStart, fEnd) { self.profile_.addStaticCode(fName, fStart, fEnd); self.setCodeType(fName, 'CPP'); }); @@ -559,7 +559,7 @@ function CppEntriesProvider() { CppEntriesProvider.prototype.parseVmSymbols = function( - libName, libStart, libEnd, processorFunc) { + libName, libStart, libEnd, libASLRSlide, processorFunc) { this.loadSymbols(libName); var prevEntry; @@ -588,6 +588,7 @@ CppEntriesProvider.prototype.parseVmSymbols = function( } else if (funcInfo === false) { break; } + funcInfo.start += libASLRSlide; if (funcInfo.start < libStart && funcInfo.start < libEnd - libStart) { funcInfo.start += libStart; } diff --git a/tools/try_perf.py b/tools/try_perf.py index fbd4036d..5565b808 100755 --- a/tools/try_perf.py +++ b/tools/try_perf.py @@ -44,6 +44,7 @@ PUBLIC_BENCHMARKS = [ 'octane-tf-pr', 'simdjs', 'sunspider', + 'wasm', ] V8_BASE = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) diff --git a/tools/verify_source_deps.py b/tools/verify_source_deps.py index 50caace7..56e31565 100755 --- a/tools/verify_source_deps.py +++ b/tools/verify_source_deps.py @@ -24,10 +24,10 @@ V8_INCLUDE_BASE = os.path.join(V8_BASE, 'include') GYP_FILES = [ os.path.join(V8_BASE, 'src', 'd8.gyp'), + os.path.join(V8_BASE, 'src', 'v8.gyp'), os.path.join(V8_BASE, 'src', 'third_party', 'vtune', 'v8vtune.gyp'), os.path.join(V8_BASE, 'test', 'cctest', 'cctest.gyp'), os.path.join(V8_BASE, 'test', 'unittests', 'unittests.gyp'), - os.path.join(V8_BASE, 'tools', 'gyp', 'v8.gyp'), os.path.join(V8_BASE, 'tools', 'parser-shell.gyp'), ] diff --git a/tools/whitespace.txt b/tools/whitespace.txt index d1395f5d..c571b763 100644 --- a/tools/whitespace.txt +++ b/tools/whitespace.txt @@ -5,4 +5,4 @@ Try to write something funny. And please don't add trailing whitespace. A Smi balks into a war and says: "I'm so deoptimized today!" The doubles heard this and started to unbox. -The Smi looked at them when a crazy v8-autoroll account showed up.. +The Smi looked at them when a crazy v8-autoroll account showed NaN.. |