| 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 info = TypeInfo::String(); | 54 info = TypeInfo::String(); |
| 55 } else { | 55 } else { |
| 56 info = TypeInfo::Unknown(); | 56 info = TypeInfo::Unknown(); |
| 57 } | 57 } |
| 58 return info; | 58 return info; |
| 59 } | 59 } |
| 60 | 60 |
| 61 | 61 |
| 62 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, | 62 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, |
| 63 Handle<Context> global_context, | 63 Handle<Context> global_context, |
| 64 Isolate* isolate) { | 64 Isolate* isolate, |
| 65 Zone* zone) { |
| 65 global_context_ = global_context; | 66 global_context_ = global_context; |
| 66 isolate_ = isolate; | 67 isolate_ = isolate; |
| 68 zone_ = zone; |
| 67 BuildDictionary(code); | 69 BuildDictionary(code); |
| 68 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); | 70 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); |
| 69 } | 71 } |
| 70 | 72 |
| 71 | 73 |
| 72 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { | 74 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { |
| 73 int entry = dictionary_->FindEntry(ast_id); | 75 int entry = dictionary_->FindEntry(ast_id); |
| 74 return entry != UnseededNumberDictionary::kNotFound | 76 return entry != UnseededNumberDictionary::kNotFound |
| 75 ? Handle<Object>(dictionary_->ValueAt(entry)) | 77 ? Handle<Object>(dictionary_->ValueAt(entry)) |
| 76 : Handle<Object>::cast(isolate_->factory()->undefined_value()); | 78 : Handle<Object>::cast(isolate_->factory()->undefined_value()); |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 SmallMapList* types) { | 496 SmallMapList* types) { |
| 495 Handle<Object> object = GetInfo(ast_id); | 497 Handle<Object> object = GetInfo(ast_id); |
| 496 if (object->IsUndefined() || object->IsSmi()) return; | 498 if (object->IsUndefined() || object->IsSmi()) return; |
| 497 | 499 |
| 498 if (*object == | 500 if (*object == |
| 499 isolate_->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { | 501 isolate_->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { |
| 500 // TODO(fschneider): We could collect the maps and signal that | 502 // TODO(fschneider): We could collect the maps and signal that |
| 501 // we need a generic store (or load) here. | 503 // we need a generic store (or load) here. |
| 502 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); | 504 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); |
| 503 } else if (object->IsMap()) { | 505 } else if (object->IsMap()) { |
| 504 types->Add(Handle<Map>::cast(object)); | 506 types->Add(Handle<Map>::cast(object), zone()); |
| 505 } else if (FLAG_collect_megamorphic_maps_from_stub_cache && | 507 } else if (FLAG_collect_megamorphic_maps_from_stub_cache && |
| 506 Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { | 508 Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { |
| 507 types->Reserve(4); | 509 types->Reserve(4, zone()); |
| 508 ASSERT(object->IsCode()); | 510 ASSERT(object->IsCode()); |
| 509 isolate_->stub_cache()->CollectMatchingMaps(types, | 511 isolate_->stub_cache()->CollectMatchingMaps(types, |
| 510 *name, | 512 *name, |
| 511 flags, | 513 flags, |
| 512 global_context_); | 514 global_context_); |
| 513 } | 515 } |
| 514 } | 516 } |
| 515 | 517 |
| 516 | 518 |
| 517 // Check if a map originates from a given global context. We use this | 519 // Check if a map originates from a given global context. We use this |
| (...skipping 23 matching lines...) Expand all Loading... |
| 541 } | 543 } |
| 542 | 544 |
| 543 | 545 |
| 544 bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function, | 546 bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function, |
| 545 Context* global_context) { | 547 Context* global_context) { |
| 546 return function->context()->global() != global_context->global() | 548 return function->context()->global() != global_context->global() |
| 547 && function->context()->global() != global_context->builtins(); | 549 && function->context()->global() != global_context->builtins(); |
| 548 } | 550 } |
| 549 | 551 |
| 550 | 552 |
| 551 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list) { | 553 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list, |
| 554 Zone* zone) { |
| 552 for (int i = 0; i < list->length(); ++i) { | 555 for (int i = 0; i < list->length(); ++i) { |
| 553 if (list->at(i).is_identical_to(map)) return; | 556 if (list->at(i).is_identical_to(map)) return; |
| 554 } | 557 } |
| 555 list->Add(map); | 558 list->Add(map, zone); |
| 556 } | 559 } |
| 557 | 560 |
| 558 | 561 |
| 559 void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id, | 562 void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id, |
| 560 SmallMapList* types) { | 563 SmallMapList* types) { |
| 561 Handle<Object> object = GetInfo(ast_id); | 564 Handle<Object> object = GetInfo(ast_id); |
| 562 if (!object->IsCode()) return; | 565 if (!object->IsCode()) return; |
| 563 Handle<Code> code = Handle<Code>::cast(object); | 566 Handle<Code> code = Handle<Code>::cast(object); |
| 564 if (code->kind() == Code::KEYED_LOAD_IC || | 567 if (code->kind() == Code::KEYED_LOAD_IC || |
| 565 code->kind() == Code::KEYED_STORE_IC) { | 568 code->kind() == Code::KEYED_STORE_IC) { |
| 566 AssertNoAllocation no_allocation; | 569 AssertNoAllocation no_allocation; |
| 567 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 570 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 568 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 571 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
| 569 RelocInfo* info = it.rinfo(); | 572 RelocInfo* info = it.rinfo(); |
| 570 Object* object = info->target_object(); | 573 Object* object = info->target_object(); |
| 571 if (object->IsMap()) { | 574 if (object->IsMap()) { |
| 572 Map* map = Map::cast(object); | 575 Map* map = Map::cast(object); |
| 573 if (!CanRetainOtherContext(map, *global_context_)) { | 576 if (!CanRetainOtherContext(map, *global_context_)) { |
| 574 AddMapIfMissing(Handle<Map>(map), types); | 577 AddMapIfMissing(Handle<Map>(map), types, zone()); |
| 575 } | 578 } |
| 576 } | 579 } |
| 577 } | 580 } |
| 578 } | 581 } |
| 579 } | 582 } |
| 580 | 583 |
| 581 | 584 |
| 582 byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) { | 585 byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) { |
| 583 Handle<Object> object = GetInfo(ast_id); | 586 Handle<Object> object = GetInfo(ast_id); |
| 584 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; | 587 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; |
| 585 } | 588 } |
| 586 | 589 |
| 587 | 590 |
| 588 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 591 // Things are a bit tricky here: The iterator for the RelocInfos and the infos |
| 589 // themselves are not GC-safe, so we first get all infos, then we create the | 592 // themselves are not GC-safe, so we first get all infos, then we create the |
| 590 // dictionary (possibly triggering GC), and finally we relocate the collected | 593 // dictionary (possibly triggering GC), and finally we relocate the collected |
| 591 // infos before we process them. | 594 // infos before we process them. |
| 592 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 595 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
| 593 AssertNoAllocation no_allocation; | 596 AssertNoAllocation no_allocation; |
| 594 ZoneList<RelocInfo> infos(16); | 597 ZoneList<RelocInfo> infos(16, zone()); |
| 595 HandleScope scope; | 598 HandleScope scope; |
| 596 GetRelocInfos(code, &infos); | 599 GetRelocInfos(code, &infos); |
| 597 CreateDictionary(code, &infos); | 600 CreateDictionary(code, &infos); |
| 598 ProcessRelocInfos(&infos); | 601 ProcessRelocInfos(&infos); |
| 599 ProcessTypeFeedbackCells(code); | 602 ProcessTypeFeedbackCells(code); |
| 600 // Allocate handle in the parent scope. | 603 // Allocate handle in the parent scope. |
| 601 dictionary_ = scope.CloseAndEscape(dictionary_); | 604 dictionary_ = scope.CloseAndEscape(dictionary_); |
| 602 } | 605 } |
| 603 | 606 |
| 604 | 607 |
| 605 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, | 608 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, |
| 606 ZoneList<RelocInfo>* infos) { | 609 ZoneList<RelocInfo>* infos) { |
| 607 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 610 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
| 608 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 611 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
| 609 infos->Add(*it.rinfo()); | 612 infos->Add(*it.rinfo(), zone()); |
| 610 } | 613 } |
| 611 } | 614 } |
| 612 | 615 |
| 613 | 616 |
| 614 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, | 617 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, |
| 615 ZoneList<RelocInfo>* infos) { | 618 ZoneList<RelocInfo>* infos) { |
| 616 DisableAssertNoAllocation allocation_allowed; | 619 DisableAssertNoAllocation allocation_allowed; |
| 617 int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo() | 620 int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo() |
| 618 ? TypeFeedbackInfo::cast(code->type_feedback_info())-> | 621 ? TypeFeedbackInfo::cast(code->type_feedback_info())-> |
| 619 type_feedback_cells()->CellCount() | 622 type_feedback_cells()->CellCount() |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 USE(maybe_result); | 714 USE(maybe_result); |
| 712 #ifdef DEBUG | 715 #ifdef DEBUG |
| 713 Object* result = NULL; | 716 Object* result = NULL; |
| 714 // Dictionary has been allocated with sufficient size for all elements. | 717 // Dictionary has been allocated with sufficient size for all elements. |
| 715 ASSERT(maybe_result->ToObject(&result)); | 718 ASSERT(maybe_result->ToObject(&result)); |
| 716 ASSERT(*dictionary_ == result); | 719 ASSERT(*dictionary_ == result); |
| 717 #endif | 720 #endif |
| 718 } | 721 } |
| 719 | 722 |
| 720 } } // namespace v8::internal | 723 } } // namespace v8::internal |
| OLD | NEW |