| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 | 2 |
| 3 // Check that we can traverse very deep stacks of ConsStrings using | 3 // Check that we can traverse very deep stacks of ConsStrings using |
| 4 // StringInputBuffer. Check that Get(int) works on very deep stacks | 4 // StringInputBuffer. Check that Get(int) works on very deep stacks |
| 5 // of ConsStrings. These operations may not be very fast, but they | 5 // of ConsStrings. These operations may not be very fast, but they |
| 6 // should be possible without getting errors due to too deep recursion. | 6 // should be possible without getting errors due to too deep recursion. |
| 7 | 7 |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 | 9 |
| 10 #include "v8.h" | 10 #include "v8.h" |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 | 424 |
| 425 // Setup lengths that guarantee we'll get slices instead of simple | 425 // Setup lengths that guarantee we'll get slices instead of simple |
| 426 // flat strings. | 426 // flat strings. |
| 427 static const int kFullStringLength = String::kMinNonFlatLength * 2; | 427 static const int kFullStringLength = String::kMinNonFlatLength * 2; |
| 428 static const int kSliceStringLength = String::kMinNonFlatLength + 1; | 428 static const int kSliceStringLength = String::kMinNonFlatLength + 1; |
| 429 | 429 |
| 430 uint16_t* source = new uint16_t[kFullStringLength]; | 430 uint16_t* source = new uint16_t[kFullStringLength]; |
| 431 for (int i = 0; i < kFullStringLength; i++) source[i] = '1'; | 431 for (int i = 0; i < kFullStringLength; i++) source[i] = '1'; |
| 432 char* key = new char[kSliceStringLength]; | 432 char* key = new char[kSliceStringLength]; |
| 433 for (int i = 0; i < kSliceStringLength; i++) key[i] = '1'; | 433 for (int i = 0; i < kSliceStringLength; i++) key[i] = '1'; |
| 434 Vector<const char> key_vector(key, kSliceStringLength); |
| 434 | 435 |
| 435 // Allocate an external string resource that keeps track of when it | 436 // Allocate an external string resource that keeps track of when it |
| 436 // is destructed. | 437 // is destructed. |
| 437 bool resource_destructed = false; | 438 bool resource_destructed = false; |
| 438 TwoByteResource* resource = | 439 TwoByteResource* resource = |
| 439 new TwoByteResource(source, kFullStringLength, &resource_destructed); | 440 new TwoByteResource(source, kFullStringLength, &resource_destructed); |
| 440 | 441 |
| 441 { | 442 { |
| 442 v8::HandleScope scope; | 443 v8::HandleScope scope; |
| 443 | 444 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 Handle<JSObject> wrapper = GetScriptWrapper(script); | 476 Handle<JSObject> wrapper = GetScriptWrapper(script); |
| 476 } | 477 } |
| 477 | 478 |
| 478 // When we collect all garbage, we cannot get rid of the sliced | 479 // When we collect all garbage, we cannot get rid of the sliced |
| 479 // symbol entry in the symbol table because it is used by the script | 480 // symbol entry in the symbol table because it is used by the script |
| 480 // kept alive by the weak wrapper. Make sure we don't destruct the | 481 // kept alive by the weak wrapper. Make sure we don't destruct the |
| 481 // external string. | 482 // external string. |
| 482 Heap::CollectAllGarbage(); | 483 Heap::CollectAllGarbage(); |
| 483 CHECK(!resource_destructed); | 484 CHECK(!resource_destructed); |
| 484 | 485 |
| 485 // Make sure the sliced symbol is still in the table. | 486 { |
| 487 v8::HandleScope scope; |
| 488 |
| 489 // Make sure the sliced symbol is still in the table. |
| 490 Handle<String> symbol = Factory::LookupSymbol(key_vector); |
| 491 CHECK(StringShape(*symbol).IsSliced()); |
| 492 |
| 493 // Make sure the buffer is still a two-byte external string. |
| 494 Handle<String> buffer(Handle<SlicedString>::cast(symbol)->buffer()); |
| 495 CHECK(StringShape(*buffer).IsExternal()); |
| 496 CHECK(buffer->IsTwoByteRepresentation()); |
| 497 } |
| 498 |
| 499 // Forcing another garbage collection should let us get rid of the |
| 500 // slice from the symbol table. The external string remains in the |
| 501 // heap until the next GC. |
| 502 Heap::CollectAllGarbage(); |
| 503 CHECK(!resource_destructed); |
| 486 v8::HandleScope scope; | 504 v8::HandleScope scope; |
| 487 Vector<const char> vector(key, kSliceStringLength); | 505 Handle<String> key_string = Factory::NewStringFromAscii(key_vector); |
| 488 Handle<String> symbol = Factory::LookupSymbol(vector); | 506 String* out; |
| 489 CHECK(StringShape(*symbol).IsSliced()); | 507 CHECK(!Heap::LookupSymbolIfExists(*key_string, &out)); |
| 490 | 508 |
| 491 // Make sure the buffer is still a two-byte external string. | 509 // Forcing yet another garbage collection must allow us to finally |
| 492 Handle<String> buffer(Handle<SlicedString>::cast(symbol)->buffer()); | 510 // get rid of the external string. |
| 493 CHECK(StringShape(*buffer).IsExternal()); | 511 Heap::CollectAllGarbage(); |
| 494 CHECK(buffer->IsTwoByteRepresentation()); | 512 CHECK(resource_destructed); |
| 495 | 513 |
| 496 delete[] source; | 514 delete[] source; |
| 497 delete[] key; | 515 delete[] key; |
| 498 } | 516 } |
| OLD | NEW |