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 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 __ RecordJSReturn(); | 210 __ RecordJSReturn(); |
211 // Do not use the leave instruction here because it is too short to | 211 // Do not use the leave instruction here because it is too short to |
212 // patch with the code required by the debugger. | 212 // patch with the code required by the debugger. |
213 __ mov(esp, ebp); | 213 __ mov(esp, ebp); |
214 __ pop(ebp); | 214 __ pop(ebp); |
215 __ ret((scope()->num_parameters() + 1) * kPointerSize); | 215 __ ret((scope()->num_parameters() + 1) * kPointerSize); |
216 #ifdef ENABLE_DEBUGGER_SUPPORT | 216 #ifdef ENABLE_DEBUGGER_SUPPORT |
217 // Check that the size of the code used for returning matches what is | 217 // Check that the size of the code used for returning matches what is |
218 // expected by the debugger. | 218 // expected by the debugger. |
219 ASSERT_EQ(Assembler::kJSReturnSequenceLength, | 219 ASSERT_EQ(Assembler::kJSReturnSequenceLength, |
220 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 220 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
221 #endif | 221 #endif |
222 } | 222 } |
223 } | 223 } |
224 | 224 |
225 | 225 |
| 226 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( |
| 227 Token::Value op, Expression* left, Expression* right) { |
| 228 ASSERT(ShouldInlineSmiCase(op)); |
| 229 if (op == Token::DIV || op == Token::MOD || op == Token::MUL) { |
| 230 // We never generate inlined constant smi operations for these. |
| 231 return kNoConstants; |
| 232 } else if (right->IsSmiLiteral()) { |
| 233 return kRightConstant; |
| 234 } else if (left->IsSmiLiteral() && !Token::IsShiftOp(op)) { |
| 235 return kLeftConstant; |
| 236 } else { |
| 237 return kNoConstants; |
| 238 } |
| 239 } |
| 240 |
| 241 |
226 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { | 242 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { |
227 switch (context) { | 243 switch (context) { |
228 case Expression::kUninitialized: | 244 case Expression::kUninitialized: |
229 UNREACHABLE(); | 245 UNREACHABLE(); |
230 | 246 |
231 case Expression::kEffect: | 247 case Expression::kEffect: |
232 // Nothing to do. | 248 // Nothing to do. |
233 break; | 249 break; |
234 | 250 |
235 case Expression::kValue: | 251 case Expression::kValue: |
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1145 // on the left-hand side. | 1161 // on the left-hand side. |
1146 if (!expr->target()->IsValidLeftHandSide()) { | 1162 if (!expr->target()->IsValidLeftHandSide()) { |
1147 VisitForEffect(expr->target()); | 1163 VisitForEffect(expr->target()); |
1148 return; | 1164 return; |
1149 } | 1165 } |
1150 | 1166 |
1151 // Left-hand side can only be a property, a global or a (parameter or local) | 1167 // Left-hand side can only be a property, a global or a (parameter or local) |
1152 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1168 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1153 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1169 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1154 LhsKind assign_type = VARIABLE; | 1170 LhsKind assign_type = VARIABLE; |
1155 Property* prop = expr->target()->AsProperty(); | 1171 Property* property = expr->target()->AsProperty(); |
1156 if (prop != NULL) { | 1172 if (property != NULL) { |
1157 assign_type = | 1173 assign_type = (property->key()->IsPropertyName()) |
1158 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 1174 ? NAMED_PROPERTY |
| 1175 : KEYED_PROPERTY; |
1159 } | 1176 } |
1160 | 1177 |
1161 // Evaluate LHS expression. | 1178 // Evaluate LHS expression. |
1162 switch (assign_type) { | 1179 switch (assign_type) { |
1163 case VARIABLE: | 1180 case VARIABLE: |
1164 // Nothing to do here. | 1181 // Nothing to do here. |
1165 break; | 1182 break; |
1166 case NAMED_PROPERTY: | 1183 case NAMED_PROPERTY: |
1167 if (expr->is_compound()) { | 1184 if (expr->is_compound()) { |
1168 // We need the receiver both on the stack and in the accumulator. | 1185 // We need the receiver both on the stack and in the accumulator. |
1169 VisitForValue(prop->obj(), kAccumulator); | 1186 VisitForValue(property->obj(), kAccumulator); |
1170 __ push(result_register()); | 1187 __ push(result_register()); |
1171 } else { | 1188 } else { |
1172 VisitForValue(prop->obj(), kStack); | 1189 VisitForValue(property->obj(), kStack); |
1173 } | 1190 } |
1174 break; | 1191 break; |
1175 case KEYED_PROPERTY: | 1192 case KEYED_PROPERTY: |
1176 if (expr->is_compound()) { | 1193 if (expr->is_compound()) { |
1177 VisitForValue(prop->obj(), kStack); | 1194 VisitForValue(property->obj(), kStack); |
1178 VisitForValue(prop->key(), kAccumulator); | 1195 VisitForValue(property->key(), kAccumulator); |
1179 __ mov(edx, Operand(esp, 0)); | 1196 __ mov(edx, Operand(esp, 0)); |
1180 __ push(eax); | 1197 __ push(eax); |
1181 } else { | 1198 } else { |
1182 VisitForValue(prop->obj(), kStack); | 1199 VisitForValue(property->obj(), kStack); |
1183 VisitForValue(prop->key(), kStack); | 1200 VisitForValue(property->key(), kStack); |
1184 } | 1201 } |
1185 break; | 1202 break; |
1186 } | 1203 } |
1187 | 1204 |
1188 // If we have a compound assignment: Get value of LHS expression and | |
1189 // store in on top of the stack. | |
1190 if (expr->is_compound()) { | 1205 if (expr->is_compound()) { |
1191 Location saved_location = location_; | 1206 Location saved_location = location_; |
1192 location_ = kStack; | 1207 location_ = kAccumulator; |
1193 switch (assign_type) { | 1208 switch (assign_type) { |
1194 case VARIABLE: | 1209 case VARIABLE: |
1195 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), | 1210 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), |
1196 Expression::kValue); | 1211 Expression::kValue); |
1197 break; | 1212 break; |
1198 case NAMED_PROPERTY: | 1213 case NAMED_PROPERTY: |
1199 EmitNamedPropertyLoad(prop); | 1214 EmitNamedPropertyLoad(property); |
1200 __ push(result_register()); | |
1201 break; | 1215 break; |
1202 case KEYED_PROPERTY: | 1216 case KEYED_PROPERTY: |
1203 EmitKeyedPropertyLoad(prop); | 1217 EmitKeyedPropertyLoad(property); |
1204 __ push(result_register()); | |
1205 break; | 1218 break; |
1206 } | 1219 } |
1207 location_ = saved_location; | |
1208 } | |
1209 | 1220 |
1210 // Evaluate RHS expression. | 1221 Token::Value op = expr->binary_op(); |
1211 Expression* rhs = expr->value(); | 1222 ConstantOperand constant = ShouldInlineSmiCase(op) |
1212 VisitForValue(rhs, kAccumulator); | 1223 ? GetConstantOperand(op, expr->target(), expr->value()) |
| 1224 : kNoConstants; |
| 1225 ASSERT(constant == kRightConstant || constant == kNoConstants); |
| 1226 if (constant == kNoConstants) { |
| 1227 __ push(eax); // Left operand goes on the stack. |
| 1228 VisitForValue(expr->value(), kAccumulator); |
| 1229 } |
1213 | 1230 |
1214 // If we have a compound assignment: Apply operator. | |
1215 if (expr->is_compound()) { | |
1216 Location saved_location = location_; | |
1217 location_ = kAccumulator; | |
1218 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1231 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
1219 ? OVERWRITE_RIGHT | 1232 ? OVERWRITE_RIGHT |
1220 : NO_OVERWRITE; | 1233 : NO_OVERWRITE; |
1221 EmitBinaryOp(expr->binary_op(), Expression::kValue, mode); | 1234 SetSourcePosition(expr->position() + 1); |
| 1235 if (ShouldInlineSmiCase(op)) { |
| 1236 EmitInlineSmiBinaryOp(expr, |
| 1237 op, |
| 1238 Expression::kValue, |
| 1239 mode, |
| 1240 expr->target(), |
| 1241 expr->value(), |
| 1242 constant); |
| 1243 } else { |
| 1244 EmitBinaryOp(op, Expression::kValue, mode); |
| 1245 } |
1222 location_ = saved_location; | 1246 location_ = saved_location; |
| 1247 |
| 1248 } else { |
| 1249 VisitForValue(expr->value(), kAccumulator); |
1223 } | 1250 } |
1224 | 1251 |
1225 // Record source position before possible IC call. | 1252 // Record source position before possible IC call. |
1226 SetSourcePosition(expr->position()); | 1253 SetSourcePosition(expr->position()); |
1227 | 1254 |
1228 // Store the value. | 1255 // Store the value. |
1229 switch (assign_type) { | 1256 switch (assign_type) { |
1230 case VARIABLE: | 1257 case VARIABLE: |
1231 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1258 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
1232 expr->op(), | 1259 expr->op(), |
(...skipping 20 matching lines...) Expand all Loading... |
1253 | 1280 |
1254 | 1281 |
1255 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1282 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1256 SetSourcePosition(prop->position()); | 1283 SetSourcePosition(prop->position()); |
1257 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1284 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1258 __ call(ic, RelocInfo::CODE_TARGET); | 1285 __ call(ic, RelocInfo::CODE_TARGET); |
1259 __ nop(); | 1286 __ nop(); |
1260 } | 1287 } |
1261 | 1288 |
1262 | 1289 |
| 1290 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, |
| 1291 Expression::Context context, |
| 1292 OverwriteMode mode, |
| 1293 bool left_is_constant_smi, |
| 1294 Smi* value) { |
| 1295 Label call_stub, done; |
| 1296 __ add(Operand(eax), Immediate(value)); |
| 1297 __ j(overflow, &call_stub); |
| 1298 __ test(eax, Immediate(kSmiTagMask)); |
| 1299 __ j(zero, &done); |
| 1300 |
| 1301 // Undo the optimistic add operation and call the shared stub. |
| 1302 __ bind(&call_stub); |
| 1303 __ sub(Operand(eax), Immediate(value)); |
| 1304 Token::Value op = Token::ADD; |
| 1305 GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); |
| 1306 if (left_is_constant_smi) { |
| 1307 __ push(Immediate(value)); |
| 1308 __ push(eax); |
| 1309 } else { |
| 1310 __ push(eax); |
| 1311 __ push(Immediate(value)); |
| 1312 } |
| 1313 __ CallStub(&stub); |
| 1314 __ bind(&done); |
| 1315 Apply(context, eax); |
| 1316 } |
| 1317 |
| 1318 |
| 1319 void FullCodeGenerator::EmitConstantSmiSub(Expression* expr, |
| 1320 Expression::Context context, |
| 1321 OverwriteMode mode, |
| 1322 bool left_is_constant_smi, |
| 1323 Smi* value) { |
| 1324 Label call_stub, done; |
| 1325 if (left_is_constant_smi) { |
| 1326 __ mov(ecx, eax); |
| 1327 __ mov(eax, Immediate(value)); |
| 1328 __ sub(Operand(eax), ecx); |
| 1329 } else { |
| 1330 __ sub(Operand(eax), Immediate(value)); |
| 1331 } |
| 1332 __ j(overflow, &call_stub); |
| 1333 __ test(eax, Immediate(kSmiTagMask)); |
| 1334 __ j(zero, &done); |
| 1335 |
| 1336 __ bind(&call_stub); |
| 1337 if (left_is_constant_smi) { |
| 1338 __ push(Immediate(value)); |
| 1339 __ push(ecx); |
| 1340 } else { |
| 1341 // Undo the optimistic sub operation. |
| 1342 __ add(Operand(eax), Immediate(value)); |
| 1343 |
| 1344 __ push(eax); |
| 1345 __ push(Immediate(value)); |
| 1346 } |
| 1347 |
| 1348 Token::Value op = Token::SUB; |
| 1349 GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); |
| 1350 __ CallStub(&stub); |
| 1351 __ bind(&done); |
| 1352 Apply(context, eax); |
| 1353 } |
| 1354 |
| 1355 |
| 1356 void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr, |
| 1357 Token::Value op, |
| 1358 Expression::Context context, |
| 1359 OverwriteMode mode, |
| 1360 Smi* value) { |
| 1361 Label call_stub, smi_case, done; |
| 1362 int shift_value = value->value() & 0x1f; |
| 1363 |
| 1364 __ test(eax, Immediate(kSmiTagMask)); |
| 1365 __ j(zero, &smi_case); |
| 1366 |
| 1367 __ bind(&call_stub); |
| 1368 GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); |
| 1369 __ push(eax); |
| 1370 __ push(Immediate(value)); |
| 1371 __ CallStub(&stub); |
| 1372 __ jmp(&done); |
| 1373 |
| 1374 __ bind(&smi_case); |
| 1375 switch (op) { |
| 1376 case Token::SHL: |
| 1377 if (shift_value != 0) { |
| 1378 __ mov(edx, eax); |
| 1379 if (shift_value > 1) { |
| 1380 __ shl(edx, shift_value - 1); |
| 1381 } |
| 1382 // Convert int result to smi, checking that it is in int range. |
| 1383 ASSERT(kSmiTagSize == 1); // Adjust code if not the case. |
| 1384 __ add(edx, Operand(edx)); |
| 1385 __ j(overflow, &call_stub); |
| 1386 __ mov(eax, edx); // Put result back into eax. |
| 1387 } |
| 1388 break; |
| 1389 case Token::SAR: |
| 1390 if (shift_value != 0) { |
| 1391 __ sar(eax, shift_value); |
| 1392 __ and_(eax, ~kSmiTagMask); |
| 1393 } |
| 1394 break; |
| 1395 case Token::SHR: |
| 1396 if (shift_value < 2) { |
| 1397 __ mov(edx, eax); |
| 1398 __ SmiUntag(edx); |
| 1399 __ shr(edx, shift_value); |
| 1400 __ test(edx, Immediate(0xc0000000)); |
| 1401 __ j(not_zero, &call_stub); |
| 1402 __ SmiTag(edx); |
| 1403 __ mov(eax, edx); // Put result back into eax. |
| 1404 } else { |
| 1405 __ SmiUntag(eax); |
| 1406 __ shr(eax, shift_value); |
| 1407 __ SmiTag(eax); |
| 1408 } |
| 1409 break; |
| 1410 default: |
| 1411 UNREACHABLE(); |
| 1412 } |
| 1413 |
| 1414 __ bind(&done); |
| 1415 Apply(context, eax); |
| 1416 } |
| 1417 |
| 1418 |
| 1419 void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr, |
| 1420 Token::Value op, |
| 1421 Expression::Context context, |
| 1422 OverwriteMode mode, |
| 1423 Smi* value) { |
| 1424 Label smi_case, done; |
| 1425 __ test(eax, Immediate(kSmiTagMask)); |
| 1426 __ j(zero, &smi_case); |
| 1427 |
| 1428 GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); |
| 1429 // The order of the arguments does not matter for bit-ops with a |
| 1430 // constant operand. |
| 1431 __ push(Immediate(value)); |
| 1432 __ push(eax); |
| 1433 __ CallStub(&stub); |
| 1434 __ jmp(&done); |
| 1435 |
| 1436 __ bind(&smi_case); |
| 1437 switch (op) { |
| 1438 case Token::BIT_OR: |
| 1439 __ or_(Operand(eax), Immediate(value)); |
| 1440 break; |
| 1441 case Token::BIT_XOR: |
| 1442 __ xor_(Operand(eax), Immediate(value)); |
| 1443 break; |
| 1444 case Token::BIT_AND: |
| 1445 __ and_(Operand(eax), Immediate(value)); |
| 1446 break; |
| 1447 default: |
| 1448 UNREACHABLE(); |
| 1449 } |
| 1450 |
| 1451 __ bind(&done); |
| 1452 Apply(context, eax); |
| 1453 } |
| 1454 |
| 1455 |
| 1456 void FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr, |
| 1457 Token::Value op, |
| 1458 Expression::Context context, |
| 1459 OverwriteMode mode, |
| 1460 bool left_is_constant_smi, |
| 1461 Smi* value) { |
| 1462 switch (op) { |
| 1463 case Token::BIT_OR: |
| 1464 case Token::BIT_XOR: |
| 1465 case Token::BIT_AND: |
| 1466 EmitConstantSmiBitOp(expr, op, context, mode, value); |
| 1467 break; |
| 1468 case Token::SHL: |
| 1469 case Token::SAR: |
| 1470 case Token::SHR: |
| 1471 ASSERT(!left_is_constant_smi); |
| 1472 EmitConstantSmiShiftOp(expr, op, context, mode, value); |
| 1473 break; |
| 1474 case Token::ADD: |
| 1475 EmitConstantSmiAdd(expr, context, mode, left_is_constant_smi, value); |
| 1476 break; |
| 1477 case Token::SUB: |
| 1478 EmitConstantSmiSub(expr, context, mode, left_is_constant_smi, value); |
| 1479 break; |
| 1480 default: |
| 1481 UNREACHABLE(); |
| 1482 } |
| 1483 } |
| 1484 |
| 1485 |
| 1486 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, |
| 1487 Token::Value op, |
| 1488 Expression::Context context, |
| 1489 OverwriteMode mode, |
| 1490 Expression* left, |
| 1491 Expression* right, |
| 1492 ConstantOperand constant) { |
| 1493 if (constant == kRightConstant) { |
| 1494 Smi* value = Smi::cast(*right->AsLiteral()->handle()); |
| 1495 EmitConstantSmiBinaryOp(expr, op, context, mode, false, value); |
| 1496 return; |
| 1497 } else if (constant == kLeftConstant) { |
| 1498 Smi* value = Smi::cast(*left->AsLiteral()->handle()); |
| 1499 EmitConstantSmiBinaryOp(expr, op, context, mode, true, value); |
| 1500 return; |
| 1501 } |
| 1502 |
| 1503 // Do combined smi check of the operands. Left operand is on the |
| 1504 // stack. Right operand is in eax. |
| 1505 Label done, stub_call, smi_case; |
| 1506 __ pop(edx); |
| 1507 __ mov(ecx, eax); |
| 1508 __ or_(eax, Operand(edx)); |
| 1509 __ test(eax, Immediate(kSmiTagMask)); |
| 1510 __ j(zero, &smi_case); |
| 1511 |
| 1512 __ bind(&stub_call); |
| 1513 GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); |
| 1514 if (stub.ArgsInRegistersSupported()) { |
| 1515 stub.GenerateCall(masm_, edx, ecx); |
| 1516 } else { |
| 1517 __ push(edx); |
| 1518 __ push(ecx); |
| 1519 __ CallStub(&stub); |
| 1520 } |
| 1521 __ jmp(&done); |
| 1522 |
| 1523 __ bind(&smi_case); |
| 1524 __ mov(eax, edx); // Copy left operand in case of a stub call. |
| 1525 |
| 1526 switch (op) { |
| 1527 case Token::SAR: |
| 1528 __ SmiUntag(eax); |
| 1529 __ SmiUntag(ecx); |
| 1530 __ sar_cl(eax); // No checks of result necessary |
| 1531 __ SmiTag(eax); |
| 1532 break; |
| 1533 case Token::SHL: { |
| 1534 Label result_ok; |
| 1535 __ SmiUntag(eax); |
| 1536 __ SmiUntag(ecx); |
| 1537 __ shl_cl(eax); |
| 1538 // Check that the *signed* result fits in a smi. |
| 1539 __ cmp(eax, 0xc0000000); |
| 1540 __ j(positive, &result_ok); |
| 1541 __ SmiTag(ecx); |
| 1542 __ jmp(&stub_call); |
| 1543 __ bind(&result_ok); |
| 1544 __ SmiTag(eax); |
| 1545 break; |
| 1546 } |
| 1547 case Token::SHR: { |
| 1548 Label result_ok; |
| 1549 __ SmiUntag(eax); |
| 1550 __ SmiUntag(ecx); |
| 1551 __ shr_cl(eax); |
| 1552 __ test(eax, Immediate(0xc0000000)); |
| 1553 __ j(zero, &result_ok); |
| 1554 __ SmiTag(ecx); |
| 1555 __ jmp(&stub_call); |
| 1556 __ bind(&result_ok); |
| 1557 __ SmiTag(eax); |
| 1558 break; |
| 1559 } |
| 1560 case Token::ADD: |
| 1561 __ add(eax, Operand(ecx)); |
| 1562 __ j(overflow, &stub_call); |
| 1563 break; |
| 1564 case Token::SUB: |
| 1565 __ sub(eax, Operand(ecx)); |
| 1566 __ j(overflow, &stub_call); |
| 1567 break; |
| 1568 case Token::MUL: { |
| 1569 __ SmiUntag(eax); |
| 1570 __ imul(eax, Operand(ecx)); |
| 1571 __ j(overflow, &stub_call); |
| 1572 __ test(eax, Operand(eax)); |
| 1573 __ j(not_zero, &done, taken); |
| 1574 __ mov(ebx, edx); |
| 1575 __ or_(ebx, Operand(ecx)); |
| 1576 __ j(negative, &stub_call); |
| 1577 break; |
| 1578 } |
| 1579 case Token::BIT_OR: |
| 1580 __ or_(eax, Operand(ecx)); |
| 1581 break; |
| 1582 case Token::BIT_AND: |
| 1583 __ and_(eax, Operand(ecx)); |
| 1584 break; |
| 1585 case Token::BIT_XOR: |
| 1586 __ xor_(eax, Operand(ecx)); |
| 1587 break; |
| 1588 default: |
| 1589 UNREACHABLE(); |
| 1590 } |
| 1591 |
| 1592 __ bind(&done); |
| 1593 Apply(context, eax); |
| 1594 } |
| 1595 |
| 1596 |
1263 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1597 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1264 Expression::Context context, | 1598 Expression::Context context, |
1265 OverwriteMode mode) { | 1599 OverwriteMode mode) { |
1266 TypeInfo type = TypeInfo::Unknown(); | 1600 TypeInfo type = TypeInfo::Unknown(); |
1267 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS, type); | 1601 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS, type); |
1268 if (stub.ArgsInRegistersSupported()) { | 1602 if (stub.ArgsInRegistersSupported()) { |
1269 __ pop(edx); | 1603 __ pop(edx); |
1270 stub.GenerateCall(masm_, edx, eax); | 1604 stub.GenerateCall(masm_, edx, eax); |
1271 } else { | 1605 } else { |
1272 __ push(result_register()); | 1606 __ push(result_register()); |
(...skipping 1898 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3171 // And return. | 3505 // And return. |
3172 __ ret(0); | 3506 __ ret(0); |
3173 } | 3507 } |
3174 | 3508 |
3175 | 3509 |
3176 #undef __ | 3510 #undef __ |
3177 | 3511 |
3178 } } // namespace v8::internal | 3512 } } // namespace v8::internal |
3179 | 3513 |
3180 #endif // V8_TARGET_ARCH_IA32 | 3514 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |