OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/ast.h" | 7 #include "src/ast.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { | 74 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { |
75 Handle<Object> maybe_code = GetInfo(id); | 75 Handle<Object> maybe_code = GetInfo(id); |
76 if (maybe_code->IsCode()) { | 76 if (maybe_code->IsCode()) { |
77 Handle<Code> code = Handle<Code>::cast(maybe_code); | 77 Handle<Code> code = Handle<Code>::cast(maybe_code); |
78 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 78 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; |
79 } | 79 } |
80 return false; | 80 return false; |
81 } | 81 } |
82 | 82 |
83 | 83 |
| 84 bool TypeFeedbackOracle::LoadIsUninitialized(FeedbackVectorICSlot slot) { |
| 85 Code::Kind kind = feedback_vector_->GetKind(slot); |
| 86 if (kind == Code::LOAD_IC) { |
| 87 LoadICNexus nexus(feedback_vector_, slot); |
| 88 return nexus.StateFromFeedback() == UNINITIALIZED; |
| 89 } else if (kind == Code::KEYED_LOAD_IC) { |
| 90 KeyedLoadICNexus nexus(feedback_vector_, slot); |
| 91 return nexus.StateFromFeedback() == UNINITIALIZED; |
| 92 } else if (kind == Code::NUMBER_OF_KINDS) { |
| 93 // Code::NUMBER_OF_KINDS indicates a slot that was never even compiled |
| 94 // in full code. |
| 95 return true; |
| 96 } |
| 97 |
| 98 return false; |
| 99 } |
| 100 |
| 101 |
84 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { | 102 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { |
85 Handle<Object> maybe_code = GetInfo(ast_id); | 103 Handle<Object> maybe_code = GetInfo(ast_id); |
86 if (!maybe_code->IsCode()) return false; | 104 if (!maybe_code->IsCode()) return false; |
87 Handle<Code> code = Handle<Code>::cast(maybe_code); | 105 Handle<Code> code = Handle<Code>::cast(maybe_code); |
88 return code->ic_state() == UNINITIALIZED; | 106 return code->ic_state() == UNINITIALIZED; |
89 } | 107 } |
90 | 108 |
91 | 109 |
92 bool TypeFeedbackOracle::CallIsUninitialized(FeedbackVectorICSlot slot) { | 110 bool TypeFeedbackOracle::CallIsUninitialized(FeedbackVectorICSlot slot) { |
93 Handle<Object> value = GetInfo(slot); | 111 Handle<Object> value = GetInfo(slot); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 | 288 |
271 void TypeFeedbackOracle::PropertyReceiverTypes(TypeFeedbackId id, | 289 void TypeFeedbackOracle::PropertyReceiverTypes(TypeFeedbackId id, |
272 Handle<String> name, | 290 Handle<String> name, |
273 SmallMapList* receiver_types) { | 291 SmallMapList* receiver_types) { |
274 receiver_types->Clear(); | 292 receiver_types->Clear(); |
275 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 293 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
276 CollectReceiverTypes(id, name, flags, receiver_types); | 294 CollectReceiverTypes(id, name, flags, receiver_types); |
277 } | 295 } |
278 | 296 |
279 | 297 |
| 298 bool TypeFeedbackOracle::HasOnlyStringMaps(SmallMapList* receiver_types) { |
| 299 bool all_strings = receiver_types->length() > 0; |
| 300 for (int i = 0; i < receiver_types->length(); i++) { |
| 301 all_strings &= receiver_types->at(i)->IsStringMap(); |
| 302 } |
| 303 return all_strings; |
| 304 } |
| 305 |
| 306 |
280 void TypeFeedbackOracle::KeyedPropertyReceiverTypes( | 307 void TypeFeedbackOracle::KeyedPropertyReceiverTypes( |
281 TypeFeedbackId id, SmallMapList* receiver_types, bool* is_string) { | 308 TypeFeedbackId id, SmallMapList* receiver_types, bool* is_string) { |
282 receiver_types->Clear(); | 309 receiver_types->Clear(); |
283 CollectReceiverTypes(id, receiver_types); | 310 CollectReceiverTypes(id, receiver_types); |
284 | 311 *is_string = HasOnlyStringMaps(receiver_types); |
285 // Are all the receiver maps string maps? | |
286 bool all_strings = receiver_types->length() > 0; | |
287 for (int i = 0; i < receiver_types->length(); i++) { | |
288 all_strings &= receiver_types->at(i)->IsStringMap(); | |
289 } | |
290 *is_string = all_strings; | |
291 } | 312 } |
292 | 313 |
293 | 314 |
| 315 void TypeFeedbackOracle::PropertyReceiverTypes(FeedbackVectorICSlot slot, |
| 316 Handle<String> name, |
| 317 SmallMapList* receiver_types) { |
| 318 receiver_types->Clear(); |
| 319 LoadICNexus nexus(feedback_vector_, slot); |
| 320 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 321 CollectReceiverTypes(&nexus, name, flags, receiver_types); |
| 322 } |
| 323 |
| 324 |
| 325 void TypeFeedbackOracle::KeyedPropertyReceiverTypes( |
| 326 FeedbackVectorICSlot slot, SmallMapList* receiver_types, bool* is_string) { |
| 327 receiver_types->Clear(); |
| 328 KeyedLoadICNexus nexus(feedback_vector_, slot); |
| 329 CollectReceiverTypes<FeedbackNexus>(&nexus, receiver_types); |
| 330 *is_string = HasOnlyStringMaps(receiver_types); |
| 331 } |
| 332 |
| 333 |
294 void TypeFeedbackOracle::AssignmentReceiverTypes( | 334 void TypeFeedbackOracle::AssignmentReceiverTypes( |
295 TypeFeedbackId id, Handle<String> name, SmallMapList* receiver_types) { | 335 TypeFeedbackId id, Handle<String> name, SmallMapList* receiver_types) { |
296 receiver_types->Clear(); | 336 receiver_types->Clear(); |
297 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); | 337 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); |
298 CollectReceiverTypes(id, name, flags, receiver_types); | 338 CollectReceiverTypes(id, name, flags, receiver_types); |
299 } | 339 } |
300 | 340 |
301 | 341 |
302 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( | 342 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( |
303 TypeFeedbackId id, SmallMapList* receiver_types, | 343 TypeFeedbackId id, SmallMapList* receiver_types, |
(...skipping 13 matching lines...) Expand all Loading... |
317 | 357 |
318 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, | 358 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, |
319 Handle<String> name, | 359 Handle<String> name, |
320 Code::Flags flags, | 360 Code::Flags flags, |
321 SmallMapList* types) { | 361 SmallMapList* types) { |
322 Handle<Object> object = GetInfo(ast_id); | 362 Handle<Object> object = GetInfo(ast_id); |
323 if (object->IsUndefined() || object->IsSmi()) return; | 363 if (object->IsUndefined() || object->IsSmi()) return; |
324 | 364 |
325 DCHECK(object->IsCode()); | 365 DCHECK(object->IsCode()); |
326 Handle<Code> code(Handle<Code>::cast(object)); | 366 Handle<Code> code(Handle<Code>::cast(object)); |
| 367 CollectReceiverTypes<Code>(*code, name, flags, types); |
| 368 } |
327 | 369 |
| 370 |
| 371 template <class T> |
| 372 void TypeFeedbackOracle::CollectReceiverTypes(T* obj, Handle<String> name, |
| 373 Code::Flags flags, |
| 374 SmallMapList* types) { |
328 if (FLAG_collect_megamorphic_maps_from_stub_cache && | 375 if (FLAG_collect_megamorphic_maps_from_stub_cache && |
329 code->ic_state() == MEGAMORPHIC) { | 376 obj->ic_state() == MEGAMORPHIC) { |
330 types->Reserve(4, zone()); | 377 types->Reserve(4, zone()); |
331 isolate()->stub_cache()->CollectMatchingMaps( | 378 isolate()->stub_cache()->CollectMatchingMaps( |
332 types, name, flags, native_context_, zone()); | 379 types, name, flags, native_context_, zone()); |
333 } else { | 380 } else { |
334 CollectReceiverTypes(ast_id, types); | 381 CollectReceiverTypes<T>(obj, types); |
335 } | 382 } |
336 } | 383 } |
337 | 384 |
338 | 385 |
339 // Check if a map originates from a given native context. We use this | 386 // Check if a map originates from a given native context. We use this |
340 // information to filter out maps from different context to avoid | 387 // information to filter out maps from different context to avoid |
341 // retaining objects from different tabs in Chrome via optimized code. | 388 // retaining objects from different tabs in Chrome via optimized code. |
342 bool TypeFeedbackOracle::CanRetainOtherContext(Map* map, | 389 bool TypeFeedbackOracle::CanRetainOtherContext(Map* map, |
343 Context* native_context) { | 390 Context* native_context) { |
344 Object* constructor = NULL; | 391 Object* constructor = NULL; |
(...skipping 23 matching lines...) Expand all Loading... |
368 return function->context()->global_object() != native_context->global_object() | 415 return function->context()->global_object() != native_context->global_object() |
369 && function->context()->global_object() != native_context->builtins(); | 416 && function->context()->global_object() != native_context->builtins(); |
370 } | 417 } |
371 | 418 |
372 | 419 |
373 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, | 420 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, |
374 SmallMapList* types) { | 421 SmallMapList* types) { |
375 Handle<Object> object = GetInfo(ast_id); | 422 Handle<Object> object = GetInfo(ast_id); |
376 if (!object->IsCode()) return; | 423 if (!object->IsCode()) return; |
377 Handle<Code> code = Handle<Code>::cast(object); | 424 Handle<Code> code = Handle<Code>::cast(object); |
| 425 CollectReceiverTypes<Code>(*code, types); |
| 426 } |
| 427 |
| 428 |
| 429 template <class T> |
| 430 void TypeFeedbackOracle::CollectReceiverTypes(T* obj, SmallMapList* types) { |
378 MapHandleList maps; | 431 MapHandleList maps; |
379 if (code->ic_state() == MONOMORPHIC) { | 432 if (obj->ic_state() == MONOMORPHIC) { |
380 Map* map = code->FindFirstMap(); | 433 Map* map = obj->FindFirstMap(); |
381 if (map != NULL) maps.Add(handle(map)); | 434 if (map != NULL) maps.Add(handle(map)); |
382 } else if (code->ic_state() == POLYMORPHIC) { | 435 } else if (obj->ic_state() == POLYMORPHIC) { |
383 code->FindAllMaps(&maps); | 436 obj->FindAllMaps(&maps); |
384 } else { | 437 } else { |
385 return; | 438 return; |
386 } | 439 } |
387 types->Reserve(maps.length(), zone()); | 440 types->Reserve(maps.length(), zone()); |
388 for (int i = 0; i < maps.length(); i++) { | 441 for (int i = 0; i < maps.length(); i++) { |
389 Handle<Map> map(maps.at(i)); | 442 Handle<Map> map(maps.at(i)); |
390 if (!CanRetainOtherContext(*map, *native_context_)) { | 443 if (!CanRetainOtherContext(*map, *native_context_)) { |
391 types->AddMapIfMissing(map, zone()); | 444 types->AddMapIfMissing(map, zone()); |
392 } | 445 } |
393 } | 446 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 UnseededNumberDictionary::kNotFound); | 530 UnseededNumberDictionary::kNotFound); |
478 // Dictionary has been allocated with sufficient size for all elements. | 531 // Dictionary has been allocated with sufficient size for all elements. |
479 DisallowHeapAllocation no_need_to_resize_dictionary; | 532 DisallowHeapAllocation no_need_to_resize_dictionary; |
480 HandleScope scope(isolate()); | 533 HandleScope scope(isolate()); |
481 USE(UnseededNumberDictionary::AtNumberPut( | 534 USE(UnseededNumberDictionary::AtNumberPut( |
482 dictionary_, IdToKey(ast_id), handle(target, isolate()))); | 535 dictionary_, IdToKey(ast_id), handle(target, isolate()))); |
483 } | 536 } |
484 | 537 |
485 | 538 |
486 } } // namespace v8::internal | 539 } } // namespace v8::internal |
OLD | NEW |