<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[212616] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/212616">212616</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2017-02-19 14:07:58 -0800 (Sun, 19 Feb 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>Unreviewed, rolling out <a href="http://trac.webkit.org/projects/webkit/changeset/212466">r212466</a>.
https://bugs.webkit.org/show_bug.cgi?id=168577
causes crashes on AArch64 on linux, maybe it's causing crashes
on iOS too (Requested by pizlo on #webkit).
Reverted changeset:
"The collector thread should only start when the mutator
doesn't have heap access"
https://bugs.webkit.org/show_bug.cgi?id=167737
http://trac.webkit.org/changeset/212466</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGWorklistcpp">trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGWorklisth">trunk/Source/JavaScriptCore/dfg/DFGWorklist.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapEdenGCActivityCallbackcpp">trunk/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapFullGCActivityCallbackcpp">trunk/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapInlinesh">trunk/Source/JavaScriptCore/heap/HeapInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapIncrementalSweepercpp">trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapIncrementalSweeperh">trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMachineStackMarkercpp">trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMachineStackMarkerh">trunk/Source/JavaScriptCore/heap/MachineStackMarker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedAllocatorcpp">trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockcpp">trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedSpacecpp">trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMutatorStatecpp">trunk/Source/JavaScriptCore/heap/MutatorState.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMutatorStateh">trunk/Source/JavaScriptCore/heap/MutatorState.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorcpp">trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorh">trunk/Source/JavaScriptCore/heap/SlotVisitor.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapStochasticSpaceTimeMutatorSchedulercpp">trunk/Source/JavaScriptCore/heap/StochasticSpaceTimeMutatorScheduler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITWorklistcpp">trunk/Source/JavaScriptCore/jit/JITWorklist.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeInitializeThreadingcpp">trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCellInlinesh">trunk/Source/JavaScriptCore/runtime/JSCellInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionscpp">trunk/Source/JavaScriptCore/runtime/Options.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeTestRunnerUtilscpp">trunk/Source/JavaScriptCore/runtime/TestRunnerUtils.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfAutomaticThreadcpp">trunk/Source/WTF/wtf/AutomaticThread.cpp</a></li>
<li><a href="#trunkSourceWTFwtfAutomaticThreadh">trunk/Source/WTF/wtf/AutomaticThread.h</a></li>
<li><a href="#trunkSourceWTFwtfNumberOfCorescpp">trunk/Source/WTF/wtf/NumberOfCores.cpp</a></li>
<li><a href="#trunkSourceWTFwtfParallelHelperPoolcpp">trunk/Source/WTF/wtf/ParallelHelperPool.cpp</a></li>
<li><a href="#trunkSourceWTFwtfParallelHelperPoolh">trunk/Source/WTF/wtf/ParallelHelperPool.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsCommonVMcpp">trunk/Source/WebCore/bindings/js/CommonVM.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsidl">trunk/Source/WebCore/testing/Internals.idl</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsScriptsrunjscstresstests">trunk/Tools/Scripts/run-jsc-stress-tests</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreheapHeapStatisticscpp">trunk/Source/JavaScriptCore/heap/HeapStatistics.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapStatisticsh">trunk/Source/JavaScriptCore/heap/HeapStatistics.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHelpingGCScopeh">trunk/Source/JavaScriptCore/heap/HelpingGCScope.h</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkJSTestsstresssplayflashaccess1msjs">trunk/JSTests/stress/splay-flash-access-1ms.js</a></li>
<li><a href="#trunkJSTestsstresssplayflashaccessjs">trunk/JSTests/stress/splay-flash-access.js</a></li>
<li><a href="#trunkLayoutTestsjsdomgcslotvisitorparalleldrainpingsrunloopwhendoneexpectedtxt">trunk/LayoutTests/js/dom/gc-slot-visitor-parallel-drain-pings-runloop-when-done-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsdomgcslotvisitorparalleldrainpingsrunloopwhendonehtml">trunk/LayoutTests/js/dom/gc-slot-visitor-parallel-drain-pings-runloop-when-done.html</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCollectingScopeh">trunk/Source/JavaScriptCore/heap/CollectingScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCollectorPhasecpp">trunk/Source/JavaScriptCore/heap/CollectorPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCollectorPhaseh">trunk/Source/JavaScriptCore/heap/CollectorPhase.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCConductorcpp">trunk/Source/JavaScriptCore/heap/GCConductor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCConductorh">trunk/Source/JavaScriptCore/heap/GCConductor.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCFinalizationCallbackcpp">trunk/Source/JavaScriptCore/heap/GCFinalizationCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCFinalizationCallbackh">trunk/Source/JavaScriptCore/heap/GCFinalizationCallback.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapRegisterStateh">trunk/Source/JavaScriptCore/heap/RegisterState.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapRunningScopeh">trunk/Source/JavaScriptCore/heap/RunningScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSweepingScopeh">trunk/Source/JavaScriptCore/heap/SweepingScope.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapGCFinalizationCallbackh">trunk/Source/WebCore/ForwardingHeaders/heap/GCFinalizationCallback.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapIncrementalSweeperh">trunk/Source/WebCore/ForwardingHeaders/heap/IncrementalSweeper.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapMachineStackMarkerh">trunk/Source/WebCore/ForwardingHeaders/heap/MachineStackMarker.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapRunningScopeh">trunk/Source/WebCore/ForwardingHeaders/heap/RunningScope.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/JSTests/ChangeLog        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2017-02-19 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r212466.
+ https://bugs.webkit.org/show_bug.cgi?id=168577
+
+ causes crashes on AArch64 on linux, maybe it's causing crashes
+ on iOS too (Requested by pizlo on #webkit).
+
+ Reverted changeset:
+
+ "The collector thread should only start when the mutator
+ doesn't have heap access"
+ https://bugs.webkit.org/show_bug.cgi?id=167737
+ http://trac.webkit.org/changeset/212466
+
</ins><span class="cx"> 2017-02-10 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> The collector thread should only start when the mutator doesn't have heap access
</span></span></pre></div>
<a id="trunkJSTestsstresssplayflashaccess1msjs"></a>
<div class="delfile"><h4>Deleted: trunk/JSTests/stress/splay-flash-access-1ms.js (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/splay-flash-access-1ms.js        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/JSTests/stress/splay-flash-access-1ms.js        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,902 +0,0 @@
</span><del>-//@ runNoisyTestDefault
-//@ runNoisyTestNoCJIT
-
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Copyright (C) 2015 Apple Inc. 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.
-
-
-// Performance.now is used in latency benchmarks, the fallback is Date.now.
-var performance = performance || {};
-performance.now = (function() {
- return performance.now ||
- performance.mozNow ||
- performance.msNow ||
- performance.oNow ||
- performance.webkitNow ||
- Date.now;
-})();
-
-// Simple framework for running the benchmark suites and
-// computing a score based on the timing measurements.
-
-
-// A benchmark has a name (string) and a function that will be run to
-// do the performance measurement. The optional setup and tearDown
-// arguments are functions that will be invoked before and after
-// running the benchmark, but the running time of these functions will
-// not be accounted for in the benchmark score.
-function Benchmark(name, doWarmup, doDeterministic, run, setup, tearDown, latencyResult, minIterations) {
- this.name = name;
- this.doWarmup = doWarmup;
- this.doDeterministic = doDeterministic;
- this.run = run;
- this.Setup = setup ? setup : function() { };
- this.TearDown = tearDown ? tearDown : function() { };
- this.latencyResult = latencyResult ? latencyResult : null;
- this.minIterations = minIterations ? minIterations : 32;
-}
-
-
-// Benchmark results hold the benchmark and the measured time used to
-// run the benchmark. The benchmark score is computed later once a
-// full benchmark suite has run to completion. If latency is set to 0
-// then there is no latency score for this benchmark.
-function BenchmarkResult(benchmark, time, latency) {
- this.benchmark = benchmark;
- this.time = time;
- this.latency = latency;
-}
-
-
-// Automatically convert results to numbers. Used by the geometric
-// mean computation.
-BenchmarkResult.prototype.valueOf = function() {
- return this.time;
-}
-
-
-// Suites of benchmarks consist of a name and the set of benchmarks in
-// addition to the reference timing that the final score will be based
-// on. This way, all scores are relative to a reference run and higher
-// scores implies better performance.
-function BenchmarkSuite(name, reference, benchmarks) {
- this.name = name;
- this.reference = reference;
- this.benchmarks = benchmarks;
- BenchmarkSuite.suites.push(this);
-}
-
-
-// Keep track of all declared benchmark suites.
-BenchmarkSuite.suites = [];
-
-// Scores are not comparable across versions. Bump the version if
-// you're making changes that will affect that scores, e.g. if you add
-// a new benchmark or change an existing one.
-BenchmarkSuite.version = '9';
-
-// Override the alert function to throw an exception instead.
-alert = function(s) {
- throw "Alert called with argument: " + s;
-};
-
-
-// To make the benchmark results predictable, we replace Math.random
-// with a 100% deterministic alternative.
-BenchmarkSuite.ResetRNG = function() {
- Math.random = (function() {
- var seed = 49734321;
- return function() {
- // Robert Jenkins' 32 bit integer hash function.
- seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff;
- seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
- seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
- seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
- seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
- seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
- return (seed & 0xfffffff) / 0x10000000;
- };
- })();
-}
-
-
-// Runs all registered benchmark suites and optionally yields between
-// each individual benchmark to avoid running for too long in the
-// context of browsers. Once done, the final score is reported to the
-// runner.
-BenchmarkSuite.RunSuites = function(runner) {
- var continuation = null;
- var suites = BenchmarkSuite.suites;
- var length = suites.length;
- BenchmarkSuite.scores = [];
- var index = 0;
- function RunStep() {
- while (continuation || index < length) {
- if (continuation) {
- continuation = continuation();
- } else {
- var suite = suites[index++];
- if (runner.NotifyStart) runner.NotifyStart(suite.name);
- continuation = suite.RunStep(runner);
- }
- if (continuation && typeof window != 'undefined' && window.setTimeout) {
- window.setTimeout(RunStep, 25);
- return;
- }
- }
-
- // show final result
- if (runner.NotifyScore) {
- var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores);
- var formatted = BenchmarkSuite.FormatScore(100 * score);
- runner.NotifyScore(formatted);
- }
- }
- RunStep();
-}
-
-
-// Counts the total number of registered benchmarks. Useful for
-// showing progress as a percentage.
-BenchmarkSuite.CountBenchmarks = function() {
- var result = 0;
- var suites = BenchmarkSuite.suites;
- for (var i = 0; i < suites.length; i++) {
- result += suites[i].benchmarks.length;
- }
- return result;
-}
-
-
-// Computes the geometric mean of a set of numbers.
-BenchmarkSuite.GeometricMean = function(numbers) {
- var log = 0;
- for (var i = 0; i < numbers.length; i++) {
- log += Math.log(numbers[i]);
- }
- return Math.pow(Math.E, log / numbers.length);
-}
-
-
-// Computes the geometric mean of a set of throughput time measurements.
-BenchmarkSuite.GeometricMeanTime = function(measurements) {
- var log = 0;
- for (var i = 0; i < measurements.length; i++) {
- log += Math.log(measurements[i].time);
- }
- return Math.pow(Math.E, log / measurements.length);
-}
-
-
-// Computes the average of the worst samples. For example, if percentile is 99, this will report the
-// average of the worst 1% of the samples.
-BenchmarkSuite.AverageAbovePercentile = function(numbers, percentile) {
- // Don't change the original array.
- numbers = numbers.slice();
-
- // Sort in ascending order.
- numbers.sort(function(a, b) { return a - b; });
-
- // Now the elements we want are at the end. Keep removing them until the array size shrinks too much.
- // Examples assuming percentile = 99:
- //
- // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore,
- // since then numbers.length / originalLength = 0.99.
- //
- // - numbers.length starts at 1000: we will remove the ten worst.
- //
- // - numbers.length starts at 10: we will remove just the worst.
- var numbersWeWant = [];
- var originalLength = numbers.length;
- while (numbers.length / originalLength > percentile / 100)
- numbersWeWant.push(numbers.pop());
-
- var sum = 0;
- for (var i = 0; i < numbersWeWant.length; ++i)
- sum += numbersWeWant[i];
-
- var result = sum / numbersWeWant.length;
-
- // Do a sanity check.
- if (numbers.length && result < numbers[numbers.length - 1]) {
- throw "Sanity check fail: the worst case result is " + result +
- " but we didn't take into account " + numbers;
- }
-
- return result;
-}
-
-
-// Computes the geometric mean of a set of latency measurements.
-BenchmarkSuite.GeometricMeanLatency = function(measurements) {
- var log = 0;
- var hasLatencyResult = false;
- for (var i = 0; i < measurements.length; i++) {
- if (measurements[i].latency != 0) {
- log += Math.log(measurements[i].latency);
- hasLatencyResult = true;
- }
- }
- if (hasLatencyResult) {
- return Math.pow(Math.E, log / measurements.length);
- } else {
- return 0;
- }
-}
-
-
-// Converts a score value to a string with at least three significant
-// digits.
-BenchmarkSuite.FormatScore = function(value) {
- if (value > 100) {
- return value.toFixed(0);
- } else {
- return value.toPrecision(3);
- }
-}
-
-// Notifies the runner that we're done running a single benchmark in
-// the benchmark suite. This can be useful to report progress.
-BenchmarkSuite.prototype.NotifyStep = function(result) {
- this.results.push(result);
- if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name);
-}
-
-
-// Notifies the runner that we're done with running a suite and that
-// we have a result which can be reported to the user if needed.
-BenchmarkSuite.prototype.NotifyResult = function() {
- var mean = BenchmarkSuite.GeometricMeanTime(this.results);
- var score = this.reference[0] / mean;
- BenchmarkSuite.scores.push(score);
- if (this.runner.NotifyResult) {
- var formatted = BenchmarkSuite.FormatScore(100 * score);
- this.runner.NotifyResult(this.name, formatted);
- }
- if (this.reference.length == 2) {
- var meanLatency = BenchmarkSuite.GeometricMeanLatency(this.results);
- if (meanLatency != 0) {
- var scoreLatency = this.reference[1] / meanLatency;
- BenchmarkSuite.scores.push(scoreLatency);
- if (this.runner.NotifyResult) {
- var formattedLatency = BenchmarkSuite.FormatScore(100 * scoreLatency)
- this.runner.NotifyResult(this.name + "Latency", formattedLatency);
- }
- }
- }
-}
-
-
-// Notifies the runner that running a benchmark resulted in an error.
-BenchmarkSuite.prototype.NotifyError = function(error) {
- if (this.runner.NotifyError) {
- this.runner.NotifyError(this.name, error);
- }
- if (this.runner.NotifyStep) {
- this.runner.NotifyStep(this.name);
- }
-}
-
-
-// Runs a single benchmark for at least a second and computes the
-// average time it takes to run a single iteration.
-BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) {
- function Measure(data) {
- var elapsed = 0;
- var start = new Date();
-
- // Run either for 1 second or for the number of iterations specified
- // by minIterations, depending on the config flag doDeterministic.
- for (var i = 0; (benchmark.doDeterministic ?
- i<benchmark.minIterations : elapsed < 1000); i++) {
- benchmark.run();
- elapsed = new Date() - start;
- }
- if (data != null) {
- data.runs += i;
- data.elapsed += elapsed;
- }
- }
-
- // Sets up data in order to skip or not the warmup phase.
- if (!benchmark.doWarmup && data == null) {
- data = { runs: 0, elapsed: 0 };
- }
-
- if (data == null) {
- Measure(null);
- return { runs: 0, elapsed: 0 };
- } else {
- Measure(data);
- // If we've run too few iterations, we continue for another second.
- if (data.runs < benchmark.minIterations) return data;
- var usec = (data.elapsed * 1000) / data.runs;
- var latencySamples = (benchmark.latencyResult != null) ? benchmark.latencyResult() : [0];
- var percentile = 99.5;
- var latency = BenchmarkSuite.AverageAbovePercentile(latencySamples, percentile) * 1000;
- this.NotifyStep(new BenchmarkResult(benchmark, usec, latency));
- return null;
- }
-}
-
-
-// This function starts running a suite, but stops between each
-// individual benchmark in the suite and returns a continuation
-// function which can be invoked to run the next benchmark. Once the
-// last benchmark has been executed, null is returned.
-BenchmarkSuite.prototype.RunStep = function(runner) {
- BenchmarkSuite.ResetRNG();
- this.results = [];
- this.runner = runner;
- var length = this.benchmarks.length;
- var index = 0;
- var suite = this;
- var data;
-
- // Run the setup, the actual benchmark, and the tear down in three
- // separate steps to allow the framework to yield between any of the
- // steps.
-
- function RunNextSetup() {
- if (index < length) {
- try {
- suite.benchmarks[index].Setup();
- } catch (e) {
- suite.NotifyError(e);
- return null;
- }
- return RunNextBenchmark;
- }
- suite.NotifyResult();
- return null;
- }
-
- function RunNextBenchmark() {
- try {
- data = suite.RunSingleBenchmark(suite.benchmarks[index], data);
- } catch (e) {
- suite.NotifyError(e);
- return null;
- }
- // If data is null, we're done with this benchmark.
- return (data == null) ? RunNextTearDown : RunNextBenchmark();
- }
-
- function RunNextTearDown() {
- try {
- suite.benchmarks[index++].TearDown();
- } catch (e) {
- suite.NotifyError(e);
- return null;
- }
- return RunNextSetup;
- }
-
- // Start out running the setup.
- return RunNextSetup();
-}
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Copyright (C) 2015 Apple Inc. 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.
-
-// This benchmark is based on a JavaScript log processing module used
-// by the V8 profiler to generate execution time profiles for runs of
-// JavaScript applications, and it effectively measures how fast the
-// JavaScript engine is at allocating nodes and reclaiming the memory
-// used for old nodes. Because of the way splay trees work, the engine
-// also has to deal with a lot of changes to the large tree object
-// graph.
-
-var Splay = new BenchmarkSuite('Splay', [81491, 2739514], [
- new Benchmark("Splay", true, false,
- SplayRun, SplaySetup, SplayTearDown, SplayLatency)
-]);
-
-
-// Configuration.
-var kSplayTreeSize = 8000;
-var kSplayTreeModifications = 80;
-var kSplayTreePayloadDepth = 5;
-
-var splayTree = null;
-var splaySampleTimeStart = 0.0;
-
-function GeneratePayloadTree(depth, tag) {
- if (depth == 0) {
- return {
- array : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
- string : 'String for key ' + tag + ' in leaf node'
- };
- } else {
- return {
- left: GeneratePayloadTree(depth - 1, tag),
- right: GeneratePayloadTree(depth - 1, tag)
- };
- }
-}
-
-
-function GenerateKey() {
- // The benchmark framework guarantees that Math.random is
- // deterministic; see base.js.
- return Math.random();
-}
-
-var splaySamples = [];
-
-function SplayLatency() {
- return splaySamples;
-}
-
-function SplayUpdateStats(time) {
- var pause = time - splaySampleTimeStart;
- splaySampleTimeStart = time;
- splaySamples.push(pause);
-}
-
-function InsertNewNode() {
- // Insert new node with a unique key.
- var key;
- do {
- key = GenerateKey();
- } while (splayTree.find(key) != null);
- var payload = GeneratePayloadTree(kSplayTreePayloadDepth, String(key));
- splayTree.insert(key, payload);
- return key;
-}
-
-
-function SplaySetup() {
- // Check if the platform has the performance.now high resolution timer.
- // If not, throw exception and quit.
- if (!performance.now) {
- throw "PerformanceNowUnsupported";
- }
-
- splayTree = new SplayTree();
- splaySampleTimeStart = performance.now()
- for (var i = 0; i < kSplayTreeSize; i++) {
- InsertNewNode();
- if ((i+1) % 20 == 19) {
- SplayUpdateStats(performance.now());
- }
- }
-}
-
-
-function SplayTearDown() {
- // Allow the garbage collector to reclaim the memory
- // used by the splay tree no matter how we exit the
- // tear down function.
- var keys = splayTree.exportKeys();
- splayTree = null;
-
- splaySamples = [];
-
- // Verify that the splay tree has the right size.
- var length = keys.length;
- if (length != kSplayTreeSize) {
- throw new Error("Splay tree has wrong size");
- }
-
- // Verify that the splay tree has sorted, unique keys.
- for (var i = 0; i < length - 1; i++) {
- if (keys[i] >= keys[i + 1]) {
- throw new Error("Splay tree not sorted");
- }
- }
-}
-
-
-function SplayRun() {
- // Replace a few nodes in the splay tree.
- for (var i = 0; i < kSplayTreeModifications; i++) {
- var key = InsertNewNode();
- var greatest = splayTree.findGreatestLessThan(key);
- if (greatest == null) splayTree.remove(key);
- else splayTree.remove(greatest.key);
- }
- SplayUpdateStats(performance.now());
-}
-
-
-/**
- * Constructs a Splay tree. A splay tree is a self-balancing binary
- * search tree with the additional property that recently accessed
- * elements are quick to access again. It performs basic operations
- * such as insertion, look-up and removal in O(log(n)) amortized time.
- *
- * @constructor
- */
-function SplayTree() {
-};
-
-
-/**
- * Pointer to the root node of the tree.
- *
- * @type {SplayTree.Node}
- * @private
- */
-SplayTree.prototype.root_ = null;
-
-
-/**
- * @return {boolean} Whether the tree is empty.
- */
-SplayTree.prototype.isEmpty = function() {
- return !this.root_;
-};
-
-
-/**
- * Inserts a node into the tree with the specified key and value if
- * the tree does not already contain a node with the specified key. If
- * the value is inserted, it becomes the root of the tree.
- *
- * @param {number} key Key to insert into the tree.
- * @param {*} value Value to insert into the tree.
- */
-SplayTree.prototype.insert = function(key, value) {
- if (this.isEmpty()) {
- this.root_ = new SplayTree.Node(key, value);
- return;
- }
- // Splay on the key to move the last node on the search path for
- // the key to the root of the tree.
- this.splay_(key);
- if (this.root_.key == key) {
- return;
- }
- var node = new SplayTree.Node(key, value);
- if (key > this.root_.key) {
- node.left = this.root_;
- node.right = this.root_.right;
- this.root_.right = null;
- } else {
- node.right = this.root_;
- node.left = this.root_.left;
- this.root_.left = null;
- }
- this.root_ = node;
-};
-
-
-/**
- * Removes a node with the specified key from the tree if the tree
- * contains a node with this key. The removed node is returned. If the
- * key is not found, an exception is thrown.
- *
- * @param {number} key Key to find and remove from the tree.
- * @return {SplayTree.Node} The removed node.
- */
-SplayTree.prototype.remove = function(key) {
- if (this.isEmpty()) {
- throw Error('Key not found: ' + key);
- }
- this.splay_(key);
- if (this.root_.key != key) {
- throw Error('Key not found: ' + key);
- }
- var removed = this.root_;
- if (!this.root_.left) {
- this.root_ = this.root_.right;
- } else {
- var right = this.root_.right;
- this.root_ = this.root_.left;
- // Splay to make sure that the new root has an empty right child.
- this.splay_(key);
- // Insert the original right child as the right child of the new
- // root.
- this.root_.right = right;
- }
- return removed;
-};
-
-
-/**
- * Returns the node having the specified key or null if the tree doesn't contain
- * a node with the specified key.
- *
- * @param {number} key Key to find in the tree.
- * @return {SplayTree.Node} Node having the specified key.
- */
-SplayTree.prototype.find = function(key) {
- if (this.isEmpty()) {
- return null;
- }
- this.splay_(key);
- return this.root_.key == key ? this.root_ : null;
-};
-
-
-/**
- * @return {SplayTree.Node} Node having the maximum key value.
- */
-SplayTree.prototype.findMax = function(opt_startNode) {
- if (this.isEmpty()) {
- return null;
- }
- var current = opt_startNode || this.root_;
- while (current.right) {
- current = current.right;
- }
- return current;
-};
-
-
-/**
- * @return {SplayTree.Node} Node having the maximum key value that
- * is less than the specified key value.
- */
-SplayTree.prototype.findGreatestLessThan = function(key) {
- if (this.isEmpty()) {
- return null;
- }
- // Splay on the key to move the node with the given key or the last
- // node on the search path to the top of the tree.
- this.splay_(key);
- // Now the result is either the root node or the greatest node in
- // the left subtree.
- if (this.root_.key < key) {
- return this.root_;
- } else if (this.root_.left) {
- return this.findMax(this.root_.left);
- } else {
- return null;
- }
-};
-
-
-/**
- * @return {Array<*>} An array containing all the keys of tree's nodes.
- */
-SplayTree.prototype.exportKeys = function() {
- var result = [];
- if (!this.isEmpty()) {
- this.root_.traverse_(function(node) { result.push(node.key); });
- }
- return result;
-};
-
-
-/**
- * Perform the splay operation for the given key. Moves the node with
- * the given key to the top of the tree. If no node has the given
- * key, the last node on the search path is moved to the top of the
- * tree. This is the simplified top-down splaying algorithm from:
- * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
- *
- * @param {number} key Key to splay the tree on.
- * @private
- */
-SplayTree.prototype.splay_ = function(key) {
- if (this.isEmpty()) {
- return;
- }
- // Create a dummy node. The use of the dummy node is a bit
- // counter-intuitive: The right child of the dummy node will hold
- // the L tree of the algorithm. The left child of the dummy node
- // will hold the R tree of the algorithm. Using a dummy node, left
- // and right will always be nodes and we avoid special cases.
- var dummy, left, right;
- dummy = left = right = new SplayTree.Node(null, null);
- var current = this.root_;
- while (true) {
- if (key < current.key) {
- if (!current.left) {
- break;
- }
- if (key < current.left.key) {
- // Rotate right.
- var tmp = current.left;
- current.left = tmp.right;
- tmp.right = current;
- current = tmp;
- if (!current.left) {
- break;
- }
- }
- // Link right.
- right.left = current;
- right = current;
- current = current.left;
- } else if (key > current.key) {
- if (!current.right) {
- break;
- }
- if (key > current.right.key) {
- // Rotate left.
- var tmp = current.right;
- current.right = tmp.left;
- tmp.left = current;
- current = tmp;
- if (!current.right) {
- break;
- }
- }
- // Link left.
- left.right = current;
- left = current;
- current = current.right;
- } else {
- break;
- }
- }
- // Assemble.
- left.right = current.left;
- right.left = current.right;
- current.left = dummy.right;
- current.right = dummy.left;
- this.root_ = current;
-};
-
-
-/**
- * Constructs a Splay tree node.
- *
- * @param {number} key Key.
- * @param {*} value Value.
- */
-SplayTree.Node = function(key, value) {
- this.key = key;
- this.value = value;
-};
-
-
-/**
- * @type {SplayTree.Node}
- */
-SplayTree.Node.prototype.left = null;
-
-
-/**
- * @type {SplayTree.Node}
- */
-SplayTree.Node.prototype.right = null;
-
-
-/**
- * Performs an ordered traversal of the subtree starting at
- * this SplayTree.Node.
- *
- * @param {function(SplayTree.Node)} f Visitor function.
- * @private
- */
-SplayTree.Node.prototype.traverse_ = function(f) {
- var current = this;
- while (current) {
- var left = current.left;
- if (left) left.traverse_(f);
- f(current);
- current = current.right;
- }
-};
-function jscSetUp() {
- SplaySetup();
-}
-
-function jscTearDown() {
- SplayTearDown();
-}
-
-function jscRun() {
- SplayRun();
-}
-
-jscSetUp();
-var __before = preciseTime();
-var times = [];
-for (var i = 0; i < 2000; ++i) {
- var _before = preciseTime();
- jscRun();
- var _after = preciseTime();
- times.push(_after - _before);
- flashHeapAccess(1);
-}
-var __after = preciseTime();
-jscTearDown();
-
-function averageAbovePercentile(numbers, percentile) {
- // Don't change the original array.
- numbers = numbers.slice();
-
- // Sort in ascending order.
- numbers.sort(function(a, b) { return a - b; });
-
- // Now the elements we want are at the end. Keep removing them until the array size shrinks too much.
- // Examples assuming percentile = 99:
- //
- // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore,
- // since then numbers.length / originalLength = 0.99.
- //
- // - numbers.length starts at 1000: we will remove the ten worst.
- //
- // - numbers.length starts at 10: we will remove just the worst.
- var numbersWeWant = [];
- var originalLength = numbers.length;
- while (numbers.length / originalLength > percentile / 100)
- numbersWeWant.push(numbers.pop());
-
- var sum = 0;
- for (var i = 0; i < numbersWeWant.length; ++i)
- sum += numbersWeWant[i];
-
- var result = sum / numbersWeWant.length;
-
- // Do a sanity check.
- if (numbers.length && result < numbers[numbers.length - 1]) {
- throw "Sanity check fail: the worst case result is " + result +
- " but we didn't take into account " + numbers;
- }
-
- return result;
-}
-
-print("That took " + (__after - __before) * 1000 + " ms.");
-
-function printPercentile(percentile)
-{
- print("Above " + percentile + "%: " + averageAbovePercentile(times, percentile) * 1000 + " ms.");
-}
-
-printPercentile(99.9);
-printPercentile(99.5);
-printPercentile(99);
-printPercentile(97.5);
-printPercentile(95);
-printPercentile(90);
-printPercentile(75);
-printPercentile(50);
-printPercentile(0);
-
-gc();
</del></span></pre></div>
<a id="trunkJSTestsstresssplayflashaccessjs"></a>
<div class="delfile"><h4>Deleted: trunk/JSTests/stress/splay-flash-access.js (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/splay-flash-access.js        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/JSTests/stress/splay-flash-access.js        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,903 +0,0 @@
</span><del>-//@ runNoisyTestDefault
-//@ runNoisyTestNoCJIT
-
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Copyright (C) 2015 Apple Inc. 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.
-
-
-// Performance.now is used in latency benchmarks, the fallback is Date.now.
-var performance = performance || {};
-performance.now = (function() {
- return performance.now ||
- performance.mozNow ||
- performance.msNow ||
- performance.oNow ||
- performance.webkitNow ||
- Date.now;
-})();
-
-// Simple framework for running the benchmark suites and
-// computing a score based on the timing measurements.
-
-
-// A benchmark has a name (string) and a function that will be run to
-// do the performance measurement. The optional setup and tearDown
-// arguments are functions that will be invoked before and after
-// running the benchmark, but the running time of these functions will
-// not be accounted for in the benchmark score.
-function Benchmark(name, doWarmup, doDeterministic, run, setup, tearDown, latencyResult, minIterations) {
- this.name = name;
- this.doWarmup = doWarmup;
- this.doDeterministic = doDeterministic;
- this.run = run;
- this.Setup = setup ? setup : function() { };
- this.TearDown = tearDown ? tearDown : function() { };
- this.latencyResult = latencyResult ? latencyResult : null;
- this.minIterations = minIterations ? minIterations : 32;
-}
-
-
-// Benchmark results hold the benchmark and the measured time used to
-// run the benchmark. The benchmark score is computed later once a
-// full benchmark suite has run to completion. If latency is set to 0
-// then there is no latency score for this benchmark.
-function BenchmarkResult(benchmark, time, latency) {
- this.benchmark = benchmark;
- this.time = time;
- this.latency = latency;
-}
-
-
-// Automatically convert results to numbers. Used by the geometric
-// mean computation.
-BenchmarkResult.prototype.valueOf = function() {
- return this.time;
-}
-
-
-// Suites of benchmarks consist of a name and the set of benchmarks in
-// addition to the reference timing that the final score will be based
-// on. This way, all scores are relative to a reference run and higher
-// scores implies better performance.
-function BenchmarkSuite(name, reference, benchmarks) {
- this.name = name;
- this.reference = reference;
- this.benchmarks = benchmarks;
- BenchmarkSuite.suites.push(this);
-}
-
-
-// Keep track of all declared benchmark suites.
-BenchmarkSuite.suites = [];
-
-// Scores are not comparable across versions. Bump the version if
-// you're making changes that will affect that scores, e.g. if you add
-// a new benchmark or change an existing one.
-BenchmarkSuite.version = '9';
-
-// Override the alert function to throw an exception instead.
-alert = function(s) {
- throw "Alert called with argument: " + s;
-};
-
-
-// To make the benchmark results predictable, we replace Math.random
-// with a 100% deterministic alternative.
-BenchmarkSuite.ResetRNG = function() {
- Math.random = (function() {
- var seed = 49734321;
- return function() {
- // Robert Jenkins' 32 bit integer hash function.
- seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff;
- seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
- seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
- seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
- seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
- seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
- return (seed & 0xfffffff) / 0x10000000;
- };
- })();
-}
-
-
-// Runs all registered benchmark suites and optionally yields between
-// each individual benchmark to avoid running for too long in the
-// context of browsers. Once done, the final score is reported to the
-// runner.
-BenchmarkSuite.RunSuites = function(runner) {
- var continuation = null;
- var suites = BenchmarkSuite.suites;
- var length = suites.length;
- BenchmarkSuite.scores = [];
- var index = 0;
- function RunStep() {
- while (continuation || index < length) {
- if (continuation) {
- continuation = continuation();
- } else {
- var suite = suites[index++];
- if (runner.NotifyStart) runner.NotifyStart(suite.name);
- continuation = suite.RunStep(runner);
- }
- if (continuation && typeof window != 'undefined' && window.setTimeout) {
- window.setTimeout(RunStep, 25);
- return;
- }
- }
-
- // show final result
- if (runner.NotifyScore) {
- var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores);
- var formatted = BenchmarkSuite.FormatScore(100 * score);
- runner.NotifyScore(formatted);
- }
- }
- RunStep();
-}
-
-
-// Counts the total number of registered benchmarks. Useful for
-// showing progress as a percentage.
-BenchmarkSuite.CountBenchmarks = function() {
- var result = 0;
- var suites = BenchmarkSuite.suites;
- for (var i = 0; i < suites.length; i++) {
- result += suites[i].benchmarks.length;
- }
- return result;
-}
-
-
-// Computes the geometric mean of a set of numbers.
-BenchmarkSuite.GeometricMean = function(numbers) {
- var log = 0;
- for (var i = 0; i < numbers.length; i++) {
- log += Math.log(numbers[i]);
- }
- return Math.pow(Math.E, log / numbers.length);
-}
-
-
-// Computes the geometric mean of a set of throughput time measurements.
-BenchmarkSuite.GeometricMeanTime = function(measurements) {
- var log = 0;
- for (var i = 0; i < measurements.length; i++) {
- log += Math.log(measurements[i].time);
- }
- return Math.pow(Math.E, log / measurements.length);
-}
-
-
-// Computes the average of the worst samples. For example, if percentile is 99, this will report the
-// average of the worst 1% of the samples.
-BenchmarkSuite.AverageAbovePercentile = function(numbers, percentile) {
- // Don't change the original array.
- numbers = numbers.slice();
-
- // Sort in ascending order.
- numbers.sort(function(a, b) { return a - b; });
-
- // Now the elements we want are at the end. Keep removing them until the array size shrinks too much.
- // Examples assuming percentile = 99:
- //
- // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore,
- // since then numbers.length / originalLength = 0.99.
- //
- // - numbers.length starts at 1000: we will remove the ten worst.
- //
- // - numbers.length starts at 10: we will remove just the worst.
- var numbersWeWant = [];
- var originalLength = numbers.length;
- while (numbers.length / originalLength > percentile / 100)
- numbersWeWant.push(numbers.pop());
-
- var sum = 0;
- for (var i = 0; i < numbersWeWant.length; ++i)
- sum += numbersWeWant[i];
-
- var result = sum / numbersWeWant.length;
-
- // Do a sanity check.
- if (numbers.length && result < numbers[numbers.length - 1]) {
- throw "Sanity check fail: the worst case result is " + result +
- " but we didn't take into account " + numbers;
- }
-
- return result;
-}
-
-
-// Computes the geometric mean of a set of latency measurements.
-BenchmarkSuite.GeometricMeanLatency = function(measurements) {
- var log = 0;
- var hasLatencyResult = false;
- for (var i = 0; i < measurements.length; i++) {
- if (measurements[i].latency != 0) {
- log += Math.log(measurements[i].latency);
- hasLatencyResult = true;
- }
- }
- if (hasLatencyResult) {
- return Math.pow(Math.E, log / measurements.length);
- } else {
- return 0;
- }
-}
-
-
-// Converts a score value to a string with at least three significant
-// digits.
-BenchmarkSuite.FormatScore = function(value) {
- if (value > 100) {
- return value.toFixed(0);
- } else {
- return value.toPrecision(3);
- }
-}
-
-// Notifies the runner that we're done running a single benchmark in
-// the benchmark suite. This can be useful to report progress.
-BenchmarkSuite.prototype.NotifyStep = function(result) {
- this.results.push(result);
- if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name);
-}
-
-
-// Notifies the runner that we're done with running a suite and that
-// we have a result which can be reported to the user if needed.
-BenchmarkSuite.prototype.NotifyResult = function() {
- var mean = BenchmarkSuite.GeometricMeanTime(this.results);
- var score = this.reference[0] / mean;
- BenchmarkSuite.scores.push(score);
- if (this.runner.NotifyResult) {
- var formatted = BenchmarkSuite.FormatScore(100 * score);
- this.runner.NotifyResult(this.name, formatted);
- }
- if (this.reference.length == 2) {
- var meanLatency = BenchmarkSuite.GeometricMeanLatency(this.results);
- if (meanLatency != 0) {
- var scoreLatency = this.reference[1] / meanLatency;
- BenchmarkSuite.scores.push(scoreLatency);
- if (this.runner.NotifyResult) {
- var formattedLatency = BenchmarkSuite.FormatScore(100 * scoreLatency)
- this.runner.NotifyResult(this.name + "Latency", formattedLatency);
- }
- }
- }
-}
-
-
-// Notifies the runner that running a benchmark resulted in an error.
-BenchmarkSuite.prototype.NotifyError = function(error) {
- if (this.runner.NotifyError) {
- this.runner.NotifyError(this.name, error);
- }
- if (this.runner.NotifyStep) {
- this.runner.NotifyStep(this.name);
- }
-}
-
-
-// Runs a single benchmark for at least a second and computes the
-// average time it takes to run a single iteration.
-BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) {
- function Measure(data) {
- var elapsed = 0;
- var start = new Date();
-
- // Run either for 1 second or for the number of iterations specified
- // by minIterations, depending on the config flag doDeterministic.
- for (var i = 0; (benchmark.doDeterministic ?
- i<benchmark.minIterations : elapsed < 1000); i++) {
- benchmark.run();
- elapsed = new Date() - start;
- }
- if (data != null) {
- data.runs += i;
- data.elapsed += elapsed;
- }
- }
-
- // Sets up data in order to skip or not the warmup phase.
- if (!benchmark.doWarmup && data == null) {
- data = { runs: 0, elapsed: 0 };
- }
-
- if (data == null) {
- Measure(null);
- return { runs: 0, elapsed: 0 };
- } else {
- Measure(data);
- // If we've run too few iterations, we continue for another second.
- if (data.runs < benchmark.minIterations) return data;
- var usec = (data.elapsed * 1000) / data.runs;
- var latencySamples = (benchmark.latencyResult != null) ? benchmark.latencyResult() : [0];
- var percentile = 99.5;
- var latency = BenchmarkSuite.AverageAbovePercentile(latencySamples, percentile) * 1000;
- this.NotifyStep(new BenchmarkResult(benchmark, usec, latency));
- return null;
- }
-}
-
-
-// This function starts running a suite, but stops between each
-// individual benchmark in the suite and returns a continuation
-// function which can be invoked to run the next benchmark. Once the
-// last benchmark has been executed, null is returned.
-BenchmarkSuite.prototype.RunStep = function(runner) {
- BenchmarkSuite.ResetRNG();
- this.results = [];
- this.runner = runner;
- var length = this.benchmarks.length;
- var index = 0;
- var suite = this;
- var data;
-
- // Run the setup, the actual benchmark, and the tear down in three
- // separate steps to allow the framework to yield between any of the
- // steps.
-
- function RunNextSetup() {
- if (index < length) {
- try {
- suite.benchmarks[index].Setup();
- } catch (e) {
- suite.NotifyError(e);
- return null;
- }
- return RunNextBenchmark;
- }
- suite.NotifyResult();
- return null;
- }
-
- function RunNextBenchmark() {
- try {
- data = suite.RunSingleBenchmark(suite.benchmarks[index], data);
- } catch (e) {
- suite.NotifyError(e);
- return null;
- }
- // If data is null, we're done with this benchmark.
- return (data == null) ? RunNextTearDown : RunNextBenchmark();
- }
-
- function RunNextTearDown() {
- try {
- suite.benchmarks[index++].TearDown();
- } catch (e) {
- suite.NotifyError(e);
- return null;
- }
- return RunNextSetup;
- }
-
- // Start out running the setup.
- return RunNextSetup();
-}
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Copyright (C) 2015 Apple Inc. 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.
-
-// This benchmark is based on a JavaScript log processing module used
-// by the V8 profiler to generate execution time profiles for runs of
-// JavaScript applications, and it effectively measures how fast the
-// JavaScript engine is at allocating nodes and reclaiming the memory
-// used for old nodes. Because of the way splay trees work, the engine
-// also has to deal with a lot of changes to the large tree object
-// graph.
-
-var Splay = new BenchmarkSuite('Splay', [81491, 2739514], [
- new Benchmark("Splay", true, false,
- SplayRun, SplaySetup, SplayTearDown, SplayLatency)
-]);
-
-
-// Configuration.
-var kSplayTreeSize = 8000;
-var kSplayTreeModifications = 80;
-var kSplayTreePayloadDepth = 5;
-
-var splayTree = null;
-var splaySampleTimeStart = 0.0;
-
-function GeneratePayloadTree(depth, tag) {
- if (depth == 0) {
- return {
- array : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
- string : 'String for key ' + tag + ' in leaf node'
- };
- } else {
- return {
- left: GeneratePayloadTree(depth - 1, tag),
- right: GeneratePayloadTree(depth - 1, tag)
- };
- }
-}
-
-
-function GenerateKey() {
- // The benchmark framework guarantees that Math.random is
- // deterministic; see base.js.
- return Math.random();
-}
-
-var splaySamples = [];
-
-function SplayLatency() {
- return splaySamples;
-}
-
-function SplayUpdateStats(time) {
- var pause = time - splaySampleTimeStart;
- splaySampleTimeStart = time;
- splaySamples.push(pause);
-}
-
-function InsertNewNode() {
- // Insert new node with a unique key.
- var key;
- do {
- key = GenerateKey();
- } while (splayTree.find(key) != null);
- var payload = GeneratePayloadTree(kSplayTreePayloadDepth, String(key));
- splayTree.insert(key, payload);
- return key;
-}
-
-
-function SplaySetup() {
- // Check if the platform has the performance.now high resolution timer.
- // If not, throw exception and quit.
- if (!performance.now) {
- throw "PerformanceNowUnsupported";
- }
-
- splayTree = new SplayTree();
- splaySampleTimeStart = performance.now()
- for (var i = 0; i < kSplayTreeSize; i++) {
- InsertNewNode();
- if ((i+1) % 20 == 19) {
- SplayUpdateStats(performance.now());
- }
- }
-}
-
-
-function SplayTearDown() {
- // Allow the garbage collector to reclaim the memory
- // used by the splay tree no matter how we exit the
- // tear down function.
- var keys = splayTree.exportKeys();
- splayTree = null;
-
- splaySamples = [];
-
- // Verify that the splay tree has the right size.
- var length = keys.length;
- if (length != kSplayTreeSize) {
- throw new Error("Splay tree has wrong size");
- }
-
- // Verify that the splay tree has sorted, unique keys.
- for (var i = 0; i < length - 1; i++) {
- if (keys[i] >= keys[i + 1]) {
- throw new Error("Splay tree not sorted");
- }
- }
-}
-
-
-function SplayRun() {
- // Replace a few nodes in the splay tree.
- for (var i = 0; i < kSplayTreeModifications; i++) {
- var key = InsertNewNode();
- var greatest = splayTree.findGreatestLessThan(key);
- if (greatest == null) splayTree.remove(key);
- else splayTree.remove(greatest.key);
- }
- SplayUpdateStats(performance.now());
-}
-
-
-/**
- * Constructs a Splay tree. A splay tree is a self-balancing binary
- * search tree with the additional property that recently accessed
- * elements are quick to access again. It performs basic operations
- * such as insertion, look-up and removal in O(log(n)) amortized time.
- *
- * @constructor
- */
-function SplayTree() {
-};
-
-
-/**
- * Pointer to the root node of the tree.
- *
- * @type {SplayTree.Node}
- * @private
- */
-SplayTree.prototype.root_ = null;
-
-
-/**
- * @return {boolean} Whether the tree is empty.
- */
-SplayTree.prototype.isEmpty = function() {
- return !this.root_;
-};
-
-
-/**
- * Inserts a node into the tree with the specified key and value if
- * the tree does not already contain a node with the specified key. If
- * the value is inserted, it becomes the root of the tree.
- *
- * @param {number} key Key to insert into the tree.
- * @param {*} value Value to insert into the tree.
- */
-SplayTree.prototype.insert = function(key, value) {
- if (this.isEmpty()) {
- this.root_ = new SplayTree.Node(key, value);
- return;
- }
- // Splay on the key to move the last node on the search path for
- // the key to the root of the tree.
- this.splay_(key);
- if (this.root_.key == key) {
- return;
- }
- var node = new SplayTree.Node(key, value);
- if (key > this.root_.key) {
- node.left = this.root_;
- node.right = this.root_.right;
- this.root_.right = null;
- } else {
- node.right = this.root_;
- node.left = this.root_.left;
- this.root_.left = null;
- }
- this.root_ = node;
-};
-
-
-/**
- * Removes a node with the specified key from the tree if the tree
- * contains a node with this key. The removed node is returned. If the
- * key is not found, an exception is thrown.
- *
- * @param {number} key Key to find and remove from the tree.
- * @return {SplayTree.Node} The removed node.
- */
-SplayTree.prototype.remove = function(key) {
- if (this.isEmpty()) {
- throw Error('Key not found: ' + key);
- }
- this.splay_(key);
- if (this.root_.key != key) {
- throw Error('Key not found: ' + key);
- }
- var removed = this.root_;
- if (!this.root_.left) {
- this.root_ = this.root_.right;
- } else {
- var right = this.root_.right;
- this.root_ = this.root_.left;
- // Splay to make sure that the new root has an empty right child.
- this.splay_(key);
- // Insert the original right child as the right child of the new
- // root.
- this.root_.right = right;
- }
- return removed;
-};
-
-
-/**
- * Returns the node having the specified key or null if the tree doesn't contain
- * a node with the specified key.
- *
- * @param {number} key Key to find in the tree.
- * @return {SplayTree.Node} Node having the specified key.
- */
-SplayTree.prototype.find = function(key) {
- if (this.isEmpty()) {
- return null;
- }
- this.splay_(key);
- return this.root_.key == key ? this.root_ : null;
-};
-
-
-/**
- * @return {SplayTree.Node} Node having the maximum key value.
- */
-SplayTree.prototype.findMax = function(opt_startNode) {
- if (this.isEmpty()) {
- return null;
- }
- var current = opt_startNode || this.root_;
- while (current.right) {
- current = current.right;
- }
- return current;
-};
-
-
-/**
- * @return {SplayTree.Node} Node having the maximum key value that
- * is less than the specified key value.
- */
-SplayTree.prototype.findGreatestLessThan = function(key) {
- if (this.isEmpty()) {
- return null;
- }
- // Splay on the key to move the node with the given key or the last
- // node on the search path to the top of the tree.
- this.splay_(key);
- // Now the result is either the root node or the greatest node in
- // the left subtree.
- if (this.root_.key < key) {
- return this.root_;
- } else if (this.root_.left) {
- return this.findMax(this.root_.left);
- } else {
- return null;
- }
-};
-
-
-/**
- * @return {Array<*>} An array containing all the keys of tree's nodes.
- */
-SplayTree.prototype.exportKeys = function() {
- var result = [];
- if (!this.isEmpty()) {
- this.root_.traverse_(function(node) { result.push(node.key); });
- }
- return result;
-};
-
-
-/**
- * Perform the splay operation for the given key. Moves the node with
- * the given key to the top of the tree. If no node has the given
- * key, the last node on the search path is moved to the top of the
- * tree. This is the simplified top-down splaying algorithm from:
- * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
- *
- * @param {number} key Key to splay the tree on.
- * @private
- */
-SplayTree.prototype.splay_ = function(key) {
- if (this.isEmpty()) {
- return;
- }
- // Create a dummy node. The use of the dummy node is a bit
- // counter-intuitive: The right child of the dummy node will hold
- // the L tree of the algorithm. The left child of the dummy node
- // will hold the R tree of the algorithm. Using a dummy node, left
- // and right will always be nodes and we avoid special cases.
- var dummy, left, right;
- dummy = left = right = new SplayTree.Node(null, null);
- var current = this.root_;
- while (true) {
- if (key < current.key) {
- if (!current.left) {
- break;
- }
- if (key < current.left.key) {
- // Rotate right.
- var tmp = current.left;
- current.left = tmp.right;
- tmp.right = current;
- current = tmp;
- if (!current.left) {
- break;
- }
- }
- // Link right.
- right.left = current;
- right = current;
- current = current.left;
- } else if (key > current.key) {
- if (!current.right) {
- break;
- }
- if (key > current.right.key) {
- // Rotate left.
- var tmp = current.right;
- current.right = tmp.left;
- tmp.left = current;
- current = tmp;
- if (!current.right) {
- break;
- }
- }
- // Link left.
- left.right = current;
- left = current;
- current = current.right;
- } else {
- break;
- }
- }
- // Assemble.
- left.right = current.left;
- right.left = current.right;
- current.left = dummy.right;
- current.right = dummy.left;
- this.root_ = current;
-};
-
-
-/**
- * Constructs a Splay tree node.
- *
- * @param {number} key Key.
- * @param {*} value Value.
- */
-SplayTree.Node = function(key, value) {
- this.key = key;
- this.value = value;
-};
-
-
-/**
- * @type {SplayTree.Node}
- */
-SplayTree.Node.prototype.left = null;
-
-
-/**
- * @type {SplayTree.Node}
- */
-SplayTree.Node.prototype.right = null;
-
-
-/**
- * Performs an ordered traversal of the subtree starting at
- * this SplayTree.Node.
- *
- * @param {function(SplayTree.Node)} f Visitor function.
- * @private
- */
-SplayTree.Node.prototype.traverse_ = function(f) {
- var current = this;
- while (current) {
- var left = current.left;
- if (left) left.traverse_(f);
- f(current);
- current = current.right;
- }
-};
-function jscSetUp() {
- SplaySetup();
-}
-
-function jscTearDown() {
- SplayTearDown();
-}
-
-function jscRun() {
- SplayRun();
-}
-
-jscSetUp();
-var __before = preciseTime();
-var times = [];
-for (var i = 0; i < 10000; ++i) {
-//for (var i = 0; i < 1000000; ++i) {
- var _before = preciseTime();
- jscRun();
- var _after = preciseTime();
- times.push(_after - _before);
- flashHeapAccess();
-}
-var __after = preciseTime();
-jscTearDown();
-
-function averageAbovePercentile(numbers, percentile) {
- // Don't change the original array.
- numbers = numbers.slice();
-
- // Sort in ascending order.
- numbers.sort(function(a, b) { return a - b; });
-
- // Now the elements we want are at the end. Keep removing them until the array size shrinks too much.
- // Examples assuming percentile = 99:
- //
- // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore,
- // since then numbers.length / originalLength = 0.99.
- //
- // - numbers.length starts at 1000: we will remove the ten worst.
- //
- // - numbers.length starts at 10: we will remove just the worst.
- var numbersWeWant = [];
- var originalLength = numbers.length;
- while (numbers.length / originalLength > percentile / 100)
- numbersWeWant.push(numbers.pop());
-
- var sum = 0;
- for (var i = 0; i < numbersWeWant.length; ++i)
- sum += numbersWeWant[i];
-
- var result = sum / numbersWeWant.length;
-
- // Do a sanity check.
- if (numbers.length && result < numbers[numbers.length - 1]) {
- throw "Sanity check fail: the worst case result is " + result +
- " but we didn't take into account " + numbers;
- }
-
- return result;
-}
-
-print("That took " + (__after - __before) * 1000 + " ms.");
-
-function printPercentile(percentile)
-{
- print("Above " + percentile + "%: " + averageAbovePercentile(times, percentile) * 1000 + " ms.");
-}
-
-printPercentile(99.9);
-printPercentile(99.5);
-printPercentile(99);
-printPercentile(97.5);
-printPercentile(95);
-printPercentile(90);
-printPercentile(75);
-printPercentile(50);
-printPercentile(0);
-
-gc();
</del></span></pre></div>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/LayoutTests/ChangeLog        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2017-02-19 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r212466.
+ https://bugs.webkit.org/show_bug.cgi?id=168577
+
+ causes crashes on AArch64 on linux, maybe it's causing crashes
+ on iOS too (Requested by pizlo on #webkit).
+
+ Reverted changeset:
+
+ "The collector thread should only start when the mutator
+ doesn't have heap access"
+ https://bugs.webkit.org/show_bug.cgi?id=167737
+ http://trac.webkit.org/changeset/212466
+
</ins><span class="cx"> 2017-02-19 Carlos Garcia Campos <cgarcia@igalia.com>
</span><span class="cx">
</span><span class="cx"> Unreviewed GTK+ gardening. Rebaseline fast/visual-viewport/rubberbanding-viewport-rects-extended-background.html again.
</span></span></pre></div>
<a id="trunkLayoutTestsjsdomgcslotvisitorparalleldrainpingsrunloopwhendoneexpectedtxt"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/js/dom/gc-slot-visitor-parallel-drain-pings-runloop-when-done-expected.txt (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/dom/gc-slot-visitor-parallel-drain-pings-runloop-when-done-expected.txt        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/LayoutTests/js/dom/gc-slot-visitor-parallel-drain-pings-runloop-when-done-expected.txt        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,5 +0,0 @@
</span><del>-Testing if the GC SlotVisitor pings the runloop when done.
-Running 200 iterations of splay...
-GC finished.
-Test passed.
-
</del></span></pre></div>
<a id="trunkLayoutTestsjsdomgcslotvisitorparalleldrainpingsrunloopwhendonehtml"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/js/dom/gc-slot-visitor-parallel-drain-pings-runloop-when-done.html (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/dom/gc-slot-visitor-parallel-drain-pings-runloop-when-done.html        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/LayoutTests/js/dom/gc-slot-visitor-parallel-drain-pings-runloop-when-done.html        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,896 +0,0 @@
</span><del>-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-</head>
-<body>
-<script>
-function getOrCreate(id, tagName)
-{
- var element = document.getElementById(id);
- if (element)
- return element;
-
- element = document.createElement(tagName);
- element.id = id;
- var parent = document.body || document.documentElement;
- var refNode = parent.firstChild;
-
- parent.insertBefore(element, refNode);
- return element;
-}
-
-function debug(msg)
-{
- var span = document.createElement("span");
- getOrCreate("console", "div").appendChild(span); // insert it first so XHTML knows the namespace
- span.innerHTML = msg + '<br />';
-}
-
-if (window.testRunner) {
- testRunner.dumpAsText();
- testRunner.waitUntilDone();
-}
-
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Copyright (C) 2015 Apple Inc. 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.
-
-
-// Performance.now is used in latency benchmarks, the fallback is Date.now.
-var performance = performance || {};
-performance.now = (function() {
- return performance.now ||
- performance.mozNow ||
- performance.msNow ||
- performance.oNow ||
- performance.webkitNow ||
- Date.now;
-})();
-
-// Simple framework for running the benchmark suites and
-// computing a score based on the timing measurements.
-
-
-// A benchmark has a name (string) and a function that will be run to
-// do the performance measurement. The optional setup and tearDown
-// arguments are functions that will be invoked before and after
-// running the benchmark, but the running time of these functions will
-// not be accounted for in the benchmark score.
-function Benchmark(name, doWarmup, doDeterministic, run, setup, tearDown, latencyResult, minIterations) {
- this.name = name;
- this.doWarmup = doWarmup;
- this.doDeterministic = doDeterministic;
- this.run = run;
- this.Setup = setup ? setup : function() { };
- this.TearDown = tearDown ? tearDown : function() { };
- this.latencyResult = latencyResult ? latencyResult : null;
- this.minIterations = minIterations ? minIterations : 32;
-}
-
-
-// Benchmark results hold the benchmark and the measured time used to
-// run the benchmark. The benchmark score is computed later once a
-// full benchmark suite has run to completion. If latency is set to 0
-// then there is no latency score for this benchmark.
-function BenchmarkResult(benchmark, time, latency) {
- this.benchmark = benchmark;
- this.time = time;
- this.latency = latency;
-}
-
-
-// Automatically convert results to numbers. Used by the geometric
-// mean computation.
-BenchmarkResult.prototype.valueOf = function() {
- return this.time;
-}
-
-
-// Suites of benchmarks consist of a name and the set of benchmarks in
-// addition to the reference timing that the final score will be based
-// on. This way, all scores are relative to a reference run and higher
-// scores implies better performance.
-function BenchmarkSuite(name, reference, benchmarks) {
- this.name = name;
- this.reference = reference;
- this.benchmarks = benchmarks;
- BenchmarkSuite.suites.push(this);
-}
-
-
-// Keep track of all declared benchmark suites.
-BenchmarkSuite.suites = [];
-
-// Scores are not comparable across versions. Bump the version if
-// you're making changes that will affect that scores, e.g. if you add
-// a new benchmark or change an existing one.
-BenchmarkSuite.version = '9';
-
-// Override the alert function to throw an exception instead.
-alert = function(s) {
- throw "Alert called with argument: " + s;
-};
-
-
-// To make the benchmark results predictable, we replace Math.random
-// with a 100% deterministic alternative.
-BenchmarkSuite.ResetRNG = function() {
- Math.random = (function() {
- var seed = 49734321;
- return function() {
- // Robert Jenkins' 32 bit integer hash function.
- seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff;
- seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
- seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
- seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
- seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
- seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
- return (seed & 0xfffffff) / 0x10000000;
- };
- })();
-}
-
-
-// Runs all registered benchmark suites and optionally yields between
-// each individual benchmark to avoid running for too long in the
-// context of browsers. Once done, the final score is reported to the
-// runner.
-BenchmarkSuite.RunSuites = function(runner) {
- var continuation = null;
- var suites = BenchmarkSuite.suites;
- var length = suites.length;
- BenchmarkSuite.scores = [];
- var index = 0;
- function RunStep() {
- while (continuation || index < length) {
- if (continuation) {
- continuation = continuation();
- } else {
- var suite = suites[index++];
- if (runner.NotifyStart) runner.NotifyStart(suite.name);
- continuation = suite.RunStep(runner);
- }
- if (continuation && typeof window != 'undefined' && window.setTimeout) {
- window.setTimeout(RunStep, 25);
- return;
- }
- }
-
- // show final result
- if (runner.NotifyScore) {
- var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores);
- var formatted = BenchmarkSuite.FormatScore(100 * score);
- runner.NotifyScore(formatted);
- }
- }
- RunStep();
-}
-
-
-// Counts the total number of registered benchmarks. Useful for
-// showing progress as a percentage.
-BenchmarkSuite.CountBenchmarks = function() {
- var result = 0;
- var suites = BenchmarkSuite.suites;
- for (var i = 0; i < suites.length; i++) {
- result += suites[i].benchmarks.length;
- }
- return result;
-}
-
-
-// Computes the geometric mean of a set of numbers.
-BenchmarkSuite.GeometricMean = function(numbers) {
- var log = 0;
- for (var i = 0; i < numbers.length; i++) {
- log += Math.log(numbers[i]);
- }
- return Math.pow(Math.E, log / numbers.length);
-}
-
-
-// Computes the geometric mean of a set of throughput time measurements.
-BenchmarkSuite.GeometricMeanTime = function(measurements) {
- var log = 0;
- for (var i = 0; i < measurements.length; i++) {
- log += Math.log(measurements[i].time);
- }
- return Math.pow(Math.E, log / measurements.length);
-}
-
-
-// Computes the average of the worst samples. For example, if percentile is 99, this will report the
-// average of the worst 1% of the samples.
-BenchmarkSuite.AverageAbovePercentile = function(numbers, percentile) {
- // Don't change the original array.
- numbers = numbers.slice();
-
- // Sort in ascending order.
- numbers.sort(function(a, b) { return a - b; });
-
- // Now the elements we want are at the end. Keep removing them until the array size shrinks too much.
- // Examples assuming percentile = 99:
- //
- // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore,
- // since then numbers.length / originalLength = 0.99.
- //
- // - numbers.length starts at 1000: we will remove the ten worst.
- //
- // - numbers.length starts at 10: we will remove just the worst.
- var numbersWeWant = [];
- var originalLength = numbers.length;
- while (numbers.length / originalLength > percentile / 100)
- numbersWeWant.push(numbers.pop());
-
- var sum = 0;
- for (var i = 0; i < numbersWeWant.length; ++i)
- sum += numbersWeWant[i];
-
- var result = sum / numbersWeWant.length;
-
- // Do a sanity check.
- if (numbers.length && result < numbers[numbers.length - 1]) {
- throw "Sanity check fail: the worst case result is " + result +
- " but we didn't take into account " + numbers;
- }
-
- return result;
-}
-
-
-// Computes the geometric mean of a set of latency measurements.
-BenchmarkSuite.GeometricMeanLatency = function(measurements) {
- var log = 0;
- var hasLatencyResult = false;
- for (var i = 0; i < measurements.length; i++) {
- if (measurements[i].latency != 0) {
- log += Math.log(measurements[i].latency);
- hasLatencyResult = true;
- }
- }
- if (hasLatencyResult) {
- return Math.pow(Math.E, log / measurements.length);
- } else {
- return 0;
- }
-}
-
-
-// Converts a score value to a string with at least three significant
-// digits.
-BenchmarkSuite.FormatScore = function(value) {
- if (value > 100) {
- return value.toFixed(0);
- } else {
- return value.toPrecision(3);
- }
-}
-
-// Notifies the runner that we're done running a single benchmark in
-// the benchmark suite. This can be useful to report progress.
-BenchmarkSuite.prototype.NotifyStep = function(result) {
- this.results.push(result);
- if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name);
-}
-
-
-// Notifies the runner that we're done with running a suite and that
-// we have a result which can be reported to the user if needed.
-BenchmarkSuite.prototype.NotifyResult = function() {
- var mean = BenchmarkSuite.GeometricMeanTime(this.results);
- var score = this.reference[0] / mean;
- BenchmarkSuite.scores.push(score);
- if (this.runner.NotifyResult) {
- var formatted = BenchmarkSuite.FormatScore(100 * score);
- this.runner.NotifyResult(this.name, formatted);
- }
- if (this.reference.length == 2) {
- var meanLatency = BenchmarkSuite.GeometricMeanLatency(this.results);
- if (meanLatency != 0) {
- var scoreLatency = this.reference[1] / meanLatency;
- BenchmarkSuite.scores.push(scoreLatency);
- if (this.runner.NotifyResult) {
- var formattedLatency = BenchmarkSuite.FormatScore(100 * scoreLatency)
- this.runner.NotifyResult(this.name + "Latency", formattedLatency);
- }
- }
- }
-}
-
-
-// Notifies the runner that running a benchmark resulted in an error.
-BenchmarkSuite.prototype.NotifyError = function(error) {
- if (this.runner.NotifyError) {
- this.runner.NotifyError(this.name, error);
- }
- if (this.runner.NotifyStep) {
- this.runner.NotifyStep(this.name);
- }
-}
-
-
-// Runs a single benchmark for at least a second and computes the
-// average time it takes to run a single iteration.
-BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) {
- function Measure(data) {
- var elapsed = 0;
- var start = new Date();
-
- // Run either for 1 second or for the number of iterations specified
- // by minIterations, depending on the config flag doDeterministic.
- for (var i = 0; (benchmark.doDeterministic ?
- i<benchmark.minIterations : elapsed < 1000); i++) {
- benchmark.run();
- elapsed = new Date() - start;
- }
- if (data != null) {
- data.runs += i;
- data.elapsed += elapsed;
- }
- }
-
- // Sets up data in order to skip or not the warmup phase.
- if (!benchmark.doWarmup && data == null) {
- data = { runs: 0, elapsed: 0 };
- }
-
- if (data == null) {
- Measure(null);
- return { runs: 0, elapsed: 0 };
- } else {
- Measure(data);
- // If we've run too few iterations, we continue for another second.
- if (data.runs < benchmark.minIterations) return data;
- var usec = (data.elapsed * 1000) / data.runs;
- var latencySamples = (benchmark.latencyResult != null) ? benchmark.latencyResult() : [0];
- var percentile = 99.5;
- var latency = BenchmarkSuite.AverageAbovePercentile(latencySamples, percentile) * 1000;
- this.NotifyStep(new BenchmarkResult(benchmark, usec, latency));
- return null;
- }
-}
-
-
-// This function starts running a suite, but stops between each
-// individual benchmark in the suite and returns a continuation
-// function which can be invoked to run the next benchmark. Once the
-// last benchmark has been executed, null is returned.
-BenchmarkSuite.prototype.RunStep = function(runner) {
- BenchmarkSuite.ResetRNG();
- this.results = [];
- this.runner = runner;
- var length = this.benchmarks.length;
- var index = 0;
- var suite = this;
- var data;
-
- // Run the setup, the actual benchmark, and the tear down in three
- // separate steps to allow the framework to yield between any of the
- // steps.
-
- function RunNextSetup() {
- if (index < length) {
- try {
- suite.benchmarks[index].Setup();
- } catch (e) {
- suite.NotifyError(e);
- return null;
- }
- return RunNextBenchmark;
- }
- suite.NotifyResult();
- return null;
- }
-
- function RunNextBenchmark() {
- try {
- data = suite.RunSingleBenchmark(suite.benchmarks[index], data);
- } catch (e) {
- suite.NotifyError(e);
- return null;
- }
- // If data is null, we're done with this benchmark.
- return (data == null) ? RunNextTearDown : RunNextBenchmark();
- }
-
- function RunNextTearDown() {
- try {
- suite.benchmarks[index++].TearDown();
- } catch (e) {
- suite.NotifyError(e);
- return null;
- }
- return RunNextSetup;
- }
-
- // Start out running the setup.
- return RunNextSetup();
-}
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Copyright (C) 2015 Apple Inc. 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.
-
-// This benchmark is based on a JavaScript log processing module used
-// by the V8 profiler to generate execution time profiles for runs of
-// JavaScript applications, and it effectively measures how fast the
-// JavaScript engine is at allocating nodes and reclaiming the memory
-// used for old nodes. Because of the way splay trees work, the engine
-// also has to deal with a lot of changes to the large tree object
-// graph.
-
-var Splay = new BenchmarkSuite('Splay', [81491, 2739514], [
- new Benchmark("Splay", true, false,
- SplayRun, SplaySetup, SplayTearDown, SplayLatency)
-]);
-
-
-// Configuration.
-var kSplayTreeSize = 8000;
-var kSplayTreeModifications = 80;
-var kSplayTreePayloadDepth = 5;
-
-var splayTree = null;
-var splaySampleTimeStart = 0.0;
-
-function GeneratePayloadTree(depth, tag) {
- if (depth == 0) {
- return {
- array : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
- string : 'String for key ' + tag + ' in leaf node'
- };
- } else {
- return {
- left: GeneratePayloadTree(depth - 1, tag),
- right: GeneratePayloadTree(depth - 1, tag)
- };
- }
-}
-
-
-function GenerateKey() {
- // The benchmark framework guarantees that Math.random is
- // deterministic; see base.js.
- return Math.random();
-}
-
-var splaySamples = [];
-
-function SplayLatency() {
- return splaySamples;
-}
-
-function SplayUpdateStats(time) {
- var pause = time - splaySampleTimeStart;
- splaySampleTimeStart = time;
- splaySamples.push(pause);
-}
-
-function InsertNewNode() {
- // Insert new node with a unique key.
- var key;
- do {
- key = GenerateKey();
- } while (splayTree.find(key) != null);
- var payload = GeneratePayloadTree(kSplayTreePayloadDepth, String(key));
- splayTree.insert(key, payload);
- return key;
-}
-
-
-function SplaySetup() {
- // Check if the platform has the performance.now high resolution timer.
- // If not, throw exception and quit.
- if (!performance.now) {
- throw "PerformanceNowUnsupported";
- }
-
- splayTree = new SplayTree();
- splaySampleTimeStart = performance.now()
- for (var i = 0; i < kSplayTreeSize; i++) {
- InsertNewNode();
- if ((i+1) % 20 == 19) {
- SplayUpdateStats(performance.now());
- }
- }
-}
-
-
-function SplayTearDown() {
- // Allow the garbage collector to reclaim the memory
- // used by the splay tree no matter how we exit the
- // tear down function.
- var keys = splayTree.exportKeys();
- splayTree = null;
-
- splaySamples = [];
-
- // Verify that the splay tree has the right size.
- var length = keys.length;
- if (length != kSplayTreeSize) {
- throw new Error("Splay tree has wrong size");
- }
-
- // Verify that the splay tree has sorted, unique keys.
- for (var i = 0; i < length - 1; i++) {
- if (keys[i] >= keys[i + 1]) {
- throw new Error("Splay tree not sorted");
- }
- }
-}
-
-
-function SplayRun() {
- // Replace a few nodes in the splay tree.
- for (var i = 0; i < kSplayTreeModifications; i++) {
- var key = InsertNewNode();
- var greatest = splayTree.findGreatestLessThan(key);
- if (greatest == null) splayTree.remove(key);
- else splayTree.remove(greatest.key);
- }
- SplayUpdateStats(performance.now());
-}
-
-
-/**
- * Constructs a Splay tree. A splay tree is a self-balancing binary
- * search tree with the additional property that recently accessed
- * elements are quick to access again. It performs basic operations
- * such as insertion, look-up and removal in O(log(n)) amortized time.
- *
- * @constructor
- */
-function SplayTree() {
-};
-
-
-/**
- * Pointer to the root node of the tree.
- *
- * @type {SplayTree.Node}
- * @private
- */
-SplayTree.prototype.root_ = null;
-
-
-/**
- * @return {boolean} Whether the tree is empty.
- */
-SplayTree.prototype.isEmpty = function() {
- return !this.root_;
-};
-
-
-/**
- * Inserts a node into the tree with the specified key and value if
- * the tree does not already contain a node with the specified key. If
- * the value is inserted, it becomes the root of the tree.
- *
- * @param {number} key Key to insert into the tree.
- * @param {*} value Value to insert into the tree.
- */
-SplayTree.prototype.insert = function(key, value) {
- if (this.isEmpty()) {
- this.root_ = new SplayTree.Node(key, value);
- return;
- }
- // Splay on the key to move the last node on the search path for
- // the key to the root of the tree.
- this.splay_(key);
- if (this.root_.key == key) {
- return;
- }
- var node = new SplayTree.Node(key, value);
- if (key > this.root_.key) {
- node.left = this.root_;
- node.right = this.root_.right;
- this.root_.right = null;
- } else {
- node.right = this.root_;
- node.left = this.root_.left;
- this.root_.left = null;
- }
- this.root_ = node;
-};
-
-
-/**
- * Removes a node with the specified key from the tree if the tree
- * contains a node with this key. The removed node is returned. If the
- * key is not found, an exception is thrown.
- *
- * @param {number} key Key to find and remove from the tree.
- * @return {SplayTree.Node} The removed node.
- */
-SplayTree.prototype.remove = function(key) {
- if (this.isEmpty()) {
- throw Error('Key not found: ' + key);
- }
- this.splay_(key);
- if (this.root_.key != key) {
- throw Error('Key not found: ' + key);
- }
- var removed = this.root_;
- if (!this.root_.left) {
- this.root_ = this.root_.right;
- } else {
- var right = this.root_.right;
- this.root_ = this.root_.left;
- // Splay to make sure that the new root has an empty right child.
- this.splay_(key);
- // Insert the original right child as the right child of the new
- // root.
- this.root_.right = right;
- }
- return removed;
-};
-
-
-/**
- * Returns the node having the specified key or null if the tree doesn't contain
- * a node with the specified key.
- *
- * @param {number} key Key to find in the tree.
- * @return {SplayTree.Node} Node having the specified key.
- */
-SplayTree.prototype.find = function(key) {
- if (this.isEmpty()) {
- return null;
- }
- this.splay_(key);
- return this.root_.key == key ? this.root_ : null;
-};
-
-
-/**
- * @return {SplayTree.Node} Node having the maximum key value.
- */
-SplayTree.prototype.findMax = function(opt_startNode) {
- if (this.isEmpty()) {
- return null;
- }
- var current = opt_startNode || this.root_;
- while (current.right) {
- current = current.right;
- }
- return current;
-};
-
-
-/**
- * @return {SplayTree.Node} Node having the maximum key value that
- * is less than the specified key value.
- */
-SplayTree.prototype.findGreatestLessThan = function(key) {
- if (this.isEmpty()) {
- return null;
- }
- // Splay on the key to move the node with the given key or the last
- // node on the search path to the top of the tree.
- this.splay_(key);
- // Now the result is either the root node or the greatest node in
- // the left subtree.
- if (this.root_.key < key) {
- return this.root_;
- } else if (this.root_.left) {
- return this.findMax(this.root_.left);
- } else {
- return null;
- }
-};
-
-
-/**
- * @return {Array<*>} An array containing all the keys of tree's nodes.
- */
-SplayTree.prototype.exportKeys = function() {
- var result = [];
- if (!this.isEmpty()) {
- this.root_.traverse_(function(node) { result.push(node.key); });
- }
- return result;
-};
-
-
-/**
- * Perform the splay operation for the given key. Moves the node with
- * the given key to the top of the tree. If no node has the given
- * key, the last node on the search path is moved to the top of the
- * tree. This is the simplified top-down splaying algorithm from:
- * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
- *
- * @param {number} key Key to splay the tree on.
- * @private
- */
-SplayTree.prototype.splay_ = function(key) {
- if (this.isEmpty()) {
- return;
- }
- // Create a dummy node. The use of the dummy node is a bit
- // counter-intuitive: The right child of the dummy node will hold
- // the L tree of the algorithm. The left child of the dummy node
- // will hold the R tree of the algorithm. Using a dummy node, left
- // and right will always be nodes and we avoid special cases.
- var dummy, left, right;
- dummy = left = right = new SplayTree.Node(null, null);
- var current = this.root_;
- while (true) {
- if (key < current.key) {
- if (!current.left) {
- break;
- }
- if (key < current.left.key) {
- // Rotate right.
- var tmp = current.left;
- current.left = tmp.right;
- tmp.right = current;
- current = tmp;
- if (!current.left) {
- break;
- }
- }
- // Link right.
- right.left = current;
- right = current;
- current = current.left;
- } else if (key > current.key) {
- if (!current.right) {
- break;
- }
- if (key > current.right.key) {
- // Rotate left.
- var tmp = current.right;
- current.right = tmp.left;
- tmp.left = current;
- current = tmp;
- if (!current.right) {
- break;
- }
- }
- // Link left.
- left.right = current;
- left = current;
- current = current.right;
- } else {
- break;
- }
- }
- // Assemble.
- left.right = current.left;
- right.left = current.right;
- current.left = dummy.right;
- current.right = dummy.left;
- this.root_ = current;
-};
-
-
-/**
- * Constructs a Splay tree node.
- *
- * @param {number} key Key.
- * @param {*} value Value.
- */
-SplayTree.Node = function(key, value) {
- this.key = key;
- this.value = value;
-};
-
-
-/**
- * @type {SplayTree.Node}
- */
-SplayTree.Node.prototype.left = null;
-
-
-/**
- * @type {SplayTree.Node}
- */
-SplayTree.Node.prototype.right = null;
-
-
-/**
- * Performs an ordered traversal of the subtree starting at
- * this SplayTree.Node.
- *
- * @param {function(SplayTree.Node)} f Visitor function.
- * @private
- */
-SplayTree.Node.prototype.traverse_ = function(f) {
- var current = this;
- while (current) {
- var left = current.left;
- if (left) left.traverse_(f);
- f(current);
- current = current.right;
- }
-};
-function jscSetUp() {
- SplaySetup();
-}
-
-function jscTearDown() {
- SplayTearDown();
-}
-
-function jscRun() {
- SplayRun();
-}
-
-debug("Testing if the GC SlotVisitor pings the runloop when done.");
-debug("Running 200 iterations of splay...");
-
-window.internals.stopSweeping();
-
-// Allocate the callback here.
-var callback = function() {
- debug("GC finished.");
- debug("Test passed.");
- window.internals.startSweeping();
- if (window.testRunner)
- testRunner.notifyDone();
-};
-
-jscSetUp();
-for (var i = 0; i < 50 || !window.internals.isGCRunning(); ++i)
- jscRun();
-// We are relying on the fact that there will not be any safepoints between isGCRunning and
-// addGCFinalizationCallback. If there is a safepoint, then the test might pass even if the GC doesn't
-// do the SlotVisitor thing. So, we should try to avoid putting safepoints on this path, but it's not
-// the end of the world if we have to.
-
-// We have to stop the sweeper, because the sweeper will poll the GC even if SlotVisitor doesn't notify
-// the runloop.
-window.internals.stopSweeping();
-
-// Register a totally shady callback into the heart of the GC. It will run when the GC finalizes.
-window.internals.addGCFinalizationCallback(callback);
-</script>
-</body>
-</html>
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -474,7 +474,6 @@
</span><span class="cx"> heap/CellContainer.cpp
</span><span class="cx"> heap/CodeBlockSet.cpp
</span><span class="cx"> heap/CollectionScope.cpp
</span><del>- heap/CollectorPhase.cpp
</del><span class="cx"> heap/ConservativeRoots.cpp
</span><span class="cx"> heap/DeferGC.cpp
</span><span class="cx"> heap/DestructionMode.cpp
</span><span class="lines">@@ -482,8 +481,6 @@
</span><span class="cx"> heap/FullGCActivityCallback.cpp
</span><span class="cx"> heap/FreeList.cpp
</span><span class="cx"> heap/GCActivityCallback.cpp
</span><del>- heap/GCConductor.cpp
- heap/GCFinalizationCallback.cpp
</del><span class="cx"> heap/GCLogging.cpp
</span><span class="cx"> heap/HandleSet.cpp
</span><span class="cx"> heap/HandleStack.cpp
</span><span class="lines">@@ -493,6 +490,7 @@
</span><span class="cx"> heap/HeapProfiler.cpp
</span><span class="cx"> heap/HeapSnapshot.cpp
</span><span class="cx"> heap/HeapSnapshotBuilder.cpp
</span><ins>+ heap/HeapStatistics.cpp
</ins><span class="cx"> heap/HeapTimer.cpp
</span><span class="cx"> heap/HeapVerifier.cpp
</span><span class="cx"> heap/IncrementalSweeper.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2017-02-19 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r212466.
+ https://bugs.webkit.org/show_bug.cgi?id=168577
+
+ causes crashes on AArch64 on linux, maybe it's causing crashes
+ on iOS too (Requested by pizlo on #webkit).
+
+ Reverted changeset:
+
+ "The collector thread should only start when the mutator
+ doesn't have heap access"
+ https://bugs.webkit.org/show_bug.cgi?id=167737
+ http://trac.webkit.org/changeset/212466
+
</ins><span class="cx"> 2017-02-17 Michael Saboff <msaboff@apple.com>
</span><span class="cx">
</span><span class="cx"> Improve ARM64 disassembler handling of pseudo ops, unsupported opcodes and zero reg
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -269,9 +269,6 @@
</span><span class="cx">                 0F2BDC4D1522818600CD8910 /* DFGMinifiedNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC4C1522818300CD8910 /* DFGMinifiedNode.cpp */; };
</span><span class="cx">                 0F2BDC4F15228BF300CD8910 /* DFGValueSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC4E15228BE700CD8910 /* DFGValueSource.cpp */; };
</span><span class="cx">                 0F2BDC5115228FFD00CD8910 /* DFGVariableEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC5015228FFA00CD8910 /* DFGVariableEvent.cpp */; };
</span><del>-                0F2C63A71E4F8FD300C13839 /* GCFinalizationCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2C63A51E4F8FD100C13839 /* GCFinalizationCallback.cpp */; };
-                0F2C63A81E4F8FD500C13839 /* GCFinalizationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C63A61E4F8FD100C13839 /* GCFinalizationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
-                0F2C63AA1E4FA42E00C13839 /* RunningScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C63A91E4FA42C00C13839 /* RunningScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx">                 0F2D4DDD19832D34007D4B19 /* DebuggerScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2D4DDB19832D34007D4B19 /* DebuggerScope.cpp */; };
</span><span class="cx">                 0F2D4DDE19832D34007D4B19 /* DebuggerScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2D4DDC19832D34007D4B19 /* DebuggerScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F2D4DE819832DAC007D4B19 /* ToThisStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2D4DE519832DAC007D4B19 /* ToThisStatus.cpp */; };
</span><span class="lines">@@ -637,6 +634,7 @@
</span><span class="cx">                 0FA762051DB9242900B7A2FD /* CollectionScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA762011DB9242300B7A2FD /* CollectionScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FA762061DB9243100B7A2FD /* MutatorState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA762021DB9242300B7A2FD /* MutatorState.cpp */; };
</span><span class="cx">                 0FA762071DB9243300B7A2FD /* MutatorState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA762031DB9242300B7A2FD /* MutatorState.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0FA762091DB9283E00B7A2FD /* HelpingGCScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA762081DB9283C00B7A2FD /* HelpingGCScope.h */; };
</ins><span class="cx">                 0FA7620B1DB959F900B7A2FD /* AllocatingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA7620A1DB959F600B7A2FD /* AllocatingScope.h */; };
</span><span class="cx">                 0FA7A8EB18B413C80052371D /* Reg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA7A8E918B413C80052371D /* Reg.cpp */; };
</span><span class="cx">                 0FA7A8EC18B413C80052371D /* Reg.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA7A8EA18B413C80052371D /* Reg.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -737,13 +735,6 @@
</span><span class="cx">                 0FCEFAAC1804C13E00472CE4 /* FTLSaveRestore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FCEFADF180738C000472CE4 /* FTLLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFADD180738C000472CE4 /* FTLLocation.cpp */; };
</span><span class="cx">                 0FCEFAE0180738C000472CE4 /* FTLLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFADE180738C000472CE4 /* FTLLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                0FD0E5E91E43D3490006AB08 /* CollectorPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD0E5E61E43D3470006AB08 /* CollectorPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
-                0FD0E5EA1E43D34D0006AB08 /* GCConductor.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD0E5E81E43D3470006AB08 /* GCConductor.h */; settings = {ATTRIBUTES = (Private, ); }; };
-                0FD0E5EB1E43D3500006AB08 /* CollectorPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD0E5E51E43D3470006AB08 /* CollectorPhase.cpp */; };
-                0FD0E5EC1E43D3530006AB08 /* GCConductor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD0E5E71E43D3470006AB08 /* GCConductor.cpp */; };
-                0FD0E5EE1E468A570006AB08 /* SweepingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD0E5ED1E468A540006AB08 /* SweepingScope.h */; };
-                0FD0E5F01E46BF250006AB08 /* RegisterState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD0E5EF1E46BF230006AB08 /* RegisterState.h */; settings = {ATTRIBUTES = (Private, ); }; };
-                0FD0E5F21E46C8AF0006AB08 /* CollectingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD0E5F11E46C8AD0006AB08 /* CollectingScope.h */; };
</del><span class="cx">                 0FD2C92416D01EE900C7803F /* StructureInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD2C92316D01EE900C7803F /* StructureInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD3C82014115CF800FD81CB /* DFGDriver.cpp */; };
</span><span class="cx">                 0FD3C82814115D4F00FD81CB /* DFGDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3C82214115D0E00FD81CB /* DFGDriver.h */; };
</span><span class="lines">@@ -1214,7 +1205,7 @@
</span><span class="cx">                 14B723B812D7DA6F003BD5ED /* MachineStackMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 14B8EC720A5652090062BE54 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; };
</span><span class="cx">                 14BA78F113AAB88F005B7C2C /* SlotVisitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BA78F013AAB88F005B7C2C /* SlotVisitor.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                14BA7A9713AADFF8005B7C2C /* Heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BA7A9513AADFF8005B7C2C /* Heap.cpp */; settings = {COMPILER_FLAGS = "-fno-optimize-sibling-calls"; }; };
</del><ins>+                14BA7A9713AADFF8005B7C2C /* Heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BA7A9513AADFF8005B7C2C /* Heap.cpp */; };
</ins><span class="cx">                 14BA7A9813AADFF8005B7C2C /* Heap.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BA7A9613AADFF8005B7C2C /* Heap.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 14BD59C50A3E8F9F00BAF59C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; };
</span><span class="cx">                 14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD5A290A3E91F600BAF59C /* JSContextRef.cpp */; };
</span><span class="lines">@@ -2186,6 +2177,8 @@
</span><span class="cx">                 C2181FC218A948FB0025A235 /* JSExportTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = C2181FC118A948FB0025A235 /* JSExportTests.mm */; };
</span><span class="cx">                 C225494315F7DBAA0065E898 /* SlotVisitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C225494215F7DBAA0065E898 /* SlotVisitor.cpp */; };
</span><span class="cx">                 C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F77008E1402FDD60078EB39 /* SamplingCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                C24D31E2161CD695002AA4DB /* HeapStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C24D31E0161CD695002AA4DB /* HeapStatistics.cpp */; };
+                C24D31E3161CD695002AA4DB /* HeapStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = C24D31E1161CD695002AA4DB /* HeapStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 C25D709B16DE99F400FCA6BC /* JSManagedValue.mm in Sources */ = {isa = PBXBuildFile; fileRef = C25D709916DE99F400FCA6BC /* JSManagedValue.mm */; };
</span><span class="cx">                 C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */ = {isa = PBXBuildFile; fileRef = C25D709A16DE99F400FCA6BC /* JSManagedValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
</span><span class="cx">                 C25F8BCD157544A900245B71 /* IncrementalSweeper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */; };
</span><span class="lines">@@ -2752,9 +2745,6 @@
</span><span class="cx">                 0F2BDC4C1522818300CD8910 /* DFGMinifiedNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMinifiedNode.cpp; path = dfg/DFGMinifiedNode.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F2BDC4E15228BE700CD8910 /* DFGValueSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGValueSource.cpp; path = dfg/DFGValueSource.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F2BDC5015228FFA00CD8910 /* DFGVariableEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableEvent.cpp; path = dfg/DFGVariableEvent.cpp; sourceTree = "<group>"; };
</span><del>-                0F2C63A51E4F8FD100C13839 /* GCFinalizationCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCFinalizationCallback.cpp; sourceTree = "<group>"; };
-                0F2C63A61E4F8FD100C13839 /* GCFinalizationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCFinalizationCallback.h; sourceTree = "<group>"; };
-                0F2C63A91E4FA42C00C13839 /* RunningScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RunningScope.h; sourceTree = "<group>"; };
</del><span class="cx">                 0F2D4DDB19832D34007D4B19 /* DebuggerScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerScope.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F2D4DDC19832D34007D4B19 /* DebuggerScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerScope.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F2D4DDF19832D91007D4B19 /* TypeProfilerLog.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeProfilerLog.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -3114,6 +3104,7 @@
</span><span class="cx">                 0FA762011DB9242300B7A2FD /* CollectionScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionScope.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FA762021DB9242300B7A2FD /* MutatorState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MutatorState.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0FA762031DB9242300B7A2FD /* MutatorState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MutatorState.h; sourceTree = "<group>"; };
</span><ins>+                0FA762081DB9283C00B7A2FD /* HelpingGCScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HelpingGCScope.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0FA7620A1DB959F600B7A2FD /* AllocatingScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllocatingScope.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FA7A8E918B413C80052371D /* Reg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Reg.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0FA7A8EA18B413C80052371D /* Reg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reg.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -3226,13 +3217,6 @@
</span><span class="cx">                 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSaveRestore.h; path = ftl/FTLSaveRestore.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FCEFADD180738C000472CE4 /* FTLLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLocation.cpp; path = ftl/FTLLocation.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0FCEFADE180738C000472CE4 /* FTLLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLLocation.h; path = ftl/FTLLocation.h; sourceTree = "<group>"; };
</span><del>-                0FD0E5E51E43D3470006AB08 /* CollectorPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollectorPhase.cpp; sourceTree = "<group>"; };
-                0FD0E5E61E43D3470006AB08 /* CollectorPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectorPhase.h; sourceTree = "<group>"; };
-                0FD0E5E71E43D3470006AB08 /* GCConductor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCConductor.cpp; sourceTree = "<group>"; };
-                0FD0E5E81E43D3470006AB08 /* GCConductor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCConductor.h; sourceTree = "<group>"; };
-                0FD0E5ED1E468A540006AB08 /* SweepingScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SweepingScope.h; sourceTree = "<group>"; };
-                0FD0E5EF1E46BF230006AB08 /* RegisterState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterState.h; sourceTree = "<group>"; };
-                0FD0E5F11E46C8AD0006AB08 /* CollectingScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectingScope.h; sourceTree = "<group>"; };
</del><span class="cx">                 0FD2C92316D01EE900C7803F /* StructureInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureInlines.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FD3C82014115CF800FD81CB /* DFGDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDriver.cpp; path = dfg/DFGDriver.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0FD3C82214115D0E00FD81CB /* DFGDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDriver.h; path = dfg/DFGDriver.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -4706,6 +4690,8 @@
</span><span class="cx">                 C2181FC018A948FB0025A235 /* JSExportTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSExportTests.h; path = API/tests/JSExportTests.h; sourceTree = "<group>"; };
</span><span class="cx">                 C2181FC118A948FB0025A235 /* JSExportTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = JSExportTests.mm; path = API/tests/JSExportTests.mm; sourceTree = "<group>"; };
</span><span class="cx">                 C225494215F7DBAA0065E898 /* SlotVisitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SlotVisitor.cpp; sourceTree = "<group>"; };
</span><ins>+                C24D31E0161CD695002AA4DB /* HeapStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapStatistics.cpp; sourceTree = "<group>"; };
+                C24D31E1161CD695002AA4DB /* HeapStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapStatistics.h; sourceTree = "<group>"; };
</ins><span class="cx">                 C25D709916DE99F400FCA6BC /* JSManagedValue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JSManagedValue.mm; sourceTree = "<group>"; };
</span><span class="cx">                 C25D709A16DE99F400FCA6BC /* JSManagedValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSManagedValue.h; sourceTree = "<group>"; };
</span><span class="cx">                 C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IncrementalSweeper.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -5768,11 +5754,8 @@
</span><span class="cx">                                 0FD8A31117D4326C00CA2C40 /* CodeBlockSet.cpp */,
</span><span class="cx">                                 0FD8A31217D4326C00CA2C40 /* CodeBlockSet.h */,
</span><span class="cx">                                 0F664CE71DA304ED00B00A11 /* CodeBlockSetInlines.h */,
</span><del>-                                0FD0E5F11E46C8AD0006AB08 /* CollectingScope.h */,
</del><span class="cx">                                 0FA762001DB9242300B7A2FD /* CollectionScope.cpp */,
</span><span class="cx">                                 0FA762011DB9242300B7A2FD /* CollectionScope.h */,
</span><del>-                                0FD0E5E51E43D3470006AB08 /* CollectorPhase.cpp */,
-                                0FD0E5E61E43D3470006AB08 /* CollectorPhase.h */,
</del><span class="cx">                                 146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */,
</span><span class="cx">                                 149DAAF212EB559D0083B12B /* ConservativeRoots.h */,
</span><span class="cx">                                 0F7DF12F1E2970D50095951B /* ConstraintVolatility.h */,
</span><span class="lines">@@ -5790,12 +5773,8 @@
</span><span class="cx">                                 2AACE63A18CA5A0300ED0191 /* GCActivityCallback.cpp */,
</span><span class="cx">                                 2AACE63B18CA5A0300ED0191 /* GCActivityCallback.h */,
</span><span class="cx">                                 BCBE2CAD14E985AA000593AD /* GCAssertions.h */,
</span><del>-                                0FD0E5E71E43D3470006AB08 /* GCConductor.cpp */,
-                                0FD0E5E81E43D3470006AB08 /* GCConductor.h */,
</del><span class="cx">                                 0FB4767C1D99AEA7008EA6CB /* GCDeferralContext.h */,
</span><span class="cx">                                 0FB4767D1D99AEA7008EA6CB /* GCDeferralContextInlines.h */,
</span><del>-                                0F2C63A51E4F8FD100C13839 /* GCFinalizationCallback.cpp */,
-                                0F2C63A61E4F8FD100C13839 /* GCFinalizationCallback.h */,
</del><span class="cx">                                 0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */,
</span><span class="cx">                                 0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */,
</span><span class="cx">                                 0F2B66AA17B6B53D00A7AE3F /* GCIncomingRefCountedSet.h */,
</span><span class="lines">@@ -5829,11 +5808,14 @@
</span><span class="cx">                                 A54C2AAF1C6544D100A18D78 /* HeapSnapshot.h */,
</span><span class="cx">                                 A5311C341C77CEAC00E6B1B6 /* HeapSnapshotBuilder.cpp */,
</span><span class="cx">                                 A5311C351C77CEAC00E6B1B6 /* HeapSnapshotBuilder.h */,
</span><ins>+                                C24D31E0161CD695002AA4DB /* HeapStatistics.cpp */,
+                                C24D31E1161CD695002AA4DB /* HeapStatistics.h */,
</ins><span class="cx">                                 C2E526BB1590EF000054E48D /* HeapTimer.cpp */,
</span><span class="cx">                                 C2E526BC1590EF000054E48D /* HeapTimer.h */,
</span><span class="cx">                                 0FADE6721D4D23BC00768457 /* HeapUtil.h */,
</span><span class="cx">                                 FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */,
</span><span class="cx">                                 FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */,
</span><ins>+                                0FA762081DB9283C00B7A2FD /* HelpingGCScope.h */,
</ins><span class="cx">                                 C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */,
</span><span class="cx">                                 C25F8BCC157544A900245B71 /* IncrementalSweeper.h */,
</span><span class="cx">                                 0F766D2915A8CC34008F363E /* JITStubRoutineSet.cpp */,
</span><span class="lines">@@ -5871,9 +5853,7 @@
</span><span class="cx">                                 0FA762031DB9242300B7A2FD /* MutatorState.h */,
</span><span class="cx">                                 ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */,
</span><span class="cx">                                 0FBB73B61DEF3AAC002C009E /* PreventCollectionScope.h */,
</span><del>-                                0FD0E5EF1E46BF230006AB08 /* RegisterState.h */,
</del><span class="cx">                                 0F7CF94E1DBEEE860098CC12 /* ReleaseHeapAccessScope.h */,
</span><del>-                                0F2C63A91E4FA42C00C13839 /* RunningScope.h */,
</del><span class="cx">                                 C225494215F7DBAA0065E898 /* SlotVisitor.cpp */,
</span><span class="cx">                                 14BA78F013AAB88F005B7C2C /* SlotVisitor.h */,
</span><span class="cx">                                 0FCB408515C0A3C30048932B /* SlotVisitorInlines.h */,
</span><span class="lines">@@ -5888,7 +5868,6 @@
</span><span class="cx">                                 0F7DF1311E2970D50095951B /* Subspace.cpp */,
</span><span class="cx">                                 0F7DF1321E2970D50095951B /* Subspace.h */,
</span><span class="cx">                                 0F7DF1331E2970D50095951B /* SubspaceInlines.h */,
</span><del>-                                0FD0E5ED1E468A540006AB08 /* SweepingScope.h */,
</del><span class="cx">                                 0F1FB38A1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp */,
</span><span class="cx">                                 0F1FB38B1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h */,
</span><span class="cx">                                 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */,
</span><span class="lines">@@ -8009,7 +7988,6 @@
</span><span class="cx">                                 0F6B8AE31C4EFE1700969052 /* B3BreakCriticalEdges.h in Headers */,
</span><span class="cx">                                 DC9A0C201D2D9CB30085124E /* B3CaseCollection.h in Headers */,
</span><span class="cx">                                 DC9A0C1F1D2D9CB10085124E /* B3CaseCollectionInlines.h in Headers */,
</span><del>-                                0FD0E5EE1E468A570006AB08 /* SweepingScope.h in Headers */,
</del><span class="cx">                                 0F338DFA1BE96AA80013C88F /* B3CCallValue.h in Headers */,
</span><span class="cx">                                 0F33FCFB1C1625BE00323F67 /* B3CFG.h in Headers */,
</span><span class="cx">                                 0FEC85061BDACDAC0080FF74 /* B3CheckSpecial.h in Headers */,
</span><span class="lines">@@ -8285,7 +8263,6 @@
</span><span class="cx">                                 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */,
</span><span class="cx">                                 0F2017801DCADC3500EA5950 /* DFGFlowIndexing.h in Headers */,
</span><span class="cx">                                 0F2017821DCADD4200EA5950 /* DFGFlowMap.h in Headers */,
</span><del>-                                0F2C63AA1E4FA42E00C13839 /* RunningScope.h in Headers */,
</del><span class="cx">                                 0F9D339717FFC4E60073C2BC /* DFGFlushedAt.h in Headers */,
</span><span class="cx">                                 A7D89CF817A0B8CC00773AD8 /* DFGFlushFormat.h in Headers */,
</span><span class="cx">                                 0F2DD8151AB3D8BE00BBB8E8 /* DFGForAllKills.h in Headers */,
</span><span class="lines">@@ -8578,10 +8555,11 @@
</span><span class="cx">                                 A5398FAB1C750DA40060A963 /* HeapProfiler.h in Headers */,
</span><span class="cx">                                 A54C2AB11C6544F200A18D78 /* HeapSnapshot.h in Headers */,
</span><span class="cx">                                 A5311C361C77CEC500E6B1B6 /* HeapSnapshotBuilder.h in Headers */,
</span><ins>+                                C24D31E3161CD695002AA4DB /* HeapStatistics.h in Headers */,
</ins><span class="cx">                                 C2E526BE1590EF000054E48D /* HeapTimer.h in Headers */,
</span><del>-                                0FD0E5EA1E43D34D0006AB08 /* GCConductor.h in Headers */,
</del><span class="cx">                                 0FADE6731D4D23BE00768457 /* HeapUtil.h in Headers */,
</span><span class="cx">                                 FE7BA6101A1A7CEC00F1F7B4 /* HeapVerifier.h in Headers */,
</span><ins>+                                0FA762091DB9283E00B7A2FD /* HelpingGCScope.h in Headers */,
</ins><span class="cx">                                 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */,
</span><span class="cx">                                 DC2143071CA32E55000A8869 /* ICStats.h in Headers */,
</span><span class="cx">                                 BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */,
</span><span class="lines">@@ -8642,7 +8620,6 @@
</span><span class="cx">                                 A1B9E23E1B4E0D6700BC7FED /* IntlCollatorPrototype.h in Headers */,
</span><span class="cx">                                 A18193E41B4E0CDB00FC1029 /* IntlCollatorPrototype.lut.h in Headers */,
</span><span class="cx">                                 A1587D6E1B4DC14100D69849 /* IntlDateTimeFormat.h in Headers */,
</span><del>-                                0FD0E5E91E43D3490006AB08 /* CollectorPhase.h in Headers */,
</del><span class="cx">                                 A1587D701B4DC14100D69849 /* IntlDateTimeFormatConstructor.h in Headers */,
</span><span class="cx">                                 A1587D751B4DC1C600D69849 /* IntlDateTimeFormatConstructor.lut.h in Headers */,
</span><span class="cx">                                 A1587D721B4DC14100D69849 /* IntlDateTimeFormatPrototype.h in Headers */,
</span><span class="lines">@@ -8652,7 +8629,6 @@
</span><span class="cx">                                 A125846E1B45A36000CC7F6C /* IntlNumberFormatConstructor.lut.h in Headers */,
</span><span class="cx">                                 A1D793011B43864B004516F5 /* IntlNumberFormatPrototype.h in Headers */,
</span><span class="cx">                                 A125846F1B45A36000CC7F6C /* IntlNumberFormatPrototype.lut.h in Headers */,
</span><del>-                                0FD0E5F01E46BF250006AB08 /* RegisterState.h in Headers */,
</del><span class="cx">                                 A12BBFF21B044A8B00664B69 /* IntlObject.h in Headers */,
</span><span class="cx">                                 708EBE241CE8F35800453146 /* IntlObjectInlines.h in Headers */,
</span><span class="cx">                                 860BD801148EA6F200112B2F /* Intrinsic.h in Headers */,
</span><span class="lines">@@ -9118,7 +9094,6 @@
</span><span class="cx">                                 2AAAA31218BD49D100394CC8 /* StructureIDBlob.h in Headers */,
</span><span class="cx">                                 2AF7382D18BBBF92008A5A37 /* StructureIDTable.h in Headers */,
</span><span class="cx">                                 0FD2C92416D01EE900C7803F /* StructureInlines.h in Headers */,
</span><del>-                                0F2C63A81E4F8FD500C13839 /* GCFinalizationCallback.h in Headers */,
</del><span class="cx">                                 C2FE18A416BAEC4000AF3061 /* StructureRareData.h in Headers */,
</span><span class="cx">                                 C20BA92D16BB1C1500B3AEA2 /* StructureRareDataInlines.h in Headers */,
</span><span class="cx">                                 0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */,
</span><span class="lines">@@ -9234,7 +9209,6 @@
</span><span class="cx">                                 AD2FCBED1DB58DAD00B3E736 /* WebAssemblyCompileErrorConstructor.h in Headers */,
</span><span class="cx">                                 AD2FCC161DB59CB200B3E736 /* WebAssemblyCompileErrorConstructor.lut.h in Headers */,
</span><span class="cx">                                 AD2FCBEF1DB58DAD00B3E736 /* WebAssemblyCompileErrorPrototype.h in Headers */,
</span><del>-                                0FD0E5F21E46C8AF0006AB08 /* CollectingScope.h in Headers */,
</del><span class="cx">                                 AD2FCC171DB59CB200B3E736 /* WebAssemblyCompileErrorPrototype.lut.h in Headers */,
</span><span class="cx">                                 AD4937D41DDD27DE0077C807 /* WebAssemblyFunction.h in Headers */,
</span><span class="cx">                                 AD2FCBF11DB58DAD00B3E736 /* WebAssemblyInstanceConstructor.h in Headers */,
</span><span class="lines">@@ -10209,6 +10183,7 @@
</span><span class="cx">                                 A5398FAC1C750DA60060A963 /* HeapProfiler.cpp in Sources */,
</span><span class="cx">                                 A54C2AB01C6544EE00A18D78 /* HeapSnapshot.cpp in Sources */,
</span><span class="cx">                                 A5311C371C77CECA00E6B1B6 /* HeapSnapshotBuilder.cpp in Sources */,
</span><ins>+                                C24D31E2161CD695002AA4DB /* HeapStatistics.cpp in Sources */,
</ins><span class="cx">                                 C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */,
</span><span class="cx">                                 FE7BA60F1A1A7CEC00F1F7B4 /* HeapVerifier.cpp in Sources */,
</span><span class="cx">                                 0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */,
</span><span class="lines">@@ -10273,7 +10248,6 @@
</span><span class="cx">                                 0FAF7EFD165BA91B000C8455 /* JITDisassembler.cpp in Sources */,
</span><span class="cx">                                 FE187A0E1C030D640038BBCA /* JITDivGenerator.cpp in Sources */,
</span><span class="cx">                                 0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */,
</span><del>-                                0FD0E5EB1E43D3500006AB08 /* CollectorPhase.cpp in Sources */,
</del><span class="cx">                                 0FB14E1E18124ACE009B6B4D /* JITInlineCacheGenerator.cpp in Sources */,
</span><span class="cx">                                 FE3A06BD1C11040D00390FDD /* JITLeftShiftGenerator.cpp in Sources */,
</span><span class="cx">                                 FE187A011BFBE55E0038BBCA /* JITMulGenerator.cpp in Sources */,
</span><span class="lines">@@ -10521,7 +10495,6 @@
</span><span class="cx">                                 6540C7A01B82E1C3000F6B79 /* RegisterAtOffset.cpp in Sources */,
</span><span class="cx">                                 6540C7A11B82E1C3000F6B79 /* RegisterAtOffsetList.cpp in Sources */,
</span><span class="cx">                                 0FC3141518146D7000033232 /* RegisterSet.cpp in Sources */,
</span><del>-                                0FD0E5EC1E43D3530006AB08 /* GCConductor.cpp in Sources */,
</del><span class="cx">                                 A57D23ED1891B5540031C7FA /* RegularExpression.cpp in Sources */,
</span><span class="cx">                                 992ABCF91BEA9BD2006403A0 /* RemoteAutomationTarget.cpp in Sources */,
</span><span class="cx">                                 992F56B41E4E84A40035953B /* RemoteConnectionToTargetCocoa.mm in Sources */,
</span><span class="lines">@@ -10584,7 +10557,6 @@
</span><span class="cx">                                 705B41AB1A6E501E00716757 /* Symbol.cpp in Sources */,
</span><span class="cx">                                 705B41AD1A6E501E00716757 /* SymbolConstructor.cpp in Sources */,
</span><span class="cx">                                 705B41AF1A6E501E00716757 /* SymbolObject.cpp in Sources */,
</span><del>-                                0F2C63A71E4F8FD300C13839 /* GCFinalizationCallback.cpp in Sources */,
</del><span class="cx">                                 705B41B11A6E501E00716757 /* SymbolPrototype.cpp in Sources */,
</span><span class="cx">                                 0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */,
</span><span class="cx">                                 0F1FB38E1E173A6500A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -2532,12 +2532,7 @@
</span><span class="cx"> visitor.reportExtraMemoryVisited(m_jitCode->size());
</span><span class="cx"> if (m_instructions.size()) {
</span><span class="cx"> unsigned refCount = m_instructions.refCount();
</span><del>- if (!refCount) {
- dataLog("CodeBlock: ", RawPointer(this), "\n");
- dataLog("m_instructions.data(): ", RawPointer(m_instructions.data()), "\n");
- dataLog("refCount: ", refCount, "\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
</del><ins>+ RELEASE_ASSERT(refCount);
</ins><span class="cx"> visitor.reportExtraMemoryVisited(m_instructions.size() * sizeof(Instruction) / refCount);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGWorklistcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx">
</span><span class="cx"> class Worklist::ThreadBody : public AutomaticThread {
</span><span class="cx"> public:
</span><del>- ThreadBody(const AbstractLocker& locker, Worklist& worklist, ThreadData& data, Box<Lock> lock, RefPtr<AutomaticThreadCondition> condition, int relativePriority)
</del><ins>+ ThreadBody(const LockHolder& locker, Worklist& worklist, ThreadData& data, Box<Lock> lock, RefPtr<AutomaticThreadCondition> condition, int relativePriority)
</ins><span class="cx"> : AutomaticThread(locker, lock, condition)
</span><span class="cx"> , m_worklist(worklist)
</span><span class="cx"> , m_data(data)
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> protected:
</span><del>- PollResult poll(const AbstractLocker& locker) override
</del><ins>+ PollResult poll(const LockHolder& locker) override
</ins><span class="cx"> {
</span><span class="cx"> if (m_worklist.m_queue.isEmpty())
</span><span class="cx"> return PollResult::Wait;
</span><span class="lines">@@ -150,7 +150,7 @@
</span><span class="cx"> m_longLivedState = std::make_unique<LongLivedState>();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void threadIsStopping(const AbstractLocker&) override
</del><ins>+ void threadIsStopping(const LockHolder&) override
</ins><span class="cx"> {
</span><span class="cx"> // We're holding the Worklist::m_lock, so we should be careful not to deadlock.
</span><span class="cx">
</span><span class="lines">@@ -479,7 +479,7 @@
</span><span class="cx"> dump(locker, out);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Worklist::dump(const AbstractLocker&, PrintStream& out) const
</del><ins>+void Worklist::dump(const LockHolder&, PrintStream& out) const
</ins><span class="cx"> {
</span><span class="cx"> out.print(
</span><span class="cx"> "Worklist(", RawPointer(this), ")[Queue Length = ", m_queue.size(),
</span><span class="lines">@@ -535,41 +535,6 @@
</span><span class="cx"> return ensureGlobalDFGWorklist();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-unsigned numberOfWorklists() { return 2; }
-
-Worklist& ensureWorklistForIndex(unsigned index)
-{
- switch (index) {
- case 0:
- return ensureGlobalDFGWorklist();
- case 1:
- return ensureGlobalFTLWorklist();
- default:
- RELEASE_ASSERT_NOT_REACHED();
- return ensureGlobalDFGWorklist();
- }
-}
-
-Worklist* existingWorklistForIndexOrNull(unsigned index)
-{
- switch (index) {
- case 0:
- return existingGlobalDFGWorklistOrNull();
- case 1:
- return existingGlobalFTLWorklistOrNull();
- default:
- RELEASE_ASSERT_NOT_REACHED();
- return 0;
- }
-}
-
-Worklist& existingWorklistForIndex(unsigned index)
-{
- Worklist* result = existingWorklistForIndexOrNull(index);
- RELEASE_ASSERT(result);
- return *result;
-}
-
</del><span class="cx"> void completeAllPlansForVM(VM& vm)
</span><span class="cx"> {
</span><span class="cx"> for (unsigned i = DFG::numberOfWorklists(); i--;) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGWorklisth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGWorklist.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGWorklist.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/dfg/DFGWorklist.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -93,7 +93,7 @@
</span><span class="cx">
</span><span class="cx"> void removeAllReadyPlansForVM(VM&, Vector<RefPtr<Plan>, 8>&);
</span><span class="cx">
</span><del>- void dump(const AbstractLocker&, PrintStream&) const;
</del><ins>+ void dump(const LockHolder&, PrintStream&) const;
</ins><span class="cx">
</span><span class="cx"> CString m_threadName;
</span><span class="cx">
</span><span class="lines">@@ -132,10 +132,37 @@
</span><span class="cx"> Worklist& ensureGlobalWorklistFor(CompilationMode);
</span><span class="cx">
</span><span class="cx"> // Simplify doing things for all worklists.
</span><del>-unsigned numberOfWorklists();
-Worklist& ensureWorklistForIndex(unsigned index);
-Worklist* existingWorklistForIndexOrNull(unsigned index);
-Worklist& existingWorklistForIndex(unsigned index);
</del><ins>+inline unsigned numberOfWorklists() { return 2; }
+inline Worklist& ensureWorklistForIndex(unsigned index)
+{
+ switch (index) {
+ case 0:
+ return ensureGlobalDFGWorklist();
+ case 1:
+ return ensureGlobalFTLWorklist();
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return ensureGlobalDFGWorklist();
+ }
+}
+inline Worklist* existingWorklistForIndexOrNull(unsigned index)
+{
+ switch (index) {
+ case 0:
+ return existingGlobalDFGWorklistOrNull();
+ case 1:
+ return existingGlobalFTLWorklistOrNull();
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return 0;
+ }
+}
+inline Worklist& existingWorklistForIndex(unsigned index)
+{
+ Worklist* result = existingWorklistForIndexOrNull(index);
+ RELEASE_ASSERT(result);
+ return *result;
+}
</ins><span class="cx">
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCollectingScopeh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/CollectingScope.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CollectingScope.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/CollectingScope.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,52 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
- */
-
-#pragma once
-
-#include "Heap.h"
-
-namespace JSC {
-
-class CollectingScope {
-public:
- CollectingScope(Heap& heap)
- : m_heap(heap)
- , m_oldState(m_heap.m_mutatorState)
- {
- m_heap.m_mutatorState = MutatorState::Collecting;
- }
-
- ~CollectingScope()
- {
- m_heap.m_mutatorState = m_oldState;
- }
-
-private:
- Heap& m_heap;
- MutatorState m_oldState;
-};
-
-} // namespace JSC
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCollectorPhasecpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/CollectorPhase.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CollectorPhase.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/CollectorPhase.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,84 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
- */
-
-#include "config.h"
-#include "CollectorPhase.h"
-
-#include <wtf/PrintStream.h>
-
-namespace JSC {
-
-bool worldShouldBeSuspended(CollectorPhase phase)
-{
- switch (phase) {
- case CollectorPhase::NotRunning:
- case CollectorPhase::Concurrent:
- return false;
-
- case CollectorPhase::Begin:
- case CollectorPhase::Fixpoint:
- case CollectorPhase::Reloop:
- case CollectorPhase::End:
- return true;
- }
-
- RELEASE_ASSERT_NOT_REACHED();
- return false;
-}
-
-} // namespace JSC
-
-namespace WTF {
-
-using namespace JSC;
-
-void printInternal(PrintStream& out, JSC::CollectorPhase phase)
-{
- switch (phase) {
- case CollectorPhase::NotRunning:
- out.print("NotRunning");
- return;
- case CollectorPhase::Begin:
- out.print("Begin");
- return;
- case CollectorPhase::Fixpoint:
- out.print("Fixpoint");
- return;
- case CollectorPhase::Concurrent:
- out.print("Concurrent");
- return;
- case CollectorPhase::Reloop:
- out.print("Reloop");
- return;
- case CollectorPhase::End:
- out.print("End");
- return;
- }
-
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-} // namespace WTF
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCollectorPhaseh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/CollectorPhase.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CollectorPhase.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/CollectorPhase.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,75 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
- */
-
-#pragma once
-
-namespace JSC {
-
-// We track collector phase in order to allow either the collector thread or the mutator thread to
-// jump in and do work. The collector and mutator trade the conn
-// (https://en.wikipedia.org/wiki/Conn_(nautical)) with each other based on who is available to do work,
-// and they use the phase to help each other know what to do once they take the conn.
-//
-// The collector relinquishes the conn whenever it stopTheMutator's and the mutator is running. Then the
-// collector thread goes to sleep.
-//
-// The mutator relinquishes the conn whenever it releaseAccess's. That wakes up the collector thread.
-enum class CollectorPhase : uint8_t {
- // We use this phase when the collector is not running at all. After this state is Begin.
- NotRunning,
-
- // This is everything from when the collector begins to when it first yields to the mutator for
- // marking. After this is Fixpoint.
- Begin,
-
- // This means that we should try to do some progress with the world stopped. This usually means
- // doing an iteration of MarkingConstraintSet::executeConvergence, but it could also mean marking
- // with the world stopped. After this is either Concurrent or End.
- Fixpoint,
-
- // In this state the collector is relying on the parallel helpers and incremental mutator work to
- // make progress. After this is Reloop, once marking stalls.
- Concurrent,
-
- // We did some concurrent marking and now we ran out of work. This phase prepares the GC for another
- // Fixpoint. After this is Fixpoint.
- Reloop,
-
- // The collector is trying to finish up. After this state is NotRunning.
- End
-};
-
-bool worldShouldBeSuspended(CollectorPhase phase);
-
-} // namespace JSC
-
-namespace WTF {
-
-class PrintStream;
-
-void printInternal(PrintStream&, JSC::CollectorPhase);
-
-} // namespace WTF
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapEdenGCActivityCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx">
</span><span class="cx"> double EdenGCActivityCallback::lastGCLength()
</span><span class="cx"> {
</span><del>- return m_vm->heap.lastEdenGCLength().seconds();
</del><ins>+ return m_vm->heap.lastEdenGCLength();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> double EdenGCActivityCallback::deathRate()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapFullGCActivityCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx"> double startTime = WTF::monotonicallyIncreasingTime();
</span><span class="cx"> if (heap.isPagedOut(startTime + pagingTimeOut)) {
</span><span class="cx"> cancel();
</span><del>- heap.increaseLastFullGCLength(Seconds(pagingTimeOut));
</del><ins>+ heap.increaseLastFullGCLength(pagingTimeOut);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx">
</span><span class="cx"> double FullGCActivityCallback::lastGCLength()
</span><span class="cx"> {
</span><del>- return m_vm->heap.lastFullGCLength().seconds();
</del><ins>+ return m_vm->heap.lastFullGCLength();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> double FullGCActivityCallback::deathRate()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCConductorcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/GCConductor.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCConductor.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/GCConductor.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,66 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
- */
-
-#include "config.h"
-#include "GCConductor.h"
-
-#include <wtf/PrintStream.h>
-
-namespace JSC {
-
-const char* gcConductorShortName(GCConductor conn)
-{
- switch (conn) {
- case GCConductor::Mutator:
- return "M";
- case GCConductor::Collector:
- return "C";
- }
-
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-} // namespace JSC
-
-namespace WTF {
-
-using namespace JSC;
-
-void printInternal(PrintStream& out, GCConductor conn)
-{
- switch (conn) {
- case GCConductor::Mutator:
- out.print("Mutator");
- return;
- case GCConductor::Collector:
- out.print("Collector");
- return;
- }
-
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-} // namespace WTF
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCConductorh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/GCConductor.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCConductor.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/GCConductor.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,49 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
- */
-
-#pragma once
-
-namespace JSC {
-
-// Either the mutator has the conn (https://en.wikipedia.org/wiki/Conn_(nautical)), meaning that the
-// mutator will incrementally drive the collector when it calls into slow paths; or the collector has the
-// conn, meaning that the collector thread will drive the collector.
-enum class GCConductor : uint8_t {
- Mutator,
- Collector
-};
-
-const char* gcConductorShortName(GCConductor officer);
-
-} // namespace JSC
-
-namespace WTF {
-
-class PrintStream;
-
-void printInternal(PrintStream&, JSC::GCConductor);
-
-} // namespace WTF
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCFinalizationCallbackcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/GCFinalizationCallback.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCFinalizationCallback.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/GCFinalizationCallback.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,40 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
- */
-
-#include "config.h"
-#include "GCFinalizationCallback.h"
-
-namespace JSC {
-
-GCFinalizationCallback::GCFinalizationCallback()
-{
-}
-
-GCFinalizationCallback::~GCFinalizationCallback()
-{
-}
-
-} // namespace JSC
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCFinalizationCallbackh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/GCFinalizationCallback.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCFinalizationCallback.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/GCFinalizationCallback.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,69 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
- */
-
-#pragma once
-
-#include <wtf/RefPtr.h>
-#include <wtf/ThreadSafeRefCounted.h>
-
-namespace JSC {
-
-class Heap;
-
-class JS_EXPORT_PRIVATE GCFinalizationCallback : public ThreadSafeRefCounted<GCFinalizationCallback> {
- WTF_MAKE_NONCOPYABLE(GCFinalizationCallback);
-
-public:
- GCFinalizationCallback();
- virtual ~GCFinalizationCallback();
-
- virtual void didFinalize(Heap&) = 0;
-};
-
-template<typename Func>
-class GCFinalizationCallbackFuncAdaptor : public GCFinalizationCallback {
-public:
- GCFinalizationCallbackFuncAdaptor(const Func& func)
- : m_func(func)
- {
- }
-
- void didFinalize(Heap& heap) override
- {
- m_func(this, heap);
- }
-
-private:
- Func m_func;
-};
-
-template<typename Func>
-RefPtr<GCFinalizationCallbackFuncAdaptor<Func>> createGCFinalizationCallback(const Func& func)
-{
- return adoptRef(new GCFinalizationCallbackFuncAdaptor<Func>(func));
-}
-
-} // namespace JSC
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -23,7 +23,6 @@
</span><span class="cx">
</span><span class="cx"> #include "CodeBlock.h"
</span><span class="cx"> #include "CodeBlockSetInlines.h"
</span><del>-#include "CollectingScope.h"
</del><span class="cx"> #include "ConservativeRoots.h"
</span><span class="cx"> #include "DFGWorklistInlines.h"
</span><span class="cx"> #include "EdenGCActivityCallback.h"
</span><span class="lines">@@ -30,7 +29,6 @@
</span><span class="cx"> #include "Exception.h"
</span><span class="cx"> #include "FullGCActivityCallback.h"
</span><span class="cx"> #include "GCActivityCallback.h"
</span><del>-#include "GCFinalizationCallback.h"
</del><span class="cx"> #include "GCIncomingRefCountedSetInlines.h"
</span><span class="cx"> #include "GCSegmentedArrayInlines.h"
</span><span class="cx"> #include "GCTypeMap.h"
</span><span class="lines">@@ -39,7 +37,9 @@
</span><span class="cx"> #include "HeapIterationScope.h"
</span><span class="cx"> #include "HeapProfiler.h"
</span><span class="cx"> #include "HeapSnapshot.h"
</span><ins>+#include "HeapStatistics.h"
</ins><span class="cx"> #include "HeapVerifier.h"
</span><ins>+#include "HelpingGCScope.h"
</ins><span class="cx"> #include "IncrementalSweeper.h"
</span><span class="cx"> #include "Interpreter.h"
</span><span class="cx"> #include "JITStubRoutineSet.h"
</span><span class="lines">@@ -48,7 +48,6 @@
</span><span class="cx"> #include "JSGlobalObject.h"
</span><span class="cx"> #include "JSLock.h"
</span><span class="cx"> #include "JSVirtualMachineInternal.h"
</span><del>-#include "MachineStackMarker.h"
</del><span class="cx"> #include "MarkedSpaceInlines.h"
</span><span class="cx"> #include "MarkingConstraintSet.h"
</span><span class="cx"> #include "PreventCollectionScope.h"
</span><span class="lines">@@ -58,7 +57,6 @@
</span><span class="cx"> #include "SuperSampler.h"
</span><span class="cx"> #include "StochasticSpaceTimeMutatorScheduler.h"
</span><span class="cx"> #include "StopIfNecessaryTimer.h"
</span><del>-#include "SweepingScope.h"
</del><span class="cx"> #include "SynchronousStopTheWorldMutatorScheduler.h"
</span><span class="cx"> #include "TypeProfilerLog.h"
</span><span class="cx"> #include "UnlinkedCodeBlock.h"
</span><span class="lines">@@ -208,7 +206,7 @@
</span><span class="cx">
</span><span class="cx"> class Heap::Thread : public AutomaticThread {
</span><span class="cx"> public:
</span><del>- Thread(const AbstractLocker& locker, Heap& heap)
</del><ins>+ Thread(const LockHolder& locker, Heap& heap)
</ins><span class="cx"> : AutomaticThread(locker, heap.m_threadLock, heap.m_threadCondition)
</span><span class="cx"> , m_heap(heap)
</span><span class="cx"> {
</span><span class="lines">@@ -215,13 +213,13 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> protected:
</span><del>- PollResult poll(const AbstractLocker& locker) override
</del><ins>+ PollResult poll(const LockHolder& locker) override
</ins><span class="cx"> {
</span><span class="cx"> if (m_heap.m_threadShouldStop) {
</span><span class="cx"> m_heap.notifyThreadStopping(locker);
</span><span class="cx"> return PollResult::Stop;
</span><span class="cx"> }
</span><del>- if (m_heap.shouldCollectInCollectorThread(locker))
</del><ins>+ if (m_heap.shouldCollectInThread(locker))
</ins><span class="cx"> return PollResult::Work;
</span><span class="cx"> return PollResult::Wait;
</span><span class="cx"> }
</span><span class="lines">@@ -228,7 +226,7 @@
</span><span class="cx">
</span><span class="cx"> WorkResult work() override
</span><span class="cx"> {
</span><del>- m_heap.collectInCollectorThread();
</del><ins>+ m_heap.collectInThread();
</ins><span class="cx"> return WorkResult::Continue;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -259,9 +257,9 @@
</span><span class="cx"> , m_objectSpace(this)
</span><span class="cx"> , m_extraMemorySize(0)
</span><span class="cx"> , m_deprecatedExtraMemorySize(0)
</span><del>- , m_machineThreads(std::make_unique<MachineThreads>(this))
- , m_collectorSlotVisitor(std::make_unique<SlotVisitor>(*this, "C"))
- , m_mutatorSlotVisitor(std::make_unique<SlotVisitor>(*this, "M"))
</del><ins>+ , m_machineThreads(this)
+ , m_collectorSlotVisitor(std::make_unique<SlotVisitor>(*this))
+ , m_mutatorSlotVisitor(std::make_unique<SlotVisitor>(*this))
</ins><span class="cx"> , m_mutatorMarkStack(std::make_unique<MarkStackArray>())
</span><span class="cx"> , m_raceMarkStack(std::make_unique<MarkStackArray>())
</span><span class="cx"> , m_constraintSet(std::make_unique<MarkingConstraintSet>())
</span><span class="lines">@@ -335,12 +333,6 @@
</span><span class="cx"> // Run all pending finalizers now because we won't get another chance.
</span><span class="cx"> void Heap::lastChanceToFinalize()
</span><span class="cx"> {
</span><del>- MonotonicTime before;
- if (Options::logGC()) {
- before = MonotonicTime::now();
- dataLog("[GC<", RawPointer(this), ">: shutdown ");
- }
-
</del><span class="cx"> RELEASE_ASSERT(!m_vm->entryScope);
</span><span class="cx"> RELEASE_ASSERT(m_mutatorState == MutatorState::Running);
</span><span class="cx">
</span><span class="lines">@@ -353,62 +345,26 @@
</span><span class="cx"> waitForThreadCompletion(m_collectContinuouslyThread);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (Options::logGC())
- dataLog("1");
-
- // Prevent new collections from being started. This is probably not even necessary, since we're not
- // going to call into anything that starts collections. Still, this makes the algorithm more
- // obviously sound.
- m_isSafeToCollect = false;
-
- if (Options::logGC())
- dataLog("2");
-
- bool isCollecting;
- {
- auto locker = holdLock(*m_threadLock);
- RELEASE_ASSERT(m_lastServedTicket <= m_lastGrantedTicket);
- isCollecting = m_lastServedTicket < m_lastGrantedTicket;
- }
- if (isCollecting) {
- if (Options::logGC())
- dataLog("...]\n");
-
- // Wait for the current collection to finish.
- waitForCollector(
- [&] (const AbstractLocker&) -> bool {
- RELEASE_ASSERT(m_lastServedTicket <= m_lastGrantedTicket);
- return m_lastServedTicket == m_lastGrantedTicket;
- });
-
- if (Options::logGC())
- dataLog("[GC<", RawPointer(this), ">: shutdown ");
- }
- if (Options::logGC())
- dataLog("3");
-
- RELEASE_ASSERT(m_requests.isEmpty());
- RELEASE_ASSERT(m_lastServedTicket == m_lastGrantedTicket);
-
- // Carefully bring the thread down.
</del><ins>+ // Carefully bring the thread down. We need to use waitForCollector() until we know that there
+ // won't be any other collections.
</ins><span class="cx"> bool stopped = false;
</span><span class="cx"> {
</span><span class="cx"> LockHolder locker(*m_threadLock);
</span><span class="cx"> stopped = m_thread->tryStop(locker);
</span><del>- m_threadShouldStop = true;
- if (!stopped)
</del><ins>+ if (!stopped) {
+ m_threadShouldStop = true;
</ins><span class="cx"> m_threadCondition->notifyOne(locker);
</span><ins>+ }
</ins><span class="cx"> }
</span><del>-
- if (Options::logGC())
- dataLog("4");
-
- if (!stopped)
</del><ins>+ if (!stopped) {
+ waitForCollector(
+ [&] (const LockHolder&) -> bool {
+ return m_threadIsStopping;
+ });
+ // It's now safe to join the thread, since we know that there will not be any more collections.
</ins><span class="cx"> m_thread->join();
</span><ins>+ }
</ins><span class="cx">
</span><del>- if (Options::logGC())
- dataLog("5 ");
-
</del><span class="cx"> m_arrayBuffers.lastChanceToFinalize();
</span><span class="cx"> m_codeBlocks->lastChanceToFinalize(*m_vm);
</span><span class="cx"> m_objectSpace.stopAllocating();
</span><span class="lines">@@ -416,9 +372,6 @@
</span><span class="cx"> releaseDelayedReleasedObjects();
</span><span class="cx">
</span><span class="cx"> sweepAllLogicallyEmptyWeakBlocks();
</span><del>-
- if (Options::logGC())
- dataLog((MonotonicTime::now() - before).milliseconds(), "ms]\n");
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void Heap::releaseDelayedReleasedObjects()
</span><span class="lines">@@ -572,9 +525,186 @@
</span><span class="cx"> RELEASE_ASSERT(ok);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void Heap::markToFixpoint(double gcStartTime)
+{
+ TimingScope markToFixpointTimingScope(*this, "Heap::markToFixpoint");
+
+ if (m_collectionScope == CollectionScope::Full) {
+ m_opaqueRoots.clear();
+ m_collectorSlotVisitor->clearMarkStacks();
+ m_mutatorMarkStack->clear();
+ }
+
+ RELEASE_ASSERT(m_raceMarkStack->isEmpty());
+
+ beginMarking();
+
+ forEachSlotVisitor(
+ [&] (SlotVisitor& visitor) {
+ visitor.didStartMarking();
+ });
+
+ m_parallelMarkersShouldExit = false;
+
+ m_helperClient.setFunction(
+ [this] () {
+ SlotVisitor* slotVisitor;
+ {
+ LockHolder locker(m_parallelSlotVisitorLock);
+ if (m_availableParallelSlotVisitors.isEmpty()) {
+ std::unique_ptr<SlotVisitor> newVisitor =
+ std::make_unique<SlotVisitor>(*this);
+
+ if (Options::optimizeParallelSlotVisitorsForStoppedMutator())
+ newVisitor->optimizeForStoppedMutator();
+
+ newVisitor->didStartMarking();
+
+ slotVisitor = newVisitor.get();
+ m_parallelSlotVisitors.append(WTFMove(newVisitor));
+ } else
+ slotVisitor = m_availableParallelSlotVisitors.takeLast();
+ }
+
+ WTF::registerGCThread(GCThreadType::Helper);
+
+ {
+ ParallelModeEnabler parallelModeEnabler(*slotVisitor);
+ slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
+ }
+
+ {
+ LockHolder locker(m_parallelSlotVisitorLock);
+ m_availableParallelSlotVisitors.append(slotVisitor);
+ }
+ });
+
+ SlotVisitor& slotVisitor = *m_collectorSlotVisitor;
+
+ m_constraintSet->didStartMarking();
+
+ m_scheduler->beginCollection();
+ if (Options::logGC())
+ m_scheduler->log();
+
+ // After this, we will almost certainly fall through all of the "slotVisitor.isEmpty()"
+ // checks because bootstrap would have put things into the visitor. So, we should fall
+ // through to draining.
+
+ if (!slotVisitor.didReachTermination()) {
+ dataLog("Fatal: SlotVisitor should think that GC should terminate before constraint solving, but it does not think this.\n");
+ dataLog("slotVisitor.isEmpty(): ", slotVisitor.isEmpty(), "\n");
+ dataLog("slotVisitor.collectorMarkStack().isEmpty(): ", slotVisitor.collectorMarkStack().isEmpty(), "\n");
+ dataLog("slotVisitor.mutatorMarkStack().isEmpty(): ", slotVisitor.mutatorMarkStack().isEmpty(), "\n");
+ dataLog("m_numberOfActiveParallelMarkers: ", m_numberOfActiveParallelMarkers, "\n");
+ dataLog("m_sharedCollectorMarkStack->isEmpty(): ", m_sharedCollectorMarkStack->isEmpty(), "\n");
+ dataLog("m_sharedMutatorMarkStack->isEmpty(): ", m_sharedMutatorMarkStack->isEmpty(), "\n");
+ dataLog("slotVisitor.didReachTermination(): ", slotVisitor.didReachTermination(), "\n");
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ for (;;) {
+ if (Options::logGC())
+ dataLog("v=", bytesVisited() / 1024, "kb o=", m_opaqueRoots.size(), " b=", m_barriersExecuted, " ");
+
+ if (slotVisitor.didReachTermination()) {
+ m_scheduler->didReachTermination();
+
+ assertSharedMarkStacksEmpty();
+
+ slotVisitor.mergeIfNecessary();
+ for (auto& parallelVisitor : m_parallelSlotVisitors)
+ parallelVisitor->mergeIfNecessary();
+
+ // FIXME: Take m_mutatorDidRun into account when scheduling constraints. Most likely,
+ // we don't have to execute root constraints again unless the mutator did run. At a
+ // minimum, we could use this for work estimates - but it's probably more than just an
+ // estimate.
+ // https://bugs.webkit.org/show_bug.cgi?id=166828
+
+ // FIXME: We should take advantage of the fact that we could timeout. This only comes
+ // into play if we're executing constraints for the first time. But that will matter
+ // when we have deep stacks or a lot of DOM stuff.
+ // https://bugs.webkit.org/show_bug.cgi?id=166831
+
+ // Wondering what this does? Look at Heap::addCoreConstraints(). The DOM and others can also
+ // add their own using Heap::addMarkingConstraint().
+ bool converged =
+ m_constraintSet->executeConvergence(slotVisitor, MonotonicTime::infinity());
+ if (converged && slotVisitor.isEmpty()) {
+ assertSharedMarkStacksEmpty();
+ break;
+ }
+
+ m_scheduler->didExecuteConstraints();
+ }
+
+ if (Options::logGC())
+ dataLog(slotVisitor.collectorMarkStack().size(), "+", m_mutatorMarkStack->size() + slotVisitor.mutatorMarkStack().size(), " ");
+
+ {
+ ParallelModeEnabler enabler(slotVisitor);
+ slotVisitor.drainInParallel(m_scheduler->timeToResume());
+ }
+
+ m_scheduler->synchronousDrainingDidStall();
+
+ if (slotVisitor.didReachTermination())
+ continue;
+
+ if (!m_scheduler->shouldResume())
+ continue;
+
+ m_scheduler->willResume();
+
+ if (Options::logGC()) {
+ double thisPauseMS = (MonotonicTime::now() - m_stopTime).milliseconds();
+ dataLog("p=", thisPauseMS, "ms (max ", maxPauseMS(thisPauseMS), ")...]\n");
+ }
+
+ // Forgive the mutator for its past failures to keep up.
+ // FIXME: Figure out if moving this to different places results in perf changes.
+ m_incrementBalance = 0;
+
+ resumeTheWorld();
+
+ {
+ ParallelModeEnabler enabler(slotVisitor);
+ slotVisitor.drainInParallelPassively(m_scheduler->timeToStop());
+ }
+
+ stopTheWorld();
+
+ if (Options::logGC())
+ dataLog("[GC: ");
+
+ m_scheduler->didStop();
+
+ if (Options::logGC())
+ m_scheduler->log();
+ }
+
+ m_scheduler->endCollection();
+
+ {
+ std::lock_guard<Lock> lock(m_markingMutex);
+ m_parallelMarkersShouldExit = true;
+ m_markingConditionVariable.notifyAll();
+ }
+ m_helperClient.finish();
+
+ iterateExecutingAndCompilingCodeBlocks(
+ [&] (CodeBlock* codeBlock) {
+ writeBarrier(codeBlock);
+ });
+
+ updateObjectCounts(gcStartTime);
+ endMarking();
+}
+
</ins><span class="cx"> void Heap::gatherStackRoots(ConservativeRoots& roots)
</span><span class="cx"> {
</span><del>- m_machineThreads->gatherConservativeRoots(roots, *m_jitStubRoutines, *m_codeBlocks, m_currentThreadState);
</del><ins>+ m_machineThreads.gatherConservativeRoots(roots, *m_jitStubRoutines, *m_codeBlocks);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void Heap::gatherJSStackRoots(ConservativeRoots& roots)
</span><span class="lines">@@ -674,8 +804,12 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Heap::updateObjectCounts()
</del><ins>+void Heap::updateObjectCounts(double gcStartTime)
</ins><span class="cx"> {
</span><ins>+ if (Options::logGC() == GCLogging::Verbose) {
+ dataLogF("\nNumber of live Objects after GC %lu, took %.6f secs\n", static_cast<unsigned long>(visitCount()), WTF::monotonicallyIncreasingTime() - gcStartTime);
+ }
+
</ins><span class="cx"> if (m_collectionScope == CollectionScope::Full)
</span><span class="cx"> m_totalBytesVisited = 0;
</span><span class="cx">
</span><span class="lines">@@ -899,7 +1033,7 @@
</span><span class="cx"> {
</span><span class="cx"> double before = 0;
</span><span class="cx"> if (Options::logGC()) {
</span><del>- dataLog("Full sweep: ", capacity() / 1024, "kb ");
</del><ins>+ dataLog("[Full sweep: ", capacity() / 1024, "kb ");
</ins><span class="cx"> before = currentTimeMS();
</span><span class="cx"> }
</span><span class="cx"> m_objectSpace.sweep();
</span><span class="lines">@@ -906,7 +1040,7 @@
</span><span class="cx"> m_objectSpace.shrink();
</span><span class="cx"> if (Options::logGC()) {
</span><span class="cx"> double after = currentTimeMS();
</span><del>- dataLog("=> ", capacity() / 1024, "kb, ", after - before, "ms");
</del><ins>+ dataLog("=> ", capacity() / 1024, "kb, ", after - before, "ms] ");
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -919,15 +1053,13 @@
</span><span class="cx">
</span><span class="cx"> DeferGCForAWhile deferGC(*this);
</span><span class="cx"> if (UNLIKELY(Options::useImmortalObjects()))
</span><del>- sweeper()->stopSweeping();
</del><ins>+ sweeper()->willFinishSweeping();
</ins><span class="cx">
</span><span class="cx"> bool alreadySweptInCollectSync = Options::sweepSynchronously();
</span><span class="cx"> if (!alreadySweptInCollectSync) {
</span><del>- if (Options::logGC())
- dataLog("[GC<", RawPointer(this), ">: ");
</del><span class="cx"> sweepSynchronously();
</span><span class="cx"> if (Options::logGC())
</span><del>- dataLog("]\n");
</del><ins>+ dataLog("\n");
</ins><span class="cx"> }
</span><span class="cx"> m_objectSpace.assertNoUnswept();
</span><span class="cx">
</span><span class="lines">@@ -976,109 +1108,18 @@
</span><span class="cx"> waitForCollection(requestCollection(scope));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool Heap::shouldCollectInCollectorThread(const AbstractLocker&)
</del><ins>+bool Heap::shouldCollectInThread(const LockHolder&)
</ins><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT(m_requests.isEmpty() == (m_lastServedTicket == m_lastGrantedTicket));
</span><span class="cx"> RELEASE_ASSERT(m_lastServedTicket <= m_lastGrantedTicket);
</span><span class="cx">
</span><del>- if (false)
- dataLog("Mutator has the conn = ", !!(m_worldState.load() & mutatorHasConnBit), "\n");
-
- return !m_requests.isEmpty() && !(m_worldState.load() & mutatorHasConnBit);
</del><ins>+ return !m_requests.isEmpty();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void Heap::collectInCollectorThread()
</del><ins>+void Heap::collectInThread()
</ins><span class="cx"> {
</span><del>- for (;;) {
- RunCurrentPhaseResult result = runCurrentPhase(GCConductor::Collector, nullptr);
- switch (result) {
- case RunCurrentPhaseResult::Finished:
- return;
- case RunCurrentPhaseResult::Continue:
- break;
- case RunCurrentPhaseResult::NeedCurrentThreadState:
- RELEASE_ASSERT_NOT_REACHED();
- break;
- }
- }
-}
-
-void Heap::checkConn(GCConductor conn)
-{
- switch (conn) {
- case GCConductor::Mutator:
- RELEASE_ASSERT(m_worldState.load() & mutatorHasConnBit);
- return;
- case GCConductor::Collector:
- RELEASE_ASSERT(!(m_worldState.load() & mutatorHasConnBit));
- return;
- }
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-auto Heap::runCurrentPhase(GCConductor conn, CurrentThreadState* currentThreadState) -> RunCurrentPhaseResult
-{
- checkConn(conn);
- m_currentThreadState = currentThreadState;
</del><ins>+ m_currentGCStartTime = MonotonicTime::now();
</ins><span class="cx">
</span><del>- // If the collector transfers the conn to the mutator, it leaves us in between phases.
- if (!finishChangingPhase(conn)) {
- // A mischevious mutator could repeatedly relinquish the conn back to us. We try to avoid doing
- // this, but it's probably not the end of the world if it did happen.
- if (false)
- dataLog("Conn bounce-back.\n");
- return RunCurrentPhaseResult::Finished;
- }
-
- bool result = false;
- switch (m_currentPhase) {
- case CollectorPhase::NotRunning:
- result = runNotRunningPhase(conn);
- break;
-
- case CollectorPhase::Begin:
- result = runBeginPhase(conn);
- break;
-
- case CollectorPhase::Fixpoint:
- if (!currentThreadState && conn == GCConductor::Mutator)
- return RunCurrentPhaseResult::NeedCurrentThreadState;
-
- result = runFixpointPhase(conn);
- break;
-
- case CollectorPhase::Concurrent:
- result = runConcurrentPhase(conn);
- break;
-
- case CollectorPhase::Reloop:
- result = runReloopPhase(conn);
- break;
-
- case CollectorPhase::End:
- result = runEndPhase(conn);
- break;
- }
-
- return result ? RunCurrentPhaseResult::Continue : RunCurrentPhaseResult::Finished;
-}
-
-NEVER_INLINE bool Heap::runNotRunningPhase(GCConductor conn)
-{
- // Check m_requests since the mutator calls this to poll what's going on.
- {
- auto locker = holdLock(*m_threadLock);
- if (m_requests.isEmpty())
- return false;
- }
-
- return changePhase(conn, CollectorPhase::Begin);
-}
-
-NEVER_INLINE bool Heap::runBeginPhase(GCConductor conn)
-{
- m_currentGCStartTime = MonotonicTime::now();
-
</del><span class="cx"> std::optional<CollectionScope> scope;
</span><span class="cx"> {
</span><span class="cx"> LockHolder locker(*m_threadLock);
</span><span class="lines">@@ -1085,19 +1126,37 @@
</span><span class="cx"> RELEASE_ASSERT(!m_requests.isEmpty());
</span><span class="cx"> scope = m_requests.first();
</span><span class="cx"> }
</span><del>-
- if (Options::logGC())
- dataLog("[GC<", RawPointer(this), ">: START ", gcConductorShortName(conn), " ", capacity() / 1024, "kb ");
</del><ins>+
+ SuperSamplerScope superSamplerScope(false);
+ TimingScope collectImplTimingScope(scope, "Heap::collectInThread");
+
+#if ENABLE(ALLOCATION_LOGGING)
+ dataLogF("JSC GC starting collection.\n");
+#endif
+
+ stopTheWorld();
+
+ if (false)
+ dataLog("GC START!\n");
</ins><span class="cx">
</span><del>- m_beforeGC = MonotonicTime::now();
-
</del><ins>+ MonotonicTime before;
+ if (Options::logGC()) {
+ dataLog("[GC: START ", capacity() / 1024, "kb ");
+ before = MonotonicTime::now();
+ }
+
+ double gcStartTime;
+
+ ASSERT(m_isSafeToCollect);
</ins><span class="cx"> if (m_collectionScope) {
</span><span class="cx"> dataLog("Collection scope already set during GC: ", *m_collectionScope, "\n");
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> willStartCollection(scope);
</span><del>-
</del><ins>+ collectImplTimingScope.setScope(*this);
+
+ gcStartTime = WTF::monotonicallyIncreasingTime();
</ins><span class="cx"> if (m_verifier) {
</span><span class="cx"> // Verify that live objects from the last GC cycle haven't been corrupted by
</span><span class="cx"> // mutators before we begin this new GC cycle.
</span><span class="lines">@@ -1106,232 +1165,11 @@
</span><span class="cx"> m_verifier->initializeGCCycle();
</span><span class="cx"> m_verifier->gatherLiveObjects(HeapVerifier::Phase::BeforeMarking);
</span><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> prepareForMarking();
</span><del>-
- if (m_collectionScope == CollectionScope::Full) {
- m_opaqueRoots.clear();
- m_collectorSlotVisitor->clearMarkStacks();
- m_mutatorMarkStack->clear();
- }
-
- RELEASE_ASSERT(m_raceMarkStack->isEmpty());
-
- beginMarking();
-
- forEachSlotVisitor(
- [&] (SlotVisitor& visitor) {
- visitor.didStartMarking();
- });
-
- m_parallelMarkersShouldExit = false;
-
- m_helperClient.setFunction(
- [this] () {
- SlotVisitor* slotVisitor;
- {
- LockHolder locker(m_parallelSlotVisitorLock);
- if (m_availableParallelSlotVisitors.isEmpty()) {
- std::unique_ptr<SlotVisitor> newVisitor = std::make_unique<SlotVisitor>(
- *this, toCString("P", m_parallelSlotVisitors.size() + 1));
-
- if (Options::optimizeParallelSlotVisitorsForStoppedMutator())
- newVisitor->optimizeForStoppedMutator();
-
- newVisitor->didStartMarking();
-
- slotVisitor = newVisitor.get();
- m_parallelSlotVisitors.append(WTFMove(newVisitor));
- } else
- slotVisitor = m_availableParallelSlotVisitors.takeLast();
- }
-
- WTF::registerGCThread(GCThreadType::Helper);
-
- {
- ParallelModeEnabler parallelModeEnabler(*slotVisitor);
- slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
- }
-
- {
- LockHolder locker(m_parallelSlotVisitorLock);
- m_availableParallelSlotVisitors.append(slotVisitor);
- }
- });
-
- SlotVisitor& slotVisitor = *m_collectorSlotVisitor;
-
- m_constraintSet->didStartMarking();
</del><span class="cx">
</span><del>- m_scheduler->beginCollection();
- if (Options::logGC())
- m_scheduler->log();
</del><ins>+ markToFixpoint(gcStartTime);
</ins><span class="cx">
</span><del>- // After this, we will almost certainly fall through all of the "slotVisitor.isEmpty()"
- // checks because bootstrap would have put things into the visitor. So, we should fall
- // through to draining.
-
- if (!slotVisitor.didReachTermination()) {
- dataLog("Fatal: SlotVisitor should think that GC should terminate before constraint solving, but it does not think this.\n");
- dataLog("slotVisitor.isEmpty(): ", slotVisitor.isEmpty(), "\n");
- dataLog("slotVisitor.collectorMarkStack().isEmpty(): ", slotVisitor.collectorMarkStack().isEmpty(), "\n");
- dataLog("slotVisitor.mutatorMarkStack().isEmpty(): ", slotVisitor.mutatorMarkStack().isEmpty(), "\n");
- dataLog("m_numberOfActiveParallelMarkers: ", m_numberOfActiveParallelMarkers, "\n");
- dataLog("m_sharedCollectorMarkStack->isEmpty(): ", m_sharedCollectorMarkStack->isEmpty(), "\n");
- dataLog("m_sharedMutatorMarkStack->isEmpty(): ", m_sharedMutatorMarkStack->isEmpty(), "\n");
- dataLog("slotVisitor.didReachTermination(): ", slotVisitor.didReachTermination(), "\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
-
- return changePhase(conn, CollectorPhase::Fixpoint);
-}
-
-NEVER_INLINE bool Heap::runFixpointPhase(GCConductor conn)
-{
- RELEASE_ASSERT(conn == GCConductor::Collector || m_currentThreadState);
-
- SlotVisitor& slotVisitor = *m_collectorSlotVisitor;
-
- if (Options::logGC()) {
- HashMap<const char*, size_t> visitMap;
- forEachSlotVisitor(
- [&] (SlotVisitor& slotVisitor) {
- visitMap.add(slotVisitor.codeName(), slotVisitor.bytesVisited() / 1024);
- });
-
- auto perVisitorDump = sortedMapDump(
- visitMap,
- [] (const char* a, const char* b) -> bool {
- return strcmp(a, b) < 0;
- },
- ":", " ");
-
- dataLog("v=", bytesVisited() / 1024, "kb (", perVisitorDump, ") o=", m_opaqueRoots.size(), " b=", m_barriersExecuted, " ");
- }
-
- if (slotVisitor.didReachTermination()) {
- m_scheduler->didReachTermination();
-
- assertSharedMarkStacksEmpty();
-
- slotVisitor.mergeIfNecessary();
- for (auto& parallelVisitor : m_parallelSlotVisitors)
- parallelVisitor->mergeIfNecessary();
-
- // FIXME: Take m_mutatorDidRun into account when scheduling constraints. Most likely,
- // we don't have to execute root constraints again unless the mutator did run. At a
- // minimum, we could use this for work estimates - but it's probably more than just an
- // estimate.
- // https://bugs.webkit.org/show_bug.cgi?id=166828
-
- // FIXME: We should take advantage of the fact that we could timeout. This only comes
- // into play if we're executing constraints for the first time. But that will matter
- // when we have deep stacks or a lot of DOM stuff.
- // https://bugs.webkit.org/show_bug.cgi?id=166831
-
- // Wondering what this does? Look at Heap::addCoreConstraints(). The DOM and others can also
- // add their own using Heap::addMarkingConstraint().
- bool converged =
- m_constraintSet->executeConvergence(slotVisitor, MonotonicTime::infinity());
- if (converged && slotVisitor.isEmpty()) {
- assertSharedMarkStacksEmpty();
- return changePhase(conn, CollectorPhase::End);
- }
-
- m_scheduler->didExecuteConstraints();
- }
-
- if (Options::logGC())
- dataLog(slotVisitor.collectorMarkStack().size(), "+", m_mutatorMarkStack->size() + slotVisitor.mutatorMarkStack().size(), " ");
-
- {
- ParallelModeEnabler enabler(slotVisitor);
- slotVisitor.drainInParallel(m_scheduler->timeToResume());
- }
-
- m_scheduler->synchronousDrainingDidStall();
-
- if (slotVisitor.didReachTermination())
- return true; // This is like relooping to the top if runFixpointPhase().
-
- if (!m_scheduler->shouldResume())
- return true;
-
- m_scheduler->willResume();
-
- if (Options::logGC()) {
- double thisPauseMS = (MonotonicTime::now() - m_stopTime).milliseconds();
- dataLog("p=", thisPauseMS, "ms (max ", maxPauseMS(thisPauseMS), ")...]\n");
- }
-
- // Forgive the mutator for its past failures to keep up.
- // FIXME: Figure out if moving this to different places results in perf changes.
- m_incrementBalance = 0;
-
- return changePhase(conn, CollectorPhase::Concurrent);
-}
-
-NEVER_INLINE bool Heap::runConcurrentPhase(GCConductor conn)
-{
- SlotVisitor& slotVisitor = *m_collectorSlotVisitor;
-
- ParallelModeEnabler enabler(slotVisitor);
-
- switch (conn) {
- case GCConductor::Mutator: {
- // When the mutator has the conn, we poll runConcurrentPhase() on every time someone says
- // stopIfNecessary(), so on every allocation slow path. When that happens we poll if it's time
- // to stop and do some work.
- if (slotVisitor.didReachTermination()
- || m_scheduler->shouldStop())
- return changePhase(conn, CollectorPhase::Reloop);
-
- // We could be coming from a collector phase that stuffed our SlotVisitor, so make sure we donate
- // everything. This is super cheap if the SlotVisitor is already empty.
- slotVisitor.donateAll();
- return false;
- }
- case GCConductor::Collector: {
- slotVisitor.drainInParallelPassively(m_scheduler->timeToStop());
- return changePhase(conn, CollectorPhase::Reloop);
- } }
-
- RELEASE_ASSERT_NOT_REACHED();
- return false;
-}
-
-NEVER_INLINE bool Heap::runReloopPhase(GCConductor conn)
-{
- if (Options::logGC())
- dataLog("[GC<", RawPointer(this), ">: ", gcConductorShortName(conn), " ");
-
- m_scheduler->didStop();
-
- if (Options::logGC())
- m_scheduler->log();
-
- return changePhase(conn, CollectorPhase::Fixpoint);
-}
-
-NEVER_INLINE bool Heap::runEndPhase(GCConductor conn)
-{
- m_scheduler->endCollection();
-
- {
- auto locker = holdLock(m_markingMutex);
- m_parallelMarkersShouldExit = true;
- m_markingConditionVariable.notifyAll();
- }
- m_helperClient.finish();
-
- iterateExecutingAndCompilingCodeBlocks(
- [&] (CodeBlock* codeBlock) {
- writeBarrier(codeBlock);
- });
-
- updateObjectCounts();
- endMarking();
-
</del><span class="cx"> if (m_verifier) {
</span><span class="cx"> m_verifier->gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
</span><span class="cx"> m_verifier->verify(HeapVerifier::Phase::AfterMarking);
</span><span class="lines">@@ -1357,7 +1195,7 @@
</span><span class="cx"> m_objectSpace.prepareForAllocation();
</span><span class="cx"> updateAllocationLimits();
</span><span class="cx">
</span><del>- didFinishCollection();
</del><ins>+ didFinishCollection(gcStartTime);
</ins><span class="cx">
</span><span class="cx"> if (m_verifier) {
</span><span class="cx"> m_verifier->trimDeadObjects();
</span><span class="lines">@@ -1370,12 +1208,13 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (Options::logGC()) {
</span><del>- double thisPauseMS = (m_afterGC - m_stopTime).milliseconds();
- dataLog("p=", thisPauseMS, "ms (max ", maxPauseMS(thisPauseMS), "), cycle ", (m_afterGC - m_beforeGC).milliseconds(), "ms END]\n");
</del><ins>+ MonotonicTime after = MonotonicTime::now();
+ double thisPauseMS = (after - m_stopTime).milliseconds();
+ dataLog("p=", thisPauseMS, "ms (max ", maxPauseMS(thisPauseMS), "), cycle ", (after - before).milliseconds(), "ms END]\n");
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> {
</span><del>- auto locker = holdLock(*m_threadLock);
</del><ins>+ LockHolder locker(*m_threadLock);
</ins><span class="cx"> m_requests.removeFirst();
</span><span class="cx"> m_lastServedTicket++;
</span><span class="cx"> clearMutatorWaiting();
</span><span class="lines">@@ -1386,79 +1225,23 @@
</span><span class="cx"> dataLog("GC END!\n");
</span><span class="cx">
</span><span class="cx"> setNeedFinalize();
</span><del>-
</del><ins>+ resumeTheWorld();
+
</ins><span class="cx"> m_lastGCStartTime = m_currentGCStartTime;
</span><span class="cx"> m_lastGCEndTime = MonotonicTime::now();
</span><del>-
- return changePhase(conn, CollectorPhase::NotRunning);
</del><span class="cx"> }
</span><span class="cx">
</span><del>-bool Heap::changePhase(GCConductor conn, CollectorPhase nextPhase)
</del><ins>+void Heap::stopTheWorld()
</ins><span class="cx"> {
</span><del>- checkConn(conn);
-
- m_nextPhase = nextPhase;
-
- return finishChangingPhase(conn);
-}
-
-NEVER_INLINE bool Heap::finishChangingPhase(GCConductor conn)
-{
- checkConn(conn);
</del><ins>+ RELEASE_ASSERT(!m_collectorBelievesThatTheWorldIsStopped);
+ waitWhileNeedFinalize();
+ stopTheMutator();
</ins><span class="cx">
</span><del>- if (m_nextPhase == m_currentPhase)
- return true;
-
- if (false)
- dataLog(conn, ": Going to phase: ", m_nextPhase, " (from ", m_currentPhase, ")\n");
-
- bool suspendedBefore = worldShouldBeSuspended(m_currentPhase);
- bool suspendedAfter = worldShouldBeSuspended(m_nextPhase);
-
- if (suspendedBefore != suspendedAfter) {
- if (suspendedBefore) {
- RELEASE_ASSERT(!suspendedAfter);
-
- resumeThePeriphery();
- if (conn == GCConductor::Collector)
- resumeTheMutator();
- else
- handleNeedFinalize();
- } else {
- RELEASE_ASSERT(!suspendedBefore);
- RELEASE_ASSERT(suspendedAfter);
-
- if (conn == GCConductor::Collector) {
- waitWhileNeedFinalize();
- if (!stopTheMutator()) {
- if (false)
- dataLog("Returning false.\n");
- return false;
- }
- } else {
- sanitizeStackForVM(m_vm);
- handleNeedFinalize();
- }
- stopThePeriphery(conn);
- }
- }
-
- m_currentPhase = m_nextPhase;
- return true;
-}
-
-void Heap::stopThePeriphery(GCConductor conn)
-{
- if (m_collectorBelievesThatTheWorldIsStopped) {
- dataLog("FATAL: world already stopped.\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
-
</del><span class="cx"> if (m_mutatorDidRun)
</span><span class="cx"> m_mutatorExecutionVersion++;
</span><span class="cx">
</span><span class="cx"> m_mutatorDidRun = false;
</span><del>-
</del><ins>+
</ins><span class="cx"> suspendCompilerThreads();
</span><span class="cx"> m_collectorBelievesThatTheWorldIsStopped = true;
</span><span class="cx">
</span><span class="lines">@@ -1470,8 +1253,7 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> {
</span><span class="cx"> DeferGCForAWhile awhile(*this);
</span><del>- if (JITWorklist::instance()->completeAllForVM(*m_vm)
- && conn == GCConductor::Collector)
</del><ins>+ if (JITWorklist::instance()->completeAllForVM(*m_vm))
</ins><span class="cx"> setGCDidJIT();
</span><span class="cx"> }
</span><span class="cx"> #else
</span><span class="lines">@@ -1486,7 +1268,7 @@
</span><span class="cx"> m_stopTime = MonotonicTime::now();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-NEVER_INLINE void Heap::resumeThePeriphery()
</del><ins>+void Heap::resumeTheWorld()
</ins><span class="cx"> {
</span><span class="cx"> // Calling resumeAllocating does the Right Thing depending on whether this is the end of a
</span><span class="cx"> // collection cycle or this is just a concurrent phase within a collection cycle:
</span><span class="lines">@@ -1497,10 +1279,7 @@
</span><span class="cx">
</span><span class="cx"> m_barriersExecuted = 0;
</span><span class="cx">
</span><del>- if (!m_collectorBelievesThatTheWorldIsStopped) {
- dataLog("Fatal: collector does not believe that the world is stopped.\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
</del><ins>+ RELEASE_ASSERT(m_collectorBelievesThatTheWorldIsStopped);
</ins><span class="cx"> m_collectorBelievesThatTheWorldIsStopped = false;
</span><span class="cx">
</span><span class="cx"> // FIXME: This could be vastly improved: we want to grab the locks in the order in which they
</span><span class="lines">@@ -1538,72 +1317,59 @@
</span><span class="cx"> slotVisitor->updateMutatorIsStopped();
</span><span class="cx">
</span><span class="cx"> resumeCompilerThreads();
</span><ins>+ resumeTheMutator();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-bool Heap::stopTheMutator()
</del><ins>+void Heap::stopTheMutator()
</ins><span class="cx"> {
</span><span class="cx"> for (;;) {
</span><span class="cx"> unsigned oldState = m_worldState.load();
</span><del>- if (oldState & stoppedBit) {
- RELEASE_ASSERT(!(oldState & hasAccessBit));
- RELEASE_ASSERT(!(oldState & mutatorWaitingBit));
- RELEASE_ASSERT(!(oldState & mutatorHasConnBit));
- return true;
</del><ins>+ if ((oldState & stoppedBit)
+ && (oldState & shouldStopBit))
+ return;
+
+ // Note: We could just have the mutator stop in-place like we do when !hasAccessBit. We could
+ // switch to that if it turned out to be less confusing, but then it would not give the
+ // mutator the opportunity to react to the world being stopped.
+ if (oldState & mutatorWaitingBit) {
+ if (m_worldState.compareExchangeWeak(oldState, oldState & ~mutatorWaitingBit))
+ ParkingLot::unparkAll(&m_worldState);
+ continue;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- if (oldState & mutatorHasConnBit) {
- RELEASE_ASSERT(!(oldState & hasAccessBit));
- RELEASE_ASSERT(!(oldState & stoppedBit));
- return false;
- }
-
- if (!(oldState & hasAccessBit)) {
- RELEASE_ASSERT(!(oldState & mutatorHasConnBit));
- RELEASE_ASSERT(!(oldState & mutatorWaitingBit));
</del><ins>+ if (!(oldState & hasAccessBit)
+ || (oldState & stoppedBit)) {
</ins><span class="cx"> // We can stop the world instantly.
</span><del>- if (m_worldState.compareExchangeWeak(oldState, oldState | stoppedBit))
- return true;
</del><ins>+ if (m_worldState.compareExchangeWeak(oldState, oldState | stoppedBit | shouldStopBit))
+ return;
</ins><span class="cx"> continue;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- // Transfer the conn to the mutator and bail.
</del><span class="cx"> RELEASE_ASSERT(oldState & hasAccessBit);
</span><span class="cx"> RELEASE_ASSERT(!(oldState & stoppedBit));
</span><del>- unsigned newState = (oldState | mutatorHasConnBit) & ~mutatorWaitingBit;
- if (m_worldState.compareExchangeWeak(oldState, newState)) {
- if (false)
- dataLog("Handed off the conn.\n");
- m_stopIfNecessaryTimer->scheduleSoon();
- ParkingLot::unparkAll(&m_worldState);
- return false;
- }
</del><ins>+ m_worldState.compareExchangeStrong(oldState, oldState | shouldStopBit);
+ m_stopIfNecessaryTimer->scheduleSoon();
+ ParkingLot::compareAndPark(&m_worldState, oldState | shouldStopBit);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-NEVER_INLINE void Heap::resumeTheMutator()
</del><ins>+void Heap::resumeTheMutator()
</ins><span class="cx"> {
</span><del>- if (false)
- dataLog("Resuming the mutator.\n");
</del><span class="cx"> for (;;) {
</span><span class="cx"> unsigned oldState = m_worldState.load();
</span><del>- if (!!(oldState & hasAccessBit) != !(oldState & stoppedBit)) {
- dataLog("Fatal: hasAccess = ", !!(oldState & hasAccessBit), ", stopped = ", !!(oldState & stoppedBit), "\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
- if (oldState & mutatorHasConnBit) {
- dataLog("Fatal: mutator has the conn.\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
</del><ins>+ RELEASE_ASSERT(oldState & shouldStopBit);
</ins><span class="cx">
</span><del>- if (!(oldState & stoppedBit)) {
- if (false)
- dataLog("Returning because not stopped.\n");
- return;
</del><ins>+ if (!(oldState & hasAccessBit)) {
+ // We can resume the world instantly.
+ if (m_worldState.compareExchangeWeak(oldState, oldState & ~(stoppedBit | shouldStopBit))) {
+ ParkingLot::unparkAll(&m_worldState);
+ return;
+ }
+ continue;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- if (m_worldState.compareExchangeWeak(oldState, oldState & ~stoppedBit)) {
- if (false)
- dataLog("CASing and returning.\n");
</del><ins>+ // We can tell the world to resume.
+ if (m_worldState.compareExchangeWeak(oldState, oldState & ~shouldStopBit)) {
</ins><span class="cx"> ParkingLot::unparkAll(&m_worldState);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="lines">@@ -1625,54 +1391,30 @@
</span><span class="cx"> bool Heap::stopIfNecessarySlow(unsigned oldState)
</span><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT(oldState & hasAccessBit);
</span><del>- RELEASE_ASSERT(!(oldState & stoppedBit));
</del><span class="cx">
</span><span class="cx"> // It's possible for us to wake up with finalization already requested but the world not yet
</span><span class="cx"> // resumed. If that happens, we can't run finalization yet.
</span><del>- if (handleNeedFinalize(oldState))
</del><ins>+ if (!(oldState & stoppedBit)
+ && handleNeedFinalize(oldState))
</ins><span class="cx"> return true;
</span><del>-
- // FIXME: When entering the concurrent phase, we could arrange for this branch not to fire, and then
- // have the SlotVisitor do things to the m_worldState to make this branch fire again. That would
- // prevent us from polling this so much. Ideally, stopIfNecessary would ignore the mutatorHasConnBit
- // and there would be some other bit indicating whether we were in some GC phase other than the
- // NotRunning or Concurrent ones.
- if (oldState & mutatorHasConnBit)
- collectInMutatorThread();
</del><span class="cx">
</span><del>- return false;
-}
</del><ins>+ if (!(oldState & shouldStopBit) && !m_scheduler->shouldStop()) {
+ if (!(oldState & stoppedBit))
+ return false;
+ m_worldState.compareExchangeStrong(oldState, oldState & ~stoppedBit);
+ return true;
+ }
+
+ sanitizeStackForVM(m_vm);
</ins><span class="cx">
</span><del>-NEVER_INLINE void Heap::collectInMutatorThread()
-{
- CollectingScope collectingScope(*this);
- for (;;) {
- RunCurrentPhaseResult result = runCurrentPhase(GCConductor::Mutator, nullptr);
- switch (result) {
- case RunCurrentPhaseResult::Finished:
- return;
- case RunCurrentPhaseResult::Continue:
- break;
- case RunCurrentPhaseResult::NeedCurrentThreadState:
- sanitizeStackForVM(m_vm);
- auto lambda = [&] (CurrentThreadState& state) {
- for (;;) {
- RunCurrentPhaseResult result = runCurrentPhase(GCConductor::Mutator, &state);
- switch (result) {
- case RunCurrentPhaseResult::Finished:
- return;
- case RunCurrentPhaseResult::Continue:
- break;
- case RunCurrentPhaseResult::NeedCurrentThreadState:
- RELEASE_ASSERT_NOT_REACHED();
- break;
- }
- }
- };
- callWithCurrentThreadState(scopedLambda<void(CurrentThreadState&)>(WTFMove(lambda)));
- return;
- }
</del><ins>+ if (verboseStop) {
+ dataLog("Stopping!\n");
+ WTFReportBacktrace();
</ins><span class="cx"> }
</span><ins>+ m_worldState.compareExchangeStrong(oldState, oldState | stoppedBit);
+ ParkingLot::unparkAll(&m_worldState);
+ ParkingLot::compareAndPark(&m_worldState, oldState | stoppedBit);
+ return true;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template<typename Func>
</span><span class="lines">@@ -1685,7 +1427,6 @@
</span><span class="cx"> done = func(locker);
</span><span class="cx"> if (!done) {
</span><span class="cx"> setMutatorWaiting();
</span><del>-
</del><span class="cx"> // At this point, the collector knows that we intend to wait, and he will clear the
</span><span class="cx"> // waiting bit and then unparkAll when the GC cycle finishes. Clearing the bit
</span><span class="cx"> // prevents us from parking except if there is also stop-the-world. Unparking after
</span><span class="lines">@@ -1692,16 +1433,12 @@
</span><span class="cx"> // clearing means that if the clearing happens after we park, then we will unpark.
</span><span class="cx"> }
</span><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> // If we're in a stop-the-world scenario, we need to wait for that even if done is true.
</span><span class="cx"> unsigned oldState = m_worldState.load();
</span><span class="cx"> if (stopIfNecessarySlow(oldState))
</span><span class="cx"> continue;
</span><span class="cx">
</span><del>- // FIXME: We wouldn't need this if stopIfNecessarySlow() had a mode where it knew to just
- // do the collection.
- relinquishConn();
-
</del><span class="cx"> if (done) {
</span><span class="cx"> clearMutatorWaiting(); // Clean up just in case.
</span><span class="cx"> return;
</span><span class="lines">@@ -1718,7 +1455,8 @@
</span><span class="cx"> unsigned oldState = m_worldState.load();
</span><span class="cx"> RELEASE_ASSERT(!(oldState & hasAccessBit));
</span><span class="cx">
</span><del>- if (oldState & stoppedBit) {
</del><ins>+ if (oldState & shouldStopBit) {
+ RELEASE_ASSERT(oldState & stoppedBit);
</ins><span class="cx"> if (verboseStop) {
</span><span class="cx"> dataLog("Stopping in acquireAccess!\n");
</span><span class="cx"> WTFReportBacktrace();
</span><span class="lines">@@ -1734,7 +1472,6 @@
</span><span class="cx"> handleGCDidJIT();
</span><span class="cx"> handleNeedFinalize();
</span><span class="cx"> m_mutatorDidRun = true;
</span><del>- stopIfNecessary();
</del><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -1744,73 +1481,28 @@
</span><span class="cx"> {
</span><span class="cx"> for (;;) {
</span><span class="cx"> unsigned oldState = m_worldState.load();
</span><del>- if (!(oldState & hasAccessBit)) {
- dataLog("FATAL: Attempting to release access but the mutator does not have access.\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
- if (oldState & stoppedBit) {
- dataLog("FATAL: Attempting to release access but the mutator is stopped.\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
</del><ins>+ RELEASE_ASSERT(oldState & hasAccessBit);
+ RELEASE_ASSERT(!(oldState & stoppedBit));
</ins><span class="cx">
</span><span class="cx"> if (handleNeedFinalize(oldState))
</span><span class="cx"> continue;
</span><span class="cx">
</span><del>- unsigned newState = oldState & ~(hasAccessBit | mutatorHasConnBit);
</del><ins>+ if (oldState & shouldStopBit) {
+ unsigned newState = (oldState & ~hasAccessBit) | stoppedBit;
+ if (m_worldState.compareExchangeWeak(oldState, newState)) {
+ ParkingLot::unparkAll(&m_worldState);
+ return;
+ }
+ continue;
+ }
</ins><span class="cx">
</span><del>- if ((oldState & mutatorHasConnBit)
- && m_nextPhase != m_currentPhase) {
- // This means that the collector thread had given us the conn so that we would do something
- // for it. Stop ourselves as we release access. This ensures that acquireAccess blocks. In
- // the meantime, since we're handing the conn over, the collector will be awoken and it is
- // sure to have work to do.
- newState |= stoppedBit;
- }
-
- if (m_worldState.compareExchangeWeak(oldState, newState)) {
- if (oldState & mutatorHasConnBit)
- finishRelinquishingConn();
</del><ins>+ RELEASE_ASSERT(!(oldState & shouldStopBit));
+
+ if (m_worldState.compareExchangeWeak(oldState, oldState & ~hasAccessBit))
</ins><span class="cx"> return;
</span><del>- }
</del><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool Heap::relinquishConn(unsigned oldState)
-{
- RELEASE_ASSERT(oldState & hasAccessBit);
- RELEASE_ASSERT(!(oldState & stoppedBit));
-
- if (!(oldState & mutatorHasConnBit))
- return false; // Done.
-
- if (m_threadShouldStop)
- return false;
-
- if (!m_worldState.compareExchangeWeak(oldState, oldState & ~mutatorHasConnBit))
- return true; // Loop around.
-
- finishRelinquishingConn();
- return true;
-}
-
-void Heap::finishRelinquishingConn()
-{
- if (false)
- dataLog("Relinquished the conn.\n");
-
- sanitizeStackForVM(m_vm);
-
- auto locker = holdLock(*m_threadLock);
- if (!m_requests.isEmpty())
- m_threadCondition->notifyOne(locker);
- ParkingLot::unparkAll(&m_worldState);
-}
-
-void Heap::relinquishConn()
-{
- while (relinquishConn(m_worldState.load())) { }
-}
-
</del><span class="cx"> bool Heap::handleGCDidJIT(unsigned oldState)
</span><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT(oldState & hasAccessBit);
</span><span class="lines">@@ -1823,7 +1515,7 @@
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-NEVER_INLINE bool Heap::handleNeedFinalize(unsigned oldState)
</del><ins>+bool Heap::handleNeedFinalize(unsigned oldState)
</ins><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT(oldState & hasAccessBit);
</span><span class="cx"> RELEASE_ASSERT(!(oldState & stoppedBit));
</span><span class="lines">@@ -1890,7 +1582,7 @@
</span><span class="cx"> m_worldState.exchangeAnd(~mutatorWaitingBit);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Heap::notifyThreadStopping(const AbstractLocker&)
</del><ins>+void Heap::notifyThreadStopping(const LockHolder&)
</ins><span class="cx"> {
</span><span class="cx"> m_threadIsStopping = true;
</span><span class="cx"> clearMutatorWaiting();
</span><span class="lines">@@ -1902,11 +1594,11 @@
</span><span class="cx"> MonotonicTime before;
</span><span class="cx"> if (Options::logGC()) {
</span><span class="cx"> before = MonotonicTime::now();
</span><del>- dataLog("[GC<", RawPointer(this), ">: finalize ");
</del><ins>+ dataLog("[GC: finalize ");
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> {
</span><del>- SweepingScope helpingGCScope(*this);
</del><ins>+ HelpingGCScope helpingGCScope(*this);
</ins><span class="cx"> deleteUnmarkedCompiledCode();
</span><span class="cx"> deleteSourceProviderCaches();
</span><span class="cx"> sweepLargeAllocations();
</span><span class="lines">@@ -1914,14 +1606,6 @@
</span><span class="cx">
</span><span class="cx"> if (HasOwnPropertyCache* cache = vm()->hasOwnPropertyCache())
</span><span class="cx"> cache->clear();
</span><del>-
- {
- // This idiom allows callbacks to call addFinalizationCallback() if they want to be added back.
- Vector<RefPtr<GCFinalizationCallback>> myCallbacks;
- std::swap(myCallbacks, m_finalizationCallbacks);
- for (auto& callback : myCallbacks)
- callback->didFinalize(*this);
- }
</del><span class="cx">
</span><span class="cx"> if (Options::sweepSynchronously())
</span><span class="cx"> sweepSynchronously();
</span><span class="lines">@@ -1932,11 +1616,6 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Heap::addFinalizationCallback(RefPtr<GCFinalizationCallback> callback)
-{
- m_finalizationCallbacks.append(callback);
-}
-
</del><span class="cx"> Heap::Ticket Heap::requestCollection(std::optional<CollectionScope> scope)
</span><span class="cx"> {
</span><span class="cx"> stopIfNecessary();
</span><span class="lines">@@ -1945,20 +1624,9 @@
</span><span class="cx"> RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable());
</span><span class="cx">
</span><span class="cx"> LockHolder locker(*m_threadLock);
</span><del>- // We may be able to steal the conn. That only works if the collector is definitely not running
- // right now. This is an optimization that prevents the collector thread from ever starting in most
- // cases.
- ASSERT(m_lastServedTicket <= m_lastGrantedTicket);
- if (m_lastServedTicket == m_lastGrantedTicket) {
- if (false)
- dataLog("Taking the conn.\n");
- m_worldState.exchangeOr(mutatorHasConnBit);
- }
-
</del><span class="cx"> m_requests.append(scope);
</span><span class="cx"> m_lastGrantedTicket++;
</span><del>- if (!(m_worldState.load() & mutatorHasConnBit))
- m_threadCondition->notifyOne(locker);
</del><ins>+ m_threadCondition->notifyOne(locker);
</ins><span class="cx"> return m_lastGrantedTicket;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1965,7 +1633,7 @@
</span><span class="cx"> void Heap::waitForCollection(Ticket ticket)
</span><span class="cx"> {
</span><span class="cx"> waitForCollector(
</span><del>- [&] (const AbstractLocker&) -> bool {
</del><ins>+ [&] (const LockHolder&) -> bool {
</ins><span class="cx"> return m_lastServedTicket >= ticket;
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="lines">@@ -2104,6 +1772,9 @@
</span><span class="cx"> if (verbose)
</span><span class="cx"> dataLog("extraMemorySize() = ", extraMemorySize(), ", currentHeapSize = ", currentHeapSize, "\n");
</span><span class="cx">
</span><ins>+ if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize())
+ HeapStatistics::exitWithFailure();
+
</ins><span class="cx"> if (m_collectionScope == CollectionScope::Full) {
</span><span class="cx"> // To avoid pathological GC churn in very small and very large heaps, we set
</span><span class="cx"> // the new allocation limit based on the current size of the heap, with a
</span><span class="lines">@@ -2156,19 +1827,25 @@
</span><span class="cx"> dataLog("=> ", currentHeapSize / 1024, "kb, ");
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Heap::didFinishCollection()
</del><ins>+void Heap::didFinishCollection(double gcStartTime)
</ins><span class="cx"> {
</span><del>- m_afterGC = MonotonicTime::now();
</del><ins>+ double gcEndTime = WTF::monotonicallyIncreasingTime();
</ins><span class="cx"> CollectionScope scope = *m_collectionScope;
</span><span class="cx"> if (scope == CollectionScope::Full)
</span><del>- m_lastFullGCLength = m_afterGC - m_beforeGC;
</del><ins>+ m_lastFullGCLength = gcEndTime - gcStartTime;
</ins><span class="cx"> else
</span><del>- m_lastEdenGCLength = m_afterGC - m_beforeGC;
</del><ins>+ m_lastEdenGCLength = gcEndTime - gcStartTime;
</ins><span class="cx">
</span><span class="cx"> #if ENABLE(RESOURCE_USAGE)
</span><span class="cx"> ASSERT(externalMemorySize() <= extraMemorySize());
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+ if (Options::recordGCPauseTimes())
+ HeapStatistics::recordGCPauseTime(gcStartTime, gcEndTime);
+
+ if (Options::dumpObjectStatistics())
+ HeapStatistics::dumpObjectStatistics(this);
+
</ins><span class="cx"> if (HeapProfiler* heapProfiler = m_vm->heapProfiler()) {
</span><span class="cx"> gatherExtraHeapSnapshotData(*heapProfiler);
</span><span class="cx"> removeDeadHeapSnapshotNodes(*heapProfiler);
</span><span class="lines">@@ -2395,14 +2072,8 @@
</span><span class="cx">
</span><span class="cx"> if (!m_isSafeToCollect)
</span><span class="cx"> return;
</span><del>- switch (mutatorState()) {
- case MutatorState::Running:
- case MutatorState::Allocating:
- break;
- case MutatorState::Sweeping:
- case MutatorState::Collecting:
</del><ins>+ if (mutatorState() == MutatorState::HelpingGC)
</ins><span class="cx"> return;
</span><del>- }
</del><span class="cx"> if (!Options::useGC())
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="lines">@@ -2411,8 +2082,11 @@
</span><span class="cx"> deferralContext->m_shouldGC = true;
</span><span class="cx"> else if (isDeferred())
</span><span class="cx"> m_didDeferGCWork = true;
</span><del>- else
</del><ins>+ else {
</ins><span class="cx"> stopIfNecessary();
</span><ins>+ // FIXME: Check if the scheduler wants us to stop.
+ // https://bugs.webkit.org/show_bug.cgi?id=166827
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (UNLIKELY(Options::gcMaxHeapSize())) {
</span><span class="lines">@@ -2427,10 +2101,8 @@
</span><span class="cx"> deferralContext->m_shouldGC = true;
</span><span class="cx"> else if (isDeferred())
</span><span class="cx"> m_didDeferGCWork = true;
</span><del>- else {
</del><ins>+ else
</ins><span class="cx"> collectAsync();
</span><del>- stopIfNecessary(); // This will immediately start the collection if we have the conn.
- }
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void Heap::decrementDeferralDepthAndGCIfNeededSlow()
</span><span class="lines">@@ -2633,12 +2305,6 @@
</span><span class="cx">
</span><span class="cx"> void Heap::notifyIsSafeToCollect()
</span><span class="cx"> {
</span><del>- MonotonicTime before;
- if (Options::logGC()) {
- before = MonotonicTime::now();
- dataLog("[GC<", RawPointer(this), ">: starting ");
- }
-
</del><span class="cx"> addCoreConstraints();
</span><span class="cx">
</span><span class="cx"> m_isSafeToCollect = true;
</span><span class="lines">@@ -2673,9 +2339,6 @@
</span><span class="cx"> }
</span><span class="cx"> });
</span><span class="cx"> }
</span><del>-
- if (Options::logGC())
- dataLog((MonotonicTime::now() - before).milliseconds(), "ms]\n");
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void Heap::preventCollection()
</span><span class="lines">@@ -2688,7 +2351,7 @@
</span><span class="cx">
</span><span class="cx"> // Wait for all collections to finish.
</span><span class="cx"> waitForCollector(
</span><del>- [&] (const AbstractLocker&) -> bool {
</del><ins>+ [&] (const LockHolder&) -> bool {
</ins><span class="cx"> ASSERT(m_lastServedTicket <= m_lastGrantedTicket);
</span><span class="cx"> return m_lastServedTicket == m_lastGrantedTicket;
</span><span class="cx"> });
</span><span class="lines">@@ -2741,11 +2404,22 @@
</span><span class="cx"> return;
</span><span class="cx"> targetBytes = std::min(targetBytes, Options::gcIncrementMaxBytes());
</span><span class="cx">
</span><ins>+ MonotonicTime before;
+ if (Options::logGC()) {
+ dataLog("[GC: increment t=", targetBytes / 1024, "kb ");
+ before = MonotonicTime::now();
+ }
+
</ins><span class="cx"> SlotVisitor& slotVisitor = *m_mutatorSlotVisitor;
</span><span class="cx"> ParallelModeEnabler parallelModeEnabler(slotVisitor);
</span><span class="cx"> size_t bytesVisited = slotVisitor.performIncrementOfDraining(static_cast<size_t>(targetBytes));
</span><span class="cx"> // incrementBalance may go negative here because it'll remember how many bytes we overshot.
</span><span class="cx"> m_incrementBalance -= bytesVisited;
</span><ins>+
+ if (Options::logGC()) {
+ MonotonicTime after = MonotonicTime::now();
+ dataLog("p=", (after - before).milliseconds(), "ms b=", m_incrementBalance / 1024, "kb]\n");
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -24,14 +24,13 @@
</span><span class="cx"> #include "ArrayBuffer.h"
</span><span class="cx"> #include "CellState.h"
</span><span class="cx"> #include "CollectionScope.h"
</span><del>-#include "CollectorPhase.h"
</del><span class="cx"> #include "DeleteAllCodeEffort.h"
</span><del>-#include "GCConductor.h"
</del><span class="cx"> #include "GCIncomingRefCountedSet.h"
</span><span class="cx"> #include "HandleSet.h"
</span><span class="cx"> #include "HandleStack.h"
</span><span class="cx"> #include "HeapObserver.h"
</span><span class="cx"> #include "ListableHandler.h"
</span><ins>+#include "MachineStackMarker.h"
</ins><span class="cx"> #include "MarkedBlock.h"
</span><span class="cx"> #include "MarkedBlockSet.h"
</span><span class="cx"> #include "MarkedSpace.h"
</span><span class="lines">@@ -54,8 +53,6 @@
</span><span class="cx">
</span><span class="cx"> class CodeBlock;
</span><span class="cx"> class CodeBlockSet;
</span><del>-class CollectingScope;
-class ConservativeRoots;
</del><span class="cx"> class GCDeferralContext;
</span><span class="cx"> class EdenGCActivityCallback;
</span><span class="cx"> class ExecutableBase;
</span><span class="lines">@@ -62,10 +59,10 @@
</span><span class="cx"> class FullGCActivityCallback;
</span><span class="cx"> class GCActivityCallback;
</span><span class="cx"> class GCAwareJITStubRoutine;
</span><del>-class GCFinalizationCallback;
</del><span class="cx"> class Heap;
</span><span class="cx"> class HeapProfiler;
</span><span class="cx"> class HeapVerifier;
</span><ins>+class HelpingGCScope;
</ins><span class="cx"> class IncrementalSweeper;
</span><span class="cx"> class JITStubRoutine;
</span><span class="cx"> class JITStubRoutineSet;
</span><span class="lines">@@ -72,7 +69,6 @@
</span><span class="cx"> class JSCell;
</span><span class="cx"> class JSValue;
</span><span class="cx"> class LLIntOffsetsExtractor;
</span><del>-class MachineThreads;
</del><span class="cx"> class MarkStackArray;
</span><span class="cx"> class MarkedAllocator;
</span><span class="cx"> class MarkedArgumentBuffer;
</span><span class="lines">@@ -79,13 +75,10 @@
</span><span class="cx"> class MarkingConstraint;
</span><span class="cx"> class MarkingConstraintSet;
</span><span class="cx"> class MutatorScheduler;
</span><del>-class RunningScope;
</del><span class="cx"> class SlotVisitor;
</span><span class="cx"> class SpaceTimeMutatorScheduler;
</span><span class="cx"> class StopIfNecessaryTimer;
</span><del>-class SweepingScope;
</del><span class="cx"> class VM;
</span><del>-struct CurrentThreadState;
</del><span class="cx">
</span><span class="cx"> namespace DFG {
</span><span class="cx"> class SpeculativeJIT;
</span><span class="lines">@@ -138,7 +131,7 @@
</span><span class="cx"> VM* vm() const;
</span><span class="cx">
</span><span class="cx"> MarkedSpace& objectSpace() { return m_objectSpace; }
</span><del>- MachineThreads& machineThreads() { return *m_machineThreads; }
</del><ins>+ MachineThreads& machineThreads() { return m_machineThreads; }
</ins><span class="cx">
</span><span class="cx"> SlotVisitor& collectorSlotVisitor() { return *m_collectorSlotVisitor; }
</span><span class="cx">
</span><span class="lines">@@ -154,6 +147,7 @@
</span><span class="cx"> MutatorState mutatorState() const { return m_mutatorState; }
</span><span class="cx"> std::optional<CollectionScope> collectionScope() const { return m_collectionScope; }
</span><span class="cx"> bool hasHeapAccess() const;
</span><ins>+ bool mutatorIsStopped() const;
</ins><span class="cx"> bool collectorBelievesThatTheWorldIsStopped() const;
</span><span class="cx">
</span><span class="cx"> // We're always busy on the collection threads. On the main thread, this returns true if we're
</span><span class="lines">@@ -235,9 +229,9 @@
</span><span class="cx"> void willStartIterating();
</span><span class="cx"> void didFinishIterating();
</span><span class="cx">
</span><del>- Seconds lastFullGCLength() const { return m_lastFullGCLength; }
- Seconds lastEdenGCLength() const { return m_lastEdenGCLength; }
- void increaseLastFullGCLength(Seconds amount) { m_lastFullGCLength += amount; }
</del><ins>+ double lastFullGCLength() const { return m_lastFullGCLength; }
+ double lastEdenGCLength() const { return m_lastEdenGCLength; }
+ void increaseLastFullGCLength(double amount) { m_lastFullGCLength += amount; }
</ins><span class="cx">
</span><span class="cx"> size_t sizeBeforeLastEdenCollection() const { return m_sizeBeforeLastEdenCollect; }
</span><span class="cx"> size_t sizeAfterLastEdenCollection() const { return m_sizeAfterLastEdenCollect; }
</span><span class="lines">@@ -325,9 +319,6 @@
</span><span class="cx"> // already be called for you at the right times.
</span><span class="cx"> void stopIfNecessary();
</span><span class="cx">
</span><del>- // This gives the conn to the collector.
- void relinquishConn();
-
</del><span class="cx"> bool mayNeedToStop();
</span><span class="cx">
</span><span class="cx"> void performIncrement(size_t bytes);
</span><span class="lines">@@ -352,13 +343,10 @@
</span><span class="cx"> CFRunLoopRef runLoop() const { return m_runLoop.get(); }
</span><span class="cx"> JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef);
</span><span class="cx"> #endif // USE(CF)
</span><del>-
- JS_EXPORT_PRIVATE void addFinalizationCallback(RefPtr<GCFinalizationCallback>);
</del><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> friend class AllocatingScope;
</span><span class="cx"> friend class CodeBlock;
</span><del>- friend class CollectingScope;
</del><span class="cx"> friend class DeferGC;
</span><span class="cx"> friend class DeferGCForAWhile;
</span><span class="cx"> friend class GCAwareJITStubRoutine;
</span><span class="lines">@@ -367,16 +355,15 @@
</span><span class="cx"> friend class HandleSet;
</span><span class="cx"> friend class HeapUtil;
</span><span class="cx"> friend class HeapVerifier;
</span><ins>+ friend class HelpingGCScope;
</ins><span class="cx"> friend class JITStubRoutine;
</span><span class="cx"> friend class LLIntOffsetsExtractor;
</span><span class="cx"> friend class MarkedSpace;
</span><span class="cx"> friend class MarkedAllocator;
</span><span class="cx"> friend class MarkedBlock;
</span><del>- friend class RunningScope;
</del><span class="cx"> friend class SlotVisitor;
</span><span class="cx"> friend class SpaceTimeMutatorScheduler;
</span><span class="cx"> friend class StochasticSpaceTimeMutatorScheduler;
</span><del>- friend class SweepingScope;
</del><span class="cx"> friend class IncrementalSweeper;
</span><span class="cx"> friend class HeapStatistics;
</span><span class="cx"> friend class VM;
</span><span class="lines">@@ -395,35 +382,13 @@
</span><span class="cx"> JS_EXPORT_PRIVATE void reportExtraMemoryAllocatedSlowCase(size_t);
</span><span class="cx"> JS_EXPORT_PRIVATE void deprecatedReportExtraMemorySlowCase(size_t);
</span><span class="cx">
</span><del>- bool shouldCollectInCollectorThread(const AbstractLocker&);
- void collectInCollectorThread();
</del><ins>+ bool shouldCollectInThread(const LockHolder&);
+ void collectInThread();
</ins><span class="cx">
</span><del>- void checkConn(GCConductor);
-
- enum class RunCurrentPhaseResult {
- Finished,
- Continue,
- NeedCurrentThreadState
- };
- RunCurrentPhaseResult runCurrentPhase(GCConductor, CurrentThreadState*);
</del><ins>+ void stopTheWorld();
+ void resumeTheWorld();
</ins><span class="cx">
</span><del>- // Returns true if we should keep doing things.
- bool runNotRunningPhase(GCConductor);
- bool runBeginPhase(GCConductor);
- bool runFixpointPhase(GCConductor);
- bool runConcurrentPhase(GCConductor);
- bool runReloopPhase(GCConductor);
- bool runEndPhase(GCConductor);
- bool changePhase(GCConductor, CollectorPhase);
- bool finishChangingPhase(GCConductor);
-
- void collectInMutatorThread();
-
- void stopThePeriphery(GCConductor);
- void resumeThePeriphery();
-
- // Returns true if the mutator is stopped, false if the mutator has the conn now.
- bool stopTheMutator();
</del><ins>+ void stopTheMutator();
</ins><span class="cx"> void resumeTheMutator();
</span><span class="cx">
</span><span class="cx"> void stopIfNecessarySlow();
</span><span class="lines">@@ -436,14 +401,10 @@
</span><span class="cx"> JS_EXPORT_PRIVATE void releaseAccessSlow();
</span><span class="cx">
</span><span class="cx"> bool handleGCDidJIT(unsigned);
</span><ins>+ bool handleNeedFinalize(unsigned);
</ins><span class="cx"> void handleGCDidJIT();
</span><del>-
- bool handleNeedFinalize(unsigned);
</del><span class="cx"> void handleNeedFinalize();
</span><span class="cx">
</span><del>- bool relinquishConn(unsigned);
- void finishRelinquishingConn();
-
</del><span class="cx"> void setGCDidJIT();
</span><span class="cx"> void setNeedFinalize();
</span><span class="cx"> void waitWhileNeedFinalize();
</span><span class="lines">@@ -450,7 +411,7 @@
</span><span class="cx">
</span><span class="cx"> void setMutatorWaiting();
</span><span class="cx"> void clearMutatorWaiting();
</span><del>- void notifyThreadStopping(const AbstractLocker&);
</del><ins>+ void notifyThreadStopping(const LockHolder&);
</ins><span class="cx">
</span><span class="cx"> typedef uint64_t Ticket;
</span><span class="cx"> Ticket requestCollection(std::optional<CollectionScope>);
</span><span class="lines">@@ -460,6 +421,7 @@
</span><span class="cx"> void willStartCollection(std::optional<CollectionScope>);
</span><span class="cx"> void prepareForMarking();
</span><span class="cx">
</span><ins>+ void markToFixpoint(double gcStartTime);
</ins><span class="cx"> void gatherStackRoots(ConservativeRoots&);
</span><span class="cx"> void gatherJSStackRoots(ConservativeRoots&);
</span><span class="cx"> void gatherScratchBufferRoots(ConservativeRoots&);
</span><span class="lines">@@ -466,7 +428,7 @@
</span><span class="cx"> void beginMarking();
</span><span class="cx"> void visitCompilerWorklistWeakReferences();
</span><span class="cx"> void removeDeadCompilerWorklistEntries();
</span><del>- void updateObjectCounts();
</del><ins>+ void updateObjectCounts(double gcStartTime);
</ins><span class="cx"> void endMarking();
</span><span class="cx">
</span><span class="cx"> void reapWeakHandles();
</span><span class="lines">@@ -481,7 +443,7 @@
</span><span class="cx"> void deleteUnmarkedCompiledCode();
</span><span class="cx"> JS_EXPORT_PRIVATE void addToRememberedSet(const JSCell*);
</span><span class="cx"> void updateAllocationLimits();
</span><del>- void didFinishCollection();
</del><ins>+ void didFinishCollection(double gcStartTime);
</ins><span class="cx"> void resumeCompilerThreads();
</span><span class="cx"> void gatherExtraHeapSnapshotData(HeapProfiler&);
</span><span class="cx"> void removeDeadHeapSnapshotNodes(HeapProfiler&);
</span><span class="lines">@@ -548,7 +510,7 @@
</span><span class="cx"> ProtectCountSet m_protectedValues;
</span><span class="cx"> std::unique_ptr<HashSet<MarkedArgumentBuffer*>> m_markListSet;
</span><span class="cx">
</span><del>- std::unique_ptr<MachineThreads> m_machineThreads;
</del><ins>+ MachineThreads m_machineThreads;
</ins><span class="cx">
</span><span class="cx"> std::unique_ptr<SlotVisitor> m_collectorSlotVisitor;
</span><span class="cx"> std::unique_ptr<SlotVisitor> m_mutatorSlotVisitor;
</span><span class="lines">@@ -582,8 +544,8 @@
</span><span class="cx"> unsigned m_barrierThreshold { Options::forceFencedBarrier() ? tautologicalThreshold : blackThreshold };
</span><span class="cx">
</span><span class="cx"> VM* m_vm;
</span><del>- Seconds m_lastFullGCLength;
- Seconds m_lastEdenGCLength;
</del><ins>+ double m_lastFullGCLength;
+ double m_lastEdenGCLength;
</ins><span class="cx">
</span><span class="cx"> Vector<ExecutableBase*> m_executables;
</span><span class="cx">
</span><span class="lines">@@ -639,8 +601,8 @@
</span><span class="cx">
</span><span class="cx"> std::unique_ptr<MutatorScheduler> m_scheduler;
</span><span class="cx">
</span><del>- static const unsigned mutatorHasConnBit = 1u << 0u; // Must also be protected by threadLock.
- static const unsigned stoppedBit = 1u << 1u; // Only set when !hasAccessBit
</del><ins>+ static const unsigned shouldStopBit = 1u << 0u;
+ static const unsigned stoppedBit = 1u << 1u;
</ins><span class="cx"> static const unsigned hasAccessBit = 1u << 2u;
</span><span class="cx"> static const unsigned gcDidJITBit = 1u << 3u; // Set when the GC did some JITing, so on resume we need to cpuid.
</span><span class="cx"> static const unsigned needFinalizeBit = 1u << 4u;
</span><span class="lines">@@ -647,15 +609,11 @@
</span><span class="cx"> static const unsigned mutatorWaitingBit = 1u << 5u; // Allows the mutator to use this as a condition variable.
</span><span class="cx"> Atomic<unsigned> m_worldState;
</span><span class="cx"> bool m_collectorBelievesThatTheWorldIsStopped { false };
</span><del>- MonotonicTime m_beforeGC;
- MonotonicTime m_afterGC;
</del><span class="cx"> MonotonicTime m_stopTime;
</span><span class="cx">
</span><span class="cx"> Deque<std::optional<CollectionScope>> m_requests;
</span><span class="cx"> Ticket m_lastServedTicket { 0 };
</span><span class="cx"> Ticket m_lastGrantedTicket { 0 };
</span><del>- CollectorPhase m_currentPhase { CollectorPhase::NotRunning };
- CollectorPhase m_nextPhase { CollectorPhase::NotRunning };
</del><span class="cx"> bool m_threadShouldStop { false };
</span><span class="cx"> bool m_threadIsStopping { false };
</span><span class="cx"> bool m_mutatorDidRun { true };
</span><span class="lines">@@ -674,10 +632,6 @@
</span><span class="cx"> MonotonicTime m_currentGCStartTime;
</span><span class="cx">
</span><span class="cx"> uintptr_t m_barriersExecuted { 0 };
</span><del>-
- CurrentThreadState* m_currentThreadState { nullptr };
-
- Vector<RefPtr<GCFinalizationCallback>> m_finalizationCallbacks;
</del><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapInlines.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapInlines.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/HeapInlines.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -61,6 +61,24 @@
</span><span class="cx"> return m_worldState.load() & hasAccessBit;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+inline bool Heap::mutatorIsStopped() const
+{
+ unsigned state = m_worldState.load();
+ bool shouldStop = state & shouldStopBit;
+ bool stopped = state & stoppedBit;
+ // I only got it right when I considered all four configurations of shouldStop/stopped:
+ // !shouldStop, !stopped: The GC has not requested that we stop and we aren't stopped, so we
+ // should return false.
+ // !shouldStop, stopped: The mutator is still stopped but the GC is done and the GC has requested
+ // that we resume, so we should return false.
+ // shouldStop, !stopped: The GC called stopTheWorld() but the mutator hasn't hit a safepoint yet.
+ // The mutator should be able to do whatever it wants in this state, as if we were not
+ // stopped. So return false.
+ // shouldStop, stopped: The GC requested stop the world and the mutator obliged. The world is
+ // stopped, so return true.
+ return shouldStop & stopped;
+}
+
</ins><span class="cx"> inline bool Heap::collectorBelievesThatTheWorldIsStopped() const
</span><span class="cx"> {
</span><span class="cx"> return m_collectorBelievesThatTheWorldIsStopped;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapStatisticscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/HeapStatistics.cpp (0 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapStatistics.cpp         (rev 0)
+++ trunk/Source/JavaScriptCore/heap/HeapStatistics.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -0,0 +1,251 @@
</span><ins>+/*
+ * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#include "config.h"
+#include "HeapStatistics.h"
+
+#include "Heap.h"
+#include "HeapIterationScope.h"
+#include "JSCInlines.h"
+#include "JSObject.h"
+#include "MarkedSpaceInlines.h"
+#include "Options.h"
+#include <stdlib.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/DataLog.h>
+#include <wtf/StdLibExtras.h>
+
+#if OS(UNIX)
+#include <sys/resource.h>
+#endif
+
+namespace JSC {
+
+double HeapStatistics::s_startTime = 0.0;
+double HeapStatistics::s_endTime = 0.0;
+Vector<double>* HeapStatistics::s_pauseTimeStarts = 0;
+Vector<double>* HeapStatistics::s_pauseTimeEnds = 0;
+
+#if OS(UNIX)
+
+void HeapStatistics::initialize()
+{
+ ASSERT(Options::recordGCPauseTimes());
+ s_startTime = WTF::monotonicallyIncreasingTime();
+ s_pauseTimeStarts = new Vector<double>();
+ s_pauseTimeEnds = new Vector<double>();
+}
+
+void HeapStatistics::recordGCPauseTime(double start, double end)
+{
+ ASSERT(Options::recordGCPauseTimes());
+ ASSERT(s_pauseTimeStarts);
+ ASSERT(s_pauseTimeEnds);
+ s_pauseTimeStarts->append(start);
+ s_pauseTimeEnds->append(end);
+}
+
+void HeapStatistics::logStatistics()
+{
+ struct rusage usage;
+ getrusage(RUSAGE_SELF, &usage);
+#if USE(CF) || OS(UNIX)
+ char* vmName = getenv("JSVMName");
+ char* suiteName = getenv("JSSuiteName");
+ char* benchmarkName = getenv("JSBenchmarkName");
+#else
+#error "The HeapStatistics module is not supported on this platform."
+#endif
+ if (!vmName || !suiteName || !benchmarkName)
+ dataLogF("HeapStatistics: {\"max_rss\": %ld", usage.ru_maxrss);
+ else
+ dataLogF("HeapStatistics: {\"max_rss\": %ld, \"vm_name\": \"%s\", \"suite_name\": \"%s\", \"benchmark_name\": \"%s\"",
+ usage.ru_maxrss, vmName, suiteName, benchmarkName);
+
+ if (Options::recordGCPauseTimes()) {
+ dataLogF(", \"pause_times\": [");
+ Vector<double>::iterator startIt = s_pauseTimeStarts->begin();
+ Vector<double>::iterator endIt = s_pauseTimeEnds->begin();
+ if (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) {
+ dataLogF("[%f, %f]", *startIt, *endIt);
+ ++startIt;
+ ++endIt;
+ }
+ while (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) {
+ dataLogF(", [%f, %f]", *startIt, *endIt);
+ ++startIt;
+ ++endIt;
+ }
+ dataLogF("], \"start_time\": %f, \"end_time\": %f", s_startTime, s_endTime);
+ }
+ dataLogF("}\n");
+}
+
+void HeapStatistics::exitWithFailure()
+{
+ ASSERT(Options::logHeapStatisticsAtExit());
+ s_endTime = WTF::monotonicallyIncreasingTime();
+ logStatistics();
+ exit(-1);
+}
+
+void HeapStatistics::reportSuccess()
+{
+ ASSERT(Options::logHeapStatisticsAtExit());
+ s_endTime = WTF::monotonicallyIncreasingTime();
+ logStatistics();
+}
+
+#else
+
+void HeapStatistics::initialize()
+{
+}
+
+void HeapStatistics::recordGCPauseTime(double, double)
+{
+}
+
+void HeapStatistics::logStatistics()
+{
+}
+
+void HeapStatistics::exitWithFailure()
+{
+ exit(-1);
+}
+
+void HeapStatistics::reportSuccess()
+{
+}
+
+#endif // OS(UNIX)
+
+class StorageStatistics : public MarkedBlock::VoidFunctor {
+public:
+ StorageStatistics();
+
+ IterationStatus operator()(HeapCell*, HeapCell::Kind) const;
+
+ size_t objectWithOutOfLineStorageCount();
+ size_t objectCount();
+
+ size_t storageSize();
+ size_t storageCapacity();
+
+private:
+ void visit(JSCell*);
+
+ size_t m_objectWithOutOfLineStorageCount;
+ size_t m_objectCount;
+ size_t m_storageSize;
+ size_t m_storageCapacity;
+};
+
+inline StorageStatistics::StorageStatistics()
+ : m_objectWithOutOfLineStorageCount(0)
+ , m_objectCount(0)
+ , m_storageSize(0)
+ , m_storageCapacity(0)
+{
+}
+
+inline void StorageStatistics::visit(JSCell* cell)
+{
+ if (!cell->isObject())
+ return;
+
+ JSObject* object = jsCast<JSObject*>(cell);
+ if (hasIndexedProperties(object->indexingType()))
+ return;
+
+ if (object->structure()->isUncacheableDictionary())
+ return;
+
+ ++m_objectCount;
+ if (!object->hasInlineStorage())
+ ++m_objectWithOutOfLineStorageCount;
+ m_storageSize += object->structure()->totalStorageSize() * sizeof(WriteBarrierBase<Unknown>);
+ m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase<Unknown>);
+}
+
+inline IterationStatus StorageStatistics::operator()(HeapCell* cell, HeapCell::Kind kind) const
+{
+ if (kind == HeapCell::JSCell) {
+ // FIXME: This const_cast exists because this isn't a C++ lambda.
+ // https://bugs.webkit.org/show_bug.cgi?id=159644
+ const_cast<StorageStatistics*>(this)->visit(static_cast<JSCell*>(cell));
+ }
+ return IterationStatus::Continue;
+}
+
+inline size_t StorageStatistics::objectWithOutOfLineStorageCount()
+{
+ return m_objectWithOutOfLineStorageCount;
+}
+
+inline size_t StorageStatistics::objectCount()
+{
+ return m_objectCount;
+}
+
+inline size_t StorageStatistics::storageSize()
+{
+ return m_storageSize;
+}
+
+inline size_t StorageStatistics::storageCapacity()
+{
+ return m_storageCapacity;
+}
+
+void HeapStatistics::dumpObjectStatistics(Heap* heap)
+{
+ dataLogF("\n=== Heap Statistics: ===\n");
+ dataLogF("size: %ldkB\n", static_cast<long>(heap->m_sizeAfterLastCollect / KB));
+ dataLogF("capacity: %ldkB\n", static_cast<long>(heap->capacity() / KB));
+ dataLogF("pause time: %lfs\n\n", heap->m_lastFullGCLength);
+
+ StorageStatistics storageStatistics;
+ {
+ HeapIterationScope iterationScope(*heap);
+ heap->m_objectSpace.forEachLiveCell(iterationScope, storageStatistics);
+ }
+ long wastedPropertyStorageBytes = 0;
+ long wastedPropertyStoragePercent = 0;
+ long objectWithOutOfLineStorageCount = 0;
+ long objectsWithOutOfLineStoragePercent = 0;
+ if ((storageStatistics.storageCapacity() > 0) && (storageStatistics.objectCount() > 0)) {
+ wastedPropertyStorageBytes = static_cast<long>((storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB);
+ wastedPropertyStoragePercent = static_cast<long>(
+ (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100 / storageStatistics.storageCapacity());
+ objectWithOutOfLineStorageCount = static_cast<long>(storageStatistics.objectWithOutOfLineStorageCount());
+ objectsWithOutOfLineStoragePercent = objectWithOutOfLineStorageCount * 100 / storageStatistics.objectCount();
+ }
+ dataLogF("wasted .property storage: %ldkB (%ld%%)\n", wastedPropertyStorageBytes, wastedPropertyStoragePercent);
+ dataLogF("objects with out-of-line .property storage: %ld (%ld%%)\n", objectWithOutOfLineStorageCount, objectsWithOutOfLineStoragePercent);
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapStatisticshfromrev212615trunkSourceJavaScriptCoreheapSweepingScopeh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/heap/HeapStatistics.h (from rev 212615, trunk/Source/JavaScriptCore/heap/SweepingScope.h) (0 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapStatistics.h         (rev 0)
+++ trunk/Source/JavaScriptCore/heap/HeapStatistics.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#pragma once
+
+#include "JSExportMacros.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class Heap;
+
+class HeapStatistics {
+public:
+ NO_RETURN static void exitWithFailure();
+ JS_EXPORT_PRIVATE static void reportSuccess();
+
+ static void initialize();
+ static void recordGCPauseTime(double start, double end);
+
+ static void dumpObjectStatistics(Heap*);
+
+private:
+ static void logStatistics();
+ static Vector<double>* s_pauseTimeStarts;
+ static Vector<double>* s_pauseTimeEnds;
+ static double s_startTime;
+ static double s_endTime;
+};
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHelpingGCScopehfromrev212615trunkSourceJavaScriptCoreheapRunningScopeh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/heap/HelpingGCScope.h (from rev 212615, trunk/Source/JavaScriptCore/heap/RunningScope.h) (0 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HelpingGCScope.h         (rev 0)
+++ trunk/Source/JavaScriptCore/heap/HelpingGCScope.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#pragma once
+
+#include "Heap.h"
+
+namespace JSC {
+
+class HelpingGCScope {
+public:
+ HelpingGCScope(Heap& heap)
+ : m_heap(heap)
+ , m_oldState(m_heap.m_mutatorState)
+ {
+ m_heap.m_mutatorState = MutatorState::HelpingGC;
+ }
+
+ ~HelpingGCScope()
+ {
+ m_heap.m_mutatorState = m_oldState;
+ }
+
+private:
+ Heap& m_heap;
+ MutatorState m_oldState;
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapIncrementalSweepercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -97,7 +97,7 @@
</span><span class="cx"> m_currentAllocator = m_vm->heap.objectSpace().firstAllocator();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void IncrementalSweeper::stopSweeping()
</del><ins>+void IncrementalSweeper::willFinishSweeping()
</ins><span class="cx"> {
</span><span class="cx"> m_currentAllocator = nullptr;
</span><span class="cx"> if (m_vm)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapIncrementalSweeperh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -37,11 +37,11 @@
</span><span class="cx"> public:
</span><span class="cx"> JS_EXPORT_PRIVATE explicit IncrementalSweeper(Heap*);
</span><span class="cx">
</span><del>- JS_EXPORT_PRIVATE void startSweeping();
</del><ins>+ void startSweeping();
</ins><span class="cx">
</span><span class="cx"> JS_EXPORT_PRIVATE void doWork() override;
</span><span class="cx"> bool sweepNextBlock();
</span><del>- JS_EXPORT_PRIVATE void stopSweeping();
</del><ins>+ void willFinishSweeping();
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> void doSweep(double startTime);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMachineStackMarkercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2003-2009, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx"> * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
</span><span class="cx"> * Copyright (C) 2009 Acision BV. All rights reserved.
</span><span class="cx"> *
</span><span class="lines">@@ -313,18 +313,6 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-SUPPRESS_ASAN
-void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks, CurrentThreadState& currentThreadState)
-{
- if (currentThreadState.registerState) {
- void* registersBegin = currentThreadState.registerState;
- void* registersEnd = reinterpret_cast<void*>(roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(currentThreadState.registerState + 1)));
- conservativeRoots.add(registersBegin, registersEnd, jitStubRoutines, codeBlocks);
- }
-
- conservativeRoots.add(currentThreadState.stackTop, currentThreadState.stackOrigin, jitStubRoutines, codeBlocks);
-}
-
</del><span class="cx"> MachineThreads::Thread::Thread(const PlatformThread& platThread, void* base, void* end)
</span><span class="cx"> : platformThread(platThread)
</span><span class="cx"> , stackBase(base)
</span><span class="lines">@@ -1032,11 +1020,8 @@
</span><span class="cx"> *buffer = fastMalloc(*capacity);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks, CurrentThreadState* currentThreadState)
</del><ins>+void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks)
</ins><span class="cx"> {
</span><del>- if (currentThreadState)
- gatherFromCurrentThread(conservativeRoots, jitStubRoutines, codeBlocks, *currentThreadState);
-
</del><span class="cx"> size_t size;
</span><span class="cx"> size_t capacity = 0;
</span><span class="cx"> void* buffer = nullptr;
</span><span class="lines">@@ -1051,11 +1036,4 @@
</span><span class="cx"> fastFree(buffer);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-NEVER_INLINE int callWithCurrentThreadState(const ScopedLambda<void(CurrentThreadState&)>& lambda)
-{
- DECLARE_AND_COMPUTE_CURRENT_THREAD_STATE(state);
- lambda(state);
- return 42; // Suppress tail call optimization.
-}
-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMachineStackMarkerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MachineStackMarker.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MachineStackMarker.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/MachineStackMarker.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx"> * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><span class="cx"> * Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2003-2009, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * This library is free software; you can redistribute it and/or
</span><span class="cx"> * modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -21,10 +21,9 @@
</span><span class="cx">
</span><span class="cx"> #pragma once
</span><span class="cx">
</span><del>-#include "RegisterState.h"
</del><ins>+#include <setjmp.h>
</ins><span class="cx"> #include <wtf/Lock.h>
</span><span class="cx"> #include <wtf/Noncopyable.h>
</span><del>-#include <wtf/ScopedLambda.h>
</del><span class="cx"> #include <wtf/ThreadSpecific.h>
</span><span class="cx">
</span><span class="cx"> #if OS(DARWIN)
</span><span class="lines">@@ -58,19 +57,15 @@
</span><span class="cx"> class Heap;
</span><span class="cx"> class JITStubRoutineSet;
</span><span class="cx">
</span><del>-struct CurrentThreadState {
- void* stackOrigin { nullptr };
- void* stackTop { nullptr };
- RegisterState* registerState { nullptr };
-};
-
</del><span class="cx"> class MachineThreads {
</span><span class="cx"> WTF_MAKE_NONCOPYABLE(MachineThreads);
</span><span class="cx"> public:
</span><ins>+ typedef jmp_buf RegisterState;
+
</ins><span class="cx"> MachineThreads(Heap*);
</span><span class="cx"> ~MachineThreads();
</span><span class="cx">
</span><del>- void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&, CurrentThreadState*);
</del><ins>+ void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&);
</ins><span class="cx">
</span><span class="cx"> JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
</span><span class="cx">
</span><span class="lines">@@ -150,8 +145,6 @@
</span><span class="cx"> Thread* machineThreadForCurrentThread();
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- void gatherFromCurrentThread(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&, CurrentThreadState&);
-
</del><span class="cx"> void tryCopyOtherThreadStack(Thread*, void*, size_t capacity, size_t*);
</span><span class="cx"> bool tryCopyOtherThreadStacks(LockHolder&, void*, size_t capacity, size_t*);
</span><span class="cx">
</span><span class="lines">@@ -168,15 +161,24 @@
</span><span class="cx"> #endif
</span><span class="cx"> };
</span><span class="cx">
</span><del>-#define DECLARE_AND_COMPUTE_CURRENT_THREAD_STATE(stateName) \
- CurrentThreadState stateName; \
- stateName.stackTop = &stateName; \
- stateName.stackOrigin = wtfThreadData().stack().origin(); \
- ALLOCATE_AND_GET_REGISTER_STATE(stateName ## _registerState); \
- stateName.registerState = &stateName ## _registerState
</del><ins>+} // namespace JSC
</ins><span class="cx">
</span><del>-// The return value is meaningless. We just use it to suppress tail call optimization.
-int callWithCurrentThreadState(const ScopedLambda<void(CurrentThreadState&)>&);
</del><ins>+#if COMPILER(GCC_OR_CLANG)
+#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
+#else
+#define REGISTER_BUFFER_ALIGNMENT
+#endif
</ins><span class="cx">
</span><del>-} // namespace JSC
-
</del><ins>+// ALLOCATE_AND_GET_REGISTER_STATE() is a macro so that it is always "inlined" even in debug builds.
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable: 4611)
+#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \
+ MachineThreads::RegisterState registers REGISTER_BUFFER_ALIGNMENT; \
+ setjmp(registers)
+#pragma warning(pop)
+#else
+#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \
+ MachineThreads::RegisterState registers REGISTER_BUFFER_ALIGNMENT; \
+ setjmp(registers)
+#endif
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -216,14 +216,6 @@
</span><span class="cx">
</span><span class="cx"> m_heap->collectIfNecessaryOrDefer(deferralContext);
</span><span class="cx">
</span><del>- // Goofy corner case: the GC called a callback and now this allocator has a currentBlock. This only
- // happens when running WebKit tests, which inject a callback into the GC's finalization.
- if (UNLIKELY(m_currentBlock)) {
- if (crashOnFailure)
- return allocate(deferralContext);
- return tryAllocate(deferralContext);
- }
-
</del><span class="cx"> void* result = tryAllocateWithoutCollecting();
</span><span class="cx">
</span><span class="cx"> if (LIKELY(result != 0))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -26,12 +26,12 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "MarkedBlock.h"
</span><span class="cx">
</span><ins>+#include "HelpingGCScope.h"
</ins><span class="cx"> #include "JSCell.h"
</span><span class="cx"> #include "JSDestructibleObject.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><span class="cx"> #include "MarkedBlockInlines.h"
</span><span class="cx"> #include "SuperSampler.h"
</span><del>-#include "SweepingScope.h"
</del><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><span class="lines">@@ -409,7 +409,8 @@
</span><span class="cx">
</span><span class="cx"> FreeList MarkedBlock::Handle::sweep(SweepMode sweepMode)
</span><span class="cx"> {
</span><del>- SweepingScope sweepingScope(*heap());
</del><ins>+ // FIXME: Maybe HelpingGCScope should just be called SweepScope?
+ HelpingGCScope helpingGCScope(*heap());
</ins><span class="cx">
</span><span class="cx"> m_allocator->setIsUnswept(NoLockingNecessary, this, false);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedSpacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -225,7 +225,7 @@
</span><span class="cx">
</span><span class="cx"> void MarkedSpace::sweep()
</span><span class="cx"> {
</span><del>- m_heap->sweeper()->stopSweeping();
</del><ins>+ m_heap->sweeper()->willFinishSweeping();
</ins><span class="cx"> forEachAllocator(
</span><span class="cx"> [&] (MarkedAllocator& allocator) -> IterationStatus {
</span><span class="cx"> allocator.sweep();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMutatorStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MutatorState.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MutatorState.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/MutatorState.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -41,12 +41,9 @@
</span><span class="cx"> case MutatorState::Allocating:
</span><span class="cx"> out.print("Allocating");
</span><span class="cx"> return;
</span><del>- case MutatorState::Sweeping:
- out.print("Sweeping");
</del><ins>+ case MutatorState::HelpingGC:
+ out.print("HelpingGC");
</ins><span class="cx"> return;
</span><del>- case MutatorState::Collecting:
- out.print("Collecting");
- return;
</del><span class="cx"> }
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMutatorStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MutatorState.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MutatorState.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/MutatorState.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -34,11 +34,8 @@
</span><span class="cx"> // The mutator is in an allocation slow path.
</span><span class="cx"> Allocating,
</span><span class="cx">
</span><del>- // The mutator is sweeping.
- Sweeping,
-
- // The mutator is collecting.
- Collecting
</del><ins>+ // The mutator was asked by the GC to do some work.
+ HelpingGC
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapRegisterStateh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/RegisterState.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/RegisterState.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/RegisterState.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,158 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
- */
-
-#pragma once
-
-#include <setjmp.h>
-
-namespace JSC {
-
-#if !OS(WINDOWS)
-
-// ALLOCATE_AND_GET_REGISTER_STATE has to ensure that the GC sees callee-saves. It achieves this by
-// ensuring that the callee-saves are either spilled to the stack or saved in the RegisterState. The code
-// looks like it's achieving only the latter. However, it's possible that the compiler chooses to use
-// a callee-save for one of the caller's variables, which means that the value that we were interested in
-// got spilled. In that case, we will store something bogus into the RegisterState, and that's OK.
-
-#if CPU(X86)
-struct RegisterState {
- uint32_t ebx;
- uint32_t edi;
- uint32_t esi;
-};
-
-#define SAVE_REG(regname, where) \
- asm volatile ("movl %%" #regname ", %0" : "=m"(where) : : "memory")
-
-#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \
- RegisterState registers; \
- SAVE_REG(ebx, registers.ebx); \
- SAVE_REG(edi, registers.edi); \
- SAVE_REG(esi, registers.esi)
-
-#elif CPU(X86_64)
-struct RegisterState {
- uint64_t rbx;
- uint64_t r12;
- uint64_t r13;
- uint64_t r14;
- uint64_t r15;
-};
-
-#define SAVE_REG(regname, where) \
- asm volatile ("movq %%" #regname ", %0" : "=m"(where) : : "memory")
-
-#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \
- RegisterState registers; \
- SAVE_REG(rbx, registers.rbx); \
- SAVE_REG(r12, registers.r12); \
- SAVE_REG(r13, registers.r13); \
- SAVE_REG(r14, registers.r14); \
- SAVE_REG(r15, registers.r15)
-
-#elif CPU(ARM_THUMB2)
-struct RegisterState {
- uint32_t r4;
- uint32_t r5;
- uint32_t r6;
- uint32_t r8;
- uint32_t r9;
- uint32_t r10;
- uint32_t r11;
-};
-
-#define SAVE_REG(regname, where) \
- asm volatile ("str " #regname ", %0" : "=m"(where) : : "memory")
-
-#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \
- RegisterState registers; \
- SAVE_REG(r4, registers.r4); \
- SAVE_REG(r5, registers.r5); \
- SAVE_REG(r6, registers.r6); \
- SAVE_REG(r8, registers.r8); \
- SAVE_REG(r9, registers.r9); \
- SAVE_REG(r10, registers.r10); \
- SAVE_REG(r11, registers.r11)
-
-#elif CPU(ARM64)
-struct RegisterState {
- uint64_t x19;
- uint64_t x20;
- uint64_t x21;
- uint64_t x22;
- uint64_t x23;
- uint64_t x24;
- uint64_t x25;
- uint64_t x26;
- uint64_t x27;
- uint64_t x28;
-};
-
-#define SAVE_REG(regname, where) \
- asm volatile ("str " #regname ", %0" : "=m"(where) : : "memory")
-
-#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \
- RegisterState registers; \
- SAVE_REG(x19, registers.x19); \
- SAVE_REG(x20, registers.x20); \
- SAVE_REG(x21, registers.x21); \
- SAVE_REG(x22, registers.x22); \
- SAVE_REG(x23, registers.x23); \
- SAVE_REG(x24, registers.x24); \
- SAVE_REG(x25, registers.x25); \
- SAVE_REG(x26, registers.x26); \
- SAVE_REG(x27, registers.x27); \
- SAVE_REG(x28, registers.x28)
-
-#endif
-#endif // !OS(WINDOWS)
-
-#ifndef ALLOCATE_AND_GET_REGISTER_STATE
-#if COMPILER(GCC_OR_CLANG)
-#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
-#else
-#define REGISTER_BUFFER_ALIGNMENT
-#endif
-
-typedef jmp_buf RegisterState;
-
-// ALLOCATE_AND_GET_REGISTER_STATE() is a macro so that it is always "inlined" even in debug builds.
-#if COMPILER(MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4611)
-#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \
- RegisterState registers REGISTER_BUFFER_ALIGNMENT; \
- setjmp(registers)
-#pragma warning(pop)
-#else
-#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \
- RegisterState registers REGISTER_BUFFER_ALIGNMENT; \
- setjmp(registers)
-#endif
-#endif // ALLOCATE_AND_GET_REGISTER_STATE
-
-} // namespace JSC
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapRunningScopeh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/RunningScope.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/RunningScope.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/RunningScope.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,52 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
- */
-
-#pragma once
-
-#include "Heap.h"
-
-namespace JSC {
-
-class RunningScope {
-public:
- RunningScope(Heap& heap)
- : m_heap(heap)
- , m_oldState(m_heap.m_mutatorState)
- {
- m_heap.m_mutatorState = MutatorState::Running;
- }
-
- ~RunningScope()
- {
- m_heap.m_mutatorState = m_oldState;
- }
-
-private:
- Heap& m_heap;
- MutatorState m_oldState;
-};
-
-} // namespace JSC
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -38,7 +38,6 @@
</span><span class="cx"> #include "JSString.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><span class="cx"> #include "SlotVisitorInlines.h"
</span><del>-#include "StopIfNecessaryTimer.h"
</del><span class="cx"> #include "SuperSampler.h"
</span><span class="cx"> #include "VM.h"
</span><span class="cx"> #include <wtf/Lock.h>
</span><span class="lines">@@ -76,13 +75,12 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx">
</span><del>-SlotVisitor::SlotVisitor(Heap& heap, CString codeName)
</del><ins>+SlotVisitor::SlotVisitor(Heap& heap)
</ins><span class="cx"> : m_bytesVisited(0)
</span><span class="cx"> , m_visitCount(0)
</span><span class="cx"> , m_isInParallelMode(false)
</span><span class="cx"> , m_markingVersion(MarkedSpace::initialVersion)
</span><span class="cx"> , m_heap(heap)
</span><del>- , m_codeName(codeName)
</del><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx"> , m_isCheckingForDefaultMarkViolation(false)
</span><span class="cx"> , m_isDraining(false)
</span><span class="lines">@@ -471,12 +469,9 @@
</span><span class="cx"> m_canOptimizeForStoppedMutator = true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-NEVER_INLINE void SlotVisitor::drain(MonotonicTime timeout)
</del><ins>+void SlotVisitor::drain(MonotonicTime timeout)
</ins><span class="cx"> {
</span><del>- if (!m_isInParallelMode) {
- dataLog("FATAL: attempting to drain when not in parallel mode.\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
</del><ins>+ RELEASE_ASSERT(m_isInParallelMode);
</ins><span class="cx">
</span><span class="cx"> auto locker = holdLock(m_rightToRun);
</span><span class="cx">
</span><span class="lines">@@ -586,7 +581,7 @@
</span><span class="cx"> || !m_heap.m_sharedMutatorMarkStack->isEmpty();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-NEVER_INLINE SlotVisitor::SharedDrainResult SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode, MonotonicTime timeout)
</del><ins>+SlotVisitor::SharedDrainResult SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode, MonotonicTime timeout)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(m_isInParallelMode);
</span><span class="cx">
</span><span class="lines">@@ -621,22 +616,8 @@
</span><span class="cx"> if (hasElapsed(timeout))
</span><span class="cx"> return SharedDrainResult::TimedOut;
</span><span class="cx">
</span><del>- if (didReachTermination(locker)) {
</del><ins>+ if (didReachTermination(locker))
</ins><span class="cx"> m_heap.m_markingConditionVariable.notifyAll();
</span><del>-
- // If we're in concurrent mode, then we know that the mutator will eventually do
- // the right thing because:
- // - It's possible that the collector has the conn. In that case, the collector will
- // wake up from the notification above. This will happen if the app released heap
- // access. Native apps can spend a lot of time with heap access released.
- // - It's possible that the mutator will allocate soon. Then it will check if we
- // reached termination. This is the most likely outcome in programs that allocate
- // a lot.
- // - WebCore never releases access. But WebCore has a runloop. The runloop will check
- // if we reached termination.
- // So, this tells the runloop that it's got things to do.
- m_heap.m_stopIfNecessaryTimer->scheduleSoon();
- }
</del><span class="cx">
</span><span class="cx"> auto isReady = [&] () -> bool {
</span><span class="cx"> return hasWork(locker)
</span><span class="lines">@@ -678,9 +659,7 @@
</span><span class="cx">
</span><span class="cx"> ASSERT(Options::numberOfGCMarkers());
</span><span class="cx">
</span><del>- if (Options::numberOfGCMarkers() == 1
- || (m_heap.m_worldState.load() & Heap::mutatorWaitingBit)
- || !m_heap.hasHeapAccess()
</del><ins>+ if (!m_heap.hasHeapAccess()
</ins><span class="cx"> || m_heap.collectorBelievesThatTheWorldIsStopped()) {
</span><span class="cx"> // This is an optimization over drainInParallel() when we have a concurrent mutator but
</span><span class="cx"> // otherwise it is not profitable.
</span><span class="lines">@@ -705,9 +684,6 @@
</span><span class="cx">
</span><span class="cx"> void SlotVisitor::donateAll()
</span><span class="cx"> {
</span><del>- if (isEmpty())
- return;
-
</del><span class="cx"> donateAll(holdLock(m_heap.m_markingMutex));
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -779,11 +755,7 @@
</span><span class="cx">
</span><span class="cx"> void SlotVisitor::donate()
</span><span class="cx"> {
</span><del>- if (!m_isInParallelMode) {
- dataLog("FATAL: Attempting to donate when not in parallel mode.\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
-
</del><ins>+ ASSERT(m_isInParallelMode);
</ins><span class="cx"> if (Options::numberOfGCMarkers() == 1)
</span><span class="cx"> return;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -56,7 +56,7 @@
</span><span class="cx"> friend class Heap;
</span><span class="cx">
</span><span class="cx"> public:
</span><del>- SlotVisitor(Heap&, CString codeName);
</del><ins>+ SlotVisitor(Heap&);
</ins><span class="cx"> ~SlotVisitor();
</span><span class="cx">
</span><span class="cx"> MarkStackArray& collectorMarkStack() { return m_collectorStack; }
</span><span class="lines">@@ -167,8 +167,6 @@
</span><span class="cx"> void setIgnoreNewOpaqueRoots(bool value) { m_ignoreNewOpaqueRoots = value; }
</span><span class="cx">
</span><span class="cx"> void donateAll();
</span><del>-
- const char* codeName() const { return m_codeName.data(); }
</del><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> friend class ParallelModeEnabler;
</span><span class="lines">@@ -230,8 +228,6 @@
</span><span class="cx"> bool m_canOptimizeForStoppedMutator { false };
</span><span class="cx"> Lock m_rightToRun;
</span><span class="cx">
</span><del>- CString m_codeName;
-
</del><span class="cx"> public:
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx"> bool m_isCheckingForDefaultMarkViolation;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapStochasticSpaceTimeMutatorSchedulercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/StochasticSpaceTimeMutatorScheduler.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/StochasticSpaceTimeMutatorScheduler.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/StochasticSpaceTimeMutatorScheduler.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -76,10 +76,6 @@
</span><span class="cx"> m_bytesAllocatedThisCycleAtTheEnd =
</span><span class="cx"> Options::concurrentGCMaxHeadroom() *
</span><span class="cx"> std::max<double>(m_bytesAllocatedThisCycleAtTheBeginning, m_heap.m_maxEdenSize);
</span><del>-
- if (Options::logGC())
- dataLog("ca=", m_bytesAllocatedThisCycleAtTheBeginning / 1024, "kb h=", (m_bytesAllocatedThisCycleAtTheEnd - m_bytesAllocatedThisCycleAtTheBeginning) / 1024, "kb ");
-
</del><span class="cx"> m_beforeConstraints = MonotonicTime::now();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -121,11 +117,6 @@
</span><span class="cx"> Snapshot snapshot(*this);
</span><span class="cx">
</span><span class="cx"> double resumeProbability = mutatorUtilization(snapshot);
</span><del>- if (resumeProbability < Options::epsilonMutatorUtilization()) {
- m_plannedResumeTime = MonotonicTime::infinity();
- return;
- }
-
</del><span class="cx"> bool shouldResume = m_random.get() < resumeProbability;
</span><span class="cx">
</span><span class="cx"> if (shouldResume) {
</span><span class="lines">@@ -144,10 +135,8 @@
</span><span class="cx"> case Stopped:
</span><span class="cx"> return MonotonicTime::now();
</span><span class="cx"> case Resumed: {
</span><del>- // Once we're running, we keep going unless we run out of headroom.
- Snapshot snapshot(*this);
- if (mutatorUtilization(snapshot) < Options::epsilonMutatorUtilization())
- return MonotonicTime::now();
</del><ins>+ // Once we're running, we keep going.
+ // FIXME: Maybe force stop when we run out of headroom?
</ins><span class="cx"> return MonotonicTime::infinity();
</span><span class="cx"> } }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSweepingScopeh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/SweepingScope.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SweepingScope.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/heap/SweepingScope.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,52 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
- */
-
-#pragma once
-
-#include "Heap.h"
-
-namespace JSC {
-
-class SweepingScope {
-public:
- SweepingScope(Heap& heap)
- : m_heap(heap)
- , m_oldState(m_heap.m_mutatorState)
- {
- m_heap.m_mutatorState = MutatorState::Sweeping;
- }
-
- ~SweepingScope()
- {
- m_heap.m_mutatorState = m_oldState;
- }
-
-private:
- Heap& m_heap;
- MutatorState m_oldState;
-};
-
-} // namespace JSC
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITWorklistcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITWorklist.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITWorklist.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/jit/JITWorklist.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -99,7 +99,7 @@
</span><span class="cx">
</span><span class="cx"> class JITWorklist::Thread : public AutomaticThread {
</span><span class="cx"> public:
</span><del>- Thread(const AbstractLocker& locker, JITWorklist& worklist)
</del><ins>+ Thread(const LockHolder& locker, JITWorklist& worklist)
</ins><span class="cx"> : AutomaticThread(locker, worklist.m_lock, worklist.m_condition)
</span><span class="cx"> , m_worklist(worklist)
</span><span class="cx"> {
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> protected:
</span><del>- PollResult poll(const AbstractLocker&) override
</del><ins>+ PollResult poll(const LockHolder&) override
</ins><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT(m_worklist.m_numAvailableThreads);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> #include "GetterSetter.h"
</span><span class="cx"> #include "HeapProfiler.h"
</span><span class="cx"> #include "HeapSnapshotBuilder.h"
</span><ins>+#include "HeapStatistics.h"
</ins><span class="cx"> #include "InitializeThreading.h"
</span><span class="cx"> #include "Interpreter.h"
</span><span class="cx"> #include "JIT.h"
</span><span class="lines">@@ -1083,7 +1084,6 @@
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState*);
</span><del>-static EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState*);
</del><span class="cx">
</span><span class="cx"> struct Script {
</span><span class="cx"> enum class StrictMode {
</span><span class="lines">@@ -1366,7 +1366,6 @@
</span><span class="cx"> addFunction(vm, "waitForReport", functionWaitForReport, 0);
</span><span class="cx">
</span><span class="cx"> addFunction(vm, "heapCapacity", functionHeapCapacity, 0);
</span><del>- addFunction(vm, "flashHeapAccess", functionFlashHeapAccess, 0);
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void addFunction(VM& vm, JSObject* object, const char* name, NativeFunction function, unsigned arguments)
</span><span class="lines">@@ -2649,21 +2648,6 @@
</span><span class="cx"> return JSValue::encode(jsNumber(vm.heap.capacity()));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState* exec)
-{
- VM& vm = exec->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- vm.heap.releaseAccess();
- if (exec->argumentCount() >= 1) {
- double ms = exec->argument(0).toNumber(exec);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- sleep(Seconds::fromMilliseconds(ms));
- }
- vm.heap.acquireAccess();
- return JSValue::encode(jsUndefined());
-}
-
</del><span class="cx"> template<typename ValueType>
</span><span class="cx"> typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, Identifier, ValueType) { }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeInitializeThreadingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx">
</span><span class="cx"> #include "ExecutableAllocator.h"
</span><span class="cx"> #include "Heap.h"
</span><ins>+#include "HeapStatistics.h"
</ins><span class="cx"> #include "Identifier.h"
</span><span class="cx"> #include "JSDateMath.h"
</span><span class="cx"> #include "JSGlobalObject.h"
</span><span class="lines">@@ -59,6 +60,8 @@
</span><span class="cx"> WTF::initializeThreading();
</span><span class="cx"> WTF::initializeGCThreads();
</span><span class="cx"> Options::initialize();
</span><ins>+ if (Options::recordGCPauseTimes())
+ HeapStatistics::initialize();
</ins><span class="cx"> #if ENABLE(WRITE_BARRIER_PROFILING)
</span><span class="cx"> WriteBarrierCounters::initialize();
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCellInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCellInlines.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCellInlines.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/runtime/JSCellInlines.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -280,7 +280,7 @@
</span><span class="cx"> // destructing the object. The GC thread or JIT threads, unlike the mutator thread, are able to access classInfo
</span><span class="cx"> // independent of whether the mutator thread is sweeping or not. Hence, we also check for ownerThread() !=
</span><span class="cx"> // std::this_thread::get_id() to allow the GC thread or JIT threads to pass this assertion.
</span><del>- ASSERT(vm.heap.mutatorState() != MutatorState::Sweeping || vm.apiLock().ownerThread() != std::this_thread::get_id());
</del><ins>+ ASSERT(vm.heap.mutatorState() == MutatorState::Running || vm.apiLock().ownerThread() != std::this_thread::get_id());
</ins><span class="cx"> return structure(vm)->classInfo();
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/runtime/Options.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -317,11 +317,7 @@
</span><span class="cx"> Options::maximumMutatorUtilization() = 0.6;
</span><span class="cx"> Options::concurrentGCMaxHeadroom() = 1.4;
</span><span class="cx"> Options::minimumGCPauseMS() = 1;
</span><del>- Options::useStochasticMutatorScheduler() = false;
- if (WTF::numberOfProcessorCores() <= 1)
- Options::gcIncrementScale() = 1;
- else
- Options::gcIncrementScale() = 0;
</del><ins>+ Options::gcIncrementScale() = 1;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -200,7 +200,6 @@
</span><span class="cx"> v(double, largeHeapGrowthFactor, 1.24, Normal, nullptr) \
</span><span class="cx"> v(double, minimumMutatorUtilization, 0, Normal, nullptr) \
</span><span class="cx"> v(double, maximumMutatorUtilization, 0.7, Normal, nullptr) \
</span><del>- v(double, epsilonMutatorUtilization, 0.01, Normal, nullptr) \
</del><span class="cx"> v(double, concurrentGCMaxHeadroom, 1.5, Normal, nullptr) \
</span><span class="cx"> v(double, concurrentGCPeriodMS, 2, Normal, nullptr) \
</span><span class="cx"> v(bool, useStochasticMutatorScheduler, true, Normal, nullptr) \
</span><span class="lines">@@ -345,6 +344,7 @@
</span><span class="cx"> v(bool, useZombieMode, false, Normal, "debugging option to scribble over dead objects with 0xbadbeef0") \
</span><span class="cx"> v(bool, useImmortalObjects, false, Normal, "debugging option to keep all objects alive forever") \
</span><span class="cx"> v(bool, sweepSynchronously, false, Normal, "debugging option to sweep all dead objects synchronously at GC end before resuming mutator") \
</span><ins>+ v(bool, dumpObjectStatistics, false, Normal, nullptr) \
</ins><span class="cx"> v(unsigned, maxSingleAllocationSize, 0, Configurable, "debugging option to limit individual allocations to a max size (0 = limit not set, N = limit size in bytes)") \
</span><span class="cx"> \
</span><span class="cx"> v(gcLogLevel, logGC, GCLogging::None, Normal, "debugging option to log GC activity (0 = None, 1 = Basic, 2 = Verbose)") \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeTestRunnerUtilscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/TestRunnerUtils.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/TestRunnerUtils.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/JavaScriptCore/runtime/TestRunnerUtils.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx">
</span><span class="cx"> #include "CodeBlock.h"
</span><span class="cx"> #include "FunctionCodeBlock.h"
</span><ins>+#include "HeapStatistics.h"
</ins><span class="cx"> #include "JSCInlines.h"
</span><span class="cx"> #include "LLIntData.h"
</span><span class="cx">
</span><span class="lines">@@ -159,6 +160,8 @@
</span><span class="cx"> // This is a hook called at the bitter end of some of our tests.
</span><span class="cx"> void finalizeStatsAtEndOfTesting()
</span><span class="cx"> {
</span><ins>+ if (Options::logHeapStatisticsAtExit())
+ HeapStatistics::reportSuccess();
</ins><span class="cx"> if (Options::reportLLIntStats())
</span><span class="cx"> LLInt::Data::finalizeStats();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WTF/ChangeLog        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2017-02-19 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r212466.
+ https://bugs.webkit.org/show_bug.cgi?id=168577
+
+ causes crashes on AArch64 on linux, maybe it's causing crashes
+ on iOS too (Requested by pizlo on #webkit).
+
+ Reverted changeset:
+
+ "The collector thread should only start when the mutator
+ doesn't have heap access"
+ https://bugs.webkit.org/show_bug.cgi?id=167737
+ http://trac.webkit.org/changeset/212466
+
</ins><span class="cx"> 2017-02-18 Chris Dumez <cdumez@apple.com>
</span><span class="cx">
</span><span class="cx"> Recursive MessagePort.postMessage() calls causes tab to become unresponsive
</span></span></pre></div>
<a id="trunkSourceWTFwtfAutomaticThreadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/AutomaticThread.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/AutomaticThread.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WTF/wtf/AutomaticThread.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AutomaticThreadCondition::notifyOne(const AbstractLocker& locker)
</del><ins>+void AutomaticThreadCondition::notifyOne(const LockHolder& locker)
</ins><span class="cx"> {
</span><span class="cx"> for (AutomaticThread* thread : m_threads) {
</span><span class="cx"> if (thread->isWaiting(locker)) {
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx"> m_condition.notifyOne();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AutomaticThreadCondition::notifyAll(const AbstractLocker& locker)
</del><ins>+void AutomaticThreadCondition::notifyAll(const LockHolder& locker)
</ins><span class="cx"> {
</span><span class="cx"> m_condition.notifyAll();
</span><span class="cx">
</span><span class="lines">@@ -81,24 +81,24 @@
</span><span class="cx"> m_condition.wait(lock);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AutomaticThreadCondition::add(const AbstractLocker&, AutomaticThread* thread)
</del><ins>+void AutomaticThreadCondition::add(const LockHolder&, AutomaticThread* thread)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(!m_threads.contains(thread));
</span><span class="cx"> m_threads.append(thread);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AutomaticThreadCondition::remove(const AbstractLocker&, AutomaticThread* thread)
</del><ins>+void AutomaticThreadCondition::remove(const LockHolder&, AutomaticThread* thread)
</ins><span class="cx"> {
</span><span class="cx"> m_threads.removeFirst(thread);
</span><span class="cx"> ASSERT(!m_threads.contains(thread));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool AutomaticThreadCondition::contains(const AbstractLocker&, AutomaticThread* thread)
</del><ins>+bool AutomaticThreadCondition::contains(const LockHolder&, AutomaticThread* thread)
</ins><span class="cx"> {
</span><span class="cx"> return m_threads.contains(thread);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-AutomaticThread::AutomaticThread(const AbstractLocker& locker, Box<Lock> lock, RefPtr<AutomaticThreadCondition> condition)
</del><ins>+AutomaticThread::AutomaticThread(const LockHolder& locker, Box<Lock> lock, RefPtr<AutomaticThreadCondition> condition)
</ins><span class="cx"> : m_lock(lock)
</span><span class="cx"> , m_condition(condition)
</span><span class="cx"> {
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx"> m_condition->remove(locker, this);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool AutomaticThread::tryStop(const AbstractLocker&)
</del><ins>+bool AutomaticThread::tryStop(const LockHolder&)
</ins><span class="cx"> {
</span><span class="cx"> if (!m_isRunning)
</span><span class="cx"> return true;
</span><span class="lines">@@ -128,12 +128,12 @@
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool AutomaticThread::isWaiting(const AbstractLocker& locker)
</del><ins>+bool AutomaticThread::isWaiting(const LockHolder& locker)
</ins><span class="cx"> {
</span><span class="cx"> return hasUnderlyingThread(locker) && m_isWaiting;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool AutomaticThread::notify(const AbstractLocker& locker)
</del><ins>+bool AutomaticThread::notify(const LockHolder& locker)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT_UNUSED(locker, hasUnderlyingThread(locker));
</span><span class="cx"> m_isWaiting = false;
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx"> m_isRunningCondition.wait(*m_lock);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AutomaticThread::start(const AbstractLocker&)
</del><ins>+void AutomaticThread::start(const LockHolder&)
</ins><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT(m_isRunning);
</span><span class="cx">
</span><span class="lines">@@ -169,18 +169,18 @@
</span><span class="cx"> ASSERT(m_condition->contains(locker, this));
</span><span class="cx"> }
</span><span class="cx">
</span><del>- auto stopImpl = [&] (const AbstractLocker& locker) {
</del><ins>+ auto stopImpl = [&] (const LockHolder& locker) {
</ins><span class="cx"> thread->threadIsStopping(locker);
</span><span class="cx"> thread->m_hasUnderlyingThread = false;
</span><span class="cx"> };
</span><span class="cx">
</span><del>- auto stopPermanently = [&] (const AbstractLocker& locker) {
</del><ins>+ auto stopPermanently = [&] (const LockHolder& locker) {
</ins><span class="cx"> m_isRunning = false;
</span><span class="cx"> m_isRunningCondition.notifyAll();
</span><span class="cx"> stopImpl(locker);
</span><span class="cx"> };
</span><span class="cx">
</span><del>- auto stopForTimeout = [&] (const AbstractLocker& locker) {
</del><ins>+ auto stopForTimeout = [&] (const LockHolder& locker) {
</ins><span class="cx"> stopImpl(locker);
</span><span class="cx"> };
</span><span class="cx">
</span><span class="lines">@@ -227,7 +227,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AutomaticThread::threadIsStopping(const AbstractLocker&)
</del><ins>+void AutomaticThread::threadIsStopping(const LockHolder&)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWTFwtfAutomaticThreadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/AutomaticThread.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/AutomaticThread.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WTF/wtf/AutomaticThread.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -75,8 +75,8 @@
</span><span class="cx">
</span><span class="cx"> WTF_EXPORT_PRIVATE ~AutomaticThreadCondition();
</span><span class="cx">
</span><del>- WTF_EXPORT_PRIVATE void notifyOne(const AbstractLocker&);
- WTF_EXPORT_PRIVATE void notifyAll(const AbstractLocker&);
</del><ins>+ WTF_EXPORT_PRIVATE void notifyOne(const LockHolder&);
+ WTF_EXPORT_PRIVATE void notifyAll(const LockHolder&);
</ins><span class="cx">
</span><span class="cx"> // You can reuse this condition for other things, just as you would any other condition.
</span><span class="cx"> // However, since conflating conditions could lead to thundering herd, it's best to avoid it.
</span><span class="lines">@@ -90,9 +90,9 @@
</span><span class="cx">
</span><span class="cx"> WTF_EXPORT_PRIVATE AutomaticThreadCondition();
</span><span class="cx">
</span><del>- void add(const AbstractLocker&, AutomaticThread*);
- void remove(const AbstractLocker&, AutomaticThread*);
- bool contains(const AbstractLocker&, AutomaticThread*);
</del><ins>+ void add(const LockHolder&, AutomaticThread*);
+ void remove(const LockHolder&, AutomaticThread*);
+ bool contains(const LockHolder&, AutomaticThread*);
</ins><span class="cx">
</span><span class="cx"> Condition m_condition;
</span><span class="cx"> Vector<AutomaticThread*> m_threads;
</span><span class="lines">@@ -113,17 +113,17 @@
</span><span class="cx"> virtual ~AutomaticThread();
</span><span class="cx">
</span><span class="cx"> // Sometimes it's possible to optimize for the case that there is no underlying thread.
</span><del>- bool hasUnderlyingThread(const AbstractLocker&) const { return m_hasUnderlyingThread; }
</del><ins>+ bool hasUnderlyingThread(const LockHolder&) const { return m_hasUnderlyingThread; }
</ins><span class="cx">
</span><span class="cx"> // This attempts to quickly stop the thread. This will succeed if the thread happens to not be
</span><span class="cx"> // running. Returns true if the thread has been stopped. A good idiom for stopping your automatic
</span><span class="cx"> // thread is to first try this, and if that doesn't work, to tell the thread using your own
</span><span class="cx"> // mechanism (set some flag and then notify the condition).
</span><del>- bool tryStop(const AbstractLocker&);
</del><ins>+ bool tryStop(const LockHolder&);
</ins><span class="cx">
</span><del>- bool isWaiting(const AbstractLocker&);
</del><ins>+ bool isWaiting(const LockHolder&);
</ins><span class="cx">
</span><del>- bool notify(const AbstractLocker&);
</del><ins>+ bool notify(const LockHolder&);
</ins><span class="cx">
</span><span class="cx"> void join();
</span><span class="cx">
</span><span class="lines">@@ -130,7 +130,7 @@
</span><span class="cx"> protected:
</span><span class="cx"> // This logically creates the thread, but in reality the thread won't be created until someone
</span><span class="cx"> // calls AutomaticThreadCondition::notifyOne() or notifyAll().
</span><del>- AutomaticThread(const AbstractLocker&, Box<Lock>, RefPtr<AutomaticThreadCondition>);
</del><ins>+ AutomaticThread(const LockHolder&, Box<Lock>, RefPtr<AutomaticThreadCondition>);
</ins><span class="cx">
</span><span class="cx"> // To understand PollResult and WorkResult, imagine that poll() and work() are being called like
</span><span class="cx"> // so:
</span><span class="lines">@@ -159,7 +159,7 @@
</span><span class="cx"> // }
</span><span class="cx">
</span><span class="cx"> enum class PollResult { Work, Stop, Wait };
</span><del>- virtual PollResult poll(const AbstractLocker&) = 0;
</del><ins>+ virtual PollResult poll(const LockHolder&) = 0;
</ins><span class="cx">
</span><span class="cx"> enum class WorkResult { Continue, Stop };
</span><span class="cx"> virtual WorkResult work() = 0;
</span><span class="lines">@@ -168,12 +168,12 @@
</span><span class="cx"> // when the thread dies. These methods let you do this. You can override these methods, and you
</span><span class="cx"> // can be sure that the default ones don't do anything (so you don't need a super call).
</span><span class="cx"> virtual void threadDidStart();
</span><del>- virtual void threadIsStopping(const AbstractLocker&);
</del><ins>+ virtual void threadIsStopping(const LockHolder&);
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> friend class AutomaticThreadCondition;
</span><span class="cx">
</span><del>- void start(const AbstractLocker&);
</del><ins>+ void start(const LockHolder&);
</ins><span class="cx">
</span><span class="cx"> Box<Lock> m_lock;
</span><span class="cx"> RefPtr<AutomaticThreadCondition> m_condition;
</span></span></pre></div>
<a id="trunkSourceWTFwtfNumberOfCorescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/NumberOfCores.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/NumberOfCores.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WTF/wtf/NumberOfCores.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -47,15 +47,6 @@
</span><span class="cx">
</span><span class="cx"> if (s_numberOfCores > 0)
</span><span class="cx"> return s_numberOfCores;
</span><del>-
- if (const char* coresEnv = getenv("WTF_numberOfProcessorCores")) {
- unsigned numberOfCores;
- if (sscanf(coresEnv, "%u", &numberOfCores) == 1) {
- s_numberOfCores = numberOfCores;
- return s_numberOfCores;
- } else
- fprintf(stderr, "WARNING: failed to parse WTF_numberOfProcessorCores=%s\n", coresEnv);
- }
</del><span class="cx">
</span><span class="cx"> #if OS(DARWIN)
</span><span class="cx"> unsigned result;
</span></span></pre></div>
<a id="trunkSourceWTFwtfParallelHelperPoolcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/ParallelHelperPool.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/ParallelHelperPool.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WTF/wtf/ParallelHelperPool.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -88,7 +88,7 @@
</span><span class="cx"> finish();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void ParallelHelperClient::finish(const AbstractLocker&)
</del><ins>+void ParallelHelperClient::finish(const LockHolder&)
</ins><span class="cx"> {
</span><span class="cx"> m_task = nullptr;
</span><span class="cx"> while (m_numActive)
</span><span class="lines">@@ -95,7 +95,7 @@
</span><span class="cx"> m_pool->m_workCompleteCondition.wait(*m_pool->m_lock);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RefPtr<SharedTask<void ()>> ParallelHelperClient::claimTask(const AbstractLocker&)
</del><ins>+RefPtr<SharedTask<void ()>> ParallelHelperClient::claimTask(const LockHolder&)
</ins><span class="cx"> {
</span><span class="cx"> if (!m_task)
</span><span class="cx"> return nullptr;
</span><span class="lines">@@ -170,7 +170,7 @@
</span><span class="cx">
</span><span class="cx"> class ParallelHelperPool::Thread : public AutomaticThread {
</span><span class="cx"> public:
</span><del>- Thread(const AbstractLocker& locker, ParallelHelperPool& pool)
</del><ins>+ Thread(const LockHolder& locker, ParallelHelperPool& pool)
</ins><span class="cx"> : AutomaticThread(locker, pool.m_lock, pool.m_workAvailableCondition)
</span><span class="cx"> , m_pool(pool)
</span><span class="cx"> {
</span><span class="lines">@@ -177,7 +177,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> protected:
</span><del>- PollResult poll(const AbstractLocker& locker) override
</del><ins>+ PollResult poll(const LockHolder& locker) override
</ins><span class="cx"> {
</span><span class="cx"> if (m_pool.m_isDying)
</span><span class="cx"> return PollResult::Stop;
</span><span class="lines">@@ -203,7 +203,7 @@
</span><span class="cx"> RefPtr<SharedTask<void ()>> m_task;
</span><span class="cx"> };
</span><span class="cx">
</span><del>-void ParallelHelperPool::didMakeWorkAvailable(const AbstractLocker& locker)
</del><ins>+void ParallelHelperPool::didMakeWorkAvailable(const LockHolder& locker)
</ins><span class="cx"> {
</span><span class="cx"> while (m_numThreads > m_threads.size())
</span><span class="cx"> m_threads.append(adoptRef(new Thread(locker, *this)));
</span><span class="lines">@@ -210,12 +210,12 @@
</span><span class="cx"> m_workAvailableCondition->notifyAll(locker);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool ParallelHelperPool::hasClientWithTask(const AbstractLocker& locker)
</del><ins>+bool ParallelHelperPool::hasClientWithTask(const LockHolder& locker)
</ins><span class="cx"> {
</span><span class="cx"> return !!getClientWithTask(locker);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-ParallelHelperClient* ParallelHelperPool::getClientWithTask(const AbstractLocker&)
</del><ins>+ParallelHelperClient* ParallelHelperPool::getClientWithTask(const LockHolder&)
</ins><span class="cx"> {
</span><span class="cx"> // We load-balance by being random.
</span><span class="cx"> unsigned startIndex = m_random.getUint32(m_clients.size());
</span></span></pre></div>
<a id="trunkSourceWTFwtfParallelHelperPoolh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/ParallelHelperPool.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/ParallelHelperPool.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WTF/wtf/ParallelHelperPool.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -168,8 +168,8 @@
</span><span class="cx"> private:
</span><span class="cx"> friend class ParallelHelperPool;
</span><span class="cx">
</span><del>- void finish(const AbstractLocker&);
- RefPtr<SharedTask<void ()>> claimTask(const AbstractLocker&);
</del><ins>+ void finish(const LockHolder&);
+ RefPtr<SharedTask<void ()>> claimTask(const LockHolder&);
</ins><span class="cx"> void runTask(RefPtr<SharedTask<void ()>>);
</span><span class="cx">
</span><span class="cx"> RefPtr<ParallelHelperPool> m_pool;
</span><span class="lines">@@ -193,11 +193,11 @@
</span><span class="cx"> class Thread;
</span><span class="cx"> friend class Thread;
</span><span class="cx">
</span><del>- void didMakeWorkAvailable(const AbstractLocker&);
</del><ins>+ void didMakeWorkAvailable(const LockHolder&);
</ins><span class="cx">
</span><del>- bool hasClientWithTask(const AbstractLocker&);
- ParallelHelperClient* getClientWithTask(const AbstractLocker&);
- ParallelHelperClient* waitForClientWithTask(const AbstractLocker&);
</del><ins>+ bool hasClientWithTask(const LockHolder&);
+ ParallelHelperClient* getClientWithTask(const LockHolder&);
+ ParallelHelperClient* waitForClientWithTask(const LockHolder&);
</ins><span class="cx">
</span><span class="cx"> Box<Lock> m_lock; // AutomaticThread wants this in a box for safety.
</span><span class="cx"> RefPtr<AutomaticThreadCondition> m_workAvailableCondition;
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WebCore/ChangeLog        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2017-02-19 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r212466.
+ https://bugs.webkit.org/show_bug.cgi?id=168577
+
+ causes crashes on AArch64 on linux, maybe it's causing crashes
+ on iOS too (Requested by pizlo on #webkit).
+
+ Reverted changeset:
+
+ "The collector thread should only start when the mutator
+ doesn't have heap access"
+ https://bugs.webkit.org/show_bug.cgi?id=167737
+ http://trac.webkit.org/changeset/212466
+
</ins><span class="cx"> 2017-02-19 Zalan Bujtas <zalan@apple.com>
</span><span class="cx">
</span><span class="cx"> Simple line layout: Implement positionForPoint.
</span></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapGCFinalizationCallbackh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/ForwardingHeaders/heap/GCFinalizationCallback.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/GCFinalizationCallback.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/GCFinalizationCallback.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,3 +0,0 @@
</span><del>-#pragma once
-#include <JavaScriptCore/GCFinalizationCallback.h>
-
</del></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapIncrementalSweeperh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/ForwardingHeaders/heap/IncrementalSweeper.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/IncrementalSweeper.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/IncrementalSweeper.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,2 +0,0 @@
</span><del>-#pragma once
-#include <JavaScriptCore/IncrementalSweeper.h>
</del></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapMachineStackMarkerh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/ForwardingHeaders/heap/MachineStackMarker.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/MachineStackMarker.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/MachineStackMarker.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,2 +0,0 @@
</span><del>-#pragma once
-#include <JavaScriptCore/MachineStackMarker.h>
</del></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapRunningScopeh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/ForwardingHeaders/heap/RunningScope.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/RunningScope.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/RunningScope.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,2 +0,0 @@
</span><del>-#pragma once
-#include <JavaScriptCore/RunningScope.h>
</del></span></pre></div>
<a id="trunkSourceWebCorebindingsjsCommonVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/CommonVM.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/CommonVM.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WebCore/bindings/js/CommonVM.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -30,7 +30,6 @@
</span><span class="cx"> #include "Settings.h"
</span><span class="cx"> #include "WebCoreJSClientData.h"
</span><span class="cx"> #include <heap/HeapInlines.h>
</span><del>-#include "heap/MachineStackMarker.h"
</del><span class="cx"> #include <runtime/VM.h>
</span><span class="cx"> #include <wtf/MainThread.h>
</span><span class="cx"> #include <wtf/text/AtomicString.h>
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WebCore/testing/Internals.cpp        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -138,9 +138,6 @@
</span><span class="cx"> #include "WritingDirection.h"
</span><span class="cx"> #include "XMLHttpRequest.h"
</span><span class="cx"> #include <bytecode/CodeBlock.h>
</span><del>-#include <heap/GCFinalizationCallback.h>
-#include <heap/IncrementalSweeper.h>
-#include <heap/RunningScope.h>
</del><span class="cx"> #include <inspector/InspectorAgentBase.h>
</span><span class="cx"> #include <inspector/InspectorFrontendChannel.h>
</span><span class="cx"> #include <inspector/InspectorValues.h>
</span><span class="lines">@@ -234,15 +231,10 @@
</span><span class="cx"> #include "QuickLook.h"
</span><span class="cx"> #endif
</span><span class="cx">
</span><del>-using JSC::ArgList;
</del><span class="cx"> using JSC::CallData;
</span><span class="cx"> using JSC::CallType;
</span><span class="cx"> using JSC::CodeBlock;
</span><del>-using JSC::DeferGCForAWhile;
-using JSC::ExecState;
</del><span class="cx"> using JSC::FunctionExecutable;
</span><del>-using JSC::GCFinalizationCallback;
-using JSC::Heap;
</del><span class="cx"> using JSC::Identifier;
</span><span class="cx"> using JSC::JSFunction;
</span><span class="cx"> using JSC::JSGlobalObject;
</span><span class="lines">@@ -250,11 +242,8 @@
</span><span class="cx"> using JSC::JSValue;
</span><span class="cx"> using JSC::MarkedArgumentBuffer;
</span><span class="cx"> using JSC::PropertySlot;
</span><del>-using JSC::RunningScope;
</del><span class="cx"> using JSC::ScriptExecutable;
</span><span class="cx"> using JSC::StackVisitor;
</span><del>-using JSC::Strong;
-using JSC::VM;
</del><span class="cx">
</span><span class="cx"> using namespace Inspector;
</span><span class="cx">
</span><span class="lines">@@ -1694,8 +1683,8 @@
</span><span class="cx">
</span><span class="cx"> String Internals::parserMetaData(JSC::JSValue code)
</span><span class="cx"> {
</span><del>- VM& vm = contextDocument()->vm();
- ExecState* exec = vm.topCallFrame;
</del><ins>+ JSC::VM& vm = contextDocument()->vm();
+ JSC::ExecState* exec = vm.topCallFrame;
</ins><span class="cx"> ScriptExecutable* executable;
</span><span class="cx">
</span><span class="cx"> if (!code || code.isNull() || code.isUndefined()) {
</span><span class="lines">@@ -3548,7 +3537,7 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE(READABLE_STREAM_API)
</span><span class="cx">
</span><del>-bool Internals::isReadableStreamDisturbed(ExecState& state, JSValue stream)
</del><ins>+bool Internals::isReadableStreamDisturbed(JSC::ExecState& state, JSValue stream)
</ins><span class="cx"> {
</span><span class="cx"> JSGlobalObject* globalObject = state.vmEntryGlobalObject();
</span><span class="cx"> JSVMClientData* clientData = static_cast<JSVMClientData*>(state.vm().clientData);
</span><span class="lines">@@ -3723,47 +3712,4 @@
</span><span class="cx"> document.page()->setAsRunningUserScripts();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool Internals::isGCRunning(ExecState& exec)
-{
- return !!exec.vm().heap.collectionScope();
-}
-
-void Internals::addGCFinalizationCallback(ExecState& exec, JSValue value)
-{
- VM& vm = exec.vm();
- Strong<JSC::Unknown> callback(vm, value);
- Strong<JSGlobalObject> globalObject(vm, exec.lexicalGlobalObject());
- exec.vm().heap.addFinalizationCallback(
- JSC::createGCFinalizationCallback(
- [=] (GCFinalizationCallback*, Heap&) mutable {
- // This code is basically unsound. Everything in JSC assumes that some allocations, like
- // string allocations, are pure: they aren't going to clobber the heap. So, any JS code
- // you supply to this callback better be super careful that it doesn't violate that
- // assumption in some scary way. This kind of hack is really only appropriate for test
- // code.
- ExecState* exec = globalObject->globalExec();
- VM& vm = exec->vm();
- DeferGCForAWhile deferGC(vm.heap);
- RunningScope runningScope(vm.heap);
- auto scope = DECLARE_CATCH_SCOPE(vm);
- CallData callData;
- CallType callType = JSC::getCallData(callback.get(), callData);
- JSC::call(exec, callback.get(), callType, callData, JSC::jsNull(), ArgList());
- if (scope.exception()) {
- dataLog("Warning: got exception.\n");
- scope.clearException();
- }
- }));
-}
-
-void Internals::stopSweeping(ExecState& exec)
-{
- exec.vm().heap.sweeper()->stopSweeping();
-}
-
-void Internals::startSweeping(ExecState& exec)
-{
- exec.vm().heap.sweeper()->startSweeping();
-}
-
</del><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WebCore/testing/Internals.h        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -530,11 +530,6 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> void setAsRunningUserScripts(Document&);
</span><del>-
- bool isGCRunning(JSC::ExecState&);
- void addGCFinalizationCallback(JSC::ExecState&, JSC::JSValue);
- void stopSweeping(JSC::ExecState&);
- void startSweeping(JSC::ExecState&);
</del><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> explicit Internals(Document&);
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.idl (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.idl        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Source/WebCore/testing/Internals.idl        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -504,9 +504,4 @@
</span><span class="cx"> [CallWith=Document] void setAsRunningUserScripts();
</span><span class="cx">
</span><span class="cx"> void disableTileSizeUpdateDelay();
</span><del>-
- [CallWith=ScriptState] boolean isGCRunning();
- [CallWith=ScriptState] void addGCFinalizationCallback(any callback);
- [CallWith=ScriptState] void stopSweeping();
- [CallWith=ScriptState] void startSweeping();
</del><span class="cx"> };
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Tools/ChangeLog        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2017-02-19 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r212466.
+ https://bugs.webkit.org/show_bug.cgi?id=168577
+
+ causes crashes on AArch64 on linux, maybe it's causing crashes
+ on iOS too (Requested by pizlo on #webkit).
+
+ Reverted changeset:
+
+ "The collector thread should only start when the mutator
+ doesn't have heap access"
+ https://bugs.webkit.org/show_bug.cgi?id=167737
+ http://trac.webkit.org/changeset/212466
+
</ins><span class="cx"> 2017-02-17 Aakash Jain <aakash_jain@apple.com>
</span><span class="cx">
</span><span class="cx"> Fix failure from r212579.
</span></span></pre></div>
<a id="trunkToolsScriptsrunjscstresstests"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/run-jsc-stress-tests (212615 => 212616)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/run-jsc-stress-tests        2017-02-19 16:24:20 UTC (rev 212615)
+++ trunk/Tools/Scripts/run-jsc-stress-tests        2017-02-19 22:07:58 UTC (rev 212616)
</span><span class="lines">@@ -1468,11 +1468,11 @@
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> def runNoisyTestNoCJIT
</span><del>- runNoisyTest("ftl-no-cjit", "--validateBytecode=true", "--validateGraphAtEachPhase=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS))
</del><ins>+ runNoisyTest("ftl-no-cjit", "--validateBytecode=true", "--validateGraphAtEachPhase=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS))
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> def runNoisyTestEagerNoCJIT
</span><del>- runNoisyTest("ftl-eager-no-cjit", "--validateBytecode=true", "--validateGraphAtEachPhase=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS))
</del><ins>+ runNoisyTest("ftl-eager-no-cjit", "--validateBytecode=true", "--validateGraphAtEachPhase=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS))
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> def defaultRunNoisyTest
</span></span></pre>
</div>
</div>
</body>
</html>