| 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 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 !scope_->outer_scope_calls_non_strict_eval() && | 228 !scope_->outer_scope_calls_non_strict_eval() && |
| 229 !scope_->inside_with(); | 229 !scope_->inside_with(); |
| 230 SetMode(is_optimizable_closure ? BASE : NONOPT); | 230 SetMode(is_optimizable_closure ? BASE : NONOPT); |
| 231 } | 231 } |
| 232 | 232 |
| 233 | 233 |
| 234 // Primitive functions are unlikely to be picked up by the stack-walking | 234 // Primitive functions are unlikely to be picked up by the stack-walking |
| 235 // profiler, so they trigger their own optimization when they're called | 235 // profiler, so they trigger their own optimization when they're called |
| 236 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time. | 236 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time. |
| 237 bool CompilationInfo::ShouldSelfOptimize() { | 237 bool CompilationInfo::ShouldSelfOptimize() { |
| 238 return FLAG_self_optimization && | 238 return FLAG_crankshaft && |
| 239 FLAG_crankshaft && | |
| 240 !function()->flags()->Contains(kDontSelfOptimize) && | 239 !function()->flags()->Contains(kDontSelfOptimize) && |
| 241 !function()->dont_optimize() && | 240 !function()->dont_optimize() && |
| 242 function()->scope()->AllowsLazyCompilation() && | 241 function()->scope()->AllowsLazyCompilation() && |
| 243 (shared_info().is_null() || !shared_info()->optimization_disabled()); | 242 (shared_info().is_null() || !shared_info()->optimization_disabled()); |
| 244 } | 243 } |
| 245 | 244 |
| 246 | 245 |
| 247 // Determine whether to use the full compiler for all code. If the flag | 246 // Determine whether to use the full compiler for all code. If the flag |
| 248 // --always-full-compiler is specified this is the case. For the virtual frame | 247 // --always-full-compiler is specified this is the case. For the virtual frame |
| 249 // based compiler the full compiler is also used if a debugger is connected, as | 248 // based compiler the full compiler is also used if a debugger is connected, as |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 status = job.OptimizeGraph(); | 316 status = job.OptimizeGraph(); |
| 318 if (status != RecompileJob::SUCCEEDED) { | 317 if (status != RecompileJob::SUCCEEDED) { |
| 319 status = job.AbortOptimization(); | 318 status = job.AbortOptimization(); |
| 320 return status != RecompileJob::FAILED; | 319 return status != RecompileJob::FAILED; |
| 321 } | 320 } |
| 322 status = job.GenerateAndInstallCode(); | 321 status = job.GenerateAndInstallCode(); |
| 323 return status != RecompileJob::FAILED; | 322 return status != RecompileJob::FAILED; |
| 324 } | 323 } |
| 325 | 324 |
| 326 | 325 |
| 327 class HOptimizedGraphBuilderWithPotisions: public HOptimizedGraphBuilder { | 326 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { |
| 328 public: | 327 public: |
| 329 explicit HOptimizedGraphBuilderWithPotisions(CompilationInfo* info) | 328 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) |
| 330 : HOptimizedGraphBuilder(info) { | 329 : HOptimizedGraphBuilder(info) { |
| 331 } | 330 } |
| 332 | 331 |
| 333 #define DEF_VISIT(type) \ | 332 #define DEF_VISIT(type) \ |
| 334 virtual void Visit##type(type* node) V8_OVERRIDE { \ | 333 virtual void Visit##type(type* node) V8_OVERRIDE { \ |
| 335 if (node->position() != RelocInfo::kNoPosition) { \ | 334 if (node->position() != RelocInfo::kNoPosition) { \ |
| 336 SetSourcePosition(node->position()); \ | 335 SetSourcePosition(node->position()); \ |
| 337 } \ | 336 } \ |
| 338 HOptimizedGraphBuilder::Visit##type(node); \ | 337 HOptimizedGraphBuilder::Visit##type(node); \ |
| 339 } | 338 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 // optimizations. When using the always_opt flag we disregard the | 452 // optimizations. When using the always_opt flag we disregard the |
| 454 // optimizable marker in the code object and optimize anyway. This | 453 // optimizable marker in the code object and optimize anyway. This |
| 455 // is safe as long as the unoptimized code has deoptimization | 454 // is safe as long as the unoptimized code has deoptimization |
| 456 // support. | 455 // support. |
| 457 ASSERT(FLAG_always_opt || info()->shared_info()->code()->optimizable()); | 456 ASSERT(FLAG_always_opt || info()->shared_info()->code()->optimizable()); |
| 458 ASSERT(info()->shared_info()->has_deoptimization_support()); | 457 ASSERT(info()->shared_info()->has_deoptimization_support()); |
| 459 | 458 |
| 460 if (FLAG_trace_hydrogen) { | 459 if (FLAG_trace_hydrogen) { |
| 461 Handle<String> name = info()->function()->debug_name(); | 460 Handle<String> name = info()->function()->debug_name(); |
| 462 PrintF("-----------------------------------------------------------\n"); | 461 PrintF("-----------------------------------------------------------\n"); |
| 463 PrintF("Compiling method %s using hydrogen\n", *name->ToCString()); | 462 PrintF("Compiling method %s using hydrogen\n", name->ToCString().get()); |
| 464 isolate()->GetHTracer()->TraceCompilation(info()); | 463 isolate()->GetHTracer()->TraceCompilation(info()); |
| 465 } | 464 } |
| 466 | 465 |
| 467 // Type-check the function. | 466 // Type-check the function. |
| 468 AstTyper::Run(info()); | 467 AstTyper::Run(info()); |
| 469 | 468 |
| 470 graph_builder_ = FLAG_emit_opt_code_positions | 469 graph_builder_ = FLAG_emit_opt_code_positions |
| 471 ? new(info()->zone()) HOptimizedGraphBuilderWithPotisions(info()) | 470 ? new(info()->zone()) HOptimizedGraphBuilderWithPositions(info()) |
| 472 : new(info()->zone()) HOptimizedGraphBuilder(info()); | 471 : new(info()->zone()) HOptimizedGraphBuilder(info()); |
| 473 | 472 |
| 474 Timer t(this, &time_taken_to_create_graph_); | 473 Timer t(this, &time_taken_to_create_graph_); |
| 475 graph_ = graph_builder_->CreateGraph(); | 474 graph_ = graph_builder_->CreateGraph(); |
| 476 | 475 |
| 477 if (isolate()->has_pending_exception()) { | 476 if (isolate()->has_pending_exception()) { |
| 478 info()->SetCode(Handle<Code>::null()); | 477 info()->SetCode(Handle<Code>::null()); |
| 479 return SetLastStatus(FAILED); | 478 return SetLastStatus(FAILED); |
| 480 } | 479 } |
| 481 | 480 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 506 DisallowHeapAllocation no_allocation; | 505 DisallowHeapAllocation no_allocation; |
| 507 DisallowHandleAllocation no_handles; | 506 DisallowHandleAllocation no_handles; |
| 508 DisallowHandleDereference no_deref; | 507 DisallowHandleDereference no_deref; |
| 509 DisallowCodeDependencyChange no_dependency_change; | 508 DisallowCodeDependencyChange no_dependency_change; |
| 510 | 509 |
| 511 ASSERT(last_status() == SUCCEEDED); | 510 ASSERT(last_status() == SUCCEEDED); |
| 512 Timer t(this, &time_taken_to_optimize_); | 511 Timer t(this, &time_taken_to_optimize_); |
| 513 ASSERT(graph_ != NULL); | 512 ASSERT(graph_ != NULL); |
| 514 BailoutReason bailout_reason = kNoReason; | 513 BailoutReason bailout_reason = kNoReason; |
| 515 if (!graph_->Optimize(&bailout_reason)) { | 514 if (!graph_->Optimize(&bailout_reason)) { |
| 516 if (bailout_reason == kNoReason) graph_builder_->Bailout(bailout_reason); | 515 if (bailout_reason != kNoReason) graph_builder_->Bailout(bailout_reason); |
| 517 return SetLastStatus(BAILED_OUT); | 516 return SetLastStatus(BAILED_OUT); |
| 518 } else { | 517 } else { |
| 519 chunk_ = LChunk::NewChunk(graph_); | 518 chunk_ = LChunk::NewChunk(graph_); |
| 520 if (chunk_ == NULL) { | 519 if (chunk_ == NULL) { |
| 521 return SetLastStatus(BAILED_OUT); | 520 return SetLastStatus(BAILED_OUT); |
| 522 } | 521 } |
| 523 } | 522 } |
| 524 return SetLastStatus(SUCCEEDED); | 523 return SetLastStatus(SUCCEEDED); |
| 525 } | 524 } |
| 526 | 525 |
| (...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 } | 1048 } |
| 1050 } | 1049 } |
| 1051 } | 1050 } |
| 1052 | 1051 |
| 1053 ASSERT(info->code().is_null()); | 1052 ASSERT(info->code().is_null()); |
| 1054 return false; | 1053 return false; |
| 1055 } | 1054 } |
| 1056 | 1055 |
| 1057 | 1056 |
| 1058 bool Compiler::RecompileConcurrent(Handle<JSFunction> closure, | 1057 bool Compiler::RecompileConcurrent(Handle<JSFunction> closure, |
| 1058 Handle<Code> unoptimized, |
| 1059 uint32_t osr_pc_offset) { | 1059 uint32_t osr_pc_offset) { |
| 1060 bool compiling_for_osr = (osr_pc_offset != 0); | 1060 bool compiling_for_osr = (osr_pc_offset != 0); |
| 1061 | 1061 |
| 1062 Isolate* isolate = closure->GetIsolate(); | 1062 Isolate* isolate = closure->GetIsolate(); |
| 1063 // Here we prepare compile data for the concurrent recompilation thread, but | 1063 // Here we prepare compile data for the concurrent recompilation thread, but |
| 1064 // this still happens synchronously and interrupts execution. | 1064 // this still happens synchronously and interrupts execution. |
| 1065 Logger::TimerEventScope timer( | 1065 Logger::TimerEventScope timer( |
| 1066 isolate, Logger::TimerEventScope::v8_recompile_synchronous); | 1066 isolate, Logger::TimerEventScope::v8_recompile_synchronous); |
| 1067 | 1067 |
| 1068 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { | 1068 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { |
| 1069 if (FLAG_trace_concurrent_recompilation) { | 1069 if (FLAG_trace_concurrent_recompilation) { |
| 1070 PrintF(" ** Compilation queue full, will retry optimizing "); | 1070 PrintF(" ** Compilation queue full, will retry optimizing "); |
| 1071 closure->PrintName(); | 1071 closure->PrintName(); |
| 1072 PrintF(" on next run.\n"); | 1072 PrintF(" on next run.\n"); |
| 1073 } | 1073 } |
| 1074 return false; | 1074 return false; |
| 1075 } | 1075 } |
| 1076 | 1076 |
| 1077 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure)); | 1077 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure)); |
| 1078 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1078 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 1079 | 1079 |
| 1080 if (compiling_for_osr) { | 1080 if (compiling_for_osr) { |
| 1081 BailoutId osr_ast_id = | 1081 BailoutId osr_ast_id = unoptimized->TranslatePcOffsetToAstId(osr_pc_offset); |
| 1082 shared->code()->TranslatePcOffsetToAstId(osr_pc_offset); | |
| 1083 ASSERT(!osr_ast_id.IsNone()); | 1082 ASSERT(!osr_ast_id.IsNone()); |
| 1084 info->SetOptimizing(osr_ast_id); | 1083 info->SetOptimizing(osr_ast_id); |
| 1085 info->set_osr_pc_offset(osr_pc_offset); | 1084 info->SetOsrInfo(unoptimized, osr_pc_offset); |
| 1086 | 1085 |
| 1087 if (FLAG_trace_osr) { | 1086 if (FLAG_trace_osr) { |
| 1088 PrintF("[COSR - attempt to queue "); | 1087 PrintF("[COSR - attempt to queue "); |
| 1089 closure->PrintName(); | 1088 closure->PrintName(); |
| 1090 PrintF(" at AST id %d]\n", osr_ast_id.ToInt()); | 1089 PrintF(" at AST id %d]\n", osr_ast_id.ToInt()); |
| 1091 } | 1090 } |
| 1092 } else { | 1091 } else { |
| 1093 info->SetOptimizing(BailoutId::None()); | 1092 info->SetOptimizing(BailoutId::None()); |
| 1094 } | 1093 } |
| 1095 | 1094 |
| 1096 VMState<COMPILER> state(isolate); | 1095 VMState<COMPILER> state(isolate); |
| 1097 PostponeInterruptsScope postpone(isolate); | 1096 PostponeInterruptsScope postpone(isolate); |
| 1098 | 1097 |
| 1099 int compiled_size = shared->end_position() - shared->start_position(); | 1098 int compiled_size = shared->end_position() - shared->start_position(); |
| 1100 isolate->counters()->total_compile_size()->Increment(compiled_size); | 1099 isolate->counters()->total_compile_size()->Increment(compiled_size); |
| 1101 | 1100 |
| 1102 { | 1101 { |
| 1103 CompilationHandleScope handle_scope(*info); | 1102 CompilationHandleScope handle_scope(info.get()); |
| 1104 | 1103 |
| 1105 if (!compiling_for_osr && InstallCodeFromOptimizedCodeMap(*info)) { | 1104 if (!compiling_for_osr && InstallCodeFromOptimizedCodeMap(info.get())) { |
| 1106 return true; | 1105 return true; |
| 1107 } | 1106 } |
| 1108 | 1107 |
| 1109 if (Parser::Parse(*info)) { | 1108 if (Parser::Parse(info.get())) { |
| 1110 LanguageMode language_mode = info->function()->language_mode(); | 1109 LanguageMode language_mode = info->function()->language_mode(); |
| 1111 info->SetLanguageMode(language_mode); | 1110 info->SetLanguageMode(language_mode); |
| 1112 shared->set_language_mode(language_mode); | 1111 shared->set_language_mode(language_mode); |
| 1113 info->SaveHandles(); | 1112 info->SaveHandles(); |
| 1114 | 1113 |
| 1115 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) { | 1114 if (Rewriter::Rewrite(info.get()) && Scope::Analyze(info.get())) { |
| 1116 RecompileJob* job = new(info->zone()) RecompileJob(*info); | 1115 RecompileJob* job = new(info->zone()) RecompileJob(info.get()); |
| 1117 RecompileJob::Status status = job->CreateGraph(); | 1116 RecompileJob::Status status = job->CreateGraph(); |
| 1118 if (status == RecompileJob::SUCCEEDED) { | 1117 if (status == RecompileJob::SUCCEEDED) { |
| 1119 info.Detach(); | 1118 info.Detach(); |
| 1120 shared->code()->set_profiler_ticks(0); | 1119 unoptimized->set_profiler_ticks(0); |
| 1121 isolate->optimizing_compiler_thread()->QueueForOptimization(job); | 1120 isolate->optimizing_compiler_thread()->QueueForOptimization(job); |
| 1122 ASSERT(!isolate->has_pending_exception()); | 1121 ASSERT(!isolate->has_pending_exception()); |
| 1123 return true; | 1122 return true; |
| 1124 } else if (status == RecompileJob::BAILED_OUT) { | 1123 } else if (status == RecompileJob::BAILED_OUT) { |
| 1125 isolate->clear_pending_exception(); | 1124 isolate->clear_pending_exception(); |
| 1126 InstallFullCode(*info); | 1125 InstallFullCode(info.get()); |
| 1127 } | 1126 } |
| 1128 } | 1127 } |
| 1129 } | 1128 } |
| 1130 } | 1129 } |
| 1131 | 1130 |
| 1132 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 1131 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
| 1133 return false; | 1132 return false; |
| 1134 } | 1133 } |
| 1135 | 1134 |
| 1136 | 1135 |
| 1137 Handle<Code> Compiler::InstallOptimizedCode(RecompileJob* job) { | 1136 Handle<Code> Compiler::InstallOptimizedCode(RecompileJob* job) { |
| 1138 SmartPointer<CompilationInfo> info(job->info()); | 1137 SmartPointer<CompilationInfo> info(job->info()); |
| 1139 // The function may have already been optimized by OSR. Simply continue. | 1138 // The function may have already been optimized by OSR. Simply continue. |
| 1140 // Except when OSR already disabled optimization for some reason. | 1139 // Except when OSR already disabled optimization for some reason. |
| 1141 if (info->shared_info()->optimization_disabled()) { | 1140 if (info->shared_info()->optimization_disabled()) { |
| 1142 info->AbortOptimization(); | 1141 info->AbortOptimization(); |
| 1143 InstallFullCode(*info); | 1142 InstallFullCode(info.get()); |
| 1144 if (FLAG_trace_concurrent_recompilation) { | 1143 if (FLAG_trace_concurrent_recompilation) { |
| 1145 PrintF(" ** aborting optimization for "); | 1144 PrintF(" ** aborting optimization for "); |
| 1146 info->closure()->PrintName(); | 1145 info->closure()->PrintName(); |
| 1147 PrintF(" as it has been disabled.\n"); | 1146 PrintF(" as it has been disabled.\n"); |
| 1148 } | 1147 } |
| 1149 ASSERT(!info->closure()->IsInRecompileQueue()); | 1148 ASSERT(!info->closure()->IsInRecompileQueue()); |
| 1150 return Handle<Code>::null(); | 1149 return Handle<Code>::null(); |
| 1151 } | 1150 } |
| 1152 | 1151 |
| 1153 Isolate* isolate = info->isolate(); | 1152 Isolate* isolate = info->isolate(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1165 status = job->AbortOptimization(); | 1164 status = job->AbortOptimization(); |
| 1166 } else if (isolate->DebuggerHasBreakPoints()) { | 1165 } else if (isolate->DebuggerHasBreakPoints()) { |
| 1167 info->set_bailout_reason(kDebuggerIsActive); | 1166 info->set_bailout_reason(kDebuggerIsActive); |
| 1168 status = job->AbortOptimization(); | 1167 status = job->AbortOptimization(); |
| 1169 } else { | 1168 } else { |
| 1170 status = job->GenerateAndInstallCode(); | 1169 status = job->GenerateAndInstallCode(); |
| 1171 ASSERT(status == RecompileJob::SUCCEEDED || | 1170 ASSERT(status == RecompileJob::SUCCEEDED || |
| 1172 status == RecompileJob::BAILED_OUT); | 1171 status == RecompileJob::BAILED_OUT); |
| 1173 } | 1172 } |
| 1174 | 1173 |
| 1175 InstallCodeCommon(*info); | 1174 InstallCodeCommon(info.get()); |
| 1176 if (status == RecompileJob::SUCCEEDED) { | 1175 if (status == RecompileJob::SUCCEEDED) { |
| 1177 Handle<Code> code = info->code(); | 1176 Handle<Code> code = info->code(); |
| 1178 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate)); | 1177 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate)); |
| 1179 info->closure()->ReplaceCode(*code); | 1178 info->closure()->ReplaceCode(*code); |
| 1180 if (info->shared_info()->SearchOptimizedCodeMap( | 1179 if (info->shared_info()->SearchOptimizedCodeMap( |
| 1181 info->closure()->context()->native_context()) == -1) { | 1180 info->closure()->context()->native_context()) == -1) { |
| 1182 InsertCodeIntoOptimizedCodeMap(*info); | 1181 InsertCodeIntoOptimizedCodeMap(info.get()); |
| 1183 } | 1182 } |
| 1184 if (FLAG_trace_concurrent_recompilation) { | 1183 if (FLAG_trace_concurrent_recompilation) { |
| 1185 PrintF(" ** Optimized code for "); | 1184 PrintF(" ** Optimized code for "); |
| 1186 info->closure()->PrintName(); | 1185 info->closure()->PrintName(); |
| 1187 PrintF(" installed.\n"); | 1186 PrintF(" installed.\n"); |
| 1188 } | 1187 } |
| 1189 } else { | 1188 } else { |
| 1190 info->AbortOptimization(); | 1189 info->AbortOptimization(); |
| 1191 InstallFullCode(*info); | 1190 InstallFullCode(info.get()); |
| 1192 } | 1191 } |
| 1193 // Optimized code is finally replacing unoptimized code. Reset the latter's | 1192 // Optimized code is finally replacing unoptimized code. Reset the latter's |
| 1194 // profiler ticks to prevent too soon re-opt after a deopt. | 1193 // profiler ticks to prevent too soon re-opt after a deopt. |
| 1195 info->shared_info()->code()->set_profiler_ticks(0); | 1194 info->shared_info()->code()->set_profiler_ticks(0); |
| 1196 ASSERT(!info->closure()->IsInRecompileQueue()); | 1195 ASSERT(!info->closure()->IsInRecompileQueue()); |
| 1197 return (status == RecompileJob::SUCCEEDED) ? info->code() | 1196 return (status == RecompileJob::SUCCEEDED) ? info->code() |
| 1198 : Handle<Code>::null(); | 1197 : Handle<Code>::null(); |
| 1199 } | 1198 } |
| 1200 | 1199 |
| 1201 | 1200 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 AllowHandleDereference allow_deref; | 1360 AllowHandleDereference allow_deref; |
| 1362 bool tracing_on = info()->IsStub() | 1361 bool tracing_on = info()->IsStub() |
| 1363 ? FLAG_trace_hydrogen_stubs | 1362 ? FLAG_trace_hydrogen_stubs |
| 1364 : (FLAG_trace_hydrogen && | 1363 : (FLAG_trace_hydrogen && |
| 1365 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); | 1364 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); |
| 1366 return (tracing_on && | 1365 return (tracing_on && |
| 1367 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); | 1366 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); |
| 1368 } | 1367 } |
| 1369 | 1368 |
| 1370 } } // namespace v8::internal | 1369 } } // namespace v8::internal |
| OLD | NEW |