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: 231 231 100.0 %
Date: 2019-01-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/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             : 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         180 :     main_graph_.SetStart(main_graph_.NewNode(common()->Start(0)));
      40             :     main_graph_.SetEnd(
      41          90 :         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         545 :   Factory* factory() { return main_isolate()->factory(); }
      50             : };
      51             : 
      52             : 
      53       28342 : 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       28342 : TEST(MinusZeroConstant) {
      69           5 :   JSConstantCacheTester T;
      70             : 
      71          15 :   Node* minus_zero = T.Constant(-0.0);
      72          10 :   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       28342 : 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       28342 : 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       28342 : 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       28342 : 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       28342 : 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          55 :   for (size_t i = 0; i < arraysize(nodes); i++) {
     159         500 :     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       28342 : TEST(CanonicalizingNumbers) {
     167           5 :   JSConstantCacheTester T;
     168             : 
     169         250 :   FOR_FLOAT64_INPUTS(i) {
     170         245 :     Node* node = T.Constant(*i);
     171        1470 :     for (int j = 0; j < 5; j++) {
     172        1225 :       CHECK_EQ(node, T.Constant(*i));
     173             :     }
     174             :   }
     175           5 : }
     176             : 
     177             : 
     178       28342 : TEST(HeapNumbers) {
     179           5 :   JSConstantCacheTester T;
     180             : 
     181         250 :   FOR_FLOAT64_INPUTS(i) {
     182         245 :     double value = *i;
     183         245 :     Handle<Object> num = T.factory()->NewNumber(value);
     184         245 :     Handle<HeapNumber> heap = T.factory()->NewHeapNumber(value);
     185         245 :     Node* node1 = T.Constant(value);
     186         245 :     Node* node2 = T.Constant(num);
     187         245 :     Node* node3 = T.Constant(heap);
     188         245 :     CHECK_EQ(node1, node2);
     189         245 :     CHECK_EQ(node1, node3);
     190             :   }
     191           5 : }
     192             : 
     193             : 
     194       28342 : TEST(OddballHandle) {
     195           5 :   JSConstantCacheTester T;
     196             : 
     197           5 :   CHECK_EQ(T.UndefinedConstant(), T.Constant(T.factory()->undefined_value()));
     198           5 :   CHECK_EQ(T.TheHoleConstant(), T.Constant(T.factory()->the_hole_value()));
     199           5 :   CHECK_EQ(T.TrueConstant(), T.Constant(T.factory()->true_value()));
     200           5 :   CHECK_EQ(T.FalseConstant(), T.Constant(T.factory()->false_value()));
     201           5 :   CHECK_EQ(T.NullConstant(), T.Constant(T.factory()->null_value()));
     202           5 :   CHECK_EQ(T.NaNConstant(), T.Constant(T.factory()->nan_value()));
     203           5 : }
     204             : 
     205             : 
     206       28342 : TEST(OddballValues) {
     207           5 :   JSConstantCacheTester T;
     208             : 
     209          20 :   CHECK_EQ(*T.factory()->undefined_value(), *T.handle(T.UndefinedConstant()));
     210          20 :   CHECK_EQ(*T.factory()->the_hole_value(), *T.handle(T.TheHoleConstant()));
     211          20 :   CHECK_EQ(*T.factory()->true_value(), *T.handle(T.TrueConstant()));
     212          20 :   CHECK_EQ(*T.factory()->false_value(), *T.handle(T.FalseConstant()));
     213          20 :   CHECK_EQ(*T.factory()->null_value(), *T.handle(T.NullConstant()));
     214           5 : }
     215             : 
     216             : 
     217       28342 : TEST(ExternalReferences) {
     218             :   // TODO(titzer): test canonicalization of external references.
     219           5 : }
     220             : 
     221             : 
     222         915 : static bool Contains(NodeVector* nodes, Node* n) {
     223       12498 :   for (size_t i = 0; i < nodes->size(); i++) {
     224       12498 :     if (nodes->at(i) == n) return true;
     225             :   }
     226             :   return false;
     227             : }
     228             : 
     229             : 
     230         645 : static void CheckGetCachedNodesContains(JSConstantCacheTester* T, Node* n) {
     231             :   NodeVector nodes(T->main_zone());
     232         645 :   T->GetCachedNodes(&nodes);
     233         645 :   CHECK(Contains(&nodes, n));
     234         645 : }
     235             : 
     236             : 
     237       28342 : TEST(JSGraph_GetCachedNodes1) {
     238           5 :   JSConstantCacheTester T;
     239           5 :   CheckGetCachedNodesContains(&T, T.TrueConstant());
     240           5 :   CheckGetCachedNodesContains(&T, T.UndefinedConstant());
     241           5 :   CheckGetCachedNodesContains(&T, T.TheHoleConstant());
     242           5 :   CheckGetCachedNodesContains(&T, T.TrueConstant());
     243           5 :   CheckGetCachedNodesContains(&T, T.FalseConstant());
     244           5 :   CheckGetCachedNodesContains(&T, T.NullConstant());
     245           5 :   CheckGetCachedNodesContains(&T, T.ZeroConstant());
     246           5 :   CheckGetCachedNodesContains(&T, T.OneConstant());
     247           5 :   CheckGetCachedNodesContains(&T, T.NaNConstant());
     248           5 : }
     249             : 
     250             : 
     251       28342 : TEST(JSGraph_GetCachedNodes_int32) {
     252           5 :   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           5 :                          25, 15, 30,  31,  45,  46,  47,  48};
     258             : 
     259         210 :   for (size_t i = 0; i < arraysize(constants); i++) {
     260         205 :     size_t count_before = T.graph()->NodeCount();
     261             :     NodeVector nodes_before(T.main_zone());
     262         205 :     T.GetCachedNodes(&nodes_before);
     263         205 :     Node* n = T.Int32Constant(constants[i]);
     264         205 :     if (n->id() < count_before) {
     265             :       // An old ID indicates a cached node. It should have been in the set.
     266          45 :       CHECK(Contains(&nodes_before, n));
     267             :     }
     268             :     // Old or new, it should be in the cached set afterwards.
     269         205 :     CheckGetCachedNodesContains(&T, n);
     270             :   }
     271           5 : }
     272             : 
     273             : 
     274       28342 : TEST(JSGraph_GetCachedNodes_float64) {
     275           5 :   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           5 :                         11,  11,   -33.3, -33.3, -22,  -11};
     280             : 
     281         115 :   for (size_t i = 0; i < arraysize(constants); i++) {
     282         110 :     size_t count_before = T.graph()->NodeCount();
     283             :     NodeVector nodes_before(T.main_zone());
     284         110 :     T.GetCachedNodes(&nodes_before);
     285         110 :     Node* n = T.Float64Constant(constants[i]);
     286         110 :     if (n->id() < count_before) {
     287             :       // An old ID indicates a cached node. It should have been in the set.
     288          40 :       CHECK(Contains(&nodes_before, n));
     289             :     }
     290             :     // Old or new, it should be in the cached set afterwards.
     291         110 :     CheckGetCachedNodesContains(&T, n);
     292             :   }
     293           5 : }
     294             : 
     295             : 
     296       28342 : TEST(JSGraph_GetCachedNodes_int64) {
     297           5 :   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           5 :                          19,  20,  20, 21, 21, 22, 23,  24,  25};
     302             : 
     303         140 :   for (size_t i = 0; i < arraysize(constants); i++) {
     304         135 :     size_t count_before = T.graph()->NodeCount();
     305             :     NodeVector nodes_before(T.main_zone());
     306         135 :     T.GetCachedNodes(&nodes_before);
     307         135 :     Node* n = T.Int64Constant(constants[i]);
     308         135 :     if (n->id() < count_before) {
     309             :       // An old ID indicates a cached node. It should have been in the set.
     310          30 :       CHECK(Contains(&nodes_before, n));
     311             :     }
     312             :     // Old or new, it should be in the cached set afterwards.
     313         135 :     CheckGetCachedNodesContains(&T, n);
     314             :   }
     315           5 : }
     316             : 
     317             : 
     318       28342 : TEST(JSGraph_GetCachedNodes_number) {
     319           5 :   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           5 :                         11,  11,   -33.3, -33.3, -22,  -11};
     324             : 
     325         115 :   for (size_t i = 0; i < arraysize(constants); i++) {
     326         110 :     size_t count_before = T.graph()->NodeCount();
     327             :     NodeVector nodes_before(T.main_zone());
     328         110 :     T.GetCachedNodes(&nodes_before);
     329         110 :     Node* n = T.Constant(constants[i]);
     330         110 :     if (n->id() < count_before) {
     331             :       // An old ID indicates a cached node. It should have been in the set.
     332          40 :       CHECK(Contains(&nodes_before, n));
     333             :     }
     334             :     // Old or new, it should be in the cached set afterwards.
     335         110 :     CheckGetCachedNodesContains(&T, n);
     336             :   }
     337           5 : }
     338             : 
     339             : 
     340       28342 : TEST(JSGraph_GetCachedNodes_external) {
     341           5 :   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           5 :                                    ExternalReference::address_of_one_half()};
     351             : 
     352          45 :   for (size_t i = 0; i < arraysize(constants); i++) {
     353          40 :     size_t count_before = T.graph()->NodeCount();
     354             :     NodeVector nodes_before(T.main_zone());
     355          40 :     T.GetCachedNodes(&nodes_before);
     356          40 :     Node* n = T.ExternalConstant(constants[i]);
     357          40 :     if (n->id() < count_before) {
     358             :       // An old ID indicates a cached node. It should have been in the set.
     359          25 :       CHECK(Contains(&nodes_before, n));
     360             :     }
     361             :     // Old or new, it should be in the cached set afterwards.
     362          40 :     CheckGetCachedNodesContains(&T, n);
     363             :   }
     364           5 : }
     365             : 
     366             : 
     367       28342 : TEST(JSGraph_GetCachedNodes_together) {
     368           5 :   JSConstantCacheTester T;
     369             : 
     370             :   Node* constants[] = {
     371           5 :       T.TrueConstant(),
     372           5 :       T.UndefinedConstant(),
     373           5 :       T.TheHoleConstant(),
     374           5 :       T.TrueConstant(),
     375           5 :       T.FalseConstant(),
     376           5 :       T.NullConstant(),
     377           5 :       T.ZeroConstant(),
     378           5 :       T.OneConstant(),
     379           5 :       T.NaNConstant(),
     380           5 :       T.Int32Constant(0),
     381           5 :       T.Int32Constant(1),
     382           5 :       T.Int64Constant(-2),
     383           5 :       T.Int64Constant(-4),
     384           5 :       T.Float64Constant(0.9),
     385           5 :       T.Float64Constant(V8_INFINITY),
     386           5 :       T.Constant(0.99),
     387           5 :       T.Constant(1.11),
     388          85 :       T.ExternalConstant(ExternalReference::address_of_one_half())};
     389             : 
     390             :   NodeVector nodes(T.main_zone());
     391           5 :   T.GetCachedNodes(&nodes);
     392             : 
     393          95 :   for (size_t i = 0; i < arraysize(constants); i++) {
     394          90 :     CHECK(Contains(&nodes, constants[i]));
     395             :   }
     396           5 : }
     397             : 
     398             : }  // namespace compiler
     399             : }  // namespace internal
     400       85011 : }  // namespace v8

Generated by: LCOV version 1.10