| 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 3056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3067 // where there are 2 pages left instead of 1, then we should increase the | 3067 // where there are 2 pages left instead of 1, then we should increase the |
| 3068 // size of the first page a little in SizeOfFirstPage in spaces.cc. The | 3068 // size of the first page a little in SizeOfFirstPage in spaces.cc. The |
| 3069 // first page should be small in order to reduce memory used when the VM | 3069 // first page should be small in order to reduce memory used when the VM |
| 3070 // boots, but if the 20 small arrays don't fit on the first page then that's | 3070 // boots, but if the 20 small arrays don't fit on the first page then that's |
| 3071 // an indication that it is too small. | 3071 // an indication that it is too small. |
| 3072 heap->CollectAllAvailableGarbage("triggered really hard"); | 3072 heap->CollectAllAvailableGarbage("triggered really hard"); |
| 3073 CHECK_EQ(1, old_pointer_space->CountTotalPages()); | 3073 CHECK_EQ(1, old_pointer_space->CountTotalPages()); |
| 3074 } | 3074 } |
| 3075 | 3075 |
| 3076 | 3076 |
| 3077 // Tests the FlushEagerly class from heap.h |
| 3078 TEST(ReleaseUnoptimizedCode) { |
| 3079 i::FLAG_trace_gc = true; |
| 3080 // The optimizer can allocate stuff, messing up the test. |
| 3081 i::FLAG_crankshaft = false; |
| 3082 if (i::FLAG_always_opt) return; |
| 3083 |
| 3084 CcTest::InitializeVM(); |
| 3085 Isolate* isolate = CcTest::i_isolate(); |
| 3086 Heap* heap = isolate->heap(); |
| 3087 v8::HandleScope scope(CcTest::isolate()); |
| 3088 |
| 3089 PagedSpace* code_space = heap->code_space(); |
| 3090 CompileRun( |
| 3091 "var a = [];" |
| 3092 "var sum = 0;" |
| 3093 "for (var j = 0; j < 1e4; j++) {" |
| 3094 " var fn = new Function(" |
| 3095 " 'var k; var o = {}; for (k in o) { } return ' + j + ';');" |
| 3096 " sum += fn();" |
| 3097 " a.push(fn);" |
| 3098 "}"); |
| 3099 heap->CollectAllGarbage(Heap::kNoGCFlags, "triggered for preparation"); |
| 3100 CHECK_GE(code_space->CountTotalPages(), 5); |
| 3101 // We trigger an emergency GC, but only one round, because that should be |
| 3102 // enough to flush out the code. |
| 3103 heap->CollectAllAvailableGarbage("triggered really hard", 2); |
| 3104 CHECK_LE(code_space->CountTotalPages(), 2); |
| 3105 } |
| 3106 |
| 3107 |
| 3108 // Tests the FlushEagerly class from heap.h on regexp code. |
| 3109 TEST(ReleaseRegexpCode) { |
| 3110 i::FLAG_trace_gc = true; |
| 3111 // The optimizer can allocate stuff, messing up the test. |
| 3112 i::FLAG_crankshaft = false; |
| 3113 if (i::FLAG_always_opt) return; |
| 3114 |
| 3115 CcTest::InitializeVM(); |
| 3116 Isolate* isolate = CcTest::i_isolate(); |
| 3117 Heap* heap = isolate->heap(); |
| 3118 v8::HandleScope scope(CcTest::isolate()); |
| 3119 |
| 3120 PagedSpace* code_space = heap->code_space(); |
| 3121 CompileRun( |
| 3122 "var a = [];" |
| 3123 "for (var j = 0; j < 2e4; j++) {" |
| 3124 " var re = RegExp(j + '?');" |
| 3125 " a.push(re);" |
| 3126 " re.test('foo');" |
| 3127 "}"); |
| 3128 heap->CollectAllGarbage(Heap::kNoGCFlags, "triggered for preparation"); |
| 3129 CHECK_GT(code_space->CountTotalPages(), 5); |
| 3130 // We trigger an emergency GC, but only one round, because that should be |
| 3131 // enough to flush out the code. |
| 3132 heap->CollectAllAvailableGarbage("triggered really hard", 1); |
| 3133 CHECK_LE(code_space->CountTotalPages(), 2); |
| 3134 } |
| 3135 |
| 3136 |
| 3077 TEST(Regress2237) { | 3137 TEST(Regress2237) { |
| 3078 i::FLAG_stress_compaction = false; | 3138 i::FLAG_stress_compaction = false; |
| 3079 CcTest::InitializeVM(); | 3139 CcTest::InitializeVM(); |
| 3080 Isolate* isolate = CcTest::i_isolate(); | 3140 Isolate* isolate = CcTest::i_isolate(); |
| 3081 Factory* factory = isolate->factory(); | 3141 Factory* factory = isolate->factory(); |
| 3082 v8::HandleScope scope(CcTest::isolate()); | 3142 v8::HandleScope scope(CcTest::isolate()); |
| 3083 Handle<String> slice(CcTest::heap()->empty_string()); | 3143 Handle<String> slice(CcTest::heap()->empty_string()); |
| 3084 | 3144 |
| 3085 { | 3145 { |
| 3086 // Generate a parent that lives in new-space. | 3146 // Generate a parent that lives in new-space. |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3359 v8::Handle<v8::String> source_string = | 3419 v8::Handle<v8::String> source_string = |
| 3360 v8::String::NewExternal(isolate, resource); | 3420 v8::String::NewExternal(isolate, resource); |
| 3361 i_isolate->heap()->CollectAllAvailableGarbage(); | 3421 i_isolate->heap()->CollectAllAvailableGarbage(); |
| 3362 v8::Script::Compile(source_string)->Run(); | 3422 v8::Script::Compile(source_string)->Run(); |
| 3363 CHECK(!resource->IsDisposed()); | 3423 CHECK(!resource->IsDisposed()); |
| 3364 } | 3424 } |
| 3365 // i_isolate->heap()->CollectAllAvailableGarbage(); | 3425 // i_isolate->heap()->CollectAllAvailableGarbage(); |
| 3366 CHECK(!resource->IsDisposed()); | 3426 CHECK(!resource->IsDisposed()); |
| 3367 | 3427 |
| 3368 CompileRun(accessor); | 3428 CompileRun(accessor); |
| 3369 i_isolate->heap()->CollectAllAvailableGarbage(); | 3429 i_isolate->heap()->CollectAllAvailableGarbage( |
| 3430 "force release of external source in one round", 1); |
| 3370 | 3431 |
| 3371 // External source has been released. | 3432 // External source has been released. |
| 3372 CHECK(resource->IsDisposed()); | 3433 CHECK(resource->IsDisposed()); |
| 3373 delete resource; | 3434 delete resource; |
| 3374 } | 3435 } |
| 3375 | 3436 |
| 3376 | 3437 |
| 3377 UNINITIALIZED_TEST(ReleaseStackTraceData) { | 3438 UNINITIALIZED_TEST(ReleaseStackTraceData) { |
| 3378 if (i::FLAG_always_opt) { | 3439 if (i::FLAG_always_opt) { |
| 3379 // TODO(ulan): Remove this once the memory leak via code_next_link is fixed. | 3440 // TODO(ulan): Remove this once the memory leak via code_next_link is fixed. |
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4119 { | 4180 { |
| 4120 HandleScope scope(heap->isolate()); | 4181 HandleScope scope(heap->isolate()); |
| 4121 Handle<JSFunction> mortal = OptimizeDummyFunction("mortal"); | 4182 Handle<JSFunction> mortal = OptimizeDummyFunction("mortal"); |
| 4122 Handle<JSFunction> immortal = OptimizeDummyFunction("immortal"); | 4183 Handle<JSFunction> immortal = OptimizeDummyFunction("immortal"); |
| 4123 CHECK_EQ(immortal->code()->next_code_link(), mortal->code()); | 4184 CHECK_EQ(immortal->code()->next_code_link(), mortal->code()); |
| 4124 code_chain_length_before = GetCodeChainLength(immortal->code()); | 4185 code_chain_length_before = GetCodeChainLength(immortal->code()); |
| 4125 // Keep the immortal code and let the mortal code die. | 4186 // Keep the immortal code and let the mortal code die. |
| 4126 code = scope.CloseAndEscape(Handle<Code>(immortal->code())); | 4187 code = scope.CloseAndEscape(Handle<Code>(immortal->code())); |
| 4127 CompileRun("mortal = null; immortal = null;"); | 4188 CompileRun("mortal = null; immortal = null;"); |
| 4128 } | 4189 } |
| 4129 heap->CollectAllAvailableGarbage(); | 4190 heap->CollectAllAvailableGarbage("kill mortal code", 1); |
| 4130 // Now mortal code should be dead. | 4191 // Now mortal code should be dead. |
| 4131 code_chain_length_after = GetCodeChainLength(*code); | 4192 code_chain_length_after = GetCodeChainLength(*code); |
| 4132 CHECK_EQ(code_chain_length_before - 1, code_chain_length_after); | 4193 CHECK_EQ(code_chain_length_before - 1, code_chain_length_after); |
| 4133 } | 4194 } |
| 4134 | 4195 |
| 4135 | 4196 |
| 4136 static Handle<Code> DummyOptimizedCode(Isolate* isolate) { | 4197 static Handle<Code> DummyOptimizedCode(Isolate* isolate) { |
| 4137 i::byte buffer[i::Assembler::kMinimalBufferSize]; | 4198 i::byte buffer[i::Assembler::kMinimalBufferSize]; |
| 4138 MacroAssembler masm(isolate, buffer, sizeof(buffer)); | 4199 MacroAssembler masm(isolate, buffer, sizeof(buffer)); |
| 4139 CodeDesc desc; | 4200 CodeDesc desc; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4162 Handle<Object> old_head(context->get(Context::OPTIMIZED_CODE_LIST), isolate); | 4223 Handle<Object> old_head(context->get(Context::OPTIMIZED_CODE_LIST), isolate); |
| 4163 { | 4224 { |
| 4164 HandleScope scope(heap->isolate()); | 4225 HandleScope scope(heap->isolate()); |
| 4165 Handle<Code> immortal = DummyOptimizedCode(isolate); | 4226 Handle<Code> immortal = DummyOptimizedCode(isolate); |
| 4166 Handle<Code> mortal = DummyOptimizedCode(isolate); | 4227 Handle<Code> mortal = DummyOptimizedCode(isolate); |
| 4167 mortal->set_next_code_link(*old_head); | 4228 mortal->set_next_code_link(*old_head); |
| 4168 immortal->set_next_code_link(*mortal); | 4229 immortal->set_next_code_link(*mortal); |
| 4169 context->set(Context::OPTIMIZED_CODE_LIST, *immortal); | 4230 context->set(Context::OPTIMIZED_CODE_LIST, *immortal); |
| 4170 new_head = scope.CloseAndEscape(immortal); | 4231 new_head = scope.CloseAndEscape(immortal); |
| 4171 } | 4232 } |
| 4172 heap->CollectAllAvailableGarbage(); | 4233 heap->CollectAllAvailableGarbage("kill mortal code", 1); |
| 4173 // Now mortal code should be dead. | 4234 // Now mortal code should be dead. |
| 4174 CHECK_EQ(*old_head, new_head->next_code_link()); | 4235 CHECK_EQ(*old_head, new_head->next_code_link()); |
| 4175 } | 4236 } |
| 4176 | 4237 |
| 4177 | 4238 |
| 4178 static bool weak_ic_cleared = false; | 4239 static bool weak_ic_cleared = false; |
| 4179 | 4240 |
| 4180 static void ClearWeakIC(const v8::WeakCallbackData<v8::Object, void>& data) { | 4241 static void ClearWeakIC(const v8::WeakCallbackData<v8::Object, void>& data) { |
| 4181 printf("clear weak is called\n"); | 4242 printf("clear weak is called\n"); |
| 4182 weak_ic_cleared = true; | 4243 weak_ic_cleared = true; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4304 weak_cell2 = inner_scope.CloseAndEscape(factory->NewWeakCell(survivor)); | 4365 weak_cell2 = inner_scope.CloseAndEscape(factory->NewWeakCell(survivor)); |
| 4305 } | 4366 } |
| 4306 CHECK(weak_cell1->value()->IsFixedArray()); | 4367 CHECK(weak_cell1->value()->IsFixedArray()); |
| 4307 CHECK_EQ(*survivor, weak_cell2->value()); | 4368 CHECK_EQ(*survivor, weak_cell2->value()); |
| 4308 heap->CollectGarbage(NEW_SPACE); | 4369 heap->CollectGarbage(NEW_SPACE); |
| 4309 CHECK(weak_cell1->value()->IsFixedArray()); | 4370 CHECK(weak_cell1->value()->IsFixedArray()); |
| 4310 CHECK_EQ(*survivor, weak_cell2->value()); | 4371 CHECK_EQ(*survivor, weak_cell2->value()); |
| 4311 heap->CollectGarbage(NEW_SPACE); | 4372 heap->CollectGarbage(NEW_SPACE); |
| 4312 CHECK(weak_cell1->value()->IsFixedArray()); | 4373 CHECK(weak_cell1->value()->IsFixedArray()); |
| 4313 CHECK_EQ(*survivor, weak_cell2->value()); | 4374 CHECK_EQ(*survivor, weak_cell2->value()); |
| 4314 heap->CollectAllAvailableGarbage(); | 4375 heap->CollectAllAvailableGarbage("kill weak cell", 1); |
| 4315 CHECK(weak_cell1->cleared()); | 4376 CHECK(weak_cell1->cleared()); |
| 4316 CHECK_EQ(*survivor, weak_cell2->value()); | 4377 CHECK_EQ(*survivor, weak_cell2->value()); |
| 4317 } | 4378 } |
| 4318 | 4379 |
| 4319 | 4380 |
| 4320 TEST(WeakCellsWithIncrementalMarking) { | 4381 TEST(WeakCellsWithIncrementalMarking) { |
| 4321 CcTest::InitializeVM(); | 4382 CcTest::InitializeVM(); |
| 4322 Isolate* isolate = CcTest::i_isolate(); | 4383 Isolate* isolate = CcTest::i_isolate(); |
| 4323 v8::internal::Heap* heap = CcTest::heap(); | 4384 v8::internal::Heap* heap = CcTest::heap(); |
| 4324 v8::internal::Factory* factory = isolate->factory(); | 4385 v8::internal::Factory* factory = isolate->factory(); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4613 #ifdef DEBUG | 4674 #ifdef DEBUG |
| 4614 TEST(PathTracer) { | 4675 TEST(PathTracer) { |
| 4615 CcTest::InitializeVM(); | 4676 CcTest::InitializeVM(); |
| 4616 v8::HandleScope scope(CcTest::isolate()); | 4677 v8::HandleScope scope(CcTest::isolate()); |
| 4617 | 4678 |
| 4618 v8::Local<v8::Value> result = CompileRun("'abc'"); | 4679 v8::Local<v8::Value> result = CompileRun("'abc'"); |
| 4619 Handle<Object> o = v8::Utils::OpenHandle(*result); | 4680 Handle<Object> o = v8::Utils::OpenHandle(*result); |
| 4620 CcTest::i_isolate()->heap()->TracePathToObject(*o); | 4681 CcTest::i_isolate()->heap()->TracePathToObject(*o); |
| 4621 } | 4682 } |
| 4622 #endif // DEBUG | 4683 #endif // DEBUG |
| OLD | NEW |