| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 11 matching lines...) Expand all Loading... |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_TYPE_INFO_H_ | 28 #ifndef V8_TYPE_INFO_H_ |
| 29 #define V8_TYPE_INFO_H_ | 29 #define V8_TYPE_INFO_H_ |
| 30 | 30 |
| 31 #include "globals.h" | 31 #include "globals.h" |
| 32 #include "zone.h" |
| 33 #include "zone-inl.h" |
| 32 | 34 |
| 33 namespace v8 { | 35 namespace v8 { |
| 34 namespace internal { | 36 namespace internal { |
| 35 | 37 |
| 36 // Unknown | 38 // Unknown |
| 37 // | | 39 // | | |
| 38 // PrimitiveType | 40 // | \--------------| |
| 39 // | \--------| | 41 // Primitive Non-primitive |
| 40 // Number String | 42 // | \--------| | |
| 41 // / | | | 43 // Number String | |
| 42 // Double Integer32 | | 44 // / | | | |
| 43 // | | / | 45 // Double Integer32 | / |
| 44 // | Smi / | 46 // | | / / |
| 45 // | / / | 47 // | Smi / / |
| 46 // Uninitialized. | 48 // | | / / |
| 49 // | | / / |
| 50 // Uninitialized.--/ |
| 47 | 51 |
| 48 class TypeInfo { | 52 class TypeInfo { |
| 49 public: | 53 public: |
| 50 TypeInfo() : type_(kUnknownType) { } | 54 TypeInfo() : type_(kUninitialized) { } |
| 51 | 55 |
| 52 static inline TypeInfo Unknown(); | 56 static TypeInfo Unknown() { return TypeInfo(kUnknown); } |
| 53 // We know it's a primitive type. | 57 // We know it's a primitive type. |
| 54 static inline TypeInfo Primitive(); | 58 static TypeInfo Primitive() { return TypeInfo(kPrimitive); } |
| 55 // We know it's a number of some sort. | 59 // We know it's a number of some sort. |
| 56 static inline TypeInfo Number(); | 60 static TypeInfo Number() { return TypeInfo(kNumber); } |
| 57 // We know it's signed 32 bit integer. | 61 // We know it's a signed 32 bit integer. |
| 58 static inline TypeInfo Integer32(); | 62 static TypeInfo Integer32() { return TypeInfo(kInteger32); } |
| 59 // We know it's a Smi. | 63 // We know it's a Smi. |
| 60 static inline TypeInfo Smi(); | 64 static TypeInfo Smi() { return TypeInfo(kSmi); } |
| 61 // We know it's a heap number. | 65 // We know it's a heap number. |
| 62 static inline TypeInfo Double(); | 66 static TypeInfo Double() { return TypeInfo(kDouble); } |
| 63 // We know it's a string. | 67 // We know it's a string. |
| 64 static inline TypeInfo String(); | 68 static TypeInfo String() { return TypeInfo(kString); } |
| 69 // We know it's a non-primitive (object) type. |
| 70 static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); } |
| 65 // We haven't started collecting info yet. | 71 // We haven't started collecting info yet. |
| 66 static inline TypeInfo Uninitialized(); | 72 static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); } |
| 67 | 73 |
| 68 // Return compact representation. Very sensitive to enum values below! | 74 // Return compact representation. Very sensitive to enum values below! |
| 69 // Compacting drops information about primtive types and strings types. | 75 // Compacting drops information about primitive types and strings types. |
| 70 // We use the compact representation when we only care about number types. | 76 // We use the compact representation when we only care about number types. |
| 71 int ThreeBitRepresentation() { | 77 int ThreeBitRepresentation() { |
| 72 ASSERT(type_ != kUninitializedType); | 78 ASSERT(type_ != kUninitialized); |
| 73 int answer = type_ & 0xf; | 79 int answer = type_ & 0xf; |
| 74 answer = answer > 6 ? answer - 2 : answer; | 80 answer = answer > 6 ? answer - 2 : answer; |
| 75 ASSERT(answer >= 0); | 81 ASSERT(answer >= 0); |
| 76 ASSERT(answer <= 7); | 82 ASSERT(answer <= 7); |
| 77 return answer; | 83 return answer; |
| 78 } | 84 } |
| 79 | 85 |
| 80 // Decode compact representation. Very sensitive to enum values below! | 86 // Decode compact representation. Very sensitive to enum values below! |
| 81 static TypeInfo ExpandedRepresentation(int three_bit_representation) { | 87 static TypeInfo ExpandedRepresentation(int three_bit_representation) { |
| 82 Type t = static_cast<Type>(three_bit_representation > 4 ? | 88 Type t = static_cast<Type>(three_bit_representation > 4 ? |
| 83 three_bit_representation + 2 : | 89 three_bit_representation + 2 : |
| 84 three_bit_representation); | 90 three_bit_representation); |
| 85 t = (t == kUnknownType) ? t : static_cast<Type>(t | kPrimitiveType); | 91 t = (t == kUnknown) ? t : static_cast<Type>(t | kPrimitive); |
| 86 ASSERT(t == kUnknownType || | 92 ASSERT(t == kUnknown || |
| 87 t == kNumberType || | 93 t == kNumber || |
| 88 t == kInteger32Type || | 94 t == kInteger32 || |
| 89 t == kSmiType || | 95 t == kSmi || |
| 90 t == kDoubleType); | 96 t == kDouble); |
| 91 return TypeInfo(t); | 97 return TypeInfo(t); |
| 92 } | 98 } |
| 93 | 99 |
| 94 int ToInt() { | 100 int ToInt() { |
| 95 return type_; | 101 return type_; |
| 96 } | 102 } |
| 97 | 103 |
| 98 static TypeInfo FromInt(int bit_representation) { | 104 static TypeInfo FromInt(int bit_representation) { |
| 99 Type t = static_cast<Type>(bit_representation); | 105 Type t = static_cast<Type>(bit_representation); |
| 100 ASSERT(t == kUnknownType || | 106 ASSERT(t == kUnknown || |
| 101 t == kPrimitiveType || | 107 t == kPrimitive || |
| 102 t == kNumberType || | 108 t == kNumber || |
| 103 t == kInteger32Type || | 109 t == kInteger32 || |
| 104 t == kSmiType || | 110 t == kSmi || |
| 105 t == kDoubleType || | 111 t == kDouble || |
| 106 t == kStringType); | 112 t == kString || |
| 113 t == kNonPrimitive); |
| 107 return TypeInfo(t); | 114 return TypeInfo(t); |
| 108 } | 115 } |
| 109 | 116 |
| 110 // Return the weakest (least precise) common type. | 117 // Return the weakest (least precise) common type. |
| 111 static TypeInfo Combine(TypeInfo a, TypeInfo b) { | 118 static TypeInfo Combine(TypeInfo a, TypeInfo b) { |
| 112 return TypeInfo(static_cast<Type>(a.type_ & b.type_)); | 119 return TypeInfo(static_cast<Type>(a.type_ & b.type_)); |
| 113 } | 120 } |
| 114 | 121 |
| 115 | 122 |
| 116 // Integer32 is an integer that can be represented as a signed | 123 // Integer32 is an integer that can be represented as either a signed |
| 117 // 32-bit integer. It has to be in the range [-2^31, 2^31 - 1]. | 124 // 32-bit integer or as an unsigned 32-bit integer. It has to be |
| 118 // We also have to check for negative 0 as it is not an Integer32. | 125 // in the range [-2^31, 2^32 - 1]. We also have to check for negative 0 |
| 126 // as it is not an Integer32. |
| 119 static inline bool IsInt32Double(double value) { | 127 static inline bool IsInt32Double(double value) { |
| 120 const DoubleRepresentation minus_zero(-0.0); | 128 const DoubleRepresentation minus_zero(-0.0); |
| 121 DoubleRepresentation rep(value); | 129 DoubleRepresentation rep(value); |
| 122 if (rep.bits == minus_zero.bits) return false; | 130 if (rep.bits == minus_zero.bits) return false; |
| 123 if (value >= kMinInt && value <= kMaxInt) { | 131 if (value >= kMinInt && value <= kMaxInt && |
| 124 if (value == static_cast<int32_t>(value)) return true; | 132 value == static_cast<int32_t>(value)) { |
| 133 return true; |
| 125 } | 134 } |
| 126 return false; | 135 return false; |
| 127 } | 136 } |
| 128 | 137 |
| 129 static TypeInfo TypeFromValue(Handle<Object> value); | 138 static TypeInfo TypeFromValue(Handle<Object> value); |
| 130 | 139 |
| 140 bool Equals(const TypeInfo& other) { |
| 141 return type_ == other.type_; |
| 142 } |
| 143 |
| 131 inline bool IsUnknown() { | 144 inline bool IsUnknown() { |
| 132 return type_ == kUnknownType; | 145 ASSERT(type_ != kUninitialized); |
| 146 return type_ == kUnknown; |
| 147 } |
| 148 |
| 149 inline bool IsPrimitive() { |
| 150 ASSERT(type_ != kUninitialized); |
| 151 return ((type_ & kPrimitive) == kPrimitive); |
| 133 } | 152 } |
| 134 | 153 |
| 135 inline bool IsNumber() { | 154 inline bool IsNumber() { |
| 136 ASSERT(type_ != kUninitializedType); | 155 ASSERT(type_ != kUninitialized); |
| 137 return ((type_ & kNumberType) == kNumberType); | 156 return ((type_ & kNumber) == kNumber); |
| 138 } | 157 } |
| 139 | 158 |
| 140 inline bool IsSmi() { | 159 inline bool IsSmi() { |
| 141 ASSERT(type_ != kUninitializedType); | 160 ASSERT(type_ != kUninitialized); |
| 142 return ((type_ & kSmiType) == kSmiType); | 161 return ((type_ & kSmi) == kSmi); |
| 143 } | 162 } |
| 144 | 163 |
| 145 inline bool IsInteger32() { | 164 inline bool IsInteger32() { |
| 146 ASSERT(type_ != kUninitializedType); | 165 ASSERT(type_ != kUninitialized); |
| 147 return ((type_ & kInteger32Type) == kInteger32Type); | 166 return ((type_ & kInteger32) == kInteger32); |
| 148 } | 167 } |
| 149 | 168 |
| 150 inline bool IsDouble() { | 169 inline bool IsDouble() { |
| 151 ASSERT(type_ != kUninitializedType); | 170 ASSERT(type_ != kUninitialized); |
| 152 return ((type_ & kDoubleType) == kDoubleType); | 171 return ((type_ & kDouble) == kDouble); |
| 153 } | 172 } |
| 154 | 173 |
| 155 inline bool IsString() { | 174 inline bool IsString() { |
| 156 ASSERT(type_ != kUninitializedType); | 175 ASSERT(type_ != kUninitialized); |
| 157 return ((type_ & kStringType) == kStringType); | 176 return ((type_ & kString) == kString); |
| 177 } |
| 178 |
| 179 inline bool IsNonPrimitive() { |
| 180 ASSERT(type_ != kUninitialized); |
| 181 return ((type_ & kNonPrimitive) == kNonPrimitive); |
| 158 } | 182 } |
| 159 | 183 |
| 160 inline bool IsUninitialized() { | 184 inline bool IsUninitialized() { |
| 161 return type_ == kUninitializedType; | 185 return type_ == kUninitialized; |
| 162 } | 186 } |
| 163 | 187 |
| 164 const char* ToString() { | 188 const char* ToString() { |
| 165 switch (type_) { | 189 switch (type_) { |
| 166 case kUnknownType: return "UnknownType"; | 190 case kUnknown: return "Unknown"; |
| 167 case kPrimitiveType: return "PrimitiveType"; | 191 case kPrimitive: return "Primitive"; |
| 168 case kNumberType: return "NumberType"; | 192 case kNumber: return "Number"; |
| 169 case kInteger32Type: return "Integer32Type"; | 193 case kInteger32: return "Integer32"; |
| 170 case kSmiType: return "SmiType"; | 194 case kSmi: return "Smi"; |
| 171 case kDoubleType: return "DoubleType"; | 195 case kDouble: return "Double"; |
| 172 case kStringType: return "StringType"; | 196 case kString: return "String"; |
| 173 case kUninitializedType: | 197 case kNonPrimitive: return "Object"; |
| 174 UNREACHABLE(); | 198 case kUninitialized: return "Uninitialized"; |
| 175 return "UninitializedType"; | |
| 176 } | 199 } |
| 177 UNREACHABLE(); | 200 UNREACHABLE(); |
| 178 return "Unreachable code"; | 201 return "Unreachable code"; |
| 179 } | 202 } |
| 180 | 203 |
| 181 private: | 204 private: |
| 182 // We use 6 bits to represent the types. | |
| 183 enum Type { | 205 enum Type { |
| 184 kUnknownType = 0, // 000000 | 206 kUnknown = 0, // 0000000 |
| 185 kPrimitiveType = 0x10, // 010000 | 207 kPrimitive = 0x10, // 0010000 |
| 186 kNumberType = 0x11, // 010001 | 208 kNumber = 0x11, // 0010001 |
| 187 kInteger32Type = 0x13, // 010011 | 209 kInteger32 = 0x13, // 0010011 |
| 188 kSmiType = 0x17, // 010111 | 210 kSmi = 0x17, // 0010111 |
| 189 kDoubleType = 0x19, // 011001 | 211 kDouble = 0x19, // 0011001 |
| 190 kStringType = 0x30, // 110000 | 212 kString = 0x30, // 0110000 |
| 191 kUninitializedType = 0x3f // 111111 | 213 kNonPrimitive = 0x40, // 1000000 |
| 214 kUninitialized = 0x7f // 1111111 |
| 192 }; | 215 }; |
| 193 explicit inline TypeInfo(Type t) : type_(t) { } | 216 explicit inline TypeInfo(Type t) : type_(t) { } |
| 194 | 217 |
| 195 Type type_; | 218 Type type_; |
| 196 }; | 219 }; |
| 197 | 220 |
| 198 | 221 |
| 199 TypeInfo TypeInfo::Unknown() { | 222 // Forward declarations. |
| 200 return TypeInfo(kUnknownType); | 223 class Assignment; |
| 201 } | 224 class BinaryOperation; |
| 225 class Call; |
| 226 class CompareOperation; |
| 227 class CompilationInfo; |
| 228 class Property; |
| 229 class CaseClause; |
| 202 | 230 |
| 231 class TypeFeedbackOracle BASE_EMBEDDED { |
| 232 public: |
| 233 enum Side { |
| 234 LEFT, |
| 235 RIGHT, |
| 236 RESULT |
| 237 }; |
| 203 | 238 |
| 204 TypeInfo TypeInfo::Primitive() { | 239 explicit TypeFeedbackOracle(Handle<Code> code); |
| 205 return TypeInfo(kPrimitiveType); | |
| 206 } | |
| 207 | 240 |
| 241 bool LoadIsMonomorphic(Property* expr); |
| 242 bool StoreIsMonomorphic(Assignment* expr); |
| 243 bool CallIsMonomorphic(Call* expr); |
| 208 | 244 |
| 209 TypeInfo TypeInfo::Number() { | 245 Handle<Map> LoadMonomorphicReceiverType(Property* expr); |
| 210 return TypeInfo(kNumberType); | 246 Handle<Map> StoreMonomorphicReceiverType(Assignment* expr); |
| 211 } | 247 Handle<Map> CallMonomorphicReceiverType(Call* expr); |
| 212 | 248 |
| 249 ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name); |
| 250 ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name); |
| 251 ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name); |
| 213 | 252 |
| 214 TypeInfo TypeInfo::Integer32() { | 253 bool LoadIsBuiltin(Property* expr, Builtins::Name id); |
| 215 return TypeInfo(kInteger32Type); | |
| 216 } | |
| 217 | 254 |
| 255 // Get type information for arithmetic operations and compares. |
| 256 TypeInfo BinaryType(BinaryOperation* expr, Side side); |
| 257 TypeInfo CompareType(CompareOperation* expr, Side side); |
| 258 TypeInfo SwitchType(CaseClause* clause); |
| 218 | 259 |
| 219 TypeInfo TypeInfo::Smi() { | 260 private: |
| 220 return TypeInfo(kSmiType); | 261 void Initialize(Handle<Code> code); |
| 221 } | |
| 222 | 262 |
| 263 bool IsMonomorphic(int pos) { return GetElement(map_, pos)->IsMap(); } |
| 223 | 264 |
| 224 TypeInfo TypeInfo::Double() { | 265 ZoneMapList* CollectReceiverTypes(int position, |
| 225 return TypeInfo(kDoubleType); | 266 Handle<String> name, |
| 226 } | 267 Code::Flags flags); |
| 227 | 268 |
| 269 void PopulateMap(Handle<Code> code); |
| 228 | 270 |
| 229 TypeInfo TypeInfo::String() { | 271 void CollectPositions(Code* code, |
| 230 return TypeInfo(kStringType); | 272 List<int>* code_positions, |
| 231 } | 273 List<int>* source_positions); |
| 232 | 274 |
| 275 Handle<JSObject> map_; |
| 233 | 276 |
| 234 TypeInfo TypeInfo::Uninitialized() { | 277 DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle); |
| 235 return TypeInfo(kUninitializedType); | 278 }; |
| 236 } | |
| 237 | 279 |
| 238 } } // namespace v8::internal | 280 } } // namespace v8::internal |
| 239 | 281 |
| 240 #endif // V8_TYPE_INFO_H_ | 282 #endif // V8_TYPE_INFO_H_ |
| OLD | NEW |