| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 #include "mark-compact.h" | 42 #include "mark-compact.h" |
| 43 #include "natives.h" | 43 #include "natives.h" |
| 44 #include "objects-visiting.h" | 44 #include "objects-visiting.h" |
| 45 #include "objects-visiting-inl.h" | 45 #include "objects-visiting-inl.h" |
| 46 #include "once.h" | 46 #include "once.h" |
| 47 #include "runtime-profiler.h" | 47 #include "runtime-profiler.h" |
| 48 #include "scopeinfo.h" | 48 #include "scopeinfo.h" |
| 49 #include "snapshot.h" | 49 #include "snapshot.h" |
| 50 #include "store-buffer.h" | 50 #include "store-buffer.h" |
| 51 #include "utils/random-number-generator.h" | 51 #include "utils/random-number-generator.h" |
| 52 #include "v8conversions.h" |
| 52 #include "v8threads.h" | 53 #include "v8threads.h" |
| 53 #include "v8utils.h" | 54 #include "v8utils.h" |
| 54 #include "vm-state-inl.h" | 55 #include "vm-state-inl.h" |
| 55 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP | 56 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP |
| 56 #include "regexp-macro-assembler.h" | 57 #include "regexp-macro-assembler.h" |
| 57 #include "arm/regexp-macro-assembler-arm.h" | 58 #include "arm/regexp-macro-assembler-arm.h" |
| 58 #endif | 59 #endif |
| 59 #if V8_TARGET_ARCH_MIPS && !V8_INTERPRETED_REGEXP | 60 #if V8_TARGET_ARCH_MIPS && !V8_INTERPRETED_REGEXP |
| 60 #include "regexp-macro-assembler.h" | 61 #include "regexp-macro-assembler.h" |
| 61 #include "mips/regexp-macro-assembler-mips.h" | 62 #include "mips/regexp-macro-assembler-mips.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 last_idle_notification_gc_count_init_(false), | 142 last_idle_notification_gc_count_init_(false), |
| 142 mark_sweeps_since_idle_round_started_(0), | 143 mark_sweeps_since_idle_round_started_(0), |
| 143 gc_count_at_last_idle_gc_(0), | 144 gc_count_at_last_idle_gc_(0), |
| 144 scavenges_since_last_idle_round_(kIdleScavengeThreshold), | 145 scavenges_since_last_idle_round_(kIdleScavengeThreshold), |
| 145 full_codegen_bytes_generated_(0), | 146 full_codegen_bytes_generated_(0), |
| 146 crankshaft_codegen_bytes_generated_(0), | 147 crankshaft_codegen_bytes_generated_(0), |
| 147 gcs_since_last_deopt_(0), | 148 gcs_since_last_deopt_(0), |
| 148 #ifdef VERIFY_HEAP | 149 #ifdef VERIFY_HEAP |
| 149 no_weak_object_verification_scope_depth_(0), | 150 no_weak_object_verification_scope_depth_(0), |
| 150 #endif | 151 #endif |
| 152 allocation_sites_scratchpad_length(0), |
| 151 promotion_queue_(this), | 153 promotion_queue_(this), |
| 152 configured_(false), | 154 configured_(false), |
| 153 chunks_queued_for_free_(NULL), | 155 chunks_queued_for_free_(NULL), |
| 154 relocation_mutex_(NULL) { | 156 relocation_mutex_(NULL) { |
| 155 // Allow build-time customization of the max semispace size. Building | 157 // Allow build-time customization of the max semispace size. Building |
| 156 // V8 with snapshots and a non-default max semispace size is much | 158 // V8 with snapshots and a non-default max semispace size is much |
| 157 // easier if you can define it as part of the build environment. | 159 // easier if you can define it as part of the build environment. |
| 158 #if defined(V8_MAX_SEMISPACE_SIZE) | 160 #if defined(V8_MAX_SEMISPACE_SIZE) |
| 159 max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; | 161 max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; |
| 160 #endif | 162 #endif |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 new_space_.ReportStatistics(); | 431 new_space_.ReportStatistics(); |
| 430 } | 432 } |
| 431 #else | 433 #else |
| 432 if (FLAG_log_gc) new_space_.ReportStatistics(); | 434 if (FLAG_log_gc) new_space_.ReportStatistics(); |
| 433 #endif // DEBUG | 435 #endif // DEBUG |
| 434 } | 436 } |
| 435 | 437 |
| 436 | 438 |
| 437 void Heap::GarbageCollectionPrologue() { | 439 void Heap::GarbageCollectionPrologue() { |
| 438 { AllowHeapAllocation for_the_first_part_of_prologue; | 440 { AllowHeapAllocation for_the_first_part_of_prologue; |
| 439 isolate_->transcendental_cache()->Clear(); | |
| 440 ClearJSFunctionResultCaches(); | 441 ClearJSFunctionResultCaches(); |
| 441 gc_count_++; | 442 gc_count_++; |
| 442 unflattened_strings_length_ = 0; | 443 unflattened_strings_length_ = 0; |
| 443 | 444 |
| 444 if (FLAG_flush_code && FLAG_flush_code_incrementally) { | 445 if (FLAG_flush_code && FLAG_flush_code_incrementally) { |
| 445 mark_compact_collector()->EnableCodeFlushing(true); | 446 mark_compact_collector()->EnableCodeFlushing(true); |
| 446 } | 447 } |
| 447 | 448 |
| 448 #ifdef VERIFY_HEAP | 449 #ifdef VERIFY_HEAP |
| 449 if (FLAG_verify_heap) { | 450 if (FLAG_verify_heap) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 void Heap::RepairFreeListsAfterBoot() { | 498 void Heap::RepairFreeListsAfterBoot() { |
| 498 PagedSpaces spaces(this); | 499 PagedSpaces spaces(this); |
| 499 for (PagedSpace* space = spaces.next(); | 500 for (PagedSpace* space = spaces.next(); |
| 500 space != NULL; | 501 space != NULL; |
| 501 space = spaces.next()) { | 502 space = spaces.next()) { |
| 502 space->RepairFreeListsAfterBoot(); | 503 space->RepairFreeListsAfterBoot(); |
| 503 } | 504 } |
| 504 } | 505 } |
| 505 | 506 |
| 506 | 507 |
| 507 void Heap::GarbageCollectionEpilogue() { | 508 void Heap::ProcessPretenuringFeedback() { |
| 508 if (FLAG_allocation_site_pretenuring) { | 509 if (FLAG_allocation_site_pretenuring) { |
| 509 int tenure_decisions = 0; | 510 int tenure_decisions = 0; |
| 510 int dont_tenure_decisions = 0; | 511 int dont_tenure_decisions = 0; |
| 511 int allocation_mementos_found = 0; | 512 int allocation_mementos_found = 0; |
| 513 int allocation_sites = 0; |
| 514 int active_allocation_sites = 0; |
| 512 | 515 |
| 513 Object* cur = allocation_sites_list(); | 516 // If the scratchpad overflowed, we have to iterate over the allocation |
| 514 while (cur->IsAllocationSite()) { | 517 // stites list. |
| 515 AllocationSite* casted = AllocationSite::cast(cur); | 518 bool use_scratchpad = |
| 516 allocation_mementos_found += casted->memento_found_count()->value(); | 519 allocation_sites_scratchpad_length < kAllocationSiteScratchpadSize; |
| 517 if (casted->DigestPretenuringFeedback()) { | 520 |
| 518 if (casted->GetPretenureMode() == TENURED) { | 521 int i = 0; |
| 522 Object* list_element = allocation_sites_list(); |
| 523 while (use_scratchpad ? |
| 524 i < allocation_sites_scratchpad_length : |
| 525 list_element->IsAllocationSite()) { |
| 526 AllocationSite* site = use_scratchpad ? |
| 527 allocation_sites_scratchpad[i] : AllocationSite::cast(list_element); |
| 528 allocation_mementos_found += site->memento_found_count()->value(); |
| 529 if (site->memento_found_count()->value() > 0) { |
| 530 active_allocation_sites++; |
| 531 } |
| 532 if (site->DigestPretenuringFeedback()) { |
| 533 if (site->GetPretenureMode() == TENURED) { |
| 519 tenure_decisions++; | 534 tenure_decisions++; |
| 520 } else { | 535 } else { |
| 521 dont_tenure_decisions++; | 536 dont_tenure_decisions++; |
| 522 } | 537 } |
| 523 } | 538 } |
| 524 cur = casted->weak_next(); | 539 allocation_sites++; |
| 540 if (use_scratchpad) { |
| 541 i++; |
| 542 } else { |
| 543 list_element = site->weak_next(); |
| 544 } |
| 525 } | 545 } |
| 546 allocation_sites_scratchpad_length = 0; |
| 526 | 547 |
| 527 // TODO(mvstanton): Pretenure decisions are only made once for an allocation | 548 // TODO(mvstanton): Pretenure decisions are only made once for an allocation |
| 528 // site. Find a sane way to decide about revisiting the decision later. | 549 // site. Find a sane way to decide about revisiting the decision later. |
| 529 | 550 |
| 530 if (FLAG_trace_track_allocation_sites && | 551 if (FLAG_trace_track_allocation_sites && |
| 531 (allocation_mementos_found > 0 || | 552 (allocation_mementos_found > 0 || |
| 532 tenure_decisions > 0 || | 553 tenure_decisions > 0 || |
| 533 dont_tenure_decisions > 0)) { | 554 dont_tenure_decisions > 0)) { |
| 534 PrintF("GC: (#mementos, #tenure decisions, #donttenure decisions) " | 555 PrintF("GC: (mode, #visited allocation sites, #active allocation sites, " |
| 535 "(%d, %d, %d)\n", | 556 "#mementos, #tenure decisions, #donttenure decisions) " |
| 557 "(%s, %d, %d, %d, %d, %d)\n", |
| 558 use_scratchpad ? "use scratchpad" : "use list", |
| 559 allocation_sites, |
| 560 active_allocation_sites, |
| 536 allocation_mementos_found, | 561 allocation_mementos_found, |
| 537 tenure_decisions, | 562 tenure_decisions, |
| 538 dont_tenure_decisions); | 563 dont_tenure_decisions); |
| 539 } | 564 } |
| 540 } | 565 } |
| 566 } |
| 541 | 567 |
| 568 |
| 569 void Heap::GarbageCollectionEpilogue() { |
| 542 store_buffer()->GCEpilogue(); | 570 store_buffer()->GCEpilogue(); |
| 543 | 571 |
| 544 // In release mode, we only zap the from space under heap verification. | 572 // In release mode, we only zap the from space under heap verification. |
| 545 if (Heap::ShouldZapGarbage()) { | 573 if (Heap::ShouldZapGarbage()) { |
| 546 ZapFromSpace(); | 574 ZapFromSpace(); |
| 547 } | 575 } |
| 548 | 576 |
| 549 #ifdef VERIFY_HEAP | 577 #ifdef VERIFY_HEAP |
| 550 if (FLAG_verify_heap) { | 578 if (FLAG_verify_heap) { |
| 551 Verify(); | 579 Verify(); |
| (...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1541 &IsUnscavengedHeapObject); | 1569 &IsUnscavengedHeapObject); |
| 1542 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( | 1570 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( |
| 1543 &scavenge_visitor); | 1571 &scavenge_visitor); |
| 1544 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1572 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
| 1545 | 1573 |
| 1546 UpdateNewSpaceReferencesInExternalStringTable( | 1574 UpdateNewSpaceReferencesInExternalStringTable( |
| 1547 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1575 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
| 1548 | 1576 |
| 1549 promotion_queue_.Destroy(); | 1577 promotion_queue_.Destroy(); |
| 1550 | 1578 |
| 1551 if (!FLAG_watch_ic_patching) { | |
| 1552 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | |
| 1553 } | |
| 1554 incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1579 incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
| 1555 | 1580 |
| 1556 ScavengeWeakObjectRetainer weak_object_retainer(this); | 1581 ScavengeWeakObjectRetainer weak_object_retainer(this); |
| 1557 ProcessWeakReferences(&weak_object_retainer); | 1582 ProcessWeakReferences(&weak_object_retainer); |
| 1558 | 1583 |
| 1559 ASSERT(new_space_front == new_space_.top()); | 1584 ASSERT(new_space_front == new_space_.top()); |
| 1560 | 1585 |
| 1561 // Set age mark. | 1586 // Set age mark. |
| 1562 new_space_.set_age_mark(new_space_.top()); | 1587 new_space_.set_age_mark(new_space_.top()); |
| 1563 | 1588 |
| 1564 new_space_.LowerInlineAllocationLimit( | 1589 new_space_.LowerInlineAllocationLimit( |
| 1565 new_space_.inline_allocation_limit_step()); | 1590 new_space_.inline_allocation_limit_step()); |
| 1566 | 1591 |
| 1567 // Update how much has survived scavenge. | 1592 // Update how much has survived scavenge. |
| 1568 IncrementYoungSurvivorsCounter(static_cast<int>( | 1593 IncrementYoungSurvivorsCounter(static_cast<int>( |
| 1569 (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); | 1594 (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); |
| 1570 | 1595 |
| 1596 ProcessPretenuringFeedback(); |
| 1597 |
| 1571 LOG(isolate_, ResourceEvent("scavenge", "end")); | 1598 LOG(isolate_, ResourceEvent("scavenge", "end")); |
| 1572 | 1599 |
| 1573 gc_state_ = NOT_IN_GC; | 1600 gc_state_ = NOT_IN_GC; |
| 1574 | 1601 |
| 1575 scavenges_since_last_idle_round_++; | 1602 scavenges_since_last_idle_round_++; |
| 1576 } | 1603 } |
| 1577 | 1604 |
| 1578 | 1605 |
| 1579 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, | 1606 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, |
| 1580 Object** p) { | 1607 Object** p) { |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1934 Object* allocation_site_obj = | 1961 Object* allocation_site_obj = |
| 1935 VisitWeakList<AllocationSite>(this, | 1962 VisitWeakList<AllocationSite>(this, |
| 1936 allocation_sites_list(), | 1963 allocation_sites_list(), |
| 1937 retainer, record_slots); | 1964 retainer, record_slots); |
| 1938 set_allocation_sites_list(allocation_site_obj); | 1965 set_allocation_sites_list(allocation_site_obj); |
| 1939 } | 1966 } |
| 1940 | 1967 |
| 1941 | 1968 |
| 1942 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { | 1969 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { |
| 1943 DisallowHeapAllocation no_allocation; | 1970 DisallowHeapAllocation no_allocation; |
| 1944 | 1971 // All external strings are listed in the external string table. |
| 1945 // Both the external string table and the string table may contain | |
| 1946 // external strings, but neither lists them exhaustively, nor is the | |
| 1947 // intersection set empty. Therefore we iterate over the external string | |
| 1948 // table first, ignoring internalized strings, and then over the | |
| 1949 // internalized string table. | |
| 1950 | 1972 |
| 1951 class ExternalStringTableVisitorAdapter : public ObjectVisitor { | 1973 class ExternalStringTableVisitorAdapter : public ObjectVisitor { |
| 1952 public: | 1974 public: |
| 1953 explicit ExternalStringTableVisitorAdapter( | 1975 explicit ExternalStringTableVisitorAdapter( |
| 1954 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} | 1976 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} |
| 1955 virtual void VisitPointers(Object** start, Object** end) { | 1977 virtual void VisitPointers(Object** start, Object** end) { |
| 1956 for (Object** p = start; p < end; p++) { | 1978 for (Object** p = start; p < end; p++) { |
| 1957 // Visit non-internalized external strings, | 1979 ASSERT((*p)->IsExternalString()); |
| 1958 // since internalized strings are listed in the string table. | 1980 visitor_->VisitExternalString(Utils::ToLocal( |
| 1959 if (!(*p)->IsInternalizedString()) { | 1981 Handle<String>(String::cast(*p)))); |
| 1960 ASSERT((*p)->IsExternalString()); | |
| 1961 visitor_->VisitExternalString(Utils::ToLocal( | |
| 1962 Handle<String>(String::cast(*p)))); | |
| 1963 } | |
| 1964 } | 1982 } |
| 1965 } | 1983 } |
| 1966 private: | 1984 private: |
| 1967 v8::ExternalResourceVisitor* visitor_; | 1985 v8::ExternalResourceVisitor* visitor_; |
| 1968 } external_string_table_visitor(visitor); | 1986 } external_string_table_visitor(visitor); |
| 1969 | 1987 |
| 1970 external_string_table_.Iterate(&external_string_table_visitor); | 1988 external_string_table_.Iterate(&external_string_table_visitor); |
| 1971 | |
| 1972 class StringTableVisitorAdapter : public ObjectVisitor { | |
| 1973 public: | |
| 1974 explicit StringTableVisitorAdapter( | |
| 1975 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} | |
| 1976 virtual void VisitPointers(Object** start, Object** end) { | |
| 1977 for (Object** p = start; p < end; p++) { | |
| 1978 if ((*p)->IsExternalString()) { | |
| 1979 ASSERT((*p)->IsInternalizedString()); | |
| 1980 visitor_->VisitExternalString(Utils::ToLocal( | |
| 1981 Handle<String>(String::cast(*p)))); | |
| 1982 } | |
| 1983 } | |
| 1984 } | |
| 1985 private: | |
| 1986 v8::ExternalResourceVisitor* visitor_; | |
| 1987 } string_table_visitor(visitor); | |
| 1988 | |
| 1989 string_table()->IterateElements(&string_table_visitor); | |
| 1990 } | 1989 } |
| 1991 | 1990 |
| 1992 | 1991 |
| 1993 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { | 1992 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { |
| 1994 public: | 1993 public: |
| 1995 static inline void VisitPointer(Heap* heap, Object** p) { | 1994 static inline void VisitPointer(Heap* heap, Object** p) { |
| 1996 Object* object = *p; | 1995 Object* object = *p; |
| 1997 if (!heap->InNewSpace(object)) return; | 1996 if (!heap->InNewSpace(object)) return; |
| 1998 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 1997 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
| 1999 reinterpret_cast<HeapObject*>(object)); | 1998 reinterpret_cast<HeapObject*>(object)); |
| (...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2639 AllocatePartialMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); | 2638 AllocatePartialMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); |
| 2640 if (!maybe_obj->ToObject(&obj)) return false; | 2639 if (!maybe_obj->ToObject(&obj)) return false; |
| 2641 } | 2640 } |
| 2642 set_fixed_array_map(Map::cast(obj)); | 2641 set_fixed_array_map(Map::cast(obj)); |
| 2643 | 2642 |
| 2644 { MaybeObject* maybe_obj = AllocatePartialMap(ODDBALL_TYPE, Oddball::kSize); | 2643 { MaybeObject* maybe_obj = AllocatePartialMap(ODDBALL_TYPE, Oddball::kSize); |
| 2645 if (!maybe_obj->ToObject(&obj)) return false; | 2644 if (!maybe_obj->ToObject(&obj)) return false; |
| 2646 } | 2645 } |
| 2647 set_oddball_map(Map::cast(obj)); | 2646 set_oddball_map(Map::cast(obj)); |
| 2648 | 2647 |
| 2648 { MaybeObject* maybe_obj = |
| 2649 AllocatePartialMap(CONSTANT_POOL_ARRAY_TYPE, kVariableSizeSentinel); |
| 2650 if (!maybe_obj->ToObject(&obj)) return false; |
| 2651 } |
| 2652 set_constant_pool_array_map(Map::cast(obj)); |
| 2653 |
| 2649 // Allocate the empty array. | 2654 // Allocate the empty array. |
| 2650 { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); | 2655 { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); |
| 2651 if (!maybe_obj->ToObject(&obj)) return false; | 2656 if (!maybe_obj->ToObject(&obj)) return false; |
| 2652 } | 2657 } |
| 2653 set_empty_fixed_array(FixedArray::cast(obj)); | 2658 set_empty_fixed_array(FixedArray::cast(obj)); |
| 2654 | 2659 |
| 2655 { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_POINTER_SPACE); | 2660 { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_POINTER_SPACE); |
| 2656 if (!maybe_obj->ToObject(&obj)) return false; | 2661 if (!maybe_obj->ToObject(&obj)) return false; |
| 2657 } | 2662 } |
| 2658 set_null_value(Oddball::cast(obj)); | 2663 set_null_value(Oddball::cast(obj)); |
| 2659 Oddball::cast(obj)->set_kind(Oddball::kNull); | 2664 Oddball::cast(obj)->set_kind(Oddball::kNull); |
| 2660 | 2665 |
| 2661 { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_POINTER_SPACE); | 2666 { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_POINTER_SPACE); |
| 2662 if (!maybe_obj->ToObject(&obj)) return false; | 2667 if (!maybe_obj->ToObject(&obj)) return false; |
| 2663 } | 2668 } |
| 2664 set_undefined_value(Oddball::cast(obj)); | 2669 set_undefined_value(Oddball::cast(obj)); |
| 2665 Oddball::cast(obj)->set_kind(Oddball::kUndefined); | 2670 Oddball::cast(obj)->set_kind(Oddball::kUndefined); |
| 2666 ASSERT(!InNewSpace(undefined_value())); | 2671 ASSERT(!InNewSpace(undefined_value())); |
| 2667 | 2672 |
| 2668 // Allocate the empty descriptor array. | 2673 // Allocate the empty descriptor array. |
| 2669 { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); | 2674 { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); |
| 2670 if (!maybe_obj->ToObject(&obj)) return false; | 2675 if (!maybe_obj->ToObject(&obj)) return false; |
| 2671 } | 2676 } |
| 2672 set_empty_descriptor_array(DescriptorArray::cast(obj)); | 2677 set_empty_descriptor_array(DescriptorArray::cast(obj)); |
| 2673 | 2678 |
| 2679 // Allocate the constant pool array. |
| 2680 { MaybeObject* maybe_obj = AllocateEmptyConstantPoolArray(); |
| 2681 if (!maybe_obj->ToObject(&obj)) return false; |
| 2682 } |
| 2683 set_empty_constant_pool_array(ConstantPoolArray::cast(obj)); |
| 2684 |
| 2674 // Fix the instance_descriptors for the existing maps. | 2685 // Fix the instance_descriptors for the existing maps. |
| 2675 meta_map()->set_code_cache(empty_fixed_array()); | 2686 meta_map()->set_code_cache(empty_fixed_array()); |
| 2676 meta_map()->set_dependent_code(DependentCode::cast(empty_fixed_array())); | 2687 meta_map()->set_dependent_code(DependentCode::cast(empty_fixed_array())); |
| 2677 meta_map()->init_back_pointer(undefined_value()); | 2688 meta_map()->init_back_pointer(undefined_value()); |
| 2678 meta_map()->set_instance_descriptors(empty_descriptor_array()); | 2689 meta_map()->set_instance_descriptors(empty_descriptor_array()); |
| 2679 | 2690 |
| 2680 fixed_array_map()->set_code_cache(empty_fixed_array()); | 2691 fixed_array_map()->set_code_cache(empty_fixed_array()); |
| 2681 fixed_array_map()->set_dependent_code( | 2692 fixed_array_map()->set_dependent_code( |
| 2682 DependentCode::cast(empty_fixed_array())); | 2693 DependentCode::cast(empty_fixed_array())); |
| 2683 fixed_array_map()->init_back_pointer(undefined_value()); | 2694 fixed_array_map()->init_back_pointer(undefined_value()); |
| 2684 fixed_array_map()->set_instance_descriptors(empty_descriptor_array()); | 2695 fixed_array_map()->set_instance_descriptors(empty_descriptor_array()); |
| 2685 | 2696 |
| 2686 oddball_map()->set_code_cache(empty_fixed_array()); | 2697 oddball_map()->set_code_cache(empty_fixed_array()); |
| 2687 oddball_map()->set_dependent_code(DependentCode::cast(empty_fixed_array())); | 2698 oddball_map()->set_dependent_code(DependentCode::cast(empty_fixed_array())); |
| 2688 oddball_map()->init_back_pointer(undefined_value()); | 2699 oddball_map()->init_back_pointer(undefined_value()); |
| 2689 oddball_map()->set_instance_descriptors(empty_descriptor_array()); | 2700 oddball_map()->set_instance_descriptors(empty_descriptor_array()); |
| 2690 | 2701 |
| 2702 constant_pool_array_map()->set_code_cache(empty_fixed_array()); |
| 2703 constant_pool_array_map()->set_dependent_code( |
| 2704 DependentCode::cast(empty_fixed_array())); |
| 2705 constant_pool_array_map()->init_back_pointer(undefined_value()); |
| 2706 constant_pool_array_map()->set_instance_descriptors(empty_descriptor_array()); |
| 2707 |
| 2691 // Fix prototype object for existing maps. | 2708 // Fix prototype object for existing maps. |
| 2692 meta_map()->set_prototype(null_value()); | 2709 meta_map()->set_prototype(null_value()); |
| 2693 meta_map()->set_constructor(null_value()); | 2710 meta_map()->set_constructor(null_value()); |
| 2694 | 2711 |
| 2695 fixed_array_map()->set_prototype(null_value()); | 2712 fixed_array_map()->set_prototype(null_value()); |
| 2696 fixed_array_map()->set_constructor(null_value()); | 2713 fixed_array_map()->set_constructor(null_value()); |
| 2697 | 2714 |
| 2698 oddball_map()->set_prototype(null_value()); | 2715 oddball_map()->set_prototype(null_value()); |
| 2699 oddball_map()->set_constructor(null_value()); | 2716 oddball_map()->set_constructor(null_value()); |
| 2700 | 2717 |
| 2718 constant_pool_array_map()->set_prototype(null_value()); |
| 2719 constant_pool_array_map()->set_constructor(null_value()); |
| 2720 |
| 2701 { MaybeObject* maybe_obj = | 2721 { MaybeObject* maybe_obj = |
| 2702 AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); | 2722 AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); |
| 2703 if (!maybe_obj->ToObject(&obj)) return false; | 2723 if (!maybe_obj->ToObject(&obj)) return false; |
| 2704 } | 2724 } |
| 2705 set_fixed_cow_array_map(Map::cast(obj)); | 2725 set_fixed_cow_array_map(Map::cast(obj)); |
| 2706 ASSERT(fixed_array_map() != fixed_cow_array_map()); | 2726 ASSERT(fixed_array_map() != fixed_cow_array_map()); |
| 2707 | 2727 |
| 2708 { MaybeObject* maybe_obj = | 2728 { MaybeObject* maybe_obj = |
| 2709 AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); | 2729 AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); |
| 2710 if (!maybe_obj->ToObject(&obj)) return false; | 2730 if (!maybe_obj->ToObject(&obj)) return false; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2747 set_undetectable_ascii_string_map(Map::cast(obj)); | 2767 set_undetectable_ascii_string_map(Map::cast(obj)); |
| 2748 Map::cast(obj)->set_is_undetectable(); | 2768 Map::cast(obj)->set_is_undetectable(); |
| 2749 | 2769 |
| 2750 { MaybeObject* maybe_obj = | 2770 { MaybeObject* maybe_obj = |
| 2751 AllocateMap(FIXED_DOUBLE_ARRAY_TYPE, kVariableSizeSentinel); | 2771 AllocateMap(FIXED_DOUBLE_ARRAY_TYPE, kVariableSizeSentinel); |
| 2752 if (!maybe_obj->ToObject(&obj)) return false; | 2772 if (!maybe_obj->ToObject(&obj)) return false; |
| 2753 } | 2773 } |
| 2754 set_fixed_double_array_map(Map::cast(obj)); | 2774 set_fixed_double_array_map(Map::cast(obj)); |
| 2755 | 2775 |
| 2756 { MaybeObject* maybe_obj = | 2776 { MaybeObject* maybe_obj = |
| 2757 AllocateMap(CONSTANT_POOL_ARRAY_TYPE, kVariableSizeSentinel); | |
| 2758 if (!maybe_obj->ToObject(&obj)) return false; | |
| 2759 } | |
| 2760 set_constant_pool_array_map(Map::cast(obj)); | |
| 2761 | |
| 2762 { MaybeObject* maybe_obj = | |
| 2763 AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel); | 2777 AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel); |
| 2764 if (!maybe_obj->ToObject(&obj)) return false; | 2778 if (!maybe_obj->ToObject(&obj)) return false; |
| 2765 } | 2779 } |
| 2766 set_byte_array_map(Map::cast(obj)); | 2780 set_byte_array_map(Map::cast(obj)); |
| 2767 | 2781 |
| 2768 { MaybeObject* maybe_obj = | 2782 { MaybeObject* maybe_obj = |
| 2769 AllocateMap(FREE_SPACE_TYPE, kVariableSizeSentinel); | 2783 AllocateMap(FREE_SPACE_TYPE, kVariableSizeSentinel); |
| 2770 if (!maybe_obj->ToObject(&obj)) return false; | 2784 if (!maybe_obj->ToObject(&obj)) return false; |
| 2771 } | 2785 } |
| 2772 set_free_space_map(Map::cast(obj)); | 2786 set_free_space_map(Map::cast(obj)); |
| (...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3689 case kExternalDoubleArray: | 3703 case kExternalDoubleArray: |
| 3690 return kExternalDoubleArrayMapRootIndex; | 3704 return kExternalDoubleArrayMapRootIndex; |
| 3691 case kExternalPixelArray: | 3705 case kExternalPixelArray: |
| 3692 return kExternalPixelArrayMapRootIndex; | 3706 return kExternalPixelArrayMapRootIndex; |
| 3693 default: | 3707 default: |
| 3694 UNREACHABLE(); | 3708 UNREACHABLE(); |
| 3695 return kUndefinedValueRootIndex; | 3709 return kUndefinedValueRootIndex; |
| 3696 } | 3710 } |
| 3697 } | 3711 } |
| 3698 | 3712 |
| 3713 |
| 3699 Heap::RootListIndex Heap::RootIndexForEmptyExternalArray( | 3714 Heap::RootListIndex Heap::RootIndexForEmptyExternalArray( |
| 3700 ElementsKind elementsKind) { | 3715 ElementsKind elementsKind) { |
| 3701 switch (elementsKind) { | 3716 switch (elementsKind) { |
| 3702 case EXTERNAL_BYTE_ELEMENTS: | 3717 case EXTERNAL_BYTE_ELEMENTS: |
| 3703 return kEmptyExternalByteArrayRootIndex; | 3718 return kEmptyExternalByteArrayRootIndex; |
| 3704 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3719 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3705 return kEmptyExternalUnsignedByteArrayRootIndex; | 3720 return kEmptyExternalUnsignedByteArrayRootIndex; |
| 3706 case EXTERNAL_SHORT_ELEMENTS: | 3721 case EXTERNAL_SHORT_ELEMENTS: |
| 3707 return kEmptyExternalShortArrayRootIndex; | 3722 return kEmptyExternalShortArrayRootIndex; |
| 3708 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3723 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3723 } | 3738 } |
| 3724 } | 3739 } |
| 3725 | 3740 |
| 3726 | 3741 |
| 3727 ExternalArray* Heap::EmptyExternalArrayForMap(Map* map) { | 3742 ExternalArray* Heap::EmptyExternalArrayForMap(Map* map) { |
| 3728 return ExternalArray::cast( | 3743 return ExternalArray::cast( |
| 3729 roots_[RootIndexForEmptyExternalArray(map->elements_kind())]); | 3744 roots_[RootIndexForEmptyExternalArray(map->elements_kind())]); |
| 3730 } | 3745 } |
| 3731 | 3746 |
| 3732 | 3747 |
| 3733 | |
| 3734 | |
| 3735 MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) { | 3748 MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) { |
| 3736 // We need to distinguish the minus zero value and this cannot be | 3749 // We need to distinguish the minus zero value and this cannot be |
| 3737 // done after conversion to int. Doing this by comparing bit | 3750 // done after conversion to int. Doing this by comparing bit |
| 3738 // patterns is faster than using fpclassify() et al. | 3751 // patterns is faster than using fpclassify() et al. |
| 3739 static const DoubleRepresentation minus_zero(-0.0); | 3752 if (IsMinusZero(value)) { |
| 3740 | |
| 3741 DoubleRepresentation rep(value); | |
| 3742 if (rep.bits == minus_zero.bits) { | |
| 3743 return AllocateHeapNumber(-0.0, pretenure); | 3753 return AllocateHeapNumber(-0.0, pretenure); |
| 3744 } | 3754 } |
| 3745 | 3755 |
| 3746 int int_value = FastD2I(value); | 3756 int int_value = FastD2I(value); |
| 3747 if (value == int_value && Smi::IsValid(int_value)) { | 3757 if (value == int_value && Smi::IsValid(int_value)) { |
| 3748 return Smi::FromInt(int_value); | 3758 return Smi::FromInt(int_value); |
| 3749 } | 3759 } |
| 3750 | 3760 |
| 3751 // Materialize the value in the heap. | 3761 // Materialize the value in the heap. |
| 3752 return AllocateHeapNumber(value, pretenure); | 3762 return AllocateHeapNumber(value, pretenure); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3823 message->set_arguments(arguments); | 3833 message->set_arguments(arguments); |
| 3824 message->set_start_position(start_position); | 3834 message->set_start_position(start_position); |
| 3825 message->set_end_position(end_position); | 3835 message->set_end_position(end_position); |
| 3826 message->set_script(script); | 3836 message->set_script(script); |
| 3827 message->set_stack_trace(stack_trace); | 3837 message->set_stack_trace(stack_trace); |
| 3828 message->set_stack_frames(stack_frames); | 3838 message->set_stack_frames(stack_frames); |
| 3829 return result; | 3839 return result; |
| 3830 } | 3840 } |
| 3831 | 3841 |
| 3832 | 3842 |
| 3833 | |
| 3834 // Returns true for a character in a range. Both limits are inclusive. | |
| 3835 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { | |
| 3836 // This makes uses of the the unsigned wraparound. | |
| 3837 return character - from <= to - from; | |
| 3838 } | |
| 3839 | |
| 3840 | |
| 3841 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString( | |
| 3842 Heap* heap, | |
| 3843 uint16_t c1, | |
| 3844 uint16_t c2) { | |
| 3845 String* result; | |
| 3846 // Numeric strings have a different hash algorithm not known by | |
| 3847 // LookupTwoCharsStringIfExists, so we skip this step for such strings. | |
| 3848 if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) && | |
| 3849 heap->string_table()->LookupTwoCharsStringIfExists(c1, c2, &result)) { | |
| 3850 return result; | |
| 3851 // Now we know the length is 2, we might as well make use of that fact | |
| 3852 // when building the new string. | |
| 3853 } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) { | |
| 3854 // We can do this. | |
| 3855 ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this. | |
| 3856 Object* result; | |
| 3857 { MaybeObject* maybe_result = heap->AllocateRawOneByteString(2); | |
| 3858 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 3859 } | |
| 3860 uint8_t* dest = SeqOneByteString::cast(result)->GetChars(); | |
| 3861 dest[0] = static_cast<uint8_t>(c1); | |
| 3862 dest[1] = static_cast<uint8_t>(c2); | |
| 3863 return result; | |
| 3864 } else { | |
| 3865 Object* result; | |
| 3866 { MaybeObject* maybe_result = heap->AllocateRawTwoByteString(2); | |
| 3867 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 3868 } | |
| 3869 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); | |
| 3870 dest[0] = c1; | |
| 3871 dest[1] = c2; | |
| 3872 return result; | |
| 3873 } | |
| 3874 } | |
| 3875 | |
| 3876 | |
| 3877 MaybeObject* Heap::AllocateConsString(String* first, String* second) { | |
| 3878 int first_length = first->length(); | |
| 3879 if (first_length == 0) { | |
| 3880 return second; | |
| 3881 } | |
| 3882 | |
| 3883 int second_length = second->length(); | |
| 3884 if (second_length == 0) { | |
| 3885 return first; | |
| 3886 } | |
| 3887 | |
| 3888 int length = first_length + second_length; | |
| 3889 | |
| 3890 // Optimization for 2-byte strings often used as keys in a decompression | |
| 3891 // dictionary. Check whether we already have the string in the string | |
| 3892 // table to prevent creation of many unneccesary strings. | |
| 3893 if (length == 2) { | |
| 3894 uint16_t c1 = first->Get(0); | |
| 3895 uint16_t c2 = second->Get(0); | |
| 3896 return MakeOrFindTwoCharacterString(this, c1, c2); | |
| 3897 } | |
| 3898 | |
| 3899 bool first_is_one_byte = first->IsOneByteRepresentation(); | |
| 3900 bool second_is_one_byte = second->IsOneByteRepresentation(); | |
| 3901 bool is_one_byte = first_is_one_byte && second_is_one_byte; | |
| 3902 // Make sure that an out of memory exception is thrown if the length | |
| 3903 // of the new cons string is too large. | |
| 3904 if (length > String::kMaxLength || length < 0) { | |
| 3905 isolate()->context()->mark_out_of_memory(); | |
| 3906 return Failure::OutOfMemoryException(0x4); | |
| 3907 } | |
| 3908 | |
| 3909 bool is_one_byte_data_in_two_byte_string = false; | |
| 3910 if (!is_one_byte) { | |
| 3911 // At least one of the strings uses two-byte representation so we | |
| 3912 // can't use the fast case code for short ASCII strings below, but | |
| 3913 // we can try to save memory if all chars actually fit in ASCII. | |
| 3914 is_one_byte_data_in_two_byte_string = | |
| 3915 first->HasOnlyOneByteChars() && second->HasOnlyOneByteChars(); | |
| 3916 if (is_one_byte_data_in_two_byte_string) { | |
| 3917 isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment(); | |
| 3918 } | |
| 3919 } | |
| 3920 | |
| 3921 // If the resulting string is small make a flat string. | |
| 3922 if (length < ConsString::kMinLength) { | |
| 3923 // Note that neither of the two inputs can be a slice because: | |
| 3924 STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength); | |
| 3925 ASSERT(first->IsFlat()); | |
| 3926 ASSERT(second->IsFlat()); | |
| 3927 if (is_one_byte) { | |
| 3928 Object* result; | |
| 3929 { MaybeObject* maybe_result = AllocateRawOneByteString(length); | |
| 3930 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 3931 } | |
| 3932 // Copy the characters into the new object. | |
| 3933 uint8_t* dest = SeqOneByteString::cast(result)->GetChars(); | |
| 3934 // Copy first part. | |
| 3935 const uint8_t* src; | |
| 3936 if (first->IsExternalString()) { | |
| 3937 src = ExternalAsciiString::cast(first)->GetChars(); | |
| 3938 } else { | |
| 3939 src = SeqOneByteString::cast(first)->GetChars(); | |
| 3940 } | |
| 3941 for (int i = 0; i < first_length; i++) *dest++ = src[i]; | |
| 3942 // Copy second part. | |
| 3943 if (second->IsExternalString()) { | |
| 3944 src = ExternalAsciiString::cast(second)->GetChars(); | |
| 3945 } else { | |
| 3946 src = SeqOneByteString::cast(second)->GetChars(); | |
| 3947 } | |
| 3948 for (int i = 0; i < second_length; i++) *dest++ = src[i]; | |
| 3949 return result; | |
| 3950 } else { | |
| 3951 if (is_one_byte_data_in_two_byte_string) { | |
| 3952 Object* result; | |
| 3953 { MaybeObject* maybe_result = AllocateRawOneByteString(length); | |
| 3954 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 3955 } | |
| 3956 // Copy the characters into the new object. | |
| 3957 uint8_t* dest = SeqOneByteString::cast(result)->GetChars(); | |
| 3958 String::WriteToFlat(first, dest, 0, first_length); | |
| 3959 String::WriteToFlat(second, dest + first_length, 0, second_length); | |
| 3960 isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment(); | |
| 3961 return result; | |
| 3962 } | |
| 3963 | |
| 3964 Object* result; | |
| 3965 { MaybeObject* maybe_result = AllocateRawTwoByteString(length); | |
| 3966 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 3967 } | |
| 3968 // Copy the characters into the new object. | |
| 3969 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); | |
| 3970 String::WriteToFlat(first, dest, 0, first_length); | |
| 3971 String::WriteToFlat(second, dest + first_length, 0, second_length); | |
| 3972 return result; | |
| 3973 } | |
| 3974 } | |
| 3975 | |
| 3976 Map* map = (is_one_byte || is_one_byte_data_in_two_byte_string) ? | |
| 3977 cons_ascii_string_map() : cons_string_map(); | |
| 3978 | |
| 3979 Object* result; | |
| 3980 { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); | |
| 3981 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 3982 } | |
| 3983 | |
| 3984 DisallowHeapAllocation no_gc; | |
| 3985 ConsString* cons_string = ConsString::cast(result); | |
| 3986 WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc); | |
| 3987 cons_string->set_length(length); | |
| 3988 cons_string->set_hash_field(String::kEmptyHashField); | |
| 3989 cons_string->set_first(first, mode); | |
| 3990 cons_string->set_second(second, mode); | |
| 3991 return result; | |
| 3992 } | |
| 3993 | |
| 3994 | |
| 3995 MaybeObject* Heap::AllocateSubString(String* buffer, | |
| 3996 int start, | |
| 3997 int end, | |
| 3998 PretenureFlag pretenure) { | |
| 3999 int length = end - start; | |
| 4000 if (length <= 0) { | |
| 4001 return empty_string(); | |
| 4002 } | |
| 4003 | |
| 4004 // Make an attempt to flatten the buffer to reduce access time. | |
| 4005 buffer = buffer->TryFlattenGetString(); | |
| 4006 | |
| 4007 if (length == 1) { | |
| 4008 return LookupSingleCharacterStringFromCode(buffer->Get(start)); | |
| 4009 } else if (length == 2) { | |
| 4010 // Optimization for 2-byte strings often used as keys in a decompression | |
| 4011 // dictionary. Check whether we already have the string in the string | |
| 4012 // table to prevent creation of many unnecessary strings. | |
| 4013 uint16_t c1 = buffer->Get(start); | |
| 4014 uint16_t c2 = buffer->Get(start + 1); | |
| 4015 return MakeOrFindTwoCharacterString(this, c1, c2); | |
| 4016 } | |
| 4017 | |
| 4018 if (!FLAG_string_slices || | |
| 4019 !buffer->IsFlat() || | |
| 4020 length < SlicedString::kMinLength || | |
| 4021 pretenure == TENURED) { | |
| 4022 Object* result; | |
| 4023 // WriteToFlat takes care of the case when an indirect string has a | |
| 4024 // different encoding from its underlying string. These encodings may | |
| 4025 // differ because of externalization. | |
| 4026 bool is_one_byte = buffer->IsOneByteRepresentation(); | |
| 4027 { MaybeObject* maybe_result = is_one_byte | |
| 4028 ? AllocateRawOneByteString(length, pretenure) | |
| 4029 : AllocateRawTwoByteString(length, pretenure); | |
| 4030 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 4031 } | |
| 4032 String* string_result = String::cast(result); | |
| 4033 // Copy the characters into the new object. | |
| 4034 if (is_one_byte) { | |
| 4035 ASSERT(string_result->IsOneByteRepresentation()); | |
| 4036 uint8_t* dest = SeqOneByteString::cast(string_result)->GetChars(); | |
| 4037 String::WriteToFlat(buffer, dest, start, end); | |
| 4038 } else { | |
| 4039 ASSERT(string_result->IsTwoByteRepresentation()); | |
| 4040 uc16* dest = SeqTwoByteString::cast(string_result)->GetChars(); | |
| 4041 String::WriteToFlat(buffer, dest, start, end); | |
| 4042 } | |
| 4043 return result; | |
| 4044 } | |
| 4045 | |
| 4046 ASSERT(buffer->IsFlat()); | |
| 4047 #if VERIFY_HEAP | |
| 4048 if (FLAG_verify_heap) { | |
| 4049 buffer->StringVerify(); | |
| 4050 } | |
| 4051 #endif | |
| 4052 | |
| 4053 Object* result; | |
| 4054 // When slicing an indirect string we use its encoding for a newly created | |
| 4055 // slice and don't check the encoding of the underlying string. This is safe | |
| 4056 // even if the encodings are different because of externalization. If an | |
| 4057 // indirect ASCII string is pointing to a two-byte string, the two-byte char | |
| 4058 // codes of the underlying string must still fit into ASCII (because | |
| 4059 // externalization must not change char codes). | |
| 4060 { Map* map = buffer->IsOneByteRepresentation() | |
| 4061 ? sliced_ascii_string_map() | |
| 4062 : sliced_string_map(); | |
| 4063 MaybeObject* maybe_result = Allocate(map, NEW_SPACE); | |
| 4064 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 4065 } | |
| 4066 | |
| 4067 DisallowHeapAllocation no_gc; | |
| 4068 SlicedString* sliced_string = SlicedString::cast(result); | |
| 4069 sliced_string->set_length(length); | |
| 4070 sliced_string->set_hash_field(String::kEmptyHashField); | |
| 4071 if (buffer->IsConsString()) { | |
| 4072 ConsString* cons = ConsString::cast(buffer); | |
| 4073 ASSERT(cons->second()->length() == 0); | |
| 4074 sliced_string->set_parent(cons->first()); | |
| 4075 sliced_string->set_offset(start); | |
| 4076 } else if (buffer->IsSlicedString()) { | |
| 4077 // Prevent nesting sliced strings. | |
| 4078 SlicedString* parent_slice = SlicedString::cast(buffer); | |
| 4079 sliced_string->set_parent(parent_slice->parent()); | |
| 4080 sliced_string->set_offset(start + parent_slice->offset()); | |
| 4081 } else { | |
| 4082 sliced_string->set_parent(buffer); | |
| 4083 sliced_string->set_offset(start); | |
| 4084 } | |
| 4085 ASSERT(sliced_string->parent()->IsSeqString() || | |
| 4086 sliced_string->parent()->IsExternalString()); | |
| 4087 return result; | |
| 4088 } | |
| 4089 | |
| 4090 | |
| 4091 MaybeObject* Heap::AllocateExternalStringFromAscii( | 3843 MaybeObject* Heap::AllocateExternalStringFromAscii( |
| 4092 const ExternalAsciiString::Resource* resource) { | 3844 const ExternalAsciiString::Resource* resource) { |
| 4093 size_t length = resource->length(); | 3845 size_t length = resource->length(); |
| 4094 if (length > static_cast<size_t>(String::kMaxLength)) { | 3846 if (length > static_cast<size_t>(String::kMaxLength)) { |
| 4095 isolate()->context()->mark_out_of_memory(); | 3847 isolate()->context()->mark_out_of_memory(); |
| 4096 return Failure::OutOfMemoryException(0x5); | 3848 return Failure::OutOfMemoryException(0x5); |
| 4097 } | 3849 } |
| 4098 | 3850 |
| 4099 Map* map = external_ascii_string_map(); | 3851 Map* map = external_ascii_string_map(); |
| 4100 Object* result; | 3852 Object* result; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4257 } | 4009 } |
| 4258 | 4010 |
| 4259 // Initialize the object | 4011 // Initialize the object |
| 4260 result->set_map_no_write_barrier(code_map()); | 4012 result->set_map_no_write_barrier(code_map()); |
| 4261 Code* code = Code::cast(result); | 4013 Code* code = Code::cast(result); |
| 4262 ASSERT(!isolate_->code_range()->exists() || | 4014 ASSERT(!isolate_->code_range()->exists() || |
| 4263 isolate_->code_range()->contains(code->address())); | 4015 isolate_->code_range()->contains(code->address())); |
| 4264 code->set_instruction_size(desc.instr_size); | 4016 code->set_instruction_size(desc.instr_size); |
| 4265 code->set_relocation_info(reloc_info); | 4017 code->set_relocation_info(reloc_info); |
| 4266 code->set_flags(flags); | 4018 code->set_flags(flags); |
| 4019 code->set_raw_kind_specific_flags1(0); |
| 4020 code->set_raw_kind_specific_flags2(0); |
| 4267 if (code->is_call_stub() || code->is_keyed_call_stub()) { | 4021 if (code->is_call_stub() || code->is_keyed_call_stub()) { |
| 4268 code->set_check_type(RECEIVER_MAP_CHECK); | 4022 code->set_check_type(RECEIVER_MAP_CHECK); |
| 4269 } | 4023 } |
| 4270 code->set_is_crankshafted(crankshafted); | 4024 code->set_is_crankshafted(crankshafted); |
| 4271 code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER); | 4025 code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER); |
| 4272 code->set_raw_type_feedback_info(undefined_value()); | 4026 code->set_raw_type_feedback_info(undefined_value()); |
| 4273 code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER); | 4027 code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER); |
| 4274 code->set_gc_metadata(Smi::FromInt(0)); | 4028 code->set_gc_metadata(Smi::FromInt(0)); |
| 4275 code->set_ic_age(global_ic_age_); | 4029 code->set_ic_age(global_ic_age_); |
| 4276 code->set_prologue_offset(prologue_offset); | 4030 code->set_prologue_offset(prologue_offset); |
| 4277 if (code->kind() == Code::OPTIMIZED_FUNCTION) { | 4031 if (code->kind() == Code::OPTIMIZED_FUNCTION) { |
| 4278 code->set_marked_for_deoptimization(false); | 4032 code->set_marked_for_deoptimization(false); |
| 4279 } | 4033 } |
| 4034 code->set_constant_pool(empty_constant_pool_array()); |
| 4280 | 4035 |
| 4281 #ifdef ENABLE_DEBUGGER_SUPPORT | 4036 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 4282 if (code->kind() == Code::FUNCTION) { | 4037 if (code->kind() == Code::FUNCTION) { |
| 4283 code->set_has_debug_break_slots( | 4038 code->set_has_debug_break_slots( |
| 4284 isolate_->debugger()->IsDebuggerActive()); | 4039 isolate_->debugger()->IsDebuggerActive()); |
| 4285 } | 4040 } |
| 4286 #endif | 4041 #endif |
| 4287 | 4042 |
| 4288 // Allow self references to created code object by patching the handle to | 4043 // Allow self references to created code object by patching the handle to |
| 4289 // point to the newly allocated Code object. | 4044 // point to the newly allocated Code object. |
| (...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5509 if (!maybe_object->To<HeapObject>(&object)) return maybe_object; | 5264 if (!maybe_object->To<HeapObject>(&object)) return maybe_object; |
| 5510 } | 5265 } |
| 5511 object = EnsureDoubleAligned(this, object, size); | 5266 object = EnsureDoubleAligned(this, object, size); |
| 5512 HeapObject::cast(object)->set_map_no_write_barrier(constant_pool_array_map()); | 5267 HeapObject::cast(object)->set_map_no_write_barrier(constant_pool_array_map()); |
| 5513 | 5268 |
| 5514 ConstantPoolArray* constant_pool = | 5269 ConstantPoolArray* constant_pool = |
| 5515 reinterpret_cast<ConstantPoolArray*>(object); | 5270 reinterpret_cast<ConstantPoolArray*>(object); |
| 5516 constant_pool->SetEntryCounts(number_of_int64_entries, | 5271 constant_pool->SetEntryCounts(number_of_int64_entries, |
| 5517 number_of_ptr_entries, | 5272 number_of_ptr_entries, |
| 5518 number_of_int32_entries); | 5273 number_of_int32_entries); |
| 5519 MemsetPointer( | 5274 if (number_of_ptr_entries > 0) { |
| 5520 HeapObject::RawField( | 5275 MemsetPointer( |
| 5521 constant_pool, | 5276 HeapObject::RawField( |
| 5522 constant_pool->OffsetOfElementAt(constant_pool->first_ptr_index())), | 5277 constant_pool, |
| 5523 undefined_value(), | 5278 constant_pool->OffsetOfElementAt(constant_pool->first_ptr_index())), |
| 5524 number_of_ptr_entries); | 5279 undefined_value(), |
| 5280 number_of_ptr_entries); |
| 5281 } |
| 5525 return constant_pool; | 5282 return constant_pool; |
| 5526 } | 5283 } |
| 5527 | 5284 |
| 5528 | 5285 |
| 5286 MaybeObject* Heap::AllocateEmptyConstantPoolArray() { |
| 5287 int size = ConstantPoolArray::SizeFor(0, 0, 0); |
| 5288 Object* result; |
| 5289 { MaybeObject* maybe_result = |
| 5290 AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE); |
| 5291 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5292 } |
| 5293 HeapObject::cast(result)->set_map_no_write_barrier(constant_pool_array_map()); |
| 5294 ConstantPoolArray::cast(result)->SetEntryCounts(0, 0, 0); |
| 5295 return result; |
| 5296 } |
| 5297 |
| 5298 |
| 5529 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { | 5299 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { |
| 5530 Object* result; | 5300 Object* result; |
| 5531 { MaybeObject* maybe_result = AllocateFixedArray(length, pretenure); | 5301 { MaybeObject* maybe_result = AllocateFixedArray(length, pretenure); |
| 5532 if (!maybe_result->ToObject(&result)) return maybe_result; | 5302 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5533 } | 5303 } |
| 5534 reinterpret_cast<HeapObject*>(result)->set_map_no_write_barrier( | 5304 reinterpret_cast<HeapObject*>(result)->set_map_no_write_barrier( |
| 5535 hash_table_map()); | 5305 hash_table_map()); |
| 5536 ASSERT(result->IsHashTable()); | 5306 ASSERT(result->IsHashTable()); |
| 5537 return result; | 5307 return result; |
| 5538 } | 5308 } |
| (...skipping 2243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7782 #ifdef DEBUG | 7552 #ifdef DEBUG |
| 7783 void Heap::GarbageCollectionGreedyCheck() { | 7553 void Heap::GarbageCollectionGreedyCheck() { |
| 7784 ASSERT(FLAG_gc_greedy); | 7554 ASSERT(FLAG_gc_greedy); |
| 7785 if (isolate_->bootstrapper()->IsActive()) return; | 7555 if (isolate_->bootstrapper()->IsActive()) return; |
| 7786 if (disallow_allocation_failure()) return; | 7556 if (disallow_allocation_failure()) return; |
| 7787 CollectGarbage(NEW_SPACE); | 7557 CollectGarbage(NEW_SPACE); |
| 7788 } | 7558 } |
| 7789 #endif | 7559 #endif |
| 7790 | 7560 |
| 7791 | 7561 |
| 7792 TranscendentalCache::SubCache::SubCache(Isolate* isolate, Type t) | |
| 7793 : type_(t), | |
| 7794 isolate_(isolate) { | |
| 7795 uint32_t in0 = 0xffffffffu; // Bit-pattern for a NaN that isn't | |
| 7796 uint32_t in1 = 0xffffffffu; // generated by the FPU. | |
| 7797 for (int i = 0; i < kCacheSize; i++) { | |
| 7798 elements_[i].in[0] = in0; | |
| 7799 elements_[i].in[1] = in1; | |
| 7800 elements_[i].output = NULL; | |
| 7801 } | |
| 7802 } | |
| 7803 | |
| 7804 | |
| 7805 void TranscendentalCache::Clear() { | |
| 7806 for (int i = 0; i < kNumberOfCaches; i++) { | |
| 7807 if (caches_[i] != NULL) { | |
| 7808 delete caches_[i]; | |
| 7809 caches_[i] = NULL; | |
| 7810 } | |
| 7811 } | |
| 7812 } | |
| 7813 | |
| 7814 | |
| 7815 void ExternalStringTable::CleanUp() { | 7562 void ExternalStringTable::CleanUp() { |
| 7816 int last = 0; | 7563 int last = 0; |
| 7817 for (int i = 0; i < new_space_strings_.length(); ++i) { | 7564 for (int i = 0; i < new_space_strings_.length(); ++i) { |
| 7818 if (new_space_strings_[i] == heap_->the_hole_value()) { | 7565 if (new_space_strings_[i] == heap_->the_hole_value()) { |
| 7819 continue; | 7566 continue; |
| 7820 } | 7567 } |
| 7821 ASSERT(new_space_strings_[i]->IsExternalString()); | 7568 ASSERT(new_space_strings_[i]->IsExternalString()); |
| 7822 if (heap_->InNewSpace(new_space_strings_[i])) { | 7569 if (heap_->InNewSpace(new_space_strings_[i])) { |
| 7823 new_space_strings_[last++] = new_space_strings_[i]; | 7570 new_space_strings_[last++] = new_space_strings_[i]; |
| 7824 } else { | 7571 } else { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7993 static_cast<int>(object_sizes_last_time_[index])); | 7740 static_cast<int>(object_sizes_last_time_[index])); |
| 7994 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 7741 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 7995 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7742 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 7996 | 7743 |
| 7997 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7744 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 7998 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7745 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 7999 ClearObjectStats(); | 7746 ClearObjectStats(); |
| 8000 } | 7747 } |
| 8001 | 7748 |
| 8002 } } // namespace v8::internal | 7749 } } // namespace v8::internal |
| OLD | NEW |