OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 1416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1427 frame_->RestoreContextRegister(); | 1427 frame_->RestoreContextRegister(); |
1428 frame_->SetElementAt(0, &answer); | 1428 frame_->SetElementAt(0, &answer); |
1429 } else { | 1429 } else { |
1430 // Call the C runtime function. | 1430 // Call the C runtime function. |
1431 Result answer = frame_->CallRuntime(function, arg_count); | 1431 Result answer = frame_->CallRuntime(function, arg_count); |
1432 frame_->Push(&answer); | 1432 frame_->Push(&answer); |
1433 } | 1433 } |
1434 } | 1434 } |
1435 | 1435 |
1436 | 1436 |
1437 void CodeGenerator::VisitUnaryOperation(UnaryOperation* a) { | 1437 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
1438 UNIMPLEMENTED(); | 1438 // Note that because of NOT and an optimization in comparison of a typeof |
| 1439 // expression to a literal string, this function can fail to leave a value |
| 1440 // on top of the frame or in the cc register. |
| 1441 Comment cmnt(masm_, "[ UnaryOperation"); |
| 1442 |
| 1443 Token::Value op = node->op(); |
| 1444 |
| 1445 if (op == Token::NOT) { |
| 1446 // Swap the true and false targets but keep the same actual label |
| 1447 // as the fall through. |
| 1448 destination()->Invert(); |
| 1449 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, destination(), true); |
| 1450 // Swap the labels back. |
| 1451 destination()->Invert(); |
| 1452 |
| 1453 } else if (op == Token::DELETE) { |
| 1454 Property* property = node->expression()->AsProperty(); |
| 1455 if (property != NULL) { |
| 1456 Load(property->obj()); |
| 1457 Load(property->key()); |
| 1458 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); |
| 1459 frame_->Push(&answer); |
| 1460 return; |
| 1461 } |
| 1462 |
| 1463 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
| 1464 if (variable != NULL) { |
| 1465 Slot* slot = variable->slot(); |
| 1466 if (variable->is_global()) { |
| 1467 LoadGlobal(); |
| 1468 frame_->Push(variable->name()); |
| 1469 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, |
| 1470 CALL_FUNCTION, 2); |
| 1471 frame_->Push(&answer); |
| 1472 return; |
| 1473 |
| 1474 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 1475 // Call the runtime to look up the context holding the named |
| 1476 // variable. Sync the virtual frame eagerly so we can push the |
| 1477 // arguments directly into place. |
| 1478 frame_->SyncRange(0, frame_->element_count() - 1); |
| 1479 frame_->EmitPush(rsi); |
| 1480 frame_->EmitPush(variable->name()); |
| 1481 Result context = frame_->CallRuntime(Runtime::kLookupContext, 2); |
| 1482 ASSERT(context.is_register()); |
| 1483 frame_->EmitPush(context.reg()); |
| 1484 context.Unuse(); |
| 1485 frame_->EmitPush(variable->name()); |
| 1486 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, |
| 1487 CALL_FUNCTION, 2); |
| 1488 frame_->Push(&answer); |
| 1489 return; |
| 1490 } |
| 1491 |
| 1492 // Default: Result of deleting non-global, not dynamically |
| 1493 // introduced variables is false. |
| 1494 frame_->Push(Factory::false_value()); |
| 1495 |
| 1496 } else { |
| 1497 // Default: Result of deleting expressions is true. |
| 1498 Load(node->expression()); // may have side-effects |
| 1499 frame_->SetElementAt(0, Factory::true_value()); |
| 1500 } |
| 1501 |
| 1502 } else if (op == Token::TYPEOF) { |
| 1503 // Special case for loading the typeof expression; see comment on |
| 1504 // LoadTypeofExpression(). |
| 1505 LoadTypeofExpression(node->expression()); |
| 1506 Result answer = frame_->CallRuntime(Runtime::kTypeof, 1); |
| 1507 frame_->Push(&answer); |
| 1508 |
| 1509 } else if (op == Token::VOID) { |
| 1510 Expression* expression = node->expression(); |
| 1511 if (expression && expression->AsLiteral() && ( |
| 1512 expression->AsLiteral()->IsTrue() || |
| 1513 expression->AsLiteral()->IsFalse() || |
| 1514 expression->AsLiteral()->handle()->IsNumber() || |
| 1515 expression->AsLiteral()->handle()->IsString() || |
| 1516 expression->AsLiteral()->handle()->IsJSRegExp() || |
| 1517 expression->AsLiteral()->IsNull())) { |
| 1518 // Omit evaluating the value of the primitive literal. |
| 1519 // It will be discarded anyway, and can have no side effect. |
| 1520 frame_->Push(Factory::undefined_value()); |
| 1521 } else { |
| 1522 Load(node->expression()); |
| 1523 frame_->SetElementAt(0, Factory::undefined_value()); |
| 1524 } |
| 1525 |
| 1526 } else { |
| 1527 Load(node->expression()); |
| 1528 switch (op) { |
| 1529 case Token::NOT: |
| 1530 case Token::DELETE: |
| 1531 case Token::TYPEOF: |
| 1532 UNREACHABLE(); // handled above |
| 1533 break; |
| 1534 |
| 1535 case Token::SUB: { |
| 1536 bool overwrite = |
| 1537 (node->AsBinaryOperation() != NULL && |
| 1538 node->AsBinaryOperation()->ResultOverwriteAllowed()); |
| 1539 UnarySubStub stub(overwrite); |
| 1540 // TODO(1222589): remove dependency of TOS being cached inside stub |
| 1541 Result operand = frame_->Pop(); |
| 1542 Result answer = frame_->CallStub(&stub, &operand); |
| 1543 frame_->Push(&answer); |
| 1544 break; |
| 1545 } |
| 1546 |
| 1547 case Token::BIT_NOT: { |
| 1548 // Smi check. |
| 1549 JumpTarget smi_label; |
| 1550 JumpTarget continue_label; |
| 1551 Result operand = frame_->Pop(); |
| 1552 operand.ToRegister(); |
| 1553 __ testl(operand.reg(), Immediate(kSmiTagMask)); |
| 1554 smi_label.Branch(zero, &operand); |
| 1555 |
| 1556 frame_->Push(&operand); // undo popping of TOS |
| 1557 Result answer = frame_->InvokeBuiltin(Builtins::BIT_NOT, |
| 1558 CALL_FUNCTION, 1); |
| 1559 continue_label.Jump(&answer); |
| 1560 smi_label.Bind(&answer); |
| 1561 answer.ToRegister(); |
| 1562 frame_->Spill(answer.reg()); |
| 1563 __ not_(answer.reg()); |
| 1564 // Remove inverted smi-tag. The mask is sign-extended to 64 bits. |
| 1565 __ xor_(answer.reg(), Immediate(kSmiTagMask)); |
| 1566 continue_label.Bind(&answer); |
| 1567 frame_->Push(&answer); |
| 1568 break; |
| 1569 } |
| 1570 |
| 1571 case Token::ADD: { |
| 1572 // Smi check. |
| 1573 JumpTarget continue_label; |
| 1574 Result operand = frame_->Pop(); |
| 1575 operand.ToRegister(); |
| 1576 __ testl(operand.reg(), Immediate(kSmiTagMask)); |
| 1577 continue_label.Branch(zero, &operand, taken); |
| 1578 |
| 1579 frame_->Push(&operand); |
| 1580 Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER, |
| 1581 CALL_FUNCTION, 1); |
| 1582 |
| 1583 continue_label.Bind(&answer); |
| 1584 frame_->Push(&answer); |
| 1585 break; |
| 1586 } |
| 1587 |
| 1588 default: |
| 1589 UNREACHABLE(); |
| 1590 } |
| 1591 } |
1439 } | 1592 } |
1440 | 1593 |
| 1594 |
1441 void CodeGenerator::VisitCountOperation(CountOperation* a) { | 1595 void CodeGenerator::VisitCountOperation(CountOperation* a) { |
1442 UNIMPLEMENTED(); | 1596 UNIMPLEMENTED(); |
1443 } | 1597 } |
1444 | 1598 |
1445 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 1599 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { |
1446 // TODO(X64): This code was copied verbatim from codegen-ia32. | 1600 // TODO(X64): This code was copied verbatim from codegen-ia32. |
1447 // Either find a reason to change it or move it to a shared location. | 1601 // Either find a reason to change it or move it to a shared location. |
1448 | 1602 |
1449 // Note that due to an optimization in comparison operations (typeof | 1603 // Note that due to an optimization in comparison operations (typeof |
1450 // compared to a string literal), we can evaluate a binary expression such | 1604 // compared to a string literal), we can evaluate a binary expression such |
(...skipping 3530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4981 break; | 5135 break; |
4982 default: | 5136 default: |
4983 UNREACHABLE(); | 5137 UNREACHABLE(); |
4984 } | 5138 } |
4985 } | 5139 } |
4986 | 5140 |
4987 | 5141 |
4988 #undef __ | 5142 #undef __ |
4989 | 5143 |
4990 } } // namespace v8::internal | 5144 } } // namespace v8::internal |
OLD | NEW |