Revision: 23094
Author: [email protected]
Date: Wed Aug 13 00:04:54 2014 UTC
Log: Version 3.28.73 (based on bleeding_edge revision r23084)
Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=23094
Added:
/trunk/src/compiler/change-lowering.cc
/trunk/src/compiler/change-lowering.h
/trunk/test/compiler-unittests/change-lowering-unittest.cc
/trunk/test/compiler-unittests/node-matchers.cc
/trunk/test/compiler-unittests/node-matchers.h
/trunk/test/mjsunit/own-symbols.js
/trunk/test/mjsunit/runtime-gen/createprivateownsymbol.js
/trunk/testing/gtest-type-names.h
Modified:
/trunk/ChangeLog
/trunk/src/api.cc
/trunk/src/arm/assembler-arm.h
/trunk/src/arm/lithium-arm.h
/trunk/src/arm64/assembler-arm64.h
/trunk/src/arm64/instrument-arm64.h
/trunk/src/arm64/lithium-arm64.h
/trunk/src/arm64/macro-assembler-arm64.h
/trunk/src/base/platform/platform.h
/trunk/src/bootstrapper.cc
/trunk/src/code-stubs.h
/trunk/src/compiler/node-properties-inl.h
/trunk/src/compiler/node-properties.h
/trunk/src/compiler/pipeline.cc
/trunk/src/compiler/representation-change.h
/trunk/src/effects.h
/trunk/src/factory.cc
/trunk/src/factory.h
/trunk/src/globals.h
/trunk/src/heap/heap.cc
/trunk/src/hydrogen-instructions.h
/trunk/src/hydrogen.cc
/trunk/src/ia32/lithium-ia32.h
/trunk/src/interpreter-irregexp.cc
/trunk/src/libplatform/worker-thread.cc
/trunk/src/log.cc
/trunk/src/lookup.h
/trunk/src/macro-assembler.h
/trunk/src/math.js
/trunk/src/mips/lithium-mips.h
/trunk/src/mips64/lithium-mips64.h
/trunk/src/objects-inl.h
/trunk/src/objects-printer.cc
/trunk/src/objects.cc
/trunk/src/objects.h
/trunk/src/optimizing-compiler-thread.h
/trunk/src/runtime.cc
/trunk/src/runtime.h
/trunk/src/splay-tree.h
/trunk/src/unique.h
/trunk/src/version.cc
/trunk/src/x64/lithium-x64.h
/trunk/src/x87/lithium-x87.h
/trunk/test/base-unittests/platform/condition-variable-unittest.cc
/trunk/test/base-unittests/platform/platform-unittest.cc
/trunk/test/benchmarks/benchmarks.status
/trunk/test/cctest/cctest.h
/trunk/test/cctest/compiler/graph-builder-tester.cc
/trunk/test/cctest/compiler/test-instruction.cc
/trunk/test/cctest/compiler/test-representation-change.cc
/trunk/test/cctest/compiler/test-simplified-lowering.cc
/trunk/test/cctest/test-api.cc
/trunk/test/cctest/test-circular-queue.cc
/trunk/test/cctest/test-debug.cc
/trunk/test/cctest/test-declarative-accessors.cc
/trunk/test/cctest/test-libplatform.h
/trunk/test/cctest/test-lockers.cc
/trunk/test/cctest/test-semaphore.cc
/trunk/test/cctest/test-thread-termination.cc
/trunk/test/cctest/test-threads.cc
/trunk/test/compiler-unittests/DEPS
/trunk/test/compiler-unittests/arm/instruction-selector-arm-unittest.cc
/trunk/test/compiler-unittests/compiler-unittests.gyp
/trunk/test/compiler-unittests/compiler-unittests.h
/trunk/test/compiler-unittests/instruction-selector-unittest.cc
/trunk/test/mjsunit/es6/math-log1p.js
/trunk/test/mjsunit/mjsunit.status
/trunk/testing/gtest.gyp
/trunk/third_party/fdlibm/fdlibm.cc
/trunk/third_party/fdlibm/fdlibm.h
/trunk/third_party/fdlibm/fdlibm.js
/trunk/tools/generate-runtime-tests.py
/trunk/tools/gyp/v8.gyp
/trunk/tools/whitespace.txt
=======================================
--- /dev/null
+++ /trunk/src/compiler/change-lowering.cc Wed Aug 13 00:04:54 2014 UTC
@@ -0,0 +1,260 @@
+// 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/change-lowering.h"
+
+#include "src/compiler/common-node-cache.h"
+#include "src/compiler/graph.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+ChangeLoweringBase::ChangeLoweringBase(Graph* graph, Linkage* linkage,
+ CommonNodeCache* cache)
+ : graph_(graph),
+ isolate_(graph->zone()->isolate()),
+ linkage_(linkage),
+ cache_(cache),
+ common_(graph->zone()),
+ machine_(graph->zone()) {}
+
+
+ChangeLoweringBase::~ChangeLoweringBase() {}
+
+
+Node* ChangeLoweringBase::ExternalConstant(ExternalReference reference) {
+ Node** loc = cache()->FindExternalConstant(reference);
+ if (*loc == NULL) {
+ *loc = graph()->NewNode(common()->ExternalConstant(reference));
+ }
+ return *loc;
+}
+
+
+Node* ChangeLoweringBase::HeapConstant(PrintableUnique<HeapObject> value) {
+ // TODO(bmeurer): Use common node cache.
+ return graph()->NewNode(common()->HeapConstant(value));
+}
+
+
+Node* ChangeLoweringBase::ImmovableHeapConstant(Handle<HeapObject> value) {
+ return HeapConstant(
+ PrintableUnique<HeapObject>::CreateImmovable(graph()->zone(),
value));
+}
+
+
+Node* ChangeLoweringBase::Int32Constant(int32_t value) {
+ Node** loc = cache()->FindInt32Constant(value);
+ if (*loc == NULL) {
+ *loc = graph()->NewNode(common()->Int32Constant(value));
+ }
+ return *loc;
+}
+
+
+Node* ChangeLoweringBase::NumberConstant(double value) {
+ Node** loc = cache()->FindNumberConstant(value);
+ if (*loc == NULL) {
+ *loc = graph()->NewNode(common()->NumberConstant(value));
+ }
+ return *loc;
+}
+
+
+Node* ChangeLoweringBase::CEntryStubConstant() {
+ if (!c_entry_stub_constant_.is_set()) {
+ c_entry_stub_constant_.set(
+ ImmovableHeapConstant(CEntryStub(isolate(), 1).GetCode()));
+ }
+ return c_entry_stub_constant_.get();
+}
+
+
+Node* ChangeLoweringBase::TrueConstant() {
+ if (!true_constant_.is_set()) {
+ true_constant_.set(
+ ImmovableHeapConstant(isolate()->factory()->true_value()));
+ }
+ return true_constant_.get();
+}
+
+
+Node* ChangeLoweringBase::FalseConstant() {
+ if (!false_constant_.is_set()) {
+ false_constant_.set(
+ ImmovableHeapConstant(isolate()->factory()->false_value()));
+ }
+ return false_constant_.get();
+}
+
+
+Reduction ChangeLoweringBase::ChangeBitToBool(Node* val, Node* control) {
+ Node* branch = graph()->NewNode(common()->Branch(), val, control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* true_value = TrueConstant();
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* false_value = FalseConstant();
+
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ Node* phi =
+ graph()->NewNode(common()->Phi(2), true_value, false_value, merge);
+
+ return Replace(phi);
+}
+
+
+template <size_t kPointerSize>
+ChangeLowering<kPointerSize>::ChangeLowering(Graph* graph, Linkage*
linkage)
+ : ChangeLoweringBase(graph, linkage,
+ new (graph->zone())
CommonNodeCache(graph->zone())) {}
+
+
+template <size_t kPointerSize>
+Reduction ChangeLowering<kPointerSize>::Reduce(Node* node) {
+ Node* control = graph()->start();
+ Node* effect = control;
+ switch (node->opcode()) {
+ case IrOpcode::kChangeBitToBool:
+ return ChangeBitToBool(node->InputAt(0), control);
+ case IrOpcode::kChangeBoolToBit:
+ return ChangeBoolToBit(node->InputAt(0));
+ case IrOpcode::kChangeInt32ToTagged:
+ return ChangeInt32ToTagged(node->InputAt(0), effect, control);
+ case IrOpcode::kChangeTaggedToFloat64:
+ return ChangeTaggedToFloat64(node->InputAt(0), effect, control);
+ default:
+ return NoChange();
+ }
+ UNREACHABLE();
+ return NoChange();
+}
+
+
+template <>
+Reduction ChangeLowering<4>::ChangeBoolToBit(Node* val) {
+ return Replace(
+ graph()->NewNode(machine()->Word32Equal(), val, TrueConstant()));
+}
+
+
+template <>
+Reduction ChangeLowering<8>::ChangeBoolToBit(Node* val) {
+ return Replace(
+ graph()->NewNode(machine()->Word64Equal(), val, TrueConstant()));
+}
+
+
+template <>
+Reduction ChangeLowering<4>::ChangeInt32ToTagged(Node* val, Node* effect,
+ Node* control) {
+ Node* context = NumberConstant(0);
+
+ Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), val,
val);
+ Node* ovf = graph()->NewNode(common()->Projection(1), add);
+
+ Node* branch = graph()->NewNode(common()->Branch(), ovf, control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* number = graph()->NewNode(machine()->ChangeInt32ToFloat64(), val);
+
+ // TODO(bmeurer): Inline allocation if possible.
+ const Runtime::Function* fn =
+ Runtime::FunctionForId(Runtime::kAllocateHeapNumber);
+ DCHECK_EQ(0, fn->nargs);
+ CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor(
+ fn->function_id, 0, Operator::kNoProperties);
+ Node* heap_number =
+ graph()->NewNode(common()->Call(desc), CEntryStubConstant(),
+ ExternalConstant(ExternalReference(fn, isolate())),
+ Int32Constant(0), context, effect, if_true);
+
+ Node* store = graph()->NewNode(
+ machine()->Store(kMachineFloat64, kNoWriteBarrier), heap_number,
+ Int32Constant(HeapNumber::kValueOffset - kHeapObjectTag), number,
effect,
+ heap_number);
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* smi = graph()->NewNode(common()->Projection(0), add);
+
+ Node* merge = graph()->NewNode(common()->Merge(2), store, if_false);
+ Node* phi = graph()->NewNode(common()->Phi(2), heap_number, smi, merge);
+
+ return Replace(phi);
+}
+
+
+template <>
+Reduction ChangeLowering<8>::ChangeInt32ToTagged(Node* val, Node* effect,
+ Node* control) {
+ return Replace(graph()->NewNode(
+ machine()->Word64Shl(), val,
+ Int32Constant(SmiTagging<8>::kSmiShiftSize + kSmiTagSize)));
+}
+
+
+template <>
+Reduction ChangeLowering<4>::ChangeTaggedToFloat64(Node* val, Node* effect,
+ Node* control) {
+ Node* branch = graph()->NewNode(
+ common()->Branch(),
+ graph()->NewNode(machine()->Word32And(), val,
Int32Constant(kSmiTagMask)),
+ control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* load = graph()->NewNode(
+ machine()->Load(kMachineFloat64), val,
+ Int32Constant(HeapNumber::kValueOffset - kHeapObjectTag), if_true);
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* number = graph()->NewNode(
+ machine()->ChangeInt32ToFloat64(),
+ graph()->NewNode(
+ machine()->Word32Sar(), val,
+ Int32Constant(SmiTagging<4>::kSmiShiftSize + kSmiTagSize)));
+
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ Node* phi = graph()->NewNode(common()->Phi(2), load, number, merge);
+
+ return Replace(phi);
+}
+
+
+template <>
+Reduction ChangeLowering<8>::ChangeTaggedToFloat64(Node* val, Node* effect,
+ Node* control) {
+ Node* branch = graph()->NewNode(
+ common()->Branch(),
+ graph()->NewNode(machine()->Word64And(), val,
Int32Constant(kSmiTagMask)),
+ control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* load = graph()->NewNode(
+ machine()->Load(kMachineFloat64), val,
+ Int32Constant(HeapNumber::kValueOffset - kHeapObjectTag), if_true);
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* number = graph()->NewNode(
+ machine()->ChangeInt32ToFloat64(),
+ graph()->NewNode(
+ machine()->ConvertInt64ToInt32(),
+ graph()->NewNode(
+ machine()->Word64Sar(), val,
+ Int32Constant(SmiTagging<8>::kSmiShiftSize + kSmiTagSize))));
+
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ Node* phi = graph()->NewNode(common()->Phi(2), load, number, merge);
+
+ return Replace(phi);
+}
+
+
+template class ChangeLowering<4>;
+template class ChangeLowering<8>;
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
=======================================
--- /dev/null
+++ /trunk/src/compiler/change-lowering.h Wed Aug 13 00:04:54 2014 UTC
@@ -0,0 +1,79 @@
+// 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_CHANGE_LOWERING_H_
+#define V8_COMPILER_CHANGE_LOWERING_H_
+
+#include "include/v8.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/graph-reducer.h"
+#include "src/compiler/machine-operator.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// Forward declarations.
+class CommonNodeCache;
+class Linkage;
+
+class ChangeLoweringBase : public Reducer {
+ public:
+ ChangeLoweringBase(Graph* graph, Linkage* linkage, CommonNodeCache*
cache);
+ virtual ~ChangeLoweringBase();
+
+ protected:
+ Node* ExternalConstant(ExternalReference reference);
+ Node* HeapConstant(PrintableUnique<HeapObject> value);
+ Node* ImmovableHeapConstant(Handle<HeapObject> value);
+ Node* Int32Constant(int32_t value);
+ Node* NumberConstant(double value);
+ Node* CEntryStubConstant();
+ Node* TrueConstant();
+ Node* FalseConstant();
+
+ Reduction ChangeBitToBool(Node* val, Node* control);
+
+ Graph* graph() const { return graph_; }
+ Isolate* isolate() const { return isolate_; }
+ Linkage* linkage() const { return linkage_; }
+ CommonNodeCache* cache() const { return cache_; }
+ CommonOperatorBuilder* common() { return &common_; }
+ MachineOperatorBuilder* machine() { return &machine_; }
+
+ private:
+ Graph* graph_;
+ Isolate* isolate_;
+ Linkage* linkage_;
+ CommonNodeCache* cache_;
+ CommonOperatorBuilder common_;
+ MachineOperatorBuilder machine_;
+
+ SetOncePointer<Node> c_entry_stub_constant_;
+ SetOncePointer<Node> true_constant_;
+ SetOncePointer<Node> false_constant_;
+};
+
+
+template <size_t kPointerSize = kApiPointerSize>
+class ChangeLowering V8_FINAL : public ChangeLoweringBase {
+ public:
+ ChangeLowering(Graph* graph, Linkage* linkage);
+ ChangeLowering(Graph* graph, Linkage* linkage, CommonNodeCache* cache)
+ : ChangeLoweringBase(graph, linkage, cache) {}
+ virtual ~ChangeLowering() {}
+
+ virtual Reduction Reduce(Node* node) V8_OVERRIDE;
+
+ private:
+ Reduction ChangeBoolToBit(Node* val);
+ Reduction ChangeInt32ToTagged(Node* val, Node* effect, Node* control);
+ Reduction ChangeTaggedToFloat64(Node* val, Node* effect, Node* control);
+};
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
+
+#endif // V8_COMPILER_CHANGE_LOWERING_H_
=======================================
--- /dev/null
+++ /trunk/test/compiler-unittests/change-lowering-unittest.cc Wed Aug 13
00:04:54 2014 UTC
@@ -0,0 +1,257 @@
+// 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/change-lowering.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/simplified-operator.h"
+#include "src/factory.h"
+#include "test/compiler-unittests/compiler-unittests.h"
+#include "test/compiler-unittests/node-matchers.h"
+#include "testing/gtest-type-names.h"
+
+using testing::_;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+template <typename T>
+class ChangeLoweringTest : public CompilerTest {
+ public:
+ static const size_t kPointerSize = sizeof(T);
+
+ explicit ChangeLoweringTest(int num_parameters = 1)
+ : graph_(zone()), common_(zone()), simplified_(zone()) {
+ graph()->SetStart(graph()->NewNode(common()->Start(num_parameters)));
+ }
+ virtual ~ChangeLoweringTest() {}
+
+ protected:
+ Node* Parameter(int32_t index = 0) {
+ return graph()->NewNode(common()->Parameter(index), graph()->start());
+ }
+
+ Reduction Reduce(Node* node) {
+ CompilationInfo info(isolate(), zone());
+ Linkage linkage(&info);
+ ChangeLowering<kPointerSize> reducer(graph(), &linkage);
+ return reducer.Reduce(node);
+ }
+
+ Graph* graph() { return &graph_; }
+ Factory* factory() const { return isolate()->factory(); }
+ CommonOperatorBuilder* common() { return &common_; }
+ SimplifiedOperatorBuilder* simplified() { return &simplified_; }
+
+ PrintableUnique<HeapObject> true_unique() {
+ return PrintableUnique<HeapObject>::CreateImmovable(
+ zone(), factory()->true_value());
+ }
+ PrintableUnique<HeapObject> false_unique() {
+ return PrintableUnique<HeapObject>::CreateImmovable(
+ zone(), factory()->false_value());
+ }
+
+ private:
+ Graph graph_;
+ CommonOperatorBuilder common_;
+ SimplifiedOperatorBuilder simplified_;
+};
+
+
+typedef ::testing::Types<int32_t, int64_t> ChangeLoweringTypes;
+TYPED_TEST_CASE(ChangeLoweringTest, ChangeLoweringTypes);
+
+
+TARGET_TYPED_TEST(ChangeLoweringTest, ChangeBitToBool) {
+ Node* val = this->Parameter(0);
+ Node* node =
+ this->graph()->NewNode(this->simplified()->ChangeBitToBool(), val);
+ Reduction reduction = this->Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ EXPECT_THAT(phi, IsPhi(IsHeapConstant(this->true_unique()),
+ IsHeapConstant(this->false_unique()), _));
+
+ Node* merge = NodeProperties::GetControlInput(phi);
+ ASSERT_EQ(IrOpcode::kMerge, merge->opcode());
+
+ Node* if_true = NodeProperties::GetControlInput(merge, 0);
+ ASSERT_EQ(IrOpcode::kIfTrue, if_true->opcode());
+
+ Node* if_false = NodeProperties::GetControlInput(merge, 1);
+ ASSERT_EQ(IrOpcode::kIfFalse, if_false->opcode());
+
+ Node* branch = NodeProperties::GetControlInput(if_true);
+ EXPECT_EQ(branch, NodeProperties::GetControlInput(if_false));
+ EXPECT_THAT(branch, IsBranch(val, this->graph()->start()));
+}
+
+
+TARGET_TYPED_TEST(ChangeLoweringTest, StringAdd) {
+ Node* node = this->graph()->NewNode(this->simplified()->StringAdd(),
+ this->Parameter(0),
this->Parameter(1));
+ Reduction reduction = this->Reduce(node);
+ EXPECT_FALSE(reduction.Changed());
+}
+
+
+class ChangeLowering32Test : public ChangeLoweringTest<int32_t> {
+ public:
+ virtual ~ChangeLowering32Test() {}
+};
+
+
+TARGET_TEST_F(ChangeLowering32Test, ChangeBoolToBit) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ EXPECT_THAT(reduction.replacement(),
+ IsWord32Equal(val, IsHeapConstant(true_unique())));
+}
+
+
+TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ ASSERT_EQ(IrOpcode::kPhi, phi->opcode());
+
+ Node* smi = NodeProperties::GetValueInput(phi, 1);
+ ASSERT_THAT(smi, IsProjection(0, IsInt32AddWithOverflow(val, val)));
+
+ Node* heap_number = NodeProperties::GetValueInput(phi, 0);
+ ASSERT_EQ(IrOpcode::kCall, heap_number->opcode());
+
+ Node* merge = NodeProperties::GetControlInput(phi);
+ ASSERT_EQ(IrOpcode::kMerge, merge->opcode());
+
+ const int32_t kValueOffset = HeapNumber::kValueOffset - kHeapObjectTag;
+ EXPECT_THAT(NodeProperties::GetControlInput(merge, 0),
+ IsStore(kMachineFloat64, kNoWriteBarrier, heap_number,
+ IsInt32Constant(kValueOffset),
+ IsChangeInt32ToFloat64(val), _, heap_number));
+
+ Node* if_true = NodeProperties::GetControlInput(heap_number);
+ ASSERT_EQ(IrOpcode::kIfTrue, if_true->opcode());
+
+ Node* if_false = NodeProperties::GetControlInput(merge, 1);
+ ASSERT_EQ(IrOpcode::kIfFalse, if_false->opcode());
+
+ Node* branch = NodeProperties::GetControlInput(if_true);
+ EXPECT_EQ(branch, NodeProperties::GetControlInput(if_false));
+ EXPECT_THAT(branch,
+ IsBranch(IsProjection(1, IsInt32AddWithOverflow(val, val)),
+ graph()->start()));
+}
+
+
+TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ const int32_t kShiftAmount =
+ kSmiTagSize + SmiTagging<kPointerSize>::kSmiShiftSize;
+ const int32_t kValueOffset = HeapNumber::kValueOffset - kHeapObjectTag;
+ Node* phi = reduction.replacement();
+ ASSERT_THAT(
+ phi, IsPhi(IsLoad(kMachineFloat64, val,
IsInt32Constant(kValueOffset), _),
+ IsChangeInt32ToFloat64(
+ IsWord32Sar(val, IsInt32Constant(kShiftAmount))),
+ _));
+
+ Node* merge = NodeProperties::GetControlInput(phi);
+ ASSERT_EQ(IrOpcode::kMerge, merge->opcode());
+
+ Node* if_true = NodeProperties::GetControlInput(merge, 0);
+ ASSERT_EQ(IrOpcode::kIfTrue, if_true->opcode());
+
+ Node* if_false = NodeProperties::GetControlInput(merge, 1);
+ ASSERT_EQ(IrOpcode::kIfFalse, if_false->opcode());
+
+ Node* branch = NodeProperties::GetControlInput(if_true);
+ EXPECT_EQ(branch, NodeProperties::GetControlInput(if_false));
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+ EXPECT_THAT(branch, IsBranch(IsWord32And(val,
IsInt32Constant(kSmiTagMask)),
+ graph()->start()));
+}
+
+
+class ChangeLowering64Test : public ChangeLoweringTest<int64_t> {
+ public:
+ virtual ~ChangeLowering64Test() {}
+};
+
+
+TARGET_TEST_F(ChangeLowering64Test, ChangeBoolToBit) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ EXPECT_THAT(reduction.replacement(),
+ IsWord64Equal(val, IsHeapConstant(true_unique())));
+}
+
+
+TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ const int32_t kShiftAmount =
+ kSmiTagSize + SmiTagging<kPointerSize>::kSmiShiftSize;
+ EXPECT_THAT(reduction.replacement(),
+ IsWord64Shl(val, IsInt32Constant(kShiftAmount)));
+}
+
+
+TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ const int32_t kShiftAmount =
+ kSmiTagSize + SmiTagging<kPointerSize>::kSmiShiftSize;
+ const int32_t kValueOffset = HeapNumber::kValueOffset - kHeapObjectTag;
+ Node* phi = reduction.replacement();
+ ASSERT_THAT(
+ phi, IsPhi(IsLoad(kMachineFloat64, val,
IsInt32Constant(kValueOffset), _),
+ IsChangeInt32ToFloat64(IsConvertInt64ToInt32(
+ IsWord64Sar(val, IsInt32Constant(kShiftAmount)))),
+ _));
+
+ Node* merge = NodeProperties::GetControlInput(phi);
+ ASSERT_EQ(IrOpcode::kMerge, merge->opcode());
+
+ Node* if_true = NodeProperties::GetControlInput(merge, 0);
+ ASSERT_EQ(IrOpcode::kIfTrue, if_true->opcode());
+
+ Node* if_false = NodeProperties::GetControlInput(merge, 1);
+ ASSERT_EQ(IrOpcode::kIfFalse, if_false->opcode());
+
+ Node* branch = NodeProperties::GetControlInput(if_true);
+ EXPECT_EQ(branch, NodeProperties::GetControlInput(if_false));
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+ EXPECT_THAT(branch, IsBranch(IsWord64And(val,
IsInt32Constant(kSmiTagMask)),
+ graph()->start()));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
=======================================
--- /dev/null
+++ /trunk/test/compiler-unittests/node-matchers.cc Wed Aug 13 00:04:54
2014 UTC
@@ -0,0 +1,454 @@
+// 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 "test/compiler-unittests/node-matchers.h"
+
+#include <ostream> // NOLINT(readability/streams)
+
+#include "src/compiler/node-properties-inl.h"
+
+using testing::MakeMatcher;
+using testing::MatcherInterface;
+using testing::MatchResultListener;
+using testing::StringMatchResultListener;
+
+namespace v8 {
+namespace internal {
+
+// TODO(bmeurer): Find a new home for these functions.
+template <typename T>
+inline std::ostream& operator<<(std::ostream& os,
+ const PrintableUnique<T>& value) {
+ return os << value.string();
+}
+
+namespace compiler {
+
+namespace {
+
+template <typename T>
+bool PrintMatchAndExplain(const T& value, const char* value_name,
+ const Matcher<T>& value_matcher,
+ MatchResultListener* listener) {
+ StringMatchResultListener value_listener;
+ if (!value_matcher.MatchAndExplain(value, &value_listener)) {
+ *listener << "whose " << value_name << " " << value << " doesn't
match";
+ if (value_listener.str() != "") {
+ *listener << ", " << value_listener.str();
+ }
+ return false;
+ }
+ return true;
+}
+
+
+class NodeMatcher : public MatcherInterface<Node*> {
+ public:
+ explicit NodeMatcher(IrOpcode::Value opcode) : opcode_(opcode) {}
+
+ virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+ *os << "is a " << IrOpcode::Mnemonic(opcode_) << " node";
+ }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener)
const
+ V8_OVERRIDE {
+ if (node == NULL) {
+ *listener << "which is NULL";
+ return false;
+ }
+ if (node->opcode() != opcode_) {
+ *listener << "whose opcode is " <<
IrOpcode::Mnemonic(node->opcode());
+ return false;
+ }
+ return true;
+ }
+
+ private:
+ const IrOpcode::Value opcode_;
+};
+
+
+class IsBranchMatcher V8_FINAL : public NodeMatcher {
+ public:
+ IsBranchMatcher(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher)
+ : NodeMatcher(IrOpcode::kBranch),
+ value_matcher_(value_matcher),
+ control_matcher_(control_matcher) {}
+
+ virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose value (";
+ value_matcher_.DescribeTo(os);
+ *os << ") and control (";
+ control_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener)
const
+ V8_OVERRIDE {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
+ "value", value_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetControlInput(node),
+ "control", control_matcher_, listener));
+ }
+
+ private:
+ const Matcher<Node*> value_matcher_;
+ const Matcher<Node*> control_matcher_;
+};
+
+
+template <typename T>
+class IsConstantMatcher V8_FINAL : public NodeMatcher {
+ public:
+ IsConstantMatcher(IrOpcode::Value opcode, const Matcher<T>&
value_matcher)
+ : NodeMatcher(opcode), value_matcher_(value_matcher) {}
+
+ virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose value (";
+ value_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener)
const
+ V8_OVERRIDE {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(OpParameter<T>(node), "value",
value_matcher_,
+ listener));
+ }
+
+ private:
+ const Matcher<T> value_matcher_;
+};
+
+
+class IsPhiMatcher V8_FINAL : public NodeMatcher {
+ public:
+ IsPhiMatcher(const Matcher<Node*>& value0_matcher,
+ const Matcher<Node*>& value1_matcher,
+ const Matcher<Node*>& control_matcher)
+ : NodeMatcher(IrOpcode::kPhi),
+ value0_matcher_(value0_matcher),
+ value1_matcher_(value1_matcher),
+ control_matcher_(control_matcher) {}
+
+ virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose value0 (";
+ value0_matcher_.DescribeTo(os);
+ *os << "), value1 (";
+ value1_matcher_.DescribeTo(os);
+ *os << ") and control (";
+ control_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener)
const
+ V8_OVERRIDE {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
+ "value0", value0_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
+ "value1", value1_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetControlInput(node),
+ "control", control_matcher_, listener));
+ }
+
+ private:
+ const Matcher<Node*> value0_matcher_;
+ const Matcher<Node*> value1_matcher_;
+ const Matcher<Node*> control_matcher_;
+};
+
+
+class IsProjectionMatcher V8_FINAL : public NodeMatcher {
+ public:
+ IsProjectionMatcher(const Matcher<int32_t>& index_matcher,
+ const Matcher<Node*>& base_matcher)
+ : NodeMatcher(IrOpcode::kProjection),
+ index_matcher_(index_matcher),
+ base_matcher_(base_matcher) {}
+
+ virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose index (";
+ index_matcher_.DescribeTo(os);
+ *os << ") and base (";
+ base_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener)
const
+ V8_OVERRIDE {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(OpParameter<int32_t>(node), "index",
+ index_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node,
0), "base",
+ base_matcher_, listener));
+ }
+
+ private:
+ const Matcher<int32_t> index_matcher_;
+ const Matcher<Node*> base_matcher_;
+};
+
+
+class IsLoadMatcher V8_FINAL : public NodeMatcher {
+ public:
+ IsLoadMatcher(const Matcher<MachineType>& type_matcher,
+ const Matcher<Node*>& base_matcher,
+ const Matcher<Node*>& index_matcher,
+ const Matcher<Node*>& effect_matcher)
+ : NodeMatcher(IrOpcode::kLoad),
+ type_matcher_(type_matcher),
+ base_matcher_(base_matcher),
+ index_matcher_(index_matcher),
+ effect_matcher_(effect_matcher) {}
+
+ virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose type (";
+ type_matcher_.DescribeTo(os);
+ *os << "), base (";
+ base_matcher_.DescribeTo(os);
+ *os << "), index (";
+ index_matcher_.DescribeTo(os);
+ *os << ") and effect (";
+ effect_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener)
const
+ V8_OVERRIDE {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(OpParameter<MachineType>(node), "type",
+ type_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node,
0), "base",
+ base_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
+ "index", index_matcher_, listener) &&
+
PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
+ effect_matcher_, listener));
+ }
+
+ private:
+ const Matcher<MachineType> type_matcher_;
+ const Matcher<Node*> base_matcher_;
+ const Matcher<Node*> index_matcher_;
+ const Matcher<Node*> effect_matcher_;
+};
+
+
+class IsStoreMatcher V8_FINAL : public NodeMatcher {
+ public:
+ IsStoreMatcher(const Matcher<MachineType>& type_matcher,
+ const Matcher<WriteBarrierKind> write_barrier_matcher,
+ const Matcher<Node*>& base_matcher,
+ const Matcher<Node*>& index_matcher,
+ const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher)
+ : NodeMatcher(IrOpcode::kStore),
+ type_matcher_(type_matcher),
+ write_barrier_matcher_(write_barrier_matcher),
+ base_matcher_(base_matcher),
+ index_matcher_(index_matcher),
+ value_matcher_(value_matcher),
+ effect_matcher_(effect_matcher),
+ control_matcher_(control_matcher) {}
+
+ virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose type (";
+ type_matcher_.DescribeTo(os);
+ *os << "), write barrier (";
+ write_barrier_matcher_.DescribeTo(os);
+ *os << "), base (";
+ base_matcher_.DescribeTo(os);
+ *os << "), index (";
+ index_matcher_.DescribeTo(os);
+ *os << "), value (";
+ value_matcher_.DescribeTo(os);
+ *os << "), effect (";
+ effect_matcher_.DescribeTo(os);
+ *os << ") and control (";
+ control_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener)
const
+ V8_OVERRIDE {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+
PrintMatchAndExplain(OpParameter<StoreRepresentation>(node).rep,
+ "type", type_matcher_, listener) &&
+ PrintMatchAndExplain(
+ OpParameter<StoreRepresentation>(node).write_barrier_kind,
+ "write barrier", write_barrier_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node,
0), "base",
+ base_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
+ "index", index_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2),
+ "value", value_matcher_, listener) &&
+
PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
+ effect_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetControlInput(node),
+ "control", control_matcher_, listener));
+ }
+
+ private:
+ const Matcher<MachineType> type_matcher_;
+ const Matcher<WriteBarrierKind> write_barrier_matcher_;
+ const Matcher<Node*> base_matcher_;
+ const Matcher<Node*> index_matcher_;
+ const Matcher<Node*> value_matcher_;
+ const Matcher<Node*> effect_matcher_;
+ const Matcher<Node*> control_matcher_;
+};
+
+
+class IsBinopMatcher V8_FINAL : public NodeMatcher {
+ public:
+ IsBinopMatcher(IrOpcode::Value opcode, const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher)
+ : NodeMatcher(opcode),
+ lhs_matcher_(lhs_matcher),
+ rhs_matcher_(rhs_matcher) {}
+
+ virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose lhs (";
+ lhs_matcher_.DescribeTo(os);
+ *os << ") and rhs (";
+ rhs_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener)
const
+ V8_OVERRIDE {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node,
0), "lhs",
+ lhs_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node,
1), "rhs",
+ rhs_matcher_, listener));
+ }
+
+ private:
+ const Matcher<Node*> lhs_matcher_;
+ const Matcher<Node*> rhs_matcher_;
+};
+
+
+class IsUnopMatcher V8_FINAL : public NodeMatcher {
+ public:
+ IsUnopMatcher(IrOpcode::Value opcode, const Matcher<Node*>&
input_matcher)
+ : NodeMatcher(opcode), input_matcher_(input_matcher) {}
+
+ virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose input (";
+ input_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener)
const
+ V8_OVERRIDE {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
+ "input", input_matcher_, listener));
+ }
+
+ private:
+ const Matcher<Node*> input_matcher_;
+};
+
+}
+
+
+Matcher<Node*> IsBranch(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher) {
+ return MakeMatcher(new IsBranchMatcher(value_matcher, control_matcher));
+}
+
+
+Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher) {
+ return MakeMatcher(
+ new IsConstantMatcher<int32_t>(IrOpcode::kInt32Constant,
value_matcher));
+}
+
+
+Matcher<Node*> IsHeapConstant(
+ const Matcher<PrintableUnique<HeapObject> >& value_matcher) {
+ return MakeMatcher(new IsConstantMatcher<PrintableUnique<HeapObject> >(
+ IrOpcode::kHeapConstant, value_matcher));
+}
+
+
+Matcher<Node*> IsPhi(const Matcher<Node*>& value0_matcher,
+ const Matcher<Node*>& value1_matcher,
+ const Matcher<Node*>& merge_matcher) {
+ return MakeMatcher(
+ new IsPhiMatcher(value0_matcher, value1_matcher, merge_matcher));
+}
+
+
+Matcher<Node*> IsProjection(const Matcher<int32_t>& index_matcher,
+ const Matcher<Node*>& base_matcher) {
+ return MakeMatcher(new IsProjectionMatcher(index_matcher, base_matcher));
+}
+
+
+Matcher<Node*> IsLoad(const Matcher<MachineType>& type_matcher,
+ const Matcher<Node*>& base_matcher,
+ const Matcher<Node*>& index_matcher,
+ const Matcher<Node*>& effect_matcher) {
+ return MakeMatcher(new IsLoadMatcher(type_matcher, base_matcher,
+ index_matcher, effect_matcher));
+}
+
+
+Matcher<Node*> IsStore(const Matcher<MachineType>& type_matcher,
+ const Matcher<WriteBarrierKind>&
write_barrier_matcher,
+ const Matcher<Node*>& base_matcher,
+ const Matcher<Node*>& index_matcher,
+ const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher) {
+ return MakeMatcher(new IsStoreMatcher(
+ type_matcher, write_barrier_matcher, base_matcher, index_matcher,
+ value_matcher, effect_matcher, control_matcher));
+}
+
+
+#define IS_BINOP_MATCHER(Name) \
+ Matcher<Node*> Is##Name(const Matcher<Node*>& lhs_matcher, \
+ const Matcher<Node*>& rhs_matcher) { \
+ return MakeMatcher( \
+ new IsBinopMatcher(IrOpcode::k##Name, lhs_matcher, rhs_matcher)); \
+ }
+IS_BINOP_MATCHER(Word32And)
+IS_BINOP_MATCHER(Word32Sar)
+IS_BINOP_MATCHER(Word32Equal)
+IS_BINOP_MATCHER(Word64And)
+IS_BINOP_MATCHER(Word64Sar)
+IS_BINOP_MATCHER(Word64Shl)
+IS_BINOP_MATCHER(Word64Equal)
+IS_BINOP_MATCHER(Int32AddWithOverflow)
+#undef IS_BINOP_MATCHER
+
+
+#define
IS_UNOP_MATCHER(Name) \
+ Matcher<Node*> Is##Name(const Matcher<Node*>& input_matcher)
{ \
+ return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name,
input_matcher)); \
+ }
+IS_UNOP_MATCHER(ConvertInt64ToInt32)
+IS_UNOP_MATCHER(ChangeInt32ToFloat64)
+#undef IS_UNOP_MATCHER
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
=======================================
--- /dev/null
+++ /trunk/test/compiler-unittests/node-matchers.h Wed Aug 13 00:04:54 2014
UTC
@@ -0,0 +1,71 @@
+// 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_UNITTESTS_NODE_MATCHERS_H_
+#define V8_COMPILER_UNITTESTS_NODE_MATCHERS_H_
+
+#include "src/compiler/machine-operator.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class HeapObject;
+template <class T>
+class PrintableUnique;
+
+namespace compiler {
+
+// Forward declarations.
+class Node;
+
+using testing::Matcher;
+
+Matcher<Node*> IsBranch(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsHeapConstant(
+ const Matcher<PrintableUnique<HeapObject> >& value_matcher);
+Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher);
+Matcher<Node*> IsPhi(const Matcher<Node*>& value0_matcher,
+ const Matcher<Node*>& value1_matcher,
+ const Matcher<Node*>& merge_matcher);
+Matcher<Node*> IsProjection(const Matcher<int32_t>& index_matcher,
+ const Matcher<Node*>& base_matcher);
+
+Matcher<Node*> IsLoad(const Matcher<MachineType>& type_matcher,
+ const Matcher<Node*>& base_matcher,
+ const Matcher<Node*>& index_matcher,
+ const Matcher<Node*>& effect_matcher);
+Matcher<Node*> IsStore(const Matcher<MachineType>& type_matcher,
+ const Matcher<WriteBarrierKind>&
write_barrier_matcher,
+ const Matcher<Node*>& base_matcher,
+ const Matcher<Node*>& index_matcher,
+ const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsWord32And(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsWord32Sar(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsWord32Equal(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsWord64And(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsWord64Shl(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsWord64Sar(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsWord64Equal(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsInt32AddWithOverflow(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsConvertInt64ToInt32(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsChangeInt32ToFloat64(const Matcher<Node*>& input_matcher);
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
+
+#endif // V8_COMPILER_UNITTESTS_NODE_MATCHERS_H_
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/own-symbols.js Wed Aug 13 00:04:54 2014 UTC
@@ -0,0 +1,55 @@
+// 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.
+//
+// Flags: --allow-natives-syntax
+
+var s = %CreatePrivateOwnSymbol("s");
+var s1 = %CreatePrivateOwnSymbol("s1");
+
+function TestSimple() {
+ var p = {}
+ p[s] = "moo";
+
+ var o = Object.create(p);
+
+ assertEquals(undefined, o[s]);
+ assertEquals("moo", p[s]);
+
+ o[s] = "bow-wow";
+ assertEquals("bow-wow", o[s]);
+ assertEquals("moo", p[s]);
+}
+
+TestSimple();
+
+
+function TestICs() {
+ var p = {}
+ p[s] = "moo";
+
+
+ var o = Object.create(p);
+ o[s1] = "bow-wow";
+ function checkNonOwn(o) {
+ assertEquals(undefined, o[s]);
+ assertEquals("bow-wow", o[s1]);
+ }
+
+ checkNonOwn(o);
+
+ // Test monomorphic/optimized.
+ for (var i = 0; i < 1000; i++) {
+ checkNonOwn(o);
+ }
+
+ // Test non-monomorphic.
+ for (var i = 0; i < 1000; i++) {
+ var oNew = Object.create(p);
+ oNew["s" + i] = i;
+ oNew[s1] = "bow-wow";
+ checkNonOwn(oNew);
+ }
+}
+
+TestICs();
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/runtime-gen/createprivateownsymbol.js Wed Aug 13
00:04:54 2014 UTC
@@ -0,0 +1,5 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
+// Flags: --allow-natives-syntax --harmony --harmony-proxies
+var arg0 = "foo";
+%CreatePrivateOwnSymbol(arg0);
=======================================
--- /dev/null
+++ /trunk/testing/gtest-type-names.h Wed Aug 13 00:04:54 2014 UTC
@@ -0,0 +1,34 @@
+// 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_TESTING_GTEST_TYPE_NAMES_H_
+#define V8_TESTING_GTEST_TYPE_NAMES_H_
+
+#include "include/v8stdint.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+#define GET_TYPE_NAME(type) \
+ template <> \
+ std::string GetTypeName<type>() { \
+ return #type; \
+ }
+GET_TYPE_NAME(int8_t)
+GET_TYPE_NAME(uint8_t)
+GET_TYPE_NAME(int16_t)
+GET_TYPE_NAME(uint16_t)
+GET_TYPE_NAME(int32_t)
+GET_TYPE_NAME(uint32_t)
+GET_TYPE_NAME(int64_t)
+GET_TYPE_NAME(uint64_t)
+GET_TYPE_NAME(float)
+GET_TYPE_NAME(double)
+#undef GET_TYPE_NAME
+
+} // namespace internal
+} // namespace testing
+
+#endif // V8_TESTING_GTEST_TYPE_NAMES_H_
=======================================
--- /trunk/ChangeLog Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/ChangeLog Wed Aug 13 00:04:54 2014 UTC
@@ -1,3 +1,8 @@
+2014-08-13: Version 3.28.73
+
+ Performance and stability improvements on all platforms.
+
+
2014-08-12: Version 3.28.71
ToNumber(Symbol) should throw TypeError (issue 3499).
=======================================
--- /trunk/src/api.cc Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/api.cc Wed Aug 13 00:04:54 2014 UTC
@@ -4290,9 +4290,7 @@
class Visitor {
public:
- inline explicit Visitor()
- : utf8_length_(0),
- state_(kInitialState) {}
+ Visitor() : utf8_length_(0), state_(kInitialState) {}
void VisitOneByteString(const uint8_t* chars, int length) {
int utf8_length = 0;
=======================================
--- /trunk/src/arm/assembler-arm.h Thu Aug 7 08:39:21 2014 UTC
+++ /trunk/src/arm/assembler-arm.h Wed Aug 13 00:04:54 2014 UTC
@@ -649,7 +649,7 @@
// Class used to build a constant pool.
class ConstantPoolBuilder BASE_EMBEDDED {
public:
- explicit ConstantPoolBuilder();
+ ConstantPoolBuilder();
ConstantPoolArray::LayoutSection AddEntry(Assembler* assm,
const RelocInfo& rinfo);
void Relocate(int pc_delta);
=======================================
--- /trunk/src/arm/lithium-arm.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/arm/lithium-arm.h Wed Aug 13 00:04:54 2014 UTC
@@ -414,7 +414,7 @@
class LDummy V8_FINAL : public LTemplateInstruction<1, 0, 0> {
public:
- explicit LDummy() { }
+ LDummy() {}
DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
};
=======================================
--- /trunk/src/arm64/assembler-arm64.h Fri Aug 8 15:46:17 2014 UTC
+++ /trunk/src/arm64/assembler-arm64.h Wed Aug 13 00:04:54 2014 UTC
@@ -697,7 +697,7 @@
// MemOperand represents a memory operand in a load or store instruction.
class MemOperand {
public:
- inline explicit MemOperand();
+ inline MemOperand();
inline explicit MemOperand(Register base,
ptrdiff_t offset = 0,
AddrMode addrmode = Offset);
=======================================
--- /trunk/src/arm64/instrument-arm64.h Mon Jun 23 08:21:41 2014 UTC
+++ /trunk/src/arm64/instrument-arm64.h Wed Aug 13 00:04:54 2014 UTC
@@ -32,7 +32,7 @@
class Counter {
public:
- Counter(const char* name, CounterType type = Gauge);
+ explicit Counter(const char* name, CounterType type = Gauge);
void Increment();
void Enable();
=======================================
--- /trunk/src/arm64/lithium-arm64.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/arm64/lithium-arm64.h Wed Aug 13 00:04:54 2014 UTC
@@ -452,7 +452,7 @@
class LDummy V8_FINAL : public LTemplateInstruction<1, 0, 0> {
public:
- explicit LDummy() { }
+ LDummy() {}
DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
};
@@ -943,7 +943,7 @@
class LCheckMaps V8_FINAL : public LTemplateInstruction<0, 1, 1> {
public:
- LCheckMaps(LOperand* value = NULL, LOperand* temp = NULL) {
+ explicit LCheckMaps(LOperand* value = NULL, LOperand* temp = NULL) {
inputs_[0] = value;
temps_[0] = temp;
}
=======================================
--- /trunk/src/arm64/macro-assembler-arm64.h Fri Aug 8 15:46:17 2014 UTC
+++ /trunk/src/arm64/macro-assembler-arm64.h Wed Aug 13 00:04:54 2014 UTC
@@ -2201,7 +2201,7 @@
// emitted is what you specified when creating the scope.
class InstructionAccurateScope BASE_EMBEDDED {
public:
- InstructionAccurateScope(MacroAssembler* masm, size_t count = 0)
+ explicit InstructionAccurateScope(MacroAssembler* masm, size_t count = 0)
: masm_(masm)
#ifdef DEBUG
,
=======================================
--- /trunk/src/base/platform/platform.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/base/platform/platform.h Wed Aug 13 00:04:54 2014 UTC
@@ -428,7 +428,7 @@
class Options {
public:
Options() : name_("v8:<unknown>"), stack_size_(0) {}
- Options(const char* name, int stack_size = 0)
+ explicit Options(const char* name, int stack_size = 0)
: name_(name), stack_size_(stack_size) {}
const char* name() const { return name_; }
=======================================
--- /trunk/src/bootstrapper.cc Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/bootstrapper.cc Wed Aug 13 00:04:54 2014 UTC
@@ -2655,19 +2655,17 @@
NONE).Assert();
// Initialize trigonometric lookup tables and constants.
- const int constants_size =
- ARRAY_SIZE(fdlibm::TrigonometricConstants::constants);
+ const int constants_size =
ARRAY_SIZE(fdlibm::MathConstants::constants);
const int table_num_bytes = constants_size * kDoubleSize;
v8::Local<v8::ArrayBuffer> trig_buffer = v8::ArrayBuffer::New(
reinterpret_cast<v8::Isolate*>(isolate),
- const_cast<double*>(fdlibm::TrigonometricConstants::constants),
- table_num_bytes);
+ const_cast<double*>(fdlibm::MathConstants::constants),
table_num_bytes);
v8::Local<v8::Float64Array> trig_table =
v8::Float64Array::New(trig_buffer, 0, constants_size);
Runtime::DefineObjectProperty(
builtins,
- factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("kTrig")),
+ factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("kMath")),
Utils::OpenHandle(*trig_table), NONE).Assert();
}
=======================================
--- /trunk/src/code-stubs.h Fri Aug 8 15:46:17 2014 UTC
+++ /trunk/src/code-stubs.h Wed Aug 13 00:04:54 2014 UTC
@@ -437,7 +437,8 @@
INITIALIZED
};
- HydrogenCodeStub(Isolate* isolate, InitializationState state =
INITIALIZED)
+ explicit HydrogenCodeStub(Isolate* isolate,
+ InitializationState state = INITIALIZED)
: CodeStub(isolate) {
is_uninitialized_ = (state == UNINITIALIZED);
}
=======================================
--- /trunk/src/compiler/node-properties-inl.h Fri Aug 8 15:46:17 2014 UTC
+++ /trunk/src/compiler/node-properties-inl.h Wed Aug 13 00:04:54 2014 UTC
@@ -23,12 +23,11 @@
// Inputs are always arranged in order as follows:
// 0 [ values, context, effects, control ] node->InputCount()
+inline int NodeProperties::FirstValueIndex(Node* node) { return 0; }
-inline int NodeProperties::GetContextIndex(Node* node) {
+inline int NodeProperties::FirstContextIndex(Node* node) {
return PastValueIndex(node);
}
-
-inline int NodeProperties::FirstValueIndex(Node* node) { return 0; }
inline int NodeProperties::FirstEffectIndex(Node* node) {
return PastContextIndex(node);
@@ -45,7 +44,7 @@
}
inline int NodeProperties::PastContextIndex(Node* node) {
- return GetContextIndex(node) +
+ return FirstContextIndex(node) +
OperatorProperties::GetContextInputCount(node->op());
}
@@ -71,7 +70,7 @@
inline Node* NodeProperties::GetContextInput(Node* node) {
DCHECK(OperatorProperties::HasContextInput(node->op()));
- return node->InputAt(GetContextIndex(node));
+ return node->InputAt(FirstContextIndex(node));
}
inline Node* NodeProperties::GetEffectInput(Node* node, int index) {
@@ -106,7 +105,7 @@
inline bool NodeProperties::IsContextEdge(Node::Edge edge) {
Node* node = edge.from();
- return IsInputRange(edge, GetContextIndex(node),
+ return IsInputRange(edge, FirstContextIndex(node),
OperatorProperties::GetContextInputCount(node->op()));
}
@@ -134,13 +133,14 @@
//
-----------------------------------------------------------------------------
// Miscellaneous mutators.
+inline void NodeProperties::ReplaceControlInput(Node* node, Node* control)
{
+ node->ReplaceInput(FirstControlIndex(node), control);
+}
+
inline void NodeProperties::ReplaceEffectInput(Node* node, Node* effect,
int index) {
DCHECK(index < OperatorProperties::GetEffectInputCount(node->op()));
- return node->ReplaceInput(
- OperatorProperties::GetValueInputCount(node->op()) +
- OperatorProperties::GetContextInputCount(node->op()) + index,
- effect);
+ return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
}
inline void NodeProperties::RemoveNonValueInputs(Node* node) {
=======================================
--- /trunk/src/compiler/node-properties.h Mon Aug 11 12:49:03 2014 UTC
+++ /trunk/src/compiler/node-properties.h Wed Aug 13 00:04:54 2014 UTC
@@ -5,15 +5,13 @@
#ifndef V8_COMPILER_NODE_PROPERTIES_H_
#define V8_COMPILER_NODE_PROPERTIES_H_
-#include "src/v8.h"
-
+#include "src/compiler/node.h"
#include "src/types.h"
namespace v8 {
namespace internal {
namespace compiler {
-class Node;
class Operator;
// A facade that simplifies access to the different kinds of inputs to a
node.
@@ -31,6 +29,7 @@
static inline bool IsControl(Node* node);
+ static inline void ReplaceControlInput(Node* node, Node* control);
static inline void ReplaceEffectInput(Node* node, Node* effect,
int index = 0);
static inline void RemoveNonValueInputs(Node* node);
@@ -38,9 +37,9 @@
static inline Bounds GetBounds(Node* node);
static inline void SetBounds(Node* node, Bounds bounds);
- static inline int GetContextIndex(Node* node);
-
+ private:
static inline int FirstValueIndex(Node* node);
+ static inline int FirstContextIndex(Node* node);
static inline int FirstEffectIndex(Node* node);
static inline int FirstControlIndex(Node* node);
static inline int PastValueIndex(Node* node);
@@ -50,8 +49,9 @@
static inline bool IsInputRange(Node::Edge edge, int first, int count);
};
-}
-}
-} // namespace v8::internal::compiler
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
#endif // V8_COMPILER_NODE_PROPERTIES_H_
=======================================
--- /trunk/src/compiler/pipeline.cc Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/compiler/pipeline.cc Wed Aug 13 00:04:54 2014 UTC
@@ -14,6 +14,7 @@
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-generic-lowering.h"
#include "src/compiler/js-typed-lowering.h"
+#include "src/compiler/phi-reducer.h"
#include "src/compiler/register-allocator.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
@@ -22,6 +23,7 @@
#include "src/compiler/verifier.h"
#include "src/hydrogen.h"
#include "src/ostreams.h"
+#include "src/utils.h"
namespace v8 {
namespace internal {
@@ -73,9 +75,25 @@
void Pipeline::VerifyAndPrintGraph(Graph* graph, const char* phase) {
if (FLAG_trace_turbo) {
+ char buffer[256];
+ Vector<char> filename(buffer, sizeof(buffer));
+ SmartArrayPointer<char> functionname =
+ info_->shared_info()->DebugName()->ToCString();
+ if (strlen(functionname.get()) > 0) {
+ SNPrintF(filename, "turbo-%s-%s.dot", functionname.get(), phase);
+ } else {
+ SNPrintF(filename, "turbo-%p-%s.dot", static_cast<void*>(info_),
phase);
+ }
+ std::replace(filename.start(), filename.start() +
filename.length(), ' ',
+ '_');
+ FILE* file = base::OS::FOpen(filename.start(), "w+");
+ OFStream of(file);
+ of << AsDOT(*graph);
+ fclose(file);
+
OFStream os(stdout);
- os << "-- " << phase << " graph -----------------------------------\n"
- << AsDOT(*graph);
+ os << "-- " << phase << " graph printed to file " << filename.start()
+ << "\n";
}
if (VerifyGraphs()) Verifier::Run(graph);
}
@@ -144,6 +162,17 @@
graph_builder.CreateGraph();
context_node = graph_builder.GetFunctionContext();
}
+ {
+ PhaseStats phi_reducer_stats(info(), PhaseStats::CREATE_GRAPH,
+ "phi reduction");
+ PhiReducer phi_reducer;
+ GraphReducer graph_reducer(&graph);
+ graph_reducer.AddReducer(&phi_reducer);
+ graph_reducer.ReduceGraph();
+ // TODO(mstarzinger): Running reducer once ought to be enough for
everyone.
+ graph_reducer.ReduceGraph();
+ graph_reducer.ReduceGraph();
+ }
VerifyAndPrintGraph(&graph, "Initial untyped");
=======================================
--- /trunk/src/compiler/representation-change.h Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/compiler/representation-change.h Wed Aug 13 00:04:54 2014 UTC
@@ -88,7 +88,7 @@
} else if (use_type & rFloat64) {
return GetFloat64RepresentationFor(node, output_type);
} else if (use_type & rWord32) {
- return GetWord32RepresentationFor(node, output_type);
+ return GetWord32RepresentationFor(node, output_type, use_type &
tUint32);
} else if (use_type & rBit) {
return GetBitRepresentationFor(node, output_type);
} else if (use_type & rWord64) {
@@ -165,10 +165,8 @@
if (output_type & rWord32) {
if (output_type & tUint32) {
op = machine()->ChangeUint32ToFloat64();
- } else if (output_type & tInt32) {
+ } else {
op = machine()->ChangeInt32ToFloat64();
- } else {
- return TypeError(node, output_type, rFloat64);
}
} else if (output_type & rTagged) {
op = simplified()->ChangeTaggedToFloat64();
@@ -178,22 +176,23 @@
return jsgraph()->graph()->NewNode(op, node);
}
- Node* GetWord32RepresentationFor(Node* node, RepTypeUnion output_type) {
+ Node* GetWord32RepresentationFor(Node* node, RepTypeUnion output_type,
+ bool use_unsigned) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
case IrOpcode::kInt32Constant:
return node; // No change necessary.
case IrOpcode::kNumberConstant:
case IrOpcode::kFloat64Constant: {
- if (output_type & tUint32) {
- int32_t value = static_cast<int32_t>(
- static_cast<uint32_t>(ValueOf<double>(node->op())));
- return jsgraph()->Int32Constant(value);
- } else if (output_type & tInt32) {
- int32_t value = FastD2I(ValueOf<double>(node->op()));
- return jsgraph()->Int32Constant(value);
+ double value = ValueOf<double>(node->op());
+ if (value < 0) {
+ DCHECK(IsInt32Double(value));
+ int32_t iv = static_cast<int32_t>(value);
+ return jsgraph()->Int32Constant(iv);
} else {
- return TypeError(node, output_type, rWord32);
+ DCHECK(IsUint32Double(value));
+ int32_t iv = static_cast<int32_t>(static_cast<uint32_t>(value));
+ return jsgraph()->Int32Constant(iv);
}
}
default:
@@ -202,20 +201,16 @@
// Select the correct X -> Word32 operator.
Operator* op = NULL;
if (output_type & rFloat64) {
- if (output_type & tUint32) {
+ if (output_type & tUint32 || use_unsigned) {
op = machine()->ChangeFloat64ToUint32();
- } else if (output_type & tInt32) {
+ } else {
op = machine()->ChangeFloat64ToInt32();
- } else {
- return TypeError(node, output_type, rWord32);
}
} else if (output_type & rTagged) {
- if (output_type & tUint32) {
+ if (output_type & tUint32 || use_unsigned) {
op = simplified()->ChangeTaggedToUint32();
- } else if (output_type & tInt32) {
+ } else {
op = simplified()->ChangeTaggedToInt32();
- } else {
- return TypeError(node, output_type, rWord32);
}
} else if (output_type & rBit) {
return node; // Sloppy comparison -> word32.
=======================================
--- /trunk/src/effects.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/effects.h Wed Aug 13 00:04:54 2014 UTC
@@ -33,7 +33,7 @@
Bounds bounds;
Effect() : modality(DEFINITE) {}
- Effect(Bounds b, Modality m = DEFINITE) : modality(m), bounds(b) {}
+ explicit Effect(Bounds b, Modality m = DEFINITE) : modality(m),
bounds(b) {}
// The unknown effect.
static Effect Unknown(Zone* zone) {
=======================================
--- /trunk/src/factory.cc Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/factory.cc Wed Aug 13 00:04:54 2014 UTC
@@ -662,6 +662,14 @@
symbol->set_is_private(true);
return symbol;
}
+
+
+Handle<Symbol> Factory::NewPrivateOwnSymbol() {
+ Handle<Symbol> symbol = NewSymbol();
+ symbol->set_is_private(true);
+ symbol->set_is_own(true);
+ return symbol;
+}
Handle<Context> Factory::NewNativeContext() {
=======================================
--- /trunk/src/factory.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/factory.h Wed Aug 13 00:04:54 2014 UTC
@@ -221,6 +221,7 @@
// Create a symbol.
Handle<Symbol> NewSymbol();
Handle<Symbol> NewPrivateSymbol();
+ Handle<Symbol> NewPrivateOwnSymbol();
// Create a global (but otherwise uninitialized) context.
Handle<Context> NewNativeContext();
=======================================
--- /trunk/src/globals.h Fri Aug 8 15:46:17 2014 UTC
+++ /trunk/src/globals.h Wed Aug 13 00:04:54 2014 UTC
@@ -31,8 +31,7 @@
#else
#define V8_TURBOFAN_BACKEND 0
#endif
-#if V8_TURBOFAN_BACKEND && !V8_TARGET_ARCH_ARM64 && \
- !(V8_OS_WIN && V8_TARGET_ARCH_X64)
+#if V8_TURBOFAN_BACKEND && !(V8_OS_WIN && V8_TARGET_ARCH_X64)
#define V8_TURBOFAN_TARGET 1
#else
#define V8_TURBOFAN_TARGET 0
=======================================
--- /trunk/src/heap/heap.cc Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/heap/heap.cc Wed Aug 13 00:04:54 2014 UTC
@@ -2834,7 +2834,7 @@
// Allocate the dictionary of intrinsic function names.
Handle<NameDictionary> intrinsic_names =
- NameDictionary::New(isolate(), Runtime::kNumFunctions);
+ NameDictionary::New(isolate(), Runtime::kNumFunctions, TENURED);
Runtime::InitializeIntrinsicFunctionNames(isolate(), intrinsic_names);
set_intrinsic_function_names(*intrinsic_names);
=======================================
--- /trunk/src/hydrogen-instructions.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/hydrogen-instructions.h Wed Aug 13 00:04:54 2014 UTC
@@ -551,7 +551,7 @@
return IsShl() || IsShr() || IsSar();
}
- HValue(HType type = HType::Tagged())
+ explicit HValue(HType type = HType::Tagged())
: block_(NULL),
id_(kNoNumber),
type_(type),
@@ -1205,7 +1205,7 @@
DECLARE_ABSTRACT_INSTRUCTION(Instruction)
protected:
- HInstruction(HType type = HType::Tagged())
+ explicit HInstruction(HType type = HType::Tagged())
: HValue(type),
next_(NULL),
previous_(NULL),
@@ -1238,7 +1238,8 @@
}
protected:
- HTemplateInstruction(HType type = HType::Tagged()) : HInstruction(type)
{}
+ explicit HTemplateInstruction(HType type = HType::Tagged())
+ : HInstruction(type) {}
virtual void InternalSetOperandAt(int i, HValue* value) V8_FINAL
V8_OVERRIDE {
inputs_[i] = value;
@@ -1598,7 +1599,7 @@
class HUnaryOperation : public HTemplateInstruction<1> {
public:
- HUnaryOperation(HValue* value, HType type = HType::Tagged())
+ explicit HUnaryOperation(HValue* value, HType type = HType::Tagged())
: HTemplateInstruction<1>(type) {
SetOperandAt(0, value);
}
@@ -2716,7 +2717,7 @@
}
private:
- HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
+ explicit HLoadRoot(Heap::RootListIndex index, HType type =
HType::Tagged())
: HTemplateInstruction<0>(type), index_(index) {
SetFlag(kUseGVN);
// TODO(bmeurer): We'll need kDependsOnRoots once we add the
@@ -3706,7 +3707,8 @@
private:
friend class HGraph;
- HConstant(Handle<Object> handle, Representation r =
Representation::None());
+ explicit HConstant(Handle<Object> handle,
+ Representation r = Representation::None());
HConstant(int32_t value,
Representation r = Representation::None(),
bool is_not_in_new_space = true,
=======================================
--- /trunk/src/hydrogen.cc Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/hydrogen.cc Wed Aug 13 00:04:54 2014 UTC
@@ -7439,8 +7439,8 @@
class FunctionSorter {
public:
- FunctionSorter(int index = 0, int ticks = 0, int size = 0)
- : index_(index), ticks_(ticks), size_(size) { }
+ explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
+ : index_(index), ticks_(ticks), size_(size) {}
int index() const { return index_; }
int ticks() const { return ticks_; }
=======================================
--- /trunk/src/ia32/lithium-ia32.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/ia32/lithium-ia32.h Wed Aug 13 00:04:54 2014 UTC
@@ -409,7 +409,7 @@
class LDummy V8_FINAL : public LTemplateInstruction<1, 0, 0> {
public:
- explicit LDummy() { }
+ LDummy() {}
DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
};
=======================================
--- /trunk/src/interpreter-irregexp.cc Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/interpreter-irregexp.cc Wed Aug 13 00:04:54 2014 UTC
@@ -136,9 +136,7 @@
// matching terminates.
class BacktrackStack {
public:
- explicit BacktrackStack() {
- data_ = NewArray<int>(kBacktrackStackSize);
- }
+ BacktrackStack() { data_ = NewArray<int>(kBacktrackStackSize); }
~BacktrackStack() {
DeleteArray(data_);
=======================================
--- /trunk/src/libplatform/worker-thread.cc Tue Jul 1 11:58:10 2014 UTC
+++ /trunk/src/libplatform/worker-thread.cc Wed Aug 13 00:04:54 2014 UTC
@@ -11,7 +11,7 @@
namespace platform {
WorkerThread::WorkerThread(TaskQueue* queue)
- : Thread("V8 WorkerThread"), queue_(queue) {
+ : Thread(Options("V8 WorkerThread")), queue_(queue) {
Start();
}
=======================================
--- /trunk/src/log.cc Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/log.cc Wed Aug 13 00:04:54 2014 UTC
@@ -693,7 +693,7 @@
// Profiler implementation.
//
Profiler::Profiler(Isolate* isolate)
- : base::Thread("v8:Profiler"),
+ : base::Thread(Options("v8:Profiler")),
isolate_(isolate),
head_(0),
tail_(0),
@@ -701,8 +701,7 @@
buffer_semaphore_(0),
engaged_(false),
running_(false),
- paused_(false) {
-}
+ paused_(false) {}
void Profiler::Engage() {
=======================================
--- /trunk/src/lookup.h Thu Aug 7 08:39:21 2014 UTC
+++ /trunk/src/lookup.h Wed Aug 13 00:04:54 2014 UTC
@@ -47,7 +47,7 @@
LookupIterator(Handle<Object> receiver,
Handle<Name> name,
Configuration configuration = CHECK_ALL)
- : configuration_(configuration),
+ : configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
property_kind_(DATA),
property_encoding_(DESCRIPTOR),
@@ -66,7 +66,7 @@
Handle<Name> name,
Handle<JSReceiver> holder,
Configuration configuration = CHECK_ALL)
- : configuration_(configuration),
+ : configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
property_kind_(DATA),
property_encoding_(DESCRIPTOR),
@@ -186,6 +186,15 @@
DCHECK_EQ(DICTIONARY, property_encoding_);
return number_;
}
+
+ static Configuration ComputeConfiguration(
+ Configuration configuration, Handle<Name> name) {
+ if (name->IsOwn()) {
+ return static_cast<Configuration>(configuration & CHECK_OWN);
+ } else {
+ return configuration;
+ }
+ }
Configuration configuration_;
State state_;
=======================================
--- /trunk/src/macro-assembler.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/macro-assembler.h Wed Aug 13 00:04:54 2014 UTC
@@ -47,42 +47,42 @@
#include "src/assembler.h"
#include "src/x64/assembler-x64.h"
#include "src/x64/assembler-x64-inl.h"
-#include "src/code.h" // must be after assembler_*.h
+#include "src/code.h" // NOLINT, must be after assembler_*.h
#include "src/x64/macro-assembler-x64.h"
#elif V8_TARGET_ARCH_ARM64
#include "src/arm64/constants-arm64.h"
#include "src/assembler.h"
#include "src/arm64/assembler-arm64.h" // NOLINT
#include "src/arm64/assembler-arm64-inl.h"
-#include "src/code.h" // must be after assembler_*.h
-#include "src/arm64/macro-assembler-arm64.h"
+#include "src/code.h" // NOLINT, must be after assembler_*.h
+#include "src/arm64/macro-assembler-arm64.h" // NOLINT
#include "src/arm64/macro-assembler-arm64-inl.h"
#elif V8_TARGET_ARCH_ARM
#include "src/arm/constants-arm.h"
#include "src/assembler.h"
#include "src/arm/assembler-arm.h" // NOLINT
#include "src/arm/assembler-arm-inl.h"
-#include "src/code.h" // must be after assembler_*.h
-#include "src/arm/macro-assembler-arm.h"
+#include "src/code.h" // NOLINT, must be after
assembler_*.h
+#include "src/arm/macro-assembler-arm.h" // NOLINT
#elif V8_TARGET_ARCH_MIPS
#include "src/mips/constants-mips.h"
-#include "src/assembler.h"
+#include "src/assembler.h" // NOLINT
#include "src/mips/assembler-mips.h" // NOLINT
#include "src/mips/assembler-mips-inl.h"
-#include "src/code.h" // must be after assembler_*.h
+#include "src/code.h" // NOLINT, must be after assembler_*.h
#include "src/mips/macro-assembler-mips.h"
#elif V8_TARGET_ARCH_MIPS64
#include "src/mips64/constants-mips64.h"
-#include "src/assembler.h"
+#include "src/assembler.h" // NOLINT
#include "src/mips64/assembler-mips64.h" // NOLINT
#include "src/mips64/assembler-mips64-inl.h"
-#include "src/code.h" // must be after assembler_*.h
+#include "src/code.h" // NOLINT, must be after assembler_*.h
#include "src/mips64/macro-assembler-mips64.h"
#elif V8_TARGET_ARCH_X87
#include "src/assembler.h"
#include "src/x87/assembler-x87.h"
#include "src/x87/assembler-x87-inl.h"
-#include "src/code.h" // must be after assembler_*.h
+#include "src/code.h" // NOLINT, must be after assembler_*.h
#include "src/x87/macro-assembler-x87.h"
#else
#error Unsupported target architecture.
=======================================
--- /trunk/src/math.js Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/math.js Wed Aug 13 00:04:54 2014 UTC
@@ -346,26 +346,6 @@
return MathExp(x) - 1;
}
}
-
-// ES6 draft 09-27-13, section 20.2.2.20.
-// Use Taylor series to approximate. With y = x + 1;
-// log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ...
-// == 0 + x - x^2/2 + x^3/3 ...
-// The closer x is to 0, the fewer terms are required.
-function MathLog1p(x) {
- if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
- var xabs = MathAbs(x);
- if (xabs < 1E-7) {
- return x * (1 - x * (1/2));
- } else if (xabs < 3E-5) {
- return x * (1 - x * (1/2 - x * (1/3)));
- } else if (xabs < 7E-3) {
- return x * (1 - x * (1/2 - x * (1/3 - x * (1/4 -
- x * (1/5 - x * (1/6 - x * (1/7)))))));
- } else { // Use regular log if not close enough to 0.
- return MathLog(1 + x);
- }
-}
// -------------------------------------------------------------------
@@ -428,7 +408,7 @@
"fround", MathFroundJS,
"clz32", MathClz32,
"cbrt", MathCbrt,
- "log1p", MathLog1p,
+ "log1p", MathLog1p, // implemented by third_party/fdlibm
"expm1", MathExpm1
));
=======================================
--- /trunk/src/mips/lithium-mips.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/mips/lithium-mips.h Wed Aug 13 00:04:54 2014 UTC
@@ -411,7 +411,7 @@
class LDummy V8_FINAL : public LTemplateInstruction<1, 0, 0> {
public:
- explicit LDummy() { }
+ LDummy() {}
DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
};
=======================================
--- /trunk/src/mips64/lithium-mips64.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/mips64/lithium-mips64.h Wed Aug 13 00:04:54 2014 UTC
@@ -410,7 +410,7 @@
class LDummy V8_FINAL : public LTemplateInstruction<1, 0, 0> {
public:
- explicit LDummy() { }
+ LDummy() {}
DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
};
=======================================
--- /trunk/src/objects-inl.h Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/objects-inl.h Wed Aug 13 00:04:54 2014 UTC
@@ -3372,6 +3372,7 @@
ACCESSORS(Symbol, name, Object, kNameOffset)
ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
+BOOL_ACCESSORS(Symbol, flags, is_own, kOwnBit)
bool String::Equals(String* other) {
@@ -6495,6 +6496,10 @@
// Slow case: compute hash code and set it. Has to be a string.
return String::cast(this)->ComputeAndSetHash();
}
+
+bool Name::IsOwn() {
+ return this->IsSymbol() && Symbol::cast(this)->is_own();
+}
StringHasher::StringHasher(int length, uint32_t seed)
=======================================
--- /trunk/src/objects-printer.cc Fri Aug 8 15:46:17 2014 UTC
+++ /trunk/src/objects-printer.cc Wed Aug 13 00:04:54 2014 UTC
@@ -430,7 +430,8 @@
HeapObject::PrintHeader(os, "Symbol");
os << " - hash: " << Hash();
os << "\n - name: " << Brief(name());
- os << " - private: " << is_private();
+ os << "\n - private: " << is_private();
+ os << "\n - own: " << is_own();
os << "\n";
}
=======================================
--- /trunk/src/objects.cc Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/objects.cc Wed Aug 13 00:04:54 2014 UTC
@@ -3560,6 +3560,11 @@
void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name,
LookupResult* result) {
+ if (name->IsOwn()) {
+ result->NotFound();
+ return;
+ }
+
DisallowHeapAllocation no_gc;
Isolate* isolate = GetIsolate();
for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd();
iter.Advance()) {
@@ -6107,7 +6112,7 @@
}
js_object->LookupOwnRealNamedProperty(name, result);
- if (result->IsFound() || !search_hidden_prototypes) return;
+ if (result->IsFound() || name->IsOwn() || !search_hidden_prototypes)
return;
PrototypeIterator iter(GetIsolate(), js_object);
if (!iter.GetCurrent()->IsJSReceiver()) return;
@@ -6126,6 +6131,10 @@
!iter.IsAtEnd(); iter.Advance()) {
JSReceiver::cast(iter.GetCurrent())->LookupOwn(name, result, false);
if (result->IsFound()) return;
+ if (name->IsOwn()) {
+ result->NotFound();
+ return;
+ }
}
result->NotFound();
}
=======================================
--- /trunk/src/objects.h Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/objects.h Wed Aug 13 00:04:54 2014 UTC
@@ -8954,6 +8954,9 @@
// Conversion.
inline bool AsArrayIndex(uint32_t* index);
+ // Whether name can only name own properties.
+ inline bool IsOwn();
+
DECLARE_CAST(Name)
DECLARE_PRINTER(Name)
@@ -9029,6 +9032,10 @@
// [is_private]: whether this is a private symbol.
DECL_BOOLEAN_ACCESSORS(is_private)
+ // [is_own]: whether this is an own symbol, that is, only used to
designate
+ // own properties of objects.
+ DECL_BOOLEAN_ACCESSORS(is_own)
+
DECLARE_CAST(Symbol)
// Dispatched behavior.
@@ -9044,6 +9051,7 @@
private:
static const int kPrivateBit = 0;
+ static const int kOwnBit = 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(Symbol);
};
=======================================
--- /trunk/src/optimizing-compiler-thread.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/optimizing-compiler-thread.h Wed Aug 13 00:04:54 2014 UTC
@@ -22,22 +22,22 @@
class OptimizingCompilerThread : public base::Thread {
public:
- explicit OptimizingCompilerThread(Isolate *isolate) :
- Thread("OptimizingCompilerThread"),
+ explicit OptimizingCompilerThread(Isolate* isolate)
+ : Thread(Options("OptimizingCompilerThread")),
#ifdef DEBUG
- thread_id_(0),
+ thread_id_(0),
#endif
- isolate_(isolate),
- stop_semaphore_(0),
- input_queue_semaphore_(0),
- input_queue_capacity_(FLAG_concurrent_recompilation_queue_length),
- input_queue_length_(0),
- input_queue_shift_(0),
- osr_buffer_capacity_(FLAG_concurrent_recompilation_queue_length + 4),
- osr_buffer_cursor_(0),
- osr_hits_(0),
- osr_attempts_(0),
- blocked_jobs_(0) {
+ isolate_(isolate),
+ stop_semaphore_(0),
+ input_queue_semaphore_(0),
+ input_queue_capacity_(FLAG_concurrent_recompilation_queue_length),
+ input_queue_length_(0),
+ input_queue_shift_(0),
+ osr_buffer_capacity_(FLAG_concurrent_recompilation_queue_length +
4),
+ osr_buffer_cursor_(0),
+ osr_hits_(0),
+ osr_attempts_(0),
+ blocked_jobs_(0) {
base::NoBarrier_Store(&stop_thread_,
static_cast<base::AtomicWord>(CONTINUE));
input_queue_ = NewArray<OptimizedCompileJob*>(input_queue_capacity_);
=======================================
--- /trunk/src/runtime.cc Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/runtime.cc Wed Aug 13 00:04:54 2014 UTC
@@ -606,6 +606,17 @@
if (name->IsString()) symbol->set_name(*name);
return *symbol;
}
+
+
+RUNTIME_FUNCTION(Runtime_CreatePrivateOwnSymbol) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
+ RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
+ Handle<Symbol> symbol = isolate->factory()->NewPrivateOwnSymbol();
+ if (name->IsString()) symbol->set_name(*name);
+ return *symbol;
+}
RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) {
=======================================
--- /trunk/src/runtime.h Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/runtime.h Wed Aug 13 00:04:54 2014 UTC
@@ -260,6 +260,7 @@
F(CreateSymbol, 1, 1) \
F(CreatePrivateSymbol, 1, 1) \
F(CreateGlobalPrivateSymbol, 1, 1) \
+ F(CreatePrivateOwnSymbol, 1, 1) \
F(NewSymbolWrapper, 1, 1) \
F(SymbolDescription, 1, 1) \
F(SymbolRegistry, 0, 1) \
=======================================
--- /trunk/src/splay-tree.h Wed Jun 4 00:06:13 2014 UTC
+++ /trunk/src/splay-tree.h Wed Aug 13 00:04:54 2014 UTC
@@ -35,8 +35,8 @@
class Locator;
- SplayTree(AllocationPolicy allocator = AllocationPolicy())
- : root_(NULL), allocator_(allocator) { }
+ explicit SplayTree(AllocationPolicy allocator = AllocationPolicy())
+ : root_(NULL), allocator_(allocator) {}
~SplayTree();
INLINE(void* operator new(size_t size,
=======================================
--- /trunk/src/unique.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/unique.h Wed Aug 13 00:04:54 2014 UTC
@@ -174,7 +174,7 @@
return PrintableUnique<T>(zone, reinterpret_cast<Address>(*handle),
handle);
}
- const char* string() { return string_; }
+ const char* string() const { return string_; }
private:
const char* string_;
=======================================
--- /trunk/src/version.cc Tue Aug 12 15:33:05 2014 UTC
+++ /trunk/src/version.cc Wed Aug 13 00:04:54 2014 UTC
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 28
-#define BUILD_NUMBER 71
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 73
+#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
=======================================
--- /trunk/src/x64/lithium-x64.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/x64/lithium-x64.h Wed Aug 13 00:04:54 2014 UTC
@@ -419,7 +419,7 @@
class LDummy V8_FINAL : public LTemplateInstruction<1, 0, 0> {
public:
- explicit LDummy() { }
+ LDummy() {}
DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
};
=======================================
***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.