Home | History | Annotate | Download | only in compiler
      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/v8.h"
      6 
      7 #include "src/compiler/js-graph.h"
      8 #include "src/compiler/node-properties-inl.h"
      9 #include "src/compiler/typer.h"
     10 #include "src/types.h"
     11 #include "test/cctest/cctest.h"
     12 #include "test/cctest/compiler/value-helper.h"
     13 
     14 using namespace v8::internal;
     15 using namespace v8::internal::compiler;
     16 
     17 class JSCacheTesterHelper {
     18  protected:
     19   explicit JSCacheTesterHelper(Zone* zone)
     20       : main_graph_(zone),
     21         main_common_(zone),
     22         main_javascript_(zone),
     23         main_typer_(zone),
     24         main_machine_() {}
     25   Graph main_graph_;
     26   CommonOperatorBuilder main_common_;
     27   JSOperatorBuilder main_javascript_;
     28   Typer main_typer_;
     29   MachineOperatorBuilder main_machine_;
     30 };
     31 
     32 
     33 class JSConstantCacheTester : public HandleAndZoneScope,
     34                               public JSCacheTesterHelper,
     35                               public JSGraph {
     36  public:
     37   JSConstantCacheTester()
     38       : JSCacheTesterHelper(main_zone()),
     39         JSGraph(&main_graph_, &main_common_, &main_javascript_, &main_typer_,
     40                 &main_machine_) {}
     41 
     42   Type* upper(Node* node) { return NodeProperties::GetBounds(node).upper; }
     43 
     44   Handle<Object> handle(Node* node) {
     45     CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
     46     return OpParameter<Unique<Object> >(node).handle();
     47   }
     48 
     49   Factory* factory() { return main_isolate()->factory(); }
     50 };
     51 
     52 
     53 TEST(ZeroConstant1) {
     54   JSConstantCacheTester T;
     55 
     56   Node* zero = T.ZeroConstant();
     57 
     58   CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
     59   CHECK_EQ(zero, T.Constant(0));
     60   CHECK_NE(zero, T.Constant(-0.0));
     61   CHECK_NE(zero, T.Constant(1.0));
     62   CHECK_NE(zero, T.Constant(v8::base::OS::nan_value()));
     63   CHECK_NE(zero, T.Float64Constant(0));
     64   CHECK_NE(zero, T.Int32Constant(0));
     65 
     66   Type* t = T.upper(zero);
     67 
     68   CHECK(t->Is(Type::Number()));
     69   CHECK(t->Is(Type::Integral32()));
     70   CHECK(t->Is(Type::Signed32()));
     71   CHECK(t->Is(Type::Unsigned32()));
     72   CHECK(t->Is(Type::SignedSmall()));
     73   CHECK(t->Is(Type::UnsignedSmall()));
     74 }
     75 
     76 
     77 TEST(MinusZeroConstant) {
     78   JSConstantCacheTester T;
     79 
     80   Node* minus_zero = T.Constant(-0.0);
     81   Node* zero = T.ZeroConstant();
     82 
     83   CHECK_EQ(IrOpcode::kNumberConstant, minus_zero->opcode());
     84   CHECK_EQ(minus_zero, T.Constant(-0.0));
     85   CHECK_NE(zero, minus_zero);
     86 
     87   Type* t = T.upper(minus_zero);
     88 
     89   CHECK(t->Is(Type::Number()));
     90   CHECK(t->Is(Type::MinusZero()));
     91   CHECK(!t->Is(Type::Integral32()));
     92   CHECK(!t->Is(Type::Signed32()));
     93   CHECK(!t->Is(Type::Unsigned32()));
     94   CHECK(!t->Is(Type::SignedSmall()));
     95   CHECK(!t->Is(Type::UnsignedSmall()));
     96 
     97   double zero_value = OpParameter<double>(zero);
     98   double minus_zero_value = OpParameter<double>(minus_zero);
     99 
    100   CHECK_EQ(0.0, zero_value);
    101   CHECK_NE(-0.0, zero_value);
    102   CHECK_EQ(-0.0, minus_zero_value);
    103   CHECK_NE(0.0, minus_zero_value);
    104 }
    105 
    106 
    107 TEST(ZeroConstant2) {
    108   JSConstantCacheTester T;
    109 
    110   Node* zero = T.Constant(0);
    111 
    112   CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
    113   CHECK_EQ(zero, T.ZeroConstant());
    114   CHECK_NE(zero, T.Constant(-0.0));
    115   CHECK_NE(zero, T.Constant(1.0));
    116   CHECK_NE(zero, T.Constant(v8::base::OS::nan_value()));
    117   CHECK_NE(zero, T.Float64Constant(0));
    118   CHECK_NE(zero, T.Int32Constant(0));
    119 
    120   Type* t = T.upper(zero);
    121 
    122   CHECK(t->Is(Type::Number()));
    123   CHECK(t->Is(Type::Integral32()));
    124   CHECK(t->Is(Type::Signed32()));
    125   CHECK(t->Is(Type::Unsigned32()));
    126   CHECK(t->Is(Type::SignedSmall()));
    127   CHECK(t->Is(Type::UnsignedSmall()));
    128 }
    129 
    130 
    131 TEST(OneConstant1) {
    132   JSConstantCacheTester T;
    133 
    134   Node* one = T.OneConstant();
    135 
    136   CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
    137   CHECK_EQ(one, T.Constant(1));
    138   CHECK_EQ(one, T.Constant(1.0));
    139   CHECK_NE(one, T.Constant(1.01));
    140   CHECK_NE(one, T.Constant(-1.01));
    141   CHECK_NE(one, T.Constant(v8::base::OS::nan_value()));
    142   CHECK_NE(one, T.Float64Constant(1.0));
    143   CHECK_NE(one, T.Int32Constant(1));
    144 
    145   Type* t = T.upper(one);
    146 
    147   CHECK(t->Is(Type::Number()));
    148   CHECK(t->Is(Type::Integral32()));
    149   CHECK(t->Is(Type::Signed32()));
    150   CHECK(t->Is(Type::Unsigned32()));
    151   CHECK(t->Is(Type::SignedSmall()));
    152   CHECK(t->Is(Type::UnsignedSmall()));
    153 }
    154 
    155 
    156 TEST(OneConstant2) {
    157   JSConstantCacheTester T;
    158 
    159   Node* one = T.Constant(1);
    160 
    161   CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
    162   CHECK_EQ(one, T.OneConstant());
    163   CHECK_EQ(one, T.Constant(1.0));
    164   CHECK_NE(one, T.Constant(1.01));
    165   CHECK_NE(one, T.Constant(-1.01));
    166   CHECK_NE(one, T.Constant(v8::base::OS::nan_value()));
    167   CHECK_NE(one, T.Float64Constant(1.0));
    168   CHECK_NE(one, T.Int32Constant(1));
    169 
    170   Type* t = T.upper(one);
    171 
    172   CHECK(t->Is(Type::Number()));
    173   CHECK(t->Is(Type::Integral32()));
    174   CHECK(t->Is(Type::Signed32()));
    175   CHECK(t->Is(Type::Unsigned32()));
    176   CHECK(t->Is(Type::SignedSmall()));
    177   CHECK(t->Is(Type::UnsignedSmall()));
    178 }
    179 
    180 
    181 TEST(Canonicalizations) {
    182   JSConstantCacheTester T;
    183 
    184   CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
    185   CHECK_EQ(T.UndefinedConstant(), T.UndefinedConstant());
    186   CHECK_EQ(T.TheHoleConstant(), T.TheHoleConstant());
    187   CHECK_EQ(T.TrueConstant(), T.TrueConstant());
    188   CHECK_EQ(T.FalseConstant(), T.FalseConstant());
    189   CHECK_EQ(T.NullConstant(), T.NullConstant());
    190   CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
    191   CHECK_EQ(T.OneConstant(), T.OneConstant());
    192   CHECK_EQ(T.NaNConstant(), T.NaNConstant());
    193 }
    194 
    195 
    196 TEST(NoAliasing) {
    197   JSConstantCacheTester T;
    198 
    199   Node* nodes[] = {T.UndefinedConstant(), T.TheHoleConstant(), T.TrueConstant(),
    200                    T.FalseConstant(),     T.NullConstant(),    T.ZeroConstant(),
    201                    T.OneConstant(),       T.NaNConstant(),     T.Constant(21),
    202                    T.Constant(22.2)};
    203 
    204   for (size_t i = 0; i < arraysize(nodes); i++) {
    205     for (size_t j = 0; j < arraysize(nodes); j++) {
    206       if (i != j) CHECK_NE(nodes[i], nodes[j]);
    207     }
    208   }
    209 }
    210 
    211 
    212 TEST(CanonicalizingNumbers) {
    213   JSConstantCacheTester T;
    214 
    215   FOR_FLOAT64_INPUTS(i) {
    216     Node* node = T.Constant(*i);
    217     for (int j = 0; j < 5; j++) {
    218       CHECK_EQ(node, T.Constant(*i));
    219     }
    220   }
    221 }
    222 
    223 
    224 TEST(NumberTypes) {
    225   JSConstantCacheTester T;
    226 
    227   FOR_FLOAT64_INPUTS(i) {
    228     double value = *i;
    229     Node* node = T.Constant(value);
    230     CHECK(T.upper(node)->Equals(Type::Of(value, T.main_zone())));
    231   }
    232 }
    233 
    234 
    235 TEST(HeapNumbers) {
    236   JSConstantCacheTester T;
    237 
    238   FOR_FLOAT64_INPUTS(i) {
    239     double value = *i;
    240     Handle<Object> num = T.factory()->NewNumber(value);
    241     Handle<HeapNumber> heap = T.factory()->NewHeapNumber(value);
    242     Node* node1 = T.Constant(value);
    243     Node* node2 = T.Constant(num);
    244     Node* node3 = T.Constant(heap);
    245     CHECK_EQ(node1, node2);
    246     CHECK_EQ(node1, node3);
    247   }
    248 }
    249 
    250 
    251 TEST(OddballHandle) {
    252   JSConstantCacheTester T;
    253 
    254   CHECK_EQ(T.UndefinedConstant(), T.Constant(T.factory()->undefined_value()));
    255   CHECK_EQ(T.TheHoleConstant(), T.Constant(T.factory()->the_hole_value()));
    256   CHECK_EQ(T.TrueConstant(), T.Constant(T.factory()->true_value()));
    257   CHECK_EQ(T.FalseConstant(), T.Constant(T.factory()->false_value()));
    258   CHECK_EQ(T.NullConstant(), T.Constant(T.factory()->null_value()));
    259   CHECK_EQ(T.NaNConstant(), T.Constant(T.factory()->nan_value()));
    260 }
    261 
    262 
    263 TEST(OddballValues) {
    264   JSConstantCacheTester T;
    265 
    266   CHECK_EQ(*T.factory()->undefined_value(), *T.handle(T.UndefinedConstant()));
    267   CHECK_EQ(*T.factory()->the_hole_value(), *T.handle(T.TheHoleConstant()));
    268   CHECK_EQ(*T.factory()->true_value(), *T.handle(T.TrueConstant()));
    269   CHECK_EQ(*T.factory()->false_value(), *T.handle(T.FalseConstant()));
    270   CHECK_EQ(*T.factory()->null_value(), *T.handle(T.NullConstant()));
    271 }
    272 
    273 
    274 TEST(OddballTypes) {
    275   JSConstantCacheTester T;
    276 
    277   CHECK(T.upper(T.UndefinedConstant())->Is(Type::Undefined()));
    278   // TODO(dcarney): figure this out.
    279   // CHECK(T.upper(T.TheHoleConstant())->Is(Type::Internal()));
    280   CHECK(T.upper(T.TrueConstant())->Is(Type::Boolean()));
    281   CHECK(T.upper(T.FalseConstant())->Is(Type::Boolean()));
    282   CHECK(T.upper(T.NullConstant())->Is(Type::Null()));
    283   CHECK(T.upper(T.ZeroConstant())->Is(Type::Number()));
    284   CHECK(T.upper(T.OneConstant())->Is(Type::Number()));
    285   CHECK(T.upper(T.NaNConstant())->Is(Type::NaN()));
    286 }
    287 
    288 
    289 TEST(ExternalReferences) {
    290   // TODO(titzer): test canonicalization of external references.
    291 }
    292