| 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 |