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 3734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3745 | 3745 |
3746 // Now make sure that a gc should get rid of the function | 3746 // Now make sure that a gc should get rid of the function |
3747 for (int i = 0; i < 4; i++) { | 3747 for (int i = 0; i < 4; i++) { |
3748 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 3748 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
3749 } | 3749 } |
3750 | 3750 |
3751 ASSERT(code->marked_for_deoptimization()); | 3751 ASSERT(code->marked_for_deoptimization()); |
3752 } | 3752 } |
3753 | 3753 |
3754 | 3754 |
| 3755 |
| 3756 static Handle<JSFunction> OptimizeDummyFunction(const char* name) { |
| 3757 EmbeddedVector<char, 256> source; |
| 3758 OS::SNPrintF(source, |
| 3759 "function %s() { return 0; }" |
| 3760 "%s(); %s();" |
| 3761 "%%OptimizeFunctionOnNextCall(%s);" |
| 3762 "%s();", name, name, name, name, name); |
| 3763 CompileRun(source.start()); |
| 3764 Handle<JSFunction> fun = |
| 3765 v8::Utils::OpenHandle( |
| 3766 *v8::Handle<v8::Function>::Cast( |
| 3767 CcTest::global()->Get(v8_str(name)))); |
| 3768 return fun; |
| 3769 } |
| 3770 |
| 3771 |
| 3772 static int GetCodeChainLength(Code* code) { |
| 3773 int result = 0; |
| 3774 while (code->next_code_link()->IsCode()) { |
| 3775 result++; |
| 3776 code = Code::cast(code->next_code_link()); |
| 3777 } |
| 3778 return result; |
| 3779 } |
| 3780 |
| 3781 |
| 3782 TEST(NextCodeLinkIsWeak) { |
| 3783 i::FLAG_allow_natives_syntax = true; |
| 3784 CcTest::InitializeVM(); |
| 3785 Isolate* isolate = CcTest::i_isolate(); |
| 3786 v8::internal::Heap* heap = CcTest::heap(); |
| 3787 |
| 3788 if (!isolate->use_crankshaft()) return; |
| 3789 HandleScope outer_scope(heap->isolate()); |
| 3790 Handle<Code> code; |
| 3791 heap->CollectAllAvailableGarbage(); |
| 3792 int code_chain_length_before, code_chain_length_after; |
| 3793 { |
| 3794 HandleScope scope(heap->isolate()); |
| 3795 Handle<JSFunction> mortal = OptimizeDummyFunction("mortal"); |
| 3796 Handle<JSFunction> immortal = OptimizeDummyFunction("immortal"); |
| 3797 CHECK_EQ(immortal->code()->next_code_link(), mortal->code()); |
| 3798 code_chain_length_before = GetCodeChainLength(immortal->code()); |
| 3799 // Keep the immortal code and let the mortal code die. |
| 3800 code = scope.CloseAndEscape(Handle<Code>(immortal->code())); |
| 3801 CompileRun("mortal = null; immortal = null;"); |
| 3802 } |
| 3803 heap->CollectAllAvailableGarbage(); |
| 3804 // Now mortal code should be dead. |
| 3805 code_chain_length_after = GetCodeChainLength(*code); |
| 3806 CHECK_EQ(code_chain_length_before - 1, code_chain_length_after); |
| 3807 } |
| 3808 |
| 3809 |
| 3810 static Handle<Code> DummyOptimizedCode(Isolate* isolate) { |
| 3811 i::byte buffer[i::Assembler::kMinimalBufferSize]; |
| 3812 MacroAssembler masm(isolate, buffer, sizeof(buffer)); |
| 3813 CodeDesc desc; |
| 3814 masm.Prologue(BUILD_FUNCTION_FRAME); |
| 3815 masm.GetCode(&desc); |
| 3816 Handle<Object> undefined(isolate->heap()->undefined_value(), isolate); |
| 3817 Handle<Code> code = isolate->factory()->NewCode( |
| 3818 desc, Code::ComputeFlags(Code::OPTIMIZED_FUNCTION), undefined); |
| 3819 CHECK(code->IsCode()); |
| 3820 return code; |
| 3821 } |
| 3822 |
| 3823 |
| 3824 TEST(NextCodeLinkIsWeak2) { |
| 3825 i::FLAG_allow_natives_syntax = true; |
| 3826 CcTest::InitializeVM(); |
| 3827 Isolate* isolate = CcTest::i_isolate(); |
| 3828 v8::internal::Heap* heap = CcTest::heap(); |
| 3829 |
| 3830 if (!isolate->use_crankshaft()) return; |
| 3831 HandleScope outer_scope(heap->isolate()); |
| 3832 heap->CollectAllAvailableGarbage(); |
| 3833 Handle<Context> context(Context::cast(heap->native_contexts_list()), isolate); |
| 3834 Handle<Code> new_head; |
| 3835 Handle<Object> old_head(context->get(Context::OPTIMIZED_CODE_LIST), isolate); |
| 3836 { |
| 3837 HandleScope scope(heap->isolate()); |
| 3838 Handle<Code> immortal = DummyOptimizedCode(isolate); |
| 3839 Handle<Code> mortal = DummyOptimizedCode(isolate); |
| 3840 mortal->set_next_code_link(*old_head); |
| 3841 immortal->set_next_code_link(*mortal); |
| 3842 context->set(Context::OPTIMIZED_CODE_LIST, *immortal); |
| 3843 new_head = scope.CloseAndEscape(immortal); |
| 3844 } |
| 3845 heap->CollectAllAvailableGarbage(); |
| 3846 // Now mortal code should be dead. |
| 3847 CHECK_EQ(*old_head, new_head->next_code_link()); |
| 3848 } |
| 3849 |
| 3850 |
3755 #ifdef DEBUG | 3851 #ifdef DEBUG |
3756 TEST(AddInstructionChangesNewSpacePromotion) { | 3852 TEST(AddInstructionChangesNewSpacePromotion) { |
3757 i::FLAG_allow_natives_syntax = true; | 3853 i::FLAG_allow_natives_syntax = true; |
3758 i::FLAG_expose_gc = true; | 3854 i::FLAG_expose_gc = true; |
3759 i::FLAG_stress_compaction = true; | 3855 i::FLAG_stress_compaction = true; |
3760 i::FLAG_gc_interval = 1000; | 3856 i::FLAG_gc_interval = 1000; |
3761 CcTest::InitializeVM(); | 3857 CcTest::InitializeVM(); |
3762 if (!i::FLAG_allocation_site_pretenuring) return; | 3858 if (!i::FLAG_allocation_site_pretenuring) return; |
3763 v8::HandleScope scope(CcTest::isolate()); | 3859 v8::HandleScope scope(CcTest::isolate()); |
3764 Isolate* isolate = CcTest::i_isolate(); | 3860 Isolate* isolate = CcTest::i_isolate(); |
(...skipping 22 matching lines...) Expand all Loading... |
3787 v8::Handle<v8::Object> global = CcTest::global(); | 3883 v8::Handle<v8::Object> global = CcTest::global(); |
3788 v8::Handle<v8::Function> g = | 3884 v8::Handle<v8::Function> g = |
3789 v8::Handle<v8::Function>::Cast(global->Get(v8_str("crash"))); | 3885 v8::Handle<v8::Function>::Cast(global->Get(v8_str("crash"))); |
3790 v8::Handle<v8::Value> args1[] = { v8_num(1) }; | 3886 v8::Handle<v8::Value> args1[] = { v8_num(1) }; |
3791 heap->DisableInlineAllocation(); | 3887 heap->DisableInlineAllocation(); |
3792 heap->set_allocation_timeout(1); | 3888 heap->set_allocation_timeout(1); |
3793 g->Call(global, 1, args1); | 3889 g->Call(global, 1, args1); |
3794 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 3890 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
3795 } | 3891 } |
3796 #endif | 3892 #endif |
OLD | NEW |