LCOV - code coverage report
Current view: top level - test/cctest/compiler - test-js-constant-cache.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 230 230 100.0 %
Date: 2017-10-20 Functions: 26 26 100.0 %

          Line data    Source code
       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/assembler.h"
       6             : #include "src/compiler/js-graph.h"
       7             : #include "src/compiler/node-properties.h"
       8             : #include "src/factory-inl.h"
       9             : #include "test/cctest/cctest.h"
      10             : #include "test/cctest/compiler/value-helper.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : namespace compiler {
      15             : 
      16             : class JSCacheTesterHelper {
      17             :  protected:
      18         108 :   JSCacheTesterHelper(Isolate* isolate, Zone* zone)
      19             :       : main_graph_(zone),
      20             :         main_common_(zone),
      21             :         main_javascript_(zone),
      22         216 :         main_machine_(zone) {}
      23             :   Graph main_graph_;
      24             :   CommonOperatorBuilder main_common_;
      25             :   JSOperatorBuilder main_javascript_;
      26             :   MachineOperatorBuilder main_machine_;
      27             : };
      28             : 
      29             : 
      30             : // TODO(dcarney): JSConstantCacheTester inherits from JSGraph???
      31         108 : class JSConstantCacheTester : public HandleAndZoneScope,
      32             :                               public JSCacheTesterHelper,
      33             :                               public JSGraph {
      34             :  public:
      35         108 :   JSConstantCacheTester()
      36             :       : JSCacheTesterHelper(main_isolate(), main_zone()),
      37             :         JSGraph(main_isolate(), &main_graph_, &main_common_, &main_javascript_,
      38         432 :                 nullptr, &main_machine_) {
      39         108 :     main_graph_.SetStart(main_graph_.NewNode(common()->Start(0)));
      40             :     main_graph_.SetEnd(
      41         108 :         main_graph_.NewNode(common()->End(1), main_graph_.start()));
      42         108 :   }
      43             : 
      44          30 :   Handle<HeapObject> handle(Node* node) {
      45          30 :     CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
      46          30 :     return OpParameter<Handle<HeapObject>>(node);
      47             :   }
      48             : 
      49         654 :   Factory* factory() { return main_isolate()->factory(); }
      50             : };
      51             : 
      52             : 
      53       23724 : TEST(ZeroConstant1) {
      54           6 :   JSConstantCacheTester T;
      55             : 
      56           6 :   Node* zero = T.ZeroConstant();
      57             : 
      58           6 :   CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
      59           6 :   CHECK_EQ(zero, T.Constant(0));
      60           6 :   CHECK_NE(zero, T.Constant(-0.0));
      61           6 :   CHECK_NE(zero, T.Constant(1.0));
      62           6 :   CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN()));
      63           6 :   CHECK_NE(zero, T.Float64Constant(0));
      64           6 :   CHECK_NE(zero, T.Int32Constant(0));
      65           6 : }
      66             : 
      67             : 
      68       23724 : TEST(MinusZeroConstant) {
      69           6 :   JSConstantCacheTester T;
      70             : 
      71          12 :   Node* minus_zero = T.Constant(-0.0);
      72           6 :   Node* zero = T.ZeroConstant();
      73             : 
      74           6 :   CHECK_EQ(IrOpcode::kNumberConstant, minus_zero->opcode());
      75           6 :   CHECK_EQ(minus_zero, T.Constant(-0.0));
      76           6 :   CHECK_NE(zero, minus_zero);
      77             : 
      78           6 :   double zero_value = OpParameter<double>(zero);
      79           6 :   double minus_zero_value = OpParameter<double>(minus_zero);
      80             : 
      81           6 :   CHECK(bit_cast<uint64_t>(0.0) == bit_cast<uint64_t>(zero_value));
      82           6 :   CHECK(bit_cast<uint64_t>(-0.0) != bit_cast<uint64_t>(zero_value));
      83           6 :   CHECK(bit_cast<uint64_t>(0.0) != bit_cast<uint64_t>(minus_zero_value));
      84           6 :   CHECK(bit_cast<uint64_t>(-0.0) == bit_cast<uint64_t>(minus_zero_value));
      85           6 : }
      86             : 
      87             : 
      88       23724 : TEST(ZeroConstant2) {
      89           6 :   JSConstantCacheTester T;
      90             : 
      91           6 :   Node* zero = T.Constant(0);
      92             : 
      93           6 :   CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
      94           6 :   CHECK_EQ(zero, T.ZeroConstant());
      95           6 :   CHECK_NE(zero, T.Constant(-0.0));
      96           6 :   CHECK_NE(zero, T.Constant(1.0));
      97           6 :   CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN()));
      98           6 :   CHECK_NE(zero, T.Float64Constant(0));
      99           6 :   CHECK_NE(zero, T.Int32Constant(0));
     100           6 : }
     101             : 
     102             : 
     103       23724 : TEST(OneConstant1) {
     104           6 :   JSConstantCacheTester T;
     105             : 
     106           6 :   Node* one = T.OneConstant();
     107             : 
     108           6 :   CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
     109           6 :   CHECK_EQ(one, T.Constant(1));
     110           6 :   CHECK_EQ(one, T.Constant(1.0));
     111           6 :   CHECK_NE(one, T.Constant(1.01));
     112           6 :   CHECK_NE(one, T.Constant(-1.01));
     113           6 :   CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN()));
     114           6 :   CHECK_NE(one, T.Float64Constant(1.0));
     115           6 :   CHECK_NE(one, T.Int32Constant(1));
     116           6 : }
     117             : 
     118             : 
     119       23724 : TEST(OneConstant2) {
     120           6 :   JSConstantCacheTester T;
     121             : 
     122           6 :   Node* one = T.Constant(1);
     123             : 
     124           6 :   CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
     125           6 :   CHECK_EQ(one, T.OneConstant());
     126           6 :   CHECK_EQ(one, T.Constant(1.0));
     127           6 :   CHECK_NE(one, T.Constant(1.01));
     128           6 :   CHECK_NE(one, T.Constant(-1.01));
     129           6 :   CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN()));
     130           6 :   CHECK_NE(one, T.Float64Constant(1.0));
     131           6 :   CHECK_NE(one, T.Int32Constant(1));
     132           6 : }
     133             : 
     134             : 
     135       23724 : TEST(Canonicalizations) {
     136           6 :   JSConstantCacheTester T;
     137             : 
     138           6 :   CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
     139           6 :   CHECK_EQ(T.UndefinedConstant(), T.UndefinedConstant());
     140           6 :   CHECK_EQ(T.TheHoleConstant(), T.TheHoleConstant());
     141           6 :   CHECK_EQ(T.TrueConstant(), T.TrueConstant());
     142           6 :   CHECK_EQ(T.FalseConstant(), T.FalseConstant());
     143           6 :   CHECK_EQ(T.NullConstant(), T.NullConstant());
     144           6 :   CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
     145           6 :   CHECK_EQ(T.OneConstant(), T.OneConstant());
     146           6 :   CHECK_EQ(T.NaNConstant(), T.NaNConstant());
     147           6 : }
     148             : 
     149             : 
     150       23724 : TEST(NoAliasing) {
     151           6 :   JSConstantCacheTester T;
     152             : 
     153          18 :   Node* nodes[] = {T.UndefinedConstant(), T.TheHoleConstant(), T.TrueConstant(),
     154          18 :                    T.FalseConstant(),     T.NullConstant(),    T.ZeroConstant(),
     155          18 :                    T.OneConstant(),       T.NaNConstant(),     T.Constant(21),
     156          54 :                    T.Constant(22.2)};
     157             : 
     158          66 :   for (size_t i = 0; i < arraysize(nodes); i++) {
     159         600 :     for (size_t j = 0; j < arraysize(nodes); j++) {
     160         600 :       if (i != j) CHECK_NE(nodes[i], nodes[j]);
     161             :     }
     162             :   }
     163           6 : }
     164             : 
     165             : 
     166       23724 : TEST(CanonicalizingNumbers) {
     167           6 :   JSConstantCacheTester T;
     168             : 
     169         300 :   FOR_FLOAT64_INPUTS(i) {
     170         294 :     Node* node = T.Constant(*i);
     171        1764 :     for (int j = 0; j < 5; j++) {
     172        1470 :       CHECK_EQ(node, T.Constant(*i));
     173             :     }
     174             :   }
     175           6 : }
     176             : 
     177             : 
     178       23724 : TEST(HeapNumbers) {
     179           6 :   JSConstantCacheTester T;
     180             : 
     181         300 :   FOR_FLOAT64_INPUTS(i) {
     182         294 :     double value = *i;
     183         294 :     Handle<Object> num = T.factory()->NewNumber(value);
     184             :     Handle<HeapNumber> heap = T.factory()->NewHeapNumber(value);
     185         294 :     Node* node1 = T.Constant(value);
     186         294 :     Node* node2 = T.Constant(num);
     187         294 :     Node* node3 = T.Constant(heap);
     188         294 :     CHECK_EQ(node1, node2);
     189         294 :     CHECK_EQ(node1, node3);
     190             :   }
     191           6 : }
     192             : 
     193             : 
     194       23724 : TEST(OddballHandle) {
     195           6 :   JSConstantCacheTester T;
     196             : 
     197           6 :   CHECK_EQ(T.UndefinedConstant(), T.Constant(T.factory()->undefined_value()));
     198           6 :   CHECK_EQ(T.TheHoleConstant(), T.Constant(T.factory()->the_hole_value()));
     199           6 :   CHECK_EQ(T.TrueConstant(), T.Constant(T.factory()->true_value()));
     200           6 :   CHECK_EQ(T.FalseConstant(), T.Constant(T.factory()->false_value()));
     201           6 :   CHECK_EQ(T.NullConstant(), T.Constant(T.factory()->null_value()));
     202           6 :   CHECK_EQ(T.NaNConstant(), T.Constant(T.factory()->nan_value()));
     203           6 : }
     204             : 
     205             : 
     206       23724 : TEST(OddballValues) {
     207           6 :   JSConstantCacheTester T;
     208             : 
     209          12 :   CHECK_EQ(*T.factory()->undefined_value(), *T.handle(T.UndefinedConstant()));
     210          12 :   CHECK_EQ(*T.factory()->the_hole_value(), *T.handle(T.TheHoleConstant()));
     211          12 :   CHECK_EQ(*T.factory()->true_value(), *T.handle(T.TrueConstant()));
     212          12 :   CHECK_EQ(*T.factory()->false_value(), *T.handle(T.FalseConstant()));
     213          12 :   CHECK_EQ(*T.factory()->null_value(), *T.handle(T.NullConstant()));
     214           6 : }
     215             : 
     216             : 
     217       23724 : TEST(ExternalReferences) {
     218             :   // TODO(titzer): test canonicalization of external references.
     219           6 : }
     220             : 
     221             : 
     222        1098 : static bool Contains(NodeVector* nodes, Node* n) {
     223       14972 :   for (size_t i = 0; i < nodes->size(); i++) {
     224       14972 :     if (nodes->at(i) == n) return true;
     225             :   }
     226             :   return false;
     227             : }
     228             : 
     229             : 
     230         774 : static void CheckGetCachedNodesContains(JSConstantCacheTester* T, Node* n) {
     231             :   NodeVector nodes(T->main_zone());
     232         774 :   T->GetCachedNodes(&nodes);
     233         774 :   CHECK(Contains(&nodes, n));
     234         774 : }
     235             : 
     236             : 
     237       23724 : TEST(JSGraph_GetCachedNodes1) {
     238           6 :   JSConstantCacheTester T;
     239           6 :   CheckGetCachedNodesContains(&T, T.TrueConstant());
     240           6 :   CheckGetCachedNodesContains(&T, T.UndefinedConstant());
     241           6 :   CheckGetCachedNodesContains(&T, T.TheHoleConstant());
     242           6 :   CheckGetCachedNodesContains(&T, T.TrueConstant());
     243           6 :   CheckGetCachedNodesContains(&T, T.FalseConstant());
     244           6 :   CheckGetCachedNodesContains(&T, T.NullConstant());
     245           6 :   CheckGetCachedNodesContains(&T, T.ZeroConstant());
     246           6 :   CheckGetCachedNodesContains(&T, T.OneConstant());
     247           6 :   CheckGetCachedNodesContains(&T, T.NaNConstant());
     248           6 : }
     249             : 
     250             : 
     251       23724 : TEST(JSGraph_GetCachedNodes_int32) {
     252           6 :   JSConstantCacheTester T;
     253             : 
     254             :   int32_t constants[] = {0,  1,  1,   1,   1,   2,   3,   4,  11, 12, 13,
     255             :                          14, 55, -55, -44, -33, -22, -11, 16, 16, 17, 17,
     256             :                          18, 18, 19,  19,  20,  20,  21,  21, 22, 23, 24,
     257           6 :                          25, 15, 30,  31,  45,  46,  47,  48};
     258             : 
     259         252 :   for (size_t i = 0; i < arraysize(constants); i++) {
     260         246 :     size_t count_before = T.graph()->NodeCount();
     261             :     NodeVector nodes_before(T.main_zone());
     262         246 :     T.GetCachedNodes(&nodes_before);
     263         246 :     Node* n = T.Int32Constant(constants[i]);
     264         246 :     if (n->id() < count_before) {
     265             :       // An old ID indicates a cached node. It should have been in the set.
     266          54 :       CHECK(Contains(&nodes_before, n));
     267             :     }
     268             :     // Old or new, it should be in the cached set afterwards.
     269         246 :     CheckGetCachedNodesContains(&T, n);
     270             :   }
     271           6 : }
     272             : 
     273             : 
     274       23724 : TEST(JSGraph_GetCachedNodes_float64) {
     275           6 :   JSConstantCacheTester T;
     276             : 
     277             :   double constants[] = {0,   11.1, 12.2,  13,    14,   55.5, -55.5, -44.4,
     278             :                         -33, -22,  -11,   0,     11.1, 11.1, 12.3,  12.3,
     279           6 :                         11,  11,   -33.3, -33.3, -22,  -11};
     280             : 
     281         138 :   for (size_t i = 0; i < arraysize(constants); i++) {
     282         132 :     size_t count_before = T.graph()->NodeCount();
     283             :     NodeVector nodes_before(T.main_zone());
     284         132 :     T.GetCachedNodes(&nodes_before);
     285         132 :     Node* n = T.Float64Constant(constants[i]);
     286         132 :     if (n->id() < count_before) {
     287             :       // An old ID indicates a cached node. It should have been in the set.
     288          48 :       CHECK(Contains(&nodes_before, n));
     289             :     }
     290             :     // Old or new, it should be in the cached set afterwards.
     291         132 :     CheckGetCachedNodesContains(&T, n);
     292             :   }
     293           6 : }
     294             : 
     295             : 
     296       23724 : TEST(JSGraph_GetCachedNodes_int64) {
     297           6 :   JSConstantCacheTester T;
     298             : 
     299             :   int32_t constants[] = {0,   11,  12, 13, 14, 55, -55, -44, -33,
     300             :                          -22, -11, 16, 16, 17, 17, 18,  18,  19,
     301           6 :                          19,  20,  20, 21, 21, 22, 23,  24,  25};
     302             : 
     303         168 :   for (size_t i = 0; i < arraysize(constants); i++) {
     304         162 :     size_t count_before = T.graph()->NodeCount();
     305             :     NodeVector nodes_before(T.main_zone());
     306         162 :     T.GetCachedNodes(&nodes_before);
     307         162 :     Node* n = T.Int64Constant(constants[i]);
     308         162 :     if (n->id() < count_before) {
     309             :       // An old ID indicates a cached node. It should have been in the set.
     310          36 :       CHECK(Contains(&nodes_before, n));
     311             :     }
     312             :     // Old or new, it should be in the cached set afterwards.
     313         162 :     CheckGetCachedNodesContains(&T, n);
     314             :   }
     315           6 : }
     316             : 
     317             : 
     318       23724 : TEST(JSGraph_GetCachedNodes_number) {
     319           6 :   JSConstantCacheTester T;
     320             : 
     321             :   double constants[] = {0,   11.1, 12.2,  13,    14,   55.5, -55.5, -44.4,
     322             :                         -33, -22,  -11,   0,     11.1, 11.1, 12.3,  12.3,
     323           6 :                         11,  11,   -33.3, -33.3, -22,  -11};
     324             : 
     325         138 :   for (size_t i = 0; i < arraysize(constants); i++) {
     326         132 :     size_t count_before = T.graph()->NodeCount();
     327             :     NodeVector nodes_before(T.main_zone());
     328         132 :     T.GetCachedNodes(&nodes_before);
     329         132 :     Node* n = T.Constant(constants[i]);
     330         132 :     if (n->id() < count_before) {
     331             :       // An old ID indicates a cached node. It should have been in the set.
     332          48 :       CHECK(Contains(&nodes_before, n));
     333             :     }
     334             :     // Old or new, it should be in the cached set afterwards.
     335         132 :     CheckGetCachedNodesContains(&T, n);
     336             :   }
     337           6 : }
     338             : 
     339             : 
     340       23724 : TEST(JSGraph_GetCachedNodes_external) {
     341           6 :   JSConstantCacheTester T;
     342             : 
     343             :   ExternalReference constants[] = {ExternalReference::address_of_min_int(),
     344             :                                    ExternalReference::address_of_min_int(),
     345             :                                    ExternalReference::address_of_min_int(),
     346             :                                    ExternalReference::address_of_one_half(),
     347             :                                    ExternalReference::address_of_one_half(),
     348             :                                    ExternalReference::address_of_min_int(),
     349             :                                    ExternalReference::address_of_the_hole_nan(),
     350           6 :                                    ExternalReference::address_of_one_half()};
     351             : 
     352          54 :   for (size_t i = 0; i < arraysize(constants); i++) {
     353          48 :     size_t count_before = T.graph()->NodeCount();
     354             :     NodeVector nodes_before(T.main_zone());
     355          48 :     T.GetCachedNodes(&nodes_before);
     356          48 :     Node* n = T.ExternalConstant(constants[i]);
     357          48 :     if (n->id() < count_before) {
     358             :       // An old ID indicates a cached node. It should have been in the set.
     359          30 :       CHECK(Contains(&nodes_before, n));
     360             :     }
     361             :     // Old or new, it should be in the cached set afterwards.
     362          48 :     CheckGetCachedNodesContains(&T, n);
     363             :   }
     364           6 : }
     365             : 
     366             : 
     367       23724 : TEST(JSGraph_GetCachedNodes_together) {
     368           6 :   JSConstantCacheTester T;
     369             : 
     370             :   Node* constants[] = {
     371           6 :       T.TrueConstant(),
     372           6 :       T.UndefinedConstant(),
     373           6 :       T.TheHoleConstant(),
     374           6 :       T.TrueConstant(),
     375           6 :       T.FalseConstant(),
     376           6 :       T.NullConstant(),
     377           6 :       T.ZeroConstant(),
     378           6 :       T.OneConstant(),
     379           6 :       T.NaNConstant(),
     380           6 :       T.Int32Constant(0),
     381           6 :       T.Int32Constant(1),
     382           6 :       T.Int64Constant(-2),
     383           6 :       T.Int64Constant(-4),
     384           6 :       T.Float64Constant(0.9),
     385           6 :       T.Float64Constant(V8_INFINITY),
     386           6 :       T.Constant(0.99),
     387           6 :       T.Constant(1.11),
     388         102 :       T.ExternalConstant(ExternalReference::address_of_one_half())};
     389             : 
     390             :   NodeVector nodes(T.main_zone());
     391           6 :   T.GetCachedNodes(&nodes);
     392             : 
     393         114 :   for (size_t i = 0; i < arraysize(constants); i++) {
     394         108 :     CHECK(Contains(&nodes, constants[i]));
     395             :   }
     396           6 : }
     397             : 
     398             : }  // namespace compiler
     399             : }  // namespace internal
     400       71154 : }  // namespace v8

Generated by: LCOV version 1.10