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 |