| 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 |