Revision f230a1cf deps/v8/src/compiler.cc
deps/v8/src/compiler.cc | ||
---|---|---|
112 | 112 |
zone_ = zone; |
113 | 113 |
deferred_handles_ = NULL; |
114 | 114 |
code_stub_ = NULL; |
115 |
prologue_offset_ = kPrologueOffsetNotSet; |
|
115 |
prologue_offset_ = Code::kPrologueOffsetNotSet;
|
|
116 | 116 |
opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count(); |
117 | 117 |
no_frame_ranges_ = isolate->cpu_profiler()->is_profiling() |
118 | 118 |
? new List<OffsetRange>(2) : NULL; |
... | ... | |
123 | 123 |
mode_ = STUB; |
124 | 124 |
return; |
125 | 125 |
} |
126 |
mode_ = isolate->use_crankshaft() ? mode : NONOPT;
|
|
126 |
mode_ = mode;
|
|
127 | 127 |
abort_due_to_dependency_ = false; |
128 | 128 |
if (script_->type()->value() == Script::TYPE_NATIVE) { |
129 | 129 |
MarkAsNative(); |
... | ... | |
260 | 260 |
} |
261 | 261 |
|
262 | 262 |
|
263 |
void OptimizingCompiler::RecordOptimizationStats() {
|
|
263 |
void RecompileJob::RecordOptimizationStats() {
|
|
264 | 264 |
Handle<JSFunction> function = info()->closure(); |
265 | 265 |
int opt_count = function->shared()->opt_count(); |
266 | 266 |
function->shared()->set_opt_count(opt_count + 1); |
... | ... | |
297 | 297 |
// A return value of true indicates the compilation pipeline is still |
298 | 298 |
// going, not necessarily that we optimized the code. |
299 | 299 |
static bool MakeCrankshaftCode(CompilationInfo* info) { |
300 |
OptimizingCompiler compiler(info);
|
|
301 |
OptimizingCompiler::Status status = compiler.CreateGraph();
|
|
300 |
RecompileJob job(info);
|
|
301 |
RecompileJob::Status status = job.CreateGraph();
|
|
302 | 302 |
|
303 |
if (status != OptimizingCompiler::SUCCEEDED) {
|
|
304 |
return status != OptimizingCompiler::FAILED;
|
|
303 |
if (status != RecompileJob::SUCCEEDED) {
|
|
304 |
return status != RecompileJob::FAILED;
|
|
305 | 305 |
} |
306 |
status = compiler.OptimizeGraph();
|
|
307 |
if (status != OptimizingCompiler::SUCCEEDED) {
|
|
308 |
status = compiler.AbortOptimization();
|
|
309 |
return status != OptimizingCompiler::FAILED;
|
|
306 |
status = job.OptimizeGraph();
|
|
307 |
if (status != RecompileJob::SUCCEEDED) {
|
|
308 |
status = job.AbortOptimization();
|
|
309 |
return status != RecompileJob::FAILED;
|
|
310 | 310 |
} |
311 |
status = compiler.GenerateAndInstallCode();
|
|
312 |
return status != OptimizingCompiler::FAILED;
|
|
311 |
status = job.GenerateAndInstallCode();
|
|
312 |
return status != RecompileJob::FAILED;
|
|
313 | 313 |
} |
314 | 314 |
|
315 | 315 |
|
316 |
OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { |
|
316 |
class HOptimizedGraphBuilderWithPotisions: public HOptimizedGraphBuilder { |
|
317 |
public: |
|
318 |
explicit HOptimizedGraphBuilderWithPotisions(CompilationInfo* info) |
|
319 |
: HOptimizedGraphBuilder(info) { |
|
320 |
} |
|
321 |
|
|
322 |
#define DEF_VISIT(type) \ |
|
323 |
virtual void Visit##type(type* node) V8_OVERRIDE { \ |
|
324 |
if (node->position() != RelocInfo::kNoPosition) { \ |
|
325 |
SetSourcePosition(node->position()); \ |
|
326 |
} \ |
|
327 |
HOptimizedGraphBuilder::Visit##type(node); \ |
|
328 |
} |
|
329 |
EXPRESSION_NODE_LIST(DEF_VISIT) |
|
330 |
#undef DEF_VISIT |
|
331 |
|
|
332 |
#define DEF_VISIT(type) \ |
|
333 |
virtual void Visit##type(type* node) V8_OVERRIDE { \ |
|
334 |
if (node->position() != RelocInfo::kNoPosition) { \ |
|
335 |
SetSourcePosition(node->position()); \ |
|
336 |
} \ |
|
337 |
HOptimizedGraphBuilder::Visit##type(node); \ |
|
338 |
} |
|
339 |
STATEMENT_NODE_LIST(DEF_VISIT) |
|
340 |
#undef DEF_VISIT |
|
341 |
|
|
342 |
#define DEF_VISIT(type) \ |
|
343 |
virtual void Visit##type(type* node) V8_OVERRIDE { \ |
|
344 |
HOptimizedGraphBuilder::Visit##type(node); \ |
|
345 |
} |
|
346 |
MODULE_NODE_LIST(DEF_VISIT) |
|
347 |
DECLARATION_NODE_LIST(DEF_VISIT) |
|
348 |
AUXILIARY_NODE_LIST(DEF_VISIT) |
|
349 |
#undef DEF_VISIT |
|
350 |
}; |
|
351 |
|
|
352 |
|
|
353 |
RecompileJob::Status RecompileJob::CreateGraph() { |
|
317 | 354 |
ASSERT(isolate()->use_crankshaft()); |
318 | 355 |
ASSERT(info()->IsOptimizing()); |
319 | 356 |
ASSERT(!info()->IsCompilingForDebugging()); |
... | ... | |
419 | 456 |
// Type-check the function. |
420 | 457 |
AstTyper::Run(info()); |
421 | 458 |
|
422 |
graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info()); |
|
459 |
graph_builder_ = FLAG_emit_opt_code_positions |
|
460 |
? new(info()->zone()) HOptimizedGraphBuilderWithPotisions(info()) |
|
461 |
: new(info()->zone()) HOptimizedGraphBuilder(info()); |
|
423 | 462 |
|
424 | 463 |
Timer t(this, &time_taken_to_create_graph_); |
425 | 464 |
graph_ = graph_builder_->CreateGraph(); |
... | ... | |
452 | 491 |
} |
453 | 492 |
|
454 | 493 |
|
455 |
OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
|
|
494 |
RecompileJob::Status RecompileJob::OptimizeGraph() {
|
|
456 | 495 |
DisallowHeapAllocation no_allocation; |
457 | 496 |
DisallowHandleAllocation no_handles; |
458 | 497 |
DisallowHandleDereference no_deref; |
... | ... | |
475 | 514 |
} |
476 | 515 |
|
477 | 516 |
|
478 |
OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
|
|
517 |
RecompileJob::Status RecompileJob::GenerateAndInstallCode() {
|
|
479 | 518 |
ASSERT(last_status() == SUCCEEDED); |
480 | 519 |
ASSERT(!info()->HasAbortedDueToDependencyChange()); |
481 | 520 |
DisallowCodeDependencyChange no_dependency_change; |
... | ... | |
555 | 594 |
} |
556 | 595 |
|
557 | 596 |
|
597 |
// Sets the expected number of properties based on estimate from compiler. |
|
598 |
void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared, |
|
599 |
int estimate) { |
|
600 |
// See the comment in SetExpectedNofProperties. |
|
601 |
if (shared->live_objects_may_exist()) return; |
|
602 |
|
|
603 |
// If no properties are added in the constructor, they are more likely |
|
604 |
// to be added later. |
|
605 |
if (estimate == 0) estimate = 2; |
|
606 |
|
|
607 |
// TODO(yangguo): check whether those heuristics are still up-to-date. |
|
608 |
// We do not shrink objects that go into a snapshot (yet), so we adjust |
|
609 |
// the estimate conservatively. |
|
610 |
if (Serializer::enabled()) { |
|
611 |
estimate += 2; |
|
612 |
} else if (FLAG_clever_optimizations) { |
|
613 |
// Inobject slack tracking will reclaim redundant inobject space later, |
|
614 |
// so we can afford to adjust the estimate generously. |
|
615 |
estimate += 8; |
|
616 |
} else { |
|
617 |
estimate += 3; |
|
618 |
} |
|
619 |
|
|
620 |
shared->set_expected_nof_properties(estimate); |
|
621 |
} |
|
622 |
|
|
623 |
|
|
558 | 624 |
static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) { |
559 | 625 |
Isolate* isolate = info->isolate(); |
560 | 626 |
PostponeInterruptsScope postpone(isolate); |
... | ... | |
599 | 665 |
} |
600 | 666 |
} |
601 | 667 |
|
602 |
// Measure how long it takes to do the compilation; only take the |
|
603 |
// rest of the function into account to avoid overlap with the |
|
604 |
// parsing statistics. |
|
605 |
HistogramTimer* rate = info->is_eval() |
|
606 |
? info->isolate()->counters()->compile_eval() |
|
607 |
: info->isolate()->counters()->compile(); |
|
608 |
HistogramTimerScope timer(rate); |
|
609 |
|
|
610 |
// Compile the code. |
|
611 | 668 |
FunctionLiteral* lit = info->function(); |
612 | 669 |
LiveEditFunctionTracker live_edit_tracker(isolate, lit); |
613 |
if (!MakeCode(info)) { |
|
614 |
if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
|
615 |
return Handle<SharedFunctionInfo>::null(); |
|
616 |
} |
|
670 |
Handle<SharedFunctionInfo> result; |
|
671 |
{ |
|
672 |
// Measure how long it takes to do the compilation; only take the |
|
673 |
// rest of the function into account to avoid overlap with the |
|
674 |
// parsing statistics. |
|
675 |
HistogramTimer* rate = info->is_eval() |
|
676 |
? info->isolate()->counters()->compile_eval() |
|
677 |
: info->isolate()->counters()->compile(); |
|
678 |
HistogramTimerScope timer(rate); |
|
617 | 679 |
|
618 |
// Allocate function. |
|
619 |
ASSERT(!info->code().is_null()); |
|
620 |
Handle<SharedFunctionInfo> result = |
|
621 |
isolate->factory()->NewSharedFunctionInfo( |
|
622 |
lit->name(), |
|
623 |
lit->materialized_literal_count(), |
|
624 |
lit->is_generator(), |
|
625 |
info->code(), |
|
626 |
ScopeInfo::Create(info->scope(), info->zone())); |
|
627 |
|
|
628 |
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); |
|
629 |
Compiler::SetFunctionInfo(result, lit, true, script); |
|
630 |
|
|
631 |
if (script->name()->IsString()) { |
|
632 |
PROFILE(isolate, CodeCreateEvent( |
|
633 |
info->is_eval() |
|
634 |
? Logger::EVAL_TAG |
|
635 |
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
|
636 |
*info->code(), |
|
637 |
*result, |
|
638 |
info, |
|
639 |
String::cast(script->name()))); |
|
640 |
GDBJIT(AddCode(Handle<String>(String::cast(script->name())), |
|
641 |
script, |
|
642 |
info->code(), |
|
643 |
info)); |
|
644 |
} else { |
|
645 |
PROFILE(isolate, CodeCreateEvent( |
|
646 |
info->is_eval() |
|
647 |
? Logger::EVAL_TAG |
|
648 |
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
|
649 |
*info->code(), |
|
650 |
*result, |
|
651 |
info, |
|
652 |
isolate->heap()->empty_string())); |
|
653 |
GDBJIT(AddCode(Handle<String>(), script, info->code(), info)); |
|
654 |
} |
|
680 |
// Compile the code. |
|
681 |
if (!MakeCode(info)) { |
|
682 |
if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
|
683 |
return Handle<SharedFunctionInfo>::null(); |
|
684 |
} |
|
685 |
|
|
686 |
// Allocate function. |
|
687 |
ASSERT(!info->code().is_null()); |
|
688 |
result = |
|
689 |
isolate->factory()->NewSharedFunctionInfo( |
|
690 |
lit->name(), |
|
691 |
lit->materialized_literal_count(), |
|
692 |
lit->is_generator(), |
|
693 |
info->code(), |
|
694 |
ScopeInfo::Create(info->scope(), info->zone())); |
|
695 |
|
|
696 |
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); |
|
697 |
Compiler::SetFunctionInfo(result, lit, true, script); |
|
698 |
|
|
699 |
if (script->name()->IsString()) { |
|
700 |
PROFILE(isolate, CodeCreateEvent( |
|
701 |
info->is_eval() |
|
702 |
? Logger::EVAL_TAG |
|
703 |
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
|
704 |
*info->code(), |
|
705 |
*result, |
|
706 |
info, |
|
707 |
String::cast(script->name()))); |
|
708 |
GDBJIT(AddCode(Handle<String>(String::cast(script->name())), |
|
709 |
script, |
|
710 |
info->code(), |
|
711 |
info)); |
|
712 |
} else { |
|
713 |
PROFILE(isolate, CodeCreateEvent( |
|
714 |
info->is_eval() |
|
715 |
? Logger::EVAL_TAG |
|
716 |
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
|
717 |
*info->code(), |
|
718 |
*result, |
|
719 |
info, |
|
720 |
isolate->heap()->empty_string())); |
|
721 |
GDBJIT(AddCode(Handle<String>(), script, info->code(), info)); |
|
722 |
} |
|
655 | 723 |
|
656 |
// Hint to the runtime system used when allocating space for initial |
|
657 |
// property space by setting the expected number of properties for |
|
658 |
// the instances of the function. |
|
659 |
SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count()); |
|
724 |
// Hint to the runtime system used when allocating space for initial |
|
725 |
// property space by setting the expected number of properties for |
|
726 |
// the instances of the function. |
|
727 |
SetExpectedNofPropertiesFromEstimate(result, |
|
728 |
lit->expected_property_count()); |
|
660 | 729 |
|
661 |
script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); |
|
730 |
script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); |
|
731 |
} |
|
662 | 732 |
|
663 | 733 |
#ifdef ENABLE_DEBUGGER_SUPPORT |
664 | 734 |
// Notify debugger |
... | ... | |
1032 | 1102 |
info->SaveHandles(); |
1033 | 1103 |
|
1034 | 1104 |
if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) { |
1035 |
OptimizingCompiler* compiler = |
|
1036 |
new(info->zone()) OptimizingCompiler(*info); |
|
1037 |
OptimizingCompiler::Status status = compiler->CreateGraph(); |
|
1038 |
if (status == OptimizingCompiler::SUCCEEDED) { |
|
1105 |
RecompileJob* job = new(info->zone()) RecompileJob(*info); |
|
1106 |
RecompileJob::Status status = job->CreateGraph(); |
|
1107 |
if (status == RecompileJob::SUCCEEDED) { |
|
1039 | 1108 |
info.Detach(); |
1040 | 1109 |
shared->code()->set_profiler_ticks(0); |
1041 |
isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
|
|
1110 |
isolate->optimizing_compiler_thread()->QueueForOptimization(job);
|
|
1042 | 1111 |
ASSERT(!isolate->has_pending_exception()); |
1043 | 1112 |
return true; |
1044 |
} else if (status == OptimizingCompiler::BAILED_OUT) {
|
|
1113 |
} else if (status == RecompileJob::BAILED_OUT) {
|
|
1045 | 1114 |
isolate->clear_pending_exception(); |
1046 | 1115 |
InstallFullCode(*info); |
1047 | 1116 |
} |
... | ... | |
1054 | 1123 |
} |
1055 | 1124 |
|
1056 | 1125 |
|
1057 |
Handle<Code> Compiler::InstallOptimizedCode( |
|
1058 |
OptimizingCompiler* optimizing_compiler) { |
|
1059 |
SmartPointer<CompilationInfo> info(optimizing_compiler->info()); |
|
1126 |
Handle<Code> Compiler::InstallOptimizedCode(RecompileJob* job) { |
|
1127 |
SmartPointer<CompilationInfo> info(job->info()); |
|
1060 | 1128 |
// The function may have already been optimized by OSR. Simply continue. |
1061 | 1129 |
// Except when OSR already disabled optimization for some reason. |
1062 | 1130 |
if (info->shared_info()->optimization_disabled()) { |
... | ... | |
1077 | 1145 |
isolate, Logger::TimerEventScope::v8_recompile_synchronous); |
1078 | 1146 |
// If crankshaft succeeded, install the optimized code else install |
1079 | 1147 |
// the unoptimized code. |
1080 |
OptimizingCompiler::Status status = optimizing_compiler->last_status();
|
|
1148 |
RecompileJob::Status status = job->last_status();
|
|
1081 | 1149 |
if (info->HasAbortedDueToDependencyChange()) { |
1082 | 1150 |
info->set_bailout_reason(kBailedOutDueToDependencyChange); |
1083 |
status = optimizing_compiler->AbortOptimization();
|
|
1084 |
} else if (status != OptimizingCompiler::SUCCEEDED) {
|
|
1151 |
status = job->AbortOptimization();
|
|
1152 |
} else if (status != RecompileJob::SUCCEEDED) {
|
|
1085 | 1153 |
info->set_bailout_reason(kFailedBailedOutLastTime); |
1086 |
status = optimizing_compiler->AbortOptimization();
|
|
1154 |
status = job->AbortOptimization();
|
|
1087 | 1155 |
} else if (isolate->DebuggerHasBreakPoints()) { |
1088 | 1156 |
info->set_bailout_reason(kDebuggerIsActive); |
1089 |
status = optimizing_compiler->AbortOptimization();
|
|
1157 |
status = job->AbortOptimization();
|
|
1090 | 1158 |
} else { |
1091 |
status = optimizing_compiler->GenerateAndInstallCode();
|
|
1092 |
ASSERT(status == OptimizingCompiler::SUCCEEDED ||
|
|
1093 |
status == OptimizingCompiler::BAILED_OUT);
|
|
1159 |
status = job->GenerateAndInstallCode();
|
|
1160 |
ASSERT(status == RecompileJob::SUCCEEDED ||
|
|
1161 |
status == RecompileJob::BAILED_OUT);
|
|
1094 | 1162 |
} |
1095 | 1163 |
|
1096 | 1164 |
InstallCodeCommon(*info); |
1097 |
if (status == OptimizingCompiler::SUCCEEDED) {
|
|
1165 |
if (status == RecompileJob::SUCCEEDED) {
|
|
1098 | 1166 |
Handle<Code> code = info->code(); |
1099 | 1167 |
ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate)); |
1100 | 1168 |
info->closure()->ReplaceCode(*code); |
... | ... | |
1115 | 1183 |
// profiler ticks to prevent too soon re-opt after a deopt. |
1116 | 1184 |
info->shared_info()->code()->set_profiler_ticks(0); |
1117 | 1185 |
ASSERT(!info->closure()->IsInRecompileQueue()); |
1118 |
return (status == OptimizingCompiler::SUCCEEDED) ? info->code()
|
|
1119 |
: Handle<Code>::null();
|
|
1186 |
return (status == RecompileJob::SUCCEEDED) ? info->code()
|
|
1187 |
: Handle<Code>::null(); |
|
1120 | 1188 |
} |
1121 | 1189 |
|
1122 | 1190 |
|
Also available in: Unified diff