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 14using namespace v8::internal; 15using namespace v8::internal::compiler; 16 17class 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 33class 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 53TEST(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 77TEST(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 107TEST(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 131TEST(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 156TEST(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 181TEST(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 196TEST(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 212TEST(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 224TEST(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 235TEST(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 251TEST(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 263TEST(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 274TEST(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 289TEST(ExternalReferences) { 290 // TODO(titzer): test canonicalization of external references. 291} 292