OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 Isolate* isolate, | 64 Isolate* isolate, |
65 Zone* zone) { | 65 Zone* zone) { |
66 global_context_ = global_context; | 66 global_context_ = global_context; |
67 isolate_ = isolate; | 67 isolate_ = isolate; |
68 zone_ = zone; | 68 zone_ = zone; |
69 BuildDictionary(code); | 69 BuildDictionary(code); |
70 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); | 70 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); |
71 } | 71 } |
72 | 72 |
73 | 73 |
74 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { | 74 static uint32_t IdToKey(TypeFeedbackId ast_id) { |
75 int entry = dictionary_->FindEntry(ast_id); | 75 return static_cast<uint32_t>(ast_id.ToInt()); |
| 76 } |
| 77 |
| 78 |
| 79 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { |
| 80 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
76 return entry != UnseededNumberDictionary::kNotFound | 81 return entry != UnseededNumberDictionary::kNotFound |
77 ? Handle<Object>(dictionary_->ValueAt(entry)) | 82 ? Handle<Object>(dictionary_->ValueAt(entry)) |
78 : Handle<Object>::cast(isolate_->factory()->undefined_value()); | 83 : Handle<Object>::cast(isolate_->factory()->undefined_value()); |
79 } | 84 } |
80 | 85 |
81 | 86 |
82 bool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) { | 87 bool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) { |
83 Handle<Object> map_or_code = GetInfo(expr->id()); | 88 Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); |
84 if (map_or_code->IsMap()) return false; | 89 if (map_or_code->IsMap()) return false; |
85 if (map_or_code->IsCode()) { | 90 if (map_or_code->IsCode()) { |
86 Handle<Code> code = Handle<Code>::cast(map_or_code); | 91 Handle<Code> code = Handle<Code>::cast(map_or_code); |
87 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 92 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; |
88 } | 93 } |
89 return false; | 94 return false; |
90 } | 95 } |
91 | 96 |
92 | 97 |
93 bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) { | 98 bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) { |
94 Handle<Object> map_or_code = GetInfo(expr->id()); | 99 Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); |
95 if (map_or_code->IsMap()) return true; | 100 if (map_or_code->IsMap()) return true; |
96 if (map_or_code->IsCode()) { | 101 if (map_or_code->IsCode()) { |
97 Handle<Code> code = Handle<Code>::cast(map_or_code); | 102 Handle<Code> code = Handle<Code>::cast(map_or_code); |
98 return code->is_keyed_load_stub() && | 103 return code->is_keyed_load_stub() && |
99 code->ic_state() == MONOMORPHIC && | 104 code->ic_state() == MONOMORPHIC && |
100 Code::ExtractTypeFromFlags(code->flags()) == Code::NORMAL && | 105 Code::ExtractTypeFromFlags(code->flags()) == Code::NORMAL && |
101 code->FindFirstMap() != NULL && | 106 code->FindFirstMap() != NULL && |
102 !CanRetainOtherContext(code->FindFirstMap(), *global_context_); | 107 !CanRetainOtherContext(code->FindFirstMap(), *global_context_); |
103 } | 108 } |
104 return false; | 109 return false; |
105 } | 110 } |
106 | 111 |
107 | 112 |
108 bool TypeFeedbackOracle::LoadIsMegamorphicWithTypeInfo(Property* expr) { | 113 bool TypeFeedbackOracle::LoadIsMegamorphicWithTypeInfo(Property* expr) { |
109 Handle<Object> map_or_code = GetInfo(expr->id()); | 114 Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); |
110 if (map_or_code->IsCode()) { | 115 if (map_or_code->IsCode()) { |
111 Handle<Code> code = Handle<Code>::cast(map_or_code); | 116 Handle<Code> code = Handle<Code>::cast(map_or_code); |
112 Builtins* builtins = isolate_->builtins(); | 117 Builtins* builtins = isolate_->builtins(); |
113 return code->is_keyed_load_stub() && | 118 return code->is_keyed_load_stub() && |
114 *code != builtins->builtin(Builtins::kKeyedLoadIC_Generic) && | 119 *code != builtins->builtin(Builtins::kKeyedLoadIC_Generic) && |
115 code->ic_state() == MEGAMORPHIC; | 120 code->ic_state() == MEGAMORPHIC; |
116 } | 121 } |
117 return false; | 122 return false; |
118 } | 123 } |
119 | 124 |
120 | 125 |
121 bool TypeFeedbackOracle::StoreIsMonomorphicNormal(Expression* expr) { | 126 bool TypeFeedbackOracle::StoreIsMonomorphicNormal(TypeFeedbackId ast_id) { |
122 Handle<Object> map_or_code = GetInfo(expr->id()); | 127 Handle<Object> map_or_code = GetInfo(ast_id); |
123 if (map_or_code->IsMap()) return true; | 128 if (map_or_code->IsMap()) return true; |
124 if (map_or_code->IsCode()) { | 129 if (map_or_code->IsCode()) { |
125 Handle<Code> code = Handle<Code>::cast(map_or_code); | 130 Handle<Code> code = Handle<Code>::cast(map_or_code); |
126 bool allow_growth = | 131 bool allow_growth = |
127 Code::GetKeyedAccessGrowMode(code->extra_ic_state()) == | 132 Code::GetKeyedAccessGrowMode(code->extra_ic_state()) == |
128 ALLOW_JSARRAY_GROWTH; | 133 ALLOW_JSARRAY_GROWTH; |
129 return code->is_keyed_store_stub() && | 134 return code->is_keyed_store_stub() && |
130 !allow_growth && | 135 !allow_growth && |
131 code->ic_state() == MONOMORPHIC && | 136 code->ic_state() == MONOMORPHIC && |
132 Code::ExtractTypeFromFlags(code->flags()) == Code::NORMAL && | 137 Code::ExtractTypeFromFlags(code->flags()) == Code::NORMAL && |
133 code->FindFirstMap() != NULL && | 138 code->FindFirstMap() != NULL && |
134 !CanRetainOtherContext(code->FindFirstMap(), *global_context_); | 139 !CanRetainOtherContext(code->FindFirstMap(), *global_context_); |
135 } | 140 } |
136 return false; | 141 return false; |
137 } | 142 } |
138 | 143 |
139 | 144 |
140 bool TypeFeedbackOracle::StoreIsMegamorphicWithTypeInfo(Expression* expr) { | 145 bool TypeFeedbackOracle::StoreIsMegamorphicWithTypeInfo(TypeFeedbackId ast_id) { |
141 Handle<Object> map_or_code = GetInfo(expr->id()); | 146 Handle<Object> map_or_code = GetInfo(ast_id); |
142 if (map_or_code->IsCode()) { | 147 if (map_or_code->IsCode()) { |
143 Handle<Code> code = Handle<Code>::cast(map_or_code); | 148 Handle<Code> code = Handle<Code>::cast(map_or_code); |
144 Builtins* builtins = isolate_->builtins(); | 149 Builtins* builtins = isolate_->builtins(); |
145 bool allow_growth = | 150 bool allow_growth = |
146 Code::GetKeyedAccessGrowMode(code->extra_ic_state()) == | 151 Code::GetKeyedAccessGrowMode(code->extra_ic_state()) == |
147 ALLOW_JSARRAY_GROWTH; | 152 ALLOW_JSARRAY_GROWTH; |
148 return code->is_keyed_store_stub() && | 153 return code->is_keyed_store_stub() && |
149 !allow_growth && | 154 !allow_growth && |
150 *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic) && | 155 *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic) && |
151 *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic_Strict) && | 156 *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic_Strict) && |
152 code->ic_state() == MEGAMORPHIC; | 157 code->ic_state() == MEGAMORPHIC; |
153 } | 158 } |
154 return false; | 159 return false; |
155 } | 160 } |
156 | 161 |
157 | 162 |
158 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { | 163 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { |
159 Handle<Object> value = GetInfo(expr->id()); | 164 Handle<Object> value = GetInfo(expr->CallFeedbackId()); |
160 return value->IsMap() || value->IsSmi() || value->IsJSFunction(); | 165 return value->IsMap() || value->IsSmi() || value->IsJSFunction(); |
161 } | 166 } |
162 | 167 |
163 | 168 |
164 bool TypeFeedbackOracle::CallNewIsMonomorphic(CallNew* expr) { | 169 bool TypeFeedbackOracle::CallNewIsMonomorphic(CallNew* expr) { |
165 Handle<Object> value = GetInfo(expr->id()); | 170 Handle<Object> value = GetInfo(expr->CallNewFeedbackId()); |
166 return value->IsJSFunction(); | 171 return value->IsJSFunction(); |
167 } | 172 } |
168 | 173 |
169 | 174 |
170 bool TypeFeedbackOracle::ObjectLiteralStoreIsMonomorphic( | 175 bool TypeFeedbackOracle::ObjectLiteralStoreIsMonomorphic( |
171 ObjectLiteral::Property* prop) { | 176 ObjectLiteral::Property* prop) { |
172 Handle<Object> map_or_code = GetInfo(prop->key()->id()); | 177 Handle<Object> map_or_code = GetInfo(prop->key()->LiteralFeedbackId()); |
173 return map_or_code->IsMap(); | 178 return map_or_code->IsMap(); |
174 } | 179 } |
175 | 180 |
176 | 181 |
177 bool TypeFeedbackOracle::IsForInFastCase(ForInStatement* stmt) { | 182 bool TypeFeedbackOracle::IsForInFastCase(ForInStatement* stmt) { |
178 Handle<Object> value = GetInfo(stmt->PrepareId()); | 183 Handle<Object> value = GetInfo(stmt->ForInFeedbackId()); |
179 return value->IsSmi() && | 184 return value->IsSmi() && |
180 Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker; | 185 Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker; |
181 } | 186 } |
182 | 187 |
183 | 188 |
184 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { | 189 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { |
185 ASSERT(LoadIsMonomorphicNormal(expr)); | 190 ASSERT(LoadIsMonomorphicNormal(expr)); |
186 Handle<Object> map_or_code = GetInfo(expr->id()); | 191 Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); |
187 if (map_or_code->IsCode()) { | 192 if (map_or_code->IsCode()) { |
188 Handle<Code> code = Handle<Code>::cast(map_or_code); | 193 Handle<Code> code = Handle<Code>::cast(map_or_code); |
189 Map* first_map = code->FindFirstMap(); | 194 Map* first_map = code->FindFirstMap(); |
190 ASSERT(first_map != NULL); | 195 ASSERT(first_map != NULL); |
191 return CanRetainOtherContext(first_map, *global_context_) | 196 return CanRetainOtherContext(first_map, *global_context_) |
192 ? Handle<Map>::null() | 197 ? Handle<Map>::null() |
193 : Handle<Map>(first_map); | 198 : Handle<Map>(first_map); |
194 } | 199 } |
195 return Handle<Map>::cast(map_or_code); | 200 return Handle<Map>::cast(map_or_code); |
196 } | 201 } |
197 | 202 |
198 | 203 |
199 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { | 204 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType( |
200 ASSERT(StoreIsMonomorphicNormal(expr)); | 205 TypeFeedbackId ast_id) { |
201 Handle<Object> map_or_code = GetInfo(expr->id()); | 206 ASSERT(StoreIsMonomorphicNormal(ast_id)); |
| 207 Handle<Object> map_or_code = GetInfo(ast_id); |
202 if (map_or_code->IsCode()) { | 208 if (map_or_code->IsCode()) { |
203 Handle<Code> code = Handle<Code>::cast(map_or_code); | 209 Handle<Code> code = Handle<Code>::cast(map_or_code); |
204 Map* first_map = code->FindFirstMap(); | 210 Map* first_map = code->FindFirstMap(); |
205 ASSERT(first_map != NULL); | 211 ASSERT(first_map != NULL); |
206 return CanRetainOtherContext(first_map, *global_context_) | 212 return CanRetainOtherContext(first_map, *global_context_) |
207 ? Handle<Map>::null() | 213 ? Handle<Map>::null() |
208 : Handle<Map>(first_map); | 214 : Handle<Map>(first_map); |
209 } | 215 } |
210 return Handle<Map>::cast(map_or_code); | 216 return Handle<Map>::cast(map_or_code); |
211 } | 217 } |
212 | 218 |
213 | 219 |
214 void TypeFeedbackOracle::LoadReceiverTypes(Property* expr, | 220 void TypeFeedbackOracle::LoadReceiverTypes(Property* expr, |
215 Handle<String> name, | 221 Handle<String> name, |
216 SmallMapList* types) { | 222 SmallMapList* types) { |
217 Code::Flags flags = | 223 Code::Flags flags = |
218 Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::NORMAL); | 224 Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::NORMAL); |
219 CollectReceiverTypes(expr->id(), name, flags, types); | 225 CollectReceiverTypes(expr->PropertyFeedbackId(), name, flags, types); |
220 } | 226 } |
221 | 227 |
222 | 228 |
223 void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, | 229 void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, |
224 Handle<String> name, | 230 Handle<String> name, |
225 SmallMapList* types) { | 231 SmallMapList* types) { |
226 Code::Flags flags = | 232 Code::Flags flags = |
227 Code::ComputeMonomorphicFlags(Code::STORE_IC, Code::NORMAL); | 233 Code::ComputeMonomorphicFlags(Code::STORE_IC, Code::NORMAL); |
228 CollectReceiverTypes(expr->id(), name, flags, types); | 234 CollectReceiverTypes(expr->AssignmentFeedbackId(), name, flags, types); |
229 } | 235 } |
230 | 236 |
231 | 237 |
232 void TypeFeedbackOracle::CallReceiverTypes(Call* expr, | 238 void TypeFeedbackOracle::CallReceiverTypes(Call* expr, |
233 Handle<String> name, | 239 Handle<String> name, |
234 CallKind call_kind, | 240 CallKind call_kind, |
235 SmallMapList* types) { | 241 SmallMapList* types) { |
236 int arity = expr->arguments()->length(); | 242 int arity = expr->arguments()->length(); |
237 | 243 |
238 // Note: Currently we do not take string extra ic data into account | 244 // Note: Currently we do not take string extra ic data into account |
239 // here. | 245 // here. |
240 Code::ExtraICState extra_ic_state = | 246 Code::ExtraICState extra_ic_state = |
241 CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION); | 247 CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION); |
242 | 248 |
243 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 249 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, |
244 Code::NORMAL, | 250 Code::NORMAL, |
245 extra_ic_state, | 251 extra_ic_state, |
246 OWN_MAP, | 252 OWN_MAP, |
247 arity); | 253 arity); |
248 CollectReceiverTypes(expr->id(), name, flags, types); | 254 CollectReceiverTypes(expr->CallFeedbackId(), name, flags, types); |
249 } | 255 } |
250 | 256 |
251 | 257 |
252 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { | 258 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { |
253 Handle<Object> value = GetInfo(expr->id()); | 259 Handle<Object> value = GetInfo(expr->CallFeedbackId()); |
254 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; | 260 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; |
255 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); | 261 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); |
256 ASSERT(check != RECEIVER_MAP_CHECK); | 262 ASSERT(check != RECEIVER_MAP_CHECK); |
257 return check; | 263 return check; |
258 } | 264 } |
259 | 265 |
260 | 266 |
261 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( | 267 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( |
262 CheckType check) { | 268 CheckType check) { |
263 JSFunction* function = NULL; | 269 JSFunction* function = NULL; |
(...skipping 10 matching lines...) Expand all Loading... |
274 case BOOLEAN_CHECK: | 280 case BOOLEAN_CHECK: |
275 function = global_context_->boolean_function(); | 281 function = global_context_->boolean_function(); |
276 break; | 282 break; |
277 } | 283 } |
278 ASSERT(function != NULL); | 284 ASSERT(function != NULL); |
279 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); | 285 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); |
280 } | 286 } |
281 | 287 |
282 | 288 |
283 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(Call* expr) { | 289 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(Call* expr) { |
284 return Handle<JSFunction>::cast(GetInfo(expr->id())); | 290 return Handle<JSFunction>::cast(GetInfo(expr->CallFeedbackId())); |
285 } | 291 } |
286 | 292 |
287 | 293 |
288 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(CallNew* expr) { | 294 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(CallNew* expr) { |
289 return Handle<JSFunction>::cast(GetInfo(expr->id())); | 295 return Handle<JSFunction>::cast(GetInfo(expr->CallNewFeedbackId())); |
290 } | 296 } |
291 | 297 |
292 | 298 |
293 Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap( | 299 Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap( |
294 ObjectLiteral::Property* prop) { | 300 ObjectLiteral::Property* prop) { |
295 ASSERT(ObjectLiteralStoreIsMonomorphic(prop)); | 301 ASSERT(ObjectLiteralStoreIsMonomorphic(prop)); |
296 return Handle<Map>::cast(GetInfo(prop->key()->id())); | 302 return Handle<Map>::cast(GetInfo(prop->key()->LiteralFeedbackId())); |
297 } | 303 } |
298 | 304 |
299 | 305 |
300 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { | 306 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { |
301 return *GetInfo(expr->id()) == | 307 return *GetInfo(expr->PropertyFeedbackId()) == |
302 isolate_->builtins()->builtin(id); | 308 isolate_->builtins()->builtin(id); |
303 } | 309 } |
304 | 310 |
305 | 311 |
306 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { | 312 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { |
307 Handle<Object> object = GetInfo(expr->id()); | 313 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); |
308 TypeInfo unknown = TypeInfo::Unknown(); | 314 TypeInfo unknown = TypeInfo::Unknown(); |
309 if (!object->IsCode()) return unknown; | 315 if (!object->IsCode()) return unknown; |
310 Handle<Code> code = Handle<Code>::cast(object); | 316 Handle<Code> code = Handle<Code>::cast(object); |
311 if (!code->is_compare_ic_stub()) return unknown; | 317 if (!code->is_compare_ic_stub()) return unknown; |
312 | 318 |
313 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 319 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); |
314 switch (state) { | 320 switch (state) { |
315 case CompareIC::UNINITIALIZED: | 321 case CompareIC::UNINITIALIZED: |
316 // Uninitialized means never executed. | 322 // Uninitialized means never executed. |
317 return TypeInfo::Uninitialized(); | 323 return TypeInfo::Uninitialized(); |
318 case CompareIC::SMIS: | 324 case CompareIC::SMIS: |
319 return TypeInfo::Smi(); | 325 return TypeInfo::Smi(); |
320 case CompareIC::HEAP_NUMBERS: | 326 case CompareIC::HEAP_NUMBERS: |
321 return TypeInfo::Number(); | 327 return TypeInfo::Number(); |
322 case CompareIC::SYMBOLS: | 328 case CompareIC::SYMBOLS: |
323 case CompareIC::STRINGS: | 329 case CompareIC::STRINGS: |
324 return TypeInfo::String(); | 330 return TypeInfo::String(); |
325 case CompareIC::OBJECTS: | 331 case CompareIC::OBJECTS: |
326 case CompareIC::KNOWN_OBJECTS: | 332 case CompareIC::KNOWN_OBJECTS: |
327 // TODO(kasperl): We really need a type for JS objects here. | 333 // TODO(kasperl): We really need a type for JS objects here. |
328 return TypeInfo::NonPrimitive(); | 334 return TypeInfo::NonPrimitive(); |
329 case CompareIC::GENERIC: | 335 case CompareIC::GENERIC: |
330 default: | 336 default: |
331 return unknown; | 337 return unknown; |
332 } | 338 } |
333 } | 339 } |
334 | 340 |
335 | 341 |
336 bool TypeFeedbackOracle::IsSymbolCompare(CompareOperation* expr) { | 342 bool TypeFeedbackOracle::IsSymbolCompare(CompareOperation* expr) { |
337 Handle<Object> object = GetInfo(expr->id()); | 343 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); |
338 if (!object->IsCode()) return false; | 344 if (!object->IsCode()) return false; |
339 Handle<Code> code = Handle<Code>::cast(object); | 345 Handle<Code> code = Handle<Code>::cast(object); |
340 if (!code->is_compare_ic_stub()) return false; | 346 if (!code->is_compare_ic_stub()) return false; |
341 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 347 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); |
342 return state == CompareIC::SYMBOLS; | 348 return state == CompareIC::SYMBOLS; |
343 } | 349 } |
344 | 350 |
345 | 351 |
346 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { | 352 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { |
347 Handle<Object> object = GetInfo(expr->id()); | 353 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); |
348 if (!object->IsCode()) return Handle<Map>::null(); | 354 if (!object->IsCode()) return Handle<Map>::null(); |
349 Handle<Code> code = Handle<Code>::cast(object); | 355 Handle<Code> code = Handle<Code>::cast(object); |
350 if (!code->is_compare_ic_stub()) return Handle<Map>::null(); | 356 if (!code->is_compare_ic_stub()) return Handle<Map>::null(); |
351 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 357 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); |
352 if (state != CompareIC::KNOWN_OBJECTS) { | 358 if (state != CompareIC::KNOWN_OBJECTS) { |
353 return Handle<Map>::null(); | 359 return Handle<Map>::null(); |
354 } | 360 } |
355 Map* first_map = code->FindFirstMap(); | 361 Map* first_map = code->FindFirstMap(); |
356 ASSERT(first_map != NULL); | 362 ASSERT(first_map != NULL); |
357 return CanRetainOtherContext(first_map, *global_context_) | 363 return CanRetainOtherContext(first_map, *global_context_) |
358 ? Handle<Map>::null() | 364 ? Handle<Map>::null() |
359 : Handle<Map>(first_map); | 365 : Handle<Map>(first_map); |
360 } | 366 } |
361 | 367 |
362 | 368 |
363 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { | 369 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { |
364 Handle<Object> object = GetInfo(expr->id()); | 370 Handle<Object> object = GetInfo(expr->UnaryOperationFeedbackId()); |
365 TypeInfo unknown = TypeInfo::Unknown(); | 371 TypeInfo unknown = TypeInfo::Unknown(); |
366 if (!object->IsCode()) return unknown; | 372 if (!object->IsCode()) return unknown; |
367 Handle<Code> code = Handle<Code>::cast(object); | 373 Handle<Code> code = Handle<Code>::cast(object); |
368 ASSERT(code->is_unary_op_stub()); | 374 ASSERT(code->is_unary_op_stub()); |
369 UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( | 375 UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( |
370 code->unary_op_type()); | 376 code->unary_op_type()); |
371 switch (type) { | 377 switch (type) { |
372 case UnaryOpIC::SMI: | 378 case UnaryOpIC::SMI: |
373 return TypeInfo::Smi(); | 379 return TypeInfo::Smi(); |
374 case UnaryOpIC::HEAP_NUMBER: | 380 case UnaryOpIC::HEAP_NUMBER: |
375 return TypeInfo::Double(); | 381 return TypeInfo::Double(); |
376 default: | 382 default: |
377 return unknown; | 383 return unknown; |
378 } | 384 } |
379 } | 385 } |
380 | 386 |
381 | 387 |
382 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { | 388 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { |
383 Handle<Object> object = GetInfo(expr->id()); | 389 Handle<Object> object = GetInfo(expr->BinaryOperationFeedbackId()); |
384 TypeInfo unknown = TypeInfo::Unknown(); | 390 TypeInfo unknown = TypeInfo::Unknown(); |
385 if (!object->IsCode()) return unknown; | 391 if (!object->IsCode()) return unknown; |
386 Handle<Code> code = Handle<Code>::cast(object); | 392 Handle<Code> code = Handle<Code>::cast(object); |
387 if (code->is_binary_op_stub()) { | 393 if (code->is_binary_op_stub()) { |
388 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( | 394 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( |
389 code->binary_op_type()); | 395 code->binary_op_type()); |
390 BinaryOpIC::TypeInfo result_type = static_cast<BinaryOpIC::TypeInfo>( | 396 BinaryOpIC::TypeInfo result_type = static_cast<BinaryOpIC::TypeInfo>( |
391 code->binary_op_result_type()); | 397 code->binary_op_result_type()); |
392 | 398 |
393 switch (type) { | 399 switch (type) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 // TODO(kasperl): We really need a type for JS objects here. | 463 // TODO(kasperl): We really need a type for JS objects here. |
458 return TypeInfo::NonPrimitive(); | 464 return TypeInfo::NonPrimitive(); |
459 case CompareIC::GENERIC: | 465 case CompareIC::GENERIC: |
460 default: | 466 default: |
461 return unknown; | 467 return unknown; |
462 } | 468 } |
463 } | 469 } |
464 | 470 |
465 | 471 |
466 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { | 472 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { |
467 Handle<Object> object = GetInfo(expr->CountId()); | 473 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); |
468 TypeInfo unknown = TypeInfo::Unknown(); | 474 TypeInfo unknown = TypeInfo::Unknown(); |
469 if (!object->IsCode()) return unknown; | 475 if (!object->IsCode()) return unknown; |
470 Handle<Code> code = Handle<Code>::cast(object); | 476 Handle<Code> code = Handle<Code>::cast(object); |
471 if (!code->is_binary_op_stub()) return unknown; | 477 if (!code->is_binary_op_stub()) return unknown; |
472 | 478 |
473 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( | 479 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( |
474 code->binary_op_type()); | 480 code->binary_op_type()); |
475 switch (type) { | 481 switch (type) { |
476 case BinaryOpIC::UNINITIALIZED: | 482 case BinaryOpIC::UNINITIALIZED: |
477 case BinaryOpIC::SMI: | 483 case BinaryOpIC::SMI: |
478 return TypeInfo::Smi(); | 484 return TypeInfo::Smi(); |
479 case BinaryOpIC::INT32: | 485 case BinaryOpIC::INT32: |
480 return TypeInfo::Integer32(); | 486 return TypeInfo::Integer32(); |
481 case BinaryOpIC::HEAP_NUMBER: | 487 case BinaryOpIC::HEAP_NUMBER: |
482 return TypeInfo::Double(); | 488 return TypeInfo::Double(); |
483 case BinaryOpIC::BOTH_STRING: | 489 case BinaryOpIC::BOTH_STRING: |
484 case BinaryOpIC::STRING: | 490 case BinaryOpIC::STRING: |
485 case BinaryOpIC::GENERIC: | 491 case BinaryOpIC::GENERIC: |
486 return unknown; | 492 return unknown; |
487 default: | 493 default: |
488 return unknown; | 494 return unknown; |
489 } | 495 } |
490 UNREACHABLE(); | 496 UNREACHABLE(); |
491 return unknown; | 497 return unknown; |
492 } | 498 } |
493 | 499 |
494 | 500 |
495 void TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id, | 501 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, |
496 Handle<String> name, | 502 Handle<String> name, |
497 Code::Flags flags, | 503 Code::Flags flags, |
498 SmallMapList* types) { | 504 SmallMapList* types) { |
499 Handle<Object> object = GetInfo(ast_id); | 505 Handle<Object> object = GetInfo(ast_id); |
500 if (object->IsUndefined() || object->IsSmi()) return; | 506 if (object->IsUndefined() || object->IsSmi()) return; |
501 | 507 |
502 if (*object == | 508 if (*object == |
503 isolate_->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { | 509 isolate_->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { |
504 // TODO(fschneider): We could collect the maps and signal that | 510 // TODO(fschneider): We could collect the maps and signal that |
505 // we need a generic store (or load) here. | 511 // we need a generic store (or load) here. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 | 561 |
556 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list, | 562 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list, |
557 Zone* zone) { | 563 Zone* zone) { |
558 for (int i = 0; i < list->length(); ++i) { | 564 for (int i = 0; i < list->length(); ++i) { |
559 if (list->at(i).is_identical_to(map)) return; | 565 if (list->at(i).is_identical_to(map)) return; |
560 } | 566 } |
561 list->Add(map, zone); | 567 list->Add(map, zone); |
562 } | 568 } |
563 | 569 |
564 | 570 |
565 void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id, | 571 void TypeFeedbackOracle::CollectKeyedReceiverTypes(TypeFeedbackId ast_id, |
566 SmallMapList* types) { | 572 SmallMapList* types) { |
567 Handle<Object> object = GetInfo(ast_id); | 573 Handle<Object> object = GetInfo(ast_id); |
568 if (!object->IsCode()) return; | 574 if (!object->IsCode()) return; |
569 Handle<Code> code = Handle<Code>::cast(object); | 575 Handle<Code> code = Handle<Code>::cast(object); |
570 if (code->kind() == Code::KEYED_LOAD_IC || | 576 if (code->kind() == Code::KEYED_LOAD_IC || |
571 code->kind() == Code::KEYED_STORE_IC) { | 577 code->kind() == Code::KEYED_STORE_IC) { |
572 AssertNoAllocation no_allocation; | 578 AssertNoAllocation no_allocation; |
573 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 579 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
574 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 580 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
575 RelocInfo* info = it.rinfo(); | 581 RelocInfo* info = it.rinfo(); |
576 Object* object = info->target_object(); | 582 Object* object = info->target_object(); |
577 if (object->IsMap()) { | 583 if (object->IsMap()) { |
578 Map* map = Map::cast(object); | 584 Map* map = Map::cast(object); |
579 if (!CanRetainOtherContext(map, *global_context_)) { | 585 if (!CanRetainOtherContext(map, *global_context_)) { |
580 AddMapIfMissing(Handle<Map>(map), types, zone()); | 586 AddMapIfMissing(Handle<Map>(map), types, zone()); |
581 } | 587 } |
582 } | 588 } |
583 } | 589 } |
584 } | 590 } |
585 } | 591 } |
586 | 592 |
587 | 593 |
588 byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) { | 594 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId ast_id) { |
589 Handle<Object> object = GetInfo(ast_id); | 595 Handle<Object> object = GetInfo(ast_id); |
590 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; | 596 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; |
591 } | 597 } |
592 | 598 |
593 | 599 |
594 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 600 // Things are a bit tricky here: The iterator for the RelocInfos and the infos |
595 // themselves are not GC-safe, so we first get all infos, then we create the | 601 // themselves are not GC-safe, so we first get all infos, then we create the |
596 // dictionary (possibly triggering GC), and finally we relocate the collected | 602 // dictionary (possibly triggering GC), and finally we relocate the collected |
597 // infos before we process them. | 603 // infos before we process them. |
598 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 604 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 RelocInfo* info = &(*infos)[i]; | 645 RelocInfo* info = &(*infos)[i]; |
640 info->set_pc(new_start + (info->pc() - old_start)); | 646 info->set_pc(new_start + (info->pc() - old_start)); |
641 } | 647 } |
642 } | 648 } |
643 | 649 |
644 | 650 |
645 void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { | 651 void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { |
646 for (int i = 0; i < infos->length(); i++) { | 652 for (int i = 0; i < infos->length(); i++) { |
647 RelocInfo reloc_entry = (*infos)[i]; | 653 RelocInfo reloc_entry = (*infos)[i]; |
648 Address target_address = reloc_entry.target_address(); | 654 Address target_address = reloc_entry.target_address(); |
649 unsigned ast_id = static_cast<unsigned>((*infos)[i].data()); | 655 TypeFeedbackId ast_id = |
| 656 TypeFeedbackId(static_cast<unsigned>((*infos)[i].data())); |
650 Code* target = Code::GetCodeFromTargetAddress(target_address); | 657 Code* target = Code::GetCodeFromTargetAddress(target_address); |
651 switch (target->kind()) { | 658 switch (target->kind()) { |
652 case Code::LOAD_IC: | 659 case Code::LOAD_IC: |
653 case Code::STORE_IC: | 660 case Code::STORE_IC: |
654 case Code::CALL_IC: | 661 case Code::CALL_IC: |
655 case Code::KEYED_CALL_IC: | 662 case Code::KEYED_CALL_IC: |
656 if (target->ic_state() == MONOMORPHIC) { | 663 if (target->ic_state() == MONOMORPHIC) { |
657 if (target->kind() == Code::CALL_IC && | 664 if (target->kind() == Code::CALL_IC && |
658 target->check_type() != RECEIVER_MAP_CHECK) { | 665 target->check_type() != RECEIVER_MAP_CHECK) { |
659 SetInfo(ast_id, Smi::FromInt(target->check_type())); | 666 SetInfo(ast_id, Smi::FromInt(target->check_type())); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 } | 699 } |
693 } | 700 } |
694 | 701 |
695 | 702 |
696 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { | 703 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { |
697 Object* raw_info = code->type_feedback_info(); | 704 Object* raw_info = code->type_feedback_info(); |
698 if (!raw_info->IsTypeFeedbackInfo()) return; | 705 if (!raw_info->IsTypeFeedbackInfo()) return; |
699 Handle<TypeFeedbackCells> cache( | 706 Handle<TypeFeedbackCells> cache( |
700 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); | 707 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); |
701 for (int i = 0; i < cache->CellCount(); i++) { | 708 for (int i = 0; i < cache->CellCount(); i++) { |
702 unsigned ast_id = cache->AstId(i)->value(); | 709 TypeFeedbackId ast_id = cache->AstId(i); |
703 Object* value = cache->Cell(i)->value(); | 710 Object* value = cache->Cell(i)->value(); |
704 if (value->IsSmi() || | 711 if (value->IsSmi() || |
705 (value->IsJSFunction() && | 712 (value->IsJSFunction() && |
706 !CanRetainOtherContext(JSFunction::cast(value), | 713 !CanRetainOtherContext(JSFunction::cast(value), |
707 *global_context_))) { | 714 *global_context_))) { |
708 SetInfo(ast_id, value); | 715 SetInfo(ast_id, value); |
709 } | 716 } |
710 } | 717 } |
711 } | 718 } |
712 | 719 |
713 | 720 |
714 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { | 721 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { |
715 ASSERT(dictionary_->FindEntry(ast_id) == UnseededNumberDictionary::kNotFound); | 722 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == |
716 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); | 723 UnseededNumberDictionary::kNotFound); |
| 724 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); |
717 USE(maybe_result); | 725 USE(maybe_result); |
718 #ifdef DEBUG | 726 #ifdef DEBUG |
719 Object* result = NULL; | 727 Object* result = NULL; |
720 // Dictionary has been allocated with sufficient size for all elements. | 728 // Dictionary has been allocated with sufficient size for all elements. |
721 ASSERT(maybe_result->ToObject(&result)); | 729 ASSERT(maybe_result->ToObject(&result)); |
722 ASSERT(*dictionary_ == result); | 730 ASSERT(*dictionary_ == result); |
723 #endif | 731 #endif |
724 } | 732 } |
725 | 733 |
726 } } // namespace v8::internal | 734 } } // namespace v8::internal |
OLD | NEW |