• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 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"
32 #include "zone.h"
33 #include "zone-inl.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 //         Unknown
39 //           |   |
40 //           |   \--------------|
41 //      Primitive             Non-primitive
42 //           |   \--------|     |
43 //         Number      String   |
44 //         /    |         |     |
45 //    Double  Integer32   |    /
46 //        |      |       /    /
47 //        |     Smi     /    /
48 //        |      |     /    /
49 //        |      |    /    /
50 //        Uninitialized.--/
51 
52 class TypeInfo {
53  public:
TypeInfo()54   TypeInfo() : type_(kUninitialized) { }
55 
Unknown()56   static TypeInfo Unknown() { return TypeInfo(kUnknown); }
57   // We know it's a primitive type.
Primitive()58   static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
59   // We know it's a number of some sort.
Number()60   static TypeInfo Number() { return TypeInfo(kNumber); }
61   // We know it's a signed 32 bit integer.
Integer32()62   static TypeInfo Integer32() { return TypeInfo(kInteger32); }
63   // We know it's a Smi.
Smi()64   static TypeInfo Smi() { return TypeInfo(kSmi); }
65   // We know it's a heap number.
Double()66   static TypeInfo Double() { return TypeInfo(kDouble); }
67   // We know it's a string.
String()68   static TypeInfo String() { return TypeInfo(kString); }
69   // We know it's a non-primitive (object) type.
NonPrimitive()70   static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
71   // We haven't started collecting info yet.
Uninitialized()72   static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
73 
74   // Return compact representation.  Very sensitive to enum values below!
75   // Compacting drops information about primitive types and strings types.
76   // We use the compact representation when we only care about number types.
ThreeBitRepresentation()77   int ThreeBitRepresentation() {
78     ASSERT(type_ != kUninitialized);
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!
ExpandedRepresentation(int three_bit_representation)87   static TypeInfo ExpandedRepresentation(int three_bit_representation) {
88     Type t = static_cast<Type>(three_bit_representation > 4 ?
89                                three_bit_representation + 2 :
90                                three_bit_representation);
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);
97     return TypeInfo(t);
98   }
99 
ToInt()100   int ToInt() {
101     return type_;
102   }
103 
FromInt(int bit_representation)104   static TypeInfo FromInt(int bit_representation) {
105     Type t = static_cast<Type>(bit_representation);
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);
114     return TypeInfo(t);
115   }
116 
117   // Return the weakest (least precise) common type.
Combine(TypeInfo a,TypeInfo b)118   static TypeInfo Combine(TypeInfo a, TypeInfo b) {
119     return TypeInfo(static_cast<Type>(a.type_ & b.type_));
120   }
121 
122 
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
126   // as it is not an Integer32.
IsInt32Double(double value)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;
131     if (value >= kMinInt && value <= kMaxInt &&
132         value == static_cast<int32_t>(value)) {
133       return true;
134     }
135     return false;
136   }
137 
138   static TypeInfo TypeFromValue(Handle<Object> value);
139 
Equals(const TypeInfo & other)140   bool Equals(const TypeInfo& other) {
141     return type_ == other.type_;
142   }
143 
IsUnknown()144   inline bool IsUnknown() {
145     ASSERT(type_ != kUninitialized);
146     return type_ == kUnknown;
147   }
148 
IsPrimitive()149   inline bool IsPrimitive() {
150     ASSERT(type_ != kUninitialized);
151     return ((type_ & kPrimitive) == kPrimitive);
152   }
153 
IsNumber()154   inline bool IsNumber() {
155     ASSERT(type_ != kUninitialized);
156     return ((type_ & kNumber) == kNumber);
157   }
158 
IsSmi()159   inline bool IsSmi() {
160     ASSERT(type_ != kUninitialized);
161     return ((type_ & kSmi) == kSmi);
162   }
163 
IsInteger32()164   inline bool IsInteger32() {
165     ASSERT(type_ != kUninitialized);
166     return ((type_ & kInteger32) == kInteger32);
167   }
168 
IsDouble()169   inline bool IsDouble() {
170     ASSERT(type_ != kUninitialized);
171     return ((type_ & kDouble) == kDouble);
172   }
173 
IsString()174   inline bool IsString() {
175     ASSERT(type_ != kUninitialized);
176     return ((type_ & kString) == kString);
177   }
178 
IsNonPrimitive()179   inline bool IsNonPrimitive() {
180     ASSERT(type_ != kUninitialized);
181     return ((type_ & kNonPrimitive) == kNonPrimitive);
182   }
183 
IsUninitialized()184   inline bool IsUninitialized() {
185     return type_ == kUninitialized;
186   }
187 
ToString()188   const char* ToString() {
189     switch (type_) {
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";
199     }
200     UNREACHABLE();
201     return "Unreachable code";
202   }
203 
204  private:
205   enum Type {
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
215   };
TypeInfo(Type t)216   explicit inline TypeInfo(Type t) : type_(t) { }
217 
218   Type type_;
219 };
220 
221 
222 enum StringStubFeedback {
223   DEFAULT_STRING_STUB = 0,
224   STRING_INDEX_OUT_OF_BOUNDS = 1
225 };
226 
227 
228 // Forward declarations.
229 class Assignment;
230 class BinaryOperation;
231 class Call;
232 class CompareOperation;
233 class CompilationInfo;
234 class Property;
235 class CaseClause;
236 
237 class TypeFeedbackOracle BASE_EMBEDDED {
238  public:
239   TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context);
240 
241   bool LoadIsMonomorphic(Property* expr);
242   bool StoreIsMonomorphic(Expression* expr);
243   bool CallIsMonomorphic(Call* expr);
244 
245   Handle<Map> LoadMonomorphicReceiverType(Property* expr);
246   Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
247 
248   ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
249   ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
250   ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name);
251 
252   ExternalArrayType GetKeyedLoadExternalArrayType(Property* expr);
253   ExternalArrayType GetKeyedStoreExternalArrayType(Expression* expr);
254 
255   CheckType GetCallCheckType(Call* expr);
256   Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
257 
258   bool LoadIsBuiltin(Property* expr, Builtins::Name id);
259 
260   // Get type information for arithmetic operations and compares.
261   TypeInfo BinaryType(BinaryOperation* expr);
262   TypeInfo CompareType(CompareOperation* expr);
263   TypeInfo SwitchType(CaseClause* clause);
264 
265  private:
266   ZoneMapList* CollectReceiverTypes(int position,
267                                     Handle<String> name,
268                                     Code::Flags flags);
269 
270   void SetInfo(int position, Object* target);
271 
272   void PopulateMap(Handle<Code> code);
273 
274   void CollectPositions(Code* code,
275                         List<int>* code_positions,
276                         List<int>* source_positions);
277 
278   // Returns an element from the backing store. Returns undefined if
279   // there is no information.
280   Handle<Object> GetInfo(int pos);
281 
282   Handle<Context> global_context_;
283   Handle<NumberDictionary> dictionary_;
284 
285   DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
286 };
287 
288 } }  // namespace v8::internal
289 
290 #endif  // V8_TYPE_INFO_H_
291