OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler.h" | 5 #include "src/compiler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "src/asmjs/asm-js.h" | 10 #include "src/asmjs/asm-js.h" |
11 #include "src/asmjs/asm-typer.h" | 11 #include "src/asmjs/asm-typer.h" |
12 #include "src/ast/ast-numbering.h" | 12 #include "src/ast/ast-numbering.h" |
13 #include "src/ast/prettyprinter.h" | 13 #include "src/ast/prettyprinter.h" |
14 #include "src/ast/scopes.h" | 14 #include "src/ast/scopes.h" |
15 #include "src/bootstrapper.h" | 15 #include "src/bootstrapper.h" |
16 #include "src/codegen.h" | 16 #include "src/codegen.h" |
17 #include "src/compilation-cache.h" | 17 #include "src/compilation-cache.h" |
18 #include "src/compiler-dispatcher/compiler-dispatcher.h" | |
18 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" | 19 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" |
19 #include "src/compiler/pipeline.h" | 20 #include "src/compiler/pipeline.h" |
20 #include "src/crankshaft/hydrogen.h" | 21 #include "src/crankshaft/hydrogen.h" |
21 #include "src/debug/debug.h" | 22 #include "src/debug/debug.h" |
22 #include "src/debug/liveedit.h" | 23 #include "src/debug/liveedit.h" |
23 #include "src/frames-inl.h" | 24 #include "src/frames-inl.h" |
24 #include "src/full-codegen/full-codegen.h" | 25 #include "src/full-codegen/full-codegen.h" |
25 #include "src/globals.h" | 26 #include "src/globals.h" |
26 #include "src/heap/heap.h" | 27 #include "src/heap/heap.h" |
27 #include "src/interpreter/interpreter.h" | 28 #include "src/interpreter/interpreter.h" |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
368 // Checks whether top level functions should be passed by the filter. | 369 // Checks whether top level functions should be passed by the filter. |
369 if (shared->is_toplevel()) { | 370 if (shared->is_toplevel()) { |
370 Vector<const char> filter = CStrVector(FLAG_ignition_filter); | 371 Vector<const char> filter = CStrVector(FLAG_ignition_filter); |
371 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); | 372 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); |
372 } | 373 } |
373 | 374 |
374 // Finally respect the filter. | 375 // Finally respect the filter. |
375 return shared->PassesFilter(FLAG_ignition_filter); | 376 return shared->PassesFilter(FLAG_ignition_filter); |
376 } | 377 } |
377 | 378 |
379 bool UseAsmWasm(CompilationInfo* info) { | |
380 return FLAG_validate_asm && info->scope()->asm_module() && | |
381 !info->shared_info()->is_asm_wasm_broken() && !info->is_debug(); | |
382 } | |
383 | |
378 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { | 384 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { |
379 // Function should have been parsed and analyzed before creating a compilation | 385 // Function should have been parsed and analyzed before creating a compilation |
380 // job. | 386 // job. |
381 DCHECK_NOT_NULL(info->literal()); | 387 DCHECK_NOT_NULL(info->literal()); |
382 DCHECK_NOT_NULL(info->scope()); | 388 DCHECK_NOT_NULL(info->scope()); |
383 | 389 |
384 EnsureFeedbackMetadata(info); | 390 EnsureFeedbackMetadata(info); |
385 if (ShouldUseIgnition(info)) { | 391 if (ShouldUseIgnition(info)) { |
386 return interpreter::Interpreter::NewCompilationJob(info); | 392 return interpreter::Interpreter::NewCompilationJob(info); |
387 } else { | 393 } else { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
421 // Update the shared function info with the scope info. | 427 // Update the shared function info with the scope info. |
422 InstallSharedScopeInfo(info, shared); | 428 InstallSharedScopeInfo(info, shared); |
423 | 429 |
424 // Install compilation result on the shared function info | 430 // Install compilation result on the shared function info |
425 InstallSharedCompilationResult(info, shared); | 431 InstallSharedCompilationResult(info, shared); |
426 } | 432 } |
427 | 433 |
428 CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { | 434 CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { |
429 CompilationJob::Status status = job->FinalizeJob(); | 435 CompilationJob::Status status = job->FinalizeJob(); |
430 if (status == CompilationJob::SUCCEEDED) { | 436 if (status == CompilationJob::SUCCEEDED) { |
431 InstallUnoptimizedCode(job->info()); | 437 CompilationInfo* info = job->info(); |
marja
2017/01/10 09:58:54
I'm confused; why is this kind of change needed in
rmcilroy
2017/01/12 12:31:55
The reason is that the MarkToBeExecutedOnce used t
| |
438 DCHECK(!info->code().is_null()); | |
439 if (info->parse_info()->literal()->should_be_used_once_hint()) { | |
440 info->code()->MarkToBeExecutedOnce(info->isolate()); | |
441 } | |
442 InstallUnoptimizedCode(info); | |
432 job->RecordUnoptimizedCompilationStats(); | 443 job->RecordUnoptimizedCompilationStats(); |
433 } | 444 } |
434 return status; | 445 return status; |
435 } | 446 } |
436 | 447 |
437 bool Renumber(ParseInfo* parse_info) { | 448 bool Renumber(ParseInfo* parse_info) { |
438 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), | 449 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), |
439 parse_info->literal(), | 450 parse_info->literal(), |
440 parse_info->eager_inner_function_literals())) { | 451 parse_info->eager_inner_function_literals())) { |
441 return false; | 452 return false; |
442 } | 453 } |
443 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); | 454 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); |
444 if (!shared_info.is_null()) { | 455 if (!shared_info.is_null()) { |
445 FunctionLiteral* lit = parse_info->literal(); | 456 FunctionLiteral* lit = parse_info->literal(); |
446 shared_info->set_ast_node_count(lit->ast_node_count()); | 457 shared_info->set_ast_node_count(lit->ast_node_count()); |
447 if (lit->dont_optimize_reason() != kNoReason) { | 458 if (lit->dont_optimize_reason() != kNoReason) { |
448 shared_info->DisableOptimization(lit->dont_optimize_reason()); | 459 shared_info->DisableOptimization(lit->dont_optimize_reason()); |
449 } | 460 } |
450 if (lit->flags() & AstProperties::kMustUseIgnitionTurbo) { | 461 if (lit->flags() & AstProperties::kMustUseIgnitionTurbo) { |
451 shared_info->set_must_use_ignition_turbo(true); | 462 shared_info->set_must_use_ignition_turbo(true); |
452 } | 463 } |
453 } | 464 } |
454 return true; | 465 return true; |
455 } | 466 } |
456 | 467 |
457 bool GenerateUnoptimizedCode(CompilationInfo* info) { | 468 bool GenerateUnoptimizedCode(CompilationInfo* info) { |
458 if (FLAG_validate_asm && info->scope()->asm_module() && | 469 if (UseAsmWasm(info)) { |
459 !info->shared_info()->is_asm_wasm_broken() && !info->is_debug()) { | |
460 EnsureFeedbackMetadata(info); | 470 EnsureFeedbackMetadata(info); |
461 MaybeHandle<FixedArray> wasm_data; | 471 MaybeHandle<FixedArray> wasm_data; |
462 wasm_data = AsmJs::CompileAsmViaWasm(info); | 472 wasm_data = AsmJs::CompileAsmViaWasm(info); |
463 if (!wasm_data.is_null()) { | 473 if (!wasm_data.is_null()) { |
464 info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked()); | 474 info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked()); |
465 info->SetCode(info->isolate()->builtins()->InstantiateAsmJs()); | 475 info->SetCode(info->isolate()->builtins()->InstantiateAsmJs()); |
466 InstallUnoptimizedCode(info); | 476 InstallUnoptimizedCode(info); |
467 return true; | 477 return true; |
468 } | 478 } |
469 } | 479 } |
(...skipping 22 matching lines...) Expand all Loading... | |
492 script->FindSharedFunctionInfo(isolate, literal); | 502 script->FindSharedFunctionInfo(isolate, literal); |
493 if (maybe_existing.ToHandle(&shared)) { | 503 if (maybe_existing.ToHandle(&shared)) { |
494 DCHECK(!shared->is_toplevel()); | 504 DCHECK(!shared->is_toplevel()); |
495 // If we found an existing shared function info with compiled code, | 505 // If we found an existing shared function info with compiled code, |
496 // we are done. | 506 // we are done. |
497 if (shared->is_compiled()) continue; | 507 if (shared->is_compiled()) continue; |
498 } else { | 508 } else { |
499 shared = | 509 shared = |
500 isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script); | 510 isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script); |
501 shared->set_is_toplevel(false); | 511 shared->set_is_toplevel(false); |
512 Scope* outer_scope = literal->scope()->GetOuterScopeWithContext(); | |
513 if (outer_scope) { | |
514 shared->set_outer_scope_info(*outer_scope->scope_info()); | |
515 } | |
502 } | 516 } |
503 | 517 |
504 Zone zone(isolate->allocator(), ZONE_NAME); | 518 std::unique_ptr<Zone> zone(new Zone(isolate->allocator(), ZONE_NAME)); |
505 ParseInfo parse_info(&zone, script); | 519 std::unique_ptr<ParseInfo> parse_info(new ParseInfo(zone.get(), script)); |
506 parse_info.set_literal(literal); | 520 std::unique_ptr<CompilationInfo> info( |
507 parse_info.set_shared_info(shared); | 521 new CompilationInfo(parse_info.get(), Handle<JSFunction>::null())); |
508 parse_info.set_function_literal_id(shared->function_literal_id()); | 522 |
509 parse_info.set_language_mode(literal->scope()->language_mode()); | 523 parse_info->set_literal(literal); |
510 parse_info.set_ast_value_factory( | 524 parse_info->set_shared_info(shared); |
525 parse_info->set_function_literal_id(shared->function_literal_id()); | |
526 parse_info->set_language_mode(literal->scope()->language_mode()); | |
527 parse_info->set_ast_value_factory( | |
511 outer_info->parse_info()->ast_value_factory()); | 528 outer_info->parse_info()->ast_value_factory()); |
512 parse_info.set_ast_value_factory_owned(false); | 529 parse_info->set_ast_value_factory_owned(false); |
513 | 530 |
514 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); | 531 if (outer_info->will_serialize()) info->PrepareForSerializing(); |
515 if (outer_info->will_serialize()) info.PrepareForSerializing(); | 532 if (outer_info->is_debug()) info->MarkAsDebug(); |
516 if (outer_info->is_debug()) info.MarkAsDebug(); | |
517 | 533 |
518 if (!Renumber(&parse_info) || | 534 if (!Renumber(parse_info.get()) || |
519 !CompileUnoptimizedInnerFunctionsRecursively( | 535 !CompileUnoptimizedInnerFunctionsRecursively( |
520 parse_info.eager_inner_function_literals(), &info) || | 536 parse_info->eager_inner_function_literals(), info.get())) { |
521 !GenerateUnoptimizedCode(&info)) { | |
522 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 537 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
523 return false; | 538 return false; |
524 } | 539 } |
525 | 540 |
526 DCHECK(!info.code().is_null()); | 541 if (isolate->compiler_dispatcher()->IsEnabled() && |
527 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info); | 542 !UseAsmWasm(info.get())) { |
528 if (literal->should_be_used_once_hint()) { | 543 std::unique_ptr<CompilationJob> job( |
529 info.code()->MarkToBeExecutedOnce(isolate); | 544 Compiler::PrepareUnoptimizedCompilationJob(info.get())); |
545 if (!job || | |
546 !isolate->compiler_dispatcher()->Enqueue( | |
547 zone.release(), parse_info.release(), info.release(), | |
548 job.release())) { | |
549 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | |
marja
2017/01/10 09:58:54
This logic ("if isolate doesn't have a pending exc
rmcilroy
2017/01/12 12:31:55
I agree this is getting scattered everywhere. I've
| |
550 return false; | |
551 } | |
552 } else { | |
553 if (!GenerateUnoptimizedCode(info.get())) { | |
554 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | |
555 return false; | |
556 } | |
530 } | 557 } |
531 } | 558 } |
532 return true; | 559 return true; |
533 } | 560 } |
534 | 561 |
535 bool CompileUnoptimizedCode(CompilationInfo* info) { | 562 bool CompileUnoptimizedCode(CompilationInfo* info) { |
536 Isolate* isolate = info->isolate(); | 563 Isolate* isolate = info->isolate(); |
537 DCHECK(AllowCompilation::IsAllowed(isolate)); | 564 DCHECK(AllowCompilation::IsAllowed(isolate)); |
538 | 565 |
539 if (!Compiler::Analyze(info->parse_info()) || | 566 if (!Compiler::Analyze(info->parse_info()) || |
540 !CompileUnoptimizedInnerFunctionsRecursively( | 567 !CompileUnoptimizedInnerFunctionsRecursively( |
541 info->parse_info()->eager_inner_function_literals(), info) || | 568 info->parse_info()->eager_inner_function_literals(), info) || |
542 !GenerateUnoptimizedCode(info)) { | 569 !GenerateUnoptimizedCode(info)) { |
543 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 570 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
544 return false; | 571 return false; |
545 } | 572 } |
546 | 573 |
574 if (isolate->compiler_dispatcher()->IsEnabled()) { | |
575 // TODO(rmcilroy): Remove this once the enqueued tasks can keep the parsed | |
576 // zone and handles alive and replace with a check in CompileLazy to finish | |
577 // the task itself. | |
578 isolate->compiler_dispatcher()->FinishAllNow(); | |
579 } | |
580 | |
547 return true; | 581 return true; |
548 } | 582 } |
549 | 583 |
550 void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* info) { | 584 void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* info) { |
551 DCHECK(info->is_toplevel()); | 585 DCHECK(info->is_toplevel()); |
552 DCHECK(!info->script().is_null()); | 586 DCHECK(!info->script().is_null()); |
553 if (info->script()->shared_function_infos()->length() > 0) { | 587 if (info->script()->shared_function_infos()->length() > 0) { |
554 DCHECK_EQ(info->script()->shared_function_infos()->length(), | 588 DCHECK_EQ(info->script()->shared_function_infos()->length(), |
555 info->max_function_literal_id() + 1); | 589 info->max_function_literal_id() + 1); |
556 return; | 590 return; |
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1759 DCHECK(shared->is_compiled()); | 1793 DCHECK(shared->is_compiled()); |
1760 function->set_literals(cached.literals); | 1794 function->set_literals(cached.literals); |
1761 } else if (shared->is_compiled()) { | 1795 } else if (shared->is_compiled()) { |
1762 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 1796 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
1763 JSFunction::EnsureLiterals(function); | 1797 JSFunction::EnsureLiterals(function); |
1764 } | 1798 } |
1765 } | 1799 } |
1766 | 1800 |
1767 } // namespace internal | 1801 } // namespace internal |
1768 } // namespace v8 | 1802 } // namespace v8 |
OLD | NEW |