| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 !scope_->HasTrivialOuterContext() && | 102 !scope_->HasTrivialOuterContext() && |
| 103 !scope_->outer_scope_calls_non_strict_eval() && | 103 !scope_->outer_scope_calls_non_strict_eval() && |
| 104 !scope_->inside_with(); | 104 !scope_->inside_with(); |
| 105 SetMode(is_optimizable_closure ? BASE : NONOPT); | 105 SetMode(is_optimizable_closure ? BASE : NONOPT); |
| 106 } | 106 } |
| 107 | 107 |
| 108 | 108 |
| 109 void CompilationInfo::AbortOptimization() { | 109 void CompilationInfo::AbortOptimization() { |
| 110 Handle<Code> code(shared_info()->code()); | 110 Handle<Code> code(shared_info()->code()); |
| 111 SetCode(code); | 111 SetCode(code); |
| 112 Isolate* isolate = code->GetIsolate(); | |
| 113 isolate->compilation_cache()->MarkForLazyOptimizing(closure()); | |
| 114 } | 112 } |
| 115 | 113 |
| 116 | 114 |
| 117 // Determine whether to use the full compiler for all code. If the flag | 115 // Determine whether to use the full compiler for all code. If the flag |
| 118 // --always-full-compiler is specified this is the case. For the virtual frame | 116 // --always-full-compiler is specified this is the case. For the virtual frame |
| 119 // based compiler the full compiler is also used if a debugger is connected, as | 117 // based compiler the full compiler is also used if a debugger is connected, as |
| 120 // the code from the full compiler supports mode precise break points. For the | 118 // the code from the full compiler supports mode precise break points. For the |
| 121 // crankshaft adaptive compiler debugging the optimized code is not possible at | 119 // crankshaft adaptive compiler debugging the optimized code is not possible at |
| 122 // all. However crankshaft support recompilation of functions, so in this case | 120 // all. However crankshaft support recompilation of functions, so in this case |
| 123 // the full compiler need not be be used if a debugger is attached, but only if | 121 // the full compiler need not be be used if a debugger is attached, but only if |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 return true; | 204 return true; |
| 207 } | 205 } |
| 208 | 206 |
| 209 // Due to an encoding limit on LUnallocated operands in the Lithium | 207 // Due to an encoding limit on LUnallocated operands in the Lithium |
| 210 // language, we cannot optimize functions with too many formal parameters | 208 // language, we cannot optimize functions with too many formal parameters |
| 211 // or perform on-stack replacement for function with too many | 209 // or perform on-stack replacement for function with too many |
| 212 // stack-allocated local variables. | 210 // stack-allocated local variables. |
| 213 // | 211 // |
| 214 // The encoding is as a signed value, with parameters and receiver using | 212 // The encoding is as a signed value, with parameters and receiver using |
| 215 // the negative indices and locals the non-negative ones. | 213 // the negative indices and locals the non-negative ones. |
| 216 const int limit = LUnallocated::kMaxFixedIndices / 2; | 214 const int parameter_limit = -LUnallocated::kMinFixedIndex; |
| 215 const int locals_limit = LUnallocated::kMaxFixedIndex; |
| 217 Scope* scope = info->scope(); | 216 Scope* scope = info->scope(); |
| 218 if ((scope->num_parameters() + 1) > limit || | 217 if ((scope->num_parameters() + 1) > parameter_limit || |
| 219 scope->num_stack_slots() > limit) { | 218 (info->osr_ast_id() != AstNode::kNoNumber && |
| 219 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) { |
| 220 info->AbortOptimization(); | 220 info->AbortOptimization(); |
| 221 Handle<JSFunction> closure = info->closure(); | 221 Handle<JSFunction> closure = info->closure(); |
| 222 info->shared_info()->DisableOptimization(*closure); | 222 info->shared_info()->DisableOptimization(*closure); |
| 223 // True indicates the compilation pipeline is still going, not | 223 // True indicates the compilation pipeline is still going, not |
| 224 // necessarily that we optimized the code. | 224 // necessarily that we optimized the code. |
| 225 return true; | 225 return true; |
| 226 } | 226 } |
| 227 | 227 |
| 228 // Take --hydrogen-filter into account. | 228 // Take --hydrogen-filter into account. |
| 229 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter); | 229 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 SerializedScopeInfo::Create(info->scope()); | 331 SerializedScopeInfo::Create(info->scope()); |
| 332 info->shared_info()->set_scope_info(*scope_info); | 332 info->shared_info()->set_scope_info(*scope_info); |
| 333 } | 333 } |
| 334 return succeeded; | 334 return succeeded; |
| 335 } | 335 } |
| 336 #endif | 336 #endif |
| 337 | 337 |
| 338 | 338 |
| 339 static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) { | 339 static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) { |
| 340 Isolate* isolate = info->isolate(); | 340 Isolate* isolate = info->isolate(); |
| 341 CompilationZoneScope zone_scope(isolate, DELETE_ON_EXIT); | 341 ZoneScope zone_scope(isolate, DELETE_ON_EXIT); |
| 342 PostponeInterruptsScope postpone(isolate); | 342 PostponeInterruptsScope postpone(isolate); |
| 343 | 343 |
| 344 ASSERT(!isolate->global_context().is_null()); | 344 ASSERT(!isolate->global_context().is_null()); |
| 345 Handle<Script> script = info->script(); | 345 Handle<Script> script = info->script(); |
| 346 script->set_context_data((*isolate->global_context())->data()); | 346 script->set_context_data((*isolate->global_context())->data()); |
| 347 | 347 |
| 348 #ifdef ENABLE_DEBUGGER_SUPPORT | 348 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 349 if (info->is_eval()) { | 349 if (info->is_eval()) { |
| 350 Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL; | 350 Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL; |
| 351 script->set_compilation_type(Smi::FromInt(compilation_type)); | 351 script->set_compilation_type(Smi::FromInt(compilation_type)); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 if (script->name()->IsString()) { | 404 if (script->name()->IsString()) { |
| 405 PROFILE(isolate, CodeCreateEvent( | 405 PROFILE(isolate, CodeCreateEvent( |
| 406 info->is_eval() | 406 info->is_eval() |
| 407 ? Logger::EVAL_TAG | 407 ? Logger::EVAL_TAG |
| 408 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), | 408 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
| 409 *info->code(), | 409 *info->code(), |
| 410 *result, | 410 *result, |
| 411 String::cast(script->name()))); | 411 String::cast(script->name()))); |
| 412 GDBJIT(AddCode(Handle<String>(String::cast(script->name())), | 412 GDBJIT(AddCode(Handle<String>(String::cast(script->name())), |
| 413 script, | 413 script, |
| 414 info->code())); | 414 info->code(), |
| 415 info)); |
| 415 } else { | 416 } else { |
| 416 PROFILE(isolate, CodeCreateEvent( | 417 PROFILE(isolate, CodeCreateEvent( |
| 417 info->is_eval() | 418 info->is_eval() |
| 418 ? Logger::EVAL_TAG | 419 ? Logger::EVAL_TAG |
| 419 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), | 420 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
| 420 *info->code(), | 421 *info->code(), |
| 421 *result, | 422 *result, |
| 422 isolate->heap()->empty_string())); | 423 isolate->heap()->empty_string())); |
| 423 GDBJIT(AddCode(Handle<String>(), script, info->code())); | 424 GDBJIT(AddCode(Handle<String>(), script, info->code(), info)); |
| 424 } | 425 } |
| 425 | 426 |
| 426 // Hint to the runtime system used when allocating space for initial | 427 // Hint to the runtime system used when allocating space for initial |
| 427 // property space by setting the expected number of properties for | 428 // property space by setting the expected number of properties for |
| 428 // the instances of the function. | 429 // the instances of the function. |
| 429 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count()); | 430 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count()); |
| 430 | 431 |
| 431 #ifdef ENABLE_DEBUGGER_SUPPORT | 432 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 432 // Notify debugger | 433 // Notify debugger |
| 433 isolate->debugger()->OnAfterCompile( | 434 isolate->debugger()->OnAfterCompile( |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 } | 502 } |
| 502 | 503 |
| 503 script->set_data(script_data.is_null() ? HEAP->undefined_value() | 504 script->set_data(script_data.is_null() ? HEAP->undefined_value() |
| 504 : *script_data); | 505 : *script_data); |
| 505 | 506 |
| 506 // Compile the function and add it to the cache. | 507 // Compile the function and add it to the cache. |
| 507 CompilationInfo info(script); | 508 CompilationInfo info(script); |
| 508 info.MarkAsGlobal(); | 509 info.MarkAsGlobal(); |
| 509 info.SetExtension(extension); | 510 info.SetExtension(extension); |
| 510 info.SetPreParseData(pre_data); | 511 info.SetPreParseData(pre_data); |
| 511 if (natives == NATIVES_CODE) info.MarkAsAllowingNativesSyntax(); | 512 if (natives == NATIVES_CODE) { |
| 513 info.MarkAsAllowingNativesSyntax(); |
| 514 info.MarkAsNative(); |
| 515 } |
| 512 result = MakeFunctionInfo(&info); | 516 result = MakeFunctionInfo(&info); |
| 513 if (extension == NULL && !result.is_null()) { | 517 if (extension == NULL && !result.is_null()) { |
| 514 compilation_cache->PutScript(source, result); | 518 compilation_cache->PutScript(source, result); |
| 515 } | 519 } |
| 516 | 520 |
| 517 // Get rid of the pre-parsing data (if necessary). | 521 // Get rid of the pre-parsing data (if necessary). |
| 518 if (input_pre_data == NULL && pre_data != NULL) { | 522 if (input_pre_data == NULL && pre_data != NULL) { |
| 519 delete pre_data; | 523 delete pre_data; |
| 520 } | 524 } |
| 521 } | 525 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 } | 569 } |
| 566 } | 570 } |
| 567 | 571 |
| 568 return result; | 572 return result; |
| 569 } | 573 } |
| 570 | 574 |
| 571 | 575 |
| 572 bool Compiler::CompileLazy(CompilationInfo* info) { | 576 bool Compiler::CompileLazy(CompilationInfo* info) { |
| 573 Isolate* isolate = info->isolate(); | 577 Isolate* isolate = info->isolate(); |
| 574 | 578 |
| 575 CompilationZoneScope zone_scope(isolate, DELETE_ON_EXIT); | 579 ZoneScope zone_scope(isolate, DELETE_ON_EXIT); |
| 576 | 580 |
| 577 // The VM is in the COMPILER state until exiting this function. | 581 // The VM is in the COMPILER state until exiting this function. |
| 578 VMState state(isolate, COMPILER); | 582 VMState state(isolate, COMPILER); |
| 579 | 583 |
| 580 PostponeInterruptsScope postpone(isolate); | 584 PostponeInterruptsScope postpone(isolate); |
| 581 | 585 |
| 582 Handle<SharedFunctionInfo> shared = info->shared_info(); | 586 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 583 int compiled_size = shared->end_position() - shared->start_position(); | 587 int compiled_size = shared->end_position() - shared->start_position(); |
| 584 isolate->counters()->total_compile_size()->Increment(compiled_size); | 588 isolate->counters()->total_compile_size()->Increment(compiled_size); |
| 585 | 589 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 606 Handle<Code> code = info->code(); | 610 Handle<Code> code = info->code(); |
| 607 // Set optimizable to false if this is disallowed by the shared | 611 // Set optimizable to false if this is disallowed by the shared |
| 608 // function info, e.g., we might have flushed the code and must | 612 // function info, e.g., we might have flushed the code and must |
| 609 // reset this bit when lazy compiling the code again. | 613 // reset this bit when lazy compiling the code again. |
| 610 if (shared->optimization_disabled()) code->set_optimizable(false); | 614 if (shared->optimization_disabled()) code->set_optimizable(false); |
| 611 | 615 |
| 612 Handle<JSFunction> function = info->closure(); | 616 Handle<JSFunction> function = info->closure(); |
| 613 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); | 617 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); |
| 614 | 618 |
| 615 if (info->IsOptimizing()) { | 619 if (info->IsOptimizing()) { |
| 620 ASSERT(shared->scope_info() != SerializedScopeInfo::Empty()); |
| 616 function->ReplaceCode(*code); | 621 function->ReplaceCode(*code); |
| 617 } else { | 622 } else { |
| 618 // Update the shared function info with the compiled code and the | 623 // Update the shared function info with the compiled code and the |
| 619 // scope info. Please note, that the order of the shared function | 624 // scope info. Please note, that the order of the shared function |
| 620 // info initialization is important since set_scope_info might | 625 // info initialization is important since set_scope_info might |
| 621 // trigger a GC, causing the ASSERT below to be invalid if the code | 626 // trigger a GC, causing the ASSERT below to be invalid if the code |
| 622 // was flushed. By settting the code object last we avoid this. | 627 // was flushed. By settting the code object last we avoid this. |
| 623 Handle<SerializedScopeInfo> scope_info = | 628 Handle<SerializedScopeInfo> scope_info = |
| 624 SerializedScopeInfo::Create(info->scope()); | 629 SerializedScopeInfo::Create(info->scope()); |
| 625 shared->set_scope_info(*scope_info); | 630 shared->set_scope_info(*scope_info); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 647 | 652 |
| 648 if (info->AllowOptimize() && !shared->optimization_disabled()) { | 653 if (info->AllowOptimize() && !shared->optimization_disabled()) { |
| 649 // If we're asked to always optimize, we compile the optimized | 654 // If we're asked to always optimize, we compile the optimized |
| 650 // version of the function right away - unless the debugger is | 655 // version of the function right away - unless the debugger is |
| 651 // active as it makes no sense to compile optimized code then. | 656 // active as it makes no sense to compile optimized code then. |
| 652 if (FLAG_always_opt && | 657 if (FLAG_always_opt && |
| 653 !Isolate::Current()->DebuggerHasBreakPoints()) { | 658 !Isolate::Current()->DebuggerHasBreakPoints()) { |
| 654 CompilationInfo optimized(function); | 659 CompilationInfo optimized(function); |
| 655 optimized.SetOptimizing(AstNode::kNoNumber); | 660 optimized.SetOptimizing(AstNode::kNoNumber); |
| 656 return CompileLazy(&optimized); | 661 return CompileLazy(&optimized); |
| 657 } else if (isolate->compilation_cache()->ShouldOptimizeEagerly( | |
| 658 function)) { | |
| 659 isolate->runtime_profiler()->OptimizeSoon(*function); | |
| 660 } | 662 } |
| 661 } | 663 } |
| 662 } | 664 } |
| 663 | 665 |
| 664 return true; | 666 return true; |
| 665 } | 667 } |
| 666 } | 668 } |
| 667 | 669 |
| 668 ASSERT(info->code().is_null()); | 670 ASSERT(info->code().is_null()); |
| 669 return false; | 671 return false; |
| 670 } | 672 } |
| 671 | 673 |
| 672 | 674 |
| 673 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, | 675 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, |
| 674 Handle<Script> script) { | 676 Handle<Script> script) { |
| 675 // Precondition: code has been parsed and scopes have been analyzed. | 677 // Precondition: code has been parsed and scopes have been analyzed. |
| 676 CompilationInfo info(script); | 678 CompilationInfo info(script); |
| 677 info.SetFunction(literal); | 679 info.SetFunction(literal); |
| 678 info.SetScope(literal->scope()); | 680 info.SetScope(literal->scope()); |
| 679 if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode(); | 681 if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode(); |
| 682 if (script->type()->value() == Script::TYPE_NATIVE) info.MarkAsNative(); |
| 680 | 683 |
| 681 LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal); | 684 LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal); |
| 682 // Determine if the function can be lazily compiled. This is necessary to | 685 // Determine if the function can be lazily compiled. This is necessary to |
| 683 // allow some of our builtin JS files to be lazily compiled. These | 686 // allow some of our builtin JS files to be lazily compiled. These |
| 684 // builtins cannot be handled lazily by the parser, since we have to know | 687 // builtins cannot be handled lazily by the parser, since we have to know |
| 685 // if a function uses the special natives syntax, which is something the | 688 // if a function uses the special natives syntax, which is something the |
| 686 // parser records. | 689 // parser records. |
| 687 bool allow_lazy = literal->AllowsLazyCompilation() && | 690 bool allow_lazy = literal->AllowsLazyCompilation() && |
| 688 !LiveEditFunctionTracker::IsActive(info.isolate()); | 691 !LiveEditFunctionTracker::IsActive(info.isolate()); |
| 689 | 692 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 function_info->set_start_position(lit->start_position()); | 738 function_info->set_start_position(lit->start_position()); |
| 736 function_info->set_end_position(lit->end_position()); | 739 function_info->set_end_position(lit->end_position()); |
| 737 function_info->set_is_expression(lit->is_expression()); | 740 function_info->set_is_expression(lit->is_expression()); |
| 738 function_info->set_is_toplevel(is_toplevel); | 741 function_info->set_is_toplevel(is_toplevel); |
| 739 function_info->set_inferred_name(*lit->inferred_name()); | 742 function_info->set_inferred_name(*lit->inferred_name()); |
| 740 function_info->SetThisPropertyAssignmentsInfo( | 743 function_info->SetThisPropertyAssignmentsInfo( |
| 741 lit->has_only_simple_this_property_assignments(), | 744 lit->has_only_simple_this_property_assignments(), |
| 742 *lit->this_property_assignments()); | 745 *lit->this_property_assignments()); |
| 743 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); | 746 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); |
| 744 function_info->set_strict_mode(lit->strict_mode()); | 747 function_info->set_strict_mode(lit->strict_mode()); |
| 748 function_info->set_uses_arguments(lit->scope()->arguments() != NULL); |
| 749 function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters()); |
| 745 } | 750 } |
| 746 | 751 |
| 747 | 752 |
| 748 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, | 753 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, |
| 749 CompilationInfo* info, | 754 CompilationInfo* info, |
| 750 Handle<SharedFunctionInfo> shared) { | 755 Handle<SharedFunctionInfo> shared) { |
| 751 // SharedFunctionInfo is passed separately, because if CompilationInfo | 756 // SharedFunctionInfo is passed separately, because if CompilationInfo |
| 752 // was created using Script object, it will not have it. | 757 // was created using Script object, it will not have it. |
| 753 | 758 |
| 754 // Log the code generation. If source information is available include | 759 // Log the code generation. If source information is available include |
| (...skipping 18 matching lines...) Expand all Loading... |
| 773 PROFILE(info->isolate(), | 778 PROFILE(info->isolate(), |
| 774 CodeCreateEvent(Logger::ToNativeByScript(tag, *script), | 779 CodeCreateEvent(Logger::ToNativeByScript(tag, *script), |
| 775 *code, | 780 *code, |
| 776 *shared, | 781 *shared, |
| 777 shared->DebugName())); | 782 shared->DebugName())); |
| 778 } | 783 } |
| 779 } | 784 } |
| 780 | 785 |
| 781 GDBJIT(AddCode(Handle<String>(shared->DebugName()), | 786 GDBJIT(AddCode(Handle<String>(shared->DebugName()), |
| 782 Handle<Script>(info->script()), | 787 Handle<Script>(info->script()), |
| 783 Handle<Code>(info->code()))); | 788 Handle<Code>(info->code()), |
| 789 info)); |
| 784 } | 790 } |
| 785 | 791 |
| 786 } } // namespace v8::internal | 792 } } // namespace v8::internal |
| OLD | NEW |