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 3680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3691 | 3691 |
3692 // Now make sure that a gc should get rid of the function | 3692 // Now make sure that a gc should get rid of the function |
3693 for (int i = 0; i < 4; i++) { | 3693 for (int i = 0; i < 4; i++) { |
3694 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 3694 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
3695 } | 3695 } |
3696 | 3696 |
3697 ASSERT(code->marked_for_deoptimization()); | 3697 ASSERT(code->marked_for_deoptimization()); |
3698 } | 3698 } |
3699 | 3699 |
3700 | 3700 |
3701 | |
3702 static Handle<JSFunction> OptimizeDummyFunction(const char* name) { | |
3703 EmbeddedVector<char, 256> source; | |
3704 OS::SNPrintF(source, | |
3705 "function %s() { return 0; }" | |
3706 "%s(); %s();" | |
3707 "%%OptimizeFunctionOnNextCall(%s);" | |
3708 "%s();", name, name, name, name, name); | |
3709 CompileRun(source.start()); | |
3710 Handle<JSFunction> fun = | |
3711 v8::Utils::OpenHandle( | |
3712 *v8::Handle<v8::Function>::Cast( | |
3713 CcTest::global()->Get(v8_str(name)))); | |
3714 return fun; | |
3715 } | |
3716 | |
3717 | |
3718 static int GetCodeChainLength(Code* code) { | |
3719 int result = 0; | |
3720 while (code->next_code_link()->IsCode()) { | |
3721 result++; | |
3722 code = Code::cast(code->next_code_link()); | |
3723 } | |
3724 return result; | |
3725 } | |
3726 | |
3727 | |
3728 TEST(NextCodeLinkIsWeak) { | |
3729 i::FLAG_allow_natives_syntax = true; | |
3730 CcTest::InitializeVM(); | |
3731 Isolate* isolate = CcTest::i_isolate(); | |
3732 v8::internal::Heap* heap = CcTest::heap(); | |
3733 | |
3734 if (!isolate->use_crankshaft()) return; | |
3735 HandleScope outer_scope(heap->isolate()); | |
3736 Handle<Code> code; | |
3737 heap->CollectAllAvailableGarbage(); | |
3738 int code_chain_length_before, code_chain_length_after; | |
3739 { | |
3740 HandleScope scope(heap->isolate()); | |
3741 Handle<JSFunction> mortal = OptimizeDummyFunction("mortal"); | |
3742 Handle<JSFunction> immortal = OptimizeDummyFunction("immortal"); | |
3743 CHECK_EQ(immortal->code()->next_code_link(), mortal->code()); | |
3744 code_chain_length_before = GetCodeChainLength(immortal->code()); | |
3745 // Keep the immortal code and let the mortal code die. | |
3746 code = scope.CloseAndEscape(Handle<Code>(immortal->code())); | |
3747 CompileRun("mortal = null; immortal = null;"); | |
3748 } | |
3749 heap->CollectAllAvailableGarbage(); | |
3750 // Now mortal code should be dead. | |
3751 code_chain_length_after = GetCodeChainLength(*code); | |
3752 CHECK_EQ(code_chain_length_before - 1, code_chain_length_after); | |
3753 } | |
3754 | |
3755 | |
3756 static Handle<Code> DummyOptimizedCode(Isolate* isolate) { | |
3757 i::byte buffer[i::Assembler::kMinimalBufferSize]; | |
3758 MacroAssembler masm(isolate, buffer, sizeof(buffer)); | |
3759 CodeDesc desc; | |
3760 masm.Prologue(BUILD_FUNCTION_FRAME); | |
3761 masm.GetCode(&desc); | |
3762 Handle<Object> undefined(isolate->heap()->undefined_value(), isolate); | |
3763 Handle<Code> code = isolate->factory()->NewCode( | |
3764 desc, Code::ComputeFlags(Code::OPTIMIZED_FUNCTION), undefined); | |
3765 CHECK(code->IsCode()); | |
3766 return code; | |
3767 } | |
3768 | |
3769 | |
3770 TEST(NextCodeLinkIsWeak2) { | |
3771 i::FLAG_allow_natives_syntax = true; | |
3772 CcTest::InitializeVM(); | |
3773 Isolate* isolate = CcTest::i_isolate(); | |
3774 v8::internal::Heap* heap = CcTest::heap(); | |
3775 | |
3776 if (!isolate->use_crankshaft()) return; | |
3777 HandleScope outer_scope(heap->isolate()); | |
3778 heap->CollectAllAvailableGarbage(); | |
3779 Handle<Context> context(Context::cast(heap->native_contexts_list()), isolate); | |
3780 Handle<Code> new_head; | |
3781 Handle<Object> old_head(context->get(Context::OPTIMIZED_CODE_LIST), isolate); | |
3782 { | |
3783 HandleScope scope(heap->isolate()); | |
3784 Handle<Code> immortal = DummyOptimizedCode(isolate); | |
3785 Handle<Code> mortal = DummyOptimizedCode(isolate); | |
3786 mortal->set_next_code_link(*old_head); | |
3787 immortal->set_next_code_link(*mortal); | |
3788 context->set(Context::OPTIMIZED_CODE_LIST, *immortal); | |
3789 new_head = scope.CloseAndEscape(immortal); | |
3790 } | |
3791 heap->CollectAllAvailableGarbage(); | |
3792 // Now mortal code should be dead. | |
3793 CHECK_EQ(*old_head, new_head->next_code_link()); | |
3794 } | |
3795 | |
3796 | |
3797 #ifdef DEBUG | 3701 #ifdef DEBUG |
3798 TEST(AddInstructionChangesNewSpacePromotion) { | 3702 TEST(AddInstructionChangesNewSpacePromotion) { |
3799 i::FLAG_allow_natives_syntax = true; | 3703 i::FLAG_allow_natives_syntax = true; |
3800 i::FLAG_expose_gc = true; | 3704 i::FLAG_expose_gc = true; |
3801 i::FLAG_stress_compaction = true; | 3705 i::FLAG_stress_compaction = true; |
3802 i::FLAG_gc_interval = 1000; | 3706 i::FLAG_gc_interval = 1000; |
3803 CcTest::InitializeVM(); | 3707 CcTest::InitializeVM(); |
3804 if (!i::FLAG_allocation_site_pretenuring) return; | 3708 if (!i::FLAG_allocation_site_pretenuring) return; |
3805 v8::HandleScope scope(CcTest::isolate()); | 3709 v8::HandleScope scope(CcTest::isolate()); |
3806 Isolate* isolate = CcTest::i_isolate(); | 3710 Isolate* isolate = CcTest::i_isolate(); |
(...skipping 22 matching lines...) Expand all Loading... |
3829 v8::Handle<v8::Object> global = CcTest::global(); | 3733 v8::Handle<v8::Object> global = CcTest::global(); |
3830 v8::Handle<v8::Function> g = | 3734 v8::Handle<v8::Function> g = |
3831 v8::Handle<v8::Function>::Cast(global->Get(v8_str("crash"))); | 3735 v8::Handle<v8::Function>::Cast(global->Get(v8_str("crash"))); |
3832 v8::Handle<v8::Value> args1[] = { v8_num(1) }; | 3736 v8::Handle<v8::Value> args1[] = { v8_num(1) }; |
3833 heap->DisableInlineAllocation(); | 3737 heap->DisableInlineAllocation(); |
3834 heap->set_allocation_timeout(1); | 3738 heap->set_allocation_timeout(1); |
3835 g->Call(global, 1, args1); | 3739 g->Call(global, 1, args1); |
3836 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 3740 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
3837 } | 3741 } |
3838 #endif | 3742 #endif |
OLD | NEW |