OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 11 matching lines...) Expand all Loading... | |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
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 <climits> | 28 #include <climits> |
29 #include <csignal> | 29 #include <csignal> |
30 #include <string> | 30 #include <string> |
31 #include <map> | 31 #include <map> |
32 #include <utility> | |
Michael Starzinger
2013/12/02 15:34:10
nit: Can we alpha-sort the system includes block?
Sven Panne
2013/12/02 17:30:53
Done.
| |
32 | 33 |
33 #include "v8.h" | 34 #include "v8.h" |
34 | 35 |
35 #if V8_OS_POSIX | 36 #if V8_OS_POSIX |
36 #include <unistd.h> // NOLINT | 37 #include <unistd.h> // NOLINT |
37 #endif | 38 #endif |
38 | 39 |
39 #include "api.h" | 40 #include "api.h" |
40 #include "arguments.h" | 41 #include "arguments.h" |
41 #include "cctest.h" | 42 #include "cctest.h" |
42 #include "compilation-cache.h" | 43 #include "compilation-cache.h" |
43 #include "cpu-profiler.h" | 44 #include "cpu-profiler.h" |
44 #include "execution.h" | 45 #include "execution.h" |
45 #include "isolate.h" | 46 #include "isolate.h" |
46 #include "objects.h" | 47 #include "objects.h" |
47 #include "parser.h" | 48 #include "parser.h" |
48 #include "platform.h" | 49 #include "platform.h" |
49 #include "snapshot.h" | 50 #include "snapshot.h" |
50 #include "unicode-inl.h" | 51 #include "unicode-inl.h" |
51 #include "utils.h" | 52 #include "utils.h" |
52 #include "vm-state.h" | 53 #include "vm-state.h" |
53 | 54 |
54 static const bool kLogThreading = false; | 55 static const bool kLogThreading = false; |
55 | 56 |
57 using std::pair; | |
58 | |
56 using ::v8::Boolean; | 59 using ::v8::Boolean; |
57 using ::v8::BooleanObject; | 60 using ::v8::BooleanObject; |
58 using ::v8::Context; | 61 using ::v8::Context; |
59 using ::v8::Extension; | 62 using ::v8::Extension; |
60 using ::v8::Function; | 63 using ::v8::Function; |
61 using ::v8::FunctionTemplate; | 64 using ::v8::FunctionTemplate; |
62 using ::v8::Handle; | 65 using ::v8::Handle; |
63 using ::v8::HandleScope; | 66 using ::v8::HandleScope; |
64 using ::v8::Local; | 67 using ::v8::Local; |
65 using ::v8::Message; | 68 using ::v8::Message; |
(...skipping 3372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3438 int id() { return id_; } | 3441 int id() { return id_; } |
3439 void increment() { number_of_weak_calls_++; } | 3442 void increment() { number_of_weak_calls_++; } |
3440 int NumberOfWeakCalls() { return number_of_weak_calls_; } | 3443 int NumberOfWeakCalls() { return number_of_weak_calls_; } |
3441 private: | 3444 private: |
3442 int id_; | 3445 int id_; |
3443 int number_of_weak_calls_; | 3446 int number_of_weak_calls_; |
3444 }; | 3447 }; |
3445 | 3448 |
3446 | 3449 |
3447 template<typename T> | 3450 template<typename T> |
3448 static void WeakPointerCallback(v8::Isolate* isolate, | 3451 static void WeakPointerCallback( |
3449 Persistent<T>* handle, | 3452 const v8::WeakCallbackData<T, std::pair<v8::Persistent<T>*, |
3450 WeakCallCounter* counter) { | 3453 WeakCallCounter*> >& data) { |
3451 CHECK_EQ(1234, counter->id()); | 3454 CHECK_EQ(1234, data.GetParameter()->second->id()); |
3452 counter->increment(); | 3455 data.GetParameter()->second->increment(); |
3453 handle->Reset(); | 3456 data.GetParameter()->first->Reset(); |
3454 } | 3457 } |
3455 | 3458 |
3456 | 3459 |
3457 template<typename T> | 3460 template<typename T> |
3458 static UniqueId MakeUniqueId(const Persistent<T>& p) { | 3461 static UniqueId MakeUniqueId(const Persistent<T>& p) { |
3459 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p))); | 3462 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p))); |
3460 } | 3463 } |
3461 | 3464 |
3462 | 3465 |
3463 THREADED_TEST(ApiObjectGroups) { | 3466 THREADED_TEST(ApiObjectGroups) { |
3464 LocalContext env; | 3467 LocalContext env; |
3465 v8::Isolate* iso = env->GetIsolate(); | 3468 v8::Isolate* iso = env->GetIsolate(); |
3466 HandleScope scope(iso); | 3469 HandleScope scope(iso); |
3467 | 3470 |
3468 Persistent<Value> g1s1; | 3471 Persistent<Value> g1s1; |
3469 Persistent<Value> g1s2; | 3472 Persistent<Value> g1s2; |
3470 Persistent<Value> g1c1; | 3473 Persistent<Value> g1c1; |
3471 Persistent<Value> g2s1; | 3474 Persistent<Value> g2s1; |
3472 Persistent<Value> g2s2; | 3475 Persistent<Value> g2s2; |
3473 Persistent<Value> g2c1; | 3476 Persistent<Value> g2c1; |
3474 | 3477 |
3475 WeakCallCounter counter(1234); | 3478 WeakCallCounter counter(1234); |
3476 | 3479 |
3480 pair<Persistent<Value>*, WeakCallCounter*> g1s1p(&g1s1, &counter); | |
3481 pair<Persistent<Value>*, WeakCallCounter*> g1s2p(&g1s2, &counter); | |
3482 pair<Persistent<Value>*, WeakCallCounter*> g1c1p(&g1c1, &counter); | |
3483 pair<Persistent<Value>*, WeakCallCounter*> g2s1p(&g2s1, &counter); | |
3484 pair<Persistent<Value>*, WeakCallCounter*> g2s2p(&g2s2, &counter); | |
3485 pair<Persistent<Value>*, WeakCallCounter*> g2c1p(&g2c1, &counter); | |
3486 | |
3477 { | 3487 { |
3478 HandleScope scope(iso); | 3488 HandleScope scope(iso); |
3479 g1s1.Reset(iso, Object::New()); | 3489 g1s1.Reset(iso, Object::New()); |
3480 g1s2.Reset(iso, Object::New()); | 3490 g1s2.Reset(iso, Object::New()); |
3481 g1c1.Reset(iso, Object::New()); | 3491 g1c1.Reset(iso, Object::New()); |
3482 g1s1.MakeWeak(&counter, &WeakPointerCallback); | 3492 g1s1.SetWeak(&g1s1p, &WeakPointerCallback); |
3483 g1s2.MakeWeak(&counter, &WeakPointerCallback); | 3493 g1s2.SetWeak(&g1s2p, &WeakPointerCallback); |
3484 g1c1.MakeWeak(&counter, &WeakPointerCallback); | 3494 g1c1.SetWeak(&g1c1p, &WeakPointerCallback); |
3485 | 3495 |
3486 g2s1.Reset(iso, Object::New()); | 3496 g2s1.Reset(iso, Object::New()); |
3487 g2s2.Reset(iso, Object::New()); | 3497 g2s2.Reset(iso, Object::New()); |
3488 g2c1.Reset(iso, Object::New()); | 3498 g2c1.Reset(iso, Object::New()); |
3489 g2s1.MakeWeak(&counter, &WeakPointerCallback); | 3499 g2s1.SetWeak(&g2s1p, &WeakPointerCallback); |
3490 g2s2.MakeWeak(&counter, &WeakPointerCallback); | 3500 g2s2.SetWeak(&g2s2p, &WeakPointerCallback); |
3491 g2c1.MakeWeak(&counter, &WeakPointerCallback); | 3501 g2c1.SetWeak(&g2c1p, &WeakPointerCallback); |
3492 } | 3502 } |
3493 | 3503 |
3494 Persistent<Value> root(iso, g1s1); // make a root. | 3504 Persistent<Value> root(iso, g1s1); // make a root. |
3505 pair<Persistent<Value>*, WeakCallCounter*> rootp(&root, &counter); | |
3495 | 3506 |
3496 // Connect group 1 and 2, make a cycle. | 3507 // Connect group 1 and 2, make a cycle. |
3497 { | 3508 { |
3498 HandleScope scope(iso); | 3509 HandleScope scope(iso); |
3499 CHECK(Local<Object>::New(iso, g1s2.As<Object>())-> | 3510 CHECK(Local<Object>::New(iso, g1s2.As<Object>())-> |
3500 Set(0, Local<Value>::New(iso, g2s2))); | 3511 Set(0, Local<Value>::New(iso, g2s2))); |
3501 CHECK(Local<Object>::New(iso, g2s1.As<Object>())-> | 3512 CHECK(Local<Object>::New(iso, g2s1.As<Object>())-> |
3502 Set(0, Local<Value>::New(iso, g1s1))); | 3513 Set(0, Local<Value>::New(iso, g1s1))); |
3503 } | 3514 } |
3504 | 3515 |
3505 { | 3516 { |
3506 UniqueId id1 = MakeUniqueId(g1s1); | 3517 UniqueId id1 = MakeUniqueId(g1s1); |
3507 UniqueId id2 = MakeUniqueId(g2s2); | 3518 UniqueId id2 = MakeUniqueId(g2s2); |
3508 iso->SetObjectGroupId(g1s1, id1); | 3519 iso->SetObjectGroupId(g1s1, id1); |
3509 iso->SetObjectGroupId(g1s2, id1); | 3520 iso->SetObjectGroupId(g1s2, id1); |
3510 iso->SetReferenceFromGroup(id1, g1c1); | 3521 iso->SetReferenceFromGroup(id1, g1c1); |
3511 iso->SetObjectGroupId(g2s1, id2); | 3522 iso->SetObjectGroupId(g2s1, id2); |
3512 iso->SetObjectGroupId(g2s2, id2); | 3523 iso->SetObjectGroupId(g2s2, id2); |
3513 iso->SetReferenceFromGroup(id2, g2c1); | 3524 iso->SetReferenceFromGroup(id2, g2c1); |
3514 } | 3525 } |
3515 // Do a single full GC, ensure incremental marking is stopped. | 3526 // Do a single full GC, ensure incremental marking is stopped. |
3516 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( | 3527 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( |
3517 iso)->heap(); | 3528 iso)->heap(); |
3518 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3529 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
3519 | 3530 |
3520 // All object should be alive. | 3531 // All object should be alive. |
3521 CHECK_EQ(0, counter.NumberOfWeakCalls()); | 3532 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
3522 | 3533 |
3523 // Weaken the root. | 3534 // Weaken the root. |
3524 root.MakeWeak(&counter, &WeakPointerCallback); | 3535 root.SetWeak(&rootp, &WeakPointerCallback); |
3525 // But make children strong roots---all the objects (except for children) | 3536 // But make children strong roots---all the objects (except for children) |
3526 // should be collectable now. | 3537 // should be collectable now. |
3527 g1c1.ClearWeak(); | 3538 g1c1.ClearWeak(); |
3528 g2c1.ClearWeak(); | 3539 g2c1.ClearWeak(); |
3529 | 3540 |
3530 // Groups are deleted, rebuild groups. | 3541 // Groups are deleted, rebuild groups. |
3531 { | 3542 { |
3532 UniqueId id1 = MakeUniqueId(g1s1); | 3543 UniqueId id1 = MakeUniqueId(g1s1); |
3533 UniqueId id2 = MakeUniqueId(g2s2); | 3544 UniqueId id2 = MakeUniqueId(g2s2); |
3534 iso->SetObjectGroupId(g1s1, id1); | 3545 iso->SetObjectGroupId(g1s1, id1); |
3535 iso->SetObjectGroupId(g1s2, id1); | 3546 iso->SetObjectGroupId(g1s2, id1); |
3536 iso->SetReferenceFromGroup(id1, g1c1); | 3547 iso->SetReferenceFromGroup(id1, g1c1); |
3537 iso->SetObjectGroupId(g2s1, id2); | 3548 iso->SetObjectGroupId(g2s1, id2); |
3538 iso->SetObjectGroupId(g2s2, id2); | 3549 iso->SetObjectGroupId(g2s2, id2); |
3539 iso->SetReferenceFromGroup(id2, g2c1); | 3550 iso->SetReferenceFromGroup(id2, g2c1); |
3540 } | 3551 } |
3541 | 3552 |
3542 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3553 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
3543 | 3554 |
3544 // All objects should be gone. 5 global handles in total. | 3555 // All objects should be gone. 5 global handles in total. |
3545 CHECK_EQ(5, counter.NumberOfWeakCalls()); | 3556 CHECK_EQ(5, counter.NumberOfWeakCalls()); |
3546 | 3557 |
3547 // And now make children weak again and collect them. | 3558 // And now make children weak again and collect them. |
3548 g1c1.MakeWeak(&counter, &WeakPointerCallback); | 3559 g1c1.SetWeak(&g1c1p, &WeakPointerCallback); |
3549 g2c1.MakeWeak(&counter, &WeakPointerCallback); | 3560 g2c1.SetWeak(&g2c1p, &WeakPointerCallback); |
3550 | 3561 |
3551 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3562 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
3552 CHECK_EQ(7, counter.NumberOfWeakCalls()); | 3563 CHECK_EQ(7, counter.NumberOfWeakCalls()); |
3553 } | 3564 } |
3554 | 3565 |
3555 | 3566 |
3556 THREADED_TEST(ApiObjectGroupsForSubtypes) { | 3567 THREADED_TEST(ApiObjectGroupsForSubtypes) { |
3557 LocalContext env; | 3568 LocalContext env; |
3558 v8::Isolate* iso = env->GetIsolate(); | 3569 v8::Isolate* iso = env->GetIsolate(); |
3559 HandleScope scope(iso); | 3570 HandleScope scope(iso); |
3560 | 3571 |
3561 Persistent<Object> g1s1; | 3572 Persistent<Object> g1s1; |
3562 Persistent<String> g1s2; | 3573 Persistent<String> g1s2; |
3563 Persistent<String> g1c1; | 3574 Persistent<String> g1c1; |
3564 Persistent<Object> g2s1; | 3575 Persistent<Object> g2s1; |
3565 Persistent<String> g2s2; | 3576 Persistent<String> g2s2; |
3566 Persistent<String> g2c1; | 3577 Persistent<String> g2c1; |
3567 | 3578 |
3568 WeakCallCounter counter(1234); | 3579 WeakCallCounter counter(1234); |
3569 | 3580 |
3581 pair<Persistent<Object>*, WeakCallCounter*> g1s1p(&g1s1, &counter); | |
3582 pair<Persistent<String>*, WeakCallCounter*> g1s2p(&g1s2, &counter); | |
3583 pair<Persistent<String>*, WeakCallCounter*> g1c1p(&g1c1, &counter); | |
3584 pair<Persistent<Object>*, WeakCallCounter*> g2s1p(&g2s1, &counter); | |
3585 pair<Persistent<String>*, WeakCallCounter*> g2s2p(&g2s2, &counter); | |
3586 pair<Persistent<String>*, WeakCallCounter*> g2c1p(&g2c1, &counter); | |
3587 | |
3570 { | 3588 { |
3571 HandleScope scope(iso); | 3589 HandleScope scope(iso); |
3572 g1s1.Reset(iso, Object::New()); | 3590 g1s1.Reset(iso, Object::New()); |
3573 g1s2.Reset(iso, String::NewFromUtf8(iso, "foo1")); | 3591 g1s2.Reset(iso, String::NewFromUtf8(iso, "foo1")); |
3574 g1c1.Reset(iso, String::NewFromUtf8(iso, "foo2")); | 3592 g1c1.Reset(iso, String::NewFromUtf8(iso, "foo2")); |
3575 g1s1.MakeWeak(&counter, &WeakPointerCallback); | 3593 g1s1.SetWeak(&g1s1p, &WeakPointerCallback); |
3576 g1s2.MakeWeak(&counter, &WeakPointerCallback); | 3594 g1s2.SetWeak(&g1s2p, &WeakPointerCallback); |
3577 g1c1.MakeWeak(&counter, &WeakPointerCallback); | 3595 g1c1.SetWeak(&g1c1p, &WeakPointerCallback); |
3578 | 3596 |
3579 g2s1.Reset(iso, Object::New()); | 3597 g2s1.Reset(iso, Object::New()); |
3580 g2s2.Reset(iso, String::NewFromUtf8(iso, "foo3")); | 3598 g2s2.Reset(iso, String::NewFromUtf8(iso, "foo3")); |
3581 g2c1.Reset(iso, String::NewFromUtf8(iso, "foo4")); | 3599 g2c1.Reset(iso, String::NewFromUtf8(iso, "foo4")); |
3582 g2s1.MakeWeak(&counter, &WeakPointerCallback); | 3600 g2s1.SetWeak(&g2s1p, &WeakPointerCallback); |
3583 g2s2.MakeWeak(&counter, &WeakPointerCallback); | 3601 g2s2.SetWeak(&g2s2p, &WeakPointerCallback); |
3584 g2c1.MakeWeak(&counter, &WeakPointerCallback); | 3602 g2c1.SetWeak(&g2c1p, &WeakPointerCallback); |
3585 } | 3603 } |
3586 | 3604 |
3587 Persistent<Value> root(iso, g1s1); // make a root. | 3605 Persistent<Value> root(iso, g1s1); // make a root. |
3606 pair<Persistent<Value>*, WeakCallCounter*> rootp(&root, &counter); | |
3588 | 3607 |
3589 // Connect group 1 and 2, make a cycle. | 3608 // Connect group 1 and 2, make a cycle. |
3590 { | 3609 { |
3591 HandleScope scope(iso); | 3610 HandleScope scope(iso); |
3592 CHECK(Local<Object>::New(iso, g1s1)->Set(0, Local<Object>::New(iso, g2s1))); | 3611 CHECK(Local<Object>::New(iso, g1s1)->Set(0, Local<Object>::New(iso, g2s1))); |
3593 CHECK(Local<Object>::New(iso, g2s1)->Set(0, Local<Object>::New(iso, g1s1))); | 3612 CHECK(Local<Object>::New(iso, g2s1)->Set(0, Local<Object>::New(iso, g1s1))); |
3594 } | 3613 } |
3595 | 3614 |
3596 { | 3615 { |
3597 UniqueId id1 = MakeUniqueId(g1s1); | 3616 UniqueId id1 = MakeUniqueId(g1s1); |
3598 UniqueId id2 = MakeUniqueId(g2s2); | 3617 UniqueId id2 = MakeUniqueId(g2s2); |
3599 iso->SetObjectGroupId(g1s1, id1); | 3618 iso->SetObjectGroupId(g1s1, id1); |
3600 iso->SetObjectGroupId(g1s2, id1); | 3619 iso->SetObjectGroupId(g1s2, id1); |
3601 iso->SetReference(g1s1, g1c1); | 3620 iso->SetReference(g1s1, g1c1); |
3602 iso->SetObjectGroupId(g2s1, id2); | 3621 iso->SetObjectGroupId(g2s1, id2); |
3603 iso->SetObjectGroupId(g2s2, id2); | 3622 iso->SetObjectGroupId(g2s2, id2); |
3604 iso->SetReferenceFromGroup(id2, g2c1); | 3623 iso->SetReferenceFromGroup(id2, g2c1); |
3605 } | 3624 } |
3606 // Do a single full GC, ensure incremental marking is stopped. | 3625 // Do a single full GC, ensure incremental marking is stopped. |
3607 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( | 3626 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( |
3608 iso)->heap(); | 3627 iso)->heap(); |
3609 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3628 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
3610 | 3629 |
3611 // All object should be alive. | 3630 // All object should be alive. |
3612 CHECK_EQ(0, counter.NumberOfWeakCalls()); | 3631 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
3613 | 3632 |
3614 // Weaken the root. | 3633 // Weaken the root. |
3615 root.MakeWeak(&counter, &WeakPointerCallback); | 3634 root.SetWeak(&rootp, &WeakPointerCallback); |
3616 // But make children strong roots---all the objects (except for children) | 3635 // But make children strong roots---all the objects (except for children) |
3617 // should be collectable now. | 3636 // should be collectable now. |
3618 g1c1.ClearWeak(); | 3637 g1c1.ClearWeak(); |
3619 g2c1.ClearWeak(); | 3638 g2c1.ClearWeak(); |
3620 | 3639 |
3621 // Groups are deleted, rebuild groups. | 3640 // Groups are deleted, rebuild groups. |
3622 { | 3641 { |
3623 UniqueId id1 = MakeUniqueId(g1s1); | 3642 UniqueId id1 = MakeUniqueId(g1s1); |
3624 UniqueId id2 = MakeUniqueId(g2s2); | 3643 UniqueId id2 = MakeUniqueId(g2s2); |
3625 iso->SetObjectGroupId(g1s1, id1); | 3644 iso->SetObjectGroupId(g1s1, id1); |
3626 iso->SetObjectGroupId(g1s2, id1); | 3645 iso->SetObjectGroupId(g1s2, id1); |
3627 iso->SetReference(g1s1, g1c1); | 3646 iso->SetReference(g1s1, g1c1); |
3628 iso->SetObjectGroupId(g2s1, id2); | 3647 iso->SetObjectGroupId(g2s1, id2); |
3629 iso->SetObjectGroupId(g2s2, id2); | 3648 iso->SetObjectGroupId(g2s2, id2); |
3630 iso->SetReferenceFromGroup(id2, g2c1); | 3649 iso->SetReferenceFromGroup(id2, g2c1); |
3631 } | 3650 } |
3632 | 3651 |
3633 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3652 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
3634 | 3653 |
3635 // All objects should be gone. 5 global handles in total. | 3654 // All objects should be gone. 5 global handles in total. |
3636 CHECK_EQ(5, counter.NumberOfWeakCalls()); | 3655 CHECK_EQ(5, counter.NumberOfWeakCalls()); |
3637 | 3656 |
3638 // And now make children weak again and collect them. | 3657 // And now make children weak again and collect them. |
3639 g1c1.MakeWeak(&counter, &WeakPointerCallback); | 3658 g1c1.SetWeak(&g1c1p, &WeakPointerCallback); |
3640 g2c1.MakeWeak(&counter, &WeakPointerCallback); | 3659 g2c1.SetWeak(&g2c1p, &WeakPointerCallback); |
3641 | 3660 |
3642 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3661 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
3643 CHECK_EQ(7, counter.NumberOfWeakCalls()); | 3662 CHECK_EQ(7, counter.NumberOfWeakCalls()); |
3644 } | 3663 } |
3645 | 3664 |
3646 | 3665 |
3647 THREADED_TEST(ApiObjectGroupsCycle) { | 3666 THREADED_TEST(ApiObjectGroupsCycle) { |
3648 LocalContext env; | 3667 LocalContext env; |
3649 v8::Isolate* iso = env->GetIsolate(); | 3668 v8::Isolate* iso = env->GetIsolate(); |
3650 HandleScope scope(iso); | 3669 HandleScope scope(iso); |
3651 | 3670 |
3652 WeakCallCounter counter(1234); | 3671 WeakCallCounter counter(1234); |
3653 | 3672 |
3654 Persistent<Value> g1s1; | 3673 Persistent<Value> g1s1; |
3655 Persistent<Value> g1s2; | 3674 Persistent<Value> g1s2; |
3656 Persistent<Value> g2s1; | 3675 Persistent<Value> g2s1; |
3657 Persistent<Value> g2s2; | 3676 Persistent<Value> g2s2; |
3658 Persistent<Value> g3s1; | 3677 Persistent<Value> g3s1; |
3659 Persistent<Value> g3s2; | 3678 Persistent<Value> g3s2; |
3660 Persistent<Value> g4s1; | 3679 Persistent<Value> g4s1; |
3661 Persistent<Value> g4s2; | 3680 Persistent<Value> g4s2; |
3662 | 3681 |
3682 pair<Persistent<Value>*, WeakCallCounter*> g1s1p(&g1s1, &counter); | |
3683 pair<Persistent<Value>*, WeakCallCounter*> g1s2p(&g1s2, &counter); | |
3684 pair<Persistent<Value>*, WeakCallCounter*> g2s1p(&g2s1, &counter); | |
3685 pair<Persistent<Value>*, WeakCallCounter*> g2s2p(&g2s2, &counter); | |
3686 pair<Persistent<Value>*, WeakCallCounter*> g3s1p(&g3s1, &counter); | |
3687 pair<Persistent<Value>*, WeakCallCounter*> g3s2p(&g3s2, &counter); | |
3688 pair<Persistent<Value>*, WeakCallCounter*> g4s1p(&g4s1, &counter); | |
3689 pair<Persistent<Value>*, WeakCallCounter*> g4s2p(&g4s2, &counter); | |
3690 | |
3663 { | 3691 { |
3664 HandleScope scope(iso); | 3692 HandleScope scope(iso); |
3665 g1s1.Reset(iso, Object::New()); | 3693 g1s1.Reset(iso, Object::New()); |
3666 g1s2.Reset(iso, Object::New()); | 3694 g1s2.Reset(iso, Object::New()); |
3667 g1s1.MakeWeak(&counter, &WeakPointerCallback); | 3695 g1s1.SetWeak(&g1s1p, &WeakPointerCallback); |
3668 g1s2.MakeWeak(&counter, &WeakPointerCallback); | 3696 g1s2.SetWeak(&g1s2p, &WeakPointerCallback); |
3669 CHECK(g1s1.IsWeak()); | 3697 CHECK(g1s1.IsWeak()); |
3670 CHECK(g1s2.IsWeak()); | 3698 CHECK(g1s2.IsWeak()); |
3671 | 3699 |
3672 g2s1.Reset(iso, Object::New()); | 3700 g2s1.Reset(iso, Object::New()); |
3673 g2s2.Reset(iso, Object::New()); | 3701 g2s2.Reset(iso, Object::New()); |
3674 g2s1.MakeWeak(&counter, &WeakPointerCallback); | 3702 g2s1.SetWeak(&g2s1p, &WeakPointerCallback); |
3675 g2s2.MakeWeak(&counter, &WeakPointerCallback); | 3703 g2s2.SetWeak(&g2s2p, &WeakPointerCallback); |
3676 CHECK(g2s1.IsWeak()); | 3704 CHECK(g2s1.IsWeak()); |
3677 CHECK(g2s2.IsWeak()); | 3705 CHECK(g2s2.IsWeak()); |
3678 | 3706 |
3679 g3s1.Reset(iso, Object::New()); | 3707 g3s1.Reset(iso, Object::New()); |
3680 g3s2.Reset(iso, Object::New()); | 3708 g3s2.Reset(iso, Object::New()); |
3681 g3s1.MakeWeak(&counter, &WeakPointerCallback); | 3709 g3s1.SetWeak(&g3s1p, &WeakPointerCallback); |
3682 g3s2.MakeWeak(&counter, &WeakPointerCallback); | 3710 g3s2.SetWeak(&g3s2p, &WeakPointerCallback); |
3683 CHECK(g3s1.IsWeak()); | 3711 CHECK(g3s1.IsWeak()); |
3684 CHECK(g3s2.IsWeak()); | 3712 CHECK(g3s2.IsWeak()); |
3685 | 3713 |
3686 g4s1.Reset(iso, Object::New()); | 3714 g4s1.Reset(iso, Object::New()); |
3687 g4s2.Reset(iso, Object::New()); | 3715 g4s2.Reset(iso, Object::New()); |
3688 g4s1.MakeWeak(&counter, &WeakPointerCallback); | 3716 g4s1.SetWeak(&g4s1p, &WeakPointerCallback); |
3689 g4s2.MakeWeak(&counter, &WeakPointerCallback); | 3717 g4s2.SetWeak(&g4s2p, &WeakPointerCallback); |
3690 CHECK(g4s1.IsWeak()); | 3718 CHECK(g4s1.IsWeak()); |
3691 CHECK(g4s2.IsWeak()); | 3719 CHECK(g4s2.IsWeak()); |
3692 } | 3720 } |
3693 | 3721 |
3694 Persistent<Value> root(iso, g1s1); // make a root. | 3722 Persistent<Value> root(iso, g1s1); // make a root. |
3723 pair<Persistent<Value>*, WeakCallCounter*> rootp(&root, &counter); | |
3695 | 3724 |
3696 // Connect groups. We're building the following cycle: | 3725 // Connect groups. We're building the following cycle: |
3697 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other | 3726 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other |
3698 // groups. | 3727 // groups. |
3699 { | 3728 { |
3700 UniqueId id1 = MakeUniqueId(g1s1); | 3729 UniqueId id1 = MakeUniqueId(g1s1); |
3701 UniqueId id2 = MakeUniqueId(g2s1); | 3730 UniqueId id2 = MakeUniqueId(g2s1); |
3702 UniqueId id3 = MakeUniqueId(g3s1); | 3731 UniqueId id3 = MakeUniqueId(g3s1); |
3703 UniqueId id4 = MakeUniqueId(g4s1); | 3732 UniqueId id4 = MakeUniqueId(g4s1); |
3704 iso->SetObjectGroupId(g1s1, id1); | 3733 iso->SetObjectGroupId(g1s1, id1); |
(...skipping 11 matching lines...) Expand all Loading... | |
3716 } | 3745 } |
3717 // Do a single full GC | 3746 // Do a single full GC |
3718 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( | 3747 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( |
3719 iso)->heap(); | 3748 iso)->heap(); |
3720 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3749 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
3721 | 3750 |
3722 // All object should be alive. | 3751 // All object should be alive. |
3723 CHECK_EQ(0, counter.NumberOfWeakCalls()); | 3752 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
3724 | 3753 |
3725 // Weaken the root. | 3754 // Weaken the root. |
3726 root.MakeWeak(&counter, &WeakPointerCallback); | 3755 root.SetWeak(&rootp, &WeakPointerCallback); |
3727 | 3756 |
3728 // Groups are deleted, rebuild groups. | 3757 // Groups are deleted, rebuild groups. |
3729 { | 3758 { |
3730 UniqueId id1 = MakeUniqueId(g1s1); | 3759 UniqueId id1 = MakeUniqueId(g1s1); |
3731 UniqueId id2 = MakeUniqueId(g2s1); | 3760 UniqueId id2 = MakeUniqueId(g2s1); |
3732 UniqueId id3 = MakeUniqueId(g3s1); | 3761 UniqueId id3 = MakeUniqueId(g3s1); |
3733 UniqueId id4 = MakeUniqueId(g4s1); | 3762 UniqueId id4 = MakeUniqueId(g4s1); |
3734 iso->SetObjectGroupId(g1s1, id1); | 3763 iso->SetObjectGroupId(g1s1, id1); |
3735 iso->SetObjectGroupId(g1s2, id1); | 3764 iso->SetObjectGroupId(g1s2, id1); |
3736 iso->SetReferenceFromGroup(id1, g2s1); | 3765 iso->SetReferenceFromGroup(id1, g2s1); |
(...skipping 26 matching lines...) Expand all Loading... | |
3763 | 3792 |
3764 WeakCallCounter counter(1234); | 3793 WeakCallCounter counter(1234); |
3765 | 3794 |
3766 Persistent<Value> g1s1; | 3795 Persistent<Value> g1s1; |
3767 Persistent<Value> g1s2; | 3796 Persistent<Value> g1s2; |
3768 Persistent<Value> g2s1; | 3797 Persistent<Value> g2s1; |
3769 Persistent<Value> g2s2; | 3798 Persistent<Value> g2s2; |
3770 Persistent<Value> g3s1; | 3799 Persistent<Value> g3s1; |
3771 Persistent<Value> g3s2; | 3800 Persistent<Value> g3s2; |
3772 | 3801 |
3802 pair<Persistent<Value>*, WeakCallCounter*> g1s1p(&g1s1, &counter); | |
3803 pair<Persistent<Value>*, WeakCallCounter*> g1s2p(&g1s2, &counter); | |
3804 pair<Persistent<Value>*, WeakCallCounter*> g2s1p(&g2s1, &counter); | |
3805 pair<Persistent<Value>*, WeakCallCounter*> g2s2p(&g2s2, &counter); | |
3806 pair<Persistent<Value>*, WeakCallCounter*> g3s1p(&g3s1, &counter); | |
3807 pair<Persistent<Value>*, WeakCallCounter*> g3s2p(&g3s2, &counter); | |
3808 | |
3773 { | 3809 { |
3774 HandleScope scope(iso); | 3810 HandleScope scope(iso); |
3775 g1s1.Reset(iso, Object::New()); | 3811 g1s1.Reset(iso, Object::New()); |
3776 g1s2.Reset(iso, Object::New()); | 3812 g1s2.Reset(iso, Object::New()); |
3777 g1s1.MakeWeak(&counter, &WeakPointerCallback); | 3813 g1s1.SetWeak(&g1s1p, &WeakPointerCallback); |
3778 g1s2.MakeWeak(&counter, &WeakPointerCallback); | 3814 g1s2.SetWeak(&g1s2p, &WeakPointerCallback); |
3779 | 3815 |
3780 g2s1.Reset(iso, Object::New()); | 3816 g2s1.Reset(iso, Object::New()); |
3781 g2s2.Reset(iso, Object::New()); | 3817 g2s2.Reset(iso, Object::New()); |
3782 g2s1.MakeWeak(&counter, &WeakPointerCallback); | 3818 g2s1.SetWeak(&g2s1p, &WeakPointerCallback); |
3783 g2s2.MakeWeak(&counter, &WeakPointerCallback); | 3819 g2s2.SetWeak(&g2s2p, &WeakPointerCallback); |
3784 | 3820 |
3785 g3s1.Reset(iso, Object::New()); | 3821 g3s1.Reset(iso, Object::New()); |
3786 g3s2.Reset(iso, Object::New()); | 3822 g3s2.Reset(iso, Object::New()); |
3787 g3s1.MakeWeak(&counter, &WeakPointerCallback); | 3823 g3s1.SetWeak(&g3s1p, &WeakPointerCallback); |
3788 g3s2.MakeWeak(&counter, &WeakPointerCallback); | 3824 g3s2.SetWeak(&g3s2p, &WeakPointerCallback); |
3789 } | 3825 } |
3790 | 3826 |
3791 // Make a root. | 3827 // Make a root. |
3792 Persistent<Value> root(iso, g1s1); | 3828 Persistent<Value> root(iso, g1s1); |
3829 pair<Persistent<Value>*, WeakCallCounter*> rootp(&root, &counter); | |
3793 root.MarkPartiallyDependent(); | 3830 root.MarkPartiallyDependent(); |
3794 | 3831 |
3795 // Connect groups. We're building the following cycle: | 3832 // Connect groups. We're building the following cycle: |
3796 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other | 3833 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other |
3797 // groups. | 3834 // groups. |
3798 { | 3835 { |
3799 HandleScope handle_scope(iso); | 3836 HandleScope handle_scope(iso); |
3800 g1s1.MarkPartiallyDependent(); | 3837 g1s1.MarkPartiallyDependent(); |
3801 g1s2.MarkPartiallyDependent(); | 3838 g1s2.MarkPartiallyDependent(); |
3802 g2s1.MarkPartiallyDependent(); | 3839 g2s1.MarkPartiallyDependent(); |
(...skipping 15 matching lines...) Expand all Loading... | |
3818 } | 3855 } |
3819 | 3856 |
3820 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( | 3857 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( |
3821 iso)->heap(); | 3858 iso)->heap(); |
3822 heap->CollectGarbage(i::NEW_SPACE); | 3859 heap->CollectGarbage(i::NEW_SPACE); |
3823 | 3860 |
3824 // All objects should be alive. | 3861 // All objects should be alive. |
3825 CHECK_EQ(0, counter.NumberOfWeakCalls()); | 3862 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
3826 | 3863 |
3827 // Weaken the root. | 3864 // Weaken the root. |
3828 root.MakeWeak(&counter, &WeakPointerCallback); | 3865 root.SetWeak(&rootp, &WeakPointerCallback); |
3829 root.MarkPartiallyDependent(); | 3866 root.MarkPartiallyDependent(); |
3830 | 3867 |
3831 // Groups are deleted, rebuild groups. | 3868 // Groups are deleted, rebuild groups. |
3832 { | 3869 { |
3833 HandleScope handle_scope(iso); | 3870 HandleScope handle_scope(iso); |
3834 g1s1.MarkPartiallyDependent(); | 3871 g1s1.MarkPartiallyDependent(); |
3835 g1s2.MarkPartiallyDependent(); | 3872 g1s2.MarkPartiallyDependent(); |
3836 g2s1.MarkPartiallyDependent(); | 3873 g2s1.MarkPartiallyDependent(); |
3837 g2s2.MarkPartiallyDependent(); | 3874 g2s2.MarkPartiallyDependent(); |
3838 g3s1.MarkPartiallyDependent(); | 3875 g3s1.MarkPartiallyDependent(); |
(...skipping 3103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6942 v8::V8::AddMessageListener(MissingScriptInfoMessageListener); | 6979 v8::V8::AddMessageListener(MissingScriptInfoMessageListener); |
6943 Script::Compile(v8_str("throw Error()"))->Run(); | 6980 Script::Compile(v8_str("throw Error()"))->Run(); |
6944 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener); | 6981 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener); |
6945 } | 6982 } |
6946 | 6983 |
6947 | 6984 |
6948 int global_index = 0; | 6985 int global_index = 0; |
6949 | 6986 |
6950 class Snorkel { | 6987 class Snorkel { |
6951 public: | 6988 public: |
6952 Snorkel() { index_ = global_index++; } | 6989 explicit Snorkel(v8::Persistent<v8::Object>* prev) |
6990 : prev_(prev), index_(global_index++) { } | |
6991 v8::Persistent<v8::Object>* prev_; | |
6953 int index_; | 6992 int index_; |
6954 }; | 6993 }; |
6955 | 6994 |
6956 class Whammy { | 6995 class Whammy { |
6957 public: | 6996 public: |
6958 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { } | 6997 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { } |
6959 ~Whammy() { script_.Reset(); } | 6998 ~Whammy() { script_.Reset(); } |
6960 v8::Handle<Script> getScript() { | 6999 v8::Handle<Script> getScript() { |
6961 if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo")); | 7000 if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo")); |
6962 return Local<Script>::New(isolate_, script_); | 7001 return Local<Script>::New(isolate_, script_); |
6963 } | 7002 } |
6964 | 7003 |
6965 public: | 7004 public: |
6966 static const int kObjectCount = 256; | 7005 static const int kObjectCount = 256; |
6967 int cursor_; | 7006 int cursor_; |
6968 v8::Isolate* isolate_; | 7007 v8::Isolate* isolate_; |
6969 v8::Persistent<v8::Object> objects_[kObjectCount]; | 7008 v8::Persistent<v8::Object> objects_[kObjectCount]; |
6970 v8::Persistent<Script> script_; | 7009 v8::Persistent<Script> script_; |
6971 }; | 7010 }; |
6972 | 7011 |
6973 static void HandleWeakReference(v8::Isolate* isolate, | 7012 static void HandleWeakReference( |
6974 v8::Persistent<v8::Value>* obj, | 7013 const v8::WeakCallbackData<v8::Object, Snorkel>& data) { |
6975 Snorkel* snorkel) { | 7014 data.GetParameter()->prev_->ClearWeak(); |
6976 delete snorkel; | 7015 delete data.GetParameter(); |
6977 obj->ClearWeak(); | |
6978 } | 7016 } |
6979 | 7017 |
6980 void WhammyPropertyGetter(Local<String> name, | 7018 void WhammyPropertyGetter(Local<String> name, |
6981 const v8::PropertyCallbackInfo<v8::Value>& info) { | 7019 const v8::PropertyCallbackInfo<v8::Value>& info) { |
6982 Whammy* whammy = | 7020 Whammy* whammy = |
6983 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); | 7021 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); |
6984 | 7022 |
6985 v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_]; | 7023 v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_]; |
6986 | 7024 |
6987 v8::Handle<v8::Object> obj = v8::Object::New(); | 7025 v8::Handle<v8::Object> obj = v8::Object::New(); |
6988 if (!prev.IsEmpty()) { | 7026 if (!prev.IsEmpty()) { |
6989 v8::Local<v8::Object>::New(info.GetIsolate(), prev) | 7027 v8::Local<v8::Object>::New(info.GetIsolate(), prev) |
6990 ->Set(v8_str("next"), obj); | 7028 ->Set(v8_str("next"), obj); |
6991 prev.MakeWeak<Value, Snorkel>(new Snorkel(), &HandleWeakReference); | 7029 prev.SetWeak(new Snorkel(&prev), &HandleWeakReference); |
6992 } | 7030 } |
6993 whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj); | 7031 whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj); |
6994 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount; | 7032 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount; |
6995 info.GetReturnValue().Set(whammy->getScript()->Run()); | 7033 info.GetReturnValue().Set(whammy->getScript()->Run()); |
6996 } | 7034 } |
6997 | 7035 |
6998 | 7036 |
6999 THREADED_TEST(WeakReference) { | 7037 THREADED_TEST(WeakReference) { |
7000 v8::HandleScope handle_scope(CcTest::isolate()); | 7038 v8::HandleScope handle_scope(CcTest::isolate()); |
7001 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(); | 7039 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(); |
(...skipping 17 matching lines...) Expand all Loading... | |
7019 " last = obj;" | 7057 " last = obj;" |
7020 "}" | 7058 "}" |
7021 "gc();" | 7059 "gc();" |
7022 "4"; | 7060 "4"; |
7023 v8::Handle<Value> result = CompileRun(code); | 7061 v8::Handle<Value> result = CompileRun(code); |
7024 CHECK_EQ(4.0, result->NumberValue()); | 7062 CHECK_EQ(4.0, result->NumberValue()); |
7025 delete whammy; | 7063 delete whammy; |
7026 } | 7064 } |
7027 | 7065 |
7028 | 7066 |
7029 static void DisposeAndSetFlag(v8::Isolate* isolate, | 7067 static void DisposeAndSetFlag( |
7030 v8::Persistent<v8::Object>* obj, | 7068 const v8::WeakCallbackData<v8::Object, |
7031 bool* data) { | 7069 pair<v8::Persistent<v8::Object>*, |
7032 obj->Reset(); | 7070 bool> >& data) { |
7033 *(data) = true; | 7071 data.GetParameter()->first->Reset(); |
7072 data.GetParameter()->second = true; | |
7034 } | 7073 } |
7035 | 7074 |
7036 | 7075 |
7037 THREADED_TEST(IndependentWeakHandle) { | 7076 THREADED_TEST(IndependentWeakHandle) { |
7038 v8::Isolate* iso = CcTest::isolate(); | 7077 v8::Isolate* iso = CcTest::isolate(); |
7039 v8::HandleScope scope(iso); | 7078 v8::HandleScope scope(iso); |
7040 v8::Handle<Context> context = Context::New(iso); | 7079 v8::Handle<Context> context = Context::New(iso); |
7041 Context::Scope context_scope(context); | 7080 Context::Scope context_scope(context); |
7042 | 7081 |
7043 v8::Persistent<v8::Object> object_a, object_b; | 7082 v8::Persistent<v8::Object> object_a, object_b; |
7044 | 7083 |
7045 { | 7084 { |
7046 v8::HandleScope handle_scope(iso); | 7085 v8::HandleScope handle_scope(iso); |
7047 object_a.Reset(iso, v8::Object::New()); | 7086 object_a.Reset(iso, v8::Object::New()); |
7048 object_b.Reset(iso, v8::Object::New()); | 7087 object_b.Reset(iso, v8::Object::New()); |
7049 } | 7088 } |
7050 | 7089 |
7051 bool object_a_disposed = false; | 7090 pair<v8::Persistent<v8::Object>*, bool> object_a_pair(&object_a, false); |
7052 bool object_b_disposed = false; | 7091 pair<v8::Persistent<v8::Object>*, bool> object_b_pair(&object_b, false); |
7053 object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag); | 7092 object_a.SetWeak(&object_a_pair, &DisposeAndSetFlag); |
7054 object_b.MakeWeak(&object_b_disposed, &DisposeAndSetFlag); | 7093 object_b.SetWeak(&object_b_pair, &DisposeAndSetFlag); |
7055 CHECK(!object_b.IsIndependent()); | 7094 CHECK(!object_b.IsIndependent()); |
7056 object_a.MarkIndependent(); | 7095 object_a.MarkIndependent(); |
7057 object_b.MarkIndependent(); | 7096 object_b.MarkIndependent(); |
7058 CHECK(object_b.IsIndependent()); | 7097 CHECK(object_b.IsIndependent()); |
7059 CcTest::heap()->PerformScavenge(); | 7098 CcTest::heap()->PerformScavenge(); |
7060 CHECK(object_a_disposed); | 7099 CHECK(object_a_pair.second); |
7061 CHECK(object_b_disposed); | 7100 CHECK(object_b_pair.second); |
7062 } | 7101 } |
7063 | 7102 |
7064 | 7103 |
7065 static void InvokeScavenge() { | 7104 static void InvokeScavenge() { |
7066 CcTest::heap()->PerformScavenge(); | 7105 CcTest::heap()->PerformScavenge(); |
7067 } | 7106 } |
7068 | 7107 |
7069 | 7108 |
7070 static void InvokeMarkSweep() { | 7109 static void InvokeMarkSweep() { |
7071 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 7110 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
7072 } | 7111 } |
7073 | 7112 |
7074 | 7113 |
7075 static void ForceScavenge(v8::Isolate* isolate, | 7114 static void ForceScavenge( |
7076 v8::Persistent<v8::Object>* obj, | 7115 const v8::WeakCallbackData<v8::Object, |
7077 bool* data) { | 7116 pair<v8::Persistent<v8::Object>*, |
7078 obj->Reset(); | 7117 bool> >& data) { |
7079 *(data) = true; | 7118 data.GetParameter()->first->Reset(); |
7119 data.GetParameter()->second = true; | |
7080 InvokeScavenge(); | 7120 InvokeScavenge(); |
7081 } | 7121 } |
7082 | 7122 |
7083 | 7123 |
7084 static void ForceMarkSweep(v8::Isolate* isolate, | 7124 static void ForceMarkSweep( |
7085 v8::Persistent<v8::Object>* obj, | 7125 const v8::WeakCallbackData<v8::Object, |
7086 bool* data) { | 7126 pair<v8::Persistent<v8::Object>*, |
7087 obj->Reset(); | 7127 bool> >& data) { |
7088 *(data) = true; | 7128 data.GetParameter()->first->Reset(); |
7129 data.GetParameter()->second = true; | |
7089 InvokeMarkSweep(); | 7130 InvokeMarkSweep(); |
7090 } | 7131 } |
7091 | 7132 |
7092 | 7133 |
7093 THREADED_TEST(GCFromWeakCallbacks) { | 7134 THREADED_TEST(GCFromWeakCallbacks) { |
7094 v8::Isolate* isolate = CcTest::isolate(); | 7135 v8::Isolate* isolate = CcTest::isolate(); |
7095 v8::HandleScope scope(isolate); | 7136 v8::HandleScope scope(isolate); |
7096 v8::Handle<Context> context = Context::New(isolate); | 7137 v8::Handle<Context> context = Context::New(isolate); |
7097 Context::Scope context_scope(context); | 7138 Context::Scope context_scope(context); |
7098 | 7139 |
7099 static const int kNumberOfGCTypes = 2; | 7140 static const int kNumberOfGCTypes = 2; |
7100 typedef v8::WeakReferenceCallbacks<v8::Object, bool>::Revivable Callback; | 7141 typedef v8::WeakCallbackData<v8::Object, |
7142 pair<v8::Persistent<v8::Object>*, | |
7143 bool> >::Callback Callback; | |
7101 Callback gc_forcing_callback[kNumberOfGCTypes] = | 7144 Callback gc_forcing_callback[kNumberOfGCTypes] = |
7102 {&ForceScavenge, &ForceMarkSweep}; | 7145 {&ForceScavenge, &ForceMarkSweep}; |
7103 | 7146 |
7104 typedef void (*GCInvoker)(); | 7147 typedef void (*GCInvoker)(); |
7105 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep}; | 7148 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep}; |
7106 | 7149 |
7107 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) { | 7150 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) { |
7108 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) { | 7151 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) { |
7109 v8::Persistent<v8::Object> object; | 7152 v8::Persistent<v8::Object> object; |
7110 { | 7153 { |
7111 v8::HandleScope handle_scope(isolate); | 7154 v8::HandleScope handle_scope(isolate); |
7112 object.Reset(isolate, v8::Object::New()); | 7155 object.Reset(isolate, v8::Object::New()); |
7113 } | 7156 } |
7114 bool disposed = false; | 7157 pair<v8::Persistent<v8::Object>*, bool> object_pair(&object, false); |
7115 object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]); | 7158 object.SetWeak(&object_pair, gc_forcing_callback[inner_gc]); |
7116 object.MarkIndependent(); | 7159 object.MarkIndependent(); |
7117 invoke_gc[outer_gc](); | 7160 invoke_gc[outer_gc](); |
7118 CHECK(disposed); | 7161 CHECK(object_pair.second); |
7119 } | 7162 } |
7120 } | 7163 } |
7121 } | 7164 } |
7122 | 7165 |
7123 | 7166 |
7124 static void RevivingCallback(v8::Isolate* isolate, | 7167 static void RevivingCallback( |
7125 v8::Persistent<v8::Object>* obj, | 7168 const v8::WeakCallbackData<v8::Object, |
7126 bool* data) { | 7169 std::pair<v8::Persistent<Object>*, |
7127 obj->ClearWeak(); | 7170 bool> >& data) { |
7128 *(data) = true; | 7171 data.GetParameter()->first->ClearWeak(); |
7172 data.GetParameter()->second = true; | |
7129 } | 7173 } |
7130 | 7174 |
7131 | 7175 |
7132 THREADED_TEST(IndependentHandleRevival) { | 7176 THREADED_TEST(IndependentHandleRevival) { |
7133 v8::Isolate* isolate = CcTest::isolate(); | 7177 v8::Isolate* isolate = CcTest::isolate(); |
7134 v8::HandleScope scope(isolate); | 7178 v8::HandleScope scope(isolate); |
7135 v8::Handle<Context> context = Context::New(isolate); | 7179 v8::Handle<Context> context = Context::New(isolate); |
7136 Context::Scope context_scope(context); | 7180 Context::Scope context_scope(context); |
7137 | 7181 |
7138 v8::Persistent<v8::Object> object; | 7182 v8::Persistent<v8::Object> object; |
7139 { | 7183 { |
7140 v8::HandleScope handle_scope(isolate); | 7184 v8::HandleScope handle_scope(isolate); |
7141 v8::Local<v8::Object> o = v8::Object::New(); | 7185 v8::Local<v8::Object> o = v8::Object::New(); |
7142 object.Reset(isolate, o); | 7186 object.Reset(isolate, o); |
7143 o->Set(v8_str("x"), v8::Integer::New(1)); | 7187 o->Set(v8_str("x"), v8::Integer::New(1)); |
7144 v8::Local<String> y_str = v8_str("y"); | 7188 v8::Local<String> y_str = v8_str("y"); |
7145 o->Set(y_str, y_str); | 7189 o->Set(y_str, y_str); |
7146 } | 7190 } |
7147 bool revived = false; | 7191 pair<v8::Persistent<v8::Object>*, bool> revived(&object, false); |
7148 object.MakeWeak(&revived, &RevivingCallback); | 7192 object.SetWeak(&revived, &RevivingCallback); |
7149 object.MarkIndependent(); | 7193 object.MarkIndependent(); |
7150 CcTest::heap()->PerformScavenge(); | 7194 CcTest::heap()->PerformScavenge(); |
7151 CHECK(revived); | 7195 CHECK(revived.second); |
7152 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 7196 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
7153 { | 7197 { |
7154 v8::HandleScope handle_scope(isolate); | 7198 v8::HandleScope handle_scope(isolate); |
7155 v8::Local<v8::Object> o = v8::Local<v8::Object>::New(isolate, object); | 7199 v8::Local<v8::Object> o = v8::Local<v8::Object>::New(isolate, object); |
7156 v8::Local<String> y_str = v8_str("y"); | 7200 v8::Local<String> y_str = v8_str("y"); |
7157 CHECK_EQ(v8::Integer::New(1), o->Get(v8_str("x"))); | 7201 CHECK_EQ(v8::Integer::New(1), o->Get(v8_str("x"))); |
7158 CHECK(o->Get(y_str)->Equals(y_str)); | 7202 CHECK(o->Get(y_str)->Equals(y_str)); |
7159 } | 7203 } |
7160 } | 7204 } |
7161 | 7205 |
(...skipping 5937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13099 reinterpret_cast<i::Isolate*>(isolate)->heap()-> | 13143 reinterpret_cast<i::Isolate*>(isolate)->heap()-> |
13100 CollectAllGarbage(i::Heap::kNoGCFlags); | 13144 CollectAllGarbage(i::Heap::kNoGCFlags); |
13101 // Verify disposed. | 13145 // Verify disposed. |
13102 CHECK_EQ(initial_handles, globals->global_handles_count()); | 13146 CHECK_EQ(initial_handles, globals->global_handles_count()); |
13103 } | 13147 } |
13104 | 13148 |
13105 | 13149 |
13106 v8::Persistent<v8::Object> some_object; | 13150 v8::Persistent<v8::Object> some_object; |
13107 v8::Persistent<v8::Object> bad_handle; | 13151 v8::Persistent<v8::Object> bad_handle; |
13108 | 13152 |
13109 void NewPersistentHandleCallback(v8::Isolate* isolate, | 13153 void NewPersistentHandleCallback( |
13110 v8::Persistent<v8::Value>* handle, | 13154 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) { |
13111 void*) { | 13155 v8::HandleScope scope(data.GetIsolate()); |
13112 v8::HandleScope scope(isolate); | 13156 bad_handle.Reset(data.GetIsolate(), some_object); |
13113 bad_handle.Reset(isolate, some_object); | 13157 data.GetParameter()->Reset(); |
13114 handle->Reset(); | |
13115 } | 13158 } |
13116 | 13159 |
13117 | 13160 |
13118 THREADED_TEST(NewPersistentHandleFromWeakCallback) { | 13161 THREADED_TEST(NewPersistentHandleFromWeakCallback) { |
13119 LocalContext context; | 13162 LocalContext context; |
13120 v8::Isolate* isolate = context->GetIsolate(); | 13163 v8::Isolate* isolate = context->GetIsolate(); |
13121 | 13164 |
13122 v8::Persistent<v8::Object> handle1, handle2; | 13165 v8::Persistent<v8::Object> handle1, handle2; |
13123 { | 13166 { |
13124 v8::HandleScope scope(isolate); | 13167 v8::HandleScope scope(isolate); |
13125 some_object.Reset(isolate, v8::Object::New()); | 13168 some_object.Reset(isolate, v8::Object::New()); |
13126 handle1.Reset(isolate, v8::Object::New()); | 13169 handle1.Reset(isolate, v8::Object::New()); |
13127 handle2.Reset(isolate, v8::Object::New()); | 13170 handle2.Reset(isolate, v8::Object::New()); |
13128 } | 13171 } |
13129 // Note: order is implementation dependent alas: currently | 13172 // Note: order is implementation dependent alas: currently |
13130 // global handle nodes are processed by PostGarbageCollectionProcessing | 13173 // global handle nodes are processed by PostGarbageCollectionProcessing |
13131 // in reverse allocation order, so if second allocated handle is deleted, | 13174 // in reverse allocation order, so if second allocated handle is deleted, |
13132 // weak callback of the first handle would be able to 'reallocate' it. | 13175 // weak callback of the first handle would be able to 'reallocate' it. |
13133 handle1.MakeWeak<v8::Value, void>(NULL, NewPersistentHandleCallback); | 13176 handle1.SetWeak(&handle1, NewPersistentHandleCallback); |
13134 handle2.Reset(); | 13177 handle2.Reset(); |
13135 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 13178 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
13136 } | 13179 } |
13137 | 13180 |
13138 | 13181 |
13139 v8::Persistent<v8::Object> to_be_disposed; | 13182 v8::Persistent<v8::Object> to_be_disposed; |
13140 | 13183 |
13141 void DisposeAndForceGcCallback(v8::Isolate* isolate, | 13184 void DisposeAndForceGcCallback( |
13142 v8::Persistent<v8::Value>* handle, | 13185 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) { |
13143 void*) { | |
13144 to_be_disposed.Reset(); | 13186 to_be_disposed.Reset(); |
13145 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 13187 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
13146 handle->Reset(); | 13188 data.GetParameter()->Reset(); |
13147 } | 13189 } |
13148 | 13190 |
13149 | 13191 |
13150 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { | 13192 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { |
13151 LocalContext context; | 13193 LocalContext context; |
13152 v8::Isolate* isolate = context->GetIsolate(); | 13194 v8::Isolate* isolate = context->GetIsolate(); |
13153 | 13195 |
13154 v8::Persistent<v8::Object> handle1, handle2; | 13196 v8::Persistent<v8::Object> handle1, handle2; |
13155 { | 13197 { |
13156 v8::HandleScope scope(isolate); | 13198 v8::HandleScope scope(isolate); |
13157 handle1.Reset(isolate, v8::Object::New()); | 13199 handle1.Reset(isolate, v8::Object::New()); |
13158 handle2.Reset(isolate, v8::Object::New()); | 13200 handle2.Reset(isolate, v8::Object::New()); |
13159 } | 13201 } |
13160 handle1.MakeWeak<v8::Value, void>(NULL, DisposeAndForceGcCallback); | 13202 handle1.SetWeak(&handle1, DisposeAndForceGcCallback); |
13161 to_be_disposed.Reset(isolate, handle2); | 13203 to_be_disposed.Reset(isolate, handle2); |
13162 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 13204 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
13163 } | 13205 } |
13164 | 13206 |
13165 void DisposingCallback(v8::Isolate* isolate, | 13207 void DisposingCallback( |
13166 v8::Persistent<v8::Value>* handle, | 13208 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) { |
13167 void*) { | 13209 data.GetParameter()->Reset(); |
13168 handle->Reset(); | |
13169 } | 13210 } |
13170 | 13211 |
13171 void HandleCreatingCallback(v8::Isolate* isolate, | 13212 void HandleCreatingCallback( |
13172 v8::Persistent<v8::Value>* handle, | 13213 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) { |
13173 void*) { | 13214 v8::HandleScope scope(data.GetIsolate()); |
13174 v8::HandleScope scope(isolate); | 13215 v8::Persistent<v8::Object>(data.GetIsolate(), v8::Object::New()); |
13175 v8::Persistent<v8::Object>(isolate, v8::Object::New()); | 13216 data.GetParameter()->Reset(); |
13176 handle->Reset(); | |
13177 } | 13217 } |
13178 | 13218 |
13179 | 13219 |
13180 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { | 13220 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { |
13181 LocalContext context; | 13221 LocalContext context; |
13182 v8::Isolate* isolate = context->GetIsolate(); | 13222 v8::Isolate* isolate = context->GetIsolate(); |
13183 | 13223 |
13184 v8::Persistent<v8::Object> handle1, handle2, handle3; | 13224 v8::Persistent<v8::Object> handle1, handle2, handle3; |
13185 { | 13225 { |
13186 v8::HandleScope scope(isolate); | 13226 v8::HandleScope scope(isolate); |
13187 handle3.Reset(isolate, v8::Object::New()); | 13227 handle3.Reset(isolate, v8::Object::New()); |
13188 handle2.Reset(isolate, v8::Object::New()); | 13228 handle2.Reset(isolate, v8::Object::New()); |
13189 handle1.Reset(isolate, v8::Object::New()); | 13229 handle1.Reset(isolate, v8::Object::New()); |
13190 } | 13230 } |
13191 handle2.MakeWeak<v8::Value, void>(NULL, DisposingCallback); | 13231 handle2.SetWeak(&handle2, DisposingCallback); |
13192 handle3.MakeWeak<v8::Value, void>(NULL, HandleCreatingCallback); | 13232 handle3.SetWeak(&handle3, HandleCreatingCallback); |
13193 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 13233 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
13194 } | 13234 } |
13195 | 13235 |
13196 | 13236 |
13197 THREADED_TEST(CheckForCrossContextObjectLiterals) { | 13237 THREADED_TEST(CheckForCrossContextObjectLiterals) { |
13198 v8::V8::Initialize(); | 13238 v8::V8::Initialize(); |
13199 | 13239 |
13200 const int nof = 2; | 13240 const int nof = 2; |
13201 const char* sources[nof] = { | 13241 const char* sources[nof] = { |
13202 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }", | 13242 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }", |
(...skipping 7651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
20854 } | 20894 } |
20855 for (int i = 0; i < runs; i++) { | 20895 for (int i = 0; i < runs; i++) { |
20856 Local<String> expected; | 20896 Local<String> expected; |
20857 if (i != 0) { | 20897 if (i != 0) { |
20858 CHECK_EQ(v8_str("escape value"), values[i]); | 20898 CHECK_EQ(v8_str("escape value"), values[i]); |
20859 } else { | 20899 } else { |
20860 CHECK(values[i].IsEmpty()); | 20900 CHECK(values[i].IsEmpty()); |
20861 } | 20901 } |
20862 } | 20902 } |
20863 } | 20903 } |
OLD | NEW |