| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 | 8 |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| 11 #include "src/compilation-cache.h" | 11 #include "src/compilation-cache.h" |
| 12 #include "src/compiler/pipeline.h" |
| 12 #include "src/cpu-profiler.h" | 13 #include "src/cpu-profiler.h" |
| 13 #include "src/debug.h" | 14 #include "src/debug.h" |
| 14 #include "src/deoptimizer.h" | 15 #include "src/deoptimizer.h" |
| 15 #include "src/full-codegen.h" | 16 #include "src/full-codegen.h" |
| 16 #include "src/gdb-jit.h" | 17 #include "src/gdb-jit.h" |
| 17 #include "src/hydrogen.h" | 18 #include "src/hydrogen.h" |
| 18 #include "src/isolate-inl.h" | 19 #include "src/isolate-inl.h" |
| 19 #include "src/lithium.h" | 20 #include "src/lithium.h" |
| 20 #include "src/liveedit.h" | 21 #include "src/liveedit.h" |
| 21 #include "src/parser.h" | 22 #include "src/parser.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 50 osr_ast_id_(BailoutId::None()), | 51 osr_ast_id_(BailoutId::None()), |
| 51 parameter_count_(0), | 52 parameter_count_(0), |
| 52 this_has_uses_(true), | 53 this_has_uses_(true), |
| 53 optimization_id_(-1), | 54 optimization_id_(-1), |
| 54 ast_value_factory_(NULL), | 55 ast_value_factory_(NULL), |
| 55 ast_value_factory_owned_(false) { | 56 ast_value_factory_owned_(false) { |
| 56 Initialize(script->GetIsolate(), BASE, zone); | 57 Initialize(script->GetIsolate(), BASE, zone); |
| 57 } | 58 } |
| 58 | 59 |
| 59 | 60 |
| 61 CompilationInfo::CompilationInfo(Isolate* isolate, Zone* zone) |
| 62 : flags_(StrictModeField::encode(SLOPPY)), |
| 63 script_(Handle<Script>::null()), |
| 64 osr_ast_id_(BailoutId::None()), |
| 65 parameter_count_(0), |
| 66 this_has_uses_(true), |
| 67 optimization_id_(-1), |
| 68 ast_value_factory_(NULL), |
| 69 ast_value_factory_owned_(false) { |
| 70 Initialize(isolate, STUB, zone); |
| 71 } |
| 72 |
| 73 |
| 60 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info, | 74 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info, |
| 61 Zone* zone) | 75 Zone* zone) |
| 62 : flags_(StrictModeField::encode(SLOPPY) | IsLazy::encode(true)), | 76 : flags_(StrictModeField::encode(SLOPPY) | IsLazy::encode(true)), |
| 63 shared_info_(shared_info), | 77 shared_info_(shared_info), |
| 64 script_(Handle<Script>(Script::cast(shared_info->script()))), | 78 script_(Handle<Script>(Script::cast(shared_info->script()))), |
| 65 osr_ast_id_(BailoutId::None()), | 79 osr_ast_id_(BailoutId::None()), |
| 66 parameter_count_(0), | 80 parameter_count_(0), |
| 67 this_has_uses_(true), | 81 this_has_uses_(true), |
| 68 optimization_id_(-1), | 82 optimization_id_(-1), |
| 69 ast_value_factory_(NULL), | 83 ast_value_factory_(NULL), |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 const int locals_limit = LUnallocated::kMaxFixedSlotIndex; | 361 const int locals_limit = LUnallocated::kMaxFixedSlotIndex; |
| 348 if (info()->is_osr() && | 362 if (info()->is_osr() && |
| 349 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) { | 363 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) { |
| 350 return AbortAndDisableOptimization(kTooManyParametersLocals); | 364 return AbortAndDisableOptimization(kTooManyParametersLocals); |
| 351 } | 365 } |
| 352 | 366 |
| 353 if (scope->HasIllegalRedeclaration()) { | 367 if (scope->HasIllegalRedeclaration()) { |
| 354 return AbortAndDisableOptimization(kFunctionWithIllegalRedeclaration); | 368 return AbortAndDisableOptimization(kFunctionWithIllegalRedeclaration); |
| 355 } | 369 } |
| 356 | 370 |
| 357 // Take --hydrogen-filter into account. | 371 // Check the whitelist for Crankshaft. |
| 358 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) { | 372 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) { |
| 359 return AbortOptimization(kHydrogenFilter); | 373 return AbortOptimization(kHydrogenFilter); |
| 360 } | 374 } |
| 361 | 375 |
| 376 // Crankshaft requires a version of fullcode with deoptimization support. |
| 362 // Recompile the unoptimized version of the code if the current version | 377 // Recompile the unoptimized version of the code if the current version |
| 363 // doesn't have deoptimization support. Alternatively, we may decide to | 378 // doesn't have deoptimization support already. |
| 364 // run the full code generator to get a baseline for the compile-time | 379 // Otherwise, if we are gathering compilation time and space statistics |
| 365 // performance of the hydrogen-based compiler. | 380 // for hydrogen, gather baseline statistics for a fullcode compilation. |
| 366 bool should_recompile = !info()->shared_info()->has_deoptimization_support(); | 381 bool should_recompile = !info()->shared_info()->has_deoptimization_support(); |
| 367 if (should_recompile || FLAG_hydrogen_stats) { | 382 if (should_recompile || FLAG_hydrogen_stats) { |
| 368 base::ElapsedTimer timer; | 383 base::ElapsedTimer timer; |
| 369 if (FLAG_hydrogen_stats) { | 384 if (FLAG_hydrogen_stats) { |
| 370 timer.Start(); | 385 timer.Start(); |
| 371 } | 386 } |
| 372 CompilationInfoWithZone unoptimized(info()->shared_info()); | 387 CompilationInfoWithZone unoptimized(info()->shared_info()); |
| 373 // Note that we use the same AST that we will use for generating the | 388 // Note that we use the same AST that we will use for generating the |
| 374 // optimized code. | 389 // optimized code. |
| 375 unoptimized.SetFunction(info()->function()); | 390 unoptimized.SetFunction(info()->function()); |
| 376 unoptimized.PrepareForCompilation(info()->scope()); | 391 unoptimized.PrepareForCompilation(info()->scope()); |
| 377 unoptimized.SetContext(info()->context()); | 392 unoptimized.SetContext(info()->context()); |
| 378 if (should_recompile) unoptimized.EnableDeoptimizationSupport(); | 393 if (should_recompile) unoptimized.EnableDeoptimizationSupport(); |
| 379 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized); | 394 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized); |
| 380 if (should_recompile) { | 395 if (should_recompile) { |
| 381 if (!succeeded) return SetLastStatus(FAILED); | 396 if (!succeeded) return SetLastStatus(FAILED); |
| 382 Handle<SharedFunctionInfo> shared = info()->shared_info(); | 397 Handle<SharedFunctionInfo> shared = info()->shared_info(); |
| 383 shared->EnableDeoptimizationSupport(*unoptimized.code()); | 398 shared->EnableDeoptimizationSupport(*unoptimized.code()); |
| 384 // The existing unoptimized code was replaced with the new one. | 399 // The existing unoptimized code was replaced with the new one. |
| 385 Compiler::RecordFunctionCompilation( | 400 Compiler::RecordFunctionCompilation( |
| 386 Logger::LAZY_COMPILE_TAG, &unoptimized, shared); | 401 Logger::LAZY_COMPILE_TAG, &unoptimized, shared); |
| 387 } | 402 } |
| 388 if (FLAG_hydrogen_stats) { | 403 if (FLAG_hydrogen_stats) { |
| 389 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); | 404 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); |
| 390 } | 405 } |
| 391 } | 406 } |
| 392 | 407 |
| 393 // Check that the unoptimized, shared code is ready for | |
| 394 // optimizations. When using the always_opt flag we disregard the | |
| 395 // optimizable marker in the code object and optimize anyway. This | |
| 396 // is safe as long as the unoptimized code has deoptimization | |
| 397 // support. | |
| 398 ASSERT(FLAG_always_opt || info()->shared_info()->code()->optimizable()); | |
| 399 ASSERT(info()->shared_info()->has_deoptimization_support()); | 408 ASSERT(info()->shared_info()->has_deoptimization_support()); |
| 400 | 409 |
| 410 // Check the whitelist for TurboFan. |
| 411 if (info()->closure()->PassesFilter(FLAG_turbo_filter) && |
| 412 // TODO(turbofan): Make try-catch work and remove this bailout. |
| 413 info()->function()->dont_optimize_reason() != kTryCatchStatement && |
| 414 info()->function()->dont_optimize_reason() != kTryFinallyStatement && |
| 415 // TODO(turbofan): Make OSR work and remove this bailout. |
| 416 !info()->is_osr()) { |
| 417 compiler::Pipeline pipeline(info()); |
| 418 pipeline.GenerateCode(); |
| 419 return SetLastStatus(SUCCEEDED); |
| 420 } |
| 421 |
| 401 if (FLAG_trace_hydrogen) { | 422 if (FLAG_trace_hydrogen) { |
| 402 Handle<String> name = info()->function()->debug_name(); | 423 Handle<String> name = info()->function()->debug_name(); |
| 403 PrintF("-----------------------------------------------------------\n"); | 424 PrintF("-----------------------------------------------------------\n"); |
| 404 PrintF("Compiling method %s using hydrogen\n", name->ToCString().get()); | 425 PrintF("Compiling method %s using hydrogen\n", name->ToCString().get()); |
| 405 isolate()->GetHTracer()->TraceCompilation(info()); | 426 isolate()->GetHTracer()->TraceCompilation(info()); |
| 406 } | 427 } |
| 407 | 428 |
| 408 // Type-check the function. | 429 // Type-check the function. |
| 409 AstTyper::Run(info()); | 430 AstTyper::Run(info()); |
| 410 | 431 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 440 } | 461 } |
| 441 | 462 |
| 442 | 463 |
| 443 OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() { | 464 OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() { |
| 444 DisallowHeapAllocation no_allocation; | 465 DisallowHeapAllocation no_allocation; |
| 445 DisallowHandleAllocation no_handles; | 466 DisallowHandleAllocation no_handles; |
| 446 DisallowHandleDereference no_deref; | 467 DisallowHandleDereference no_deref; |
| 447 DisallowCodeDependencyChange no_dependency_change; | 468 DisallowCodeDependencyChange no_dependency_change; |
| 448 | 469 |
| 449 ASSERT(last_status() == SUCCEEDED); | 470 ASSERT(last_status() == SUCCEEDED); |
| 471 // TODO(turbofan): Currently everything is done in the first phase. |
| 472 if (!info()->code().is_null()) { |
| 473 return last_status(); |
| 474 } |
| 475 |
| 450 Timer t(this, &time_taken_to_optimize_); | 476 Timer t(this, &time_taken_to_optimize_); |
| 451 ASSERT(graph_ != NULL); | 477 ASSERT(graph_ != NULL); |
| 452 BailoutReason bailout_reason = kNoReason; | 478 BailoutReason bailout_reason = kNoReason; |
| 453 | 479 |
| 454 if (graph_->Optimize(&bailout_reason)) { | 480 if (graph_->Optimize(&bailout_reason)) { |
| 455 chunk_ = LChunk::NewChunk(graph_); | 481 chunk_ = LChunk::NewChunk(graph_); |
| 456 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED); | 482 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED); |
| 457 } else if (bailout_reason != kNoReason) { | 483 } else if (bailout_reason != kNoReason) { |
| 458 graph_builder_->Bailout(bailout_reason); | 484 graph_builder_->Bailout(bailout_reason); |
| 459 } | 485 } |
| 460 | 486 |
| 461 return AbortOptimization(); | 487 return AbortOptimization(); |
| 462 } | 488 } |
| 463 | 489 |
| 464 | 490 |
| 465 OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { | 491 OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { |
| 466 ASSERT(last_status() == SUCCEEDED); | 492 ASSERT(last_status() == SUCCEEDED); |
| 493 // TODO(turbofan): Currently everything is done in the first phase. |
| 494 if (!info()->code().is_null()) { |
| 495 RecordOptimizationStats(); |
| 496 return last_status(); |
| 497 } |
| 498 |
| 467 ASSERT(!info()->HasAbortedDueToDependencyChange()); | 499 ASSERT(!info()->HasAbortedDueToDependencyChange()); |
| 468 DisallowCodeDependencyChange no_dependency_change; | 500 DisallowCodeDependencyChange no_dependency_change; |
| 469 DisallowJavascriptExecution no_js(isolate()); | 501 DisallowJavascriptExecution no_js(isolate()); |
| 470 { // Scope for timer. | 502 { // Scope for timer. |
| 471 Timer timer(this, &time_taken_to_codegen_); | 503 Timer timer(this, &time_taken_to_codegen_); |
| 472 ASSERT(chunk_ != NULL); | 504 ASSERT(chunk_ != NULL); |
| 473 ASSERT(graph_ != NULL); | 505 ASSERT(graph_ != NULL); |
| 474 // Deferred handles reference objects that were accessible during | 506 // Deferred handles reference objects that were accessible during |
| 475 // graph creation. To make sure that we don't encounter inconsistencies | 507 // graph creation. To make sure that we don't encounter inconsistencies |
| 476 // between graph creation and code generation, we disallow accessing | 508 // between graph creation and code generation, we disallow accessing |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 } | 1140 } |
| 1109 } | 1141 } |
| 1110 return MaybeHandle<Code>(); | 1142 return MaybeHandle<Code>(); |
| 1111 } | 1143 } |
| 1112 | 1144 |
| 1113 | 1145 |
| 1114 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { | 1146 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { |
| 1115 Handle<Code> code = info->code(); | 1147 Handle<Code> code = info->code(); |
| 1116 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. | 1148 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. |
| 1117 | 1149 |
| 1150 // Context specialization folds-in the context, so no sharing can occur. |
| 1151 if (code->is_turbofanned() && FLAG_context_specialization) return; |
| 1152 |
| 1118 // Cache optimized code. | 1153 // Cache optimized code. |
| 1119 if (FLAG_cache_optimized_code) { | 1154 if (FLAG_cache_optimized_code) { |
| 1120 Handle<JSFunction> function = info->closure(); | 1155 Handle<JSFunction> function = info->closure(); |
| 1121 Handle<SharedFunctionInfo> shared(function->shared()); | 1156 Handle<SharedFunctionInfo> shared(function->shared()); |
| 1122 // Do not cache bound functions. | 1157 // Do not cache bound functions. |
| 1123 if (shared->bound()) return; | 1158 if (shared->bound()) return; |
| 1124 Handle<FixedArray> literals(function->literals()); | 1159 Handle<FixedArray> literals(function->literals()); |
| 1125 Handle<Context> native_context(function->context()->native_context()); | 1160 Handle<Context> native_context(function->context()->native_context()); |
| 1126 SharedFunctionInfo::AddToOptimizedCodeMap( | 1161 SharedFunctionInfo::AddToOptimizedCodeMap( |
| 1127 shared, native_context, code, literals, info->osr_ast_id()); | 1162 shared, native_context, code, literals, info->osr_ast_id()); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1345 AllowHandleDereference allow_deref; | 1380 AllowHandleDereference allow_deref; |
| 1346 bool tracing_on = info()->IsStub() | 1381 bool tracing_on = info()->IsStub() |
| 1347 ? FLAG_trace_hydrogen_stubs | 1382 ? FLAG_trace_hydrogen_stubs |
| 1348 : (FLAG_trace_hydrogen && | 1383 : (FLAG_trace_hydrogen && |
| 1349 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); | 1384 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); |
| 1350 return (tracing_on && | 1385 return (tracing_on && |
| 1351 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); | 1386 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); |
| 1352 } | 1387 } |
| 1353 | 1388 |
| 1354 } } // namespace v8::internal | 1389 } } // namespace v8::internal |
| OLD | NEW |