OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 fast_cgen.Generate(info); | 449 fast_cgen.Generate(info); |
450 if (fast_cgen.HasStackOverflow()) { | 450 if (fast_cgen.HasStackOverflow()) { |
451 ASSERT(!Top::has_pending_exception()); | 451 ASSERT(!Top::has_pending_exception()); |
452 return Handle<Code>::null(); | 452 return Handle<Code>::null(); |
453 } | 453 } |
454 | 454 |
455 // Generate the full code for the function in bailout mode, using the same | 455 // Generate the full code for the function in bailout mode, using the same |
456 // macro assembler. | 456 // macro assembler. |
457 CodeGenerator cgen(&masm); | 457 CodeGenerator cgen(&masm); |
458 CodeGeneratorScope scope(&cgen); | 458 CodeGeneratorScope scope(&cgen); |
459 cgen.Generate(info, CodeGenerator::SECONDARY); | 459 info->set_mode(CompilationInfo::SECONDARY); |
| 460 cgen.Generate(info); |
460 if (cgen.HasStackOverflow()) { | 461 if (cgen.HasStackOverflow()) { |
461 ASSERT(!Top::has_pending_exception()); | 462 ASSERT(!Top::has_pending_exception()); |
462 return Handle<Code>::null(); | 463 return Handle<Code>::null(); |
463 } | 464 } |
464 | 465 |
465 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); | 466 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); |
466 return CodeGenerator::MakeCodeEpilogue(&masm, flags, info); | 467 return CodeGenerator::MakeCodeEpilogue(&masm, flags, info); |
467 } | 468 } |
468 | 469 |
469 | 470 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 void FastCodeGenerator::EmitBitOr() { | 581 void FastCodeGenerator::EmitBitOr() { |
581 if (is_smi(accumulator0()) && is_smi(accumulator1())) { | 582 if (is_smi(accumulator0()) && is_smi(accumulator1())) { |
582 // If both operands are known to be a smi then there is no need to check | 583 // If both operands are known to be a smi then there is no need to check |
583 // the operands or result. There is no need to perform the operation in | 584 // the operands or result. There is no need to perform the operation in |
584 // an effect context. | 585 // an effect context. |
585 if (!destination().is(no_reg)) { | 586 if (!destination().is(no_reg)) { |
586 // Leave the result in the destination register. Bitwise or is | 587 // Leave the result in the destination register. Bitwise or is |
587 // commutative. | 588 // commutative. |
588 __ or_(destination(), Operand(other_accumulator(destination()))); | 589 __ or_(destination(), Operand(other_accumulator(destination()))); |
589 } | 590 } |
590 } else if (destination().is(no_reg)) { | |
591 // Result is not needed but do not clobber the operands in case of | |
592 // bailout. | |
593 __ mov(scratch0(), accumulator1()); | |
594 __ or_(scratch0(), Operand(accumulator0())); | |
595 __ test(scratch0(), Immediate(kSmiTagMask)); | |
596 __ j(not_zero, bailout(), not_taken); | |
597 } else { | 591 } else { |
598 // Preserve the destination operand in a scratch register in case of | 592 // Left is in accumulator1, right in accumulator0. |
599 // bailout. | 593 Label* bailout = NULL; |
600 __ mov(scratch0(), destination()); | 594 if (destination().is(accumulator0())) { |
601 __ or_(destination(), Operand(other_accumulator(destination()))); | 595 __ mov(scratch0(), accumulator0()); |
602 __ test(destination(), Immediate(kSmiTagMask)); | 596 __ or_(destination(), Operand(accumulator1())); // Or is commutative. |
603 __ j(not_zero, bailout(), not_taken); | 597 __ test(destination(), Immediate(kSmiTagMask)); |
| 598 bailout = info()->AddBailout(accumulator1(), scratch0()); // Left, right. |
| 599 } else if (destination().is(accumulator1())) { |
| 600 __ mov(scratch0(), accumulator1()); |
| 601 __ or_(destination(), Operand(accumulator0())); |
| 602 __ test(destination(), Immediate(kSmiTagMask)); |
| 603 bailout = info()->AddBailout(scratch0(), accumulator0()); |
| 604 } else { |
| 605 ASSERT(destination().is(no_reg)); |
| 606 __ mov(scratch0(), accumulator1()); |
| 607 __ or_(scratch0(), Operand(accumulator0())); |
| 608 __ test(scratch0(), Immediate(kSmiTagMask)); |
| 609 bailout = info()->AddBailout(accumulator1(), accumulator0()); |
| 610 } |
| 611 __ j(not_zero, bailout, not_taken); |
604 } | 612 } |
605 | 613 |
606 // If we didn't bailout, the result (in fact, both inputs too) is known to | 614 // If we didn't bailout, the result (in fact, both inputs too) is known to |
607 // be a smi. | 615 // be a smi. |
608 set_as_smi(accumulator0()); | 616 set_as_smi(accumulator0()); |
609 set_as_smi(accumulator1()); | 617 set_as_smi(accumulator1()); |
610 } | 618 } |
611 | 619 |
612 | 620 |
613 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { | 621 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { |
614 ASSERT(info_ == NULL); | 622 ASSERT(info_ == NULL); |
615 info_ = compilation_info; | 623 info_ = compilation_info; |
616 | 624 |
617 // Save the caller's frame pointer and set up our own. | 625 // Save the caller's frame pointer and set up our own. |
618 Comment prologue_cmnt(masm(), ";; Prologue"); | 626 Comment prologue_cmnt(masm(), ";; Prologue"); |
619 __ push(ebp); | 627 __ push(ebp); |
620 __ mov(ebp, esp); | 628 __ mov(ebp, esp); |
621 __ push(esi); // Context. | 629 __ push(esi); // Context. |
622 __ push(edi); // Closure. | 630 __ push(edi); // Closure. |
623 // Note that we keep a live register reference to esi (context) at this | 631 // Note that we keep a live register reference to esi (context) at this |
624 // point. | 632 // point. |
625 | 633 |
| 634 Label* bailout_to_beginning = info()->AddBailout(); |
626 // Receiver (this) is allocated to a fixed register. | 635 // Receiver (this) is allocated to a fixed register. |
627 if (info()->has_this_properties()) { | 636 if (info()->has_this_properties()) { |
628 Comment cmnt(masm(), ";; MapCheck(this)"); | 637 Comment cmnt(masm(), ";; MapCheck(this)"); |
629 if (FLAG_print_ir) { | 638 if (FLAG_print_ir) { |
630 PrintF("#: MapCheck(this)\n"); | 639 PrintF("#: MapCheck(this)\n"); |
631 } | 640 } |
632 ASSERT(info()->has_receiver() && info()->receiver()->IsHeapObject()); | 641 ASSERT(info()->has_receiver() && info()->receiver()->IsHeapObject()); |
633 Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); | 642 Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); |
634 Handle<Map> map(object->map()); | 643 Handle<Map> map(object->map()); |
635 EmitLoadReceiver(); | 644 EmitLoadReceiver(); |
636 __ CheckMap(receiver_reg(), map, bailout(), false); | 645 __ CheckMap(receiver_reg(), map, bailout_to_beginning, false); |
637 } | 646 } |
638 | 647 |
639 // If there is a global variable access check if the global object is the | 648 // If there is a global variable access check if the global object is the |
640 // same as at lazy-compilation time. | 649 // same as at lazy-compilation time. |
641 if (info()->has_globals()) { | 650 if (info()->has_globals()) { |
642 Comment cmnt(masm(), ";; MapCheck(GLOBAL)"); | 651 Comment cmnt(masm(), ";; MapCheck(GLOBAL)"); |
643 if (FLAG_print_ir) { | 652 if (FLAG_print_ir) { |
644 PrintF("#: MapCheck(GLOBAL)\n"); | 653 PrintF("#: MapCheck(GLOBAL)\n"); |
645 } | 654 } |
646 ASSERT(info()->has_global_object()); | 655 ASSERT(info()->has_global_object()); |
647 Handle<Map> map(info()->global_object()->map()); | 656 Handle<Map> map(info()->global_object()->map()); |
648 __ mov(scratch0(), CodeGenerator::GlobalObject()); | 657 __ mov(scratch0(), CodeGenerator::GlobalObject()); |
649 __ CheckMap(scratch0(), map, bailout(), true); | 658 __ CheckMap(scratch0(), map, bailout_to_beginning, true); |
650 } | 659 } |
651 | 660 |
652 VisitStatements(function()->body()); | 661 VisitStatements(function()->body()); |
653 | 662 |
654 Comment return_cmnt(masm(), ";; Return(<undefined>)"); | 663 Comment return_cmnt(masm(), ";; Return(<undefined>)"); |
655 if (FLAG_print_ir) { | 664 if (FLAG_print_ir) { |
656 PrintF("#: Return(<undefined>)\n"); | 665 PrintF("#: Return(<undefined>)\n"); |
657 } | 666 } |
658 __ mov(eax, Factory::undefined_value()); | 667 __ mov(eax, Factory::undefined_value()); |
659 __ mov(esp, ebp); | 668 __ mov(esp, ebp); |
660 __ pop(ebp); | 669 __ pop(ebp); |
661 __ ret((scope()->num_parameters() + 1) * kPointerSize); | 670 __ ret((scope()->num_parameters() + 1) * kPointerSize); |
662 | |
663 __ bind(&bailout_); | |
664 } | 671 } |
665 | 672 |
666 | 673 |
667 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { | 674 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { |
668 UNREACHABLE(); | 675 UNREACHABLE(); |
669 } | 676 } |
670 | 677 |
671 | 678 |
672 void FastCodeGenerator::VisitBlock(Block* stmt) { | 679 void FastCodeGenerator::VisitBlock(Block* stmt) { |
673 VisitStatements(stmt->statements()); | 680 VisitStatements(stmt->statements()); |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 | 945 |
939 | 946 |
940 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 947 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
941 UNREACHABLE(); | 948 UNREACHABLE(); |
942 } | 949 } |
943 | 950 |
944 #undef __ | 951 #undef __ |
945 | 952 |
946 | 953 |
947 } } // namespace v8::internal | 954 } } // namespace v8::internal |
OLD | NEW |