| 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 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 return *GetInfo(expr->PropertyFeedbackId()) == | 331 return *GetInfo(expr->PropertyFeedbackId()) == |
| 332 isolate_->builtins()->builtin(id); | 332 isolate_->builtins()->builtin(id); |
| 333 } | 333 } |
| 334 | 334 |
| 335 | 335 |
| 336 bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) { | 336 bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) { |
| 337 Handle<Object> object = GetInfo(expr->PropertyFeedbackId()); | 337 Handle<Object> object = GetInfo(expr->PropertyFeedbackId()); |
| 338 if (!object->IsCode()) return false; | 338 if (!object->IsCode()) return false; |
| 339 Handle<Code> code = Handle<Code>::cast(object); | 339 Handle<Code> code = Handle<Code>::cast(object); |
| 340 if (!code->is_load_stub()) return false; | 340 if (!code->is_load_stub()) return false; |
| 341 if (code->ic_state() != MONOMORPHIC) return false; |
| 341 return stub->Describes(*code); | 342 return stub->Describes(*code); |
| 342 } | 343 } |
| 343 | 344 |
| 344 | 345 |
| 345 static TypeInfo TypeFromCompareType(CompareIC::State state) { | 346 static TypeInfo TypeFromCompareType(CompareIC::State state) { |
| 346 switch (state) { | 347 switch (state) { |
| 347 case CompareIC::UNINITIALIZED: | 348 case CompareIC::UNINITIALIZED: |
| 348 // Uninitialized means never executed. | 349 // Uninitialized means never executed. |
| 349 return TypeInfo::Uninitialized(); | 350 return TypeInfo::Uninitialized(); |
| 350 case CompareIC::SMI: | 351 case CompareIC::SMI: |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 case BinaryOpIC::GENERIC: | 508 case BinaryOpIC::GENERIC: |
| 508 return unknown; | 509 return unknown; |
| 509 default: | 510 default: |
| 510 return unknown; | 511 return unknown; |
| 511 } | 512 } |
| 512 UNREACHABLE(); | 513 UNREACHABLE(); |
| 513 return unknown; | 514 return unknown; |
| 514 } | 515 } |
| 515 | 516 |
| 516 | 517 |
| 518 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list, |
| 519 Zone* zone) { |
| 520 for (int i = 0; i < list->length(); ++i) { |
| 521 if (list->at(i).is_identical_to(map)) return; |
| 522 } |
| 523 list->Add(map, zone); |
| 524 } |
| 525 |
| 526 |
| 527 void TypeFeedbackOracle::CollectPolymorphicMaps(Handle<Code> code, |
| 528 SmallMapList* types) { |
| 529 MapHandleList maps; |
| 530 code->FindAllMaps(&maps); |
| 531 types->Reserve(maps.length(), zone()); |
| 532 for (int i = 0; i < maps.length(); i++) { |
| 533 Handle<Map> map(maps.at(i)); |
| 534 if (!CanRetainOtherContext(*map, *native_context_)) { |
| 535 AddMapIfMissing(map, types, zone()); |
| 536 } |
| 537 } |
| 538 } |
| 539 |
| 540 |
| 517 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, | 541 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, |
| 518 Handle<String> name, | 542 Handle<String> name, |
| 519 Code::Flags flags, | 543 Code::Flags flags, |
| 520 SmallMapList* types) { | 544 SmallMapList* types) { |
| 521 Handle<Object> object = GetInfo(ast_id); | 545 Handle<Object> object = GetInfo(ast_id); |
| 522 if (object->IsUndefined() || object->IsSmi()) return; | 546 if (object->IsUndefined() || object->IsSmi()) return; |
| 523 | 547 |
| 524 if (object.is_identical_to(isolate_->builtins()->StoreIC_GlobalProxy())) { | 548 if (object.is_identical_to(isolate_->builtins()->StoreIC_GlobalProxy())) { |
| 525 // TODO(fschneider): We could collect the maps and signal that | 549 // TODO(fschneider): We could collect the maps and signal that |
| 526 // we need a generic store (or load) here. | 550 // we need a generic store (or load) here. |
| 527 ASSERT(Handle<Code>::cast(object)->ic_state() == GENERIC); | 551 ASSERT(Handle<Code>::cast(object)->ic_state() == GENERIC); |
| 528 } else if (object->IsMap()) { | 552 } else if (object->IsMap()) { |
| 529 types->Add(Handle<Map>::cast(object), zone()); | 553 types->Add(Handle<Map>::cast(object), zone()); |
| 554 } else if (Handle<Code>::cast(object)->ic_state() == POLYMORPHIC) { |
| 555 CollectPolymorphicMaps(Handle<Code>::cast(object), types); |
| 530 } else if (FLAG_collect_megamorphic_maps_from_stub_cache && | 556 } else if (FLAG_collect_megamorphic_maps_from_stub_cache && |
| 531 Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { | 557 Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { |
| 532 types->Reserve(4, zone()); | 558 types->Reserve(4, zone()); |
| 533 ASSERT(object->IsCode()); | 559 ASSERT(object->IsCode()); |
| 534 isolate_->stub_cache()->CollectMatchingMaps(types, | 560 isolate_->stub_cache()->CollectMatchingMaps(types, |
| 535 *name, | 561 *name, |
| 536 flags, | 562 flags, |
| 537 native_context_, | 563 native_context_, |
| 538 zone()); | 564 zone()); |
| 539 } | 565 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 567 } | 593 } |
| 568 | 594 |
| 569 | 595 |
| 570 bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function, | 596 bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function, |
| 571 Context* native_context) { | 597 Context* native_context) { |
| 572 return function->context()->global_object() != native_context->global_object() | 598 return function->context()->global_object() != native_context->global_object() |
| 573 && function->context()->global_object() != native_context->builtins(); | 599 && function->context()->global_object() != native_context->builtins(); |
| 574 } | 600 } |
| 575 | 601 |
| 576 | 602 |
| 577 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list, | |
| 578 Zone* zone) { | |
| 579 for (int i = 0; i < list->length(); ++i) { | |
| 580 if (list->at(i).is_identical_to(map)) return; | |
| 581 } | |
| 582 list->Add(map, zone); | |
| 583 } | |
| 584 | |
| 585 | |
| 586 void TypeFeedbackOracle::CollectKeyedReceiverTypes(TypeFeedbackId ast_id, | 603 void TypeFeedbackOracle::CollectKeyedReceiverTypes(TypeFeedbackId ast_id, |
| 587 SmallMapList* types) { | 604 SmallMapList* types) { |
| 588 Handle<Object> object = GetInfo(ast_id); | 605 Handle<Object> object = GetInfo(ast_id); |
| 589 if (!object->IsCode()) return; | 606 if (!object->IsCode()) return; |
| 590 Handle<Code> code = Handle<Code>::cast(object); | 607 Handle<Code> code = Handle<Code>::cast(object); |
| 591 if (code->kind() == Code::KEYED_LOAD_IC || | 608 if (code->kind() == Code::KEYED_LOAD_IC || |
| 592 code->kind() == Code::KEYED_STORE_IC) { | 609 code->kind() == Code::KEYED_STORE_IC) { |
| 593 AssertNoAllocation no_allocation; | 610 CollectPolymorphicMaps(code, types); |
| 594 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | |
| 595 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | |
| 596 RelocInfo* info = it.rinfo(); | |
| 597 Object* object = info->target_object(); | |
| 598 if (object->IsMap()) { | |
| 599 Map* map = Map::cast(object); | |
| 600 if (!CanRetainOtherContext(map, *native_context_)) { | |
| 601 AddMapIfMissing(Handle<Map>(map), types, zone()); | |
| 602 } | |
| 603 } | |
| 604 } | |
| 605 } | 611 } |
| 606 } | 612 } |
| 607 | 613 |
| 608 | 614 |
| 609 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId ast_id) { | 615 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId ast_id) { |
| 610 Handle<Object> object = GetInfo(ast_id); | 616 Handle<Object> object = GetInfo(ast_id); |
| 611 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; | 617 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; |
| 612 } | 618 } |
| 613 | 619 |
| 614 | 620 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 USE(maybe_result); | 746 USE(maybe_result); |
| 741 #ifdef DEBUG | 747 #ifdef DEBUG |
| 742 Object* result = NULL; | 748 Object* result = NULL; |
| 743 // Dictionary has been allocated with sufficient size for all elements. | 749 // Dictionary has been allocated with sufficient size for all elements. |
| 744 ASSERT(maybe_result->ToObject(&result)); | 750 ASSERT(maybe_result->ToObject(&result)); |
| 745 ASSERT(*dictionary_ == result); | 751 ASSERT(*dictionary_ == result); |
| 746 #endif | 752 #endif |
| 747 } | 753 } |
| 748 | 754 |
| 749 } } // namespace v8::internal | 755 } } // namespace v8::internal |
| OLD | NEW |