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 22 matching lines...) Expand all Loading... |
33 #include "src/deoptimizer.h" | 33 #include "src/deoptimizer.h" |
34 #include "src/execution.h" | 34 #include "src/execution.h" |
35 #include "src/factory.h" | 35 #include "src/factory.h" |
36 #include "src/global-handles.h" | 36 #include "src/global-handles.h" |
37 #include "src/heap/gc-tracer.h" | 37 #include "src/heap/gc-tracer.h" |
38 #include "src/ic/ic.h" | 38 #include "src/ic/ic.h" |
39 #include "src/macro-assembler.h" | 39 #include "src/macro-assembler.h" |
40 #include "src/snapshot/snapshot.h" | 40 #include "src/snapshot/snapshot.h" |
41 #include "test/cctest/cctest.h" | 41 #include "test/cctest/cctest.h" |
42 #include "test/cctest/heap-tester.h" | 42 #include "test/cctest/heap-tester.h" |
| 43 #include "test/cctest/test-feedback-vector.h" |
43 | 44 |
44 using v8::Just; | 45 using v8::Just; |
45 | 46 |
46 namespace v8 { | 47 namespace v8 { |
47 namespace internal { | 48 namespace internal { |
48 | 49 |
49 static void CheckMap(Map* map, int type, int instance_size) { | 50 static void CheckMap(Map* map, int type, int instance_size) { |
50 CHECK(map->IsHeapObject()); | 51 CHECK(map->IsHeapObject()); |
51 #ifdef DEBUG | 52 #ifdef DEBUG |
52 CHECK(CcTest::heap()->Contains(map)); | 53 CHECK(CcTest::heap()->Contains(map)); |
(...skipping 3601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3654 CcTest::global()->Set(v8_str("fun1"), fun1); | 3655 CcTest::global()->Set(v8_str("fun1"), fun1); |
3655 CcTest::global()->Set(v8_str("fun2"), fun2); | 3656 CcTest::global()->Set(v8_str("fun2"), fun2); |
3656 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); | 3657 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); |
3657 | 3658 |
3658 Handle<JSFunction> f = | 3659 Handle<JSFunction> f = |
3659 v8::Utils::OpenHandle( | 3660 v8::Utils::OpenHandle( |
3660 *v8::Handle<v8::Function>::Cast( | 3661 *v8::Handle<v8::Function>::Cast( |
3661 CcTest::global()->Get(v8_str("f")))); | 3662 CcTest::global()->Get(v8_str("f")))); |
3662 | 3663 |
3663 Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector()); | 3664 Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector()); |
| 3665 FeedbackVectorHelper feedback_helper(feedback_vector); |
3664 | 3666 |
3665 int expected_slots = 2; | 3667 int expected_slots = 2; |
3666 CHECK_EQ(expected_slots, feedback_vector->ICSlots()); | 3668 CHECK_EQ(expected_slots, feedback_helper.slot_count()); |
3667 int slot1 = 0; | 3669 int slot1 = 0; |
3668 int slot2 = 1; | 3670 int slot2 = 1; |
3669 CHECK(feedback_vector->Get(FeedbackVectorICSlot(slot1))->IsWeakCell()); | 3671 CHECK(feedback_vector->Get(feedback_helper.slot(slot1))->IsWeakCell()); |
3670 CHECK(feedback_vector->Get(FeedbackVectorICSlot(slot2))->IsWeakCell()); | 3672 CHECK(feedback_vector->Get(feedback_helper.slot(slot2))->IsWeakCell()); |
3671 | 3673 |
3672 SimulateIncrementalMarking(CcTest::heap()); | 3674 SimulateIncrementalMarking(CcTest::heap()); |
3673 CcTest::heap()->CollectAllGarbage(); | 3675 CcTest::heap()->CollectAllGarbage(); |
3674 | 3676 |
3675 CHECK(!WeakCell::cast(feedback_vector->Get(FeedbackVectorICSlot(slot1))) | 3677 CHECK(!WeakCell::cast(feedback_vector->Get(feedback_helper.slot(slot1))) |
3676 ->cleared()); | 3678 ->cleared()); |
3677 CHECK(!WeakCell::cast(feedback_vector->Get(FeedbackVectorICSlot(slot2))) | 3679 CHECK(!WeakCell::cast(feedback_vector->Get(feedback_helper.slot(slot2))) |
3678 ->cleared()); | 3680 ->cleared()); |
3679 } | 3681 } |
3680 | 3682 |
3681 | 3683 |
3682 static Code* FindFirstIC(Code* code, Code::Kind kind) { | 3684 static Code* FindFirstIC(Code* code, Code::Kind kind) { |
3683 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | | 3685 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
3684 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | | 3686 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | |
3685 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 3687 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
3686 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 3688 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
3687 RelocInfo* info = it.rinfo(); | 3689 RelocInfo* info = it.rinfo(); |
3688 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); | 3690 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); |
3689 if (target->is_inline_cache_stub() && target->kind() == kind) { | 3691 if (target->is_inline_cache_stub() && target->kind() == kind) { |
3690 return target; | 3692 return target; |
3691 } | 3693 } |
3692 } | 3694 } |
3693 return NULL; | 3695 return NULL; |
3694 } | 3696 } |
3695 | 3697 |
3696 | 3698 |
3697 static void CheckVectorIC(Handle<JSFunction> f, int ic_slot_index, | 3699 static void CheckVectorIC(Handle<JSFunction> f, int slot_index, |
3698 InlineCacheState desired_state) { | 3700 InlineCacheState desired_state) { |
3699 Handle<TypeFeedbackVector> vector = | 3701 Handle<TypeFeedbackVector> vector = |
3700 Handle<TypeFeedbackVector>(f->shared()->feedback_vector()); | 3702 Handle<TypeFeedbackVector>(f->shared()->feedback_vector()); |
3701 FeedbackVectorICSlot slot(ic_slot_index); | 3703 FeedbackVectorHelper helper(vector); |
| 3704 FeedbackVectorSlot slot = helper.slot(slot_index); |
3702 if (vector->GetKind(slot) == FeedbackVectorSlotKind::LOAD_IC) { | 3705 if (vector->GetKind(slot) == FeedbackVectorSlotKind::LOAD_IC) { |
3703 LoadICNexus nexus(vector, slot); | 3706 LoadICNexus nexus(vector, slot); |
3704 CHECK(nexus.StateFromFeedback() == desired_state); | 3707 CHECK(nexus.StateFromFeedback() == desired_state); |
3705 } else { | 3708 } else { |
3706 CHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); | 3709 CHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); |
3707 KeyedLoadICNexus nexus(vector, slot); | 3710 KeyedLoadICNexus nexus(vector, slot); |
3708 CHECK(nexus.StateFromFeedback() == desired_state); | 3711 CHECK(nexus.StateFromFeedback() == desired_state); |
3709 } | 3712 } |
3710 } | 3713 } |
3711 | 3714 |
3712 | 3715 |
3713 static void CheckVectorICCleared(Handle<JSFunction> f, int ic_slot_index) { | 3716 static void CheckVectorICCleared(Handle<JSFunction> f, int slot_index) { |
3714 Handle<TypeFeedbackVector> vector = | 3717 Handle<TypeFeedbackVector> vector = |
3715 Handle<TypeFeedbackVector>(f->shared()->feedback_vector()); | 3718 Handle<TypeFeedbackVector>(f->shared()->feedback_vector()); |
3716 FeedbackVectorICSlot slot(ic_slot_index); | 3719 FeedbackVectorSlot slot(slot_index); |
3717 LoadICNexus nexus(vector, slot); | 3720 LoadICNexus nexus(vector, slot); |
3718 CHECK(IC::IsCleared(&nexus)); | 3721 CHECK(IC::IsCleared(&nexus)); |
3719 } | 3722 } |
3720 | 3723 |
3721 | 3724 |
3722 TEST(ICInBuiltInIsClearedAppropriately) { | 3725 TEST(ICInBuiltInIsClearedAppropriately) { |
3723 if (i::FLAG_always_opt) return; | 3726 if (i::FLAG_always_opt) return; |
3724 CcTest::InitializeVM(); | 3727 CcTest::InitializeVM(); |
3725 v8::HandleScope scope(CcTest::isolate()); | 3728 v8::HandleScope scope(CcTest::isolate()); |
3726 | 3729 |
3727 Handle<JSFunction> apply; | 3730 Handle<JSFunction> apply; |
3728 { | 3731 { |
3729 LocalContext env; | 3732 LocalContext env; |
3730 v8::Local<v8::Value> res = CompileRun("Function.apply"); | 3733 v8::Local<v8::Value> res = CompileRun("Function.apply"); |
3731 Handle<JSObject> maybe_apply = | 3734 Handle<JSObject> maybe_apply = |
3732 v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res)); | 3735 v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res)); |
3733 apply = Handle<JSFunction>::cast(maybe_apply); | 3736 apply = Handle<JSFunction>::cast(maybe_apply); |
3734 TypeFeedbackVector* vector = apply->shared()->feedback_vector(); | 3737 Handle<TypeFeedbackVector> vector(apply->shared()->feedback_vector()); |
3735 CHECK(vector->ICSlots() == 1); | 3738 FeedbackVectorHelper feedback_helper(vector); |
| 3739 CHECK_EQ(1, feedback_helper.slot_count()); |
3736 CheckVectorIC(apply, 0, UNINITIALIZED); | 3740 CheckVectorIC(apply, 0, UNINITIALIZED); |
3737 CompileRun( | 3741 CompileRun( |
3738 "function b(a1, a2, a3) { return a1 + a2 + a3; }" | 3742 "function b(a1, a2, a3) { return a1 + a2 + a3; }" |
3739 "function fun(bar) { bar.apply({}, [1, 2, 3]); };" | 3743 "function fun(bar) { bar.apply({}, [1, 2, 3]); };" |
3740 "fun(b); fun(b)"); | 3744 "fun(b); fun(b)"); |
3741 CheckVectorIC(apply, 0, MONOMORPHIC); | 3745 CheckVectorIC(apply, 0, MONOMORPHIC); |
3742 } | 3746 } |
3743 | 3747 |
3744 // Fire context dispose notification. | 3748 // Fire context dispose notification. |
3745 CcTest::isolate()->ContextDisposedNotification(); | 3749 CcTest::isolate()->ContextDisposedNotification(); |
(...skipping 1487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5233 | 5237 |
5234 Handle<JSFunction> GetFunctionByName(Isolate* isolate, const char* name) { | 5238 Handle<JSFunction> GetFunctionByName(Isolate* isolate, const char* name) { |
5235 Handle<String> str = isolate->factory()->InternalizeUtf8String(name); | 5239 Handle<String> str = isolate->factory()->InternalizeUtf8String(name); |
5236 Handle<Object> obj = | 5240 Handle<Object> obj = |
5237 Object::GetProperty(isolate->global_object(), str).ToHandleChecked(); | 5241 Object::GetProperty(isolate->global_object(), str).ToHandleChecked(); |
5238 return Handle<JSFunction>::cast(obj); | 5242 return Handle<JSFunction>::cast(obj); |
5239 } | 5243 } |
5240 | 5244 |
5241 | 5245 |
5242 void CheckIC(Code* code, Code::Kind kind, SharedFunctionInfo* shared, | 5246 void CheckIC(Code* code, Code::Kind kind, SharedFunctionInfo* shared, |
5243 int ic_slot, InlineCacheState state) { | 5247 int slot_index, InlineCacheState state) { |
5244 if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC || | 5248 if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC || |
5245 kind == Code::CALL_IC) { | 5249 kind == Code::CALL_IC) { |
5246 TypeFeedbackVector* vector = shared->feedback_vector(); | 5250 TypeFeedbackVector* vector = shared->feedback_vector(); |
5247 FeedbackVectorICSlot slot(ic_slot); | 5251 FeedbackVectorSlot slot(slot_index); |
5248 if (kind == Code::LOAD_IC) { | 5252 if (kind == Code::LOAD_IC) { |
5249 LoadICNexus nexus(vector, slot); | 5253 LoadICNexus nexus(vector, slot); |
5250 CHECK_EQ(nexus.StateFromFeedback(), state); | 5254 CHECK_EQ(nexus.StateFromFeedback(), state); |
5251 } else if (kind == Code::KEYED_LOAD_IC) { | 5255 } else if (kind == Code::KEYED_LOAD_IC) { |
5252 KeyedLoadICNexus nexus(vector, slot); | 5256 KeyedLoadICNexus nexus(vector, slot); |
5253 CHECK_EQ(nexus.StateFromFeedback(), state); | 5257 CHECK_EQ(nexus.StateFromFeedback(), state); |
5254 } else if (kind == Code::CALL_IC) { | 5258 } else if (kind == Code::CALL_IC) { |
5255 CallICNexus nexus(vector, slot); | 5259 CallICNexus nexus(vector, slot); |
5256 CHECK_EQ(nexus.StateFromFeedback(), state); | 5260 CHECK_EQ(nexus.StateFromFeedback(), state); |
5257 } | 5261 } |
(...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6360 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) { | 6364 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) { |
6361 if (!obj->IsSharedFunctionInfo()) continue; | 6365 if (!obj->IsSharedFunctionInfo()) continue; |
6362 // Shared function infos without a script (API functions or C++ builtins) | 6366 // Shared function infos without a script (API functions or C++ builtins) |
6363 // are not returned by the iterator because they are not created from a | 6367 // are not returned by the iterator because they are not created from a |
6364 // script. They are not interesting for type feedback vector anyways. | 6368 // script. They are not interesting for type feedback vector anyways. |
6365 | 6369 |
6366 // TODO(mvstanton): There are builtins that use type feedback vectors, | 6370 // TODO(mvstanton): There are builtins that use type feedback vectors, |
6367 // consider adding these to the iterator. | 6371 // consider adding these to the iterator. |
6368 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 6372 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
6369 if (shared->script()->IsUndefined()) { | 6373 if (shared->script()->IsUndefined()) { |
6370 CHECK(shared->native() || 0 == shared->feedback_vector()->ICSlots()); | 6374 CHECK(shared->native() || shared->feedback_vector()->is_empty()); |
6371 } else { | 6375 } else { |
6372 sfi_count++; | 6376 sfi_count++; |
6373 } | 6377 } |
6374 } | 6378 } |
6375 } | 6379 } |
6376 | 6380 |
6377 { | 6381 { |
6378 SharedFunctionInfo::Iterator iterator(isolate); | 6382 SharedFunctionInfo::Iterator iterator(isolate); |
6379 while (iterator.Next()) sfi_count--; | 6383 while (iterator.Next()) sfi_count--; |
6380 } | 6384 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6412 // The CollectGarbage call above starts sweeper threads. | 6416 // The CollectGarbage call above starts sweeper threads. |
6413 // The crash will happen if the following two functions | 6417 // The crash will happen if the following two functions |
6414 // are called before sweeping finishes. | 6418 // are called before sweeping finishes. |
6415 heap->StartIncrementalMarking(); | 6419 heap->StartIncrementalMarking(); |
6416 heap->FinalizeIncrementalMarkingIfComplete("test"); | 6420 heap->FinalizeIncrementalMarkingIfComplete("test"); |
6417 } | 6421 } |
6418 | 6422 |
6419 | 6423 |
6420 } // namespace internal | 6424 } // namespace internal |
6421 } // namespace v8 | 6425 } // namespace v8 |
OLD | NEW |