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 2390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2401 map->set_bit_field2(1 << Map::kIsExtensible); | 2401 map->set_bit_field2(1 << Map::kIsExtensible); |
2402 int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) | | 2402 int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) | |
2403 Map::OwnsDescriptors::encode(true); | 2403 Map::OwnsDescriptors::encode(true); |
2404 map->set_bit_field3(bit_field3); | 2404 map->set_bit_field3(bit_field3); |
2405 map->set_elements_kind(elements_kind); | 2405 map->set_elements_kind(elements_kind); |
2406 | 2406 |
2407 return map; | 2407 return map; |
2408 } | 2408 } |
2409 | 2409 |
2410 | 2410 |
2411 MaybeObject* Heap::AllocateCodeCache() { | |
2412 CodeCache* code_cache; | |
2413 { MaybeObject* maybe_code_cache = AllocateStruct(CODE_CACHE_TYPE); | |
2414 if (!maybe_code_cache->To(&code_cache)) return maybe_code_cache; | |
2415 } | |
2416 code_cache->set_default_cache(empty_fixed_array(), SKIP_WRITE_BARRIER); | |
2417 code_cache->set_normal_type_cache(undefined_value(), SKIP_WRITE_BARRIER); | |
2418 return code_cache; | |
2419 } | |
2420 | |
2421 | |
2422 MaybeObject* Heap::AllocatePolymorphicCodeCache() { | 2411 MaybeObject* Heap::AllocatePolymorphicCodeCache() { |
2423 return AllocateStruct(POLYMORPHIC_CODE_CACHE_TYPE); | 2412 return AllocateStruct(POLYMORPHIC_CODE_CACHE_TYPE); |
2424 } | 2413 } |
2425 | 2414 |
2426 | 2415 |
2427 const Heap::StringTypeTable Heap::string_type_table[] = { | 2416 const Heap::StringTypeTable Heap::string_type_table[] = { |
2428 #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ | 2417 #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ |
2429 {type, size, k##camel_name##MapRootIndex}, | 2418 {type, size, k##camel_name##MapRootIndex}, |
2430 STRING_TYPE_LIST(STRING_TYPE_ELEMENT) | 2419 STRING_TYPE_LIST(STRING_TYPE_ELEMENT) |
2431 #undef STRING_TYPE_ELEMENT | 2420 #undef STRING_TYPE_ELEMENT |
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3248 // size to ensure that it is bigger after being made 'full size'. | 3237 // size to ensure that it is bigger after being made 'full size'. |
3249 int number_string_cache_size = max_semispace_size_ / 512; | 3238 int number_string_cache_size = max_semispace_size_ / 512; |
3250 number_string_cache_size = Max(kInitialNumberStringCacheSize * 2, | 3239 number_string_cache_size = Max(kInitialNumberStringCacheSize * 2, |
3251 Min(0x4000, number_string_cache_size)); | 3240 Min(0x4000, number_string_cache_size)); |
3252 // There is a string and a number per entry so the length is twice the number | 3241 // There is a string and a number per entry so the length is twice the number |
3253 // of entries. | 3242 // of entries. |
3254 return number_string_cache_size * 2; | 3243 return number_string_cache_size * 2; |
3255 } | 3244 } |
3256 | 3245 |
3257 | 3246 |
3258 void Heap::AllocateFullSizeNumberStringCache() { | |
3259 // The idea is to have a small number string cache in the snapshot to keep | |
3260 // boot-time memory usage down. If we expand the number string cache already | |
3261 // while creating the snapshot then that didn't work out. | |
3262 ASSERT(!Serializer::enabled() || FLAG_extra_code != NULL); | |
3263 MaybeObject* maybe_obj = | |
3264 AllocateFixedArray(FullSizeNumberStringCacheLength(), TENURED); | |
3265 Object* new_cache; | |
3266 if (maybe_obj->ToObject(&new_cache)) { | |
3267 // We don't bother to repopulate the cache with entries from the old cache. | |
3268 // It will be repopulated soon enough with new strings. | |
3269 set_number_string_cache(FixedArray::cast(new_cache)); | |
3270 } | |
3271 // If allocation fails then we just return without doing anything. It is only | |
3272 // a cache, so best effort is OK here. | |
3273 } | |
3274 | |
3275 | |
3276 void Heap::FlushNumberStringCache() { | 3247 void Heap::FlushNumberStringCache() { |
3277 // Flush the number to string cache. | 3248 // Flush the number to string cache. |
3278 int len = number_string_cache()->length(); | 3249 int len = number_string_cache()->length(); |
3279 for (int i = 0; i < len; i++) { | 3250 for (int i = 0; i < len; i++) { |
3280 number_string_cache()->set_undefined(i); | 3251 number_string_cache()->set_undefined(i); |
3281 } | 3252 } |
3282 } | 3253 } |
3283 | 3254 |
3284 | 3255 |
3285 static inline int double_get_hash(double d) { | |
3286 DoubleRepresentation rep(d); | |
3287 return static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32); | |
3288 } | |
3289 | |
3290 | |
3291 static inline int smi_get_hash(Smi* smi) { | |
3292 return smi->value(); | |
3293 } | |
3294 | |
3295 | |
3296 Object* Heap::GetNumberStringCache(Object* number) { | |
3297 int hash; | |
3298 int mask = (number_string_cache()->length() >> 1) - 1; | |
3299 if (number->IsSmi()) { | |
3300 hash = smi_get_hash(Smi::cast(number)) & mask; | |
3301 } else { | |
3302 hash = double_get_hash(number->Number()) & mask; | |
3303 } | |
3304 Object* key = number_string_cache()->get(hash * 2); | |
3305 if (key == number) { | |
3306 return String::cast(number_string_cache()->get(hash * 2 + 1)); | |
3307 } else if (key->IsHeapNumber() && | |
3308 number->IsHeapNumber() && | |
3309 key->Number() == number->Number()) { | |
3310 return String::cast(number_string_cache()->get(hash * 2 + 1)); | |
3311 } | |
3312 return undefined_value(); | |
3313 } | |
3314 | |
3315 | |
3316 void Heap::SetNumberStringCache(Object* number, String* string) { | |
3317 int hash; | |
3318 int mask = (number_string_cache()->length() >> 1) - 1; | |
3319 if (number->IsSmi()) { | |
3320 hash = smi_get_hash(Smi::cast(number)) & mask; | |
3321 } else { | |
3322 hash = double_get_hash(number->Number()) & mask; | |
3323 } | |
3324 if (number_string_cache()->get(hash * 2) != undefined_value() && | |
3325 number_string_cache()->length() != FullSizeNumberStringCacheLength()) { | |
3326 // The first time we have a hash collision, we move to the full sized | |
3327 // number string cache. | |
3328 AllocateFullSizeNumberStringCache(); | |
3329 return; | |
3330 } | |
3331 number_string_cache()->set(hash * 2, number); | |
3332 number_string_cache()->set(hash * 2 + 1, string); | |
3333 } | |
3334 | |
3335 | |
3336 MaybeObject* Heap::NumberToString(Object* number, | |
3337 bool check_number_string_cache) { | |
3338 isolate_->counters()->number_to_string_runtime()->Increment(); | |
3339 if (check_number_string_cache) { | |
3340 Object* cached = GetNumberStringCache(number); | |
3341 if (cached != undefined_value()) { | |
3342 return cached; | |
3343 } | |
3344 } | |
3345 | |
3346 char arr[100]; | |
3347 Vector<char> buffer(arr, ARRAY_SIZE(arr)); | |
3348 const char* str; | |
3349 if (number->IsSmi()) { | |
3350 int num = Smi::cast(number)->value(); | |
3351 str = IntToCString(num, buffer); | |
3352 } else { | |
3353 double num = HeapNumber::cast(number)->value(); | |
3354 str = DoubleToCString(num, buffer); | |
3355 } | |
3356 | |
3357 Object* js_string; | |
3358 | |
3359 // We tenure the allocated string since it is referenced from the | |
3360 // number-string cache which lives in the old space. | |
3361 MaybeObject* maybe_js_string = | |
3362 AllocateStringFromOneByte(CStrVector(str), TENURED); | |
3363 if (maybe_js_string->ToObject(&js_string)) { | |
3364 SetNumberStringCache(number, String::cast(js_string)); | |
3365 } | |
3366 return maybe_js_string; | |
3367 } | |
3368 | |
3369 | |
3370 MaybeObject* Heap::Uint32ToString(uint32_t value, | |
3371 bool check_number_string_cache) { | |
3372 Object* number; | |
3373 MaybeObject* maybe = NumberFromUint32(value); | |
3374 if (!maybe->To<Object>(&number)) return maybe; | |
3375 return NumberToString(number, check_number_string_cache); | |
3376 } | |
3377 | |
3378 | |
3379 MaybeObject* Heap::AllocateAllocationSitesScratchpad() { | 3256 MaybeObject* Heap::AllocateAllocationSitesScratchpad() { |
3380 MaybeObject* maybe_obj = | 3257 MaybeObject* maybe_obj = |
3381 AllocateFixedArray(kAllocationSiteScratchpadSize, TENURED); | 3258 AllocateFixedArray(kAllocationSiteScratchpadSize, TENURED); |
3382 return maybe_obj; | 3259 return maybe_obj; |
3383 } | 3260 } |
3384 | 3261 |
3385 | 3262 |
3386 void Heap::FlushAllocationSitesScratchpad() { | 3263 void Heap::FlushAllocationSitesScratchpad() { |
3387 for (int i = 0; i < allocation_sites_scratchpad_length_; i++) { | 3264 for (int i = 0; i < allocation_sites_scratchpad_length_; i++) { |
3388 allocation_sites_scratchpad()->set_undefined(i); | 3265 allocation_sites_scratchpad()->set_undefined(i); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3506 roots_[RootIndexForEmptyExternalArray(map->elements_kind())]); | 3383 roots_[RootIndexForEmptyExternalArray(map->elements_kind())]); |
3507 } | 3384 } |
3508 | 3385 |
3509 | 3386 |
3510 FixedTypedArrayBase* Heap::EmptyFixedTypedArrayForMap(Map* map) { | 3387 FixedTypedArrayBase* Heap::EmptyFixedTypedArrayForMap(Map* map) { |
3511 return FixedTypedArrayBase::cast( | 3388 return FixedTypedArrayBase::cast( |
3512 roots_[RootIndexForEmptyFixedTypedArray(map->elements_kind())]); | 3389 roots_[RootIndexForEmptyFixedTypedArray(map->elements_kind())]); |
3513 } | 3390 } |
3514 | 3391 |
3515 | 3392 |
3516 MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) { | |
3517 // We need to distinguish the minus zero value and this cannot be | |
3518 // done after conversion to int. Doing this by comparing bit | |
3519 // patterns is faster than using fpclassify() et al. | |
3520 if (IsMinusZero(value)) { | |
3521 return AllocateHeapNumber(-0.0, pretenure); | |
3522 } | |
3523 | |
3524 int int_value = FastD2I(value); | |
3525 if (value == int_value && Smi::IsValid(int_value)) { | |
3526 return Smi::FromInt(int_value); | |
3527 } | |
3528 | |
3529 // Materialize the value in the heap. | |
3530 return AllocateHeapNumber(value, pretenure); | |
3531 } | |
3532 | |
3533 | |
3534 MaybeObject* Heap::AllocateForeign(Address address, PretenureFlag pretenure) { | 3393 MaybeObject* Heap::AllocateForeign(Address address, PretenureFlag pretenure) { |
3535 // Statically ensure that it is safe to allocate foreigns in paged spaces. | 3394 // Statically ensure that it is safe to allocate foreigns in paged spaces. |
3536 STATIC_ASSERT(Foreign::kSize <= Page::kMaxRegularHeapObjectSize); | 3395 STATIC_ASSERT(Foreign::kSize <= Page::kMaxRegularHeapObjectSize); |
3537 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | 3396 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
3538 Foreign* result; | 3397 Foreign* result; |
3539 MaybeObject* maybe_result = Allocate(foreign_map(), space); | 3398 MaybeObject* maybe_result = Allocate(foreign_map(), space); |
3540 if (!maybe_result->To(&result)) return maybe_result; | 3399 if (!maybe_result->To(&result)) return maybe_result; |
3541 result->set_foreign_address(address); | 3400 result->set_foreign_address(address); |
3542 return result; | 3401 return result; |
3543 } | 3402 } |
(...skipping 3520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7064 static_cast<int>(object_sizes_last_time_[index])); | 6923 static_cast<int>(object_sizes_last_time_[index])); |
7065 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6924 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
7066 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6925 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
7067 | 6926 |
7068 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6927 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
7069 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6928 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
7070 ClearObjectStats(); | 6929 ClearObjectStats(); |
7071 } | 6930 } |
7072 | 6931 |
7073 } } // namespace v8::internal | 6932 } } // namespace v8::internal |
OLD | NEW |