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

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 6597029: [Isolates] Merge r 6300:6500 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: Created 9 years, 10 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
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 if (slots > 0) { 132 if (slots > 0) {
133 if (FLAG_debug_code) { 133 if (FLAG_debug_code) {
134 __ mov(Operand(eax), Immediate(slots)); 134 __ mov(Operand(eax), Immediate(slots));
135 Label loop; 135 Label loop;
136 __ bind(&loop); 136 __ bind(&loop);
137 __ push(Immediate(kSlotsZapValue)); 137 __ push(Immediate(kSlotsZapValue));
138 __ dec(eax); 138 __ dec(eax);
139 __ j(not_zero, &loop); 139 __ j(not_zero, &loop);
140 } else { 140 } else {
141 __ sub(Operand(esp), Immediate(slots * kPointerSize)); 141 __ sub(Operand(esp), Immediate(slots * kPointerSize));
142 #ifdef _MSC_VER
143 // On windows, you may not access the stack more than one page below
144 // the most recently mapped page. To make the allocated area randomly
145 // accessible, we write to each page in turn (the value is irrelevant).
146 const int kPageSize = 4 * KB;
147 for (int offset = slots * kPointerSize - kPageSize;
148 offset > 0;
149 offset -= kPageSize) {
150 __ mov(Operand(esp, offset), eax);
151 }
152 #endif
142 } 153 }
143 } 154 }
144 155
145 // Trace the call. 156 // Trace the call.
146 if (FLAG_trace) { 157 if (FLAG_trace) {
147 __ CallRuntime(Runtime::kTraceEnter, 0); 158 __ CallRuntime(Runtime::kTraceEnter, 0);
148 } 159 }
149 return !is_aborted(); 160 return !is_aborted();
150 } 161 }
151 162
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 // Local or spill slot. Skip the frame pointer, function, and 269 // Local or spill slot. Skip the frame pointer, function, and
259 // context in the fixed part of the frame. 270 // context in the fixed part of the frame.
260 return Operand(ebp, -(index + 3) * kPointerSize); 271 return Operand(ebp, -(index + 3) * kPointerSize);
261 } else { 272 } else {
262 // Incoming parameter. Skip the return address. 273 // Incoming parameter. Skip the return address.
263 return Operand(ebp, -(index - 1) * kPointerSize); 274 return Operand(ebp, -(index - 1) * kPointerSize);
264 } 275 }
265 } 276 }
266 277
267 278
279 Operand LCodeGen::HighOperand(LOperand* op) {
280 ASSERT(op->IsDoubleStackSlot());
281 int index = op->index();
282 int offset = (index >= 0) ? index + 3 : index - 1;
283 return Operand(ebp, -offset * kPointerSize);
284 }
285
286
268 void LCodeGen::WriteTranslation(LEnvironment* environment, 287 void LCodeGen::WriteTranslation(LEnvironment* environment,
269 Translation* translation) { 288 Translation* translation) {
270 if (environment == NULL) return; 289 if (environment == NULL) return;
271 290
272 // The translation includes one command per value in the environment. 291 // The translation includes one command per value in the environment.
273 int translation_size = environment->values()->length(); 292 int translation_size = environment->values()->length();
274 // The output frame height does not include the parameters. 293 // The output frame height does not include the parameters.
275 int height = translation_size - environment->parameter_count(); 294 int height = translation_size - environment->parameter_count();
276 295
277 WriteTranslation(environment->outer(), translation); 296 WriteTranslation(environment->outer(), translation);
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 } else { 612 } else {
594 Comment(";;; B%d", label->block_id()); 613 Comment(";;; B%d", label->block_id());
595 } 614 }
596 __ bind(label->label()); 615 __ bind(label->label());
597 current_block_ = label->block_id(); 616 current_block_ = label->block_id();
598 LCodeGen::DoGap(label); 617 LCodeGen::DoGap(label);
599 } 618 }
600 619
601 620
602 void LCodeGen::DoParallelMove(LParallelMove* move) { 621 void LCodeGen::DoParallelMove(LParallelMove* move) {
603 // xmm0 must always be a scratch register. 622 resolver_.Resolve(move);
604 XMMRegister xmm_scratch = xmm0;
605 LUnallocated marker_operand(LUnallocated::NONE);
606
607 Register cpu_scratch = esi;
608 bool destroys_cpu_scratch = false;
609
610 const ZoneList<LMoveOperands>* moves =
611 resolver_.Resolve(move->move_operands(), &marker_operand);
612 for (int i = moves->length() - 1; i >= 0; --i) {
613 LMoveOperands move = moves->at(i);
614 LOperand* from = move.from();
615 LOperand* to = move.to();
616 ASSERT(!from->IsDoubleRegister() ||
617 !ToDoubleRegister(from).is(xmm_scratch));
618 ASSERT(!to->IsDoubleRegister() || !ToDoubleRegister(to).is(xmm_scratch));
619 ASSERT(!from->IsRegister() || !ToRegister(from).is(cpu_scratch));
620 ASSERT(!to->IsRegister() || !ToRegister(to).is(cpu_scratch));
621 if (from->IsConstantOperand()) {
622 __ mov(ToOperand(to), ToImmediate(from));
623 } else if (from == &marker_operand) {
624 if (to->IsRegister() || to->IsStackSlot()) {
625 __ mov(ToOperand(to), cpu_scratch);
626 ASSERT(destroys_cpu_scratch);
627 } else {
628 ASSERT(to->IsDoubleRegister() || to->IsDoubleStackSlot());
629 __ movdbl(ToOperand(to), xmm_scratch);
630 }
631 } else if (to == &marker_operand) {
632 if (from->IsRegister() || from->IsStackSlot()) {
633 __ mov(cpu_scratch, ToOperand(from));
634 destroys_cpu_scratch = true;
635 } else {
636 ASSERT(from->IsDoubleRegister() || from->IsDoubleStackSlot());
637 __ movdbl(xmm_scratch, ToOperand(from));
638 }
639 } else if (from->IsRegister()) {
640 __ mov(ToOperand(to), ToRegister(from));
641 } else if (to->IsRegister()) {
642 __ mov(ToRegister(to), ToOperand(from));
643 } else if (from->IsStackSlot()) {
644 ASSERT(to->IsStackSlot());
645 __ push(eax);
646 __ mov(eax, ToOperand(from));
647 __ mov(ToOperand(to), eax);
648 __ pop(eax);
649 } else if (from->IsDoubleRegister()) {
650 __ movdbl(ToOperand(to), ToDoubleRegister(from));
651 } else if (to->IsDoubleRegister()) {
652 __ movdbl(ToDoubleRegister(to), ToOperand(from));
653 } else {
654 ASSERT(to->IsDoubleStackSlot() && from->IsDoubleStackSlot());
655 __ movdbl(xmm_scratch, ToOperand(from));
656 __ movdbl(ToOperand(to), xmm_scratch);
657 }
658 }
659
660 if (destroys_cpu_scratch) {
661 __ mov(cpu_scratch, Operand(ebp, -kPointerSize));
662 }
663 } 623 }
664 624
665 625
666 void LCodeGen::DoGap(LGap* gap) { 626 void LCodeGen::DoGap(LGap* gap) {
667 for (int i = LGap::FIRST_INNER_POSITION; 627 for (int i = LGap::FIRST_INNER_POSITION;
668 i <= LGap::LAST_INNER_POSITION; 628 i <= LGap::LAST_INNER_POSITION;
669 i++) { 629 i++) {
670 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 630 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
671 LParallelMove* move = gap->GetParallelMove(inner_pos); 631 LParallelMove* move = gap->GetParallelMove(inner_pos);
672 if (move != NULL) DoParallelMove(move); 632 if (move != NULL) DoParallelMove(move);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 } 699 }
740 } 700 }
741 701
742 702
743 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 703 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
744 // Nothing to do. 704 // Nothing to do.
745 } 705 }
746 706
747 707
748 void LCodeGen::DoModI(LModI* instr) { 708 void LCodeGen::DoModI(LModI* instr) {
749 LOperand* right = instr->right(); 709 LOperand* right = instr->InputAt(1);
750 ASSERT(ToRegister(instr->result()).is(edx)); 710 ASSERT(ToRegister(instr->result()).is(edx));
751 ASSERT(ToRegister(instr->left()).is(eax)); 711 ASSERT(ToRegister(instr->InputAt(0)).is(eax));
752 ASSERT(!ToRegister(instr->right()).is(eax)); 712 ASSERT(!ToRegister(instr->InputAt(1)).is(eax));
753 ASSERT(!ToRegister(instr->right()).is(edx)); 713 ASSERT(!ToRegister(instr->InputAt(1)).is(edx));
754 714
755 Register right_reg = ToRegister(right); 715 Register right_reg = ToRegister(right);
756 716
757 // Check for x % 0. 717 // Check for x % 0.
758 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 718 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
759 __ test(right_reg, ToOperand(right)); 719 __ test(right_reg, ToOperand(right));
760 DeoptimizeIf(zero, instr->environment()); 720 DeoptimizeIf(zero, instr->environment());
761 } 721 }
762 722
763 // Sign extend to edx. 723 // Sign extend to edx.
(...skipping 15 matching lines...) Expand all
779 __ bind(&positive_left); 739 __ bind(&positive_left);
780 __ idiv(right_reg); 740 __ idiv(right_reg);
781 __ bind(&done); 741 __ bind(&done);
782 } else { 742 } else {
783 __ idiv(right_reg); 743 __ idiv(right_reg);
784 } 744 }
785 } 745 }
786 746
787 747
788 void LCodeGen::DoDivI(LDivI* instr) { 748 void LCodeGen::DoDivI(LDivI* instr) {
789 LOperand* right = instr->right(); 749 LOperand* right = instr->InputAt(1);
790 ASSERT(ToRegister(instr->result()).is(eax)); 750 ASSERT(ToRegister(instr->result()).is(eax));
791 ASSERT(ToRegister(instr->left()).is(eax)); 751 ASSERT(ToRegister(instr->InputAt(0)).is(eax));
792 ASSERT(!ToRegister(instr->right()).is(eax)); 752 ASSERT(!ToRegister(instr->InputAt(1)).is(eax));
793 ASSERT(!ToRegister(instr->right()).is(edx)); 753 ASSERT(!ToRegister(instr->InputAt(1)).is(edx));
794 754
795 Register left_reg = eax; 755 Register left_reg = eax;
796 756
797 // Check for x / 0. 757 // Check for x / 0.
798 Register right_reg = ToRegister(right); 758 Register right_reg = ToRegister(right);
799 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 759 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
800 __ test(right_reg, ToOperand(right)); 760 __ test(right_reg, ToOperand(right));
801 DeoptimizeIf(zero, instr->environment()); 761 DeoptimizeIf(zero, instr->environment());
802 } 762 }
803 763
(...skipping 21 matching lines...) Expand all
825 __ cdq(); 785 __ cdq();
826 __ idiv(right_reg); 786 __ idiv(right_reg);
827 787
828 // Deoptimize if remainder is not 0. 788 // Deoptimize if remainder is not 0.
829 __ test(edx, Operand(edx)); 789 __ test(edx, Operand(edx));
830 DeoptimizeIf(not_zero, instr->environment()); 790 DeoptimizeIf(not_zero, instr->environment());
831 } 791 }
832 792
833 793
834 void LCodeGen::DoMulI(LMulI* instr) { 794 void LCodeGen::DoMulI(LMulI* instr) {
835 Register left = ToRegister(instr->left()); 795 Register left = ToRegister(instr->InputAt(0));
836 LOperand* right = instr->right(); 796 LOperand* right = instr->InputAt(1);
837 797
838 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 798 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
839 __ mov(ToRegister(instr->temp()), left); 799 __ mov(ToRegister(instr->TempAt(0)), left);
840 } 800 }
841 801
842 if (right->IsConstantOperand()) { 802 if (right->IsConstantOperand()) {
843 __ imul(left, left, ToInteger32(LConstantOperand::cast(right))); 803 __ imul(left, left, ToInteger32(LConstantOperand::cast(right)));
844 } else { 804 } else {
845 __ imul(left, ToOperand(right)); 805 __ imul(left, ToOperand(right));
846 } 806 }
847 807
848 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 808 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
849 DeoptimizeIf(overflow, instr->environment()); 809 DeoptimizeIf(overflow, instr->environment());
850 } 810 }
851 811
852 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 812 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
853 // Bail out if the result is supposed to be negative zero. 813 // Bail out if the result is supposed to be negative zero.
854 NearLabel done; 814 NearLabel done;
855 __ test(left, Operand(left)); 815 __ test(left, Operand(left));
856 __ j(not_zero, &done); 816 __ j(not_zero, &done);
857 if (right->IsConstantOperand()) { 817 if (right->IsConstantOperand()) {
858 if (ToInteger32(LConstantOperand::cast(right)) < 0) { 818 if (ToInteger32(LConstantOperand::cast(right)) < 0) {
859 DeoptimizeIf(no_condition, instr->environment()); 819 DeoptimizeIf(no_condition, instr->environment());
860 } 820 }
861 } else { 821 } else {
862 // Test the non-zero operand for negative sign. 822 // Test the non-zero operand for negative sign.
863 __ or_(ToRegister(instr->temp()), ToOperand(right)); 823 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right));
864 DeoptimizeIf(sign, instr->environment()); 824 DeoptimizeIf(sign, instr->environment());
865 } 825 }
866 __ bind(&done); 826 __ bind(&done);
867 } 827 }
868 } 828 }
869 829
870 830
871 void LCodeGen::DoBitI(LBitI* instr) { 831 void LCodeGen::DoBitI(LBitI* instr) {
872 LOperand* left = instr->left(); 832 LOperand* left = instr->InputAt(0);
873 LOperand* right = instr->right(); 833 LOperand* right = instr->InputAt(1);
874 ASSERT(left->Equals(instr->result())); 834 ASSERT(left->Equals(instr->result()));
875 ASSERT(left->IsRegister()); 835 ASSERT(left->IsRegister());
876 836
877 if (right->IsConstantOperand()) { 837 if (right->IsConstantOperand()) {
878 int right_operand = ToInteger32(LConstantOperand::cast(right)); 838 int right_operand = ToInteger32(LConstantOperand::cast(right));
879 switch (instr->op()) { 839 switch (instr->op()) {
880 case Token::BIT_AND: 840 case Token::BIT_AND:
881 __ and_(ToRegister(left), right_operand); 841 __ and_(ToRegister(left), right_operand);
882 break; 842 break;
883 case Token::BIT_OR: 843 case Token::BIT_OR:
(...skipping 19 matching lines...) Expand all
903 break; 863 break;
904 default: 864 default:
905 UNREACHABLE(); 865 UNREACHABLE();
906 break; 866 break;
907 } 867 }
908 } 868 }
909 } 869 }
910 870
911 871
912 void LCodeGen::DoShiftI(LShiftI* instr) { 872 void LCodeGen::DoShiftI(LShiftI* instr) {
913 LOperand* left = instr->left(); 873 LOperand* left = instr->InputAt(0);
914 LOperand* right = instr->right(); 874 LOperand* right = instr->InputAt(1);
915 ASSERT(left->Equals(instr->result())); 875 ASSERT(left->Equals(instr->result()));
916 ASSERT(left->IsRegister()); 876 ASSERT(left->IsRegister());
917 if (right->IsRegister()) { 877 if (right->IsRegister()) {
918 ASSERT(ToRegister(right).is(ecx)); 878 ASSERT(ToRegister(right).is(ecx));
919 879
920 switch (instr->op()) { 880 switch (instr->op()) {
921 case Token::SAR: 881 case Token::SAR:
922 __ sar_cl(ToRegister(left)); 882 __ sar_cl(ToRegister(left));
923 break; 883 break;
924 case Token::SHR: 884 case Token::SHR:
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 break; 919 break;
960 default: 920 default:
961 UNREACHABLE(); 921 UNREACHABLE();
962 break; 922 break;
963 } 923 }
964 } 924 }
965 } 925 }
966 926
967 927
968 void LCodeGen::DoSubI(LSubI* instr) { 928 void LCodeGen::DoSubI(LSubI* instr) {
969 LOperand* left = instr->left(); 929 LOperand* left = instr->InputAt(0);
970 LOperand* right = instr->right(); 930 LOperand* right = instr->InputAt(1);
971 ASSERT(left->Equals(instr->result())); 931 ASSERT(left->Equals(instr->result()));
972 932
973 if (right->IsConstantOperand()) { 933 if (right->IsConstantOperand()) {
974 __ sub(ToOperand(left), ToImmediate(right)); 934 __ sub(ToOperand(left), ToImmediate(right));
975 } else { 935 } else {
976 __ sub(ToRegister(left), ToOperand(right)); 936 __ sub(ToRegister(left), ToOperand(right));
977 } 937 }
978 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 938 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
979 DeoptimizeIf(overflow, instr->environment()); 939 DeoptimizeIf(overflow, instr->environment());
980 } 940 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 975
1016 976
1017 void LCodeGen::DoConstantT(LConstantT* instr) { 977 void LCodeGen::DoConstantT(LConstantT* instr) {
1018 ASSERT(instr->result()->IsRegister()); 978 ASSERT(instr->result()->IsRegister());
1019 __ Set(ToRegister(instr->result()), Immediate(instr->value())); 979 __ Set(ToRegister(instr->result()), Immediate(instr->value()));
1020 } 980 }
1021 981
1022 982
1023 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { 983 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
1024 Register result = ToRegister(instr->result()); 984 Register result = ToRegister(instr->result());
1025 Register array = ToRegister(instr->input()); 985 Register array = ToRegister(instr->InputAt(0));
1026 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); 986 __ mov(result, FieldOperand(array, JSArray::kLengthOffset));
1027 } 987 }
1028 988
1029 989
1030 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { 990 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
1031 Register result = ToRegister(instr->result()); 991 Register result = ToRegister(instr->result());
1032 Register array = ToRegister(instr->input()); 992 Register array = ToRegister(instr->InputAt(0));
1033 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset)); 993 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset));
1034 } 994 }
1035 995
1036 996
1037 void LCodeGen::DoValueOf(LValueOf* instr) { 997 void LCodeGen::DoValueOf(LValueOf* instr) {
1038 Register input = ToRegister(instr->input()); 998 Register input = ToRegister(instr->InputAt(0));
1039 Register result = ToRegister(instr->result()); 999 Register result = ToRegister(instr->result());
1040 Register map = ToRegister(instr->temporary()); 1000 Register map = ToRegister(instr->TempAt(0));
1041 ASSERT(input.is(result)); 1001 ASSERT(input.is(result));
1042 NearLabel done; 1002 NearLabel done;
1043 // If the object is a smi return the object. 1003 // If the object is a smi return the object.
1044 __ test(input, Immediate(kSmiTagMask)); 1004 __ test(input, Immediate(kSmiTagMask));
1045 __ j(zero, &done); 1005 __ j(zero, &done);
1046 1006
1047 // If the object is not a value type, return the object. 1007 // If the object is not a value type, return the object.
1048 __ CmpObjectType(input, JS_VALUE_TYPE, map); 1008 __ CmpObjectType(input, JS_VALUE_TYPE, map);
1049 __ j(not_equal, &done); 1009 __ j(not_equal, &done);
1050 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); 1010 __ mov(result, FieldOperand(input, JSValue::kValueOffset));
1051 1011
1052 __ bind(&done); 1012 __ bind(&done);
1053 } 1013 }
1054 1014
1055 1015
1056 void LCodeGen::DoBitNotI(LBitNotI* instr) { 1016 void LCodeGen::DoBitNotI(LBitNotI* instr) {
1057 LOperand* input = instr->input(); 1017 LOperand* input = instr->InputAt(0);
1058 ASSERT(input->Equals(instr->result())); 1018 ASSERT(input->Equals(instr->result()));
1059 __ not_(ToRegister(input)); 1019 __ not_(ToRegister(input));
1060 } 1020 }
1061 1021
1062 1022
1063 void LCodeGen::DoThrow(LThrow* instr) { 1023 void LCodeGen::DoThrow(LThrow* instr) {
1064 __ push(ToOperand(instr->input())); 1024 __ push(ToOperand(instr->InputAt(0)));
1065 CallRuntime(Runtime::kThrow, 1, instr); 1025 CallRuntime(Runtime::kThrow, 1, instr);
1066 1026
1067 if (FLAG_debug_code) { 1027 if (FLAG_debug_code) {
1068 Comment("Unreachable code."); 1028 Comment("Unreachable code.");
1069 __ int3(); 1029 __ int3();
1070 } 1030 }
1071 } 1031 }
1072 1032
1073 1033
1074 void LCodeGen::DoAddI(LAddI* instr) { 1034 void LCodeGen::DoAddI(LAddI* instr) {
1075 LOperand* left = instr->left(); 1035 LOperand* left = instr->InputAt(0);
1076 LOperand* right = instr->right(); 1036 LOperand* right = instr->InputAt(1);
1077 ASSERT(left->Equals(instr->result())); 1037 ASSERT(left->Equals(instr->result()));
1078 1038
1079 if (right->IsConstantOperand()) { 1039 if (right->IsConstantOperand()) {
1080 __ add(ToOperand(left), ToImmediate(right)); 1040 __ add(ToOperand(left), ToImmediate(right));
1081 } else { 1041 } else {
1082 __ add(ToRegister(left), ToOperand(right)); 1042 __ add(ToRegister(left), ToOperand(right));
1083 } 1043 }
1084 1044
1085 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1045 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1086 DeoptimizeIf(overflow, instr->environment()); 1046 DeoptimizeIf(overflow, instr->environment());
1087 } 1047 }
1088 } 1048 }
1089 1049
1090 1050
1091 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { 1051 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
1092 LOperand* left = instr->left(); 1052 LOperand* left = instr->InputAt(0);
1093 LOperand* right = instr->right(); 1053 LOperand* right = instr->InputAt(1);
1094 // Modulo uses a fixed result register. 1054 // Modulo uses a fixed result register.
1095 ASSERT(instr->op() == Token::MOD || left->Equals(instr->result())); 1055 ASSERT(instr->op() == Token::MOD || left->Equals(instr->result()));
1096 switch (instr->op()) { 1056 switch (instr->op()) {
1097 case Token::ADD: 1057 case Token::ADD:
1098 __ addsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1058 __ addsd(ToDoubleRegister(left), ToDoubleRegister(right));
1099 break; 1059 break;
1100 case Token::SUB: 1060 case Token::SUB:
1101 __ subsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1061 __ subsd(ToDoubleRegister(left), ToDoubleRegister(right));
1102 break; 1062 break;
1103 case Token::MUL: 1063 case Token::MUL:
(...skipping 18 matching lines...) Expand all
1122 break; 1082 break;
1123 } 1083 }
1124 default: 1084 default:
1125 UNREACHABLE(); 1085 UNREACHABLE();
1126 break; 1086 break;
1127 } 1087 }
1128 } 1088 }
1129 1089
1130 1090
1131 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { 1091 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
1132 ASSERT(ToRegister(instr->left()).is(edx)); 1092 ASSERT(ToRegister(instr->InputAt(0)).is(edx));
1133 ASSERT(ToRegister(instr->right()).is(eax)); 1093 ASSERT(ToRegister(instr->InputAt(1)).is(eax));
1134 ASSERT(ToRegister(instr->result()).is(eax)); 1094 ASSERT(ToRegister(instr->result()).is(eax));
1135 1095
1136 TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); 1096 TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
1137 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1097 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1138 } 1098 }
1139 1099
1140 1100
1141 int LCodeGen::GetNextEmittedBlock(int block) { 1101 int LCodeGen::GetNextEmittedBlock(int block) {
1142 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { 1102 for (int i = block + 1; i < graph()->blocks()->length(); ++i) {
1143 LLabel* label = chunk_->GetLabel(i); 1103 LLabel* label = chunk_->GetLabel(i);
(...skipping 20 matching lines...) Expand all
1164 } 1124 }
1165 } 1125 }
1166 1126
1167 1127
1168 void LCodeGen::DoBranch(LBranch* instr) { 1128 void LCodeGen::DoBranch(LBranch* instr) {
1169 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1129 int true_block = chunk_->LookupDestination(instr->true_block_id());
1170 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1130 int false_block = chunk_->LookupDestination(instr->false_block_id());
1171 1131
1172 Representation r = instr->hydrogen()->representation(); 1132 Representation r = instr->hydrogen()->representation();
1173 if (r.IsInteger32()) { 1133 if (r.IsInteger32()) {
1174 Register reg = ToRegister(instr->input()); 1134 Register reg = ToRegister(instr->InputAt(0));
1175 __ test(reg, Operand(reg)); 1135 __ test(reg, Operand(reg));
1176 EmitBranch(true_block, false_block, not_zero); 1136 EmitBranch(true_block, false_block, not_zero);
1177 } else if (r.IsDouble()) { 1137 } else if (r.IsDouble()) {
1178 XMMRegister reg = ToDoubleRegister(instr->input()); 1138 XMMRegister reg = ToDoubleRegister(instr->InputAt(0));
1179 __ xorpd(xmm0, xmm0); 1139 __ xorpd(xmm0, xmm0);
1180 __ ucomisd(reg, xmm0); 1140 __ ucomisd(reg, xmm0);
1181 EmitBranch(true_block, false_block, not_equal); 1141 EmitBranch(true_block, false_block, not_equal);
1182 } else { 1142 } else {
1183 ASSERT(r.IsTagged()); 1143 ASSERT(r.IsTagged());
1184 Register reg = ToRegister(instr->input()); 1144 Register reg = ToRegister(instr->InputAt(0));
1185 if (instr->hydrogen()->type().IsBoolean()) { 1145 if (instr->hydrogen()->type().IsBoolean()) {
1186 __ cmp(reg, FACTORY->true_value()); 1146 __ cmp(reg, FACTORY->true_value());
1187 EmitBranch(true_block, false_block, equal); 1147 EmitBranch(true_block, false_block, equal);
1188 } else { 1148 } else {
1189 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1149 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1190 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1150 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1191 1151
1192 __ cmp(reg, FACTORY->undefined_value()); 1152 __ cmp(reg, FACTORY->undefined_value());
1193 __ j(equal, false_label); 1153 __ j(equal, false_label);
1194 __ cmp(reg, FACTORY->true_value()); 1154 __ cmp(reg, FACTORY->true_value());
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1302 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { 1262 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
1303 if (right->IsConstantOperand()) { 1263 if (right->IsConstantOperand()) {
1304 __ cmp(ToOperand(left), ToImmediate(right)); 1264 __ cmp(ToOperand(left), ToImmediate(right));
1305 } else { 1265 } else {
1306 __ cmp(ToRegister(left), ToOperand(right)); 1266 __ cmp(ToRegister(left), ToOperand(right));
1307 } 1267 }
1308 } 1268 }
1309 1269
1310 1270
1311 void LCodeGen::DoCmpID(LCmpID* instr) { 1271 void LCodeGen::DoCmpID(LCmpID* instr) {
1312 LOperand* left = instr->left(); 1272 LOperand* left = instr->InputAt(0);
1313 LOperand* right = instr->right(); 1273 LOperand* right = instr->InputAt(1);
1314 LOperand* result = instr->result(); 1274 LOperand* result = instr->result();
1315 1275
1316 NearLabel unordered; 1276 NearLabel unordered;
1317 if (instr->is_double()) { 1277 if (instr->is_double()) {
1318 // Don't base result on EFLAGS when a NaN is involved. Instead 1278 // Don't base result on EFLAGS when a NaN is involved. Instead
1319 // jump to the unordered case, which produces a false value. 1279 // jump to the unordered case, which produces a false value.
1320 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 1280 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1321 __ j(parity_even, &unordered, not_taken); 1281 __ j(parity_even, &unordered, not_taken);
1322 } else { 1282 } else {
1323 EmitCmpI(left, right); 1283 EmitCmpI(left, right);
1324 } 1284 }
1325 1285
1326 NearLabel done; 1286 NearLabel done;
1327 Condition cc = TokenToCondition(instr->op(), instr->is_double()); 1287 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1328 __ mov(ToRegister(result), Handle<Object>(HEAP->true_value())); 1288 __ mov(ToRegister(result), FACTORY->true_value());
1329 __ j(cc, &done); 1289 __ j(cc, &done);
1330 1290
1331 __ bind(&unordered); 1291 __ bind(&unordered);
1332 __ mov(ToRegister(result), Handle<Object>(HEAP->false_value())); 1292 __ mov(ToRegister(result), FACTORY->false_value());
1333 __ bind(&done); 1293 __ bind(&done);
1334 } 1294 }
1335 1295
1336 1296
1337 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1297 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1338 LOperand* left = instr->left(); 1298 LOperand* left = instr->InputAt(0);
1339 LOperand* right = instr->right(); 1299 LOperand* right = instr->InputAt(1);
1340 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1300 int false_block = chunk_->LookupDestination(instr->false_block_id());
1341 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1301 int true_block = chunk_->LookupDestination(instr->true_block_id());
1342 1302
1343 if (instr->is_double()) { 1303 if (instr->is_double()) {
1344 // Don't base result on EFLAGS when a NaN is involved. Instead 1304 // Don't base result on EFLAGS when a NaN is involved. Instead
1345 // jump to the false block. 1305 // jump to the false block.
1346 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 1306 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1347 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); 1307 __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
1348 } else { 1308 } else {
1349 EmitCmpI(left, right); 1309 EmitCmpI(left, right);
1350 } 1310 }
1351 1311
1352 Condition cc = TokenToCondition(instr->op(), instr->is_double()); 1312 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1353 EmitBranch(true_block, false_block, cc); 1313 EmitBranch(true_block, false_block, cc);
1354 } 1314 }
1355 1315
1356 1316
1357 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { 1317 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) {
1358 Register left = ToRegister(instr->left()); 1318 Register left = ToRegister(instr->InputAt(0));
1359 Register right = ToRegister(instr->right()); 1319 Register right = ToRegister(instr->InputAt(1));
1360 Register result = ToRegister(instr->result()); 1320 Register result = ToRegister(instr->result());
1361 1321
1362 __ cmp(left, Operand(right)); 1322 __ cmp(left, Operand(right));
1363 __ mov(result, Handle<Object>(HEAP->true_value())); 1323 __ mov(result, FACTORY->true_value());
1364 NearLabel done; 1324 NearLabel done;
1365 __ j(equal, &done); 1325 __ j(equal, &done);
1366 __ mov(result, Handle<Object>(HEAP->false_value())); 1326 __ mov(result, FACTORY->false_value());
1367 __ bind(&done); 1327 __ bind(&done);
1368 } 1328 }
1369 1329
1370 1330
1371 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { 1331 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
1372 Register left = ToRegister(instr->left()); 1332 Register left = ToRegister(instr->InputAt(0));
1373 Register right = ToRegister(instr->right()); 1333 Register right = ToRegister(instr->InputAt(1));
1374 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1334 int false_block = chunk_->LookupDestination(instr->false_block_id());
1375 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1335 int true_block = chunk_->LookupDestination(instr->true_block_id());
1376 1336
1377 __ cmp(left, Operand(right)); 1337 __ cmp(left, Operand(right));
1378 EmitBranch(true_block, false_block, equal); 1338 EmitBranch(true_block, false_block, equal);
1379 } 1339 }
1380 1340
1381 1341
1382 void LCodeGen::DoIsNull(LIsNull* instr) { 1342 void LCodeGen::DoIsNull(LIsNull* instr) {
1383 Register reg = ToRegister(instr->input()); 1343 Register reg = ToRegister(instr->InputAt(0));
1384 Register result = ToRegister(instr->result()); 1344 Register result = ToRegister(instr->result());
1385 1345
1386 // TODO(fsc): If the expression is known to be a smi, then it's 1346 // TODO(fsc): If the expression is known to be a smi, then it's
1387 // definitely not null. Materialize false. 1347 // definitely not null. Materialize false.
1388 1348
1389 __ cmp(reg, FACTORY->null_value()); 1349 __ cmp(reg, FACTORY->null_value());
1390 if (instr->is_strict()) { 1350 if (instr->is_strict()) {
1391 __ mov(result, Handle<Object>(HEAP->true_value())); 1351 __ mov(result, FACTORY->true_value());
1392 NearLabel done; 1352 NearLabel done;
1393 __ j(equal, &done); 1353 __ j(equal, &done);
1394 __ mov(result, Handle<Object>(HEAP->false_value())); 1354 __ mov(result, FACTORY->false_value());
1395 __ bind(&done); 1355 __ bind(&done);
1396 } else { 1356 } else {
1397 NearLabel true_value, false_value, done; 1357 NearLabel true_value, false_value, done;
1398 __ j(equal, &true_value); 1358 __ j(equal, &true_value);
1399 __ cmp(reg, FACTORY->undefined_value()); 1359 __ cmp(reg, FACTORY->undefined_value());
1400 __ j(equal, &true_value); 1360 __ j(equal, &true_value);
1401 __ test(reg, Immediate(kSmiTagMask)); 1361 __ test(reg, Immediate(kSmiTagMask));
1402 __ j(zero, &false_value); 1362 __ j(zero, &false_value);
1403 // Check for undetectable objects by looking in the bit field in 1363 // Check for undetectable objects by looking in the bit field in
1404 // the map. The object has already been smi checked. 1364 // the map. The object has already been smi checked.
1405 Register scratch = result; 1365 Register scratch = result;
1406 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 1366 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
1407 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); 1367 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
1408 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); 1368 __ test(scratch, Immediate(1 << Map::kIsUndetectable));
1409 __ j(not_zero, &true_value); 1369 __ j(not_zero, &true_value);
1410 __ bind(&false_value); 1370 __ bind(&false_value);
1411 __ mov(result, Handle<Object>(HEAP->false_value())); 1371 __ mov(result, FACTORY->false_value());
1412 __ jmp(&done); 1372 __ jmp(&done);
1413 __ bind(&true_value); 1373 __ bind(&true_value);
1414 __ mov(result, Handle<Object>(HEAP->true_value())); 1374 __ mov(result, FACTORY->true_value());
1415 __ bind(&done); 1375 __ bind(&done);
1416 } 1376 }
1417 } 1377 }
1418 1378
1419 1379
1420 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 1380 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
1421 Register reg = ToRegister(instr->input()); 1381 Register reg = ToRegister(instr->InputAt(0));
1422 1382
1423 // TODO(fsc): If the expression is known to be a smi, then it's 1383 // TODO(fsc): If the expression is known to be a smi, then it's
1424 // definitely not null. Jump to the false block. 1384 // definitely not null. Jump to the false block.
1425 1385
1426 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1386 int true_block = chunk_->LookupDestination(instr->true_block_id());
1427 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1387 int false_block = chunk_->LookupDestination(instr->false_block_id());
1428 1388
1429 __ cmp(reg, FACTORY->null_value()); 1389 __ cmp(reg, FACTORY->null_value());
1430 if (instr->is_strict()) { 1390 if (instr->is_strict()) {
1431 EmitBranch(true_block, false_block, equal); 1391 EmitBranch(true_block, false_block, equal);
1432 } else { 1392 } else {
1433 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1393 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1434 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1394 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1435 __ j(equal, true_label); 1395 __ j(equal, true_label);
1436 __ cmp(reg, FACTORY->undefined_value()); 1396 __ cmp(reg, FACTORY->undefined_value());
1437 __ j(equal, true_label); 1397 __ j(equal, true_label);
1438 __ test(reg, Immediate(kSmiTagMask)); 1398 __ test(reg, Immediate(kSmiTagMask));
1439 __ j(zero, false_label); 1399 __ j(zero, false_label);
1440 // Check for undetectable objects by looking in the bit field in 1400 // Check for undetectable objects by looking in the bit field in
1441 // the map. The object has already been smi checked. 1401 // the map. The object has already been smi checked.
1442 Register scratch = ToRegister(instr->temp()); 1402 Register scratch = ToRegister(instr->TempAt(0));
1443 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 1403 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
1444 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); 1404 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
1445 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); 1405 __ test(scratch, Immediate(1 << Map::kIsUndetectable));
1446 EmitBranch(true_block, false_block, not_zero); 1406 EmitBranch(true_block, false_block, not_zero);
1447 } 1407 }
1448 } 1408 }
1449 1409
1450 1410
1451 Condition LCodeGen::EmitIsObject(Register input, 1411 Condition LCodeGen::EmitIsObject(Register input,
1452 Register temp1, 1412 Register temp1,
(...skipping 18 matching lines...) Expand all
1471 1431
1472 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); 1432 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset));
1473 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); 1433 __ cmp(temp2, FIRST_JS_OBJECT_TYPE);
1474 __ j(below, is_not_object); 1434 __ j(below, is_not_object);
1475 __ cmp(temp2, LAST_JS_OBJECT_TYPE); 1435 __ cmp(temp2, LAST_JS_OBJECT_TYPE);
1476 return below_equal; 1436 return below_equal;
1477 } 1437 }
1478 1438
1479 1439
1480 void LCodeGen::DoIsObject(LIsObject* instr) { 1440 void LCodeGen::DoIsObject(LIsObject* instr) {
1481 Register reg = ToRegister(instr->input()); 1441 Register reg = ToRegister(instr->InputAt(0));
1482 Register result = ToRegister(instr->result()); 1442 Register result = ToRegister(instr->result());
1483 Register temp = ToRegister(instr->temp()); 1443 Register temp = ToRegister(instr->TempAt(0));
1484 Label is_false, is_true, done; 1444 Label is_false, is_true, done;
1485 1445
1486 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); 1446 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true);
1487 __ j(true_cond, &is_true); 1447 __ j(true_cond, &is_true);
1488 1448
1489 __ bind(&is_false); 1449 __ bind(&is_false);
1490 __ mov(result, Handle<Object>(HEAP->false_value())); 1450 __ mov(result, FACTORY->false_value());
1491 __ jmp(&done); 1451 __ jmp(&done);
1492 1452
1493 __ bind(&is_true); 1453 __ bind(&is_true);
1494 __ mov(result, Handle<Object>(HEAP->true_value())); 1454 __ mov(result, FACTORY->true_value());
1495 1455
1496 __ bind(&done); 1456 __ bind(&done);
1497 } 1457 }
1498 1458
1499 1459
1500 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 1460 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
1501 Register reg = ToRegister(instr->input()); 1461 Register reg = ToRegister(instr->InputAt(0));
1502 Register temp = ToRegister(instr->temp()); 1462 Register temp = ToRegister(instr->TempAt(0));
1503 Register temp2 = ToRegister(instr->temp2()); 1463 Register temp2 = ToRegister(instr->TempAt(1));
1504 1464
1505 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1465 int true_block = chunk_->LookupDestination(instr->true_block_id());
1506 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1466 int false_block = chunk_->LookupDestination(instr->false_block_id());
1507 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1467 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1508 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1468 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1509 1469
1510 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); 1470 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label);
1511 1471
1512 EmitBranch(true_block, false_block, true_cond); 1472 EmitBranch(true_block, false_block, true_cond);
1513 } 1473 }
1514 1474
1515 1475
1516 void LCodeGen::DoIsSmi(LIsSmi* instr) { 1476 void LCodeGen::DoIsSmi(LIsSmi* instr) {
1517 Operand input = ToOperand(instr->input()); 1477 Operand input = ToOperand(instr->InputAt(0));
1518 Register result = ToRegister(instr->result()); 1478 Register result = ToRegister(instr->result());
1519 1479
1520 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1480 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1521 __ test(input, Immediate(kSmiTagMask)); 1481 __ test(input, Immediate(kSmiTagMask));
1522 __ mov(result, Handle<Object>(HEAP->true_value())); 1482 __ mov(result, FACTORY->true_value());
1523 NearLabel done; 1483 NearLabel done;
1524 __ j(zero, &done); 1484 __ j(zero, &done);
1525 __ mov(result, Handle<Object>(HEAP->false_value())); 1485 __ mov(result, FACTORY->false_value());
1526 __ bind(&done); 1486 __ bind(&done);
1527 } 1487 }
1528 1488
1529 1489
1530 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 1490 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
1531 Operand input = ToOperand(instr->input()); 1491 Operand input = ToOperand(instr->InputAt(0));
1532 1492
1533 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1493 int true_block = chunk_->LookupDestination(instr->true_block_id());
1534 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1494 int false_block = chunk_->LookupDestination(instr->false_block_id());
1535 1495
1536 __ test(input, Immediate(kSmiTagMask)); 1496 __ test(input, Immediate(kSmiTagMask));
1537 EmitBranch(true_block, false_block, zero); 1497 EmitBranch(true_block, false_block, zero);
1538 } 1498 }
1539 1499
1540 1500
1541 InstanceType LHasInstanceType::TestType() { 1501 static InstanceType TestType(HHasInstanceType* instr) {
1542 InstanceType from = hydrogen()->from(); 1502 InstanceType from = instr->from();
1543 InstanceType to = hydrogen()->to(); 1503 InstanceType to = instr->to();
1544 if (from == FIRST_TYPE) return to; 1504 if (from == FIRST_TYPE) return to;
1545 ASSERT(from == to || to == LAST_TYPE); 1505 ASSERT(from == to || to == LAST_TYPE);
1546 return from; 1506 return from;
1547 } 1507 }
1548 1508
1549 1509
1550 1510 static Condition BranchCondition(HHasInstanceType* instr) {
1551 Condition LHasInstanceType::BranchCondition() { 1511 InstanceType from = instr->from();
1552 InstanceType from = hydrogen()->from(); 1512 InstanceType to = instr->to();
1553 InstanceType to = hydrogen()->to();
1554 if (from == to) return equal; 1513 if (from == to) return equal;
1555 if (to == LAST_TYPE) return above_equal; 1514 if (to == LAST_TYPE) return above_equal;
1556 if (from == FIRST_TYPE) return below_equal; 1515 if (from == FIRST_TYPE) return below_equal;
1557 UNREACHABLE(); 1516 UNREACHABLE();
1558 return equal; 1517 return equal;
1559 } 1518 }
1560 1519
1561 1520
1562 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { 1521 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1563 Register input = ToRegister(instr->input()); 1522 Register input = ToRegister(instr->InputAt(0));
1564 Register result = ToRegister(instr->result()); 1523 Register result = ToRegister(instr->result());
1565 1524
1566 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1525 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1567 __ test(input, Immediate(kSmiTagMask)); 1526 __ test(input, Immediate(kSmiTagMask));
1568 NearLabel done, is_false; 1527 NearLabel done, is_false;
1569 __ j(zero, &is_false); 1528 __ j(zero, &is_false);
1570 __ CmpObjectType(input, instr->TestType(), result); 1529 __ CmpObjectType(input, TestType(instr->hydrogen()), result);
1571 __ j(NegateCondition(instr->BranchCondition()), &is_false); 1530 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false);
1572 __ mov(result, Handle<Object>(HEAP->true_value())); 1531 __ mov(result, FACTORY->true_value());
1573 __ jmp(&done); 1532 __ jmp(&done);
1574 __ bind(&is_false); 1533 __ bind(&is_false);
1575 __ mov(result, Handle<Object>(HEAP->false_value())); 1534 __ mov(result, FACTORY->false_value());
1576 __ bind(&done); 1535 __ bind(&done);
1577 } 1536 }
1578 1537
1579 1538
1580 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1539 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1581 Register input = ToRegister(instr->input()); 1540 Register input = ToRegister(instr->InputAt(0));
1582 Register temp = ToRegister(instr->temp()); 1541 Register temp = ToRegister(instr->TempAt(0));
1583 1542
1584 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1543 int true_block = chunk_->LookupDestination(instr->true_block_id());
1585 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1544 int false_block = chunk_->LookupDestination(instr->false_block_id());
1586 1545
1587 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1546 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1588 1547
1589 __ test(input, Immediate(kSmiTagMask)); 1548 __ test(input, Immediate(kSmiTagMask));
1590 __ j(zero, false_label); 1549 __ j(zero, false_label);
1591 1550
1592 __ CmpObjectType(input, instr->TestType(), temp); 1551 __ CmpObjectType(input, TestType(instr->hydrogen()), temp);
1593 EmitBranch(true_block, false_block, instr->BranchCondition()); 1552 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
1594 } 1553 }
1595 1554
1596 1555
1597 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { 1556 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1598 Register input = ToRegister(instr->input()); 1557 Register input = ToRegister(instr->InputAt(0));
1599 Register result = ToRegister(instr->result()); 1558 Register result = ToRegister(instr->result());
1600 1559
1601 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1560 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1602 __ mov(result, Handle<Object>(HEAP->true_value())); 1561 __ mov(result, FACTORY->true_value());
1603 __ test(FieldOperand(input, String::kHashFieldOffset), 1562 __ test(FieldOperand(input, String::kHashFieldOffset),
1604 Immediate(String::kContainsCachedArrayIndexMask)); 1563 Immediate(String::kContainsCachedArrayIndexMask));
1605 NearLabel done; 1564 NearLabel done;
1606 __ j(not_zero, &done); 1565 __ j(not_zero, &done);
1607 __ mov(result, Handle<Object>(HEAP->false_value())); 1566 __ mov(result, FACTORY->false_value());
1608 __ bind(&done); 1567 __ bind(&done);
1609 } 1568 }
1610 1569
1611 1570
1612 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1571 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1613 LHasCachedArrayIndexAndBranch* instr) { 1572 LHasCachedArrayIndexAndBranch* instr) {
1614 Register input = ToRegister(instr->input()); 1573 Register input = ToRegister(instr->InputAt(0));
1615 1574
1616 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1575 int true_block = chunk_->LookupDestination(instr->true_block_id());
1617 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1576 int false_block = chunk_->LookupDestination(instr->false_block_id());
1618 1577
1619 __ test(FieldOperand(input, String::kHashFieldOffset), 1578 __ test(FieldOperand(input, String::kHashFieldOffset),
1620 Immediate(String::kContainsCachedArrayIndexMask)); 1579 Immediate(String::kContainsCachedArrayIndexMask));
1621 EmitBranch(true_block, false_block, not_equal); 1580 EmitBranch(true_block, false_block, not_equal);
1622 } 1581 }
1623 1582
1624 1583
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 // booted. This routine isn't expected to work for random API-created 1632 // booted. This routine isn't expected to work for random API-created
1674 // classes and it doesn't have to because you can't access it with natives 1633 // classes and it doesn't have to because you can't access it with natives
1675 // syntax. Since both sides are symbols it is sufficient to use an identity 1634 // syntax. Since both sides are symbols it is sufficient to use an identity
1676 // comparison. 1635 // comparison.
1677 __ cmp(temp, class_name); 1636 __ cmp(temp, class_name);
1678 // End with the answer in the z flag. 1637 // End with the answer in the z flag.
1679 } 1638 }
1680 1639
1681 1640
1682 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { 1641 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
1683 Register input = ToRegister(instr->input()); 1642 Register input = ToRegister(instr->InputAt(0));
1684 Register result = ToRegister(instr->result()); 1643 Register result = ToRegister(instr->result());
1685 ASSERT(input.is(result)); 1644 ASSERT(input.is(result));
1686 Register temp = ToRegister(instr->temporary()); 1645 Register temp = ToRegister(instr->TempAt(0));
1687 Handle<String> class_name = instr->hydrogen()->class_name(); 1646 Handle<String> class_name = instr->hydrogen()->class_name();
1688 NearLabel done; 1647 NearLabel done;
1689 Label is_true, is_false; 1648 Label is_true, is_false;
1690 1649
1691 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); 1650 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input);
1692 1651
1693 __ j(not_equal, &is_false); 1652 __ j(not_equal, &is_false);
1694 1653
1695 __ bind(&is_true); 1654 __ bind(&is_true);
1696 __ mov(result, Handle<Object>(HEAP->true_value())); 1655 __ mov(result, FACTORY->true_value());
1697 __ jmp(&done); 1656 __ jmp(&done);
1698 1657
1699 __ bind(&is_false); 1658 __ bind(&is_false);
1700 __ mov(result, Handle<Object>(HEAP->false_value())); 1659 __ mov(result, FACTORY->false_value());
1701 __ bind(&done); 1660 __ bind(&done);
1702 } 1661 }
1703 1662
1704 1663
1705 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 1664 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
1706 Register input = ToRegister(instr->input()); 1665 Register input = ToRegister(instr->InputAt(0));
1707 Register temp = ToRegister(instr->temporary()); 1666 Register temp = ToRegister(instr->TempAt(0));
1708 Register temp2 = ToRegister(instr->temporary2()); 1667 Register temp2 = ToRegister(instr->TempAt(1));
1709 if (input.is(temp)) { 1668 if (input.is(temp)) {
1710 // Swap. 1669 // Swap.
1711 Register swapper = temp; 1670 Register swapper = temp;
1712 temp = temp2; 1671 temp = temp2;
1713 temp2 = swapper; 1672 temp2 = swapper;
1714 } 1673 }
1715 Handle<String> class_name = instr->hydrogen()->class_name(); 1674 Handle<String> class_name = instr->hydrogen()->class_name();
1716 1675
1717 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1676 int true_block = chunk_->LookupDestination(instr->true_block_id());
1718 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1677 int false_block = chunk_->LookupDestination(instr->false_block_id());
1719 1678
1720 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1679 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1721 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1680 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1722 1681
1723 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); 1682 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
1724 1683
1725 EmitBranch(true_block, false_block, equal); 1684 EmitBranch(true_block, false_block, equal);
1726 } 1685 }
1727 1686
1728 1687
1729 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 1688 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
1730 Register reg = ToRegister(instr->input()); 1689 Register reg = ToRegister(instr->InputAt(0));
1731 int true_block = instr->true_block_id(); 1690 int true_block = instr->true_block_id();
1732 int false_block = instr->false_block_id(); 1691 int false_block = instr->false_block_id();
1733 1692
1734 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); 1693 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
1735 EmitBranch(true_block, false_block, equal); 1694 EmitBranch(true_block, false_block, equal);
1736 } 1695 }
1737 1696
1738 1697
1739 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1698 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
1740 // Object and function are in fixed registers defined by the stub. 1699 // Object and function are in fixed registers defined by the stub.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1777 1736
1778 private: 1737 private:
1779 LInstanceOfKnownGlobal* instr_; 1738 LInstanceOfKnownGlobal* instr_;
1780 Label map_check_; 1739 Label map_check_;
1781 }; 1740 };
1782 1741
1783 DeferredInstanceOfKnownGlobal* deferred; 1742 DeferredInstanceOfKnownGlobal* deferred;
1784 deferred = new DeferredInstanceOfKnownGlobal(this, instr); 1743 deferred = new DeferredInstanceOfKnownGlobal(this, instr);
1785 1744
1786 Label done, false_result; 1745 Label done, false_result;
1787 Register object = ToRegister(instr->input()); 1746 Register object = ToRegister(instr->InputAt(0));
1788 Register temp = ToRegister(instr->temp()); 1747 Register temp = ToRegister(instr->TempAt(0));
1789 1748
1790 // A Smi is not instance of anything. 1749 // A Smi is not instance of anything.
1791 __ test(object, Immediate(kSmiTagMask)); 1750 __ test(object, Immediate(kSmiTagMask));
1792 __ j(zero, &false_result, not_taken); 1751 __ j(zero, &false_result, not_taken);
1793 1752
1794 // This is the inlined call site instanceof cache. The two occourences of the 1753 // This is the inlined call site instanceof cache. The two occourences of the
1795 // hole value will be patched to the last map/result pair generated by the 1754 // hole value will be patched to the last map/result pair generated by the
1796 // instanceof stub. 1755 // instanceof stub.
1797 NearLabel cache_miss; 1756 NearLabel cache_miss;
1798 Register map = ToRegister(instr->temp()); 1757 Register map = ToRegister(instr->TempAt(0));
1799 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); 1758 __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
1800 __ bind(deferred->map_check()); // Label for calculating code patching. 1759 __ bind(deferred->map_check()); // Label for calculating code patching.
1801 __ cmp(map, FACTORY->the_hole_value()); // Patched to cached map. 1760 __ cmp(map, FACTORY->the_hole_value()); // Patched to cached map.
1802 __ j(not_equal, &cache_miss, not_taken); 1761 __ j(not_equal, &cache_miss, not_taken);
1803 __ mov(eax, FACTORY->the_hole_value()); // Patched to either true or false. 1762 __ mov(eax, FACTORY->the_hole_value()); // Patched to either true or false.
1804 __ jmp(&done); 1763 __ jmp(&done);
1805 1764
1806 // The inlined call site cache did not match. Check null and string before 1765 // The inlined call site cache did not match. Check null and string before
1807 // calling the deferred code. 1766 // calling the deferred code.
1808 __ bind(&cache_miss); 1767 __ bind(&cache_miss);
(...skipping 27 matching lines...) Expand all
1836 flags | InstanceofStub::kArgsInRegisters); 1795 flags | InstanceofStub::kArgsInRegisters);
1837 flags = static_cast<InstanceofStub::Flags>( 1796 flags = static_cast<InstanceofStub::Flags>(
1838 flags | InstanceofStub::kCallSiteInlineCheck); 1797 flags | InstanceofStub::kCallSiteInlineCheck);
1839 flags = static_cast<InstanceofStub::Flags>( 1798 flags = static_cast<InstanceofStub::Flags>(
1840 flags | InstanceofStub::kReturnTrueFalseObject); 1799 flags | InstanceofStub::kReturnTrueFalseObject);
1841 InstanceofStub stub(flags); 1800 InstanceofStub stub(flags);
1842 1801
1843 // Get the temp register reserved by the instruction. This needs to be edi as 1802 // Get the temp register reserved by the instruction. This needs to be edi as
1844 // its slot of the pushing of safepoint registers is used to communicate the 1803 // its slot of the pushing of safepoint registers is used to communicate the
1845 // offset to the location of the map check. 1804 // offset to the location of the map check.
1846 Register temp = ToRegister(instr->temp()); 1805 Register temp = ToRegister(instr->TempAt(0));
1847 ASSERT(temp.is(edi)); 1806 ASSERT(temp.is(edi));
1848 __ mov(InstanceofStub::right(), Immediate(instr->function())); 1807 __ mov(InstanceofStub::right(), Immediate(instr->function()));
1849 static const int kAdditionalDelta = 13; 1808 static const int kAdditionalDelta = 13;
1850 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; 1809 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
1851 Label before_push_delta; 1810 Label before_push_delta;
1852 __ bind(&before_push_delta); 1811 __ bind(&before_push_delta);
1853 __ mov(temp, Immediate(delta)); 1812 __ mov(temp, Immediate(delta));
1854 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); 1813 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp);
1855 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); 1814 __ call(stub.GetCode(), RelocInfo::CODE_TARGET);
1856 ASSERT_EQ(kAdditionalDelta, 1815 ASSERT_EQ(kAdditionalDelta,
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1941 Register result = ToRegister(instr->result()); 1900 Register result = ToRegister(instr->result());
1942 __ mov(result, Operand::Cell(instr->hydrogen()->cell())); 1901 __ mov(result, Operand::Cell(instr->hydrogen()->cell()));
1943 if (instr->hydrogen()->check_hole_value()) { 1902 if (instr->hydrogen()->check_hole_value()) {
1944 __ cmp(result, FACTORY->the_hole_value()); 1903 __ cmp(result, FACTORY->the_hole_value());
1945 DeoptimizeIf(equal, instr->environment()); 1904 DeoptimizeIf(equal, instr->environment());
1946 } 1905 }
1947 } 1906 }
1948 1907
1949 1908
1950 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { 1909 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
1951 Register value = ToRegister(instr->input()); 1910 Register value = ToRegister(instr->InputAt(0));
1952 __ mov(Operand::Cell(instr->hydrogen()->cell()), value); 1911 __ mov(Operand::Cell(instr->hydrogen()->cell()), value);
1953 } 1912 }
1954 1913
1955 1914
1915 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
1916 // TODO(antonm): load a context with a separate instruction.
1917 Register result = ToRegister(instr->result());
1918 __ LoadContext(result, instr->context_chain_length());
1919 __ mov(result, ContextOperand(result, instr->slot_index()));
1920 }
1921
1922
1956 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 1923 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
1957 Register object = ToRegister(instr->input()); 1924 Register object = ToRegister(instr->InputAt(0));
1958 Register result = ToRegister(instr->result()); 1925 Register result = ToRegister(instr->result());
1959 if (instr->hydrogen()->is_in_object()) { 1926 if (instr->hydrogen()->is_in_object()) {
1960 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); 1927 __ mov(result, FieldOperand(object, instr->hydrogen()->offset()));
1961 } else { 1928 } else {
1962 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 1929 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
1963 __ mov(result, FieldOperand(result, instr->hydrogen()->offset())); 1930 __ mov(result, FieldOperand(result, instr->hydrogen()->offset()));
1964 } 1931 }
1965 } 1932 }
1966 1933
1967 1934
1968 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { 1935 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
1969 ASSERT(ToRegister(instr->object()).is(eax)); 1936 ASSERT(ToRegister(instr->object()).is(eax));
1970 ASSERT(ToRegister(instr->result()).is(eax)); 1937 ASSERT(ToRegister(instr->result()).is(eax));
1971 1938
1972 __ mov(ecx, instr->name()); 1939 __ mov(ecx, instr->name());
1973 Handle<Code> ic(Isolate::Current()->builtins()->builtin( 1940 Handle<Code> ic(Isolate::Current()->builtins()->builtin(
1974 Builtins::LoadIC_Initialize)); 1941 Builtins::LoadIC_Initialize));
1975 CallCode(ic, RelocInfo::CODE_TARGET, instr); 1942 CallCode(ic, RelocInfo::CODE_TARGET, instr);
1976 } 1943 }
1977 1944
1978 1945
1979 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 1946 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
1980 Register function = ToRegister(instr->function()); 1947 Register function = ToRegister(instr->function());
1981 Register temp = ToRegister(instr->temporary()); 1948 Register temp = ToRegister(instr->TempAt(0));
1982 Register result = ToRegister(instr->result()); 1949 Register result = ToRegister(instr->result());
1983 1950
1984 // Check that the function really is a function. 1951 // Check that the function really is a function.
1985 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); 1952 __ CmpObjectType(function, JS_FUNCTION_TYPE, result);
1986 DeoptimizeIf(not_equal, instr->environment()); 1953 DeoptimizeIf(not_equal, instr->environment());
1987 1954
1988 // Check whether the function has an instance prototype. 1955 // Check whether the function has an instance prototype.
1989 NearLabel non_instance; 1956 NearLabel non_instance;
1990 __ test_b(FieldOperand(result, Map::kBitFieldOffset), 1957 __ test_b(FieldOperand(result, Map::kBitFieldOffset),
1991 1 << Map::kHasNonInstancePrototype); 1958 1 << Map::kHasNonInstancePrototype);
(...skipping 20 matching lines...) Expand all
2012 // in the function's map. 1979 // in the function's map.
2013 __ bind(&non_instance); 1980 __ bind(&non_instance);
2014 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); 1981 __ mov(result, FieldOperand(result, Map::kConstructorOffset));
2015 1982
2016 // All done. 1983 // All done.
2017 __ bind(&done); 1984 __ bind(&done);
2018 } 1985 }
2019 1986
2020 1987
2021 void LCodeGen::DoLoadElements(LLoadElements* instr) { 1988 void LCodeGen::DoLoadElements(LLoadElements* instr) {
2022 ASSERT(instr->result()->Equals(instr->input())); 1989 ASSERT(instr->result()->Equals(instr->InputAt(0)));
2023 Register reg = ToRegister(instr->input()); 1990 Register reg = ToRegister(instr->InputAt(0));
2024 __ mov(reg, FieldOperand(reg, JSObject::kElementsOffset)); 1991 __ mov(reg, FieldOperand(reg, JSObject::kElementsOffset));
2025 if (FLAG_debug_code) { 1992 if (FLAG_debug_code) {
2026 NearLabel done; 1993 NearLabel done;
2027 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 1994 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
2028 Immediate(FACTORY->fixed_array_map())); 1995 Immediate(FACTORY->fixed_array_map()));
2029 __ j(equal, &done); 1996 __ j(equal, &done);
2030 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 1997 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
2031 Immediate(FACTORY->fixed_cow_array_map())); 1998 Immediate(FACTORY->fixed_cow_array_map()));
2032 __ Check(equal, "Check for fast elements failed."); 1999 __ Check(equal, "Check for fast elements failed.");
2033 __ bind(&done); 2000 __ bind(&done);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2094 __ bind(&adapted); 2061 __ bind(&adapted);
2095 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2062 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2096 2063
2097 // Result is the frame pointer for the frame if not adapted and for the real 2064 // Result is the frame pointer for the frame if not adapted and for the real
2098 // frame below the adaptor frame if adapted. 2065 // frame below the adaptor frame if adapted.
2099 __ bind(&done); 2066 __ bind(&done);
2100 } 2067 }
2101 2068
2102 2069
2103 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { 2070 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
2104 Operand elem = ToOperand(instr->input()); 2071 Operand elem = ToOperand(instr->InputAt(0));
2105 Register result = ToRegister(instr->result()); 2072 Register result = ToRegister(instr->result());
2106 2073
2107 NearLabel done; 2074 NearLabel done;
2108 2075
2109 // If no arguments adaptor frame the number of arguments is fixed. 2076 // If no arguments adaptor frame the number of arguments is fixed.
2110 __ cmp(ebp, elem); 2077 __ cmp(ebp, elem);
2111 __ mov(result, Immediate(scope()->num_parameters())); 2078 __ mov(result, Immediate(scope()->num_parameters()));
2112 __ j(equal, &done); 2079 __ j(equal, &done);
2113 2080
2114 // Arguments adaptor frame present. Get argument length from there. 2081 // Arguments adaptor frame present. Get argument length from there.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 ASSERT(receiver.is(eax)); 2135 ASSERT(receiver.is(eax));
2169 v8::internal::ParameterCount actual(eax); 2136 v8::internal::ParameterCount actual(eax);
2170 SafepointGenerator safepoint_generator(this, 2137 SafepointGenerator safepoint_generator(this,
2171 instr->pointer_map(), 2138 instr->pointer_map(),
2172 Safepoint::kNoDeoptimizationIndex); 2139 Safepoint::kNoDeoptimizationIndex);
2173 __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator); 2140 __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator);
2174 } 2141 }
2175 2142
2176 2143
2177 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2144 void LCodeGen::DoPushArgument(LPushArgument* instr) {
2178 LOperand* argument = instr->input(); 2145 LOperand* argument = instr->InputAt(0);
2179 if (argument->IsConstantOperand()) { 2146 if (argument->IsConstantOperand()) {
2180 __ push(ToImmediate(argument)); 2147 __ push(ToImmediate(argument));
2181 } else { 2148 } else {
2182 __ push(ToOperand(argument)); 2149 __ push(ToOperand(argument));
2183 } 2150 }
2184 } 2151 }
2185 2152
2186 2153
2187 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { 2154 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
2188 Register result = ToRegister(instr->result()); 2155 Register result = ToRegister(instr->result());
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2234 2201
2235 2202
2236 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 2203 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
2237 ASSERT(ToRegister(instr->result()).is(eax)); 2204 ASSERT(ToRegister(instr->result()).is(eax));
2238 __ mov(edi, instr->function()); 2205 __ mov(edi, instr->function());
2239 CallKnownFunction(instr->function(), instr->arity(), instr); 2206 CallKnownFunction(instr->function(), instr->arity(), instr);
2240 } 2207 }
2241 2208
2242 2209
2243 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { 2210 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
2244 Register input_reg = ToRegister(instr->input()); 2211 Register input_reg = ToRegister(instr->InputAt(0));
2245 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 2212 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
2246 FACTORY->heap_number_map()); 2213 FACTORY->heap_number_map());
2247 DeoptimizeIf(not_equal, instr->environment()); 2214 DeoptimizeIf(not_equal, instr->environment());
2248 2215
2249 Label done; 2216 Label done;
2250 Register tmp = input_reg.is(eax) ? ecx : eax; 2217 Register tmp = input_reg.is(eax) ? ecx : eax;
2251 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; 2218 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
2252 2219
2253 // Preserve the value of all registers. 2220 // Preserve the value of all registers.
2254 __ PushSafepointRegisters(); 2221 __ PushSafepointRegisters();
2255 2222
2256 Label negative; 2223 Label negative;
2257 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 2224 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
2258 // Check the sign of the argument. If the argument is positive, 2225 // Check the sign of the argument. If the argument is positive, just
2259 // just return it. 2226 // return it. We do not need to patch the stack since |input| and
2227 // |result| are the same register and |input| will be restored
2228 // unchanged by popping safepoint registers.
2260 __ test(tmp, Immediate(HeapNumber::kSignMask)); 2229 __ test(tmp, Immediate(HeapNumber::kSignMask));
2261 __ j(not_zero, &negative); 2230 __ j(not_zero, &negative);
2262 __ mov(tmp, input_reg);
2263 __ jmp(&done); 2231 __ jmp(&done);
2264 2232
2265 __ bind(&negative); 2233 __ bind(&negative);
2266 2234
2267 Label allocated, slow; 2235 Label allocated, slow;
2268 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); 2236 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
2269 __ jmp(&allocated); 2237 __ jmp(&allocated);
2270 2238
2271 // Slow case: Call the runtime system to do the number allocation. 2239 // Slow case: Call the runtime system to do the number allocation.
2272 __ bind(&slow); 2240 __ bind(&slow);
2273 2241
2274 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 2242 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
2275 RecordSafepointWithRegisters( 2243 RecordSafepointWithRegisters(
2276 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 2244 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2277 // Set the pointer to the new heap number in tmp. 2245 // Set the pointer to the new heap number in tmp.
2278 if (!tmp.is(eax)) __ mov(tmp, eax); 2246 if (!tmp.is(eax)) __ mov(tmp, eax);
2279 2247
2280 // Restore input_reg after call to runtime. 2248 // Restore input_reg after call to runtime.
2281 __ mov(input_reg, Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize)); 2249 __ mov(input_reg, Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize));
2282 2250
2283 __ bind(&allocated); 2251 __ bind(&allocated);
2284 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 2252 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset));
2285 __ and_(tmp2, ~HeapNumber::kSignMask); 2253 __ and_(tmp2, ~HeapNumber::kSignMask);
2286 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); 2254 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
2287 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 2255 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
2288 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); 2256 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
2257 __ mov(Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize), tmp);
2289 2258
2290 __ bind(&done); 2259 __ bind(&done);
2291 __ mov(Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize), tmp); 2260 __ PopSafepointRegisters();
2261 }
2292 2262
2293 __ PopSafepointRegisters(); 2263
2264 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
2265 Register input_reg = ToRegister(instr->InputAt(0));
2266 __ test(input_reg, Operand(input_reg));
2267 Label is_positive;
2268 __ j(not_sign, &is_positive);
2269 __ neg(input_reg);
2270 __ test(input_reg, Operand(input_reg));
2271 DeoptimizeIf(negative, instr->environment());
2272 __ bind(&is_positive);
2294 } 2273 }
2295 2274
2296 2275
2297 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 2276 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
2298 // Class for deferred case. 2277 // Class for deferred case.
2299 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 2278 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
2300 public: 2279 public:
2301 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 2280 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
2302 LUnaryMathOperation* instr) 2281 LUnaryMathOperation* instr)
2303 : LDeferredCode(codegen), instr_(instr) { } 2282 : LDeferredCode(codegen), instr_(instr) { }
2304 virtual void Generate() { 2283 virtual void Generate() {
2305 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 2284 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
2306 } 2285 }
2307 private: 2286 private:
2308 LUnaryMathOperation* instr_; 2287 LUnaryMathOperation* instr_;
2309 }; 2288 };
2310 2289
2311 ASSERT(instr->input()->Equals(instr->result())); 2290 ASSERT(instr->InputAt(0)->Equals(instr->result()));
2312 Representation r = instr->hydrogen()->value()->representation(); 2291 Representation r = instr->hydrogen()->value()->representation();
2313 2292
2314 if (r.IsDouble()) { 2293 if (r.IsDouble()) {
2315 XMMRegister scratch = xmm0; 2294 XMMRegister scratch = xmm0;
2316 XMMRegister input_reg = ToDoubleRegister(instr->input()); 2295 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2317 __ pxor(scratch, scratch); 2296 __ pxor(scratch, scratch);
2318 __ subsd(scratch, input_reg); 2297 __ subsd(scratch, input_reg);
2319 __ pand(input_reg, scratch); 2298 __ pand(input_reg, scratch);
2320 } else if (r.IsInteger32()) { 2299 } else if (r.IsInteger32()) {
2321 Register input_reg = ToRegister(instr->input()); 2300 EmitIntegerMathAbs(instr);
2322 __ test(input_reg, Operand(input_reg));
2323 Label is_positive;
2324 __ j(not_sign, &is_positive);
2325 __ neg(input_reg);
2326 __ test(input_reg, Operand(input_reg));
2327 DeoptimizeIf(negative, instr->environment());
2328 __ bind(&is_positive);
2329 } else { // Tagged case. 2301 } else { // Tagged case.
2330 DeferredMathAbsTaggedHeapNumber* deferred = 2302 DeferredMathAbsTaggedHeapNumber* deferred =
2331 new DeferredMathAbsTaggedHeapNumber(this, instr); 2303 new DeferredMathAbsTaggedHeapNumber(this, instr);
2332 Label not_smi; 2304 Register input_reg = ToRegister(instr->InputAt(0));
2333 Register input_reg = ToRegister(instr->input());
2334 // Smi check. 2305 // Smi check.
2335 __ test(input_reg, Immediate(kSmiTagMask)); 2306 __ test(input_reg, Immediate(kSmiTagMask));
2336 __ j(not_zero, deferred->entry()); 2307 __ j(not_zero, deferred->entry());
2337 __ test(input_reg, Operand(input_reg)); 2308 EmitIntegerMathAbs(instr);
2338 Label is_positive;
2339 __ j(not_sign, &is_positive);
2340 __ neg(input_reg);
2341
2342 __ test(input_reg, Operand(input_reg));
2343 DeoptimizeIf(negative, instr->environment());
2344
2345 __ bind(&is_positive);
2346 __ bind(deferred->exit()); 2309 __ bind(deferred->exit());
2347 } 2310 }
2348 } 2311 }
2349 2312
2350 2313
2351 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { 2314 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
2352 XMMRegister xmm_scratch = xmm0; 2315 XMMRegister xmm_scratch = xmm0;
2353 Register output_reg = ToRegister(instr->result()); 2316 Register output_reg = ToRegister(instr->result());
2354 XMMRegister input_reg = ToDoubleRegister(instr->input()); 2317 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2355 __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. 2318 __ xorpd(xmm_scratch, xmm_scratch); // Zero the register.
2356 __ ucomisd(input_reg, xmm_scratch); 2319 __ ucomisd(input_reg, xmm_scratch);
2357 2320
2358 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 2321 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
2359 DeoptimizeIf(below_equal, instr->environment()); 2322 DeoptimizeIf(below_equal, instr->environment());
2360 } else { 2323 } else {
2361 DeoptimizeIf(below, instr->environment()); 2324 DeoptimizeIf(below, instr->environment());
2362 } 2325 }
2363 2326
2364 // Use truncating instruction (OK because input is positive). 2327 // Use truncating instruction (OK because input is positive).
2365 __ cvttsd2si(output_reg, Operand(input_reg)); 2328 __ cvttsd2si(output_reg, Operand(input_reg));
2366 2329
2367 // Overflow is signalled with minint. 2330 // Overflow is signalled with minint.
2368 __ cmp(output_reg, 0x80000000u); 2331 __ cmp(output_reg, 0x80000000u);
2369 DeoptimizeIf(equal, instr->environment()); 2332 DeoptimizeIf(equal, instr->environment());
2370 } 2333 }
2371 2334
2372 2335
2373 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 2336 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
2374 XMMRegister xmm_scratch = xmm0; 2337 XMMRegister xmm_scratch = xmm0;
2375 Register output_reg = ToRegister(instr->result()); 2338 Register output_reg = ToRegister(instr->result());
2376 XMMRegister input_reg = ToDoubleRegister(instr->input()); 2339 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2377 2340
2378 // xmm_scratch = 0.5 2341 // xmm_scratch = 0.5
2379 ExternalReference one_half = ExternalReference::address_of_one_half(); 2342 ExternalReference one_half = ExternalReference::address_of_one_half();
2380 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); 2343 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half));
2381 2344
2382 // input = input + 0.5 2345 // input = input + 0.5
2383 __ addsd(input_reg, xmm_scratch); 2346 __ addsd(input_reg, xmm_scratch);
2384 2347
2385 // We need to return -0 for the input range [-0.5, 0[, otherwise 2348 // We need to return -0 for the input range [-0.5, 0[, otherwise
2386 // compute Math.floor(value + 0.5). 2349 // compute Math.floor(value + 0.5).
(...skipping 12 matching lines...) Expand all
2399 // Use truncating instruction (OK because input is positive). 2362 // Use truncating instruction (OK because input is positive).
2400 __ cvttsd2si(output_reg, Operand(input_reg)); 2363 __ cvttsd2si(output_reg, Operand(input_reg));
2401 2364
2402 // Overflow is signalled with minint. 2365 // Overflow is signalled with minint.
2403 __ cmp(output_reg, 0x80000000u); 2366 __ cmp(output_reg, 0x80000000u);
2404 DeoptimizeIf(equal, instr->environment()); 2367 DeoptimizeIf(equal, instr->environment());
2405 } 2368 }
2406 2369
2407 2370
2408 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 2371 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
2409 XMMRegister input_reg = ToDoubleRegister(instr->input()); 2372 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2410 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2373 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
2411 __ sqrtsd(input_reg, input_reg); 2374 __ sqrtsd(input_reg, input_reg);
2412 } 2375 }
2413 2376
2414 2377
2415 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { 2378 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
2416 XMMRegister xmm_scratch = xmm0; 2379 XMMRegister xmm_scratch = xmm0;
2417 XMMRegister input_reg = ToDoubleRegister(instr->input()); 2380 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2418 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2381 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
2419 ExternalReference negative_infinity = 2382 ExternalReference negative_infinity =
2420 ExternalReference::address_of_negative_infinity(); 2383 ExternalReference::address_of_negative_infinity();
2421 __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); 2384 __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity));
2422 __ ucomisd(xmm_scratch, input_reg); 2385 __ ucomisd(xmm_scratch, input_reg);
2423 DeoptimizeIf(equal, instr->environment()); 2386 DeoptimizeIf(equal, instr->environment());
2424 __ sqrtsd(input_reg, input_reg); 2387 __ sqrtsd(input_reg, input_reg);
2425 } 2388 }
2426 2389
2427 2390
2428 void LCodeGen::DoPower(LPower* instr) { 2391 void LCodeGen::DoPower(LPower* instr) {
2429 LOperand* left = instr->left(); 2392 LOperand* left = instr->InputAt(0);
2430 LOperand* right = instr->right(); 2393 LOperand* right = instr->InputAt(1);
2431 DoubleRegister result_reg = ToDoubleRegister(instr->result()); 2394 DoubleRegister result_reg = ToDoubleRegister(instr->result());
2432 Representation exponent_type = instr->hydrogen()->right()->representation(); 2395 Representation exponent_type = instr->hydrogen()->right()->representation();
2433 if (exponent_type.IsDouble()) { 2396 if (exponent_type.IsDouble()) {
2434 // It is safe to use ebx directly since the instruction is marked 2397 // It is safe to use ebx directly since the instruction is marked
2435 // as a call. 2398 // as a call.
2436 __ PrepareCallCFunction(4, ebx); 2399 __ PrepareCallCFunction(4, ebx);
2437 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); 2400 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left));
2438 __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); 2401 __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right));
2439 __ CallCFunction(ExternalReference::power_double_double_function(), 4); 2402 __ CallCFunction(ExternalReference::power_double_double_function(), 4);
2440 } else if (exponent_type.IsInteger32()) { 2403 } else if (exponent_type.IsInteger32()) {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
2533 break; 2496 break;
2534 2497
2535 default: 2498 default:
2536 UNREACHABLE(); 2499 UNREACHABLE();
2537 } 2500 }
2538 } 2501 }
2539 2502
2540 2503
2541 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { 2504 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
2542 ASSERT(ToRegister(instr->result()).is(eax)); 2505 ASSERT(ToRegister(instr->result()).is(eax));
2506 ASSERT(ToRegister(instr->InputAt(0)).is(ecx));
2543 2507
2544 int arity = instr->arity(); 2508 int arity = instr->arity();
2545 Handle<Code> ic = Isolate::Current()->stub_cache()-> 2509 Handle<Code> ic = Isolate::Current()->stub_cache()->
2546 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); 2510 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
2547 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2511 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2548 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2512 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2549 } 2513 }
2550 2514
2551 2515
2552 void LCodeGen::DoCallNamed(LCallNamed* instr) { 2516 void LCodeGen::DoCallNamed(LCallNamed* instr) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2585 2549
2586 2550
2587 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { 2551 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
2588 ASSERT(ToRegister(instr->result()).is(eax)); 2552 ASSERT(ToRegister(instr->result()).is(eax));
2589 __ mov(edi, instr->target()); 2553 __ mov(edi, instr->target());
2590 CallKnownFunction(instr->target(), instr->arity(), instr); 2554 CallKnownFunction(instr->target(), instr->arity(), instr);
2591 } 2555 }
2592 2556
2593 2557
2594 void LCodeGen::DoCallNew(LCallNew* instr) { 2558 void LCodeGen::DoCallNew(LCallNew* instr) {
2595 ASSERT(ToRegister(instr->input()).is(edi)); 2559 ASSERT(ToRegister(instr->InputAt(0)).is(edi));
2596 ASSERT(ToRegister(instr->result()).is(eax)); 2560 ASSERT(ToRegister(instr->result()).is(eax));
2597 2561
2598 Handle<Code> builtin(Isolate::Current()->builtins()->builtin( 2562 Handle<Code> builtin(Isolate::Current()->builtins()->builtin(
2599 Builtins::JSConstructCall)); 2563 Builtins::JSConstructCall));
2600 __ Set(eax, Immediate(instr->arity())); 2564 __ Set(eax, Immediate(instr->arity()));
2601 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); 2565 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr);
2602 } 2566 }
2603 2567
2604 2568
2605 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { 2569 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
2606 CallRuntime(instr->function(), instr->arity(), instr); 2570 CallRuntime(instr->function(), instr->arity(), instr);
2607 } 2571 }
2608 2572
2609 2573
2610 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 2574 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
2611 Register object = ToRegister(instr->object()); 2575 Register object = ToRegister(instr->object());
2612 Register value = ToRegister(instr->value()); 2576 Register value = ToRegister(instr->value());
2613 int offset = instr->offset(); 2577 int offset = instr->offset();
2614 2578
2615 if (!instr->transition().is_null()) { 2579 if (!instr->transition().is_null()) {
2616 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); 2580 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition());
2617 } 2581 }
2618 2582
2619 // Do the store. 2583 // Do the store.
2620 if (instr->is_in_object()) { 2584 if (instr->is_in_object()) {
2621 __ mov(FieldOperand(object, offset), value); 2585 __ mov(FieldOperand(object, offset), value);
2622 if (instr->needs_write_barrier()) { 2586 if (instr->needs_write_barrier()) {
2623 Register temp = ToRegister(instr->temp()); 2587 Register temp = ToRegister(instr->TempAt(0));
2624 // Update the write barrier for the object for in-object properties. 2588 // Update the write barrier for the object for in-object properties.
2625 __ RecordWrite(object, offset, value, temp); 2589 __ RecordWrite(object, offset, value, temp);
2626 } 2590 }
2627 } else { 2591 } else {
2628 Register temp = ToRegister(instr->temp()); 2592 Register temp = ToRegister(instr->TempAt(0));
2629 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); 2593 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset));
2630 __ mov(FieldOperand(temp, offset), value); 2594 __ mov(FieldOperand(temp, offset), value);
2631 if (instr->needs_write_barrier()) { 2595 if (instr->needs_write_barrier()) {
2632 // Update the write barrier for the properties array. 2596 // Update the write barrier for the properties array.
2633 // object is used as a scratch register. 2597 // object is used as a scratch register.
2634 __ RecordWrite(temp, offset, value, object); 2598 __ RecordWrite(temp, offset, value, object);
2635 } 2599 }
2636 } 2600 }
2637 } 2601 }
2638 2602
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2683 ASSERT(ToRegister(instr->object()).is(edx)); 2647 ASSERT(ToRegister(instr->object()).is(edx));
2684 ASSERT(ToRegister(instr->key()).is(ecx)); 2648 ASSERT(ToRegister(instr->key()).is(ecx));
2685 ASSERT(ToRegister(instr->value()).is(eax)); 2649 ASSERT(ToRegister(instr->value()).is(eax));
2686 2650
2687 Handle<Code> ic(Isolate::Current()->builtins()->builtin( 2651 Handle<Code> ic(Isolate::Current()->builtins()->builtin(
2688 Builtins::KeyedStoreIC_Initialize)); 2652 Builtins::KeyedStoreIC_Initialize));
2689 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2653 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2690 } 2654 }
2691 2655
2692 2656
2657 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
2658 class DeferredStringCharCodeAt: public LDeferredCode {
2659 public:
2660 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
2661 : LDeferredCode(codegen), instr_(instr) { }
2662 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
2663 private:
2664 LStringCharCodeAt* instr_;
2665 };
2666
2667 Register string = ToRegister(instr->string());
2668 Register index = no_reg;
2669 int const_index = -1;
2670 if (instr->index()->IsConstantOperand()) {
2671 const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2672 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
2673 if (!Smi::IsValid(const_index)) {
2674 // Guaranteed to be out of bounds because of the assert above.
2675 // So the bounds check that must dominate this instruction must
2676 // have deoptimized already.
2677 if (FLAG_debug_code) {
2678 __ Abort("StringCharCodeAt: out of bounds index.");
2679 }
2680 // No code needs to be generated.
2681 return;
2682 }
2683 } else {
2684 index = ToRegister(instr->index());
2685 }
2686 Register result = ToRegister(instr->result());
2687
2688 DeferredStringCharCodeAt* deferred =
2689 new DeferredStringCharCodeAt(this, instr);
2690
2691 NearLabel flat_string, ascii_string, done;
2692
2693 // Fetch the instance type of the receiver into result register.
2694 __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
2695 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
2696
2697 // We need special handling for non-flat strings.
2698 STATIC_ASSERT(kSeqStringTag == 0);
2699 __ test(result, Immediate(kStringRepresentationMask));
2700 __ j(zero, &flat_string);
2701
2702 // Handle non-flat strings.
2703 __ test(result, Immediate(kIsConsStringMask));
2704 __ j(zero, deferred->entry());
2705
2706 // ConsString.
2707 // Check whether the right hand side is the empty string (i.e. if
2708 // this is really a flat string in a cons string). If that is not
2709 // the case we would rather go to the runtime system now to flatten
2710 // the string.
2711 __ cmp(FieldOperand(string, ConsString::kSecondOffset),
2712 Immediate(FACTORY->empty_string()));
2713 __ j(not_equal, deferred->entry());
2714 // Get the first of the two strings and load its instance type.
2715 __ mov(string, FieldOperand(string, ConsString::kFirstOffset));
2716 __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
2717 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
2718 // If the first cons component is also non-flat, then go to runtime.
2719 STATIC_ASSERT(kSeqStringTag == 0);
2720 __ test(result, Immediate(kStringRepresentationMask));
2721 __ j(not_zero, deferred->entry());
2722
2723 // Check for 1-byte or 2-byte string.
2724 __ bind(&flat_string);
2725 STATIC_ASSERT(kAsciiStringTag != 0);
2726 __ test(result, Immediate(kStringEncodingMask));
2727 __ j(not_zero, &ascii_string);
2728
2729 // 2-byte string.
2730 // Load the 2-byte character code into the result register.
2731 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2732 if (instr->index()->IsConstantOperand()) {
2733 __ movzx_w(result,
2734 FieldOperand(string,
2735 SeqTwoByteString::kHeaderSize + 2 * const_index));
2736 } else {
2737 __ movzx_w(result, FieldOperand(string,
2738 index,
2739 times_2,
2740 SeqTwoByteString::kHeaderSize));
2741 }
2742 __ jmp(&done);
2743
2744 // ASCII string.
2745 // Load the byte into the result register.
2746 __ bind(&ascii_string);
2747 if (instr->index()->IsConstantOperand()) {
2748 __ movzx_b(result, FieldOperand(string,
2749 SeqAsciiString::kHeaderSize + const_index));
2750 } else {
2751 __ movzx_b(result, FieldOperand(string,
2752 index,
2753 times_1,
2754 SeqAsciiString::kHeaderSize));
2755 }
2756 __ bind(&done);
2757 __ bind(deferred->exit());
2758 }
2759
2760
2761 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
2762 Register string = ToRegister(instr->string());
2763 Register result = ToRegister(instr->result());
2764
2765 // TODO(3095996): Get rid of this. For now, we need to make the
2766 // result register contain a valid pointer because it is already
2767 // contained in the register pointer map.
2768 __ Set(result, Immediate(0));
2769
2770 __ PushSafepointRegisters();
2771 __ push(string);
2772 // Push the index as a smi. This is safe because of the checks in
2773 // DoStringCharCodeAt above.
2774 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
2775 if (instr->index()->IsConstantOperand()) {
2776 int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2777 __ push(Immediate(Smi::FromInt(const_index)));
2778 } else {
2779 Register index = ToRegister(instr->index());
2780 __ SmiTag(index);
2781 __ push(index);
2782 }
2783 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt);
2784 RecordSafepointWithRegisters(
2785 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex);
2786 if (FLAG_debug_code) {
2787 __ AbortIfNotSmi(eax);
2788 }
2789 __ SmiUntag(eax);
2790 __ mov(Operand(esp, EspIndexForPushAll(result) * kPointerSize), eax);
2791 __ PopSafepointRegisters();
2792 }
2793
2794
2795 void LCodeGen::DoStringLength(LStringLength* instr) {
2796 Register string = ToRegister(instr->string());
2797 Register result = ToRegister(instr->result());
2798 __ mov(result, FieldOperand(string, String::kLengthOffset));
2799 }
2800
2801
2693 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 2802 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
2694 LOperand* input = instr->input(); 2803 LOperand* input = instr->InputAt(0);
2695 ASSERT(input->IsRegister() || input->IsStackSlot()); 2804 ASSERT(input->IsRegister() || input->IsStackSlot());
2696 LOperand* output = instr->result(); 2805 LOperand* output = instr->result();
2697 ASSERT(output->IsDoubleRegister()); 2806 ASSERT(output->IsDoubleRegister());
2698 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); 2807 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input));
2699 } 2808 }
2700 2809
2701 2810
2702 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { 2811 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
2703 class DeferredNumberTagI: public LDeferredCode { 2812 class DeferredNumberTagI: public LDeferredCode {
2704 public: 2813 public:
2705 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) 2814 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
2706 : LDeferredCode(codegen), instr_(instr) { } 2815 : LDeferredCode(codegen), instr_(instr) { }
2707 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } 2816 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); }
2708 private: 2817 private:
2709 LNumberTagI* instr_; 2818 LNumberTagI* instr_;
2710 }; 2819 };
2711 2820
2712 LOperand* input = instr->input(); 2821 LOperand* input = instr->InputAt(0);
2713 ASSERT(input->IsRegister() && input->Equals(instr->result())); 2822 ASSERT(input->IsRegister() && input->Equals(instr->result()));
2714 Register reg = ToRegister(input); 2823 Register reg = ToRegister(input);
2715 2824
2716 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); 2825 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr);
2717 __ SmiTag(reg); 2826 __ SmiTag(reg);
2718 __ j(overflow, deferred->entry()); 2827 __ j(overflow, deferred->entry());
2719 __ bind(deferred->exit()); 2828 __ bind(deferred->exit());
2720 } 2829 }
2721 2830
2722 2831
2723 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { 2832 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
2724 Label slow; 2833 Label slow;
2725 Register reg = ToRegister(instr->input()); 2834 Register reg = ToRegister(instr->InputAt(0));
2726 Register tmp = reg.is(eax) ? ecx : eax; 2835 Register tmp = reg.is(eax) ? ecx : eax;
2727 2836
2728 // Preserve the value of all registers. 2837 // Preserve the value of all registers.
2729 __ PushSafepointRegisters(); 2838 __ PushSafepointRegisters();
2730 2839
2731 // There was overflow, so bits 30 and 31 of the original integer 2840 // There was overflow, so bits 30 and 31 of the original integer
2732 // disagree. Try to allocate a heap number in new space and store 2841 // disagree. Try to allocate a heap number in new space and store
2733 // the value in there. If that fails, call the runtime system. 2842 // the value in there. If that fails, call the runtime system.
2734 NearLabel done; 2843 NearLabel done;
2735 __ SmiUntag(reg); 2844 __ SmiUntag(reg);
(...skipping 29 matching lines...) Expand all
2765 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 2874 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
2766 class DeferredNumberTagD: public LDeferredCode { 2875 class DeferredNumberTagD: public LDeferredCode {
2767 public: 2876 public:
2768 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 2877 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
2769 : LDeferredCode(codegen), instr_(instr) { } 2878 : LDeferredCode(codegen), instr_(instr) { }
2770 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 2879 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
2771 private: 2880 private:
2772 LNumberTagD* instr_; 2881 LNumberTagD* instr_;
2773 }; 2882 };
2774 2883
2775 XMMRegister input_reg = ToDoubleRegister(instr->input()); 2884 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2776 Register reg = ToRegister(instr->result()); 2885 Register reg = ToRegister(instr->result());
2777 Register tmp = ToRegister(instr->temp()); 2886 Register tmp = ToRegister(instr->TempAt(0));
2778 2887
2779 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); 2888 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
2780 if (FLAG_inline_new) { 2889 if (FLAG_inline_new) {
2781 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); 2890 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
2782 } else { 2891 } else {
2783 __ jmp(deferred->entry()); 2892 __ jmp(deferred->entry());
2784 } 2893 }
2785 __ bind(deferred->exit()); 2894 __ bind(deferred->exit());
2786 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); 2895 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
2787 } 2896 }
2788 2897
2789 2898
2790 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 2899 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
2791 // TODO(3095996): Get rid of this. For now, we need to make the 2900 // TODO(3095996): Get rid of this. For now, we need to make the
2792 // result register contain a valid pointer because it is already 2901 // result register contain a valid pointer because it is already
2793 // contained in the register pointer map. 2902 // contained in the register pointer map.
2794 Register reg = ToRegister(instr->result()); 2903 Register reg = ToRegister(instr->result());
2795 __ Set(reg, Immediate(0)); 2904 __ Set(reg, Immediate(0));
2796 2905
2797 __ PushSafepointRegisters(); 2906 __ PushSafepointRegisters();
2798 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 2907 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
2799 RecordSafepointWithRegisters( 2908 RecordSafepointWithRegisters(
2800 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 2909 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2801 __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), eax); 2910 __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), eax);
2802 __ PopSafepointRegisters(); 2911 __ PopSafepointRegisters();
2803 } 2912 }
2804 2913
2805 2914
2806 void LCodeGen::DoSmiTag(LSmiTag* instr) { 2915 void LCodeGen::DoSmiTag(LSmiTag* instr) {
2807 LOperand* input = instr->input(); 2916 LOperand* input = instr->InputAt(0);
2808 ASSERT(input->IsRegister() && input->Equals(instr->result())); 2917 ASSERT(input->IsRegister() && input->Equals(instr->result()));
2809 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 2918 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
2810 __ SmiTag(ToRegister(input)); 2919 __ SmiTag(ToRegister(input));
2811 } 2920 }
2812 2921
2813 2922
2814 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 2923 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
2815 LOperand* input = instr->input(); 2924 LOperand* input = instr->InputAt(0);
2816 ASSERT(input->IsRegister() && input->Equals(instr->result())); 2925 ASSERT(input->IsRegister() && input->Equals(instr->result()));
2817 if (instr->needs_check()) { 2926 if (instr->needs_check()) {
2818 __ test(ToRegister(input), Immediate(kSmiTagMask)); 2927 __ test(ToRegister(input), Immediate(kSmiTagMask));
2819 DeoptimizeIf(not_zero, instr->environment()); 2928 DeoptimizeIf(not_zero, instr->environment());
2820 } 2929 }
2821 __ SmiUntag(ToRegister(input)); 2930 __ SmiUntag(ToRegister(input));
2822 } 2931 }
2823 2932
2824 2933
2825 void LCodeGen::EmitNumberUntagD(Register input_reg, 2934 void LCodeGen::EmitNumberUntagD(Register input_reg,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2865 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 2974 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
2866 : LDeferredCode(codegen), instr_(instr) { } 2975 : LDeferredCode(codegen), instr_(instr) { }
2867 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 2976 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
2868 private: 2977 private:
2869 LTaggedToI* instr_; 2978 LTaggedToI* instr_;
2870 }; 2979 };
2871 2980
2872 2981
2873 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { 2982 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
2874 NearLabel done, heap_number; 2983 NearLabel done, heap_number;
2875 Register input_reg = ToRegister(instr->input()); 2984 Register input_reg = ToRegister(instr->InputAt(0));
2876 2985
2877 // Heap number map check. 2986 // Heap number map check.
2878 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 2987 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
2879 FACTORY->heap_number_map()); 2988 FACTORY->heap_number_map());
2880 2989
2881 if (instr->truncating()) { 2990 if (instr->truncating()) {
2882 __ j(equal, &heap_number); 2991 __ j(equal, &heap_number);
2883 // Check for undefined. Undefined is converted to zero for truncating 2992 // Check for undefined. Undefined is converted to zero for truncating
2884 // conversions. 2993 // conversions.
2885 __ cmp(input_reg, FACTORY->undefined_value()); 2994 __ cmp(input_reg, FACTORY->undefined_value());
(...skipping 22 matching lines...) Expand all
2908 3017
2909 // Reserve space for 64 bit answer. 3018 // Reserve space for 64 bit answer.
2910 __ bind(&convert); 3019 __ bind(&convert);
2911 __ sub(Operand(esp), Immediate(kDoubleSize)); 3020 __ sub(Operand(esp), Immediate(kDoubleSize));
2912 // Do conversion, which cannot fail because we checked the exponent. 3021 // Do conversion, which cannot fail because we checked the exponent.
2913 __ fisttp_d(Operand(esp, 0)); 3022 __ fisttp_d(Operand(esp, 0));
2914 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. 3023 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result.
2915 __ add(Operand(esp), Immediate(kDoubleSize)); 3024 __ add(Operand(esp), Immediate(kDoubleSize));
2916 } else { 3025 } else {
2917 NearLabel deopt; 3026 NearLabel deopt;
2918 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); 3027 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0));
2919 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3028 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
2920 __ cvttsd2si(input_reg, Operand(xmm0)); 3029 __ cvttsd2si(input_reg, Operand(xmm0));
2921 __ cmp(input_reg, 0x80000000u); 3030 __ cmp(input_reg, 0x80000000u);
2922 __ j(not_equal, &done); 3031 __ j(not_equal, &done);
2923 // Check if the input was 0x8000000 (kMinInt). 3032 // Check if the input was 0x8000000 (kMinInt).
2924 // If no, then we got an overflow and we deoptimize. 3033 // If no, then we got an overflow and we deoptimize.
2925 ExternalReference min_int = ExternalReference::address_of_min_int(); 3034 ExternalReference min_int = ExternalReference::address_of_min_int();
2926 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); 3035 __ movdbl(xmm_temp, Operand::StaticVariable(min_int));
2927 __ ucomisd(xmm_temp, xmm0); 3036 __ ucomisd(xmm_temp, xmm0);
2928 DeoptimizeIf(not_equal, instr->environment()); 3037 DeoptimizeIf(not_equal, instr->environment());
2929 DeoptimizeIf(parity_even, instr->environment()); // NaN. 3038 DeoptimizeIf(parity_even, instr->environment()); // NaN.
2930 } 3039 }
2931 } else { 3040 } else {
2932 // Deoptimize if we don't have a heap number. 3041 // Deoptimize if we don't have a heap number.
2933 DeoptimizeIf(not_equal, instr->environment()); 3042 DeoptimizeIf(not_equal, instr->environment());
2934 3043
2935 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); 3044 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0));
2936 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3045 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
2937 __ cvttsd2si(input_reg, Operand(xmm0)); 3046 __ cvttsd2si(input_reg, Operand(xmm0));
2938 __ cvtsi2sd(xmm_temp, Operand(input_reg)); 3047 __ cvtsi2sd(xmm_temp, Operand(input_reg));
2939 __ ucomisd(xmm0, xmm_temp); 3048 __ ucomisd(xmm0, xmm_temp);
2940 DeoptimizeIf(not_equal, instr->environment()); 3049 DeoptimizeIf(not_equal, instr->environment());
2941 DeoptimizeIf(parity_even, instr->environment()); // NaN. 3050 DeoptimizeIf(parity_even, instr->environment()); // NaN.
2942 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3051 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
2943 __ test(input_reg, Operand(input_reg)); 3052 __ test(input_reg, Operand(input_reg));
2944 __ j(not_zero, &done); 3053 __ j(not_zero, &done);
2945 __ movmskpd(input_reg, xmm0); 3054 __ movmskpd(input_reg, xmm0);
2946 __ and_(input_reg, 1); 3055 __ and_(input_reg, 1);
2947 DeoptimizeIf(not_zero, instr->environment()); 3056 DeoptimizeIf(not_zero, instr->environment());
2948 } 3057 }
2949 } 3058 }
2950 __ bind(&done); 3059 __ bind(&done);
2951 } 3060 }
2952 3061
2953 3062
2954 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 3063 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
2955 LOperand* input = instr->input(); 3064 LOperand* input = instr->InputAt(0);
2956 ASSERT(input->IsRegister()); 3065 ASSERT(input->IsRegister());
2957 ASSERT(input->Equals(instr->result())); 3066 ASSERT(input->Equals(instr->result()));
2958 3067
2959 Register input_reg = ToRegister(input); 3068 Register input_reg = ToRegister(input);
2960 3069
2961 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); 3070 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr);
2962 3071
2963 // Smi check. 3072 // Smi check.
2964 __ test(input_reg, Immediate(kSmiTagMask)); 3073 __ test(input_reg, Immediate(kSmiTagMask));
2965 __ j(not_zero, deferred->entry()); 3074 __ j(not_zero, deferred->entry());
2966 3075
2967 // Smi to int32 conversion 3076 // Smi to int32 conversion
2968 __ SmiUntag(input_reg); // Untag smi. 3077 __ SmiUntag(input_reg); // Untag smi.
2969 3078
2970 __ bind(deferred->exit()); 3079 __ bind(deferred->exit());
2971 } 3080 }
2972 3081
2973 3082
2974 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 3083 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
2975 LOperand* input = instr->input(); 3084 LOperand* input = instr->InputAt(0);
2976 ASSERT(input->IsRegister()); 3085 ASSERT(input->IsRegister());
2977 LOperand* result = instr->result(); 3086 LOperand* result = instr->result();
2978 ASSERT(result->IsDoubleRegister()); 3087 ASSERT(result->IsDoubleRegister());
2979 3088
2980 Register input_reg = ToRegister(input); 3089 Register input_reg = ToRegister(input);
2981 XMMRegister result_reg = ToDoubleRegister(result); 3090 XMMRegister result_reg = ToDoubleRegister(result);
2982 3091
2983 EmitNumberUntagD(input_reg, result_reg, instr->environment()); 3092 EmitNumberUntagD(input_reg, result_reg, instr->environment());
2984 } 3093 }
2985 3094
2986 3095
2987 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3096 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
2988 LOperand* input = instr->input(); 3097 LOperand* input = instr->InputAt(0);
2989 ASSERT(input->IsDoubleRegister()); 3098 ASSERT(input->IsDoubleRegister());
2990 LOperand* result = instr->result(); 3099 LOperand* result = instr->result();
2991 ASSERT(result->IsRegister()); 3100 ASSERT(result->IsRegister());
2992 3101
2993 XMMRegister input_reg = ToDoubleRegister(input); 3102 XMMRegister input_reg = ToDoubleRegister(input);
2994 Register result_reg = ToRegister(result); 3103 Register result_reg = ToRegister(result);
2995 3104
2996 if (instr->truncating()) { 3105 if (instr->truncating()) {
2997 // Performs a truncating conversion of a floating point number as used by 3106 // Performs a truncating conversion of a floating point number as used by
2998 // the JS bitwise operations. 3107 // the JS bitwise operations.
(...skipping 17 matching lines...) Expand all
3016 DeoptimizeIf(no_condition, instr->environment()); 3125 DeoptimizeIf(no_condition, instr->environment());
3017 __ bind(&convert); 3126 __ bind(&convert);
3018 // Do conversion, which cannot fail because we checked the exponent. 3127 // Do conversion, which cannot fail because we checked the exponent.
3019 __ fld_d(Operand(esp, 0)); 3128 __ fld_d(Operand(esp, 0));
3020 __ fisttp_d(Operand(esp, 0)); 3129 __ fisttp_d(Operand(esp, 0));
3021 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. 3130 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result.
3022 __ add(Operand(esp), Immediate(kDoubleSize)); 3131 __ add(Operand(esp), Immediate(kDoubleSize));
3023 __ bind(&done); 3132 __ bind(&done);
3024 } else { 3133 } else {
3025 NearLabel done; 3134 NearLabel done;
3026 Register temp_reg = ToRegister(instr->temporary()); 3135 Register temp_reg = ToRegister(instr->TempAt(0));
3027 XMMRegister xmm_scratch = xmm0; 3136 XMMRegister xmm_scratch = xmm0;
3028 3137
3029 // If cvttsd2si succeeded, we're done. Otherwise, we attempt 3138 // If cvttsd2si succeeded, we're done. Otherwise, we attempt
3030 // manual conversion. 3139 // manual conversion.
3031 __ j(not_equal, &done); 3140 __ j(not_equal, &done);
3032 3141
3033 // Get high 32 bits of the input in result_reg and temp_reg. 3142 // Get high 32 bits of the input in result_reg and temp_reg.
3034 __ pshufd(xmm_scratch, input_reg, 1); 3143 __ pshufd(xmm_scratch, input_reg, 1);
3035 __ movd(Operand(temp_reg), xmm_scratch); 3144 __ movd(Operand(temp_reg), xmm_scratch);
3036 __ mov(result_reg, temp_reg); 3145 __ mov(result_reg, temp_reg);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
3095 // deoptimize. 3204 // deoptimize.
3096 __ and_(result_reg, 1); 3205 __ and_(result_reg, 1);
3097 DeoptimizeIf(not_zero, instr->environment()); 3206 DeoptimizeIf(not_zero, instr->environment());
3098 } 3207 }
3099 __ bind(&done); 3208 __ bind(&done);
3100 } 3209 }
3101 } 3210 }
3102 3211
3103 3212
3104 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 3213 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
3105 LOperand* input = instr->input(); 3214 LOperand* input = instr->InputAt(0);
3106 ASSERT(input->IsRegister()); 3215 ASSERT(input->IsRegister());
3107 __ test(ToRegister(input), Immediate(kSmiTagMask)); 3216 __ test(ToRegister(input), Immediate(kSmiTagMask));
3108 DeoptimizeIf(instr->condition(), instr->environment()); 3217 DeoptimizeIf(instr->condition(), instr->environment());
3109 } 3218 }
3110 3219
3111 3220
3112 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 3221 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
3113 Register input = ToRegister(instr->input()); 3222 Register input = ToRegister(instr->InputAt(0));
3114 Register temp = ToRegister(instr->temp()); 3223 Register temp = ToRegister(instr->TempAt(0));
3115 InstanceType first = instr->hydrogen()->first(); 3224 InstanceType first = instr->hydrogen()->first();
3116 InstanceType last = instr->hydrogen()->last(); 3225 InstanceType last = instr->hydrogen()->last();
3117 3226
3118 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 3227 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
3119 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
3120 static_cast<int8_t>(first));
3121 3228
3122 // If there is only one type in the interval check for equality. 3229 // If there is only one type in the interval check for equality.
3123 if (first == last) { 3230 if (first == last) {
3231 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
3232 static_cast<int8_t>(first));
3124 DeoptimizeIf(not_equal, instr->environment()); 3233 DeoptimizeIf(not_equal, instr->environment());
3125 } else { 3234 } else if (first == FIRST_STRING_TYPE && last == LAST_STRING_TYPE) {
3235 // String has a dedicated bit in instance type.
3236 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), kIsNotStringMask);
3237 DeoptimizeIf(not_zero, instr->environment());
3238 } else {
3239 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
3240 static_cast<int8_t>(first));
3126 DeoptimizeIf(below, instr->environment()); 3241 DeoptimizeIf(below, instr->environment());
3127 // Omit check for the last type. 3242 // Omit check for the last type.
3128 if (last != LAST_TYPE) { 3243 if (last != LAST_TYPE) {
3129 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 3244 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
3130 static_cast<int8_t>(last)); 3245 static_cast<int8_t>(last));
3131 DeoptimizeIf(above, instr->environment()); 3246 DeoptimizeIf(above, instr->environment());
3132 } 3247 }
3133 } 3248 }
3134 } 3249 }
3135 3250
3136 3251
3137 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { 3252 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
3138 ASSERT(instr->input()->IsRegister()); 3253 ASSERT(instr->InputAt(0)->IsRegister());
3139 Register reg = ToRegister(instr->input()); 3254 Register reg = ToRegister(instr->InputAt(0));
3140 __ cmp(reg, instr->hydrogen()->target()); 3255 __ cmp(reg, instr->hydrogen()->target());
3141 DeoptimizeIf(not_equal, instr->environment()); 3256 DeoptimizeIf(not_equal, instr->environment());
3142 } 3257 }
3143 3258
3144 3259
3145 void LCodeGen::DoCheckMap(LCheckMap* instr) { 3260 void LCodeGen::DoCheckMap(LCheckMap* instr) {
3146 LOperand* input = instr->input(); 3261 LOperand* input = instr->InputAt(0);
3147 ASSERT(input->IsRegister()); 3262 ASSERT(input->IsRegister());
3148 Register reg = ToRegister(input); 3263 Register reg = ToRegister(input);
3149 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 3264 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
3150 instr->hydrogen()->map()); 3265 instr->hydrogen()->map());
3151 DeoptimizeIf(not_equal, instr->environment()); 3266 DeoptimizeIf(not_equal, instr->environment());
3152 } 3267 }
3153 3268
3154 3269
3155 void LCodeGen::LoadPrototype(Register result, Handle<JSObject> prototype) { 3270 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) {
3156 if (HEAP->InNewSpace(*prototype)) { 3271 if (HEAP->InNewSpace(*object)) {
3157 Handle<JSGlobalPropertyCell> cell = 3272 Handle<JSGlobalPropertyCell> cell =
3158 FACTORY->NewJSGlobalPropertyCell(prototype); 3273 FACTORY->NewJSGlobalPropertyCell(object);
3159 __ mov(result, Operand::Cell(cell)); 3274 __ mov(result, Operand::Cell(cell));
3160 } else { 3275 } else {
3161 __ mov(result, prototype); 3276 __ mov(result, object);
3162 } 3277 }
3163 } 3278 }
3164 3279
3165 3280
3166 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { 3281 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
3167 Register reg = ToRegister(instr->temp()); 3282 Register reg = ToRegister(instr->TempAt(0));
3168 3283
3169 Handle<JSObject> holder = instr->holder(); 3284 Handle<JSObject> holder = instr->holder();
3170 Handle<JSObject> current_prototype = instr->prototype(); 3285 Handle<JSObject> current_prototype = instr->prototype();
3171 3286
3172 // Load prototype object. 3287 // Load prototype object.
3173 LoadPrototype(reg, current_prototype); 3288 LoadHeapObject(reg, current_prototype);
3174 3289
3175 // Check prototype maps up to the holder. 3290 // Check prototype maps up to the holder.
3176 while (!current_prototype.is_identical_to(holder)) { 3291 while (!current_prototype.is_identical_to(holder)) {
3177 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 3292 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
3178 Handle<Map>(current_prototype->map())); 3293 Handle<Map>(current_prototype->map()));
3179 DeoptimizeIf(not_equal, instr->environment()); 3294 DeoptimizeIf(not_equal, instr->environment());
3180 current_prototype = 3295 current_prototype =
3181 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); 3296 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
3182 // Load next prototype object. 3297 // Load next prototype object.
3183 LoadPrototype(reg, current_prototype); 3298 LoadHeapObject(reg, current_prototype);
3184 } 3299 }
3185 3300
3186 // Check the holder map. 3301 // Check the holder map.
3187 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 3302 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
3188 Handle<Map>(current_prototype->map())); 3303 Handle<Map>(current_prototype->map()));
3189 DeoptimizeIf(not_equal, instr->environment()); 3304 DeoptimizeIf(not_equal, instr->environment());
3190 } 3305 }
3191 3306
3192 3307
3193 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 3308 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
3301 __ push(Immediate(shared_info)); 3416 __ push(Immediate(shared_info));
3302 __ push(Immediate(pretenure 3417 __ push(Immediate(pretenure
3303 ? FACTORY->true_value() 3418 ? FACTORY->true_value()
3304 : FACTORY->false_value())); 3419 : FACTORY->false_value()));
3305 CallRuntime(Runtime::kNewClosure, 3, instr); 3420 CallRuntime(Runtime::kNewClosure, 3, instr);
3306 } 3421 }
3307 } 3422 }
3308 3423
3309 3424
3310 void LCodeGen::DoTypeof(LTypeof* instr) { 3425 void LCodeGen::DoTypeof(LTypeof* instr) {
3311 LOperand* input = instr->input(); 3426 LOperand* input = instr->InputAt(0);
3312 if (input->IsConstantOperand()) { 3427 if (input->IsConstantOperand()) {
3313 __ push(ToImmediate(input)); 3428 __ push(ToImmediate(input));
3314 } else { 3429 } else {
3315 __ push(ToOperand(input)); 3430 __ push(ToOperand(input));
3316 } 3431 }
3317 CallRuntime(Runtime::kTypeof, 1, instr); 3432 CallRuntime(Runtime::kTypeof, 1, instr);
3318 } 3433 }
3319 3434
3320 3435
3321 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { 3436 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
3322 Register input = ToRegister(instr->input()); 3437 Register input = ToRegister(instr->InputAt(0));
3323 Register result = ToRegister(instr->result()); 3438 Register result = ToRegister(instr->result());
3324 Label true_label; 3439 Label true_label;
3325 Label false_label; 3440 Label false_label;
3326 NearLabel done; 3441 NearLabel done;
3327 3442
3328 Condition final_branch_condition = EmitTypeofIs(&true_label, 3443 Condition final_branch_condition = EmitTypeofIs(&true_label,
3329 &false_label, 3444 &false_label,
3330 input, 3445 input,
3331 instr->type_literal()); 3446 instr->type_literal());
3332 __ j(final_branch_condition, &true_label); 3447 __ j(final_branch_condition, &true_label);
3333 __ bind(&false_label); 3448 __ bind(&false_label);
3334 __ mov(result, Handle<Object>(HEAP->false_value())); 3449 __ mov(result, FACTORY->false_value());
3335 __ jmp(&done); 3450 __ jmp(&done);
3336 3451
3337 __ bind(&true_label); 3452 __ bind(&true_label);
3338 __ mov(result, Handle<Object>(HEAP->true_value())); 3453 __ mov(result, FACTORY->true_value());
3339 3454
3340 __ bind(&done); 3455 __ bind(&done);
3341 } 3456 }
3342 3457
3343 3458
3344 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 3459 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
3345 Register input = ToRegister(instr->input()); 3460 Register input = ToRegister(instr->InputAt(0));
3346 int true_block = chunk_->LookupDestination(instr->true_block_id()); 3461 int true_block = chunk_->LookupDestination(instr->true_block_id());
3347 int false_block = chunk_->LookupDestination(instr->false_block_id()); 3462 int false_block = chunk_->LookupDestination(instr->false_block_id());
3348 Label* true_label = chunk_->GetAssemblyLabel(true_block); 3463 Label* true_label = chunk_->GetAssemblyLabel(true_block);
3349 Label* false_label = chunk_->GetAssemblyLabel(false_block); 3464 Label* false_label = chunk_->GetAssemblyLabel(false_block);
3350 3465
3351 Condition final_branch_condition = EmitTypeofIs(true_label, 3466 Condition final_branch_condition = EmitTypeofIs(true_label,
3352 false_label, 3467 false_label,
3353 input, 3468 input,
3354 instr->type_literal()); 3469 instr->type_literal());
3355 3470
(...skipping 17 matching lines...) Expand all
3373 __ test(input, Immediate(kSmiTagMask)); 3488 __ test(input, Immediate(kSmiTagMask));
3374 __ j(zero, false_label); 3489 __ j(zero, false_label);
3375 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); 3490 __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
3376 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 3491 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
3377 1 << Map::kIsUndetectable); 3492 1 << Map::kIsUndetectable);
3378 __ j(not_zero, false_label); 3493 __ j(not_zero, false_label);
3379 __ CmpInstanceType(input, FIRST_NONSTRING_TYPE); 3494 __ CmpInstanceType(input, FIRST_NONSTRING_TYPE);
3380 final_branch_condition = below; 3495 final_branch_condition = below;
3381 3496
3382 } else if (type_name->Equals(HEAP->boolean_symbol())) { 3497 } else if (type_name->Equals(HEAP->boolean_symbol())) {
3383 __ cmp(input, Handle<Object>(HEAP->true_value())); 3498 __ cmp(input, FACTORY->true_value());
3384 __ j(equal, true_label); 3499 __ j(equal, true_label);
3385 __ cmp(input, Handle<Object>(HEAP->false_value())); 3500 __ cmp(input, FACTORY->false_value());
3386 final_branch_condition = equal; 3501 final_branch_condition = equal;
3387 3502
3388 } else if (type_name->Equals(HEAP->undefined_symbol())) { 3503 } else if (type_name->Equals(HEAP->undefined_symbol())) {
3389 __ cmp(input, FACTORY->undefined_value()); 3504 __ cmp(input, FACTORY->undefined_value());
3390 __ j(equal, true_label); 3505 __ j(equal, true_label);
3391 __ test(input, Immediate(kSmiTagMask)); 3506 __ test(input, Immediate(kSmiTagMask));
3392 __ j(zero, false_label); 3507 __ j(zero, false_label);
3393 // Check for undetectable objects => true. 3508 // Check for undetectable objects => true.
3394 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); 3509 __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
3395 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 3510 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
3489 ASSERT(osr_pc_offset_ == -1); 3604 ASSERT(osr_pc_offset_ == -1);
3490 osr_pc_offset_ = masm()->pc_offset(); 3605 osr_pc_offset_ = masm()->pc_offset();
3491 } 3606 }
3492 3607
3493 3608
3494 #undef __ 3609 #undef __
3495 3610
3496 } } // namespace v8::internal 3611 } } // namespace v8::internal
3497 3612
3498 #endif // V8_TARGET_ARCH_IA32 3613 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698