| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 2457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2468 } | 2468 } |
| 2469 cons->set_first(*result); | 2469 cons->set_first(*result); |
| 2470 cons->set_second(isolate->heap()->empty_string()); | 2470 cons->set_second(isolate->heap()->empty_string()); |
| 2471 DCHECK(result->IsFlat()); | 2471 DCHECK(result->IsFlat()); |
| 2472 return result; | 2472 return result; |
| 2473 } | 2473 } |
| 2474 | 2474 |
| 2475 | 2475 |
| 2476 | 2476 |
| 2477 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { | 2477 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { |
| 2478 DisallowHeapAllocation no_allocation; |
| 2478 // Externalizing twice leaks the external resource, so it's | 2479 // Externalizing twice leaks the external resource, so it's |
| 2479 // prohibited by the API. | 2480 // prohibited by the API. |
| 2480 DCHECK(!this->IsExternalString()); | 2481 DCHECK(!this->IsExternalString()); |
| 2481 DCHECK(!resource->IsCompressible()); | 2482 DCHECK(!resource->IsCompressible()); |
| 2482 #ifdef ENABLE_SLOW_DCHECKS | 2483 #ifdef ENABLE_SLOW_DCHECKS |
| 2483 if (FLAG_enable_slow_asserts) { | 2484 if (FLAG_enable_slow_asserts) { |
| 2484 // Assert that the resource and the string are equivalent. | 2485 // Assert that the resource and the string are equivalent. |
| 2485 DCHECK(static_cast<size_t>(this->length()) == resource->length()); | 2486 DCHECK(static_cast<size_t>(this->length()) == resource->length()); |
| 2486 ScopedVector<uc16> smart_chars(this->length()); | 2487 ScopedVector<uc16> smart_chars(this->length()); |
| 2487 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 2488 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 2488 DCHECK(memcmp(smart_chars.start(), | 2489 DCHECK(memcmp(smart_chars.start(), |
| 2489 resource->data(), | 2490 resource->data(), |
| 2490 resource->length() * sizeof(smart_chars[0])) == 0); | 2491 resource->length() * sizeof(smart_chars[0])) == 0); |
| 2491 } | 2492 } |
| 2492 #endif // DEBUG | 2493 #endif // DEBUG |
| 2493 int size = this->Size(); // Byte size of the original string. | 2494 int size = this->Size(); // Byte size of the original string. |
| 2494 // Abort if size does not allow in-place conversion. | 2495 // Abort if size does not allow in-place conversion. |
| 2495 if (size < ExternalString::kShortSize) return false; | 2496 if (size < ExternalString::kShortSize) return false; |
| 2496 Heap* heap = GetHeap(); | 2497 Heap* heap = GetHeap(); |
| 2497 bool is_one_byte = this->IsOneByteRepresentation(); | 2498 bool is_one_byte = this->IsOneByteRepresentation(); |
| 2498 bool is_internalized = this->IsInternalizedString(); | 2499 bool is_internalized = this->IsInternalizedString(); |
| 2499 bool has_pointers = StringShape(this).IsIndirect(); | 2500 bool has_pointers = StringShape(this).IsIndirect(); |
| 2500 | 2501 if (has_pointers) { |
| 2502 heap->NotifyObjectLayoutChange(this, no_allocation); |
| 2503 } |
| 2501 // Morph the string to an external string by replacing the map and | 2504 // Morph the string to an external string by replacing the map and |
| 2502 // reinitializing the fields. This won't work if the space the existing | 2505 // reinitializing the fields. This won't work if the space the existing |
| 2503 // string occupies is too small for a regular external string. | 2506 // string occupies is too small for a regular external string. |
| 2504 // Instead, we resort to a short external string instead, omitting | 2507 // Instead, we resort to a short external string instead, omitting |
| 2505 // the field caching the address of the backing store. When we encounter | 2508 // the field caching the address of the backing store. When we encounter |
| 2506 // short external strings in generated code, we need to bailout to runtime. | 2509 // short external strings in generated code, we need to bailout to runtime. |
| 2507 Map* new_map; | 2510 Map* new_map; |
| 2508 if (size < ExternalString::kSize) { | 2511 if (size < ExternalString::kSize) { |
| 2509 new_map = is_internalized | 2512 new_map = is_internalized |
| 2510 ? (is_one_byte | 2513 ? (is_one_byte |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2536 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); | 2539 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); |
| 2537 self->set_resource(resource); | 2540 self->set_resource(resource); |
| 2538 if (is_internalized) self->Hash(); // Force regeneration of the hash value. | 2541 if (is_internalized) self->Hash(); // Force regeneration of the hash value. |
| 2539 | 2542 |
| 2540 heap->AdjustLiveBytes(this, new_size - size); | 2543 heap->AdjustLiveBytes(this, new_size - size); |
| 2541 return true; | 2544 return true; |
| 2542 } | 2545 } |
| 2543 | 2546 |
| 2544 | 2547 |
| 2545 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) { | 2548 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) { |
| 2549 DisallowHeapAllocation no_allocation; |
| 2546 // Externalizing twice leaks the external resource, so it's | 2550 // Externalizing twice leaks the external resource, so it's |
| 2547 // prohibited by the API. | 2551 // prohibited by the API. |
| 2548 DCHECK(!this->IsExternalString()); | 2552 DCHECK(!this->IsExternalString()); |
| 2549 DCHECK(!resource->IsCompressible()); | 2553 DCHECK(!resource->IsCompressible()); |
| 2550 #ifdef ENABLE_SLOW_DCHECKS | 2554 #ifdef ENABLE_SLOW_DCHECKS |
| 2551 if (FLAG_enable_slow_asserts) { | 2555 if (FLAG_enable_slow_asserts) { |
| 2552 // Assert that the resource and the string are equivalent. | 2556 // Assert that the resource and the string are equivalent. |
| 2553 DCHECK(static_cast<size_t>(this->length()) == resource->length()); | 2557 DCHECK(static_cast<size_t>(this->length()) == resource->length()); |
| 2554 if (this->IsTwoByteRepresentation()) { | 2558 if (this->IsTwoByteRepresentation()) { |
| 2555 ScopedVector<uint16_t> smart_chars(this->length()); | 2559 ScopedVector<uint16_t> smart_chars(this->length()); |
| 2556 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 2560 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 2557 DCHECK(String::IsOneByte(smart_chars.start(), this->length())); | 2561 DCHECK(String::IsOneByte(smart_chars.start(), this->length())); |
| 2558 } | 2562 } |
| 2559 ScopedVector<char> smart_chars(this->length()); | 2563 ScopedVector<char> smart_chars(this->length()); |
| 2560 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 2564 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 2561 DCHECK(memcmp(smart_chars.start(), | 2565 DCHECK(memcmp(smart_chars.start(), |
| 2562 resource->data(), | 2566 resource->data(), |
| 2563 resource->length() * sizeof(smart_chars[0])) == 0); | 2567 resource->length() * sizeof(smart_chars[0])) == 0); |
| 2564 } | 2568 } |
| 2565 #endif // DEBUG | 2569 #endif // DEBUG |
| 2566 int size = this->Size(); // Byte size of the original string. | 2570 int size = this->Size(); // Byte size of the original string. |
| 2567 // Abort if size does not allow in-place conversion. | 2571 // Abort if size does not allow in-place conversion. |
| 2568 if (size < ExternalString::kShortSize) return false; | 2572 if (size < ExternalString::kShortSize) return false; |
| 2569 Heap* heap = GetHeap(); | 2573 Heap* heap = GetHeap(); |
| 2570 bool is_internalized = this->IsInternalizedString(); | 2574 bool is_internalized = this->IsInternalizedString(); |
| 2571 bool has_pointers = StringShape(this).IsIndirect(); | 2575 bool has_pointers = StringShape(this).IsIndirect(); |
| 2572 | 2576 |
| 2577 if (has_pointers) { |
| 2578 heap->NotifyObjectLayoutChange(this, no_allocation); |
| 2579 } |
| 2580 |
| 2573 // Morph the string to an external string by replacing the map and | 2581 // Morph the string to an external string by replacing the map and |
| 2574 // reinitializing the fields. This won't work if the space the existing | 2582 // reinitializing the fields. This won't work if the space the existing |
| 2575 // string occupies is too small for a regular external string. | 2583 // string occupies is too small for a regular external string. |
| 2576 // Instead, we resort to a short external string instead, omitting | 2584 // Instead, we resort to a short external string instead, omitting |
| 2577 // the field caching the address of the backing store. When we encounter | 2585 // the field caching the address of the backing store. When we encounter |
| 2578 // short external strings in generated code, we need to bailout to runtime. | 2586 // short external strings in generated code, we need to bailout to runtime. |
| 2579 Map* new_map; | 2587 Map* new_map; |
| 2580 if (size < ExternalString::kSize) { | 2588 if (size < ExternalString::kSize) { |
| 2581 new_map = is_internalized | 2589 new_map = is_internalized |
| 2582 ? heap->short_external_one_byte_internalized_string_map() | 2590 ? heap->short_external_one_byte_internalized_string_map() |
| (...skipping 14802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17385 } else { | 17393 } else { |
| 17386 // If the external string is duped into an existing non-external | 17394 // If the external string is duped into an existing non-external |
| 17387 // internalized string, free its resource (it's about to be rewritten | 17395 // internalized string, free its resource (it's about to be rewritten |
| 17388 // into a ThinString below). | 17396 // into a ThinString below). |
| 17389 isolate->heap()->FinalizeExternalString(string); | 17397 isolate->heap()->FinalizeExternalString(string); |
| 17390 } | 17398 } |
| 17391 } | 17399 } |
| 17392 | 17400 |
| 17393 if (!string->IsInternalizedString()) { | 17401 if (!string->IsInternalizedString()) { |
| 17394 DisallowHeapAllocation no_gc; | 17402 DisallowHeapAllocation no_gc; |
| 17403 isolate->heap()->NotifyObjectLayoutChange(string, no_gc); |
| 17395 bool one_byte = internalized->IsOneByteRepresentation(); | 17404 bool one_byte = internalized->IsOneByteRepresentation(); |
| 17396 Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map() | 17405 Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map() |
| 17397 : isolate->factory()->thin_string_map(); | 17406 : isolate->factory()->thin_string_map(); |
| 17398 int old_size = string->Size(); | 17407 int old_size = string->Size(); |
| 17399 DCHECK(old_size >= ThinString::kSize); | 17408 DCHECK(old_size >= ThinString::kSize); |
| 17400 string->synchronized_set_map(*map); | 17409 string->synchronized_set_map(*map); |
| 17401 ThinString* thin = ThinString::cast(string); | 17410 ThinString* thin = ThinString::cast(string); |
| 17402 thin->set_actual(internalized); | 17411 thin->set_actual(internalized); |
| 17403 Address thin_end = thin->address() + ThinString::kSize; | 17412 Address thin_end = thin->address() + ThinString::kSize; |
| 17404 int size_delta = old_size - ThinString::kSize; | 17413 int size_delta = old_size - ThinString::kSize; |
| (...skipping 3108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20513 // not | 20522 // not |
| 20514 // depend on this. | 20523 // depend on this. |
| 20515 return DICTIONARY_ELEMENTS; | 20524 return DICTIONARY_ELEMENTS; |
| 20516 } | 20525 } |
| 20517 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20526 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
| 20518 return kind; | 20527 return kind; |
| 20519 } | 20528 } |
| 20520 } | 20529 } |
| 20521 } // namespace internal | 20530 } // namespace internal |
| 20522 } // namespace v8 | 20531 } // namespace v8 |
| OLD | NEW |