sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 1 | // Copyright 2010 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_TYPE_INFO_H_ |
| 29 | #define V8_TYPE_INFO_H_ |
| 30 | |
| 31 | #include "globals.h" |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 32 | #include "zone.h" |
| 33 | #include "zone-inl.h" |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 34 | |
| 35 | namespace v8 { |
| 36 | namespace internal { |
| 37 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 38 | // Unknown |
| 39 | // | | |
| 40 | // | \--------------| |
| 41 | // Primitive Non-primitive |
| 42 | // | \--------| | |
| 43 | // Number String | |
| 44 | // / | | | |
| 45 | // Double Integer32 | / |
| 46 | // | | / / |
| 47 | // | Smi / / |
| 48 | // | | / / |
| 49 | // | | / / |
| 50 | // Uninitialized.--/ |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 51 | |
| 52 | class TypeInfo { |
| 53 | public: |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 54 | TypeInfo() : type_(kUninitialized) { } |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 55 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 56 | static TypeInfo Unknown() { return TypeInfo(kUnknown); } |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 57 | // We know it's a primitive type. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 58 | static TypeInfo Primitive() { return TypeInfo(kPrimitive); } |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 59 | // We know it's a number of some sort. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 60 | static TypeInfo Number() { return TypeInfo(kNumber); } |
| 61 | // We know it's a signed 32 bit integer. |
| 62 | static TypeInfo Integer32() { return TypeInfo(kInteger32); } |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 63 | // We know it's a Smi. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 64 | static TypeInfo Smi() { return TypeInfo(kSmi); } |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 65 | // We know it's a heap number. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 66 | static TypeInfo Double() { return TypeInfo(kDouble); } |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 67 | // We know it's a string. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 68 | static TypeInfo String() { return TypeInfo(kString); } |
| 69 | // We know it's a non-primitive (object) type. |
| 70 | static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); } |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 71 | // We haven't started collecting info yet. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 72 | static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); } |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 73 | |
| 74 | // Return compact representation. Very sensitive to enum values below! |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 75 | // Compacting drops information about primitive types and strings types. |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 76 | // We use the compact representation when we only care about number types. |
| 77 | int ThreeBitRepresentation() { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 78 | ASSERT(type_ != kUninitialized); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 79 | int answer = type_ & 0xf; |
| 80 | answer = answer > 6 ? answer - 2 : answer; |
| 81 | ASSERT(answer >= 0); |
| 82 | ASSERT(answer <= 7); |
| 83 | return answer; |
| 84 | } |
| 85 | |
| 86 | // Decode compact representation. Very sensitive to enum values below! |
| 87 | static TypeInfo ExpandedRepresentation(int three_bit_representation) { |
lrn@chromium.org | 32d961d | 2010-06-30 09:09:34 +0000 | [diff] [blame] | 88 | Type t = static_cast<Type>(three_bit_representation > 4 ? |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 89 | three_bit_representation + 2 : |
| 90 | three_bit_representation); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 91 | t = (t == kUnknown) ? t : static_cast<Type>(t | kPrimitive); |
| 92 | ASSERT(t == kUnknown || |
| 93 | t == kNumber || |
| 94 | t == kInteger32 || |
| 95 | t == kSmi || |
| 96 | t == kDouble); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 97 | return TypeInfo(t); |
| 98 | } |
| 99 | |
| 100 | int ToInt() { |
| 101 | return type_; |
| 102 | } |
| 103 | |
| 104 | static TypeInfo FromInt(int bit_representation) { |
| 105 | Type t = static_cast<Type>(bit_representation); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 106 | ASSERT(t == kUnknown || |
| 107 | t == kPrimitive || |
| 108 | t == kNumber || |
| 109 | t == kInteger32 || |
| 110 | t == kSmi || |
| 111 | t == kDouble || |
| 112 | t == kString || |
| 113 | t == kNonPrimitive); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 114 | return TypeInfo(t); |
| 115 | } |
| 116 | |
| 117 | // Return the weakest (least precise) common type. |
| 118 | static TypeInfo Combine(TypeInfo a, TypeInfo b) { |
| 119 | return TypeInfo(static_cast<Type>(a.type_ & b.type_)); |
| 120 | } |
| 121 | |
| 122 | |
ricow@chromium.org | 83aa549 | 2011-02-07 12:42:56 +0000 | [diff] [blame] | 123 | // Integer32 is an integer that can be represented as a signed |
| 124 | // 32-bit integer. It has to be |
| 125 | // in the range [-2^31, 2^31 - 1]. We also have to check for negative 0 |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 126 | // as it is not an Integer32. |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 127 | static inline bool IsInt32Double(double value) { |
| 128 | const DoubleRepresentation minus_zero(-0.0); |
| 129 | DoubleRepresentation rep(value); |
| 130 | if (rep.bits == minus_zero.bits) return false; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 131 | if (value >= kMinInt && value <= kMaxInt && |
| 132 | value == static_cast<int32_t>(value)) { |
| 133 | return true; |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 134 | } |
| 135 | return false; |
| 136 | } |
| 137 | |
ricow@chromium.org | aa1b616 | 2010-03-29 07:44:58 +0000 | [diff] [blame] | 138 | static TypeInfo TypeFromValue(Handle<Object> value); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 139 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 140 | bool Equals(const TypeInfo& other) { |
| 141 | return type_ == other.type_; |
| 142 | } |
| 143 | |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 144 | inline bool IsUnknown() { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 145 | ASSERT(type_ != kUninitialized); |
| 146 | return type_ == kUnknown; |
| 147 | } |
| 148 | |
| 149 | inline bool IsPrimitive() { |
| 150 | ASSERT(type_ != kUninitialized); |
| 151 | return ((type_ & kPrimitive) == kPrimitive); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 152 | } |
| 153 | |
| 154 | inline bool IsNumber() { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 155 | ASSERT(type_ != kUninitialized); |
| 156 | return ((type_ & kNumber) == kNumber); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 157 | } |
| 158 | |
| 159 | inline bool IsSmi() { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 160 | ASSERT(type_ != kUninitialized); |
| 161 | return ((type_ & kSmi) == kSmi); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | inline bool IsInteger32() { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 165 | ASSERT(type_ != kUninitialized); |
| 166 | return ((type_ & kInteger32) == kInteger32); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | inline bool IsDouble() { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 170 | ASSERT(type_ != kUninitialized); |
| 171 | return ((type_ & kDouble) == kDouble); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 172 | } |
| 173 | |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 174 | inline bool IsString() { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 175 | ASSERT(type_ != kUninitialized); |
| 176 | return ((type_ & kString) == kString); |
| 177 | } |
| 178 | |
| 179 | inline bool IsNonPrimitive() { |
| 180 | ASSERT(type_ != kUninitialized); |
| 181 | return ((type_ & kNonPrimitive) == kNonPrimitive); |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 182 | } |
| 183 | |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 184 | inline bool IsUninitialized() { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 185 | return type_ == kUninitialized; |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | const char* ToString() { |
| 189 | switch (type_) { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 190 | case kUnknown: return "Unknown"; |
| 191 | case kPrimitive: return "Primitive"; |
| 192 | case kNumber: return "Number"; |
| 193 | case kInteger32: return "Integer32"; |
| 194 | case kSmi: return "Smi"; |
| 195 | case kDouble: return "Double"; |
| 196 | case kString: return "String"; |
| 197 | case kNonPrimitive: return "Object"; |
| 198 | case kUninitialized: return "Uninitialized"; |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 199 | } |
| 200 | UNREACHABLE(); |
| 201 | return "Unreachable code"; |
| 202 | } |
| 203 | |
| 204 | private: |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 205 | enum Type { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 206 | kUnknown = 0, // 0000000 |
| 207 | kPrimitive = 0x10, // 0010000 |
| 208 | kNumber = 0x11, // 0010001 |
| 209 | kInteger32 = 0x13, // 0010011 |
| 210 | kSmi = 0x17, // 0010111 |
| 211 | kDouble = 0x19, // 0011001 |
| 212 | kString = 0x30, // 0110000 |
| 213 | kNonPrimitive = 0x40, // 1000000 |
| 214 | kUninitialized = 0x7f // 1111111 |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 215 | }; |
| 216 | explicit inline TypeInfo(Type t) : type_(t) { } |
| 217 | |
| 218 | Type type_; |
| 219 | }; |
| 220 | |
| 221 | |
erik.corry@gmail.com | 0511e24 | 2011-01-19 11:11:08 +0000 | [diff] [blame] | 222 | enum StringStubFeedback { |
| 223 | DEFAULT_STRING_STUB = 0, |
| 224 | STRING_INDEX_OUT_OF_BOUNDS = 1 |
| 225 | }; |
| 226 | |
| 227 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 228 | // Forward declarations. |
| 229 | class Assignment; |
| 230 | class BinaryOperation; |
| 231 | class Call; |
| 232 | class CompareOperation; |
| 233 | class CompilationInfo; |
| 234 | class Property; |
| 235 | class CaseClause; |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 236 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 237 | class TypeFeedbackOracle BASE_EMBEDDED { |
| 238 | public: |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 239 | TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 240 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 241 | bool LoadIsMonomorphic(Property* expr); |
| 242 | bool StoreIsMonomorphic(Assignment* expr); |
| 243 | bool CallIsMonomorphic(Call* expr); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 244 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 245 | Handle<Map> LoadMonomorphicReceiverType(Property* expr); |
| 246 | Handle<Map> StoreMonomorphicReceiverType(Assignment* expr); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 247 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 248 | ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name); |
| 249 | ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name); |
| 250 | ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 251 | |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 252 | CheckType GetCallCheckType(Call* expr); |
| 253 | Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check); |
| 254 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 255 | bool LoadIsBuiltin(Property* expr, Builtins::Name id); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 256 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 257 | // Get type information for arithmetic operations and compares. |
ager@chromium.org | 378b34e | 2011-01-28 08:04:38 +0000 | [diff] [blame] | 258 | TypeInfo BinaryType(BinaryOperation* expr); |
| 259 | TypeInfo CompareType(CompareOperation* expr); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 260 | TypeInfo SwitchType(CaseClause* clause); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 261 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 262 | private: |
| 263 | void Initialize(Handle<Code> code); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 264 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 265 | ZoneMapList* CollectReceiverTypes(int position, |
| 266 | Handle<String> name, |
| 267 | Code::Flags flags); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 268 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 269 | void PopulateMap(Handle<Code> code); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 270 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 271 | void CollectPositions(Code* code, |
| 272 | List<int>* code_positions, |
| 273 | List<int>* source_positions); |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 274 | |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 275 | Handle<Context> global_context_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 276 | Handle<JSObject> map_; |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 277 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 278 | DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle); |
| 279 | }; |
sgjesse@chromium.org | df7a284 | 2010-03-25 14:34:15 +0000 | [diff] [blame] | 280 | |
| 281 | } } // namespace v8::internal |
| 282 | |
| 283 | #endif // V8_TYPE_INFO_H_ |