| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 // Update how much has survived scavenge. | 1018 // Update how much has survived scavenge. |
| 1019 IncrementYoungSurvivorsCounter(static_cast<int>( | 1019 IncrementYoungSurvivorsCounter(static_cast<int>( |
| 1020 (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); | 1020 (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); |
| 1021 | 1021 |
| 1022 LOG(ResourceEvent("scavenge", "end")); | 1022 LOG(ResourceEvent("scavenge", "end")); |
| 1023 | 1023 |
| 1024 gc_state_ = NOT_IN_GC; | 1024 gc_state_ = NOT_IN_GC; |
| 1025 } | 1025 } |
| 1026 | 1026 |
| 1027 | 1027 |
| 1028 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Object** p) { | 1028 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, |
| 1029 Object** p) { |
| 1029 MapWord first_word = HeapObject::cast(*p)->map_word(); | 1030 MapWord first_word = HeapObject::cast(*p)->map_word(); |
| 1030 | 1031 |
| 1031 if (!first_word.IsForwardingAddress()) { | 1032 if (!first_word.IsForwardingAddress()) { |
| 1032 // Unreachable external string can be finalized. | 1033 // Unreachable external string can be finalized. |
| 1033 HEAP->FinalizeExternalString(String::cast(*p)); | 1034 heap->FinalizeExternalString(String::cast(*p)); |
| 1034 return NULL; | 1035 return NULL; |
| 1035 } | 1036 } |
| 1036 | 1037 |
| 1037 // String is still reachable. | 1038 // String is still reachable. |
| 1038 return String::cast(first_word.ToForwardingAddress()); | 1039 return String::cast(first_word.ToForwardingAddress()); |
| 1039 } | 1040 } |
| 1040 | 1041 |
| 1041 | 1042 |
| 1042 void Heap::UpdateNewSpaceReferencesInExternalStringTable( | 1043 void Heap::UpdateNewSpaceReferencesInExternalStringTable( |
| 1043 ExternalStringTableUpdaterCallback updater_func) { | 1044 ExternalStringTableUpdaterCallback updater_func) { |
| 1044 external_string_table_.Verify(); | 1045 external_string_table_.Verify(); |
| 1045 | 1046 |
| 1046 if (external_string_table_.new_space_strings_.is_empty()) return; | 1047 if (external_string_table_.new_space_strings_.is_empty()) return; |
| 1047 | 1048 |
| 1048 Object** start = &external_string_table_.new_space_strings_[0]; | 1049 Object** start = &external_string_table_.new_space_strings_[0]; |
| 1049 Object** end = start + external_string_table_.new_space_strings_.length(); | 1050 Object** end = start + external_string_table_.new_space_strings_.length(); |
| 1050 Object** last = start; | 1051 Object** last = start; |
| 1051 | 1052 |
| 1052 for (Object** p = start; p < end; ++p) { | 1053 for (Object** p = start; p < end; ++p) { |
| 1053 ASSERT(InFromSpace(*p)); | 1054 ASSERT(InFromSpace(*p)); |
| 1054 String* target = updater_func(p); | 1055 String* target = updater_func(this, p); |
| 1055 | 1056 |
| 1056 if (target == NULL) continue; | 1057 if (target == NULL) continue; |
| 1057 | 1058 |
| 1058 ASSERT(target->IsExternalString()); | 1059 ASSERT(target->IsExternalString()); |
| 1059 | 1060 |
| 1060 if (InNewSpace(target)) { | 1061 if (InNewSpace(target)) { |
| 1061 // String is still in new space. Update the table entry. | 1062 // String is still in new space. Update the table entry. |
| 1062 *last = target; | 1063 *last = target; |
| 1063 ++last; | 1064 ++last; |
| 1064 } else { | 1065 } else { |
| (...skipping 1077 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2142 return MakeOrFindTwoCharacterString(this, c1, c2); | 2143 return MakeOrFindTwoCharacterString(this, c1, c2); |
| 2143 } | 2144 } |
| 2144 | 2145 |
| 2145 bool first_is_ascii = first->IsAsciiRepresentation(); | 2146 bool first_is_ascii = first->IsAsciiRepresentation(); |
| 2146 bool second_is_ascii = second->IsAsciiRepresentation(); | 2147 bool second_is_ascii = second->IsAsciiRepresentation(); |
| 2147 bool is_ascii = first_is_ascii && second_is_ascii; | 2148 bool is_ascii = first_is_ascii && second_is_ascii; |
| 2148 | 2149 |
| 2149 // Make sure that an out of memory exception is thrown if the length | 2150 // Make sure that an out of memory exception is thrown if the length |
| 2150 // of the new cons string is too large. | 2151 // of the new cons string is too large. |
| 2151 if (length > String::kMaxLength || length < 0) { | 2152 if (length > String::kMaxLength || length < 0) { |
| 2152 Isolate::Current()->context()->mark_out_of_memory(); | 2153 isolate()->context()->mark_out_of_memory(); |
| 2153 return Failure::OutOfMemoryException(); | 2154 return Failure::OutOfMemoryException(); |
| 2154 } | 2155 } |
| 2155 | 2156 |
| 2156 bool is_ascii_data_in_two_byte_string = false; | 2157 bool is_ascii_data_in_two_byte_string = false; |
| 2157 if (!is_ascii) { | 2158 if (!is_ascii) { |
| 2158 // At least one of the strings uses two-byte representation so we | 2159 // At least one of the strings uses two-byte representation so we |
| 2159 // can't use the fast case code for short ascii strings below, but | 2160 // can't use the fast case code for short ascii strings below, but |
| 2160 // we can try to save memory if all chars actually fit in ascii. | 2161 // we can try to save memory if all chars actually fit in ascii. |
| 2161 is_ascii_data_in_two_byte_string = | 2162 is_ascii_data_in_two_byte_string = |
| 2162 first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars(); | 2163 first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars(); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2266 } | 2267 } |
| 2267 | 2268 |
| 2268 return result; | 2269 return result; |
| 2269 } | 2270 } |
| 2270 | 2271 |
| 2271 | 2272 |
| 2272 Object* Heap::AllocateExternalStringFromAscii( | 2273 Object* Heap::AllocateExternalStringFromAscii( |
| 2273 ExternalAsciiString::Resource* resource) { | 2274 ExternalAsciiString::Resource* resource) { |
| 2274 size_t length = resource->length(); | 2275 size_t length = resource->length(); |
| 2275 if (length > static_cast<size_t>(String::kMaxLength)) { | 2276 if (length > static_cast<size_t>(String::kMaxLength)) { |
| 2276 Isolate::Current()->context()->mark_out_of_memory(); | 2277 isolate()->context()->mark_out_of_memory(); |
| 2277 return Failure::OutOfMemoryException(); | 2278 return Failure::OutOfMemoryException(); |
| 2278 } | 2279 } |
| 2279 | 2280 |
| 2280 Map* map = external_ascii_string_map(); | 2281 Map* map = external_ascii_string_map(); |
| 2281 Object* result = Allocate(map, NEW_SPACE); | 2282 Object* result = Allocate(map, NEW_SPACE); |
| 2282 if (result->IsFailure()) return result; | 2283 if (result->IsFailure()) return result; |
| 2283 | 2284 |
| 2284 ExternalAsciiString* external_string = ExternalAsciiString::cast(result); | 2285 ExternalAsciiString* external_string = ExternalAsciiString::cast(result); |
| 2285 external_string->set_length(static_cast<int>(length)); | 2286 external_string->set_length(static_cast<int>(length)); |
| 2286 external_string->set_hash_field(String::kEmptyHashField); | 2287 external_string->set_hash_field(String::kEmptyHashField); |
| 2287 external_string->set_resource(resource); | 2288 external_string->set_resource(resource); |
| 2288 | 2289 |
| 2289 return result; | 2290 return result; |
| 2290 } | 2291 } |
| 2291 | 2292 |
| 2292 | 2293 |
| 2293 Object* Heap::AllocateExternalStringFromTwoByte( | 2294 Object* Heap::AllocateExternalStringFromTwoByte( |
| 2294 ExternalTwoByteString::Resource* resource) { | 2295 ExternalTwoByteString::Resource* resource) { |
| 2295 size_t length = resource->length(); | 2296 size_t length = resource->length(); |
| 2296 if (length > static_cast<size_t>(String::kMaxLength)) { | 2297 if (length > static_cast<size_t>(String::kMaxLength)) { |
| 2297 Isolate::Current()->context()->mark_out_of_memory(); | 2298 isolate()->context()->mark_out_of_memory(); |
| 2298 return Failure::OutOfMemoryException(); | 2299 return Failure::OutOfMemoryException(); |
| 2299 } | 2300 } |
| 2300 | 2301 |
| 2301 // For small strings we check whether the resource contains only | 2302 // For small strings we check whether the resource contains only |
| 2302 // ascii characters. If yes, we use a different string map. | 2303 // ascii characters. If yes, we use a different string map. |
| 2303 bool is_ascii = true; | 2304 bool is_ascii = true; |
| 2304 if (length >= static_cast<size_t>(String::kMinNonFlatLength)) { | 2305 if (length >= static_cast<size_t>(String::kMinNonFlatLength)) { |
| 2305 is_ascii = false; | 2306 is_ascii = false; |
| 2306 } else { | 2307 } else { |
| 2307 const uc16* data = resource->data(); | 2308 const uc16* data = resource->data(); |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2620 | 2621 |
| 2621 Object* Heap::AllocateArgumentsObject(Object* callee, int length) { | 2622 Object* Heap::AllocateArgumentsObject(Object* callee, int length) { |
| 2622 // To get fast allocation and map sharing for arguments objects we | 2623 // To get fast allocation and map sharing for arguments objects we |
| 2623 // allocate them based on an arguments boilerplate. | 2624 // allocate them based on an arguments boilerplate. |
| 2624 | 2625 |
| 2625 // This calls Copy directly rather than using Heap::AllocateRaw so we | 2626 // This calls Copy directly rather than using Heap::AllocateRaw so we |
| 2626 // duplicate the check here. | 2627 // duplicate the check here. |
| 2627 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); | 2628 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); |
| 2628 | 2629 |
| 2629 JSObject* boilerplate = | 2630 JSObject* boilerplate = |
| 2630 Isolate::Current()->context()->global_context()->arguments_boilerplate(); | 2631 isolate()->context()->global_context()->arguments_boilerplate(); |
| 2631 | 2632 |
| 2632 // Check that the size of the boilerplate matches our | 2633 // Check that the size of the boilerplate matches our |
| 2633 // expectations. The ArgumentsAccessStub::GenerateNewObject relies | 2634 // expectations. The ArgumentsAccessStub::GenerateNewObject relies |
| 2634 // on the size being a known constant. | 2635 // on the size being a known constant. |
| 2635 ASSERT(kArgumentsObjectSize == boilerplate->map()->instance_size()); | 2636 ASSERT(kArgumentsObjectSize == boilerplate->map()->instance_size()); |
| 2636 | 2637 |
| 2637 // Do the allocation. | 2638 // Do the allocation. |
| 2638 Object* result = | 2639 Object* result = |
| 2639 AllocateRaw(kArgumentsObjectSize, NEW_SPACE, OLD_POINTER_SPACE); | 2640 AllocateRaw(kArgumentsObjectSize, NEW_SPACE, OLD_POINTER_SPACE); |
| 2640 if (result->IsFailure()) return result; | 2641 if (result->IsFailure()) return result; |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3485 ASSERT(contexts_disposed_ == 0); | 3486 ASSERT(contexts_disposed_ == 0); |
| 3486 if (uncommit) UncommitFromSpace(); | 3487 if (uncommit) UncommitFromSpace(); |
| 3487 return finished; | 3488 return finished; |
| 3488 } | 3489 } |
| 3489 | 3490 |
| 3490 | 3491 |
| 3491 #ifdef DEBUG | 3492 #ifdef DEBUG |
| 3492 | 3493 |
| 3493 void Heap::Print() { | 3494 void Heap::Print() { |
| 3494 if (!HasBeenSetup()) return; | 3495 if (!HasBeenSetup()) return; |
| 3495 Isolate::Current()->PrintStack(); | 3496 isolate()->PrintStack(); |
| 3496 AllSpaces spaces; | 3497 AllSpaces spaces; |
| 3497 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) | 3498 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) |
| 3498 space->Print(); | 3499 space->Print(); |
| 3499 } | 3500 } |
| 3500 | 3501 |
| 3501 | 3502 |
| 3502 void Heap::ReportCodeStatistics(const char* title) { | 3503 void Heap::ReportCodeStatistics(const char* title) { |
| 3503 PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title); | 3504 PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title); |
| 3504 PagedSpace::ResetCodeStatistics(); | 3505 PagedSpace::ResetCodeStatistics(); |
| 3505 // We do not look for code in new space, map space, or old space. If code | 3506 // We do not look for code in new space, map space, or old space. If code |
| (...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4443 // This should be called only after initial objects have been created. | 4444 // This should be called only after initial objects have been created. |
| 4444 isolate_->producer_heap_profile()->Setup(); | 4445 isolate_->producer_heap_profile()->Setup(); |
| 4445 #endif | 4446 #endif |
| 4446 | 4447 |
| 4447 return true; | 4448 return true; |
| 4448 } | 4449 } |
| 4449 | 4450 |
| 4450 | 4451 |
| 4451 void Heap::SetStackLimits() { | 4452 void Heap::SetStackLimits() { |
| 4452 ASSERT(isolate_ != NULL); | 4453 ASSERT(isolate_ != NULL); |
| 4453 ASSERT(isolate_ == Isolate::Current()); | 4454 ASSERT(isolate_ == isolate()); |
| 4454 // On 64 bit machines, pointers are generally out of range of Smis. We write | 4455 // On 64 bit machines, pointers are generally out of range of Smis. We write |
| 4455 // something that looks like an out of range Smi to the GC. | 4456 // something that looks like an out of range Smi to the GC. |
| 4456 | 4457 |
| 4457 // Set up the special root array entries containing the stack limits. | 4458 // Set up the special root array entries containing the stack limits. |
| 4458 // These are actually addresses, but the tag makes the GC ignore it. | 4459 // These are actually addresses, but the tag makes the GC ignore it. |
| 4459 roots_[kStackLimitRootIndex] = | 4460 roots_[kStackLimitRootIndex] = |
| 4460 reinterpret_cast<Object*>( | 4461 reinterpret_cast<Object*>( |
| 4461 (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag); | 4462 (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag); |
| 4462 roots_[kRealStackLimitRootIndex] = | 4463 roots_[kRealStackLimitRootIndex] = |
| 4463 reinterpret_cast<Object*>( | 4464 reinterpret_cast<Object*>( |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5049 } | 5050 } |
| 5050 | 5051 |
| 5051 | 5052 |
| 5052 void ExternalStringTable::TearDown() { | 5053 void ExternalStringTable::TearDown() { |
| 5053 new_space_strings_.Free(); | 5054 new_space_strings_.Free(); |
| 5054 old_space_strings_.Free(); | 5055 old_space_strings_.Free(); |
| 5055 } | 5056 } |
| 5056 | 5057 |
| 5057 | 5058 |
| 5058 } } // namespace v8::internal | 5059 } } // namespace v8::internal |
| OLD | NEW |