OLD | NEW |
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 969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 // Nothing to do. | 980 // Nothing to do. |
981 } | 981 } |
982 | 982 |
983 | 983 |
984 void LCodeGen::DoModI(LModI* instr) { | 984 void LCodeGen::DoModI(LModI* instr) { |
985 class DeferredModI: public LDeferredCode { | 985 class DeferredModI: public LDeferredCode { |
986 public: | 986 public: |
987 DeferredModI(LCodeGen* codegen, LModI* instr) | 987 DeferredModI(LCodeGen* codegen, LModI* instr) |
988 : LDeferredCode(codegen), instr_(instr) { } | 988 : LDeferredCode(codegen), instr_(instr) { } |
989 virtual void Generate() { | 989 virtual void Generate() { |
990 codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD); | 990 codegen()->DoDeferredBinaryOpStub(instr_, Token::MOD); |
991 } | 991 } |
992 private: | 992 private: |
993 LModI* instr_; | 993 LModI* instr_; |
994 }; | 994 }; |
995 // These registers hold untagged 32 bit values. | 995 // These registers hold untagged 32 bit values. |
996 Register left = ToRegister(instr->InputAt(0)); | 996 Register left = ToRegister(instr->InputAt(0)); |
997 Register right = ToRegister(instr->InputAt(1)); | 997 Register right = ToRegister(instr->InputAt(1)); |
998 Register result = ToRegister(instr->result()); | 998 Register result = ToRegister(instr->result()); |
999 Register scratch = scratch0(); | 999 Register scratch = scratch0(); |
1000 | 1000 |
1001 Label deoptimize, done; | 1001 Label deoptimize, done; |
1002 // Check for x % 0. | 1002 // Check for x % 0. |
1003 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1003 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
1004 __ tst(right, Operand(right)); | 1004 __ tst(right, Operand(right)); |
1005 __ b(eq, &deoptimize); | 1005 __ b(eq, &deoptimize); |
1006 } | 1006 } |
1007 | 1007 |
1008 // Check for (0 % -x) that will produce negative zero. | 1008 // Check for (0 % -x) that will produce negative zero. |
1009 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1009 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1010 Label ok; | 1010 Label ok; |
1011 __ tst(left, Operand(left)); | 1011 __ tst(left, Operand(left)); |
1012 __ b(ne, &ok); | 1012 __ b(ne, &ok); |
1013 __ tst(right, Operand(right)); | 1013 __ tst(right, Operand(right)); |
1014 __ b(pl, &ok); | 1014 __ b(pl, &ok); |
1015 __ b(al, &deoptimize); | 1015 __ b(al, &deoptimize); |
1016 __ bind(&ok); | 1016 __ bind(&ok); |
1017 } | 1017 } |
1018 | 1018 |
1019 // Try a few common cases before using the generic stub. | 1019 // Try a few common cases before using the stub. |
1020 Label call_stub; | 1020 Label call_stub; |
1021 const int kUnfolds = 3; | 1021 const int kUnfolds = 3; |
1022 // Skip if either side is negative. | 1022 // Skip if either side is negative. |
1023 __ cmp(left, Operand(0)); | 1023 __ cmp(left, Operand(0)); |
1024 __ cmp(right, Operand(0), NegateCondition(mi)); | 1024 __ cmp(right, Operand(0), NegateCondition(mi)); |
1025 __ b(mi, &call_stub); | 1025 __ b(mi, &call_stub); |
1026 // If the right hand side is smaller than the (nonnegative) | 1026 // If the right hand side is smaller than the (nonnegative) |
1027 // left hand side, it is the result. Else try a few subtractions | 1027 // left hand side, it is the result. Else try a few subtractions |
1028 // of the left hand side. | 1028 // of the left hand side. |
1029 __ mov(scratch, left); | 1029 __ mov(scratch, left); |
1030 for (int i = 0; i < kUnfolds; i++) { | 1030 for (int i = 0; i < kUnfolds; i++) { |
1031 // Check if the left hand side is less or equal than the | 1031 // Check if the left hand side is less or equal than the |
1032 // the right hand side. | 1032 // the right hand side. |
1033 __ cmp(scratch, right); | 1033 __ cmp(scratch, right); |
1034 __ mov(result, scratch, LeaveCC, lt); | 1034 __ mov(result, scratch, LeaveCC, lt); |
1035 __ b(lt, &done); | 1035 __ b(lt, &done); |
1036 // If not, reduce the left hand side by the right hand | 1036 // If not, reduce the left hand side by the right hand |
1037 // side and check again. | 1037 // side and check again. |
1038 if (i < kUnfolds - 1) __ sub(scratch, scratch, right); | 1038 if (i < kUnfolds - 1) __ sub(scratch, scratch, right); |
1039 } | 1039 } |
1040 | 1040 |
1041 // Check for power of two on the right hand side. | 1041 // Check for power of two on the right hand side. |
1042 __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub); | 1042 __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub); |
1043 // Perform modulo operation (scratch contains right - 1). | 1043 // Perform modulo operation (scratch contains right - 1). |
1044 __ and_(result, scratch, Operand(left)); | 1044 __ and_(result, scratch, Operand(left)); |
1045 | 1045 |
1046 __ bind(&call_stub); | 1046 __ bind(&call_stub); |
1047 // Call the generic stub. The numbers in r0 and r1 have | 1047 // Call the stub. The numbers in r0 and r1 have |
1048 // to be tagged to Smis. If that is not possible, deoptimize. | 1048 // to be tagged to Smis. If that is not possible, deoptimize. |
1049 DeferredModI* deferred = new DeferredModI(this, instr); | 1049 DeferredModI* deferred = new DeferredModI(this, instr); |
1050 __ TrySmiTag(left, &deoptimize, scratch); | 1050 __ TrySmiTag(left, &deoptimize, scratch); |
1051 __ TrySmiTag(right, &deoptimize, scratch); | 1051 __ TrySmiTag(right, &deoptimize, scratch); |
1052 | 1052 |
1053 __ b(al, deferred->entry()); | 1053 __ b(al, deferred->entry()); |
1054 __ bind(deferred->exit()); | 1054 __ bind(deferred->exit()); |
1055 | 1055 |
1056 // If the result in r0 is a Smi, untag it, else deoptimize. | 1056 // If the result in r0 is a Smi, untag it, else deoptimize. |
1057 __ JumpIfNotSmi(result, &deoptimize); | 1057 __ JumpIfNotSmi(result, &deoptimize); |
1058 __ SmiUntag(result); | 1058 __ SmiUntag(result); |
1059 | 1059 |
1060 __ b(al, &done); | 1060 __ b(al, &done); |
1061 __ bind(&deoptimize); | 1061 __ bind(&deoptimize); |
1062 DeoptimizeIf(al, instr->environment()); | 1062 DeoptimizeIf(al, instr->environment()); |
1063 __ bind(&done); | 1063 __ bind(&done); |
1064 } | 1064 } |
1065 | 1065 |
1066 | 1066 |
1067 void LCodeGen::DoDivI(LDivI* instr) { | 1067 void LCodeGen::DoDivI(LDivI* instr) { |
1068 class DeferredDivI: public LDeferredCode { | 1068 class DeferredDivI: public LDeferredCode { |
1069 public: | 1069 public: |
1070 DeferredDivI(LCodeGen* codegen, LDivI* instr) | 1070 DeferredDivI(LCodeGen* codegen, LDivI* instr) |
1071 : LDeferredCode(codegen), instr_(instr) { } | 1071 : LDeferredCode(codegen), instr_(instr) { } |
1072 virtual void Generate() { | 1072 virtual void Generate() { |
1073 codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV); | 1073 codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV); |
1074 } | 1074 } |
1075 private: | 1075 private: |
1076 LDivI* instr_; | 1076 LDivI* instr_; |
1077 }; | 1077 }; |
1078 | 1078 |
1079 const Register left = ToRegister(instr->InputAt(0)); | 1079 const Register left = ToRegister(instr->InputAt(0)); |
1080 const Register right = ToRegister(instr->InputAt(1)); | 1080 const Register right = ToRegister(instr->InputAt(1)); |
1081 const Register scratch = scratch0(); | 1081 const Register scratch = scratch0(); |
1082 const Register result = ToRegister(instr->result()); | 1082 const Register result = ToRegister(instr->result()); |
1083 | 1083 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 __ cmp(right, Operand(2)); | 1116 __ cmp(right, Operand(2)); |
1117 __ tst(left, Operand(1), eq); | 1117 __ tst(left, Operand(1), eq); |
1118 __ mov(result, Operand(left, ASR, 1), LeaveCC, eq); | 1118 __ mov(result, Operand(left, ASR, 1), LeaveCC, eq); |
1119 __ b(eq, &done); | 1119 __ b(eq, &done); |
1120 | 1120 |
1121 __ cmp(right, Operand(4)); | 1121 __ cmp(right, Operand(4)); |
1122 __ tst(left, Operand(3), eq); | 1122 __ tst(left, Operand(3), eq); |
1123 __ mov(result, Operand(left, ASR, 2), LeaveCC, eq); | 1123 __ mov(result, Operand(left, ASR, 2), LeaveCC, eq); |
1124 __ b(eq, &done); | 1124 __ b(eq, &done); |
1125 | 1125 |
1126 // Call the generic stub. The numbers in r0 and r1 have | 1126 // Call the stub. The numbers in r0 and r1 have |
1127 // to be tagged to Smis. If that is not possible, deoptimize. | 1127 // to be tagged to Smis. If that is not possible, deoptimize. |
1128 DeferredDivI* deferred = new DeferredDivI(this, instr); | 1128 DeferredDivI* deferred = new DeferredDivI(this, instr); |
1129 | 1129 |
1130 __ TrySmiTag(left, &deoptimize, scratch); | 1130 __ TrySmiTag(left, &deoptimize, scratch); |
1131 __ TrySmiTag(right, &deoptimize, scratch); | 1131 __ TrySmiTag(right, &deoptimize, scratch); |
1132 | 1132 |
1133 __ b(al, deferred->entry()); | 1133 __ b(al, deferred->entry()); |
1134 __ bind(deferred->exit()); | 1134 __ bind(deferred->exit()); |
1135 | 1135 |
1136 // If the result in r0 is a Smi, untag it, else deoptimize. | 1136 // If the result in r0 is a Smi, untag it, else deoptimize. |
1137 __ JumpIfNotSmi(result, &deoptimize); | 1137 __ JumpIfNotSmi(result, &deoptimize); |
1138 __ SmiUntag(result); | 1138 __ SmiUntag(result); |
1139 __ b(&done); | 1139 __ b(&done); |
1140 | 1140 |
1141 __ bind(&deoptimize); | 1141 __ bind(&deoptimize); |
1142 DeoptimizeIf(al, instr->environment()); | 1142 DeoptimizeIf(al, instr->environment()); |
1143 __ bind(&done); | 1143 __ bind(&done); |
1144 } | 1144 } |
1145 | 1145 |
1146 | 1146 |
1147 template<int T> | 1147 template<int T> |
1148 void LCodeGen::DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr, | 1148 void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, |
1149 Token::Value op) { | 1149 Token::Value op) { |
1150 Register left = ToRegister(instr->InputAt(0)); | 1150 Register left = ToRegister(instr->InputAt(0)); |
1151 Register right = ToRegister(instr->InputAt(1)); | 1151 Register right = ToRegister(instr->InputAt(1)); |
1152 | 1152 |
1153 __ PushSafepointRegistersAndDoubles(); | 1153 __ PushSafepointRegistersAndDoubles(); |
1154 GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right); | 1154 // Move left to r1 and right to r0 for the stub call. |
| 1155 if (left.is(r1)) { |
| 1156 __ Move(r0, right); |
| 1157 } else if (left.is(r0) && right.is(r1)) { |
| 1158 __ Swap(r0, r1, r2); |
| 1159 } else if (left.is(r0)) { |
| 1160 ASSERT(!right.is(r1)); |
| 1161 __ mov(r1, r0); |
| 1162 __ mov(r0, right); |
| 1163 } else { |
| 1164 ASSERT(!left.is(r0) && !right.is(r0)); |
| 1165 __ mov(r0, right); |
| 1166 __ mov(r1, left); |
| 1167 } |
| 1168 TypeRecordingBinaryOpStub stub(op, OVERWRITE_LEFT); |
1155 __ CallStub(&stub); | 1169 __ CallStub(&stub); |
1156 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1170 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
1157 0, | 1171 0, |
1158 Safepoint::kNoDeoptimizationIndex); | 1172 Safepoint::kNoDeoptimizationIndex); |
1159 // Overwrite the stored value of r0 with the result of the stub. | 1173 // Overwrite the stored value of r0 with the result of the stub. |
1160 __ StoreToSafepointRegistersAndDoublesSlot(r0); | 1174 __ StoreToSafepointRegistersAndDoublesSlot(r0); |
1161 __ PopSafepointRegistersAndDoubles(); | 1175 __ PopSafepointRegistersAndDoubles(); |
1162 } | 1176 } |
1163 | 1177 |
1164 | 1178 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1424 break; | 1438 break; |
1425 } | 1439 } |
1426 } | 1440 } |
1427 | 1441 |
1428 | 1442 |
1429 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1443 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
1430 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); | 1444 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); |
1431 ASSERT(ToRegister(instr->InputAt(1)).is(r0)); | 1445 ASSERT(ToRegister(instr->InputAt(1)).is(r0)); |
1432 ASSERT(ToRegister(instr->result()).is(r0)); | 1446 ASSERT(ToRegister(instr->result()).is(r0)); |
1433 | 1447 |
1434 // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current | 1448 TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); |
1435 // GenericBinaryOpStub: | |
1436 // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); | |
1437 GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0); | |
1438 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1449 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1439 } | 1450 } |
1440 | 1451 |
1441 | 1452 |
1442 int LCodeGen::GetNextEmittedBlock(int block) { | 1453 int LCodeGen::GetNextEmittedBlock(int block) { |
1443 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 1454 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
1444 LLabel* label = chunk_->GetLabel(i); | 1455 LLabel* label = chunk_->GetLabel(i); |
1445 if (!label->HasReplacement()) return i; | 1456 if (!label->HasReplacement()) return i; |
1446 } | 1457 } |
1447 return -1; | 1458 return -1; |
(...skipping 2508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3956 ASSERT(!environment->HasBeenRegistered()); | 3967 ASSERT(!environment->HasBeenRegistered()); |
3957 RegisterEnvironmentForDeoptimization(environment); | 3968 RegisterEnvironmentForDeoptimization(environment); |
3958 ASSERT(osr_pc_offset_ == -1); | 3969 ASSERT(osr_pc_offset_ == -1); |
3959 osr_pc_offset_ = masm()->pc_offset(); | 3970 osr_pc_offset_ = masm()->pc_offset(); |
3960 } | 3971 } |
3961 | 3972 |
3962 | 3973 |
3963 #undef __ | 3974 #undef __ |
3964 | 3975 |
3965 } } // namespace v8::internal | 3976 } } // namespace v8::internal |
OLD | NEW |