Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: src/arm/codegen-arm.cc

Issue 1604002: Simple register allocation for ARM. Only top of expression... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 #endif 174 #endif
175 175
176 if (info->mode() == CompilationInfo::PRIMARY) { 176 if (info->mode() == CompilationInfo::PRIMARY) {
177 frame_->Enter(); 177 frame_->Enter();
178 // tos: code slot 178 // tos: code slot
179 179
180 // Allocate space for locals and initialize them. This also checks 180 // Allocate space for locals and initialize them. This also checks
181 // for stack overflow. 181 // for stack overflow.
182 frame_->AllocateStackSlots(); 182 frame_->AllocateStackSlots();
183 183
184 VirtualFrame::SpilledScope spilled_scope; 184 VirtualFrame::SpilledScope spilled_scope(frame_);
185 int heap_slots = scope()->num_heap_slots(); 185 int heap_slots = scope()->num_heap_slots();
186 if (heap_slots > 0) { 186 if (heap_slots > 0) {
187 // Allocate local context. 187 // Allocate local context.
188 // Get outer context and create a new context based on it. 188 // Get outer context and create a new context based on it.
189 __ ldr(r0, frame_->Function()); 189 __ ldr(r0, frame_->Function());
190 frame_->EmitPush(r0); 190 frame_->EmitPush(r0);
191 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 191 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
192 FastNewContextStub stub(heap_slots); 192 FastNewContextStub stub(heap_slots);
193 frame_->CallStub(&stub, 1); 193 frame_->CallStub(&stub, 1);
194 } else { 194 } else {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 if (scope()->is_function_scope() && scope()->function() != NULL) { 267 if (scope()->is_function_scope() && scope()->function() != NULL) {
268 __ mov(ip, Operand(Factory::the_hole_value())); 268 __ mov(ip, Operand(Factory::the_hole_value()));
269 frame_->EmitPush(ip); 269 frame_->EmitPush(ip);
270 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); 270 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT);
271 } 271 }
272 } else { 272 } else {
273 // When used as the secondary compiler for splitting, r1, cp, 273 // When used as the secondary compiler for splitting, r1, cp,
274 // fp, and lr have been pushed on the stack. Adjust the virtual 274 // fp, and lr have been pushed on the stack. Adjust the virtual
275 // frame to match this state. 275 // frame to match this state.
276 frame_->Adjust(4); 276 frame_->Adjust(4);
277 allocator_->Unuse(r1);
278 allocator_->Unuse(lr);
279 277
280 // Bind all the bailout labels to the beginning of the function. 278 // Bind all the bailout labels to the beginning of the function.
281 List<CompilationInfo::Bailout*>* bailouts = info->bailouts(); 279 List<CompilationInfo::Bailout*>* bailouts = info->bailouts();
282 for (int i = 0; i < bailouts->length(); i++) { 280 for (int i = 0; i < bailouts->length(); i++) {
283 __ bind(bailouts->at(i)->label()); 281 __ bind(bailouts->at(i)->label());
284 } 282 }
285 } 283 }
286 284
287 // Initialize the function return target after the locals are set 285 // Initialize the function return target after the locals are set
288 // up, because it needs the expected frame height from the frame. 286 // up, because it needs the expected frame height from the frame.
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 // code as we unwind the C++ stack. 496 // code as we unwind the C++ stack.
499 // 497 //
500 // It's possible to have both a stack overflow and a valid frame 498 // It's possible to have both a stack overflow and a valid frame
501 // state (eg, a subexpression overflowed, visiting it returned 499 // state (eg, a subexpression overflowed, visiting it returned
502 // with a dummied frame state, and visiting this expression 500 // with a dummied frame state, and visiting this expression
503 // returned with a normal-looking state). 501 // returned with a normal-looking state).
504 if (HasStackOverflow() && 502 if (HasStackOverflow() &&
505 has_valid_frame() && 503 has_valid_frame() &&
506 !has_cc() && 504 !has_cc() &&
507 frame_->height() == original_height) { 505 frame_->height() == original_height) {
506 frame_->SpillAll();
508 true_target->Jump(); 507 true_target->Jump();
509 } 508 }
510 } 509 }
511 if (force_cc && frame_ != NULL && !has_cc()) { 510 if (force_cc && frame_ != NULL && !has_cc()) {
512 // Convert the TOS value to a boolean in the condition code register. 511 // Convert the TOS value to a boolean in the condition code register.
513 ToBoolean(true_target, false_target); 512 ToBoolean(true_target, false_target);
514 } 513 }
515 ASSERT(!force_cc || !has_valid_frame() || has_cc()); 514 ASSERT(!force_cc || !has_valid_frame() || has_cc());
516 ASSERT(!has_valid_frame() || 515 ASSERT(!has_valid_frame() ||
517 (has_cc() && frame_->height() == original_height) || 516 (has_cc() && frame_->height() == original_height) ||
518 (!has_cc() && frame_->height() == original_height + 1)); 517 (!has_cc() && frame_->height() == original_height + 1));
519 } 518 }
520 519
521 520
522 void CodeGenerator::Load(Expression* expr) { 521 void CodeGenerator::Load(Expression* expr) {
523 #ifdef DEBUG 522 #ifdef DEBUG
524 int original_height = frame_->height(); 523 int original_height = frame_->height();
525 #endif 524 #endif
526 JumpTarget true_target; 525 JumpTarget true_target;
527 JumpTarget false_target; 526 JumpTarget false_target;
528 LoadCondition(expr, &true_target, &false_target, false); 527 LoadCondition(expr, &true_target, &false_target, false);
529 528
530 if (has_cc()) { 529 if (has_cc()) {
531 // Convert cc_reg_ into a boolean value. 530 // Convert cc_reg_ into a boolean value.
531 VirtualFrame::SpilledScope scope(frame_);
532 JumpTarget loaded; 532 JumpTarget loaded;
533 JumpTarget materialize_true; 533 JumpTarget materialize_true;
534 materialize_true.Branch(cc_reg_); 534 materialize_true.Branch(cc_reg_);
535 __ LoadRoot(r0, Heap::kFalseValueRootIndex); 535 __ LoadRoot(r0, Heap::kFalseValueRootIndex);
536 frame_->EmitPush(r0); 536 frame_->EmitPush(r0);
537 loaded.Jump(); 537 loaded.Jump();
538 materialize_true.Bind(); 538 materialize_true.Bind();
539 __ LoadRoot(r0, Heap::kTrueValueRootIndex); 539 __ LoadRoot(r0, Heap::kTrueValueRootIndex);
540 frame_->EmitPush(r0); 540 frame_->EmitPush(r0);
541 loaded.Bind(); 541 loaded.Bind();
542 cc_reg_ = al; 542 cc_reg_ = al;
543 } 543 }
544 544
545 if (true_target.is_linked() || false_target.is_linked()) { 545 if (true_target.is_linked() || false_target.is_linked()) {
546 VirtualFrame::SpilledScope scope(frame_);
546 // We have at least one condition value that has been "translated" 547 // We have at least one condition value that has been "translated"
547 // into a branch, thus it needs to be loaded explicitly. 548 // into a branch, thus it needs to be loaded explicitly.
548 JumpTarget loaded; 549 JumpTarget loaded;
549 if (frame_ != NULL) { 550 if (frame_ != NULL) {
550 loaded.Jump(); // Don't lose the current TOS. 551 loaded.Jump(); // Don't lose the current TOS.
551 } 552 }
552 bool both = true_target.is_linked() && false_target.is_linked(); 553 bool both = true_target.is_linked() && false_target.is_linked();
553 // Load "true" if necessary. 554 // Load "true" if necessary.
554 if (true_target.is_linked()) { 555 if (true_target.is_linked()) {
555 true_target.Bind(); 556 true_target.Bind();
(...skipping 14 matching lines...) Expand all
570 // A value is loaded on all paths reaching this point. 571 // A value is loaded on all paths reaching this point.
571 loaded.Bind(); 572 loaded.Bind();
572 } 573 }
573 ASSERT(has_valid_frame()); 574 ASSERT(has_valid_frame());
574 ASSERT(!has_cc()); 575 ASSERT(!has_cc());
575 ASSERT(frame_->height() == original_height + 1); 576 ASSERT(frame_->height() == original_height + 1);
576 } 577 }
577 578
578 579
579 void CodeGenerator::LoadGlobal() { 580 void CodeGenerator::LoadGlobal() {
580 VirtualFrame::SpilledScope spilled_scope; 581 VirtualFrame::SpilledScope spilled_scope(frame_);
581 __ ldr(r0, GlobalObject()); 582 __ ldr(r0, GlobalObject());
582 frame_->EmitPush(r0); 583 frame_->EmitPush(r0);
583 } 584 }
584 585
585 586
586 void CodeGenerator::LoadGlobalReceiver(Register scratch) { 587 void CodeGenerator::LoadGlobalReceiver(Register scratch) {
587 VirtualFrame::SpilledScope spilled_scope; 588 VirtualFrame::SpilledScope spilled_scope(frame_);
588 __ ldr(scratch, ContextOperand(cp, Context::GLOBAL_INDEX)); 589 __ ldr(scratch, ContextOperand(cp, Context::GLOBAL_INDEX));
589 __ ldr(scratch, 590 __ ldr(scratch,
590 FieldMemOperand(scratch, GlobalObject::kGlobalReceiverOffset)); 591 FieldMemOperand(scratch, GlobalObject::kGlobalReceiverOffset));
591 frame_->EmitPush(scratch); 592 frame_->EmitPush(scratch);
592 } 593 }
593 594
594 595
595 void CodeGenerator::LoadTypeofExpression(Expression* expr) { 596 void CodeGenerator::LoadTypeofExpression(Expression* expr) {
596 // Special handling of identifiers as subexpressions of typeof. 597 // Special handling of identifiers as subexpressions of typeof.
597 VirtualFrame::SpilledScope spilled_scope; 598 VirtualFrame::SpilledScope spilled_scope(frame_);
598 Variable* variable = expr->AsVariableProxy()->AsVariable(); 599 Variable* variable = expr->AsVariableProxy()->AsVariable();
599 if (variable != NULL && !variable->is_this() && variable->is_global()) { 600 if (variable != NULL && !variable->is_this() && variable->is_global()) {
600 // For a global variable we build the property reference 601 // For a global variable we build the property reference
601 // <global>.<variable> and perform a (regular non-contextual) property 602 // <global>.<variable> and perform a (regular non-contextual) property
602 // load to make sure we do not get reference errors. 603 // load to make sure we do not get reference errors.
603 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); 604 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
604 Literal key(variable->name()); 605 Literal key(variable->name());
605 Property property(&global, &key, RelocInfo::kNoPosition); 606 Property property(&global, &key, RelocInfo::kNoPosition);
606 Reference ref(this, &property); 607 Reference ref(this, &property);
607 ref.GetValueAndSpill(); 608 ref.GetValue();
608 } else if (variable != NULL && variable->slot() != NULL) { 609 } else if (variable != NULL && variable->slot() != NULL) {
609 // For a variable that rewrites to a slot, we signal it is the immediate 610 // For a variable that rewrites to a slot, we signal it is the immediate
610 // subexpression of a typeof. 611 // subexpression of a typeof.
611 LoadFromSlot(variable->slot(), INSIDE_TYPEOF); 612 LoadFromSlot(variable->slot(), INSIDE_TYPEOF);
612 frame_->SpillAll(); 613 frame_->SpillAll();
613 } else { 614 } else {
614 // Anything else can be handled normally. 615 // Anything else can be handled normally.
615 LoadAndSpill(expr); 616 LoadAndSpill(expr);
616 } 617 }
617 } 618 }
618 619
619 620
620 Reference::Reference(CodeGenerator* cgen, 621 Reference::Reference(CodeGenerator* cgen,
621 Expression* expression, 622 Expression* expression,
622 bool persist_after_get) 623 bool persist_after_get)
623 : cgen_(cgen), 624 : cgen_(cgen),
624 expression_(expression), 625 expression_(expression),
625 type_(ILLEGAL), 626 type_(ILLEGAL),
626 persist_after_get_(persist_after_get) { 627 persist_after_get_(persist_after_get) {
627 cgen->LoadReference(this); 628 cgen->LoadReference(this);
628 } 629 }
629 630
630 631
631 Reference::~Reference() { 632 Reference::~Reference() {
632 ASSERT(is_unloaded() || is_illegal()); 633 ASSERT(is_unloaded() || is_illegal());
633 } 634 }
634 635
635 636
636 void CodeGenerator::LoadReference(Reference* ref) { 637 void CodeGenerator::LoadReference(Reference* ref) {
637 VirtualFrame::SpilledScope spilled_scope; 638 VirtualFrame::SpilledScope spilled_scope(frame_);
638 Comment cmnt(masm_, "[ LoadReference"); 639 Comment cmnt(masm_, "[ LoadReference");
639 Expression* e = ref->expression(); 640 Expression* e = ref->expression();
640 Property* property = e->AsProperty(); 641 Property* property = e->AsProperty();
641 Variable* var = e->AsVariableProxy()->AsVariable(); 642 Variable* var = e->AsVariableProxy()->AsVariable();
642 643
643 if (property != NULL) { 644 if (property != NULL) {
644 // The expression is either a property or a variable proxy that rewrites 645 // The expression is either a property or a variable proxy that rewrites
645 // to a property. 646 // to a property.
646 LoadAndSpill(property->obj()); 647 LoadAndSpill(property->obj());
647 if (property->key()->IsPropertyName()) { 648 if (property->key()->IsPropertyName()) {
(...skipping 14 matching lines...) Expand all
662 } 663 }
663 } else { 664 } else {
664 // Anything else is a runtime error. 665 // Anything else is a runtime error.
665 LoadAndSpill(e); 666 LoadAndSpill(e);
666 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); 667 frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
667 } 668 }
668 } 669 }
669 670
670 671
671 void CodeGenerator::UnloadReference(Reference* ref) { 672 void CodeGenerator::UnloadReference(Reference* ref) {
672 VirtualFrame::SpilledScope spilled_scope; 673 int size = ref->size();
674 ref->set_unloaded();
675 if (size == 0) return;
676
673 // Pop a reference from the stack while preserving TOS. 677 // Pop a reference from the stack while preserving TOS.
678 VirtualFrame::RegisterAllocationScope scope(this);
674 Comment cmnt(masm_, "[ UnloadReference"); 679 Comment cmnt(masm_, "[ UnloadReference");
675 int size = ref->size();
676 if (size > 0) { 680 if (size > 0) {
677 frame_->EmitPop(r0); 681 Register tos = frame_->PopToRegister();
678 frame_->Drop(size); 682 frame_->Drop(size);
679 frame_->EmitPush(r0); 683 frame_->EmitPush(tos);
680 } 684 }
681 ref->set_unloaded();
682 } 685 }
683 686
684 687
685 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given 688 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given
686 // register to a boolean in the condition code register. The code 689 // register to a boolean in the condition code register. The code
687 // may jump to 'false_target' in case the register converts to 'false'. 690 // may jump to 'false_target' in case the register converts to 'false'.
688 void CodeGenerator::ToBoolean(JumpTarget* true_target, 691 void CodeGenerator::ToBoolean(JumpTarget* true_target,
689 JumpTarget* false_target) { 692 JumpTarget* false_target) {
690 VirtualFrame::SpilledScope spilled_scope; 693 VirtualFrame::SpilledScope spilled_scope(frame_);
691 // Note: The generated code snippet does not change stack variables. 694 // Note: The generated code snippet does not change stack variables.
692 // Only the condition code should be set. 695 // Only the condition code should be set.
693 frame_->EmitPop(r0); 696 frame_->EmitPop(r0);
694 697
695 // Fast case checks 698 // Fast case checks
696 699
697 // Check if the value is 'false'. 700 // Check if the value is 'false'.
698 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 701 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
699 __ cmp(r0, ip); 702 __ cmp(r0, ip);
700 false_target->Branch(eq); 703 false_target->Branch(eq);
(...skipping 21 matching lines...) Expand all
722 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 725 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
723 __ cmp(r0, ip); 726 __ cmp(r0, ip);
724 727
725 cc_reg_ = ne; 728 cc_reg_ = ne;
726 } 729 }
727 730
728 731
729 void CodeGenerator::GenericBinaryOperation(Token::Value op, 732 void CodeGenerator::GenericBinaryOperation(Token::Value op,
730 OverwriteMode overwrite_mode, 733 OverwriteMode overwrite_mode,
731 int constant_rhs) { 734 int constant_rhs) {
732 VirtualFrame::SpilledScope spilled_scope; 735 VirtualFrame::SpilledScope spilled_scope(frame_);
733 // sp[0] : y 736 // sp[0] : y
734 // sp[1] : x 737 // sp[1] : x
735 // result : r0 738 // result : r0
736 739
737 // Stub is entered with a call: 'return address' is in lr. 740 // Stub is entered with a call: 'return address' is in lr.
738 switch (op) { 741 switch (op) {
739 case Token::ADD: // fall through. 742 case Token::ADD: // fall through.
740 case Token::SUB: // fall through. 743 case Token::SUB: // fall through.
741 case Token::MUL: 744 case Token::MUL:
742 case Token::DIV: 745 case Token::DIV:
(...skipping 18 matching lines...) Expand all
761 break; 764 break;
762 765
763 default: 766 default:
764 // Other cases should have been handled before this point. 767 // Other cases should have been handled before this point.
765 UNREACHABLE(); 768 UNREACHABLE();
766 break; 769 break;
767 } 770 }
768 } 771 }
769 772
770 773
774 void CodeGenerator::VirtualFrameBinaryOperation(Token::Value op,
775 OverwriteMode overwrite_mode,
776 int constant_rhs) {
777 // top of virtual frame: y
778 // 2nd elt. on virtual frame : x
779 // result : top of virtual frame
780
781 // Stub is entered with a call: 'return address' is in lr.
782 switch (op) {
783 case Token::ADD: // fall through.
Søren Thygesen Gjesse 2010/04/07 10:46:51 Either repeat this "fall through" comment all the
Erik Corry 2010/04/07 12:49:17 Removed.
784 case Token::SUB: // fall through.
785 case Token::MUL:
786 case Token::DIV:
787 case Token::MOD:
788 case Token::BIT_OR:
789 case Token::BIT_AND:
790 case Token::BIT_XOR:
791 case Token::SHL:
792 case Token::SHR:
793 case Token::SAR: {
794 frame_->PopToR1R0(); // Pop y to r0 and x to r1.
795 {
796 VirtualFrame::SpilledScope spilled_scope(frame_);
797 GenericBinaryOpStub stub(op, overwrite_mode, constant_rhs);
798 frame_->CallStub(&stub, 0);
799 }
800 frame_->EmitPush(r0);
801 break;
802 }
803
804 case Token::COMMA: {
Søren Thygesen Gjesse 2010/04/07 10:46:51 Am I missing something here, or shouldn't we make
Erik Corry 2010/04/07 12:49:17 Yes we should. I can't imagine that the , operato
805 Register scratch = VirtualFrame::scratch0();
806 frame_->EmitPop(scratch);
807 // simply discard left value
Kasper Lund 2010/04/07 08:09:50 // Simply discard left value.
Erik Corry 2010/04/07 12:49:17 Done.
808 frame_->Drop();
809 frame_->EmitPush(scratch);
810 break;
811 }
812
813 default:
814 // Other cases should have been handled before this point.
815 UNREACHABLE();
816 break;
817 }
818 }
819
820
771 class DeferredInlineSmiOperation: public DeferredCode { 821 class DeferredInlineSmiOperation: public DeferredCode {
772 public: 822 public:
773 DeferredInlineSmiOperation(Token::Value op, 823 DeferredInlineSmiOperation(Token::Value op,
774 int value, 824 int value,
775 bool reversed, 825 bool reversed,
776 OverwriteMode overwrite_mode) 826 OverwriteMode overwrite_mode,
827 Register tos = r0)
Kasper Lund 2010/04/07 08:09:50 I would try to avoid these default arguments. Mayb
Erik Corry 2010/04/07 12:49:17 Default argument removed.
777 : op_(op), 828 : op_(op),
778 value_(value), 829 value_(value),
779 reversed_(reversed), 830 reversed_(reversed),
780 overwrite_mode_(overwrite_mode) { 831 overwrite_mode_(overwrite_mode),
832 tos_register_(tos) {
781 set_comment("[ DeferredInlinedSmiOperation"); 833 set_comment("[ DeferredInlinedSmiOperation");
782 } 834 }
783 835
784 virtual void Generate(); 836 virtual void Generate();
785 837
786 private: 838 private:
787 Token::Value op_; 839 Token::Value op_;
788 int value_; 840 int value_;
789 bool reversed_; 841 bool reversed_;
790 OverwriteMode overwrite_mode_; 842 OverwriteMode overwrite_mode_;
843 Register tos_register_;
791 }; 844 };
792 845
793 846
794 void DeferredInlineSmiOperation::Generate() { 847 void DeferredInlineSmiOperation::Generate() {
795 switch (op_) { 848 switch (op_) {
796 case Token::ADD: { 849 case Token::ADD: {
797 // Revert optimistic add. 850 // Revert optimistic add.
798 if (reversed_) { 851 if (reversed_) {
799 __ sub(r0, r0, Operand(Smi::FromInt(value_))); 852 __ sub(r0, tos_register_, Operand(Smi::FromInt(value_)));
800 __ mov(r1, Operand(Smi::FromInt(value_))); 853 __ mov(r1, Operand(Smi::FromInt(value_)));
801 } else { 854 } else {
802 __ sub(r1, r0, Operand(Smi::FromInt(value_))); 855 __ sub(r1, tos_register_, Operand(Smi::FromInt(value_)));
803 __ mov(r0, Operand(Smi::FromInt(value_))); 856 __ mov(r0, Operand(Smi::FromInt(value_)));
804 } 857 }
805 break; 858 break;
806 } 859 }
807 860
808 case Token::SUB: { 861 case Token::SUB: {
809 // Revert optimistic sub. 862 // Revert optimistic sub.
810 if (reversed_) { 863 if (reversed_) {
811 __ rsb(r0, r0, Operand(Smi::FromInt(value_))); 864 __ rsb(r0, tos_register_, Operand(Smi::FromInt(value_)));
812 __ mov(r1, Operand(Smi::FromInt(value_))); 865 __ mov(r1, Operand(Smi::FromInt(value_)));
813 } else { 866 } else {
814 __ add(r1, r0, Operand(Smi::FromInt(value_))); 867 __ add(r1, tos_register_, Operand(Smi::FromInt(value_)));
815 __ mov(r0, Operand(Smi::FromInt(value_))); 868 __ mov(r0, Operand(Smi::FromInt(value_)));
816 } 869 }
817 break; 870 break;
818 } 871 }
819 872
820 // For these operations there is no optimistic operation that needs to be 873 // For these operations there is no optimistic operation that needs to be
821 // reverted. 874 // reverted.
822 case Token::MUL: 875 case Token::MUL:
823 case Token::MOD: 876 case Token::MOD:
824 case Token::BIT_OR: 877 case Token::BIT_OR:
825 case Token::BIT_XOR: 878 case Token::BIT_XOR:
826 case Token::BIT_AND: { 879 case Token::BIT_AND: {
827 if (reversed_) { 880 if (reversed_) {
881 if (!tos_register_.is(r0)) {
Kasper Lund 2010/04/07 08:09:50 How about adding a special Move macro to the macro
Erik Corry 2010/04/07 12:49:17 Done. That was a nice cleanup in unrelated code t
882 __ mov(r0, Operand(tos_register_));
883 }
828 __ mov(r1, Operand(Smi::FromInt(value_))); 884 __ mov(r1, Operand(Smi::FromInt(value_)));
829 } else { 885 } else {
830 __ mov(r1, Operand(r0)); 886 if (!tos_register_.is(r1)) {
887 __ mov(r1, Operand(tos_register_));
888 }
831 __ mov(r0, Operand(Smi::FromInt(value_))); 889 __ mov(r0, Operand(Smi::FromInt(value_)));
832 } 890 }
833 break; 891 break;
834 } 892 }
835 893
836 case Token::SHL: 894 case Token::SHL:
837 case Token::SHR: 895 case Token::SHR:
838 case Token::SAR: { 896 case Token::SAR: {
839 if (!reversed_) { 897 if (!reversed_) {
840 __ mov(r1, Operand(r0)); 898 if (!tos_register_.is(r1)) {
899 __ mov(r1, Operand(tos_register_));
900 }
841 __ mov(r0, Operand(Smi::FromInt(value_))); 901 __ mov(r0, Operand(Smi::FromInt(value_)));
842 } else { 902 } else {
843 UNREACHABLE(); // Should have been handled in SmiOperation. 903 UNREACHABLE(); // Should have been handled in SmiOperation.
844 } 904 }
845 break; 905 break;
846 } 906 }
847 907
848 default: 908 default:
849 // Other cases should have been handled before this point. 909 // Other cases should have been handled before this point.
850 UNREACHABLE(); 910 UNREACHABLE();
851 break; 911 break;
852 } 912 }
853 913
854 GenericBinaryOpStub stub(op_, overwrite_mode_, value_); 914 GenericBinaryOpStub stub(op_, overwrite_mode_, value_);
855 __ CallStub(&stub); 915 __ CallStub(&stub);
916 // The generic stub returns its value in r0, but that's not
917 // necessarily what we want. We want whatever the inlined code
918 // expected, which is that the answer is in the same register as
919 // the operand was.
920 if (!tos_register_.is(r0)) {
921 __ mov(tos_register_, Operand(r0));
922 }
856 } 923 }
857 924
858 925
859 static bool PopCountLessThanEqual2(unsigned int x) { 926 static bool PopCountLessThanEqual2(unsigned int x) {
860 x &= x - 1; 927 x &= x - 1;
861 return (x & (x - 1)) == 0; 928 return (x & (x - 1)) == 0;
862 } 929 }
863 930
864 931
865 // Returns the index of the lowest bit set. 932 // Returns the index of the lowest bit set.
866 static int BitPosition(unsigned x) { 933 static int BitPosition(unsigned x) {
867 int bit_posn = 0; 934 int bit_posn = 0;
868 while ((x & 0xf) == 0) { 935 while ((x & 0xf) == 0) {
869 bit_posn += 4; 936 bit_posn += 4;
870 x >>= 4; 937 x >>= 4;
871 } 938 }
872 while ((x & 1) == 0) { 939 while ((x & 1) == 0) {
873 bit_posn++; 940 bit_posn++;
874 x >>= 1; 941 x >>= 1;
875 } 942 }
876 return bit_posn; 943 return bit_posn;
877 } 944 }
878 945
879 946
947 void CodeGenerator::VirtualFrameSmiOperation(Token::Value op,
948 Handle<Object> value,
949 bool reversed,
950 OverwriteMode mode) {
951 int int_value = Smi::cast(*value)->value();
952
953 bool something_to_inline;
954 switch (op) {
955 case Token::ADD:
956 case Token::SUB:
957 case Token::BIT_AND:
958 case Token::BIT_OR:
959 case Token::BIT_XOR: {
960 something_to_inline = true;
961 break;
962 }
963 case Token::SHL:
964 case Token::SHR:
965 case Token::SAR: {
966 if (reversed) {
967 something_to_inline = false;
968 } else {
969 something_to_inline = true;
970 }
971 break;
972 }
973 case Token::MOD: {
974 if (reversed || int_value < 2 || !IsPowerOf2(int_value)) {
975 something_to_inline = false;
976 } else {
977 something_to_inline = true;
978 }
979 break;
980 }
981 case Token::MUL: {
982 if (!IsEasyToMultiplyBy(int_value)) {
983 something_to_inline = false;
984 } else {
985 something_to_inline = true;
986 }
987 break;
988 }
989 default: {
990 something_to_inline = false;
991 break;
992 }
993 }
994
995 if (!something_to_inline) {
996 if (!reversed) {
997 // Move the lhs to r1.
998 frame_->PopToR1();
999 // Flush any other registers to the stack.
1000 frame_->SpillAll();
1001 // Tell the virtual frame that TOS is in r1 (no code emitted).
1002 frame_->EmitPush(r1);
1003 // We know that r0 is free.
1004 __ mov(r0, Operand(value));
1005 // Push r0 on the virtual frame (no code emitted).
1006 frame_->EmitPush(r0);
1007 // This likes having r1 and r0 on top of the stack. It pushes
1008 // the answer on the virtual frame.
1009 VirtualFrameBinaryOperation(op, mode, int_value);
1010 } else {
1011 // Move the rhs to r0.
1012 frame_->PopToR0();
1013 // Flush any other registers to the stack.
1014 frame_->SpillAll();
1015 // We know that r1 is free.
1016 __ mov(r1, Operand(value));
1017 // Tell the virtual frame that TOS is in r1 (no code emitted).
1018 frame_->EmitPush(r1);
1019 // Push r0 on the virtual frame (no code emitted).
1020 frame_->EmitPush(r0);
1021 // This likes having r1 and r0 on top of the stack. It pushes
1022 // the answer on the virtual frame.
1023 VirtualFrameBinaryOperation(op, mode, kUnknownIntValue);
1024 }
1025 return;
1026 }
1027
1028
Kasper Lund 2010/04/07 08:09:50 Too much whitespace.
Erik Corry 2010/04/07 12:49:17 Done.
1029 // We move the top of stack to a register (normally no move is invoved).
1030 Register tos = frame_->PopToRegister();
1031 // All other registers are spilled. The deferred code expects one argument
1032 // in a register and all other values are flushed to the stack. The
1033 // answer is returned in the same register that the top of stack argument was
1034 // in.
1035 frame_->SpillAll();
1036
1037 switch (op) {
1038 case Token::ADD: {
1039 DeferredCode* deferred =
1040 new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos);
1041
1042 __ add(tos, tos, Operand(value), SetCC);
1043 deferred->Branch(vs);
1044 __ tst(tos, Operand(kSmiTagMask));
1045 deferred->Branch(ne);
1046 deferred->BindExit();
1047 frame_->EmitPush(tos);
1048 break;
1049 }
1050
1051 case Token::SUB: {
1052 DeferredCode* deferred =
1053 new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos);
1054
1055 if (reversed) {
1056 __ rsb(tos, tos, Operand(value), SetCC);
1057 } else {
1058 __ sub(tos, tos, Operand(value), SetCC);
1059 }
1060 deferred->Branch(vs);
1061 __ tst(tos, Operand(kSmiTagMask));
1062 deferred->Branch(ne);
1063 deferred->BindExit();
1064 frame_->EmitPush(tos);
1065 break;
1066 }
1067
1068
1069 case Token::BIT_OR:
1070 case Token::BIT_XOR:
1071 case Token::BIT_AND: {
1072 DeferredCode* deferred =
1073 new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos);
1074 __ tst(tos, Operand(kSmiTagMask));
1075 deferred->Branch(ne);
1076 switch (op) {
1077 case Token::BIT_OR: __ orr(tos, tos, Operand(value)); break;
1078 case Token::BIT_XOR: __ eor(tos, tos, Operand(value)); break;
1079 case Token::BIT_AND: __ and_(tos, tos, Operand(value)); break;
1080 default: UNREACHABLE();
1081 }
1082 deferred->BindExit();
1083 frame_->EmitPush(tos);
1084 break;
1085 }
1086
1087 case Token::SHL:
1088 case Token::SHR:
1089 case Token::SAR: {
1090 ASSERT(!reversed);
1091 int shift_value = int_value & 0x1f; // least significant 5 bits
1092 DeferredCode* deferred =
1093 new DeferredInlineSmiOperation(op, shift_value, false, mode, tos);
1094 __ tst(tos, Operand(kSmiTagMask));
1095 deferred->Branch(ne);
Søren Thygesen Gjesse 2010/04/07 10:46:51 Wouldn't it be better to use VirtualFrame::scratch
Erik Corry 2010/04/07 12:49:17 Done.
1096 __ mov(r2, Operand(tos, ASR, kSmiTagSize)); // remove tags
1097 switch (op) {
1098 case Token::SHL: {
1099 if (shift_value != 0) {
1100 __ mov(r2, Operand(r2, LSL, shift_value));
1101 }
1102 // check that the *unsigned* result fits in a smi
1103 __ add(r3, r2, Operand(0x40000000), SetCC);
1104 deferred->Branch(mi);
1105 break;
1106 }
1107 case Token::SHR: {
1108 // LSR by immediate 0 means shifting 32 bits.
1109 if (shift_value != 0) {
1110 __ mov(r2, Operand(r2, LSR, shift_value));
1111 }
1112 // check that the *unsigned* result fits in a smi
1113 // neither of the two high-order bits can be set:
1114 // - 0x80000000: high bit would be lost when smi tagging
1115 // - 0x40000000: this number would convert to negative when
1116 // smi tagging these two cases can only happen with shifts
1117 // by 0 or 1 when handed a valid smi
1118 __ and_(r3, r2, Operand(0xc0000000), SetCC);
1119 deferred->Branch(ne);
1120 break;
1121 }
1122 case Token::SAR: {
1123 if (shift_value != 0) {
1124 // ASR by immediate 0 means shifting 32 bits.
1125 __ mov(r2, Operand(r2, ASR, shift_value));
1126 }
1127 break;
1128 }
1129 default: UNREACHABLE();
1130 }
1131 __ mov(tos, Operand(r2, LSL, kSmiTagSize));
1132 deferred->BindExit();
1133 frame_->EmitPush(tos);
1134 break;
1135 }
1136
1137 case Token::MOD: {
1138 ASSERT(!reversed);
1139 ASSERT(int_value >= 2);
1140 ASSERT(IsPowerOf2(int_value));
1141 DeferredCode* deferred =
1142 new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos);
1143 unsigned mask = (0x80000000u | kSmiTagMask);
1144 __ tst(tos, Operand(mask));
1145 deferred->Branch(ne); // Go to deferred code on non-Smis and negative.
1146 mask = (int_value << kSmiTagSize) - 1;
1147 __ and_(tos, tos, Operand(mask));
1148 deferred->BindExit();
1149 frame_->EmitPush(tos);
1150 break;
1151 }
1152
1153 case Token::MUL: {
1154 ASSERT(IsEasyToMultiplyBy(int_value));
1155 DeferredCode* deferred =
1156 new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos);
1157 unsigned max_smi_that_wont_overflow = Smi::kMaxValue / int_value;
1158 max_smi_that_wont_overflow <<= kSmiTagSize;
1159 unsigned mask = 0x80000000u;
1160 while ((mask & max_smi_that_wont_overflow) == 0) {
1161 mask |= mask >> 1;
1162 }
1163 mask |= kSmiTagMask;
1164 // This does a single mask that checks for a too high value in a
1165 // conservative way and for a non-Smi. It also filters out negative
1166 // numbers, unfortunately, but since this code is inline we prefer
1167 // brevity to comprehensiveness.
1168 __ tst(tos, Operand(mask));
1169 deferred->Branch(ne);
1170 MultiplyByKnownInt(masm_, tos, tos, int_value);
1171 deferred->BindExit();
1172 frame_->EmitPush(tos);
1173 break;
1174 }
1175
1176 default:
1177 UNREACHABLE();
1178 break;
1179 }
1180 }
1181
1182
880 void CodeGenerator::SmiOperation(Token::Value op, 1183 void CodeGenerator::SmiOperation(Token::Value op,
881 Handle<Object> value, 1184 Handle<Object> value,
882 bool reversed, 1185 bool reversed,
883 OverwriteMode mode) { 1186 OverwriteMode mode) {
884 VirtualFrame::SpilledScope spilled_scope; 1187 VirtualFrame::SpilledScope spilled_scope(frame_);
885 // NOTE: This is an attempt to inline (a bit) more of the code for 1188 // NOTE: This is an attempt to inline (a bit) more of the code for
886 // some possible smi operations (like + and -) when (at least) one 1189 // some possible smi operations (like + and -) when (at least) one
887 // of the operands is a literal smi. With this optimization, the 1190 // of the operands is a literal smi. With this optimization, the
888 // performance of the system is increased by ~15%, and the generated 1191 // performance of the system is increased by ~15%, and the generated
889 // code size is increased by ~1% (measured on a combination of 1192 // code size is increased by ~1% (measured on a combination of
890 // different benchmarks). 1193 // different benchmarks).
891 1194
892 // sp[0] : operand 1195 // sp[0] : operand
893 1196
894 int int_value = Smi::cast(*value)->value(); 1197 int int_value = Smi::cast(*value)->value();
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 } 1360 }
1058 1361
1059 exit.Bind(); 1362 exit.Bind();
1060 } 1363 }
1061 1364
1062 1365
1063 void CodeGenerator::Comparison(Condition cc, 1366 void CodeGenerator::Comparison(Condition cc,
1064 Expression* left, 1367 Expression* left,
1065 Expression* right, 1368 Expression* right,
1066 bool strict) { 1369 bool strict) {
1067 if (left != NULL) LoadAndSpill(left); 1370 VirtualFrame::RegisterAllocationScope scope(this);
1068 if (right != NULL) LoadAndSpill(right);
1069 1371
1070 VirtualFrame::SpilledScope spilled_scope; 1372 if (left != NULL) Load(left);
1373 if (right != NULL) Load(right);
1374
1071 // sp[0] : y 1375 // sp[0] : y
1072 // sp[1] : x 1376 // sp[1] : x
1073 // result : cc register 1377 // result : cc register
1074 1378
1075 // Strict only makes sense for equality comparisons. 1379 // Strict only makes sense for equality comparisons.
1076 ASSERT(!strict || cc == eq); 1380 ASSERT(!strict || cc == eq);
1077 1381
1078 JumpTarget exit; 1382 Register lhs;
1079 JumpTarget smi; 1383 Register rhs;
1384
1385 // We load the top two stack positions into registers chosen by the virtual
1386 // frame. This should keep the register shuffling to a minimum.
1080 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 1387 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
1081 if (cc == gt || cc == le) { 1388 if (cc == gt || cc == le) {
1082 cc = ReverseCondition(cc); 1389 cc = ReverseCondition(cc);
1083 frame_->EmitPop(r1); 1390 lhs = frame_->PopToRegister();
1084 frame_->EmitPop(r0); 1391 rhs = frame_->PopToRegister(lhs); // Don't pop to the same register again!
1085 } else { 1392 } else {
1086 frame_->EmitPop(r0); 1393 rhs = frame_->PopToRegister();
1087 frame_->EmitPop(r1); 1394 lhs = frame_->PopToRegister(rhs); // Don't pop to the same register again!
1088 } 1395 }
1089 __ orr(r2, r0, Operand(r1)); 1396
1397 ASSERT(rhs.is(r0) || rhs.is(r1));
1398 ASSERT(lhs.is(r0) || lhs.is(r1));
1399
1400 // Now we have the two sides in r0 and r1. We flush any other registers
1401 // because the stub doesn't know about register allocation.
1402 frame_->SpillAll();
1403 __ orr(r2, lhs, Operand(rhs));
Søren Thygesen Gjesse 2010/04/07 10:46:51 VirtualFrame::scratchX()?
Erik Corry 2010/04/07 12:49:17 Done.
1090 __ tst(r2, Operand(kSmiTagMask)); 1404 __ tst(r2, Operand(kSmiTagMask));
1405 JumpTarget smi;
1091 smi.Branch(eq); 1406 smi.Branch(eq);
1092 1407
1093 // Perform non-smi comparison by stub. 1408 // Perform non-smi comparison by stub.
1094 // CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0. 1409 // CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0.
1095 // We call with 0 args because there are 0 on the stack. 1410 // We call with 0 args because there are 0 on the stack.
1411 if (!rhs.is(r0)) {
Søren Thygesen Gjesse 2010/04/07 07:53:37 Should this be MacroAssembler::Swap?
Erik Corry 2010/04/07 12:49:17 Done.
1412 __ eor(rhs, rhs, Operand(lhs));
Kasper Lund 2010/04/07 08:09:50 Add macro SwapRegisters or at least a comment here
Erik Corry 2010/04/07 12:49:17 Done.
1413 __ eor(lhs, lhs, Operand(rhs));
1414 __ eor(rhs, rhs, Operand(lhs));
1415 }
1416
1096 CompareStub stub(cc, strict); 1417 CompareStub stub(cc, strict);
1097 frame_->CallStub(&stub, 0); 1418 frame_->CallStub(&stub, 0);
1098 __ cmp(r0, Operand(0)); 1419 __ cmp(r0, Operand(0));
1420 JumpTarget exit;
1099 exit.Jump(); 1421 exit.Jump();
1100 1422
1101 // Do smi comparisons by pointer comparison. 1423 // Do smi comparisons by pointer comparison.
1102 smi.Bind(); 1424 smi.Bind();
1103 __ cmp(r1, Operand(r0)); 1425 __ cmp(lhs, Operand(rhs));
1104 1426
1105 exit.Bind(); 1427 exit.Bind();
1106 cc_reg_ = cc; 1428 cc_reg_ = cc;
1107 } 1429 }
1108 1430
1109 1431
1110 // Call the function on the stack with the given arguments. 1432 // Call the function on the stack with the given arguments.
1111 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 1433 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
1112 CallFunctionFlags flags, 1434 CallFunctionFlags flags,
1113 int position) { 1435 int position) {
1114 VirtualFrame::SpilledScope spilled_scope; 1436 VirtualFrame::SpilledScope spilled_scope(frame_);
1115 // Push the arguments ("left-to-right") on the stack. 1437 // Push the arguments ("left-to-right") on the stack.
1116 int arg_count = args->length(); 1438 int arg_count = args->length();
1117 for (int i = 0; i < arg_count; i++) { 1439 for (int i = 0; i < arg_count; i++) {
1118 LoadAndSpill(args->at(i)); 1440 LoadAndSpill(args->at(i));
1119 } 1441 }
1120 1442
1121 // Record the position for debugging purposes. 1443 // Record the position for debugging purposes.
1122 CodeForSourcePosition(position); 1444 CodeForSourcePosition(position);
1123 1445
1124 // Use the shared code stub to call the function. 1446 // Use the shared code stub to call the function.
1125 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; 1447 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
1126 CallFunctionStub call_function(arg_count, in_loop, flags); 1448 CallFunctionStub call_function(arg_count, in_loop, flags);
1127 frame_->CallStub(&call_function, arg_count + 1); 1449 frame_->CallStub(&call_function, arg_count + 1);
1128 1450
1129 // Restore context and pop function from the stack. 1451 // Restore context and pop function from the stack.
1130 __ ldr(cp, frame_->Context()); 1452 __ ldr(cp, frame_->Context());
1131 frame_->Drop(); // discard the TOS 1453 frame_->Drop(); // discard the TOS
1132 } 1454 }
1133 1455
1134 1456
1135 void CodeGenerator::Branch(bool if_true, JumpTarget* target) { 1457 void CodeGenerator::Branch(bool if_true, JumpTarget* target) {
1136 VirtualFrame::SpilledScope spilled_scope; 1458 VirtualFrame::SpilledScope spilled_scope(frame_);
1137 ASSERT(has_cc()); 1459 ASSERT(has_cc());
1138 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); 1460 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
1139 target->Branch(cc); 1461 target->Branch(cc);
1140 cc_reg_ = al; 1462 cc_reg_ = al;
1141 } 1463 }
1142 1464
1143 1465
1144 void CodeGenerator::CheckStack() { 1466 void CodeGenerator::CheckStack() {
1145 VirtualFrame::SpilledScope spilled_scope; 1467 VirtualFrame::SpilledScope spilled_scope(frame_);
1146 Comment cmnt(masm_, "[ check stack"); 1468 Comment cmnt(masm_, "[ check stack");
1147 __ LoadRoot(ip, Heap::kStackLimitRootIndex); 1469 __ LoadRoot(ip, Heap::kStackLimitRootIndex);
1148 // Put the lr setup instruction in the delay slot. kInstrSize is added to 1470 // Put the lr setup instruction in the delay slot. kInstrSize is added to
1149 // the implicit 8 byte offset that always applies to operations with pc and 1471 // the implicit 8 byte offset that always applies to operations with pc and
1150 // gives a return address 12 bytes down. 1472 // gives a return address 12 bytes down.
1151 masm_->add(lr, pc, Operand(Assembler::kInstrSize)); 1473 masm_->add(lr, pc, Operand(Assembler::kInstrSize));
1152 masm_->cmp(sp, Operand(ip)); 1474 masm_->cmp(sp, Operand(ip));
1153 StackCheckStub stub; 1475 StackCheckStub stub;
1154 // Call the stub if lower. 1476 // Call the stub if lower.
1155 masm_->mov(pc, 1477 masm_->mov(pc,
1156 Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()), 1478 Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()),
1157 RelocInfo::CODE_TARGET), 1479 RelocInfo::CODE_TARGET),
1158 LeaveCC, 1480 LeaveCC,
1159 lo); 1481 lo);
1160 } 1482 }
1161 1483
1162 1484
1163 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { 1485 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
1164 #ifdef DEBUG 1486 #ifdef DEBUG
1165 int original_height = frame_->height(); 1487 int original_height = frame_->height();
1166 #endif 1488 #endif
1167 VirtualFrame::SpilledScope spilled_scope; 1489 VirtualFrame::SpilledScope spilled_scope(frame_);
1168 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { 1490 for (int i = 0; frame_ != NULL && i < statements->length(); i++) {
1169 VisitAndSpill(statements->at(i)); 1491 VisitAndSpill(statements->at(i));
1170 } 1492 }
1171 ASSERT(!has_valid_frame() || frame_->height() == original_height); 1493 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1172 } 1494 }
1173 1495
1174 1496
1175 void CodeGenerator::VisitBlock(Block* node) { 1497 void CodeGenerator::VisitBlock(Block* node) {
1176 #ifdef DEBUG 1498 #ifdef DEBUG
1177 int original_height = frame_->height(); 1499 int original_height = frame_->height();
1178 #endif 1500 #endif
1179 VirtualFrame::SpilledScope spilled_scope; 1501 VirtualFrame::SpilledScope spilled_scope(frame_);
1180 Comment cmnt(masm_, "[ Block"); 1502 Comment cmnt(masm_, "[ Block");
1181 CodeForStatementPosition(node); 1503 CodeForStatementPosition(node);
1182 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 1504 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1183 VisitStatementsAndSpill(node->statements()); 1505 VisitStatementsAndSpill(node->statements());
1184 if (node->break_target()->is_linked()) { 1506 if (node->break_target()->is_linked()) {
1185 node->break_target()->Bind(); 1507 node->break_target()->Bind();
1186 } 1508 }
1187 node->break_target()->Unuse(); 1509 node->break_target()->Unuse();
1188 ASSERT(!has_valid_frame() || frame_->height() == original_height); 1510 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1189 } 1511 }
1190 1512
1191 1513
1192 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1514 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1193 VirtualFrame::SpilledScope spilled_scope; 1515 VirtualFrame::SpilledScope spilled_scope(frame_);
1194 frame_->EmitPush(cp); 1516 frame_->EmitPush(cp);
1195 __ mov(r0, Operand(pairs)); 1517 __ mov(r0, Operand(pairs));
1196 frame_->EmitPush(r0); 1518 frame_->EmitPush(r0);
1197 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 1519 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
1198 frame_->EmitPush(r0); 1520 frame_->EmitPush(r0);
1199 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 1521 frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
1200 // The result is discarded. 1522 // The result is discarded.
1201 } 1523 }
1202 1524
1203 1525
1204 void CodeGenerator::VisitDeclaration(Declaration* node) { 1526 void CodeGenerator::VisitDeclaration(Declaration* node) {
1205 #ifdef DEBUG 1527 #ifdef DEBUG
1206 int original_height = frame_->height(); 1528 int original_height = frame_->height();
1207 #endif 1529 #endif
1208 VirtualFrame::SpilledScope spilled_scope; 1530 VirtualFrame::SpilledScope spilled_scope(frame_);
1209 Comment cmnt(masm_, "[ Declaration"); 1531 Comment cmnt(masm_, "[ Declaration");
1210 Variable* var = node->proxy()->var(); 1532 Variable* var = node->proxy()->var();
1211 ASSERT(var != NULL); // must have been resolved 1533 ASSERT(var != NULL); // must have been resolved
1212 Slot* slot = var->slot(); 1534 Slot* slot = var->slot();
1213 1535
1214 // If it was not possible to allocate the variable at compile time, 1536 // If it was not possible to allocate the variable at compile time,
1215 // we need to "declare" it at runtime to make sure it actually 1537 // we need to "declare" it at runtime to make sure it actually
1216 // exists in the local context. 1538 // exists in the local context.
1217 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1539 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1218 // Variables with a "LOOKUP" slot were introduced as non-locals 1540 // Variables with a "LOOKUP" slot were introduced as non-locals
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 frame_->Drop(); 1589 frame_->Drop();
1268 } 1590 }
1269 ASSERT(frame_->height() == original_height); 1591 ASSERT(frame_->height() == original_height);
1270 } 1592 }
1271 1593
1272 1594
1273 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1595 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1274 #ifdef DEBUG 1596 #ifdef DEBUG
1275 int original_height = frame_->height(); 1597 int original_height = frame_->height();
1276 #endif 1598 #endif
1277 VirtualFrame::SpilledScope spilled_scope; 1599 VirtualFrame::SpilledScope spilled_scope(frame_);
1278 Comment cmnt(masm_, "[ ExpressionStatement"); 1600 Comment cmnt(masm_, "[ ExpressionStatement");
1279 CodeForStatementPosition(node); 1601 CodeForStatementPosition(node);
1280 Expression* expression = node->expression(); 1602 Expression* expression = node->expression();
1281 expression->MarkAsStatement(); 1603 expression->MarkAsStatement();
1282 LoadAndSpill(expression); 1604 LoadAndSpill(expression);
1283 frame_->Drop(); 1605 frame_->Drop();
1284 ASSERT(frame_->height() == original_height); 1606 ASSERT(frame_->height() == original_height);
1285 } 1607 }
1286 1608
1287 1609
1288 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { 1610 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
1289 #ifdef DEBUG 1611 #ifdef DEBUG
1290 int original_height = frame_->height(); 1612 int original_height = frame_->height();
1291 #endif 1613 #endif
1292 VirtualFrame::SpilledScope spilled_scope; 1614 VirtualFrame::SpilledScope spilled_scope(frame_);
1293 Comment cmnt(masm_, "// EmptyStatement"); 1615 Comment cmnt(masm_, "// EmptyStatement");
1294 CodeForStatementPosition(node); 1616 CodeForStatementPosition(node);
1295 // nothing to do 1617 // nothing to do
1296 ASSERT(frame_->height() == original_height); 1618 ASSERT(frame_->height() == original_height);
1297 } 1619 }
1298 1620
1299 1621
1300 void CodeGenerator::VisitIfStatement(IfStatement* node) { 1622 void CodeGenerator::VisitIfStatement(IfStatement* node) {
1301 #ifdef DEBUG 1623 #ifdef DEBUG
1302 int original_height = frame_->height(); 1624 int original_height = frame_->height();
1303 #endif 1625 #endif
1304 VirtualFrame::SpilledScope spilled_scope; 1626 VirtualFrame::SpilledScope spilled_scope(frame_);
1305 Comment cmnt(masm_, "[ IfStatement"); 1627 Comment cmnt(masm_, "[ IfStatement");
1306 // Generate different code depending on which parts of the if statement 1628 // Generate different code depending on which parts of the if statement
1307 // are present or not. 1629 // are present or not.
1308 bool has_then_stm = node->HasThenStatement(); 1630 bool has_then_stm = node->HasThenStatement();
1309 bool has_else_stm = node->HasElseStatement(); 1631 bool has_else_stm = node->HasElseStatement();
1310 1632
1311 CodeForStatementPosition(node); 1633 CodeForStatementPosition(node);
1312 1634
1313 JumpTarget exit; 1635 JumpTarget exit;
1314 if (has_then_stm && has_else_stm) { 1636 if (has_then_stm && has_else_stm) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 1702
1381 // end 1703 // end
1382 if (exit.is_linked()) { 1704 if (exit.is_linked()) {
1383 exit.Bind(); 1705 exit.Bind();
1384 } 1706 }
1385 ASSERT(!has_valid_frame() || frame_->height() == original_height); 1707 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1386 } 1708 }
1387 1709
1388 1710
1389 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { 1711 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
1390 VirtualFrame::SpilledScope spilled_scope; 1712 VirtualFrame::SpilledScope spilled_scope(frame_);
1391 Comment cmnt(masm_, "[ ContinueStatement"); 1713 Comment cmnt(masm_, "[ ContinueStatement");
1392 CodeForStatementPosition(node); 1714 CodeForStatementPosition(node);
1393 node->target()->continue_target()->Jump(); 1715 node->target()->continue_target()->Jump();
1394 } 1716 }
1395 1717
1396 1718
1397 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { 1719 void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
1398 VirtualFrame::SpilledScope spilled_scope; 1720 VirtualFrame::SpilledScope spilled_scope(frame_);
1399 Comment cmnt(masm_, "[ BreakStatement"); 1721 Comment cmnt(masm_, "[ BreakStatement");
1400 CodeForStatementPosition(node); 1722 CodeForStatementPosition(node);
1401 node->target()->break_target()->Jump(); 1723 node->target()->break_target()->Jump();
1402 } 1724 }
1403 1725
1404 1726
1405 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { 1727 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
1406 VirtualFrame::SpilledScope spilled_scope; 1728 VirtualFrame::SpilledScope spilled_scope(frame_);
1407 Comment cmnt(masm_, "[ ReturnStatement"); 1729 Comment cmnt(masm_, "[ ReturnStatement");
1408 1730
1409 CodeForStatementPosition(node); 1731 CodeForStatementPosition(node);
1410 LoadAndSpill(node->expression()); 1732 LoadAndSpill(node->expression());
1411 if (function_return_is_shadowed_) { 1733 if (function_return_is_shadowed_) {
1412 frame_->EmitPop(r0); 1734 frame_->EmitPop(r0);
1413 function_return_.Jump(); 1735 function_return_.Jump();
1414 } else { 1736 } else {
1415 // Pop the result from the frame and prepare the frame for 1737 // Pop the result from the frame and prepare the frame for
1416 // returning thus making it easier to merge. 1738 // returning thus making it easier to merge.
1417 frame_->EmitPop(r0); 1739 frame_->EmitPop(r0);
1418 frame_->PrepareForReturn(); 1740 frame_->PrepareForReturn();
1419 1741
1420 function_return_.Jump(); 1742 function_return_.Jump();
1421 } 1743 }
1422 } 1744 }
1423 1745
1424 1746
1425 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 1747 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
1426 #ifdef DEBUG 1748 #ifdef DEBUG
1427 int original_height = frame_->height(); 1749 int original_height = frame_->height();
1428 #endif 1750 #endif
1429 VirtualFrame::SpilledScope spilled_scope; 1751 VirtualFrame::SpilledScope spilled_scope(frame_);
1430 Comment cmnt(masm_, "[ WithEnterStatement"); 1752 Comment cmnt(masm_, "[ WithEnterStatement");
1431 CodeForStatementPosition(node); 1753 CodeForStatementPosition(node);
1432 LoadAndSpill(node->expression()); 1754 LoadAndSpill(node->expression());
1433 if (node->is_catch_block()) { 1755 if (node->is_catch_block()) {
1434 frame_->CallRuntime(Runtime::kPushCatchContext, 1); 1756 frame_->CallRuntime(Runtime::kPushCatchContext, 1);
1435 } else { 1757 } else {
1436 frame_->CallRuntime(Runtime::kPushContext, 1); 1758 frame_->CallRuntime(Runtime::kPushContext, 1);
1437 } 1759 }
1438 #ifdef DEBUG 1760 #ifdef DEBUG
1439 JumpTarget verified_true; 1761 JumpTarget verified_true;
1440 __ cmp(r0, Operand(cp)); 1762 __ cmp(r0, Operand(cp));
1441 verified_true.Branch(eq); 1763 verified_true.Branch(eq);
1442 __ stop("PushContext: r0 is expected to be the same as cp"); 1764 __ stop("PushContext: r0 is expected to be the same as cp");
1443 verified_true.Bind(); 1765 verified_true.Bind();
1444 #endif 1766 #endif
1445 // Update context local. 1767 // Update context local.
1446 __ str(cp, frame_->Context()); 1768 __ str(cp, frame_->Context());
1447 ASSERT(frame_->height() == original_height); 1769 ASSERT(frame_->height() == original_height);
1448 } 1770 }
1449 1771
1450 1772
1451 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { 1773 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
1452 #ifdef DEBUG 1774 #ifdef DEBUG
1453 int original_height = frame_->height(); 1775 int original_height = frame_->height();
1454 #endif 1776 #endif
1455 VirtualFrame::SpilledScope spilled_scope; 1777 VirtualFrame::SpilledScope spilled_scope(frame_);
1456 Comment cmnt(masm_, "[ WithExitStatement"); 1778 Comment cmnt(masm_, "[ WithExitStatement");
1457 CodeForStatementPosition(node); 1779 CodeForStatementPosition(node);
1458 // Pop context. 1780 // Pop context.
1459 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); 1781 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX));
1460 // Update context local. 1782 // Update context local.
1461 __ str(cp, frame_->Context()); 1783 __ str(cp, frame_->Context());
1462 ASSERT(frame_->height() == original_height); 1784 ASSERT(frame_->height() == original_height);
1463 } 1785 }
1464 1786
1465 1787
1466 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 1788 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
1467 #ifdef DEBUG 1789 #ifdef DEBUG
1468 int original_height = frame_->height(); 1790 int original_height = frame_->height();
1469 #endif 1791 #endif
1470 VirtualFrame::SpilledScope spilled_scope; 1792 VirtualFrame::SpilledScope spilled_scope(frame_);
1471 Comment cmnt(masm_, "[ SwitchStatement"); 1793 Comment cmnt(masm_, "[ SwitchStatement");
1472 CodeForStatementPosition(node); 1794 CodeForStatementPosition(node);
1473 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 1795 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1474 1796
1475 LoadAndSpill(node->tag()); 1797 LoadAndSpill(node->tag());
1476 1798
1477 JumpTarget next_test; 1799 JumpTarget next_test;
1478 JumpTarget fall_through; 1800 JumpTarget fall_through;
1479 JumpTarget default_entry; 1801 JumpTarget default_entry;
1480 JumpTarget default_exit(JumpTarget::BIDIRECTIONAL); 1802 JumpTarget default_exit(JumpTarget::BIDIRECTIONAL);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1549 } 1871 }
1550 node->break_target()->Unuse(); 1872 node->break_target()->Unuse();
1551 ASSERT(!has_valid_frame() || frame_->height() == original_height); 1873 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1552 } 1874 }
1553 1875
1554 1876
1555 void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) { 1877 void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) {
1556 #ifdef DEBUG 1878 #ifdef DEBUG
1557 int original_height = frame_->height(); 1879 int original_height = frame_->height();
1558 #endif 1880 #endif
1559 VirtualFrame::SpilledScope spilled_scope; 1881 VirtualFrame::SpilledScope spilled_scope(frame_);
1560 Comment cmnt(masm_, "[ DoWhileStatement"); 1882 Comment cmnt(masm_, "[ DoWhileStatement");
1561 CodeForStatementPosition(node); 1883 CodeForStatementPosition(node);
1562 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 1884 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1563 JumpTarget body(JumpTarget::BIDIRECTIONAL); 1885 JumpTarget body(JumpTarget::BIDIRECTIONAL);
1564 1886
1565 // Label the top of the loop for the backward CFG edge. If the test 1887 // Label the top of the loop for the backward CFG edge. If the test
1566 // is always true we can use the continue target, and if the test is 1888 // is always true we can use the continue target, and if the test is
1567 // always false there is no need. 1889 // always false there is no need.
1568 ConditionAnalysis info = AnalyzeCondition(node->cond()); 1890 ConditionAnalysis info = AnalyzeCondition(node->cond());
1569 switch (info) { 1891 switch (info) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1622 node->break_target()->Bind(); 1944 node->break_target()->Bind();
1623 } 1945 }
1624 ASSERT(!has_valid_frame() || frame_->height() == original_height); 1946 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1625 } 1947 }
1626 1948
1627 1949
1628 void CodeGenerator::VisitWhileStatement(WhileStatement* node) { 1950 void CodeGenerator::VisitWhileStatement(WhileStatement* node) {
1629 #ifdef DEBUG 1951 #ifdef DEBUG
1630 int original_height = frame_->height(); 1952 int original_height = frame_->height();
1631 #endif 1953 #endif
1632 VirtualFrame::SpilledScope spilled_scope; 1954 VirtualFrame::SpilledScope spilled_scope(frame_);
1633 Comment cmnt(masm_, "[ WhileStatement"); 1955 Comment cmnt(masm_, "[ WhileStatement");
1634 CodeForStatementPosition(node); 1956 CodeForStatementPosition(node);
1635 1957
1636 // If the test is never true and has no side effects there is no need 1958 // If the test is never true and has no side effects there is no need
1637 // to compile the test or body. 1959 // to compile the test or body.
1638 ConditionAnalysis info = AnalyzeCondition(node->cond()); 1960 ConditionAnalysis info = AnalyzeCondition(node->cond());
1639 if (info == ALWAYS_FALSE) return; 1961 if (info == ALWAYS_FALSE) return;
1640 1962
1641 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 1963 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1642 1964
(...skipping 28 matching lines...) Expand all
1671 node->break_target()->Bind(); 1993 node->break_target()->Bind();
1672 } 1994 }
1673 ASSERT(!has_valid_frame() || frame_->height() == original_height); 1995 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1674 } 1996 }
1675 1997
1676 1998
1677 void CodeGenerator::VisitForStatement(ForStatement* node) { 1999 void CodeGenerator::VisitForStatement(ForStatement* node) {
1678 #ifdef DEBUG 2000 #ifdef DEBUG
1679 int original_height = frame_->height(); 2001 int original_height = frame_->height();
1680 #endif 2002 #endif
1681 VirtualFrame::SpilledScope spilled_scope; 2003 VirtualFrame::SpilledScope spilled_scope(frame_);
1682 Comment cmnt(masm_, "[ ForStatement"); 2004 Comment cmnt(masm_, "[ ForStatement");
1683 CodeForStatementPosition(node); 2005 CodeForStatementPosition(node);
1684 if (node->init() != NULL) { 2006 if (node->init() != NULL) {
1685 VisitAndSpill(node->init()); 2007 VisitAndSpill(node->init());
1686 } 2008 }
1687 2009
1688 // If the test is never true there is no need to compile the test or 2010 // If the test is never true there is no need to compile the test or
1689 // body. 2011 // body.
1690 ConditionAnalysis info = AnalyzeCondition(node->cond()); 2012 ConditionAnalysis info = AnalyzeCondition(node->cond());
1691 if (info == ALWAYS_FALSE) return; 2013 if (info == ALWAYS_FALSE) return;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1746 node->break_target()->Bind(); 2068 node->break_target()->Bind();
1747 } 2069 }
1748 ASSERT(!has_valid_frame() || frame_->height() == original_height); 2070 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1749 } 2071 }
1750 2072
1751 2073
1752 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 2074 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
1753 #ifdef DEBUG 2075 #ifdef DEBUG
1754 int original_height = frame_->height(); 2076 int original_height = frame_->height();
1755 #endif 2077 #endif
1756 VirtualFrame::SpilledScope spilled_scope; 2078 VirtualFrame::SpilledScope spilled_scope(frame_);
1757 Comment cmnt(masm_, "[ ForInStatement"); 2079 Comment cmnt(masm_, "[ ForInStatement");
1758 CodeForStatementPosition(node); 2080 CodeForStatementPosition(node);
1759 2081
1760 JumpTarget primitive; 2082 JumpTarget primitive;
1761 JumpTarget jsobject; 2083 JumpTarget jsobject;
1762 JumpTarget fixed_array; 2084 JumpTarget fixed_array;
1763 JumpTarget entry(JumpTarget::BIDIRECTIONAL); 2085 JumpTarget entry(JumpTarget::BIDIRECTIONAL);
1764 JumpTarget end_del_check; 2086 JumpTarget end_del_check;
1765 JumpTarget exit; 2087 JumpTarget exit;
1766 2088
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1982 node->continue_target()->Unuse(); 2304 node->continue_target()->Unuse();
1983 node->break_target()->Unuse(); 2305 node->break_target()->Unuse();
1984 ASSERT(frame_->height() == original_height); 2306 ASSERT(frame_->height() == original_height);
1985 } 2307 }
1986 2308
1987 2309
1988 void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) { 2310 void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) {
1989 #ifdef DEBUG 2311 #ifdef DEBUG
1990 int original_height = frame_->height(); 2312 int original_height = frame_->height();
1991 #endif 2313 #endif
1992 VirtualFrame::SpilledScope spilled_scope; 2314 VirtualFrame::SpilledScope spilled_scope(frame_);
1993 Comment cmnt(masm_, "[ TryCatchStatement"); 2315 Comment cmnt(masm_, "[ TryCatchStatement");
1994 CodeForStatementPosition(node); 2316 CodeForStatementPosition(node);
1995 2317
1996 JumpTarget try_block; 2318 JumpTarget try_block;
1997 JumpTarget exit; 2319 JumpTarget exit;
1998 2320
1999 try_block.Call(); 2321 try_block.Call();
2000 // --- Catch block --- 2322 // --- Catch block ---
2001 frame_->EmitPush(r0); 2323 frame_->EmitPush(r0);
2002 2324
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2103 2425
2104 exit.Bind(); 2426 exit.Bind();
2105 ASSERT(!has_valid_frame() || frame_->height() == original_height); 2427 ASSERT(!has_valid_frame() || frame_->height() == original_height);
2106 } 2428 }
2107 2429
2108 2430
2109 void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) { 2431 void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) {
2110 #ifdef DEBUG 2432 #ifdef DEBUG
2111 int original_height = frame_->height(); 2433 int original_height = frame_->height();
2112 #endif 2434 #endif
2113 VirtualFrame::SpilledScope spilled_scope; 2435 VirtualFrame::SpilledScope spilled_scope(frame_);
2114 Comment cmnt(masm_, "[ TryFinallyStatement"); 2436 Comment cmnt(masm_, "[ TryFinallyStatement");
2115 CodeForStatementPosition(node); 2437 CodeForStatementPosition(node);
2116 2438
2117 // State: Used to keep track of reason for entering the finally 2439 // State: Used to keep track of reason for entering the finally
2118 // block. Should probably be extended to hold information for 2440 // block. Should probably be extended to hold information for
2119 // break/continue from within the try block. 2441 // break/continue from within the try block.
2120 enum { FALLING, THROWING, JUMPING }; 2442 enum { FALLING, THROWING, JUMPING };
2121 2443
2122 JumpTarget try_block; 2444 JumpTarget try_block;
2123 JumpTarget finally_block; 2445 JumpTarget finally_block;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
2287 exit.Bind(); 2609 exit.Bind();
2288 } 2610 }
2289 ASSERT(!has_valid_frame() || frame_->height() == original_height); 2611 ASSERT(!has_valid_frame() || frame_->height() == original_height);
2290 } 2612 }
2291 2613
2292 2614
2293 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { 2615 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
2294 #ifdef DEBUG 2616 #ifdef DEBUG
2295 int original_height = frame_->height(); 2617 int original_height = frame_->height();
2296 #endif 2618 #endif
2297 VirtualFrame::SpilledScope spilled_scope; 2619 VirtualFrame::SpilledScope spilled_scope(frame_);
2298 Comment cmnt(masm_, "[ DebuggerStatament"); 2620 Comment cmnt(masm_, "[ DebuggerStatament");
2299 CodeForStatementPosition(node); 2621 CodeForStatementPosition(node);
2300 #ifdef ENABLE_DEBUGGER_SUPPORT 2622 #ifdef ENABLE_DEBUGGER_SUPPORT
2301 frame_->DebugBreak(); 2623 frame_->DebugBreak();
2302 #endif 2624 #endif
2303 // Ignore the return value. 2625 // Ignore the return value.
2304 ASSERT(frame_->height() == original_height); 2626 ASSERT(frame_->height() == original_height);
2305 } 2627 }
2306 2628
2307 2629
2308 void CodeGenerator::InstantiateFunction( 2630 void CodeGenerator::InstantiateFunction(
2309 Handle<SharedFunctionInfo> function_info) { 2631 Handle<SharedFunctionInfo> function_info) {
2310 VirtualFrame::SpilledScope spilled_scope; 2632 VirtualFrame::SpilledScope spilled_scope(frame_);
2311 __ mov(r0, Operand(function_info)); 2633 __ mov(r0, Operand(function_info));
2312 // Use the fast case closure allocation code that allocates in new 2634 // Use the fast case closure allocation code that allocates in new
2313 // space for nested functions that don't need literals cloning. 2635 // space for nested functions that don't need literals cloning.
2314 if (scope()->is_function_scope() && function_info->num_literals() == 0) { 2636 if (scope()->is_function_scope() && function_info->num_literals() == 0) {
2315 FastNewClosureStub stub; 2637 FastNewClosureStub stub;
2316 frame_->EmitPush(r0); 2638 frame_->EmitPush(r0);
2317 frame_->CallStub(&stub, 1); 2639 frame_->CallStub(&stub, 1);
2318 frame_->EmitPush(r0); 2640 frame_->EmitPush(r0);
2319 } else { 2641 } else {
2320 // Create a new closure. 2642 // Create a new closure.
2321 frame_->EmitPush(cp); 2643 frame_->EmitPush(cp);
2322 frame_->EmitPush(r0); 2644 frame_->EmitPush(r0);
2323 frame_->CallRuntime(Runtime::kNewClosure, 2); 2645 frame_->CallRuntime(Runtime::kNewClosure, 2);
2324 frame_->EmitPush(r0); 2646 frame_->EmitPush(r0);
2325 } 2647 }
2326 } 2648 }
2327 2649
2328 2650
2329 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 2651 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
2330 #ifdef DEBUG 2652 #ifdef DEBUG
2331 int original_height = frame_->height(); 2653 int original_height = frame_->height();
2332 #endif 2654 #endif
2333 VirtualFrame::SpilledScope spilled_scope; 2655 VirtualFrame::SpilledScope spilled_scope(frame_);
2334 Comment cmnt(masm_, "[ FunctionLiteral"); 2656 Comment cmnt(masm_, "[ FunctionLiteral");
2335 2657
2336 // Build the function info and instantiate it. 2658 // Build the function info and instantiate it.
2337 Handle<SharedFunctionInfo> function_info = 2659 Handle<SharedFunctionInfo> function_info =
2338 Compiler::BuildFunctionInfo(node, script(), this); 2660 Compiler::BuildFunctionInfo(node, script(), this);
2339 // Check for stack-overflow exception. 2661 // Check for stack-overflow exception.
2340 if (HasStackOverflow()) { 2662 if (HasStackOverflow()) {
2341 ASSERT(frame_->height() == original_height); 2663 ASSERT(frame_->height() == original_height);
2342 return; 2664 return;
2343 } 2665 }
2344 InstantiateFunction(function_info); 2666 InstantiateFunction(function_info);
2345 ASSERT(frame_->height() == original_height + 1); 2667 ASSERT(frame_->height() == original_height + 1);
2346 } 2668 }
2347 2669
2348 2670
2349 void CodeGenerator::VisitSharedFunctionInfoLiteral( 2671 void CodeGenerator::VisitSharedFunctionInfoLiteral(
2350 SharedFunctionInfoLiteral* node) { 2672 SharedFunctionInfoLiteral* node) {
2351 #ifdef DEBUG 2673 #ifdef DEBUG
2352 int original_height = frame_->height(); 2674 int original_height = frame_->height();
2353 #endif 2675 #endif
2354 VirtualFrame::SpilledScope spilled_scope; 2676 VirtualFrame::SpilledScope spilled_scope(frame_);
2355 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral"); 2677 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
2356 InstantiateFunction(node->shared_function_info()); 2678 InstantiateFunction(node->shared_function_info());
2357 ASSERT(frame_->height() == original_height + 1); 2679 ASSERT(frame_->height() == original_height + 1);
2358 } 2680 }
2359 2681
2360 2682
2361 void CodeGenerator::VisitConditional(Conditional* node) { 2683 void CodeGenerator::VisitConditional(Conditional* node) {
2362 #ifdef DEBUG 2684 #ifdef DEBUG
2363 int original_height = frame_->height(); 2685 int original_height = frame_->height();
2364 #endif 2686 #endif
2365 VirtualFrame::SpilledScope spilled_scope; 2687 VirtualFrame::SpilledScope spilled_scope(frame_);
2366 Comment cmnt(masm_, "[ Conditional"); 2688 Comment cmnt(masm_, "[ Conditional");
2367 JumpTarget then; 2689 JumpTarget then;
2368 JumpTarget else_; 2690 JumpTarget else_;
2369 LoadConditionAndSpill(node->condition(), &then, &else_, true); 2691 LoadConditionAndSpill(node->condition(), &then, &else_, true);
2370 if (has_valid_frame()) { 2692 if (has_valid_frame()) {
2371 Branch(false, &else_); 2693 Branch(false, &else_);
2372 } 2694 }
2373 if (has_valid_frame() || then.is_linked()) { 2695 if (has_valid_frame() || then.is_linked()) {
2374 then.Bind(); 2696 then.Bind();
2375 LoadAndSpill(node->then_expression()); 2697 LoadAndSpill(node->then_expression());
2376 } 2698 }
2377 if (else_.is_linked()) { 2699 if (else_.is_linked()) {
2378 JumpTarget exit; 2700 JumpTarget exit;
2379 if (has_valid_frame()) exit.Jump(); 2701 if (has_valid_frame()) exit.Jump();
2380 else_.Bind(); 2702 else_.Bind();
2381 LoadAndSpill(node->else_expression()); 2703 LoadAndSpill(node->else_expression());
2382 if (exit.is_linked()) exit.Bind(); 2704 if (exit.is_linked()) exit.Bind();
2383 } 2705 }
2384 ASSERT(frame_->height() == original_height + 1); 2706 ASSERT(frame_->height() == original_height + 1);
2385 } 2707 }
2386 2708
2387 2709
2388 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2710 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2389 VirtualFrame::SpilledScope spilled_scope;
2390 if (slot->type() == Slot::LOOKUP) { 2711 if (slot->type() == Slot::LOOKUP) {
2712 VirtualFrame::SpilledScope spilled_scope(frame_);
2391 ASSERT(slot->var()->is_dynamic()); 2713 ASSERT(slot->var()->is_dynamic());
2392 2714
2393 JumpTarget slow; 2715 JumpTarget slow;
2394 JumpTarget done; 2716 JumpTarget done;
2395 2717
2396 // Generate fast-case code for variables that might be shadowed by 2718 // Generate fast-case code for variables that might be shadowed by
2397 // eval-introduced variables. Eval is used a lot without 2719 // eval-introduced variables. Eval is used a lot without
2398 // introducing variables. In those cases, we do not want to 2720 // introducing variables. In those cases, we do not want to
2399 // perform a runtime call for all variables in the scope 2721 // perform a runtime call for all variables in the scope
2400 // containing the eval. 2722 // containing the eval.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2438 if (typeof_state == INSIDE_TYPEOF) { 2760 if (typeof_state == INSIDE_TYPEOF) {
2439 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2761 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2440 } else { 2762 } else {
2441 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 2763 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
2442 } 2764 }
2443 2765
2444 done.Bind(); 2766 done.Bind();
2445 frame_->EmitPush(r0); 2767 frame_->EmitPush(r0);
2446 2768
2447 } else { 2769 } else {
2448 // Special handling for locals allocated in registers. 2770 Register scratch = VirtualFrame::scratch0();
2449 __ ldr(r0, SlotOperand(slot, r2)); 2771 frame_->EmitPush(SlotOperand(slot, scratch));
2450 frame_->EmitPush(r0);
2451 if (slot->var()->mode() == Variable::CONST) { 2772 if (slot->var()->mode() == Variable::CONST) {
2452 // Const slots may contain 'the hole' value (the constant hasn't been 2773 // Const slots may contain 'the hole' value (the constant hasn't been
2453 // initialized yet) which needs to be converted into the 'undefined' 2774 // initialized yet) which needs to be converted into the 'undefined'
2454 // value. 2775 // value.
2455 Comment cmnt(masm_, "[ Unhole const"); 2776 Comment cmnt(masm_, "[ Unhole const");
2456 frame_->EmitPop(r0); 2777 frame_->EmitPop(scratch);
2457 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2778 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2458 __ cmp(r0, ip); 2779 __ cmp(scratch, ip);
2459 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 2780 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex, eq);
2460 frame_->EmitPush(r0); 2781 frame_->EmitPush(scratch);
2461 } 2782 }
2462 } 2783 }
2463 } 2784 }
2464 2785
2465 2786
2466 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { 2787 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
2467 ASSERT(slot != NULL); 2788 ASSERT(slot != NULL);
2468 if (slot->type() == Slot::LOOKUP) { 2789 if (slot->type() == Slot::LOOKUP) {
2790 VirtualFrame::SpilledScope spilled_scope(frame_);
2469 ASSERT(slot->var()->is_dynamic()); 2791 ASSERT(slot->var()->is_dynamic());
2470 2792
2471 // For now, just do a runtime call. 2793 // For now, just do a runtime call.
2472 frame_->EmitPush(cp); 2794 frame_->EmitPush(cp);
2473 __ mov(r0, Operand(slot->var()->name())); 2795 __ mov(r0, Operand(slot->var()->name()));
2474 frame_->EmitPush(r0); 2796 frame_->EmitPush(r0);
2475 2797
2476 if (init_state == CONST_INIT) { 2798 if (init_state == CONST_INIT) {
2477 // Same as the case for a normal store, but ignores attribute 2799 // Same as the case for a normal store, but ignores attribute
2478 // (e.g. READ_ONLY) of context slot so that we can initialize 2800 // (e.g. READ_ONLY) of context slot so that we can initialize
(...skipping 13 matching lines...) Expand all
2492 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2814 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2493 } else { 2815 } else {
2494 frame_->CallRuntime(Runtime::kStoreContextSlot, 3); 2816 frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
2495 } 2817 }
2496 // Storing a variable must keep the (new) value on the expression 2818 // Storing a variable must keep the (new) value on the expression
2497 // stack. This is necessary for compiling assignment expressions. 2819 // stack. This is necessary for compiling assignment expressions.
2498 frame_->EmitPush(r0); 2820 frame_->EmitPush(r0);
2499 2821
2500 } else { 2822 } else {
2501 ASSERT(!slot->var()->is_dynamic()); 2823 ASSERT(!slot->var()->is_dynamic());
2824 Register scratch = VirtualFrame::scratch0();
2825 VirtualFrame::RegisterAllocationScope scope(this);
2502 2826
2827 // The frame must be spilled when branching to this target.
2503 JumpTarget exit; 2828 JumpTarget exit;
2829
2504 if (init_state == CONST_INIT) { 2830 if (init_state == CONST_INIT) {
2505 ASSERT(slot->var()->mode() == Variable::CONST); 2831 ASSERT(slot->var()->mode() == Variable::CONST);
2506 // Only the first const initialization must be executed (the slot 2832 // Only the first const initialization must be executed (the slot
2507 // still contains 'the hole' value). When the assignment is 2833 // still contains 'the hole' value). When the assignment is
2508 // executed, the code is identical to a normal store (see below). 2834 // executed, the code is identical to a normal store (see below).
2509 Comment cmnt(masm_, "[ Init const"); 2835 Comment cmnt(masm_, "[ Init const");
2510 __ ldr(r2, SlotOperand(slot, r2)); 2836 __ ldr(scratch, SlotOperand(slot, scratch));
2511 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2837 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2512 __ cmp(r2, ip); 2838 __ cmp(scratch, ip);
2839 frame_->SpillAll();
2513 exit.Branch(ne); 2840 exit.Branch(ne);
2514 } 2841 }
2515 2842
2516 // We must execute the store. Storing a variable must keep the 2843 // We must execute the store. Storing a variable must keep the
2517 // (new) value on the stack. This is necessary for compiling 2844 // (new) value on the stack. This is necessary for compiling
2518 // assignment expressions. 2845 // assignment expressions.
2519 // 2846 //
2520 // Note: We will reach here even with slot->var()->mode() == 2847 // Note: We will reach here even with slot->var()->mode() ==
2521 // Variable::CONST because of const declarations which will 2848 // Variable::CONST because of const declarations which will
2522 // initialize consts to 'the hole' value and by doing so, end up 2849 // initialize consts to 'the hole' value and by doing so, end up
2523 // calling this code. r2 may be loaded with context; used below in 2850 // calling this code. r2 may be loaded with context; used below in
2524 // RecordWrite. 2851 // RecordWrite.
2525 frame_->EmitPop(r0); 2852 Register tos = frame_->Peek();
2526 __ str(r0, SlotOperand(slot, r2)); 2853 __ str(tos, SlotOperand(slot, scratch));
2527 frame_->EmitPush(r0);
2528 if (slot->type() == Slot::CONTEXT) { 2854 if (slot->type() == Slot::CONTEXT) {
2529 // Skip write barrier if the written value is a smi. 2855 // Skip write barrier if the written value is a smi.
2530 __ tst(r0, Operand(kSmiTagMask)); 2856 __ tst(tos, Operand(kSmiTagMask));
2857 VirtualFrame::SpilledScope spilled_scope(frame_);
2531 exit.Branch(eq); 2858 exit.Branch(eq);
2532 // r2 is loaded with context when calling SlotOperand above. 2859 // scratch is loaded with context when calling SlotOperand above.
2533 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 2860 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
Søren Thygesen Gjesse 2010/04/07 10:46:51 VirtualFrame::scratchX()?
Erik Corry 2010/04/07 12:49:17 We are in a spilled scope here.
2534 __ mov(r3, Operand(offset)); 2861 __ mov(r3, Operand(offset));
2535 __ RecordWrite(r2, r3, r1); 2862 __ RecordWrite(scratch, r3, r1);
Søren Thygesen Gjesse 2010/04/07 10:46:51 What about r1 here, will tos always be r0? If so a
Erik Corry 2010/04/07 12:49:17 r1 is a scratch register, but we don't use tos any
2536 } 2863 }
2537 // If we definitely did not jump over the assignment, we do not need 2864 // If we definitely did not jump over the assignment, we do not need
2538 // to bind the exit label. Doing so can defeat peephole 2865 // to bind the exit label. Doing so can defeat peephole
2539 // optimization. 2866 // optimization.
2540 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { 2867 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) {
2868 frame_->SpillAll();
2541 exit.Bind(); 2869 exit.Bind();
2542 } 2870 }
2543 } 2871 }
2544 } 2872 }
2545 2873
2546 2874
2547 void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot, 2875 void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot,
2548 TypeofState typeof_state, 2876 TypeofState typeof_state,
2549 Register tmp, 2877 Register tmp,
2550 Register tmp2, 2878 Register tmp2,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 2938
2611 // Drop the global object. The result is in r0. 2939 // Drop the global object. The result is in r0.
2612 frame_->Drop(); 2940 frame_->Drop();
2613 } 2941 }
2614 2942
2615 2943
2616 void CodeGenerator::VisitSlot(Slot* node) { 2944 void CodeGenerator::VisitSlot(Slot* node) {
2617 #ifdef DEBUG 2945 #ifdef DEBUG
2618 int original_height = frame_->height(); 2946 int original_height = frame_->height();
2619 #endif 2947 #endif
2620 VirtualFrame::SpilledScope spilled_scope;
2621 Comment cmnt(masm_, "[ Slot"); 2948 Comment cmnt(masm_, "[ Slot");
2622 LoadFromSlot(node, NOT_INSIDE_TYPEOF); 2949 LoadFromSlot(node, NOT_INSIDE_TYPEOF);
2623 ASSERT(frame_->height() == original_height + 1); 2950 ASSERT(frame_->height() == original_height + 1);
2624 } 2951 }
2625 2952
2626 2953
2627 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2954 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
2628 #ifdef DEBUG 2955 #ifdef DEBUG
2629 int original_height = frame_->height(); 2956 int original_height = frame_->height();
2630 #endif 2957 #endif
2631 VirtualFrame::SpilledScope spilled_scope;
2632 Comment cmnt(masm_, "[ VariableProxy"); 2958 Comment cmnt(masm_, "[ VariableProxy");
2633 2959
2634 Variable* var = node->var(); 2960 Variable* var = node->var();
2635 Expression* expr = var->rewrite(); 2961 Expression* expr = var->rewrite();
2636 if (expr != NULL) { 2962 if (expr != NULL) {
2637 Visit(expr); 2963 Visit(expr);
2638 } else { 2964 } else {
2639 ASSERT(var->is_global()); 2965 ASSERT(var->is_global());
2640 Reference ref(this, node); 2966 Reference ref(this, node);
2641 ref.GetValueAndSpill(); 2967 ref.GetValue();
2642 } 2968 }
2643 ASSERT(frame_->height() == original_height + 1); 2969 ASSERT(frame_->height() == original_height + 1);
2644 } 2970 }
2645 2971
2646 2972
2647 void CodeGenerator::VisitLiteral(Literal* node) { 2973 void CodeGenerator::VisitLiteral(Literal* node) {
2648 #ifdef DEBUG 2974 #ifdef DEBUG
2649 int original_height = frame_->height(); 2975 int original_height = frame_->height();
2650 #endif 2976 #endif
2651 VirtualFrame::SpilledScope spilled_scope;
2652 Comment cmnt(masm_, "[ Literal"); 2977 Comment cmnt(masm_, "[ Literal");
2653 __ mov(r0, Operand(node->handle())); 2978 Register reg = frame_->GetTOSRegister();
2654 frame_->EmitPush(r0); 2979 __ mov(reg, Operand(node->handle()));
2980 frame_->EmitPush(reg);
2655 ASSERT(frame_->height() == original_height + 1); 2981 ASSERT(frame_->height() == original_height + 1);
2656 } 2982 }
2657 2983
2658 2984
2659 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 2985 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
2660 #ifdef DEBUG 2986 #ifdef DEBUG
2661 int original_height = frame_->height(); 2987 int original_height = frame_->height();
2662 #endif 2988 #endif
2663 VirtualFrame::SpilledScope spilled_scope; 2989 VirtualFrame::SpilledScope spilled_scope(frame_);
2664 Comment cmnt(masm_, "[ RexExp Literal"); 2990 Comment cmnt(masm_, "[ RexExp Literal");
2665 2991
2666 // Retrieve the literal array and check the allocated entry. 2992 // Retrieve the literal array and check the allocated entry.
2667 2993
2668 // Load the function of this activation. 2994 // Load the function of this activation.
2669 __ ldr(r1, frame_->Function()); 2995 __ ldr(r1, frame_->Function());
2670 2996
2671 // Load the literals array of the function. 2997 // Load the literals array of the function.
2672 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); 2998 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
2673 2999
(...skipping 23 matching lines...) Expand all
2697 // Push the literal. 3023 // Push the literal.
2698 frame_->EmitPush(r2); 3024 frame_->EmitPush(r2);
2699 ASSERT(frame_->height() == original_height + 1); 3025 ASSERT(frame_->height() == original_height + 1);
2700 } 3026 }
2701 3027
2702 3028
2703 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 3029 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
2704 #ifdef DEBUG 3030 #ifdef DEBUG
2705 int original_height = frame_->height(); 3031 int original_height = frame_->height();
2706 #endif 3032 #endif
2707 VirtualFrame::SpilledScope spilled_scope; 3033 VirtualFrame::SpilledScope spilled_scope(frame_);
2708 Comment cmnt(masm_, "[ ObjectLiteral"); 3034 Comment cmnt(masm_, "[ ObjectLiteral");
2709 3035
2710 // Load the function of this activation. 3036 // Load the function of this activation.
2711 __ ldr(r3, frame_->Function()); 3037 __ ldr(r3, frame_->Function());
2712 // Literal array. 3038 // Literal array.
2713 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 3039 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
2714 // Literal index. 3040 // Literal index.
2715 __ mov(r2, Operand(Smi::FromInt(node->literal_index()))); 3041 __ mov(r2, Operand(Smi::FromInt(node->literal_index())));
2716 // Constant properties. 3042 // Constant properties.
2717 __ mov(r1, Operand(node->constant_properties())); 3043 __ mov(r1, Operand(node->constant_properties()));
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2778 } 3104 }
2779 } 3105 }
2780 ASSERT(frame_->height() == original_height + 1); 3106 ASSERT(frame_->height() == original_height + 1);
2781 } 3107 }
2782 3108
2783 3109
2784 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 3110 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
2785 #ifdef DEBUG 3111 #ifdef DEBUG
2786 int original_height = frame_->height(); 3112 int original_height = frame_->height();
2787 #endif 3113 #endif
2788 VirtualFrame::SpilledScope spilled_scope; 3114 VirtualFrame::SpilledScope spilled_scope(frame_);
2789 Comment cmnt(masm_, "[ ArrayLiteral"); 3115 Comment cmnt(masm_, "[ ArrayLiteral");
2790 3116
2791 // Load the function of this activation. 3117 // Load the function of this activation.
2792 __ ldr(r2, frame_->Function()); 3118 __ ldr(r2, frame_->Function());
2793 // Load the literals array of the function. 3119 // Load the literals array of the function.
2794 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); 3120 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset));
2795 __ mov(r1, Operand(Smi::FromInt(node->literal_index()))); 3121 __ mov(r1, Operand(Smi::FromInt(node->literal_index())));
2796 __ mov(r0, Operand(node->constant_elements())); 3122 __ mov(r0, Operand(node->constant_elements()));
2797 frame_->EmitPushMultiple(3, r2.bit() | r1.bit() | r0.bit()); 3123 frame_->EmitPushMultiple(3, r2.bit() | r1.bit() | r0.bit());
2798 int length = node->values()->length(); 3124 int length = node->values()->length();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2837 __ RecordWrite(r1, r3, r2); 3163 __ RecordWrite(r1, r3, r2);
2838 } 3164 }
2839 ASSERT(frame_->height() == original_height + 1); 3165 ASSERT(frame_->height() == original_height + 1);
2840 } 3166 }
2841 3167
2842 3168
2843 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { 3169 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) {
2844 #ifdef DEBUG 3170 #ifdef DEBUG
2845 int original_height = frame_->height(); 3171 int original_height = frame_->height();
2846 #endif 3172 #endif
2847 VirtualFrame::SpilledScope spilled_scope; 3173 VirtualFrame::SpilledScope spilled_scope(frame_);
2848 // Call runtime routine to allocate the catch extension object and 3174 // Call runtime routine to allocate the catch extension object and
2849 // assign the exception value to the catch variable. 3175 // assign the exception value to the catch variable.
2850 Comment cmnt(masm_, "[ CatchExtensionObject"); 3176 Comment cmnt(masm_, "[ CatchExtensionObject");
2851 LoadAndSpill(node->key()); 3177 LoadAndSpill(node->key());
2852 LoadAndSpill(node->value()); 3178 LoadAndSpill(node->value());
2853 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); 3179 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
2854 frame_->EmitPush(r0); 3180 frame_->EmitPush(r0);
2855 ASSERT(frame_->height() == original_height + 1); 3181 ASSERT(frame_->height() == original_height + 1);
2856 } 3182 }
2857 3183
2858 3184
2859 void CodeGenerator::VisitAssignment(Assignment* node) { 3185 void CodeGenerator::VisitAssignment(Assignment* node) {
3186 VirtualFrame::RegisterAllocationScope scope(this);
2860 #ifdef DEBUG 3187 #ifdef DEBUG
2861 int original_height = frame_->height(); 3188 int original_height = frame_->height();
2862 #endif 3189 #endif
2863 VirtualFrame::SpilledScope spilled_scope;
2864 Comment cmnt(masm_, "[ Assignment"); 3190 Comment cmnt(masm_, "[ Assignment");
2865 3191
2866 { Reference target(this, node->target(), node->is_compound()); 3192 { Reference target(this, node->target(), node->is_compound());
2867 if (target.is_illegal()) { 3193 if (target.is_illegal()) {
2868 // Fool the virtual frame into thinking that we left the assignment's 3194 // Fool the virtual frame into thinking that we left the assignment's
2869 // value on the frame. 3195 // value on the frame.
2870 __ mov(r0, Operand(Smi::FromInt(0))); 3196 Register tos = frame_->GetTOSRegister();
2871 frame_->EmitPush(r0); 3197 __ mov(tos, Operand(Smi::FromInt(0)));
3198 frame_->EmitPush(tos);
2872 ASSERT(frame_->height() == original_height + 1); 3199 ASSERT(frame_->height() == original_height + 1);
2873 return; 3200 return;
2874 } 3201 }
2875 3202
2876 if (node->op() == Token::ASSIGN || 3203 if (node->op() == Token::ASSIGN ||
2877 node->op() == Token::INIT_VAR || 3204 node->op() == Token::INIT_VAR ||
2878 node->op() == Token::INIT_CONST) { 3205 node->op() == Token::INIT_CONST) {
2879 LoadAndSpill(node->value()); 3206 Load(node->value());
2880 3207
2881 } else { // Assignment is a compound assignment. 3208 } else { // Assignment is a compound assignment.
2882 // Get the old value of the lhs. 3209 // Get the old value of the lhs.
2883 target.GetValueAndSpill(); 3210 target.GetValue();
2884 Literal* literal = node->value()->AsLiteral(); 3211 Literal* literal = node->value()->AsLiteral();
2885 bool overwrite = 3212 bool overwrite =
2886 (node->value()->AsBinaryOperation() != NULL && 3213 (node->value()->AsBinaryOperation() != NULL &&
2887 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 3214 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
2888 if (literal != NULL && literal->handle()->IsSmi()) { 3215 if (literal != NULL && literal->handle()->IsSmi()) {
2889 SmiOperation(node->binary_op(), 3216 VirtualFrameSmiOperation(node->binary_op(),
Søren Thygesen Gjesse 2010/04/07 07:53:37 VirtualFrameSmiOperation -> VirtualFrameSmiCompoun
Erik Corry 2010/04/07 12:49:17 I think that's too long. The non-virtual frame ba
2890 literal->handle(), 3217 literal->handle(),
2891 false, 3218 false,
2892 overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE); 3219 overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
2893 frame_->EmitPush(r0);
2894
2895 } else { 3220 } else {
2896 LoadAndSpill(node->value()); 3221 Load(node->value());
2897 GenericBinaryOperation(node->binary_op(), 3222 VirtualFrameBinaryOperation(node->binary_op(),
2898 overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE); 3223 overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
2899 frame_->EmitPush(r0);
2900 } 3224 }
2901 } 3225 }
2902 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 3226 Variable* var = node->target()->AsVariableProxy()->AsVariable();
2903 if (var != NULL && 3227 if (var != NULL &&
2904 (var->mode() == Variable::CONST) && 3228 (var->mode() == Variable::CONST) &&
2905 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 3229 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
2906 // Assignment ignored - leave the value on the stack. 3230 // Assignment ignored - leave the value on the stack.
2907 UnloadReference(&target); 3231 UnloadReference(&target);
2908 } else { 3232 } else {
2909 CodeForSourcePosition(node->position()); 3233 CodeForSourcePosition(node->position());
2910 if (node->op() == Token::INIT_CONST) { 3234 if (node->op() == Token::INIT_CONST) {
2911 // Dynamic constant initializations must use the function context 3235 // Dynamic constant initializations must use the function context
2912 // and initialize the actual constant declared. Dynamic variable 3236 // and initialize the actual constant declared. Dynamic variable
2913 // initializations are simply assignments and use SetValue. 3237 // initializations are simply assignments and use SetValue.
2914 target.SetValue(CONST_INIT); 3238 target.SetValue(CONST_INIT);
2915 } else { 3239 } else {
2916 target.SetValue(NOT_CONST_INIT); 3240 target.SetValue(NOT_CONST_INIT);
2917 } 3241 }
2918 } 3242 }
2919 } 3243 }
2920 ASSERT(frame_->height() == original_height + 1); 3244 ASSERT(frame_->height() == original_height + 1);
2921 } 3245 }
2922 3246
2923 3247
2924 void CodeGenerator::VisitThrow(Throw* node) { 3248 void CodeGenerator::VisitThrow(Throw* node) {
2925 #ifdef DEBUG 3249 #ifdef DEBUG
2926 int original_height = frame_->height(); 3250 int original_height = frame_->height();
2927 #endif 3251 #endif
2928 VirtualFrame::SpilledScope spilled_scope; 3252 VirtualFrame::SpilledScope spilled_scope(frame_);
2929 Comment cmnt(masm_, "[ Throw"); 3253 Comment cmnt(masm_, "[ Throw");
2930 3254
2931 LoadAndSpill(node->exception()); 3255 LoadAndSpill(node->exception());
2932 CodeForSourcePosition(node->position()); 3256 CodeForSourcePosition(node->position());
2933 frame_->CallRuntime(Runtime::kThrow, 1); 3257 frame_->CallRuntime(Runtime::kThrow, 1);
2934 frame_->EmitPush(r0); 3258 frame_->EmitPush(r0);
2935 ASSERT(frame_->height() == original_height + 1); 3259 ASSERT(frame_->height() == original_height + 1);
2936 } 3260 }
2937 3261
2938 3262
2939 void CodeGenerator::VisitProperty(Property* node) { 3263 void CodeGenerator::VisitProperty(Property* node) {
2940 #ifdef DEBUG 3264 #ifdef DEBUG
2941 int original_height = frame_->height(); 3265 int original_height = frame_->height();
2942 #endif 3266 #endif
2943 VirtualFrame::SpilledScope spilled_scope; 3267 VirtualFrame::SpilledScope spilled_scope(frame_);
2944 Comment cmnt(masm_, "[ Property"); 3268 Comment cmnt(masm_, "[ Property");
2945 3269
2946 { Reference property(this, node); 3270 { Reference property(this, node);
2947 property.GetValueAndSpill(); 3271 property.GetValue();
2948 } 3272 }
2949 ASSERT(frame_->height() == original_height + 1); 3273 ASSERT(frame_->height() == original_height + 1);
2950 } 3274 }
2951 3275
2952 3276
2953 void CodeGenerator::VisitCall(Call* node) { 3277 void CodeGenerator::VisitCall(Call* node) {
2954 #ifdef DEBUG 3278 #ifdef DEBUG
2955 int original_height = frame_->height(); 3279 int original_height = frame_->height();
2956 #endif 3280 #endif
2957 VirtualFrame::SpilledScope spilled_scope; 3281 VirtualFrame::SpilledScope spilled_scope(frame_);
2958 Comment cmnt(masm_, "[ Call"); 3282 Comment cmnt(masm_, "[ Call");
2959 3283
2960 Expression* function = node->expression(); 3284 Expression* function = node->expression();
2961 ZoneList<Expression*>* args = node->arguments(); 3285 ZoneList<Expression*>* args = node->arguments();
2962 3286
2963 // Standard function call. 3287 // Standard function call.
2964 // Check if the function is a variable or a property. 3288 // Check if the function is a variable or a property.
2965 Variable* var = function->AsVariableProxy()->AsVariable(); 3289 Variable* var = function->AsVariableProxy()->AsVariable();
2966 Property* property = function->AsProperty(); 3290 Property* property = function->AsProperty();
2967 3291
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
3138 frame_->EmitPush(r0); 3462 frame_->EmitPush(r0);
3139 } 3463 }
3140 ASSERT(frame_->height() == original_height + 1); 3464 ASSERT(frame_->height() == original_height + 1);
3141 } 3465 }
3142 3466
3143 3467
3144 void CodeGenerator::VisitCallNew(CallNew* node) { 3468 void CodeGenerator::VisitCallNew(CallNew* node) {
3145 #ifdef DEBUG 3469 #ifdef DEBUG
3146 int original_height = frame_->height(); 3470 int original_height = frame_->height();
3147 #endif 3471 #endif
3148 VirtualFrame::SpilledScope spilled_scope; 3472 VirtualFrame::SpilledScope spilled_scope(frame_);
3149 Comment cmnt(masm_, "[ CallNew"); 3473 Comment cmnt(masm_, "[ CallNew");
3150 3474
3151 // According to ECMA-262, section 11.2.2, page 44, the function 3475 // According to ECMA-262, section 11.2.2, page 44, the function
3152 // expression in new calls must be evaluated before the 3476 // expression in new calls must be evaluated before the
3153 // arguments. This is different from ordinary calls, where the 3477 // arguments. This is different from ordinary calls, where the
3154 // actual function to call is resolved after the arguments have been 3478 // actual function to call is resolved after the arguments have been
3155 // evaluated. 3479 // evaluated.
3156 3480
3157 // Compute function to call and use the global object as the 3481 // Compute function to call and use the global object as the
3158 // receiver. There is no need to use the global proxy here because 3482 // receiver. There is no need to use the global proxy here because
(...skipping 19 matching lines...) Expand all
3178 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 3502 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
3179 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); 3503 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1);
3180 3504
3181 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). 3505 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
3182 __ str(r0, frame_->Top()); 3506 __ str(r0, frame_->Top());
3183 ASSERT(frame_->height() == original_height + 1); 3507 ASSERT(frame_->height() == original_height + 1);
3184 } 3508 }
3185 3509
3186 3510
3187 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { 3511 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) {
3188 VirtualFrame::SpilledScope spilled_scope; 3512 VirtualFrame::SpilledScope spilled_scope(frame_);
3189 ASSERT(args->length() == 1); 3513 ASSERT(args->length() == 1);
3190 JumpTarget leave, null, function, non_function_constructor; 3514 JumpTarget leave, null, function, non_function_constructor;
3191 3515
3192 // Load the object into r0. 3516 // Load the object into r0.
3193 LoadAndSpill(args->at(0)); 3517 LoadAndSpill(args->at(0));
3194 frame_->EmitPop(r0); 3518 frame_->EmitPop(r0);
3195 3519
3196 // If the object is a smi, we return null. 3520 // If the object is a smi, we return null.
3197 __ tst(r0, Operand(kSmiTagMask)); 3521 __ tst(r0, Operand(kSmiTagMask));
3198 null.Branch(eq); 3522 null.Branch(eq);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3238 null.Bind(); 3562 null.Bind();
3239 __ LoadRoot(r0, Heap::kNullValueRootIndex); 3563 __ LoadRoot(r0, Heap::kNullValueRootIndex);
3240 frame_->EmitPush(r0); 3564 frame_->EmitPush(r0);
3241 3565
3242 // All done. 3566 // All done.
3243 leave.Bind(); 3567 leave.Bind();
3244 } 3568 }
3245 3569
3246 3570
3247 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 3571 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
3248 VirtualFrame::SpilledScope spilled_scope; 3572 VirtualFrame::SpilledScope spilled_scope(frame_);
3249 ASSERT(args->length() == 1); 3573 ASSERT(args->length() == 1);
3250 JumpTarget leave; 3574 JumpTarget leave;
3251 LoadAndSpill(args->at(0)); 3575 LoadAndSpill(args->at(0));
3252 frame_->EmitPop(r0); // r0 contains object. 3576 frame_->EmitPop(r0); // r0 contains object.
3253 // if (object->IsSmi()) return the object. 3577 // if (object->IsSmi()) return the object.
3254 __ tst(r0, Operand(kSmiTagMask)); 3578 __ tst(r0, Operand(kSmiTagMask));
3255 leave.Branch(eq); 3579 leave.Branch(eq);
3256 // It is a heap object - get map. If (!object->IsJSValue()) return the object. 3580 // It is a heap object - get map. If (!object->IsJSValue()) return the object.
3257 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); 3581 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
3258 leave.Branch(ne); 3582 leave.Branch(ne);
3259 // Load the value. 3583 // Load the value.
3260 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 3584 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
3261 leave.Bind(); 3585 leave.Bind();
3262 frame_->EmitPush(r0); 3586 frame_->EmitPush(r0);
3263 } 3587 }
3264 3588
3265 3589
3266 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 3590 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
3267 VirtualFrame::SpilledScope spilled_scope; 3591 VirtualFrame::SpilledScope spilled_scope(frame_);
3268 ASSERT(args->length() == 2); 3592 ASSERT(args->length() == 2);
3269 JumpTarget leave; 3593 JumpTarget leave;
3270 LoadAndSpill(args->at(0)); // Load the object. 3594 LoadAndSpill(args->at(0)); // Load the object.
3271 LoadAndSpill(args->at(1)); // Load the value. 3595 LoadAndSpill(args->at(1)); // Load the value.
3272 frame_->EmitPop(r0); // r0 contains value 3596 frame_->EmitPop(r0); // r0 contains value
3273 frame_->EmitPop(r1); // r1 contains object 3597 frame_->EmitPop(r1); // r1 contains object
3274 // if (object->IsSmi()) return object. 3598 // if (object->IsSmi()) return object.
3275 __ tst(r1, Operand(kSmiTagMask)); 3599 __ tst(r1, Operand(kSmiTagMask));
3276 leave.Branch(eq); 3600 leave.Branch(eq);
3277 // It is a heap object - get map. If (!object->IsJSValue()) return the object. 3601 // It is a heap object - get map. If (!object->IsJSValue()) return the object.
3278 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); 3602 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
3279 leave.Branch(ne); 3603 leave.Branch(ne);
3280 // Store the value. 3604 // Store the value.
3281 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 3605 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
3282 // Update the write barrier. 3606 // Update the write barrier.
3283 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); 3607 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag));
3284 __ RecordWrite(r1, r2, r3); 3608 __ RecordWrite(r1, r2, r3);
3285 // Leave. 3609 // Leave.
3286 leave.Bind(); 3610 leave.Bind();
3287 frame_->EmitPush(r0); 3611 frame_->EmitPush(r0);
3288 } 3612 }
3289 3613
3290 3614
3291 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 3615 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
3292 VirtualFrame::SpilledScope spilled_scope; 3616 VirtualFrame::SpilledScope spilled_scope(frame_);
3293 ASSERT(args->length() == 1); 3617 ASSERT(args->length() == 1);
3294 LoadAndSpill(args->at(0)); 3618 LoadAndSpill(args->at(0));
3295 frame_->EmitPop(r0); 3619 frame_->EmitPop(r0);
3296 __ tst(r0, Operand(kSmiTagMask)); 3620 __ tst(r0, Operand(kSmiTagMask));
3297 cc_reg_ = eq; 3621 cc_reg_ = eq;
3298 } 3622 }
3299 3623
3300 3624
3301 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { 3625 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) {
3302 VirtualFrame::SpilledScope spilled_scope; 3626 VirtualFrame::SpilledScope spilled_scope(frame_);
3303 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc. 3627 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc.
3304 ASSERT_EQ(args->length(), 3); 3628 ASSERT_EQ(args->length(), 3);
3305 #ifdef ENABLE_LOGGING_AND_PROFILING 3629 #ifdef ENABLE_LOGGING_AND_PROFILING
3306 if (ShouldGenerateLog(args->at(0))) { 3630 if (ShouldGenerateLog(args->at(0))) {
3307 LoadAndSpill(args->at(1)); 3631 LoadAndSpill(args->at(1));
3308 LoadAndSpill(args->at(2)); 3632 LoadAndSpill(args->at(2));
3309 __ CallRuntime(Runtime::kLog, 2); 3633 __ CallRuntime(Runtime::kLog, 2);
3310 } 3634 }
3311 #endif 3635 #endif
3312 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 3636 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
3313 frame_->EmitPush(r0); 3637 frame_->EmitPush(r0);
3314 } 3638 }
3315 3639
3316 3640
3317 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3641 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
3318 VirtualFrame::SpilledScope spilled_scope; 3642 VirtualFrame::SpilledScope spilled_scope(frame_);
3319 ASSERT(args->length() == 1); 3643 ASSERT(args->length() == 1);
3320 LoadAndSpill(args->at(0)); 3644 LoadAndSpill(args->at(0));
3321 frame_->EmitPop(r0); 3645 frame_->EmitPop(r0);
3322 __ tst(r0, Operand(kSmiTagMask | 0x80000000u)); 3646 __ tst(r0, Operand(kSmiTagMask | 0x80000000u));
3323 cc_reg_ = eq; 3647 cc_reg_ = eq;
3324 } 3648 }
3325 3649
3326 3650
3327 // Generates the Math.pow method - currently just calls runtime. 3651 // Generates the Math.pow method - currently just calls runtime.
3328 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { 3652 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
(...skipping 11 matching lines...) Expand all
3340 Load(args->at(0)); 3664 Load(args->at(0));
3341 frame_->CallRuntime(Runtime::kMath_sqrt, 1); 3665 frame_->CallRuntime(Runtime::kMath_sqrt, 1);
3342 frame_->EmitPush(r0); 3666 frame_->EmitPush(r0);
3343 } 3667 }
3344 3668
3345 3669
3346 // This should generate code that performs a charCodeAt() call or returns 3670 // This should generate code that performs a charCodeAt() call or returns
3347 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 3671 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
3348 // It is not yet implemented on ARM, so it always goes to the slow case. 3672 // It is not yet implemented on ARM, so it always goes to the slow case.
3349 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3673 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
3350 VirtualFrame::SpilledScope spilled_scope; 3674 VirtualFrame::SpilledScope spilled_scope(frame_);
3351 ASSERT(args->length() == 2); 3675 ASSERT(args->length() == 2);
3352 Comment(masm_, "[ GenerateFastCharCodeAt"); 3676 Comment(masm_, "[ GenerateFastCharCodeAt");
3353 3677
3354 LoadAndSpill(args->at(0)); 3678 LoadAndSpill(args->at(0));
3355 LoadAndSpill(args->at(1)); 3679 LoadAndSpill(args->at(1));
3356 frame_->EmitPop(r0); // Index. 3680 frame_->EmitPop(r0); // Index.
3357 frame_->EmitPop(r1); // String. 3681 frame_->EmitPop(r1); // String.
3358 3682
3359 Label slow, end, not_a_flat_string, ascii_string, try_again_with_new_string; 3683 Label slow, end, not_a_flat_string, ascii_string, try_again_with_new_string;
3360 3684
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
3458 slow_case.Bind(); 3782 slow_case.Bind();
3459 frame_->EmitPush(r0); 3783 frame_->EmitPush(r0);
3460 frame_->CallRuntime(Runtime::kCharFromCode, 1); 3784 frame_->CallRuntime(Runtime::kCharFromCode, 1);
3461 frame_->EmitPush(r0); 3785 frame_->EmitPush(r0);
3462 3786
3463 exit.Bind(); 3787 exit.Bind();
3464 } 3788 }
3465 3789
3466 3790
3467 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3791 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3468 VirtualFrame::SpilledScope spilled_scope; 3792 VirtualFrame::SpilledScope spilled_scope(frame_);
3469 ASSERT(args->length() == 1); 3793 ASSERT(args->length() == 1);
3470 LoadAndSpill(args->at(0)); 3794 LoadAndSpill(args->at(0));
3471 JumpTarget answer; 3795 JumpTarget answer;
3472 // We need the CC bits to come out as not_equal in the case where the 3796 // We need the CC bits to come out as not_equal in the case where the
3473 // object is a smi. This can't be done with the usual test opcode so 3797 // object is a smi. This can't be done with the usual test opcode so
3474 // we use XOR to get the right CC bits. 3798 // we use XOR to get the right CC bits.
3475 frame_->EmitPop(r0); 3799 frame_->EmitPop(r0);
3476 __ and_(r1, r0, Operand(kSmiTagMask)); 3800 __ and_(r1, r0, Operand(kSmiTagMask));
3477 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); 3801 __ eor(r1, r1, Operand(kSmiTagMask), SetCC);
3478 answer.Branch(ne); 3802 answer.Branch(ne);
3479 // It is a heap object - get the map. Check if the object is a JS array. 3803 // It is a heap object - get the map. Check if the object is a JS array.
3480 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 3804 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
3481 answer.Bind(); 3805 answer.Bind();
3482 cc_reg_ = eq; 3806 cc_reg_ = eq;
3483 } 3807 }
3484 3808
3485 3809
3486 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { 3810 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) {
3487 VirtualFrame::SpilledScope spilled_scope; 3811 VirtualFrame::SpilledScope spilled_scope(frame_);
3488 ASSERT(args->length() == 1); 3812 ASSERT(args->length() == 1);
3489 LoadAndSpill(args->at(0)); 3813 LoadAndSpill(args->at(0));
3490 JumpTarget answer; 3814 JumpTarget answer;
3491 // We need the CC bits to come out as not_equal in the case where the 3815 // We need the CC bits to come out as not_equal in the case where the
3492 // object is a smi. This can't be done with the usual test opcode so 3816 // object is a smi. This can't be done with the usual test opcode so
3493 // we use XOR to get the right CC bits. 3817 // we use XOR to get the right CC bits.
3494 frame_->EmitPop(r0); 3818 frame_->EmitPop(r0);
3495 __ and_(r1, r0, Operand(kSmiTagMask)); 3819 __ and_(r1, r0, Operand(kSmiTagMask));
3496 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); 3820 __ eor(r1, r1, Operand(kSmiTagMask), SetCC);
3497 answer.Branch(ne); 3821 answer.Branch(ne);
3498 // It is a heap object - get the map. Check if the object is a regexp. 3822 // It is a heap object - get the map. Check if the object is a regexp.
3499 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 3823 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
3500 answer.Bind(); 3824 answer.Bind();
3501 cc_reg_ = eq; 3825 cc_reg_ = eq;
3502 } 3826 }
3503 3827
3504 3828
3505 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { 3829 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
3506 // This generates a fast version of: 3830 // This generates a fast version of:
3507 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp') 3831 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp')
3508 VirtualFrame::SpilledScope spilled_scope; 3832 VirtualFrame::SpilledScope spilled_scope(frame_);
3509 ASSERT(args->length() == 1); 3833 ASSERT(args->length() == 1);
3510 LoadAndSpill(args->at(0)); 3834 LoadAndSpill(args->at(0));
3511 frame_->EmitPop(r1); 3835 frame_->EmitPop(r1);
3512 __ tst(r1, Operand(kSmiTagMask)); 3836 __ tst(r1, Operand(kSmiTagMask));
3513 false_target()->Branch(eq); 3837 false_target()->Branch(eq);
3514 3838
3515 __ LoadRoot(ip, Heap::kNullValueRootIndex); 3839 __ LoadRoot(ip, Heap::kNullValueRootIndex);
3516 __ cmp(r1, ip); 3840 __ cmp(r1, ip);
3517 true_target()->Branch(eq); 3841 true_target()->Branch(eq);
3518 3842
3519 Register map_reg = r2; 3843 Register map_reg = r2;
3520 __ ldr(map_reg, FieldMemOperand(r1, HeapObject::kMapOffset)); 3844 __ ldr(map_reg, FieldMemOperand(r1, HeapObject::kMapOffset));
3521 // Undetectable objects behave like undefined when tested with typeof. 3845 // Undetectable objects behave like undefined when tested with typeof.
3522 __ ldrb(r1, FieldMemOperand(map_reg, Map::kBitFieldOffset)); 3846 __ ldrb(r1, FieldMemOperand(map_reg, Map::kBitFieldOffset));
3523 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); 3847 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
3524 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); 3848 __ cmp(r1, Operand(1 << Map::kIsUndetectable));
3525 false_target()->Branch(eq); 3849 false_target()->Branch(eq);
3526 3850
3527 __ ldrb(r1, FieldMemOperand(map_reg, Map::kInstanceTypeOffset)); 3851 __ ldrb(r1, FieldMemOperand(map_reg, Map::kInstanceTypeOffset));
3528 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 3852 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
3529 false_target()->Branch(lt); 3853 false_target()->Branch(lt);
3530 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); 3854 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
3531 cc_reg_ = le; 3855 cc_reg_ = le;
3532 } 3856 }
3533 3857
3534 3858
3535 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { 3859 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
3536 // This generates a fast version of: 3860 // This generates a fast version of:
3537 // (%_ClassOf(arg) === 'Function') 3861 // (%_ClassOf(arg) === 'Function')
3538 VirtualFrame::SpilledScope spilled_scope; 3862 VirtualFrame::SpilledScope spilled_scope(frame_);
3539 ASSERT(args->length() == 1); 3863 ASSERT(args->length() == 1);
3540 LoadAndSpill(args->at(0)); 3864 LoadAndSpill(args->at(0));
3541 frame_->EmitPop(r0); 3865 frame_->EmitPop(r0);
3542 __ tst(r0, Operand(kSmiTagMask)); 3866 __ tst(r0, Operand(kSmiTagMask));
3543 false_target()->Branch(eq); 3867 false_target()->Branch(eq);
3544 Register map_reg = r2; 3868 Register map_reg = r2;
3545 __ CompareObjectType(r0, map_reg, r1, JS_FUNCTION_TYPE); 3869 __ CompareObjectType(r0, map_reg, r1, JS_FUNCTION_TYPE);
3546 cc_reg_ = eq; 3870 cc_reg_ = eq;
3547 } 3871 }
3548 3872
3549 3873
3550 void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) { 3874 void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) {
3551 VirtualFrame::SpilledScope spilled_scope; 3875 VirtualFrame::SpilledScope spilled_scope(frame_);
3552 ASSERT(args->length() == 1); 3876 ASSERT(args->length() == 1);
3553 LoadAndSpill(args->at(0)); 3877 LoadAndSpill(args->at(0));
3554 frame_->EmitPop(r0); 3878 frame_->EmitPop(r0);
3555 __ tst(r0, Operand(kSmiTagMask)); 3879 __ tst(r0, Operand(kSmiTagMask));
3556 false_target()->Branch(eq); 3880 false_target()->Branch(eq);
3557 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 3881 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
3558 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 3882 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
3559 __ tst(r1, Operand(1 << Map::kIsUndetectable)); 3883 __ tst(r1, Operand(1 << Map::kIsUndetectable));
3560 cc_reg_ = ne; 3884 cc_reg_ = ne;
3561 } 3885 }
3562 3886
3563 3887
3564 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { 3888 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
3565 VirtualFrame::SpilledScope spilled_scope; 3889 VirtualFrame::SpilledScope spilled_scope(frame_);
3566 ASSERT(args->length() == 0); 3890 ASSERT(args->length() == 0);
3567 3891
3568 // Get the frame pointer for the calling frame. 3892 // Get the frame pointer for the calling frame.
3569 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 3893 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3570 3894
3571 // Skip the arguments adaptor frame if it exists. 3895 // Skip the arguments adaptor frame if it exists.
3572 Label check_frame_marker; 3896 Label check_frame_marker;
3573 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); 3897 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
3574 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3898 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3575 __ b(ne, &check_frame_marker); 3899 __ b(ne, &check_frame_marker);
3576 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); 3900 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
3577 3901
3578 // Check the marker in the calling frame. 3902 // Check the marker in the calling frame.
3579 __ bind(&check_frame_marker); 3903 __ bind(&check_frame_marker);
3580 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); 3904 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
3581 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 3905 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
3582 cc_reg_ = eq; 3906 cc_reg_ = eq;
3583 } 3907 }
3584 3908
3585 3909
3586 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 3910 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
3587 VirtualFrame::SpilledScope spilled_scope; 3911 VirtualFrame::SpilledScope spilled_scope(frame_);
3588 ASSERT(args->length() == 0); 3912 ASSERT(args->length() == 0);
3589 3913
3590 Label exit; 3914 Label exit;
3591 3915
3592 // Get the number of formal parameters. 3916 // Get the number of formal parameters.
3593 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); 3917 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
3594 3918
3595 // Check if the calling frame is an arguments adaptor frame. 3919 // Check if the calling frame is an arguments adaptor frame.
3596 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 3920 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3597 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 3921 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
3598 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3922 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3599 __ b(ne, &exit); 3923 __ b(ne, &exit);
3600 3924
3601 // Arguments adaptor case: Read the arguments length from the 3925 // Arguments adaptor case: Read the arguments length from the
3602 // adaptor frame. 3926 // adaptor frame.
3603 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 3927 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
3604 3928
3605 __ bind(&exit); 3929 __ bind(&exit);
3606 frame_->EmitPush(r0); 3930 frame_->EmitPush(r0);
3607 } 3931 }
3608 3932
3609 3933
3610 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { 3934 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
3611 VirtualFrame::SpilledScope spilled_scope; 3935 VirtualFrame::SpilledScope spilled_scope(frame_);
3612 ASSERT(args->length() == 1); 3936 ASSERT(args->length() == 1);
3613 3937
3614 // Satisfy contract with ArgumentsAccessStub: 3938 // Satisfy contract with ArgumentsAccessStub:
3615 // Load the key into r1 and the formal parameters count into r0. 3939 // Load the key into r1 and the formal parameters count into r0.
3616 LoadAndSpill(args->at(0)); 3940 LoadAndSpill(args->at(0));
3617 frame_->EmitPop(r1); 3941 frame_->EmitPop(r1);
3618 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); 3942 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
3619 3943
3620 // Call the shared stub to get to arguments[key]. 3944 // Call the shared stub to get to arguments[key].
3621 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 3945 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
3622 frame_->CallStub(&stub, 0); 3946 frame_->CallStub(&stub, 0);
3623 frame_->EmitPush(r0); 3947 frame_->EmitPush(r0);
3624 } 3948 }
3625 3949
3626 3950
3627 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { 3951 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) {
3628 VirtualFrame::SpilledScope spilled_scope; 3952 VirtualFrame::SpilledScope spilled_scope(frame_);
3629 ASSERT(args->length() == 0); 3953 ASSERT(args->length() == 0);
3630 __ Call(ExternalReference::random_positive_smi_function().address(), 3954 __ Call(ExternalReference::random_positive_smi_function().address(),
3631 RelocInfo::RUNTIME_ENTRY); 3955 RelocInfo::RUNTIME_ENTRY);
3632 frame_->EmitPush(r0); 3956 frame_->EmitPush(r0);
3633 } 3957 }
3634 3958
3635 3959
3636 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { 3960 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) {
3637 ASSERT_EQ(2, args->length()); 3961 ASSERT_EQ(2, args->length());
3638 3962
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
3707 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { 4031 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
3708 ASSERT_EQ(args->length(), 1); 4032 ASSERT_EQ(args->length(), 1);
3709 // Load the argument on the stack and jump to the runtime. 4033 // Load the argument on the stack and jump to the runtime.
3710 Load(args->at(0)); 4034 Load(args->at(0));
3711 frame_->CallRuntime(Runtime::kMath_cos, 1); 4035 frame_->CallRuntime(Runtime::kMath_cos, 1);
3712 frame_->EmitPush(r0); 4036 frame_->EmitPush(r0);
3713 } 4037 }
3714 4038
3715 4039
3716 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 4040 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
3717 VirtualFrame::SpilledScope spilled_scope; 4041 VirtualFrame::SpilledScope spilled_scope(frame_);
3718 ASSERT(args->length() == 2); 4042 ASSERT(args->length() == 2);
3719 4043
3720 // Load the two objects into registers and perform the comparison. 4044 // Load the two objects into registers and perform the comparison.
3721 LoadAndSpill(args->at(0)); 4045 LoadAndSpill(args->at(0));
3722 LoadAndSpill(args->at(1)); 4046 LoadAndSpill(args->at(1));
3723 frame_->EmitPop(r0); 4047 frame_->EmitPop(r0);
3724 frame_->EmitPop(r1); 4048 frame_->EmitPop(r1);
3725 __ cmp(r0, Operand(r1)); 4049 __ cmp(r0, Operand(r1));
3726 cc_reg_ = eq; 4050 cc_reg_ = eq;
3727 } 4051 }
3728 4052
3729 4053
3730 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 4054 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
3731 #ifdef DEBUG 4055 #ifdef DEBUG
3732 int original_height = frame_->height(); 4056 int original_height = frame_->height();
3733 #endif 4057 #endif
3734 VirtualFrame::SpilledScope spilled_scope; 4058 VirtualFrame::SpilledScope spilled_scope(frame_);
3735 if (CheckForInlineRuntimeCall(node)) { 4059 if (CheckForInlineRuntimeCall(node)) {
3736 ASSERT((has_cc() && frame_->height() == original_height) || 4060 ASSERT((has_cc() && frame_->height() == original_height) ||
3737 (!has_cc() && frame_->height() == original_height + 1)); 4061 (!has_cc() && frame_->height() == original_height + 1));
3738 return; 4062 return;
3739 } 4063 }
3740 4064
3741 ZoneList<Expression*>* args = node->arguments(); 4065 ZoneList<Expression*>* args = node->arguments();
3742 Comment cmnt(masm_, "[ CallRuntime"); 4066 Comment cmnt(masm_, "[ CallRuntime");
3743 Runtime::Function* function = node->function(); 4067 Runtime::Function* function = node->function();
3744 4068
(...skipping 25 matching lines...) Expand all
3770 frame_->EmitPush(r0); 4094 frame_->EmitPush(r0);
3771 } 4095 }
3772 ASSERT(frame_->height() == original_height + 1); 4096 ASSERT(frame_->height() == original_height + 1);
3773 } 4097 }
3774 4098
3775 4099
3776 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 4100 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
3777 #ifdef DEBUG 4101 #ifdef DEBUG
3778 int original_height = frame_->height(); 4102 int original_height = frame_->height();
3779 #endif 4103 #endif
3780 VirtualFrame::SpilledScope spilled_scope; 4104 VirtualFrame::SpilledScope spilled_scope(frame_);
3781 Comment cmnt(masm_, "[ UnaryOperation"); 4105 Comment cmnt(masm_, "[ UnaryOperation");
3782 4106
3783 Token::Value op = node->op(); 4107 Token::Value op = node->op();
3784 4108
3785 if (op == Token::NOT) { 4109 if (op == Token::NOT) {
3786 LoadConditionAndSpill(node->expression(), 4110 LoadConditionAndSpill(node->expression(),
3787 false_target(), 4111 false_target(),
3788 true_target(), 4112 true_target(),
3789 true); 4113 true);
3790 // LoadCondition may (and usually does) leave a test and branch to 4114 // LoadCondition may (and usually does) leave a test and branch to
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
3901 ASSERT(!has_valid_frame() || 4225 ASSERT(!has_valid_frame() ||
3902 (has_cc() && frame_->height() == original_height) || 4226 (has_cc() && frame_->height() == original_height) ||
3903 (!has_cc() && frame_->height() == original_height + 1)); 4227 (!has_cc() && frame_->height() == original_height + 1));
3904 } 4228 }
3905 4229
3906 4230
3907 void CodeGenerator::VisitCountOperation(CountOperation* node) { 4231 void CodeGenerator::VisitCountOperation(CountOperation* node) {
3908 #ifdef DEBUG 4232 #ifdef DEBUG
3909 int original_height = frame_->height(); 4233 int original_height = frame_->height();
3910 #endif 4234 #endif
3911 VirtualFrame::SpilledScope spilled_scope; 4235 VirtualFrame::SpilledScope spilled_scope(frame_);
3912 Comment cmnt(masm_, "[ CountOperation"); 4236 Comment cmnt(masm_, "[ CountOperation");
3913 4237
3914 bool is_postfix = node->is_postfix(); 4238 bool is_postfix = node->is_postfix();
3915 bool is_increment = node->op() == Token::INC; 4239 bool is_increment = node->op() == Token::INC;
3916 4240
3917 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 4241 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
3918 bool is_const = (var != NULL && var->mode() == Variable::CONST); 4242 bool is_const = (var != NULL && var->mode() == Variable::CONST);
3919 4243
3920 // Postfix: Make room for the result. 4244 // Postfix: Make room for the result.
3921 if (is_postfix) { 4245 if (is_postfix) {
3922 __ mov(r0, Operand(0)); 4246 __ mov(r0, Operand(0));
3923 frame_->EmitPush(r0); 4247 frame_->EmitPush(r0);
3924 } 4248 }
3925 4249
3926 // A constant reference is not saved to, so a constant reference is not a 4250 // A constant reference is not saved to, so a constant reference is not a
3927 // compound assignment reference. 4251 // compound assignment reference.
3928 { Reference target(this, node->expression(), !is_const); 4252 { Reference target(this, node->expression(), !is_const);
3929 if (target.is_illegal()) { 4253 if (target.is_illegal()) {
3930 // Spoof the virtual frame to have the expected height (one higher 4254 // Spoof the virtual frame to have the expected height (one higher
3931 // than on entry). 4255 // than on entry).
3932 if (!is_postfix) { 4256 if (!is_postfix) {
3933 __ mov(r0, Operand(Smi::FromInt(0))); 4257 __ mov(r0, Operand(Smi::FromInt(0)));
3934 frame_->EmitPush(r0); 4258 frame_->EmitPush(r0);
3935 } 4259 }
3936 ASSERT(frame_->height() == original_height + 1); 4260 ASSERT(frame_->height() == original_height + 1);
3937 return; 4261 return;
3938 } 4262 }
3939 target.GetValueAndSpill(); 4263 target.GetValue();
3940 frame_->EmitPop(r0); 4264 frame_->EmitPop(r0);
3941 4265
3942 JumpTarget slow; 4266 JumpTarget slow;
3943 JumpTarget exit; 4267 JumpTarget exit;
3944 4268
3945 // Load the value (1) into register r1. 4269 // Load the value (1) into register r1.
3946 __ mov(r1, Operand(Smi::FromInt(1))); 4270 __ mov(r1, Operand(Smi::FromInt(1)));
3947 4271
3948 // Check for smi operand. 4272 // Check for smi operand.
3949 __ tst(r0, Operand(kSmiTagMask)); 4273 __ tst(r0, Operand(kSmiTagMask));
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
4110 ASSERT(!has_valid_frame() && !has_cc() && !is_false.is_linked()); 4434 ASSERT(!has_valid_frame() && !has_cc() && !is_false.is_linked());
4111 } 4435 }
4112 } 4436 }
4113 } 4437 }
4114 4438
4115 4439
4116 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 4440 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
4117 #ifdef DEBUG 4441 #ifdef DEBUG
4118 int original_height = frame_->height(); 4442 int original_height = frame_->height();
4119 #endif 4443 #endif
4120 VirtualFrame::SpilledScope spilled_scope;
4121 Comment cmnt(masm_, "[ BinaryOperation"); 4444 Comment cmnt(masm_, "[ BinaryOperation");
4122 4445
4123 if (node->op() == Token::AND || node->op() == Token::OR) { 4446 if (node->op() == Token::AND || node->op() == Token::OR) {
4447 VirtualFrame::SpilledScope spilled_scope(frame_);
4124 GenerateLogicalBooleanOperation(node); 4448 GenerateLogicalBooleanOperation(node);
4125 } else { 4449 } else {
4126 // Optimize for the case where (at least) one of the expressions 4450 // Optimize for the case where (at least) one of the expressions
4127 // is a literal small integer. 4451 // is a literal small integer.
4128 Literal* lliteral = node->left()->AsLiteral(); 4452 Literal* lliteral = node->left()->AsLiteral();
4129 Literal* rliteral = node->right()->AsLiteral(); 4453 Literal* rliteral = node->right()->AsLiteral();
4130 // NOTE: The code below assumes that the slow cases (calls to runtime) 4454 // NOTE: The code below assumes that the slow cases (calls to runtime)
4131 // never return a constant/immutable object. 4455 // never return a constant/immutable object.
4132 bool overwrite_left = 4456 bool overwrite_left =
4133 (node->left()->AsBinaryOperation() != NULL && 4457 (node->left()->AsBinaryOperation() != NULL &&
4134 node->left()->AsBinaryOperation()->ResultOverwriteAllowed()); 4458 node->left()->AsBinaryOperation()->ResultOverwriteAllowed());
4135 bool overwrite_right = 4459 bool overwrite_right =
4136 (node->right()->AsBinaryOperation() != NULL && 4460 (node->right()->AsBinaryOperation() != NULL &&
4137 node->right()->AsBinaryOperation()->ResultOverwriteAllowed()); 4461 node->right()->AsBinaryOperation()->ResultOverwriteAllowed());
4138 4462
4139 if (rliteral != NULL && rliteral->handle()->IsSmi()) { 4463 if (rliteral != NULL && rliteral->handle()->IsSmi()) {
4140 LoadAndSpill(node->left()); 4464 VirtualFrame::RegisterAllocationScope scope(this);
4141 SmiOperation(node->op(), 4465 Load(node->left());
4142 rliteral->handle(), 4466 VirtualFrameSmiOperation(
4143 false, 4467 node->op(),
4144 overwrite_right ? OVERWRITE_RIGHT : NO_OVERWRITE); 4468 rliteral->handle(),
4145 4469 false,
4470 overwrite_right ? OVERWRITE_RIGHT : NO_OVERWRITE);
4146 } else if (lliteral != NULL && lliteral->handle()->IsSmi()) { 4471 } else if (lliteral != NULL && lliteral->handle()->IsSmi()) {
4147 LoadAndSpill(node->right()); 4472 VirtualFrame::RegisterAllocationScope scope(this);
4148 SmiOperation(node->op(), 4473 Load(node->right());
4149 lliteral->handle(), 4474 VirtualFrameSmiOperation(node->op(),
4150 true, 4475 lliteral->handle(),
4151 overwrite_left ? OVERWRITE_LEFT : NO_OVERWRITE); 4476 true,
4152 4477 overwrite_left ? OVERWRITE_LEFT : NO_OVERWRITE);
4153 } else { 4478 } else {
4479 VirtualFrame::RegisterAllocationScope scope(this);
4154 OverwriteMode overwrite_mode = NO_OVERWRITE; 4480 OverwriteMode overwrite_mode = NO_OVERWRITE;
4155 if (overwrite_left) { 4481 if (overwrite_left) {
4156 overwrite_mode = OVERWRITE_LEFT; 4482 overwrite_mode = OVERWRITE_LEFT;
4157 } else if (overwrite_right) { 4483 } else if (overwrite_right) {
4158 overwrite_mode = OVERWRITE_RIGHT; 4484 overwrite_mode = OVERWRITE_RIGHT;
4159 } 4485 }
4160 LoadAndSpill(node->left()); 4486 Load(node->left());
4161 LoadAndSpill(node->right()); 4487 Load(node->right());
4162 GenericBinaryOperation(node->op(), overwrite_mode); 4488 VirtualFrameBinaryOperation(node->op(), overwrite_mode);
4163 } 4489 }
4164 frame_->EmitPush(r0);
4165 } 4490 }
4166 ASSERT(!has_valid_frame() || 4491 ASSERT(!has_valid_frame() ||
4167 (has_cc() && frame_->height() == original_height) || 4492 (has_cc() && frame_->height() == original_height) ||
4168 (!has_cc() && frame_->height() == original_height + 1)); 4493 (!has_cc() && frame_->height() == original_height + 1));
4169 } 4494 }
4170 4495
4171 4496
4172 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 4497 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
4173 #ifdef DEBUG 4498 #ifdef DEBUG
4174 int original_height = frame_->height(); 4499 int original_height = frame_->height();
4175 #endif 4500 #endif
4176 VirtualFrame::SpilledScope spilled_scope; 4501 VirtualFrame::SpilledScope spilled_scope(frame_);
4177 __ ldr(r0, frame_->Function()); 4502 __ ldr(r0, frame_->Function());
4178 frame_->EmitPush(r0); 4503 frame_->EmitPush(r0);
4179 ASSERT(frame_->height() == original_height + 1); 4504 ASSERT(frame_->height() == original_height + 1);
4180 } 4505 }
4181 4506
4182 4507
4183 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { 4508 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
4184 #ifdef DEBUG 4509 #ifdef DEBUG
4185 int original_height = frame_->height(); 4510 int original_height = frame_->height();
4186 #endif 4511 #endif
4187 VirtualFrame::SpilledScope spilled_scope;
4188 Comment cmnt(masm_, "[ CompareOperation"); 4512 Comment cmnt(masm_, "[ CompareOperation");
4189 4513
4514 VirtualFrame::RegisterAllocationScope nonspilled_scope(this);
4515
4190 // Get the expressions from the node. 4516 // Get the expressions from the node.
4191 Expression* left = node->left(); 4517 Expression* left = node->left();
4192 Expression* right = node->right(); 4518 Expression* right = node->right();
4193 Token::Value op = node->op(); 4519 Token::Value op = node->op();
4194 4520
4195 // To make null checks efficient, we check if either left or right is the 4521 // To make null checks efficient, we check if either left or right is the
4196 // literal 'null'. If so, we optimize the code by inlining a null check 4522 // literal 'null'. If so, we optimize the code by inlining a null check
4197 // instead of calling the (very) general runtime routine for checking 4523 // instead of calling the (very) general runtime routine for checking
4198 // equality. 4524 // equality.
4199 if (op == Token::EQ || op == Token::EQ_STRICT) { 4525 if (op == Token::EQ || op == Token::EQ_STRICT) {
4200 bool left_is_null = 4526 bool left_is_null =
4201 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); 4527 left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
4202 bool right_is_null = 4528 bool right_is_null =
4203 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); 4529 right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
4204 // The 'null' value can only be equal to 'null' or 'undefined'. 4530 // The 'null' value can only be equal to 'null' or 'undefined'.
4205 if (left_is_null || right_is_null) { 4531 if (left_is_null || right_is_null) {
4206 LoadAndSpill(left_is_null ? right : left); 4532 Load(left_is_null ? right : left);
4207 frame_->EmitPop(r0); 4533 Register tos = frame_->PopToRegister();
4534 // JumpTargets can't cope with register allocation yet.
4535 frame_->SpillAll();
4208 __ LoadRoot(ip, Heap::kNullValueRootIndex); 4536 __ LoadRoot(ip, Heap::kNullValueRootIndex);
4209 __ cmp(r0, ip); 4537 __ cmp(tos, ip);
4210 4538
4211 // The 'null' value is only equal to 'undefined' if using non-strict 4539 // The 'null' value is only equal to 'undefined' if using non-strict
4212 // comparisons. 4540 // comparisons.
4213 if (op != Token::EQ_STRICT) { 4541 if (op != Token::EQ_STRICT) {
4214 true_target()->Branch(eq); 4542 true_target()->Branch(eq);
4215 4543
4216 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 4544 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
4217 __ cmp(r0, Operand(ip)); 4545 __ cmp(tos, Operand(ip));
4218 true_target()->Branch(eq); 4546 true_target()->Branch(eq);
4219 4547
4220 __ tst(r0, Operand(kSmiTagMask)); 4548 __ tst(tos, Operand(kSmiTagMask));
4221 false_target()->Branch(eq); 4549 false_target()->Branch(eq);
4222 4550
4223 // It can be an undetectable object. 4551 // It can be an undetectable object.
4224 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 4552 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset));
4225 __ ldrb(r0, FieldMemOperand(r0, Map::kBitFieldOffset)); 4553 __ ldrb(tos, FieldMemOperand(tos, Map::kBitFieldOffset));
4226 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); 4554 __ and_(tos, tos, Operand(1 << Map::kIsUndetectable));
4227 __ cmp(r0, Operand(1 << Map::kIsUndetectable)); 4555 __ cmp(tos, Operand(1 << Map::kIsUndetectable));
4228 } 4556 }
4229 4557
4230 cc_reg_ = eq; 4558 cc_reg_ = eq;
4231 ASSERT(has_cc() && frame_->height() == original_height); 4559 ASSERT(has_cc() && frame_->height() == original_height);
4232 return; 4560 return;
4233 } 4561 }
4234 } 4562 }
4235 4563
4236 // To make typeof testing for natives implemented in JavaScript really 4564 // To make typeof testing for natives implemented in JavaScript really
4237 // efficient, we generate special code for expressions of the form: 4565 // efficient, we generate special code for expressions of the form:
4238 // 'typeof <expression> == <string>'. 4566 // 'typeof <expression> == <string>'.
4239 UnaryOperation* operation = left->AsUnaryOperation(); 4567 UnaryOperation* operation = left->AsUnaryOperation();
4240 if ((op == Token::EQ || op == Token::EQ_STRICT) && 4568 if ((op == Token::EQ || op == Token::EQ_STRICT) &&
4241 (operation != NULL && operation->op() == Token::TYPEOF) && 4569 (operation != NULL && operation->op() == Token::TYPEOF) &&
4242 (right->AsLiteral() != NULL && 4570 (right->AsLiteral() != NULL &&
4243 right->AsLiteral()->handle()->IsString())) { 4571 right->AsLiteral()->handle()->IsString())) {
4244 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 4572 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
4245 4573
4246 // Load the operand, move it to register r1. 4574 // Load the operand, move it to register r0 or r1.
Søren Thygesen Gjesse 2010/04/07 07:53:37 This comment implies that PopToRegister will alway
Erik Corry 2010/04/07 12:49:17 We didn't actually use the fact that it is always
4247 LoadTypeofExpression(operation->expression()); 4575 LoadTypeofExpression(operation->expression());
4248 frame_->EmitPop(r1); 4576 Register tos = frame_->PopToRegister();
4577
4578 // JumpTargets can't cope with register allocation yet.
4579 frame_->SpillAll();
4580
4581 Register scratch = VirtualFrame::scratch0();
4249 4582
4250 if (check->Equals(Heap::number_symbol())) { 4583 if (check->Equals(Heap::number_symbol())) {
4251 __ tst(r1, Operand(kSmiTagMask)); 4584 __ tst(tos, Operand(kSmiTagMask));
4252 true_target()->Branch(eq); 4585 true_target()->Branch(eq);
4253 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 4586 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset));
4254 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 4587 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
4255 __ cmp(r1, ip); 4588 __ cmp(tos, ip);
4256 cc_reg_ = eq; 4589 cc_reg_ = eq;
4257 4590
4258 } else if (check->Equals(Heap::string_symbol())) { 4591 } else if (check->Equals(Heap::string_symbol())) {
4259 __ tst(r1, Operand(kSmiTagMask)); 4592 __ tst(tos, Operand(kSmiTagMask));
4260 false_target()->Branch(eq); 4593 false_target()->Branch(eq);
4261 4594
4262 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 4595 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset));
4263 4596
4264 // It can be an undetectable string object. 4597 // It can be an undetectable string object.
4265 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); 4598 __ ldrb(scratch, FieldMemOperand(tos, Map::kBitFieldOffset));
4266 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); 4599 __ and_(scratch, scratch, Operand(1 << Map::kIsUndetectable));
4267 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); 4600 __ cmp(scratch, Operand(1 << Map::kIsUndetectable));
4268 false_target()->Branch(eq); 4601 false_target()->Branch(eq);
4269 4602
4270 __ ldrb(r2, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 4603 __ ldrb(scratch, FieldMemOperand(tos, Map::kInstanceTypeOffset));
4271 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE)); 4604 __ cmp(scratch, Operand(FIRST_NONSTRING_TYPE));
4272 cc_reg_ = lt; 4605 cc_reg_ = lt;
4273 4606
4274 } else if (check->Equals(Heap::boolean_symbol())) { 4607 } else if (check->Equals(Heap::boolean_symbol())) {
4275 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 4608 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
4276 __ cmp(r1, ip); 4609 __ cmp(tos, ip);
4277 true_target()->Branch(eq); 4610 true_target()->Branch(eq);
4278 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 4611 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
4279 __ cmp(r1, ip); 4612 __ cmp(tos, ip);
4280 cc_reg_ = eq; 4613 cc_reg_ = eq;
4281 4614
4282 } else if (check->Equals(Heap::undefined_symbol())) { 4615 } else if (check->Equals(Heap::undefined_symbol())) {
4283 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 4616 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
4284 __ cmp(r1, ip); 4617 __ cmp(tos, ip);
4285 true_target()->Branch(eq); 4618 true_target()->Branch(eq);
4286 4619
4287 __ tst(r1, Operand(kSmiTagMask)); 4620 __ tst(tos, Operand(kSmiTagMask));
4288 false_target()->Branch(eq); 4621 false_target()->Branch(eq);
4289 4622
4290 // It can be an undetectable object. 4623 // It can be an undetectable object.
4291 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 4624 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset));
4292 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); 4625 __ ldrb(scratch, FieldMemOperand(tos, Map::kBitFieldOffset));
4293 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); 4626 __ and_(scratch, scratch, Operand(1 << Map::kIsUndetectable));
4294 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); 4627 __ cmp(scratch, Operand(1 << Map::kIsUndetectable));
4295 4628
4296 cc_reg_ = eq; 4629 cc_reg_ = eq;
4297 4630
4298 } else if (check->Equals(Heap::function_symbol())) { 4631 } else if (check->Equals(Heap::function_symbol())) {
4299 __ tst(r1, Operand(kSmiTagMask)); 4632 __ tst(tos, Operand(kSmiTagMask));
4300 false_target()->Branch(eq); 4633 false_target()->Branch(eq);
4301 Register map_reg = r2; 4634 Register map_reg = scratch;
4302 __ CompareObjectType(r1, map_reg, r1, JS_FUNCTION_TYPE); 4635 __ CompareObjectType(tos, map_reg, tos, JS_FUNCTION_TYPE);
4303 true_target()->Branch(eq); 4636 true_target()->Branch(eq);
4304 // Regular expressions are callable so typeof == 'function'. 4637 // Regular expressions are callable so typeof == 'function'.
4305 __ CompareInstanceType(map_reg, r1, JS_REGEXP_TYPE); 4638 __ CompareInstanceType(map_reg, tos, JS_REGEXP_TYPE);
4306 cc_reg_ = eq; 4639 cc_reg_ = eq;
4307 4640
4308 } else if (check->Equals(Heap::object_symbol())) { 4641 } else if (check->Equals(Heap::object_symbol())) {
4309 __ tst(r1, Operand(kSmiTagMask)); 4642 __ tst(tos, Operand(kSmiTagMask));
4310 false_target()->Branch(eq); 4643 false_target()->Branch(eq);
4311 4644
4312 __ LoadRoot(ip, Heap::kNullValueRootIndex); 4645 __ LoadRoot(ip, Heap::kNullValueRootIndex);
4313 __ cmp(r1, ip); 4646 __ cmp(tos, ip);
4314 true_target()->Branch(eq); 4647 true_target()->Branch(eq);
4315 4648
4316 Register map_reg = r2; 4649 Register map_reg = scratch;
4317 __ CompareObjectType(r1, map_reg, r1, JS_REGEXP_TYPE); 4650 __ CompareObjectType(tos, map_reg, tos, JS_REGEXP_TYPE);
4318 false_target()->Branch(eq); 4651 false_target()->Branch(eq);
4319 4652
4320 // It can be an undetectable object. 4653 // It can be an undetectable object.
4321 __ ldrb(r1, FieldMemOperand(map_reg, Map::kBitFieldOffset)); 4654 __ ldrb(tos, FieldMemOperand(map_reg, Map::kBitFieldOffset));
4322 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); 4655 __ and_(tos, tos, Operand(1 << Map::kIsUndetectable));
4323 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); 4656 __ cmp(tos, Operand(1 << Map::kIsUndetectable));
4324 false_target()->Branch(eq); 4657 false_target()->Branch(eq);
4325 4658
4326 __ ldrb(r1, FieldMemOperand(map_reg, Map::kInstanceTypeOffset)); 4659 __ ldrb(tos, FieldMemOperand(map_reg, Map::kInstanceTypeOffset));
4327 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 4660 __ cmp(tos, Operand(FIRST_JS_OBJECT_TYPE));
4328 false_target()->Branch(lt); 4661 false_target()->Branch(lt);
4329 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); 4662 __ cmp(tos, Operand(LAST_JS_OBJECT_TYPE));
4330 cc_reg_ = le; 4663 cc_reg_ = le;
4331 4664
4332 } else { 4665 } else {
4333 // Uncommon case: typeof testing against a string literal that is 4666 // Uncommon case: typeof testing against a string literal that is
4334 // never returned from the typeof operator. 4667 // never returned from the typeof operator.
4335 false_target()->Jump(); 4668 false_target()->Jump();
4336 } 4669 }
4337 ASSERT(!has_valid_frame() || 4670 ASSERT(!has_valid_frame() ||
4338 (has_cc() && frame_->height() == original_height)); 4671 (has_cc() && frame_->height() == original_height));
4339 return; 4672 return;
(...skipping 18 matching lines...) Expand all
4358 4691
4359 case Token::GTE: 4692 case Token::GTE:
4360 Comparison(ge, left, right); 4693 Comparison(ge, left, right);
4361 break; 4694 break;
4362 4695
4363 case Token::EQ_STRICT: 4696 case Token::EQ_STRICT:
4364 Comparison(eq, left, right, true); 4697 Comparison(eq, left, right, true);
4365 break; 4698 break;
4366 4699
4367 case Token::IN: { 4700 case Token::IN: {
4701 VirtualFrame::SpilledScope scope(frame_);
4368 LoadAndSpill(left); 4702 LoadAndSpill(left);
4369 LoadAndSpill(right); 4703 LoadAndSpill(right);
4370 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2); 4704 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2);
4371 frame_->EmitPush(r0); 4705 frame_->EmitPush(r0);
4372 break; 4706 break;
4373 } 4707 }
4374 4708
4375 case Token::INSTANCEOF: { 4709 case Token::INSTANCEOF: {
4710 VirtualFrame::SpilledScope scope(frame_);
4376 LoadAndSpill(left); 4711 LoadAndSpill(left);
4377 LoadAndSpill(right); 4712 LoadAndSpill(right);
4378 InstanceofStub stub; 4713 InstanceofStub stub;
4379 frame_->CallStub(&stub, 2); 4714 frame_->CallStub(&stub, 2);
4380 // At this point if instanceof succeeded then r0 == 0. 4715 // At this point if instanceof succeeded then r0 == 0.
4381 __ tst(r0, Operand(r0)); 4716 __ tst(r0, Operand(r0));
4382 cc_reg_ = eq; 4717 cc_reg_ = eq;
4383 break; 4718 break;
4384 } 4719 }
4385 4720
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
4497 switch (type_) { 4832 switch (type_) {
4498 case SLOT: { 4833 case SLOT: {
4499 Comment cmnt(masm, "[ Store to Slot"); 4834 Comment cmnt(masm, "[ Store to Slot");
4500 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 4835 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4501 cgen_->StoreToSlot(slot, init_state); 4836 cgen_->StoreToSlot(slot, init_state);
4502 cgen_->UnloadReference(this); 4837 cgen_->UnloadReference(this);
4503 break; 4838 break;
4504 } 4839 }
4505 4840
4506 case NAMED: { 4841 case NAMED: {
4842 VirtualFrame::SpilledScope scope(frame);
4507 Comment cmnt(masm, "[ Store to named Property"); 4843 Comment cmnt(masm, "[ Store to named Property");
4508 // Call the appropriate IC code. 4844 // Call the appropriate IC code.
4509 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 4845 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
4510 Handle<String> name(GetName()); 4846 Handle<String> name(GetName());
4511 4847
4512 frame->EmitPop(r0); 4848 frame->EmitPop(r0);
4513 frame->EmitPop(r1); 4849 frame->EmitPop(r1);
4514 __ mov(r2, Operand(name)); 4850 __ mov(r2, Operand(name));
4515 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4851 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4516 frame->EmitPush(r0); 4852 frame->EmitPush(r0);
4517 set_unloaded(); 4853 set_unloaded();
4518 break; 4854 break;
4519 } 4855 }
4520 4856
4521 case KEYED: { 4857 case KEYED: {
4858 VirtualFrame::SpilledScope scope(frame);
4522 Comment cmnt(masm, "[ Store to keyed Property"); 4859 Comment cmnt(masm, "[ Store to keyed Property");
4523 Property* property = expression_->AsProperty(); 4860 Property* property = expression_->AsProperty();
4524 ASSERT(property != NULL); 4861 ASSERT(property != NULL);
4525 cgen_->CodeForSourcePosition(property->position()); 4862 cgen_->CodeForSourcePosition(property->position());
4526 4863
4527 // Call IC code. 4864 // Call IC code.
4528 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 4865 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
4529 frame->EmitPop(r0); // value 4866 frame->EmitPop(r0); // value
4530 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4867 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4531 frame->EmitPush(r0); 4868 frame->EmitPush(r0);
(...skipping 3411 matching lines...) Expand 10 before | Expand all | Expand 10 after
7943 8280
7944 // Just jump to runtime to add the two strings. 8281 // Just jump to runtime to add the two strings.
7945 __ bind(&string_add_runtime); 8282 __ bind(&string_add_runtime);
7946 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 8283 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
7947 } 8284 }
7948 8285
7949 8286
7950 #undef __ 8287 #undef __
7951 8288
7952 } } // namespace v8::internal 8289 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/codegen-arm-inl.h » ('j') | src/arm/virtual-frame-arm.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698