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

Generated by: LCOV version 1.10