| 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 } | 56 } |
| 57 virtual const uint16_t* data() const { return data_; } | 57 virtual const uint16_t* data() const { return data_; } |
| 58 virtual size_t length() const { return length_; } | 58 virtual size_t length() const { return length_; } |
| 59 | 59 |
| 60 private: | 60 private: |
| 61 const uc16* data_; | 61 const uc16* data_; |
| 62 size_t length_; | 62 size_t length_; |
| 63 }; | 63 }; |
| 64 | 64 |
| 65 | 65 |
| 66 class AsciiResource: public v8::String::ExternalAsciiStringResource, |
| 67 public ZoneObject { |
| 68 public: |
| 69 explicit AsciiResource(Vector<const char> string): data_(string.start()) { |
| 70 length_ = string.length(); |
| 71 } |
| 72 virtual const char* data() const { return data_; } |
| 73 virtual size_t length() const { return length_; } |
| 74 |
| 75 private: |
| 76 const char* data_; |
| 77 size_t length_; |
| 78 }; |
| 79 |
| 80 |
| 66 static void InitializeBuildingBlocks( | 81 static void InitializeBuildingBlocks( |
| 67 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) { | 82 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) { |
| 68 // A list of pointers that we don't have any interest in cleaning up. | 83 // A list of pointers that we don't have any interest in cleaning up. |
| 69 // If they are reachable from a root then leak detection won't complain. | 84 // If they are reachable from a root then leak detection won't complain. |
| 70 for (int i = 0; i < NUMBER_OF_BUILDING_BLOCKS; i++) { | 85 for (int i = 0; i < NUMBER_OF_BUILDING_BLOCKS; i++) { |
| 71 int len = gen() % 16; | 86 int len = gen() % 16; |
| 72 if (len > 14) { | 87 if (len > 14) { |
| 73 len += 1234; | 88 len += 1234; |
| 74 } | 89 } |
| 75 switch (gen() % 4) { | 90 switch (gen() % 4) { |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 // Check that the contents are correct | 400 // Check that the contents are correct |
| 386 for (int j = 0; j < lengths[i]; j++) | 401 for (int j = 0; j < lengths[i]; j++) |
| 387 CHECK_EQ(as_utf8[j], static_cast<unsigned char>(buffer[j])); | 402 CHECK_EQ(as_utf8[j], static_cast<unsigned char>(buffer[j])); |
| 388 // Check that the rest of the buffer hasn't been touched | 403 // Check that the rest of the buffer hasn't been touched |
| 389 for (int j = lengths[i]; j < 11; j++) | 404 for (int j = lengths[i]; j < 11; j++) |
| 390 CHECK_EQ(kNoChar, buffer[j]); | 405 CHECK_EQ(kNoChar, buffer[j]); |
| 391 } | 406 } |
| 392 } | 407 } |
| 393 | 408 |
| 394 | 409 |
| 410 TEST(ExternalShortStringAdd) { |
| 411 ZoneScope zone(DELETE_ON_EXIT); |
| 412 |
| 413 InitializeVM(); |
| 414 v8::HandleScope handle_scope; |
| 415 |
| 416 // Make sure we cover all always-flat lengths and at least one above. |
| 417 static const int kMaxLength = 20; |
| 418 CHECK_GT(kMaxLength, i::String::kMinNonFlatLength); |
| 419 |
| 420 // Allocate two JavaScript arrays for holding short strings. |
| 421 v8::Handle<v8::Array> ascii_external_strings = |
| 422 v8::Array::New(kMaxLength + 1); |
| 423 v8::Handle<v8::Array> non_ascii_external_strings = |
| 424 v8::Array::New(kMaxLength + 1); |
| 425 |
| 426 // Generate short ascii and non-ascii external strings. |
| 427 for (int i = 0; i <= kMaxLength; i++) { |
| 428 char* ascii = Zone::NewArray<char>(i + 1); |
| 429 for (int j = 0; j < i; j++) { |
| 430 ascii[j] = 'a'; |
| 431 } |
| 432 // Terminating '\0' is left out on purpose. It is not required for external |
| 433 // string data. |
| 434 AsciiResource* ascii_resource = |
| 435 new AsciiResource(Vector<const char>(ascii, i)); |
| 436 v8::Local<v8::String> ascii_external_string = |
| 437 v8::String::NewExternal(ascii_resource); |
| 438 |
| 439 ascii_external_strings->Set(v8::Integer::New(i), ascii_external_string); |
| 440 uc16* non_ascii = Zone::NewArray<uc16>(i + 1); |
| 441 for (int j = 0; j < i; j++) { |
| 442 non_ascii[j] = 1234; |
| 443 } |
| 444 // Terminating '\0' is left out on purpose. It is not required for external |
| 445 // string data. |
| 446 Resource* resource = new Resource(Vector<const uc16>(non_ascii, i)); |
| 447 v8::Local<v8::String> non_ascii_external_string = |
| 448 v8::String::NewExternal(resource); |
| 449 non_ascii_external_strings->Set(v8::Integer::New(i), |
| 450 non_ascii_external_string); |
| 451 } |
| 452 |
| 453 // Add the arrays with the short external strings in the global object. |
| 454 v8::Handle<v8::Object> global = env->Global(); |
| 455 global->Set(v8::String::New("ascii"), ascii_external_strings); |
| 456 global->Set(v8::String::New("non_ascii"), non_ascii_external_strings); |
| 457 |
| 458 // Add short external ascii and non-ascii strings checking the result. |
| 459 static const char* source = |
| 460 "function test() {" |
| 461 " for (var i = 0; i <= 20; i++) {" |
| 462 " for (var j = 0; j < i; j++) {" |
| 463 " if (non_ascii[i] != (non_ascii[j] + non_ascii[i - j])) return false;" |
| 464 " if (ascii[i] != (ascii[j] + ascii[i - j])) return false;" |
| 465 " }" |
| 466 " }" |
| 467 " return true;" |
| 468 "};" |
| 469 "test()"; |
| 470 CHECK(v8::Script::Compile(v8::String::New(source))->Run()->BooleanValue()); |
| 471 } |
| 472 |
| 473 |
| 395 class TwoByteResource: public v8::String::ExternalStringResource { | 474 class TwoByteResource: public v8::String::ExternalStringResource { |
| 396 public: | 475 public: |
| 397 TwoByteResource(const uint16_t* data, size_t length, bool* destructed) | 476 TwoByteResource(const uint16_t* data, size_t length, bool* destructed) |
| 398 : data_(data), length_(length), destructed_(destructed) { | 477 : data_(data), length_(length), destructed_(destructed) { |
| 399 CHECK_NE(destructed, NULL); | 478 CHECK_NE(destructed, NULL); |
| 400 *destructed_ = false; | 479 *destructed_ = false; |
| 401 } | 480 } |
| 402 | 481 |
| 403 virtual ~TwoByteResource() { | 482 virtual ~TwoByteResource() { |
| 404 CHECK_NE(destructed_, NULL); | 483 CHECK_NE(destructed_, NULL); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 CHECK(!Heap::LookupSymbolIfExists(*key_string, &out)); | 588 CHECK(!Heap::LookupSymbolIfExists(*key_string, &out)); |
| 510 | 589 |
| 511 // Forcing yet another garbage collection must allow us to finally | 590 // Forcing yet another garbage collection must allow us to finally |
| 512 // get rid of the external string. | 591 // get rid of the external string. |
| 513 Heap::CollectAllGarbage(false); | 592 Heap::CollectAllGarbage(false); |
| 514 CHECK(resource_destructed); | 593 CHECK(resource_destructed); |
| 515 | 594 |
| 516 delete[] source; | 595 delete[] source; |
| 517 delete[] key; | 596 delete[] key; |
| 518 } | 597 } |
| OLD | NEW |