| 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 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 return false; | 253 return false; |
| 254 #endif | 254 #endif |
| 255 } | 255 } |
| 256 | 256 |
| 257 | 257 |
| 258 static bool AlwaysFullCompiler(Isolate* isolate) { | 258 static bool AlwaysFullCompiler(Isolate* isolate) { |
| 259 return FLAG_always_full_compiler || IsDebuggerActive(isolate); | 259 return FLAG_always_full_compiler || IsDebuggerActive(isolate); |
| 260 } | 260 } |
| 261 | 261 |
| 262 | 262 |
| 263 void OptimizingCompiler::RecordOptimizationStats() { | 263 void RecompileJob::RecordOptimizationStats() { |
| 264 Handle<JSFunction> function = info()->closure(); | 264 Handle<JSFunction> function = info()->closure(); |
| 265 int opt_count = function->shared()->opt_count(); | 265 int opt_count = function->shared()->opt_count(); |
| 266 function->shared()->set_opt_count(opt_count + 1); | 266 function->shared()->set_opt_count(opt_count + 1); |
| 267 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF(); | 267 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF(); |
| 268 double ms_optimize = time_taken_to_optimize_.InMillisecondsF(); | 268 double ms_optimize = time_taken_to_optimize_.InMillisecondsF(); |
| 269 double ms_codegen = time_taken_to_codegen_.InMillisecondsF(); | 269 double ms_codegen = time_taken_to_codegen_.InMillisecondsF(); |
| 270 if (FLAG_trace_opt) { | 270 if (FLAG_trace_opt) { |
| 271 PrintF("[optimizing "); | 271 PrintF("[optimizing "); |
| 272 function->ShortPrint(); | 272 function->ShortPrint(); |
| 273 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, | 273 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 290 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_, | 290 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_, |
| 291 time_taken_to_optimize_, | 291 time_taken_to_optimize_, |
| 292 time_taken_to_codegen_); | 292 time_taken_to_codegen_); |
| 293 } | 293 } |
| 294 } | 294 } |
| 295 | 295 |
| 296 | 296 |
| 297 // A return value of true indicates the compilation pipeline is still | 297 // A return value of true indicates the compilation pipeline is still |
| 298 // going, not necessarily that we optimized the code. | 298 // going, not necessarily that we optimized the code. |
| 299 static bool MakeCrankshaftCode(CompilationInfo* info) { | 299 static bool MakeCrankshaftCode(CompilationInfo* info) { |
| 300 OptimizingCompiler compiler(info); | 300 RecompileJob job(info); |
| 301 OptimizingCompiler::Status status = compiler.CreateGraph(); | 301 RecompileJob::Status status = job.CreateGraph(); |
| 302 | 302 |
| 303 if (status != OptimizingCompiler::SUCCEEDED) { | 303 if (status != RecompileJob::SUCCEEDED) { |
| 304 return status != OptimizingCompiler::FAILED; | 304 return status != RecompileJob::FAILED; |
| 305 } | 305 } |
| 306 status = compiler.OptimizeGraph(); | 306 status = job.OptimizeGraph(); |
| 307 if (status != OptimizingCompiler::SUCCEEDED) { | 307 if (status != RecompileJob::SUCCEEDED) { |
| 308 status = compiler.AbortOptimization(); | 308 status = job.AbortOptimization(); |
| 309 return status != OptimizingCompiler::FAILED; | 309 return status != RecompileJob::FAILED; |
| 310 } | 310 } |
| 311 status = compiler.GenerateAndInstallCode(); | 311 status = job.GenerateAndInstallCode(); |
| 312 return status != OptimizingCompiler::FAILED; | 312 return status != RecompileJob::FAILED; |
| 313 } | 313 } |
| 314 | 314 |
| 315 | 315 |
| 316 OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { | 316 RecompileJob::Status RecompileJob::CreateGraph() { |
| 317 ASSERT(isolate()->use_crankshaft()); | 317 ASSERT(isolate()->use_crankshaft()); |
| 318 ASSERT(info()->IsOptimizing()); | 318 ASSERT(info()->IsOptimizing()); |
| 319 ASSERT(!info()->IsCompilingForDebugging()); | 319 ASSERT(!info()->IsCompilingForDebugging()); |
| 320 | 320 |
| 321 // We should never arrive here if there is no code object on the | 321 // We should never arrive here if there is no code object on the |
| 322 // shared function object. | 322 // shared function object. |
| 323 ASSERT(info()->shared_info()->code()->kind() == Code::FUNCTION); | 323 ASSERT(info()->shared_info()->code()->kind() == Code::FUNCTION); |
| 324 | 324 |
| 325 if (FLAG_trace_opt) { | 325 if (FLAG_trace_opt) { |
| 326 // TODO(jbramley): This was added to help analyse the behaviour of | 326 // TODO(jbramley): This was added to help analyse the behaviour of |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 if (info()->HasAbortedDueToDependencyChange()) { | 454 if (info()->HasAbortedDueToDependencyChange()) { |
| 455 info_->set_bailout_reason(kBailedOutDueToDependencyChange); | 455 info_->set_bailout_reason(kBailedOutDueToDependencyChange); |
| 456 info_->AbortOptimization(); | 456 info_->AbortOptimization(); |
| 457 return SetLastStatus(BAILED_OUT); | 457 return SetLastStatus(BAILED_OUT); |
| 458 } | 458 } |
| 459 | 459 |
| 460 return SetLastStatus(SUCCEEDED); | 460 return SetLastStatus(SUCCEEDED); |
| 461 } | 461 } |
| 462 | 462 |
| 463 | 463 |
| 464 OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() { | 464 RecompileJob::Status RecompileJob::OptimizeGraph() { |
| 465 DisallowHeapAllocation no_allocation; | 465 DisallowHeapAllocation no_allocation; |
| 466 DisallowHandleAllocation no_handles; | 466 DisallowHandleAllocation no_handles; |
| 467 DisallowHandleDereference no_deref; | 467 DisallowHandleDereference no_deref; |
| 468 DisallowCodeDependencyChange no_dependency_change; | 468 DisallowCodeDependencyChange no_dependency_change; |
| 469 | 469 |
| 470 ASSERT(last_status() == SUCCEEDED); | 470 ASSERT(last_status() == SUCCEEDED); |
| 471 Timer t(this, &time_taken_to_optimize_); | 471 Timer t(this, &time_taken_to_optimize_); |
| 472 ASSERT(graph_ != NULL); | 472 ASSERT(graph_ != NULL); |
| 473 BailoutReason bailout_reason = kNoReason; | 473 BailoutReason bailout_reason = kNoReason; |
| 474 if (!graph_->Optimize(&bailout_reason)) { | 474 if (!graph_->Optimize(&bailout_reason)) { |
| 475 if (bailout_reason == kNoReason) graph_builder_->Bailout(bailout_reason); | 475 if (bailout_reason == kNoReason) graph_builder_->Bailout(bailout_reason); |
| 476 return SetLastStatus(BAILED_OUT); | 476 return SetLastStatus(BAILED_OUT); |
| 477 } else { | 477 } else { |
| 478 chunk_ = LChunk::NewChunk(graph_); | 478 chunk_ = LChunk::NewChunk(graph_); |
| 479 if (chunk_ == NULL) { | 479 if (chunk_ == NULL) { |
| 480 return SetLastStatus(BAILED_OUT); | 480 return SetLastStatus(BAILED_OUT); |
| 481 } | 481 } |
| 482 } | 482 } |
| 483 return SetLastStatus(SUCCEEDED); | 483 return SetLastStatus(SUCCEEDED); |
| 484 } | 484 } |
| 485 | 485 |
| 486 | 486 |
| 487 OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() { | 487 RecompileJob::Status RecompileJob::GenerateAndInstallCode() { |
| 488 ASSERT(last_status() == SUCCEEDED); | 488 ASSERT(last_status() == SUCCEEDED); |
| 489 ASSERT(!info()->HasAbortedDueToDependencyChange()); | 489 ASSERT(!info()->HasAbortedDueToDependencyChange()); |
| 490 DisallowCodeDependencyChange no_dependency_change; | 490 DisallowCodeDependencyChange no_dependency_change; |
| 491 { // Scope for timer. | 491 { // Scope for timer. |
| 492 Timer timer(this, &time_taken_to_codegen_); | 492 Timer timer(this, &time_taken_to_codegen_); |
| 493 ASSERT(chunk_ != NULL); | 493 ASSERT(chunk_ != NULL); |
| 494 ASSERT(graph_ != NULL); | 494 ASSERT(graph_ != NULL); |
| 495 // Deferred handles reference objects that were accessible during | 495 // Deferred handles reference objects that were accessible during |
| 496 // graph creation. To make sure that we don't encounter inconsistencies | 496 // graph creation. To make sure that we don't encounter inconsistencies |
| 497 // between graph creation and code generation, we disallow accessing | 497 // between graph creation and code generation, we disallow accessing |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1034 return true; | 1034 return true; |
| 1035 } | 1035 } |
| 1036 | 1036 |
| 1037 if (Parser::Parse(*info)) { | 1037 if (Parser::Parse(*info)) { |
| 1038 LanguageMode language_mode = info->function()->language_mode(); | 1038 LanguageMode language_mode = info->function()->language_mode(); |
| 1039 info->SetLanguageMode(language_mode); | 1039 info->SetLanguageMode(language_mode); |
| 1040 shared->set_language_mode(language_mode); | 1040 shared->set_language_mode(language_mode); |
| 1041 info->SaveHandles(); | 1041 info->SaveHandles(); |
| 1042 | 1042 |
| 1043 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) { | 1043 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) { |
| 1044 OptimizingCompiler* compiler = | 1044 RecompileJob* job = new(info->zone()) RecompileJob(*info); |
| 1045 new(info->zone()) OptimizingCompiler(*info); | 1045 RecompileJob::Status status = job->CreateGraph(); |
| 1046 OptimizingCompiler::Status status = compiler->CreateGraph(); | 1046 if (status == RecompileJob::SUCCEEDED) { |
| 1047 if (status == OptimizingCompiler::SUCCEEDED) { | |
| 1048 info.Detach(); | 1047 info.Detach(); |
| 1049 shared->code()->set_profiler_ticks(0); | 1048 shared->code()->set_profiler_ticks(0); |
| 1050 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler); | 1049 isolate->optimizing_compiler_thread()->QueueForOptimization(job); |
| 1051 ASSERT(!isolate->has_pending_exception()); | 1050 ASSERT(!isolate->has_pending_exception()); |
| 1052 return true; | 1051 return true; |
| 1053 } else if (status == OptimizingCompiler::BAILED_OUT) { | 1052 } else if (status == RecompileJob::BAILED_OUT) { |
| 1054 isolate->clear_pending_exception(); | 1053 isolate->clear_pending_exception(); |
| 1055 InstallFullCode(*info); | 1054 InstallFullCode(*info); |
| 1056 } | 1055 } |
| 1057 } | 1056 } |
| 1058 } | 1057 } |
| 1059 } | 1058 } |
| 1060 | 1059 |
| 1061 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 1060 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
| 1062 return false; | 1061 return false; |
| 1063 } | 1062 } |
| 1064 | 1063 |
| 1065 | 1064 |
| 1066 Handle<Code> Compiler::InstallOptimizedCode( | 1065 Handle<Code> Compiler::InstallOptimizedCode(RecompileJob* job) { |
| 1067 OptimizingCompiler* optimizing_compiler) { | 1066 SmartPointer<CompilationInfo> info(job->info()); |
| 1068 SmartPointer<CompilationInfo> info(optimizing_compiler->info()); | |
| 1069 // The function may have already been optimized by OSR. Simply continue. | 1067 // The function may have already been optimized by OSR. Simply continue. |
| 1070 // Except when OSR already disabled optimization for some reason. | 1068 // Except when OSR already disabled optimization for some reason. |
| 1071 if (info->shared_info()->optimization_disabled()) { | 1069 if (info->shared_info()->optimization_disabled()) { |
| 1072 info->AbortOptimization(); | 1070 info->AbortOptimization(); |
| 1073 InstallFullCode(*info); | 1071 InstallFullCode(*info); |
| 1074 if (FLAG_trace_concurrent_recompilation) { | 1072 if (FLAG_trace_concurrent_recompilation) { |
| 1075 PrintF(" ** aborting optimization for "); | 1073 PrintF(" ** aborting optimization for "); |
| 1076 info->closure()->PrintName(); | 1074 info->closure()->PrintName(); |
| 1077 PrintF(" as it has been disabled.\n"); | 1075 PrintF(" as it has been disabled.\n"); |
| 1078 } | 1076 } |
| 1079 ASSERT(!info->closure()->IsInRecompileQueue()); | 1077 ASSERT(!info->closure()->IsInRecompileQueue()); |
| 1080 return Handle<Code>::null(); | 1078 return Handle<Code>::null(); |
| 1081 } | 1079 } |
| 1082 | 1080 |
| 1083 Isolate* isolate = info->isolate(); | 1081 Isolate* isolate = info->isolate(); |
| 1084 VMState<COMPILER> state(isolate); | 1082 VMState<COMPILER> state(isolate); |
| 1085 Logger::TimerEventScope timer( | 1083 Logger::TimerEventScope timer( |
| 1086 isolate, Logger::TimerEventScope::v8_recompile_synchronous); | 1084 isolate, Logger::TimerEventScope::v8_recompile_synchronous); |
| 1087 // If crankshaft succeeded, install the optimized code else install | 1085 // If crankshaft succeeded, install the optimized code else install |
| 1088 // the unoptimized code. | 1086 // the unoptimized code. |
| 1089 OptimizingCompiler::Status status = optimizing_compiler->last_status(); | 1087 RecompileJob::Status status = job->last_status(); |
| 1090 if (info->HasAbortedDueToDependencyChange()) { | 1088 if (info->HasAbortedDueToDependencyChange()) { |
| 1091 info->set_bailout_reason(kBailedOutDueToDependencyChange); | 1089 info->set_bailout_reason(kBailedOutDueToDependencyChange); |
| 1092 status = optimizing_compiler->AbortOptimization(); | 1090 status = job->AbortOptimization(); |
| 1093 } else if (status != OptimizingCompiler::SUCCEEDED) { | 1091 } else if (status != RecompileJob::SUCCEEDED) { |
| 1094 info->set_bailout_reason(kFailedBailedOutLastTime); | 1092 info->set_bailout_reason(kFailedBailedOutLastTime); |
| 1095 status = optimizing_compiler->AbortOptimization(); | 1093 status = job->AbortOptimization(); |
| 1096 } else if (isolate->DebuggerHasBreakPoints()) { | 1094 } else if (isolate->DebuggerHasBreakPoints()) { |
| 1097 info->set_bailout_reason(kDebuggerIsActive); | 1095 info->set_bailout_reason(kDebuggerIsActive); |
| 1098 status = optimizing_compiler->AbortOptimization(); | 1096 status = job->AbortOptimization(); |
| 1099 } else { | 1097 } else { |
| 1100 status = optimizing_compiler->GenerateAndInstallCode(); | 1098 status = job->GenerateAndInstallCode(); |
| 1101 ASSERT(status == OptimizingCompiler::SUCCEEDED || | 1099 ASSERT(status == RecompileJob::SUCCEEDED || |
| 1102 status == OptimizingCompiler::BAILED_OUT); | 1100 status == RecompileJob::BAILED_OUT); |
| 1103 } | 1101 } |
| 1104 | 1102 |
| 1105 InstallCodeCommon(*info); | 1103 InstallCodeCommon(*info); |
| 1106 if (status == OptimizingCompiler::SUCCEEDED) { | 1104 if (status == RecompileJob::SUCCEEDED) { |
| 1107 Handle<Code> code = info->code(); | 1105 Handle<Code> code = info->code(); |
| 1108 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate)); | 1106 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate)); |
| 1109 info->closure()->ReplaceCode(*code); | 1107 info->closure()->ReplaceCode(*code); |
| 1110 if (info->shared_info()->SearchOptimizedCodeMap( | 1108 if (info->shared_info()->SearchOptimizedCodeMap( |
| 1111 info->closure()->context()->native_context()) == -1) { | 1109 info->closure()->context()->native_context()) == -1) { |
| 1112 InsertCodeIntoOptimizedCodeMap(*info); | 1110 InsertCodeIntoOptimizedCodeMap(*info); |
| 1113 } | 1111 } |
| 1114 if (FLAG_trace_concurrent_recompilation) { | 1112 if (FLAG_trace_concurrent_recompilation) { |
| 1115 PrintF(" ** Optimized code for "); | 1113 PrintF(" ** Optimized code for "); |
| 1116 info->closure()->PrintName(); | 1114 info->closure()->PrintName(); |
| 1117 PrintF(" installed.\n"); | 1115 PrintF(" installed.\n"); |
| 1118 } | 1116 } |
| 1119 } else { | 1117 } else { |
| 1120 info->AbortOptimization(); | 1118 info->AbortOptimization(); |
| 1121 InstallFullCode(*info); | 1119 InstallFullCode(*info); |
| 1122 } | 1120 } |
| 1123 // Optimized code is finally replacing unoptimized code. Reset the latter's | 1121 // Optimized code is finally replacing unoptimized code. Reset the latter's |
| 1124 // profiler ticks to prevent too soon re-opt after a deopt. | 1122 // profiler ticks to prevent too soon re-opt after a deopt. |
| 1125 info->shared_info()->code()->set_profiler_ticks(0); | 1123 info->shared_info()->code()->set_profiler_ticks(0); |
| 1126 ASSERT(!info->closure()->IsInRecompileQueue()); | 1124 ASSERT(!info->closure()->IsInRecompileQueue()); |
| 1127 return (status == OptimizingCompiler::SUCCEEDED) ? info->code() | 1125 return (status == RecompileJob::SUCCEEDED) ? info->code() |
| 1128 : Handle<Code>::null(); | 1126 : Handle<Code>::null(); |
| 1129 } | 1127 } |
| 1130 | 1128 |
| 1131 | 1129 |
| 1132 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, | 1130 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, |
| 1133 Handle<Script> script) { | 1131 Handle<Script> script) { |
| 1134 // Precondition: code has been parsed and scopes have been analyzed. | 1132 // Precondition: code has been parsed and scopes have been analyzed. |
| 1135 CompilationInfoWithZone info(script); | 1133 CompilationInfoWithZone info(script); |
| 1136 info.SetFunction(literal); | 1134 info.SetFunction(literal); |
| 1137 info.SetScope(literal->scope()); | 1135 info.SetScope(literal->scope()); |
| 1138 info.SetLanguageMode(literal->scope()->language_mode()); | 1136 info.SetLanguageMode(literal->scope()->language_mode()); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1291 AllowHandleDereference allow_deref; | 1289 AllowHandleDereference allow_deref; |
| 1292 bool tracing_on = info()->IsStub() | 1290 bool tracing_on = info()->IsStub() |
| 1293 ? FLAG_trace_hydrogen_stubs | 1291 ? FLAG_trace_hydrogen_stubs |
| 1294 : (FLAG_trace_hydrogen && | 1292 : (FLAG_trace_hydrogen && |
| 1295 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); | 1293 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); |
| 1296 return (tracing_on && | 1294 return (tracing_on && |
| 1297 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); | 1295 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); |
| 1298 } | 1296 } |
| 1299 | 1297 |
| 1300 } } // namespace v8::internal | 1298 } } // namespace v8::internal |
| OLD | NEW |