| 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/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
| 9 #include "src/debug.h" | 9 #include "src/debug.h" |
| 10 #include "src/full-codegen.h" | 10 #include "src/full-codegen.h" |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 const int kInitialBufferSize = 4 * KB; | 301 const int kInitialBufferSize = 4 * KB; |
| 302 MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize); | 302 MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize); |
| 303 if (info->will_serialize()) masm.enable_serializer(); | 303 if (info->will_serialize()) masm.enable_serializer(); |
| 304 | 304 |
| 305 LOG_CODE_EVENT(isolate, | 305 LOG_CODE_EVENT(isolate, |
| 306 CodeStartLinePosInfoRecordEvent(masm.positions_recorder())); | 306 CodeStartLinePosInfoRecordEvent(masm.positions_recorder())); |
| 307 | 307 |
| 308 FullCodeGenerator cgen(&masm, info); | 308 FullCodeGenerator cgen(&masm, info); |
| 309 cgen.Generate(); | 309 cgen.Generate(); |
| 310 if (cgen.HasStackOverflow()) { | 310 if (cgen.HasStackOverflow()) { |
| 311 ASSERT(!isolate->has_pending_exception()); | 311 DCHECK(!isolate->has_pending_exception()); |
| 312 return false; | 312 return false; |
| 313 } | 313 } |
| 314 unsigned table_offset = cgen.EmitBackEdgeTable(); | 314 unsigned table_offset = cgen.EmitBackEdgeTable(); |
| 315 | 315 |
| 316 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); | 316 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); |
| 317 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); | 317 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); |
| 318 code->set_optimizable(info->IsOptimizable() && | 318 code->set_optimizable(info->IsOptimizable() && |
| 319 !info->function()->dont_optimize() && | 319 !info->function()->dont_optimize() && |
| 320 info->function()->scope()->AllowsLazyCompilation()); | 320 info->function()->scope()->AllowsLazyCompilation()); |
| 321 cgen.PopulateDeoptimizationData(code); | 321 cgen.PopulateDeoptimizationData(code); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 if (!vector->get(slot)->IsAllocationSite()) { | 356 if (!vector->get(slot)->IsAllocationSite()) { |
| 357 Handle<AllocationSite> allocation_site = | 357 Handle<AllocationSite> allocation_site = |
| 358 isolate()->factory()->NewAllocationSite(); | 358 isolate()->factory()->NewAllocationSite(); |
| 359 vector->set(slot, *allocation_site); | 359 vector->set(slot, *allocation_site); |
| 360 } | 360 } |
| 361 } | 361 } |
| 362 | 362 |
| 363 | 363 |
| 364 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { | 364 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { |
| 365 // Fill in the deoptimization information. | 365 // Fill in the deoptimization information. |
| 366 ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty()); | 366 DCHECK(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty()); |
| 367 if (!info_->HasDeoptimizationSupport()) return; | 367 if (!info_->HasDeoptimizationSupport()) return; |
| 368 int length = bailout_entries_.length(); | 368 int length = bailout_entries_.length(); |
| 369 Handle<DeoptimizationOutputData> data = | 369 Handle<DeoptimizationOutputData> data = |
| 370 DeoptimizationOutputData::New(isolate(), length, TENURED); | 370 DeoptimizationOutputData::New(isolate(), length, TENURED); |
| 371 for (int i = 0; i < length; i++) { | 371 for (int i = 0; i < length; i++) { |
| 372 data->SetAstId(i, bailout_entries_[i].id); | 372 data->SetAstId(i, bailout_entries_[i].id); |
| 373 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state)); | 373 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state)); |
| 374 } | 374 } |
| 375 code->set_deoptimization_data(*data); | 375 code->set_deoptimization_data(*data); |
| 376 } | 376 } |
| 377 | 377 |
| 378 | 378 |
| 379 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { | 379 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { |
| 380 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); | 380 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); |
| 381 info->set_ic_total_count(ic_total_count_); | 381 info->set_ic_total_count(ic_total_count_); |
| 382 ASSERT(!isolate()->heap()->InNewSpace(*info)); | 382 DCHECK(!isolate()->heap()->InNewSpace(*info)); |
| 383 code->set_type_feedback_info(*info); | 383 code->set_type_feedback_info(*info); |
| 384 } | 384 } |
| 385 | 385 |
| 386 | 386 |
| 387 void FullCodeGenerator::Initialize() { | 387 void FullCodeGenerator::Initialize() { |
| 388 InitializeAstVisitor(info_->zone()); | 388 InitializeAstVisitor(info_->zone()); |
| 389 // The generation of debug code must match between the snapshot code and the | 389 // The generation of debug code must match between the snapshot code and the |
| 390 // code that is generated later. This is assumed by the debugger when it is | 390 // code that is generated later. This is assumed by the debugger when it is |
| 391 // calculating PC offsets after generating a debug version of code. Therefore | 391 // calculating PC offsets after generating a debug version of code. Therefore |
| 392 // we disable the production of debug code in the full compiler if we are | 392 // we disable the production of debug code in the full compiler if we are |
| (...skipping 29 matching lines...) Expand all Loading... |
| 422 // We record the offset of the function return so we can rebuild the frame | 422 // We record the offset of the function return so we can rebuild the frame |
| 423 // if the function was inlined, i.e., this is the return address in the | 423 // if the function was inlined, i.e., this is the return address in the |
| 424 // inlined function's frame. | 424 // inlined function's frame. |
| 425 // | 425 // |
| 426 // The state is ignored. We defensively set it to TOS_REG, which is the | 426 // The state is ignored. We defensively set it to TOS_REG, which is the |
| 427 // real state of the unoptimized code at the return site. | 427 // real state of the unoptimized code at the return site. |
| 428 PrepareForBailoutForId(call->ReturnId(), TOS_REG); | 428 PrepareForBailoutForId(call->ReturnId(), TOS_REG); |
| 429 #ifdef DEBUG | 429 #ifdef DEBUG |
| 430 // In debug builds, mark the return so we can verify that this function | 430 // In debug builds, mark the return so we can verify that this function |
| 431 // was called. | 431 // was called. |
| 432 ASSERT(!call->return_is_recorded_); | 432 DCHECK(!call->return_is_recorded_); |
| 433 call->return_is_recorded_ = true; | 433 call->return_is_recorded_ = true; |
| 434 #endif | 434 #endif |
| 435 } | 435 } |
| 436 | 436 |
| 437 | 437 |
| 438 void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) { | 438 void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) { |
| 439 // There's no need to prepare this code for bailouts from already optimized | 439 // There's no need to prepare this code for bailouts from already optimized |
| 440 // code or code that can't be optimized. | 440 // code or code that can't be optimized. |
| 441 if (!info_->HasDeoptimizationSupport()) return; | 441 if (!info_->HasDeoptimizationSupport()) return; |
| 442 unsigned pc_and_state = | 442 unsigned pc_and_state = |
| 443 StateField::encode(state) | PcField::encode(masm_->pc_offset()); | 443 StateField::encode(state) | PcField::encode(masm_->pc_offset()); |
| 444 ASSERT(Smi::IsValid(pc_and_state)); | 444 DCHECK(Smi::IsValid(pc_and_state)); |
| 445 #ifdef DEBUG | 445 #ifdef DEBUG |
| 446 for (int i = 0; i < bailout_entries_.length(); ++i) { | 446 for (int i = 0; i < bailout_entries_.length(); ++i) { |
| 447 ASSERT(bailout_entries_[i].id != id); | 447 DCHECK(bailout_entries_[i].id != id); |
| 448 } | 448 } |
| 449 #endif | 449 #endif |
| 450 BailoutEntry entry = { id, pc_and_state }; | 450 BailoutEntry entry = { id, pc_and_state }; |
| 451 bailout_entries_.Add(entry, zone()); | 451 bailout_entries_.Add(entry, zone()); |
| 452 } | 452 } |
| 453 | 453 |
| 454 | 454 |
| 455 void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) { | 455 void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) { |
| 456 // The pc offset does not need to be encoded and packed together with a state. | 456 // The pc offset does not need to be encoded and packed together with a state. |
| 457 ASSERT(masm_->pc_offset() > 0); | 457 DCHECK(masm_->pc_offset() > 0); |
| 458 ASSERT(loop_depth() > 0); | 458 DCHECK(loop_depth() > 0); |
| 459 uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker); | 459 uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker); |
| 460 BackEdgeEntry entry = | 460 BackEdgeEntry entry = |
| 461 { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth }; | 461 { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth }; |
| 462 back_edges_.Add(entry, zone()); | 462 back_edges_.Add(entry, zone()); |
| 463 } | 463 } |
| 464 | 464 |
| 465 | 465 |
| 466 bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) { | 466 bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) { |
| 467 // Inline smi case inside loops, but not division and modulo which | 467 // Inline smi case inside loops, but not division and modulo which |
| 468 // are too complicated and take up too much space. | 468 // are too complicated and take up too much space. |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 | 564 |
| 565 void FullCodeGenerator::DoTest(const TestContext* context) { | 565 void FullCodeGenerator::DoTest(const TestContext* context) { |
| 566 DoTest(context->condition(), | 566 DoTest(context->condition(), |
| 567 context->true_label(), | 567 context->true_label(), |
| 568 context->false_label(), | 568 context->false_label(), |
| 569 context->fall_through()); | 569 context->fall_through()); |
| 570 } | 570 } |
| 571 | 571 |
| 572 | 572 |
| 573 void FullCodeGenerator::AllocateModules(ZoneList<Declaration*>* declarations) { | 573 void FullCodeGenerator::AllocateModules(ZoneList<Declaration*>* declarations) { |
| 574 ASSERT(scope_->is_global_scope()); | 574 DCHECK(scope_->is_global_scope()); |
| 575 | 575 |
| 576 for (int i = 0; i < declarations->length(); i++) { | 576 for (int i = 0; i < declarations->length(); i++) { |
| 577 ModuleDeclaration* declaration = declarations->at(i)->AsModuleDeclaration(); | 577 ModuleDeclaration* declaration = declarations->at(i)->AsModuleDeclaration(); |
| 578 if (declaration != NULL) { | 578 if (declaration != NULL) { |
| 579 ModuleLiteral* module = declaration->module()->AsModuleLiteral(); | 579 ModuleLiteral* module = declaration->module()->AsModuleLiteral(); |
| 580 if (module != NULL) { | 580 if (module != NULL) { |
| 581 Comment cmnt(masm_, "[ Link nested modules"); | 581 Comment cmnt(masm_, "[ Link nested modules"); |
| 582 Scope* scope = module->body()->scope(); | 582 Scope* scope = module->body()->scope(); |
| 583 Interface* interface = scope->interface(); | 583 Interface* interface = scope->interface(); |
| 584 ASSERT(interface->IsModule() && interface->IsFrozen()); | 584 DCHECK(interface->IsModule() && interface->IsFrozen()); |
| 585 | 585 |
| 586 interface->Allocate(scope->module_var()->index()); | 586 interface->Allocate(scope->module_var()->index()); |
| 587 | 587 |
| 588 // Set up module context. | 588 // Set up module context. |
| 589 ASSERT(scope->interface()->Index() >= 0); | 589 DCHECK(scope->interface()->Index() >= 0); |
| 590 __ Push(Smi::FromInt(scope->interface()->Index())); | 590 __ Push(Smi::FromInt(scope->interface()->Index())); |
| 591 __ Push(scope->GetScopeInfo()); | 591 __ Push(scope->GetScopeInfo()); |
| 592 __ CallRuntime(Runtime::kPushModuleContext, 2); | 592 __ CallRuntime(Runtime::kPushModuleContext, 2); |
| 593 StoreToFrameField(StandardFrameConstants::kContextOffset, | 593 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 594 context_register()); | 594 context_register()); |
| 595 | 595 |
| 596 AllocateModules(scope->declarations()); | 596 AllocateModules(scope->declarations()); |
| 597 | 597 |
| 598 // Pop module context. | 598 // Pop module context. |
| 599 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 599 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 Handle<FixedArray> saved_modules = modules_; | 671 Handle<FixedArray> saved_modules = modules_; |
| 672 int saved_module_index = module_index_; | 672 int saved_module_index = module_index_; |
| 673 ZoneList<Handle<Object> >* saved_globals = globals_; | 673 ZoneList<Handle<Object> >* saved_globals = globals_; |
| 674 ZoneList<Handle<Object> > inner_globals(10, zone()); | 674 ZoneList<Handle<Object> > inner_globals(10, zone()); |
| 675 globals_ = &inner_globals; | 675 globals_ = &inner_globals; |
| 676 | 676 |
| 677 if (scope_->num_modules() != 0) { | 677 if (scope_->num_modules() != 0) { |
| 678 // This is a scope hosting modules. Allocate a descriptor array to pass | 678 // This is a scope hosting modules. Allocate a descriptor array to pass |
| 679 // to the runtime for initialization. | 679 // to the runtime for initialization. |
| 680 Comment cmnt(masm_, "[ Allocate modules"); | 680 Comment cmnt(masm_, "[ Allocate modules"); |
| 681 ASSERT(scope_->is_global_scope()); | 681 DCHECK(scope_->is_global_scope()); |
| 682 modules_ = | 682 modules_ = |
| 683 isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED); | 683 isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED); |
| 684 module_index_ = 0; | 684 module_index_ = 0; |
| 685 | 685 |
| 686 // Generate code for allocating all modules, including nested ones. | 686 // Generate code for allocating all modules, including nested ones. |
| 687 // The allocated contexts are stored in internal variables in this scope. | 687 // The allocated contexts are stored in internal variables in this scope. |
| 688 AllocateModules(declarations); | 688 AllocateModules(declarations); |
| 689 } | 689 } |
| 690 | 690 |
| 691 AstVisitor::VisitDeclarations(declarations); | 691 AstVisitor::VisitDeclarations(declarations); |
| 692 | 692 |
| 693 if (scope_->num_modules() != 0) { | 693 if (scope_->num_modules() != 0) { |
| 694 // Initialize modules from descriptor array. | 694 // Initialize modules from descriptor array. |
| 695 ASSERT(module_index_ == modules_->length()); | 695 DCHECK(module_index_ == modules_->length()); |
| 696 DeclareModules(modules_); | 696 DeclareModules(modules_); |
| 697 modules_ = saved_modules; | 697 modules_ = saved_modules; |
| 698 module_index_ = saved_module_index; | 698 module_index_ = saved_module_index; |
| 699 } | 699 } |
| 700 | 700 |
| 701 if (!globals_->is_empty()) { | 701 if (!globals_->is_empty()) { |
| 702 // Invoke the platform-dependent code generator to do the actual | 702 // Invoke the platform-dependent code generator to do the actual |
| 703 // declaration of the global functions and variables. | 703 // declaration of the global functions and variables. |
| 704 Handle<FixedArray> array = | 704 Handle<FixedArray> array = |
| 705 isolate()->factory()->NewFixedArray(globals_->length(), TENURED); | 705 isolate()->factory()->NewFixedArray(globals_->length(), TENURED); |
| 706 for (int i = 0; i < globals_->length(); ++i) | 706 for (int i = 0; i < globals_->length(); ++i) |
| 707 array->set(i, *globals_->at(i)); | 707 array->set(i, *globals_->at(i)); |
| 708 DeclareGlobals(array); | 708 DeclareGlobals(array); |
| 709 } | 709 } |
| 710 | 710 |
| 711 globals_ = saved_globals; | 711 globals_ = saved_globals; |
| 712 } | 712 } |
| 713 | 713 |
| 714 | 714 |
| 715 void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) { | 715 void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) { |
| 716 Block* block = module->body(); | 716 Block* block = module->body(); |
| 717 Scope* saved_scope = scope(); | 717 Scope* saved_scope = scope(); |
| 718 scope_ = block->scope(); | 718 scope_ = block->scope(); |
| 719 Interface* interface = scope_->interface(); | 719 Interface* interface = scope_->interface(); |
| 720 | 720 |
| 721 Comment cmnt(masm_, "[ ModuleLiteral"); | 721 Comment cmnt(masm_, "[ ModuleLiteral"); |
| 722 SetStatementPosition(block); | 722 SetStatementPosition(block); |
| 723 | 723 |
| 724 ASSERT(!modules_.is_null()); | 724 DCHECK(!modules_.is_null()); |
| 725 ASSERT(module_index_ < modules_->length()); | 725 DCHECK(module_index_ < modules_->length()); |
| 726 int index = module_index_++; | 726 int index = module_index_++; |
| 727 | 727 |
| 728 // Set up module context. | 728 // Set up module context. |
| 729 ASSERT(interface->Index() >= 0); | 729 DCHECK(interface->Index() >= 0); |
| 730 __ Push(Smi::FromInt(interface->Index())); | 730 __ Push(Smi::FromInt(interface->Index())); |
| 731 __ Push(Smi::FromInt(0)); | 731 __ Push(Smi::FromInt(0)); |
| 732 __ CallRuntime(Runtime::kPushModuleContext, 2); | 732 __ CallRuntime(Runtime::kPushModuleContext, 2); |
| 733 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 733 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 734 | 734 |
| 735 { | 735 { |
| 736 Comment cmnt(masm_, "[ Declarations"); | 736 Comment cmnt(masm_, "[ Declarations"); |
| 737 VisitDeclarations(scope_->declarations()); | 737 VisitDeclarations(scope_->declarations()); |
| 738 } | 738 } |
| 739 | 739 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 760 // Nothing to do. | 760 // Nothing to do. |
| 761 // The instance object is resolved statically through the module's interface. | 761 // The instance object is resolved statically through the module's interface. |
| 762 } | 762 } |
| 763 | 763 |
| 764 | 764 |
| 765 void FullCodeGenerator::VisitModuleUrl(ModuleUrl* module) { | 765 void FullCodeGenerator::VisitModuleUrl(ModuleUrl* module) { |
| 766 // TODO(rossberg): dummy allocation for now. | 766 // TODO(rossberg): dummy allocation for now. |
| 767 Scope* scope = module->body()->scope(); | 767 Scope* scope = module->body()->scope(); |
| 768 Interface* interface = scope_->interface(); | 768 Interface* interface = scope_->interface(); |
| 769 | 769 |
| 770 ASSERT(interface->IsModule() && interface->IsFrozen()); | 770 DCHECK(interface->IsModule() && interface->IsFrozen()); |
| 771 ASSERT(!modules_.is_null()); | 771 DCHECK(!modules_.is_null()); |
| 772 ASSERT(module_index_ < modules_->length()); | 772 DCHECK(module_index_ < modules_->length()); |
| 773 interface->Allocate(scope->module_var()->index()); | 773 interface->Allocate(scope->module_var()->index()); |
| 774 int index = module_index_++; | 774 int index = module_index_++; |
| 775 | 775 |
| 776 Handle<ModuleInfo> description = | 776 Handle<ModuleInfo> description = |
| 777 ModuleInfo::Create(isolate(), interface, scope_); | 777 ModuleInfo::Create(isolate(), interface, scope_); |
| 778 modules_->set(index, *description); | 778 modules_->set(index, *description); |
| 779 } | 779 } |
| 780 | 780 |
| 781 | 781 |
| 782 int FullCodeGenerator::DeclareGlobalsFlags() { | 782 int FullCodeGenerator::DeclareGlobalsFlags() { |
| 783 ASSERT(DeclareGlobalsStrictMode::is_valid(strict_mode())); | 783 DCHECK(DeclareGlobalsStrictMode::is_valid(strict_mode())); |
| 784 return DeclareGlobalsEvalFlag::encode(is_eval()) | | 784 return DeclareGlobalsEvalFlag::encode(is_eval()) | |
| 785 DeclareGlobalsNativeFlag::encode(is_native()) | | 785 DeclareGlobalsNativeFlag::encode(is_native()) | |
| 786 DeclareGlobalsStrictMode::encode(strict_mode()); | 786 DeclareGlobalsStrictMode::encode(strict_mode()); |
| 787 } | 787 } |
| 788 | 788 |
| 789 | 789 |
| 790 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { | 790 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { |
| 791 CodeGenerator::RecordPositions(masm_, fun->start_position()); | 791 CodeGenerator::RecordPositions(masm_, fun->start_position()); |
| 792 } | 792 } |
| 793 | 793 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 FullCodeGenerator::kInlineFunctionGenerators[] = { | 861 FullCodeGenerator::kInlineFunctionGenerators[] = { |
| 862 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 862 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 863 }; | 863 }; |
| 864 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 864 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
| 865 | 865 |
| 866 | 866 |
| 867 FullCodeGenerator::InlineFunctionGenerator | 867 FullCodeGenerator::InlineFunctionGenerator |
| 868 FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) { | 868 FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) { |
| 869 int lookup_index = | 869 int lookup_index = |
| 870 static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction); | 870 static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction); |
| 871 ASSERT(lookup_index >= 0); | 871 DCHECK(lookup_index >= 0); |
| 872 ASSERT(static_cast<size_t>(lookup_index) < | 872 DCHECK(static_cast<size_t>(lookup_index) < |
| 873 ARRAY_SIZE(kInlineFunctionGenerators)); | 873 ARRAY_SIZE(kInlineFunctionGenerators)); |
| 874 return kInlineFunctionGenerators[lookup_index]; | 874 return kInlineFunctionGenerators[lookup_index]; |
| 875 } | 875 } |
| 876 | 876 |
| 877 | 877 |
| 878 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { | 878 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { |
| 879 const Runtime::Function* function = expr->function(); | 879 const Runtime::Function* function = expr->function(); |
| 880 ASSERT(function != NULL); | 880 DCHECK(function != NULL); |
| 881 ASSERT(function->intrinsic_type == Runtime::INLINE); | 881 DCHECK(function->intrinsic_type == Runtime::INLINE); |
| 882 InlineFunctionGenerator generator = | 882 InlineFunctionGenerator generator = |
| 883 FindInlineFunctionGenerator(function->function_id); | 883 FindInlineFunctionGenerator(function->function_id); |
| 884 ((*this).*(generator))(expr); | 884 ((*this).*(generator))(expr); |
| 885 } | 885 } |
| 886 | 886 |
| 887 | 887 |
| 888 void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) { | 888 void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) { |
| 889 ZoneList<Expression*>* args = expr->arguments(); | 889 ZoneList<Expression*>* args = expr->arguments(); |
| 890 ASSERT(args->length() == 2); | 890 DCHECK(args->length() == 2); |
| 891 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT); | 891 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT); |
| 892 } | 892 } |
| 893 | 893 |
| 894 | 894 |
| 895 void FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) { | 895 void FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) { |
| 896 ZoneList<Expression*>* args = expr->arguments(); | 896 ZoneList<Expression*>* args = expr->arguments(); |
| 897 ASSERT(args->length() == 2); | 897 DCHECK(args->length() == 2); |
| 898 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::THROW); | 898 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::THROW); |
| 899 } | 899 } |
| 900 | 900 |
| 901 | 901 |
| 902 void FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) { | 902 void FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) { |
| 903 context()->Plug(handle(Smi::FromInt(0), isolate())); | 903 context()->Plug(handle(Smi::FromInt(0), isolate())); |
| 904 } | 904 } |
| 905 | 905 |
| 906 | 906 |
| 907 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 907 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 if (is_logical_and) { | 985 if (is_logical_and) { |
| 986 DoTest(left, &discard, &done, &discard); | 986 DoTest(left, &discard, &done, &discard); |
| 987 } else { | 987 } else { |
| 988 DoTest(left, &done, &discard, &discard); | 988 DoTest(left, &done, &discard, &discard); |
| 989 } | 989 } |
| 990 __ bind(&discard); | 990 __ bind(&discard); |
| 991 __ Drop(1); | 991 __ Drop(1); |
| 992 PrepareForBailoutForId(right_id, NO_REGISTERS); | 992 PrepareForBailoutForId(right_id, NO_REGISTERS); |
| 993 | 993 |
| 994 } else { | 994 } else { |
| 995 ASSERT(context()->IsEffect()); | 995 DCHECK(context()->IsEffect()); |
| 996 Label eval_right; | 996 Label eval_right; |
| 997 if (is_logical_and) { | 997 if (is_logical_and) { |
| 998 VisitForControl(left, &eval_right, &done, &eval_right); | 998 VisitForControl(left, &eval_right, &done, &eval_right); |
| 999 } else { | 999 } else { |
| 1000 VisitForControl(left, &done, &eval_right, &eval_right); | 1000 VisitForControl(left, &done, &eval_right, &eval_right); |
| 1001 } | 1001 } |
| 1002 PrepareForBailoutForId(right_id, NO_REGISTERS); | 1002 PrepareForBailoutForId(right_id, NO_REGISTERS); |
| 1003 __ bind(&eval_right); | 1003 __ bind(&eval_right); |
| 1004 } | 1004 } |
| 1005 | 1005 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1034 Comment cmnt(masm_, "[ Block"); | 1034 Comment cmnt(masm_, "[ Block"); |
| 1035 NestedBlock nested_block(this, stmt); | 1035 NestedBlock nested_block(this, stmt); |
| 1036 SetStatementPosition(stmt); | 1036 SetStatementPosition(stmt); |
| 1037 | 1037 |
| 1038 Scope* saved_scope = scope(); | 1038 Scope* saved_scope = scope(); |
| 1039 // Push a block context when entering a block with block scoped variables. | 1039 // Push a block context when entering a block with block scoped variables. |
| 1040 if (stmt->scope() == NULL) { | 1040 if (stmt->scope() == NULL) { |
| 1041 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 1041 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 1042 } else { | 1042 } else { |
| 1043 scope_ = stmt->scope(); | 1043 scope_ = stmt->scope(); |
| 1044 ASSERT(!scope_->is_module_scope()); | 1044 DCHECK(!scope_->is_module_scope()); |
| 1045 { Comment cmnt(masm_, "[ Extend block context"); | 1045 { Comment cmnt(masm_, "[ Extend block context"); |
| 1046 __ Push(scope_->GetScopeInfo()); | 1046 __ Push(scope_->GetScopeInfo()); |
| 1047 PushFunctionArgumentForContextAllocation(); | 1047 PushFunctionArgumentForContextAllocation(); |
| 1048 __ CallRuntime(Runtime::kPushBlockContext, 2); | 1048 __ CallRuntime(Runtime::kPushBlockContext, 2); |
| 1049 | 1049 |
| 1050 // Replace the context stored in the frame. | 1050 // Replace the context stored in the frame. |
| 1051 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1051 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1052 context_register()); | 1052 context_register()); |
| 1053 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 1053 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 1054 } | 1054 } |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1367 __ Push(stmt->variable()->name()); | 1367 __ Push(stmt->variable()->name()); |
| 1368 __ Push(result_register()); | 1368 __ Push(result_register()); |
| 1369 PushFunctionArgumentForContextAllocation(); | 1369 PushFunctionArgumentForContextAllocation(); |
| 1370 __ CallRuntime(Runtime::kPushCatchContext, 3); | 1370 __ CallRuntime(Runtime::kPushCatchContext, 3); |
| 1371 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1371 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1372 context_register()); | 1372 context_register()); |
| 1373 } | 1373 } |
| 1374 | 1374 |
| 1375 Scope* saved_scope = scope(); | 1375 Scope* saved_scope = scope(); |
| 1376 scope_ = stmt->scope(); | 1376 scope_ = stmt->scope(); |
| 1377 ASSERT(scope_->declarations()->is_empty()); | 1377 DCHECK(scope_->declarations()->is_empty()); |
| 1378 { WithOrCatch catch_body(this); | 1378 { WithOrCatch catch_body(this); |
| 1379 Visit(stmt->catch_block()); | 1379 Visit(stmt->catch_block()); |
| 1380 } | 1380 } |
| 1381 // Restore the context. | 1381 // Restore the context. |
| 1382 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1382 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 1383 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 1383 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 1384 scope_ = saved_scope; | 1384 scope_ = saved_scope; |
| 1385 __ jmp(&exit); | 1385 __ jmp(&exit); |
| 1386 | 1386 |
| 1387 // Try block code. Sets up the exception handler chain. | 1387 // Try block code. Sets up the exception handler chain. |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 | 1523 |
| 1524 void FullCodeGenerator::VisitNativeFunctionLiteral( | 1524 void FullCodeGenerator::VisitNativeFunctionLiteral( |
| 1525 NativeFunctionLiteral* expr) { | 1525 NativeFunctionLiteral* expr) { |
| 1526 Comment cmnt(masm_, "[ NativeFunctionLiteral"); | 1526 Comment cmnt(masm_, "[ NativeFunctionLiteral"); |
| 1527 | 1527 |
| 1528 // Compute the function template for the native function. | 1528 // Compute the function template for the native function. |
| 1529 Handle<String> name = expr->name(); | 1529 Handle<String> name = expr->name(); |
| 1530 v8::Handle<v8::FunctionTemplate> fun_template = | 1530 v8::Handle<v8::FunctionTemplate> fun_template = |
| 1531 expr->extension()->GetNativeFunctionTemplate( | 1531 expr->extension()->GetNativeFunctionTemplate( |
| 1532 reinterpret_cast<v8::Isolate*>(isolate()), v8::Utils::ToLocal(name)); | 1532 reinterpret_cast<v8::Isolate*>(isolate()), v8::Utils::ToLocal(name)); |
| 1533 ASSERT(!fun_template.IsEmpty()); | 1533 DCHECK(!fun_template.IsEmpty()); |
| 1534 | 1534 |
| 1535 // Instantiate the function and create a shared function info from it. | 1535 // Instantiate the function and create a shared function info from it. |
| 1536 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction()); | 1536 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction()); |
| 1537 const int literals = fun->NumberOfLiterals(); | 1537 const int literals = fun->NumberOfLiterals(); |
| 1538 Handle<Code> code = Handle<Code>(fun->shared()->code()); | 1538 Handle<Code> code = Handle<Code>(fun->shared()->code()); |
| 1539 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); | 1539 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); |
| 1540 bool is_generator = false; | 1540 bool is_generator = false; |
| 1541 bool is_arrow = false; | 1541 bool is_arrow = false; |
| 1542 Handle<SharedFunctionInfo> shared = | 1542 Handle<SharedFunctionInfo> shared = |
| 1543 isolate()->factory()->NewSharedFunctionInfo( | 1543 isolate()->factory()->NewSharedFunctionInfo( |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1602 | 1602 |
| 1603 // Increment loop nesting level by one and iterate over the back edge table | 1603 // Increment loop nesting level by one and iterate over the back edge table |
| 1604 // to find the matching loops to patch the interrupt | 1604 // to find the matching loops to patch the interrupt |
| 1605 // call to an unconditional call to the replacement code. | 1605 // call to an unconditional call to the replacement code. |
| 1606 int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level() + 1; | 1606 int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level() + 1; |
| 1607 if (loop_nesting_level > Code::kMaxLoopNestingMarker) return; | 1607 if (loop_nesting_level > Code::kMaxLoopNestingMarker) return; |
| 1608 | 1608 |
| 1609 BackEdgeTable back_edges(unoptimized, &no_gc); | 1609 BackEdgeTable back_edges(unoptimized, &no_gc); |
| 1610 for (uint32_t i = 0; i < back_edges.length(); i++) { | 1610 for (uint32_t i = 0; i < back_edges.length(); i++) { |
| 1611 if (static_cast<int>(back_edges.loop_depth(i)) == loop_nesting_level) { | 1611 if (static_cast<int>(back_edges.loop_depth(i)) == loop_nesting_level) { |
| 1612 ASSERT_EQ(INTERRUPT, GetBackEdgeState(isolate, | 1612 DCHECK_EQ(INTERRUPT, GetBackEdgeState(isolate, |
| 1613 unoptimized, | 1613 unoptimized, |
| 1614 back_edges.pc(i))); | 1614 back_edges.pc(i))); |
| 1615 PatchAt(unoptimized, back_edges.pc(i), ON_STACK_REPLACEMENT, patch); | 1615 PatchAt(unoptimized, back_edges.pc(i), ON_STACK_REPLACEMENT, patch); |
| 1616 } | 1616 } |
| 1617 } | 1617 } |
| 1618 | 1618 |
| 1619 unoptimized->set_allow_osr_at_loop_nesting_level(loop_nesting_level); | 1619 unoptimized->set_allow_osr_at_loop_nesting_level(loop_nesting_level); |
| 1620 ASSERT(Verify(isolate, unoptimized)); | 1620 DCHECK(Verify(isolate, unoptimized)); |
| 1621 } | 1621 } |
| 1622 | 1622 |
| 1623 | 1623 |
| 1624 void BackEdgeTable::Revert(Isolate* isolate, Code* unoptimized) { | 1624 void BackEdgeTable::Revert(Isolate* isolate, Code* unoptimized) { |
| 1625 DisallowHeapAllocation no_gc; | 1625 DisallowHeapAllocation no_gc; |
| 1626 Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck); | 1626 Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck); |
| 1627 | 1627 |
| 1628 // Iterate over the back edge table and revert the patched interrupt calls. | 1628 // Iterate over the back edge table and revert the patched interrupt calls. |
| 1629 int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level(); | 1629 int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level(); |
| 1630 | 1630 |
| 1631 BackEdgeTable back_edges(unoptimized, &no_gc); | 1631 BackEdgeTable back_edges(unoptimized, &no_gc); |
| 1632 for (uint32_t i = 0; i < back_edges.length(); i++) { | 1632 for (uint32_t i = 0; i < back_edges.length(); i++) { |
| 1633 if (static_cast<int>(back_edges.loop_depth(i)) <= loop_nesting_level) { | 1633 if (static_cast<int>(back_edges.loop_depth(i)) <= loop_nesting_level) { |
| 1634 ASSERT_NE(INTERRUPT, GetBackEdgeState(isolate, | 1634 DCHECK_NE(INTERRUPT, GetBackEdgeState(isolate, |
| 1635 unoptimized, | 1635 unoptimized, |
| 1636 back_edges.pc(i))); | 1636 back_edges.pc(i))); |
| 1637 PatchAt(unoptimized, back_edges.pc(i), INTERRUPT, patch); | 1637 PatchAt(unoptimized, back_edges.pc(i), INTERRUPT, patch); |
| 1638 } | 1638 } |
| 1639 } | 1639 } |
| 1640 | 1640 |
| 1641 unoptimized->set_allow_osr_at_loop_nesting_level(0); | 1641 unoptimized->set_allow_osr_at_loop_nesting_level(0); |
| 1642 // Assert that none of the back edges are patched anymore. | 1642 // Assert that none of the back edges are patched anymore. |
| 1643 ASSERT(Verify(isolate, unoptimized)); | 1643 DCHECK(Verify(isolate, unoptimized)); |
| 1644 } | 1644 } |
| 1645 | 1645 |
| 1646 | 1646 |
| 1647 void BackEdgeTable::AddStackCheck(Handle<Code> code, uint32_t pc_offset) { | 1647 void BackEdgeTable::AddStackCheck(Handle<Code> code, uint32_t pc_offset) { |
| 1648 DisallowHeapAllocation no_gc; | 1648 DisallowHeapAllocation no_gc; |
| 1649 Isolate* isolate = code->GetIsolate(); | 1649 Isolate* isolate = code->GetIsolate(); |
| 1650 Address pc = code->instruction_start() + pc_offset; | 1650 Address pc = code->instruction_start() + pc_offset; |
| 1651 Code* patch = isolate->builtins()->builtin(Builtins::kOsrAfterStackCheck); | 1651 Code* patch = isolate->builtins()->builtin(Builtins::kOsrAfterStackCheck); |
| 1652 PatchAt(*code, pc, OSR_AFTER_STACK_CHECK, patch); | 1652 PatchAt(*code, pc, OSR_AFTER_STACK_CHECK, patch); |
| 1653 } | 1653 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1682 } | 1682 } |
| 1683 return true; | 1683 return true; |
| 1684 } | 1684 } |
| 1685 #endif // DEBUG | 1685 #endif // DEBUG |
| 1686 | 1686 |
| 1687 | 1687 |
| 1688 #undef __ | 1688 #undef __ |
| 1689 | 1689 |
| 1690 | 1690 |
| 1691 } } // namespace v8::internal | 1691 } } // namespace v8::internal |
| OLD | NEW |