| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 17 matching lines...) Expand all Loading... |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "compiler.h" | 30 #include "compiler.h" |
| 31 | 31 |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "codegen-inl.h" | 33 #include "codegen-inl.h" |
| 34 #include "compilation-cache.h" | 34 #include "compilation-cache.h" |
| 35 #include "data-flow.h" | 35 #include "data-flow.h" |
| 36 #include "debug.h" | 36 #include "debug.h" |
| 37 #include "full-codegen.h" | 37 #include "full-codegen.h" |
| 38 #include "gdb-jit.h" |
| 38 #include "hydrogen.h" | 39 #include "hydrogen.h" |
| 39 #include "lithium-allocator.h" | 40 #include "lithium.h" |
| 40 #include "liveedit.h" | 41 #include "liveedit.h" |
| 41 #include "oprofile-agent.h" | |
| 42 #include "parser.h" | 42 #include "parser.h" |
| 43 #include "rewriter.h" | 43 #include "rewriter.h" |
| 44 #include "runtime-profiler.h" | 44 #include "runtime-profiler.h" |
| 45 #include "scopeinfo.h" | 45 #include "scopeinfo.h" |
| 46 #include "scopes.h" | 46 #include "scopes.h" |
| 47 #include "vm-state-inl.h" | 47 #include "vm-state-inl.h" |
| 48 | 48 |
| 49 namespace v8 { | 49 namespace v8 { |
| 50 namespace internal { | 50 namespace internal { |
| 51 | 51 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 shared_info_(Handle<SharedFunctionInfo>(closure->shared())), | 85 shared_info_(Handle<SharedFunctionInfo>(closure->shared())), |
| 86 script_(Handle<Script>(Script::cast(shared_info_->script()))), | 86 script_(Handle<Script>(Script::cast(shared_info_->script()))), |
| 87 extension_(NULL), | 87 extension_(NULL), |
| 88 pre_parse_data_(NULL), | 88 pre_parse_data_(NULL), |
| 89 supports_deoptimization_(false), | 89 supports_deoptimization_(false), |
| 90 osr_ast_id_(AstNode::kNoNumber) { | 90 osr_ast_id_(AstNode::kNoNumber) { |
| 91 Initialize(BASE); | 91 Initialize(BASE); |
| 92 } | 92 } |
| 93 | 93 |
| 94 | 94 |
| 95 void CompilationInfo::DisableOptimization() { |
| 96 if (FLAG_optimize_closures) { |
| 97 // If we allow closures optimizations and it's an optimizable closure |
| 98 // mark it correspondingly. |
| 99 bool is_closure = closure_.is_null() && !scope_->HasTrivialOuterContext(); |
| 100 if (is_closure) { |
| 101 bool is_optimizable_closure = |
| 102 !scope_->outer_scope_calls_eval() && !scope_->inside_with(); |
| 103 if (is_optimizable_closure) { |
| 104 SetMode(BASE); |
| 105 return; |
| 106 } |
| 107 } |
| 108 } |
| 109 |
| 110 SetMode(NONOPT); |
| 111 } |
| 112 |
| 113 |
| 95 // Determine whether to use the full compiler for all code. If the flag | 114 // Determine whether to use the full compiler for all code. If the flag |
| 96 // --always-full-compiler is specified this is the case. For the virtual frame | 115 // --always-full-compiler is specified this is the case. For the virtual frame |
| 97 // based compiler the full compiler is also used if a debugger is connected, as | 116 // based compiler the full compiler is also used if a debugger is connected, as |
| 98 // the code from the full compiler supports mode precise break points. For the | 117 // the code from the full compiler supports mode precise break points. For the |
| 99 // crankshaft adaptive compiler debugging the optimized code is not possible at | 118 // crankshaft adaptive compiler debugging the optimized code is not possible at |
| 100 // all. However crankshaft support recompilation of functions, so in this case | 119 // all. However crankshaft support recompilation of functions, so in this case |
| 101 // the full compiler need not be be used if a debugger is attached, but only if | 120 // the full compiler need not be be used if a debugger is attached, but only if |
| 102 // break points has actually been set. | 121 // break points has actually been set. |
| 103 static bool AlwaysFullCompiler() { | 122 static bool AlwaysFullCompiler() { |
| 104 #ifdef ENABLE_DEBUGGER_SUPPORT | 123 #ifdef ENABLE_DEBUGGER_SUPPORT |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 // Fall back to using the full code generator if it's not possible | 200 // Fall back to using the full code generator if it's not possible |
| 182 // to use the Hydrogen-based optimizing compiler. We already have | 201 // to use the Hydrogen-based optimizing compiler. We already have |
| 183 // generated code for this from the shared function object. | 202 // generated code for this from the shared function object. |
| 184 if (AlwaysFullCompiler() || !FLAG_use_hydrogen) { | 203 if (AlwaysFullCompiler() || !FLAG_use_hydrogen) { |
| 185 info->SetCode(code); | 204 info->SetCode(code); |
| 186 return true; | 205 return true; |
| 187 } | 206 } |
| 188 | 207 |
| 189 // Limit the number of times we re-compile a functions with | 208 // Limit the number of times we re-compile a functions with |
| 190 // the optimizing compiler. | 209 // the optimizing compiler. |
| 191 const int kMaxOptCount = FLAG_deopt_every_n_times == 0 ? 10 : 1000; | 210 const int kMaxOptCount = |
| 211 FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000; |
| 192 if (info->shared_info()->opt_count() > kMaxOptCount) { | 212 if (info->shared_info()->opt_count() > kMaxOptCount) { |
| 193 AbortAndDisable(info); | 213 AbortAndDisable(info); |
| 194 // True indicates the compilation pipeline is still going, not | 214 // True indicates the compilation pipeline is still going, not |
| 195 // necessarily that we optimized the code. | 215 // necessarily that we optimized the code. |
| 196 return true; | 216 return true; |
| 197 } | 217 } |
| 198 | 218 |
| 199 // Due to an encoding limit on LUnallocated operands in the Lithium | 219 // Due to an encoding limit on LUnallocated operands in the Lithium |
| 200 // language, we cannot optimize functions with too many formal parameters | 220 // language, we cannot optimize functions with too many formal parameters |
| 201 // or perform on-stack replacement for function with too many | 221 // or perform on-stack replacement for function with too many |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 // support. | 275 // support. |
| 256 ASSERT(FLAG_always_opt || info->shared_info()->code()->optimizable()); | 276 ASSERT(FLAG_always_opt || info->shared_info()->code()->optimizable()); |
| 257 ASSERT(info->shared_info()->has_deoptimization_support()); | 277 ASSERT(info->shared_info()->has_deoptimization_support()); |
| 258 | 278 |
| 259 if (FLAG_trace_hydrogen) { | 279 if (FLAG_trace_hydrogen) { |
| 260 PrintF("-----------------------------------------------------------\n"); | 280 PrintF("-----------------------------------------------------------\n"); |
| 261 PrintF("Compiling method %s using hydrogen\n", *name->ToCString()); | 281 PrintF("Compiling method %s using hydrogen\n", *name->ToCString()); |
| 262 HTracer::Instance()->TraceCompilation(info->function()); | 282 HTracer::Instance()->TraceCompilation(info->function()); |
| 263 } | 283 } |
| 264 | 284 |
| 265 TypeFeedbackOracle oracle(Handle<Code>(info->shared_info()->code())); | 285 TypeFeedbackOracle oracle( |
| 286 Handle<Code>(info->shared_info()->code()), |
| 287 Handle<Context>(info->closure()->context()->global_context())); |
| 266 HGraphBuilder builder(&oracle); | 288 HGraphBuilder builder(&oracle); |
| 267 HPhase phase(HPhase::kTotal); | 289 HPhase phase(HPhase::kTotal); |
| 268 HGraph* graph = builder.CreateGraph(info); | 290 HGraph* graph = builder.CreateGraph(info); |
| 291 if (Top::has_pending_exception()) { |
| 292 info->SetCode(Handle<Code>::null()); |
| 293 return false; |
| 294 } |
| 295 |
| 269 if (graph != NULL && FLAG_build_lithium) { | 296 if (graph != NULL && FLAG_build_lithium) { |
| 270 Handle<Code> code = graph->Compile(); | 297 Handle<Code> code = graph->Compile(); |
| 271 if (!code.is_null()) { | 298 if (!code.is_null()) { |
| 272 info->SetCode(code); | 299 info->SetCode(code); |
| 273 FinishOptimization(info->closure(), start); | 300 FinishOptimization(info->closure(), start); |
| 274 return true; | 301 return true; |
| 275 } | 302 } |
| 276 } | 303 } |
| 277 | 304 |
| 278 // Compilation with the Hydrogen compiler failed. Keep using the | 305 // Compilation with the Hydrogen compiler failed. Keep using the |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 } | 416 } |
| 390 | 417 |
| 391 ASSERT(!info->code().is_null()); | 418 ASSERT(!info->code().is_null()); |
| 392 if (script->name()->IsString()) { | 419 if (script->name()->IsString()) { |
| 393 PROFILE(CodeCreateEvent( | 420 PROFILE(CodeCreateEvent( |
| 394 info->is_eval() | 421 info->is_eval() |
| 395 ? Logger::EVAL_TAG | 422 ? Logger::EVAL_TAG |
| 396 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), | 423 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
| 397 *info->code(), | 424 *info->code(), |
| 398 String::cast(script->name()))); | 425 String::cast(script->name()))); |
| 399 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()), | 426 GDBJIT(AddCode(Handle<String>(String::cast(script->name())), |
| 400 info->code()->instruction_start(), | 427 script, |
| 401 info->code()->instruction_size())); | 428 info->code())); |
| 402 } else { | 429 } else { |
| 403 PROFILE(CodeCreateEvent( | 430 PROFILE(CodeCreateEvent( |
| 404 info->is_eval() | 431 info->is_eval() |
| 405 ? Logger::EVAL_TAG | 432 ? Logger::EVAL_TAG |
| 406 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), | 433 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
| 407 *info->code(), | 434 *info->code(), |
| 408 "")); | 435 "")); |
| 409 OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script", | 436 GDBJIT(AddCode(Handle<String>(), script, info->code())); |
| 410 info->code()->instruction_start(), | |
| 411 info->code()->instruction_size())); | |
| 412 } | 437 } |
| 413 | 438 |
| 414 // Allocate function. | 439 // Allocate function. |
| 415 Handle<SharedFunctionInfo> result = | 440 Handle<SharedFunctionInfo> result = |
| 416 Factory::NewSharedFunctionInfo( | 441 Factory::NewSharedFunctionInfo( |
| 417 lit->name(), | 442 lit->name(), |
| 418 lit->materialized_literal_count(), | 443 lit->materialized_literal_count(), |
| 419 info->code(), | 444 info->code(), |
| 420 SerializedScopeInfo::Create(info->scope())); | 445 SerializedScopeInfo::Create(info->scope())); |
| 421 | 446 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 } | 539 } |
| 515 } | 540 } |
| 516 | 541 |
| 517 if (result.is_null()) Top::ReportPendingMessages(); | 542 if (result.is_null()) Top::ReportPendingMessages(); |
| 518 return result; | 543 return result; |
| 519 } | 544 } |
| 520 | 545 |
| 521 | 546 |
| 522 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, | 547 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, |
| 523 Handle<Context> context, | 548 Handle<Context> context, |
| 524 bool is_global) { | 549 bool is_global, |
| 550 StrictModeFlag strict_mode) { |
| 525 int source_length = source->length(); | 551 int source_length = source->length(); |
| 526 Counters::total_eval_size.Increment(source_length); | 552 Counters::total_eval_size.Increment(source_length); |
| 527 Counters::total_compile_size.Increment(source_length); | 553 Counters::total_compile_size.Increment(source_length); |
| 528 | 554 |
| 529 // The VM is in the COMPILER state until exiting this function. | 555 // The VM is in the COMPILER state until exiting this function. |
| 530 VMState state(COMPILER); | 556 VMState state(COMPILER); |
| 531 | 557 |
| 532 // Do a lookup in the compilation cache; if the entry is not there, invoke | 558 // Do a lookup in the compilation cache; if the entry is not there, invoke |
| 533 // the compiler and add the result to the cache. | 559 // the compiler and add the result to the cache. |
| 534 Handle<SharedFunctionInfo> result; | 560 Handle<SharedFunctionInfo> result; |
| 535 result = CompilationCache::LookupEval(source, context, is_global); | 561 result = CompilationCache::LookupEval(source, |
| 562 context, |
| 563 is_global, |
| 564 strict_mode); |
| 536 | 565 |
| 537 if (result.is_null()) { | 566 if (result.is_null()) { |
| 538 // Create a script object describing the script to be compiled. | 567 // Create a script object describing the script to be compiled. |
| 539 Handle<Script> script = Factory::NewScript(source); | 568 Handle<Script> script = Factory::NewScript(source); |
| 540 CompilationInfo info(script); | 569 CompilationInfo info(script); |
| 541 info.MarkAsEval(); | 570 info.MarkAsEval(); |
| 542 if (is_global) info.MarkAsGlobal(); | 571 if (is_global) info.MarkAsGlobal(); |
| 572 if (strict_mode == kStrictMode) info.MarkAsStrict(); |
| 543 info.SetCallingContext(context); | 573 info.SetCallingContext(context); |
| 544 result = MakeFunctionInfo(&info); | 574 result = MakeFunctionInfo(&info); |
| 545 if (!result.is_null()) { | 575 if (!result.is_null()) { |
| 576 // If caller is strict mode, the result must be strict as well, |
| 577 // but not the other way around. Consider: |
| 578 // eval("'use strict'; ..."); |
| 579 ASSERT(strict_mode == kNonStrictMode || result->strict_mode()); |
| 546 CompilationCache::PutEval(source, context, is_global, result); | 580 CompilationCache::PutEval(source, context, is_global, result); |
| 547 } | 581 } |
| 548 } | 582 } |
| 549 | 583 |
| 550 return result; | 584 return result; |
| 551 } | 585 } |
| 552 | 586 |
| 553 | 587 |
| 554 bool Compiler::CompileLazy(CompilationInfo* info) { | 588 bool Compiler::CompileLazy(CompilationInfo* info) { |
| 555 CompilationZoneScope zone_scope(DELETE_ON_EXIT); | 589 CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
| 556 | 590 |
| 557 // The VM is in the COMPILER state until exiting this function. | 591 // The VM is in the COMPILER state until exiting this function. |
| 558 VMState state(COMPILER); | 592 VMState state(COMPILER); |
| 559 | 593 |
| 560 PostponeInterruptsScope postpone; | 594 PostponeInterruptsScope postpone; |
| 561 | 595 |
| 562 Handle<SharedFunctionInfo> shared = info->shared_info(); | 596 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 563 int compiled_size = shared->end_position() - shared->start_position(); | 597 int compiled_size = shared->end_position() - shared->start_position(); |
| 564 Counters::total_compile_size.Increment(compiled_size); | 598 Counters::total_compile_size.Increment(compiled_size); |
| 565 | 599 |
| 566 // Generate the AST for the lazily compiled function. | 600 // Generate the AST for the lazily compiled function. |
| 567 if (ParserApi::Parse(info)) { | 601 if (ParserApi::Parse(info)) { |
| 568 // Measure how long it takes to do the lazy compilation; only take the | 602 // Measure how long it takes to do the lazy compilation; only take the |
| 569 // rest of the function into account to avoid overlap with the lazy | 603 // rest of the function into account to avoid overlap with the lazy |
| 570 // parsing statistics. | 604 // parsing statistics. |
| 571 HistogramTimerScope timer(&Counters::compile_lazy); | 605 HistogramTimerScope timer(&Counters::compile_lazy); |
| 572 | 606 |
| 573 // Compile the code. | 607 // Compile the code. |
| 574 if (!MakeCode(info)) { | 608 if (!MakeCode(info)) { |
| 575 Top::StackOverflow(); | 609 if (!Top::has_pending_exception()) { |
| 610 Top::StackOverflow(); |
| 611 } |
| 576 } else { | 612 } else { |
| 577 ASSERT(!info->code().is_null()); | 613 ASSERT(!info->code().is_null()); |
| 578 Handle<Code> code = info->code(); | 614 Handle<Code> code = info->code(); |
| 579 Handle<JSFunction> function = info->closure(); | 615 Handle<JSFunction> function = info->closure(); |
| 580 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, | 616 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, |
| 581 Handle<String>(shared->DebugName()), | 617 Handle<String>(shared->DebugName()), |
| 582 shared->start_position(), | 618 shared->start_position(), |
| 583 info); | 619 info); |
| 584 | 620 |
| 585 if (info->IsOptimizing()) { | 621 if (info->IsOptimizing()) { |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 function_info->set_start_position(lit->start_position()); | 764 function_info->set_start_position(lit->start_position()); |
| 729 function_info->set_end_position(lit->end_position()); | 765 function_info->set_end_position(lit->end_position()); |
| 730 function_info->set_is_expression(lit->is_expression()); | 766 function_info->set_is_expression(lit->is_expression()); |
| 731 function_info->set_is_toplevel(is_toplevel); | 767 function_info->set_is_toplevel(is_toplevel); |
| 732 function_info->set_inferred_name(*lit->inferred_name()); | 768 function_info->set_inferred_name(*lit->inferred_name()); |
| 733 function_info->SetThisPropertyAssignmentsInfo( | 769 function_info->SetThisPropertyAssignmentsInfo( |
| 734 lit->has_only_simple_this_property_assignments(), | 770 lit->has_only_simple_this_property_assignments(), |
| 735 *lit->this_property_assignments()); | 771 *lit->this_property_assignments()); |
| 736 function_info->set_try_full_codegen(lit->try_full_codegen()); | 772 function_info->set_try_full_codegen(lit->try_full_codegen()); |
| 737 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); | 773 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); |
| 774 function_info->set_strict_mode(lit->strict_mode()); |
| 738 } | 775 } |
| 739 | 776 |
| 740 | 777 |
| 741 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, | 778 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, |
| 742 Handle<String> name, | 779 Handle<String> name, |
| 743 int start_position, | 780 int start_position, |
| 744 CompilationInfo* info) { | 781 CompilationInfo* info) { |
| 745 // Log the code generation. If source information is available include | 782 // Log the code generation. If source information is available include |
| 746 // script name and line number. Check explicitly whether logging is | 783 // script name and line number. Check explicitly whether logging is |
| 747 // enabled as finding the line number is not free. | 784 // enabled as finding the line number is not free. |
| 748 if (Logger::is_logging() || | 785 if (Logger::is_logging() || |
| 749 OProfileAgent::is_enabled() || | |
| 750 CpuProfiler::is_profiling()) { | 786 CpuProfiler::is_profiling()) { |
| 751 Handle<Script> script = info->script(); | 787 Handle<Script> script = info->script(); |
| 752 Handle<Code> code = info->code(); | 788 Handle<Code> code = info->code(); |
| 753 if (script->name()->IsString()) { | 789 if (script->name()->IsString()) { |
| 754 int line_num = GetScriptLineNumber(script, start_position) + 1; | 790 int line_num = GetScriptLineNumber(script, start_position) + 1; |
| 755 USE(line_num); | 791 USE(line_num); |
| 756 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), | 792 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), |
| 757 *code, | 793 *code, |
| 758 *name, | 794 *name, |
| 759 String::cast(script->name()), | 795 String::cast(script->name()), |
| 760 line_num)); | 796 line_num)); |
| 761 OPROFILE(CreateNativeCodeRegion(*name, | |
| 762 String::cast(script->name()), | |
| 763 line_num, | |
| 764 code->instruction_start(), | |
| 765 code->instruction_size())); | |
| 766 } else { | 797 } else { |
| 767 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), | 798 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), |
| 768 *code, | 799 *code, |
| 769 *name)); | 800 *name)); |
| 770 OPROFILE(CreateNativeCodeRegion(*name, | |
| 771 code->instruction_start(), | |
| 772 code->instruction_size())); | |
| 773 } | 801 } |
| 774 } | 802 } |
| 803 |
| 804 GDBJIT(AddCode(name, |
| 805 Handle<Script>(info->script()), |
| 806 Handle<Code>(info->code()))); |
| 775 } | 807 } |
| 776 | 808 |
| 777 } } // namespace v8::internal | 809 } } // namespace v8::internal |
| OLD | NEW |