| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 15 matching lines...) Expand all Loading... |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include <limits.h> | 28 #include <limits.h> |
| 29 | 29 |
| 30 #include "v8.h" | 30 #include "v8.h" |
| 31 | 31 |
| 32 #include "api.h" | 32 #include "api.h" |
| 33 #include "isolate.h" | 33 #include "isolate.h" |
| 34 #include "compilation-cache.h" | 34 #include "compilation-cache.h" |
| 35 #include "execution.h" | 35 #include "execution.h" |
| 36 #include "handles.h" | |
| 37 #include "snapshot.h" | 36 #include "snapshot.h" |
| 38 #include "platform.h" | 37 #include "platform.h" |
| 39 #include "utils.h" | 38 #include "utils.h" |
| 40 #include "cctest.h" | 39 #include "cctest.h" |
| 41 #include "parser.h" | 40 #include "parser.h" |
| 42 #include "unicode-inl.h" | 41 #include "unicode-inl.h" |
| 43 | 42 |
| 44 static const bool kLogThreading = false; | 43 static const bool kLogThreading = false; |
| 45 | 44 |
| 46 static bool IsNaN(double x) { | 45 static bool IsNaN(double x) { |
| (...skipping 15387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15434 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]"))); | 15433 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]"))); |
| 15435 | 15434 |
| 15436 // TODO(1547): Make the following also return "i". | 15435 // TODO(1547): Make the following also return "i". |
| 15437 // Calling with environment record as base. | 15436 // Calling with environment record as base. |
| 15438 TestReceiver(o, context->Global(), "func()"); | 15437 TestReceiver(o, context->Global(), "func()"); |
| 15439 // Calling with no base. | 15438 // Calling with no base. |
| 15440 TestReceiver(o, context->Global(), "(1,func)()"); | 15439 TestReceiver(o, context->Global(), "(1,func)()"); |
| 15441 | 15440 |
| 15442 foreign_context.Dispose(); | 15441 foreign_context.Dispose(); |
| 15443 } | 15442 } |
| 15444 | |
| 15445 | |
| 15446 | |
| 15447 class SimpleTestResource: public String::ExternalStringResource { | |
| 15448 public: | |
| 15449 explicit SimpleTestResource(const uint16_t* data) : data_(data), length_(0) { | |
| 15450 while (data[length_] != 0) length_++; | |
| 15451 } | |
| 15452 virtual ~SimpleTestResource() { } | |
| 15453 virtual const uint16_t* data() const { return data_; } | |
| 15454 virtual size_t length() const { return length_; } | |
| 15455 private: | |
| 15456 const uint16_t* data_; | |
| 15457 int length_; | |
| 15458 }; | |
| 15459 | |
| 15460 | |
| 15461 THREADED_TEST(StringLock) { | |
| 15462 v8::HandleScope scope; | |
| 15463 LocalContext env; | |
| 15464 | |
| 15465 i::Isolate* isolate = i::Isolate::Current(); | |
| 15466 i::Heap* heap = isolate->heap(); | |
| 15467 | |
| 15468 // ASCII text of test strings. | |
| 15469 const char* text = "Lorem ipsum dolor sic amet."; | |
| 15470 const size_t kTextLength = 27; | |
| 15471 CHECK(strlen(text) == kTextLength); | |
| 15472 // UC16 version of string. | |
| 15473 uint16_t uc16_text[kTextLength + 1]; | |
| 15474 for (unsigned i = 0; i <= kTextLength; i++) { | |
| 15475 uc16_text[i] = static_cast<uint16_t>(text[i]); | |
| 15476 } | |
| 15477 | |
| 15478 // Create some different strings and move them to old-space, | |
| 15479 // so that externalization can succeede. | |
| 15480 Local<String> s1 = v8_str(text); | |
| 15481 Local<String> s2 = v8_str(text + 1); | |
| 15482 Local<String> s3 = v8_str(text + 2); | |
| 15483 heap->CollectGarbage(i::NEW_SPACE); | |
| 15484 heap->CollectGarbage(i::NEW_SPACE); | |
| 15485 | |
| 15486 SimpleTestResource* r1 = new SimpleTestResource(uc16_text); | |
| 15487 SimpleTestResource* r2 = new SimpleTestResource(uc16_text + 1); | |
| 15488 SimpleTestResource* r3 = new SimpleTestResource(uc16_text + 2); | |
| 15489 | |
| 15490 // Check that externalization works. | |
| 15491 CHECK(!s1->IsExternal()); | |
| 15492 CHECK(s1->MakeExternal(r1)); | |
| 15493 CHECK(s1->IsExternal()); | |
| 15494 | |
| 15495 // Externalize while the string is locked. | |
| 15496 | |
| 15497 // Use the direct interface to string locking. | |
| 15498 i::Handle<i::String> s2i(v8::Utils::OpenHandle(*s2)); | |
| 15499 CHECK(!heap->IsStringLocked(*s2i)); | |
| 15500 LockString(s2i); // Use handle version, not Heap::LockString, to allow GC. | |
| 15501 CHECK(isolate->heap()->IsStringLocked(*s2i)); | |
| 15502 | |
| 15503 CHECK(!s2->IsExternal()); | |
| 15504 CHECK(!s2->MakeExternal(r2)); | |
| 15505 CHECK(!s2->IsExternal()); | |
| 15506 | |
| 15507 CHECK(heap->IsStringLocked(*s2i)); | |
| 15508 heap->UnlockString(*s2i); | |
| 15509 CHECK(!heap->IsStringLocked(*s2i)); | |
| 15510 | |
| 15511 CHECK(!s2->IsExternal()); | |
| 15512 CHECK(s2->MakeExternal(r2)); | |
| 15513 CHECK(s2->IsExternal()); | |
| 15514 | |
| 15515 // Use the Handle-based scoped StringLock. | |
| 15516 i::Handle<i::String> s3i(v8::Utils::OpenHandle(*s3)); | |
| 15517 { | |
| 15518 CHECK(!heap->IsStringLocked(*s3i)); | |
| 15519 i::StringLock lock(s3i); | |
| 15520 CHECK(heap->IsStringLocked(*s3i)); | |
| 15521 | |
| 15522 CHECK(!s3->IsExternal()); | |
| 15523 CHECK(!s3->MakeExternal(r3)); | |
| 15524 CHECK(!s3->IsExternal()); | |
| 15525 | |
| 15526 CHECK(heap->IsStringLocked(*s3i)); | |
| 15527 } | |
| 15528 CHECK(!heap->IsStringLocked(*s3i)); | |
| 15529 | |
| 15530 CHECK(!s3->IsExternal()); | |
| 15531 CHECK(s3->MakeExternal(r3)); | |
| 15532 CHECK(s3->IsExternal()); | |
| 15533 } | |
| 15534 | |
| 15535 | |
| 15536 THREADED_TEST(MultiStringLock) { | |
| 15537 v8::HandleScope scope; | |
| 15538 LocalContext env; | |
| 15539 i::Isolate* isolate = i::Isolate::Current(); | |
| 15540 i::Heap* heap = isolate->heap(); | |
| 15541 const char* text = "Lorem ipsum dolor sic amet."; | |
| 15542 | |
| 15543 const int N = 16; // Must be power of 2. | |
| 15544 CHECK_GT(strlen(text), static_cast<size_t>(N)); | |
| 15545 | |
| 15546 // Create a bunch of different strings. | |
| 15547 i::Handle<i::String> strings[N]; | |
| 15548 | |
| 15549 for (int i = 0; i < N; i++) { | |
| 15550 Local<String> s = v8_str(text + i); | |
| 15551 strings[i] = v8::Utils::OpenHandle(*s); | |
| 15552 } | |
| 15553 | |
| 15554 heap->CollectGarbage(i::NEW_SPACE); | |
| 15555 heap->CollectGarbage(i::NEW_SPACE); | |
| 15556 | |
| 15557 // Check that start out are unlocked. | |
| 15558 for (int i = 0; i < N; i++) { | |
| 15559 CHECK(!heap->IsStringLocked(*strings[i])); | |
| 15560 } | |
| 15561 | |
| 15562 // Lock them, one at a time. | |
| 15563 for (int i = 0; i < N; i++) { | |
| 15564 LockString(strings[i]); | |
| 15565 for (int j = 0; j < N; j++) { | |
| 15566 if (j <= i) { | |
| 15567 CHECK(heap->IsStringLocked(*strings[j])); | |
| 15568 } else { | |
| 15569 CHECK(!heap->IsStringLocked(*strings[j])); | |
| 15570 } | |
| 15571 } | |
| 15572 } | |
| 15573 | |
| 15574 // Unlock them in a slightly different order (not same as locking, | |
| 15575 // nor the reverse order). | |
| 15576 for (int i = 0; i < N; i++) { | |
| 15577 int mix_i = i ^ 3; | |
| 15578 heap->UnlockString(*strings[mix_i]); | |
| 15579 for (int j = 0; j < N; j++) { | |
| 15580 int unmix_j = j ^ 3; | |
| 15581 if (unmix_j <= i) { | |
| 15582 CHECK(!heap->IsStringLocked(*strings[j])); | |
| 15583 } else { | |
| 15584 CHECK(heap->IsStringLocked(*strings[j])); | |
| 15585 } | |
| 15586 } | |
| 15587 } | |
| 15588 } | |
| 15589 | |
| 15590 | |
| 15591 THREADED_TEST(DuplicateStringLock) { | |
| 15592 v8::HandleScope scope; | |
| 15593 LocalContext env; | |
| 15594 i::Isolate* isolate = i::Isolate::Current(); | |
| 15595 i::Heap* heap = isolate->heap(); | |
| 15596 const char* text = "Lorem ipsum dolor sic amet."; | |
| 15597 | |
| 15598 const int N = 16; // Must be power of 2. | |
| 15599 CHECK_GT(strlen(text), static_cast<size_t>(N)); | |
| 15600 | |
| 15601 // Create a bunch of different strings. | |
| 15602 i::Handle<i::String> strings[N]; | |
| 15603 | |
| 15604 for (int i = 0; i < N; i++) { | |
| 15605 Local<String> s = v8_str(text + i); | |
| 15606 strings[i] = v8::Utils::OpenHandle(*s); | |
| 15607 } | |
| 15608 | |
| 15609 heap->CollectGarbage(i::NEW_SPACE); | |
| 15610 heap->CollectGarbage(i::NEW_SPACE); | |
| 15611 | |
| 15612 // Check that strings start out unlocked. | |
| 15613 for (int i = 0; i < N; i++) { | |
| 15614 CHECK(!heap->IsStringLocked(*strings[i])); | |
| 15615 } | |
| 15616 | |
| 15617 // Lock them, one at a time. | |
| 15618 for (int i = 0; i < N; i++) { | |
| 15619 LockString(strings[i]); | |
| 15620 for (int j = 0; j < N; j++) { | |
| 15621 if (j <= i) { | |
| 15622 CHECK(heap->IsStringLocked(*strings[j])); | |
| 15623 } else { | |
| 15624 CHECK(!heap->IsStringLocked(*strings[j])); | |
| 15625 } | |
| 15626 } | |
| 15627 } | |
| 15628 | |
| 15629 // Lock the first half of them a second time. | |
| 15630 for (int i = 0; i < N / 2; i++) { | |
| 15631 LockString(strings[i]); | |
| 15632 for (int j = 0; j < N; j++) { | |
| 15633 CHECK(heap->IsStringLocked(*strings[j])); | |
| 15634 } | |
| 15635 } | |
| 15636 | |
| 15637 // Unlock them in a slightly different order (not same as locking, | |
| 15638 // nor the reverse order). | |
| 15639 for (int i = 0; i < N; i++) { | |
| 15640 int mix_i = i ^ 3; | |
| 15641 heap->UnlockString(*strings[mix_i]); | |
| 15642 for (int j = 0; j < N; j++) { | |
| 15643 int unmix_j = j ^ 3; | |
| 15644 if (unmix_j <= i && j >= N / 2) { | |
| 15645 CHECK(!heap->IsStringLocked(*strings[j])); | |
| 15646 } else { | |
| 15647 CHECK(heap->IsStringLocked(*strings[j])); | |
| 15648 } | |
| 15649 } | |
| 15650 } | |
| 15651 | |
| 15652 // Unlock the first half again. | |
| 15653 for (int i = 0; i < N / 2; i++) { | |
| 15654 heap->UnlockString(*strings[i]); | |
| 15655 for (int j = 0; j < N; j++) { | |
| 15656 if (j <= i || j >= N/ 2) { | |
| 15657 CHECK(!heap->IsStringLocked(*strings[j])); | |
| 15658 } else { | |
| 15659 CHECK(heap->IsStringLocked(*strings[j])); | |
| 15660 } | |
| 15661 } | |
| 15662 } | |
| 15663 } | |
| OLD | NEW |