Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 // Will be 4 * reserved_semispace_size_ to ensure that young | 107 // Will be 4 * reserved_semispace_size_ to ensure that young |
| 108 // generation can be aligned to its size. | 108 // generation can be aligned to its size. |
| 109 int Heap::survived_since_last_expansion_ = 0; | 109 int Heap::survived_since_last_expansion_ = 0; |
| 110 int Heap::external_allocation_limit_ = 0; | 110 int Heap::external_allocation_limit_ = 0; |
| 111 | 111 |
| 112 Heap::HeapState Heap::gc_state_ = NOT_IN_GC; | 112 Heap::HeapState Heap::gc_state_ = NOT_IN_GC; |
| 113 | 113 |
| 114 int Heap::mc_count_ = 0; | 114 int Heap::mc_count_ = 0; |
| 115 int Heap::gc_count_ = 0; | 115 int Heap::gc_count_ = 0; |
| 116 | 116 |
| 117 int Heap::unflattended_strings_length_ = 0; | |
|
Erik Corry
2010/03/23 10:12:44
That's not even a word!
| |
| 118 | |
| 117 int Heap::always_allocate_scope_depth_ = 0; | 119 int Heap::always_allocate_scope_depth_ = 0; |
| 118 int Heap::linear_allocation_scope_depth_ = 0; | 120 int Heap::linear_allocation_scope_depth_ = 0; |
| 119 int Heap::contexts_disposed_ = 0; | 121 int Heap::contexts_disposed_ = 0; |
| 120 | 122 |
| 121 #ifdef DEBUG | 123 #ifdef DEBUG |
| 122 bool Heap::allocation_allowed_ = true; | 124 bool Heap::allocation_allowed_ = true; |
| 123 | 125 |
| 124 int Heap::allocation_timeout_ = 0; | 126 int Heap::allocation_timeout_ = 0; |
| 125 bool Heap::disallow_allocation_failure_ = false; | 127 bool Heap::disallow_allocation_failure_ = false; |
| 126 #endif // DEBUG | 128 #endif // DEBUG |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 #elif defined(ENABLE_LOGGING_AND_PROFILING) | 297 #elif defined(ENABLE_LOGGING_AND_PROFILING) |
| 296 if (FLAG_log_gc) new_space_.ReportStatistics(); | 298 if (FLAG_log_gc) new_space_.ReportStatistics(); |
| 297 #endif | 299 #endif |
| 298 } | 300 } |
| 299 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 301 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 300 | 302 |
| 301 | 303 |
| 302 void Heap::GarbageCollectionPrologue() { | 304 void Heap::GarbageCollectionPrologue() { |
| 303 TranscendentalCache::Clear(); | 305 TranscendentalCache::Clear(); |
| 304 gc_count_++; | 306 gc_count_++; |
| 307 unflattended_strings_length_ = 0; | |
| 305 #ifdef DEBUG | 308 #ifdef DEBUG |
| 306 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); | 309 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); |
| 307 allow_allocation(false); | 310 allow_allocation(false); |
| 308 | 311 |
| 309 if (FLAG_verify_heap) { | 312 if (FLAG_verify_heap) { |
| 310 Verify(); | 313 Verify(); |
| 311 } | 314 } |
| 312 | 315 |
| 313 if (FLAG_gc_verbose) Print(); | 316 if (FLAG_gc_verbose) Print(); |
| 314 | 317 |
| (...skipping 1935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2250 reinterpret_cast<Object**>(old_addr), | 2253 reinterpret_cast<Object**>(old_addr), |
| 2251 obj_size); | 2254 obj_size); |
| 2252 // Relocate the copy. | 2255 // Relocate the copy. |
| 2253 Code* new_code = Code::cast(result); | 2256 Code* new_code = Code::cast(result); |
| 2254 ASSERT(!CodeRange::exists() || CodeRange::contains(code->address())); | 2257 ASSERT(!CodeRange::exists() || CodeRange::contains(code->address())); |
| 2255 new_code->Relocate(new_addr - old_addr); | 2258 new_code->Relocate(new_addr - old_addr); |
| 2256 return new_code; | 2259 return new_code; |
| 2257 } | 2260 } |
| 2258 | 2261 |
| 2259 | 2262 |
| 2263 Object* Heap::CopyCode(Code* code, Vector<byte> reloc_info) { | |
| 2264 int new_body_size = RoundUp(code->instruction_size() + reloc_info.length(), | |
| 2265 kObjectAlignment); | |
| 2266 | |
| 2267 int sinfo_size = code->sinfo_size(); | |
| 2268 | |
| 2269 int new_obj_size = Code::SizeFor(new_body_size, sinfo_size); | |
| 2270 | |
| 2271 Address old_addr = code->address(); | |
| 2272 | |
| 2273 int relocation_offset = code->relocation_start() - old_addr; | |
| 2274 | |
| 2275 Object* result; | |
| 2276 if (new_obj_size > MaxObjectSizeInPagedSpace()) { | |
| 2277 result = lo_space_->AllocateRawCode(new_obj_size); | |
| 2278 } else { | |
| 2279 result = code_space_->AllocateRaw(new_obj_size); | |
| 2280 } | |
| 2281 | |
| 2282 if (result->IsFailure()) return result; | |
| 2283 | |
| 2284 // Copy code object. | |
| 2285 Address new_addr = reinterpret_cast<HeapObject*>(result)->address(); | |
| 2286 | |
| 2287 // Copy header and instructions. | |
| 2288 memcpy(new_addr, old_addr, relocation_offset); | |
| 2289 | |
| 2290 // Copy patched rinfo. | |
| 2291 memcpy(new_addr + relocation_offset, | |
| 2292 reloc_info.start(), | |
| 2293 reloc_info.length()); | |
| 2294 | |
| 2295 Code* new_code = Code::cast(result); | |
| 2296 new_code->set_relocation_size(reloc_info.length()); | |
| 2297 | |
| 2298 // Copy sinfo. | |
| 2299 memcpy(new_code->sinfo_start(), code->sinfo_start(), code->sinfo_size()); | |
| 2300 | |
| 2301 // Relocate the copy. | |
| 2302 ASSERT(!CodeRange::exists() || CodeRange::contains(code->address())); | |
| 2303 new_code->Relocate(new_addr - old_addr); | |
| 2304 | |
| 2305 #ifdef DEBUG | |
| 2306 code->Verify(); | |
| 2307 #endif | |
| 2308 return new_code; | |
| 2309 } | |
| 2310 | |
| 2311 | |
| 2260 Object* Heap::Allocate(Map* map, AllocationSpace space) { | 2312 Object* Heap::Allocate(Map* map, AllocationSpace space) { |
| 2261 ASSERT(gc_state_ == NOT_IN_GC); | 2313 ASSERT(gc_state_ == NOT_IN_GC); |
| 2262 ASSERT(map->instance_type() != MAP_TYPE); | 2314 ASSERT(map->instance_type() != MAP_TYPE); |
| 2263 // If allocation failures are disallowed, we may allocate in a different | 2315 // If allocation failures are disallowed, we may allocate in a different |
| 2264 // space when new space is full and the object is not a large object. | 2316 // space when new space is full and the object is not a large object. |
| 2265 AllocationSpace retry_space = | 2317 AllocationSpace retry_space = |
| 2266 (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type()); | 2318 (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type()); |
| 2267 Object* result = | 2319 Object* result = |
| 2268 AllocateRaw(map->instance_size(), space, retry_space); | 2320 AllocateRaw(map->instance_size(), space, retry_space); |
| 2269 if (result->IsFailure()) return result; | 2321 if (result->IsFailure()) return result; |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2564 // If we're forced to always allocate, we use the general allocation | 2616 // If we're forced to always allocate, we use the general allocation |
| 2565 // functions which may leave us with an object in old space. | 2617 // functions which may leave us with an object in old space. |
| 2566 if (always_allocate()) { | 2618 if (always_allocate()) { |
| 2567 clone = AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE); | 2619 clone = AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE); |
| 2568 if (clone->IsFailure()) return clone; | 2620 if (clone->IsFailure()) return clone; |
| 2569 Address clone_address = HeapObject::cast(clone)->address(); | 2621 Address clone_address = HeapObject::cast(clone)->address(); |
| 2570 CopyBlock(reinterpret_cast<Object**>(clone_address), | 2622 CopyBlock(reinterpret_cast<Object**>(clone_address), |
| 2571 reinterpret_cast<Object**>(source->address()), | 2623 reinterpret_cast<Object**>(source->address()), |
| 2572 object_size); | 2624 object_size); |
| 2573 // Update write barrier for all fields that lie beyond the header. | 2625 // Update write barrier for all fields that lie beyond the header. |
| 2574 for (int offset = JSObject::kHeaderSize; | 2626 RecordWrites(clone_address, |
| 2575 offset < object_size; | 2627 JSObject::kHeaderSize, |
| 2576 offset += kPointerSize) { | 2628 object_size - JSObject::kHeaderSize); |
| 2577 RecordWrite(clone_address, offset); | |
| 2578 } | |
| 2579 } else { | 2629 } else { |
| 2580 clone = new_space_.AllocateRaw(object_size); | 2630 clone = new_space_.AllocateRaw(object_size); |
| 2581 if (clone->IsFailure()) return clone; | 2631 if (clone->IsFailure()) return clone; |
| 2582 ASSERT(Heap::InNewSpace(clone)); | 2632 ASSERT(Heap::InNewSpace(clone)); |
| 2583 // Since we know the clone is allocated in new space, we can copy | 2633 // Since we know the clone is allocated in new space, we can copy |
| 2584 // the contents without worrying about updating the write barrier. | 2634 // the contents without worrying about updating the write barrier. |
| 2585 CopyBlock(reinterpret_cast<Object**>(HeapObject::cast(clone)->address()), | 2635 CopyBlock(reinterpret_cast<Object**>(HeapObject::cast(clone)->address()), |
| 2586 reinterpret_cast<Object**>(source->address()), | 2636 reinterpret_cast<Object**>(source->address()), |
| 2587 object_size); | 2637 object_size); |
| 2588 } | 2638 } |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2899 | 2949 |
| 2900 Object* Heap::AllocateFixedArray(int length) { | 2950 Object* Heap::AllocateFixedArray(int length) { |
| 2901 ASSERT(length >= 0); | 2951 ASSERT(length >= 0); |
| 2902 if (length == 0) return empty_fixed_array(); | 2952 if (length == 0) return empty_fixed_array(); |
| 2903 Object* result = AllocateRawFixedArray(length); | 2953 Object* result = AllocateRawFixedArray(length); |
| 2904 if (!result->IsFailure()) { | 2954 if (!result->IsFailure()) { |
| 2905 // Initialize header. | 2955 // Initialize header. |
| 2906 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); | 2956 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); |
| 2907 FixedArray* array = FixedArray::cast(result); | 2957 FixedArray* array = FixedArray::cast(result); |
| 2908 array->set_length(length); | 2958 array->set_length(length); |
| 2909 Object* value = undefined_value(); | |
| 2910 // Initialize body. | 2959 // Initialize body. |
| 2911 for (int index = 0; index < length; index++) { | 2960 ASSERT(!Heap::InNewSpace(undefined_value())); |
| 2912 ASSERT(!Heap::InNewSpace(value)); // value = undefined | 2961 MemsetPointer(array->data_start(), undefined_value(), length); |
| 2913 array->set(index, value, SKIP_WRITE_BARRIER); | |
| 2914 } | |
| 2915 } | 2962 } |
| 2916 return result; | 2963 return result; |
| 2917 } | 2964 } |
| 2918 | 2965 |
| 2919 | 2966 |
| 2920 Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { | 2967 Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { |
| 2921 ASSERT(length >= 0); | 2968 ASSERT(length >= 0); |
| 2922 ASSERT(empty_fixed_array()->IsFixedArray()); | 2969 ASSERT(empty_fixed_array()->IsFixedArray()); |
| 2923 if (length < 0 || length > FixedArray::kMaxLength) { | 2970 if (length < 0 || length > FixedArray::kMaxLength) { |
| 2924 return Failure::OutOfMemoryException(); | 2971 return Failure::OutOfMemoryException(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2956 } else { | 3003 } else { |
| 2957 ASSERT(space == LO_SPACE); | 3004 ASSERT(space == LO_SPACE); |
| 2958 result = lo_space_->AllocateRawFixedArray(size); | 3005 result = lo_space_->AllocateRawFixedArray(size); |
| 2959 } | 3006 } |
| 2960 if (result->IsFailure()) return result; | 3007 if (result->IsFailure()) return result; |
| 2961 | 3008 |
| 2962 // Initialize the object. | 3009 // Initialize the object. |
| 2963 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); | 3010 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); |
| 2964 FixedArray* array = FixedArray::cast(result); | 3011 FixedArray* array = FixedArray::cast(result); |
| 2965 array->set_length(length); | 3012 array->set_length(length); |
| 2966 Object* value = undefined_value(); | 3013 ASSERT(!Heap::InNewSpace(undefined_value())); |
| 2967 for (int index = 0; index < length; index++) { | 3014 MemsetPointer(array->data_start(), undefined_value(), length); |
| 2968 ASSERT(!Heap::InNewSpace(value)); // value = undefined | |
| 2969 array->set(index, value, SKIP_WRITE_BARRIER); | |
| 2970 } | |
| 2971 return array; | 3015 return array; |
| 2972 } | 3016 } |
| 2973 | 3017 |
| 2974 | 3018 |
| 2975 Object* Heap::AllocateUninitializedFixedArray(int length) { | 3019 Object* Heap::AllocateUninitializedFixedArray(int length) { |
| 2976 if (length == 0) return empty_fixed_array(); | 3020 if (length == 0) return empty_fixed_array(); |
| 2977 | 3021 |
| 2978 Object* obj = AllocateRawFixedArray(length); | 3022 Object* obj = AllocateRawFixedArray(length); |
| 2979 if (obj->IsFailure()) return obj; | 3023 if (obj->IsFailure()) return obj; |
| 2980 | 3024 |
| 2981 reinterpret_cast<FixedArray*>(obj)->set_map(fixed_array_map()); | 3025 reinterpret_cast<FixedArray*>(obj)->set_map(fixed_array_map()); |
| 2982 FixedArray::cast(obj)->set_length(length); | 3026 FixedArray::cast(obj)->set_length(length); |
| 2983 return obj; | 3027 return obj; |
| 2984 } | 3028 } |
| 2985 | 3029 |
| 2986 | 3030 |
| 2987 Object* Heap::AllocateFixedArrayWithHoles(int length) { | 3031 Object* Heap::AllocateFixedArrayWithHoles(int length) { |
| 2988 if (length == 0) return empty_fixed_array(); | 3032 if (length == 0) return empty_fixed_array(); |
| 2989 Object* result = AllocateRawFixedArray(length); | 3033 Object* result = AllocateRawFixedArray(length); |
| 2990 if (!result->IsFailure()) { | 3034 if (!result->IsFailure()) { |
| 2991 // Initialize header. | 3035 // Initialize header. |
| 2992 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); | 3036 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); |
| 2993 FixedArray* array = FixedArray::cast(result); | 3037 FixedArray* array = FixedArray::cast(result); |
| 2994 array->set_length(length); | 3038 array->set_length(length); |
| 2995 // Initialize body. | 3039 // Initialize body. |
| 2996 ASSERT(!Heap::InNewSpace(the_hole_value())); | 3040 ASSERT(!Heap::InNewSpace(the_hole_value())); |
| 2997 MemsetPointer(HeapObject::RawField(array, FixedArray::kHeaderSize), | 3041 MemsetPointer(array->data_start(), the_hole_value(), length); |
| 2998 the_hole_value(), | |
| 2999 length); | |
| 3000 } | 3042 } |
| 3001 return result; | 3043 return result; |
| 3002 } | 3044 } |
| 3003 | 3045 |
| 3004 | 3046 |
| 3005 Object* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { | 3047 Object* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { |
| 3006 Object* result = Heap::AllocateFixedArray(length, pretenure); | 3048 Object* result = Heap::AllocateFixedArray(length, pretenure); |
| 3007 if (result->IsFailure()) return result; | 3049 if (result->IsFailure()) return result; |
| 3008 reinterpret_cast<Array*>(result)->set_map(hash_table_map()); | 3050 reinterpret_cast<Array*>(result)->set_map(hash_table_map()); |
| 3009 ASSERT(result->IsHashTable()); | 3051 ASSERT(result->IsHashTable()); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3402 ExternalStringTable::Iterate(v); | 3444 ExternalStringTable::Iterate(v); |
| 3403 } | 3445 } |
| 3404 v->Synchronize("external_string_table"); | 3446 v->Synchronize("external_string_table"); |
| 3405 } | 3447 } |
| 3406 | 3448 |
| 3407 | 3449 |
| 3408 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { | 3450 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
| 3409 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); | 3451 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); |
| 3410 v->Synchronize("strong_root_list"); | 3452 v->Synchronize("strong_root_list"); |
| 3411 | 3453 |
| 3412 v->VisitPointer(bit_cast<Object**, String**>(&hidden_symbol_)); | 3454 v->VisitPointer(BitCast<Object**, String**>(&hidden_symbol_)); |
| 3413 v->Synchronize("symbol"); | 3455 v->Synchronize("symbol"); |
| 3414 | 3456 |
| 3415 Bootstrapper::Iterate(v); | 3457 Bootstrapper::Iterate(v); |
| 3416 v->Synchronize("bootstrapper"); | 3458 v->Synchronize("bootstrapper"); |
| 3417 Top::Iterate(v); | 3459 Top::Iterate(v); |
| 3418 v->Synchronize("top"); | 3460 v->Synchronize("top"); |
| 3419 Relocatable::Iterate(v); | 3461 Relocatable::Iterate(v); |
| 3420 v->Synchronize("relocatable"); | 3462 v->Synchronize("relocatable"); |
| 3421 | 3463 |
| 3422 #ifdef ENABLE_DEBUGGER_SUPPORT | 3464 #ifdef ENABLE_DEBUGGER_SUPPORT |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4261 void ExternalStringTable::TearDown() { | 4303 void ExternalStringTable::TearDown() { |
| 4262 new_space_strings_.Free(); | 4304 new_space_strings_.Free(); |
| 4263 old_space_strings_.Free(); | 4305 old_space_strings_.Free(); |
| 4264 } | 4306 } |
| 4265 | 4307 |
| 4266 | 4308 |
| 4267 List<Object*> ExternalStringTable::new_space_strings_; | 4309 List<Object*> ExternalStringTable::new_space_strings_; |
| 4268 List<Object*> ExternalStringTable::old_space_strings_; | 4310 List<Object*> ExternalStringTable::old_space_strings_; |
| 4269 | 4311 |
| 4270 } } // namespace v8::internal | 4312 } } // namespace v8::internal |
| OLD | NEW |