| 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 |