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

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

Issue 2504153002: [TypeFeedbackVector] Root literal arrays in function literals slots (Closed)
Patch Set: REBASE. Created 3 years, 12 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
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 4278 matching lines...) Expand 10 before | Expand all | Expand 10 after
4289 CompileRun("function g() { return 2 }" 4289 CompileRun("function g() { return 2 }"
4290 "g(); %OptimizeFunctionOnNextCall(g); g();"); 4290 "g(); %OptimizeFunctionOnNextCall(g); g();");
4291 4291
4292 Handle<JSFunction> g = Handle<JSFunction>::cast( 4292 Handle<JSFunction> g = Handle<JSFunction>::cast(
4293 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( 4293 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
4294 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked()))); 4294 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked())));
4295 code = inner_scope.CloseAndEscape(handle(g->code(), isolate)); 4295 code = inner_scope.CloseAndEscape(handle(g->code(), isolate));
4296 if (!code->is_optimized_code()) return; 4296 if (!code->is_optimized_code()) return;
4297 } 4297 }
4298 4298
4299 Handle<TypeFeedbackVector> vector =
4300 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
4301 Handle<LiteralsArray> lit =
4302 LiteralsArray::New(isolate, vector, shared->num_literals());
4303 Handle<Context> context(isolate->context()); 4299 Handle<Context> context(isolate->context());
4304 4300
4305 // Add the new code several times to the optimized code map and also set an 4301 // Add the new code several times to the optimized code map and also set an
4306 // allocation timeout so that expanding the code map will trigger a GC. 4302 // allocation timeout so that expanding the code map will trigger a GC.
4307 heap->set_allocation_timeout(5); 4303 heap->set_allocation_timeout(5);
4308 FLAG_gc_interval = 1000; 4304 FLAG_gc_interval = 1000;
4309 for (int i = 0; i < 10; ++i) { 4305 for (int i = 0; i < 10; ++i) {
4310 BailoutId id = BailoutId(i); 4306 BailoutId id = BailoutId(i);
4311 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id); 4307 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, id);
4312 } 4308 }
4313 } 4309 }
4314 #endif // DEBUG 4310 #endif // DEBUG
4315 4311
4316
4317 TEST(Regress514122) {
4318 if (!i::FLAG_incremental_marking) return;
4319 i::FLAG_allow_natives_syntax = true;
4320 CcTest::InitializeVM();
4321 Isolate* isolate = CcTest::i_isolate();
4322 LocalContext env;
4323 Heap* heap = isolate->heap();
4324 HandleScope scope(isolate);
4325
4326 // Perfrom one initial GC to enable code flushing.
4327 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4328
4329 // Prepare function whose optimized code map we can use.
4330 Handle<SharedFunctionInfo> shared;
4331 {
4332 HandleScope inner_scope(isolate);
4333 CompileRun("function f() { return 1 }"
4334 "f(); %OptimizeFunctionOnNextCall(f); f();");
4335
4336 Handle<JSFunction> f = Handle<JSFunction>::cast(
4337 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
4338 CcTest::global()->Get(env.local(), v8_str("f")).ToLocalChecked())));
4339 shared = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
4340 CompileRun("f = null");
4341 }
4342
4343 // Prepare optimized code that we can use.
4344 Handle<Code> code;
4345 {
4346 HandleScope inner_scope(isolate);
4347 CompileRun("function g() { return 2 }"
4348 "g(); %OptimizeFunctionOnNextCall(g); g();");
4349
4350 Handle<JSFunction> g = Handle<JSFunction>::cast(
4351 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
4352 CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked())));
4353 code = inner_scope.CloseAndEscape(handle(g->code(), isolate));
4354 if (!code->is_optimized_code()) return;
4355 }
4356
4357 Handle<TypeFeedbackVector> vector =
4358 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
4359 Handle<LiteralsArray> lit =
4360 LiteralsArray::New(isolate, vector, shared->num_literals(), TENURED);
4361 Handle<Context> context(isolate->context());
4362
4363 // Add the code several times to the optimized code map.
4364 for (int i = 0; i < 3; ++i) {
4365 HandleScope inner_scope(isolate);
4366 BailoutId id = BailoutId(i);
4367 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id);
4368 }
4369 shared->optimized_code_map()->Print();
4370
4371 // Add the code with a literals array to be evacuated.
4372 Page* evac_page;
4373 {
4374 HandleScope inner_scope(isolate);
4375 AlwaysAllocateScope always_allocate(isolate);
4376 // Make sure literal is placed on an old-space evacuation candidate.
4377 heap::SimulateFullSpace(heap->old_space());
4378
4379 // Make sure there the number of literals is > 0.
4380 Handle<LiteralsArray> lit = LiteralsArray::New(isolate, vector, 23);
4381
4382 evac_page = Page::FromAddress(lit->address());
4383 BailoutId id = BailoutId(100);
4384 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id);
4385 }
4386
4387 // Heap is ready, force {lit_page} to become an evacuation candidate and
4388 // simulate incremental marking to enqueue optimized code map.
4389 FLAG_manual_evacuation_candidates_selection = true;
4390 heap::ForceEvacuationCandidate(evac_page);
4391 heap::SimulateIncrementalMarking(heap);
4392
4393 // No matter whether reachable or not, {boomer} is doomed.
4394 Handle<Object> boomer(shared->optimized_code_map(), isolate);
4395
4396 // Add the code several times to the optimized code map. This will leave old
4397 // copies of the optimized code map unreachable but still marked.
4398 for (int i = 3; i < 6; ++i) {
4399 HandleScope inner_scope(isolate);
4400 BailoutId id = BailoutId(i);
4401 SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id);
4402 }
4403
4404 // Trigger a GC to flush out the bug.
4405 CcTest::CollectGarbage(i::OLD_SPACE);
4406 boomer->Print();
4407 }
4408
4409
4410 TEST(OptimizedCodeMapReuseEntries) {
4411 i::FLAG_allow_natives_syntax = true;
4412 // BUG(v8:4598): Since TurboFan doesn't treat maps in code weakly, we can't
4413 // run this test.
4414 if (i::FLAG_turbo) return;
4415 CcTest::InitializeVM();
4416 v8::Isolate* v8_isolate = CcTest::isolate();
4417 Isolate* isolate = CcTest::i_isolate();
4418 HandleScope scope(isolate);
4419
4420 // Create 3 contexts, allow the 2nd one to be disposed, and verify that
4421 // a 4th context will re-use the weak slots in the optimized code map
4422 // to hold data, rather than expanding the map.
4423 v8::Local<v8::Context> c1 = v8::Context::New(v8_isolate);
4424 const char* source = "function foo(x) { var l = [1]; return x+l[0]; }";
4425 v8::ScriptCompiler::Source script_source(
4426 v8::String::NewFromUtf8(v8_isolate, source, v8::NewStringType::kNormal)
4427 .ToLocalChecked());
4428 v8::Local<v8::UnboundScript> indep =
4429 v8::ScriptCompiler::CompileUnboundScript(v8_isolate, &script_source)
4430 .ToLocalChecked();
4431 const char* toplevel = "foo(3); %OptimizeFunctionOnNextCall(foo); foo(3);";
4432 // Perfrom one initial GC to enable code flushing.
4433 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4434
4435 c1->Enter();
4436 indep->BindToCurrentContext()->Run(c1).ToLocalChecked();
4437 CompileRun(toplevel);
4438
4439 Handle<SharedFunctionInfo> shared;
4440 Handle<JSFunction> foo = Handle<JSFunction>::cast(
4441 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
4442 CcTest::global()->Get(c1, v8_str("foo")).ToLocalChecked())));
4443 CHECK(foo->shared()->is_compiled());
4444 shared = handle(foo->shared());
4445 c1->Exit();
4446
4447 {
4448 HandleScope scope(isolate);
4449 v8::Local<v8::Context> c2 = v8::Context::New(v8_isolate);
4450 c2->Enter();
4451 indep->BindToCurrentContext()->Run(c2).ToLocalChecked();
4452 CompileRun(toplevel);
4453 c2->Exit();
4454 }
4455
4456 {
4457 HandleScope scope(isolate);
4458 v8::Local<v8::Context> c3 = v8::Context::New(v8_isolate);
4459 c3->Enter();
4460 indep->BindToCurrentContext()->Run(c3).ToLocalChecked();
4461 CompileRun(toplevel);
4462 c3->Exit();
4463
4464 // Now, collect garbage. Context c2 should have no roots to it, and it's
4465 // entry in the optimized code map should be free for a new context.
4466 for (int i = 0; i < 4; i++) {
4467 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4468 }
4469
4470 Handle<FixedArray> optimized_code_map =
4471 handle(shared->optimized_code_map());
4472 // There should be 3 entries in the map.
4473 CHECK_EQ(
4474 3, ((optimized_code_map->length() - SharedFunctionInfo::kEntriesStart) /
4475 SharedFunctionInfo::kEntryLength));
4476 // But one of them (formerly for c2) should be cleared.
4477 int cleared_count = 0;
4478 for (int i = SharedFunctionInfo::kEntriesStart;
4479 i < optimized_code_map->length();
4480 i += SharedFunctionInfo::kEntryLength) {
4481 cleared_count +=
4482 WeakCell::cast(
4483 optimized_code_map->get(i + SharedFunctionInfo::kContextOffset))
4484 ->cleared()
4485 ? 1
4486 : 0;
4487 }
4488 CHECK_EQ(1, cleared_count);
4489
4490 // Verify that a new context uses the cleared entry rather than creating a
4491 // new
4492 // optimized code map array.
4493 v8::Local<v8::Context> c4 = v8::Context::New(v8_isolate);
4494 c4->Enter();
4495 indep->BindToCurrentContext()->Run(c4).ToLocalChecked();
4496 CompileRun(toplevel);
4497 c4->Exit();
4498 CHECK_EQ(*optimized_code_map, shared->optimized_code_map());
4499
4500 // Now each entry is in use.
4501 cleared_count = 0;
4502 for (int i = SharedFunctionInfo::kEntriesStart;
4503 i < optimized_code_map->length();
4504 i += SharedFunctionInfo::kEntryLength) {
4505 cleared_count +=
4506 WeakCell::cast(
4507 optimized_code_map->get(i + SharedFunctionInfo::kContextOffset))
4508 ->cleared()
4509 ? 1
4510 : 0;
4511 }
4512 CHECK_EQ(0, cleared_count);
4513 }
4514 }
4515
4516
4517 TEST(Regress513496) { 4312 TEST(Regress513496) {
4518 i::FLAG_allow_natives_syntax = true; 4313 i::FLAG_allow_natives_syntax = true;
4519 CcTest::InitializeVM(); 4314 CcTest::InitializeVM();
4520 Isolate* isolate = CcTest::i_isolate(); 4315 Isolate* isolate = CcTest::i_isolate();
4521 HandleScope scope(isolate); 4316 HandleScope scope(isolate);
4522 4317
4523 // Perfrom one initial GC to enable code flushing. 4318 // Perfrom one initial GC to enable code flushing.
4524 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); 4319 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4525 4320
4526 // Prepare an optimized closure with containing an inlined function. Then age 4321 // Prepare an optimized closure with containing an inlined function. Then age
(...skipping 25 matching lines...) Expand all
4552 Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( 4347 Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
4553 *v8::Local<v8::Function>::Cast(CcTest::global() 4348 *v8::Local<v8::Function>::Cast(CcTest::global()
4554 ->Get(context.local(), v8_str("f")) 4349 ->Get(context.local(), v8_str("f"))
4555 .ToLocalChecked()))); 4350 .ToLocalChecked())));
4556 CHECK(f->is_compiled()); 4351 CHECK(f->is_compiled());
4557 shared = inner_scope.CloseAndEscape(handle(f->shared(), isolate)); 4352 shared = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
4558 CompileRun("f = null"); 4353 CompileRun("f = null");
4559 } 4354 }
4560 4355
4561 // Lookup the optimized code and keep it alive. 4356 // Lookup the optimized code and keep it alive.
4562 CodeAndLiterals result = shared->SearchOptimizedCodeMap( 4357 Code* result = shared->SearchOptimizedCodeMap(
4563 isolate->context()->native_context(), BailoutId::None()); 4358 isolate->context()->native_context(), BailoutId::None());
4564 Handle<Code> optimized_code(result.code, isolate); 4359 Handle<Code> optimized_code(result, isolate);
4565 4360
4566 // Finish a full GC cycle so that the unoptimized code of 'g' is flushed even 4361 // Finish a full GC cycle so that the unoptimized code of 'g' is flushed even
4567 // though the optimized code for 'f' is reachable via the optimized code map. 4362 // though the optimized code for 'f' is reachable via the optimized code map.
4568 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); 4363 CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
4569 4364
4570 // Make a new closure that will get code installed from the code map. 4365 // Make a new closure that will get code installed from the code map.
4571 // Unoptimized code is missing and the deoptimizer will go ballistic. 4366 // Unoptimized code is missing and the deoptimizer will go ballistic.
4572 CompileRun("var h = mkClosure(); h('bozo');"); 4367 CompileRun("var h = mkClosure(); h('bozo');");
4573 } 4368 }
4574 4369
(...skipping 2500 matching lines...) Expand 10 before | Expand all | Expand 10 after
7075 double deadline = heap->MonotonicallyIncreasingTimeInMs() + 1; 6870 double deadline = heap->MonotonicallyIncreasingTimeInMs() + 1;
7076 marking->AdvanceIncrementalMarking( 6871 marking->AdvanceIncrementalMarking(
7077 deadline, IncrementalMarking::GC_VIA_STACK_GUARD, 6872 deadline, IncrementalMarking::GC_VIA_STACK_GUARD,
7078 IncrementalMarking::FORCE_COMPLETION, StepOrigin::kV8); 6873 IncrementalMarking::FORCE_COMPLETION, StepOrigin::kV8);
7079 } 6874 }
7080 DCHECK(marking->IsStopped()); 6875 DCHECK(marking->IsStopped());
7081 } 6876 }
7082 6877
7083 } // namespace internal 6878 } // namespace internal
7084 } // namespace v8 6879 } // namespace v8
OLDNEW
« no previous file with comments | « src/x64/interface-descriptors-x64.cc ('k') | test/cctest/interpreter/bytecode_expectations/BasicLoops.golden » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698