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 |