| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 } | 904 } |
| 905 | 905 |
| 906 | 906 |
| 907 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 907 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 908 // Nothing to do. | 908 // Nothing to do. |
| 909 } | 909 } |
| 910 | 910 |
| 911 | 911 |
| 912 void LCodeGen::DoModI(LModI* instr) { | 912 void LCodeGen::DoModI(LModI* instr) { |
| 913 Register scratch = scratch0(); | 913 Register scratch = scratch0(); |
| 914 const Register left = ToRegister(instr->InputAt(0)); | 914 const Register left = ToRegister(instr->left()); |
| 915 const Register result = ToRegister(instr->result()); | 915 const Register result = ToRegister(instr->result()); |
| 916 | 916 |
| 917 Label done; | 917 Label done; |
| 918 | 918 |
| 919 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 919 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
| 920 Register scratch = scratch0(); | 920 Register scratch = scratch0(); |
| 921 ASSERT(!left.is(scratch)); | 921 ASSERT(!left.is(scratch)); |
| 922 __ mov(scratch, left); | 922 __ mov(scratch, left); |
| 923 int32_t p2constant = HConstant::cast( | 923 int32_t p2constant = HConstant::cast( |
| 924 instr->hydrogen()->right())->Integer32Value(); | 924 instr->hydrogen()->right())->Integer32Value(); |
| 925 ASSERT(p2constant != 0); | 925 ASSERT(p2constant != 0); |
| 926 // Result always takes the sign of the dividend (left). | 926 // Result always takes the sign of the dividend (left). |
| 927 p2constant = abs(p2constant); | 927 p2constant = abs(p2constant); |
| 928 | 928 |
| 929 Label positive_dividend; | 929 Label positive_dividend; |
| 930 __ Branch(USE_DELAY_SLOT, &positive_dividend, ge, left, Operand(zero_reg)); | 930 __ Branch(USE_DELAY_SLOT, &positive_dividend, ge, left, Operand(zero_reg)); |
| 931 __ subu(result, zero_reg, left); | 931 __ subu(result, zero_reg, left); |
| 932 __ And(result, result, p2constant - 1); | 932 __ And(result, result, p2constant - 1); |
| 933 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 933 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 934 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); | 934 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); |
| 935 } | 935 } |
| 936 __ Branch(USE_DELAY_SLOT, &done); | 936 __ Branch(USE_DELAY_SLOT, &done); |
| 937 __ subu(result, zero_reg, result); | 937 __ subu(result, zero_reg, result); |
| 938 __ bind(&positive_dividend); | 938 __ bind(&positive_dividend); |
| 939 __ And(result, scratch, p2constant - 1); | 939 __ And(result, scratch, p2constant - 1); |
| 940 } else { | 940 } else { |
| 941 // div runs in the background while we check for special cases. | 941 // div runs in the background while we check for special cases. |
| 942 Register right = EmitLoadRegister(instr->InputAt(1), scratch); | 942 Register right = EmitLoadRegister(instr->right(), scratch); |
| 943 __ div(left, right); | 943 __ div(left, right); |
| 944 | 944 |
| 945 // Check for x % 0. | 945 // Check for x % 0. |
| 946 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 946 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 947 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg)); | 947 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg)); |
| 948 } | 948 } |
| 949 | 949 |
| 950 __ Branch(USE_DELAY_SLOT, &done, ge, left, Operand(zero_reg)); | 950 __ Branch(USE_DELAY_SLOT, &done, ge, left, Operand(zero_reg)); |
| 951 __ mfhi(result); | 951 __ mfhi(result); |
| 952 | 952 |
| 953 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 953 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 954 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); | 954 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); |
| 955 } | 955 } |
| 956 } | 956 } |
| 957 __ bind(&done); | 957 __ bind(&done); |
| 958 } | 958 } |
| 959 | 959 |
| 960 | 960 |
| 961 void LCodeGen::DoDivI(LDivI* instr) { | 961 void LCodeGen::DoDivI(LDivI* instr) { |
| 962 const Register left = ToRegister(instr->InputAt(0)); | 962 const Register left = ToRegister(instr->left()); |
| 963 const Register right = ToRegister(instr->InputAt(1)); | 963 const Register right = ToRegister(instr->right()); |
| 964 const Register result = ToRegister(instr->result()); | 964 const Register result = ToRegister(instr->result()); |
| 965 | 965 |
| 966 // On MIPS div is asynchronous - it will run in the background while we | 966 // On MIPS div is asynchronous - it will run in the background while we |
| 967 // check for special cases. | 967 // check for special cases. |
| 968 __ div(left, right); | 968 __ div(left, right); |
| 969 | 969 |
| 970 // Check for x / 0. | 970 // Check for x / 0. |
| 971 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 971 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 972 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg)); | 972 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg)); |
| 973 } | 973 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 991 __ mfhi(result); | 991 __ mfhi(result); |
| 992 DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg)); | 992 DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg)); |
| 993 __ mflo(result); | 993 __ mflo(result); |
| 994 } | 994 } |
| 995 | 995 |
| 996 | 996 |
| 997 void LCodeGen::DoMulI(LMulI* instr) { | 997 void LCodeGen::DoMulI(LMulI* instr) { |
| 998 Register scratch = scratch0(); | 998 Register scratch = scratch0(); |
| 999 Register result = ToRegister(instr->result()); | 999 Register result = ToRegister(instr->result()); |
| 1000 // Note that result may alias left. | 1000 // Note that result may alias left. |
| 1001 Register left = ToRegister(instr->InputAt(0)); | 1001 Register left = ToRegister(instr->left()); |
| 1002 LOperand* right_op = instr->InputAt(1); | 1002 LOperand* right_op = instr->right(); |
| 1003 | 1003 |
| 1004 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1004 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1005 bool bailout_on_minus_zero = | 1005 bool bailout_on_minus_zero = |
| 1006 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1006 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1007 | 1007 |
| 1008 if (right_op->IsConstantOperand() && !can_overflow) { | 1008 if (right_op->IsConstantOperand() && !can_overflow) { |
| 1009 // Use optimized code for specific constants. | 1009 // Use optimized code for specific constants. |
| 1010 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1010 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
| 1011 | 1011 |
| 1012 if (bailout_on_minus_zero && (constant < 0)) { | 1012 if (bailout_on_minus_zero && (constant < 0)) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 } else { | 1062 } else { |
| 1063 // Generate standard code. | 1063 // Generate standard code. |
| 1064 __ li(at, constant); | 1064 __ li(at, constant); |
| 1065 __ Mul(result, left, at); | 1065 __ Mul(result, left, at); |
| 1066 } | 1066 } |
| 1067 } | 1067 } |
| 1068 | 1068 |
| 1069 } else { | 1069 } else { |
| 1070 Register right = EmitLoadRegister(right_op, scratch); | 1070 Register right = EmitLoadRegister(right_op, scratch); |
| 1071 if (bailout_on_minus_zero) { | 1071 if (bailout_on_minus_zero) { |
| 1072 __ Or(ToRegister(instr->TempAt(0)), left, right); | 1072 __ Or(ToRegister(instr->temp()), left, right); |
| 1073 } | 1073 } |
| 1074 | 1074 |
| 1075 if (can_overflow) { | 1075 if (can_overflow) { |
| 1076 // hi:lo = left * right. | 1076 // hi:lo = left * right. |
| 1077 __ mult(left, right); | 1077 __ mult(left, right); |
| 1078 __ mfhi(scratch); | 1078 __ mfhi(scratch); |
| 1079 __ mflo(result); | 1079 __ mflo(result); |
| 1080 __ sra(at, result, 31); | 1080 __ sra(at, result, 31); |
| 1081 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 1081 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
| 1082 } else { | 1082 } else { |
| 1083 __ Mul(result, left, right); | 1083 __ Mul(result, left, right); |
| 1084 } | 1084 } |
| 1085 | 1085 |
| 1086 if (bailout_on_minus_zero) { | 1086 if (bailout_on_minus_zero) { |
| 1087 // Bail out if the result is supposed to be negative zero. | 1087 // Bail out if the result is supposed to be negative zero. |
| 1088 Label done; | 1088 Label done; |
| 1089 __ Branch(&done, ne, result, Operand(zero_reg)); | 1089 __ Branch(&done, ne, result, Operand(zero_reg)); |
| 1090 DeoptimizeIf(lt, | 1090 DeoptimizeIf(lt, |
| 1091 instr->environment(), | 1091 instr->environment(), |
| 1092 ToRegister(instr->TempAt(0)), | 1092 ToRegister(instr->temp()), |
| 1093 Operand(zero_reg)); | 1093 Operand(zero_reg)); |
| 1094 __ bind(&done); | 1094 __ bind(&done); |
| 1095 } | 1095 } |
| 1096 } | 1096 } |
| 1097 } | 1097 } |
| 1098 | 1098 |
| 1099 | 1099 |
| 1100 void LCodeGen::DoBitI(LBitI* instr) { | 1100 void LCodeGen::DoBitI(LBitI* instr) { |
| 1101 LOperand* left_op = instr->InputAt(0); | 1101 LOperand* left_op = instr->left(); |
| 1102 LOperand* right_op = instr->InputAt(1); | 1102 LOperand* right_op = instr->right(); |
| 1103 ASSERT(left_op->IsRegister()); | 1103 ASSERT(left_op->IsRegister()); |
| 1104 Register left = ToRegister(left_op); | 1104 Register left = ToRegister(left_op); |
| 1105 Register result = ToRegister(instr->result()); | 1105 Register result = ToRegister(instr->result()); |
| 1106 Operand right(no_reg); | 1106 Operand right(no_reg); |
| 1107 | 1107 |
| 1108 if (right_op->IsStackSlot() || right_op->IsArgument()) { | 1108 if (right_op->IsStackSlot() || right_op->IsArgument()) { |
| 1109 right = Operand(EmitLoadRegister(right_op, at)); | 1109 right = Operand(EmitLoadRegister(right_op, at)); |
| 1110 } else { | 1110 } else { |
| 1111 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); | 1111 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); |
| 1112 right = ToOperand(right_op); | 1112 right = ToOperand(right_op); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1125 default: | 1125 default: |
| 1126 UNREACHABLE(); | 1126 UNREACHABLE(); |
| 1127 break; | 1127 break; |
| 1128 } | 1128 } |
| 1129 } | 1129 } |
| 1130 | 1130 |
| 1131 | 1131 |
| 1132 void LCodeGen::DoShiftI(LShiftI* instr) { | 1132 void LCodeGen::DoShiftI(LShiftI* instr) { |
| 1133 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so | 1133 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so |
| 1134 // result may alias either of them. | 1134 // result may alias either of them. |
| 1135 LOperand* right_op = instr->InputAt(1); | 1135 LOperand* right_op = instr->right(); |
| 1136 Register left = ToRegister(instr->InputAt(0)); | 1136 Register left = ToRegister(instr->left()); |
| 1137 Register result = ToRegister(instr->result()); | 1137 Register result = ToRegister(instr->result()); |
| 1138 | 1138 |
| 1139 if (right_op->IsRegister()) { | 1139 if (right_op->IsRegister()) { |
| 1140 // No need to mask the right operand on MIPS, it is built into the variable | 1140 // No need to mask the right operand on MIPS, it is built into the variable |
| 1141 // shift instructions. | 1141 // shift instructions. |
| 1142 switch (instr->op()) { | 1142 switch (instr->op()) { |
| 1143 case Token::SAR: | 1143 case Token::SAR: |
| 1144 __ srav(result, left, ToRegister(right_op)); | 1144 __ srav(result, left, ToRegister(right_op)); |
| 1145 break; | 1145 break; |
| 1146 case Token::SHR: | 1146 case Token::SHR: |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1188 break; | 1188 break; |
| 1189 default: | 1189 default: |
| 1190 UNREACHABLE(); | 1190 UNREACHABLE(); |
| 1191 break; | 1191 break; |
| 1192 } | 1192 } |
| 1193 } | 1193 } |
| 1194 } | 1194 } |
| 1195 | 1195 |
| 1196 | 1196 |
| 1197 void LCodeGen::DoSubI(LSubI* instr) { | 1197 void LCodeGen::DoSubI(LSubI* instr) { |
| 1198 LOperand* left = instr->InputAt(0); | 1198 LOperand* left = instr->left(); |
| 1199 LOperand* right = instr->InputAt(1); | 1199 LOperand* right = instr->right(); |
| 1200 LOperand* result = instr->result(); | 1200 LOperand* result = instr->result(); |
| 1201 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1201 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1202 | 1202 |
| 1203 if (!can_overflow) { | 1203 if (!can_overflow) { |
| 1204 if (right->IsStackSlot() || right->IsArgument()) { | 1204 if (right->IsStackSlot() || right->IsArgument()) { |
| 1205 Register right_reg = EmitLoadRegister(right, at); | 1205 Register right_reg = EmitLoadRegister(right, at); |
| 1206 __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg)); | 1206 __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg)); |
| 1207 } else { | 1207 } else { |
| 1208 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1208 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
| 1209 __ Subu(ToRegister(result), ToRegister(left), ToOperand(right)); | 1209 __ Subu(ToRegister(result), ToRegister(left), ToOperand(right)); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1253 __ li(ToRegister(instr->result()), Operand(value)); | 1253 __ li(ToRegister(instr->result()), Operand(value)); |
| 1254 } else { | 1254 } else { |
| 1255 __ LoadHeapObject(ToRegister(instr->result()), | 1255 __ LoadHeapObject(ToRegister(instr->result()), |
| 1256 Handle<HeapObject>::cast(value)); | 1256 Handle<HeapObject>::cast(value)); |
| 1257 } | 1257 } |
| 1258 } | 1258 } |
| 1259 | 1259 |
| 1260 | 1260 |
| 1261 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1261 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 1262 Register result = ToRegister(instr->result()); | 1262 Register result = ToRegister(instr->result()); |
| 1263 Register array = ToRegister(instr->InputAt(0)); | 1263 Register array = ToRegister(instr->value()); |
| 1264 __ lw(result, FieldMemOperand(array, JSArray::kLengthOffset)); | 1264 __ lw(result, FieldMemOperand(array, JSArray::kLengthOffset)); |
| 1265 } | 1265 } |
| 1266 | 1266 |
| 1267 | 1267 |
| 1268 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { | 1268 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { |
| 1269 Register result = ToRegister(instr->result()); | 1269 Register result = ToRegister(instr->result()); |
| 1270 Register array = ToRegister(instr->InputAt(0)); | 1270 Register array = ToRegister(instr->value()); |
| 1271 __ lw(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset)); | 1271 __ lw(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset)); |
| 1272 } | 1272 } |
| 1273 | 1273 |
| 1274 | 1274 |
| 1275 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1275 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1276 Register result = ToRegister(instr->result()); | 1276 Register result = ToRegister(instr->result()); |
| 1277 Register map = ToRegister(instr->InputAt(0)); | 1277 Register map = ToRegister(instr->value()); |
| 1278 __ EnumLength(result, map); | 1278 __ EnumLength(result, map); |
| 1279 } | 1279 } |
| 1280 | 1280 |
| 1281 | 1281 |
| 1282 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1282 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
| 1283 Register result = ToRegister(instr->result()); | 1283 Register result = ToRegister(instr->result()); |
| 1284 Register input = ToRegister(instr->InputAt(0)); | 1284 Register input = ToRegister(instr->value()); |
| 1285 | 1285 |
| 1286 // Load map into |result|. | 1286 // Load map into |result|. |
| 1287 __ lw(result, FieldMemOperand(input, HeapObject::kMapOffset)); | 1287 __ lw(result, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 1288 // Load the map's "bit field 2" into |result|. We only need the first byte, | 1288 // Load the map's "bit field 2" into |result|. We only need the first byte, |
| 1289 // but the following bit field extraction takes care of that anyway. | 1289 // but the following bit field extraction takes care of that anyway. |
| 1290 __ lbu(result, FieldMemOperand(result, Map::kBitField2Offset)); | 1290 __ lbu(result, FieldMemOperand(result, Map::kBitField2Offset)); |
| 1291 // Retrieve elements_kind from bit field 2. | 1291 // Retrieve elements_kind from bit field 2. |
| 1292 __ Ext(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); | 1292 __ Ext(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); |
| 1293 } | 1293 } |
| 1294 | 1294 |
| 1295 | 1295 |
| 1296 void LCodeGen::DoValueOf(LValueOf* instr) { | 1296 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 1297 Register input = ToRegister(instr->InputAt(0)); | 1297 Register input = ToRegister(instr->value()); |
| 1298 Register result = ToRegister(instr->result()); | 1298 Register result = ToRegister(instr->result()); |
| 1299 Register map = ToRegister(instr->TempAt(0)); | 1299 Register map = ToRegister(instr->temp()); |
| 1300 Label done; | 1300 Label done; |
| 1301 | 1301 |
| 1302 // If the object is a smi return the object. | 1302 // If the object is a smi return the object. |
| 1303 __ Move(result, input); | 1303 __ Move(result, input); |
| 1304 __ JumpIfSmi(input, &done); | 1304 __ JumpIfSmi(input, &done); |
| 1305 | 1305 |
| 1306 // If the object is not a value type, return the object. | 1306 // If the object is not a value type, return the object. |
| 1307 __ GetObjectType(input, map, map); | 1307 __ GetObjectType(input, map, map); |
| 1308 __ Branch(&done, ne, map, Operand(JS_VALUE_TYPE)); | 1308 __ Branch(&done, ne, map, Operand(JS_VALUE_TYPE)); |
| 1309 __ lw(result, FieldMemOperand(input, JSValue::kValueOffset)); | 1309 __ lw(result, FieldMemOperand(input, JSValue::kValueOffset)); |
| 1310 | 1310 |
| 1311 __ bind(&done); | 1311 __ bind(&done); |
| 1312 } | 1312 } |
| 1313 | 1313 |
| 1314 | 1314 |
| 1315 void LCodeGen::DoDateField(LDateField* instr) { | 1315 void LCodeGen::DoDateField(LDateField* instr) { |
| 1316 Register object = ToRegister(instr->InputAt(0)); | 1316 Register object = ToRegister(instr->date()); |
| 1317 Register result = ToRegister(instr->result()); | 1317 Register result = ToRegister(instr->result()); |
| 1318 Register scratch = ToRegister(instr->TempAt(0)); | 1318 Register scratch = ToRegister(instr->temp()); |
| 1319 Smi* index = instr->index(); | 1319 Smi* index = instr->index(); |
| 1320 Label runtime, done; | 1320 Label runtime, done; |
| 1321 ASSERT(object.is(a0)); | 1321 ASSERT(object.is(a0)); |
| 1322 ASSERT(result.is(v0)); | 1322 ASSERT(result.is(v0)); |
| 1323 ASSERT(!scratch.is(scratch0())); | 1323 ASSERT(!scratch.is(scratch0())); |
| 1324 ASSERT(!scratch.is(object)); | 1324 ASSERT(!scratch.is(object)); |
| 1325 | 1325 |
| 1326 __ And(at, object, Operand(kSmiTagMask)); | 1326 __ And(at, object, Operand(kSmiTagMask)); |
| 1327 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 1327 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); |
| 1328 __ GetObjectType(object, scratch, scratch); | 1328 __ GetObjectType(object, scratch, scratch); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1344 __ bind(&runtime); | 1344 __ bind(&runtime); |
| 1345 __ PrepareCallCFunction(2, scratch); | 1345 __ PrepareCallCFunction(2, scratch); |
| 1346 __ li(a1, Operand(index)); | 1346 __ li(a1, Operand(index)); |
| 1347 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 1347 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 1348 __ bind(&done); | 1348 __ bind(&done); |
| 1349 } | 1349 } |
| 1350 } | 1350 } |
| 1351 | 1351 |
| 1352 | 1352 |
| 1353 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1353 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1354 Register input = ToRegister(instr->InputAt(0)); | 1354 Register input = ToRegister(instr->value()); |
| 1355 Register result = ToRegister(instr->result()); | 1355 Register result = ToRegister(instr->result()); |
| 1356 __ Nor(result, zero_reg, Operand(input)); | 1356 __ Nor(result, zero_reg, Operand(input)); |
| 1357 } | 1357 } |
| 1358 | 1358 |
| 1359 | 1359 |
| 1360 void LCodeGen::DoThrow(LThrow* instr) { | 1360 void LCodeGen::DoThrow(LThrow* instr) { |
| 1361 Register input_reg = EmitLoadRegister(instr->InputAt(0), at); | 1361 Register input_reg = EmitLoadRegister(instr->value(), at); |
| 1362 __ push(input_reg); | 1362 __ push(input_reg); |
| 1363 CallRuntime(Runtime::kThrow, 1, instr); | 1363 CallRuntime(Runtime::kThrow, 1, instr); |
| 1364 | 1364 |
| 1365 if (FLAG_debug_code) { | 1365 if (FLAG_debug_code) { |
| 1366 __ stop("Unreachable code."); | 1366 __ stop("Unreachable code."); |
| 1367 } | 1367 } |
| 1368 } | 1368 } |
| 1369 | 1369 |
| 1370 | 1370 |
| 1371 void LCodeGen::DoAddI(LAddI* instr) { | 1371 void LCodeGen::DoAddI(LAddI* instr) { |
| 1372 LOperand* left = instr->InputAt(0); | 1372 LOperand* left = instr->left(); |
| 1373 LOperand* right = instr->InputAt(1); | 1373 LOperand* right = instr->right(); |
| 1374 LOperand* result = instr->result(); | 1374 LOperand* result = instr->result(); |
| 1375 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1375 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1376 | 1376 |
| 1377 if (!can_overflow) { | 1377 if (!can_overflow) { |
| 1378 if (right->IsStackSlot() || right->IsArgument()) { | 1378 if (right->IsStackSlot() || right->IsArgument()) { |
| 1379 Register right_reg = EmitLoadRegister(right, at); | 1379 Register right_reg = EmitLoadRegister(right, at); |
| 1380 __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg)); | 1380 __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg)); |
| 1381 } else { | 1381 } else { |
| 1382 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1382 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
| 1383 __ Addu(ToRegister(result), ToRegister(left), ToOperand(right)); | 1383 __ Addu(ToRegister(result), ToRegister(left), ToOperand(right)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1401 ToRegister(left), | 1401 ToRegister(left), |
| 1402 ToRegister(right), | 1402 ToRegister(right), |
| 1403 overflow); // Reg at also used as scratch. | 1403 overflow); // Reg at also used as scratch. |
| 1404 } | 1404 } |
| 1405 DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); | 1405 DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); |
| 1406 } | 1406 } |
| 1407 } | 1407 } |
| 1408 | 1408 |
| 1409 | 1409 |
| 1410 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1410 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 1411 LOperand* left = instr->InputAt(0); | 1411 LOperand* left = instr->left(); |
| 1412 LOperand* right = instr->InputAt(1); | 1412 LOperand* right = instr->right(); |
| 1413 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1413 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| 1414 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | 1414 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; |
| 1415 if (instr->hydrogen()->representation().IsInteger32()) { | 1415 if (instr->hydrogen()->representation().IsInteger32()) { |
| 1416 Register left_reg = ToRegister(left); | 1416 Register left_reg = ToRegister(left); |
| 1417 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) | 1417 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) |
| 1418 ? ToOperand(right) | 1418 ? ToOperand(right) |
| 1419 : Operand(EmitLoadRegister(right, at)); | 1419 : Operand(EmitLoadRegister(right, at)); |
| 1420 Register result_reg = ToRegister(instr->result()); | 1420 Register result_reg = ToRegister(instr->result()); |
| 1421 Label return_right, done; | 1421 Label return_right, done; |
| 1422 if (!result_reg.is(left_reg)) { | 1422 if (!result_reg.is(left_reg)) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1463 __ bind(&return_left); | 1463 __ bind(&return_left); |
| 1464 if (!left_reg.is(result_reg)) { | 1464 if (!left_reg.is(result_reg)) { |
| 1465 __ mov_d(result_reg, left_reg); | 1465 __ mov_d(result_reg, left_reg); |
| 1466 } | 1466 } |
| 1467 __ bind(&done); | 1467 __ bind(&done); |
| 1468 } | 1468 } |
| 1469 } | 1469 } |
| 1470 | 1470 |
| 1471 | 1471 |
| 1472 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1472 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 1473 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); | 1473 DoubleRegister left = ToDoubleRegister(instr->left()); |
| 1474 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); | 1474 DoubleRegister right = ToDoubleRegister(instr->right()); |
| 1475 DoubleRegister result = ToDoubleRegister(instr->result()); | 1475 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 1476 switch (instr->op()) { | 1476 switch (instr->op()) { |
| 1477 case Token::ADD: | 1477 case Token::ADD: |
| 1478 __ add_d(result, left, right); | 1478 __ add_d(result, left, right); |
| 1479 break; | 1479 break; |
| 1480 case Token::SUB: | 1480 case Token::SUB: |
| 1481 __ sub_d(result, left, right); | 1481 __ sub_d(result, left, right); |
| 1482 break; | 1482 break; |
| 1483 case Token::MUL: | 1483 case Token::MUL: |
| 1484 __ mul_d(result, left, right); | 1484 __ mul_d(result, left, right); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1504 break; | 1504 break; |
| 1505 } | 1505 } |
| 1506 default: | 1506 default: |
| 1507 UNREACHABLE(); | 1507 UNREACHABLE(); |
| 1508 break; | 1508 break; |
| 1509 } | 1509 } |
| 1510 } | 1510 } |
| 1511 | 1511 |
| 1512 | 1512 |
| 1513 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1513 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1514 ASSERT(ToRegister(instr->InputAt(0)).is(a1)); | 1514 ASSERT(ToRegister(instr->left()).is(a1)); |
| 1515 ASSERT(ToRegister(instr->InputAt(1)).is(a0)); | 1515 ASSERT(ToRegister(instr->right()).is(a0)); |
| 1516 ASSERT(ToRegister(instr->result()).is(v0)); | 1516 ASSERT(ToRegister(instr->result()).is(v0)); |
| 1517 | 1517 |
| 1518 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1518 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1519 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1519 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1520 // Other arch use a nop here, to signal that there is no inlined | 1520 // Other arch use a nop here, to signal that there is no inlined |
| 1521 // patchable code. Mips does not need the nop, since our marker | 1521 // patchable code. Mips does not need the nop, since our marker |
| 1522 // instruction (andi zero_reg) will never be used in normal code. | 1522 // instruction (andi zero_reg) will never be used in normal code. |
| 1523 } | 1523 } |
| 1524 | 1524 |
| 1525 | 1525 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1569 } | 1569 } |
| 1570 } | 1570 } |
| 1571 | 1571 |
| 1572 | 1572 |
| 1573 void LCodeGen::DoBranch(LBranch* instr) { | 1573 void LCodeGen::DoBranch(LBranch* instr) { |
| 1574 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1574 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1575 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1575 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1576 | 1576 |
| 1577 Representation r = instr->hydrogen()->value()->representation(); | 1577 Representation r = instr->hydrogen()->value()->representation(); |
| 1578 if (r.IsInteger32()) { | 1578 if (r.IsInteger32()) { |
| 1579 Register reg = ToRegister(instr->InputAt(0)); | 1579 Register reg = ToRegister(instr->value()); |
| 1580 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); | 1580 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); |
| 1581 } else if (r.IsDouble()) { | 1581 } else if (r.IsDouble()) { |
| 1582 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1582 DoubleRegister reg = ToDoubleRegister(instr->value()); |
| 1583 // Test the double value. Zero and NaN are false. | 1583 // Test the double value. Zero and NaN are false. |
| 1584 EmitBranchF(true_block, false_block, ne, reg, kDoubleRegZero); | 1584 EmitBranchF(true_block, false_block, ne, reg, kDoubleRegZero); |
| 1585 } else { | 1585 } else { |
| 1586 ASSERT(r.IsTagged()); | 1586 ASSERT(r.IsTagged()); |
| 1587 Register reg = ToRegister(instr->InputAt(0)); | 1587 Register reg = ToRegister(instr->value()); |
| 1588 HType type = instr->hydrogen()->value()->type(); | 1588 HType type = instr->hydrogen()->value()->type(); |
| 1589 if (type.IsBoolean()) { | 1589 if (type.IsBoolean()) { |
| 1590 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 1590 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
| 1591 EmitBranch(true_block, false_block, eq, reg, Operand(at)); | 1591 EmitBranch(true_block, false_block, eq, reg, Operand(at)); |
| 1592 } else if (type.IsSmi()) { | 1592 } else if (type.IsSmi()) { |
| 1593 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); | 1593 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); |
| 1594 } else { | 1594 } else { |
| 1595 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1595 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1596 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1596 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1597 | 1597 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1711 case Token::IN: | 1711 case Token::IN: |
| 1712 case Token::INSTANCEOF: | 1712 case Token::INSTANCEOF: |
| 1713 default: | 1713 default: |
| 1714 UNREACHABLE(); | 1714 UNREACHABLE(); |
| 1715 } | 1715 } |
| 1716 return cond; | 1716 return cond; |
| 1717 } | 1717 } |
| 1718 | 1718 |
| 1719 | 1719 |
| 1720 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1720 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
| 1721 LOperand* left = instr->InputAt(0); | 1721 LOperand* left = instr->left(); |
| 1722 LOperand* right = instr->InputAt(1); | 1722 LOperand* right = instr->right(); |
| 1723 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1723 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1724 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1724 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1725 | 1725 |
| 1726 Condition cond = TokenToCondition(instr->op(), false); | 1726 Condition cond = TokenToCondition(instr->op(), false); |
| 1727 | 1727 |
| 1728 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 1728 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
| 1729 // We can statically evaluate the comparison. | 1729 // We can statically evaluate the comparison. |
| 1730 double left_val = ToDouble(LConstantOperand::cast(left)); | 1730 double left_val = ToDouble(LConstantOperand::cast(left)); |
| 1731 double right_val = ToDouble(LConstantOperand::cast(right)); | 1731 double right_val = ToDouble(LConstantOperand::cast(right)); |
| 1732 int next_block = | 1732 int next_block = |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1763 cmp_right = Operand(ToRegister(right)); | 1763 cmp_right = Operand(ToRegister(right)); |
| 1764 } | 1764 } |
| 1765 | 1765 |
| 1766 EmitBranch(true_block, false_block, cond, cmp_left, cmp_right); | 1766 EmitBranch(true_block, false_block, cond, cmp_left, cmp_right); |
| 1767 } | 1767 } |
| 1768 } | 1768 } |
| 1769 } | 1769 } |
| 1770 | 1770 |
| 1771 | 1771 |
| 1772 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 1772 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
| 1773 Register left = ToRegister(instr->InputAt(0)); | 1773 Register left = ToRegister(instr->left()); |
| 1774 Register right = ToRegister(instr->InputAt(1)); | 1774 Register right = ToRegister(instr->right()); |
| 1775 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1775 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1776 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1776 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1777 | 1777 |
| 1778 EmitBranch(true_block, false_block, eq, left, Operand(right)); | 1778 EmitBranch(true_block, false_block, eq, left, Operand(right)); |
| 1779 } | 1779 } |
| 1780 | 1780 |
| 1781 | 1781 |
| 1782 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 1782 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
| 1783 Register left = ToRegister(instr->InputAt(0)); | 1783 Register left = ToRegister(instr->left()); |
| 1784 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1784 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1785 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1785 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1786 | 1786 |
| 1787 EmitBranch(true_block, false_block, eq, left, | 1787 EmitBranch(true_block, false_block, eq, left, |
| 1788 Operand(instr->hydrogen()->right())); | 1788 Operand(instr->hydrogen()->right())); |
| 1789 } | 1789 } |
| 1790 | 1790 |
| 1791 | 1791 |
| 1792 | 1792 |
| 1793 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { | 1793 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { |
| 1794 Register scratch = scratch0(); | 1794 Register scratch = scratch0(); |
| 1795 Register reg = ToRegister(instr->InputAt(0)); | 1795 Register reg = ToRegister(instr->value()); |
| 1796 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1796 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1797 | 1797 |
| 1798 // If the expression is known to be untagged or a smi, then it's definitely | 1798 // If the expression is known to be untagged or a smi, then it's definitely |
| 1799 // not null, and it can't be a an undetectable object. | 1799 // not null, and it can't be a an undetectable object. |
| 1800 if (instr->hydrogen()->representation().IsSpecialization() || | 1800 if (instr->hydrogen()->representation().IsSpecialization() || |
| 1801 instr->hydrogen()->type().IsSmi()) { | 1801 instr->hydrogen()->type().IsSmi()) { |
| 1802 EmitGoto(false_block); | 1802 EmitGoto(false_block); |
| 1803 return; | 1803 return; |
| 1804 } | 1804 } |
| 1805 | 1805 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1851 // Load instance type and check that it is in object type range. | 1851 // Load instance type and check that it is in object type range. |
| 1852 __ lbu(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset)); | 1852 __ lbu(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset)); |
| 1853 __ Branch(is_not_object, | 1853 __ Branch(is_not_object, |
| 1854 lt, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1854 lt, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 1855 | 1855 |
| 1856 return le; | 1856 return le; |
| 1857 } | 1857 } |
| 1858 | 1858 |
| 1859 | 1859 |
| 1860 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1860 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 1861 Register reg = ToRegister(instr->InputAt(0)); | 1861 Register reg = ToRegister(instr->value()); |
| 1862 Register temp1 = ToRegister(instr->TempAt(0)); | 1862 Register temp1 = ToRegister(instr->temp()); |
| 1863 Register temp2 = scratch0(); | 1863 Register temp2 = scratch0(); |
| 1864 | 1864 |
| 1865 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1865 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1866 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1866 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1867 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1867 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1868 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1868 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1869 | 1869 |
| 1870 Condition true_cond = | 1870 Condition true_cond = |
| 1871 EmitIsObject(reg, temp1, temp2, false_label, true_label); | 1871 EmitIsObject(reg, temp1, temp2, false_label, true_label); |
| 1872 | 1872 |
| 1873 EmitBranch(true_block, false_block, true_cond, temp2, | 1873 EmitBranch(true_block, false_block, true_cond, temp2, |
| 1874 Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1874 Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 1875 } | 1875 } |
| 1876 | 1876 |
| 1877 | 1877 |
| 1878 Condition LCodeGen::EmitIsString(Register input, | 1878 Condition LCodeGen::EmitIsString(Register input, |
| 1879 Register temp1, | 1879 Register temp1, |
| 1880 Label* is_not_string) { | 1880 Label* is_not_string) { |
| 1881 __ JumpIfSmi(input, is_not_string); | 1881 __ JumpIfSmi(input, is_not_string); |
| 1882 __ GetObjectType(input, temp1, temp1); | 1882 __ GetObjectType(input, temp1, temp1); |
| 1883 | 1883 |
| 1884 return lt; | 1884 return lt; |
| 1885 } | 1885 } |
| 1886 | 1886 |
| 1887 | 1887 |
| 1888 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 1888 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
| 1889 Register reg = ToRegister(instr->InputAt(0)); | 1889 Register reg = ToRegister(instr->value()); |
| 1890 Register temp1 = ToRegister(instr->TempAt(0)); | 1890 Register temp1 = ToRegister(instr->temp()); |
| 1891 | 1891 |
| 1892 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1892 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1893 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1893 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1894 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1894 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1895 | 1895 |
| 1896 Condition true_cond = | 1896 Condition true_cond = |
| 1897 EmitIsString(reg, temp1, false_label); | 1897 EmitIsString(reg, temp1, false_label); |
| 1898 | 1898 |
| 1899 EmitBranch(true_block, false_block, true_cond, temp1, | 1899 EmitBranch(true_block, false_block, true_cond, temp1, |
| 1900 Operand(FIRST_NONSTRING_TYPE)); | 1900 Operand(FIRST_NONSTRING_TYPE)); |
| 1901 } | 1901 } |
| 1902 | 1902 |
| 1903 | 1903 |
| 1904 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1904 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 1905 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1905 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1906 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1906 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1907 | 1907 |
| 1908 Register input_reg = EmitLoadRegister(instr->InputAt(0), at); | 1908 Register input_reg = EmitLoadRegister(instr->value(), at); |
| 1909 __ And(at, input_reg, kSmiTagMask); | 1909 __ And(at, input_reg, kSmiTagMask); |
| 1910 EmitBranch(true_block, false_block, eq, at, Operand(zero_reg)); | 1910 EmitBranch(true_block, false_block, eq, at, Operand(zero_reg)); |
| 1911 } | 1911 } |
| 1912 | 1912 |
| 1913 | 1913 |
| 1914 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 1914 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
| 1915 Register input = ToRegister(instr->InputAt(0)); | 1915 Register input = ToRegister(instr->value()); |
| 1916 Register temp = ToRegister(instr->TempAt(0)); | 1916 Register temp = ToRegister(instr->temp()); |
| 1917 | 1917 |
| 1918 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1918 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1919 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1919 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1920 | 1920 |
| 1921 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 1921 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
| 1922 __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset)); | 1922 __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 1923 __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); | 1923 __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); |
| 1924 __ And(at, temp, Operand(1 << Map::kIsUndetectable)); | 1924 __ And(at, temp, Operand(1 << Map::kIsUndetectable)); |
| 1925 EmitBranch(true_block, false_block, ne, at, Operand(zero_reg)); | 1925 EmitBranch(true_block, false_block, ne, at, Operand(zero_reg)); |
| 1926 } | 1926 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1975 if (from == to) return eq; | 1975 if (from == to) return eq; |
| 1976 if (to == LAST_TYPE) return hs; | 1976 if (to == LAST_TYPE) return hs; |
| 1977 if (from == FIRST_TYPE) return ls; | 1977 if (from == FIRST_TYPE) return ls; |
| 1978 UNREACHABLE(); | 1978 UNREACHABLE(); |
| 1979 return eq; | 1979 return eq; |
| 1980 } | 1980 } |
| 1981 | 1981 |
| 1982 | 1982 |
| 1983 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1983 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 1984 Register scratch = scratch0(); | 1984 Register scratch = scratch0(); |
| 1985 Register input = ToRegister(instr->InputAt(0)); | 1985 Register input = ToRegister(instr->value()); |
| 1986 | 1986 |
| 1987 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1987 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1988 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1988 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1989 | 1989 |
| 1990 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1990 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1991 | 1991 |
| 1992 __ JumpIfSmi(input, false_label); | 1992 __ JumpIfSmi(input, false_label); |
| 1993 | 1993 |
| 1994 __ GetObjectType(input, scratch, scratch); | 1994 __ GetObjectType(input, scratch, scratch); |
| 1995 EmitBranch(true_block, | 1995 EmitBranch(true_block, |
| 1996 false_block, | 1996 false_block, |
| 1997 BranchCondition(instr->hydrogen()), | 1997 BranchCondition(instr->hydrogen()), |
| 1998 scratch, | 1998 scratch, |
| 1999 Operand(TestType(instr->hydrogen()))); | 1999 Operand(TestType(instr->hydrogen()))); |
| 2000 } | 2000 } |
| 2001 | 2001 |
| 2002 | 2002 |
| 2003 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2003 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
| 2004 Register input = ToRegister(instr->InputAt(0)); | 2004 Register input = ToRegister(instr->value()); |
| 2005 Register result = ToRegister(instr->result()); | 2005 Register result = ToRegister(instr->result()); |
| 2006 | 2006 |
| 2007 __ AbortIfNotString(input); | 2007 __ AbortIfNotString(input); |
| 2008 | 2008 |
| 2009 __ lw(result, FieldMemOperand(input, String::kHashFieldOffset)); | 2009 __ lw(result, FieldMemOperand(input, String::kHashFieldOffset)); |
| 2010 __ IndexFromHash(result, result); | 2010 __ IndexFromHash(result, result); |
| 2011 } | 2011 } |
| 2012 | 2012 |
| 2013 | 2013 |
| 2014 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2014 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 2015 LHasCachedArrayIndexAndBranch* instr) { | 2015 LHasCachedArrayIndexAndBranch* instr) { |
| 2016 Register input = ToRegister(instr->InputAt(0)); | 2016 Register input = ToRegister(instr->value()); |
| 2017 Register scratch = scratch0(); | 2017 Register scratch = scratch0(); |
| 2018 | 2018 |
| 2019 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2019 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2020 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2020 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2021 | 2021 |
| 2022 __ lw(scratch, | 2022 __ lw(scratch, |
| 2023 FieldMemOperand(input, String::kHashFieldOffset)); | 2023 FieldMemOperand(input, String::kHashFieldOffset)); |
| 2024 __ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask)); | 2024 __ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask)); |
| 2025 EmitBranch(true_block, false_block, eq, at, Operand(zero_reg)); | 2025 EmitBranch(true_block, false_block, eq, at, Operand(zero_reg)); |
| 2026 } | 2026 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2086 // classes and it doesn't have to because you can't access it with natives | 2086 // classes and it doesn't have to because you can't access it with natives |
| 2087 // syntax. Since both sides are symbols it is sufficient to use an identity | 2087 // syntax. Since both sides are symbols it is sufficient to use an identity |
| 2088 // comparison. | 2088 // comparison. |
| 2089 | 2089 |
| 2090 // End with the address of this class_name instance in temp register. | 2090 // End with the address of this class_name instance in temp register. |
| 2091 // On MIPS, the caller must do the comparison with Handle<String>class_name. | 2091 // On MIPS, the caller must do the comparison with Handle<String>class_name. |
| 2092 } | 2092 } |
| 2093 | 2093 |
| 2094 | 2094 |
| 2095 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2095 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 2096 Register input = ToRegister(instr->InputAt(0)); | 2096 Register input = ToRegister(instr->value()); |
| 2097 Register temp = scratch0(); | 2097 Register temp = scratch0(); |
| 2098 Register temp2 = ToRegister(instr->TempAt(0)); | 2098 Register temp2 = ToRegister(instr->temp()); |
| 2099 Handle<String> class_name = instr->hydrogen()->class_name(); | 2099 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 2100 | 2100 |
| 2101 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2101 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2102 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2102 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2103 | 2103 |
| 2104 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2104 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 2105 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2105 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 2106 | 2106 |
| 2107 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 2107 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
| 2108 | 2108 |
| 2109 EmitBranch(true_block, false_block, eq, temp, Operand(class_name)); | 2109 EmitBranch(true_block, false_block, eq, temp, Operand(class_name)); |
| 2110 } | 2110 } |
| 2111 | 2111 |
| 2112 | 2112 |
| 2113 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2113 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 2114 Register reg = ToRegister(instr->InputAt(0)); | 2114 Register reg = ToRegister(instr->value()); |
| 2115 Register temp = ToRegister(instr->TempAt(0)); | 2115 Register temp = ToRegister(instr->temp()); |
| 2116 int true_block = instr->true_block_id(); | 2116 int true_block = instr->true_block_id(); |
| 2117 int false_block = instr->false_block_id(); | 2117 int false_block = instr->false_block_id(); |
| 2118 | 2118 |
| 2119 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2119 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2120 EmitBranch(true_block, false_block, eq, temp, Operand(instr->map())); | 2120 EmitBranch(true_block, false_block, eq, temp, Operand(instr->map())); |
| 2121 } | 2121 } |
| 2122 | 2122 |
| 2123 | 2123 |
| 2124 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2124 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 2125 Label true_label, done; | 2125 Label true_label, done; |
| 2126 ASSERT(ToRegister(instr->InputAt(0)).is(a0)); // Object is in a0. | 2126 ASSERT(ToRegister(instr->left()).is(a0)); // Object is in a0. |
| 2127 ASSERT(ToRegister(instr->InputAt(1)).is(a1)); // Function is in a1. | 2127 ASSERT(ToRegister(instr->right()).is(a1)); // Function is in a1. |
| 2128 Register result = ToRegister(instr->result()); | 2128 Register result = ToRegister(instr->result()); |
| 2129 ASSERT(result.is(v0)); | 2129 ASSERT(result.is(v0)); |
| 2130 | 2130 |
| 2131 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2131 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 2132 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2132 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2133 | 2133 |
| 2134 __ Branch(&true_label, eq, result, Operand(zero_reg)); | 2134 __ Branch(&true_label, eq, result, Operand(zero_reg)); |
| 2135 __ li(result, Operand(factory()->false_value())); | 2135 __ li(result, Operand(factory()->false_value())); |
| 2136 __ Branch(&done); | 2136 __ Branch(&done); |
| 2137 __ bind(&true_label); | 2137 __ bind(&true_label); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2154 | 2154 |
| 2155 private: | 2155 private: |
| 2156 LInstanceOfKnownGlobal* instr_; | 2156 LInstanceOfKnownGlobal* instr_; |
| 2157 Label map_check_; | 2157 Label map_check_; |
| 2158 }; | 2158 }; |
| 2159 | 2159 |
| 2160 DeferredInstanceOfKnownGlobal* deferred; | 2160 DeferredInstanceOfKnownGlobal* deferred; |
| 2161 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2161 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
| 2162 | 2162 |
| 2163 Label done, false_result; | 2163 Label done, false_result; |
| 2164 Register object = ToRegister(instr->InputAt(0)); | 2164 Register object = ToRegister(instr->value()); |
| 2165 Register temp = ToRegister(instr->TempAt(0)); | 2165 Register temp = ToRegister(instr->temp()); |
| 2166 Register result = ToRegister(instr->result()); | 2166 Register result = ToRegister(instr->result()); |
| 2167 | 2167 |
| 2168 ASSERT(object.is(a0)); | 2168 ASSERT(object.is(a0)); |
| 2169 ASSERT(result.is(v0)); | 2169 ASSERT(result.is(v0)); |
| 2170 | 2170 |
| 2171 // A Smi is not instance of anything. | 2171 // A Smi is not instance of anything. |
| 2172 __ JumpIfSmi(object, &false_result); | 2172 __ JumpIfSmi(object, &false_result); |
| 2173 | 2173 |
| 2174 // This is the inlined call site instanceof cache. The two occurences of the | 2174 // This is the inlined call site instanceof cache. The two occurences of the |
| 2175 // hole value will be patched to the last map/result pair generated by the | 2175 // hole value will be patched to the last map/result pair generated by the |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2230 flags | InstanceofStub::kCallSiteInlineCheck); | 2230 flags | InstanceofStub::kCallSiteInlineCheck); |
| 2231 flags = static_cast<InstanceofStub::Flags>( | 2231 flags = static_cast<InstanceofStub::Flags>( |
| 2232 flags | InstanceofStub::kReturnTrueFalseObject); | 2232 flags | InstanceofStub::kReturnTrueFalseObject); |
| 2233 InstanceofStub stub(flags); | 2233 InstanceofStub stub(flags); |
| 2234 | 2234 |
| 2235 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2235 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 2236 | 2236 |
| 2237 // Get the temp register reserved by the instruction. This needs to be t0 as | 2237 // Get the temp register reserved by the instruction. This needs to be t0 as |
| 2238 // its slot of the pushing of safepoint registers is used to communicate the | 2238 // its slot of the pushing of safepoint registers is used to communicate the |
| 2239 // offset to the location of the map check. | 2239 // offset to the location of the map check. |
| 2240 Register temp = ToRegister(instr->TempAt(0)); | 2240 Register temp = ToRegister(instr->temp()); |
| 2241 ASSERT(temp.is(t0)); | 2241 ASSERT(temp.is(t0)); |
| 2242 __ LoadHeapObject(InstanceofStub::right(), instr->function()); | 2242 __ LoadHeapObject(InstanceofStub::right(), instr->function()); |
| 2243 static const int kAdditionalDelta = 7; | 2243 static const int kAdditionalDelta = 7; |
| 2244 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; | 2244 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
| 2245 Label before_push_delta; | 2245 Label before_push_delta; |
| 2246 __ bind(&before_push_delta); | 2246 __ bind(&before_push_delta); |
| 2247 { | 2247 { |
| 2248 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 2248 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
| 2249 __ li(temp, Operand(delta * kPointerSize), CONSTANT_SIZE); | 2249 __ li(temp, Operand(delta * kPointerSize), CONSTANT_SIZE); |
| 2250 __ StoreToSafepointRegisterSlot(temp, temp); | 2250 __ StoreToSafepointRegisterSlot(temp, temp); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2325 | 2325 |
| 2326 // Load the cell. | 2326 // Load the cell. |
| 2327 __ li(cell, Operand(instr->hydrogen()->cell())); | 2327 __ li(cell, Operand(instr->hydrogen()->cell())); |
| 2328 | 2328 |
| 2329 // If the cell we are storing to contains the hole it could have | 2329 // If the cell we are storing to contains the hole it could have |
| 2330 // been deleted from the property dictionary. In that case, we need | 2330 // been deleted from the property dictionary. In that case, we need |
| 2331 // to update the property details in the property dictionary to mark | 2331 // to update the property details in the property dictionary to mark |
| 2332 // it as no longer deleted. | 2332 // it as no longer deleted. |
| 2333 if (instr->hydrogen()->RequiresHoleCheck()) { | 2333 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2334 // We use a temp to check the payload. | 2334 // We use a temp to check the payload. |
| 2335 Register payload = ToRegister(instr->TempAt(0)); | 2335 Register payload = ToRegister(instr->temp()); |
| 2336 __ lw(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); | 2336 __ lw(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); |
| 2337 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2337 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2338 DeoptimizeIf(eq, instr->environment(), payload, Operand(at)); | 2338 DeoptimizeIf(eq, instr->environment(), payload, Operand(at)); |
| 2339 } | 2339 } |
| 2340 | 2340 |
| 2341 // Store the value. | 2341 // Store the value. |
| 2342 __ sw(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); | 2342 __ sw(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); |
| 2343 // Cells are always rescanned, so no write barrier here. | 2343 // Cells are always rescanned, so no write barrier here. |
| 2344 } | 2344 } |
| 2345 | 2345 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2408 kSaveFPRegs, | 2408 kSaveFPRegs, |
| 2409 EMIT_REMEMBERED_SET, | 2409 EMIT_REMEMBERED_SET, |
| 2410 check_needed); | 2410 check_needed); |
| 2411 } | 2411 } |
| 2412 | 2412 |
| 2413 __ bind(&skip_assignment); | 2413 __ bind(&skip_assignment); |
| 2414 } | 2414 } |
| 2415 | 2415 |
| 2416 | 2416 |
| 2417 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2417 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 2418 Register object = ToRegister(instr->InputAt(0)); | 2418 Register object = ToRegister(instr->object()); |
| 2419 Register result = ToRegister(instr->result()); | 2419 Register result = ToRegister(instr->result()); |
| 2420 if (instr->hydrogen()->is_in_object()) { | 2420 if (instr->hydrogen()->is_in_object()) { |
| 2421 __ lw(result, FieldMemOperand(object, instr->hydrogen()->offset())); | 2421 __ lw(result, FieldMemOperand(object, instr->hydrogen()->offset())); |
| 2422 } else { | 2422 } else { |
| 2423 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2423 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 2424 __ lw(result, FieldMemOperand(result, instr->hydrogen()->offset())); | 2424 __ lw(result, FieldMemOperand(result, instr->hydrogen()->offset())); |
| 2425 } | 2425 } |
| 2426 } | 2426 } |
| 2427 | 2427 |
| 2428 | 2428 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2561 __ bind(&non_instance); | 2561 __ bind(&non_instance); |
| 2562 __ lw(result, FieldMemOperand(result, Map::kConstructorOffset)); | 2562 __ lw(result, FieldMemOperand(result, Map::kConstructorOffset)); |
| 2563 | 2563 |
| 2564 // All done. | 2564 // All done. |
| 2565 __ bind(&done); | 2565 __ bind(&done); |
| 2566 } | 2566 } |
| 2567 | 2567 |
| 2568 | 2568 |
| 2569 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2569 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
| 2570 Register result = ToRegister(instr->result()); | 2570 Register result = ToRegister(instr->result()); |
| 2571 Register input = ToRegister(instr->InputAt(0)); | 2571 Register input = ToRegister(instr->object()); |
| 2572 Register scratch = scratch0(); | 2572 Register scratch = scratch0(); |
| 2573 | 2573 |
| 2574 __ lw(result, FieldMemOperand(input, JSObject::kElementsOffset)); | 2574 __ lw(result, FieldMemOperand(input, JSObject::kElementsOffset)); |
| 2575 if (FLAG_debug_code) { | 2575 if (FLAG_debug_code) { |
| 2576 Label done, fail; | 2576 Label done, fail; |
| 2577 __ lw(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); | 2577 __ lw(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); |
| 2578 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); | 2578 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); |
| 2579 __ Branch(USE_DELAY_SLOT, &done, eq, scratch, Operand(at)); | 2579 __ Branch(USE_DELAY_SLOT, &done, eq, scratch, Operand(at)); |
| 2580 __ LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex); // In the delay slot. | 2580 __ LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex); // In the delay slot. |
| 2581 __ Branch(&done, eq, scratch, Operand(at)); | 2581 __ Branch(&done, eq, scratch, Operand(at)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2594 __ bind(&fail); | 2594 __ bind(&fail); |
| 2595 __ Abort("Check for fast or external elements failed."); | 2595 __ Abort("Check for fast or external elements failed."); |
| 2596 __ bind(&done); | 2596 __ bind(&done); |
| 2597 } | 2597 } |
| 2598 } | 2598 } |
| 2599 | 2599 |
| 2600 | 2600 |
| 2601 void LCodeGen::DoLoadExternalArrayPointer( | 2601 void LCodeGen::DoLoadExternalArrayPointer( |
| 2602 LLoadExternalArrayPointer* instr) { | 2602 LLoadExternalArrayPointer* instr) { |
| 2603 Register to_reg = ToRegister(instr->result()); | 2603 Register to_reg = ToRegister(instr->result()); |
| 2604 Register from_reg = ToRegister(instr->InputAt(0)); | 2604 Register from_reg = ToRegister(instr->object()); |
| 2605 __ lw(to_reg, FieldMemOperand(from_reg, | 2605 __ lw(to_reg, FieldMemOperand(from_reg, |
| 2606 ExternalArray::kExternalPointerOffset)); | 2606 ExternalArray::kExternalPointerOffset)); |
| 2607 } | 2607 } |
| 2608 | 2608 |
| 2609 | 2609 |
| 2610 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2610 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 2611 Register arguments = ToRegister(instr->arguments()); | 2611 Register arguments = ToRegister(instr->arguments()); |
| 2612 Register length = ToRegister(instr->length()); | 2612 Register length = ToRegister(instr->length()); |
| 2613 Register index = ToRegister(instr->index()); | 2613 Register index = ToRegister(instr->index()); |
| 2614 Register result = ToRegister(instr->result()); | 2614 Register result = ToRegister(instr->result()); |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2867 | 2867 |
| 2868 // Result is the frame pointer for the frame if not adapted and for the real | 2868 // Result is the frame pointer for the frame if not adapted and for the real |
| 2869 // frame below the adaptor frame if adapted. | 2869 // frame below the adaptor frame if adapted. |
| 2870 __ Movn(result, fp, temp); // Move only if temp is not equal to zero (ne). | 2870 __ Movn(result, fp, temp); // Move only if temp is not equal to zero (ne). |
| 2871 __ Movz(result, scratch, temp); // Move only if temp is equal to zero (eq). | 2871 __ Movz(result, scratch, temp); // Move only if temp is equal to zero (eq). |
| 2872 } | 2872 } |
| 2873 } | 2873 } |
| 2874 | 2874 |
| 2875 | 2875 |
| 2876 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2876 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 2877 Register elem = ToRegister(instr->InputAt(0)); | 2877 Register elem = ToRegister(instr->elements()); |
| 2878 Register result = ToRegister(instr->result()); | 2878 Register result = ToRegister(instr->result()); |
| 2879 | 2879 |
| 2880 Label done; | 2880 Label done; |
| 2881 | 2881 |
| 2882 // If no arguments adaptor frame the number of arguments is fixed. | 2882 // If no arguments adaptor frame the number of arguments is fixed. |
| 2883 __ Addu(result, zero_reg, Operand(scope()->num_parameters())); | 2883 __ Addu(result, zero_reg, Operand(scope()->num_parameters())); |
| 2884 __ Branch(&done, eq, fp, Operand(elem)); | 2884 __ Branch(&done, eq, fp, Operand(elem)); |
| 2885 | 2885 |
| 2886 // Arguments adaptor frame present. Get argument length from there. | 2886 // Arguments adaptor frame present. Get argument length from there. |
| 2887 __ lw(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2887 __ lw(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2985 // The number of arguments is stored in receiver which is a0, as expected | 2985 // The number of arguments is stored in receiver which is a0, as expected |
| 2986 // by InvokeFunction. | 2986 // by InvokeFunction. |
| 2987 ParameterCount actual(receiver); | 2987 ParameterCount actual(receiver); |
| 2988 __ InvokeFunction(function, actual, CALL_FUNCTION, | 2988 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 2989 safepoint_generator, CALL_AS_METHOD); | 2989 safepoint_generator, CALL_AS_METHOD); |
| 2990 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2990 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2991 } | 2991 } |
| 2992 | 2992 |
| 2993 | 2993 |
| 2994 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2994 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 2995 LOperand* argument = instr->InputAt(0); | 2995 LOperand* argument = instr->value(); |
| 2996 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 2996 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
| 2997 Abort("DoPushArgument not implemented for double type."); | 2997 Abort("DoPushArgument not implemented for double type."); |
| 2998 } else { | 2998 } else { |
| 2999 Register argument_reg = EmitLoadRegister(argument, at); | 2999 Register argument_reg = EmitLoadRegister(argument, at); |
| 3000 __ push(argument_reg); | 3000 __ push(argument_reg); |
| 3001 } | 3001 } |
| 3002 } | 3002 } |
| 3003 | 3003 |
| 3004 | 3004 |
| 3005 void LCodeGen::DoDrop(LDrop* instr) { | 3005 void LCodeGen::DoDrop(LDrop* instr) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3036 } | 3036 } |
| 3037 | 3037 |
| 3038 | 3038 |
| 3039 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 3039 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| 3040 Register result = ToRegister(instr->result()); | 3040 Register result = ToRegister(instr->result()); |
| 3041 __ lw(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 3041 __ lw(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
| 3042 } | 3042 } |
| 3043 | 3043 |
| 3044 | 3044 |
| 3045 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 3045 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
| 3046 Register global = ToRegister(instr->global()); | 3046 Register global = ToRegister(instr->global_object()); |
| 3047 Register result = ToRegister(instr->result()); | 3047 Register result = ToRegister(instr->result()); |
| 3048 __ lw(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | 3048 __ lw(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); |
| 3049 } | 3049 } |
| 3050 | 3050 |
| 3051 | 3051 |
| 3052 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3052 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3053 int arity, | 3053 int arity, |
| 3054 LInstruction* instr, | 3054 LInstruction* instr, |
| 3055 CallKind call_kind, | 3055 CallKind call_kind, |
| 3056 A1State a1_state) { | 3056 A1State a1_state) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3097 __ mov(a0, v0); | 3097 __ mov(a0, v0); |
| 3098 CallKnownFunction(instr->function(), | 3098 CallKnownFunction(instr->function(), |
| 3099 instr->arity(), | 3099 instr->arity(), |
| 3100 instr, | 3100 instr, |
| 3101 CALL_AS_METHOD, | 3101 CALL_AS_METHOD, |
| 3102 A1_UNINITIALIZED); | 3102 A1_UNINITIALIZED); |
| 3103 } | 3103 } |
| 3104 | 3104 |
| 3105 | 3105 |
| 3106 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 3106 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 3107 Register input = ToRegister(instr->InputAt(0)); | 3107 Register input = ToRegister(instr->value()); |
| 3108 Register result = ToRegister(instr->result()); | 3108 Register result = ToRegister(instr->result()); |
| 3109 Register scratch = scratch0(); | 3109 Register scratch = scratch0(); |
| 3110 | 3110 |
| 3111 // Deoptimize if not a heap number. | 3111 // Deoptimize if not a heap number. |
| 3112 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3112 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 3113 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 3113 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 3114 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 3114 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
| 3115 | 3115 |
| 3116 Label done; | 3116 Label done; |
| 3117 Register exponent = scratch0(); | 3117 Register exponent = scratch0(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3162 __ sw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); | 3162 __ sw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
| 3163 | 3163 |
| 3164 __ StoreToSafepointRegisterSlot(tmp1, result); | 3164 __ StoreToSafepointRegisterSlot(tmp1, result); |
| 3165 } | 3165 } |
| 3166 | 3166 |
| 3167 __ bind(&done); | 3167 __ bind(&done); |
| 3168 } | 3168 } |
| 3169 | 3169 |
| 3170 | 3170 |
| 3171 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 3171 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 3172 Register input = ToRegister(instr->InputAt(0)); | 3172 Register input = ToRegister(instr->value()); |
| 3173 Register result = ToRegister(instr->result()); | 3173 Register result = ToRegister(instr->result()); |
| 3174 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 3174 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
| 3175 Label done; | 3175 Label done; |
| 3176 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); | 3176 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); |
| 3177 __ mov(result, input); | 3177 __ mov(result, input); |
| 3178 ASSERT_EQ(2, masm()->InstructionsGeneratedSince(&done)); | 3178 ASSERT_EQ(2, masm()->InstructionsGeneratedSince(&done)); |
| 3179 __ subu(result, zero_reg, input); | 3179 __ subu(result, zero_reg, input); |
| 3180 // Overflow if result is still negative, i.e. 0x80000000. | 3180 // Overflow if result is still negative, i.e. 0x80000000. |
| 3181 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); | 3181 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); |
| 3182 __ bind(&done); | 3182 __ bind(&done); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3193 virtual void Generate() { | 3193 virtual void Generate() { |
| 3194 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3194 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 3195 } | 3195 } |
| 3196 virtual LInstruction* instr() { return instr_; } | 3196 virtual LInstruction* instr() { return instr_; } |
| 3197 private: | 3197 private: |
| 3198 LUnaryMathOperation* instr_; | 3198 LUnaryMathOperation* instr_; |
| 3199 }; | 3199 }; |
| 3200 | 3200 |
| 3201 Representation r = instr->hydrogen()->value()->representation(); | 3201 Representation r = instr->hydrogen()->value()->representation(); |
| 3202 if (r.IsDouble()) { | 3202 if (r.IsDouble()) { |
| 3203 FPURegister input = ToDoubleRegister(instr->InputAt(0)); | 3203 FPURegister input = ToDoubleRegister(instr->value()); |
| 3204 FPURegister result = ToDoubleRegister(instr->result()); | 3204 FPURegister result = ToDoubleRegister(instr->result()); |
| 3205 __ abs_d(result, input); | 3205 __ abs_d(result, input); |
| 3206 } else if (r.IsInteger32()) { | 3206 } else if (r.IsInteger32()) { |
| 3207 EmitIntegerMathAbs(instr); | 3207 EmitIntegerMathAbs(instr); |
| 3208 } else { | 3208 } else { |
| 3209 // Representation is tagged. | 3209 // Representation is tagged. |
| 3210 DeferredMathAbsTaggedHeapNumber* deferred = | 3210 DeferredMathAbsTaggedHeapNumber* deferred = |
| 3211 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3211 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
| 3212 Register input = ToRegister(instr->InputAt(0)); | 3212 Register input = ToRegister(instr->value()); |
| 3213 // Smi check. | 3213 // Smi check. |
| 3214 __ JumpIfNotSmi(input, deferred->entry()); | 3214 __ JumpIfNotSmi(input, deferred->entry()); |
| 3215 // If smi, handle it directly. | 3215 // If smi, handle it directly. |
| 3216 EmitIntegerMathAbs(instr); | 3216 EmitIntegerMathAbs(instr); |
| 3217 __ bind(deferred->exit()); | 3217 __ bind(deferred->exit()); |
| 3218 } | 3218 } |
| 3219 } | 3219 } |
| 3220 | 3220 |
| 3221 | 3221 |
| 3222 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 3222 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| 3223 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3223 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3224 Register result = ToRegister(instr->result()); | 3224 Register result = ToRegister(instr->result()); |
| 3225 FPURegister single_scratch = double_scratch0().low(); | 3225 FPURegister single_scratch = double_scratch0().low(); |
| 3226 Register scratch1 = scratch0(); | 3226 Register scratch1 = scratch0(); |
| 3227 Register except_flag = ToRegister(instr->TempAt(0)); | 3227 Register except_flag = ToRegister(instr->temp()); |
| 3228 | 3228 |
| 3229 __ EmitFPUTruncate(kRoundToMinusInf, | 3229 __ EmitFPUTruncate(kRoundToMinusInf, |
| 3230 single_scratch, | 3230 single_scratch, |
| 3231 input, | 3231 input, |
| 3232 scratch1, | 3232 scratch1, |
| 3233 except_flag); | 3233 except_flag); |
| 3234 | 3234 |
| 3235 // Deopt if the operation did not succeed. | 3235 // Deopt if the operation did not succeed. |
| 3236 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 3236 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); |
| 3237 | 3237 |
| 3238 // Load the result. | 3238 // Load the result. |
| 3239 __ mfc1(result, single_scratch); | 3239 __ mfc1(result, single_scratch); |
| 3240 | 3240 |
| 3241 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3241 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3242 // Test for -0. | 3242 // Test for -0. |
| 3243 Label done; | 3243 Label done; |
| 3244 __ Branch(&done, ne, result, Operand(zero_reg)); | 3244 __ Branch(&done, ne, result, Operand(zero_reg)); |
| 3245 __ mfc1(scratch1, input.high()); | 3245 __ mfc1(scratch1, input.high()); |
| 3246 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 3246 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 3247 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 3247 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); |
| 3248 __ bind(&done); | 3248 __ bind(&done); |
| 3249 } | 3249 } |
| 3250 } | 3250 } |
| 3251 | 3251 |
| 3252 | 3252 |
| 3253 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 3253 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 3254 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3254 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3255 Register result = ToRegister(instr->result()); | 3255 Register result = ToRegister(instr->result()); |
| 3256 Register scratch = scratch0(); | 3256 Register scratch = scratch0(); |
| 3257 Label done, check_sign_on_zero; | 3257 Label done, check_sign_on_zero; |
| 3258 | 3258 |
| 3259 // Extract exponent bits. | 3259 // Extract exponent bits. |
| 3260 __ mfc1(result, input.high()); | 3260 __ mfc1(result, input.high()); |
| 3261 __ Ext(scratch, | 3261 __ Ext(scratch, |
| 3262 result, | 3262 result, |
| 3263 HeapNumber::kExponentShift, | 3263 HeapNumber::kExponentShift, |
| 3264 HeapNumber::kExponentBits); | 3264 HeapNumber::kExponentBits); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3321 __ bind(&check_sign_on_zero); | 3321 __ bind(&check_sign_on_zero); |
| 3322 __ mfc1(scratch, input.high()); | 3322 __ mfc1(scratch, input.high()); |
| 3323 __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); | 3323 __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); |
| 3324 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 3324 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); |
| 3325 } | 3325 } |
| 3326 __ bind(&done); | 3326 __ bind(&done); |
| 3327 } | 3327 } |
| 3328 | 3328 |
| 3329 | 3329 |
| 3330 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3330 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 3331 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3331 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3332 DoubleRegister result = ToDoubleRegister(instr->result()); | 3332 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3333 __ sqrt_d(result, input); | 3333 __ sqrt_d(result, input); |
| 3334 } | 3334 } |
| 3335 | 3335 |
| 3336 | 3336 |
| 3337 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3337 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
| 3338 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3338 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3339 DoubleRegister result = ToDoubleRegister(instr->result()); | 3339 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3340 DoubleRegister temp = ToDoubleRegister(instr->TempAt(0)); | 3340 DoubleRegister temp = ToDoubleRegister(instr->temp()); |
| 3341 | 3341 |
| 3342 ASSERT(!input.is(result)); | 3342 ASSERT(!input.is(result)); |
| 3343 | 3343 |
| 3344 // Note that according to ECMA-262 15.8.2.13: | 3344 // Note that according to ECMA-262 15.8.2.13: |
| 3345 // Math.pow(-Infinity, 0.5) == Infinity | 3345 // Math.pow(-Infinity, 0.5) == Infinity |
| 3346 // Math.sqrt(-Infinity) == NaN | 3346 // Math.sqrt(-Infinity) == NaN |
| 3347 Label done; | 3347 Label done; |
| 3348 __ Move(temp, -V8_INFINITY); | 3348 __ Move(temp, -V8_INFINITY); |
| 3349 __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input); | 3349 __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input); |
| 3350 // Set up Infinity in the delay slot. | 3350 // Set up Infinity in the delay slot. |
| 3351 // result is overwritten if the branch is not taken. | 3351 // result is overwritten if the branch is not taken. |
| 3352 __ neg_d(result, temp); | 3352 __ neg_d(result, temp); |
| 3353 | 3353 |
| 3354 // Add +0 to convert -0 to +0. | 3354 // Add +0 to convert -0 to +0. |
| 3355 __ add_d(result, input, kDoubleRegZero); | 3355 __ add_d(result, input, kDoubleRegZero); |
| 3356 __ sqrt_d(result, result); | 3356 __ sqrt_d(result, result); |
| 3357 __ bind(&done); | 3357 __ bind(&done); |
| 3358 } | 3358 } |
| 3359 | 3359 |
| 3360 | 3360 |
| 3361 void LCodeGen::DoPower(LPower* instr) { | 3361 void LCodeGen::DoPower(LPower* instr) { |
| 3362 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3362 Representation exponent_type = instr->hydrogen()->right()->representation(); |
| 3363 // Having marked this as a call, we can use any registers. | 3363 // Having marked this as a call, we can use any registers. |
| 3364 // Just make sure that the input/output registers are the expected ones. | 3364 // Just make sure that the input/output registers are the expected ones. |
| 3365 ASSERT(!instr->InputAt(1)->IsDoubleRegister() || | 3365 ASSERT(!instr->InputAt(1)->IsDoubleRegister() || |
| 3366 ToDoubleRegister(instr->InputAt(1)).is(f4)); | 3366 ToDoubleRegister(instr->right()).is(f4)); |
| 3367 ASSERT(!instr->InputAt(1)->IsRegister() || | 3367 ASSERT(!instr->InputAt(1)->IsRegister() || |
| 3368 ToRegister(instr->InputAt(1)).is(a2)); | 3368 ToRegister(instr->right()).is(a2)); |
| 3369 ASSERT(ToDoubleRegister(instr->InputAt(0)).is(f2)); | 3369 ASSERT(ToDoubleRegister(instr->left()).is(f2)); |
| 3370 ASSERT(ToDoubleRegister(instr->result()).is(f0)); | 3370 ASSERT(ToDoubleRegister(instr->result()).is(f0)); |
| 3371 | 3371 |
| 3372 if (exponent_type.IsTagged()) { | 3372 if (exponent_type.IsTagged()) { |
| 3373 Label no_deopt; | 3373 Label no_deopt; |
| 3374 __ JumpIfSmi(a2, &no_deopt); | 3374 __ JumpIfSmi(a2, &no_deopt); |
| 3375 __ lw(t3, FieldMemOperand(a2, HeapObject::kMapOffset)); | 3375 __ lw(t3, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 3376 DeoptimizeIf(ne, instr->environment(), t3, Operand(at)); | 3376 DeoptimizeIf(ne, instr->environment(), t3, Operand(at)); |
| 3377 __ bind(&no_deopt); | 3377 __ bind(&no_deopt); |
| 3378 MathPowStub stub(MathPowStub::TAGGED); | 3378 MathPowStub stub(MathPowStub::TAGGED); |
| 3379 __ CallStub(&stub); | 3379 __ CallStub(&stub); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3396 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } | 3396 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } |
| 3397 virtual LInstruction* instr() { return instr_; } | 3397 virtual LInstruction* instr() { return instr_; } |
| 3398 private: | 3398 private: |
| 3399 LRandom* instr_; | 3399 LRandom* instr_; |
| 3400 }; | 3400 }; |
| 3401 | 3401 |
| 3402 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); | 3402 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); |
| 3403 // Having marked this instruction as a call we can use any | 3403 // Having marked this instruction as a call we can use any |
| 3404 // registers. | 3404 // registers. |
| 3405 ASSERT(ToDoubleRegister(instr->result()).is(f0)); | 3405 ASSERT(ToDoubleRegister(instr->result()).is(f0)); |
| 3406 ASSERT(ToRegister(instr->InputAt(0)).is(a0)); | 3406 ASSERT(ToRegister(instr->global_object()).is(a0)); |
| 3407 | 3407 |
| 3408 static const int kSeedSize = sizeof(uint32_t); | 3408 static const int kSeedSize = sizeof(uint32_t); |
| 3409 STATIC_ASSERT(kPointerSize == kSeedSize); | 3409 STATIC_ASSERT(kPointerSize == kSeedSize); |
| 3410 | 3410 |
| 3411 __ lw(a0, FieldMemOperand(a0, GlobalObject::kNativeContextOffset)); | 3411 __ lw(a0, FieldMemOperand(a0, GlobalObject::kNativeContextOffset)); |
| 3412 static const int kRandomSeedOffset = | 3412 static const int kRandomSeedOffset = |
| 3413 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; | 3413 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; |
| 3414 __ lw(a2, FieldMemOperand(a0, kRandomSeedOffset)); | 3414 __ lw(a2, FieldMemOperand(a0, kRandomSeedOffset)); |
| 3415 // a2: FixedArray of the native context's random seeds | 3415 // a2: FixedArray of the native context's random seeds |
| 3416 | 3416 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3606 ASSERT(ToRegister(instr->result()).is(v0)); | 3606 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3607 CallKnownFunction(instr->target(), | 3607 CallKnownFunction(instr->target(), |
| 3608 instr->arity(), | 3608 instr->arity(), |
| 3609 instr, | 3609 instr, |
| 3610 CALL_AS_FUNCTION, | 3610 CALL_AS_FUNCTION, |
| 3611 A1_UNINITIALIZED); | 3611 A1_UNINITIALIZED); |
| 3612 } | 3612 } |
| 3613 | 3613 |
| 3614 | 3614 |
| 3615 void LCodeGen::DoCallNew(LCallNew* instr) { | 3615 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3616 ASSERT(ToRegister(instr->InputAt(0)).is(a1)); | 3616 ASSERT(ToRegister(instr->constructor()).is(a1)); |
| 3617 ASSERT(ToRegister(instr->result()).is(v0)); | 3617 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3618 | 3618 |
| 3619 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3619 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 3620 __ li(a0, Operand(instr->arity())); | 3620 __ li(a0, Operand(instr->arity())); |
| 3621 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 3621 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
| 3622 } | 3622 } |
| 3623 | 3623 |
| 3624 | 3624 |
| 3625 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3625 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 3626 CallRuntime(instr->function(), instr->arity(), instr); | 3626 CallRuntime(instr->function(), instr->arity(), instr); |
| 3627 } | 3627 } |
| 3628 | 3628 |
| 3629 | 3629 |
| 3630 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3630 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| 3631 Register object = ToRegister(instr->object()); | 3631 Register object = ToRegister(instr->object()); |
| 3632 Register value = ToRegister(instr->value()); | 3632 Register value = ToRegister(instr->value()); |
| 3633 Register scratch = scratch0(); | 3633 Register scratch = scratch0(); |
| 3634 int offset = instr->offset(); | 3634 int offset = instr->offset(); |
| 3635 | 3635 |
| 3636 ASSERT(!object.is(value)); | 3636 ASSERT(!object.is(value)); |
| 3637 | 3637 |
| 3638 if (!instr->transition().is_null()) { | 3638 if (!instr->transition().is_null()) { |
| 3639 __ li(scratch, Operand(instr->transition())); | 3639 __ li(scratch, Operand(instr->transition())); |
| 3640 __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3640 __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 3641 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3641 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 3642 Register temp = ToRegister(instr->TempAt(0)); | 3642 Register temp = ToRegister(instr->temp()); |
| 3643 // Update the write barrier for the map field. | 3643 // Update the write barrier for the map field. |
| 3644 __ RecordWriteField(object, | 3644 __ RecordWriteField(object, |
| 3645 HeapObject::kMapOffset, | 3645 HeapObject::kMapOffset, |
| 3646 scratch, | 3646 scratch, |
| 3647 temp, | 3647 temp, |
| 3648 kRAHasBeenSaved, | 3648 kRAHasBeenSaved, |
| 3649 kSaveFPRegs, | 3649 kSaveFPRegs, |
| 3650 OMIT_REMEMBERED_SET, | 3650 OMIT_REMEMBERED_SET, |
| 3651 OMIT_SMI_CHECK); | 3651 OMIT_SMI_CHECK); |
| 3652 } | 3652 } |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3924 | 3924 |
| 3925 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3925 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 3926 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3926 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 3927 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3927 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 3928 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3928 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3929 } | 3929 } |
| 3930 | 3930 |
| 3931 | 3931 |
| 3932 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 3932 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
| 3933 Register object_reg = ToRegister(instr->object()); | 3933 Register object_reg = ToRegister(instr->object()); |
| 3934 Register new_map_reg = ToRegister(instr->new_map_reg()); | 3934 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 3935 Register scratch = scratch0(); | 3935 Register scratch = scratch0(); |
| 3936 | 3936 |
| 3937 Handle<Map> from_map = instr->original_map(); | 3937 Handle<Map> from_map = instr->original_map(); |
| 3938 Handle<Map> to_map = instr->transitioned_map(); | 3938 Handle<Map> to_map = instr->transitioned_map(); |
| 3939 ElementsKind from_kind = from_map->elements_kind(); | 3939 ElementsKind from_kind = from_map->elements_kind(); |
| 3940 ElementsKind to_kind = to_map->elements_kind(); | 3940 ElementsKind to_kind = to_map->elements_kind(); |
| 3941 | 3941 |
| 3942 __ mov(ToRegister(instr->result()), object_reg); | 3942 __ mov(ToRegister(instr->result()), object_reg); |
| 3943 | 3943 |
| 3944 Label not_applicable; | 3944 Label not_applicable; |
| 3945 __ lw(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 3945 __ lw(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 3946 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); | 3946 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); |
| 3947 | 3947 |
| 3948 __ li(new_map_reg, Operand(to_map)); | 3948 __ li(new_map_reg, Operand(to_map)); |
| 3949 if (IsFastSmiElementsKind(from_kind) && IsFastObjectElementsKind(to_kind)) { | 3949 if (IsFastSmiElementsKind(from_kind) && IsFastObjectElementsKind(to_kind)) { |
| 3950 __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 3950 __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 3951 // Write barrier. | 3951 // Write barrier. |
| 3952 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 3952 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
| 3953 scratch, kRAHasBeenSaved, kDontSaveFPRegs); | 3953 scratch, kRAHasBeenSaved, kDontSaveFPRegs); |
| 3954 } else if (IsFastSmiElementsKind(from_kind) && | 3954 } else if (IsFastSmiElementsKind(from_kind) && |
| 3955 IsFastDoubleElementsKind(to_kind)) { | 3955 IsFastDoubleElementsKind(to_kind)) { |
| 3956 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3956 Register fixed_object_reg = ToRegister(instr->temp()); |
| 3957 ASSERT(fixed_object_reg.is(a2)); | 3957 ASSERT(fixed_object_reg.is(a2)); |
| 3958 ASSERT(new_map_reg.is(a3)); | 3958 ASSERT(new_map_reg.is(a3)); |
| 3959 __ mov(fixed_object_reg, object_reg); | 3959 __ mov(fixed_object_reg, object_reg); |
| 3960 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3960 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
| 3961 RelocInfo::CODE_TARGET, instr); | 3961 RelocInfo::CODE_TARGET, instr); |
| 3962 } else if (IsFastDoubleElementsKind(from_kind) && | 3962 } else if (IsFastDoubleElementsKind(from_kind) && |
| 3963 IsFastObjectElementsKind(to_kind)) { | 3963 IsFastObjectElementsKind(to_kind)) { |
| 3964 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3964 Register fixed_object_reg = ToRegister(instr->temp()); |
| 3965 ASSERT(fixed_object_reg.is(a2)); | 3965 ASSERT(fixed_object_reg.is(a2)); |
| 3966 ASSERT(new_map_reg.is(a3)); | 3966 ASSERT(new_map_reg.is(a3)); |
| 3967 __ mov(fixed_object_reg, object_reg); | 3967 __ mov(fixed_object_reg, object_reg); |
| 3968 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3968 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
| 3969 RelocInfo::CODE_TARGET, instr); | 3969 RelocInfo::CODE_TARGET, instr); |
| 3970 } else { | 3970 } else { |
| 3971 UNREACHABLE(); | 3971 UNREACHABLE(); |
| 3972 } | 3972 } |
| 3973 __ bind(¬_applicable); | 3973 __ bind(¬_applicable); |
| 3974 } | 3974 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4079 | 4079 |
| 4080 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4080 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 4081 __ SmiTag(char_code); | 4081 __ SmiTag(char_code); |
| 4082 __ push(char_code); | 4082 __ push(char_code); |
| 4083 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 4083 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); |
| 4084 __ StoreToSafepointRegisterSlot(v0, result); | 4084 __ StoreToSafepointRegisterSlot(v0, result); |
| 4085 } | 4085 } |
| 4086 | 4086 |
| 4087 | 4087 |
| 4088 void LCodeGen::DoStringLength(LStringLength* instr) { | 4088 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 4089 Register string = ToRegister(instr->InputAt(0)); | 4089 Register string = ToRegister(instr->string()); |
| 4090 Register result = ToRegister(instr->result()); | 4090 Register result = ToRegister(instr->result()); |
| 4091 __ lw(result, FieldMemOperand(string, String::kLengthOffset)); | 4091 __ lw(result, FieldMemOperand(string, String::kLengthOffset)); |
| 4092 } | 4092 } |
| 4093 | 4093 |
| 4094 | 4094 |
| 4095 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4095 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 4096 LOperand* input = instr->InputAt(0); | 4096 LOperand* input = instr->value(); |
| 4097 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4097 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 4098 LOperand* output = instr->result(); | 4098 LOperand* output = instr->result(); |
| 4099 ASSERT(output->IsDoubleRegister()); | 4099 ASSERT(output->IsDoubleRegister()); |
| 4100 FPURegister single_scratch = double_scratch0().low(); | 4100 FPURegister single_scratch = double_scratch0().low(); |
| 4101 if (input->IsStackSlot()) { | 4101 if (input->IsStackSlot()) { |
| 4102 Register scratch = scratch0(); | 4102 Register scratch = scratch0(); |
| 4103 __ lw(scratch, ToMemOperand(input)); | 4103 __ lw(scratch, ToMemOperand(input)); |
| 4104 __ mtc1(scratch, single_scratch); | 4104 __ mtc1(scratch, single_scratch); |
| 4105 } else { | 4105 } else { |
| 4106 __ mtc1(ToRegister(input), single_scratch); | 4106 __ mtc1(ToRegister(input), single_scratch); |
| 4107 } | 4107 } |
| 4108 __ cvt_d_w(ToDoubleRegister(output), single_scratch); | 4108 __ cvt_d_w(ToDoubleRegister(output), single_scratch); |
| 4109 } | 4109 } |
| 4110 | 4110 |
| 4111 | 4111 |
| 4112 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4112 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
| 4113 LOperand* input = instr->InputAt(0); | 4113 LOperand* input = instr->value(); |
| 4114 LOperand* output = instr->result(); | 4114 LOperand* output = instr->result(); |
| 4115 | 4115 |
| 4116 FPURegister dbl_scratch = double_scratch0(); | 4116 FPURegister dbl_scratch = double_scratch0(); |
| 4117 __ mtc1(ToRegister(input), dbl_scratch); | 4117 __ mtc1(ToRegister(input), dbl_scratch); |
| 4118 __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22); | 4118 __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22); |
| 4119 } | 4119 } |
| 4120 | 4120 |
| 4121 | 4121 |
| 4122 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4122 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 4123 class DeferredNumberTagI: public LDeferredCode { | 4123 class DeferredNumberTagI: public LDeferredCode { |
| 4124 public: | 4124 public: |
| 4125 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 4125 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
| 4126 : LDeferredCode(codegen), instr_(instr) { } | 4126 : LDeferredCode(codegen), instr_(instr) { } |
| 4127 virtual void Generate() { | 4127 virtual void Generate() { |
| 4128 codegen()->DoDeferredNumberTagI(instr_, | 4128 codegen()->DoDeferredNumberTagI(instr_, |
| 4129 instr_->InputAt(0), | 4129 instr_->value(), |
| 4130 SIGNED_INT32); | 4130 SIGNED_INT32); |
| 4131 } | 4131 } |
| 4132 virtual LInstruction* instr() { return instr_; } | 4132 virtual LInstruction* instr() { return instr_; } |
| 4133 private: | 4133 private: |
| 4134 LNumberTagI* instr_; | 4134 LNumberTagI* instr_; |
| 4135 }; | 4135 }; |
| 4136 | 4136 |
| 4137 Register src = ToRegister(instr->InputAt(0)); | 4137 Register src = ToRegister(instr->value()); |
| 4138 Register dst = ToRegister(instr->result()); | 4138 Register dst = ToRegister(instr->result()); |
| 4139 Register overflow = scratch0(); | 4139 Register overflow = scratch0(); |
| 4140 | 4140 |
| 4141 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); | 4141 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
| 4142 __ SmiTagCheckOverflow(dst, src, overflow); | 4142 __ SmiTagCheckOverflow(dst, src, overflow); |
| 4143 __ BranchOnOverflow(deferred->entry(), overflow); | 4143 __ BranchOnOverflow(deferred->entry(), overflow); |
| 4144 __ bind(deferred->exit()); | 4144 __ bind(deferred->exit()); |
| 4145 } | 4145 } |
| 4146 | 4146 |
| 4147 | 4147 |
| 4148 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4148 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
| 4149 class DeferredNumberTagU: public LDeferredCode { | 4149 class DeferredNumberTagU: public LDeferredCode { |
| 4150 public: | 4150 public: |
| 4151 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4151 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
| 4152 : LDeferredCode(codegen), instr_(instr) { } | 4152 : LDeferredCode(codegen), instr_(instr) { } |
| 4153 virtual void Generate() { | 4153 virtual void Generate() { |
| 4154 codegen()->DoDeferredNumberTagI(instr_, | 4154 codegen()->DoDeferredNumberTagI(instr_, |
| 4155 instr_->InputAt(0), | 4155 instr_->value(), |
| 4156 UNSIGNED_INT32); | 4156 UNSIGNED_INT32); |
| 4157 } | 4157 } |
| 4158 virtual LInstruction* instr() { return instr_; } | 4158 virtual LInstruction* instr() { return instr_; } |
| 4159 private: | 4159 private: |
| 4160 LNumberTagU* instr_; | 4160 LNumberTagU* instr_; |
| 4161 }; | 4161 }; |
| 4162 | 4162 |
| 4163 LOperand* input = instr->InputAt(0); | 4163 LOperand* input = instr->value(); |
| 4164 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4164 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4165 Register reg = ToRegister(input); | 4165 Register reg = ToRegister(input); |
| 4166 | 4166 |
| 4167 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4167 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
| 4168 __ Branch(deferred->entry(), hi, reg, Operand(Smi::kMaxValue)); | 4168 __ Branch(deferred->entry(), hi, reg, Operand(Smi::kMaxValue)); |
| 4169 __ SmiTag(reg, reg); | 4169 __ SmiTag(reg, reg); |
| 4170 __ bind(deferred->exit()); | 4170 __ bind(deferred->exit()); |
| 4171 } | 4171 } |
| 4172 | 4172 |
| 4173 | 4173 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4227 class DeferredNumberTagD: public LDeferredCode { | 4227 class DeferredNumberTagD: public LDeferredCode { |
| 4228 public: | 4228 public: |
| 4229 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4229 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 4230 : LDeferredCode(codegen), instr_(instr) { } | 4230 : LDeferredCode(codegen), instr_(instr) { } |
| 4231 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4231 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 4232 virtual LInstruction* instr() { return instr_; } | 4232 virtual LInstruction* instr() { return instr_; } |
| 4233 private: | 4233 private: |
| 4234 LNumberTagD* instr_; | 4234 LNumberTagD* instr_; |
| 4235 }; | 4235 }; |
| 4236 | 4236 |
| 4237 DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 4237 DoubleRegister input_reg = ToDoubleRegister(instr->value()); |
| 4238 Register scratch = scratch0(); | 4238 Register scratch = scratch0(); |
| 4239 Register reg = ToRegister(instr->result()); | 4239 Register reg = ToRegister(instr->result()); |
| 4240 Register temp1 = ToRegister(instr->TempAt(0)); | 4240 Register temp1 = ToRegister(instr->temp()); |
| 4241 Register temp2 = ToRegister(instr->TempAt(1)); | 4241 Register temp2 = ToRegister(instr->temp2()); |
| 4242 | 4242 |
| 4243 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4243 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 4244 if (FLAG_inline_new) { | 4244 if (FLAG_inline_new) { |
| 4245 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4245 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 4246 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); | 4246 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); |
| 4247 } else { | 4247 } else { |
| 4248 __ Branch(deferred->entry()); | 4248 __ Branch(deferred->entry()); |
| 4249 } | 4249 } |
| 4250 __ bind(deferred->exit()); | 4250 __ bind(deferred->exit()); |
| 4251 __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 4251 __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
| 4252 } | 4252 } |
| 4253 | 4253 |
| 4254 | 4254 |
| 4255 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4255 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4256 // TODO(3095996): Get rid of this. For now, we need to make the | 4256 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4257 // result register contain a valid pointer because it is already | 4257 // result register contain a valid pointer because it is already |
| 4258 // contained in the register pointer map. | 4258 // contained in the register pointer map. |
| 4259 Register reg = ToRegister(instr->result()); | 4259 Register reg = ToRegister(instr->result()); |
| 4260 __ mov(reg, zero_reg); | 4260 __ mov(reg, zero_reg); |
| 4261 | 4261 |
| 4262 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4262 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 4263 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4263 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 4264 __ StoreToSafepointRegisterSlot(v0, reg); | 4264 __ StoreToSafepointRegisterSlot(v0, reg); |
| 4265 } | 4265 } |
| 4266 | 4266 |
| 4267 | 4267 |
| 4268 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4268 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 4269 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4269 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 4270 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->InputAt(0))); | 4270 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value())); |
| 4271 } | 4271 } |
| 4272 | 4272 |
| 4273 | 4273 |
| 4274 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4274 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 4275 Register scratch = scratch0(); | 4275 Register scratch = scratch0(); |
| 4276 Register input = ToRegister(instr->InputAt(0)); | 4276 Register input = ToRegister(instr->value()); |
| 4277 Register result = ToRegister(instr->result()); | 4277 Register result = ToRegister(instr->result()); |
| 4278 if (instr->needs_check()) { | 4278 if (instr->needs_check()) { |
| 4279 STATIC_ASSERT(kHeapObjectTag == 1); | 4279 STATIC_ASSERT(kHeapObjectTag == 1); |
| 4280 // If the input is a HeapObject, value of scratch won't be zero. | 4280 // If the input is a HeapObject, value of scratch won't be zero. |
| 4281 __ And(scratch, input, Operand(kHeapObjectTag)); | 4281 __ And(scratch, input, Operand(kHeapObjectTag)); |
| 4282 __ SmiUntag(result, input); | 4282 __ SmiUntag(result, input); |
| 4283 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 4283 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); |
| 4284 } else { | 4284 } else { |
| 4285 __ SmiUntag(result, input); | 4285 __ SmiUntag(result, input); |
| 4286 } | 4286 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4331 // Smi to double register conversion | 4331 // Smi to double register conversion |
| 4332 __ bind(&load_smi); | 4332 __ bind(&load_smi); |
| 4333 // scratch: untagged value of input_reg | 4333 // scratch: untagged value of input_reg |
| 4334 __ mtc1(scratch, result_reg); | 4334 __ mtc1(scratch, result_reg); |
| 4335 __ cvt_d_w(result_reg, result_reg); | 4335 __ cvt_d_w(result_reg, result_reg); |
| 4336 __ bind(&done); | 4336 __ bind(&done); |
| 4337 } | 4337 } |
| 4338 | 4338 |
| 4339 | 4339 |
| 4340 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 4340 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 4341 Register input_reg = ToRegister(instr->InputAt(0)); | 4341 Register input_reg = ToRegister(instr->value()); |
| 4342 Register scratch1 = scratch0(); | 4342 Register scratch1 = scratch0(); |
| 4343 Register scratch2 = ToRegister(instr->TempAt(0)); | 4343 Register scratch2 = ToRegister(instr->temp()); |
| 4344 DoubleRegister double_scratch = double_scratch0(); | 4344 DoubleRegister double_scratch = double_scratch0(); |
| 4345 FPURegister single_scratch = double_scratch.low(); | 4345 FPURegister single_scratch = double_scratch.low(); |
| 4346 | 4346 |
| 4347 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); | 4347 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); |
| 4348 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); | 4348 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); |
| 4349 | 4349 |
| 4350 Label done; | 4350 Label done; |
| 4351 | 4351 |
| 4352 // The input is a tagged HeapObject. | 4352 // The input is a tagged HeapObject. |
| 4353 // Heap number map check. | 4353 // Heap number map check. |
| 4354 __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4354 __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4355 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4355 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 4356 // This 'at' value and scratch1 map value are used for tests in both clauses | 4356 // This 'at' value and scratch1 map value are used for tests in both clauses |
| 4357 // of the if. | 4357 // of the if. |
| 4358 | 4358 |
| 4359 if (instr->truncating()) { | 4359 if (instr->truncating()) { |
| 4360 Register scratch3 = ToRegister(instr->TempAt(1)); | 4360 Register scratch3 = ToRegister(instr->temp2()); |
| 4361 DoubleRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2)); | 4361 DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp3()); |
| 4362 ASSERT(!scratch3.is(input_reg) && | 4362 ASSERT(!scratch3.is(input_reg) && |
| 4363 !scratch3.is(scratch1) && | 4363 !scratch3.is(scratch1) && |
| 4364 !scratch3.is(scratch2)); | 4364 !scratch3.is(scratch2)); |
| 4365 // Performs a truncating conversion of a floating point number as used by | 4365 // Performs a truncating conversion of a floating point number as used by |
| 4366 // the JS bitwise operations. | 4366 // the JS bitwise operations. |
| 4367 Label heap_number; | 4367 Label heap_number; |
| 4368 __ Branch(&heap_number, eq, scratch1, Operand(at)); // HeapNumber map? | 4368 __ Branch(&heap_number, eq, scratch1, Operand(at)); // HeapNumber map? |
| 4369 // Check for undefined. Undefined is converted to zero for truncating | 4369 // Check for undefined. Undefined is converted to zero for truncating |
| 4370 // conversions. | 4370 // conversions. |
| 4371 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 4371 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4421 class DeferredTaggedToI: public LDeferredCode { | 4421 class DeferredTaggedToI: public LDeferredCode { |
| 4422 public: | 4422 public: |
| 4423 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4423 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 4424 : LDeferredCode(codegen), instr_(instr) { } | 4424 : LDeferredCode(codegen), instr_(instr) { } |
| 4425 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 4425 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 4426 virtual LInstruction* instr() { return instr_; } | 4426 virtual LInstruction* instr() { return instr_; } |
| 4427 private: | 4427 private: |
| 4428 LTaggedToI* instr_; | 4428 LTaggedToI* instr_; |
| 4429 }; | 4429 }; |
| 4430 | 4430 |
| 4431 LOperand* input = instr->InputAt(0); | 4431 LOperand* input = instr->value(); |
| 4432 ASSERT(input->IsRegister()); | 4432 ASSERT(input->IsRegister()); |
| 4433 ASSERT(input->Equals(instr->result())); | 4433 ASSERT(input->Equals(instr->result())); |
| 4434 | 4434 |
| 4435 Register input_reg = ToRegister(input); | 4435 Register input_reg = ToRegister(input); |
| 4436 | 4436 |
| 4437 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 4437 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
| 4438 | 4438 |
| 4439 // Let the deferred code handle the HeapObject case. | 4439 // Let the deferred code handle the HeapObject case. |
| 4440 __ JumpIfNotSmi(input_reg, deferred->entry()); | 4440 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| 4441 | 4441 |
| 4442 // Smi to int32 conversion. | 4442 // Smi to int32 conversion. |
| 4443 __ SmiUntag(input_reg); | 4443 __ SmiUntag(input_reg); |
| 4444 __ bind(deferred->exit()); | 4444 __ bind(deferred->exit()); |
| 4445 } | 4445 } |
| 4446 | 4446 |
| 4447 | 4447 |
| 4448 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4448 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 4449 LOperand* input = instr->InputAt(0); | 4449 LOperand* input = instr->value(); |
| 4450 ASSERT(input->IsRegister()); | 4450 ASSERT(input->IsRegister()); |
| 4451 LOperand* result = instr->result(); | 4451 LOperand* result = instr->result(); |
| 4452 ASSERT(result->IsDoubleRegister()); | 4452 ASSERT(result->IsDoubleRegister()); |
| 4453 | 4453 |
| 4454 Register input_reg = ToRegister(input); | 4454 Register input_reg = ToRegister(input); |
| 4455 DoubleRegister result_reg = ToDoubleRegister(result); | 4455 DoubleRegister result_reg = ToDoubleRegister(result); |
| 4456 | 4456 |
| 4457 EmitNumberUntagD(input_reg, result_reg, | 4457 EmitNumberUntagD(input_reg, result_reg, |
| 4458 instr->hydrogen()->deoptimize_on_undefined(), | 4458 instr->hydrogen()->deoptimize_on_undefined(), |
| 4459 instr->hydrogen()->deoptimize_on_minus_zero(), | 4459 instr->hydrogen()->deoptimize_on_minus_zero(), |
| 4460 instr->environment()); | 4460 instr->environment()); |
| 4461 } | 4461 } |
| 4462 | 4462 |
| 4463 | 4463 |
| 4464 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4464 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 4465 Register result_reg = ToRegister(instr->result()); | 4465 Register result_reg = ToRegister(instr->result()); |
| 4466 Register scratch1 = scratch0(); | 4466 Register scratch1 = scratch0(); |
| 4467 Register scratch2 = ToRegister(instr->TempAt(0)); | 4467 Register scratch2 = ToRegister(instr->temp()); |
| 4468 DoubleRegister double_input = ToDoubleRegister(instr->InputAt(0)); | 4468 DoubleRegister double_input = ToDoubleRegister(instr->value()); |
| 4469 FPURegister single_scratch = double_scratch0().low(); | 4469 FPURegister single_scratch = double_scratch0().low(); |
| 4470 | 4470 |
| 4471 if (instr->truncating()) { | 4471 if (instr->truncating()) { |
| 4472 Register scratch3 = ToRegister(instr->TempAt(1)); | 4472 Register scratch3 = ToRegister(instr->temp2()); |
| 4473 __ EmitECMATruncate(result_reg, | 4473 __ EmitECMATruncate(result_reg, |
| 4474 double_input, | 4474 double_input, |
| 4475 single_scratch, | 4475 single_scratch, |
| 4476 scratch1, | 4476 scratch1, |
| 4477 scratch2, | 4477 scratch2, |
| 4478 scratch3); | 4478 scratch3); |
| 4479 } else { | 4479 } else { |
| 4480 Register except_flag = scratch2; | 4480 Register except_flag = scratch2; |
| 4481 | 4481 |
| 4482 __ EmitFPUTruncate(kRoundToMinusInf, | 4482 __ EmitFPUTruncate(kRoundToMinusInf, |
| 4483 single_scratch, | 4483 single_scratch, |
| 4484 double_input, | 4484 double_input, |
| 4485 scratch1, | 4485 scratch1, |
| 4486 except_flag, | 4486 except_flag, |
| 4487 kCheckForInexactConversion); | 4487 kCheckForInexactConversion); |
| 4488 | 4488 |
| 4489 // Deopt if the operation did not succeed (except_flag != 0). | 4489 // Deopt if the operation did not succeed (except_flag != 0). |
| 4490 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 4490 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); |
| 4491 | 4491 |
| 4492 // Load the result. | 4492 // Load the result. |
| 4493 __ mfc1(result_reg, single_scratch); | 4493 __ mfc1(result_reg, single_scratch); |
| 4494 } | 4494 } |
| 4495 } | 4495 } |
| 4496 | 4496 |
| 4497 | 4497 |
| 4498 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4498 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 4499 LOperand* input = instr->InputAt(0); | 4499 LOperand* input = instr->value(); |
| 4500 __ And(at, ToRegister(input), Operand(kSmiTagMask)); | 4500 __ And(at, ToRegister(input), Operand(kSmiTagMask)); |
| 4501 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 4501 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); |
| 4502 } | 4502 } |
| 4503 | 4503 |
| 4504 | 4504 |
| 4505 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4505 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
| 4506 LOperand* input = instr->InputAt(0); | 4506 LOperand* input = instr->value(); |
| 4507 __ And(at, ToRegister(input), Operand(kSmiTagMask)); | 4507 __ And(at, ToRegister(input), Operand(kSmiTagMask)); |
| 4508 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 4508 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); |
| 4509 } | 4509 } |
| 4510 | 4510 |
| 4511 | 4511 |
| 4512 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4512 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 4513 Register input = ToRegister(instr->InputAt(0)); | 4513 Register input = ToRegister(instr->value()); |
| 4514 Register scratch = scratch0(); | 4514 Register scratch = scratch0(); |
| 4515 | 4515 |
| 4516 __ GetObjectType(input, scratch, scratch); | 4516 __ GetObjectType(input, scratch, scratch); |
| 4517 | 4517 |
| 4518 if (instr->hydrogen()->is_interval_check()) { | 4518 if (instr->hydrogen()->is_interval_check()) { |
| 4519 InstanceType first; | 4519 InstanceType first; |
| 4520 InstanceType last; | 4520 InstanceType last; |
| 4521 instr->hydrogen()->GetCheckInterval(&first, &last); | 4521 instr->hydrogen()->GetCheckInterval(&first, &last); |
| 4522 | 4522 |
| 4523 // If there is only one type in the interval check for equality. | 4523 // If there is only one type in the interval check for equality. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4573 LEnvironment* env) { | 4573 LEnvironment* env) { |
| 4574 Label success; | 4574 Label success; |
| 4575 __ CompareMapAndBranch(reg, scratch, map, &success, eq, &success, mode); | 4575 __ CompareMapAndBranch(reg, scratch, map, &success, eq, &success, mode); |
| 4576 DeoptimizeIf(al, env); | 4576 DeoptimizeIf(al, env); |
| 4577 __ bind(&success); | 4577 __ bind(&success); |
| 4578 } | 4578 } |
| 4579 | 4579 |
| 4580 | 4580 |
| 4581 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4581 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 4582 Register scratch = scratch0(); | 4582 Register scratch = scratch0(); |
| 4583 LOperand* input = instr->InputAt(0); | 4583 LOperand* input = instr->value(); |
| 4584 ASSERT(input->IsRegister()); | 4584 ASSERT(input->IsRegister()); |
| 4585 Register reg = ToRegister(input); | 4585 Register reg = ToRegister(input); |
| 4586 Label success; | 4586 Label success; |
| 4587 SmallMapList* map_set = instr->hydrogen()->map_set(); | 4587 SmallMapList* map_set = instr->hydrogen()->map_set(); |
| 4588 for (int i = 0; i < map_set->length() - 1; i++) { | 4588 for (int i = 0; i < map_set->length() - 1; i++) { |
| 4589 Handle<Map> map = map_set->at(i); | 4589 Handle<Map> map = map_set->at(i); |
| 4590 __ CompareMapAndBranch( | 4590 __ CompareMapAndBranch( |
| 4591 reg, scratch, map, &success, eq, &success, REQUIRE_EXACT_MAP); | 4591 reg, scratch, map, &success, eq, &success, REQUIRE_EXACT_MAP); |
| 4592 } | 4592 } |
| 4593 Handle<Map> map = map_set->last(); | 4593 Handle<Map> map = map_set->last(); |
| 4594 DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment()); | 4594 DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment()); |
| 4595 __ bind(&success); | 4595 __ bind(&success); |
| 4596 } | 4596 } |
| 4597 | 4597 |
| 4598 | 4598 |
| 4599 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 4599 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 4600 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); | 4600 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 4601 Register result_reg = ToRegister(instr->result()); | 4601 Register result_reg = ToRegister(instr->result()); |
| 4602 DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0)); | 4602 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
| 4603 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); | 4603 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); |
| 4604 } | 4604 } |
| 4605 | 4605 |
| 4606 | 4606 |
| 4607 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 4607 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
| 4608 Register unclamped_reg = ToRegister(instr->unclamped()); | 4608 Register unclamped_reg = ToRegister(instr->unclamped()); |
| 4609 Register result_reg = ToRegister(instr->result()); | 4609 Register result_reg = ToRegister(instr->result()); |
| 4610 __ ClampUint8(result_reg, unclamped_reg); | 4610 __ ClampUint8(result_reg, unclamped_reg); |
| 4611 } | 4611 } |
| 4612 | 4612 |
| 4613 | 4613 |
| 4614 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 4614 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
| 4615 Register scratch = scratch0(); | 4615 Register scratch = scratch0(); |
| 4616 Register input_reg = ToRegister(instr->unclamped()); | 4616 Register input_reg = ToRegister(instr->unclamped()); |
| 4617 Register result_reg = ToRegister(instr->result()); | 4617 Register result_reg = ToRegister(instr->result()); |
| 4618 DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0)); | 4618 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
| 4619 Label is_smi, done, heap_number; | 4619 Label is_smi, done, heap_number; |
| 4620 | 4620 |
| 4621 // Both smi and heap number cases are handled. | 4621 // Both smi and heap number cases are handled. |
| 4622 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); | 4622 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); |
| 4623 | 4623 |
| 4624 // Check for heap number | 4624 // Check for heap number |
| 4625 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4625 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4626 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); | 4626 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); |
| 4627 | 4627 |
| 4628 // Check for undefined. Undefined is converted to zero for clamping | 4628 // Check for undefined. Undefined is converted to zero for clamping |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4640 __ jmp(&done); | 4640 __ jmp(&done); |
| 4641 | 4641 |
| 4642 __ bind(&is_smi); | 4642 __ bind(&is_smi); |
| 4643 __ ClampUint8(result_reg, scratch); | 4643 __ ClampUint8(result_reg, scratch); |
| 4644 | 4644 |
| 4645 __ bind(&done); | 4645 __ bind(&done); |
| 4646 } | 4646 } |
| 4647 | 4647 |
| 4648 | 4648 |
| 4649 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 4649 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 4650 Register temp1 = ToRegister(instr->TempAt(0)); | 4650 Register temp1 = ToRegister(instr->temp()); |
| 4651 Register temp2 = ToRegister(instr->TempAt(1)); | 4651 Register temp2 = ToRegister(instr->temp2()); |
| 4652 | 4652 |
| 4653 Handle<JSObject> holder = instr->holder(); | 4653 Handle<JSObject> holder = instr->holder(); |
| 4654 Handle<JSObject> current_prototype = instr->prototype(); | 4654 Handle<JSObject> current_prototype = instr->prototype(); |
| 4655 | 4655 |
| 4656 // Load prototype object. | 4656 // Load prototype object. |
| 4657 __ LoadHeapObject(temp1, current_prototype); | 4657 __ LoadHeapObject(temp1, current_prototype); |
| 4658 | 4658 |
| 4659 // Check prototype maps up to the holder. | 4659 // Check prototype maps up to the holder. |
| 4660 while (!current_prototype.is_identical_to(holder)) { | 4660 while (!current_prototype.is_identical_to(holder)) { |
| 4661 DoCheckMapCommon(temp1, temp2, | 4661 DoCheckMapCommon(temp1, temp2, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4682 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } | 4682 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } |
| 4683 virtual LInstruction* instr() { return instr_; } | 4683 virtual LInstruction* instr() { return instr_; } |
| 4684 private: | 4684 private: |
| 4685 LAllocateObject* instr_; | 4685 LAllocateObject* instr_; |
| 4686 }; | 4686 }; |
| 4687 | 4687 |
| 4688 DeferredAllocateObject* deferred = | 4688 DeferredAllocateObject* deferred = |
| 4689 new(zone()) DeferredAllocateObject(this, instr); | 4689 new(zone()) DeferredAllocateObject(this, instr); |
| 4690 | 4690 |
| 4691 Register result = ToRegister(instr->result()); | 4691 Register result = ToRegister(instr->result()); |
| 4692 Register scratch = ToRegister(instr->TempAt(0)); | 4692 Register scratch = ToRegister(instr->temp()); |
| 4693 Register scratch2 = ToRegister(instr->TempAt(1)); | 4693 Register scratch2 = ToRegister(instr->temp2()); |
| 4694 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); | 4694 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); |
| 4695 Handle<Map> initial_map(constructor->initial_map()); | 4695 Handle<Map> initial_map(constructor->initial_map()); |
| 4696 int instance_size = initial_map->instance_size(); | 4696 int instance_size = initial_map->instance_size(); |
| 4697 ASSERT(initial_map->pre_allocated_property_fields() + | 4697 ASSERT(initial_map->pre_allocated_property_fields() + |
| 4698 initial_map->unused_property_fields() - | 4698 initial_map->unused_property_fields() - |
| 4699 initial_map->inobject_properties() == 0); | 4699 initial_map->inobject_properties() == 0); |
| 4700 | 4700 |
| 4701 // Allocate memory for the object. The initial map might change when | 4701 // Allocate memory for the object. The initial map might change when |
| 4702 // the constructor's prototype changes, but instance size and property | 4702 // the constructor's prototype changes, but instance size and property |
| 4703 // counts remain unchanged (if slack tracking finished). | 4703 // counts remain unchanged (if slack tracking finished). |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4979 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 4979 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
| 4980 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); | 4980 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); |
| 4981 } else { | 4981 } else { |
| 4982 FastCloneShallowObjectStub stub(properties_count); | 4982 FastCloneShallowObjectStub stub(properties_count); |
| 4983 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4983 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 4984 } | 4984 } |
| 4985 } | 4985 } |
| 4986 | 4986 |
| 4987 | 4987 |
| 4988 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 4988 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 4989 ASSERT(ToRegister(instr->InputAt(0)).is(a0)); | 4989 ASSERT(ToRegister(instr->value()).is(a0)); |
| 4990 ASSERT(ToRegister(instr->result()).is(v0)); | 4990 ASSERT(ToRegister(instr->result()).is(v0)); |
| 4991 __ push(a0); | 4991 __ push(a0); |
| 4992 CallRuntime(Runtime::kToFastProperties, 1, instr); | 4992 CallRuntime(Runtime::kToFastProperties, 1, instr); |
| 4993 } | 4993 } |
| 4994 | 4994 |
| 4995 | 4995 |
| 4996 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 4996 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 4997 Label materialized; | 4997 Label materialized; |
| 4998 // Registers will be used as follows: | 4998 // Registers will be used as follows: |
| 4999 // t3 = literals array. | 4999 // t3 = literals array. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5061 ? factory()->true_value() | 5061 ? factory()->true_value() |
| 5062 : factory()->false_value())); | 5062 : factory()->false_value())); |
| 5063 __ Push(cp, a2, a1); | 5063 __ Push(cp, a2, a1); |
| 5064 CallRuntime(Runtime::kNewClosure, 3, instr); | 5064 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 5065 } | 5065 } |
| 5066 } | 5066 } |
| 5067 | 5067 |
| 5068 | 5068 |
| 5069 void LCodeGen::DoTypeof(LTypeof* instr) { | 5069 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 5070 ASSERT(ToRegister(instr->result()).is(v0)); | 5070 ASSERT(ToRegister(instr->result()).is(v0)); |
| 5071 Register input = ToRegister(instr->InputAt(0)); | 5071 Register input = ToRegister(instr->value()); |
| 5072 __ push(input); | 5072 __ push(input); |
| 5073 CallRuntime(Runtime::kTypeof, 1, instr); | 5073 CallRuntime(Runtime::kTypeof, 1, instr); |
| 5074 } | 5074 } |
| 5075 | 5075 |
| 5076 | 5076 |
| 5077 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5077 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 5078 Register input = ToRegister(instr->InputAt(0)); | 5078 Register input = ToRegister(instr->value()); |
| 5079 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5079 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 5080 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5080 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 5081 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 5081 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 5082 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 5082 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 5083 | 5083 |
| 5084 Register cmp1 = no_reg; | 5084 Register cmp1 = no_reg; |
| 5085 Operand cmp2 = Operand(no_reg); | 5085 Operand cmp2 = Operand(no_reg); |
| 5086 | 5086 |
| 5087 Condition final_branch_condition = EmitTypeofIs(true_label, | 5087 Condition final_branch_condition = EmitTypeofIs(true_label, |
| 5088 false_label, | 5088 false_label, |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5195 cmp1 = at; | 5195 cmp1 = at; |
| 5196 cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion. | 5196 cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion. |
| 5197 __ Branch(false_label); | 5197 __ Branch(false_label); |
| 5198 } | 5198 } |
| 5199 | 5199 |
| 5200 return final_branch_condition; | 5200 return final_branch_condition; |
| 5201 } | 5201 } |
| 5202 | 5202 |
| 5203 | 5203 |
| 5204 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5204 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 5205 Register temp1 = ToRegister(instr->TempAt(0)); | 5205 Register temp1 = ToRegister(instr->temp()); |
| 5206 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5206 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 5207 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5207 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 5208 | 5208 |
| 5209 EmitIsConstructCall(temp1, scratch0()); | 5209 EmitIsConstructCall(temp1, scratch0()); |
| 5210 | 5210 |
| 5211 EmitBranch(true_block, false_block, eq, temp1, | 5211 EmitBranch(true_block, false_block, eq, temp1, |
| 5212 Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 5212 Operand(Smi::FromInt(StackFrame::CONSTRUCT))); |
| 5213 } | 5213 } |
| 5214 | 5214 |
| 5215 | 5215 |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5450 __ Subu(scratch, result, scratch); | 5450 __ Subu(scratch, result, scratch); |
| 5451 __ lw(result, FieldMemOperand(scratch, | 5451 __ lw(result, FieldMemOperand(scratch, |
| 5452 FixedArray::kHeaderSize - kPointerSize)); | 5452 FixedArray::kHeaderSize - kPointerSize)); |
| 5453 __ bind(&done); | 5453 __ bind(&done); |
| 5454 } | 5454 } |
| 5455 | 5455 |
| 5456 | 5456 |
| 5457 #undef __ | 5457 #undef __ |
| 5458 | 5458 |
| 5459 } } // namespace v8::internal | 5459 } } // namespace v8::internal |
| OLD | NEW |