Revision: 24504
Author: [email protected]
Date: Fri Oct 10 00:05:16 2014 UTC
Log: Version 3.30.7 (based on bleeding_edge revision r24503)
Fix computation of UTC time from local time at DST change points (issue
3116, Chromium issues 415424, 417640).
Convert `obj` ToObject in Object.keys() (issue 3587).
Performance and stability improvements on all platforms.
https://code.google.com/p/v8/source/detail?r=24504
Added:
/trunk/test/js-perf-test
/trunk/test/js-perf-test/Collections
/trunk/test/js-perf-test/Collections/Collections.json
/trunk/test/js-perf-test/Collections/base.js
/trunk/test/js-perf-test/Collections/map.js
/trunk/test/js-perf-test/Collections/run.js
/trunk/test/js-perf-test/Collections/set.js
/trunk/test/js-perf-test/Collections/weakmap.js
/trunk/test/js-perf-test/Collections/weakset.js
/trunk/test/mjsunit/regress/regress-3116.js
/trunk/tools/sanitizers
/trunk/tools/sanitizers/tsan_suppressions.txt
Deleted:
/trunk/test/perf-test/Collections/Collections.json
/trunk/test/perf-test/Collections/base.js
/trunk/test/perf-test/Collections/map.js
/trunk/test/perf-test/Collections/run.js
/trunk/test/perf-test/Collections/set.js
/trunk/test/perf-test/Collections/weakmap.js
/trunk/test/perf-test/Collections/weakset.js
Modified:
/trunk/AUTHORS
/trunk/ChangeLog
/trunk/build/toolchain.gypi
/trunk/include/v8-platform.h
/trunk/src/arm/codegen-arm.cc
/trunk/src/arm/full-codegen-arm.cc
/trunk/src/arm64/codegen-arm64.cc
/trunk/src/arm64/full-codegen-arm64.cc
/trunk/src/ast.h
/trunk/src/base/bits.h
/trunk/src/base/cpu.cc
/trunk/src/base/utils/random-number-generator.cc
/trunk/src/base/utils/random-number-generator.h
/trunk/src/builtins.cc
/trunk/src/builtins.h
/trunk/src/compiler/arm64/code-generator-arm64.cc
/trunk/src/compiler/arm64/instruction-codes-arm64.h
/trunk/src/compiler/arm64/instruction-selector-arm64.cc
/trunk/src/compiler/ia32/code-generator-ia32.cc
/trunk/src/compiler/machine-operator-reducer.cc
/trunk/src/compiler/machine-operator.cc
/trunk/src/compiler/machine-operator.h
/trunk/src/date.h
/trunk/src/flag-definitions.h
/trunk/src/full-codegen.h
/trunk/src/heap/mark-compact.cc
/trunk/src/ia32/assembler-ia32.cc
/trunk/src/ia32/assembler-ia32.h
/trunk/src/ia32/codegen-ia32.cc
/trunk/src/ia32/disasm-ia32.cc
/trunk/src/ia32/full-codegen-ia32.cc
/trunk/src/ia32/macro-assembler-ia32.cc
/trunk/src/ia32/macro-assembler-ia32.h
/trunk/src/ic/arm/ic-arm.cc
/trunk/src/ic/arm64/ic-arm64.cc
/trunk/src/ic/ia32/ic-ia32.cc
/trunk/src/ic/ic.cc
/trunk/src/ic/ic.h
/trunk/src/ic/mips/ic-mips.cc
/trunk/src/ic/mips64/ic-mips64.cc
/trunk/src/ic/x64/ic-x64.cc
/trunk/src/ic/x64/stub-cache-x64.cc
/trunk/src/log.cc
/trunk/src/mips/codegen-mips.cc
/trunk/src/mips/constants-mips.h
/trunk/src/mips/full-codegen-mips.cc
/trunk/src/mips64/codegen-mips64.cc
/trunk/src/mips64/full-codegen-mips64.cc
/trunk/src/mips64/macro-assembler-mips64.cc
/trunk/src/mips64/simulator-mips64.cc
/trunk/src/optimizing-compiler-thread.cc
/trunk/src/optimizing-compiler-thread.h
/trunk/src/parser.cc
/trunk/src/parser.h
/trunk/src/preparser.cc
/trunk/src/preparser.h
/trunk/src/runtime/runtime-classes.cc
/trunk/src/runtime/runtime-test.cc
/trunk/src/runtime/runtime.h
/trunk/src/v8natives.js
/trunk/src/version.cc
/trunk/src/x64/codegen-x64.cc
/trunk/src/x64/full-codegen-x64.cc
/trunk/src/x87/builtins-x87.cc
/trunk/src/x87/debug-x87.cc
/trunk/src/x87/full-codegen-x87.cc
/trunk/test/mjsunit/harmony/super.js
/trunk/test/mjsunit/third_party/object-keys.js
/trunk/test/test262/test262.status
/trunk/test/unittests/base/bits-unittest.cc
/trunk/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
/trunk/test/unittests/compiler/change-lowering-unittest.cc
/trunk/test/unittests/compiler/graph-unittest.cc
/trunk/test/unittests/compiler/graph-unittest.h
/trunk/test/unittests/compiler/machine-operator-reducer-unittest.cc
/trunk/tools/run-llprof.sh
/trunk/tools/run-tests.py
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Collections/Collections.json Fri Oct 10
00:05:16 2014 UTC
@@ -0,0 +1,15 @@
+{
+ "path": ["."],
+ "main": "run.js",
+ "flags": ["--harmony-collections"],
+ "run_count": 5,
+ "units": "score",
+ "results_regexp": "^%s\\-Collections\\(Score\\): (.+)$",
+ "total": true,
+ "tests": [
+ {"name": "Map"},
+ {"name": "Set"},
+ {"name": "WeakMap"},
+ {"name": "WeakSet"}
+ ]
+}
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Collections/base.js Fri Oct 10 00:05:16 2014
UTC
@@ -0,0 +1,367 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+// 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,
deterministicIterations,
+ run, setup, tearDown, rmsResult, minIterations) {
+ this.name = name;
+ this.doWarmup = doWarmup;
+ this.doDeterministic = doDeterministic;
+ this.deterministicIterations = deterministicIterations;
+ this.run = run;
+ this.Setup = setup ? setup : function() { };
+ this.TearDown = tearDown ? tearDown : function() { };
+ this.rmsResult = rmsResult ? rmsResult : 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 = '1';
+
+
+// Defines global benchsuite running mode that overrides benchmark suite
+// behavior. Intended to be set by the benchmark driver. Undefined
+// values here allow a benchmark to define behaviour itself.
+BenchmarkSuite.config = {
+ doWarmup: undefined,
+ doDeterministic: undefined
+};
+
+
+// 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, skipBenchmarks) {
+ skipBenchmarks = typeof skipBenchmarks === 'undefined' ? [] :
skipBenchmarks;
+ 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);
+ if (skipBenchmarks.indexOf(suite.name) > -1) {
+ suite.NotifySkipped(runner);
+ } else {
+ 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 geometric mean of a set of rms 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);
+ }
+ }
+ }
+}
+
+
+BenchmarkSuite.prototype.NotifySkipped = function(runner) {
+ BenchmarkSuite.scores.push(1); // push default reference score.
+ if (runner.NotifyResult) {
+ runner.NotifyResult(this.name, "Skipped");
+ }
+}
+
+
+// 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) {
+ var config = BenchmarkSuite.config;
+ var doWarmup = config.doWarmup !== undefined
+ ? config.doWarmup
+ : benchmark.doWarmup;
+ var doDeterministic = config.doDeterministic !== undefined
+ ? config.doDeterministic
+ : benchmark.doDeterministic;
+
+ 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; (doDeterministic ?
+ i<benchmark.deterministicIterations : 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 (!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 rms = (benchmark.rmsResult != null) ? benchmark.rmsResult() : 0;
+ this.NotifyStep(new BenchmarkResult(benchmark, usec, rms));
+ 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();
+}
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Collections/map.js Fri Oct 10 00:05:16 2014 UTC
@@ -0,0 +1,81 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var MapBenchmark = new BenchmarkSuite('Map', [1000], [
+ new Benchmark('Set', false, false, 0, MapSet),
+ new Benchmark('Has', false, false, 0, MapHas, MapSetup, MapTearDown),
+ new Benchmark('Get', false, false, 0, MapGet, MapSetup, MapTearDown),
+ new Benchmark('Delete', false, false, 0, MapDelete, MapSetup,
MapTearDown),
+ new Benchmark('ForEach', false, false, 0, MapForEach, MapSetup,
MapTearDown),
+]);
+
+
+var map;
+var N = 10;
+
+
+function MapSetup() {
+ map = new Map;
+ for (var i = 0; i < N; i++) {
+ map.set(i, i);
+ }
+}
+
+
+function MapTearDown() {
+ map = null;
+}
+
+
+function MapSet() {
+ MapSetup();
+ MapTearDown();
+}
+
+
+function MapHas() {
+ for (var i = 0; i < N; i++) {
+ if (!map.has(i)) {
+ throw new Error();
+ }
+ }
+ for (var i = N; i < 2 * N; i++) {
+ if (map.has(i)) {
+ throw new Error();
+ }
+ }
+}
+
+
+function MapGet() {
+ for (var i = 0; i < N; i++) {
+ if (map.get(i) !== i) {
+ throw new Error();
+ }
+ }
+ for (var i = N; i < 2 * N; i++) {
+ if (map.get(i) !== undefined) {
+ throw new Error();
+ }
+ }
+}
+
+
+function MapDelete() {
+ // This is run more than once per setup so we will end up deleting items
+ // more than once. Therefore, we do not the return value of delete.
+ for (var i = 0; i < N; i++) {
+ map.delete(i);
+ }
+}
+
+
+function MapForEach() {
+ map.forEach(function(v, k) {
+ if (v !== k) {
+ throw new Error();
+ }
+ });
+}
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Collections/run.js Fri Oct 10 00:05:16 2014 UTC
@@ -0,0 +1,30 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+load('base.js');
+load('map.js');
+load('set.js');
+load('weakmap.js');
+load('weakset.js');
+
+
+var success = true;
+
+function PrintResult(name, result) {
+ print(name + '-Collections(Score): ' + result);
+}
+
+
+function PrintError(name, error) {
+ PrintResult(name, error);
+ success = false;
+}
+
+
+BenchmarkSuite.config.doWarmup = undefined;
+BenchmarkSuite.config.doDeterministic = undefined;
+
+BenchmarkSuite.RunSuites({ NotifyResult: PrintResult,
+ NotifyError: PrintError });
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Collections/set.js Fri Oct 10 00:05:16 2014 UTC
@@ -0,0 +1,66 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var SetBenchmark = new BenchmarkSuite('Set', [1000], [
+ new Benchmark('Add', false, false, 0, SetAdd),
+ new Benchmark('Has', false, false, 0, SetHas, SetSetup, SetTearDown),
+ new Benchmark('Delete', false, false, 0, SetDelete, SetSetup,
SetTearDown),
+ new Benchmark('ForEach', false, false, 0, SetForEach, SetSetup,
SetTearDown),
+]);
+
+
+var set;
+var N = 10;
+
+
+function SetSetup() {
+ set = new Set;
+ for (var i = 0; i < N; i++) {
+ set.add(i);
+ }
+}
+
+
+function SetTearDown() {
+ map = null;
+}
+
+
+function SetAdd() {
+ SetSetup();
+ SetTearDown();
+}
+
+
+function SetHas() {
+ for (var i = 0; i < N; i++) {
+ if (!set.has(i)) {
+ throw new Error();
+ }
+ }
+ for (var i = N; i < 2 * N; i++) {
+ if (set.has(i)) {
+ throw new Error();
+ }
+ }
+}
+
+
+function SetDelete() {
+ // This is run more than once per setup so we will end up deleting items
+ // more than once. Therefore, we do not the return value of delete.
+ for (var i = 0; i < N; i++) {
+ set.delete(i);
+ }
+}
+
+
+function SetForEach() {
+ set.forEach(function(v, k) {
+ if (v !== k) {
+ throw new Error();
+ }
+ });
+}
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Collections/weakmap.js Fri Oct 10 00:05:16
2014 UTC
@@ -0,0 +1,80 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var MapBenchmark = new BenchmarkSuite('WeakMap', [1000], [
+ new Benchmark('Set', false, false, 0, WeakMapSet),
+ new Benchmark('Has', false, false, 0, WeakMapHas, WeakMapSetup,
+ WeakMapTearDown),
+ new Benchmark('Get', false, false, 0, WeakMapGet, WeakMapSetup,
+ WeakMapTearDown),
+ new Benchmark('Delete', false, false, 0, WeakMapDelete, WeakMapSetup,
+ WeakMapTearDown),
+]);
+
+
+var wm;
+var N = 10;
+var keys = [];
+
+
+for (var i = 0; i < N * 2; i++) {
+ keys[i] = {};
+}
+
+
+function WeakMapSetup() {
+ wm = new WeakMap;
+ for (var i = 0; i < N; i++) {
+ wm.set(keys[i], i);
+ }
+}
+
+
+function WeakMapTearDown() {
+ wm = null;
+}
+
+
+function WeakMapSet() {
+ WeakMapSetup();
+ WeakMapTearDown();
+}
+
+
+function WeakMapHas() {
+ for (var i = 0; i < N; i++) {
+ if (!wm.has(keys[i])) {
+ throw new Error();
+ }
+ }
+ for (var i = N; i < 2 * N; i++) {
+ if (wm.has(keys[i])) {
+ throw new Error();
+ }
+ }
+}
+
+
+function WeakMapGet() {
+ for (var i = 0; i < N; i++) {
+ if (wm.get(keys[i]) !== i) {
+ throw new Error();
+ }
+ }
+ for (var i = N; i < 2 * N; i++) {
+ if (wm.get(keys[i]) !== undefined) {
+ throw new Error();
+ }
+ }
+}
+
+
+function WeakMapDelete() {
+ // This is run more than once per setup so we will end up deleting items
+ // more than once. Therefore, we do not the return value of delete.
+ for (var i = 0; i < N; i++) {
+ wm.delete(keys[i]);
+ }
+}
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Collections/weakset.js Fri Oct 10 00:05:16
2014 UTC
@@ -0,0 +1,64 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var SetBenchmark = new BenchmarkSuite('WeakSet', [1000], [
+ new Benchmark('Add', false, false, 0, WeakSetAdd),
+ new Benchmark('Has', false, false, 0, WeakSetHas, WeakSetSetup,
+ WeakSetTearDown),
+ new Benchmark('Delete', false, false, 0, WeakSetDelete, WeakSetSetup,
+ WeakSetTearDown),
+]);
+
+
+var ws;
+var N = 10;
+var keys = [];
+
+
+for (var i = 0; i < N * 2; i++) {
+ keys[i] = {};
+}
+
+
+function WeakSetSetup() {
+ ws = new WeakSet;
+ for (var i = 0; i < N; i++) {
+ ws.add(keys[i]);
+ }
+}
+
+
+function WeakSetTearDown() {
+ ws = null;
+}
+
+
+function WeakSetAdd() {
+ WeakSetSetup();
+ WeakSetTearDown();
+}
+
+
+function WeakSetHas() {
+ for (var i = 0; i < N; i++) {
+ if (!ws.has(keys[i])) {
+ throw new Error();
+ }
+ }
+ for (var i = N; i < 2 * N; i++) {
+ if (ws.has(keys[i])) {
+ throw new Error();
+ }
+ }
+}
+
+
+function WeakSetDelete() {
+ // This is run more than once per setup so we will end up deleting items
+ // more than once. Therefore, we do not the return value of delete.
+ for (var i = 0; i < N; i++) {
+ ws.delete(keys[i]);
+ }
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-3116.js Fri Oct 10 00:05:16 2014 UTC
@@ -0,0 +1,314 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function timezone(tz) {
+ var str = (new Date(2014, 0, 10)).toString();
+ if (tz == "CET") {
+ return str == "Fri Jan 10 2014 00:00:00 GMT+0100 (CET)";
+ }
+ if (tz == "BRT") {
+ return str == "Fri Jan 10 2014 00:00:00 GMT-0200 (BRST)";
+ }
+ if (tz == "PST") {
+ return str == "Fri Jan 10 2014 00:00:00 GMT-0800 (PST)";
+ }
+ return false;
+}
+
+if (timezone("CET")) {
+ assertEquals("Sat Mar 29 2014 22:59:00 GMT+0100 (CET)",
+ (new Date(2014, 2, 29, 22, 59)).toString());
+ assertEquals("Sat, 29 Mar 2014 21:59:00 GMT",
+ (new Date(2014, 2, 29, 22, 59)).toUTCString());
+ assertEquals("Sat Mar 29 2014 23:00:00 GMT+0100 (CET)",
+ (new Date(2014, 2, 29, 23, 0)).toString());
+ assertEquals("Sat, 29 Mar 2014 22:00:00 GMT",
+ (new Date(2014, 2, 29, 23, 0)).toUTCString());
+ assertEquals("Sat Mar 29 2014 23:59:00 GMT+0100 (CET)",
+ (new Date(2014, 2, 29, 23, 59)).toString());
+ assertEquals("Sat, 29 Mar 2014 22:59:00 GMT",
+ (new Date(2014, 2, 29, 23, 59)).toUTCString());
+ assertEquals("Sun Mar 30 2014 00:00:00 GMT+0100 (CET)",
+ (new Date(2014, 2, 30, 0, 0)).toString());
+ assertEquals("Sat, 29 Mar 2014 23:00:00 GMT",
+ (new Date(2014, 2, 30, 0, 0)).toUTCString());
+ assertEquals("Sun Mar 30 2014 00:59:00 GMT+0100 (CET)",
+ (new Date(2014, 2, 30, 0, 59)).toString());
+ assertEquals("Sat, 29 Mar 2014 23:59:00 GMT",
+ (new Date(2014, 2, 30, 0, 59)).toUTCString());
+ assertEquals("Sun Mar 30 2014 01:00:00 GMT+0100 (CET)",
+ (new Date(2014, 2, 30, 1, 0)).toString());
+ assertEquals("Sun, 30 Mar 2014 00:00:00 GMT",
+ (new Date(2014, 2, 30, 1, 0)).toUTCString());
+ assertEquals("Sun Mar 30 2014 01:59:00 GMT+0100 (CET)",
+ (new Date(2014, 2, 30, 1, 59)).toString());
+ assertEquals("Sun, 30 Mar 2014 00:59:00 GMT",
+ (new Date(2014, 2, 30, 1, 59)).toUTCString());
+ assertEquals("Sun Mar 30 2014 03:00:00 GMT+0200 (CEST)",
+ (new Date(2014, 2, 30, 2, 0)).toString());
+ assertEquals("Sun, 30 Mar 2014 01:00:00 GMT",
+ (new Date(2014, 2, 30, 2, 0)).toUTCString());
+ assertEquals("Sun Mar 30 2014 03:59:00 GMT+0200 (CEST)",
+ (new Date(2014, 2, 30, 2, 59)).toString());
+ assertEquals("Sun, 30 Mar 2014 01:59:00 GMT",
+ (new Date(2014, 2, 30, 2, 59)).toUTCString());
+ assertEquals("Sun Mar 30 2014 03:00:00 GMT+0200 (CEST)",
+ (new Date(2014, 2, 30, 3, 0)).toString());
+ assertEquals("Sun, 30 Mar 2014 01:00:00 GMT",
+ (new Date(2014, 2, 30, 3, 0)).toUTCString());
+ assertEquals("Sun Mar 30 2014 03:59:00 GMT+0200 (CEST)",
+ (new Date(2014, 2, 30, 3, 59)).toString());
+ assertEquals("Sun, 30 Mar 2014 01:59:00 GMT",
+ (new Date(2014, 2, 30, 3, 59)).toUTCString());
+ assertEquals("Sun Mar 30 2014 04:00:00 GMT+0200 (CEST)",
+ (new Date(2014, 2, 30, 4, 0)).toString());
+ assertEquals("Sun, 30 Mar 2014 02:00:00 GMT",
+ (new Date(2014, 2, 30, 4, 0)).toUTCString());
+ assertEquals("Sat Oct 25 2014 22:59:00 GMT+0200 (CEST)",
+ (new Date(2014, 9, 25, 22, 59)).toString());
+ assertEquals("Sat, 25 Oct 2014 20:59:00 GMT",
+ (new Date(2014, 9, 25, 22, 59)).toUTCString());
+ assertEquals("Sat Oct 25 2014 23:00:00 GMT+0200 (CEST)",
+ (new Date(2014, 9, 25, 23, 0)).toString());
+ assertEquals("Sat, 25 Oct 2014 21:00:00 GMT",
+ (new Date(2014, 9, 25, 23, 0)).toUTCString());
+ assertEquals("Sat Oct 25 2014 23:59:00 GMT+0200 (CEST)",
+ (new Date(2014, 9, 25, 23, 59)).toString());
+ assertEquals("Sat, 25 Oct 2014 21:59:00 GMT",
+ (new Date(2014, 9, 25, 23, 59)).toUTCString());
+ assertEquals("Sun Oct 26 2014 00:00:00 GMT+0200 (CEST)",
+ (new Date(2014, 9, 26, 0, 0)).toString());
+ assertEquals("Sat, 25 Oct 2014 22:00:00 GMT",
+ (new Date(2014, 9, 26, 0, 0)).toUTCString());
+ assertEquals("Sun Oct 26 2014 00:59:00 GMT+0200 (CEST)",
+ (new Date(2014, 9, 26, 0, 59)).toString());
+ assertEquals("Sat, 25 Oct 2014 22:59:00 GMT",
+ (new Date(2014, 9, 26, 0, 59)).toUTCString());
+ assertEquals("Sun Oct 26 2014 01:00:00 GMT+0200 (CEST)",
+ (new Date(2014, 9, 26, 1, 0)).toString());
+ assertEquals("Sat, 25 Oct 2014 23:00:00 GMT",
+ (new Date(2014, 9, 26, 1, 0)).toUTCString());
+ assertEquals("Sun Oct 26 2014 01:59:00 GMT+0200 (CEST)",
+ (new Date(2014, 9, 26, 1, 59)).toString());
+ assertEquals("Sat, 25 Oct 2014 23:59:00 GMT",
+ (new Date(2014, 9, 26, 1, 59)).toUTCString());
+ assertEquals("Sun Oct 26 2014 02:00:00 GMT+0200 (CEST)",
+ (new Date(2014, 9, 26, 2, 0)).toString());
+ assertEquals("Sun, 26 Oct 2014 00:00:00 GMT",
+ (new Date(2014, 9, 26, 2, 0)).toUTCString());
+ assertEquals("Sun Oct 26 2014 02:59:00 GMT+0200 (CEST)",
+ (new Date(2014, 9, 26, 2, 59)).toString());
+ assertEquals("Sun, 26 Oct 2014 00:59:00 GMT",
+ (new Date(2014, 9, 26, 2, 59)).toUTCString());
+ assertEquals("Sun Oct 26 2014 03:00:00 GMT+0100 (CET)",
+ (new Date(2014, 9, 26, 3, 0)).toString());
+ assertEquals("Sun, 26 Oct 2014 02:00:00 GMT",
+ (new Date(2014, 9, 26, 3, 0)).toUTCString());
+ assertEquals("Sun Oct 26 2014 03:59:00 GMT+0100 (CET)",
+ (new Date(2014, 9, 26, 3, 59)).toString());
+ assertEquals("Sun, 26 Oct 2014 02:59:00 GMT",
+ (new Date(2014, 9, 26, 3, 59)).toUTCString());
+ assertEquals("Sun Oct 26 2014 04:00:00 GMT+0100 (CET)",
+ (new Date(2014, 9, 26, 4, 0)).toString());
+ assertEquals("Sun, 26 Oct 2014 03:00:00 GMT",
+ (new Date(2014, 9, 26, 4, 0)).toUTCString());
+}
+
+if (timezone("BRT")) {
+ assertEquals("Sat Oct 18 2014 22:59:00 GMT-0300 (BRT)",
+ (new Date(2014, 9, 18, 22, 59)).toString());
+ assertEquals("Sun, 19 Oct 2014 01:59:00 GMT",
+ (new Date(2014, 9, 18, 22, 59)).toUTCString());
+ assertEquals("Sat Oct 18 2014 23:00:00 GMT-0300 (BRT)",
+ (new Date(2014, 9, 18, 23, 0)).toString());
+ assertEquals("Sun, 19 Oct 2014 02:00:00 GMT",
+ (new Date(2014, 9, 18, 23, 0)).toUTCString());
+ assertEquals("Sat Oct 18 2014 23:59:00 GMT-0300 (BRT)",
+ (new Date(2014, 9, 18, 23, 59)).toString());
+ assertEquals("Sun, 19 Oct 2014 02:59:00 GMT",
+ (new Date(2014, 9, 18, 23, 59)).toUTCString());
+ assertEquals("Sun Oct 19 2014 01:00:00 GMT-0200 (BRST)",
+ (new Date(2014, 9, 19, 0, 0)).toString());
+ assertEquals("Sun, 19 Oct 2014 03:00:00 GMT",
+ (new Date(2014, 9, 19, 0, 0)).toUTCString());
+ assertEquals("Sun Oct 19 2014 01:59:00 GMT-0200 (BRST)",
+ (new Date(2014, 9, 19, 0, 59)).toString());
+ assertEquals("Sun, 19 Oct 2014 03:59:00 GMT",
+ (new Date(2014, 9, 19, 0, 59)).toUTCString());
+ assertEquals("Sun Oct 19 2014 01:00:00 GMT-0200 (BRST)",
+ (new Date(2014, 9, 19, 1, 0)).toString());
+ assertEquals("Sun, 19 Oct 2014 03:00:00 GMT",
+ (new Date(2014, 9, 19, 1, 0)).toUTCString());
+ assertEquals("Sun Oct 19 2014 01:59:00 GMT-0200 (BRST)",
+ (new Date(2014, 9, 19, 1, 59)).toString());
+ assertEquals("Sun, 19 Oct 2014 03:59:00 GMT",
+ (new Date(2014, 9, 19, 1, 59)).toUTCString());
+ assertEquals("Sun Oct 19 2014 02:00:00 GMT-0200 (BRST)",
+ (new Date(2014, 9, 19, 2, 0)).toString());
+ assertEquals("Sun, 19 Oct 2014 04:00:00 GMT",
+ (new Date(2014, 9, 19, 2, 0)).toUTCString());
+ assertEquals("Sun Oct 19 2014 02:59:00 GMT-0200 (BRST)",
+ (new Date(2014, 9, 19, 2, 59)).toString());
+ assertEquals("Sun, 19 Oct 2014 04:59:00 GMT",
+ (new Date(2014, 9, 19, 2, 59)).toUTCString());
+ assertEquals("Sun Oct 19 2014 03:00:00 GMT-0200 (BRST)",
+ (new Date(2014, 9, 19, 3, 0)).toString());
+ assertEquals("Sun, 19 Oct 2014 05:00:00 GMT",
+ (new Date(2014, 9, 19, 3, 0)).toUTCString());
+ assertEquals("Sun Oct 19 2014 03:59:00 GMT-0200 (BRST)",
+ (new Date(2014, 9, 19, 3, 59)).toString());
+ assertEquals("Sun, 19 Oct 2014 05:59:00 GMT",
+ (new Date(2014, 9, 19, 3, 59)).toUTCString());
+ assertEquals("Sun Oct 19 2014 04:00:00 GMT-0200 (BRST)",
+ (new Date(2014, 9, 19, 4, 0)).toString());
+ assertEquals("Sun, 19 Oct 2014 06:00:00 GMT",
+ (new Date(2014, 9, 19, 4, 0)).toUTCString());
+ assertEquals("Sat Feb 15 2014 22:59:00 GMT-0200 (BRST)",
+ (new Date(2014, 1, 15, 22, 59)).toString());
+ assertEquals("Sun, 16 Feb 2014 00:59:00 GMT",
+ (new Date(2014, 1, 15, 22, 59)).toUTCString());
+ assertEquals("Sat Feb 15 2014 23:00:00 GMT-0200 (BRST)",
+ (new Date(2014, 1, 15, 23, 0)).toString());
+ assertEquals("Sun, 16 Feb 2014 01:00:00 GMT",
+ (new Date(2014, 1, 15, 23, 0)).toUTCString());
+ assertEquals("Sat Feb 15 2014 23:59:00 GMT-0200 (BRST)",
+ (new Date(2014, 1, 15, 23, 59)).toString());
+ assertEquals("Sun, 16 Feb 2014 01:59:00 GMT",
+ (new Date(2014, 1, 15, 23, 59)).toUTCString());
+ assertEquals("Sun Feb 16 2014 00:00:00 GMT-0300 (BRT)",
+ (new Date(2014, 1, 16, 0, 0)).toString());
+ assertEquals("Sun, 16 Feb 2014 03:00:00 GMT",
+ (new Date(2014, 1, 16, 0, 0)).toUTCString());
+ assertEquals("Sun Feb 16 2014 00:59:00 GMT-0300 (BRT)",
+ (new Date(2014, 1, 16, 0, 59)).toString());
+ assertEquals("Sun, 16 Feb 2014 03:59:00 GMT",
+ (new Date(2014, 1, 16, 0, 59)).toUTCString());
+ assertEquals("Sun Feb 16 2014 01:00:00 GMT-0300 (BRT)",
+ (new Date(2014, 1, 16, 1, 0)).toString());
+ assertEquals("Sun, 16 Feb 2014 04:00:00 GMT",
+ (new Date(2014, 1, 16, 1, 0)).toUTCString());
+ assertEquals("Sun Feb 16 2014 01:59:00 GMT-0300 (BRT)",
+ (new Date(2014, 1, 16, 1, 59)).toString());
+ assertEquals("Sun, 16 Feb 2014 04:59:00 GMT",
+ (new Date(2014, 1, 16, 1, 59)).toUTCString());
+ assertEquals("Sun Feb 16 2014 02:00:00 GMT-0300 (BRT)",
+ (new Date(2014, 1, 16, 2, 0)).toString());
+ assertEquals("Sun, 16 Feb 2014 05:00:00 GMT",
+ (new Date(2014, 1, 16, 2, 0)).toUTCString());
+ assertEquals("Sun Feb 16 2014 02:59:00 GMT-0300 (BRT)",
+ (new Date(2014, 1, 16, 2, 59)).toString());
+ assertEquals("Sun, 16 Feb 2014 05:59:00 GMT",
+ (new Date(2014, 1, 16, 2, 59)).toUTCString());
+ assertEquals("Sun Feb 16 2014 03:00:00 GMT-0300 (BRT)",
+ (new Date(2014, 1, 16, 3, 0)).toString());
+ assertEquals("Sun, 16 Feb 2014 06:00:00 GMT",
+ (new Date(2014, 1, 16, 3, 0)).toUTCString());
+ assertEquals("Sun Feb 16 2014 03:59:00 GMT-0300 (BRT)",
+ (new Date(2014, 1, 16, 3, 59)).toString());
+ assertEquals("Sun, 16 Feb 2014 06:59:00 GMT",
+ (new Date(2014, 1, 16, 3, 59)).toUTCString());
+ assertEquals("Sun Feb 16 2014 04:00:00 GMT-0300 (BRT)",
+ (new Date(2014, 1, 16, 4, 0)).toString());
+ assertEquals("Sun, 16 Feb 2014 07:00:00 GMT",
+ (new Date(2014, 1, 16, 4, 0)).toUTCString());
+}
+
+if (timezone("PST")) {
+ assertEquals("Sat Mar 08 2014 22:59:00 GMT-0800 (PST)",
+ (new Date(2014, 2, 8, 22, 59)).toString());
+ assertEquals("Sun, 09 Mar 2014 06:59:00 GMT",
+ (new Date(2014, 2, 8, 22, 59)).toUTCString());
+ assertEquals("Sat Mar 08 2014 23:00:00 GMT-0800 (PST)",
+ (new Date(2014, 2, 8, 23, 0)).toString());
+ assertEquals("Sun, 09 Mar 2014 07:00:00 GMT",
+ (new Date(2014, 2, 8, 23, 0)).toUTCString());
+ assertEquals("Sat Mar 08 2014 23:59:00 GMT-0800 (PST)",
+ (new Date(2014, 2, 8, 23, 59)).toString());
+ assertEquals("Sun, 09 Mar 2014 07:59:00 GMT",
+ (new Date(2014, 2, 8, 23, 59)).toUTCString());
+ assertEquals("Sun Mar 09 2014 00:00:00 GMT-0800 (PST)",
+ (new Date(2014, 2, 9, 0, 0)).toString());
+ assertEquals("Sun, 09 Mar 2014 08:00:00 GMT",
+ (new Date(2014, 2, 9, 0, 0)).toUTCString());
+ assertEquals("Sun Mar 09 2014 00:59:00 GMT-0800 (PST)",
+ (new Date(2014, 2, 9, 0, 59)).toString());
+ assertEquals("Sun, 09 Mar 2014 08:59:00 GMT",
+ (new Date(2014, 2, 9, 0, 59)).toUTCString());
+ assertEquals("Sun Mar 09 2014 01:00:00 GMT-0800 (PST)",
+ (new Date(2014, 2, 9, 1, 0)).toString());
+ assertEquals("Sun, 09 Mar 2014 09:00:00 GMT",
+ (new Date(2014, 2, 9, 1, 0)).toUTCString());
+ assertEquals("Sun Mar 09 2014 01:59:00 GMT-0800 (PST)",
+ (new Date(2014, 2, 9, 1, 59)).toString());
+ assertEquals("Sun, 09 Mar 2014 09:59:00 GMT",
+ (new Date(2014, 2, 9, 1, 59)).toUTCString());
+ assertEquals("Sun Mar 09 2014 03:00:00 GMT-0700 (PDT)",
+ (new Date(2014, 2, 9, 2, 0)).toString());
+ assertEquals("Sun, 09 Mar 2014 10:00:00 GMT",
+ (new Date(2014, 2, 9, 2, 0)).toUTCString());
+ assertEquals("Sun Mar 09 2014 03:59:00 GMT-0700 (PDT)",
+ (new Date(2014, 2, 9, 2, 59)).toString());
+ assertEquals("Sun, 09 Mar 2014 10:59:00 GMT",
+ (new Date(2014, 2, 9, 2, 59)).toUTCString());
+ assertEquals("Sun Mar 09 2014 03:00:00 GMT-0700 (PDT)",
+ (new Date(2014, 2, 9, 3, 0)).toString());
+ assertEquals("Sun, 09 Mar 2014 10:00:00 GMT",
+ (new Date(2014, 2, 9, 3, 0)).toUTCString());
+ assertEquals("Sun Mar 09 2014 03:59:00 GMT-0700 (PDT)",
+ (new Date(2014, 2, 9, 3, 59)).toString());
+ assertEquals("Sun, 09 Mar 2014 10:59:00 GMT",
+ (new Date(2014, 2, 9, 3, 59)).toUTCString());
+ assertEquals("Sun Mar 09 2014 04:00:00 GMT-0700 (PDT)",
+ (new Date(2014, 2, 9, 4, 0)).toString());
+ assertEquals("Sun, 09 Mar 2014 11:00:00 GMT",
+ (new Date(2014, 2, 9, 4, 0)).toUTCString());
+ assertEquals("Sat Nov 01 2014 22:59:00 GMT-0700 (PDT)",
+ (new Date(2014, 10, 1, 22, 59)).toString());
+ assertEquals("Sun, 02 Nov 2014 05:59:00 GMT",
+ (new Date(2014, 10, 1, 22, 59)).toUTCString());
+ assertEquals("Sat Nov 01 2014 23:00:00 GMT-0700 (PDT)",
+ (new Date(2014, 10, 1, 23, 0)).toString());
+ assertEquals("Sun, 02 Nov 2014 06:00:00 GMT",
+ (new Date(2014, 10, 1, 23, 0)).toUTCString());
+ assertEquals("Sat Nov 01 2014 23:59:00 GMT-0700 (PDT)",
+ (new Date(2014, 10, 1, 23, 59)).toString());
+ assertEquals("Sun, 02 Nov 2014 06:59:00 GMT",
+ (new Date(2014, 10, 1, 23, 59)).toUTCString());
+ assertEquals("Sun Nov 02 2014 00:00:00 GMT-0700 (PDT)",
+ (new Date(2014, 10, 2, 0, 0)).toString());
+ assertEquals("Sun, 02 Nov 2014 07:00:00 GMT",
+ (new Date(2014, 10, 2, 0, 0)).toUTCString());
+ assertEquals("Sun Nov 02 2014 00:59:00 GMT-0700 (PDT)",
+ (new Date(2014, 10, 2, 0, 59)).toString());
+ assertEquals("Sun, 02 Nov 2014 07:59:00 GMT",
+ (new Date(2014, 10, 2, 0, 59)).toUTCString());
+ assertEquals("Sun Nov 02 2014 01:00:00 GMT-0700 (PDT)",
+ (new Date(2014, 10, 2, 1, 0)).toString());
+ assertEquals("Sun, 02 Nov 2014 08:00:00 GMT",
+ (new Date(2014, 10, 2, 1, 0)).toUTCString());
+ assertEquals("Sun Nov 02 2014 01:59:00 GMT-0700 (PDT)",
+ (new Date(2014, 10, 2, 1, 59)).toString());
+ assertEquals("Sun, 02 Nov 2014 08:59:00 GMT",
+ (new Date(2014, 10, 2, 1, 59)).toUTCString());
+ assertEquals("Sun Nov 02 2014 02:00:00 GMT-0800 (PST)",
+ (new Date(2014, 10, 2, 2, 0)).toString());
+ assertEquals("Sun, 02 Nov 2014 10:00:00 GMT",
+ (new Date(2014, 10, 2, 2, 0)).toUTCString());
+ assertEquals("Sun Nov 02 2014 02:59:00 GMT-0800 (PST)",
+ (new Date(2014, 10, 2, 2, 59)).toString());
+ assertEquals("Sun, 02 Nov 2014 10:59:00 GMT",
+ (new Date(2014, 10, 2, 2, 59)).toUTCString());
+ assertEquals("Sun Nov 02 2014 03:00:00 GMT-0800 (PST)",
+ (new Date(2014, 10, 2, 3, 0)).toString());
+ assertEquals("Sun, 02 Nov 2014 11:00:00 GMT",
+ (new Date(2014, 10, 2, 3, 0)).toUTCString());
+ assertEquals("Sun Nov 02 2014 03:59:00 GMT-0800 (PST)",
+ (new Date(2014, 10, 2, 3, 59)).toString());
+ assertEquals("Sun, 02 Nov 2014 11:59:00 GMT",
+ (new Date(2014, 10, 2, 3, 59)).toUTCString());
+ assertEquals("Sun Nov 02 2014 04:00:00 GMT-0800 (PST)",
+ (new Date(2014, 10, 2, 4, 0)).toString());
+ assertEquals("Sun, 02 Nov 2014 12:00:00 GMT",
+ (new Date(2014, 10, 2, 4, 0)).toUTCString());
+}
=======================================
--- /dev/null
+++ /trunk/tools/sanitizers/tsan_suppressions.txt Fri Oct 10 00:05:16 2014
UTC
@@ -0,0 +1,6 @@
+# Suppressions for TSan v2
+# https://code.google.com/p/thread-sanitizer/wiki/Suppressions
+
+# Incorrectly detected lock cycles in test-lockers
+# https://code.google.com/p/thread-sanitizer/issues/detail?id=81
+deadlock:LockAndUnlockDifferentIsolatesThread::Run
=======================================
--- /trunk/test/perf-test/Collections/Collections.json Tue Sep 2 12:59:15
2014 UTC
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "path": ["."],
- "main": "run.js",
- "flags": ["--harmony-collections"],
- "run_count": 5,
- "units": "score",
- "results_regexp": "^%s\\-Collections\\(Score\\): (.+)$",
- "total": true,
- "tests": [
- {"name": "Map"},
- {"name": "Set"},
- {"name": "WeakMap"},
- {"name": "WeakSet"}
- ]
-}
=======================================
--- /trunk/test/perf-test/Collections/base.js Tue Sep 2 12:59:15 2014 UTC
+++ /dev/null
@@ -1,367 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-// 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,
deterministicIterations,
- run, setup, tearDown, rmsResult, minIterations) {
- this.name = name;
- this.doWarmup = doWarmup;
- this.doDeterministic = doDeterministic;
- this.deterministicIterations = deterministicIterations;
- this.run = run;
- this.Setup = setup ? setup : function() { };
- this.TearDown = tearDown ? tearDown : function() { };
- this.rmsResult = rmsResult ? rmsResult : 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 = '1';
-
-
-// Defines global benchsuite running mode that overrides benchmark suite
-// behavior. Intended to be set by the benchmark driver. Undefined
-// values here allow a benchmark to define behaviour itself.
-BenchmarkSuite.config = {
- doWarmup: undefined,
- doDeterministic: undefined
-};
-
-
-// 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, skipBenchmarks) {
- skipBenchmarks = typeof skipBenchmarks === 'undefined' ? [] :
skipBenchmarks;
- 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);
- if (skipBenchmarks.indexOf(suite.name) > -1) {
- suite.NotifySkipped(runner);
- } else {
- 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 geometric mean of a set of rms 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);
- }
- }
- }
-}
-
-
-BenchmarkSuite.prototype.NotifySkipped = function(runner) {
- BenchmarkSuite.scores.push(1); // push default reference score.
- if (runner.NotifyResult) {
- runner.NotifyResult(this.name, "Skipped");
- }
-}
-
-
-// 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) {
- var config = BenchmarkSuite.config;
- var doWarmup = config.doWarmup !== undefined
- ? config.doWarmup
- : benchmark.doWarmup;
- var doDeterministic = config.doDeterministic !== undefined
- ? config.doDeterministic
- : benchmark.doDeterministic;
-
- 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; (doDeterministic ?
- i<benchmark.deterministicIterations : 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 (!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 rms = (benchmark.rmsResult != null) ? benchmark.rmsResult() : 0;
- this.NotifyStep(new BenchmarkResult(benchmark, usec, rms));
- 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();
-}
=======================================
--- /trunk/test/perf-test/Collections/map.js Tue Sep 2 12:59:15 2014 UTC
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-var MapBenchmark = new BenchmarkSuite('Map', [1000], [
- new Benchmark('Set', false, false, 0, MapSet),
- new Benchmark('Has', false, false, 0, MapHas, MapSetup, MapTearDown),
- new Benchmark('Get', false, false, 0, MapGet, MapSetup, MapTearDown),
- new Benchmark('Delete', false, false, 0, MapDelete, MapSetup,
MapTearDown),
- new Benchmark('ForEach', false, false, 0, MapForEach, MapSetup,
MapTearDown),
-]);
-
-
-var map;
-var N = 10;
-
-
-function MapSetup() {
- map = new Map;
- for (var i = 0; i < N; i++) {
- map.set(i, i);
- }
-}
-
-
-function MapTearDown() {
- map = null;
-}
-
-
-function MapSet() {
- MapSetup();
- MapTearDown();
-}
-
-
-function MapHas() {
- for (var i = 0; i < N; i++) {
- if (!map.has(i)) {
- throw new Error();
- }
- }
- for (var i = N; i < 2 * N; i++) {
- if (map.has(i)) {
- throw new Error();
- }
- }
-}
-
-
-function MapGet() {
- for (var i = 0; i < N; i++) {
- if (map.get(i) !== i) {
- throw new Error();
- }
- }
- for (var i = N; i < 2 * N; i++) {
- if (map.get(i) !== undefined) {
- throw new Error();
- }
- }
-}
-
-
-function MapDelete() {
- // This is run more than once per setup so we will end up deleting items
- // more than once. Therefore, we do not the return value of delete.
- for (var i = 0; i < N; i++) {
- map.delete(i);
- }
-}
-
-
-function MapForEach() {
- map.forEach(function(v, k) {
- if (v !== k) {
- throw new Error();
- }
- });
-}
=======================================
--- /trunk/test/perf-test/Collections/run.js Tue Sep 2 12:59:15 2014 UTC
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-load('base.js');
-load('map.js');
-load('set.js');
-load('weakmap.js');
-load('weakset.js');
-
-
-var success = true;
-
-function PrintResult(name, result) {
- print(name + '-Collections(Score): ' + result);
-}
-
-
-function PrintError(name, error) {
- PrintResult(name, error);
- success = false;
-}
-
-
-BenchmarkSuite.config.doWarmup = undefined;
-BenchmarkSuite.config.doDeterministic = undefined;
-
-BenchmarkSuite.RunSuites({ NotifyResult: PrintResult,
- NotifyError: PrintError });
=======================================
--- /trunk/test/perf-test/Collections/set.js Tue Sep 2 12:59:15 2014 UTC
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-var SetBenchmark = new BenchmarkSuite('Set', [1000], [
- new Benchmark('Add', false, false, 0, SetAdd),
- new Benchmark('Has', false, false, 0, SetHas, SetSetup, SetTearDown),
- new Benchmark('Delete', false, false, 0, SetDelete, SetSetup,
SetTearDown),
- new Benchmark('ForEach', false, false, 0, SetForEach, SetSetup,
SetTearDown),
-]);
-
-
-var set;
-var N = 10;
-
-
-function SetSetup() {
- set = new Set;
- for (var i = 0; i < N; i++) {
- set.add(i);
- }
-}
-
-
-function SetTearDown() {
- map = null;
-}
-
-
-function SetAdd() {
- SetSetup();
- SetTearDown();
-}
-
-
-function SetHas() {
- for (var i = 0; i < N; i++) {
- if (!set.has(i)) {
- throw new Error();
- }
- }
- for (var i = N; i < 2 * N; i++) {
- if (set.has(i)) {
- throw new Error();
- }
- }
-}
-
-
-function SetDelete() {
- // This is run more than once per setup so we will end up deleting items
- // more than once. Therefore, we do not the return value of delete.
- for (var i = 0; i < N; i++) {
- set.delete(i);
- }
-}
-
-
-function SetForEach() {
- set.forEach(function(v, k) {
- if (v !== k) {
- throw new Error();
- }
- });
-}
=======================================
--- /trunk/test/perf-test/Collections/weakmap.js Tue Sep 2 12:59:15 2014
UTC
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-var MapBenchmark = new BenchmarkSuite('WeakMap', [1000], [
- new Benchmark('Set', false, false, 0, WeakMapSet),
- new Benchmark('Has', false, false, 0, WeakMapHas, WeakMapSetup,
- WeakMapTearDown),
- new Benchmark('Get', false, false, 0, WeakMapGet, WeakMapSetup,
- WeakMapTearDown),
- new Benchmark('Delete', false, false, 0, WeakMapDelete, WeakMapSetup,
- WeakMapTearDown),
-]);
-
-
-var wm;
-var N = 10;
-var keys = [];
-
-
-for (var i = 0; i < N * 2; i++) {
- keys[i] = {};
-}
-
-
-function WeakMapSetup() {
- wm = new WeakMap;
- for (var i = 0; i < N; i++) {
- wm.set(keys[i], i);
- }
-}
-
-
-function WeakMapTearDown() {
- wm = null;
-}
-
-
-function WeakMapSet() {
- WeakMapSetup();
- WeakMapTearDown();
-}
-
-
-function WeakMapHas() {
- for (var i = 0; i < N; i++) {
- if (!wm.has(keys[i])) {
- throw new Error();
- }
- }
- for (var i = N; i < 2 * N; i++) {
- if (wm.has(keys[i])) {
- throw new Error();
- }
- }
-}
-
-
-function WeakMapGet() {
- for (var i = 0; i < N; i++) {
- if (wm.get(keys[i]) !== i) {
- throw new Error();
- }
- }
- for (var i = N; i < 2 * N; i++) {
- if (wm.get(keys[i]) !== undefined) {
- throw new Error();
- }
- }
-}
-
-
-function WeakMapDelete() {
- // This is run more than once per setup so we will end up deleting items
- // more than once. Therefore, we do not the return value of delete.
- for (var i = 0; i < N; i++) {
- wm.delete(keys[i]);
- }
-}
=======================================
--- /trunk/test/perf-test/Collections/weakset.js Tue Sep 2 12:59:15 2014
UTC
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-var SetBenchmark = new BenchmarkSuite('WeakSet', [1000], [
- new Benchmark('Add', false, false, 0, WeakSetAdd),
- new Benchmark('Has', false, false, 0, WeakSetHas, WeakSetSetup,
- WeakSetTearDown),
- new Benchmark('Delete', false, false, 0, WeakSetDelete, WeakSetSetup,
- WeakSetTearDown),
-]);
-
-
-var ws;
-var N = 10;
-var keys = [];
-
-
-for (var i = 0; i < N * 2; i++) {
- keys[i] = {};
-}
-
-
-function WeakSetSetup() {
- ws = new WeakSet;
- for (var i = 0; i < N; i++) {
- ws.add(keys[i]);
- }
-}
-
-
-function WeakSetTearDown() {
- ws = null;
-}
-
-
-function WeakSetAdd() {
- WeakSetSetup();
- WeakSetTearDown();
-}
-
-
-function WeakSetHas() {
- for (var i = 0; i < N; i++) {
- if (!ws.has(keys[i])) {
- throw new Error();
- }
- }
- for (var i = N; i < 2 * N; i++) {
- if (ws.has(keys[i])) {
- throw new Error();
- }
- }
-}
-
-
-function WeakSetDelete() {
- // This is run more than once per setup so we will end up deleting items
- // more than once. Therefore, we do not the return value of delete.
- for (var i = 0; i < N; i++) {
- ws.delete(keys[i]);
- }
-}
=======================================
--- /trunk/AUTHORS Wed Oct 1 00:05:35 2014 UTC
+++ /trunk/AUTHORS Fri Oct 10 00:05:16 2014 UTC
@@ -27,6 +27,7 @@
Baptiste Afsa <[email protected]>
Bert Belder <[email protected]>
Burcu Dogan <[email protected]>
+Caitlin Potter <[email protected]>
Craig Schlenter <[email protected]>
Chunyang Dai <[email protected]>
Daniel Andersson <[email protected]>
=======================================
--- /trunk/ChangeLog Thu Oct 9 00:05:16 2014 UTC
+++ /trunk/ChangeLog Fri Oct 10 00:05:16 2014 UTC
@@ -1,3 +1,13 @@
+2014-10-10: Version 3.30.7
+
+ Fix computation of UTC time from local time at DST change points
(issue
+ 3116, Chromium issues 415424, 417640).
+
+ Convert `obj` ToObject in Object.keys() (issue 3587).
+
+ Performance and stability improvements on all platforms.
+
+
2014-10-09: Version 3.30.6
Update unicode to 7.0.0 (issue 2892).
=======================================
--- /trunk/build/toolchain.gypi Thu Oct 9 00:05:16 2014 UTC
+++ /trunk/build/toolchain.gypi Fri Oct 10 00:05:16 2014 UTC
@@ -302,7 +302,7 @@
'cflags': ['-mfp32'],
}],
['mips_arch_variant=="r6"', {
- 'cflags!': ['-mfp32'],
+ 'cflags!': ['-mfp32', '-mfpxx'],
'cflags': ['-mips32r6', '-Wa,-mips32r6'],
'ldflags': [
'-mips32r6',
@@ -312,14 +312,17 @@
}],
['mips_arch_variant=="r2"', {
'cflags': ['-mips32r2', '-Wa,-mips32r2'],
+ 'ldflags': ['-mips32r2'],
}],
['mips_arch_variant=="r1"', {
- 'cflags!': ['-mfp64'],
+ 'cflags!': ['-mfp64', '-mfpxx'],
'cflags': ['-mips32', '-Wa,-mips32'],
+ 'ldflags': ['-mips32'],
}],
['mips_arch_variant=="rx"', {
- 'cflags!': ['-mfp64'],
- 'cflags': ['-mips32', '-Wa,-mips32'],
+ 'cflags!': ['-mfp64', '-mfp32'],
+ 'cflags': ['-mips32', '-Wa,-mips32', '-mfpxx'],
+ 'ldflags': ['-mips32'],
}],
],
}],
@@ -400,7 +403,7 @@
'cflags': ['-mfp32'],
}],
['mips_arch_variant=="r6"', {
- 'cflags!': ['-mfp32'],
+ 'cflags!': ['-mfp32', '-mfpxx'],
'cflags': ['-mips32r6', '-Wa,-mips32r6'],
'ldflags': [
'-mips32r6',
@@ -410,17 +413,20 @@
}],
['mips_arch_variant=="r2"', {
'cflags': ['-mips32r2', '-Wa,-mips32r2'],
+ 'ldflags': ['-mips32r2'],
}],
['mips_arch_variant=="r1"', {
- 'cflags!': ['-mfp64'],
+ 'cflags!': ['-mfp64', '-mfpxx'],
'cflags': ['-mips32', '-Wa,-mips32'],
+ 'ldflags': ['-mips32'],
}],
['mips_arch_variant=="rx"', {
- 'cflags!': ['-mfp64'],
- 'cflags': ['-mips32', '-Wa,-mips32'],
+ 'cflags!': ['-mfp64', '-mfp32'],
+ 'cflags': ['-mips32', '-Wa,-mips32', '-mfpxx'],
+ 'ldflags': ['-mips32'],
}],
['mips_arch_variant=="loongson"', {
- 'cflags!': ['-mfp64'],
+ 'cflags!': ['-mfp64', '-mfp32', '-mfpxx'],
'cflags': ['-mips3', '-Wa,-mips3'],
}],
],
=======================================
--- /trunk/include/v8-platform.h Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/include/v8-platform.h Fri Oct 10 00:05:16 2014 UTC
@@ -56,7 +56,6 @@
*/
virtual void CallOnForegroundThread(Isolate* isolate, Task* task) = 0;
-
/**
* Monotonically increasing time in seconds from an arbitrary fixed
point in
* the past. This function is expected to return at least
@@ -64,11 +63,7 @@
* it is recommended that the fixed point be no further in the past than
* the epoch.
**/
- virtual double MonotonicallyIncreasingTime() {
- // TODO(rmcilroy): Remove this default implementation when Chromium
- // change has landed.
- return 0;
- }
+ virtual double MonotonicallyIncreasingTime() = 0;
};
} // namespace v8
=======================================
--- /trunk/src/arm/codegen-arm.cc Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/arm/codegen-arm.cc Fri Oct 10 00:05:16 2014 UTC
@@ -604,8 +604,22 @@
__ add(src_elements, elements,
Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4));
__ add(dst_elements, array, Operand(FixedArray::kHeaderSize));
- __ add(array, array, Operand(kHeapObjectTag));
__ add(dst_end, dst_elements, Operand(length, LSL, 1));
+
+ // Allocating heap numbers in the loop below can fail and cause a jump to
+ // gc_required. We can't leave a partly initialized FixedArray behind,
+ // so pessimistically fill it with holes now.
+ Label initialization_loop, initialization_loop_entry;
+ __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
+ __ b(&initialization_loop_entry);
+ __ bind(&initialization_loop);
+ __ str(scratch, MemOperand(dst_elements, kPointerSize, PostIndex));
+ __ bind(&initialization_loop_entry);
+ __ cmp(dst_elements, dst_end);
+ __ b(lt, &initialization_loop);
+
+ __ add(dst_elements, array, Operand(FixedArray::kHeaderSize));
+ __ add(array, array, Operand(kHeapObjectTag));
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
// Using offsetted addresses in src_elements to fully take advantage of
// post-indexing.
=======================================
--- /trunk/src/arm/full-codegen-arm.cc Thu Oct 9 00:05:16 2014 UTC
+++ /trunk/src/arm/full-codegen-arm.cc Fri Oct 10 00:05:16 2014 UTC
@@ -1889,22 +1889,8 @@
Comment cmnt(masm_, "[ Assignment");
- // Left-hand side can only be a property, a global or a (parameter or
local)
- // slot.
- enum LhsKind {
- VARIABLE,
- NAMED_PROPERTY,
- KEYED_PROPERTY,
- NAMED_SUPER_PROPERTY
- };
- LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty();
- if (property != NULL) {
- assign_type = (property->key()->IsPropertyName())
- ? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
- : NAMED_PROPERTY)
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@@ -1930,6 +1916,21 @@
__ Push(scratch);
__ Push(result_register());
}
+ break;
+ case KEYED_SUPER_PROPERTY:
+ VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(property->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForAccumulatorValue(property->key());
+ __ Push(result_register());
+ if (expr->is_compound()) {
+ const Register scratch = r1;
+ __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
+ __ Push(scratch);
+ __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
+ __ Push(scratch);
+ __ Push(result_register());
+ }
break;
case KEYED_PROPERTY:
if (expr->is_compound()) {
@@ -1962,6 +1963,10 @@
EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyLoad(property);
+ PrepareForBailoutForId(property->LoadId(), TOS_REG);
+ break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
@@ -2012,6 +2017,10 @@
EmitNamedSuperPropertyStore(property);
context()->Plug(r0);
break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyStore(property);
+ context()->Plug(r0);
+ break;
case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr);
break;
@@ -2657,12 +2666,25 @@
Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL);
- __ Push(r0);
__ Push(key->value());
+ __ Push(r0);
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy),
4);
}
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
+ // Assignment to named property of super.
+ // r0 : value
+ // stack : receiver ('this'), home_object, key
+ DCHECK(prop != NULL);
+
+ __ Push(r0);
+ __ CallRuntime((strict_mode() == STRICT ?
Runtime::kStoreKeyedToSuper_Strict
+ :
Runtime::kStoreKeyedToSuper_Sloppy),
+ 4);
+}
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
@@ -4436,24 +4458,8 @@
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
- // Expression can only be a property, a global or a (parameter or local)
- // slot.
- enum LhsKind {
- VARIABLE,
- NAMED_PROPERTY,
- KEYED_PROPERTY,
- NAMED_SUPER_PROPERTY
- };
- LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty();
- // In case of a property we use the uninitialized expression context
- // of the key to detect a named property.
- if (prop != NULL) {
- assign_type =
- (prop->key()->IsPropertyName())
- ? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY :
NAMED_PROPERTY)
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@@ -4466,27 +4472,55 @@
__ mov(ip, Operand(Smi::FromInt(0)));
__ push(ip);
}
- if (assign_type == NAMED_PROPERTY) {
- // Put the object both on the stack and in the register.
- VisitForStackValue(prop->obj());
- __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
- EmitNamedPropertyLoad(prop);
- } else if (assign_type == NAMED_SUPER_PROPERTY) {
- VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(prop->obj()->AsSuperReference());
- __ Push(result_register());
- const Register scratch = r1;
- __ ldr(scratch, MemOperand(sp, kPointerSize));
- __ Push(scratch);
- __ Push(result_register());
- EmitNamedSuperPropertyLoad(prop);
- } else {
- VisitForStackValue(prop->obj());
- VisitForStackValue(prop->key());
- __ ldr(LoadDescriptor::ReceiverRegister(),
- MemOperand(sp, 1 * kPointerSize));
- __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
- EmitKeyedPropertyLoad(prop);
+ switch (assign_type) {
+ case NAMED_PROPERTY: {
+ // Put the object both on the stack and in the register.
+ VisitForStackValue(prop->obj());
+ __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
+ EmitNamedPropertyLoad(prop);
+ break;
+ }
+
+ case NAMED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ Push(result_register());
+ const Register scratch = r1;
+ __ ldr(scratch, MemOperand(sp, kPointerSize));
+ __ Push(scratch);
+ __ Push(result_register());
+ EmitNamedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForAccumulatorValue(prop->key());
+ __ Push(result_register());
+ const Register scratch = r1;
+ __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
+ __ Push(scratch);
+ __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
+ __ Push(scratch);
+ __ Push(result_register());
+ EmitKeyedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_PROPERTY: {
+ VisitForStackValue(prop->obj());
+ VisitForStackValue(prop->key());
+ __ ldr(LoadDescriptor::ReceiverRegister(),
+ MemOperand(sp, 1 * kPointerSize));
+ __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
+ EmitKeyedPropertyLoad(prop);
+ break;
+ }
+
+ case VARIABLE:
+ UNREACHABLE();
}
}
@@ -4526,6 +4560,9 @@
case KEYED_PROPERTY:
__ str(r0, MemOperand(sp, 2 * kPointerSize));
break;
+ case KEYED_SUPER_PROPERTY:
+ __ str(r0, MemOperand(sp, 3 * kPointerSize));
+ break;
}
}
}
@@ -4559,6 +4596,9 @@
case KEYED_PROPERTY:
__ str(r0, MemOperand(sp, 2 * kPointerSize));
break;
+ case KEYED_SUPER_PROPERTY:
+ __ str(r0, MemOperand(sp, 3 * kPointerSize));
+ break;
}
}
}
@@ -4620,6 +4660,17 @@
if (!context()->IsEffect()) {
context()->PlugTOS();
}
+ } else {
+ context()->Plug(r0);
+ }
+ break;
+ }
+ case KEYED_SUPER_PROPERTY: {
+ EmitKeyedSuperPropertyStore(prop);
+ if (expr->is_postfix()) {
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
+ }
} else {
context()->Plug(r0);
}
=======================================
--- /trunk/src/arm64/codegen-arm64.cc Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/arm64/codegen-arm64.cc Fri Oct 10 00:05:16 2014 UTC
@@ -290,15 +290,28 @@
Register src_elements = x10;
Register dst_elements = x11;
Register dst_end = x12;
+ Register the_hole = x14;
+ __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex);
__ Add(src_elements, elements,
FixedDoubleArray::kHeaderSize - kHeapObjectTag);
+ __ Add(dst_elements, array, FixedArray::kHeaderSize);
+ __ Add(dst_end, dst_elements, Operand(length, LSL, kPointerSizeLog2));
+
+ // Allocating heap numbers in the loop below can fail and cause a jump to
+ // gc_required. We can't leave a partly initialized FixedArray behind,
+ // so pessimistically fill it with holes now.
+ Label initialization_loop, initialization_loop_entry;
+ __ B(&initialization_loop_entry);
+ __ bind(&initialization_loop);
+ __ Str(the_hole, MemOperand(dst_elements, kPointerSize, PostIndex));
+ __ bind(&initialization_loop_entry);
+ __ Cmp(dst_elements, dst_end);
+ __ B(lt, &initialization_loop);
+
__ Add(dst_elements, array, FixedArray::kHeaderSize);
__ Add(array, array, kHeapObjectTag);
- __ Add(dst_end, dst_elements, Operand(length, LSL, kPointerSizeLog2));
- Register the_hole = x14;
Register heap_num_map = x15;
- __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex);
__ LoadRoot(heap_num_map, Heap::kHeapNumberMapRootIndex);
Label entry;
=======================================
--- /trunk/src/arm64/full-codegen-arm64.cc Thu Oct 9 00:05:16 2014 UTC
+++ /trunk/src/arm64/full-codegen-arm64.cc Fri Oct 10 00:05:16 2014 UTC
@@ -1868,22 +1868,8 @@
Comment cmnt(masm_, "[ Assignment");
- // Left-hand side can only be a property, a global or a (parameter or
local)
- // slot.
- enum LhsKind {
- VARIABLE,
- NAMED_PROPERTY,
- KEYED_PROPERTY,
- NAMED_SUPER_PROPERTY
- };
- LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty();
- if (property != NULL) {
- assign_type = (property->key()->IsPropertyName())
- ? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
- : NAMED_PROPERTY)
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@@ -1908,6 +1894,20 @@
__ Peek(scratch, kPointerSize);
__ Push(scratch, result_register());
}
+ break;
+ case KEYED_SUPER_PROPERTY:
+ VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(property->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForAccumulatorValue(property->key());
+ __ Push(result_register());
+ if (expr->is_compound()) {
+ const Register scratch1 = x10;
+ const Register scratch2 = x11;
+ __ Peek(scratch1, 2 * kPointerSize);
+ __ Peek(scratch2, kPointerSize);
+ __ Push(scratch1, scratch2, result_register());
+ }
break;
case KEYED_PROPERTY:
if (expr->is_compound()) {
@@ -1939,6 +1939,10 @@
EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyLoad(property);
+ PrepareForBailoutForId(property->LoadId(), TOS_REG);
+ break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
@@ -1989,6 +1993,10 @@
EmitNamedSuperPropertyStore(property);
context()->Plug(x0);
break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyStore(property);
+ context()->Plug(x0);
+ break;
case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr);
break;
@@ -2320,12 +2328,25 @@
Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL);
+ __ Push(key->value());
__ Push(x0);
- __ Push(key->value());
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy),
4);
}
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
+ // Assignment to named property of super.
+ // x0 : value
+ // stack : receiver ('this'), home_object, key
+ DCHECK(prop != NULL);
+
+ __ Push(x0);
+ __ CallRuntime((strict_mode() == STRICT ?
Runtime::kStoreKeyedToSuper_Strict
+ :
Runtime::kStoreKeyedToSuper_Sloppy),
+ 4);
+}
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
@@ -4101,24 +4122,8 @@
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
- // Expression can only be a property, a global or a (parameter or local)
- // slot.
- enum LhsKind {
- VARIABLE,
- NAMED_PROPERTY,
- KEYED_PROPERTY,
- NAMED_SUPER_PROPERTY
- };
- LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty();
- // In case of a property we use the uninitialized expression context
- // of the key to detect a named property.
- if (prop != NULL) {
- assign_type =
- (prop->key()->IsPropertyName())
- ? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY :
NAMED_PROPERTY)
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@@ -4130,26 +4135,52 @@
if (expr->is_postfix() && !context()->IsEffect()) {
__ Push(xzr);
}
- if (assign_type == NAMED_PROPERTY) {
- // Put the object both on the stack and in the register.
- VisitForStackValue(prop->obj());
- __ Peek(LoadDescriptor::ReceiverRegister(), 0);
- EmitNamedPropertyLoad(prop);
- } else if (assign_type == NAMED_SUPER_PROPERTY) {
- VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(prop->obj()->AsSuperReference());
- __ Push(result_register());
- const Register scratch = x10;
- __ Peek(scratch, kPointerSize);
- __ Push(scratch, result_register());
- EmitNamedSuperPropertyLoad(prop);
- } else {
- // KEYED_PROPERTY
- VisitForStackValue(prop->obj());
- VisitForStackValue(prop->key());
- __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize);
- __ Peek(LoadDescriptor::NameRegister(), 0);
- EmitKeyedPropertyLoad(prop);
+ switch (assign_type) {
+ case NAMED_PROPERTY: {
+ // Put the object both on the stack and in the register.
+ VisitForStackValue(prop->obj());
+ __ Peek(LoadDescriptor::ReceiverRegister(), 0);
+ EmitNamedPropertyLoad(prop);
+ break;
+ }
+
+ case NAMED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ Push(result_register());
+ const Register scratch = x10;
+ __ Peek(scratch, kPointerSize);
+ __ Push(scratch, result_register());
+ EmitNamedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForAccumulatorValue(prop->key());
+ __ Push(result_register());
+ const Register scratch1 = x10;
+ const Register scratch2 = x11;
+ __ Peek(scratch1, 2 * kPointerSize);
+ __ Peek(scratch2, kPointerSize);
+ __ Push(scratch1, scratch2, result_register());
+ EmitKeyedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_PROPERTY: {
+ VisitForStackValue(prop->obj());
+ VisitForStackValue(prop->key());
+ __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize);
+ __ Peek(LoadDescriptor::NameRegister(), 0);
+ EmitKeyedPropertyLoad(prop);
+ break;
+ }
+
+ case VARIABLE:
+ UNREACHABLE();
}
}
@@ -4189,6 +4220,9 @@
case KEYED_PROPERTY:
__ Poke(x0, kPointerSize * 2);
break;
+ case KEYED_SUPER_PROPERTY:
+ __ Poke(x0, kPointerSize * 3);
+ break;
}
}
}
@@ -4222,6 +4256,9 @@
case KEYED_PROPERTY:
__ Poke(x0, 2 * kXRegSize);
break;
+ case KEYED_SUPER_PROPERTY:
+ __ Poke(x0, 3 * kXRegSize);
+ break;
}
}
}
@@ -4285,6 +4322,17 @@
if (!context()->IsEffect()) {
context()->PlugTOS();
}
+ } else {
+ context()->Plug(x0);
+ }
+ break;
+ }
+ case KEYED_SUPER_PROPERTY: {
+ EmitKeyedSuperPropertyStore(prop);
+ if (expr->is_postfix()) {
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
+ }
} else {
context()->Plug(x0);
}
=======================================
--- /trunk/src/ast.h Thu Oct 9 00:05:16 2014 UTC
+++ /trunk/src/ast.h Fri Oct 10 00:05:16 2014 UTC
@@ -184,7 +184,7 @@
// For generating IDs for AstNodes.
class IdGen {
public:
- explicit IdGen(int id = 0) : id_(id) {}
+ IdGen() : id_(BailoutId::FirstUsable().ToInt()) {}
int GetNextId() { return ReserveIdRange(1); }
int ReserveIdRange(int n) {
@@ -195,6 +195,8 @@
private:
int id_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdGen);
};
#define DECLARE_TYPE_ENUM(type) k##type,
=======================================
--- /trunk/src/base/bits.h Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/base/bits.h Fri Oct 10 00:05:16 2014 UTC
@@ -19,7 +19,7 @@
namespace bits {
// CountPopulation32(value) returns the number of bits set in |value|.
-inline uint32_t CountPopulation32(uint32_t value) {
+inline unsigned CountPopulation32(uint32_t value) {
#if V8_HAS_BUILTIN_POPCOUNT
return __builtin_popcount(value);
#else
@@ -28,20 +28,31 @@
value = ((value >> 4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f);
value = ((value >> 8) & 0x00ff00ff) + (value & 0x00ff00ff);
value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff);
- return value;
+ return static_cast<unsigned>(value);
#endif
}
+
+
+// CountPopulation64(value) returns the number of bits set in |value|.
+inline unsigned CountPopulation64(uint64_t value) {
+#if V8_HAS_BUILTIN_POPCOUNT
+ return __builtin_popcountll(value);
+#else
+ return CountPopulation32(static_cast<uint32_t>(value)) +
+ CountPopulation32(static_cast<uint32_t>(value >> 32));
+#endif
+}
// CountLeadingZeros32(value) returns the number of zero bits following
the most
// significant 1 bit in |value| if |value| is non-zero, otherwise it
returns 32.
-inline uint32_t CountLeadingZeros32(uint32_t value) {
+inline unsigned CountLeadingZeros32(uint32_t value) {
#if V8_HAS_BUILTIN_CLZ
return value ? __builtin_clz(value) : 32;
#elif V8_CC_MSVC
unsigned long result; // NOLINT(runtime/int)
if (!_BitScanReverse(&result, value)) return 32;
- return static_cast<uint32_t>(31 - result);
+ return static_cast<unsigned>(31 - result);
#else
value = value | (value >> 1);
value = value | (value >> 2);
@@ -51,18 +62,35 @@
return CountPopulation32(~value);
#endif
}
+
+
+// CountLeadingZeros64(value) returns the number of zero bits following
the most
+// significant 1 bit in |value| if |value| is non-zero, otherwise it
returns 64.
+inline unsigned CountLeadingZeros64(uint64_t value) {
+#if V8_HAS_BUILTIN_CLZ
+ return value ? __builtin_clzll(value) : 64;
+#else
+ value = value | (value >> 1);
+ value = value | (value >> 2);
+ value = value | (value >> 4);
+ value = value | (value >> 8);
+ value = value | (value >> 16);
+ value = value | (value >> 32);
+ return CountPopulation64(~value);
+#endif
+}
// CountTrailingZeros32(value) returns the number of zero bits preceding
the
// least significant 1 bit in |value| if |value| is non-zero, otherwise it
// returns 32.
-inline uint32_t CountTrailingZeros32(uint32_t value) {
+inline unsigned CountTrailingZeros32(uint32_t value) {
#if V8_HAS_BUILTIN_CTZ
return value ? __builtin_ctz(value) : 32;
#elif V8_CC_MSVC
unsigned long result; // NOLINT(runtime/int)
if (!_BitScanForward(&result, value)) return 32;
- return static_cast<uint32_t>(result);
+ return static_cast<unsigned>(result);
#else
if (value == 0) return 32;
unsigned count = 0;
@@ -71,6 +99,22 @@
return count;
#endif
}
+
+
+// CountTrailingZeros64(value) returns the number of zero bits preceding
the
+// least significant 1 bit in |value| if |value| is non-zero, otherwise it
+// returns 64.
+inline unsigned CountTrailingZeros64(uint64_t value) {
+#if V8_HAS_BUILTIN_CTZ
+ return value ? __builtin_ctzll(value) : 64;
+#else
+ if (value == 0) return 64;
+ unsigned count = 0;
+ for (value ^= value - 1; value >>= 1; ++count)
+ ;
+ return count;
+#endif
+}
// Returns true iff |value| is a power of 2.
=======================================
--- /trunk/src/base/cpu.cc Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/base/cpu.cc Fri Oct 10 00:05:16 2014 UTC
@@ -121,13 +121,18 @@
int __detect_fp64_mode(void) {
double result = 0;
// Bit representation of (double)1 is 0x3FF0000000000000.
- asm(
- "lui $t0, 0x3FF0\n\t"
- "ldc1 $f0, %0\n\t"
- "mtc1 $t0, $f1\n\t"
- "sdc1 $f0, %0\n\t"
- : "+m" (result)
- : : "t0", "$f0", "$f1", "memory");
+ __asm__ volatile(
+ ".set push\n\t"
+ ".set noreorder\n\t"
+ ".set oddspreg\n\t"
+ "lui $t0, 0x3FF0\n\t"
+ "ldc1 $f0, %0\n\t"
+ "mtc1 $t0, $f1\n\t"
+ "sdc1 $f0, %0\n\t"
+ ".set pop\n\t"
+ : "+m"(result)
+ :
+ : "t0", "$f0", "$f1", "memory");
return !(result == 1);
}
@@ -135,9 +140,22 @@
int __detect_mips_arch_revision(void) {
// TODO(dusmil): Do the specific syscall as soon as it is implemented in
mips
- // kernel. Currently fail-back to the least common denominator which is
- // mips32 revision 1.
- return 1;
+ // kernel.
+ uint32_t result = 0;
+ __asm__ volatile(
+ "move $v0, $zero\n\t"
+ // Encoding for "addi $v0, $v0, 1" on non-r6,
+ // which is encoding for "bovc $v0, %v0, 1" on r6.
+ // Use machine code directly to avoid compilation errors with
different
+ // toolchains and maintain compatibility.
+ ".word 0x20420001\n\t"
+ "sw $v0, %0\n\t"
+ : "=m"(result)
+ :
+ : "v0", "memory");
+ // Result is 0 on r6 architectures, 1 on other architecture revisions.
+ // Fall-back to the least common denominator which is mips32 revision 1.
+ return result ? 1 : 6;
}
#endif
=======================================
--- /trunk/src/base/utils/random-number-generator.cc Fri Sep 26 00:05:23
2014 UTC
+++ /trunk/src/base/utils/random-number-generator.cc Fri Oct 10 00:05:16
2014 UTC
@@ -100,6 +100,13 @@
return ((static_cast<int64_t>(Next(26)) << 27) + Next(27)) /
static_cast<double>(static_cast<int64_t>(1) << 53);
}
+
+
+int64_t RandomNumberGenerator::NextInt64() {
+ uint64_t lo = bit_cast<unsigned>(Next(32));
+ uint64_t hi = bit_cast<unsigned>(Next(32));
+ return lo | (hi << 32);
+}
void RandomNumberGenerator::NextBytes(void* buffer, size_t buflen) {
=======================================
--- /trunk/src/base/utils/random-number-generator.h Tue Sep 23 08:38:19
2014 UTC
+++ /trunk/src/base/utils/random-number-generator.h Fri Oct 10 00:05:16
2014 UTC
@@ -68,6 +68,13 @@
// (exclusive), is pseudorandomly generated and returned.
double NextDouble() WARN_UNUSED_RESULT;
+ // Returns the next pseudorandom, uniformly distributed int64 value from
this
+ // random number generator's sequence. The general contract of |
NextInt64()|
+ // is that one 64-bit int value is pseudorandomly generated and returned.
+ // All 2^64 possible integer values are produced with (approximately)
equal
+ // probability.
+ int64_t NextInt64() WARN_UNUSED_RESULT;
+
// Fills the elements of a specified array of bytes with random numbers.
void NextBytes(void* buffer, size_t buflen);
=======================================
--- /trunk/src/builtins.cc Tue Sep 30 00:05:10 2014 UTC
+++ /trunk/src/builtins.cc Fri Oct 10 00:05:16 2014 UTC
@@ -1312,15 +1312,25 @@
static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
}
+
+
+static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
+ KeyedStoreIC::GenerateGeneric(masm, SLOPPY, kMissOnMissingHandler);
+}
+
+
+static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm)
{
+ KeyedStoreIC::GenerateGeneric(masm, STRICT, kMissOnMissingHandler);
+}
static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
- KeyedStoreIC::GenerateGeneric(masm, SLOPPY);
+ KeyedStoreIC::GenerateGeneric(masm, SLOPPY,
kCallRuntimeOnMissingHandler);
}
static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
- KeyedStoreIC::GenerateGeneric(masm, STRICT);
+ KeyedStoreIC::GenerateGeneric(masm, STRICT,
kCallRuntimeOnMissingHandler);
}
=======================================
--- /trunk/src/builtins.h Wed Sep 24 00:05:07 2014 UTC
+++ /trunk/src/builtins.h Fri Oct 10 00:05:16 2014 UTC
@@ -95,12 +95,15 @@
V(KeyedStoreIC_Initialize, KEYED_STORE_IC, UNINITIALIZED,
kNoExtraICState) \
V(KeyedStoreIC_PreMonomorphic, KEYED_STORE_IC,
PREMONOMORPHIC, \
kNoExtraICState) \
+ V(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, MEGAMORPHIC,
kNoExtraICState) \
V(KeyedStoreIC_Generic, KEYED_STORE_IC, GENERIC,
kNoExtraICState) \
\
V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC,
UNINITIALIZED, \
StoreIC::kStrictModeState) \
V(KeyedStoreIC_PreMonomorphic_Strict, KEYED_STORE_IC,
PREMONOMORPHIC, \
StoreIC::kStrictModeState) \
+ V(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC,
MEGAMORPHIC, \
+
StoreIC::kStrictModeState) \
V(KeyedStoreIC_Generic_Strict, KEYED_STORE_IC,
GENERIC, \
StoreIC::kStrictModeState) \
V(KeyedStoreIC_SloppyArguments, KEYED_STORE_IC,
MONOMORPHIC, \
=======================================
--- /trunk/src/compiler/arm64/code-generator-arm64.cc Thu Oct 2 00:05:29
2014 UTC
+++ /trunk/src/compiler/arm64/code-generator-arm64.cc Fri Oct 10 00:05:16
2014 UTC
@@ -319,22 +319,22 @@
__ Sub(i.OutputRegister32(), i.InputRegister32(0),
i.InputOperand32(1));
}
break;
- case kArm64Shl:
+ case kArm64Lsl:
ASSEMBLE_SHIFT(Lsl, 64);
break;
- case kArm64Shl32:
+ case kArm64Lsl32:
ASSEMBLE_SHIFT(Lsl, 32);
break;
- case kArm64Shr:
+ case kArm64Lsr:
ASSEMBLE_SHIFT(Lsr, 64);
break;
- case kArm64Shr32:
+ case kArm64Lsr32:
ASSEMBLE_SHIFT(Lsr, 32);
break;
- case kArm64Sar:
+ case kArm64Asr:
ASSEMBLE_SHIFT(Asr, 64);
break;
- case kArm64Sar32:
+ case kArm64Asr32:
ASSEMBLE_SHIFT(Asr, 32);
break;
case kArm64Ror:
@@ -349,6 +349,14 @@
case kArm64Sxtw:
__ Sxtw(i.OutputRegister(), i.InputRegister32(0));
break;
+ case kArm64Ubfx:
+ __ Ubfx(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
+ i.InputInt8(2));
+ break;
+ case kArm64Ubfx32:
+ __ Ubfx(i.OutputRegister32(), i.InputRegister32(0), i.InputInt8(1),
+ i.InputInt8(2));
+ break;
case kArm64Claim: {
int words = MiscField::decode(instr->opcode());
__ Claim(words);
=======================================
--- /trunk/src/compiler/arm64/instruction-codes-arm64.h Tue Sep 30 00:05:10
2014 UTC
+++ /trunk/src/compiler/arm64/instruction-codes-arm64.h Fri Oct 10 00:05:16
2014 UTC
@@ -54,16 +54,18 @@
V(Arm64Not32) \
V(Arm64Neg) \
V(Arm64Neg32) \
- V(Arm64Shl) \
- V(Arm64Shl32) \
- V(Arm64Shr) \
- V(Arm64Shr32) \
- V(Arm64Sar) \
- V(Arm64Sar32) \
+ V(Arm64Lsl) \
+ V(Arm64Lsl32) \
+ V(Arm64Lsr) \
+ V(Arm64Lsr32) \
+ V(Arm64Asr) \
+ V(Arm64Asr32) \
V(Arm64Ror) \
V(Arm64Ror32) \
V(Arm64Mov32) \
V(Arm64Sxtw) \
+ V(Arm64Ubfx) \
+ V(Arm64Ubfx32) \
V(Arm64Claim) \
V(Arm64Poke) \
V(Arm64PokePairZero) \
=======================================
--- /trunk/src/compiler/arm64/instruction-selector-arm64.cc Wed Oct 8
00:05:11 2014 UTC
+++ /trunk/src/compiler/arm64/instruction-selector-arm64.cc Fri Oct 10
00:05:16 2014 UTC
@@ -355,7 +355,29 @@
void InstructionSelector::VisitWord32And(Node* node) {
+ Arm64OperandGenerator g(this);
Int32BinopMatcher m(node);
+ if (m.left().IsWord32Shr() && CanCover(node, m.left().node()) &&
+ m.right().HasValue()) {
+ uint32_t mask = m.right().Value();
+ uint32_t mask_width = base::bits::CountPopulation32(mask);
+ uint32_t mask_msb = base::bits::CountLeadingZeros32(mask);
+ if ((mask_width != 0) && (mask_msb + mask_width == 32)) {
+ // The mask must be contiguous, and occupy the least-significant
bits.
+ DCHECK_EQ(0, base::bits::CountTrailingZeros32(mask));
+
+ // Select Ubfx for And(Shr(x, imm), mask) where the mask is in the
least
+ // significant bits.
+ Int32BinopMatcher mleft(m.left().node());
+ if (mleft.right().IsInRange(0, 31)) {
+ Emit(kArm64Ubfx32, g.DefineAsRegister(node),
+ g.UseRegister(mleft.left().node()),
+ g.UseImmediate(mleft.right().node()),
g.TempImmediate(mask_width));
+ return;
+ }
+ // Other cases fall through to the normal And operation.
+ }
+ }
VisitLogical<Int32BinopMatcher>(
this, node, &m, kArm64And32, CanCover(node, m.left().node()),
CanCover(node, m.right().node()), kLogical32Imm);
@@ -363,7 +385,29 @@
void InstructionSelector::VisitWord64And(Node* node) {
+ Arm64OperandGenerator g(this);
Int64BinopMatcher m(node);
+ if (m.left().IsWord64Shr() && CanCover(node, m.left().node()) &&
+ m.right().HasValue()) {
+ uint64_t mask = m.right().Value();
+ uint64_t mask_width = base::bits::CountPopulation64(mask);
+ uint64_t mask_msb = base::bits::CountLeadingZeros64(mask);
+ if ((mask_width != 0) && (mask_msb + mask_width == 64)) {
+ // The mask must be contiguous, and occupy the least-significant
bits.
+ DCHECK_EQ(0, base::bits::CountTrailingZeros64(mask));
+
+ // Select Ubfx for And(Shr(x, imm), mask) where the mask is in the
least
+ // significant bits.
+ Int64BinopMatcher mleft(m.left().node());
+ if (mleft.right().IsInRange(0, 63)) {
+ Emit(kArm64Ubfx, g.DefineAsRegister(node),
+ g.UseRegister(mleft.left().node()),
+ g.UseImmediate(mleft.right().node()),
g.TempImmediate(mask_width));
+ return;
+ }
+ // Other cases fall through to the normal And operation.
+ }
+ }
VisitLogical<Int64BinopMatcher>(
this, node, &m, kArm64And, CanCover(node, m.left().node()),
CanCover(node, m.right().node()), kLogical64Imm);
@@ -403,32 +447,72 @@
void InstructionSelector::VisitWord32Shl(Node* node) {
- VisitRRO(this, kArm64Shl32, node, kShift32Imm);
+ VisitRRO(this, kArm64Lsl32, node, kShift32Imm);
}
void InstructionSelector::VisitWord64Shl(Node* node) {
- VisitRRO(this, kArm64Shl, node, kShift64Imm);
+ VisitRRO(this, kArm64Lsl, node, kShift64Imm);
}
void InstructionSelector::VisitWord32Shr(Node* node) {
- VisitRRO(this, kArm64Shr32, node, kShift32Imm);
+ Arm64OperandGenerator g(this);
+ Int32BinopMatcher m(node);
+ if (m.left().IsWord32And() && m.right().IsInRange(0, 31)) {
+ int32_t lsb = m.right().Value();
+ Int32BinopMatcher mleft(m.left().node());
+ if (mleft.right().HasValue()) {
+ uint32_t mask = (mleft.right().Value() >> lsb) << lsb;
+ uint32_t mask_width = base::bits::CountPopulation32(mask);
+ uint32_t mask_msb = base::bits::CountLeadingZeros32(mask);
+ // Select Ubfx for Shr(And(x, mask), imm) where the result of the
mask is
+ // shifted into the least-significant bits.
+ if ((mask_msb + mask_width + lsb) == 32) {
+ DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(mask));
+ Emit(kArm64Ubfx32, g.DefineAsRegister(node),
+ g.UseRegister(mleft.left().node()), g.TempImmediate(lsb),
+ g.TempImmediate(mask_width));
+ return;
+ }
+ }
+ }
+ VisitRRO(this, kArm64Lsr32, node, kShift32Imm);
}
void InstructionSelector::VisitWord64Shr(Node* node) {
- VisitRRO(this, kArm64Shr, node, kShift64Imm);
+ Arm64OperandGenerator g(this);
+ Int64BinopMatcher m(node);
+ if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) {
+ int64_t lsb = m.right().Value();
+ Int64BinopMatcher mleft(m.left().node());
+ if (mleft.right().HasValue()) {
+ // Select Ubfx for Shr(And(x, mask), imm) where the result of the
mask is
+ // shifted into the least-significant bits.
+ uint64_t mask = (mleft.right().Value() >> lsb) << lsb;
+ uint64_t mask_width = base::bits::CountPopulation64(mask);
+ uint64_t mask_msb = base::bits::CountLeadingZeros64(mask);
+ if ((mask_msb + mask_width + lsb) == 64) {
+ DCHECK_EQ(lsb, base::bits::CountTrailingZeros64(mask));
+ Emit(kArm64Ubfx, g.DefineAsRegister(node),
+ g.UseRegister(mleft.left().node()), g.TempImmediate(lsb),
+ g.TempImmediate(mask_width));
+ return;
+ }
+ }
+ }
+ VisitRRO(this, kArm64Lsr, node, kShift64Imm);
}
void InstructionSelector::VisitWord32Sar(Node* node) {
- VisitRRO(this, kArm64Sar32, node, kShift32Imm);
+ VisitRRO(this, kArm64Asr32, node, kShift32Imm);
}
void InstructionSelector::VisitWord64Sar(Node* node) {
- VisitRRO(this, kArm64Sar, node, kShift64Imm);
+ VisitRRO(this, kArm64Asr, node, kShift64Imm);
}
=======================================
--- /trunk/src/compiler/ia32/code-generator-ia32.cc Thu Oct 9 00:05:16
2014 UTC
+++ /trunk/src/compiler/ia32/code-generator-ia32.cc Fri Oct 10 00:05:16
2014 UTC
@@ -249,7 +249,7 @@
__ idiv(i.InputOperand(1));
break;
case kIA32Udiv:
- __ xor_(edx, edx);
+ __ Move(edx, Immediate(0));
__ div(i.InputOperand(1));
break;
case kIA32Not:
@@ -552,7 +552,7 @@
switch (condition) {
case kUnorderedEqual:
__ j(parity_odd, &check, Label::kNear);
- __ mov(reg, Immediate(0));
+ __ Move(reg, Immediate(0));
__ jmp(&done, Label::kNear);
// Fall through.
case kEqual:
@@ -580,7 +580,7 @@
break;
case kUnorderedLessThan:
__ j(parity_odd, &check, Label::kNear);
- __ mov(reg, Immediate(0));
+ __ Move(reg, Immediate(0));
__ jmp(&done, Label::kNear);
// Fall through.
case kUnsignedLessThan:
@@ -596,7 +596,7 @@
break;
case kUnorderedLessThanOrEqual:
__ j(parity_odd, &check, Label::kNear);
- __ mov(reg, Immediate(0));
+ __ Move(reg, Immediate(0));
__ jmp(&done, Label::kNear);
// Fall through.
case kUnsignedLessThanOrEqual:
@@ -626,7 +626,7 @@
// Emit a branch to set a register to either 1 or 0.
Label set;
__ j(cc, &set, Label::kNear);
- __ mov(reg, Immediate(0));
+ __ Move(reg, Immediate(0));
__ jmp(&done, Label::kNear);
__ bind(&set);
__ mov(reg, Immediate(1));
@@ -899,38 +899,35 @@
}
} else if (destination->IsRegister()) {
Register dst = g.ToRegister(destination);
- __ mov(dst, g.ToImmediate(source));
+ __ Move(dst, g.ToImmediate(source));
} else if (destination->IsStackSlot()) {
Operand dst = g.ToOperand(destination);
- __ mov(dst, g.ToImmediate(source));
+ __ Move(dst, g.ToImmediate(source));
} else if (src_constant.type() == Constant::kFloat32) {
// TODO(turbofan): Can we do better here?
- Immediate src(bit_cast<int32_t>(src_constant.ToFloat32()));
+ uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32());
if (destination->IsDoubleRegister()) {
XMMRegister dst = g.ToDoubleRegister(destination);
- __ push(Immediate(src));
- __ movss(dst, Operand(esp, 0));
- __ add(esp, Immediate(kDoubleSize / 2));
+ __ Move(dst, src);
} else {
DCHECK(destination->IsDoubleStackSlot());
Operand dst = g.ToOperand(destination);
- __ mov(dst, src);
+ __ Move(dst, Immediate(src));
}
} else {
DCHECK_EQ(Constant::kFloat64, src_constant.type());
- double v = src_constant.ToFloat64();
- uint64_t int_val = bit_cast<uint64_t, double>(v);
- int32_t lower = static_cast<int32_t>(int_val);
- int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
+ uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
+ uint32_t lower = static_cast<uint32_t>(src);
+ uint32_t upper = static_cast<uint32_t>(src >> 32);
if (destination->IsDoubleRegister()) {
XMMRegister dst = g.ToDoubleRegister(destination);
- __ Move(dst, v);
+ __ Move(dst, src);
} else {
DCHECK(destination->IsDoubleStackSlot());
Operand dst0 = g.ToOperand(destination);
Operand dst1 = g.HighOperand(destination);
- __ mov(dst0, Immediate(lower));
- __ mov(dst1, Immediate(upper));
+ __ Move(dst0, Immediate(lower));
+ __ Move(dst1, Immediate(upper));
}
}
} else if (source->IsDoubleRegister()) {
=======================================
--- /trunk/src/compiler/machine-operator-reducer.cc Thu Oct 2 00:05:29
2014 UTC
+++ /trunk/src/compiler/machine-operator-reducer.cc Fri Oct 10 00:05:16
2014 UTC
@@ -473,6 +473,22 @@
if (m.IsChangeFloat32ToFloat64()) return
Replace(m.node()->InputAt(0));
break;
}
+ case IrOpcode::kStore: {
+ Node* const value = node->InputAt(2);
+ // TODO(turbofan): Extend to 64-bit?
+ if (value->opcode() == IrOpcode::kWord32And) {
+ MachineType const rep = static_cast<MachineType>(
+ StoreRepresentationOf(node->op()).machine_type() & kRepMask);
+ Uint32BinopMatcher m(value);
+ if (m.right().HasValue() &&
+ ((rep == kRepWord8 && (m.right().Value() & 0xff) == 0xff) ||
+ (rep == kRepWord16 && (m.right().Value() & 0xffff) ==
0xffff))) {
+ node->ReplaceInput(2, m.left().node());
+ return Changed(node);
+ }
+ }
+ break;
+ }
default:
break;
}
=======================================
--- /trunk/src/compiler/machine-operator.cc Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/compiler/machine-operator.cc Fri Oct 10 00:05:16 2014 UTC
@@ -44,6 +44,12 @@
return os << "(" << rep.machine_type() << " : " <<
rep.write_barrier_kind()
<< ")";
}
+
+
+StoreRepresentation const& StoreRepresentationOf(Operator const* op) {
+ DCHECK_EQ(IrOpcode::kStore, op->opcode());
+ return OpParameter<StoreRepresentation>(op);
+}
#define
PURE_OP_LIST(V) \
=======================================
--- /trunk/src/compiler/machine-operator.h Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/compiler/machine-operator.h Fri Oct 10 00:05:16 2014 UTC
@@ -49,6 +49,8 @@
std::ostream& operator<<(std::ostream&, StoreRepresentation);
+StoreRepresentation const& StoreRepresentationOf(Operator const*);
+
// Interface for building machine-level operators. These operators are
// machine-level but machine-independent and thus define a language
suitable
=======================================
--- /trunk/src/date.h Wed Sep 3 08:32:14 2014 UTC
+++ /trunk/src/date.h Fri Oct 10 00:05:16 2014 UTC
@@ -104,21 +104,51 @@
// ECMA 262 - 15.9.1.9
// LocalTime(t) = t + LocalTZA + DaylightSavingTA(t)
- // ECMA 262 assumes that DaylightSavingTA is computed using UTC time,
- // but we fetch DST from OS using local time, therefore we need:
- // LocalTime(t) = t + LocalTZA + DaylightSavingTA(t + LocalTZA).
int64_t ToLocal(int64_t time_ms) {
- time_ms += LocalOffsetInMs();
- return time_ms + DaylightSavingsOffsetInMs(time_ms);
+ return time_ms + LocalOffsetInMs() +
DaylightSavingsOffsetInMs(time_ms);
}
// ECMA 262 - 15.9.1.9
// UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
- // ECMA 262 assumes that DaylightSavingTA is computed using UTC time,
- // but we fetch DST from OS using local time, therefore we need:
- // UTC(t) = t - LocalTZA - DaylightSavingTA(t).
int64_t ToUTC(int64_t time_ms) {
- return time_ms - LocalOffsetInMs() -
DaylightSavingsOffsetInMs(time_ms);
+ // We need to compute UTC time that corresponds to the given local
time.
+ // Literally following spec here leads to incorrect time computation at
+ // the points were we transition to and from DST.
+ //
+ // The following shows that using DST for (t - LocalTZA - hour)
produces
+ // correct conversion.
+ //
+ // Consider transition to DST at local time L1.
+ // Let L0 = L1 - hour, L2 = L1 + hour,
+ // U1 = UTC time that corresponds to L1,
+ // U0 = U1 - hour.
+ // Transitioning to DST moves local clock one hour forward L1 => L2, so
+ // U0 = UTC time that corresponds to L0 = L0 - LocalTZA,
+ // U1 = UTC time that corresponds to L1 = L1 - LocalTZA,
+ // U1 = UTC time that corresponds to L2 = L2 - LocalTZA - hour.
+ // Note that DST(U0 - hour) = 0, DST(U0) = 0, DST(U1) = 1.
+ // U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour),
+ // U1 = L1 - LocalTZA - DST(L1 - LocalTZA - hour),
+ // U1 = L2 - LocalTZA - DST(L2 - LocalTZA - hour).
+ //
+ // Consider transition from DST at local time L1.
+ // Let L0 = L1 - hour,
+ // U1 = UTC time that corresponds to L1,
+ // U0 = U1 - hour, U2 = U1 + hour.
+ // Transitioning from DST moves local clock one hour back L1 => L0, so
+ // U0 = UTC time that corresponds to L0 (before transition)
+ // = L0 - LocalTZA - hour.
+ // U1 = UTC time that corresponds to L0 (after transition)
+ // = L0 - LocalTZA = L1 - LocalTZA - hour
+ // U2 = UTC time that corresponds to L1 = L1 - LocalTZA.
+ // Note that DST(U0) = 1, DST(U1) = 0, DST(U2) = 0.
+ // U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour) = L0 - LocalTZA -
DST(U0).
+ // U2 = L1 - LocalTZA - DST(L1 - LocalTZA - hour) = L1 - LocalTZA -
DST(U1).
+ // It is impossible to get U1 from local time.
+
+ const int kMsPerHour = 3600 * 1000;
+ time_ms -= LocalOffsetInMs();
+ return time_ms - DaylightSavingsOffsetInMs(time_ms - kMsPerHour);
}
=======================================
--- /trunk/src/flag-definitions.h Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/flag-definitions.h Fri Oct 10 00:05:16 2014 UTC
@@ -731,8 +731,6 @@
DEFINE_BOOL(gc_verbose, false, "print stuff during garbage collection")
DEFINE_BOOL(heap_stats, false, "report heap statistics before and after
GC")
DEFINE_BOOL(code_stats, false, "report code statistics after GC")
-DEFINE_BOOL(verify_native_context_separation, false,
- "verify that code holds on to at most one native context after
GC")
DEFINE_BOOL(print_handles, false, "report handles after GC")
DEFINE_BOOL(print_global_handles, false, "report global handles after GC")
=======================================
--- /trunk/src/full-codegen.h Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/full-codegen.h Fri Oct 10 00:05:16 2014 UTC
@@ -517,6 +517,24 @@
void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure);
// Platform-specific support for compiling assignments.
+
+ // Left-hand side can only be a property, a global or a (parameter or
local)
+ // slot.
+ enum LhsKind {
+ VARIABLE,
+ NAMED_PROPERTY,
+ KEYED_PROPERTY,
+ NAMED_SUPER_PROPERTY,
+ KEYED_SUPER_PROPERTY
+ };
+
+ static LhsKind GetAssignType(Property* property) {
+ if (property == NULL) return VARIABLE;
+ bool super_access = property->IsSuperAccess();
+ return (property->key()->IsPropertyName())
+ ? (super_access ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
+ : (super_access ? KEYED_SUPER_PROPERTY : KEYED_PROPERTY);
+ }
// Load a value from a named property.
// The receiver is left on the stack by the IC.
@@ -569,6 +587,10 @@
// is expected in accumulator.
void EmitNamedSuperPropertyStore(Property* prop);
+ // Complete a super named property assignment. The right-hand-side value
+ // is expected in accumulator.
+ void EmitKeyedSuperPropertyStore(Property* prop);
+
// Complete a keyed property assignment. The receiver and key are
// expected on top of the stack and the right-hand-side value in the
// accumulator.
=======================================
--- /trunk/src/heap/mark-compact.cc Fri Oct 3 00:04:58 2014 UTC
+++ /trunk/src/heap/mark-compact.cc Fri Oct 10 00:05:16 2014 UTC
@@ -227,103 +227,6 @@
#endif // VERIFY_HEAP
-#ifdef DEBUG
-class VerifyNativeContextSeparationVisitor : public ObjectVisitor {
- public:
- VerifyNativeContextSeparationVisitor() : current_native_context_(NULL) {}
-
- void VisitPointers(Object** start, Object** end) {
- for (Object** current = start; current < end; current++) {
- if ((*current)->IsHeapObject()) {
- HeapObject* object = HeapObject::cast(*current);
- if (object->IsString()) continue;
- switch (object->map()->instance_type()) {
- case JS_FUNCTION_TYPE:
- CheckContext(JSFunction::cast(object)->context());
- break;
- case JS_GLOBAL_PROXY_TYPE:
- CheckContext(JSGlobalProxy::cast(object)->native_context());
- break;
- case JS_GLOBAL_OBJECT_TYPE:
- case JS_BUILTINS_OBJECT_TYPE:
- CheckContext(GlobalObject::cast(object)->native_context());
- break;
- case JS_ARRAY_TYPE:
- case JS_DATE_TYPE:
- case JS_OBJECT_TYPE:
- case JS_REGEXP_TYPE:
- VisitPointer(HeapObject::RawField(object,
JSObject::kMapOffset));
- break;
- case MAP_TYPE:
- VisitPointer(HeapObject::RawField(object,
Map::kPrototypeOffset));
- VisitPointer(HeapObject::RawField(object,
Map::kConstructorOffset));
- break;
- case FIXED_ARRAY_TYPE:
- if (object->IsContext()) {
- CheckContext(object);
- } else {
- FixedArray* array = FixedArray::cast(object);
- int length = array->length();
- // Set array length to zero to prevent cycles while iterating
- // over array bodies, this is easier than intrusive marking.
- array->set_length(0);
- array->IterateBody(FIXED_ARRAY_TYPE,
FixedArray::SizeFor(length),
- this);
- array->set_length(length);
- }
- break;
- case CELL_TYPE:
- case JS_PROXY_TYPE:
- case JS_VALUE_TYPE:
- case TYPE_FEEDBACK_INFO_TYPE:
- object->Iterate(this);
- break;
- case DECLARED_ACCESSOR_INFO_TYPE:
- case EXECUTABLE_ACCESSOR_INFO_TYPE:
- case BYTE_ARRAY_TYPE:
- case CALL_HANDLER_INFO_TYPE:
- case CODE_TYPE:
- case FIXED_DOUBLE_ARRAY_TYPE:
- case HEAP_NUMBER_TYPE:
- case MUTABLE_HEAP_NUMBER_TYPE:
- case INTERCEPTOR_INFO_TYPE:
- case ODDBALL_TYPE:
- case SCRIPT_TYPE:
- case SHARED_FUNCTION_INFO_TYPE:
- break;
- default:
- UNREACHABLE();
- }
- }
- }
- }
-
- private:
- void CheckContext(Object* context) {
- if (!context->IsContext()) return;
- Context* native_context = Context::cast(context)->native_context();
- if (current_native_context_ == NULL) {
- current_native_context_ = native_context;
- } else {
- CHECK_EQ(current_native_context_, native_context);
- }
- }
-
- Context* current_native_context_;
-};
-
-
-static void VerifyNativeContextSeparation(Heap* heap) {
- HeapObjectIterator it(heap->code_space());
-
- for (Object* object = it.Next(); object != NULL; object = it.Next()) {
- VerifyNativeContextSeparationVisitor visitor;
- Code::cast(object)->CodeIterateBody(&visitor);
- }
-}
-#endif
-
-
void MarkCompactCollector::SetUp() {
free_list_old_data_space_.Reset(new FreeList(heap_->old_data_space()));
free_list_old_pointer_space_.Reset(new
FreeList(heap_->old_pointer_space()));
@@ -405,12 +308,6 @@
SweepSpaces();
-#ifdef DEBUG
- if (FLAG_verify_native_context_separation) {
- VerifyNativeContextSeparation(heap_);
- }
-#endif
-
#ifdef VERIFY_HEAP
if (heap()->weak_embedded_objects_verification_enabled()) {
VerifyWeakEmbeddedObjectsInCode();
=======================================
--- /trunk/src/ia32/assembler-ia32.cc Fri Oct 3 00:04:58 2014 UTC
+++ /trunk/src/ia32/assembler-ia32.cc Fri Oct 10 00:05:16 2014 UTC
@@ -2379,6 +2379,26 @@
EMIT(0x17);
emit_sse_operand(dst, src);
}
+
+
+void Assembler::pslld(XMMRegister reg, int8_t shift) {
+ EnsureSpace ensure_space(this);
+ EMIT(0x66);
+ EMIT(0x0F);
+ EMIT(0x72);
+ emit_sse_operand(esi, reg); // esi == 6
+ EMIT(shift);
+}
+
+
+void Assembler::psrld(XMMRegister reg, int8_t shift) {
+ EnsureSpace ensure_space(this);
+ EMIT(0x66);
+ EMIT(0x0F);
+ EMIT(0x72);
+ emit_sse_operand(edx, reg); // edx == 2
+ EMIT(shift);
+}
void Assembler::psllq(XMMRegister reg, int8_t shift) {
=======================================
--- /trunk/src/ia32/assembler-ia32.h Fri Oct 3 00:04:58 2014 UTC
+++ /trunk/src/ia32/assembler-ia32.h Fri Oct 10 00:05:16 2014 UTC
@@ -1024,6 +1024,8 @@
void por(XMMRegister dst, XMMRegister src);
void ptest(XMMRegister dst, XMMRegister src);
+ void pslld(XMMRegister reg, int8_t shift);
+ void psrld(XMMRegister reg, int8_t shift);
void psllq(XMMRegister reg, int8_t shift);
void psllq(XMMRegister dst, XMMRegister src);
void psrlq(XMMRegister reg, int8_t shift);
=======================================
--- /trunk/src/ia32/codegen-ia32.cc Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/ia32/codegen-ia32.cc Fri Oct 10 00:05:16 2014 UTC
@@ -720,6 +720,19 @@
__ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
+ // Allocating heap numbers in the loop below can fail and cause a jump to
+ // gc_required. We can't leave a partly initialized FixedArray behind,
+ // so pessimistically fill it with holes now.
+ Label initialization_loop, initialization_loop_entry;
+ __ jmp(&initialization_loop_entry, Label::kNear);
+ __ bind(&initialization_loop);
+ __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
+ masm->isolate()->factory()->the_hole_value());
+ __ bind(&initialization_loop_entry);
+ __ sub(ebx, Immediate(Smi::FromInt(1)));
+ __ j(not_sign, &initialization_loop);
+
+ __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
__ jmp(&entry);
// ebx: target map
=======================================
--- /trunk/src/ia32/disasm-ia32.cc Thu Aug 7 08:39:21 2014 UTC
+++ /trunk/src/ia32/disasm-ia32.cc Fri Oct 10 00:05:16 2014 UTC
@@ -1386,6 +1386,15 @@
NameOfXMMRegister(regop),
NameOfXMMRegister(rm));
data++;
+ } else if (*data == 0x72) {
+ data++;
+ int mod, regop, rm;
+ get_modrm(*data, &mod, ®op, &rm);
+ int8_t imm8 = static_cast<int8_t>(data[1]);
+ DCHECK(regop == esi || regop == edx);
+ AppendToBuffer("%s %s,%d", (regop == esi) ? "pslld" : "psrld",
+ NameOfXMMRegister(rm), static_cast<int>(imm8));
+ data += 2;
} else if (*data == 0x73) {
data++;
int mod, regop, rm;
=======================================
--- /trunk/src/ia32/full-codegen-ia32.cc Thu Oct 9 00:05:16 2014 UTC
+++ /trunk/src/ia32/full-codegen-ia32.cc Fri Oct 10 00:05:16 2014 UTC
@@ -1820,22 +1820,8 @@
Comment cmnt(masm_, "[ Assignment");
- // Left-hand side can only be a property, a global or a (parameter or
local)
- // slot.
- enum LhsKind {
- VARIABLE,
- NAMED_PROPERTY,
- KEYED_PROPERTY,
- NAMED_SUPER_PROPERTY
- };
- LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty();
- if (property != NULL) {
- assign_type = (property->key()->IsPropertyName())
- ? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
- : NAMED_PROPERTY)
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@@ -1859,6 +1845,18 @@
} else {
VisitForStackValue(property->obj());
}
+ break;
+ case KEYED_SUPER_PROPERTY:
+ VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(property->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForAccumulatorValue(property->key());
+ __ Push(result_register());
+ if (expr->is_compound()) {
+ __ push(MemOperand(esp, 2 * kPointerSize));
+ __ push(MemOperand(esp, 2 * kPointerSize));
+ __ push(result_register());
+ }
break;
case KEYED_PROPERTY: {
if (expr->is_compound()) {
@@ -1892,6 +1890,10 @@
EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyLoad(property);
+ PrepareForBailoutForId(property->LoadId(), TOS_REG);
+ break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
@@ -1939,7 +1941,11 @@
break;
case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyStore(property);
- context()->Plug(eax);
+ context()->Plug(result_register());
+ break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyStore(property);
+ context()->Plug(result_register());
break;
case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr);
@@ -2574,12 +2580,24 @@
Literal* key = prop->key()->AsLiteral();
DCHECK(key != NULL);
+ __ push(Immediate(key->value()));
__ push(eax);
- __ push(Immediate(key->value()));
__ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
: Runtime::kStoreToSuper_Sloppy),
4);
}
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
+ // Assignment to named property of super.
+ // eax : value
+ // stack : receiver ('this'), home_object, key
+
+ __ push(eax);
+ __ CallRuntime((strict_mode() == STRICT ?
Runtime::kStoreKeyedToSuper_Strict
+ :
Runtime::kStoreKeyedToSuper_Sloppy),
+ 4);
+}
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
@@ -4391,24 +4409,8 @@
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
- // Expression can only be a property, a global or a (parameter or local)
- // slot.
- enum LhsKind {
- VARIABLE,
- NAMED_PROPERTY,
- KEYED_PROPERTY,
- NAMED_SUPER_PROPERTY
- };
- LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty();
- // In case of a property we use the uninitialized expression context
- // of the key to detect a named property.
- if (prop != NULL) {
- assign_type =
- (prop->key()->IsPropertyName())
- ? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY :
NAMED_PROPERTY)
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@@ -4420,25 +4422,50 @@
if (expr->is_postfix() && !context()->IsEffect()) {
__ push(Immediate(Smi::FromInt(0)));
}
- if (assign_type == NAMED_PROPERTY) {
- // Put the object both on the stack and in the register.
- VisitForStackValue(prop->obj());
- __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
- EmitNamedPropertyLoad(prop);
- } else if (assign_type == NAMED_SUPER_PROPERTY) {
- VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(prop->obj()->AsSuperReference());
- __ push(result_register());
- __ push(MemOperand(esp, kPointerSize));
- __ push(result_register());
- EmitNamedSuperPropertyLoad(prop);
- } else {
- VisitForStackValue(prop->obj());
- VisitForStackValue(prop->key());
- __ mov(LoadDescriptor::ReceiverRegister(),
- Operand(esp, kPointerSize)); // Object.
- __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key.
- EmitKeyedPropertyLoad(prop);
+ switch (assign_type) {
+ case NAMED_PROPERTY: {
+ // Put the object both on the stack and in the register.
+ VisitForStackValue(prop->obj());
+ __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
+ EmitNamedPropertyLoad(prop);
+ break;
+ }
+
+ case NAMED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ push(result_register());
+ __ push(MemOperand(esp, kPointerSize));
+ __ push(result_register());
+ EmitNamedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ push(result_register());
+ VisitForAccumulatorValue(prop->key());
+ __ push(result_register());
+ __ push(MemOperand(esp, 2 * kPointerSize));
+ __ push(MemOperand(esp, 2 * kPointerSize));
+ __ push(result_register());
+ EmitKeyedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_PROPERTY: {
+ VisitForStackValue(prop->obj());
+ VisitForStackValue(prop->key());
+ __ mov(LoadDescriptor::ReceiverRegister(),
+ Operand(esp, kPointerSize)); //
Object.
+ __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key.
+ EmitKeyedPropertyLoad(prop);
+ break;
+ }
+
+ case VARIABLE:
+ UNREACHABLE();
}
}
@@ -4476,6 +4503,9 @@
case KEYED_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax);
break;
+ case KEYED_SUPER_PROPERTY:
+ __ mov(Operand(esp, 3 * kPointerSize), eax);
+ break;
}
}
}
@@ -4517,6 +4547,9 @@
case KEYED_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax);
break;
+ case KEYED_SUPER_PROPERTY:
+ __ mov(Operand(esp, 3 * kPointerSize), eax);
+ break;
}
}
}
@@ -4579,6 +4612,17 @@
if (!context()->IsEffect()) {
context()->PlugTOS();
}
+ } else {
+ context()->Plug(eax);
+ }
+ break;
+ }
+ case KEYED_SUPER_PROPERTY: {
+ EmitKeyedSuperPropertyStore(prop);
+ if (expr->is_postfix()) {
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
+ }
} else {
context()->Plug(eax);
}
=======================================
***Additional files exist in this changeset.***
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.