Revision: 24709
Author: [email protected]
Date: Fri Oct 17 20:38:26 2014 UTC
Log: Version 3.30.13 (based on bleeding_edge revision r24708)
Don't expose Array.prototype.values as it breaks webcompat (Chromium issue
409858).
Fix break location calculation (Chromium issue 419663).
Enable libstdc++ debug mode in debug builds (issue 3638).
Performance and stability improvements on all platforms.
https://code.google.com/p/v8/source/detail?r=24709
Added:
/trunk/src/compiler/control-reducer.cc
/trunk/src/compiler/control-reducer.h
/trunk/test/cctest/compiler/test-control-reducer.cc
/trunk/test/cctest/types-fuzz.h
/trunk/test/js-perf-test/Classes
/trunk/test/js-perf-test/Classes/Classes.json
/trunk/test/js-perf-test/Classes/run.js
/trunk/test/js-perf-test/Classes/super.js
/trunk/test/js-perf-test/Iterators
/trunk/test/js-perf-test/Iterators/Iterators.json
/trunk/test/js-perf-test/Iterators/forof.js
/trunk/test/js-perf-test/Iterators/run.js
/trunk/test/js-perf-test/base.js
/trunk/test/mjsunit/asm/do-while-false.js
/trunk/test/mjsunit/asm/if-folding.js
/trunk/test/mjsunit/asm/if-reduction.js
/trunk/test/mjsunit/asm/infinite-loops-taken.js
/trunk/test/mjsunit/asm/infinite-loops.js
/trunk/test/mjsunit/asm/int32array-constant-key.js
/trunk/test/mjsunit/asm/word32and.js
/trunk/test/mjsunit/regress/regress-419663.js
/trunk/test/mjsunit/unused-context-in-with.js
Deleted:
/trunk/test/js-perf-test/Collections/base.js
Modified:
/trunk/AUTHORS
/trunk/BUILD.gn
/trunk/ChangeLog
/trunk/build/standalone.gypi
/trunk/include/v8.h
/trunk/src/api.cc
/trunk/src/arm/code-stubs-arm.cc
/trunk/src/arm/disasm-arm.cc
/trunk/src/arm/full-codegen-arm.cc
/trunk/src/arm64/code-stubs-arm64.cc
/trunk/src/arm64/disasm-arm64.cc
/trunk/src/arm64/full-codegen-arm64.cc
/trunk/src/array-iterator.js
/trunk/src/array.js
/trunk/src/ast.cc
/trunk/src/ast.h
/trunk/src/code-stubs.h
/trunk/src/compiler/arm/instruction-selector-arm.cc
/trunk/src/compiler/arm64/instruction-selector-arm64.cc
/trunk/src/compiler/ast-graph-builder.cc
/trunk/src/compiler/ia32/instruction-selector-ia32.cc
/trunk/src/compiler/mips/instruction-selector-mips.cc
/trunk/src/compiler/node-matchers.h
/trunk/src/compiler/pipeline.cc
/trunk/src/compiler/simplified-operator-reducer.cc
/trunk/src/compiler/simplified-operator-reducer.h
/trunk/src/compiler/x64/code-generator-x64.cc
/trunk/src/compiler/x64/instruction-selector-x64.cc
/trunk/src/compiler.cc
/trunk/src/cpu-profiler.cc
/trunk/src/debug.cc
/trunk/src/factory.cc
/trunk/src/factory.h
/trunk/src/harmony-string.js
/trunk/src/ia32/code-stubs-ia32.cc
/trunk/src/ia32/disasm-ia32.cc
/trunk/src/ia32/full-codegen-ia32.cc
/trunk/src/ia32/macro-assembler-ia32.cc
/trunk/src/ic/x87/ic-x87.cc
/trunk/src/isolate.h
/trunk/src/lookup.cc
/trunk/src/lookup.h
/trunk/src/mips/code-stubs-mips.cc
/trunk/src/mips/full-codegen-mips.cc
/trunk/src/mips64/code-stubs-mips64.cc
/trunk/src/mips64/full-codegen-mips64.cc
/trunk/src/objects.cc
/trunk/src/objects.h
/trunk/src/runtime/runtime-classes.cc
/trunk/src/sampler.cc
/trunk/src/sampler.h
/trunk/src/version.cc
/trunk/src/x64/assembler-x64-inl.h
/trunk/src/x64/assembler-x64.cc
/trunk/src/x64/assembler-x64.h
/trunk/src/x64/code-stubs-x64.cc
/trunk/src/x64/disasm-x64.cc
/trunk/src/x64/full-codegen-x64.cc
/trunk/src/x64/macro-assembler-x64.cc
/trunk/src/x64/macro-assembler-x64.h
/trunk/src/x87/code-stubs-x87.cc
/trunk/test/cctest/cctest.gyp
/trunk/test/cctest/cctest.status
/trunk/test/cctest/compiler/test-run-jsbranches.cc
/trunk/test/cctest/compiler/test-typer.cc
/trunk/test/cctest/test-api.cc
/trunk/test/cctest/test-disasm-x64.cc
/trunk/test/cctest/test-serialize.cc
/trunk/test/cctest/test-types.cc
/trunk/test/cctest/trace-extension.cc
/trunk/test/js-perf-test/Collections/run.js
/trunk/test/mjsunit/es6/arguments-iterator.js
/trunk/test/mjsunit/es6/array-iterator.js
/trunk/test/mjsunit/es6/typed-array-iterator.js
/trunk/test/mjsunit/harmony/string-repeat.js
/trunk/test/mjsunit/harmony/super.js
/trunk/test/mjsunit/harmony/typedarrays.js
/trunk/test/mjsunit/mjsunit.status
/trunk/test/mjsunit/tools/tickprocessor-test.default
/trunk/test/mjsunit/tools/tickprocessor-test.func-info
/trunk/test/mjsunit/tools/tickprocessor-test.gc-state
/trunk/test/mjsunit/tools/tickprocessor-test.ignore-unknown
/trunk/test/mjsunit/tools/tickprocessor-test.separate-ic
/trunk/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
/trunk/test/unittests/compiler/js-typed-lowering-unittest.cc
/trunk/test/unittests/compiler/simplified-operator-reducer-unittest.cc
/trunk/test/webkit/fast/js/Object-getOwnPropertyNames-expected.txt
/trunk/test/webkit/fast/js/Object-getOwnPropertyNames.js
/trunk/tools/codemap.js
/trunk/tools/gyp/v8.gyp
/trunk/tools/logreader.js
/trunk/tools/profile.js
/trunk/tools/tickprocessor.js
=======================================
--- /dev/null
+++ /trunk/src/compiler/control-reducer.cc Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,122 @@
+// 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.
+
+#include "src/compiler/common-operator.h"
+#include "src/compiler/control-reducer.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/node-matchers.h"
+#include "src/compiler/node-properties-inl.h"
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+enum VisitState { kUnvisited, kOnStack, kRevisit, kVisited };
+
+#define TRACE(x) \
+ if (FLAG_trace_turbo) PrintF x
+
+class ControlReducerImpl {
+ public:
+ ControlReducerImpl(JSGraph* jsgraph, CommonOperatorBuilder* common)
+ : zone_(jsgraph->zone()->isolate()),
+ jsgraph_(jsgraph),
+ common_(common),
+ state_(jsgraph->graph()->NodeCount(), kUnvisited, &zone_),
+ stack_(&zone_),
+ revisit_(&zone_),
+ dead_(NULL) {}
+
+ Zone zone_;
+ JSGraph* jsgraph_;
+ CommonOperatorBuilder* common_;
+ ZoneVector<VisitState> state_;
+ ZoneDeque<Node*> stack_;
+ ZoneDeque<Node*> revisit_;
+ Node* dead_;
+
+ void Trim() {
+ // Mark all nodes reachable from end.
+ NodeVector nodes(&zone_);
+ state_.assign(jsgraph_->graph()->NodeCount(), kUnvisited);
+ Push(jsgraph_->graph()->end());
+ while (!stack_.empty()) {
+ Node* node = stack_[stack_.size() - 1];
+ stack_.pop_back();
+ state_[node->id()] = kVisited;
+ nodes.push_back(node);
+ for (InputIter i = node->inputs().begin(); i != node->inputs().end();
+ ++i) {
+ Recurse(*i); // pushes node onto the stack if necessary.
+ }
+ }
+ // Process cached nodes in the JSGraph too.
+ jsgraph_->GetCachedNodes(&nodes);
+ // Remove dead->live edges.
+ for (size_t j = 0; j < nodes.size(); j++) {
+ Node* node = nodes[j];
+ for (UseIter i = node->uses().begin(); i != node->uses().end();) {
+ size_t id = static_cast<size_t>((*i)->id());
+ if (state_[id] != kVisited) {
+ TRACE(("DeadLink: #%d:%s(%d) -> #%d:%s\n", (*i)->id(),
+ (*i)->op()->mnemonic(), i.index(), node->id(),
+ node->op()->mnemonic()));
+ i.UpdateToAndIncrement(NULL);
+ } else {
+ ++i;
+ }
+ }
+ }
+#if DEBUG
+ // Verify that no inputs to live nodes are NULL.
+ for (size_t j = 0; j < nodes.size(); j++) {
+ Node* node = nodes[j];
+ for (InputIter i = node->inputs().begin(); i != node->inputs().end();
+ ++i) {
+ CHECK_NE(NULL, *i);
+ }
+ for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i)
{
+ size_t id = static_cast<size_t>((*i)->id());
+ CHECK_EQ(kVisited, state_[id]);
+ }
+ }
+#endif
+ }
+
+ // Push a node onto the stack if its state is {kUnvisited} or {kRevisit}.
+ bool Recurse(Node* node) {
+ size_t id = static_cast<size_t>(node->id());
+ if (id < state_.size()) {
+ if (state_[id] != kRevisit && state_[id] != kUnvisited) return false;
+ } else {
+ state_.resize((3 * id) / 2, kUnvisited);
+ }
+ Push(node);
+ return true;
+ }
+
+ void Push(Node* node) {
+ state_[node->id()] = kOnStack;
+ stack_.push_back(node);
+ }
+};
+
+void ControlReducer::ReduceGraph(JSGraph* jsgraph,
+ CommonOperatorBuilder* common) {
+ ControlReducerImpl impl(jsgraph, NULL);
+ // Only trim the graph for now. Control reduction can reduce
non-terminating
+ // loops to graphs that are unschedulable at the moment.
+ impl.Trim();
+}
+
+
+void ControlReducer::TrimGraph(JSGraph* jsgraph) {
+ ControlReducerImpl impl(jsgraph, NULL);
+ impl.Trim();
+}
+}
+}
+} // namespace v8::internal::compiler
=======================================
--- /dev/null
+++ /trunk/src/compiler/control-reducer.h Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,27 @@
+// 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.
+
+#ifndef V8_COMPILER_CONTROL_REDUCER_H_
+#define V8_COMPILER_CONTROL_REDUCER_H_
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class JSGraph;
+class CommonOperatorBuilder;
+
+class ControlReducer {
+ public:
+ // Perform branch folding and dead code elimination on the graph.
+ static void ReduceGraph(JSGraph* graph, CommonOperatorBuilder* builder);
+
+ // Trim nodes in the graph that are not reachable from end.
+ static void TrimGraph(JSGraph* graph);
+};
+}
+}
+} // namespace v8::internal::compiler
+
+#endif // V8_COMPILER_CONTROL_REDUCER_H_
=======================================
--- /dev/null
+++ /trunk/test/cctest/compiler/test-control-reducer.cc Fri Oct 17 20:38:26
2014 UTC
@@ -0,0 +1,242 @@
+// 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.
+
+#include "src/v8.h"
+#include "test/cctest/cctest.h"
+
+#include "src/compiler/common-operator.h"
+#include "src/compiler/control-reducer.h"
+#include "src/compiler/graph-inl.h"
+#include "src/compiler/js-graph.h"
+
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+
+class CTrimTester : HandleAndZoneScope {
+ public:
+ CTrimTester()
+ : isolate(main_isolate()),
+ common(main_zone()),
+ graph(main_zone()),
+ jsgraph(&graph, &common, NULL, NULL),
+ start(graph.NewNode(common.Start(1))),
+ p0(graph.NewNode(common.Parameter(0), start)),
+ one(jsgraph.OneConstant()),
+ half(jsgraph.Constant(0.5)) {
+ graph.SetEnd(start);
+ graph.SetStart(start);
+ }
+
+ Isolate* isolate;
+ CommonOperatorBuilder common;
+ Graph graph;
+ JSGraph jsgraph;
+ Node* start;
+ Node* p0;
+ Node* one;
+ Node* half;
+
+ void Trim() { ControlReducer::TrimGraph(&jsgraph); }
+};
+
+
+bool IsUsedBy(Node* a, Node* b) {
+ for (UseIter i = a->uses().begin(); i != a->uses().end(); ++i) {
+ if (b == *i) return true;
+ }
+ return false;
+}
+
+
+TEST(Trim1_live) {
+ CTrimTester T;
+ CHECK(IsUsedBy(T.start, T.p0));
+ T.graph.SetEnd(T.p0);
+ T.Trim();
+ CHECK(IsUsedBy(T.start, T.p0));
+ CHECK_EQ(T.start, T.p0->InputAt(0));
+}
+
+
+TEST(Trim1_dead) {
+ CTrimTester T;
+ CHECK(IsUsedBy(T.start, T.p0));
+ T.Trim();
+ CHECK(!IsUsedBy(T.start, T.p0));
+ CHECK_EQ(NULL, T.p0->InputAt(0));
+}
+
+
+TEST(Trim2_live) {
+ CTrimTester T;
+ Node* phi =
+ T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half,
T.start);
+ CHECK(IsUsedBy(T.one, phi));
+ CHECK(IsUsedBy(T.half, phi));
+ CHECK(IsUsedBy(T.start, phi));
+ T.graph.SetEnd(phi);
+ T.Trim();
+ CHECK(IsUsedBy(T.one, phi));
+ CHECK(IsUsedBy(T.half, phi));
+ CHECK(IsUsedBy(T.start, phi));
+ CHECK_EQ(T.one, phi->InputAt(0));
+ CHECK_EQ(T.half, phi->InputAt(1));
+ CHECK_EQ(T.start, phi->InputAt(2));
+}
+
+
+TEST(Trim2_dead) {
+ CTrimTester T;
+ Node* phi =
+ T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half,
T.start);
+ CHECK(IsUsedBy(T.one, phi));
+ CHECK(IsUsedBy(T.half, phi));
+ CHECK(IsUsedBy(T.start, phi));
+ T.Trim();
+ CHECK(!IsUsedBy(T.one, phi));
+ CHECK(!IsUsedBy(T.half, phi));
+ CHECK(!IsUsedBy(T.start, phi));
+ CHECK_EQ(NULL, phi->InputAt(0));
+ CHECK_EQ(NULL, phi->InputAt(1));
+ CHECK_EQ(NULL, phi->InputAt(2));
+}
+
+
+TEST(Trim_chain1) {
+ CTrimTester T;
+ const int kDepth = 15;
+ Node* live[kDepth];
+ Node* dead[kDepth];
+ Node* end = T.start;
+ for (int i = 0; i < kDepth; i++) {
+ live[i] = end = T.graph.NewNode(T.common.Merge(1), end);
+ dead[i] = T.graph.NewNode(T.common.Merge(1), end);
+ }
+ // end -> live[last] -> live[last-1] -> ... -> start
+ // dead[last] ^ dead[last-1] ^ ... ^
+ T.graph.SetEnd(end);
+ T.Trim();
+ for (int i = 0; i < kDepth; i++) {
+ CHECK(!IsUsedBy(live[i], dead[i]));
+ CHECK_EQ(NULL, dead[i]->InputAt(0));
+ CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0));
+ }
+}
+
+
+TEST(Trim_chain2) {
+ CTrimTester T;
+ const int kDepth = 15;
+ Node* live[kDepth];
+ Node* dead[kDepth];
+ Node* l = T.start;
+ Node* d = T.start;
+ for (int i = 0; i < kDepth; i++) {
+ live[i] = l = T.graph.NewNode(T.common.Merge(1), l);
+ dead[i] = d = T.graph.NewNode(T.common.Merge(1), d);
+ }
+ // end -> live[last] -> live[last-1] -> ... -> start
+ // dead[last] -> dead[last-1] -> ... -> start
+ T.graph.SetEnd(l);
+ T.Trim();
+ CHECK(!IsUsedBy(T.start, dead[0]));
+ for (int i = 0; i < kDepth; i++) {
+ CHECK_EQ(i == 0 ? NULL : dead[i - 1], dead[i]->InputAt(0));
+ CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0));
+ }
+}
+
+
+TEST(Trim_cycle1) {
+ CTrimTester T;
+ Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start);
+ loop->ReplaceInput(1, loop);
+ Node* end = T.graph.NewNode(T.common.End(), loop);
+ T.graph.SetEnd(end);
+
+ CHECK(IsUsedBy(T.start, loop));
+ CHECK(IsUsedBy(loop, end));
+ CHECK(IsUsedBy(loop, loop));
+
+ T.Trim();
+
+ // nothing should have happened to the loop itself.
+ CHECK(IsUsedBy(T.start, loop));
+ CHECK(IsUsedBy(loop, end));
+ CHECK(IsUsedBy(loop, loop));
+ CHECK_EQ(T.start, loop->InputAt(0));
+ CHECK_EQ(loop, loop->InputAt(1));
+ CHECK_EQ(loop, end->InputAt(0));
+}
+
+
+TEST(Trim_cycle2) {
+ CTrimTester T;
+ Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start);
+ loop->ReplaceInput(1, loop);
+ Node* end = T.graph.NewNode(T.common.End(), loop);
+ Node* phi =
+ T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half,
loop);
+ T.graph.SetEnd(end);
+
+ CHECK(IsUsedBy(T.start, loop));
+ CHECK(IsUsedBy(loop, end));
+ CHECK(IsUsedBy(loop, loop));
+ CHECK(IsUsedBy(loop, phi));
+ CHECK(IsUsedBy(T.one, phi));
+ CHECK(IsUsedBy(T.half, phi));
+
+ T.Trim();
+
+ // nothing should have happened to the loop itself.
+ CHECK(IsUsedBy(T.start, loop));
+ CHECK(IsUsedBy(loop, end));
+ CHECK(IsUsedBy(loop, loop));
+ CHECK_EQ(T.start, loop->InputAt(0));
+ CHECK_EQ(loop, loop->InputAt(1));
+ CHECK_EQ(loop, end->InputAt(0));
+
+ // phi should have been trimmed away.
+ CHECK(!IsUsedBy(loop, phi));
+ CHECK(!IsUsedBy(T.one, phi));
+ CHECK(!IsUsedBy(T.half, phi));
+ CHECK_EQ(NULL, phi->InputAt(0));
+ CHECK_EQ(NULL, phi->InputAt(1));
+ CHECK_EQ(NULL, phi->InputAt(2));
+}
+
+
+void CheckTrimConstant(CTrimTester* T, Node* k) {
+ Node* phi = T->graph.NewNode(T->common.Phi(kMachInt32, 1), k, T->start);
+ CHECK(IsUsedBy(k, phi));
+ T->Trim();
+ CHECK(!IsUsedBy(k, phi));
+ CHECK_EQ(NULL, phi->InputAt(0));
+ CHECK_EQ(NULL, phi->InputAt(1));
+}
+
+
+TEST(Trim_constants) {
+ CTrimTester T;
+ int32_t int32_constants[] = {
+ 0, -1, -2, 2, 2, 3, 3, 4, 4, 5, 5, 4, 5, 6, 6, 7, 8, 7,
8, 9,
+ 0, -11, -12, 12, 12, 13, 13, 14, 14, 15, 15, 14, 15, 6, 6, 7, 8, 7,
8, 9};
+
+ for (size_t i = 0; i < arraysize(int32_constants); i++) {
+ CheckTrimConstant(&T, T.jsgraph.Int32Constant(int32_constants[i]));
+ CheckTrimConstant(&T, T.jsgraph.Float64Constant(int32_constants[i]));
+ CheckTrimConstant(&T, T.jsgraph.Constant(int32_constants[i]));
+ }
+
+ Node* other_constants[] = {
+ T.jsgraph.UndefinedConstant(), T.jsgraph.TheHoleConstant(),
+ T.jsgraph.TrueConstant(), T.jsgraph.FalseConstant(),
+ T.jsgraph.NullConstant(), T.jsgraph.ZeroConstant(),
+ T.jsgraph.OneConstant(), T.jsgraph.NaNConstant(),
+ T.jsgraph.Constant(21), T.jsgraph.Constant(22.2)};
+
+ for (size_t i = 0; i < arraysize(other_constants); i++) {
+ CheckTrimConstant(&T, other_constants[i]);
+ }
+}
=======================================
--- /dev/null
+++ /trunk/test/cctest/types-fuzz.h Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,317 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_TEST_CCTEST_TYPES_H_
+#define V8_TEST_CCTEST_TYPES_H_
+
+#include "src/v8.h"
+
+namespace v8 {
+namespace internal {
+
+
+template<class Type, class TypeHandle, class Region>
+class Types {
+ public:
+ Types(Region* region, Isolate* isolate)
+ : region_(region), rng_(isolate->random_number_generator()) {
+ #define DECLARE_TYPE(name, value) \
+ name = Type::name(region); \
+ if (SmiValuesAre31Bits() || \
+ (!Type::name(region)->Equals(Type::OtherSigned32()) && \
+ !Type::name(region)->Equals(Type::OtherUnsigned31()))) { \
+ /* Hack: Avoid generating those empty bitset types. */ \
+ types.push_back(name); \
+ }
+ PROPER_BITSET_TYPE_LIST(DECLARE_TYPE)
+ #undef DECLARE_TYPE
+
+ object_map = isolate->factory()->NewMap(
+ JS_OBJECT_TYPE, JSObject::kHeaderSize);
+ array_map = isolate->factory()->NewMap(
+ JS_ARRAY_TYPE, JSArray::kSize);
+ number_map = isolate->factory()->NewMap(
+ HEAP_NUMBER_TYPE, HeapNumber::kSize);
+ uninitialized_map = isolate->factory()->uninitialized_map();
+ ObjectClass = Type::Class(object_map, region);
+ ArrayClass = Type::Class(array_map, region);
+ NumberClass = Type::Class(number_map, region);
+ UninitializedClass = Type::Class(uninitialized_map, region);
+
+ maps.push_back(object_map);
+ maps.push_back(array_map);
+ maps.push_back(uninitialized_map);
+ for (MapVector::iterator it = maps.begin(); it != maps.end(); ++it) {
+ types.push_back(Type::Class(*it, region));
+ }
+
+ smi = handle(Smi::FromInt(666), isolate);
+ signed32 = isolate->factory()->NewHeapNumber(0x40000000);
+ object1 = isolate->factory()->NewJSObjectFromMap(object_map);
+ object2 = isolate->factory()->NewJSObjectFromMap(object_map);
+ array = isolate->factory()->NewJSArray(20);
+ uninitialized = isolate->factory()->uninitialized_value();
+ SmiConstant = Type::Constant(smi, region);
+ Signed32Constant = Type::Constant(signed32, region);
+ ObjectConstant1 = Type::Constant(object1, region);
+ ObjectConstant2 = Type::Constant(object2, region);
+ ArrayConstant = Type::Constant(array, region);
+ UninitializedConstant = Type::Constant(uninitialized, region);
+
+ values.push_back(smi);
+ values.push_back(signed32);
+ values.push_back(object1);
+ values.push_back(object2);
+ values.push_back(array);
+ values.push_back(uninitialized);
+ for (ValueVector::iterator it = values.begin(); it != values.end();
++it) {
+ types.push_back(Type::Constant(*it, region));
+ }
+
+ integers.push_back(isolate->factory()->NewNumber(-V8_INFINITY));
+ integers.push_back(isolate->factory()->NewNumber(+V8_INFINITY));
+ integers.push_back(isolate->factory()->NewNumber(-rng_->NextInt(10)));
+ integers.push_back(isolate->factory()->NewNumber(+rng_->NextInt(10)));
+ for (int i = 0; i < 10; ++i) {
+ double x = rng_->NextInt();
+ integers.push_back(isolate->factory()->NewNumber(x));
+ x *= rng_->NextInt();
+ if (!IsMinusZero(x))
integers.push_back(isolate->factory()->NewNumber(x));
+ }
+
+ NumberArray = Type::Array(Number, region);
+ StringArray = Type::Array(String, region);
+ AnyArray = Type::Array(Any, region);
+
+ SignedFunction1 = Type::Function(SignedSmall, SignedSmall, region);
+ NumberFunction1 = Type::Function(Number, Number, region);
+ NumberFunction2 = Type::Function(Number, Number, Number, region);
+ MethodFunction = Type::Function(String, Object, 0, region);
+
+ for (int i = 0; i < 30; ++i) {
+ types.push_back(Fuzz());
+ }
+ }
+
+ Handle<i::Map> object_map;
+ Handle<i::Map> array_map;
+ Handle<i::Map> number_map;
+ Handle<i::Map> uninitialized_map;
+
+ Handle<i::Smi> smi;
+ Handle<i::HeapNumber> signed32;
+ Handle<i::JSObject> object1;
+ Handle<i::JSObject> object2;
+ Handle<i::JSArray> array;
+ Handle<i::Oddball> uninitialized;
+
+ #define DECLARE_TYPE(name, value) TypeHandle name;
+ BITSET_TYPE_LIST(DECLARE_TYPE)
+ #undef DECLARE_TYPE
+
+ TypeHandle ObjectClass;
+ TypeHandle ArrayClass;
+ TypeHandle NumberClass;
+ TypeHandle UninitializedClass;
+
+ TypeHandle SmiConstant;
+ TypeHandle Signed32Constant;
+ TypeHandle ObjectConstant1;
+ TypeHandle ObjectConstant2;
+ TypeHandle ArrayConstant;
+ TypeHandle UninitializedConstant;
+
+ TypeHandle NumberArray;
+ TypeHandle StringArray;
+ TypeHandle AnyArray;
+
+ TypeHandle SignedFunction1;
+ TypeHandle NumberFunction1;
+ TypeHandle NumberFunction2;
+ TypeHandle MethodFunction;
+
+ typedef std::vector<TypeHandle> TypeVector;
+ typedef std::vector<Handle<i::Map> > MapVector;
+ typedef std::vector<Handle<i::Object> > ValueVector;
+
+ TypeVector types;
+ MapVector maps;
+ ValueVector values;
+ ValueVector integers; // "Integer" values used for range limits.
+
+ TypeHandle Of(Handle<i::Object> value) {
+ return Type::Of(value, region_);
+ }
+
+ TypeHandle NowOf(Handle<i::Object> value) {
+ return Type::NowOf(value, region_);
+ }
+
+ TypeHandle Class(Handle<i::Map> map) {
+ return Type::Class(map, region_);
+ }
+
+ TypeHandle Constant(Handle<i::Object> value) {
+ return Type::Constant(value, region_);
+ }
+
+ TypeHandle Range(Handle<i::Object> min, Handle<i::Object> max) {
+ return Type::Range(min, max, region_);
+ }
+
+ TypeHandle Context(TypeHandle outer) {
+ return Type::Context(outer, region_);
+ }
+
+ TypeHandle Array1(TypeHandle element) {
+ return Type::Array(element, region_);
+ }
+
+ TypeHandle Function0(TypeHandle result, TypeHandle receiver) {
+ return Type::Function(result, receiver, 0, region_);
+ }
+
+ TypeHandle Function1(TypeHandle result, TypeHandle receiver, TypeHandle
arg) {
+ TypeHandle type = Type::Function(result, receiver, 1, region_);
+ type->AsFunction()->InitParameter(0, arg);
+ return type;
+ }
+
+ TypeHandle Function2(TypeHandle result, TypeHandle arg1, TypeHandle
arg2) {
+ return Type::Function(result, arg1, arg2, region_);
+ }
+
+ TypeHandle Union(TypeHandle t1, TypeHandle t2) {
+ return Type::Union(t1, t2, region_);
+ }
+ TypeHandle Intersect(TypeHandle t1, TypeHandle t2) {
+ return Type::Intersect(t1, t2, region_);
+ }
+
+ template<class Type2, class TypeHandle2>
+ TypeHandle Convert(TypeHandle2 t) {
+ return Type::template Convert<Type2>(t, region_);
+ }
+
+ TypeHandle Random() {
+ return types[rng_->NextInt(static_cast<int>(types.size()))];
+ }
+
+ TypeHandle Fuzz(int depth = 4) {
+ switch (rng_->NextInt(depth == 0 ? 3 : 20)) {
+ case 0: { // bitset
+ #define COUNT_BITSET_TYPES(type, value) + 1
+ int n = 0 PROPER_BITSET_TYPE_LIST(COUNT_BITSET_TYPES);
+ #undef COUNT_BITSET_TYPES
+ // Pick a bunch of named bitsets and return their intersection.
+ TypeHandle result = Type::Any(region_);
+ for (int i = 0, m = 1 + rng_->NextInt(3); i < m; ++i) {
+ int j = rng_->NextInt(n);
+ #define PICK_BITSET_TYPE(type, value) \
+ if (j-- == 0) { \
+ if (!SmiValuesAre31Bits() && \
+ (Type::type(region_)->Equals(Type::OtherSigned32()) || \
+ Type::type(region_)->Equals(Type::OtherUnsigned31())))
{ \
+ /* Hack: Avoid generating those empty bitset types. */ \
+ continue; \
+ } \
+ TypeHandle tmp = Type::Intersect( \
+ result, Type::type(region_), region_); \
+ if (tmp->Is(Type::None()) && i != 0) { \
+ break; \
+ } else { \
+ result = tmp; \
+ continue; \
+ } \
+ }
+ PROPER_BITSET_TYPE_LIST(PICK_BITSET_TYPE)
+ #undef PICK_BITSET_TYPE
+ }
+ return result;
+ }
+ case 1: { // class
+ int i = rng_->NextInt(static_cast<int>(maps.size()));
+ return Type::Class(maps[i], region_);
+ }
+ case 2: { // constant
+ int i = rng_->NextInt(static_cast<int>(values.size()));
+ return Type::Constant(values[i], region_);
+ }
+ case 3: { // range
+ int i = rng_->NextInt(static_cast<int>(integers.size()));
+ int j = rng_->NextInt(static_cast<int>(integers.size()));
+ i::Handle<i::Object> min = integers[i];
+ i::Handle<i::Object> max = integers[j];
+ if (min->Number() > max->Number()) std::swap(min, max);
+ return Type::Range(min, max, region_);
+ }
+ case 4: { // context
+ int depth = rng_->NextInt(3);
+ TypeHandle type = Type::Internal(region_);
+ for (int i = 0; i < depth; ++i) type = Type::Context(type,
region_);
+ return type;
+ }
+ case 5: { // array
+ TypeHandle element = Fuzz(depth / 2);
+ return Type::Array(element, region_);
+ }
+ case 6:
+ case 7: { // function
+ TypeHandle result = Fuzz(depth / 2);
+ TypeHandle receiver = Fuzz(depth / 2);
+ int arity = rng_->NextInt(3);
+ TypeHandle type = Type::Function(result, receiver, arity, region_);
+ for (int i = 0; i < type->AsFunction()->Arity(); ++i) {
+ TypeHandle parameter = Fuzz(depth / 2);
+ type->AsFunction()->InitParameter(i, parameter);
+ }
+ return type;
+ }
+ default: { // union
+ int n = rng_->NextInt(10);
+ TypeHandle type = None;
+ for (int i = 0; i < n; ++i) {
+ TypeHandle operand = Fuzz(depth - 1);
+ type = Type::Union(type, operand, region_);
+ }
+ return type;
+ }
+ }
+ UNREACHABLE();
+ }
+
+ Region* region() { return region_; }
+
+ private:
+ Region* region_;
+ v8::base::RandomNumberGenerator* rng_;
+};
+
+
+} } // namespace v8::internal
+
+#endif
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Classes/Classes.json Fri Oct 17 20:38:26 2014
UTC
@@ -0,0 +1,12 @@
+{
+ "path": ["."],
+ "main": "run.js",
+ "flags": ["--harmony-classes"],
+ "run_count": 5,
+ "units": "score",
+ "results_regexp": "^%s\\-Classes\\(Score\\): (.+)$",
+ "total": true,
+ "tests": [
+ {"name": "Super"}
+ ]
+}
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Classes/run.js Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,27 @@
+// 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('super.js');
+
+
+var success = true;
+
+function PrintResult(name, result) {
+ print(name + '-Classes(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/Classes/super.js Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,59 @@
+// 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.
+'use strict';
+
+var SuperBenchmark = new BenchmarkSuite('Super', [100], [
+ new Benchmark('SuperMethodCall', false, false, 0, SuperMethodCall),
+ new Benchmark('SuperGetterCall', false, false, 0, SuperGetterCall),
+ new Benchmark('SuperSetterCall', false, false, 0, SuperSetterCall),
+]);
+
+
+function Base() { }
+Base.prototype = {
+ constructor: Base,
+ get x() {
+ return this._x++;
+ },
+ set x(v) {
+ this._x += v;
+ return this._x;
+ }
+}
+
+Base.prototype.f = function() {
+ return this._x++;
+}.toMethod(Base.prototype);
+
+function Derived() {
+ this._x = 1;
+}
+Derived.prototype = Object.create(Base.prototype);
+Object.setPrototypeOf(Derived, Base);
+
+Derived.prototype.SuperCall = function() {
+ return super.f();
+}.toMethod(Derived.prototype);
+
+Derived.prototype.GetterCall = function() {
+ return super.x;
+}.toMethod(Derived.prototype);
+
+Derived.prototype.SetterCall = function() {
+ return super.x = 5;
+}.toMethod(Derived.prototype);
+
+var derived = new Derived();
+
+function SuperMethodCall() {
+ return derived.SuperCall();
+}
+
+function SuperGetterCall() {
+ return derived.GetterCall();
+}
+
+function SuperSetterCall() {
+ return derived.SetterCall();
+}
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Iterators/Iterators.json Fri Oct 17 20:38:26
2014 UTC
@@ -0,0 +1,11 @@
+{
+ "path": ["."],
+ "main": "run.js",
+ "run_count": 5,
+ "units": "score",
+ "results_regexp": "^%s\\-Iterators\\(Score\\): (.+)$",
+ "total": true,
+ "tests": [
+ {"name": "ForOf"}
+ ]
+}
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Iterators/forof.js Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,94 @@
+// 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.
+
+new BenchmarkSuite('ForOf', [1000], [
+ new Benchmark('ArrayValues', false, false, 0,
+ ForOf, ForOfArraySetup, ForOfTearDown),
+ new Benchmark('ArrayKeys', false, false, 0,
+ ForOf, ForOfArrayKeysSetup, ForOfTearDown),
+ new Benchmark('ArrayEntries', false, false, 0,
+ ForOf, ForOfArrayEntriesSetup, ForOfTearDown),
+ new Benchmark('Uint8Array', false, false, 0,
+ ForOf, ForOfUint8ArraySetup, ForOfTearDown),
+ new Benchmark('Float64Array', false, false, 0,
+ ForOf, ForOfFloat64ArraySetup, ForOfTearDown),
+ new Benchmark('String', false, false, 0,
+ ForOf, ForOfStringSetup, ForOfTearDown),
+]);
+
+
+var iterable;
+var N = 100;
+var expected, result;
+
+
+function ForOfArraySetupHelper(constructor) {
+ iterable = new constructor(N);
+ for (var i = 0; i < N; i++) iterable[i] = i;
+ expected = N - 1;
+}
+
+
+function ForOfArraySetup() {
+ ForOfArraySetupHelper(Array);
+ // Default iterator is values().
+}
+
+
+function ForOfArrayKeysSetup() {
+ ForOfArraySetupHelper(Array);
+ iterable = iterable.keys();
+}
+
+
+function ForOfArrayEntriesSetup() {
+ ForOfArraySetupHelper(Array);
+ iterable = iterable.entries();
+ expected = [N-1, N-1];
+}
+
+
+function ForOfUint8ArraySetup() {
+ ForOfArraySetupHelper(Uint8Array);
+}
+
+
+function ForOfFloat64ArraySetup() {
+ ForOfArraySetupHelper(Float64Array);
+}
+
+
+function ForOfStringSetup() {
+ iterable
= "abcdefhijklmnopqrstuvwxyzABCDEFHIJKLMNOPQRSTUVWXYZ0123456789";
+ expected = "9";
+}
+
+
+function Equals(expected, actual) {
+ if (expected === actual) return true;
+ if (typeof expected !== typeof actual) return false;
+ if (typeof expected !== 'object') return false;
+ for (var k of Object.keys(expected)) {
+ if (!(k in actual)) return false;
+ if (!Equals(expected[k], actual[k])) return false;
+ }
+ for (var k of Object.keys(actual)) {
+ if (!(k in expected)) return false;
+ }
+ return true;
+}
+
+function ForOfTearDown() {
+ iterable = null;
+ if (!Equals(expected, result)) {
+ throw new Error("Bad result: " + result);
+ }
+}
+
+
+function ForOf() {
+ for (var x of iterable) {
+ result = x;
+ }
+}
=======================================
--- /dev/null
+++ /trunk/test/js-perf-test/Iterators/run.js Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,27 @@
+// 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('forof.js');
+
+
+var success = true;
+
+function PrintResult(name, result) {
+ print(name + '-Iterators(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/base.js Fri Oct 17 20:38:26 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/mjsunit/asm/do-while-false.js Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,78 @@
+// 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 Module() {
+ "use asm";
+
+ function d0() {
+ do { } while(false);
+ return 110;
+ }
+
+ function d1() {
+ do { return 111; } while(false);
+ return 112;
+ }
+
+ function d2() {
+ do { break; } while(false);
+ return 113;
+ }
+
+ function d3(a) {
+ a = a | 0;
+ do { if (a) return 114; } while(false);
+ return 115;
+ }
+
+ function d4(a) {
+ a = a | 0;
+ do { if (a) return 116; else break; } while(false);
+ return 117;
+ }
+
+ function d5(a) {
+ a = a | 0;
+ do { if (a) return 118; } while(false);
+ return 119;
+ }
+
+ function d6(a) {
+ a = a | 0;
+ do {
+ if (a == 0) return 120;
+ if (a == 1) break;
+ if (a == 2) return 122;
+ if (a == 3) continue;
+ if (a == 4) return 124;
+ } while(false);
+ return 125;
+ }
+
+ return {d0: d0, d1: d1, d2: d2, d3: d3, d4: d4, d5: d5, d6: d6};
+}
+
+var m = Module();
+
+assertEquals(110, m.d0());
+
+assertEquals(111, m.d1());
+
+assertEquals(113, m.d2());
+
+assertEquals(114, m.d3(1));
+assertEquals(115, m.d3(0));
+
+assertEquals(116, m.d4(1));
+assertEquals(117, m.d4(0));
+
+assertEquals(118, m.d5(1));
+assertEquals(119, m.d5(0));
+
+assertEquals(120, m.d6(0));
+assertEquals(125, m.d6(1));
+assertEquals(122, m.d6(2));
+assertEquals(125, m.d6(3));
+assertEquals(124, m.d6(4));
+assertEquals(125, m.d6(5));
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/if-folding.js Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,100 @@
+// 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 Module() {
+ "use asm";
+
+ function if0() {
+ if (0) return 11;
+ return 12;
+ }
+
+ function if1() {
+ if (1) return 13;
+ return 14;
+ }
+
+ function if2() {
+ if (0) return 15;
+ else return 16;
+ }
+
+ function if3() {
+ if (1) return 17;
+ else return 18;
+ }
+
+ function if4() {
+ return 1 ? 19 : 20;
+ }
+
+ function if5() {
+ return 0 ? 21 : 22;
+ }
+
+ function if6() {
+ var x = 0 ? 23 : 24;
+ return x;
+ }
+
+ function if7() {
+ if (0) { var x = 0 ? 25 : 26; }
+ else { var x = 0 ? 27 : 28; }
+ return x;
+ }
+
+ function if8() {
+ if (0) {
+ if (0) { var x = 0 ? 29 : 30; }
+ else { var x = 0 ? 31 : 32; }
+ } else {
+ if (0) { var x = 0 ? 33 : 34; }
+ else { var x = 0 ? 35 : 36; }
+ }
+ return x;
+ }
+
+ return {if0: if0, if1: if1, if2: if2, if3: if3, if4: if4, if5: if5, if6:
if6, if7: if7, if8: if8 };
+}
+
+var m = Module();
+assertEquals(12, m.if0());
+assertEquals(13, m.if1());
+assertEquals(16, m.if2());
+assertEquals(17, m.if3());
+assertEquals(19, m.if4());
+assertEquals(22, m.if5());
+assertEquals(24, m.if6());
+assertEquals(28, m.if7());
+assertEquals(36, m.if8());
+
+
+function Spec(a,b,c) {
+ "use asm";
+
+ var xx = a | 0;
+ var yy = b | 0;
+ var zz = c | 0;
+
+ function f() {
+ if (xx) {
+ if (yy) { var x = zz ? 29 : 30; }
+ else { var x = zz ? 31 : 32; }
+ } else {
+ if (yy) { var x = zz ? 33 : 34; }
+ else { var x = zz ? 35 : 36; }
+ }
+ return x;
+ }
+ return {f: f};
+}
+
+assertEquals(36, Spec(0,0,0).f());
+assertEquals(35, Spec(0,0,1).f());
+assertEquals(34, Spec(0,1,0).f());
+assertEquals(33, Spec(0,1,1).f());
+assertEquals(32, Spec(1,0,0).f());
+assertEquals(31, Spec(1,0,1).f());
+assertEquals(30, Spec(1,1,0).f());
+assertEquals(29, Spec(1,1,1).f());
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/if-reduction.js Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,111 @@
+// 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 Module() {
+ "use asm";
+
+ function if0() {
+ var x = 0 ? 11 : 12;
+ return (x == 11) | 0;
+ }
+
+ function if1() {
+ var x = 1 ? 13 : 14;
+ return (x == 13) | 0;
+ }
+
+ function if2() {
+ var x = 0 ? 15 : 16;
+ return (x != 15) | 0;
+ }
+
+ function if3() {
+ var x = 1 ? 17 : 18;
+ return (x != 17) | 0;
+ }
+
+ function if4() {
+ var x = 0 ? 19 : 20;
+ var y = (x == 19) ? 21 : 22;
+ return y;
+ }
+
+ function if5() {
+ var x = 1 ? 23 : 24;
+ var y = (x == 23) ? 25 : 26;
+ return y;
+ }
+
+ function if6() {
+ var x = 0 ? 27 : 28;
+ var y = (x == 27) ? 29 : 30;
+ var z = (y == 29) ? 31 : 32;
+ return z;
+ }
+
+ function if7() {
+ var x = 1 ? 33 : 34;
+ var y = (x == 33) ? 35 : 36;
+ var z = (y == 35) ? 37 : 38;
+ var w = (z == 37) ? 39 : 40;
+ return w;
+ }
+
+ function if8() {
+ if (0) {
+ var x = 0 ? 43 : 44;
+ var y = (x == 43) ? 45 : 46;
+ var z = (y == 45) ? 47 : 48;
+ var w = (z == 47) ? 49 : 50;
+ } else {
+ var x = 1 ? 53 : 54;
+ var y = (x == 53) ? 55 : 56;
+ var z = (y == 55) ? 57 : 58;
+ var w = (z == 57) ? 59 : 60;
+ }
+ return w;
+ }
+
+ return {if0: if0, if1: if1, if2: if2, if3: if3, if4: if4, if5: if5, if6:
if6, if7: if7, if8: if8 };
+}
+
+var m = Module();
+assertEquals(0, m.if0());
+assertEquals(1, m.if1());
+assertEquals(1, m.if2());
+assertEquals(0, m.if3());
+assertEquals(22, m.if4());
+assertEquals(25, m.if5());
+assertEquals(32, m.if6());
+assertEquals(39, m.if7());
+assertEquals(59, m.if8());
+
+
+function Spec(a,b) {
+ "use asm";
+
+ var xx = a | 0;
+ var yy = b | 0;
+
+ function f() {
+ if (xx) {
+ var x = yy ? 43 : 44;
+ var y = (x == 43) ? 45 : 46;
+ var z = (y == 45) ? 47 : 48;
+ var w = (z == 47) ? 49 : 50;
+ } else {
+ var x = yy ? 53 : 54;
+ var y = (x == 53) ? 55 : 56;
+ var z = (y == 55) ? 57 : 58;
+ var w = (z == 57) ? 59 : 60;
+ }
+ return w;
+ }
+ return {f: f};
+}
+
+assertEquals(60, Spec(0,0).f());
+assertEquals(59, Spec(0,1).f());
+assertEquals(50, Spec(1,0).f());
+assertEquals(49, Spec(1,1).f());
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/infinite-loops-taken.js Fri Oct 17 20:38:26
2014 UTC
@@ -0,0 +1,41 @@
+// 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 error = "error";
+function counter(x) {
+ return (function() { if (x-- == 0) throw error;});
+}
+
+function Module() {
+ "use asm";
+
+ function w0(f) {
+ while (1) f();
+ return 108;
+ }
+
+ function w1(f) {
+ if (1) while (1) f();
+ return 109;
+ }
+
+ function w2(f) {
+ if (1) while (1) f();
+ else while (1) f();
+ return 110;
+ }
+
+ function w3(f) {
+ if (0) while (1) f();
+ return 111;
+ }
+
+ return { w0: w0, w1: w1, w2: w2, w3: w3 };
+}
+
+var m = Module();
+assertThrows(function() { m.w0(counter(5)) }, error);
+assertThrows(function() { m.w1(counter(5)) }, error);
+assertThrows(function() { m.w2(counter(5)) }, error);
+assertEquals(111, m.w3(counter(5)));
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/infinite-loops.js Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,53 @@
+// 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 Module() {
+ "use asm";
+
+ function w0(a) {
+ a = a | 0;
+ if (a) while (1);
+ return 42;
+ }
+
+ function w1(a) {
+ a = a | 0;
+ while (1) return 42;
+ return 106;
+ }
+
+ function d0(a) {
+ a = a | 0;
+ if (a) do ; while(1);
+ return 42;
+ }
+
+ function d1(a) {
+ a = a | 0;
+ do return 42; while(1);
+ return 107;
+ }
+
+ function f0(a) {
+ a = a | 0;
+ if (a) for (;;) ;
+ return 42;
+ }
+
+ function f1(a) {
+ a = a | 0;
+ for(;;) return 42;
+ return 108;
+ }
+
+ return { w0: w0, w1: w1, d0: d0, d1: d1, f0: f0, f1: f1 };
+}
+
+var m = Module();
+assertEquals(42, m.w0(0));
+assertEquals(42, m.w1(0));
+assertEquals(42, m.d0(0));
+assertEquals(42, m.d1(0));
+assertEquals(42, m.f0(0));
+assertEquals(42, m.f1(0));
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/int32array-constant-key.js Fri Oct 17 20:38:26
2014 UTC
@@ -0,0 +1,32 @@
+// 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 Module(stdlib, foreign, heap) {
+ "use asm";
+ var MEM32 = new stdlib.Int32Array(heap);
+ function load0() {
+ return MEM32[0];
+ }
+ function load4() {
+ return MEM32[4];
+ }
+ function store0(v) {
+ MEM32[0] = v;
+ }
+ function store4(v) {
+ MEM32[4] = v;
+ }
+ return { load0: load0, store0: store0, load4: load4, store4: store4 };
+}
+
+var m = Module(this, {}, new ArrayBuffer(4));
+
+assertEquals(0, m.load0());
+assertEquals(undefined, m.load4());
+m.store0(0x12345678);
+assertEquals(0x12345678, m.load0());
+assertEquals(undefined, m.load4());
+m.store4(43);
+assertEquals(0x12345678, m.load0());
+assertEquals(undefined, m.load4());
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/word32and.js Fri Oct 17 20:38:26 2014 UTC
@@ -0,0 +1,29 @@
+// 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 stdlib = {};
+var foreign = {};
+var heap = new ArrayBuffer(64 * 1024);
+
+function Word32And(rhs) {
+ var name = "and_0x" + Number(rhs).toString(16);
+ var m = eval("function Module(stdlib, foreign, heap) {\n"
+ + " \"use asm\";\n"
+ + " function " + name + "(lhs) {\n"
+ + " return (lhs | 0) & 0x" + Number(rhs).toString(16) + ";\n"
+ + " }\n"
+ + " return { f: " + name + "}\n"
+ + "}; Module");
+ return m(stdlib, foreign, heap).f;
+}
+
+var masks = [0xffffffff, 0xf0f0f0f0, 0x80ffffff, 0x07f77f0f, 0xdeadbeef,
+ 0x0fffff00, 0x0ff0, 0xff, 0x00];
+for (var i in masks) {
+ var rhs = masks[i];
+ var and = Word32And(rhs);
+ for (var lhs = -2147483648; lhs < 2147483648; lhs += 3999773) {
+ assertEquals(lhs & rhs, and(lhs));
+ }
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-419663.js Fri Oct 17 20:38:26 2014
UTC
@@ -0,0 +1,37 @@
+// Copyright 2012 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.
+
+// Flags: --expose-debug-as debug
+
+var o = {
+ f: function(x) {
+ var a = x + 1;
+ o = 1;
+ }
+}
+
+function sentinel() {}
+
+var Debug = debug.Debug;
+
+Debug.setListener(function() {});
+
+var script = Debug.findScript(sentinel);
+
+// Used in Debug.setScriptBreakPointById.
+var p = Debug.findScriptSourcePosition(script, 9, 0);
+var q = Debug.setBreakPointByScriptIdAndPosition(script.id,
p).actual_position;
+var r = Debug.setBreakPointByScriptIdAndPosition(script.id,
q).actual_position;
+
+assertEquals(q, r);
+
+function assertLocation(p, l, c) {
+ var location = script.locationFromPosition(p, false);
+ assertEquals(l, location.line);
+ assertEquals(c, location.column);
+}
+
+assertLocation(p, 9, 0);
+assertLocation(q, 9, 4);
+assertLocation(r, 9, 4);
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/unused-context-in-with.js Fri Oct 17 20:38:26 2014
UTC
@@ -0,0 +1,13 @@
+// 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 x = 1;
+function foo(object) {
+ with(object) {
+ x;
+ }
+ return 100;
+}
+
+assertEquals(100,foo("str"));
=======================================
--- /trunk/test/js-perf-test/Collections/base.js Fri Oct 10 00:05:16 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/AUTHORS Fri Oct 10 00:05:16 2014 UTC
+++ /trunk/AUTHORS Fri Oct 17 20:38:26 2014 UTC
@@ -39,6 +39,7 @@
Filipe David Manana <[email protected]>
Haitao Feng <[email protected]>
Ioseb Dzmanashvili <[email protected]>
+Isiah Meadows <[email protected]>
Jacob Bramley <[email protected]>
Jan de Mooij <[email protected]>
Jay Freeman <[email protected]>
=======================================
--- /trunk/BUILD.gn Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/BUILD.gn Fri Oct 17 20:38:26 2014 UTC
@@ -487,6 +487,8 @@
"src/compiler/common-operator.h",
"src/compiler/control-builders.cc",
"src/compiler/control-builders.h",
+ "src/compiler/control-reducer.cc",
+ "src/compiler/control-reducer.h",
"src/compiler/frame.h",
"src/compiler/gap-resolver.cc",
"src/compiler/gap-resolver.h",
=======================================
--- /trunk/ChangeLog Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/ChangeLog Fri Oct 17 20:38:26 2014 UTC
@@ -1,3 +1,15 @@
+2014-10-17: Version 3.30.13
+
+ Don't expose Array.prototype.values as it breaks webcompat
(Chromium
+ issue 409858).
+
+ Fix break location calculation (Chromium issue 419663).
+
+ Enable libstdc++ debug mode in debug builds (issue 3638).
+
+ Performance and stability improvements on all platforms.
+
+
2014-10-17: Version 3.30.12
Implement .forEach() on typed arrays (issue 3578).
=======================================
--- /trunk/build/standalone.gypi Thu Oct 9 00:05:16 2014 UTC
+++ /trunk/build/standalone.gypi Fri Oct 17 20:38:26 2014 UTC
@@ -136,6 +136,14 @@
'configurations': {
'DebugBaseCommon': {
'cflags': [ '-g', '-O0' ],
+ 'conditions': [
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"
or \
+ OS=="qnx"', {
+ 'defines': [
+ '_GLIBCXX_DEBUG'
+ ],
+ }],
+ ],
},
'Optdebug': {
'inherit_from': [ 'DebugBaseCommon', 'DebugBase2' ],
=======================================
--- /trunk/include/v8.h Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/include/v8.h Fri Oct 17 20:38:26 2014 UTC
@@ -5295,6 +5295,13 @@
*/
static void VisitHandlesWithClassIds(PersistentHandleVisitor* visitor);
+ /**
+ * Iterates through all the persistent handles in isolate's heap that
have
+ * class_ids.
+ */
+ static void VisitHandlesWithClassIds(
+ Isolate* isolate, PersistentHandleVisitor* visitor);
+
/**
* Iterates through all the persistent handles in the current isolate's
heap
* that have class_ids and are candidates to be marked as partially
dependent
=======================================
--- /trunk/src/api.cc Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/src/api.cc Fri Oct 17 20:38:26 2014 UTC
@@ -5113,6 +5113,16 @@
private:
PersistentHandleVisitor* visitor_;
};
+
+
+void v8::V8::VisitHandlesWithClassIds(v8::Isolate* exported_isolate,
+ PersistentHandleVisitor* visitor) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
+ i::DisallowHeapAllocation no_allocation;
+
+ VisitorAdapter visitor_adapter(visitor);
+ isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter);
+}
void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
@@ -6089,79 +6099,23 @@
return static_cast<size_t>(obj->length()->Number());
}
-
-static inline void SetupArrayBufferView(
- i::Isolate* isolate,
- i::Handle<i::JSArrayBufferView> obj,
- i::Handle<i::JSArrayBuffer> buffer,
- size_t byte_offset,
- size_t byte_length) {
- DCHECK(byte_offset + byte_length <=
- static_cast<size_t>(buffer->byte_length()->Number()));
-
- obj->set_buffer(*buffer);
-
- obj->set_weak_next(buffer->weak_first_view());
- buffer->set_weak_first_view(*obj);
-
- i::Handle<i::Object> byte_offset_object =
- isolate->factory()->NewNumberFromSize(byte_offset);
- obj->set_byte_offset(*byte_offset_object);
-
- i::Handle<i::Object> byte_length_object =
- isolate->factory()->NewNumberFromSize(byte_length);
- obj->set_byte_length(*byte_length_object);
-}
-
-template<typename ElementType,
- ExternalArrayType array_type,
- i::ElementsKind elements_kind>
-i::Handle<i::JSTypedArray> NewTypedArray(
- i::Isolate* isolate,
- Handle<ArrayBuffer> array_buffer, size_t byte_offset, size_t length) {
- i::Handle<i::JSTypedArray> obj =
- isolate->factory()->NewJSTypedArray(array_type);
- i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
-
- DCHECK(byte_offset % sizeof(ElementType) == 0);
-
- CHECK(length <= (std::numeric_limits<size_t>::max() /
sizeof(ElementType)));
- CHECK(length <= static_cast<size_t>(i::Smi::kMaxValue));
- size_t byte_length = length * sizeof(ElementType);
- SetupArrayBufferView(
- isolate, obj, buffer, byte_offset, byte_length);
-
- i::Handle<i::Object> length_object =
- isolate->factory()->NewNumberFromSize(length);
- obj->set_length(*length_object);
-
- i::Handle<i::ExternalArray> elements =
- isolate->factory()->NewExternalArray(
- static_cast<int>(length), array_type,
- static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
- i::Handle<i::Map> map =
- i::JSObject::GetElementsTransitionMap(obj, elements_kind);
- i::JSObject::SetMapAndElements(obj, map, elements);
- return obj;
-}
-
#define TYPED_ARRAY_NEW(Type, type, TYPE, ctype,
size) \
Local<Type##Array> Type##Array::New(Handle<ArrayBuffer>
array_buffer, \
- size_t byte_offset, size_t length)
{ \
+ size_t byte_offset, size_t length)
{ \
i::Isolate* isolate =
Utils::OpenHandle(*array_buffer)->GetIsolate(); \
LOG_API(isolate, \
- "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t,
size_t)"); \
+ "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t,
size_t)"); \
ENTER_V8(isolate); \
if (!Utils::ApiCheck(length <=
static_cast<size_t>(i::Smi::kMaxValue), \
- "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t,
size_t)", \
- "length exceeds max allowed value"))
{ \
- return
Local<Type##Array>(); \
+ "v8::"
#Type \
+ "Array::New(Handle<ArrayBuffer>, size_t,
size_t)", \
+ "length exceeds max allowed value"))
{ \
+ return
Local<Type##Array>(); \
} \
- i::Handle<i::JSTypedArray> obj
= \
- NewTypedArray<ctype,
v8::kExternal##Type##Array, \
-
i::EXTERNAL_##TYPE##_ELEMENTS>( \
- isolate, array_buffer, byte_offset,
length); \
+ i::Handle<i::JSArrayBuffer> buffer =
Utils::OpenHandle(*array_buffer); \
+ i::Handle<i::JSTypedArray> obj =
isolate->factory()->NewJSTypedArray( \
+ v8::kExternal##Type##Array, buffer, byte_offset,
length); \
return
Utils::ToLocal##Type##Array(obj); \
}
@@ -6175,9 +6129,8 @@
i::Isolate* isolate = buffer->GetIsolate();
LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)");
ENTER_V8(isolate);
- i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView();
- SetupArrayBufferView(
- isolate, obj, buffer, byte_offset, byte_length);
+ i::Handle<i::JSDataView> obj =
+ isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
return Utils::ToLocal(obj);
}
@@ -6704,8 +6657,8 @@
void Isolate::GetStackSample(const RegisterState& state, void** frames,
size_t frames_limit, SampleInfo* sample_info)
{
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
- i::TickSample::GetStackSample(isolate, state, frames, frames_limit,
- sample_info);
+ i::TickSample::GetStackSample(isolate, state,
i::TickSample::kSkipCEntryFrame,
+ frames, frames_limit, sample_info);
}
=======================================
--- /trunk/src/arm/code-stubs-arm.cc Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/src/arm/code-stubs-arm.cc Fri Oct 17 20:38:26 2014 UTC
@@ -3167,8 +3167,8 @@
// r2: length
// r3: from index (untagged)
__ SmiTag(r3, r3);
- StringCharAtGenerator generator(
- r0, r3, r2, r0, &runtime, &runtime, &runtime,
STRING_INDEX_IS_NUMBER);
+ StringCharAtGenerator generator(r0, r3, r2, r0, &runtime, &runtime,
&runtime,
+ STRING_INDEX_IS_NUMBER,
RECEIVER_IS_STRING);
generator.GenerateFast(masm);
__ Drop(3);
__ Ret();
=======================================
--- /trunk/src/arm/disasm-arm.cc Wed Oct 15 00:05:09 2014 UTC
+++ /trunk/src/arm/disasm-arm.cc Fri Oct 17 20:38:26 2014 UTC
@@ -148,7 +148,7 @@
// These condition names are defined in a way to match the native
disassembler
// formatting. See for example the command "objdump -d <binary file>".
-static const char* cond_names[kNumberOfConditions] = {
+static const char* const cond_names[kNumberOfConditions] = {
"eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
"hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
};
=======================================
--- /trunk/src/arm/full-codegen-arm.cc Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/src/arm/full-codegen-arm.cc Fri Oct 17 20:38:26 2014 UTC
@@ -3076,6 +3076,15 @@
EmitKeyedCallWithLoadIC(expr, property->key());
}
}
+ } else if (call_type == Call::SUPER_CALL) {
+ SuperReference* super_ref = callee->AsSuperReference();
+ DCHECK(super_ref != NULL);
+ __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ Push(r0);
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+ __ Push(result_register());
+ VisitForStackValue(super_ref->this_var());
+ EmitCall(expr, CallICState::METHOD);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
=======================================
--- /trunk/src/arm64/code-stubs-arm64.cc Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/src/arm64/code-stubs-arm64.cc Fri Oct 17 20:38:26 2014 UTC
@@ -3812,9 +3812,9 @@
// x12: input_type
// x15: from (untagged)
__ SmiTag(from);
- StringCharAtGenerator generator(
- input_string, from, result_length, x0,
- &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER);
+ StringCharAtGenerator generator(input_string, from, result_length, x0,
+ &runtime, &runtime, &runtime,
+ STRING_INDEX_IS_NUMBER,
RECEIVER_IS_STRING);
generator.GenerateFast(masm);
__ Drop(3);
__ Ret();
=======================================
--- /trunk/src/arm64/disasm-arm64.cc Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/arm64/disasm-arm64.cc Fri Oct 17 20:38:26 2014 UTC
@@ -1695,7 +1695,7 @@
DCHECK(format[0] == 'M');
USE(format);
- static const char* options[4][4] = {
+ static const char* const options[4][4] = {
{ "sy (0b0000)", "oshld", "oshst", "osh" },
{ "sy (0b0100)", "nshld", "nshst", "nsh" },
{ "sy (0b1000)", "ishld", "ishst", "ish" },
=======================================
--- /trunk/src/arm64/full-codegen-arm64.cc Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/src/arm64/full-codegen-arm64.cc Fri Oct 17 20:38:26 2014 UTC
@@ -2741,6 +2741,15 @@
EmitKeyedCallWithLoadIC(expr, property->key());
}
}
+ } else if (call_type == Call::SUPER_CALL) {
+ SuperReference* super_ref = callee->AsSuperReference();
+ DCHECK(super_ref != NULL);
+ __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ Push(x0);
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+ __ Push(result_register());
+ VisitForStackValue(super_ref->this_var());
+ EmitCall(expr, CallICState::METHOD);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
=======================================
--- /trunk/src/array-iterator.js Thu Aug 21 07:23:04 2014 UTC
+++ /trunk/src/array-iterator.js Fri Oct 17 20:38:26 2014 UTC
@@ -120,8 +120,8 @@
%CheckIsBootstrapping();
InstallFunctions($Array.prototype, DONT_ENUM, $Array(
+ // No 'values' since it breaks webcompat: http://crbug.com/409858
'entries', ArrayEntries,
- 'values', ArrayValues,
'keys', ArrayKeys
));
=======================================
--- /trunk/src/array.js Wed Oct 15 13:35:30 2014 UTC
+++ /trunk/src/array.js Fri Oct 17 20:38:26 2014 UTC
@@ -1499,7 +1499,6 @@
find: true,
findIndex: true,
keys: true,
- values: true,
};
%AddNamedProperty($Array.prototype, symbolUnscopables, unscopables,
DONT_ENUM | READ_ONLY);
=======================================
--- /trunk/src/ast.cc Wed Oct 15 13:35:30 2014 UTC
+++ /trunk/src/ast.cc Fri Oct 17 20:38:26 2014 UTC
@@ -580,6 +580,8 @@
return LOOKUP_SLOT_CALL;
}
}
+
+ if (expression()->AsSuperReference() != NULL) return SUPER_CALL;
Property* property = expression()->AsProperty();
return property != NULL ? PROPERTY_CALL : OTHER_CALL;
=======================================
--- /trunk/src/ast.h Wed Oct 15 13:35:30 2014 UTC
+++ /trunk/src/ast.h Fri Oct 17 20:38:26 2014 UTC
@@ -1851,6 +1851,7 @@
GLOBAL_CALL,
LOOKUP_SLOT_CALL,
PROPERTY_CALL,
+ SUPER_CALL,
OTHER_CALL
};
@@ -3474,16 +3475,7 @@
Call* NewCall(Expression* expression,
ZoneList<Expression*>* arguments,
int pos) {
- SuperReference* super_ref = expression->AsSuperReference();
- Call* call;
- if (super_ref != NULL) {
- Literal* constructor =
- NewStringLiteral(ast_value_factory_->constructor_string(), pos);
- Property* superConstructor = NewProperty(super_ref, constructor,
pos);
- call = new (zone_) Call(zone_, superConstructor, arguments, pos,
id_gen_);
- } else {
- call = new (zone_) Call(zone_, expression, arguments, pos, id_gen_);
- }
+ Call* call = new (zone_) Call(zone_, expression, arguments, pos,
id_gen_);
VISIT_AND_RETURN(Call, call)
}
=======================================
--- /trunk/src/code-stubs.h Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/src/code-stubs.h Fri Oct 17 20:38:26 2014 UTC
@@ -1803,7 +1803,7 @@
ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
: char_code_at_generator_(object, index, scratch,
receiver_not_string,
index_not_number, index_out_of_range,
- index_flags),
+ index_flags, check_mode),
char_from_code_generator_(scratch, result) {}
// Generates the fast case code. On the fallthrough path |result|
=======================================
--- /trunk/src/compiler/arm/instruction-selector-arm.cc Wed Oct 15 13:35:30
2014 UTC
+++ /trunk/src/compiler/arm/instruction-selector-arm.cc Fri Oct 17 20:38:26
2014 UTC
@@ -22,6 +22,14 @@
}
return UseRegister(node);
}
+
+ bool CanBeImmediate(int32_t value) const {
+ return Assembler::ImmediateFitsAddrMode1Instruction(value);
+ }
+
+ bool CanBeImmediate(uint32_t value) const {
+ return CanBeImmediate(bit_cast<int32_t>(value));
+ }
bool CanBeImmediate(Node* node, InstructionCode opcode) {
Int32Matcher m(node);
@@ -32,22 +40,20 @@
case kArmMov:
case kArmMvn:
case kArmBic:
- return ImmediateFitsAddrMode1Instruction(value) ||
- ImmediateFitsAddrMode1Instruction(~value);
+ return CanBeImmediate(value) || CanBeImmediate(~value);
case kArmAdd:
case kArmSub:
case kArmCmp:
case kArmCmn:
- return ImmediateFitsAddrMode1Instruction(value) ||
- ImmediateFitsAddrMode1Instruction(-value);
+ return CanBeImmediate(value) || CanBeImmediate(-value);
case kArmTst:
case kArmTeq:
case kArmOrr:
case kArmEor:
case kArmRsb:
- return ImmediateFitsAddrMode1Instruction(value);
+ return CanBeImmediate(value);
case kArmVldrF32:
case kArmVstrF32:
@@ -106,11 +112,6 @@
UNREACHABLE();
return false;
}
-
- private:
- bool ImmediateFitsAddrMode1Instruction(int32_t imm) const {
- return Assembler::ImmediateFitsAddrMode1Instruction(imm);
- }
};
@@ -417,7 +418,8 @@
}
}
if (IsSupported(ARMv7) && m.right().HasValue()) {
- uint32_t value = m.right().Value();
+ // Try to interpret this AND as UBFX.
+ uint32_t const value = m.right().Value();
uint32_t width = base::bits::CountPopulation32(value);
uint32_t msb = base::bits::CountLeadingZeros32(value);
if (width != 0 && msb + width == 32) {
@@ -435,6 +437,15 @@
g.TempImmediate(0), g.TempImmediate(width));
return;
}
+
+ // Try to interpret this AND as BIC.
+ if (g.CanBeImmediate(~value)) {
+ Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I),
+ g.DefineAsRegister(node), g.UseRegister(m.left().node()),
+ g.TempImmediate(~value));
+ return;
+ }
+
// Try to interpret this AND as BFC.
width = 32 - width;
msb = base::bits::CountLeadingZeros32(~value);
@@ -857,8 +868,10 @@
opcode |= MiscField::encode(descriptor->flags());
// Emit the call instruction.
+ InstructionOperand** first_output =
+ buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
Instruction* call_instr =
- Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(),
+ Emit(opcode, buffer.outputs.size(), first_output,
buffer.instruction_args.size(),
&buffer.instruction_args.front());
call_instr->MarkAsCall();
}
=======================================
--- /trunk/src/compiler/arm64/instruction-selector-arm64.cc Wed Oct 15
13:35:30 2014 UTC
+++ /trunk/src/compiler/arm64/instruction-selector-arm64.cc Fri Oct 17
20:38:26 2014 UTC
@@ -954,8 +954,10 @@
opcode |= MiscField::encode(descriptor->flags());
// Emit the call instruction.
+ InstructionOperand** first_output =
+ buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
Instruction* call_instr =
- Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(),
+ Emit(opcode, buffer.outputs.size(), first_output,
buffer.instruction_args.size(),
&buffer.instruction_args.front());
call_instr->MarkAsCall();
}
=======================================
--- /trunk/src/compiler/ast-graph-builder.cc Mon Oct 13 00:05:20 2014 UTC
+++ /trunk/src/compiler/ast-graph-builder.cc Fri Oct 17 20:38:26 2014 UTC
@@ -1261,6 +1261,11 @@
flags = CALL_AS_METHOD;
break;
}
+ case Call::SUPER_CALL: {
+ // todo(dslomov): implement super calls in turbofan.
+ UNIMPLEMENTED();
+ break;
+ }
case Call::POSSIBLY_EVAL_CALL:
possibly_eval = true;
// Fall through.
=======================================
--- /trunk/src/compiler/ia32/instruction-selector-ia32.cc Wed Oct 15
13:35:30 2014 UTC
+++ /trunk/src/compiler/ia32/instruction-selector-ia32.cc Fri Oct 17
20:38:26 2014 UTC
@@ -638,8 +638,10 @@
opcode |= MiscField::encode(descriptor->flags());
// Emit the call instruction.
+ InstructionOperand** first_output =
+ buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
Instruction* call_instr =
- Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(),
+ Emit(opcode, buffer.outputs.size(), first_output,
buffer.instruction_args.size(),
&buffer.instruction_args.front());
call_instr->MarkAsCall();
}
=======================================
--- /trunk/src/compiler/mips/instruction-selector-mips.cc Wed Oct 15
13:35:30 2014 UTC
+++ /trunk/src/compiler/mips/instruction-selector-mips.cc Fri Oct 17
20:38:26 2014 UTC
@@ -451,8 +451,10 @@
opcode |= MiscField::encode(descriptor->flags());
// Emit the call instruction.
+ InstructionOperand** first_output =
+ buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
Instruction* call_instr =
- Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(),
+ Emit(opcode, buffer.outputs.size(), first_output,
buffer.instruction_args.size(),
&buffer.instruction_args.front());
call_instr->MarkAsCall();
}
=======================================
--- /trunk/src/compiler/node-matchers.h Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/compiler/node-matchers.h Fri Oct 17 20:38:26 2014 UTC
@@ -96,6 +96,42 @@
typedef FloatMatcher<double, IrOpcode::kNumberConstant> NumberMatcher;
+// A pattern matcher for any numberic constant.
+struct NumericValueMatcher : public NodeMatcher {
+ explicit NumericValueMatcher(Node* const node) : NodeMatcher(node) {
+ switch (opcode()) {
+ case IrOpcode::kInt32Constant:
+ has_value_ = true;
+ value_ = OpParameter<int32_t>(node);
+ break;
+ case IrOpcode::kFloat32Constant:
+ has_value_ = true;
+ value_ = OpParameter<float>(node);
+ break;
+ case IrOpcode::kFloat64Constant:
+ case IrOpcode::kNumberConstant:
+ has_value_ = true;
+ value_ = OpParameter<double>(node);
+ break;
+ default:
+ has_value_ = false;
+ value_ = 0; // Make the compiler happy.
+ break;
+ }
+ }
+
+ bool HasValue() const { return has_value_; }
+ double Value() const {
+ DCHECK(HasValue());
+ return value_;
+ }
+
+ private:
+ double value_;
+ bool has_value_;
+};
+
+
// A pattern matcher for heap object constants.
template <typename T>
struct HeapObjectMatcher FINAL
=======================================
--- /trunk/src/compiler/pipeline.cc Fri Oct 17 11:41:30 2014 UTC
+++ /trunk/src/compiler/pipeline.cc Fri Oct 17 20:38:26 2014 UTC
@@ -11,6 +11,7 @@
#include "src/compiler/basic-block-instrumentor.h"
#include "src/compiler/change-lowering.h"
#include "src/compiler/code-generator.h"
+#include "src/compiler/control-reducer.h"
#include "src/compiler/graph-replay.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/instruction.h"
@@ -301,9 +302,13 @@
"typed lowering");
SourcePositionTable::Scope pos(&source_positions,
SourcePosition::Unknown());
+ ValueNumberingReducer vn_reducer(zone());
JSTypedLowering lowering(&jsgraph);
+ SimplifiedOperatorReducer simple_reducer(&jsgraph);
GraphReducer graph_reducer(&graph);
+ graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&lowering);
+ graph_reducer.AddReducer(&simple_reducer);
graph_reducer.ReduceGraph();
VerifyAndPrintGraph(&graph, "Lowered typed");
@@ -347,6 +352,16 @@
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
VerifyAndPrintGraph(&graph, "Lowered changes", true);
}
+
+ {
+ SourcePositionTable::Scope pos(&source_positions,
+ SourcePosition::Unknown());
+ PhaseStats control_reducer_stats(info(), PhaseStats::CREATE_GRAPH,
+ "control reduction");
+ ControlReducer::ReduceGraph(&jsgraph, &common);
+
+ VerifyAndPrintGraph(&graph, "Control reduced");
+ }
}
{
=======================================
--- /trunk/src/compiler/simplified-operator-reducer.cc Wed Sep 17 00:05:08
2014 UTC
+++ /trunk/src/compiler/simplified-operator-reducer.cc Fri Oct 17 20:38:26
2014 UTC
@@ -12,6 +12,10 @@
namespace internal {
namespace compiler {
+SimplifiedOperatorReducer::SimplifiedOperatorReducer(JSGraph* jsgraph)
+ : jsgraph_(jsgraph), simplified_(jsgraph->zone()) {}
+
+
SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
@@ -95,6 +99,38 @@
if (m.HasValue()) return ReplaceNumber(FastUI2D(m.Value()));
break;
}
+ case IrOpcode::kLoadElement: {
+ ElementAccess access = ElementAccessOf(node->op());
+ if (access.bounds_check == kTypedArrayBoundsCheck) {
+ NumericValueMatcher mkey(node->InputAt(1));
+ NumericValueMatcher mlength(node->InputAt(2));
+ if (mkey.HasValue() && mlength.HasValue()) {
+ // Skip the typed array bounds check if key and length are
constant.
+ if (mkey.Value() < mlength.Value()) {
+ access.bounds_check = kNoBoundsCheck;
+ node->set_op(simplified()->LoadElement(access));
+ return Changed(node);
+ }
+ }
+ }
+ break;
+ }
+ case IrOpcode::kStoreElement: {
+ ElementAccess access = ElementAccessOf(node->op());
+ if (access.bounds_check == kTypedArrayBoundsCheck) {
+ NumericValueMatcher mkey(node->InputAt(1));
+ NumericValueMatcher mlength(node->InputAt(2));
+ if (mkey.HasValue() && mlength.HasValue()) {
+ // Skip the typed array bounds check if key and length are
constant.
+ if (mkey.Value() < mlength.Value()) {
+ access.bounds_check = kNoBoundsCheck;
+ node->set_op(simplified()->StoreElement(access));
+ return Changed(node);
+ }
+ }
+ }
+ break;
+ }
default:
break;
}
=======================================
--- /trunk/src/compiler/simplified-operator-reducer.h Wed Sep 17 00:05:08
2014 UTC
+++ /trunk/src/compiler/simplified-operator-reducer.h Fri Oct 17 20:38:26
2014 UTC
@@ -6,6 +6,7 @@
#define V8_COMPILER_SIMPLIFIED_OPERATOR_REDUCER_H_
#include "src/compiler/graph-reducer.h"
+#include "src/compiler/simplified-operator.h"
namespace v8 {
namespace internal {
@@ -21,7 +22,7 @@
class SimplifiedOperatorReducer FINAL : public Reducer {
public:
- explicit SimplifiedOperatorReducer(JSGraph* jsgraph) : jsgraph_(jsgraph)
{}
+ explicit SimplifiedOperatorReducer(JSGraph* jsgraph);
virtual ~SimplifiedOperatorReducer();
virtual Reduction Reduce(Node* node) OVERRIDE;
@@ -40,8 +41,10 @@
Factory* factory() const;
JSGraph* jsgraph() const { return jsgraph_; }
MachineOperatorBuilder* machine() const;
+ SimplifiedOperatorBuilder* simplified() { return &simplified_; }
JSGraph* jsgraph_;
+ SimplifiedOperatorBuilder simplified_;
DISALLOW_COPY_AND_ASSIGN(SimplifiedOperatorReducer);
};
=======================================
--- /trunk/src/compiler/x64/code-generator-x64.cc Fri Oct 17 11:41:30 2014
UTC
+++ /trunk/src/compiler/x64/code-generator-x64.cc Fri Oct 17 20:38:26 2014
UTC
@@ -896,22 +896,22 @@
}
} else if (src.type() == Constant::kFloat32) {
// TODO(turbofan): Can we do better here?
- __ movl(kScratchRegister,
Immediate(bit_cast<int32_t>(src.ToFloat32())));
+ uint32_t src_const = bit_cast<uint32_t>(src.ToFloat32());
if (destination->IsDoubleRegister()) {
- XMMRegister dst = g.ToDoubleRegister(destination);
- __ movq(dst, kScratchRegister);
+ __ Move(g.ToDoubleRegister(destination), src_const);
} else {
DCHECK(destination->IsDoubleStackSlot());
Operand dst = g.ToOperand(destination);
- __ movl(dst, kScratchRegister);
+ __ movl(dst, Immediate(src_const));
}
} else {
DCHECK_EQ(Constant::kFloat64, src.type());
- __ movq(kScratchRegister, bit_cast<int64_t>(src.ToFloat64()));
+ uint64_t src_const = bit_cast<uint64_t>(src.ToFloat64());
if (destination->IsDoubleRegister()) {
- __ movq(g.ToDoubleRegister(destination), kScratchRegister);
+ __ Move(g.ToDoubleRegister(destination), src_const);
} else {
DCHECK(destination->IsDoubleStackSlot());
+ __ movq(kScratchRegister, src_const);
__ movq(g.ToOperand(destination), kScratchRegister);
}
}
=======================================
***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.