| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 current_block_ = label->block_id(); | 591 current_block_ = label->block_id(); |
| 592 LCodeGen::DoGap(label); | 592 LCodeGen::DoGap(label); |
| 593 } | 593 } |
| 594 | 594 |
| 595 | 595 |
| 596 void LCodeGen::DoParallelMove(LParallelMove* move) { | 596 void LCodeGen::DoParallelMove(LParallelMove* move) { |
| 597 // d0 must always be a scratch register. | 597 // d0 must always be a scratch register. |
| 598 DoubleRegister dbl_scratch = d0; | 598 DoubleRegister dbl_scratch = d0; |
| 599 LUnallocated marker_operand(LUnallocated::NONE); | 599 LUnallocated marker_operand(LUnallocated::NONE); |
| 600 | 600 |
| 601 Register core_scratch = r9; | 601 Register core_scratch = scratch0(); |
| 602 bool destroys_core_scratch = false; | 602 bool destroys_core_scratch = false; |
| 603 | 603 |
| 604 LGapResolver resolver(move->move_operands(), &marker_operand); | 604 LGapResolver resolver(move->move_operands(), &marker_operand); |
| 605 const ZoneList<LMoveOperands>* moves = resolver.ResolveInReverseOrder(); | 605 const ZoneList<LMoveOperands>* moves = resolver.ResolveInReverseOrder(); |
| 606 for (int i = moves->length() - 1; i >= 0; --i) { | 606 for (int i = moves->length() - 1; i >= 0; --i) { |
| 607 LMoveOperands move = moves->at(i); | 607 LMoveOperands move = moves->at(i); |
| 608 LOperand* from = move.from(); | 608 LOperand* from = move.from(); |
| 609 LOperand* to = move.to(); | 609 LOperand* to = move.to(); |
| 610 ASSERT(!from->IsDoubleRegister() || | 610 ASSERT(!from->IsDoubleRegister() || |
| 611 !ToDoubleRegister(from).is(dbl_scratch)); | 611 !ToDoubleRegister(from).is(dbl_scratch)); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 } | 723 } |
| 724 } | 724 } |
| 725 | 725 |
| 726 | 726 |
| 727 void LCodeGen::DoParameter(LParameter* instr) { | 727 void LCodeGen::DoParameter(LParameter* instr) { |
| 728 // Nothing to do. | 728 // Nothing to do. |
| 729 } | 729 } |
| 730 | 730 |
| 731 | 731 |
| 732 void LCodeGen::DoCallStub(LCallStub* instr) { | 732 void LCodeGen::DoCallStub(LCallStub* instr) { |
| 733 Abort("DoCallStub unimplemented."); | 733 ASSERT(ToRegister(instr->result()).is(r0)); |
| 734 switch (instr->hydrogen()->major_key()) { |
| 735 case CodeStub::RegExpConstructResult: { |
| 736 RegExpConstructResultStub stub; |
| 737 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 738 break; |
| 739 } |
| 740 case CodeStub::RegExpExec: { |
| 741 RegExpExecStub stub; |
| 742 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 743 break; |
| 744 } |
| 745 case CodeStub::SubString: { |
| 746 SubStringStub stub; |
| 747 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 748 break; |
| 749 } |
| 750 case CodeStub::StringCharAt: { |
| 751 Abort("StringCharAtStub unimplemented."); |
| 752 break; |
| 753 } |
| 754 case CodeStub::MathPow: { |
| 755 Abort("MathPowStub unimplemented."); |
| 756 break; |
| 757 } |
| 758 case CodeStub::NumberToString: { |
| 759 NumberToStringStub stub; |
| 760 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 761 break; |
| 762 } |
| 763 case CodeStub::StringAdd: { |
| 764 StringAddStub stub(NO_STRING_ADD_FLAGS); |
| 765 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 766 break; |
| 767 } |
| 768 case CodeStub::StringCompare: { |
| 769 StringCompareStub stub; |
| 770 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 771 break; |
| 772 } |
| 773 case CodeStub::TranscendentalCache: { |
| 774 Abort("TranscendentalCache unimplemented."); |
| 775 break; |
| 776 } |
| 777 default: |
| 778 UNREACHABLE(); |
| 779 } |
| 734 } | 780 } |
| 735 | 781 |
| 736 | 782 |
| 737 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 783 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 738 // Nothing to do. | 784 // Nothing to do. |
| 739 } | 785 } |
| 740 | 786 |
| 741 | 787 |
| 742 void LCodeGen::DoModI(LModI* instr) { | 788 void LCodeGen::DoModI(LModI* instr) { |
| 743 Abort("DoModI unimplemented."); | 789 Abort("DoModI unimplemented."); |
| 744 } | 790 } |
| 745 | 791 |
| 746 | 792 |
| 747 void LCodeGen::DoDivI(LDivI* instr) { | 793 void LCodeGen::DoDivI(LDivI* instr) { |
| 748 Abort("DoDivI unimplemented."); | 794 Abort("DoDivI unimplemented."); |
| 749 } | 795 } |
| 750 | 796 |
| 751 | 797 |
| 752 void LCodeGen::DoMulI(LMulI* instr) { | 798 void LCodeGen::DoMulI(LMulI* instr) { |
| 799 Register scratch = scratch0(); |
| 753 Register left = ToRegister(instr->left()); | 800 Register left = ToRegister(instr->left()); |
| 754 Register scratch = r9; | |
| 755 Register right = EmitLoadRegister(instr->right(), scratch); | 801 Register right = EmitLoadRegister(instr->right(), scratch); |
| 756 | 802 |
| 757 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && | 803 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 758 !instr->right()->IsConstantOperand()) { | 804 !instr->right()->IsConstantOperand()) { |
| 759 __ orr(ToRegister(instr->temp()), left, right); | 805 __ orr(ToRegister(instr->temp()), left, right); |
| 760 } | 806 } |
| 761 | 807 |
| 762 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 808 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 763 // scratch:left = left * right. | 809 // scratch:left = left * right. |
| 764 __ smull(scratch, left, left, right); | 810 __ smull(scratch, left, left, right); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 __ eor(result, ToRegister(left), Operand(right_reg)); | 852 __ eor(result, ToRegister(left), Operand(right_reg)); |
| 807 break; | 853 break; |
| 808 default: | 854 default: |
| 809 UNREACHABLE(); | 855 UNREACHABLE(); |
| 810 break; | 856 break; |
| 811 } | 857 } |
| 812 } | 858 } |
| 813 | 859 |
| 814 | 860 |
| 815 void LCodeGen::DoShiftI(LShiftI* instr) { | 861 void LCodeGen::DoShiftI(LShiftI* instr) { |
| 862 Register scratch = scratch0(); |
| 816 LOperand* left = instr->left(); | 863 LOperand* left = instr->left(); |
| 817 LOperand* right = instr->right(); | 864 LOperand* right = instr->right(); |
| 818 ASSERT(left->Equals(instr->result())); | 865 ASSERT(left->Equals(instr->result())); |
| 819 ASSERT(left->IsRegister()); | 866 ASSERT(left->IsRegister()); |
| 820 Register result = ToRegister(left); | 867 Register result = ToRegister(left); |
| 821 if (right->IsRegister()) { | 868 if (right->IsRegister()) { |
| 822 // Mask the right operand. | 869 // Mask the right operand. |
| 823 __ and_(r9, ToRegister(right), Operand(0x1F)); | 870 __ and_(scratch, ToRegister(right), Operand(0x1F)); |
| 824 switch (instr->op()) { | 871 switch (instr->op()) { |
| 825 case Token::SAR: | 872 case Token::SAR: |
| 826 __ mov(result, Operand(result, ASR, r9)); | 873 __ mov(result, Operand(result, ASR, scratch)); |
| 827 break; | 874 break; |
| 828 case Token::SHR: | 875 case Token::SHR: |
| 829 if (instr->can_deopt()) { | 876 if (instr->can_deopt()) { |
| 830 __ mov(result, Operand(result, LSR, r9), SetCC); | 877 __ mov(result, Operand(result, LSR, scratch), SetCC); |
| 831 DeoptimizeIf(mi, instr->environment()); | 878 DeoptimizeIf(mi, instr->environment()); |
| 832 } else { | 879 } else { |
| 833 __ mov(result, Operand(result, LSR, r9)); | 880 __ mov(result, Operand(result, LSR, scratch)); |
| 834 } | 881 } |
| 835 break; | 882 break; |
| 836 case Token::SHL: | 883 case Token::SHL: |
| 837 __ mov(result, Operand(result, LSL, r9)); | 884 __ mov(result, Operand(result, LSL, scratch)); |
| 838 break; | 885 break; |
| 839 default: | 886 default: |
| 840 UNREACHABLE(); | 887 UNREACHABLE(); |
| 841 break; | 888 break; |
| 842 } | 889 } |
| 843 } else { | 890 } else { |
| 844 int value = ToInteger32(LConstantOperand::cast(right)); | 891 int value = ToInteger32(LConstantOperand::cast(right)); |
| 845 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); | 892 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); |
| 846 switch (instr->op()) { | 893 switch (instr->op()) { |
| 847 case Token::SAR: | 894 case Token::SAR: |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 Abort("DoConstantD unimplemented."); | 938 Abort("DoConstantD unimplemented."); |
| 892 } | 939 } |
| 893 | 940 |
| 894 | 941 |
| 895 void LCodeGen::DoConstantT(LConstantT* instr) { | 942 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 896 ASSERT(instr->result()->IsRegister()); | 943 ASSERT(instr->result()->IsRegister()); |
| 897 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 944 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 898 } | 945 } |
| 899 | 946 |
| 900 | 947 |
| 901 void LCodeGen::DoArrayLength(LArrayLength* instr) { | 948 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 902 Register result = ToRegister(instr->result()); | 949 Register result = ToRegister(instr->result()); |
| 903 | 950 Register array = ToRegister(instr->input()); |
| 904 if (instr->hydrogen()->value()->IsLoadElements()) { | 951 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); |
| 905 // We load the length directly from the elements array. | |
| 906 Register elements = ToRegister(instr->input()); | |
| 907 __ ldr(result, FieldMemOperand(elements, FixedArray::kLengthOffset)); | |
| 908 } else { | |
| 909 // Check that the receiver really is an array. | |
| 910 Register array = ToRegister(instr->input()); | |
| 911 Register temporary = ToRegister(instr->temporary()); | |
| 912 __ CompareObjectType(array, temporary, temporary, JS_ARRAY_TYPE); | |
| 913 DeoptimizeIf(ne, instr->environment()); | |
| 914 | |
| 915 // Load length directly from the array. | |
| 916 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); | |
| 917 } | |
| 918 Abort("DoArrayLength untested."); | |
| 919 } | 952 } |
| 920 | 953 |
| 921 | 954 |
| 955 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { |
| 956 Register result = ToRegister(instr->result()); |
| 957 Register array = ToRegister(instr->input()); |
| 958 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); |
| 959 Abort("DoFixedArrayLength untested."); |
| 960 } |
| 961 |
| 962 |
| 922 void LCodeGen::DoValueOf(LValueOf* instr) { | 963 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 923 Abort("DoValueOf unimplemented."); | 964 Abort("DoValueOf unimplemented."); |
| 924 } | 965 } |
| 925 | 966 |
| 926 | 967 |
| 927 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 968 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 928 LOperand* input = instr->input(); | 969 LOperand* input = instr->input(); |
| 929 ASSERT(input->Equals(instr->result())); | 970 ASSERT(input->Equals(instr->result())); |
| 930 __ mvn(ToRegister(input), Operand(ToRegister(input))); | 971 __ mvn(ToRegister(input), Operand(ToRegister(input))); |
| 931 Abort("DoBitNotI untested."); | 972 Abort("DoBitNotI untested."); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 __ cmp(reg, ip); | 1099 __ cmp(reg, ip); |
| 1059 __ b(eq, false_label); | 1100 __ b(eq, false_label); |
| 1060 __ cmp(reg, Operand(0)); | 1101 __ cmp(reg, Operand(0)); |
| 1061 __ b(eq, false_label); | 1102 __ b(eq, false_label); |
| 1062 __ tst(reg, Operand(kSmiTagMask)); | 1103 __ tst(reg, Operand(kSmiTagMask)); |
| 1063 __ b(eq, true_label); | 1104 __ b(eq, true_label); |
| 1064 | 1105 |
| 1065 // Test for double values. Zero is false. | 1106 // Test for double values. Zero is false. |
| 1066 Label call_stub; | 1107 Label call_stub; |
| 1067 DoubleRegister dbl_scratch = d0; | 1108 DoubleRegister dbl_scratch = d0; |
| 1068 Register core_scratch = r9; | 1109 Register scratch = scratch0(); |
| 1069 ASSERT(!reg.is(core_scratch)); | 1110 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1070 __ ldr(core_scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1071 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 1111 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 1072 __ cmp(core_scratch, Operand(ip)); | 1112 __ cmp(scratch, Operand(ip)); |
| 1073 __ b(ne, &call_stub); | 1113 __ b(ne, &call_stub); |
| 1074 __ sub(ip, reg, Operand(kHeapObjectTag)); | 1114 __ sub(ip, reg, Operand(kHeapObjectTag)); |
| 1075 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); | 1115 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); |
| 1076 __ vcmp(dbl_scratch, 0.0); | 1116 __ vcmp(dbl_scratch, 0.0); |
| 1077 __ b(eq, false_label); | 1117 __ b(eq, false_label); |
| 1078 __ b(true_label); | 1118 __ b(true_label); |
| 1079 | 1119 |
| 1080 // The conversion stub doesn't cause garbage collections so it's | 1120 // The conversion stub doesn't cause garbage collections so it's |
| 1081 // safe to not record a safepoint after the call. | 1121 // safe to not record a safepoint after the call. |
| 1082 __ bind(&call_stub); | 1122 __ bind(&call_stub); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1169 Abort("DoCmpJSObjectEq untested."); | 1209 Abort("DoCmpJSObjectEq untested."); |
| 1170 } | 1210 } |
| 1171 | 1211 |
| 1172 | 1212 |
| 1173 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1213 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
| 1174 Abort("DoCmpJSObjectEqAndBranch unimplemented."); | 1214 Abort("DoCmpJSObjectEqAndBranch unimplemented."); |
| 1175 } | 1215 } |
| 1176 | 1216 |
| 1177 | 1217 |
| 1178 void LCodeGen::DoIsNull(LIsNull* instr) { | 1218 void LCodeGen::DoIsNull(LIsNull* instr) { |
| 1179 Abort("DoIsNull unimplemented."); | 1219 Register reg = ToRegister(instr->input()); |
| 1220 Register result = ToRegister(instr->result()); |
| 1221 |
| 1222 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 1223 __ cmp(reg, ip); |
| 1224 if (instr->is_strict()) { |
| 1225 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); |
| 1226 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); |
| 1227 } else { |
| 1228 Label true_value, false_value, done; |
| 1229 __ b(eq, &true_value); |
| 1230 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 1231 __ cmp(ip, reg); |
| 1232 __ b(eq, &true_value); |
| 1233 __ tst(reg, Operand(kSmiTagMask)); |
| 1234 __ b(eq, &false_value); |
| 1235 // Check for undetectable objects by looking in the bit field in |
| 1236 // the map. The object has already been smi checked. |
| 1237 Register scratch = result; |
| 1238 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1239 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); |
| 1240 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); |
| 1241 __ b(ne, &true_value); |
| 1242 __ bind(&false_value); |
| 1243 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1244 __ jmp(&done); |
| 1245 __ bind(&true_value); |
| 1246 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1247 __ bind(&done); |
| 1248 } |
| 1180 } | 1249 } |
| 1181 | 1250 |
| 1182 | 1251 |
| 1183 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1252 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
| 1253 Register scratch = scratch0(); |
| 1184 Register reg = ToRegister(instr->input()); | 1254 Register reg = ToRegister(instr->input()); |
| 1185 | 1255 |
| 1186 // TODO(fsc): If the expression is known to be a smi, then it's | 1256 // TODO(fsc): If the expression is known to be a smi, then it's |
| 1187 // definitely not null. Jump to the false block. | 1257 // definitely not null. Jump to the false block. |
| 1188 | 1258 |
| 1189 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1259 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1190 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1260 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1191 | 1261 |
| 1192 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1262 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 1193 __ cmp(reg, ip); | 1263 __ cmp(reg, ip); |
| 1194 if (instr->is_strict()) { | 1264 if (instr->is_strict()) { |
| 1195 EmitBranch(true_block, false_block, eq); | 1265 EmitBranch(true_block, false_block, eq); |
| 1196 } else { | 1266 } else { |
| 1197 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1267 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1198 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1268 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1199 __ b(eq, true_label); | 1269 __ b(eq, true_label); |
| 1200 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1270 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 1201 __ cmp(reg, ip); | 1271 __ cmp(reg, ip); |
| 1202 __ b(eq, true_label); | 1272 __ b(eq, true_label); |
| 1203 __ tst(reg, Operand(kSmiTagMask)); | 1273 __ tst(reg, Operand(kSmiTagMask)); |
| 1204 __ b(eq, false_label); | 1274 __ b(eq, false_label); |
| 1205 // Check for undetectable objects by looking in the bit field in | 1275 // Check for undetectable objects by looking in the bit field in |
| 1206 // the map. The object has already been smi checked. | 1276 // the map. The object has already been smi checked. |
| 1207 Register scratch = ToRegister(instr->temp()); | |
| 1208 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1277 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1209 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); | 1278 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); |
| 1210 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); | 1279 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); |
| 1211 EmitBranch(true_block, false_block, ne); | 1280 EmitBranch(true_block, false_block, ne); |
| 1212 } | 1281 } |
| 1213 } | 1282 } |
| 1214 | 1283 |
| 1215 | 1284 |
| 1216 Condition LCodeGen::EmitIsObject(Register input, | 1285 Condition LCodeGen::EmitIsObject(Register input, |
| 1217 Register temp1, | 1286 Register temp1, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 return eq; | 1344 return eq; |
| 1276 } | 1345 } |
| 1277 | 1346 |
| 1278 | 1347 |
| 1279 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1348 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
| 1280 Abort("DoHasInstanceType unimplemented."); | 1349 Abort("DoHasInstanceType unimplemented."); |
| 1281 } | 1350 } |
| 1282 | 1351 |
| 1283 | 1352 |
| 1284 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1353 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 1354 Register scratch = scratch0(); |
| 1285 Register input = ToRegister(instr->input()); | 1355 Register input = ToRegister(instr->input()); |
| 1286 Register temp = ToRegister(instr->temp()); | |
| 1287 | 1356 |
| 1288 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1357 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1289 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1358 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1290 | 1359 |
| 1291 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1360 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1292 | 1361 |
| 1293 __ tst(input, Operand(kSmiTagMask)); | 1362 __ tst(input, Operand(kSmiTagMask)); |
| 1294 __ b(eq, false_label); | 1363 __ b(eq, false_label); |
| 1295 | 1364 |
| 1296 __ CompareObjectType(input, temp, temp, instr->TestType()); | 1365 __ CompareObjectType(input, scratch, scratch, instr->TestType()); |
| 1297 EmitBranch(true_block, false_block, instr->BranchCondition()); | 1366 EmitBranch(true_block, false_block, instr->BranchCondition()); |
| 1298 } | 1367 } |
| 1299 | 1368 |
| 1300 | 1369 |
| 1301 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1370 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
| 1302 Abort("DoHasCachedArrayIndex unimplemented."); | 1371 Abort("DoHasCachedArrayIndex unimplemented."); |
| 1303 } | 1372 } |
| 1304 | 1373 |
| 1305 | 1374 |
| 1306 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1375 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1325 Abort("DoClassOfTest unimplemented."); | 1394 Abort("DoClassOfTest unimplemented."); |
| 1326 } | 1395 } |
| 1327 | 1396 |
| 1328 | 1397 |
| 1329 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1398 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 1330 Abort("DoClassOfTestAndBranch unimplemented."); | 1399 Abort("DoClassOfTestAndBranch unimplemented."); |
| 1331 } | 1400 } |
| 1332 | 1401 |
| 1333 | 1402 |
| 1334 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1403 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 1335 Abort("DoCmpMapAndBranch unimplemented."); | 1404 Register reg = ToRegister(instr->input()); |
| 1405 Register temp = ToRegister(instr->temp()); |
| 1406 int true_block = instr->true_block_id(); |
| 1407 int false_block = instr->false_block_id(); |
| 1408 |
| 1409 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1410 __ cmp(temp, Operand(instr->map())); |
| 1411 EmitBranch(true_block, false_block, eq); |
| 1336 } | 1412 } |
| 1337 | 1413 |
| 1338 | 1414 |
| 1339 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1415 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1340 // We expect object and function in registers r1 and r0. | 1416 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. |
| 1417 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. |
| 1418 |
| 1341 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1419 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 1342 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1420 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1343 | 1421 |
| 1344 Label true_value, done; | 1422 Label true_value, done; |
| 1345 __ tst(r0, r0); | 1423 __ tst(r0, r0); |
| 1346 __ mov(r0, Operand(Factory::false_value()), LeaveCC, eq); | 1424 __ mov(r0, Operand(Factory::false_value()), LeaveCC, ne); |
| 1347 __ mov(r0, Operand(Factory::true_value()), LeaveCC, ne); | 1425 __ mov(r0, Operand(Factory::true_value()), LeaveCC, eq); |
| 1348 } | 1426 } |
| 1349 | 1427 |
| 1350 | 1428 |
| 1351 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1429 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
| 1352 Abort("DoInstanceOfAndBranch unimplemented."); | 1430 Abort("DoInstanceOfAndBranch unimplemented."); |
| 1353 } | 1431 } |
| 1354 | 1432 |
| 1355 | 1433 |
| 1356 | 1434 |
| 1357 static Condition ComputeCompareCondition(Token::Value op) { | 1435 static Condition ComputeCompareCondition(Token::Value op) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 | 1503 |
| 1426 | 1504 |
| 1427 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { | 1505 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { |
| 1428 Register value = ToRegister(instr->input()); | 1506 Register value = ToRegister(instr->input()); |
| 1429 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); | 1507 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); |
| 1430 __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); | 1508 __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); |
| 1431 } | 1509 } |
| 1432 | 1510 |
| 1433 | 1511 |
| 1434 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 1512 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 1435 Abort("DoLoadNamedField unimplemented."); | 1513 Register object = ToRegister(instr->input()); |
| 1514 Register result = ToRegister(instr->result()); |
| 1515 if (instr->hydrogen()->is_in_object()) { |
| 1516 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); |
| 1517 } else { |
| 1518 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 1519 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); |
| 1520 } |
| 1436 } | 1521 } |
| 1437 | 1522 |
| 1438 | 1523 |
| 1439 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 1524 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 1440 ASSERT(ToRegister(instr->object()).is(r0)); | 1525 ASSERT(ToRegister(instr->object()).is(r0)); |
| 1441 ASSERT(ToRegister(instr->result()).is(r0)); | 1526 ASSERT(ToRegister(instr->result()).is(r0)); |
| 1442 | 1527 |
| 1443 // Name is always in r2. | 1528 // Name is always in r2. |
| 1444 __ mov(r2, Operand(instr->name())); | 1529 __ mov(r2, Operand(instr->name())); |
| 1445 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1530 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1446 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 1531 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 1447 } | 1532 } |
| 1448 | 1533 |
| 1449 | 1534 |
| 1535 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| 1536 Register scratch = scratch0(); |
| 1537 Register function = ToRegister(instr->function()); |
| 1538 Register result = ToRegister(instr->result()); |
| 1539 |
| 1540 // Check that the function really is a function. Load map into the |
| 1541 // result register. |
| 1542 __ CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE); |
| 1543 DeoptimizeIf(ne, instr->environment()); |
| 1544 |
| 1545 // Make sure that the function has an instance prototype. |
| 1546 Label non_instance; |
| 1547 __ ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset)); |
| 1548 __ tst(scratch, Operand(1 << Map::kHasNonInstancePrototype)); |
| 1549 __ b(ne, &non_instance); |
| 1550 |
| 1551 // Get the prototype or initial map from the function. |
| 1552 __ ldr(result, |
| 1553 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 1554 |
| 1555 // Check that the function has a prototype or an initial map. |
| 1556 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 1557 __ cmp(result, ip); |
| 1558 DeoptimizeIf(eq, instr->environment()); |
| 1559 |
| 1560 // If the function does not have an initial map, we're done. |
| 1561 Label done; |
| 1562 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); |
| 1563 __ b(ne, &done); |
| 1564 |
| 1565 // Get the prototype from the initial map. |
| 1566 __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
| 1567 __ jmp(&done); |
| 1568 |
| 1569 // Non-instance prototype: Fetch prototype from constructor field |
| 1570 // in initial map. |
| 1571 __ bind(&non_instance); |
| 1572 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); |
| 1573 |
| 1574 // All done. |
| 1575 __ bind(&done); |
| 1576 } |
| 1577 |
| 1578 |
| 1450 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 1579 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
| 1451 Abort("DoLoadElements unimplemented."); | 1580 Abort("DoLoadElements unimplemented."); |
| 1452 } | 1581 } |
| 1453 | 1582 |
| 1454 | 1583 |
| 1455 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 1584 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 1456 Abort("DoAccessArgumentsAt unimplemented."); | 1585 Abort("DoAccessArgumentsAt unimplemented."); |
| 1457 } | 1586 } |
| 1458 | 1587 |
| 1459 | 1588 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1537 | 1666 |
| 1538 // Setup deoptimization. | 1667 // Setup deoptimization. |
| 1539 RegisterLazyDeoptimization(instr); | 1668 RegisterLazyDeoptimization(instr); |
| 1540 | 1669 |
| 1541 // Restore context. | 1670 // Restore context. |
| 1542 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1671 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1543 } | 1672 } |
| 1544 | 1673 |
| 1545 | 1674 |
| 1546 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 1675 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 1547 Abort("DoCallConstantFunction unimplemented."); | 1676 ASSERT(ToRegister(instr->result()).is(r0)); |
| 1677 __ mov(r1, Operand(instr->function())); |
| 1678 CallKnownFunction(instr->function(), instr->arity(), instr); |
| 1548 } | 1679 } |
| 1549 | 1680 |
| 1550 | 1681 |
| 1551 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 1682 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 1552 Abort("DoDeferredMathAbsTaggedHeapNumber unimplemented."); | 1683 Abort("DoDeferredMathAbsTaggedHeapNumber unimplemented."); |
| 1553 } | 1684 } |
| 1554 | 1685 |
| 1555 | 1686 |
| 1556 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 1687 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
| 1557 Abort("DoMathAbs unimplemented."); | 1688 Abort("DoMathAbs unimplemented."); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1597 int arity = instr->arity(); | 1728 int arity = instr->arity(); |
| 1598 Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); | 1729 Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); |
| 1599 __ mov(r2, Operand(instr->name())); | 1730 __ mov(r2, Operand(instr->name())); |
| 1600 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 1731 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 1601 // Restore context register. | 1732 // Restore context register. |
| 1602 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1733 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1603 } | 1734 } |
| 1604 | 1735 |
| 1605 | 1736 |
| 1606 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 1737 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 1607 Abort("DoCallFunction unimplemented."); | 1738 ASSERT(ToRegister(instr->result()).is(r0)); |
| 1739 |
| 1740 int arity = instr->arity(); |
| 1741 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
| 1742 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1743 __ Drop(1); |
| 1744 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1608 } | 1745 } |
| 1609 | 1746 |
| 1610 | 1747 |
| 1611 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 1748 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 1612 Abort("DoCallGlobal unimplemented."); | 1749 Abort("DoCallGlobal unimplemented."); |
| 1613 } | 1750 } |
| 1614 | 1751 |
| 1615 | 1752 |
| 1616 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 1753 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 1617 ASSERT(ToRegister(instr->result()).is(r0)); | 1754 ASSERT(ToRegister(instr->result()).is(r0)); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1645 ASSERT(ToRegister(instr->value()).is(r0)); | 1782 ASSERT(ToRegister(instr->value()).is(r0)); |
| 1646 | 1783 |
| 1647 // Name is always in r2. | 1784 // Name is always in r2. |
| 1648 __ mov(r2, Operand(instr->name())); | 1785 __ mov(r2, Operand(instr->name())); |
| 1649 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1786 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1650 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 1787 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 1651 } | 1788 } |
| 1652 | 1789 |
| 1653 | 1790 |
| 1654 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 1791 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 1655 Abort("DoBoundsCheck unimplemented."); | 1792 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
| 1793 DeoptimizeIf(hs, instr->environment()); |
| 1656 } | 1794 } |
| 1657 | 1795 |
| 1658 | 1796 |
| 1659 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 1797 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
| 1660 Abort("DoStoreKeyedFastElement unimplemented."); | 1798 Abort("DoStoreKeyedFastElement unimplemented."); |
| 1661 } | 1799 } |
| 1662 | 1800 |
| 1663 | 1801 |
| 1664 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 1802 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 1665 ASSERT(ToRegister(instr->object()).is(r2)); | 1803 ASSERT(ToRegister(instr->object()).is(r2)); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 class DeferredNumberTagD: public LDeferredCode { | 1888 class DeferredNumberTagD: public LDeferredCode { |
| 1751 public: | 1889 public: |
| 1752 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 1890 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 1753 : LDeferredCode(codegen), instr_(instr) { } | 1891 : LDeferredCode(codegen), instr_(instr) { } |
| 1754 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 1892 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 1755 private: | 1893 private: |
| 1756 LNumberTagD* instr_; | 1894 LNumberTagD* instr_; |
| 1757 }; | 1895 }; |
| 1758 | 1896 |
| 1759 DoubleRegister input_reg = ToDoubleRegister(instr->input()); | 1897 DoubleRegister input_reg = ToDoubleRegister(instr->input()); |
| 1898 Register scratch = scratch0(); |
| 1760 Register reg = ToRegister(instr->result()); | 1899 Register reg = ToRegister(instr->result()); |
| 1761 Register temp1 = ToRegister(instr->temp1()); | 1900 Register temp1 = ToRegister(instr->temp1()); |
| 1762 Register temp2 = ToRegister(instr->temp2()); | 1901 Register temp2 = ToRegister(instr->temp2()); |
| 1763 Register scratch = r9; | |
| 1764 | 1902 |
| 1765 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); | 1903 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); |
| 1766 if (FLAG_inline_new) { | 1904 if (FLAG_inline_new) { |
| 1767 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 1905 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 1768 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); | 1906 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); |
| 1769 } else { | 1907 } else { |
| 1770 __ jmp(deferred->entry()); | 1908 __ jmp(deferred->entry()); |
| 1771 } | 1909 } |
| 1772 __ bind(deferred->exit()); | 1910 __ bind(deferred->exit()); |
| 1773 __ sub(ip, reg, Operand(kHeapObjectTag)); | 1911 __ sub(ip, reg, Operand(kHeapObjectTag)); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1801 | 1939 |
| 1802 | 1940 |
| 1803 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 1941 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 1804 Abort("DoSmiUntag unimplemented."); | 1942 Abort("DoSmiUntag unimplemented."); |
| 1805 } | 1943 } |
| 1806 | 1944 |
| 1807 | 1945 |
| 1808 void LCodeGen::EmitNumberUntagD(Register input_reg, | 1946 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 1809 DoubleRegister result_reg, | 1947 DoubleRegister result_reg, |
| 1810 LEnvironment* env) { | 1948 LEnvironment* env) { |
| 1811 Register core_scratch = r9; | 1949 Register scratch = scratch0(); |
| 1812 ASSERT(!input_reg.is(core_scratch)); | |
| 1813 SwVfpRegister flt_scratch = s0; | 1950 SwVfpRegister flt_scratch = s0; |
| 1814 ASSERT(!result_reg.is(d0)); | 1951 ASSERT(!result_reg.is(d0)); |
| 1815 | 1952 |
| 1816 Label load_smi, heap_number, done; | 1953 Label load_smi, heap_number, done; |
| 1817 | 1954 |
| 1818 // Smi check. | 1955 // Smi check. |
| 1819 __ tst(input_reg, Operand(kSmiTagMask)); | 1956 __ tst(input_reg, Operand(kSmiTagMask)); |
| 1820 __ b(eq, &load_smi); | 1957 __ b(eq, &load_smi); |
| 1821 | 1958 |
| 1822 // Heap number map check. | 1959 // Heap number map check. |
| 1823 __ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 1960 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 1824 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 1961 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 1825 __ cmp(core_scratch, Operand(ip)); | 1962 __ cmp(scratch, Operand(ip)); |
| 1826 __ b(eq, &heap_number); | 1963 __ b(eq, &heap_number); |
| 1827 | 1964 |
| 1828 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1965 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 1829 __ cmp(input_reg, Operand(ip)); | 1966 __ cmp(input_reg, Operand(ip)); |
| 1830 DeoptimizeIf(ne, env); | 1967 DeoptimizeIf(ne, env); |
| 1831 | 1968 |
| 1832 // Convert undefined to NaN. | 1969 // Convert undefined to NaN. |
| 1833 __ LoadRoot(ip, Heap::kNanValueRootIndex); | 1970 __ LoadRoot(ip, Heap::kNanValueRootIndex); |
| 1834 __ sub(ip, ip, Operand(kHeapObjectTag)); | 1971 __ sub(ip, ip, Operand(kHeapObjectTag)); |
| 1835 __ vldr(result_reg, ip, HeapNumber::kValueOffset); | 1972 __ vldr(result_reg, ip, HeapNumber::kValueOffset); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1857 : LDeferredCode(codegen), instr_(instr) { } | 1994 : LDeferredCode(codegen), instr_(instr) { } |
| 1858 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 1995 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 1859 private: | 1996 private: |
| 1860 LTaggedToI* instr_; | 1997 LTaggedToI* instr_; |
| 1861 }; | 1998 }; |
| 1862 | 1999 |
| 1863 | 2000 |
| 1864 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 2001 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 1865 Label done; | 2002 Label done; |
| 1866 Register input_reg = ToRegister(instr->input()); | 2003 Register input_reg = ToRegister(instr->input()); |
| 1867 Register core_scratch = r9; | 2004 Register scratch = scratch0(); |
| 1868 ASSERT(!input_reg.is(core_scratch)); | |
| 1869 DoubleRegister dbl_scratch = d0; | 2005 DoubleRegister dbl_scratch = d0; |
| 1870 SwVfpRegister flt_scratch = s0; | 2006 SwVfpRegister flt_scratch = s0; |
| 1871 DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp()); | 2007 DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp()); |
| 1872 | 2008 |
| 1873 // Heap number map check. | 2009 // Heap number map check. |
| 1874 __ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 2010 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 1875 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 2011 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 1876 __ cmp(core_scratch, Operand(ip)); | 2012 __ cmp(scratch, Operand(ip)); |
| 1877 | 2013 |
| 1878 if (instr->truncating()) { | 2014 if (instr->truncating()) { |
| 1879 Label heap_number; | 2015 Label heap_number; |
| 1880 __ b(eq, &heap_number); | 2016 __ b(eq, &heap_number); |
| 1881 // Check for undefined. Undefined is converted to zero for truncating | 2017 // Check for undefined. Undefined is converted to zero for truncating |
| 1882 // conversions. | 2018 // conversions. |
| 1883 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 2019 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 1884 __ cmp(input_reg, Operand(ip)); | 2020 __ cmp(input_reg, Operand(ip)); |
| 1885 DeoptimizeIf(ne, instr->environment()); | 2021 DeoptimizeIf(ne, instr->environment()); |
| 1886 __ mov(input_reg, Operand(0)); | 2022 __ mov(input_reg, Operand(0)); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1978 | 2114 |
| 1979 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 2115 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
| 1980 ASSERT(instr->input()->IsRegister()); | 2116 ASSERT(instr->input()->IsRegister()); |
| 1981 Register reg = ToRegister(instr->input()); | 2117 Register reg = ToRegister(instr->input()); |
| 1982 __ cmp(reg, Operand(instr->hydrogen()->target())); | 2118 __ cmp(reg, Operand(instr->hydrogen()->target())); |
| 1983 DeoptimizeIf(ne, instr->environment()); | 2119 DeoptimizeIf(ne, instr->environment()); |
| 1984 } | 2120 } |
| 1985 | 2121 |
| 1986 | 2122 |
| 1987 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 2123 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
| 2124 Register scratch = scratch0(); |
| 1988 LOperand* input = instr->input(); | 2125 LOperand* input = instr->input(); |
| 1989 ASSERT(input->IsRegister()); | 2126 ASSERT(input->IsRegister()); |
| 1990 Register reg = ToRegister(input); | 2127 Register reg = ToRegister(input); |
| 1991 __ ldr(r9, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2128 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1992 __ cmp(r9, Operand(instr->hydrogen()->map())); | 2129 __ cmp(scratch, Operand(instr->hydrogen()->map())); |
| 1993 DeoptimizeIf(ne, instr->environment()); | 2130 DeoptimizeIf(ne, instr->environment()); |
| 1994 } | 2131 } |
| 1995 | 2132 |
| 1996 | 2133 |
| 1997 void LCodeGen::LoadPrototype(Register result, | 2134 void LCodeGen::LoadPrototype(Register result, |
| 1998 Handle<JSObject> prototype) { | 2135 Handle<JSObject> prototype) { |
| 1999 Abort("LoadPrototype unimplemented."); | 2136 if (Heap::InNewSpace(*prototype)) { |
| 2137 Handle<JSGlobalPropertyCell> cell = |
| 2138 Factory::NewJSGlobalPropertyCell(prototype); |
| 2139 __ mov(result, Operand(cell)); |
| 2140 } else { |
| 2141 __ mov(result, Operand(prototype)); |
| 2142 } |
| 2000 } | 2143 } |
| 2001 | 2144 |
| 2002 | 2145 |
| 2003 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 2146 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 2004 Abort("DoCheckPrototypeMaps unimplemented."); | 2147 Register temp1 = ToRegister(instr->temp1()); |
| 2148 Register temp2 = ToRegister(instr->temp2()); |
| 2149 |
| 2150 Handle<JSObject> holder = instr->holder(); |
| 2151 Handle<Map> receiver_map = instr->receiver_map(); |
| 2152 Handle<JSObject> current_prototype(JSObject::cast(receiver_map->prototype())); |
| 2153 |
| 2154 // Load prototype object. |
| 2155 LoadPrototype(temp1, current_prototype); |
| 2156 |
| 2157 // Check prototype maps up to the holder. |
| 2158 while (!current_prototype.is_identical_to(holder)) { |
| 2159 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); |
| 2160 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); |
| 2161 DeoptimizeIf(ne, instr->environment()); |
| 2162 current_prototype = |
| 2163 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); |
| 2164 // Load next prototype object. |
| 2165 LoadPrototype(temp1, current_prototype); |
| 2166 } |
| 2167 |
| 2168 // Check the holder map. |
| 2169 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); |
| 2170 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); |
| 2171 DeoptimizeIf(ne, instr->environment()); |
| 2005 } | 2172 } |
| 2006 | 2173 |
| 2007 | 2174 |
| 2008 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 2175 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
| 2009 Abort("DoArrayLiteral unimplemented."); | 2176 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 2177 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); |
| 2178 __ mov(r2, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 2179 __ mov(r1, Operand(instr->hydrogen()->constant_elements())); |
| 2180 __ Push(r3, r2, r1); |
| 2181 |
| 2182 // Pick the right runtime function or stub to call. |
| 2183 int length = instr->hydrogen()->length(); |
| 2184 if (instr->hydrogen()->IsCopyOnWrite()) { |
| 2185 ASSERT(instr->hydrogen()->depth() == 1); |
| 2186 FastCloneShallowArrayStub::Mode mode = |
| 2187 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; |
| 2188 FastCloneShallowArrayStub stub(mode, length); |
| 2189 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2190 } else if (instr->hydrogen()->depth() > 1) { |
| 2191 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); |
| 2192 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| 2193 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); |
| 2194 } else { |
| 2195 FastCloneShallowArrayStub::Mode mode = |
| 2196 FastCloneShallowArrayStub::CLONE_ELEMENTS; |
| 2197 FastCloneShallowArrayStub stub(mode, length); |
| 2198 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2199 } |
| 2010 } | 2200 } |
| 2011 | 2201 |
| 2012 | 2202 |
| 2013 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { | 2203 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { |
| 2014 Abort("DoObjectLiteral unimplemented."); | 2204 __ ldr(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 2205 __ ldr(r4, FieldMemOperand(r4, JSFunction::kLiteralsOffset)); |
| 2206 __ mov(r3, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 2207 __ mov(r2, Operand(instr->hydrogen()->constant_properties())); |
| 2208 __ mov(r1, Operand(Smi::FromInt(instr->hydrogen()->fast_elements() ? 1 : 0))); |
| 2209 __ Push(r4, r3, r2, r1); |
| 2210 |
| 2211 // Pick the right runtime function to call. |
| 2212 if (instr->hydrogen()->depth() > 1) { |
| 2213 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); |
| 2214 } else { |
| 2215 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); |
| 2216 } |
| 2015 } | 2217 } |
| 2016 | 2218 |
| 2017 | 2219 |
| 2018 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 2220 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 2019 Abort("DoRegExpLiteral unimplemented."); | 2221 Abort("DoRegExpLiteral unimplemented."); |
| 2020 } | 2222 } |
| 2021 | 2223 |
| 2022 | 2224 |
| 2023 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 2225 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
| 2024 Abort("DoFunctionLiteral unimplemented."); | 2226 Abort("DoFunctionLiteral unimplemented."); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2049 | 2251 |
| 2050 EmitBranch(true_block, false_block, final_branch_condition); | 2252 EmitBranch(true_block, false_block, final_branch_condition); |
| 2051 } | 2253 } |
| 2052 | 2254 |
| 2053 | 2255 |
| 2054 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 2256 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
| 2055 Label* false_label, | 2257 Label* false_label, |
| 2056 Register input, | 2258 Register input, |
| 2057 Handle<String> type_name) { | 2259 Handle<String> type_name) { |
| 2058 Condition final_branch_condition = no_condition; | 2260 Condition final_branch_condition = no_condition; |
| 2059 Register core_scratch = r9; | 2261 Register scratch = scratch0(); |
| 2060 ASSERT(!input.is(core_scratch)); | |
| 2061 if (type_name->Equals(Heap::number_symbol())) { | 2262 if (type_name->Equals(Heap::number_symbol())) { |
| 2062 __ tst(input, Operand(kSmiTagMask)); | 2263 __ tst(input, Operand(kSmiTagMask)); |
| 2063 __ b(eq, true_label); | 2264 __ b(eq, true_label); |
| 2064 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); | 2265 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 2065 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 2266 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 2066 __ cmp(input, Operand(ip)); | 2267 __ cmp(input, Operand(ip)); |
| 2067 final_branch_condition = eq; | 2268 final_branch_condition = eq; |
| 2068 | 2269 |
| 2069 } else if (type_name->Equals(Heap::string_symbol())) { | 2270 } else if (type_name->Equals(Heap::string_symbol())) { |
| 2070 __ tst(input, Operand(kSmiTagMask)); | 2271 __ tst(input, Operand(kSmiTagMask)); |
| 2071 __ b(eq, false_label); | 2272 __ b(eq, false_label); |
| 2072 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); | 2273 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 2073 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); | 2274 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); |
| 2074 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 2275 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 2075 __ b(ne, false_label); | 2276 __ b(ne, false_label); |
| 2076 __ CompareInstanceType(input, core_scratch, FIRST_NONSTRING_TYPE); | 2277 __ CompareInstanceType(input, scratch, FIRST_NONSTRING_TYPE); |
| 2077 final_branch_condition = lo; | 2278 final_branch_condition = lo; |
| 2078 | 2279 |
| 2079 } else if (type_name->Equals(Heap::boolean_symbol())) { | 2280 } else if (type_name->Equals(Heap::boolean_symbol())) { |
| 2080 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 2281 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 2081 __ cmp(input, ip); | 2282 __ cmp(input, ip); |
| 2082 __ b(eq, true_label); | 2283 __ b(eq, true_label); |
| 2083 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 2284 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 2084 __ cmp(input, ip); | 2285 __ cmp(input, ip); |
| 2085 final_branch_condition = eq; | 2286 final_branch_condition = eq; |
| 2086 | 2287 |
| 2087 } else if (type_name->Equals(Heap::undefined_symbol())) { | 2288 } else if (type_name->Equals(Heap::undefined_symbol())) { |
| 2088 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 2289 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 2089 __ cmp(input, ip); | 2290 __ cmp(input, ip); |
| 2090 __ b(eq, true_label); | 2291 __ b(eq, true_label); |
| 2091 __ tst(input, Operand(kSmiTagMask)); | 2292 __ tst(input, Operand(kSmiTagMask)); |
| 2092 __ b(eq, false_label); | 2293 __ b(eq, false_label); |
| 2093 // Check for undetectable objects => true. | 2294 // Check for undetectable objects => true. |
| 2094 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); | 2295 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 2095 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); | 2296 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); |
| 2096 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 2297 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 2097 final_branch_condition = ne; | 2298 final_branch_condition = ne; |
| 2098 | 2299 |
| 2099 } else if (type_name->Equals(Heap::function_symbol())) { | 2300 } else if (type_name->Equals(Heap::function_symbol())) { |
| 2100 __ tst(input, Operand(kSmiTagMask)); | 2301 __ tst(input, Operand(kSmiTagMask)); |
| 2101 __ b(eq, false_label); | 2302 __ b(eq, false_label); |
| 2102 __ CompareObjectType(input, input, core_scratch, JS_FUNCTION_TYPE); | 2303 __ CompareObjectType(input, input, scratch, JS_FUNCTION_TYPE); |
| 2103 __ b(eq, true_label); | 2304 __ b(eq, true_label); |
| 2104 // Regular expressions => 'function' (they are callable). | 2305 // Regular expressions => 'function' (they are callable). |
| 2105 __ CompareInstanceType(input, core_scratch, JS_REGEXP_TYPE); | 2306 __ CompareInstanceType(input, scratch, JS_REGEXP_TYPE); |
| 2106 final_branch_condition = eq; | 2307 final_branch_condition = eq; |
| 2107 | 2308 |
| 2108 } else if (type_name->Equals(Heap::object_symbol())) { | 2309 } else if (type_name->Equals(Heap::object_symbol())) { |
| 2109 __ tst(input, Operand(kSmiTagMask)); | 2310 __ tst(input, Operand(kSmiTagMask)); |
| 2110 __ b(eq, false_label); | 2311 __ b(eq, false_label); |
| 2111 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 2312 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 2112 __ cmp(input, ip); | 2313 __ cmp(input, ip); |
| 2113 __ b(eq, true_label); | 2314 __ b(eq, true_label); |
| 2114 // Regular expressions => 'function', not 'object'. | 2315 // Regular expressions => 'function', not 'object'. |
| 2115 __ CompareObjectType(input, input, core_scratch, JS_REGEXP_TYPE); | 2316 __ CompareObjectType(input, input, scratch, JS_REGEXP_TYPE); |
| 2116 __ b(eq, false_label); | 2317 __ b(eq, false_label); |
| 2117 // Check for undetectable objects => false. | 2318 // Check for undetectable objects => false. |
| 2118 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); | 2319 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); |
| 2119 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 2320 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 2120 __ b(ne, false_label); | 2321 __ b(ne, false_label); |
| 2121 // Check for JS objects => true. | 2322 // Check for JS objects => true. |
| 2122 __ CompareInstanceType(input, core_scratch, FIRST_JS_OBJECT_TYPE); | 2323 __ CompareInstanceType(input, scratch, FIRST_JS_OBJECT_TYPE); |
| 2123 __ b(lo, false_label); | 2324 __ b(lo, false_label); |
| 2124 __ CompareInstanceType(input, core_scratch, LAST_JS_OBJECT_TYPE); | 2325 __ CompareInstanceType(input, scratch, LAST_JS_OBJECT_TYPE); |
| 2125 final_branch_condition = ls; | 2326 final_branch_condition = ls; |
| 2126 | 2327 |
| 2127 } else { | 2328 } else { |
| 2128 final_branch_condition = ne; | 2329 final_branch_condition = ne; |
| 2129 __ b(false_label); | 2330 __ b(false_label); |
| 2130 // A dead branch instruction will be generated after this point. | 2331 // A dead branch instruction will be generated after this point. |
| 2131 } | 2332 } |
| 2132 | 2333 |
| 2133 return final_branch_condition; | 2334 return final_branch_condition; |
| 2134 } | 2335 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2163 | 2364 |
| 2164 | 2365 |
| 2165 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 2366 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
| 2166 Abort("DoOsrEntry unimplemented."); | 2367 Abort("DoOsrEntry unimplemented."); |
| 2167 } | 2368 } |
| 2168 | 2369 |
| 2169 | 2370 |
| 2170 #undef __ | 2371 #undef __ |
| 2171 | 2372 |
| 2172 } } // namespace v8::internal | 2373 } } // namespace v8::internal |
| OLD | NEW |