| 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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 new_space_high_promotion_mode_active_(false), | 120 new_space_high_promotion_mode_active_(false), |
| 121 old_gen_promotion_limit_(kMinimumPromotionLimit), | 121 old_gen_promotion_limit_(kMinimumPromotionLimit), |
| 122 old_gen_allocation_limit_(kMinimumAllocationLimit), | 122 old_gen_allocation_limit_(kMinimumAllocationLimit), |
| 123 old_gen_limit_factor_(1), | 123 old_gen_limit_factor_(1), |
| 124 size_of_old_gen_at_last_old_space_gc_(0), | 124 size_of_old_gen_at_last_old_space_gc_(0), |
| 125 external_allocation_limit_(0), | 125 external_allocation_limit_(0), |
| 126 amount_of_external_allocated_memory_(0), | 126 amount_of_external_allocated_memory_(0), |
| 127 amount_of_external_allocated_memory_at_last_global_gc_(0), | 127 amount_of_external_allocated_memory_at_last_global_gc_(0), |
| 128 old_gen_exhausted_(false), | 128 old_gen_exhausted_(false), |
| 129 store_buffer_rebuilder_(store_buffer()), | 129 store_buffer_rebuilder_(store_buffer()), |
| 130 hidden_symbol_(NULL), | 130 hidden_string_(NULL), |
| 131 global_gc_prologue_callback_(NULL), | 131 global_gc_prologue_callback_(NULL), |
| 132 global_gc_epilogue_callback_(NULL), | 132 global_gc_epilogue_callback_(NULL), |
| 133 gc_safe_size_of_old_object_(NULL), | 133 gc_safe_size_of_old_object_(NULL), |
| 134 total_regexp_code_generated_(0), | 134 total_regexp_code_generated_(0), |
| 135 tracer_(NULL), | 135 tracer_(NULL), |
| 136 young_survivors_after_last_gc_(0), | 136 young_survivors_after_last_gc_(0), |
| 137 high_survival_rate_period_length_(0), | 137 high_survival_rate_period_length_(0), |
| 138 low_survival_rate_period_length_(0), | 138 low_survival_rate_period_length_(0), |
| 139 survival_rate_(0), | 139 survival_rate_(0), |
| 140 previous_survival_rate_trend_(Heap::STABLE), | 140 previous_survival_rate_trend_(Heap::STABLE), |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 allow_allocation(true); | 485 allow_allocation(true); |
| 486 if (FLAG_print_global_handles) isolate_->global_handles()->Print(); | 486 if (FLAG_print_global_handles) isolate_->global_handles()->Print(); |
| 487 if (FLAG_print_handles) PrintHandles(); | 487 if (FLAG_print_handles) PrintHandles(); |
| 488 if (FLAG_gc_verbose) Print(); | 488 if (FLAG_gc_verbose) Print(); |
| 489 if (FLAG_code_stats) ReportCodeStatistics("After GC"); | 489 if (FLAG_code_stats) ReportCodeStatistics("After GC"); |
| 490 #endif | 490 #endif |
| 491 | 491 |
| 492 isolate_->counters()->alive_after_last_gc()->Set( | 492 isolate_->counters()->alive_after_last_gc()->Set( |
| 493 static_cast<int>(SizeOfObjects())); | 493 static_cast<int>(SizeOfObjects())); |
| 494 | 494 |
| 495 isolate_->counters()->symbol_table_capacity()->Set( | 495 isolate_->counters()->string_table_capacity()->Set( |
| 496 symbol_table()->Capacity()); | 496 string_table()->Capacity()); |
| 497 isolate_->counters()->number_of_symbols()->Set( | 497 isolate_->counters()->number_of_symbols()->Set( |
| 498 symbol_table()->NumberOfElements()); | 498 string_table()->NumberOfElements()); |
| 499 | 499 |
| 500 if (CommittedMemory() > 0) { | 500 if (CommittedMemory() > 0) { |
| 501 isolate_->counters()->external_fragmentation_total()->AddSample( | 501 isolate_->counters()->external_fragmentation_total()->AddSample( |
| 502 static_cast<int>(100 - (SizeOfObjects() * 100.0) / CommittedMemory())); | 502 static_cast<int>(100 - (SizeOfObjects() * 100.0) / CommittedMemory())); |
| 503 | 503 |
| 504 isolate_->counters()->heap_fraction_map_space()->AddSample( | 504 isolate_->counters()->heap_fraction_map_space()->AddSample( |
| 505 static_cast<int>( | 505 static_cast<int>( |
| 506 (map_space()->CommittedMemory() * 100.0) / CommittedMemory())); | 506 (map_space()->CommittedMemory() * 100.0) / CommittedMemory())); |
| 507 isolate_->counters()->heap_fraction_cell_space()->AddSample( | 507 isolate_->counters()->heap_fraction_cell_space()->AddSample( |
| 508 static_cast<int>( | 508 static_cast<int>( |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 if (InNewSpace(dst_objects[i])) { | 698 if (InNewSpace(dst_objects[i])) { |
| 699 RecordWrite(array->address(), array->OffsetOfElementAt(dst_index + i)); | 699 RecordWrite(array->address(), array->OffsetOfElementAt(dst_index + i)); |
| 700 } | 700 } |
| 701 } | 701 } |
| 702 } | 702 } |
| 703 incremental_marking()->RecordWrites(array); | 703 incremental_marking()->RecordWrites(array); |
| 704 } | 704 } |
| 705 | 705 |
| 706 | 706 |
| 707 #ifdef VERIFY_HEAP | 707 #ifdef VERIFY_HEAP |
| 708 // Helper class for verifying the symbol table. | 708 // Helper class for verifying the string table. |
| 709 class SymbolTableVerifier : public ObjectVisitor { | 709 class StringTableVerifier : public ObjectVisitor { |
| 710 public: | 710 public: |
| 711 void VisitPointers(Object** start, Object** end) { | 711 void VisitPointers(Object** start, Object** end) { |
| 712 // Visit all HeapObject pointers in [start, end). | 712 // Visit all HeapObject pointers in [start, end). |
| 713 for (Object** p = start; p < end; p++) { | 713 for (Object** p = start; p < end; p++) { |
| 714 if ((*p)->IsHeapObject()) { | 714 if ((*p)->IsHeapObject()) { |
| 715 // Check that the symbol is actually a symbol. | 715 // Check that the string is actually internalized. |
| 716 CHECK((*p)->IsTheHole() || (*p)->IsUndefined() || (*p)->IsSymbol()); | 716 CHECK((*p)->IsTheHole() || (*p)->IsUndefined() || |
| 717 (*p)->IsInternalizedString()); |
| 717 } | 718 } |
| 718 } | 719 } |
| 719 } | 720 } |
| 720 }; | 721 }; |
| 721 | 722 |
| 722 | 723 |
| 723 static void VerifySymbolTable() { | 724 static void VerifyStringTable() { |
| 724 SymbolTableVerifier verifier; | 725 StringTableVerifier verifier; |
| 725 HEAP->symbol_table()->IterateElements(&verifier); | 726 HEAP->string_table()->IterateElements(&verifier); |
| 726 } | 727 } |
| 727 #endif // VERIFY_HEAP | 728 #endif // VERIFY_HEAP |
| 728 | 729 |
| 729 | 730 |
| 730 static bool AbortIncrementalMarkingAndCollectGarbage( | 731 static bool AbortIncrementalMarkingAndCollectGarbage( |
| 731 Heap* heap, | 732 Heap* heap, |
| 732 AllocationSpace space, | 733 AllocationSpace space, |
| 733 const char* gc_reason = NULL) { | 734 const char* gc_reason = NULL) { |
| 734 heap->mark_compact_collector()->SetFlags(Heap::kAbortIncrementalMarkingMask); | 735 heap->mark_compact_collector()->SetFlags(Heap::kAbortIncrementalMarkingMask); |
| 735 bool result = heap->CollectGarbage(space, gc_reason); | 736 bool result = heap->CollectGarbage(space, gc_reason); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 bool Heap::PerformGarbageCollection(GarbageCollector collector, | 877 bool Heap::PerformGarbageCollection(GarbageCollector collector, |
| 877 GCTracer* tracer) { | 878 GCTracer* tracer) { |
| 878 bool next_gc_likely_to_collect_more = false; | 879 bool next_gc_likely_to_collect_more = false; |
| 879 | 880 |
| 880 if (collector != SCAVENGER) { | 881 if (collector != SCAVENGER) { |
| 881 PROFILE(isolate_, CodeMovingGCEvent()); | 882 PROFILE(isolate_, CodeMovingGCEvent()); |
| 882 } | 883 } |
| 883 | 884 |
| 884 #ifdef VERIFY_HEAP | 885 #ifdef VERIFY_HEAP |
| 885 if (FLAG_verify_heap) { | 886 if (FLAG_verify_heap) { |
| 886 VerifySymbolTable(); | 887 VerifyStringTable(); |
| 887 } | 888 } |
| 888 #endif | 889 #endif |
| 889 | 890 |
| 890 GCType gc_type = | 891 GCType gc_type = |
| 891 collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge; | 892 collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge; |
| 892 | 893 |
| 893 { | 894 { |
| 894 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 895 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 895 VMState state(isolate_, EXTERNAL); | 896 VMState state(isolate_, EXTERNAL); |
| 896 CallGCPrologueCallbacks(gc_type); | 897 CallGCPrologueCallbacks(gc_type); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 } | 1002 } |
| 1002 | 1003 |
| 1003 { | 1004 { |
| 1004 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 1005 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 1005 VMState state(isolate_, EXTERNAL); | 1006 VMState state(isolate_, EXTERNAL); |
| 1006 CallGCEpilogueCallbacks(gc_type); | 1007 CallGCEpilogueCallbacks(gc_type); |
| 1007 } | 1008 } |
| 1008 | 1009 |
| 1009 #ifdef VERIFY_HEAP | 1010 #ifdef VERIFY_HEAP |
| 1010 if (FLAG_verify_heap) { | 1011 if (FLAG_verify_heap) { |
| 1011 VerifySymbolTable(); | 1012 VerifyStringTable(); |
| 1012 } | 1013 } |
| 1013 #endif | 1014 #endif |
| 1014 | 1015 |
| 1015 return next_gc_likely_to_collect_more; | 1016 return next_gc_likely_to_collect_more; |
| 1016 } | 1017 } |
| 1017 | 1018 |
| 1018 | 1019 |
| 1019 void Heap::CallGCPrologueCallbacks(GCType gc_type) { | 1020 void Heap::CallGCPrologueCallbacks(GCType gc_type) { |
| 1020 if (gc_type == kGCTypeMarkSweepCompact && global_gc_prologue_callback_) { | 1021 if (gc_type == kGCTypeMarkSweepCompact && global_gc_prologue_callback_) { |
| 1021 global_gc_prologue_callback_(); | 1022 global_gc_prologue_callback_(); |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1618 } | 1619 } |
| 1619 | 1620 |
| 1620 // Update the head of the list of contexts. | 1621 // Update the head of the list of contexts. |
| 1621 native_contexts_list_ = head; | 1622 native_contexts_list_ = head; |
| 1622 } | 1623 } |
| 1623 | 1624 |
| 1624 | 1625 |
| 1625 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { | 1626 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { |
| 1626 AssertNoAllocation no_allocation; | 1627 AssertNoAllocation no_allocation; |
| 1627 | 1628 |
| 1628 // Both the external string table and the symbol table may contain | 1629 // Both the external string table and the string table may contain |
| 1629 // external strings, but neither lists them exhaustively, nor is the | 1630 // external strings, but neither lists them exhaustively, nor is the |
| 1630 // intersection set empty. Therefore we iterate over the external string | 1631 // intersection set empty. Therefore we iterate over the external string |
| 1631 // table first, ignoring symbols, and then over the symbol table. | 1632 // table first, ignoring internalized strings, and then over the |
| 1633 // internalized string table. |
| 1632 | 1634 |
| 1633 class ExternalStringTableVisitorAdapter : public ObjectVisitor { | 1635 class ExternalStringTableVisitorAdapter : public ObjectVisitor { |
| 1634 public: | 1636 public: |
| 1635 explicit ExternalStringTableVisitorAdapter( | 1637 explicit ExternalStringTableVisitorAdapter( |
| 1636 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} | 1638 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} |
| 1637 virtual void VisitPointers(Object** start, Object** end) { | 1639 virtual void VisitPointers(Object** start, Object** end) { |
| 1638 for (Object** p = start; p < end; p++) { | 1640 for (Object** p = start; p < end; p++) { |
| 1639 // Visit non-symbol external strings, | 1641 // Visit non-internalized external strings, |
| 1640 // since symbols are listed in the symbol table. | 1642 // since internalized strings are listed in the string table. |
| 1641 if (!(*p)->IsSymbol()) { | 1643 if (!(*p)->IsInternalizedString()) { |
| 1642 ASSERT((*p)->IsExternalString()); | 1644 ASSERT((*p)->IsExternalString()); |
| 1643 visitor_->VisitExternalString(Utils::ToLocal( | 1645 visitor_->VisitExternalString(Utils::ToLocal( |
| 1644 Handle<String>(String::cast(*p)))); | 1646 Handle<String>(String::cast(*p)))); |
| 1645 } | 1647 } |
| 1646 } | 1648 } |
| 1647 } | 1649 } |
| 1648 private: | 1650 private: |
| 1649 v8::ExternalResourceVisitor* visitor_; | 1651 v8::ExternalResourceVisitor* visitor_; |
| 1650 } external_string_table_visitor(visitor); | 1652 } external_string_table_visitor(visitor); |
| 1651 | 1653 |
| 1652 external_string_table_.Iterate(&external_string_table_visitor); | 1654 external_string_table_.Iterate(&external_string_table_visitor); |
| 1653 | 1655 |
| 1654 class SymbolTableVisitorAdapter : public ObjectVisitor { | 1656 class StringTableVisitorAdapter : public ObjectVisitor { |
| 1655 public: | 1657 public: |
| 1656 explicit SymbolTableVisitorAdapter( | 1658 explicit StringTableVisitorAdapter( |
| 1657 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} | 1659 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} |
| 1658 virtual void VisitPointers(Object** start, Object** end) { | 1660 virtual void VisitPointers(Object** start, Object** end) { |
| 1659 for (Object** p = start; p < end; p++) { | 1661 for (Object** p = start; p < end; p++) { |
| 1660 if ((*p)->IsExternalString()) { | 1662 if ((*p)->IsExternalString()) { |
| 1661 ASSERT((*p)->IsSymbol()); | 1663 ASSERT((*p)->IsInternalizedString()); |
| 1662 visitor_->VisitExternalString(Utils::ToLocal( | 1664 visitor_->VisitExternalString(Utils::ToLocal( |
| 1663 Handle<String>(String::cast(*p)))); | 1665 Handle<String>(String::cast(*p)))); |
| 1664 } | 1666 } |
| 1665 } | 1667 } |
| 1666 } | 1668 } |
| 1667 private: | 1669 private: |
| 1668 v8::ExternalResourceVisitor* visitor_; | 1670 v8::ExternalResourceVisitor* visitor_; |
| 1669 } symbol_table_visitor(visitor); | 1671 } string_table_visitor(visitor); |
| 1670 | 1672 |
| 1671 symbol_table()->IterateElements(&symbol_table_visitor); | 1673 string_table()->IterateElements(&string_table_visitor); |
| 1672 } | 1674 } |
| 1673 | 1675 |
| 1674 | 1676 |
| 1675 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { | 1677 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { |
| 1676 public: | 1678 public: |
| 1677 static inline void VisitPointer(Heap* heap, Object** p) { | 1679 static inline void VisitPointer(Heap* heap, Object** p) { |
| 1678 Object* object = *p; | 1680 Object* object = *p; |
| 1679 if (!heap->InNewSpace(object)) return; | 1681 if (!heap->InNewSpace(object)) return; |
| 1680 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 1682 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
| 1681 reinterpret_cast<HeapObject*>(object)); | 1683 reinterpret_cast<HeapObject*>(object)); |
| (...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2271 | 2273 |
| 2272 | 2274 |
| 2273 const Heap::StringTypeTable Heap::string_type_table[] = { | 2275 const Heap::StringTypeTable Heap::string_type_table[] = { |
| 2274 #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ | 2276 #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ |
| 2275 {type, size, k##camel_name##MapRootIndex}, | 2277 {type, size, k##camel_name##MapRootIndex}, |
| 2276 STRING_TYPE_LIST(STRING_TYPE_ELEMENT) | 2278 STRING_TYPE_LIST(STRING_TYPE_ELEMENT) |
| 2277 #undef STRING_TYPE_ELEMENT | 2279 #undef STRING_TYPE_ELEMENT |
| 2278 }; | 2280 }; |
| 2279 | 2281 |
| 2280 | 2282 |
| 2281 const Heap::ConstantSymbolTable Heap::constant_symbol_table[] = { | 2283 const Heap::ConstantStringTable Heap::constant_string_table[] = { |
| 2282 #define CONSTANT_SYMBOL_ELEMENT(name, contents) \ | 2284 #define CONSTANT_STRING_ELEMENT(name, contents) \ |
| 2283 {contents, k##name##RootIndex}, | 2285 {contents, k##name##RootIndex}, |
| 2284 SYMBOL_LIST(CONSTANT_SYMBOL_ELEMENT) | 2286 INTERNALIZED_STRING_LIST(CONSTANT_STRING_ELEMENT) |
| 2285 #undef CONSTANT_SYMBOL_ELEMENT | 2287 #undef CONSTANT_STRING_ELEMENT |
| 2286 }; | 2288 }; |
| 2287 | 2289 |
| 2288 | 2290 |
| 2289 const Heap::StructTable Heap::struct_table[] = { | 2291 const Heap::StructTable Heap::struct_table[] = { |
| 2290 #define STRUCT_TABLE_ELEMENT(NAME, Name, name) \ | 2292 #define STRUCT_TABLE_ELEMENT(NAME, Name, name) \ |
| 2291 { NAME##_TYPE, Name::kSize, k##Name##MapRootIndex }, | 2293 { NAME##_TYPE, Name::kSize, k##Name##MapRootIndex }, |
| 2292 STRUCT_LIST(STRUCT_TABLE_ELEMENT) | 2294 STRUCT_LIST(STRUCT_TABLE_ELEMENT) |
| 2293 #undef STRUCT_TABLE_ELEMENT | 2295 #undef STRUCT_TABLE_ELEMENT |
| 2294 }; | 2296 }; |
| 2295 | 2297 |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2738 if (!maybe_obj->ToObject(&obj)) return false; | 2740 if (!maybe_obj->ToObject(&obj)) return false; |
| 2739 } | 2741 } |
| 2740 set_nan_value(HeapNumber::cast(obj)); | 2742 set_nan_value(HeapNumber::cast(obj)); |
| 2741 | 2743 |
| 2742 { MaybeObject* maybe_obj = AllocateHeapNumber(V8_INFINITY, TENURED); | 2744 { MaybeObject* maybe_obj = AllocateHeapNumber(V8_INFINITY, TENURED); |
| 2743 if (!maybe_obj->ToObject(&obj)) return false; | 2745 if (!maybe_obj->ToObject(&obj)) return false; |
| 2744 } | 2746 } |
| 2745 set_infinity_value(HeapNumber::cast(obj)); | 2747 set_infinity_value(HeapNumber::cast(obj)); |
| 2746 | 2748 |
| 2747 // The hole has not been created yet, but we want to put something | 2749 // The hole has not been created yet, but we want to put something |
| 2748 // predictable in the gaps in the symbol table, so lets make that Smi zero. | 2750 // predictable in the gaps in the string table, so lets make that Smi zero. |
| 2749 set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0))); | 2751 set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0))); |
| 2750 | 2752 |
| 2751 // Allocate initial symbol table. | 2753 // Allocate initial string table. |
| 2752 { MaybeObject* maybe_obj = SymbolTable::Allocate(kInitialSymbolTableSize); | 2754 { MaybeObject* maybe_obj = StringTable::Allocate(kInitialStringTableSize); |
| 2753 if (!maybe_obj->ToObject(&obj)) return false; | 2755 if (!maybe_obj->ToObject(&obj)) return false; |
| 2754 } | 2756 } |
| 2755 // Don't use set_symbol_table() due to asserts. | 2757 // Don't use set_string_table() due to asserts. |
| 2756 roots_[kSymbolTableRootIndex] = obj; | 2758 roots_[kStringTableRootIndex] = obj; |
| 2757 | 2759 |
| 2758 // Finish initializing oddballs after creating symboltable. | 2760 // Finish initializing oddballs after creating the string table. |
| 2759 { MaybeObject* maybe_obj = | 2761 { MaybeObject* maybe_obj = |
| 2760 undefined_value()->Initialize("undefined", | 2762 undefined_value()->Initialize("undefined", |
| 2761 nan_value(), | 2763 nan_value(), |
| 2762 Oddball::kUndefined); | 2764 Oddball::kUndefined); |
| 2763 if (!maybe_obj->ToObject(&obj)) return false; | 2765 if (!maybe_obj->ToObject(&obj)) return false; |
| 2764 } | 2766 } |
| 2765 | 2767 |
| 2766 // Initialize the null_value. | 2768 // Initialize the null_value. |
| 2767 { MaybeObject* maybe_obj = | 2769 { MaybeObject* maybe_obj = |
| 2768 null_value()->Initialize("null", Smi::FromInt(0), Oddball::kNull); | 2770 null_value()->Initialize("null", Smi::FromInt(0), Oddball::kNull); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2804 } | 2806 } |
| 2805 set_no_interceptor_result_sentinel(obj); | 2807 set_no_interceptor_result_sentinel(obj); |
| 2806 | 2808 |
| 2807 { MaybeObject* maybe_obj = CreateOddball("termination_exception", | 2809 { MaybeObject* maybe_obj = CreateOddball("termination_exception", |
| 2808 Smi::FromInt(-3), | 2810 Smi::FromInt(-3), |
| 2809 Oddball::kOther); | 2811 Oddball::kOther); |
| 2810 if (!maybe_obj->ToObject(&obj)) return false; | 2812 if (!maybe_obj->ToObject(&obj)) return false; |
| 2811 } | 2813 } |
| 2812 set_termination_exception(obj); | 2814 set_termination_exception(obj); |
| 2813 | 2815 |
| 2814 // Allocate the empty string. | 2816 for (unsigned i = 0; i < ARRAY_SIZE(constant_string_table); i++) { |
| 2815 { MaybeObject* maybe_obj = AllocateRawOneByteString(0, TENURED); | |
| 2816 if (!maybe_obj->ToObject(&obj)) return false; | |
| 2817 } | |
| 2818 set_empty_string(String::cast(obj)); | |
| 2819 | |
| 2820 for (unsigned i = 0; i < ARRAY_SIZE(constant_symbol_table); i++) { | |
| 2821 { MaybeObject* maybe_obj = | 2817 { MaybeObject* maybe_obj = |
| 2822 LookupUtf8Symbol(constant_symbol_table[i].contents); | 2818 InternalizeUtf8String(constant_string_table[i].contents); |
| 2823 if (!maybe_obj->ToObject(&obj)) return false; | 2819 if (!maybe_obj->ToObject(&obj)) return false; |
| 2824 } | 2820 } |
| 2825 roots_[constant_symbol_table[i].index] = String::cast(obj); | 2821 roots_[constant_string_table[i].index] = String::cast(obj); |
| 2826 } | 2822 } |
| 2827 | 2823 |
| 2828 // Allocate the hidden symbol which is used to identify the hidden properties | 2824 // Allocate the hidden string which is used to identify the hidden properties |
| 2829 // in JSObjects. The hash code has a special value so that it will not match | 2825 // in JSObjects. The hash code has a special value so that it will not match |
| 2830 // the empty string when searching for the property. It cannot be part of the | 2826 // the empty string when searching for the property. It cannot be part of the |
| 2831 // loop above because it needs to be allocated manually with the special | 2827 // loop above because it needs to be allocated manually with the special |
| 2832 // hash code in place. The hash code for the hidden_symbol is zero to ensure | 2828 // hash code in place. The hash code for the hidden_string is zero to ensure |
| 2833 // that it will always be at the first entry in property descriptors. | 2829 // that it will always be at the first entry in property descriptors. |
| 2834 { MaybeObject* maybe_obj = | 2830 { MaybeObject* maybe_obj = AllocateOneByteInternalizedString( |
| 2835 AllocateOneByteSymbol(OneByteVector("", 0), String::kEmptyStringHash); | 2831 OneByteVector("", 0), String::kEmptyStringHash); |
| 2836 if (!maybe_obj->ToObject(&obj)) return false; | 2832 if (!maybe_obj->ToObject(&obj)) return false; |
| 2837 } | 2833 } |
| 2838 hidden_symbol_ = String::cast(obj); | 2834 hidden_string_ = String::cast(obj); |
| 2839 | 2835 |
| 2840 // Allocate the foreign for __proto__. | 2836 // Allocate the foreign for __proto__. |
| 2841 { MaybeObject* maybe_obj = | 2837 { MaybeObject* maybe_obj = |
| 2842 AllocateForeign((Address) &Accessors::ObjectPrototype); | 2838 AllocateForeign((Address) &Accessors::ObjectPrototype); |
| 2843 if (!maybe_obj->ToObject(&obj)) return false; | 2839 if (!maybe_obj->ToObject(&obj)) return false; |
| 2844 } | 2840 } |
| 2845 set_prototype_accessors(Foreign::cast(obj)); | 2841 set_prototype_accessors(Foreign::cast(obj)); |
| 2846 | 2842 |
| 2847 // Allocate the code_stubs dictionary. The initial size is set to avoid | 2843 // Allocate the code_stubs dictionary. The initial size is set to avoid |
| 2848 // expanding the dictionary during bootstrapping. | 2844 // expanding the dictionary during bootstrapping. |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2950 kCodeStubsRootIndex, | 2946 kCodeStubsRootIndex, |
| 2951 kNonMonomorphicCacheRootIndex, | 2947 kNonMonomorphicCacheRootIndex, |
| 2952 kPolymorphicCodeCacheRootIndex, | 2948 kPolymorphicCodeCacheRootIndex, |
| 2953 kLastScriptIdRootIndex, | 2949 kLastScriptIdRootIndex, |
| 2954 kEmptyScriptRootIndex, | 2950 kEmptyScriptRootIndex, |
| 2955 kRealStackLimitRootIndex, | 2951 kRealStackLimitRootIndex, |
| 2956 kArgumentsAdaptorDeoptPCOffsetRootIndex, | 2952 kArgumentsAdaptorDeoptPCOffsetRootIndex, |
| 2957 kConstructStubDeoptPCOffsetRootIndex, | 2953 kConstructStubDeoptPCOffsetRootIndex, |
| 2958 kGetterStubDeoptPCOffsetRootIndex, | 2954 kGetterStubDeoptPCOffsetRootIndex, |
| 2959 kSetterStubDeoptPCOffsetRootIndex, | 2955 kSetterStubDeoptPCOffsetRootIndex, |
| 2960 kSymbolTableRootIndex, | 2956 kStringTableRootIndex, |
| 2961 }; | 2957 }; |
| 2962 | 2958 |
| 2963 for (unsigned int i = 0; i < ARRAY_SIZE(writable_roots); i++) { | 2959 for (unsigned int i = 0; i < ARRAY_SIZE(writable_roots); i++) { |
| 2964 if (root_index == writable_roots[i]) | 2960 if (root_index == writable_roots[i]) |
| 2965 return true; | 2961 return true; |
| 2966 } | 2962 } |
| 2967 return false; | 2963 return false; |
| 2968 } | 2964 } |
| 2969 | 2965 |
| 2970 | 2966 |
| 2971 Object* RegExpResultsCache::Lookup(Heap* heap, | 2967 Object* RegExpResultsCache::Lookup(Heap* heap, |
| 2972 String* key_string, | 2968 String* key_string, |
| 2973 Object* key_pattern, | 2969 Object* key_pattern, |
| 2974 ResultsCacheType type) { | 2970 ResultsCacheType type) { |
| 2975 FixedArray* cache; | 2971 FixedArray* cache; |
| 2976 if (!key_string->IsSymbol()) return Smi::FromInt(0); | 2972 if (!key_string->IsInternalizedString()) return Smi::FromInt(0); |
| 2977 if (type == STRING_SPLIT_SUBSTRINGS) { | 2973 if (type == STRING_SPLIT_SUBSTRINGS) { |
| 2978 ASSERT(key_pattern->IsString()); | 2974 ASSERT(key_pattern->IsString()); |
| 2979 if (!key_pattern->IsSymbol()) return Smi::FromInt(0); | 2975 if (!key_pattern->IsInternalizedString()) return Smi::FromInt(0); |
| 2980 cache = heap->string_split_cache(); | 2976 cache = heap->string_split_cache(); |
| 2981 } else { | 2977 } else { |
| 2982 ASSERT(type == REGEXP_MULTIPLE_INDICES); | 2978 ASSERT(type == REGEXP_MULTIPLE_INDICES); |
| 2983 ASSERT(key_pattern->IsFixedArray()); | 2979 ASSERT(key_pattern->IsFixedArray()); |
| 2984 cache = heap->regexp_multiple_cache(); | 2980 cache = heap->regexp_multiple_cache(); |
| 2985 } | 2981 } |
| 2986 | 2982 |
| 2987 uint32_t hash = key_string->Hash(); | 2983 uint32_t hash = key_string->Hash(); |
| 2988 uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) & | 2984 uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) & |
| 2989 ~(kArrayEntriesPerCacheEntry - 1)); | 2985 ~(kArrayEntriesPerCacheEntry - 1)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3000 return Smi::FromInt(0); | 2996 return Smi::FromInt(0); |
| 3001 } | 2997 } |
| 3002 | 2998 |
| 3003 | 2999 |
| 3004 void RegExpResultsCache::Enter(Heap* heap, | 3000 void RegExpResultsCache::Enter(Heap* heap, |
| 3005 String* key_string, | 3001 String* key_string, |
| 3006 Object* key_pattern, | 3002 Object* key_pattern, |
| 3007 FixedArray* value_array, | 3003 FixedArray* value_array, |
| 3008 ResultsCacheType type) { | 3004 ResultsCacheType type) { |
| 3009 FixedArray* cache; | 3005 FixedArray* cache; |
| 3010 if (!key_string->IsSymbol()) return; | 3006 if (!key_string->IsInternalizedString()) return; |
| 3011 if (type == STRING_SPLIT_SUBSTRINGS) { | 3007 if (type == STRING_SPLIT_SUBSTRINGS) { |
| 3012 ASSERT(key_pattern->IsString()); | 3008 ASSERT(key_pattern->IsString()); |
| 3013 if (!key_pattern->IsSymbol()) return; | 3009 if (!key_pattern->IsInternalizedString()) return; |
| 3014 cache = heap->string_split_cache(); | 3010 cache = heap->string_split_cache(); |
| 3015 } else { | 3011 } else { |
| 3016 ASSERT(type == REGEXP_MULTIPLE_INDICES); | 3012 ASSERT(type == REGEXP_MULTIPLE_INDICES); |
| 3017 ASSERT(key_pattern->IsFixedArray()); | 3013 ASSERT(key_pattern->IsFixedArray()); |
| 3018 cache = heap->regexp_multiple_cache(); | 3014 cache = heap->regexp_multiple_cache(); |
| 3019 } | 3015 } |
| 3020 | 3016 |
| 3021 uint32_t hash = key_string->Hash(); | 3017 uint32_t hash = key_string->Hash(); |
| 3022 uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) & | 3018 uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) & |
| 3023 ~(kArrayEntriesPerCacheEntry - 1)); | 3019 ~(kArrayEntriesPerCacheEntry - 1)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3035 } else { | 3031 } else { |
| 3036 cache->set(index2 + kStringOffset, Smi::FromInt(0)); | 3032 cache->set(index2 + kStringOffset, Smi::FromInt(0)); |
| 3037 cache->set(index2 + kPatternOffset, Smi::FromInt(0)); | 3033 cache->set(index2 + kPatternOffset, Smi::FromInt(0)); |
| 3038 cache->set(index2 + kArrayOffset, Smi::FromInt(0)); | 3034 cache->set(index2 + kArrayOffset, Smi::FromInt(0)); |
| 3039 cache->set(index + kStringOffset, key_string); | 3035 cache->set(index + kStringOffset, key_string); |
| 3040 cache->set(index + kPatternOffset, key_pattern); | 3036 cache->set(index + kPatternOffset, key_pattern); |
| 3041 cache->set(index + kArrayOffset, value_array); | 3037 cache->set(index + kArrayOffset, value_array); |
| 3042 } | 3038 } |
| 3043 } | 3039 } |
| 3044 // If the array is a reasonably short list of substrings, convert it into a | 3040 // If the array is a reasonably short list of substrings, convert it into a |
| 3045 // list of symbols. | 3041 // list of internalized strings. |
| 3046 if (type == STRING_SPLIT_SUBSTRINGS && value_array->length() < 100) { | 3042 if (type == STRING_SPLIT_SUBSTRINGS && value_array->length() < 100) { |
| 3047 for (int i = 0; i < value_array->length(); i++) { | 3043 for (int i = 0; i < value_array->length(); i++) { |
| 3048 String* str = String::cast(value_array->get(i)); | 3044 String* str = String::cast(value_array->get(i)); |
| 3049 Object* symbol; | 3045 Object* internalized_str; |
| 3050 MaybeObject* maybe_symbol = heap->LookupSymbol(str); | 3046 MaybeObject* maybe_string = heap->InternalizeString(str); |
| 3051 if (maybe_symbol->ToObject(&symbol)) { | 3047 if (maybe_string->ToObject(&internalized_str)) { |
| 3052 value_array->set(i, symbol); | 3048 value_array->set(i, internalized_str); |
| 3053 } | 3049 } |
| 3054 } | 3050 } |
| 3055 } | 3051 } |
| 3056 // Convert backing store to a copy-on-write array. | 3052 // Convert backing store to a copy-on-write array. |
| 3057 value_array->set_map_no_write_barrier(heap->fixed_cow_array_map()); | 3053 value_array->set_map_no_write_barrier(heap->fixed_cow_array_map()); |
| 3058 } | 3054 } |
| 3059 | 3055 |
| 3060 | 3056 |
| 3061 void RegExpResultsCache::Clear(FixedArray* cache) { | 3057 void RegExpResultsCache::Clear(FixedArray* cache) { |
| 3062 for (int i = 0; i < kRegExpResultsCacheSize; i++) { | 3058 for (int i = 0; i < kRegExpResultsCacheSize; i++) { |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3275 | 3271 |
| 3276 // Set pointer fields. | 3272 // Set pointer fields. |
| 3277 share->set_name(name); | 3273 share->set_name(name); |
| 3278 Code* illegal = isolate_->builtins()->builtin(Builtins::kIllegal); | 3274 Code* illegal = isolate_->builtins()->builtin(Builtins::kIllegal); |
| 3279 share->set_code(illegal); | 3275 share->set_code(illegal); |
| 3280 share->ClearOptimizedCodeMap(); | 3276 share->ClearOptimizedCodeMap(); |
| 3281 share->set_scope_info(ScopeInfo::Empty()); | 3277 share->set_scope_info(ScopeInfo::Empty()); |
| 3282 Code* construct_stub = | 3278 Code* construct_stub = |
| 3283 isolate_->builtins()->builtin(Builtins::kJSConstructStubGeneric); | 3279 isolate_->builtins()->builtin(Builtins::kJSConstructStubGeneric); |
| 3284 share->set_construct_stub(construct_stub); | 3280 share->set_construct_stub(construct_stub); |
| 3285 share->set_instance_class_name(Object_symbol()); | 3281 share->set_instance_class_name(Object_string()); |
| 3286 share->set_function_data(undefined_value(), SKIP_WRITE_BARRIER); | 3282 share->set_function_data(undefined_value(), SKIP_WRITE_BARRIER); |
| 3287 share->set_script(undefined_value(), SKIP_WRITE_BARRIER); | 3283 share->set_script(undefined_value(), SKIP_WRITE_BARRIER); |
| 3288 share->set_debug_info(undefined_value(), SKIP_WRITE_BARRIER); | 3284 share->set_debug_info(undefined_value(), SKIP_WRITE_BARRIER); |
| 3289 share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER); | 3285 share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER); |
| 3290 share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER); | 3286 share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER); |
| 3291 share->set_this_property_assignments(undefined_value(), SKIP_WRITE_BARRIER); | 3287 share->set_this_property_assignments(undefined_value(), SKIP_WRITE_BARRIER); |
| 3292 share->set_ast_node_count(0); | 3288 share->set_ast_node_count(0); |
| 3293 share->set_stress_deopt_counter(FLAG_deopt_every_n_times); | 3289 share->set_stress_deopt_counter(FLAG_deopt_every_n_times); |
| 3294 share->set_counters(0); | 3290 share->set_counters(0); |
| 3295 | 3291 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3341 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { | 3337 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { |
| 3342 // This makes uses of the the unsigned wraparound. | 3338 // This makes uses of the the unsigned wraparound. |
| 3343 return character - from <= to - from; | 3339 return character - from <= to - from; |
| 3344 } | 3340 } |
| 3345 | 3341 |
| 3346 | 3342 |
| 3347 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString( | 3343 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString( |
| 3348 Heap* heap, | 3344 Heap* heap, |
| 3349 uint16_t c1, | 3345 uint16_t c1, |
| 3350 uint16_t c2) { | 3346 uint16_t c2) { |
| 3351 String* symbol; | 3347 String* result; |
| 3352 // Numeric strings have a different hash algorithm not known by | 3348 // Numeric strings have a different hash algorithm not known by |
| 3353 // LookupTwoCharsSymbolIfExists, so we skip this step for such strings. | 3349 // LookupTwoCharsStringIfExists, so we skip this step for such strings. |
| 3354 if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) && | 3350 if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) && |
| 3355 heap->symbol_table()->LookupTwoCharsSymbolIfExists(c1, c2, &symbol)) { | 3351 heap->string_table()->LookupTwoCharsStringIfExists(c1, c2, &result)) { |
| 3356 return symbol; | 3352 return result; |
| 3357 // Now we know the length is 2, we might as well make use of that fact | 3353 // Now we know the length is 2, we might as well make use of that fact |
| 3358 // when building the new string. | 3354 // when building the new string. |
| 3359 } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) { | 3355 } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) { |
| 3360 // We can do this. | 3356 // We can do this. |
| 3361 ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this. | 3357 ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this. |
| 3362 Object* result; | 3358 Object* result; |
| 3363 { MaybeObject* maybe_result = heap->AllocateRawOneByteString(2); | 3359 { MaybeObject* maybe_result = heap->AllocateRawOneByteString(2); |
| 3364 if (!maybe_result->ToObject(&result)) return maybe_result; | 3360 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3365 } | 3361 } |
| 3366 uint8_t* dest = SeqOneByteString::cast(result)->GetChars(); | 3362 uint8_t* dest = SeqOneByteString::cast(result)->GetChars(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3387 } | 3383 } |
| 3388 | 3384 |
| 3389 int second_length = second->length(); | 3385 int second_length = second->length(); |
| 3390 if (second_length == 0) { | 3386 if (second_length == 0) { |
| 3391 return first; | 3387 return first; |
| 3392 } | 3388 } |
| 3393 | 3389 |
| 3394 int length = first_length + second_length; | 3390 int length = first_length + second_length; |
| 3395 | 3391 |
| 3396 // Optimization for 2-byte strings often used as keys in a decompression | 3392 // Optimization for 2-byte strings often used as keys in a decompression |
| 3397 // dictionary. Check whether we already have the string in the symbol | 3393 // dictionary. Check whether we already have the string in the string |
| 3398 // table to prevent creation of many unneccesary strings. | 3394 // table to prevent creation of many unneccesary strings. |
| 3399 if (length == 2) { | 3395 if (length == 2) { |
| 3400 uint16_t c1 = first->Get(0); | 3396 uint16_t c1 = first->Get(0); |
| 3401 uint16_t c2 = second->Get(0); | 3397 uint16_t c2 = second->Get(0); |
| 3402 return MakeOrFindTwoCharacterString(this, c1, c2); | 3398 return MakeOrFindTwoCharacterString(this, c1, c2); |
| 3403 } | 3399 } |
| 3404 | 3400 |
| 3405 bool first_is_one_byte = first->IsOneByteRepresentation(); | 3401 bool first_is_one_byte = first->IsOneByteRepresentation(); |
| 3406 bool second_is_one_byte = second->IsOneByteRepresentation(); | 3402 bool second_is_one_byte = second->IsOneByteRepresentation(); |
| 3407 bool is_one_byte = first_is_one_byte && second_is_one_byte; | 3403 bool is_one_byte = first_is_one_byte && second_is_one_byte; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3502 int start, | 3498 int start, |
| 3503 int end, | 3499 int end, |
| 3504 PretenureFlag pretenure) { | 3500 PretenureFlag pretenure) { |
| 3505 int length = end - start; | 3501 int length = end - start; |
| 3506 if (length <= 0) { | 3502 if (length <= 0) { |
| 3507 return empty_string(); | 3503 return empty_string(); |
| 3508 } else if (length == 1) { | 3504 } else if (length == 1) { |
| 3509 return LookupSingleCharacterStringFromCode(buffer->Get(start)); | 3505 return LookupSingleCharacterStringFromCode(buffer->Get(start)); |
| 3510 } else if (length == 2) { | 3506 } else if (length == 2) { |
| 3511 // Optimization for 2-byte strings often used as keys in a decompression | 3507 // Optimization for 2-byte strings often used as keys in a decompression |
| 3512 // dictionary. Check whether we already have the string in the symbol | 3508 // dictionary. Check whether we already have the string in the string |
| 3513 // table to prevent creation of many unneccesary strings. | 3509 // table to prevent creation of many unnecessary strings. |
| 3514 uint16_t c1 = buffer->Get(start); | 3510 uint16_t c1 = buffer->Get(start); |
| 3515 uint16_t c2 = buffer->Get(start + 1); | 3511 uint16_t c2 = buffer->Get(start + 1); |
| 3516 return MakeOrFindTwoCharacterString(this, c1, c2); | 3512 return MakeOrFindTwoCharacterString(this, c1, c2); |
| 3517 } | 3513 } |
| 3518 | 3514 |
| 3519 // Make an attempt to flatten the buffer to reduce access time. | 3515 // Make an attempt to flatten the buffer to reduce access time. |
| 3520 buffer = buffer->TryFlattenGetString(); | 3516 buffer = buffer->TryFlattenGetString(); |
| 3521 | 3517 |
| 3522 if (!FLAG_string_slices || | 3518 if (!FLAG_string_slices || |
| 3523 !buffer->IsFlat() || | 3519 !buffer->IsFlat() || |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3648 | 3644 |
| 3649 MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { | 3645 MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { |
| 3650 if (code <= String::kMaxOneByteCharCode) { | 3646 if (code <= String::kMaxOneByteCharCode) { |
| 3651 Object* value = single_character_string_cache()->get(code); | 3647 Object* value = single_character_string_cache()->get(code); |
| 3652 if (value != undefined_value()) return value; | 3648 if (value != undefined_value()) return value; |
| 3653 | 3649 |
| 3654 uint8_t buffer[1]; | 3650 uint8_t buffer[1]; |
| 3655 buffer[0] = static_cast<uint8_t>(code); | 3651 buffer[0] = static_cast<uint8_t>(code); |
| 3656 Object* result; | 3652 Object* result; |
| 3657 MaybeObject* maybe_result = | 3653 MaybeObject* maybe_result = |
| 3658 LookupOneByteSymbol(Vector<const uint8_t>(buffer, 1)); | 3654 InternalizeOneByteString(Vector<const uint8_t>(buffer, 1)); |
| 3659 | 3655 |
| 3660 if (!maybe_result->ToObject(&result)) return maybe_result; | 3656 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3661 single_character_string_cache()->set(code, result); | 3657 single_character_string_cache()->set(code, result); |
| 3662 return result; | 3658 return result; |
| 3663 } | 3659 } |
| 3664 | 3660 |
| 3665 Object* result; | 3661 Object* result; |
| 3666 { MaybeObject* maybe_result = AllocateRawTwoByteString(1); | 3662 { MaybeObject* maybe_result = AllocateRawTwoByteString(1); |
| 3667 if (!maybe_result->ToObject(&result)) return maybe_result; | 3663 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3668 } | 3664 } |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3957 if (!maybe_map->To(&new_map)) return maybe_map; | 3953 if (!maybe_map->To(&new_map)) return maybe_map; |
| 3958 | 3954 |
| 3959 Object* prototype; | 3955 Object* prototype; |
| 3960 MaybeObject* maybe_prototype = AllocateJSObjectFromMap(new_map); | 3956 MaybeObject* maybe_prototype = AllocateJSObjectFromMap(new_map); |
| 3961 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; | 3957 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; |
| 3962 | 3958 |
| 3963 // When creating the prototype for the function we must set its | 3959 // When creating the prototype for the function we must set its |
| 3964 // constructor to the function. | 3960 // constructor to the function. |
| 3965 MaybeObject* maybe_failure = | 3961 MaybeObject* maybe_failure = |
| 3966 JSObject::cast(prototype)->SetLocalPropertyIgnoreAttributes( | 3962 JSObject::cast(prototype)->SetLocalPropertyIgnoreAttributes( |
| 3967 constructor_symbol(), function, DONT_ENUM); | 3963 constructor_string(), function, DONT_ENUM); |
| 3968 if (maybe_failure->IsFailure()) return maybe_failure; | 3964 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3969 | 3965 |
| 3970 return prototype; | 3966 return prototype; |
| 3971 } | 3967 } |
| 3972 | 3968 |
| 3973 | 3969 |
| 3974 MaybeObject* Heap::AllocateFunction(Map* function_map, | 3970 MaybeObject* Heap::AllocateFunction(Map* function_map, |
| 3975 SharedFunctionInfo* shared, | 3971 SharedFunctionInfo* shared, |
| 3976 Object* prototype, | 3972 Object* prototype, |
| 3977 PretenureFlag pretenure) { | 3973 PretenureFlag pretenure) { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4096 // Inline constructor can only handle inobject properties. | 4092 // Inline constructor can only handle inobject properties. |
| 4097 fun->shared()->ForbidInlineConstructor(); | 4093 fun->shared()->ForbidInlineConstructor(); |
| 4098 } else { | 4094 } else { |
| 4099 DescriptorArray* descriptors; | 4095 DescriptorArray* descriptors; |
| 4100 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(count); | 4096 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(count); |
| 4101 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 4097 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
| 4102 | 4098 |
| 4103 DescriptorArray::WhitenessWitness witness(descriptors); | 4099 DescriptorArray::WhitenessWitness witness(descriptors); |
| 4104 for (int i = 0; i < count; i++) { | 4100 for (int i = 0; i < count; i++) { |
| 4105 String* name = fun->shared()->GetThisPropertyAssignmentName(i); | 4101 String* name = fun->shared()->GetThisPropertyAssignmentName(i); |
| 4106 ASSERT(name->IsSymbol()); | 4102 ASSERT(name->IsInternalizedString()); |
| 4107 FieldDescriptor field(name, i, NONE, i + 1); | 4103 FieldDescriptor field(name, i, NONE, i + 1); |
| 4108 descriptors->Set(i, &field, witness); | 4104 descriptors->Set(i, &field, witness); |
| 4109 } | 4105 } |
| 4110 descriptors->Sort(); | 4106 descriptors->Sort(); |
| 4111 | 4107 |
| 4112 // The descriptors may contain duplicates because the compiler does not | 4108 // The descriptors may contain duplicates because the compiler does not |
| 4113 // guarantee the uniqueness of property names (it would have required | 4109 // guarantee the uniqueness of property names (it would have required |
| 4114 // quadratic time). Once the descriptors are sorted we can check for | 4110 // quadratic time). Once the descriptors are sorted we can check for |
| 4115 // duplicates in linear time. | 4111 // duplicates in linear time. |
| 4116 if (HasDuplicates(descriptors)) { | 4112 if (HasDuplicates(descriptors)) { |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4526 // Allocate the backing storage for the properties. | 4522 // Allocate the backing storage for the properties. |
| 4527 int prop_size = map->unused_property_fields() - map->inobject_properties(); | 4523 int prop_size = map->unused_property_fields() - map->inobject_properties(); |
| 4528 Object* properties; | 4524 Object* properties; |
| 4529 maybe = AllocateFixedArray(prop_size, TENURED); | 4525 maybe = AllocateFixedArray(prop_size, TENURED); |
| 4530 if (!maybe->ToObject(&properties)) return maybe; | 4526 if (!maybe->ToObject(&properties)) return maybe; |
| 4531 | 4527 |
| 4532 // Functions require some allocation, which might fail here. | 4528 // Functions require some allocation, which might fail here. |
| 4533 SharedFunctionInfo* shared = NULL; | 4529 SharedFunctionInfo* shared = NULL; |
| 4534 if (type == JS_FUNCTION_TYPE) { | 4530 if (type == JS_FUNCTION_TYPE) { |
| 4535 String* name; | 4531 String* name; |
| 4536 maybe = LookupOneByteSymbol(STATIC_ASCII_VECTOR("<freezing call trap>")); | 4532 maybe = |
| 4533 InternalizeOneByteString(STATIC_ASCII_VECTOR("<freezing call trap>")); |
| 4537 if (!maybe->To<String>(&name)) return maybe; | 4534 if (!maybe->To<String>(&name)) return maybe; |
| 4538 maybe = AllocateSharedFunctionInfo(name); | 4535 maybe = AllocateSharedFunctionInfo(name); |
| 4539 if (!maybe->To<SharedFunctionInfo>(&shared)) return maybe; | 4536 if (!maybe->To<SharedFunctionInfo>(&shared)) return maybe; |
| 4540 } | 4537 } |
| 4541 | 4538 |
| 4542 // Because of possible retries of this function after failure, | 4539 // Because of possible retries of this function after failure, |
| 4543 // we must NOT fail after this point, where we have changed the type! | 4540 // we must NOT fail after this point, where we have changed the type! |
| 4544 | 4541 |
| 4545 // Reset the map for the object. | 4542 // Reset the map for the object. |
| 4546 object->set_map(map); | 4543 object->set_map(map); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4660 CopyChars(SeqOneByteString::cast(result)->GetChars(), start, length); | 4657 CopyChars(SeqOneByteString::cast(result)->GetChars(), start, length); |
| 4661 } else { // It's not a one byte string. | 4658 } else { // It's not a one byte string. |
| 4662 MaybeObject* maybe_result = AllocateRawTwoByteString(length, pretenure); | 4659 MaybeObject* maybe_result = AllocateRawTwoByteString(length, pretenure); |
| 4663 if (!maybe_result->ToObject(&result)) return maybe_result; | 4660 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 4664 CopyChars(SeqTwoByteString::cast(result)->GetChars(), start, length); | 4661 CopyChars(SeqTwoByteString::cast(result)->GetChars(), start, length); |
| 4665 } | 4662 } |
| 4666 return result; | 4663 return result; |
| 4667 } | 4664 } |
| 4668 | 4665 |
| 4669 | 4666 |
| 4670 Map* Heap::SymbolMapForString(String* string) { | 4667 Map* Heap::InternalizedStringMapForString(String* string) { |
| 4671 // If the string is in new space it cannot be used as a symbol. | 4668 // If the string is in new space it cannot be used as internalized. |
| 4672 if (InNewSpace(string)) return NULL; | 4669 if (InNewSpace(string)) return NULL; |
| 4673 | 4670 |
| 4674 // Find the corresponding symbol map for strings. | 4671 // Find the corresponding internalized string map for strings. |
| 4675 switch (string->map()->instance_type()) { | 4672 switch (string->map()->instance_type()) { |
| 4676 case STRING_TYPE: return symbol_map(); | 4673 case STRING_TYPE: return internalized_string_map(); |
| 4677 case ASCII_STRING_TYPE: return ascii_symbol_map(); | 4674 case ASCII_STRING_TYPE: return ascii_internalized_string_map(); |
| 4678 case CONS_STRING_TYPE: return cons_symbol_map(); | 4675 case CONS_STRING_TYPE: return cons_internalized_string_map(); |
| 4679 case CONS_ASCII_STRING_TYPE: return cons_ascii_symbol_map(); | 4676 case CONS_ASCII_STRING_TYPE: return cons_ascii_internalized_string_map(); |
| 4680 case EXTERNAL_STRING_TYPE: return external_symbol_map(); | 4677 case EXTERNAL_STRING_TYPE: return external_internalized_string_map(); |
| 4681 case EXTERNAL_ASCII_STRING_TYPE: return external_ascii_symbol_map(); | 4678 case EXTERNAL_ASCII_STRING_TYPE: |
| 4679 return external_ascii_internalized_string_map(); |
| 4682 case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE: | 4680 case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE: |
| 4683 return external_symbol_with_ascii_data_map(); | 4681 return external_internalized_string_with_ascii_data_map(); |
| 4684 case SHORT_EXTERNAL_STRING_TYPE: return short_external_symbol_map(); | 4682 case SHORT_EXTERNAL_STRING_TYPE: |
| 4683 return short_external_internalized_string_map(); |
| 4685 case SHORT_EXTERNAL_ASCII_STRING_TYPE: | 4684 case SHORT_EXTERNAL_ASCII_STRING_TYPE: |
| 4686 return short_external_ascii_symbol_map(); | 4685 return short_external_ascii_internalized_string_map(); |
| 4687 case SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE: | 4686 case SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE: |
| 4688 return short_external_symbol_with_ascii_data_map(); | 4687 return short_external_internalized_string_with_ascii_data_map(); |
| 4689 default: return NULL; // No match found. | 4688 default: return NULL; // No match found. |
| 4690 } | 4689 } |
| 4691 } | 4690 } |
| 4692 | 4691 |
| 4693 | 4692 |
| 4694 static inline void WriteOneByteData(Vector<const char> vector, | 4693 static inline void WriteOneByteData(Vector<const char> vector, |
| 4695 uint8_t* chars, | 4694 uint8_t* chars, |
| 4696 int len) { | 4695 int len) { |
| 4697 // Only works for ascii. | 4696 // Only works for ascii. |
| 4698 ASSERT(vector.length() == len); | 4697 ASSERT(vector.length() == len); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4732 String::WriteToFlat(s, chars, 0, len); | 4731 String::WriteToFlat(s, chars, 0, len); |
| 4733 } | 4732 } |
| 4734 | 4733 |
| 4735 static inline void WriteTwoByteData(String* s, uint16_t* chars, int len) { | 4734 static inline void WriteTwoByteData(String* s, uint16_t* chars, int len) { |
| 4736 ASSERT(s->length() == len); | 4735 ASSERT(s->length() == len); |
| 4737 String::WriteToFlat(s, chars, 0, len); | 4736 String::WriteToFlat(s, chars, 0, len); |
| 4738 } | 4737 } |
| 4739 | 4738 |
| 4740 | 4739 |
| 4741 template<bool is_one_byte, typename T> | 4740 template<bool is_one_byte, typename T> |
| 4742 MaybeObject* Heap::AllocateInternalSymbol(T t, | 4741 MaybeObject* Heap::AllocateInternalizedStringImpl( |
| 4743 int chars, | 4742 T t, int chars, uint32_t hash_field) { |
| 4744 uint32_t hash_field) { | |
| 4745 ASSERT(chars >= 0); | 4743 ASSERT(chars >= 0); |
| 4746 // Compute map and object size. | 4744 // Compute map and object size. |
| 4747 int size; | 4745 int size; |
| 4748 Map* map; | 4746 Map* map; |
| 4749 | 4747 |
| 4750 if (is_one_byte) { | 4748 if (is_one_byte) { |
| 4751 if (chars > SeqOneByteString::kMaxLength) { | 4749 if (chars > SeqOneByteString::kMaxLength) { |
| 4752 return Failure::OutOfMemoryException(0x9); | 4750 return Failure::OutOfMemoryException(0x9); |
| 4753 } | 4751 } |
| 4754 map = ascii_symbol_map(); | 4752 map = ascii_internalized_string_map(); |
| 4755 size = SeqOneByteString::SizeFor(chars); | 4753 size = SeqOneByteString::SizeFor(chars); |
| 4756 } else { | 4754 } else { |
| 4757 if (chars > SeqTwoByteString::kMaxLength) { | 4755 if (chars > SeqTwoByteString::kMaxLength) { |
| 4758 return Failure::OutOfMemoryException(0xa); | 4756 return Failure::OutOfMemoryException(0xa); |
| 4759 } | 4757 } |
| 4760 map = symbol_map(); | 4758 map = internalized_string_map(); |
| 4761 size = SeqTwoByteString::SizeFor(chars); | 4759 size = SeqTwoByteString::SizeFor(chars); |
| 4762 } | 4760 } |
| 4763 | 4761 |
| 4764 // Allocate string. | 4762 // Allocate string. |
| 4765 Object* result; | 4763 Object* result; |
| 4766 { MaybeObject* maybe_result = (size > Page::kMaxNonCodeHeapObjectSize) | 4764 { MaybeObject* maybe_result = (size > Page::kMaxNonCodeHeapObjectSize) |
| 4767 ? lo_space_->AllocateRaw(size, NOT_EXECUTABLE) | 4765 ? lo_space_->AllocateRaw(size, NOT_EXECUTABLE) |
| 4768 : old_data_space_->AllocateRaw(size); | 4766 : old_data_space_->AllocateRaw(size); |
| 4769 if (!maybe_result->ToObject(&result)) return maybe_result; | 4767 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 4770 } | 4768 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4781 WriteOneByteData(t, SeqOneByteString::cast(answer)->GetChars(), chars); | 4779 WriteOneByteData(t, SeqOneByteString::cast(answer)->GetChars(), chars); |
| 4782 } else { | 4780 } else { |
| 4783 WriteTwoByteData(t, SeqTwoByteString::cast(answer)->GetChars(), chars); | 4781 WriteTwoByteData(t, SeqTwoByteString::cast(answer)->GetChars(), chars); |
| 4784 } | 4782 } |
| 4785 return answer; | 4783 return answer; |
| 4786 } | 4784 } |
| 4787 | 4785 |
| 4788 | 4786 |
| 4789 // Need explicit instantiations. | 4787 // Need explicit instantiations. |
| 4790 template | 4788 template |
| 4791 MaybeObject* Heap::AllocateInternalSymbol<true>(String*, int, uint32_t); | 4789 MaybeObject* Heap::AllocateInternalizedStringImpl<true>(String*, int, uint32_t); |
| 4792 template | 4790 template |
| 4793 MaybeObject* Heap::AllocateInternalSymbol<false>(String*, int, uint32_t); | 4791 MaybeObject* Heap::AllocateInternalizedStringImpl<false>( |
| 4792 String*, int, uint32_t); |
| 4794 template | 4793 template |
| 4795 MaybeObject* Heap::AllocateInternalSymbol<false>(Vector<const char>, | 4794 MaybeObject* Heap::AllocateInternalizedStringImpl<false>( |
| 4796 int, | 4795 Vector<const char>, int, uint32_t); |
| 4797 uint32_t); | |
| 4798 | 4796 |
| 4799 | 4797 |
| 4800 MaybeObject* Heap::AllocateRawOneByteString(int length, | 4798 MaybeObject* Heap::AllocateRawOneByteString(int length, |
| 4801 PretenureFlag pretenure) { | 4799 PretenureFlag pretenure) { |
| 4802 if (length < 0 || length > SeqOneByteString::kMaxLength) { | 4800 if (length < 0 || length > SeqOneByteString::kMaxLength) { |
| 4803 return Failure::OutOfMemoryException(0xb); | 4801 return Failure::OutOfMemoryException(0xb); |
| 4804 } | 4802 } |
| 4805 | 4803 |
| 4806 int size = SeqOneByteString::SizeFor(length); | 4804 int size = SeqOneByteString::SizeFor(length); |
| 4807 ASSERT(size <= SeqOneByteString::kMaxSize); | 4805 ASSERT(size <= SeqOneByteString::kMaxSize); |
| (...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5658 VerifyPointersVisitor no_dirty_regions_visitor; | 5656 VerifyPointersVisitor no_dirty_regions_visitor; |
| 5659 old_data_space_->Verify(&no_dirty_regions_visitor); | 5657 old_data_space_->Verify(&no_dirty_regions_visitor); |
| 5660 code_space_->Verify(&no_dirty_regions_visitor); | 5658 code_space_->Verify(&no_dirty_regions_visitor); |
| 5661 cell_space_->Verify(&no_dirty_regions_visitor); | 5659 cell_space_->Verify(&no_dirty_regions_visitor); |
| 5662 | 5660 |
| 5663 lo_space_->Verify(); | 5661 lo_space_->Verify(); |
| 5664 } | 5662 } |
| 5665 #endif | 5663 #endif |
| 5666 | 5664 |
| 5667 | 5665 |
| 5668 MaybeObject* Heap::LookupUtf8Symbol(Vector<const char> string) { | 5666 MaybeObject* Heap::InternalizeUtf8String(Vector<const char> string) { |
| 5669 Object* symbol = NULL; | 5667 Object* result = NULL; |
| 5670 Object* new_table; | 5668 Object* new_table; |
| 5671 { MaybeObject* maybe_new_table = | 5669 { MaybeObject* maybe_new_table = |
| 5672 symbol_table()->LookupUtf8Symbol(string, &symbol); | 5670 string_table()->LookupUtf8String(string, &result); |
| 5673 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; | 5671 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; |
| 5674 } | 5672 } |
| 5675 // Can't use set_symbol_table because SymbolTable::cast knows that | 5673 // Can't use set_string_table because StringTable::cast knows that |
| 5676 // SymbolTable is a singleton and checks for identity. | 5674 // StringTable is a singleton and checks for identity. |
| 5677 roots_[kSymbolTableRootIndex] = new_table; | 5675 roots_[kStringTableRootIndex] = new_table; |
| 5678 ASSERT(symbol != NULL); | 5676 ASSERT(result != NULL); |
| 5679 return symbol; | 5677 return result; |
| 5680 } | 5678 } |
| 5681 | 5679 |
| 5682 | 5680 |
| 5683 MaybeObject* Heap::LookupOneByteSymbol(Vector<const uint8_t> string) { | 5681 MaybeObject* Heap::InternalizeOneByteString(Vector<const uint8_t> string) { |
| 5684 Object* symbol = NULL; | 5682 Object* result = NULL; |
| 5685 Object* new_table; | 5683 Object* new_table; |
| 5686 { MaybeObject* maybe_new_table = | 5684 { MaybeObject* maybe_new_table = |
| 5687 symbol_table()->LookupOneByteSymbol(string, &symbol); | 5685 string_table()->LookupOneByteString(string, &result); |
| 5688 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; | 5686 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; |
| 5689 } | 5687 } |
| 5690 // Can't use set_symbol_table because SymbolTable::cast knows that | 5688 // Can't use set_string_table because StringTable::cast knows that |
| 5691 // SymbolTable is a singleton and checks for identity. | 5689 // StringTable is a singleton and checks for identity. |
| 5692 roots_[kSymbolTableRootIndex] = new_table; | 5690 roots_[kStringTableRootIndex] = new_table; |
| 5693 ASSERT(symbol != NULL); | 5691 ASSERT(result != NULL); |
| 5694 return symbol; | 5692 return result; |
| 5695 } | 5693 } |
| 5696 | 5694 |
| 5697 | 5695 |
| 5698 MaybeObject* Heap::LookupOneByteSymbol(Handle<SeqOneByteString> string, | 5696 MaybeObject* Heap::InternalizeOneByteString(Handle<SeqOneByteString> string, |
| 5699 int from, | 5697 int from, |
| 5700 int length) { | 5698 int length) { |
| 5701 Object* symbol = NULL; | 5699 Object* result = NULL; |
| 5702 Object* new_table; | 5700 Object* new_table; |
| 5703 { MaybeObject* maybe_new_table = | 5701 { MaybeObject* maybe_new_table = |
| 5704 symbol_table()->LookupSubStringOneByteSymbol(string, | 5702 string_table()->LookupSubStringOneByteString(string, |
| 5705 from, | 5703 from, |
| 5706 length, | 5704 length, |
| 5707 &symbol); | 5705 &result); |
| 5708 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; | 5706 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; |
| 5709 } | 5707 } |
| 5710 // Can't use set_symbol_table because SymbolTable::cast knows that | 5708 // Can't use set_string_table because StringTable::cast knows that |
| 5711 // SymbolTable is a singleton and checks for identity. | 5709 // StringTable is a singleton and checks for identity. |
| 5712 roots_[kSymbolTableRootIndex] = new_table; | 5710 roots_[kStringTableRootIndex] = new_table; |
| 5713 ASSERT(symbol != NULL); | 5711 ASSERT(result != NULL); |
| 5714 return symbol; | 5712 return result; |
| 5715 } | 5713 } |
| 5716 | 5714 |
| 5717 | 5715 |
| 5718 MaybeObject* Heap::LookupTwoByteSymbol(Vector<const uc16> string) { | 5716 MaybeObject* Heap::InternalizeTwoByteString(Vector<const uc16> string) { |
| 5719 Object* symbol = NULL; | 5717 Object* result = NULL; |
| 5720 Object* new_table; | 5718 Object* new_table; |
| 5721 { MaybeObject* maybe_new_table = | 5719 { MaybeObject* maybe_new_table = |
| 5722 symbol_table()->LookupTwoByteSymbol(string, &symbol); | 5720 string_table()->LookupTwoByteString(string, &result); |
| 5723 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; | 5721 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; |
| 5724 } | 5722 } |
| 5725 // Can't use set_symbol_table because SymbolTable::cast knows that | 5723 // Can't use set_string_table because StringTable::cast knows that |
| 5726 // SymbolTable is a singleton and checks for identity. | 5724 // StringTable is a singleton and checks for identity. |
| 5727 roots_[kSymbolTableRootIndex] = new_table; | 5725 roots_[kStringTableRootIndex] = new_table; |
| 5728 ASSERT(symbol != NULL); | 5726 ASSERT(result != NULL); |
| 5729 return symbol; | 5727 return result; |
| 5730 } | 5728 } |
| 5731 | 5729 |
| 5732 | 5730 |
| 5733 MaybeObject* Heap::LookupSymbol(String* string) { | 5731 MaybeObject* Heap::InternalizeString(String* string) { |
| 5734 if (string->IsSymbol()) return string; | 5732 if (string->IsInternalizedString()) return string; |
| 5735 Object* symbol = NULL; | 5733 Object* result = NULL; |
| 5736 Object* new_table; | 5734 Object* new_table; |
| 5737 { MaybeObject* maybe_new_table = | 5735 { MaybeObject* maybe_new_table = |
| 5738 symbol_table()->LookupString(string, &symbol); | 5736 string_table()->LookupString(string, &result); |
| 5739 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; | 5737 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; |
| 5740 } | 5738 } |
| 5741 // Can't use set_symbol_table because SymbolTable::cast knows that | 5739 // Can't use set_string_table because StringTable::cast knows that |
| 5742 // SymbolTable is a singleton and checks for identity. | 5740 // StringTable is a singleton and checks for identity. |
| 5743 roots_[kSymbolTableRootIndex] = new_table; | 5741 roots_[kStringTableRootIndex] = new_table; |
| 5744 ASSERT(symbol != NULL); | 5742 ASSERT(result != NULL); |
| 5745 return symbol; | 5743 return result; |
| 5746 } | 5744 } |
| 5747 | 5745 |
| 5748 | 5746 |
| 5749 bool Heap::LookupSymbolIfExists(String* string, String** symbol) { | 5747 bool Heap::InternalizeStringIfExists(String* string, String** result) { |
| 5750 if (string->IsSymbol()) { | 5748 if (string->IsInternalizedString()) { |
| 5751 *symbol = string; | 5749 *result = string; |
| 5752 return true; | 5750 return true; |
| 5753 } | 5751 } |
| 5754 return symbol_table()->LookupSymbolIfExists(string, symbol); | 5752 return string_table()->LookupStringIfExists(string, result); |
| 5755 } | 5753 } |
| 5756 | 5754 |
| 5757 | 5755 |
| 5758 void Heap::ZapFromSpace() { | 5756 void Heap::ZapFromSpace() { |
| 5759 NewSpacePageIterator it(new_space_.FromSpaceStart(), | 5757 NewSpacePageIterator it(new_space_.FromSpaceStart(), |
| 5760 new_space_.FromSpaceEnd()); | 5758 new_space_.FromSpaceEnd()); |
| 5761 while (it.has_next()) { | 5759 while (it.has_next()) { |
| 5762 NewSpacePage* page = it.next(); | 5760 NewSpacePage* page = it.next(); |
| 5763 for (Address cursor = page->area_start(), limit = page->area_end(); | 5761 for (Address cursor = page->area_start(), limit = page->area_end(); |
| 5764 cursor < limit; | 5762 cursor < limit; |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5972 #endif | 5970 #endif |
| 5973 | 5971 |
| 5974 | 5972 |
| 5975 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) { | 5973 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) { |
| 5976 IterateStrongRoots(v, mode); | 5974 IterateStrongRoots(v, mode); |
| 5977 IterateWeakRoots(v, mode); | 5975 IterateWeakRoots(v, mode); |
| 5978 } | 5976 } |
| 5979 | 5977 |
| 5980 | 5978 |
| 5981 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 5979 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
| 5982 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); | 5980 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex])); |
| 5983 v->Synchronize(VisitorSynchronization::kSymbolTable); | 5981 v->Synchronize(VisitorSynchronization::kStringTable); |
| 5984 if (mode != VISIT_ALL_IN_SCAVENGE && | 5982 if (mode != VISIT_ALL_IN_SCAVENGE && |
| 5985 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { | 5983 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { |
| 5986 // Scavenge collections have special processing for this. | 5984 // Scavenge collections have special processing for this. |
| 5987 external_string_table_.Iterate(v); | 5985 external_string_table_.Iterate(v); |
| 5988 error_object_list_.Iterate(v); | 5986 error_object_list_.Iterate(v); |
| 5989 } | 5987 } |
| 5990 v->Synchronize(VisitorSynchronization::kExternalStringsTable); | 5988 v->Synchronize(VisitorSynchronization::kExternalStringsTable); |
| 5991 } | 5989 } |
| 5992 | 5990 |
| 5993 | 5991 |
| 5994 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { | 5992 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
| 5995 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); | 5993 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); |
| 5996 v->Synchronize(VisitorSynchronization::kStrongRootList); | 5994 v->Synchronize(VisitorSynchronization::kStrongRootList); |
| 5997 | 5995 |
| 5998 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); | 5996 v->VisitPointer(BitCast<Object**>(&hidden_string_)); |
| 5999 v->Synchronize(VisitorSynchronization::kSymbol); | 5997 v->Synchronize(VisitorSynchronization::kInternalizedString); |
| 6000 | 5998 |
| 6001 isolate_->bootstrapper()->Iterate(v); | 5999 isolate_->bootstrapper()->Iterate(v); |
| 6002 v->Synchronize(VisitorSynchronization::kBootstrapper); | 6000 v->Synchronize(VisitorSynchronization::kBootstrapper); |
| 6003 isolate_->Iterate(v); | 6001 isolate_->Iterate(v); |
| 6004 v->Synchronize(VisitorSynchronization::kTop); | 6002 v->Synchronize(VisitorSynchronization::kTop); |
| 6005 Relocatable::Iterate(v); | 6003 Relocatable::Iterate(v); |
| 6006 v->Synchronize(VisitorSynchronization::kRelocatable); | 6004 v->Synchronize(VisitorSynchronization::kRelocatable); |
| 6007 | 6005 |
| 6008 #ifdef ENABLE_DEBUGGER_SUPPORT | 6006 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 6009 isolate_->debug()->Iterate(v); | 6007 isolate_->debug()->Iterate(v); |
| (...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7174 Key& key = keys_[index + i]; | 7172 Key& key = keys_[index + i]; |
| 7175 if ((key.map == map) && key.name->Equals(name)) { | 7173 if ((key.map == map) && key.name->Equals(name)) { |
| 7176 return field_offsets_[index + i]; | 7174 return field_offsets_[index + i]; |
| 7177 } | 7175 } |
| 7178 } | 7176 } |
| 7179 return kNotFound; | 7177 return kNotFound; |
| 7180 } | 7178 } |
| 7181 | 7179 |
| 7182 | 7180 |
| 7183 void KeyedLookupCache::Update(Map* map, String* name, int field_offset) { | 7181 void KeyedLookupCache::Update(Map* map, String* name, int field_offset) { |
| 7184 String* symbol; | 7182 String* internalized_name; |
| 7185 if (HEAP->LookupSymbolIfExists(name, &symbol)) { | 7183 if (HEAP->InternalizeStringIfExists(name, &internalized_name)) { |
| 7186 int index = (Hash(map, symbol) & kHashMask); | 7184 int index = (Hash(map, internalized_name) & kHashMask); |
| 7187 // After a GC there will be free slots, so we use them in order (this may | 7185 // After a GC there will be free slots, so we use them in order (this may |
| 7188 // help to get the most frequently used one in position 0). | 7186 // help to get the most frequently used one in position 0). |
| 7189 for (int i = 0; i< kEntriesPerBucket; i++) { | 7187 for (int i = 0; i< kEntriesPerBucket; i++) { |
| 7190 Key& key = keys_[index]; | 7188 Key& key = keys_[index]; |
| 7191 Object* free_entry_indicator = NULL; | 7189 Object* free_entry_indicator = NULL; |
| 7192 if (key.map == free_entry_indicator) { | 7190 if (key.map == free_entry_indicator) { |
| 7193 key.map = map; | 7191 key.map = map; |
| 7194 key.name = symbol; | 7192 key.name = internalized_name; |
| 7195 field_offsets_[index + i] = field_offset; | 7193 field_offsets_[index + i] = field_offset; |
| 7196 return; | 7194 return; |
| 7197 } | 7195 } |
| 7198 } | 7196 } |
| 7199 // No free entry found in this bucket, so we move them all down one and | 7197 // No free entry found in this bucket, so we move them all down one and |
| 7200 // put the new entry at position zero. | 7198 // put the new entry at position zero. |
| 7201 for (int i = kEntriesPerBucket - 1; i > 0; i--) { | 7199 for (int i = kEntriesPerBucket - 1; i > 0; i--) { |
| 7202 Key& key = keys_[index + i]; | 7200 Key& key = keys_[index + i]; |
| 7203 Key& key2 = keys_[index + i - 1]; | 7201 Key& key2 = keys_[index + i - 1]; |
| 7204 key = key2; | 7202 key = key2; |
| 7205 field_offsets_[index + i] = field_offsets_[index + i - 1]; | 7203 field_offsets_[index + i] = field_offsets_[index + i - 1]; |
| 7206 } | 7204 } |
| 7207 | 7205 |
| 7208 // Write the new first entry. | 7206 // Write the new first entry. |
| 7209 Key& key = keys_[index]; | 7207 Key& key = keys_[index]; |
| 7210 key.map = map; | 7208 key.map = map; |
| 7211 key.name = symbol; | 7209 key.name = internalized_name; |
| 7212 field_offsets_[index] = field_offset; | 7210 field_offsets_[index] = field_offset; |
| 7213 } | 7211 } |
| 7214 } | 7212 } |
| 7215 | 7213 |
| 7216 | 7214 |
| 7217 void KeyedLookupCache::Clear() { | 7215 void KeyedLookupCache::Clear() { |
| 7218 for (int index = 0; index < kLength; index++) keys_[index].map = NULL; | 7216 for (int index = 0; index < kLength; index++) keys_[index].map = NULL; |
| 7219 } | 7217 } |
| 7220 | 7218 |
| 7221 | 7219 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7334 } | 7332 } |
| 7335 | 7333 |
| 7336 | 7334 |
| 7337 void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) { | 7335 void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) { |
| 7338 // If formatting the stack trace causes a GC, this method will be | 7336 // If formatting the stack trace causes a GC, this method will be |
| 7339 // recursively called. In that case, skip the recursive call, since | 7337 // recursively called. In that case, skip the recursive call, since |
| 7340 // the loop modifies the list while iterating over it. | 7338 // the loop modifies the list while iterating over it. |
| 7341 if (nested_ || list_.is_empty() || isolate->has_pending_exception()) return; | 7339 if (nested_ || list_.is_empty() || isolate->has_pending_exception()) return; |
| 7342 nested_ = true; | 7340 nested_ = true; |
| 7343 HandleScope scope(isolate); | 7341 HandleScope scope(isolate); |
| 7344 Handle<String> stack_key = isolate->factory()->stack_symbol(); | 7342 Handle<String> stack_key = isolate->factory()->stack_string(); |
| 7345 int write_index = 0; | 7343 int write_index = 0; |
| 7346 int budget = kBudgetPerGC; | 7344 int budget = kBudgetPerGC; |
| 7347 for (int i = 0; i < list_.length(); i++) { | 7345 for (int i = 0; i < list_.length(); i++) { |
| 7348 Object* object = list_[i]; | 7346 Object* object = list_[i]; |
| 7349 JSFunction* getter_fun; | 7347 JSFunction* getter_fun; |
| 7350 | 7348 |
| 7351 { AssertNoAllocation assert; | 7349 { AssertNoAllocation assert; |
| 7352 // Skip possible holes in the list. | 7350 // Skip possible holes in the list. |
| 7353 if (object->IsTheHole()) continue; | 7351 if (object->IsTheHole()) continue; |
| 7354 if (isolate->heap()->InNewSpace(object) || budget == 0) { | 7352 if (isolate->heap()->InNewSpace(object) || budget == 0) { |
| 7355 list_[write_index++] = object; | 7353 list_[write_index++] = object; |
| 7356 continue; | 7354 continue; |
| 7357 } | 7355 } |
| 7358 | 7356 |
| 7359 // Check whether the stack property is backed by the original getter. | 7357 // Check whether the stack property is backed by the original getter. |
| 7360 LookupResult lookup(isolate); | 7358 LookupResult lookup(isolate); |
| 7361 JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup); | 7359 JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup); |
| 7362 if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue; | 7360 if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue; |
| 7363 Object* callback = lookup.GetCallbackObject(); | 7361 Object* callback = lookup.GetCallbackObject(); |
| 7364 if (!callback->IsAccessorPair()) continue; | 7362 if (!callback->IsAccessorPair()) continue; |
| 7365 Object* getter_obj = AccessorPair::cast(callback)->getter(); | 7363 Object* getter_obj = AccessorPair::cast(callback)->getter(); |
| 7366 if (!getter_obj->IsJSFunction()) continue; | 7364 if (!getter_obj->IsJSFunction()) continue; |
| 7367 getter_fun = JSFunction::cast(getter_obj); | 7365 getter_fun = JSFunction::cast(getter_obj); |
| 7368 String* key = isolate->heap()->hidden_stack_trace_symbol(); | 7366 String* key = isolate->heap()->hidden_stack_trace_string(); |
| 7369 if (key != getter_fun->GetHiddenProperty(key)) continue; | 7367 if (key != getter_fun->GetHiddenProperty(key)) continue; |
| 7370 } | 7368 } |
| 7371 | 7369 |
| 7372 budget--; | 7370 budget--; |
| 7373 HandleScope scope(isolate); | 7371 HandleScope scope(isolate); |
| 7374 bool has_exception = false; | 7372 bool has_exception = false; |
| 7375 #ifdef DEBUG | 7373 #ifdef DEBUG |
| 7376 Handle<Map> map(HeapObject::cast(object)->map(), isolate); | 7374 Handle<Map> map(HeapObject::cast(object)->map(), isolate); |
| 7377 #endif | 7375 #endif |
| 7378 Handle<Object> object_handle(object, isolate); | 7376 Handle<Object> object_handle(object, isolate); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7530 static_cast<int>(object_sizes_last_time_[index])); | 7528 static_cast<int>(object_sizes_last_time_[index])); |
| 7531 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) | 7529 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 7532 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7530 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 7533 | 7531 |
| 7534 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7532 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 7535 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7533 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 7536 ClearObjectStats(); | 7534 ClearObjectStats(); |
| 7537 } | 7535 } |
| 7538 | 7536 |
| 7539 } } // namespace v8::internal | 7537 } } // namespace v8::internal |
| OLD | NEW |