• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #include "src/compiler/js-builtin-reducer.h"
6 #include "src/compiler/js-graph.h"
7 #include "src/compiler/node-properties.h"
8 #include "src/compiler/simplified-operator.h"
9 #include "src/compiler/typer.h"
10 #include "src/isolate-inl.h"
11 #include "test/unittests/compiler/graph-unittest.h"
12 #include "test/unittests/compiler/node-test-utils.h"
13 #include "testing/gmock-support.h"
14 
15 using testing::BitEq;
16 using testing::Capture;
17 
18 namespace v8 {
19 namespace internal {
20 namespace compiler {
21 
22 class JSBuiltinReducerTest : public TypedGraphTest {
23  public:
JSBuiltinReducerTest()24   JSBuiltinReducerTest() : javascript_(zone()) {}
25 
26  protected:
Reduce(Node * node,MachineOperatorBuilder::Flags flags=MachineOperatorBuilder::Flag::kNoFlags)27   Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
28                                    MachineOperatorBuilder::Flag::kNoFlags) {
29     MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
30                                    flags);
31     SimplifiedOperatorBuilder simplified(zone());
32     JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
33                     &machine);
34     // TODO(titzer): mock the GraphReducer here for better unit testing.
35     GraphReducer graph_reducer(zone(), graph());
36     JSBuiltinReducer reducer(&graph_reducer, &jsgraph);
37     return reducer.Reduce(node);
38   }
39 
MathFunction(const char * name)40   Node* MathFunction(const char* name) {
41     Handle<Object> m =
42         JSObject::GetProperty(isolate()->global_object(),
43                               isolate()->factory()->NewStringFromAsciiChecked(
44                                   "Math")).ToHandleChecked();
45     Handle<JSFunction> f = Handle<JSFunction>::cast(
46         JSObject::GetProperty(
47             m, isolate()->factory()->NewStringFromAsciiChecked(name))
48             .ToHandleChecked());
49     return HeapConstant(f);
50   }
51 
javascript()52   JSOperatorBuilder* javascript() { return &javascript_; }
53 
54  private:
55   JSOperatorBuilder javascript_;
56 };
57 
58 
59 namespace {
60 
61 Type* const kIntegral32Types[] = {Type::UnsignedSmall(), Type::Negative32(),
62                                   Type::Unsigned31(),    Type::SignedSmall(),
63                                   Type::Signed32(),      Type::Unsigned32(),
64                                   Type::Integral32()};
65 
66 
67 const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
68 
69 
70 // TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering.
71 Type* const kNumberTypes[] = {
72     Type::UnsignedSmall(), Type::Negative32(),  Type::Unsigned31(),
73     Type::SignedSmall(),   Type::Signed32(),    Type::Unsigned32(),
74     Type::Integral32(),    Type::MinusZero(),   Type::NaN(),
75     Type::OrderedNumber(), Type::PlainNumber(), Type::Number()};
76 
77 }  // namespace
78 
79 
80 // -----------------------------------------------------------------------------
81 // Math.max
82 
83 
TEST_F(JSBuiltinReducerTest,MathMax0)84 TEST_F(JSBuiltinReducerTest, MathMax0) {
85   Node* function = MathFunction("max");
86 
87   Node* effect = graph()->start();
88   Node* control = graph()->start();
89   Node* context = UndefinedConstant();
90   Node* frame_state = graph()->start();
91   TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
92     Node* call = graph()->NewNode(javascript()->CallFunction(2, language_mode),
93                                   function, UndefinedConstant(), context,
94                                   frame_state, frame_state, effect, control);
95     Reduction r = Reduce(call);
96 
97     ASSERT_TRUE(r.Changed());
98     EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
99   }
100 }
101 
102 
TEST_F(JSBuiltinReducerTest,MathMax1)103 TEST_F(JSBuiltinReducerTest, MathMax1) {
104   Node* function = MathFunction("max");
105 
106   Node* effect = graph()->start();
107   Node* control = graph()->start();
108   Node* context = UndefinedConstant();
109   Node* frame_state = graph()->start();
110   TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
111     TRACED_FOREACH(Type*, t0, kNumberTypes) {
112       Node* p0 = Parameter(t0, 0);
113       Node* call =
114           graph()->NewNode(javascript()->CallFunction(3, language_mode),
115                            function, UndefinedConstant(), p0, context,
116                            frame_state, frame_state, effect, control);
117       Reduction r = Reduce(call);
118 
119       ASSERT_TRUE(r.Changed());
120       EXPECT_THAT(r.replacement(), p0);
121     }
122   }
123 }
124 
125 
TEST_F(JSBuiltinReducerTest,MathMax2)126 TEST_F(JSBuiltinReducerTest, MathMax2) {
127   Node* function = MathFunction("max");
128 
129   Node* effect = graph()->start();
130   Node* control = graph()->start();
131   Node* context = UndefinedConstant();
132   Node* frame_state = graph()->start();
133   TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
134     TRACED_FOREACH(Type*, t0, kIntegral32Types) {
135       TRACED_FOREACH(Type*, t1, kIntegral32Types) {
136         Node* p0 = Parameter(t0, 0);
137         Node* p1 = Parameter(t1, 1);
138         Node* call =
139             graph()->NewNode(javascript()->CallFunction(4, language_mode),
140                              function, UndefinedConstant(), p0, p1, context,
141                              frame_state, frame_state, effect, control);
142         Reduction r = Reduce(call);
143 
144         ASSERT_TRUE(r.Changed());
145         EXPECT_THAT(r.replacement(),
146                     IsSelect(MachineRepresentation::kNone,
147                              IsNumberLessThan(p1, p0), p0, p1));
148       }
149     }
150   }
151 }
152 
153 
154 // -----------------------------------------------------------------------------
155 // Math.imul
156 
157 
TEST_F(JSBuiltinReducerTest,MathImul)158 TEST_F(JSBuiltinReducerTest, MathImul) {
159   Node* function = MathFunction("imul");
160 
161   Node* effect = graph()->start();
162   Node* control = graph()->start();
163   Node* context = UndefinedConstant();
164   Node* frame_state = graph()->start();
165   TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
166     TRACED_FOREACH(Type*, t0, kIntegral32Types) {
167       TRACED_FOREACH(Type*, t1, kIntegral32Types) {
168         Node* p0 = Parameter(t0, 0);
169         Node* p1 = Parameter(t1, 1);
170         Node* call =
171             graph()->NewNode(javascript()->CallFunction(4, language_mode),
172                              function, UndefinedConstant(), p0, p1, context,
173                              frame_state, frame_state, effect, control);
174         Reduction r = Reduce(call);
175 
176         ASSERT_TRUE(r.Changed());
177         EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
178       }
179     }
180   }
181 }
182 
183 
184 // -----------------------------------------------------------------------------
185 // Math.fround
186 
187 
TEST_F(JSBuiltinReducerTest,MathFround)188 TEST_F(JSBuiltinReducerTest, MathFround) {
189   Node* function = MathFunction("fround");
190 
191   Node* effect = graph()->start();
192   Node* control = graph()->start();
193   Node* context = UndefinedConstant();
194   Node* frame_state = graph()->start();
195   TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
196     TRACED_FOREACH(Type*, t0, kNumberTypes) {
197       Node* p0 = Parameter(t0, 0);
198       Node* call =
199           graph()->NewNode(javascript()->CallFunction(3, language_mode),
200                            function, UndefinedConstant(), p0, context,
201                            frame_state, frame_state, effect, control);
202       Reduction r = Reduce(call);
203 
204       ASSERT_TRUE(r.Changed());
205       EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
206     }
207   }
208 }
209 
210 }  // namespace compiler
211 }  // namespace internal
212 }  // namespace v8
213