OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 } | 223 } |
224 // Check that the size of the code used for returning matches what is | 224 // Check that the size of the code used for returning matches what is |
225 // expected by the debugger. | 225 // expected by the debugger. |
226 ASSERT_EQ(Assembler::kJSReturnSequenceLength, | 226 ASSERT_EQ(Assembler::kJSReturnSequenceLength, |
227 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 227 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
228 #endif | 228 #endif |
229 } | 229 } |
230 } | 230 } |
231 | 231 |
232 | 232 |
| 233 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( |
| 234 Token::Value op, Expression* left, Expression* right) { |
| 235 ASSERT(ShouldInlineSmiCase(op)); |
| 236 return kNoConstants; |
| 237 } |
| 238 |
| 239 |
233 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { | 240 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { |
234 switch (context) { | 241 switch (context) { |
235 case Expression::kUninitialized: | 242 case Expression::kUninitialized: |
236 UNREACHABLE(); | 243 UNREACHABLE(); |
237 | 244 |
238 case Expression::kEffect: | 245 case Expression::kEffect: |
239 // Nothing to do. | 246 // Nothing to do. |
240 break; | 247 break; |
241 | 248 |
242 case Expression::kValue: | 249 case Expression::kValue: |
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 // on the left-hand side. | 1156 // on the left-hand side. |
1150 if (!expr->target()->IsValidLeftHandSide()) { | 1157 if (!expr->target()->IsValidLeftHandSide()) { |
1151 VisitForEffect(expr->target()); | 1158 VisitForEffect(expr->target()); |
1152 return; | 1159 return; |
1153 } | 1160 } |
1154 | 1161 |
1155 // Left-hand side can only be a property, a global or a (parameter or local) | 1162 // Left-hand side can only be a property, a global or a (parameter or local) |
1156 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1163 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1157 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1164 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1158 LhsKind assign_type = VARIABLE; | 1165 LhsKind assign_type = VARIABLE; |
1159 Property* prop = expr->target()->AsProperty(); | 1166 Property* property = expr->target()->AsProperty(); |
1160 if (prop != NULL) { | 1167 if (property != NULL) { |
1161 assign_type = | 1168 assign_type = (property->key()->IsPropertyName()) |
1162 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 1169 ? NAMED_PROPERTY |
| 1170 : KEYED_PROPERTY; |
1163 } | 1171 } |
1164 | 1172 |
1165 // Evaluate LHS expression. | 1173 // Evaluate LHS expression. |
1166 switch (assign_type) { | 1174 switch (assign_type) { |
1167 case VARIABLE: | 1175 case VARIABLE: |
1168 // Nothing to do here. | 1176 // Nothing to do here. |
1169 break; | 1177 break; |
1170 case NAMED_PROPERTY: | 1178 case NAMED_PROPERTY: |
1171 if (expr->is_compound()) { | 1179 if (expr->is_compound()) { |
1172 // We need the receiver both on the stack and in the accumulator. | 1180 // We need the receiver both on the stack and in the accumulator. |
1173 VisitForValue(prop->obj(), kAccumulator); | 1181 VisitForValue(property->obj(), kAccumulator); |
1174 __ push(result_register()); | 1182 __ push(result_register()); |
1175 } else { | 1183 } else { |
1176 VisitForValue(prop->obj(), kStack); | 1184 VisitForValue(property->obj(), kStack); |
1177 } | 1185 } |
1178 break; | 1186 break; |
1179 case KEYED_PROPERTY: | 1187 case KEYED_PROPERTY: |
1180 if (expr->is_compound()) { | 1188 if (expr->is_compound()) { |
1181 VisitForValue(prop->obj(), kStack); | 1189 VisitForValue(property->obj(), kStack); |
1182 VisitForValue(prop->key(), kAccumulator); | 1190 VisitForValue(property->key(), kAccumulator); |
1183 __ movq(rdx, Operand(rsp, 0)); | 1191 __ movq(rdx, Operand(rsp, 0)); |
1184 __ push(rax); | 1192 __ push(rax); |
1185 } else { | 1193 } else { |
1186 VisitForValue(prop->obj(), kStack); | 1194 VisitForValue(property->obj(), kStack); |
1187 VisitForValue(prop->key(), kStack); | 1195 VisitForValue(property->key(), kStack); |
1188 } | 1196 } |
1189 break; | 1197 break; |
1190 } | 1198 } |
1191 | 1199 |
1192 // If we have a compound assignment: Get value of LHS expression and | |
1193 // store in on top of the stack. | |
1194 if (expr->is_compound()) { | 1200 if (expr->is_compound()) { |
1195 Location saved_location = location_; | 1201 Location saved_location = location_; |
1196 location_ = kStack; | 1202 location_ = kAccumulator; |
1197 switch (assign_type) { | 1203 switch (assign_type) { |
1198 case VARIABLE: | 1204 case VARIABLE: |
1199 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), | 1205 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), |
1200 Expression::kValue); | 1206 Expression::kValue); |
1201 break; | 1207 break; |
1202 case NAMED_PROPERTY: | 1208 case NAMED_PROPERTY: |
1203 EmitNamedPropertyLoad(prop); | 1209 EmitNamedPropertyLoad(property); |
1204 __ push(result_register()); | |
1205 break; | 1210 break; |
1206 case KEYED_PROPERTY: | 1211 case KEYED_PROPERTY: |
1207 EmitKeyedPropertyLoad(prop); | 1212 EmitKeyedPropertyLoad(property); |
1208 __ push(result_register()); | |
1209 break; | 1213 break; |
1210 } | 1214 } |
1211 location_ = saved_location; | |
1212 } | |
1213 | 1215 |
1214 // Evaluate RHS expression. | 1216 Token::Value op = expr->binary_op(); |
1215 Expression* rhs = expr->value(); | 1217 ConstantOperand constant = ShouldInlineSmiCase(op) |
1216 VisitForValue(rhs, kAccumulator); | 1218 ? GetConstantOperand(op, expr->target(), expr->value()) |
| 1219 : kNoConstants; |
| 1220 ASSERT(constant == kRightConstant || constant == kNoConstants); |
| 1221 if (constant == kNoConstants) { |
| 1222 __ push(rax); // Left operand goes on the stack. |
| 1223 VisitForValue(expr->value(), kAccumulator); |
| 1224 } |
1217 | 1225 |
1218 // If we have a compound assignment: Apply operator. | |
1219 if (expr->is_compound()) { | |
1220 Location saved_location = location_; | |
1221 location_ = kAccumulator; | |
1222 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1226 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
1223 ? OVERWRITE_RIGHT | 1227 ? OVERWRITE_RIGHT |
1224 : NO_OVERWRITE; | 1228 : NO_OVERWRITE; |
1225 EmitBinaryOp(expr->binary_op(), Expression::kValue, mode); | 1229 SetSourcePosition(expr->position() + 1); |
| 1230 if (ShouldInlineSmiCase(op)) { |
| 1231 EmitInlineSmiBinaryOp(expr, |
| 1232 op, |
| 1233 Expression::kValue, |
| 1234 mode, |
| 1235 expr->target(), |
| 1236 expr->value(), |
| 1237 constant); |
| 1238 } else { |
| 1239 EmitBinaryOp(op, Expression::kValue, mode); |
| 1240 } |
1226 location_ = saved_location; | 1241 location_ = saved_location; |
| 1242 |
| 1243 } else { |
| 1244 VisitForValue(expr->value(), kAccumulator); |
1227 } | 1245 } |
1228 | 1246 |
1229 // Record source position before possible IC call. | 1247 // Record source position before possible IC call. |
1230 SetSourcePosition(expr->position()); | 1248 SetSourcePosition(expr->position()); |
1231 | 1249 |
1232 // Store the value. | 1250 // Store the value. |
1233 switch (assign_type) { | 1251 switch (assign_type) { |
1234 case VARIABLE: | 1252 case VARIABLE: |
1235 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1253 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
1236 expr->op(), | 1254 expr->op(), |
(...skipping 20 matching lines...) Expand all Loading... |
1257 | 1275 |
1258 | 1276 |
1259 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1277 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1260 SetSourcePosition(prop->position()); | 1278 SetSourcePosition(prop->position()); |
1261 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1279 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1262 __ Call(ic, RelocInfo::CODE_TARGET); | 1280 __ Call(ic, RelocInfo::CODE_TARGET); |
1263 __ nop(); | 1281 __ nop(); |
1264 } | 1282 } |
1265 | 1283 |
1266 | 1284 |
| 1285 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, |
| 1286 Token::Value op, |
| 1287 Expression::Context context, |
| 1288 OverwriteMode mode, |
| 1289 Expression* left, |
| 1290 Expression* right, |
| 1291 ConstantOperand constant) { |
| 1292 ASSERT(constant == kNoConstants); // Only handled case. |
| 1293 |
| 1294 // Do combined smi check of the operands. Left operand is on the |
| 1295 // stack (popped into rdx). Right operand is in rax but moved into |
| 1296 // rcx to make the shifts easier. |
| 1297 Label done, stub_call, smi_case; |
| 1298 __ pop(rdx); |
| 1299 __ movq(rcx, rax); |
| 1300 Condition smi = __ CheckBothSmi(rdx, rax); |
| 1301 __ j(smi, &smi_case); |
| 1302 |
| 1303 __ bind(&stub_call); |
| 1304 GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); |
| 1305 if (stub.ArgsInRegistersSupported()) { |
| 1306 stub.GenerateCall(masm_, rdx, rcx); |
| 1307 } else { |
| 1308 __ push(rdx); |
| 1309 __ push(rcx); |
| 1310 __ CallStub(&stub); |
| 1311 } |
| 1312 __ jmp(&done); |
| 1313 |
| 1314 __ bind(&smi_case); |
| 1315 switch (op) { |
| 1316 case Token::SAR: |
| 1317 __ SmiShiftArithmeticRight(rax, rdx, rcx); |
| 1318 break; |
| 1319 case Token::SHL: |
| 1320 __ SmiShiftLeft(rax, rdx, rcx); |
| 1321 break; |
| 1322 case Token::SHR: |
| 1323 __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call); |
| 1324 break; |
| 1325 case Token::ADD: |
| 1326 __ SmiAdd(rax, rdx, rcx, &stub_call); |
| 1327 break; |
| 1328 case Token::SUB: |
| 1329 __ SmiSub(rax, rdx, rcx, &stub_call); |
| 1330 break; |
| 1331 case Token::MUL: |
| 1332 __ SmiMul(rax, rdx, rcx, &stub_call); |
| 1333 break; |
| 1334 case Token::BIT_OR: |
| 1335 __ SmiOr(rax, rdx, rcx); |
| 1336 break; |
| 1337 case Token::BIT_AND: |
| 1338 __ SmiAnd(rax, rdx, rcx); |
| 1339 break; |
| 1340 case Token::BIT_XOR: |
| 1341 __ SmiXor(rax, rdx, rcx); |
| 1342 break; |
| 1343 default: |
| 1344 UNREACHABLE(); |
| 1345 break; |
| 1346 } |
| 1347 |
| 1348 __ bind(&done); |
| 1349 Apply(context, rax); |
| 1350 } |
| 1351 |
| 1352 |
1267 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1353 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1268 Expression::Context context, | 1354 Expression::Context context, |
1269 OverwriteMode mode) { | 1355 OverwriteMode mode) { |
1270 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS); | 1356 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS); |
1271 if (stub.ArgsInRegistersSupported()) { | 1357 if (stub.ArgsInRegistersSupported()) { |
1272 __ pop(rdx); | 1358 __ pop(rdx); |
1273 stub.GenerateCall(masm_, rdx, rax); | 1359 stub.GenerateCall(masm_, rdx, rax); |
1274 } else { | 1360 } else { |
1275 __ push(result_register()); | 1361 __ push(result_register()); |
1276 __ CallStub(&stub); | 1362 __ CallStub(&stub); |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1964 __ cmpq(rax, rbx); | 2050 __ cmpq(rax, rbx); |
1965 Split(equal, if_true, if_false, fall_through); | 2051 Split(equal, if_true, if_false, fall_through); |
1966 | 2052 |
1967 Apply(context_, if_true, if_false); | 2053 Apply(context_, if_true, if_false); |
1968 } | 2054 } |
1969 | 2055 |
1970 | 2056 |
1971 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 2057 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
1972 ASSERT(args->length() == 1); | 2058 ASSERT(args->length() == 1); |
1973 | 2059 |
1974 // ArgumentsAccessStub expects the key in edx and the formal | 2060 // ArgumentsAccessStub expects the key in rdx and the formal |
1975 // parameter count in eax. | 2061 // parameter count in rax. |
1976 VisitForValue(args->at(0), kAccumulator); | 2062 VisitForValue(args->at(0), kAccumulator); |
1977 __ movq(rdx, rax); | 2063 __ movq(rdx, rax); |
1978 __ Move(rax, Smi::FromInt(scope()->num_parameters())); | 2064 __ Move(rax, Smi::FromInt(scope()->num_parameters())); |
1979 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 2065 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
1980 __ CallStub(&stub); | 2066 __ CallStub(&stub); |
1981 Apply(context_, rax); | 2067 Apply(context_, rax); |
1982 } | 2068 } |
1983 | 2069 |
1984 | 2070 |
1985 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { | 2071 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2169 __ CallRuntime(Runtime::kMath_pow, 2); | 2255 __ CallRuntime(Runtime::kMath_pow, 2); |
2170 Apply(context_, rax); | 2256 Apply(context_, rax); |
2171 } | 2257 } |
2172 | 2258 |
2173 | 2259 |
2174 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2260 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
2175 ASSERT(args->length() == 2); | 2261 ASSERT(args->length() == 2); |
2176 | 2262 |
2177 VisitForValue(args->at(0), kStack); // Load the object. | 2263 VisitForValue(args->at(0), kStack); // Load the object. |
2178 VisitForValue(args->at(1), kAccumulator); // Load the value. | 2264 VisitForValue(args->at(1), kAccumulator); // Load the value. |
2179 __ pop(rbx); // rax = value. ebx = object. | 2265 __ pop(rbx); // rax = value. rbx = object. |
2180 | 2266 |
2181 Label done; | 2267 Label done; |
2182 // If the object is a smi, return the value. | 2268 // If the object is a smi, return the value. |
2183 __ JumpIfSmi(rbx, &done); | 2269 __ JumpIfSmi(rbx, &done); |
2184 | 2270 |
2185 // If the object is not a value type, return the value. | 2271 // If the object is not a value type, return the value. |
2186 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); | 2272 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); |
2187 __ j(not_equal, &done); | 2273 __ j(not_equal, &done); |
2188 | 2274 |
2189 // Store the value. | 2275 // Store the value. |
(...skipping 970 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3160 __ ret(0); | 3246 __ ret(0); |
3161 } | 3247 } |
3162 | 3248 |
3163 | 3249 |
3164 #undef __ | 3250 #undef __ |
3165 | 3251 |
3166 | 3252 |
3167 } } // namespace v8::internal | 3253 } } // namespace v8::internal |
3168 | 3254 |
3169 #endif // V8_TARGET_ARCH_X64 | 3255 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |