| 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 3622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3633 | 3633 |
| 3634 // Prepare function f that contains type feedback for the two closures. | 3634 // Prepare function f that contains type feedback for the two closures. |
| 3635 CHECK(CcTest::global()->Set(ctx, v8_str("fun1"), fun1).FromJust()); | 3635 CHECK(CcTest::global()->Set(ctx, v8_str("fun1"), fun1).FromJust()); |
| 3636 CHECK(CcTest::global()->Set(ctx, v8_str("fun2"), fun2).FromJust()); | 3636 CHECK(CcTest::global()->Set(ctx, v8_str("fun2"), fun2).FromJust()); |
| 3637 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); | 3637 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); |
| 3638 | 3638 |
| 3639 Handle<JSFunction> f = Handle<JSFunction>::cast( | 3639 Handle<JSFunction> f = Handle<JSFunction>::cast( |
| 3640 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( | 3640 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 3641 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); | 3641 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); |
| 3642 | 3642 |
| 3643 Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector()); | 3643 Handle<TypeFeedbackVector> feedback_vector(f->feedback_vector()); |
| 3644 FeedbackVectorHelper feedback_helper(feedback_vector); | 3644 FeedbackVectorHelper feedback_helper(feedback_vector); |
| 3645 | 3645 |
| 3646 int expected_slots = 2; | 3646 int expected_slots = 2; |
| 3647 CHECK_EQ(expected_slots, feedback_helper.slot_count()); | 3647 CHECK_EQ(expected_slots, feedback_helper.slot_count()); |
| 3648 int slot1 = 0; | 3648 int slot1 = 0; |
| 3649 int slot2 = 1; | 3649 int slot2 = 1; |
| 3650 CHECK(feedback_vector->Get(feedback_helper.slot(slot1))->IsWeakCell()); | 3650 CHECK(feedback_vector->Get(feedback_helper.slot(slot1))->IsWeakCell()); |
| 3651 CHECK(feedback_vector->Get(feedback_helper.slot(slot2))->IsWeakCell()); | 3651 CHECK(feedback_vector->Get(feedback_helper.slot(slot2))->IsWeakCell()); |
| 3652 | 3652 |
| 3653 SimulateIncrementalMarking(CcTest::heap()); | 3653 SimulateIncrementalMarking(CcTest::heap()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3670 return target; | 3670 return target; |
| 3671 } | 3671 } |
| 3672 } | 3672 } |
| 3673 return NULL; | 3673 return NULL; |
| 3674 } | 3674 } |
| 3675 | 3675 |
| 3676 | 3676 |
| 3677 static void CheckVectorIC(Handle<JSFunction> f, int slot_index, | 3677 static void CheckVectorIC(Handle<JSFunction> f, int slot_index, |
| 3678 InlineCacheState desired_state) { | 3678 InlineCacheState desired_state) { |
| 3679 Handle<TypeFeedbackVector> vector = | 3679 Handle<TypeFeedbackVector> vector = |
| 3680 Handle<TypeFeedbackVector>(f->shared()->feedback_vector()); | 3680 Handle<TypeFeedbackVector>(f->feedback_vector()); |
| 3681 FeedbackVectorHelper helper(vector); | 3681 FeedbackVectorHelper helper(vector); |
| 3682 FeedbackVectorSlot slot = helper.slot(slot_index); | 3682 FeedbackVectorSlot slot = helper.slot(slot_index); |
| 3683 if (vector->GetKind(slot) == FeedbackVectorSlotKind::LOAD_IC) { | 3683 if (vector->GetKind(slot) == FeedbackVectorSlotKind::LOAD_IC) { |
| 3684 LoadICNexus nexus(vector, slot); | 3684 LoadICNexus nexus(vector, slot); |
| 3685 CHECK(nexus.StateFromFeedback() == desired_state); | 3685 CHECK(nexus.StateFromFeedback() == desired_state); |
| 3686 } else { | 3686 } else { |
| 3687 CHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); | 3687 CHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); |
| 3688 KeyedLoadICNexus nexus(vector, slot); | 3688 KeyedLoadICNexus nexus(vector, slot); |
| 3689 CHECK(nexus.StateFromFeedback() == desired_state); | 3689 CHECK(nexus.StateFromFeedback() == desired_state); |
| 3690 } | 3690 } |
| 3691 } | 3691 } |
| 3692 | 3692 |
| 3693 | |
| 3694 static void CheckVectorICCleared(Handle<JSFunction> f, int slot_index) { | |
| 3695 Handle<TypeFeedbackVector> vector = | |
| 3696 Handle<TypeFeedbackVector>(f->shared()->feedback_vector()); | |
| 3697 FeedbackVectorSlot slot(slot_index); | |
| 3698 LoadICNexus nexus(vector, slot); | |
| 3699 CHECK(IC::IsCleared(&nexus)); | |
| 3700 } | |
| 3701 | |
| 3702 | |
| 3703 TEST(IncrementalMarkingPreservesMonomorphicConstructor) { | 3693 TEST(IncrementalMarkingPreservesMonomorphicConstructor) { |
| 3704 if (i::FLAG_always_opt) return; | 3694 if (i::FLAG_always_opt) return; |
| 3705 CcTest::InitializeVM(); | 3695 CcTest::InitializeVM(); |
| 3706 v8::HandleScope scope(CcTest::isolate()); | 3696 v8::HandleScope scope(CcTest::isolate()); |
| 3707 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); | 3697 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); |
| 3708 // Prepare function f that contains a monomorphic IC for object | 3698 // Prepare function f that contains a monomorphic IC for object |
| 3709 // originating from the same native context. | 3699 // originating from the same native context. |
| 3710 CompileRun( | 3700 CompileRun( |
| 3711 "function fun() { this.x = 1; };" | 3701 "function fun() { this.x = 1; };" |
| 3712 "function f(o) { return new o(); } f(fun); f(fun);"); | 3702 "function f(o) { return new o(); } f(fun); f(fun);"); |
| 3713 Handle<JSFunction> f = Handle<JSFunction>::cast( | 3703 Handle<JSFunction> f = Handle<JSFunction>::cast( |
| 3714 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( | 3704 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 3715 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); | 3705 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); |
| 3716 | 3706 |
| 3717 Handle<TypeFeedbackVector> vector(f->shared()->feedback_vector()); | 3707 Handle<TypeFeedbackVector> vector(f->feedback_vector()); |
| 3718 CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell()); | 3708 CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell()); |
| 3719 | 3709 |
| 3720 SimulateIncrementalMarking(CcTest::heap()); | 3710 SimulateIncrementalMarking(CcTest::heap()); |
| 3721 CcTest::heap()->CollectAllGarbage(); | 3711 CcTest::heap()->CollectAllGarbage(); |
| 3722 | 3712 |
| 3723 CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell()); | 3713 CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell()); |
| 3724 } | 3714 } |
| 3725 | 3715 |
| 3726 | |
| 3727 TEST(IncrementalMarkingClearsMonomorphicConstructor) { | |
| 3728 if (i::FLAG_always_opt) return; | |
| 3729 CcTest::InitializeVM(); | |
| 3730 Isolate* isolate = CcTest::i_isolate(); | |
| 3731 v8::HandleScope scope(CcTest::isolate()); | |
| 3732 v8::Local<v8::Value> fun1; | |
| 3733 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); | |
| 3734 | |
| 3735 { | |
| 3736 LocalContext env; | |
| 3737 CompileRun("function fun() { this.x = 1; };"); | |
| 3738 fun1 = env->Global()->Get(env.local(), v8_str("fun")).ToLocalChecked(); | |
| 3739 } | |
| 3740 | |
| 3741 // Prepare function f that contains a monomorphic constructor for object | |
| 3742 // originating from a different native context. | |
| 3743 CHECK(CcTest::global()->Set(ctx, v8_str("fun1"), fun1).FromJust()); | |
| 3744 CompileRun( | |
| 3745 "function fun() { this.x = 1; };" | |
| 3746 "function f(o) { return new o(); } f(fun1); f(fun1);"); | |
| 3747 Handle<JSFunction> f = Handle<JSFunction>::cast( | |
| 3748 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( | |
| 3749 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); | |
| 3750 | |
| 3751 | |
| 3752 Handle<TypeFeedbackVector> vector(f->shared()->feedback_vector()); | |
| 3753 CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell()); | |
| 3754 | |
| 3755 // Fire context dispose notification. | |
| 3756 CcTest::isolate()->ContextDisposedNotification(); | |
| 3757 SimulateIncrementalMarking(CcTest::heap()); | |
| 3758 CcTest::heap()->CollectAllGarbage(); | |
| 3759 | |
| 3760 CHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(isolate), | |
| 3761 vector->Get(FeedbackVectorSlot(0))); | |
| 3762 } | |
| 3763 | |
| 3764 | |
| 3765 TEST(IncrementalMarkingPreservesMonomorphicIC) { | 3716 TEST(IncrementalMarkingPreservesMonomorphicIC) { |
| 3766 if (i::FLAG_always_opt) return; | 3717 if (i::FLAG_always_opt) return; |
| 3767 CcTest::InitializeVM(); | 3718 CcTest::InitializeVM(); |
| 3768 v8::HandleScope scope(CcTest::isolate()); | 3719 v8::HandleScope scope(CcTest::isolate()); |
| 3769 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); | 3720 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); |
| 3770 // Prepare function f that contains a monomorphic IC for object | 3721 // Prepare function f that contains a monomorphic IC for object |
| 3771 // originating from the same native context. | 3722 // originating from the same native context. |
| 3772 CompileRun("function fun() { this.x = 1; }; var obj = new fun();" | 3723 CompileRun("function fun() { this.x = 1; }; var obj = new fun();" |
| 3773 "function f(o) { return o.x; } f(obj); f(obj);"); | 3724 "function f(o) { return o.x; } f(obj); f(obj);"); |
| 3774 Handle<JSFunction> f = Handle<JSFunction>::cast( | 3725 Handle<JSFunction> f = Handle<JSFunction>::cast( |
| 3775 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( | 3726 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 3776 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); | 3727 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); |
| 3777 | 3728 |
| 3778 CheckVectorIC(f, 0, MONOMORPHIC); | 3729 CheckVectorIC(f, 0, MONOMORPHIC); |
| 3779 | 3730 |
| 3780 SimulateIncrementalMarking(CcTest::heap()); | 3731 SimulateIncrementalMarking(CcTest::heap()); |
| 3781 CcTest::heap()->CollectAllGarbage(); | 3732 CcTest::heap()->CollectAllGarbage(); |
| 3782 | 3733 |
| 3783 CheckVectorIC(f, 0, MONOMORPHIC); | 3734 CheckVectorIC(f, 0, MONOMORPHIC); |
| 3784 } | 3735 } |
| 3785 | 3736 |
| 3786 | |
| 3787 TEST(IncrementalMarkingClearsMonomorphicIC) { | |
| 3788 if (i::FLAG_always_opt) return; | |
| 3789 CcTest::InitializeVM(); | |
| 3790 v8::HandleScope scope(CcTest::isolate()); | |
| 3791 v8::Local<v8::Value> obj1; | |
| 3792 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); | |
| 3793 | |
| 3794 { | |
| 3795 LocalContext env; | |
| 3796 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"); | |
| 3797 obj1 = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked(); | |
| 3798 } | |
| 3799 | |
| 3800 // Prepare function f that contains a monomorphic IC for object | |
| 3801 // originating from a different native context. | |
| 3802 CHECK(CcTest::global()->Set(ctx, v8_str("obj1"), obj1).FromJust()); | |
| 3803 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);"); | |
| 3804 Handle<JSFunction> f = Handle<JSFunction>::cast( | |
| 3805 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( | |
| 3806 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); | |
| 3807 | |
| 3808 CheckVectorIC(f, 0, MONOMORPHIC); | |
| 3809 | |
| 3810 // Fire context dispose notification. | |
| 3811 CcTest::isolate()->ContextDisposedNotification(); | |
| 3812 SimulateIncrementalMarking(CcTest::heap()); | |
| 3813 CcTest::heap()->CollectAllGarbage(); | |
| 3814 | |
| 3815 CheckVectorICCleared(f, 0); | |
| 3816 } | |
| 3817 | |
| 3818 | |
| 3819 TEST(IncrementalMarkingPreservesPolymorphicIC) { | 3737 TEST(IncrementalMarkingPreservesPolymorphicIC) { |
| 3820 if (i::FLAG_always_opt) return; | 3738 if (i::FLAG_always_opt) return; |
| 3821 CcTest::InitializeVM(); | 3739 CcTest::InitializeVM(); |
| 3822 v8::HandleScope scope(CcTest::isolate()); | 3740 v8::HandleScope scope(CcTest::isolate()); |
| 3823 v8::Local<v8::Value> obj1, obj2; | 3741 v8::Local<v8::Value> obj1, obj2; |
| 3824 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); | 3742 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); |
| 3825 | 3743 |
| 3826 { | 3744 { |
| 3827 LocalContext env; | 3745 LocalContext env; |
| 3828 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"); | 3746 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3846 | 3764 |
| 3847 CheckVectorIC(f, 0, POLYMORPHIC); | 3765 CheckVectorIC(f, 0, POLYMORPHIC); |
| 3848 | 3766 |
| 3849 // Fire context dispose notification. | 3767 // Fire context dispose notification. |
| 3850 SimulateIncrementalMarking(CcTest::heap()); | 3768 SimulateIncrementalMarking(CcTest::heap()); |
| 3851 CcTest::heap()->CollectAllGarbage(); | 3769 CcTest::heap()->CollectAllGarbage(); |
| 3852 | 3770 |
| 3853 CheckVectorIC(f, 0, POLYMORPHIC); | 3771 CheckVectorIC(f, 0, POLYMORPHIC); |
| 3854 } | 3772 } |
| 3855 | 3773 |
| 3856 | 3774 TEST(ContextDisposeDoesntClearPolymorphicIC) { |
| 3857 TEST(IncrementalMarkingClearsPolymorphicIC) { | |
| 3858 if (i::FLAG_always_opt) return; | 3775 if (i::FLAG_always_opt) return; |
| 3859 CcTest::InitializeVM(); | 3776 CcTest::InitializeVM(); |
| 3860 v8::HandleScope scope(CcTest::isolate()); | 3777 v8::HandleScope scope(CcTest::isolate()); |
| 3861 v8::Local<v8::Value> obj1, obj2; | 3778 v8::Local<v8::Value> obj1, obj2; |
| 3862 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); | 3779 v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext(); |
| 3863 | 3780 |
| 3864 { | 3781 { |
| 3865 LocalContext env; | 3782 LocalContext env; |
| 3866 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"); | 3783 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"); |
| 3867 obj1 = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked(); | 3784 obj1 = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3882 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( | 3799 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 3883 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); | 3800 CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked()))); |
| 3884 | 3801 |
| 3885 CheckVectorIC(f, 0, POLYMORPHIC); | 3802 CheckVectorIC(f, 0, POLYMORPHIC); |
| 3886 | 3803 |
| 3887 // Fire context dispose notification. | 3804 // Fire context dispose notification. |
| 3888 CcTest::isolate()->ContextDisposedNotification(); | 3805 CcTest::isolate()->ContextDisposedNotification(); |
| 3889 SimulateIncrementalMarking(CcTest::heap()); | 3806 SimulateIncrementalMarking(CcTest::heap()); |
| 3890 CcTest::heap()->CollectAllGarbage(); | 3807 CcTest::heap()->CollectAllGarbage(); |
| 3891 | 3808 |
| 3892 CheckVectorICCleared(f, 0); | 3809 CheckVectorIC(f, 0, POLYMORPHIC); |
| 3893 } | 3810 } |
| 3894 | 3811 |
| 3895 | 3812 |
| 3896 class SourceResource : public v8::String::ExternalOneByteStringResource { | 3813 class SourceResource : public v8::String::ExternalOneByteStringResource { |
| 3897 public: | 3814 public: |
| 3898 explicit SourceResource(const char* data) | 3815 explicit SourceResource(const char* data) |
| 3899 : data_(data), length_(strlen(data)) { } | 3816 : data_(data), length_(strlen(data)) { } |
| 3900 | 3817 |
| 3901 virtual void Dispose() { | 3818 virtual void Dispose() { |
| 3902 i::DeleteArray(data_); | 3819 i::DeleteArray(data_); |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4296 CompileRun("function g() { return 2 }" | 4213 CompileRun("function g() { return 2 }" |
| 4297 "g(); %OptimizeFunctionOnNextCall(g); g();"); | 4214 "g(); %OptimizeFunctionOnNextCall(g); g();"); |
| 4298 | 4215 |
| 4299 Handle<JSFunction> g = Handle<JSFunction>::cast( | 4216 Handle<JSFunction> g = Handle<JSFunction>::cast( |
| 4300 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( | 4217 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 4301 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked()))); | 4218 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked()))); |
| 4302 code = inner_scope.CloseAndEscape(handle(g->code(), isolate)); | 4219 code = inner_scope.CloseAndEscape(handle(g->code(), isolate)); |
| 4303 if (!code->is_optimized_code()) return; | 4220 if (!code->is_optimized_code()) return; |
| 4304 } | 4221 } |
| 4305 | 4222 |
| 4306 Handle<TypeFeedbackVector> vector = handle(shared->feedback_vector()); | 4223 Handle<TypeFeedbackVector> vector = |
| 4224 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); |
| 4307 Handle<LiteralsArray> lit = | 4225 Handle<LiteralsArray> lit = |
| 4308 LiteralsArray::New(isolate, vector, shared->num_literals(), TENURED); | 4226 LiteralsArray::New(isolate, vector, shared->num_literals(), TENURED); |
| 4309 Handle<Context> context(isolate->context()); | 4227 Handle<Context> context(isolate->context()); |
| 4310 | 4228 |
| 4311 // Add the new code several times to the optimized code map and also set an | 4229 // Add the new code several times to the optimized code map and also set an |
| 4312 // allocation timeout so that expanding the code map will trigger a GC. | 4230 // allocation timeout so that expanding the code map will trigger a GC. |
| 4313 heap->set_allocation_timeout(5); | 4231 heap->set_allocation_timeout(5); |
| 4314 FLAG_gc_interval = 1000; | 4232 FLAG_gc_interval = 1000; |
| 4315 for (int i = 0; i < 10; ++i) { | 4233 for (int i = 0; i < 10; ++i) { |
| 4316 BailoutId id = BailoutId(i); | 4234 BailoutId id = BailoutId(i); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4353 CompileRun("function g() { return 2 }" | 4271 CompileRun("function g() { return 2 }" |
| 4354 "g(); %OptimizeFunctionOnNextCall(g); g();"); | 4272 "g(); %OptimizeFunctionOnNextCall(g); g();"); |
| 4355 | 4273 |
| 4356 Handle<JSFunction> g = Handle<JSFunction>::cast( | 4274 Handle<JSFunction> g = Handle<JSFunction>::cast( |
| 4357 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( | 4275 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 4358 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked()))); | 4276 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked()))); |
| 4359 code = inner_scope.CloseAndEscape(handle(g->code(), isolate)); | 4277 code = inner_scope.CloseAndEscape(handle(g->code(), isolate)); |
| 4360 if (!code->is_optimized_code()) return; | 4278 if (!code->is_optimized_code()) return; |
| 4361 } | 4279 } |
| 4362 | 4280 |
| 4363 Handle<TypeFeedbackVector> vector = handle(shared->feedback_vector()); | 4281 Handle<TypeFeedbackVector> vector = |
| 4282 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); |
| 4364 Handle<LiteralsArray> lit = | 4283 Handle<LiteralsArray> lit = |
| 4365 LiteralsArray::New(isolate, vector, shared->num_literals(), TENURED); | 4284 LiteralsArray::New(isolate, vector, shared->num_literals(), TENURED); |
| 4366 Handle<Context> context(isolate->context()); | 4285 Handle<Context> context(isolate->context()); |
| 4367 | 4286 |
| 4368 // Add the code several times to the optimized code map. | 4287 // Add the code several times to the optimized code map. |
| 4369 for (int i = 0; i < 3; ++i) { | 4288 for (int i = 0; i < 3; ++i) { |
| 4370 HandleScope inner_scope(isolate); | 4289 HandleScope inner_scope(isolate); |
| 4371 BailoutId id = BailoutId(i); | 4290 BailoutId id = BailoutId(i); |
| 4372 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id); | 4291 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id); |
| 4373 } | 4292 } |
| (...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5058 weak_ic_cleared = false; | 4977 weak_ic_cleared = false; |
| 5059 garbage.SetWeak(&garbage, &ClearWeakIC, v8::WeakCallbackType::kParameter); | 4978 garbage.SetWeak(&garbage, &ClearWeakIC, v8::WeakCallbackType::kParameter); |
| 5060 Heap* heap = CcTest::i_isolate()->heap(); | 4979 Heap* heap = CcTest::i_isolate()->heap(); |
| 5061 heap->CollectAllGarbage(); | 4980 heap->CollectAllGarbage(); |
| 5062 CHECK(weak_ic_cleared); | 4981 CHECK(weak_ic_cleared); |
| 5063 | 4982 |
| 5064 // We've determined the constructor in createObj has had it's weak cell | 4983 // We've determined the constructor in createObj has had it's weak cell |
| 5065 // cleared. Now, verify that one additional call with a new function | 4984 // cleared. Now, verify that one additional call with a new function |
| 5066 // allows monomorphicity. | 4985 // allows monomorphicity. |
| 5067 Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>( | 4986 Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>( |
| 5068 createObj->shared()->feedback_vector(), CcTest::i_isolate()); | 4987 createObj->feedback_vector(), CcTest::i_isolate()); |
| 5069 for (int i = 0; i < 20; i++) { | 4988 for (int i = 0; i < 20; i++) { |
| 5070 Object* slot_value = feedback_vector->Get(FeedbackVectorSlot(0)); | 4989 Object* slot_value = feedback_vector->Get(FeedbackVectorSlot(0)); |
| 5071 CHECK(slot_value->IsWeakCell()); | 4990 CHECK(slot_value->IsWeakCell()); |
| 5072 if (WeakCell::cast(slot_value)->cleared()) break; | 4991 if (WeakCell::cast(slot_value)->cleared()) break; |
| 5073 heap->CollectAllGarbage(); | 4992 heap->CollectAllGarbage(); |
| 5074 } | 4993 } |
| 5075 | 4994 |
| 5076 Object* slot_value = feedback_vector->Get(FeedbackVectorSlot(0)); | 4995 Object* slot_value = feedback_vector->Get(FeedbackVectorSlot(0)); |
| 5077 CHECK(slot_value->IsWeakCell() && WeakCell::cast(slot_value)->cleared()); | 4996 CHECK(slot_value->IsWeakCell() && WeakCell::cast(slot_value)->cleared()); |
| 5078 CompileRun( | 4997 CompileRun( |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5259 } | 5178 } |
| 5260 | 5179 |
| 5261 | 5180 |
| 5262 Handle<JSFunction> GetFunctionByName(Isolate* isolate, const char* name) { | 5181 Handle<JSFunction> GetFunctionByName(Isolate* isolate, const char* name) { |
| 5263 Handle<String> str = isolate->factory()->InternalizeUtf8String(name); | 5182 Handle<String> str = isolate->factory()->InternalizeUtf8String(name); |
| 5264 Handle<Object> obj = | 5183 Handle<Object> obj = |
| 5265 Object::GetProperty(isolate->global_object(), str).ToHandleChecked(); | 5184 Object::GetProperty(isolate->global_object(), str).ToHandleChecked(); |
| 5266 return Handle<JSFunction>::cast(obj); | 5185 return Handle<JSFunction>::cast(obj); |
| 5267 } | 5186 } |
| 5268 | 5187 |
| 5269 | 5188 void CheckIC(Handle<JSFunction> function, Code::Kind kind, int slot_index, |
| 5270 void CheckIC(Code* code, Code::Kind kind, SharedFunctionInfo* shared, | 5189 InlineCacheState state) { |
| 5271 int slot_index, InlineCacheState state) { | |
| 5272 if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC || | 5190 if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC || |
| 5273 kind == Code::CALL_IC) { | 5191 kind == Code::CALL_IC) { |
| 5274 TypeFeedbackVector* vector = shared->feedback_vector(); | 5192 TypeFeedbackVector* vector = function->feedback_vector(); |
| 5275 FeedbackVectorSlot slot(slot_index); | 5193 FeedbackVectorSlot slot(slot_index); |
| 5276 if (kind == Code::LOAD_IC) { | 5194 if (kind == Code::LOAD_IC) { |
| 5277 LoadICNexus nexus(vector, slot); | 5195 LoadICNexus nexus(vector, slot); |
| 5278 CHECK_EQ(nexus.StateFromFeedback(), state); | 5196 CHECK_EQ(nexus.StateFromFeedback(), state); |
| 5279 } else if (kind == Code::KEYED_LOAD_IC) { | 5197 } else if (kind == Code::KEYED_LOAD_IC) { |
| 5280 KeyedLoadICNexus nexus(vector, slot); | 5198 KeyedLoadICNexus nexus(vector, slot); |
| 5281 CHECK_EQ(nexus.StateFromFeedback(), state); | 5199 CHECK_EQ(nexus.StateFromFeedback(), state); |
| 5282 } else if (kind == Code::CALL_IC) { | 5200 } else if (kind == Code::CALL_IC) { |
| 5283 CallICNexus nexus(vector, slot); | 5201 CallICNexus nexus(vector, slot); |
| 5284 CHECK_EQ(nexus.StateFromFeedback(), state); | 5202 CHECK_EQ(nexus.StateFromFeedback(), state); |
| 5285 } | 5203 } |
| 5286 } else { | 5204 } else { |
| 5287 Code* ic = FindFirstIC(code, kind); | 5205 Code* ic = FindFirstIC(function->code(), kind); |
| 5288 CHECK(ic->is_inline_cache_stub()); | 5206 CHECK(ic->is_inline_cache_stub()); |
| 5289 CHECK(ic->ic_state() == state); | 5207 CHECK(ic->ic_state() == state); |
| 5290 } | 5208 } |
| 5291 } | 5209 } |
| 5292 | 5210 |
| 5293 | 5211 |
| 5294 TEST(MonomorphicStaysMonomorphicAfterGC) { | 5212 TEST(MonomorphicStaysMonomorphicAfterGC) { |
| 5295 if (FLAG_always_opt) return; | 5213 if (FLAG_always_opt) return; |
| 5296 CcTest::InitializeVM(); | 5214 CcTest::InitializeVM(); |
| 5297 Isolate* isolate = CcTest::i_isolate(); | 5215 Isolate* isolate = CcTest::i_isolate(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5308 " loadIC(obj);" | 5226 " loadIC(obj);" |
| 5309 " loadIC(obj);" | 5227 " loadIC(obj);" |
| 5310 " return proto;" | 5228 " return proto;" |
| 5311 "};"); | 5229 "};"); |
| 5312 Handle<JSFunction> loadIC = GetFunctionByName(isolate, "loadIC"); | 5230 Handle<JSFunction> loadIC = GetFunctionByName(isolate, "loadIC"); |
| 5313 { | 5231 { |
| 5314 v8::HandleScope scope(CcTest::isolate()); | 5232 v8::HandleScope scope(CcTest::isolate()); |
| 5315 CompileRun("(testIC())"); | 5233 CompileRun("(testIC())"); |
| 5316 } | 5234 } |
| 5317 heap->CollectAllGarbage(); | 5235 heap->CollectAllGarbage(); |
| 5318 CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC); | 5236 CheckIC(loadIC, Code::LOAD_IC, 0, MONOMORPHIC); |
| 5319 { | 5237 { |
| 5320 v8::HandleScope scope(CcTest::isolate()); | 5238 v8::HandleScope scope(CcTest::isolate()); |
| 5321 CompileRun("(testIC())"); | 5239 CompileRun("(testIC())"); |
| 5322 } | 5240 } |
| 5323 CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC); | 5241 CheckIC(loadIC, Code::LOAD_IC, 0, MONOMORPHIC); |
| 5324 } | 5242 } |
| 5325 | 5243 |
| 5326 | 5244 |
| 5327 TEST(PolymorphicStaysPolymorphicAfterGC) { | 5245 TEST(PolymorphicStaysPolymorphicAfterGC) { |
| 5328 if (FLAG_always_opt) return; | 5246 if (FLAG_always_opt) return; |
| 5329 CcTest::InitializeVM(); | 5247 CcTest::InitializeVM(); |
| 5330 Isolate* isolate = CcTest::i_isolate(); | 5248 Isolate* isolate = CcTest::i_isolate(); |
| 5331 Heap* heap = isolate->heap(); | 5249 Heap* heap = isolate->heap(); |
| 5332 v8::HandleScope scope(CcTest::isolate()); | 5250 v8::HandleScope scope(CcTest::isolate()); |
| 5333 CompileRun( | 5251 CompileRun( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5344 " poly.x = true;" | 5262 " poly.x = true;" |
| 5345 " loadIC(poly);" | 5263 " loadIC(poly);" |
| 5346 " return proto;" | 5264 " return proto;" |
| 5347 "};"); | 5265 "};"); |
| 5348 Handle<JSFunction> loadIC = GetFunctionByName(isolate, "loadIC"); | 5266 Handle<JSFunction> loadIC = GetFunctionByName(isolate, "loadIC"); |
| 5349 { | 5267 { |
| 5350 v8::HandleScope scope(CcTest::isolate()); | 5268 v8::HandleScope scope(CcTest::isolate()); |
| 5351 CompileRun("(testIC())"); | 5269 CompileRun("(testIC())"); |
| 5352 } | 5270 } |
| 5353 heap->CollectAllGarbage(); | 5271 heap->CollectAllGarbage(); |
| 5354 CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC); | 5272 CheckIC(loadIC, Code::LOAD_IC, 0, POLYMORPHIC); |
| 5355 { | 5273 { |
| 5356 v8::HandleScope scope(CcTest::isolate()); | 5274 v8::HandleScope scope(CcTest::isolate()); |
| 5357 CompileRun("(testIC())"); | 5275 CompileRun("(testIC())"); |
| 5358 } | 5276 } |
| 5359 CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC); | 5277 CheckIC(loadIC, Code::LOAD_IC, 0, POLYMORPHIC); |
| 5360 } | 5278 } |
| 5361 | 5279 |
| 5362 | 5280 |
| 5363 TEST(WeakCell) { | 5281 TEST(WeakCell) { |
| 5364 CcTest::InitializeVM(); | 5282 CcTest::InitializeVM(); |
| 5365 Isolate* isolate = CcTest::i_isolate(); | 5283 Isolate* isolate = CcTest::i_isolate(); |
| 5366 v8::internal::Heap* heap = CcTest::heap(); | 5284 v8::internal::Heap* heap = CcTest::heap(); |
| 5367 v8::internal::Factory* factory = isolate->factory(); | 5285 v8::internal::Factory* factory = isolate->factory(); |
| 5368 | 5286 |
| 5369 HandleScope outer_scope(isolate); | 5287 HandleScope outer_scope(isolate); |
| (...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6738 // All objects need to be black after marking. If a white object crossed the | 6656 // All objects need to be black after marking. If a white object crossed the |
| 6739 // progress bar, we would fail here. | 6657 // progress bar, we would fail here. |
| 6740 for (int i = 0; i < arr.get()->length(); i++) { | 6658 for (int i = 0; i < arr.get()->length(); i++) { |
| 6741 CHECK(Marking::IsBlack( | 6659 CHECK(Marking::IsBlack( |
| 6742 Marking::MarkBitFrom(HeapObject::cast(arr.get()->get(i))))); | 6660 Marking::MarkBitFrom(HeapObject::cast(arr.get()->get(i))))); |
| 6743 } | 6661 } |
| 6744 } | 6662 } |
| 6745 | 6663 |
| 6746 } // namespace internal | 6664 } // namespace internal |
| 6747 } // namespace v8 | 6665 } // namespace v8 |
| OLD | NEW |