V8 Project
js-builtin-reducer-unittest.cc
Go to the documentation of this file.
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
9 #include "src/compiler/typer.h"
10 #include "testing/gmock-support.h"
11 
12 using testing::Capture;
13 
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17 
19  public:
21 
22  protected:
23  Reduction Reduce(Node* node) {
24  Typer typer(zone());
25  MachineOperatorBuilder machine;
26  JSGraph jsgraph(graph(), common(), javascript(), &typer, &machine);
27  JSBuiltinReducer reducer(&jsgraph);
28  return reducer.Reduce(node);
29  }
30 
31  Node* Parameter(Type* t, int32_t index = 0) {
32  Node* n = graph()->NewNode(common()->Parameter(index), graph()->start());
34  return n;
35  }
36 
38  return HeapConstant(
39  Unique<HeapObject>::CreateImmovable(factory()->undefined_value()));
40  }
41 
43 
44  private:
46 };
47 
48 
49 namespace {
50 
51 // TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering.
52 Type* const kNumberTypes[] = {
53  Type::UnsignedSmall(), Type::OtherSignedSmall(), Type::OtherUnsigned31(),
54  Type::OtherUnsigned32(), Type::OtherSigned32(), Type::SignedSmall(),
55  Type::Signed32(), Type::Unsigned32(), Type::Integral32(),
56  Type::MinusZero(), Type::NaN(), Type::OtherNumber(),
57  Type::OrderedNumber(), Type::Number()};
58 
59 } // namespace
60 
61 
62 // -----------------------------------------------------------------------------
63 // Math.abs
64 
65 
67  Handle<JSFunction> f(isolate()->context()->math_abs_fun());
68 
69  TRACED_FOREACH(Type*, t0, kNumberTypes) {
70  Node* p0 = Parameter(t0, 0);
71  Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
72  Node* call = graph()->NewNode(javascript()->Call(3, NO_CALL_FUNCTION_FLAGS),
73  fun, UndefinedConstant(), p0);
74  Reduction r = Reduce(call);
75 
76  if (t0->Is(Type::Unsigned32())) {
77  ASSERT_TRUE(r.Changed());
78  EXPECT_THAT(r.replacement(), p0);
79  } else {
80  Capture<Node*> branch;
81  ASSERT_TRUE(r.Changed());
82  EXPECT_THAT(
83  r.replacement(),
85  IsMerge(IsIfTrue(CaptureEq(&branch)),
86  IsIfFalse(AllOf(
87  CaptureEq(&branch),
89  graph()->start()))))));
90  }
91  }
92 }
93 
94 
95 // -----------------------------------------------------------------------------
96 // Math.sqrt
97 
98 
100  Handle<JSFunction> f(isolate()->context()->math_sqrt_fun());
101 
102  TRACED_FOREACH(Type*, t0, kNumberTypes) {
103  Node* p0 = Parameter(t0, 0);
104  Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
105  Node* call = graph()->NewNode(javascript()->Call(3, NO_CALL_FUNCTION_FLAGS),
106  fun, UndefinedConstant(), p0);
107  Reduction r = Reduce(call);
108 
109  ASSERT_TRUE(r.Changed());
110  EXPECT_THAT(r.replacement(), IsFloat64Sqrt(p0));
111  }
112 }
113 
114 
115 // -----------------------------------------------------------------------------
116 // Math.max
117 
118 
120  Handle<JSFunction> f(isolate()->context()->math_max_fun());
121 
122  Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
123  Node* call = graph()->NewNode(javascript()->Call(2, NO_CALL_FUNCTION_FLAGS),
124  fun, UndefinedConstant());
125  Reduction r = Reduce(call);
126 
127  ASSERT_TRUE(r.Changed());
128  EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
129 }
130 
131 
133  Handle<JSFunction> f(isolate()->context()->math_max_fun());
134 
135  TRACED_FOREACH(Type*, t0, kNumberTypes) {
136  Node* p0 = Parameter(t0, 0);
137  Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
138  Node* call = graph()->NewNode(javascript()->Call(3, NO_CALL_FUNCTION_FLAGS),
139  fun, UndefinedConstant(), p0);
140  Reduction r = Reduce(call);
141 
142  ASSERT_TRUE(r.Changed());
143  EXPECT_THAT(r.replacement(), p0);
144  }
145 }
146 
147 
149  Handle<JSFunction> f(isolate()->context()->math_max_fun());
150 
151  TRACED_FOREACH(Type*, t0, kNumberTypes) {
152  TRACED_FOREACH(Type*, t1, kNumberTypes) {
153  Node* p0 = Parameter(t0, 0);
154  Node* p1 = Parameter(t1, 1);
155  Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
156  Node* call =
157  graph()->NewNode(javascript()->Call(4, NO_CALL_FUNCTION_FLAGS), fun,
158  UndefinedConstant(), p0, p1);
159  Reduction r = Reduce(call);
160 
161  if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) {
162  Capture<Node*> branch;
163  ASSERT_TRUE(r.Changed());
164  EXPECT_THAT(
165  r.replacement(),
166  IsPhi(kMachNone, p1, p0,
167  IsMerge(IsIfTrue(CaptureEq(&branch)),
168  IsIfFalse(AllOf(CaptureEq(&branch),
170  graph()->start()))))));
171  } else {
172  ASSERT_FALSE(r.Changed());
173  EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode());
174  }
175  }
176  }
177 }
178 
179 
180 // -----------------------------------------------------------------------------
181 // Math.imul
182 
183 
185  Handle<JSFunction> f(isolate()->context()->math_imul_fun());
186 
187  TRACED_FOREACH(Type*, t0, kNumberTypes) {
188  TRACED_FOREACH(Type*, t1, kNumberTypes) {
189  Node* p0 = Parameter(t0, 0);
190  Node* p1 = Parameter(t1, 1);
191  Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
192  Node* call =
193  graph()->NewNode(javascript()->Call(4, NO_CALL_FUNCTION_FLAGS), fun,
194  UndefinedConstant(), p0, p1);
195  Reduction r = Reduce(call);
196 
197  if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) {
198  ASSERT_TRUE(r.Changed());
199  EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
200  } else {
201  ASSERT_FALSE(r.Changed());
202  EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode());
203  }
204  }
205  }
206 }
207 
208 
209 // -----------------------------------------------------------------------------
210 // Math.fround
211 
212 
214  Handle<Object> m =
215  JSObject::GetProperty(isolate()->global_object(),
216  isolate()->factory()->NewStringFromAsciiChecked(
217  "Math")).ToHandleChecked();
219  JSObject::GetProperty(m, isolate()->factory()->NewStringFromAsciiChecked(
220  "fround")).ToHandleChecked());
221 
222  TRACED_FOREACH(Type*, t0, kNumberTypes) {
223  Node* p0 = Parameter(t0, 0);
224  Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
225  Node* call = graph()->NewNode(javascript()->Call(3, NO_CALL_FUNCTION_FLAGS),
226  fun, UndefinedConstant(), p0);
227  Reduction r = Reduce(call);
228 
229  ASSERT_TRUE(r.Changed());
230  EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
231  }
232 }
233 
234 } // namespace compiler
235 } // namespace internal
236 } // namespace v8
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116
static MUST_USE_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it)
Definition: objects.cc:109
Factory * factory() const
Definition: test-utils.cc:52
CommonOperatorBuilder * common()
Node * HeapConstant(const Unique< HeapObject > &value)
Node * NewNode(const Operator *op, int input_count, Node **inputs)
Definition: graph.cc:24
static void SetBounds(Node *node, Bounds bounds)
#define V8_INFINITY
Definition: globals.h:25
int int32_t
Definition: unicode.cc:24
Matcher< Node * > IsMerge(const Matcher< Node * > &control0_matcher, const Matcher< Node * > &control1_matcher)
Matcher< Node * > IsTruncateFloat64ToFloat32(const Matcher< Node * > &input_matcher)
Matcher< Node * > IsFloat64Sqrt(const Matcher< Node * > &input_matcher)
Matcher< Node * > IsIfFalse(const Matcher< Node * > &control_matcher)
Matcher< Node * > IsBranch(const Matcher< Node * > &value_matcher, const Matcher< Node * > &control_matcher)
Matcher< Node * > IsNumberLessThan(const Matcher< Node * > &lhs_matcher, const Matcher< Node * > &rhs_matcher)
Matcher< Node * > IsNumberConstant(const Matcher< double > &value_matcher)
Matcher< Node * > IsInt32Mul(const Matcher< Node * > &lhs_matcher, const Matcher< Node * > &rhs_matcher)
Matcher< Node * > IsIfTrue(const Matcher< Node * > &control_matcher)
Matcher< Node * > IsNumberSubtract(const Matcher< Node * > &lhs_matcher, const Matcher< Node * > &rhs_matcher)
Matcher< Node * > IsPhi(const Matcher< MachineType > &type_matcher, const Matcher< Node * > &value0_matcher, const Matcher< Node * > &value1_matcher, const Matcher< Node * > &merge_matcher)
TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter)
BoundsImpl< ZoneTypeConfig > Bounds
Definition: types.h:1047
@ NO_CALL_FUNCTION_FLAGS
Definition: globals.h:469
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ None
Definition: v8.h:2211