| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 // | 88 // |
| 89 // Internally, all 'primitive' types, and their unions, are represented as | 89 // Internally, all 'primitive' types, and their unions, are represented as |
| 90 // bitsets via smis. Class is a heap pointer to the respective map. Only | 90 // bitsets via smis. Class is a heap pointer to the respective map. Only |
| 91 // Constant's, or unions containing Class'es or Constant's, require allocation. | 91 // Constant's, or unions containing Class'es or Constant's, require allocation. |
| 92 // Note that the bitset representation is closed under both Union and Intersect. | 92 // Note that the bitset representation is closed under both Union and Intersect. |
| 93 // | 93 // |
| 94 // The type representation is heap-allocated, so cannot (currently) be used in | 94 // The type representation is heap-allocated, so cannot (currently) be used in |
| 95 // a concurrent compilation context. | 95 // a concurrent compilation context. |
| 96 | 96 |
| 97 | 97 |
| 98 #define PRIMITIVE_TYPE_LIST(V) \ | 98 #define BITSET_TYPE_LIST(V) \ |
| 99 V(None, 0) \ | 99 V(None, 0) \ |
| 100 V(Null, 1 << 0) \ | 100 V(Null, 1 << 0) \ |
| 101 V(Undefined, 1 << 1) \ | 101 V(Undefined, 1 << 1) \ |
| 102 V(Boolean, 1 << 2) \ | 102 V(Boolean, 1 << 2) \ |
| 103 V(Smi, 1 << 3) \ | 103 V(Smi, 1 << 3) \ |
| 104 V(OtherSigned32, 1 << 4) \ | 104 V(OtherSigned32, 1 << 4) \ |
| 105 V(Unsigned32, 1 << 5) \ | 105 V(Unsigned32, 1 << 5) \ |
| 106 V(Double, 1 << 6) \ | 106 V(Double, 1 << 6) \ |
| 107 V(Symbol, 1 << 7) \ | 107 V(Symbol, 1 << 7) \ |
| 108 V(InternalizedString, 1 << 8) \ | 108 V(InternalizedString, 1 << 8) \ |
| 109 V(OtherString, 1 << 9) \ | 109 V(OtherString, 1 << 9) \ |
| 110 V(Undetectable, 1 << 10) \ | 110 V(Undetectable, 1 << 10) \ |
| 111 V(Array, 1 << 11) \ | 111 V(Array, 1 << 11) \ |
| 112 V(Function, 1 << 12) \ | 112 V(Function, 1 << 12) \ |
| 113 V(RegExp, 1 << 13) \ | 113 V(RegExp, 1 << 13) \ |
| 114 V(OtherObject, 1 << 14) \ | 114 V(OtherObject, 1 << 14) \ |
| 115 V(Proxy, 1 << 15) \ | 115 V(Proxy, 1 << 15) \ |
| 116 V(Internal, 1 << 16) | 116 V(Internal, 1 << 16) \ |
| 117 | 117 \ |
| 118 #define COMPOSED_TYPE_LIST(V) \ | |
| 119 V(Oddball, kBoolean | kNull | kUndefined) \ | 118 V(Oddball, kBoolean | kNull | kUndefined) \ |
| 120 V(Signed32, kSmi | kOtherSigned32) \ | 119 V(Signed32, kSmi | kOtherSigned32) \ |
| 121 V(Number, kSigned32 | kUnsigned32 | kDouble) \ | 120 V(Number, kSigned32 | kUnsigned32 | kDouble) \ |
| 122 V(String, kInternalizedString | kOtherString) \ | 121 V(String, kInternalizedString | kOtherString) \ |
| 123 V(UniqueName, kSymbol | kInternalizedString) \ | 122 V(UniqueName, kSymbol | kInternalizedString) \ |
| 124 V(Name, kSymbol | kString) \ | 123 V(Name, kSymbol | kString) \ |
| 125 V(NumberOrString, kNumber | kString) \ | 124 V(NumberOrString, kNumber | kString) \ |
| 126 V(Object, kUndetectable | kArray | kFunction | \ | 125 V(Object, kUndetectable | kArray | kFunction | \ |
| 127 kRegExp | kOtherObject) \ | 126 kRegExp | kOtherObject) \ |
| 128 V(Receiver, kObject | kProxy) \ | 127 V(Receiver, kObject | kProxy) \ |
| 129 V(Allocated, kDouble | kName | kReceiver) \ | 128 V(Allocated, kDouble | kName | kReceiver) \ |
| 130 V(Any, kOddball | kNumber | kAllocated | kInternal) \ | 129 V(Any, kOddball | kNumber | kAllocated | kInternal) \ |
| 131 V(NonNumber, kAny - kNumber) \ | 130 V(NonNumber, kAny - kNumber) \ |
| 132 V(Detectable, kAllocated - kUndetectable) | 131 V(Detectable, kAllocated - kUndetectable) |
| 133 | 132 |
| 134 #define TYPE_LIST(V) \ | |
| 135 PRIMITIVE_TYPE_LIST(V) \ | |
| 136 COMPOSED_TYPE_LIST(V) | |
| 137 | |
| 138 | |
| 139 | 133 |
| 140 class Type : public Object { | 134 class Type : public Object { |
| 141 public: | 135 public: |
| 142 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ | 136 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ |
| 143 static Type* type() { return from_bitset(k##type); } | 137 static Type* type() { return from_bitset(k##type); } |
| 144 TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) | 138 BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) |
| 145 #undef DEFINE_TYPE_CONSTRUCTOR | 139 #undef DEFINE_TYPE_CONSTRUCTOR |
| 146 | 140 |
| 147 static Type* Class(Handle<Map> map) { return from_handle(map); } | 141 static Type* Class(Handle<i::Map> map) { return from_handle(map); } |
| 148 static Type* Constant(Handle<HeapObject> value) { | 142 static Type* Constant(Handle<i::HeapObject> value) { |
| 149 return Constant(value, value->GetIsolate()); | 143 return Constant(value, value->GetIsolate()); |
| 150 } | 144 } |
| 151 static Type* Constant(Handle<v8::internal::Object> value, Isolate* isolate) { | 145 static Type* Constant(Handle<i::Object> value, Isolate* isolate) { |
| 152 return from_handle(isolate->factory()->NewBox(value)); | 146 return from_handle(isolate->factory()->NewBox(value)); |
| 153 } | 147 } |
| 154 | 148 |
| 155 static Type* Union(Handle<Type> type1, Handle<Type> type2); | 149 static Type* Union(Handle<Type> type1, Handle<Type> type2); |
| 156 static Type* Intersect(Handle<Type> type1, Handle<Type> type2); | 150 static Type* Intersect(Handle<Type> type1, Handle<Type> type2); |
| 157 static Type* Optional(Handle<Type> type); // type \/ Undefined | 151 static Type* Optional(Handle<Type> type); // type \/ Undefined |
| 158 | 152 |
| 159 bool Is(Type* that) { return (this == that) ? true : SlowIs(that); } | 153 static Type* Of(Handle<i::Object> value) { |
| 154 return from_bitset(LubBitset(*value)); |
| 155 } |
| 156 |
| 157 bool Is(Type* that) { return this == that || SlowIs(that); } |
| 160 bool Is(Handle<Type> that) { return this->Is(*that); } | 158 bool Is(Handle<Type> that) { return this->Is(*that); } |
| 161 bool Maybe(Type* that); | 159 bool Maybe(Type* that); |
| 162 bool Maybe(Handle<Type> that) { return this->Maybe(*that); } | 160 bool Maybe(Handle<Type> that) { return this->Maybe(*that); } |
| 163 | 161 |
| 162 // State-dependent versions of Of and Is that consider subtyping between |
| 163 // a constant and its map class. |
| 164 static Type* OfCurrently(Handle<i::Object> value); |
| 165 bool IsCurrently(Type* that); |
| 166 bool IsCurrently(Handle<Type> that) { return this->IsCurrently(*that); } |
| 167 |
| 164 bool IsClass() { return is_class(); } | 168 bool IsClass() { return is_class(); } |
| 165 bool IsConstant() { return is_constant(); } | 169 bool IsConstant() { return is_constant(); } |
| 166 Handle<Map> AsClass() { return as_class(); } | 170 Handle<i::Map> AsClass() { return as_class(); } |
| 167 Handle<v8::internal::Object> AsConstant() { return as_constant(); } | 171 Handle<i::Object> AsConstant() { return as_constant(); } |
| 168 | 172 |
| 169 int NumClasses(); | 173 int NumClasses(); |
| 170 int NumConstants(); | 174 int NumConstants(); |
| 171 | 175 |
| 172 template<class T> | 176 template<class T> |
| 173 class Iterator { | 177 class Iterator { |
| 174 public: | 178 public: |
| 175 bool Done() const { return index_ < 0; } | 179 bool Done() const { return index_ < 0; } |
| 176 Handle<T> Current(); | 180 Handle<T> Current(); |
| 177 void Advance(); | 181 void Advance(); |
| 178 | 182 |
| 179 private: | 183 private: |
| 180 friend class Type; | 184 friend class Type; |
| 181 | 185 |
| 182 Iterator() : index_(-1) {} | 186 Iterator() : index_(-1) {} |
| 183 explicit Iterator(Handle<Type> type) : type_(type), index_(-1) { | 187 explicit Iterator(Handle<Type> type) : type_(type), index_(-1) { |
| 184 Advance(); | 188 Advance(); |
| 185 } | 189 } |
| 186 | 190 |
| 187 inline bool matches(Handle<Type> type); | 191 inline bool matches(Handle<Type> type); |
| 188 inline Handle<Type> get_type(); | 192 inline Handle<Type> get_type(); |
| 189 | 193 |
| 190 Handle<Type> type_; | 194 Handle<Type> type_; |
| 191 int index_; | 195 int index_; |
| 192 }; | 196 }; |
| 193 | 197 |
| 194 Iterator<Map> Classes() { | 198 Iterator<i::Map> Classes() { |
| 195 if (this->is_bitset()) return Iterator<Map>(); | 199 if (this->is_bitset()) return Iterator<i::Map>(); |
| 196 return Iterator<Map>(this->handle()); | 200 return Iterator<i::Map>(this->handle()); |
| 197 } | 201 } |
| 198 Iterator<v8::internal::Object> Constants() { | 202 Iterator<i::Object> Constants() { |
| 199 if (this->is_bitset()) return Iterator<v8::internal::Object>(); | 203 if (this->is_bitset()) return Iterator<i::Object>(); |
| 200 return Iterator<v8::internal::Object>(this->handle()); | 204 return Iterator<i::Object>(this->handle()); |
| 201 } | 205 } |
| 202 | 206 |
| 203 static Type* cast(v8::internal::Object* object) { | 207 static Type* cast(i::Object* object) { |
| 204 Type* t = static_cast<Type*>(object); | 208 Type* t = static_cast<Type*>(object); |
| 205 ASSERT(t->is_bitset() || t->is_class() || | 209 ASSERT(t->is_bitset() || t->is_class() || |
| 206 t->is_constant() || t->is_union()); | 210 t->is_constant() || t->is_union()); |
| 207 return t; | 211 return t; |
| 208 } | 212 } |
| 209 | 213 |
| 210 #ifdef OBJECT_PRINT | 214 #ifdef OBJECT_PRINT |
| 211 void TypePrint(); | 215 void TypePrint(); |
| 212 void TypePrint(FILE* out); | 216 void TypePrint(FILE* out); |
| 213 #endif | 217 #endif |
| 214 | 218 |
| 215 private: | 219 private: |
| 216 // A union is a fixed array containing types. Invariants: | 220 // A union is a fixed array containing types. Invariants: |
| 217 // - its length is at least 2 | 221 // - its length is at least 2 |
| 218 // - at most one field is a bitset, and it must go into index 0 | 222 // - at most one field is a bitset, and it must go into index 0 |
| 219 // - no field is a union | 223 // - no field is a union |
| 220 typedef FixedArray Unioned; | 224 typedef FixedArray Unioned; |
| 221 | 225 |
| 222 enum { | 226 enum { |
| 223 #define DECLARE_TYPE(type, value) k##type = (value), | 227 #define DECLARE_TYPE(type, value) k##type = (value), |
| 224 TYPE_LIST(DECLARE_TYPE) | 228 BITSET_TYPE_LIST(DECLARE_TYPE) |
| 225 #undef DECLARE_TYPE | 229 #undef DECLARE_TYPE |
| 226 kUnusedEOL = 0 | 230 kUnusedEOL = 0 |
| 227 }; | 231 }; |
| 228 | 232 |
| 229 bool is_none() { return this == None(); } | 233 bool is_none() { return this == None(); } |
| 230 bool is_bitset() { return this->IsSmi(); } | 234 bool is_bitset() { return this->IsSmi(); } |
| 231 bool is_class() { return this->IsMap(); } | 235 bool is_class() { return this->IsMap(); } |
| 232 bool is_constant() { return this->IsBox(); } | 236 bool is_constant() { return this->IsBox(); } |
| 233 bool is_union() { return this->IsFixedArray(); } | 237 bool is_union() { return this->IsFixedArray(); } |
| 234 | 238 |
| 235 bool SlowIs(Type* that); | 239 bool SlowIs(Type* that); |
| 236 | 240 |
| 237 int as_bitset() { return Smi::cast(this)->value(); } | 241 int as_bitset() { return Smi::cast(this)->value(); } |
| 238 Handle<Map> as_class() { return Handle<Map>::cast(handle()); } | 242 Handle<i::Map> as_class() { return Handle<i::Map>::cast(handle()); } |
| 239 Handle<v8::internal::Object> as_constant() { | 243 Handle<i::Object> as_constant() { |
| 240 Handle<Box> box = Handle<Box>::cast(handle()); | 244 Handle<i::Box> box = Handle<i::Box>::cast(handle()); |
| 241 return v8::internal::handle(box->value(), box->GetIsolate()); | 245 return i::handle(box->value(), box->GetIsolate()); |
| 242 } | 246 } |
| 243 Handle<Unioned> as_union() { return Handle<Unioned>::cast(handle()); } | 247 Handle<Unioned> as_union() { return Handle<Unioned>::cast(handle()); } |
| 244 | 248 |
| 245 Handle<Type> handle() { return handle_via_isolate_of(this); } | 249 Handle<Type> handle() { return handle_via_isolate_of(this); } |
| 246 Handle<Type> handle_via_isolate_of(Type* type) { | 250 Handle<Type> handle_via_isolate_of(Type* type) { |
| 247 ASSERT(type->IsHeapObject()); | 251 ASSERT(type->IsHeapObject()); |
| 248 return v8::internal::handle(this, HeapObject::cast(type)->GetIsolate()); | 252 return i::handle(this, i::HeapObject::cast(type)->GetIsolate()); |
| 249 } | 253 } |
| 250 | 254 |
| 251 static Type* from_bitset(int bitset) { | 255 static Type* from_bitset(int bitset) { |
| 252 return static_cast<Type*>(Object::cast(Smi::FromInt(bitset))); | 256 return static_cast<Type*>(i::Object::cast(i::Smi::FromInt(bitset))); |
| 253 } | 257 } |
| 254 static Type* from_handle(Handle<HeapObject> handle) { | 258 static Type* from_handle(Handle<i::HeapObject> handle) { |
| 255 return static_cast<Type*>(Object::cast(*handle)); | 259 return static_cast<Type*>(i::Object::cast(*handle)); |
| 256 } | 260 } |
| 257 | 261 |
| 258 static Handle<Type> union_get(Handle<Unioned> unioned, int i) { | 262 static Handle<Type> union_get(Handle<Unioned> unioned, int i) { |
| 259 Type* type = static_cast<Type*>(unioned->get(i)); | 263 Type* type = static_cast<Type*>(unioned->get(i)); |
| 260 ASSERT(!type->is_union()); | 264 ASSERT(!type->is_union()); |
| 261 return type->handle_via_isolate_of(from_handle(unioned)); | 265 return type->handle_via_isolate_of(from_handle(unioned)); |
| 262 } | 266 } |
| 263 | 267 |
| 264 int LubBitset(); // least upper bound that's a bitset | 268 int LubBitset(); // least upper bound that's a bitset |
| 265 int GlbBitset(); // greatest lower bound that's a bitset | 269 int GlbBitset(); // greatest lower bound that's a bitset |
| 270 |
| 271 static int LubBitset(i::Object* value); |
| 272 static int LubBitset(i::Map* map); |
| 273 |
| 266 bool InUnion(Handle<Unioned> unioned, int current_size); | 274 bool InUnion(Handle<Unioned> unioned, int current_size); |
| 267 int ExtendUnion(Handle<Unioned> unioned, int current_size); | 275 int ExtendUnion(Handle<Unioned> unioned, int current_size); |
| 268 int ExtendIntersection( | 276 int ExtendIntersection( |
| 269 Handle<Unioned> unioned, Handle<Type> type, int current_size); | 277 Handle<Unioned> unioned, Handle<Type> type, int current_size); |
| 270 | 278 |
| 271 static const char* GetComposedName(int type) { | 279 static const char* bitset_name(int bitset); |
| 272 switch (type) { | |
| 273 #define PRINT_COMPOSED_TYPE(type, value) \ | |
| 274 case k##type: \ | |
| 275 return # type; | |
| 276 COMPOSED_TYPE_LIST(PRINT_COMPOSED_TYPE) | |
| 277 #undef PRINT_COMPOSED_TYPE | |
| 278 } | |
| 279 return NULL; | |
| 280 } | |
| 281 | |
| 282 static const char* GetPrimitiveName(int type) { | |
| 283 switch (type) { | |
| 284 #define PRINT_PRIMITIVE_TYPE(type, value) \ | |
| 285 case k##type: \ | |
| 286 return # type; | |
| 287 PRIMITIVE_TYPE_LIST(PRINT_PRIMITIVE_TYPE) | |
| 288 #undef PRINT_PRIMITIVE_TYPE | |
| 289 default: | |
| 290 UNREACHABLE(); | |
| 291 return "InvalidType"; | |
| 292 } | |
| 293 } | |
| 294 }; | 280 }; |
| 295 | 281 |
| 296 | 282 |
| 297 // A simple struct to represent a pair of lower/upper type bounds. | 283 // A simple struct to represent a pair of lower/upper type bounds. |
| 298 struct Bounds { | 284 struct Bounds { |
| 299 Handle<Type> lower; | 285 Handle<Type> lower; |
| 300 Handle<Type> upper; | 286 Handle<Type> upper; |
| 301 | 287 |
| 302 Bounds() {} | 288 Bounds() {} |
| 303 Bounds(Handle<Type> l, Handle<Type> u) : lower(l), upper(u) { | 289 Bounds(Handle<Type> l, Handle<Type> u) : lower(l), upper(u) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 static Bounds NarrowUpper(Bounds b, Handle<Type> t, Isolate* isl) { | 328 static Bounds NarrowUpper(Bounds b, Handle<Type> t, Isolate* isl) { |
| 343 return Bounds( | 329 return Bounds( |
| 344 handle(Type::Intersect(b.lower, t), isl), | 330 handle(Type::Intersect(b.lower, t), isl), |
| 345 handle(Type::Intersect(b.upper, t), isl)); | 331 handle(Type::Intersect(b.upper, t), isl)); |
| 346 } | 332 } |
| 347 }; | 333 }; |
| 348 | 334 |
| 349 } } // namespace v8::internal | 335 } } // namespace v8::internal |
| 350 | 336 |
| 351 #endif // V8_TYPES_H_ | 337 #endif // V8_TYPES_H_ |
| OLD | NEW |