Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: test/cctest/heap/test-heap.cc

Issue 2674593003: [TypeFeedbackVector] Root feedback vectors at function literal site. (Closed)
Patch Set: REBASE+liveedit fix. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/x87/macro-assembler-x87.cc ('k') | test/cctest/interpreter/interpreter-tester.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1686 matching lines...) Expand 10 before | Expand all | Expand 10 after
1697 "foo();"; 1697 "foo();";
1698 Handle<String> source = factory->InternalizeUtf8String(raw_source); 1698 Handle<String> source = factory->InternalizeUtf8String(raw_source);
1699 Handle<Context> native_context = isolate->native_context(); 1699 Handle<Context> native_context = isolate->native_context();
1700 1700
1701 { 1701 {
1702 v8::HandleScope scope(CcTest::isolate()); 1702 v8::HandleScope scope(CcTest::isolate());
1703 CompileRun(raw_source); 1703 CompileRun(raw_source);
1704 } 1704 }
1705 1705
1706 // The script should be in the cache now. 1706 // The script should be in the cache now.
1707 MaybeHandle<SharedFunctionInfo> info = compilation_cache->LookupScript( 1707 InfoVectorPair pair = compilation_cache->LookupScript(
1708 source, Handle<Object>(), 0, 0, v8::ScriptOriginOptions(true, false), 1708 source, Handle<Object>(), 0, 0, v8::ScriptOriginOptions(true, false),
1709 native_context, language_mode); 1709 native_context, language_mode);
1710 CHECK(!info.is_null()); 1710 CHECK(pair.has_shared());
1711 1711
1712 // Check that the code cache entry survives at least on GC. 1712 // Check that the code cache entry survives at least on GC.
1713 // (Unless --optimize-for-size, in which case it might get collected 1713 // (Unless --optimize-for-size, in which case it might get collected
1714 // immediately.) 1714 // immediately.)
1715 if (!FLAG_optimize_for_size) { 1715 if (!FLAG_optimize_for_size) {
1716 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); 1716 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
1717 info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, 1717 pair = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0,
1718 v8::ScriptOriginOptions(true, false), 1718 v8::ScriptOriginOptions(true, false),
1719 native_context, language_mode); 1719 native_context, language_mode);
1720 CHECK(!info.is_null()); 1720 CHECK(pair.has_shared());
1721 } 1721 }
1722 1722
1723 // Progress code age until it's old and ready for GC. 1723 // Progress code age until it's old and ready for GC.
1724 const int kAgingThreshold = 6; 1724 const int kAgingThreshold = 6;
1725 for (int i = 0; i < kAgingThreshold; i++) { 1725 for (int i = 0; i < kAgingThreshold; i++) {
1726 info.ToHandleChecked()->code()->MakeOlder(); 1726 pair.shared()->code()->MakeOlder();
1727 if (info.ToHandleChecked()->HasBytecodeArray()) { 1727 if (pair.shared()->HasBytecodeArray()) {
1728 info.ToHandleChecked()->bytecode_array()->MakeOlder(); 1728 pair.shared()->bytecode_array()->MakeOlder();
1729 } 1729 }
1730 } 1730 }
1731 1731
1732 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); 1732 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
1733 // Ensure code aging cleared the entry from the cache. 1733 // Ensure code aging cleared the entry from the cache.
1734 info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, 1734 pair = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0,
1735 v8::ScriptOriginOptions(true, false), 1735 v8::ScriptOriginOptions(true, false),
1736 native_context, language_mode); 1736 native_context, language_mode);
1737 CHECK(info.is_null()); 1737 CHECK(!pair.has_shared());
1738 } 1738 }
1739 1739
1740 1740
1741 static void OptimizeEmptyFunction(const char* name) { 1741 static void OptimizeEmptyFunction(const char* name) {
1742 HandleScope scope(CcTest::i_isolate()); 1742 HandleScope scope(CcTest::i_isolate());
1743 EmbeddedVector<char, 256> source; 1743 EmbeddedVector<char, 256> source;
1744 SNPrintF(source, 1744 SNPrintF(source,
1745 "function %s() { return 0; }" 1745 "function %s() { return 0; }"
1746 "%s(); %s();" 1746 "%s(); %s();"
1747 "%%OptimizeFunctionOnNextCall(%s);" 1747 "%%OptimizeFunctionOnNextCall(%s);"
(...skipping 2604 matching lines...) Expand 10 before | Expand all | Expand 10 after
4352 CompileRun("function g() { return 2 }" 4352 CompileRun("function g() { return 2 }"
4353 "g(); %OptimizeFunctionOnNextCall(g); g();"); 4353 "g(); %OptimizeFunctionOnNextCall(g); g();");
4354 4354
4355 Handle<JSFunction> g = Handle<JSFunction>::cast( 4355 Handle<JSFunction> g = Handle<JSFunction>::cast(
4356 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( 4356 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
4357 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked()))); 4357 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked())));
4358 code = inner_scope.CloseAndEscape(handle(g->code(), isolate)); 4358 code = inner_scope.CloseAndEscape(handle(g->code(), isolate));
4359 if (!code->is_optimized_code()) return; 4359 if (!code->is_optimized_code()) return;
4360 } 4360 }
4361 4361
4362 Handle<TypeFeedbackVector> vector =
4363 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
4364 Handle<Context> context(isolate->context()); 4362 Handle<Context> context(isolate->context());
4365 4363
4366 // Add the new code several times to the optimized code map and also set an 4364 // Add the new code several times to the optimized code map and also set an
4367 // allocation timeout so that expanding the code map will trigger a GC. 4365 // allocation timeout so that expanding the code map will trigger a GC.
4368 heap->set_allocation_timeout(5); 4366 heap->set_allocation_timeout(5);
4369 FLAG_gc_interval = 1000; 4367 FLAG_gc_interval = 1000;
4370 for (int i = 0; i < 10; ++i) { 4368 for (int i = 0; i < 10; ++i) {
4371 BailoutId id = BailoutId(i); 4369 BailoutId id = BailoutId(i);
4372 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, vector, 4370 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, id);
4373 id);
4374 } 4371 }
4375 } 4372 }
4376 #endif // DEBUG 4373 #endif // DEBUG
4377 4374
4378 TEST(Regress514122) {
4379 if (!i::FLAG_incremental_marking) return;
4380 i::FLAG_allow_natives_syntax = true;
4381 CcTest::InitializeVM();
4382 Isolate* isolate = CcTest::i_isolate();
4383 LocalContext env;
4384 Heap* heap = isolate->heap();
4385 HandleScope scope(isolate);
4386
4387 // Perfrom one initial GC to enable code flushing.
4388 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4389
4390 // Prepare function whose optimized code map we can use.
4391 Handle<SharedFunctionInfo> shared;
4392 {
4393 HandleScope inner_scope(isolate);
4394 CompileRun(
4395 "function f() { return 1 }"
4396 "f(); %OptimizeFunctionOnNextCall(f); f();");
4397
4398 Handle<JSFunction> f = Handle<JSFunction>::cast(
4399 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
4400 CcTest::global()->Get(env.local(), v8_str("f")).ToLocalChecked())));
4401 shared = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
4402 CompileRun("f = null");
4403 }
4404
4405 // Prepare optimized code that we can use.
4406 Handle<Code> code;
4407 {
4408 HandleScope inner_scope(isolate);
4409 CompileRun(
4410 "function g() { return 2 }"
4411 "g(); %OptimizeFunctionOnNextCall(g); g();");
4412
4413 Handle<JSFunction> g = Handle<JSFunction>::cast(
4414 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
4415 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked())));
4416 code = inner_scope.CloseAndEscape(handle(g->code(), isolate));
4417 if (!code->is_optimized_code()) return;
4418 }
4419
4420 Handle<TypeFeedbackVector> vector =
4421 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
4422 Handle<Context> context(isolate->context());
4423
4424 // Add the code several times to the optimized code map.
4425 for (int i = 0; i < 3; ++i) {
4426 HandleScope inner_scope(isolate);
4427 BailoutId id = BailoutId(i);
4428 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, vector,
4429 id);
4430 }
4431 shared->optimized_code_map()->Print();
4432
4433 // Add the code with a feedback vector to be evacuated.
4434 Page* evac_page;
4435 {
4436 HandleScope inner_scope(isolate);
4437 AlwaysAllocateScope always_allocate(isolate);
4438 // Make sure literal is placed on an old-space evacuation candidate.
4439 heap::SimulateFullSpace(heap->old_space());
4440
4441 // Make sure there the number of literals is > 0.
4442 Handle<TypeFeedbackVector> vector =
4443 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
4444 evac_page = Page::FromAddress(vector->address());
4445 BailoutId id = BailoutId(100);
4446 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, vector,
4447 id);
4448 }
4449
4450 // Heap is ready, force {lit_page} to become an evacuation candidate and
4451 // simulate incremental marking to enqueue optimized code map.
4452 FLAG_manual_evacuation_candidates_selection = true;
4453 heap::ForceEvacuationCandidate(evac_page);
4454 heap::SimulateIncrementalMarking(heap);
4455
4456 // No matter whether reachable or not, {boomer} is doomed.
4457 Handle<Object> boomer(shared->optimized_code_map(), isolate);
4458
4459 // Add the code several times to the optimized code map. This will leave old
4460 // copies of the optimized code map unreachable but still marked.
4461 for (int i = 3; i < 6; ++i) {
4462 HandleScope inner_scope(isolate);
4463 BailoutId id = BailoutId(i);
4464 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, vector,
4465 id);
4466 }
4467
4468 // Trigger a GC to flush out the bug.
4469 CcTest::CollectGarbage(i::OLD_SPACE);
4470 boomer->Print();
4471 }
4472
4473 TEST(OptimizedCodeMapReuseEntries) {
4474 i::FLAG_allow_natives_syntax = true;
4475 // BUG(v8:4598): Since TurboFan doesn't treat maps in code weakly, we can't
4476 // run this test.
4477 if (i::FLAG_turbo) return;
4478 CcTest::InitializeVM();
4479 v8::Isolate* v8_isolate = CcTest::isolate();
4480 Isolate* isolate = CcTest::i_isolate();
4481 HandleScope scope(isolate);
4482
4483 // Create 3 contexts, allow the 2nd one to be disposed, and verify that
4484 // a 4th context will re-use the weak slots in the optimized code map
4485 // to hold data, rather than expanding the map.
4486 v8::Local<v8::Context> c1 = v8::Context::New(v8_isolate);
4487 const char* source = "function foo(x) { var l = [1]; return x+l[0]; }";
4488 v8::ScriptCompiler::Source script_source(
4489 v8::String::NewFromUtf8(v8_isolate, source, v8::NewStringType::kNormal)
4490 .ToLocalChecked());
4491 v8::Local<v8::UnboundScript> indep =
4492 v8::ScriptCompiler::CompileUnboundScript(v8_isolate, &script_source)
4493 .ToLocalChecked();
4494 const char* toplevel = "foo(3); %OptimizeFunctionOnNextCall(foo); foo(3);";
4495 // Perfrom one initial GC to enable code flushing.
4496 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4497
4498 c1->Enter();
4499 indep->BindToCurrentContext()->Run(c1).ToLocalChecked();
4500 CompileRun(toplevel);
4501
4502 Handle<SharedFunctionInfo> shared;
4503 Handle<JSFunction> foo = Handle<JSFunction>::cast(
4504 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
4505 CcTest::global()->Get(c1, v8_str("foo")).ToLocalChecked())));
4506 CHECK(foo->shared()->is_compiled());
4507 shared = handle(foo->shared());
4508 c1->Exit();
4509
4510 {
4511 HandleScope scope(isolate);
4512 v8::Local<v8::Context> c2 = v8::Context::New(v8_isolate);
4513 c2->Enter();
4514 indep->BindToCurrentContext()->Run(c2).ToLocalChecked();
4515 CompileRun(toplevel);
4516 c2->Exit();
4517 }
4518
4519 {
4520 HandleScope scope(isolate);
4521 v8::Local<v8::Context> c3 = v8::Context::New(v8_isolate);
4522 c3->Enter();
4523 indep->BindToCurrentContext()->Run(c3).ToLocalChecked();
4524 CompileRun(toplevel);
4525 c3->Exit();
4526
4527 // Now, collect garbage. Context c2 should have no roots to it, and it's
4528 // entry in the optimized code map should be free for a new context.
4529 for (int i = 0; i < 4; i++) {
4530 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4531 }
4532
4533 Handle<FixedArray> optimized_code_map =
4534 handle(shared->optimized_code_map());
4535 // There should be 3 entries in the map.
4536 CHECK_EQ(
4537 3, ((optimized_code_map->length() - SharedFunctionInfo::kEntriesStart) /
4538 SharedFunctionInfo::kEntryLength));
4539 // But one of them (formerly for c2) should be cleared.
4540 int cleared_count = 0;
4541 for (int i = SharedFunctionInfo::kEntriesStart;
4542 i < optimized_code_map->length();
4543 i += SharedFunctionInfo::kEntryLength) {
4544 cleared_count +=
4545 WeakCell::cast(
4546 optimized_code_map->get(i + SharedFunctionInfo::kContextOffset))
4547 ->cleared()
4548 ? 1
4549 : 0;
4550 }
4551 CHECK_EQ(1, cleared_count);
4552
4553 // Verify that a new context uses the cleared entry rather than creating a
4554 // new
4555 // optimized code map array.
4556 v8::Local<v8::Context> c4 = v8::Context::New(v8_isolate);
4557 c4->Enter();
4558 indep->BindToCurrentContext()->Run(c4).ToLocalChecked();
4559 CompileRun(toplevel);
4560 c4->Exit();
4561 CHECK_EQ(*optimized_code_map, shared->optimized_code_map());
4562
4563 // Now each entry is in use.
4564 cleared_count = 0;
4565 for (int i = SharedFunctionInfo::kEntriesStart;
4566 i < optimized_code_map->length();
4567 i += SharedFunctionInfo::kEntryLength) {
4568 cleared_count +=
4569 WeakCell::cast(
4570 optimized_code_map->get(i + SharedFunctionInfo::kContextOffset))
4571 ->cleared()
4572 ? 1
4573 : 0;
4574 }
4575 CHECK_EQ(0, cleared_count);
4576 }
4577 }
4578
4579 TEST(Regress513496) { 4375 TEST(Regress513496) {
4580 i::FLAG_allow_natives_syntax = true; 4376 i::FLAG_allow_natives_syntax = true;
4581 CcTest::InitializeVM(); 4377 CcTest::InitializeVM();
4582 Isolate* isolate = CcTest::i_isolate(); 4378 Isolate* isolate = CcTest::i_isolate();
4583 HandleScope scope(isolate); 4379 HandleScope scope(isolate);
4584 4380
4585 // Perfrom one initial GC to enable code flushing. 4381 // Perfrom one initial GC to enable code flushing.
4586 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); 4382 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4587 4383
4588 // Prepare an optimized closure with containing an inlined function. Then age 4384 // Prepare an optimized closure with containing an inlined function. Then age
(...skipping 25 matching lines...) Expand all
4614 Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( 4410 Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
4615 *v8::Local<v8::Function>::Cast(CcTest::global() 4411 *v8::Local<v8::Function>::Cast(CcTest::global()
4616 ->Get(context.local(), v8_str("f")) 4412 ->Get(context.local(), v8_str("f"))
4617 .ToLocalChecked()))); 4413 .ToLocalChecked())));
4618 CHECK(f->is_compiled()); 4414 CHECK(f->is_compiled());
4619 shared = inner_scope.CloseAndEscape(handle(f->shared(), isolate)); 4415 shared = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
4620 CompileRun("f = null"); 4416 CompileRun("f = null");
4621 } 4417 }
4622 4418
4623 // Lookup the optimized code and keep it alive. 4419 // Lookup the optimized code and keep it alive.
4624 CodeAndVector result = shared->SearchOptimizedCodeMap( 4420 Code* result = shared->SearchOptimizedCodeMap(
4625 isolate->context()->native_context(), BailoutId::None()); 4421 isolate->context()->native_context(), BailoutId::None());
4626 Handle<Code> optimized_code(result.code, isolate); 4422 Handle<Code> optimized_code(result, isolate);
4627 4423
4628 // Finish a full GC cycle so that the unoptimized code of 'g' is flushed even 4424 // Finish a full GC cycle so that the unoptimized code of 'g' is flushed even
4629 // though the optimized code for 'f' is reachable via the optimized code map. 4425 // though the optimized code for 'f' is reachable via the optimized code map.
4630 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); 4426 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4631 4427
4632 // Make a new closure that will get code installed from the code map. 4428 // Make a new closure that will get code installed from the code map.
4633 // Unoptimized code is missing and the deoptimizer will go ballistic. 4429 // Unoptimized code is missing and the deoptimizer will go ballistic.
4634 CompileRun("var h = mkClosure(); h('bozo');"); 4430 CompileRun("var h = mkClosure(); h('bozo');");
4635 } 4431 }
4636 4432
(...skipping 2511 matching lines...) Expand 10 before | Expand all | Expand 10 after
7148 CHECK(!heap->code_space()->FirstPage()->Contains(code->address())); 6944 CHECK(!heap->code_space()->FirstPage()->Contains(code->address()));
7149 6945
7150 // Ensure it's not in large object space. 6946 // Ensure it's not in large object space.
7151 MemoryChunk* chunk = MemoryChunk::FromAddress(code->address()); 6947 MemoryChunk* chunk = MemoryChunk::FromAddress(code->address());
7152 CHECK(chunk->owner()->identity() != LO_SPACE); 6948 CHECK(chunk->owner()->identity() != LO_SPACE);
7153 CHECK(chunk->NeverEvacuate()); 6949 CHECK(chunk->NeverEvacuate());
7154 } 6950 }
7155 6951
7156 } // namespace internal 6952 } // namespace internal
7157 } // namespace v8 6953 } // namespace v8
OLDNEW
« no previous file with comments | « src/x87/macro-assembler-x87.cc ('k') | test/cctest/interpreter/interpreter-tester.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698