js-builtin-reducer-unittest.cc 6.85 KB
Newer Older
1 2 3 4 5 6
// 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/js-builtin-reducer.h"
#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 12
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
13 14
#include "testing/gmock-support.h"

15
using testing::BitEq;
16
using testing::Capture;
17 18 19 20 21

namespace v8 {
namespace internal {
namespace compiler {

22
class JSBuiltinReducerTest : public TypedGraphTest {
23 24 25 26
 public:
  JSBuiltinReducerTest() : javascript_(zone()) {}

 protected:
27 28
  Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
                                   MachineOperatorBuilder::Flag::kNoFlags) {
29
    MachineOperatorBuilder machine(zone(), kMachPtr, flags);
30 31
    SimplifiedOperatorBuilder simplified(zone());
    JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
32
                    &machine);
33 34 35
    // TODO(titzer): mock the GraphReducer here for better unit testing.
    GraphReducer graph_reducer(zone(), graph());
    JSBuiltinReducer reducer(&graph_reducer, &jsgraph);
36 37 38
    return reducer.Reduce(node);
  }

39
  Node* MathFunction(const char* name) {
40 41 42 43 44 45 46 47
    Handle<Object> m =
        JSObject::GetProperty(isolate()->global_object(),
                              isolate()->factory()->NewStringFromAsciiChecked(
                                  "Math")).ToHandleChecked();
    Handle<JSFunction> f = Handle<JSFunction>::cast(
        JSObject::GetProperty(
            m, isolate()->factory()->NewStringFromAsciiChecked(name))
            .ToHandleChecked());
48
    return HeapConstant(f);
49 50
  }

51 52 53 54 55 56 57 58 59
  JSOperatorBuilder* javascript() { return &javascript_; }

 private:
  JSOperatorBuilder javascript_;
};


namespace {

60 61 62 63 64 65 66 67 68
Type* const kIntegral32Types[] = {Type::UnsignedSmall(), Type::Negative32(),
                                  Type::Unsigned31(),    Type::SignedSmall(),
                                  Type::Signed32(),      Type::Unsigned32(),
                                  Type::Integral32()};


const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};


69 70
// TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering.
Type* const kNumberTypes[] = {
71 72 73 74
    Type::UnsignedSmall(), Type::Negative32(),  Type::Unsigned31(),
    Type::SignedSmall(),   Type::Signed32(),    Type::Unsigned32(),
    Type::Integral32(),    Type::MinusZero(),   Type::NaN(),
    Type::OrderedNumber(), Type::PlainNumber(), Type::Number()};
75 76 77 78

}  // namespace


79 80 81 82 83
// -----------------------------------------------------------------------------
// Math.max


TEST_F(JSBuiltinReducerTest, MathMax0) {
84
  Node* function = MathFunction("max");
85

86 87
  Node* effect = graph()->start();
  Node* control = graph()->start();
88
  Node* context = UndefinedConstant();
89
  Node* frame_state = graph()->start();
90
  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
91 92 93
    Node* call = graph()->NewNode(javascript()->CallFunction(2, language_mode),
                                  function, UndefinedConstant(), context,
                                  frame_state, frame_state, effect, control);
94 95
    Reduction r = Reduce(call);

96
    ASSERT_TRUE(r.Changed());
97
    EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
98 99 100 101
  }
}


102 103
TEST_F(JSBuiltinReducerTest, MathMax1) {
  Node* function = MathFunction("max");
104

105 106
  Node* effect = graph()->start();
  Node* control = graph()->start();
107
  Node* context = UndefinedConstant();
108
  Node* frame_state = graph()->start();
109 110
  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
    TRACED_FOREACH(Type*, t0, kNumberTypes) {
111
      Node* p0 = Parameter(t0, 0);
112 113 114 115
      Node* call =
          graph()->NewNode(javascript()->CallFunction(3, language_mode),
                           function, UndefinedConstant(), p0, context,
                           frame_state, frame_state, effect, control);
116 117
      Reduction r = Reduce(call);

118 119 120 121 122 123 124 125 126 127
      ASSERT_TRUE(r.Changed());
      EXPECT_THAT(r.replacement(), p0);
    }
  }
}


TEST_F(JSBuiltinReducerTest, MathMax2) {
  Node* function = MathFunction("max");

128 129
  Node* effect = graph()->start();
  Node* control = graph()->start();
130
  Node* context = UndefinedConstant();
131
  Node* frame_state = graph()->start();
132 133 134 135 136 137
  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
    TRACED_FOREACH(Type*, t0, kIntegral32Types) {
      TRACED_FOREACH(Type*, t1, kIntegral32Types) {
        Node* p0 = Parameter(t0, 0);
        Node* p1 = Parameter(t1, 1);
        Node* call =
138
            graph()->NewNode(javascript()->CallFunction(4, language_mode),
139 140
                             function, UndefinedConstant(), p0, p1, context,
                             frame_state, frame_state, effect, control);
141 142
        Reduction r = Reduce(call);

143
        ASSERT_TRUE(r.Changed());
144
        EXPECT_THAT(r.replacement(),
145
                    IsSelect(kMachNone, IsNumberLessThan(p1, p0), p0, p1));
146 147 148 149 150 151
      }
    }
  }
}


152 153 154 155 156
// -----------------------------------------------------------------------------
// Math.imul


TEST_F(JSBuiltinReducerTest, MathImul) {
157 158
  Node* function = MathFunction("imul");

159 160
  Node* effect = graph()->start();
  Node* control = graph()->start();
161
  Node* context = UndefinedConstant();
162
  Node* frame_state = graph()->start();
163 164 165 166 167 168
  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
    TRACED_FOREACH(Type*, t0, kIntegral32Types) {
      TRACED_FOREACH(Type*, t1, kIntegral32Types) {
        Node* p0 = Parameter(t0, 0);
        Node* p1 = Parameter(t1, 1);
        Node* call =
169
            graph()->NewNode(javascript()->CallFunction(4, language_mode),
170 171
                             function, UndefinedConstant(), p0, p1, context,
                             frame_state, frame_state, effect, control);
172
        Reduction r = Reduce(call);
173

174
        ASSERT_TRUE(r.Changed());
175 176 177 178 179 180
        EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
      }
    }
  }
}

181 182 183 184 185 186

// -----------------------------------------------------------------------------
// Math.fround


TEST_F(JSBuiltinReducerTest, MathFround) {
187
  Node* function = MathFunction("fround");
188

189 190
  Node* effect = graph()->start();
  Node* control = graph()->start();
191
  Node* context = UndefinedConstant();
192
  Node* frame_state = graph()->start();
193 194 195
  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
    TRACED_FOREACH(Type*, t0, kNumberTypes) {
      Node* p0 = Parameter(t0, 0);
196 197 198 199
      Node* call =
          graph()->NewNode(javascript()->CallFunction(3, language_mode),
                           function, UndefinedConstant(), p0, context,
                           frame_state, frame_state, effect, control);
200 201 202 203 204
      Reduction r = Reduce(call);

      ASSERT_TRUE(r.Changed());
      EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
    }
205 206 207
  }
}

208 209 210
}  // namespace compiler
}  // namespace internal
}  // namespace v8