1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_TEST_CCTEST_TYPES_H_ 29 #define V8_TEST_CCTEST_TYPES_H_ 30 31 #include "src/base/utils/random-number-generator.h" 32 #include "src/v8.h" 33 34 namespace v8 { 35 namespace internal { 36 37 38 template<class Type, class TypeHandle, class Region> 39 class Types { 40 public: Types(Region * region,Isolate * isolate,v8::base::RandomNumberGenerator * rng)41 Types(Region* region, Isolate* isolate, v8::base::RandomNumberGenerator* rng) 42 : region_(region), isolate_(isolate), rng_(rng) { 43 #define DECLARE_TYPE(name, value) \ 44 name = Type::name(region); \ 45 types.push_back(name); 46 PROPER_BITSET_TYPE_LIST(DECLARE_TYPE) 47 #undef DECLARE_TYPE 48 49 SignedSmall = Type::SignedSmall(region); 50 UnsignedSmall = Type::UnsignedSmall(region); 51 52 object_map = isolate->factory()->NewMap( 53 JS_OBJECT_TYPE, JSObject::kHeaderSize); 54 array_map = isolate->factory()->NewMap( 55 JS_ARRAY_TYPE, JSArray::kSize); 56 number_map = isolate->factory()->NewMap( 57 HEAP_NUMBER_TYPE, HeapNumber::kSize); 58 uninitialized_map = isolate->factory()->uninitialized_map(); 59 ObjectClass = Type::Class(object_map, region); 60 ArrayClass = Type::Class(array_map, region); 61 NumberClass = Type::Class(number_map, region); 62 UninitializedClass = Type::Class(uninitialized_map, region); 63 64 maps.push_back(object_map); 65 maps.push_back(array_map); 66 maps.push_back(uninitialized_map); 67 for (MapVector::iterator it = maps.begin(); it != maps.end(); ++it) { 68 types.push_back(Type::Class(*it, region)); 69 } 70 71 smi = handle(Smi::FromInt(666), isolate); 72 signed32 = isolate->factory()->NewHeapNumber(0x40000000); 73 object1 = isolate->factory()->NewJSObjectFromMap(object_map); 74 object2 = isolate->factory()->NewJSObjectFromMap(object_map); 75 array = isolate->factory()->NewJSArray(20); 76 uninitialized = isolate->factory()->uninitialized_value(); 77 SmiConstant = Type::Constant(smi, region); 78 Signed32Constant = Type::Constant(signed32, region); 79 80 ObjectConstant1 = Type::Constant(object1, region); 81 ObjectConstant2 = Type::Constant(object2, region); 82 ArrayConstant = Type::Constant(array, region); 83 UninitializedConstant = Type::Constant(uninitialized, region); 84 85 values.push_back(smi); 86 values.push_back(signed32); 87 values.push_back(object1); 88 values.push_back(object2); 89 values.push_back(array); 90 values.push_back(uninitialized); 91 for (ValueVector::iterator it = values.begin(); it != values.end(); ++it) { 92 types.push_back(Type::Constant(*it, region)); 93 } 94 95 integers.push_back(isolate->factory()->NewNumber(-V8_INFINITY)); 96 integers.push_back(isolate->factory()->NewNumber(+V8_INFINITY)); 97 integers.push_back(isolate->factory()->NewNumber(-rng_->NextInt(10))); 98 integers.push_back(isolate->factory()->NewNumber(+rng_->NextInt(10))); 99 for (int i = 0; i < 10; ++i) { 100 double x = rng_->NextInt(); 101 integers.push_back(isolate->factory()->NewNumber(x)); 102 x *= rng_->NextInt(); 103 if (!IsMinusZero(x)) integers.push_back(isolate->factory()->NewNumber(x)); 104 } 105 106 Integer = Type::Range(-V8_INFINITY, +V8_INFINITY, region); 107 108 NumberArray = Type::Array(Number, region); 109 StringArray = Type::Array(String, region); 110 AnyArray = Type::Array(Any, region); 111 112 SignedFunction1 = Type::Function(SignedSmall, SignedSmall, region); 113 NumberFunction1 = Type::Function(Number, Number, region); 114 NumberFunction2 = Type::Function(Number, Number, Number, region); 115 MethodFunction = Type::Function(String, Object, 0, region); 116 117 for (int i = 0; i < 30; ++i) { 118 types.push_back(Fuzz()); 119 } 120 } 121 122 Handle<i::Map> object_map; 123 Handle<i::Map> array_map; 124 Handle<i::Map> number_map; 125 Handle<i::Map> uninitialized_map; 126 127 Handle<i::Smi> smi; 128 Handle<i::HeapNumber> signed32; 129 Handle<i::JSObject> object1; 130 Handle<i::JSObject> object2; 131 Handle<i::JSArray> array; 132 Handle<i::Oddball> uninitialized; 133 134 #define DECLARE_TYPE(name, value) TypeHandle name; 135 PROPER_BITSET_TYPE_LIST(DECLARE_TYPE) 136 #undef DECLARE_TYPE 137 138 #define DECLARE_TYPE(name, value) TypeHandle Mask##name##ForTesting; 139 MASK_BITSET_TYPE_LIST(DECLARE_TYPE) 140 #undef DECLARE_TYPE 141 TypeHandle SignedSmall; 142 TypeHandle UnsignedSmall; 143 144 TypeHandle ObjectClass; 145 TypeHandle ArrayClass; 146 TypeHandle NumberClass; 147 TypeHandle UninitializedClass; 148 149 TypeHandle SmiConstant; 150 TypeHandle Signed32Constant; 151 TypeHandle ObjectConstant1; 152 TypeHandle ObjectConstant2; 153 TypeHandle ArrayConstant; 154 TypeHandle UninitializedConstant; 155 156 TypeHandle Integer; 157 158 TypeHandle NumberArray; 159 TypeHandle StringArray; 160 TypeHandle AnyArray; 161 162 TypeHandle SignedFunction1; 163 TypeHandle NumberFunction1; 164 TypeHandle NumberFunction2; 165 TypeHandle MethodFunction; 166 167 typedef std::vector<TypeHandle> TypeVector; 168 typedef std::vector<Handle<i::Map> > MapVector; 169 typedef std::vector<Handle<i::Object> > ValueVector; 170 171 TypeVector types; 172 MapVector maps; 173 ValueVector values; 174 ValueVector integers; // "Integer" values used for range limits. 175 Of(Handle<i::Object> value)176 TypeHandle Of(Handle<i::Object> value) { 177 return Type::Of(value, region_); 178 } 179 NowOf(Handle<i::Object> value)180 TypeHandle NowOf(Handle<i::Object> value) { 181 return Type::NowOf(value, region_); 182 } 183 Class(Handle<i::Map> map)184 TypeHandle Class(Handle<i::Map> map) { 185 return Type::Class(map, region_); 186 } 187 Constant(Handle<i::Object> value)188 TypeHandle Constant(Handle<i::Object> value) { 189 return Type::Constant(value, region_); 190 } 191 Range(double min,double max)192 TypeHandle Range(double min, double max) { 193 return Type::Range(min, max, region_); 194 } 195 Context(TypeHandle outer)196 TypeHandle Context(TypeHandle outer) { 197 return Type::Context(outer, region_); 198 } 199 Array1(TypeHandle element)200 TypeHandle Array1(TypeHandle element) { 201 return Type::Array(element, region_); 202 } 203 Function0(TypeHandle result,TypeHandle receiver)204 TypeHandle Function0(TypeHandle result, TypeHandle receiver) { 205 return Type::Function(result, receiver, 0, region_); 206 } 207 Function1(TypeHandle result,TypeHandle receiver,TypeHandle arg)208 TypeHandle Function1(TypeHandle result, TypeHandle receiver, TypeHandle arg) { 209 TypeHandle type = Type::Function(result, receiver, 1, region_); 210 type->AsFunction()->InitParameter(0, arg); 211 return type; 212 } 213 Function2(TypeHandle result,TypeHandle arg1,TypeHandle arg2)214 TypeHandle Function2(TypeHandle result, TypeHandle arg1, TypeHandle arg2) { 215 return Type::Function(result, arg1, arg2, region_); 216 } 217 Union(TypeHandle t1,TypeHandle t2)218 TypeHandle Union(TypeHandle t1, TypeHandle t2) { 219 return Type::Union(t1, t2, region_); 220 } 221 Intersect(TypeHandle t1,TypeHandle t2)222 TypeHandle Intersect(TypeHandle t1, TypeHandle t2) { 223 return Type::Intersect(t1, t2, region_); 224 } 225 Representation(TypeHandle t)226 TypeHandle Representation(TypeHandle t) { 227 return Type::Representation(t, region_); 228 } 229 230 // TypeHandle Semantic(TypeHandle t) { return Intersect(t, 231 // MaskSemanticForTesting); } Semantic(TypeHandle t)232 TypeHandle Semantic(TypeHandle t) { return Type::Semantic(t, region_); } 233 234 template<class Type2, class TypeHandle2> Convert(TypeHandle2 t)235 TypeHandle Convert(TypeHandle2 t) { 236 return Type::template Convert<Type2>(t, region_); 237 } 238 Random()239 TypeHandle Random() { 240 return types[rng_->NextInt(static_cast<int>(types.size()))]; 241 } 242 243 TypeHandle Fuzz(int depth = 4) { 244 switch (rng_->NextInt(depth == 0 ? 3 : 20)) { 245 case 0: { // bitset 246 #define COUNT_BITSET_TYPES(type, value) + 1 247 int n = 0 PROPER_BITSET_TYPE_LIST(COUNT_BITSET_TYPES); 248 #undef COUNT_BITSET_TYPES 249 // Pick a bunch of named bitsets and return their intersection. 250 TypeHandle result = Type::Any(region_); 251 for (int i = 0, m = 1 + rng_->NextInt(3); i < m; ++i) { 252 int j = rng_->NextInt(n); 253 #define PICK_BITSET_TYPE(type, value) \ 254 if (j-- == 0) { \ 255 TypeHandle tmp = Type::Intersect( \ 256 result, Type::type(region_), region_); \ 257 if (tmp->Is(Type::None()) && i != 0) { \ 258 break; \ 259 } else { \ 260 result = tmp; \ 261 continue; \ 262 } \ 263 } 264 PROPER_BITSET_TYPE_LIST(PICK_BITSET_TYPE) 265 #undef PICK_BITSET_TYPE 266 } 267 return result; 268 } 269 case 1: { // class 270 int i = rng_->NextInt(static_cast<int>(maps.size())); 271 return Type::Class(maps[i], region_); 272 } 273 case 2: { // constant 274 int i = rng_->NextInt(static_cast<int>(values.size())); 275 return Type::Constant(values[i], region_); 276 } 277 case 3: { // range 278 int i = rng_->NextInt(static_cast<int>(integers.size())); 279 int j = rng_->NextInt(static_cast<int>(integers.size())); 280 double min = integers[i]->Number(); 281 double max = integers[j]->Number(); 282 if (min > max) std::swap(min, max); 283 return Type::Range(min, max, region_); 284 } 285 case 4: { // context 286 int depth = rng_->NextInt(3); 287 TypeHandle type = Type::Internal(region_); 288 for (int i = 0; i < depth; ++i) type = Type::Context(type, region_); 289 return type; 290 } 291 case 5: { // array 292 TypeHandle element = Fuzz(depth / 2); 293 return Type::Array(element, region_); 294 } 295 case 6: 296 case 7: { // function 297 TypeHandle result = Fuzz(depth / 2); 298 TypeHandle receiver = Fuzz(depth / 2); 299 int arity = rng_->NextInt(3); 300 TypeHandle type = Type::Function(result, receiver, arity, region_); 301 for (int i = 0; i < type->AsFunction()->Arity(); ++i) { 302 TypeHandle parameter = Fuzz(depth / 2); 303 type->AsFunction()->InitParameter(i, parameter); 304 } 305 return type; 306 } 307 case 8: { // simd 308 static const int num_simd_types = 309 #define COUNT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) +1 310 SIMD128_TYPES(COUNT_SIMD_TYPE); 311 #undef COUNT_SIMD_TYPE 312 TypeHandle (*simd_constructors[num_simd_types])(Isolate*, Region*) = { 313 #define COUNT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \ 314 &Type::Name, 315 SIMD128_TYPES(COUNT_SIMD_TYPE) 316 #undef COUNT_SIMD_TYPE 317 }; 318 return simd_constructors[rng_->NextInt(num_simd_types)]( 319 isolate_, region_); 320 } 321 default: { // union 322 int n = rng_->NextInt(10); 323 TypeHandle type = None; 324 for (int i = 0; i < n; ++i) { 325 TypeHandle operand = Fuzz(depth - 1); 326 type = Type::Union(type, operand, region_); 327 } 328 return type; 329 } 330 } 331 UNREACHABLE(); 332 } 333 region()334 Region* region() { return region_; } 335 336 private: 337 Region* region_; 338 Isolate* isolate_; 339 v8::base::RandomNumberGenerator* rng_; 340 }; 341 342 343 } // namespace internal 344 } // namespace v8 345 346 #endif 347