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