| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 TestAndBranch(rax, &discard, false_label_); | 593 TestAndBranch(rax, &discard, false_label_); |
| 594 __ bind(&discard); | 594 __ bind(&discard); |
| 595 __ addq(rsp, Immediate(kPointerSize)); | 595 __ addq(rsp, Immediate(kPointerSize)); |
| 596 __ jmp(true_label_); | 596 __ jmp(true_label_); |
| 597 break; | 597 break; |
| 598 } | 598 } |
| 599 } | 599 } |
| 600 } | 600 } |
| 601 | 601 |
| 602 | 602 |
| 603 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 603 void FastCodeGenerator::EmitVariableAssignment(Expression::Context context, |
| 604 Comment cmnt(masm_, "[ Assignment"); | 604 Variable* var) { |
| 605 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 605 if (var->is_global()) { |
| 606 | |
| 607 // Record the source position for the assignment. | |
| 608 SetSourcePosition(expr->position()); | |
| 609 | |
| 610 // Left-hand side can only be a property, a global or | |
| 611 // a (parameter or local) slot. | |
| 612 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | |
| 613 Expression* rhs = expr->value(); | |
| 614 if (var == NULL) { | |
| 615 // Assignment to a property. | |
| 616 ASSERT(expr->target()->AsProperty() != NULL); | |
| 617 Property* prop = expr->target()->AsProperty(); | |
| 618 Visit(prop->obj()); | |
| 619 Literal* literal_key = prop->key()->AsLiteral(); | |
| 620 uint32_t dummy; | |
| 621 if (literal_key != NULL && | |
| 622 literal_key->handle()->IsSymbol() && | |
| 623 !String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) { | |
| 624 // NAMED property assignment | |
| 625 Visit(rhs); | |
| 626 ASSERT_EQ(Expression::kValue, rhs->context()); | |
| 627 __ pop(rax); | |
| 628 __ Move(rcx, literal_key->handle()); | |
| 629 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | |
| 630 __ call(ic, RelocInfo::CODE_TARGET); | |
| 631 __ nop(); | |
| 632 } else { | |
| 633 // KEYED property assignment | |
| 634 Visit(prop->key()); | |
| 635 Visit(rhs); | |
| 636 ASSERT_EQ(Expression::kValue, rhs->context()); | |
| 637 __ pop(rax); | |
| 638 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | |
| 639 __ call(ic, RelocInfo::CODE_TARGET); | |
| 640 __ nop(); | |
| 641 // Drop key from the stack | |
| 642 __ addq(rsp, Immediate(kPointerSize)); | |
| 643 } | |
| 644 // Overwrite the receiver on the stack with the result if needed. | |
| 645 DropAndMove(expr->context(), rax); | |
| 646 } else if (var->is_global()) { | |
| 647 // Assignment to a global variable, use inline caching. Right-hand-side | 606 // Assignment to a global variable, use inline caching. Right-hand-side |
| 648 // value is passed in rax, variable name in rcx, and the global object | 607 // value is passed in rax, variable name in rcx, and the global object |
| 649 // on the stack. | 608 // on the stack. |
| 650 | 609 __ pop(rax); |
| 651 // Code for the right-hand-side expression depends on its type. | |
| 652 if (rhs->AsLiteral() != NULL) { | |
| 653 __ Move(rax, rhs->AsLiteral()->handle()); | |
| 654 } else { | |
| 655 ASSERT_EQ(Expression::kValue, rhs->context()); | |
| 656 Visit(rhs); | |
| 657 __ pop(rax); | |
| 658 } | |
| 659 // Record position for debugger. | |
| 660 SetSourcePosition(expr->position()); | |
| 661 __ Move(rcx, var->name()); | 610 __ Move(rcx, var->name()); |
| 662 __ push(CodeGenerator::GlobalObject()); | 611 __ push(CodeGenerator::GlobalObject()); |
| 663 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 612 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 664 __ Call(ic, RelocInfo::CODE_TARGET); | 613 __ Call(ic, RelocInfo::CODE_TARGET); |
| 665 // Overwrite the global object on the stack with the result if needed. | 614 // Overwrite the global object on the stack with the result if needed. |
| 666 DropAndMove(expr->context(), rax); | 615 DropAndMove(context, rax); |
| 667 } else { | 616 } else { |
| 668 // Local or parameter assignment. | 617 switch (context) { |
| 669 | 618 case Expression::kUninitialized: |
| 670 // Code for the right-hand-side expression depends on its type. | 619 UNREACHABLE(); |
| 671 if (rhs->AsLiteral() != NULL) { | 620 case Expression::kEffect: |
| 672 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | 621 // Perform assignment and discard value. |
| 673 // discarded result. Always perform the assignment. | 622 __ pop(Operand(rbp, SlotOffset(var->slot()))); |
| 674 __ Move(kScratchRegister, rhs->AsLiteral()->handle()); | 623 break; |
| 675 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); | 624 case Expression::kValue: |
| 676 Move(expr->context(), kScratchRegister); | 625 // Perform assignment and preserve value. |
| 677 } else { | 626 __ movq(rax, Operand(rsp, 0)); |
| 678 ASSERT_EQ(Expression::kValue, rhs->context()); | 627 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); |
| 679 Visit(rhs); | 628 break; |
| 680 switch (expr->context()) { | 629 case Expression::kTest: |
| 681 case Expression::kUninitialized: | 630 // Perform assignment and test (and discard) value. |
| 682 UNREACHABLE(); | 631 __ pop(rax); |
| 683 case Expression::kEffect: | 632 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); |
| 684 // Case 'var = temp'. Discard right-hand-side temporary. | 633 TestAndBranch(rax, true_label_, false_label_); |
| 685 __ pop(Operand(rbp, SlotOffset(var->slot()))); | 634 break; |
| 686 break; | 635 case Expression::kValueTest: { |
| 687 case Expression::kValue: | 636 Label discard; |
| 688 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side | 637 __ movq(rax, Operand(rsp, 0)); |
| 689 // temporary on the stack. | 638 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); |
| 690 __ movq(kScratchRegister, Operand(rsp, 0)); | 639 TestAndBranch(rax, true_label_, &discard); |
| 691 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); | 640 __ bind(&discard); |
| 692 break; | 641 __ addq(rsp, Immediate(kPointerSize)); |
| 693 case Expression::kTest: | 642 __ jmp(false_label_); |
| 694 // Case 'if (var = temp) ...'. | 643 break; |
| 695 __ pop(rax); | 644 } |
| 696 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); | 645 case Expression::kTestValue: { |
| 697 TestAndBranch(rax, true_label_, false_label_); | 646 Label discard; |
| 698 break; | 647 __ movq(rax, Operand(rsp, 0)); |
| 699 case Expression::kValueTest: { | 648 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); |
| 700 // Case '(var = temp) || ...' in value context. | 649 TestAndBranch(rax, &discard, false_label_); |
| 701 Label discard; | 650 __ bind(&discard); |
| 702 __ movq(rax, Operand(rsp, 0)); | 651 __ addq(rsp, Immediate(kPointerSize)); |
| 703 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); | 652 __ jmp(true_label_); |
| 704 TestAndBranch(rax, true_label_, &discard); | 653 break; |
| 705 __ bind(&discard); | |
| 706 __ addq(rsp, Immediate(kPointerSize)); | |
| 707 __ jmp(false_label_); | |
| 708 break; | |
| 709 } | |
| 710 case Expression::kTestValue: { | |
| 711 // Case '(var = temp) && ...' in value context. | |
| 712 Label discard; | |
| 713 __ movq(rax, Operand(rsp, 0)); | |
| 714 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); | |
| 715 TestAndBranch(rax, &discard, false_label_); | |
| 716 __ bind(&discard); | |
| 717 __ addq(rsp, Immediate(kPointerSize)); | |
| 718 __ jmp(true_label_); | |
| 719 break; | |
| 720 } | |
| 721 } | 654 } |
| 722 } | 655 } |
| 723 } | 656 } |
| 724 } | 657 } |
| 725 | 658 |
| 726 | 659 |
| 660 void FastCodeGenerator::EmitNamedPropertyAssignment( |
| 661 Expression::Context context, |
| 662 Handle<Object> name) { |
| 663 __ pop(rax); |
| 664 __ Move(rcx, name); |
| 665 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 666 __ Call(ic, RelocInfo::CODE_TARGET); |
| 667 DropAndMove(context, rax); |
| 668 } |
| 669 |
| 670 |
| 671 void FastCodeGenerator::EmitKeyedPropertyAssignment( |
| 672 Expression::Context context) { |
| 673 __ pop(rax); |
| 674 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 675 __ Call(ic, RelocInfo::CODE_TARGET); |
| 676 // This nop signals to the IC that there is no inlined code at the call |
| 677 // site for it to patch. |
| 678 __ nop(); |
| 679 // Receiver and key are still on stack. |
| 680 __ addq(rsp, Immediate(2 * kPointerSize)); |
| 681 Move(context, rax); |
| 682 } |
| 683 |
| 684 |
| 727 void FastCodeGenerator::VisitProperty(Property* expr) { | 685 void FastCodeGenerator::VisitProperty(Property* expr) { |
| 728 Comment cmnt(masm_, "[ Property"); | 686 Comment cmnt(masm_, "[ Property"); |
| 729 Expression* key = expr->key(); | 687 Expression* key = expr->key(); |
| 730 uint32_t dummy; | 688 uint32_t dummy; |
| 731 | 689 |
| 732 // Record the source position for the property load. | 690 // Record the source position for the property load. |
| 733 SetSourcePosition(expr->position()); | 691 SetSourcePosition(expr->position()); |
| 734 | 692 |
| 735 // Evaluate receiver. | 693 // Evaluate receiver. |
| 736 Visit(expr->obj()); | 694 Visit(expr->obj()); |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 986 | 944 |
| 987 break; | 945 break; |
| 988 } | 946 } |
| 989 default: | 947 default: |
| 990 UNREACHABLE(); | 948 UNREACHABLE(); |
| 991 } | 949 } |
| 992 } | 950 } |
| 993 | 951 |
| 994 | 952 |
| 995 } } // namespace v8::internal | 953 } } // namespace v8::internal |
| OLD | NEW |