Revision: 24919
Author: bmeu...@chromium.org
Date: Tue Oct 28 08:33:52 2014 UTC
Log: [turbofan] Improve typed lowering for JSToBoolean.
- JSToBoolean(x:string) => BooleanNot(NumberEqual(x.length, #0))
- JSToBoolean(phi(x1,...,xn):primitive) =>
phi(JSToBoolean(x1),...,JSToBoolean(xn))
TEST=cctest,mjsunit/asm/do-while,mjsunit/boolean,unittests
R=dcar...@chromium.org
Review URL: https://codereview.chromium.org/681223002
https://code.google.com/p/v8/source/detail?r=24919
Added:
/branches/bleeding_edge/test/mjsunit/asm/do-while.js
Modified:
/branches/bleeding_edge/src/compiler/access-builder.cc
/branches/bleeding_edge/src/compiler/access-builder.h
/branches/bleeding_edge/src/compiler/js-typed-lowering.cc
/branches/bleeding_edge/test/cctest/compiler/test-js-typed-lowering.cc
/branches/bleeding_edge/test/mjsunit/boolean.js
/branches/bleeding_edge/test/unittests/compiler/js-typed-lowering-unittest.cc
/branches/bleeding_edge/test/unittests/compiler/node-test-utils.cc
/branches/bleeding_edge/test/unittests/compiler/node-test-utils.h
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/asm/do-while.js Tue Oct 28
08:33:52 2014 UTC
@@ -0,0 +1,30 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, buffer) {
+ "use asm";
+ function f(i) {
+ var j;
+ i = i|0;
+ do {
+ if (i > 0) {
+ j = i != 0;
+ i = (i - 1) | 0;
+ } else {
+ j = 0;
+ }
+ } while (j);
+ return i;
+ }
+ return {f:f};
+}
+
+var m = Module(this, {}, new ArrayBuffer(64*1024));
+
+assertEquals(-1, m.f("-1"));
+assertEquals(0, m.f(-Math.infinity));
+assertEquals(0, m.f(undefined));
+assertEquals(0, m.f(0));
+assertEquals(0, m.f(1));
+assertEquals(0, m.f(100));
=======================================
--- /branches/bleeding_edge/src/compiler/access-builder.cc Mon Oct 20
07:56:50 2014 UTC
+++ /branches/bleeding_edge/src/compiler/access-builder.cc Tue Oct 28
08:33:52 2014 UTC
@@ -56,6 +56,13 @@
return {kTaggedBase, Map::kInstanceTypeOffset, Handle<Name>(),
Type::UntaggedInt8(), kMachUint8};
}
+
+
+// static
+FieldAccess AccessBuilder::ForStringLength() {
+ return {kTaggedBase, String::kLengthOffset, Handle<Name>(),
+ Type::SignedSmall(), kMachAnyTagged};
+}
// static
=======================================
--- /branches/bleeding_edge/src/compiler/access-builder.h Mon Oct 20
07:56:50 2014 UTC
+++ /branches/bleeding_edge/src/compiler/access-builder.h Tue Oct 28
08:33:52 2014 UTC
@@ -37,6 +37,9 @@
// Provides access to Map::instance_type() field.
static FieldAccess ForMapInstanceType();
+ // Provides access to String::length() field.
+ static FieldAccess ForStringLength();
+
// Provides access to JSValue::value() field.
static FieldAccess ForValue();
=======================================
--- /branches/bleeding_edge/src/compiler/js-typed-lowering.cc Tue Oct 28
08:28:36 2014 UTC
+++ /branches/bleeding_edge/src/compiler/js-typed-lowering.cc Tue Oct 28
08:33:52 2014 UTC
@@ -546,7 +546,38 @@
Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
return ReplaceWith(inv);
}
- // TODO(turbofan): js-typed-lowering of ToBoolean(string)
+ if (input_type->Is(Type::String())) {
+ // JSToBoolean(x:string) => BooleanNot(NumberEqual(x.length, #0))
+ FieldAccess access = AccessBuilder::ForStringLength();
+ Node* length = graph()->NewNode(simplified()->LoadField(access), input,
+ graph()->start(), graph()->start());
+ Node* cmp = graph()->NewNode(simplified()->NumberEqual(), length,
+ jsgraph()->ZeroConstant());
+ Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
+ return ReplaceWith(inv);
+ }
+ if (input->opcode() == IrOpcode::kPhi &&
input_type->Is(Type::Primitive())) {
+ // JSToBoolean(phi(x1,...,xn):primitive)
+ // => phi(JSToBoolean(x1),...,JSToBoolean(xn))
+ int input_count = input->InputCount() - 1;
+ Node** inputs = zone()->NewArray<Node*>(input_count + 1);
+ for (int i = 0; i < input_count; ++i) {
+ Node* value = input->InputAt(i);
+ // Recursively try to reduce the value first.
+ Reduction result = ReduceJSToBooleanInput(value);
+ if (result.Changed()) {
+ inputs[i] = result.replacement();
+ } else {
+ inputs[i] = graph()->NewNode(javascript()->ToBoolean(), value,
+ jsgraph()->ZeroConstant(),
+ graph()->start(), graph()->start());
+ }
+ }
+ inputs[input_count] = input->InputAt(input_count);
+ Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged,
input_count),
+ input_count + 1, inputs);
+ return ReplaceWith(phi);
+ }
return NoChange();
}
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-js-typed-lowering.cc
Thu Oct 16 11:31:00 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/test-js-typed-lowering.cc
Tue Oct 28 08:33:52 2014 UTC
@@ -508,8 +508,12 @@
{ // ToBoolean(string)
Node* r = R.ReduceUnop(op, Type::String());
- // TODO(titzer): test will break with better js-typed-lowering
- CHECK_EQ(IrOpcode::kJSToBoolean, r->opcode());
+ CHECK_EQ(IrOpcode::kBooleanNot, r->opcode());
+ Node* i = r->InputAt(0);
+ CHECK_EQ(IrOpcode::kNumberEqual, i->opcode());
+ Node* j = i->InputAt(0);
+ CHECK_EQ(IrOpcode::kLoadField, j->opcode());
+ // ToBoolean(x:string) => BooleanNot(NumberEqual(x.length, #0))
}
{ // ToBoolean(object)
=======================================
--- /branches/bleeding_edge/test/mjsunit/boolean.js Wed Jun 15 13:33:10
2011 UTC
+++ /branches/bleeding_edge/test/mjsunit/boolean.js Tue Oct 28 08:33:52
2014 UTC
@@ -72,3 +72,10 @@
assertEquals('foo', o.p || (o.p == 0));
assertEquals('foo', o.p || (o.p == null));
assertEquals('foo', o.p || (o.p == o.p));
+
+// JSToBoolean(x:string)
+function f(x) { return !!("" + x); }
+assertEquals(false, f(""));
+assertEquals(true, f("narf"));
+assertEquals(true, f(12345678));
+assertEquals(true, f(undefined));
=======================================
---
/branches/bleeding_edge/test/unittests/compiler/js-typed-lowering-unittest.cc
Tue Oct 28 08:28:36 2014 UTC
+++
/branches/bleeding_edge/test/unittests/compiler/js-typed-lowering-unittest.cc
Tue Oct 28 08:33:52 2014 UTC
@@ -66,6 +66,46 @@
private:
JSOperatorBuilder javascript_;
};
+
+
+//
-----------------------------------------------------------------------------
+// JSToBoolean
+
+
+TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
+ Node* input = Parameter(Type::String());
+ Node* context = UndefinedConstant();
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+
+ Reduction r = Reduce(graph()->NewNode(javascript()->ToBoolean(), input,
+ context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsBooleanNot(IsNumberEqual(
+ IsLoadField(AccessBuilder::ForStringLength(), input,
+ graph()->start(), graph()->start()),
+ IsNumberConstant(0))));
+}
+
+
+TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumberAndBoolean) {
+ Node* p0 = Parameter(Type::OrderedNumber(), 0);
+ Node* p1 = Parameter(Type::Boolean(), 1);
+ Node* context = UndefinedConstant();
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(),
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 2), p0, p1, control),
+ context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsPhi(kMachAnyTagged,
+ IsBooleanNot(IsNumberEqual(p0, IsNumberConstant(0))), p1,
control));
+}
//
-----------------------------------------------------------------------------
=======================================
--- /branches/bleeding_edge/test/unittests/compiler/node-test-utils.cc Mon
Oct 20 11:26:23 2014 UTC
+++ /branches/bleeding_edge/test/unittests/compiler/node-test-utils.cc Tue
Oct 28 08:33:52 2014 UTC
@@ -355,11 +355,13 @@
public:
IsLoadFieldMatcher(const Matcher<FieldAccess>& access_matcher,
const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& effect_matcher)
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher)
: NodeMatcher(IrOpcode::kLoadField),
access_matcher_(access_matcher),
base_matcher_(base_matcher),
- effect_matcher_(effect_matcher) {}
+ effect_matcher_(effect_matcher),
+ control_matcher_(control_matcher) {}
virtual void DescribeTo(std::ostream* os) const OVERRIDE {
NodeMatcher::DescribeTo(os);
@@ -367,8 +369,10 @@
access_matcher_.DescribeTo(os);
*os << "), base (";
base_matcher_.DescribeTo(os);
- *os << ") and effect (";
+ *os << "), effect (";
effect_matcher_.DescribeTo(os);
+ *os << ") and control (";
+ control_matcher_.DescribeTo(os);
*os << ")";
}
@@ -380,13 +384,16 @@
PrintMatchAndExplain(NodeProperties::GetValueInput(node,
0), "base",
base_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
- effect_matcher_, listener));
+ effect_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetControlInput(node),
+ "control", control_matcher_, listener));
}
private:
const Matcher<FieldAccess> access_matcher_;
const Matcher<Node*> base_matcher_;
const Matcher<Node*> effect_matcher_;
+ const Matcher<Node*> control_matcher_;
};
@@ -795,9 +802,10 @@
Matcher<Node*> IsLoadField(const Matcher<FieldAccess>& access_matcher,
const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& effect_matcher) {
- return MakeMatcher(
- new IsLoadFieldMatcher(access_matcher, base_matcher,
effect_matcher));
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher) {
+ return MakeMatcher(new IsLoadFieldMatcher(access_matcher, base_matcher,
+ effect_matcher,
control_matcher));
}
@@ -854,6 +862,7 @@
return MakeMatcher( \
new IsBinopMatcher(IrOpcode::k##Name, lhs_matcher, rhs_matcher)); \
}
+IS_BINOP_MATCHER(NumberEqual)
IS_BINOP_MATCHER(NumberLessThan)
IS_BINOP_MATCHER(NumberSubtract)
IS_BINOP_MATCHER(Word32And)
@@ -881,6 +890,7 @@
Matcher<Node*> Is##Name(const Matcher<Node*>& input_matcher)
{ \
return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name,
input_matcher)); \
}
+IS_UNOP_MATCHER(BooleanNot)
IS_UNOP_MATCHER(ChangeFloat64ToInt32)
IS_UNOP_MATCHER(ChangeFloat64ToUint32)
IS_UNOP_MATCHER(ChangeInt32ToFloat64)
=======================================
--- /branches/bleeding_edge/test/unittests/compiler/node-test-utils.h Mon
Oct 20 11:26:23 2014 UTC
+++ /branches/bleeding_edge/test/unittests/compiler/node-test-utils.h Tue
Oct 28 08:33:52 2014 UTC
@@ -62,13 +62,17 @@
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsBooleanNot(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberEqual(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsNumberLessThan(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsNumberSubtract(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsLoadField(const Matcher<FieldAccess>& access_matcher,
const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& effect_matcher);
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher);
Matcher<Node*> IsLoadElement(const Matcher<ElementAccess>& access_matcher,
const Matcher<Node*>& base_matcher,
const Matcher<Node*>& index_matcher,
--
--
v8-dev mailing list
v8-dev@googlegroups.com
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 v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.