OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 3504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3515 | 3515 |
3516 | 3516 |
3517 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 3517 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
3518 Comment cmnt(masm_, "[ CompareOperation"); | 3518 Comment cmnt(masm_, "[ CompareOperation"); |
3519 | 3519 |
3520 // Get the expressions from the node. | 3520 // Get the expressions from the node. |
3521 Expression* left = node->left(); | 3521 Expression* left = node->left(); |
3522 Expression* right = node->right(); | 3522 Expression* right = node->right(); |
3523 Token::Value op = node->op(); | 3523 Token::Value op = node->op(); |
3524 | 3524 |
3525 // NOTE: To make null checks efficient, we check if either left or | 3525 // To make null checks efficient, we check if either left or right is the |
3526 // right is the literal 'null'. If so, we optimize the code by | 3526 // literal 'null'. If so, we optimize the code by inlining a null check |
3527 // inlining a null check instead of calling the (very) general | 3527 // instead of calling the (very) general runtime routine for checking |
3528 // runtime routine for checking equality. | 3528 // equality. |
3529 | |
3530 if (op == Token::EQ || op == Token::EQ_STRICT) { | 3529 if (op == Token::EQ || op == Token::EQ_STRICT) { |
3531 bool left_is_null = | 3530 bool left_is_null = |
3532 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); | 3531 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); |
3533 bool right_is_null = | 3532 bool right_is_null = |
3534 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); | 3533 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); |
3535 // The 'null' value is only equal to 'null' or 'undefined'. | 3534 // The 'null' value can only be equal to 'null' or 'undefined'. |
3536 if (left_is_null || right_is_null) { | 3535 if (left_is_null || right_is_null) { |
3537 Load(left_is_null ? right : left); | 3536 Load(left_is_null ? right : left); |
3538 Label exit, undetectable; | |
3539 frame_->Pop(eax); | 3537 frame_->Pop(eax); |
3540 __ cmp(eax, Factory::null_value()); | 3538 __ cmp(eax, Factory::null_value()); |
3541 | 3539 |
3542 // The 'null' value is only equal to 'undefined' if using | 3540 // The 'null' value is only equal to 'undefined' if using non-strict |
3543 // non-strict comparisons. | 3541 // comparisons. |
3544 if (op != Token::EQ_STRICT) { | 3542 if (op != Token::EQ_STRICT) { |
3545 __ j(equal, &exit); | 3543 __ j(equal, true_target()); |
| 3544 |
3546 __ cmp(eax, Factory::undefined_value()); | 3545 __ cmp(eax, Factory::undefined_value()); |
| 3546 __ j(equal, true_target()); |
3547 | 3547 |
3548 // NOTE: it can be an undetectable object. | |
3549 __ j(equal, &exit); | |
3550 __ test(eax, Immediate(kSmiTagMask)); | 3548 __ test(eax, Immediate(kSmiTagMask)); |
| 3549 __ j(equal, false_target()); |
3551 | 3550 |
3552 __ j(not_equal, &undetectable); | 3551 // It can be an undetectable object. |
3553 __ jmp(false_target()); | 3552 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); |
3554 | 3553 __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset)); |
3555 __ bind(&undetectable); | 3554 __ and_(eax, 1 << Map::kIsUndetectable); |
3556 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 3555 __ cmp(eax, 1 << Map::kIsUndetectable); |
3557 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); | |
3558 __ and_(ecx, 1 << Map::kIsUndetectable); | |
3559 __ cmp(ecx, 1 << Map::kIsUndetectable); | |
3560 } | 3556 } |
3561 | 3557 |
3562 __ bind(&exit); | |
3563 | |
3564 cc_reg_ = equal; | 3558 cc_reg_ = equal; |
3565 return; | 3559 return; |
3566 } | 3560 } |
3567 } | 3561 } |
3568 | 3562 |
3569 // NOTE: To make typeof testing for natives implemented in | 3563 // To make typeof testing for natives implemented in JavaScript really |
3570 // JavaScript really efficient, we generate special code for | 3564 // efficient, we generate special code for expressions of the form: |
3571 // expressions of the form: 'typeof <expression> == <string>'. | 3565 // 'typeof <expression> == <string>'. |
3572 | |
3573 UnaryOperation* operation = left->AsUnaryOperation(); | 3566 UnaryOperation* operation = left->AsUnaryOperation(); |
3574 if ((op == Token::EQ || op == Token::EQ_STRICT) && | 3567 if ((op == Token::EQ || op == Token::EQ_STRICT) && |
3575 (operation != NULL && operation->op() == Token::TYPEOF) && | 3568 (operation != NULL && operation->op() == Token::TYPEOF) && |
3576 (right->AsLiteral() != NULL && | 3569 (right->AsLiteral() != NULL && |
3577 right->AsLiteral()->handle()->IsString())) { | 3570 right->AsLiteral()->handle()->IsString())) { |
3578 Handle<String> check(String::cast(*right->AsLiteral()->handle())); | 3571 Handle<String> check(String::cast(*right->AsLiteral()->handle())); |
3579 | 3572 |
3580 // Load the operand, move it to register edx, and restore TOS. | 3573 // Load the operand and move it to register edx. |
3581 LoadTypeofExpression(operation->expression()); | 3574 LoadTypeofExpression(operation->expression()); |
3582 frame_->Pop(edx); | 3575 frame_->Pop(edx); |
3583 | 3576 |
3584 if (check->Equals(Heap::number_symbol())) { | 3577 if (check->Equals(Heap::number_symbol())) { |
3585 __ test(edx, Immediate(kSmiTagMask)); | 3578 __ test(edx, Immediate(kSmiTagMask)); |
3586 __ j(zero, true_target()); | 3579 __ j(zero, true_target()); |
3587 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); | 3580 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); |
3588 __ cmp(edx, Factory::heap_number_map()); | 3581 __ cmp(edx, Factory::heap_number_map()); |
3589 cc_reg_ = equal; | 3582 cc_reg_ = equal; |
3590 | 3583 |
3591 } else if (check->Equals(Heap::string_symbol())) { | 3584 } else if (check->Equals(Heap::string_symbol())) { |
3592 __ test(edx, Immediate(kSmiTagMask)); | 3585 __ test(edx, Immediate(kSmiTagMask)); |
3593 __ j(zero, false_target()); | 3586 __ j(zero, false_target()); |
3594 | 3587 |
3595 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); | 3588 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); |
3596 | 3589 |
3597 // NOTE: it might be an undetectable string object | 3590 // It can be an undetectable string object. |
3598 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); | 3591 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); |
3599 __ and_(ecx, 1 << Map::kIsUndetectable); | 3592 __ and_(ecx, 1 << Map::kIsUndetectable); |
3600 __ cmp(ecx, 1 << Map::kIsUndetectable); | 3593 __ cmp(ecx, 1 << Map::kIsUndetectable); |
3601 __ j(equal, false_target()); | 3594 __ j(equal, false_target()); |
3602 | 3595 |
3603 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 3596 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
3604 __ cmp(ecx, FIRST_NONSTRING_TYPE); | 3597 __ cmp(ecx, FIRST_NONSTRING_TYPE); |
3605 cc_reg_ = less; | 3598 cc_reg_ = less; |
3606 | 3599 |
3607 } else if (check->Equals(Heap::boolean_symbol())) { | 3600 } else if (check->Equals(Heap::boolean_symbol())) { |
3608 __ cmp(edx, Factory::true_value()); | 3601 __ cmp(edx, Factory::true_value()); |
3609 __ j(equal, true_target()); | 3602 __ j(equal, true_target()); |
3610 __ cmp(edx, Factory::false_value()); | 3603 __ cmp(edx, Factory::false_value()); |
3611 cc_reg_ = equal; | 3604 cc_reg_ = equal; |
3612 | 3605 |
3613 } else if (check->Equals(Heap::undefined_symbol())) { | 3606 } else if (check->Equals(Heap::undefined_symbol())) { |
3614 __ cmp(edx, Factory::undefined_value()); | 3607 __ cmp(edx, Factory::undefined_value()); |
3615 __ j(equal, true_target()); | 3608 __ j(equal, true_target()); |
3616 | 3609 |
3617 __ test(edx, Immediate(kSmiTagMask)); | 3610 __ test(edx, Immediate(kSmiTagMask)); |
3618 __ j(zero, false_target()); | 3611 __ j(zero, false_target()); |
3619 | 3612 |
3620 // NOTE: it can be an undetectable object. | 3613 // It can be an undetectable object. |
3621 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); | 3614 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); |
3622 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); | 3615 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); |
3623 __ and_(ecx, 1 << Map::kIsUndetectable); | 3616 __ and_(ecx, 1 << Map::kIsUndetectable); |
3624 __ cmp(ecx, 1 << Map::kIsUndetectable); | 3617 __ cmp(ecx, 1 << Map::kIsUndetectable); |
3625 | 3618 |
3626 cc_reg_ = equal; | 3619 cc_reg_ = equal; |
3627 | 3620 |
3628 } else if (check->Equals(Heap::function_symbol())) { | 3621 } else if (check->Equals(Heap::function_symbol())) { |
3629 __ test(edx, Immediate(kSmiTagMask)); | 3622 __ test(edx, Immediate(kSmiTagMask)); |
3630 __ j(zero, false_target()); | 3623 __ j(zero, false_target()); |
3631 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); | 3624 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); |
3632 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 3625 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
3633 __ cmp(edx, JS_FUNCTION_TYPE); | 3626 __ cmp(edx, JS_FUNCTION_TYPE); |
3634 cc_reg_ = equal; | 3627 cc_reg_ = equal; |
3635 | 3628 |
3636 } else if (check->Equals(Heap::object_symbol())) { | 3629 } else if (check->Equals(Heap::object_symbol())) { |
3637 __ test(edx, Immediate(kSmiTagMask)); | 3630 __ test(edx, Immediate(kSmiTagMask)); |
3638 __ j(zero, false_target()); | 3631 __ j(zero, false_target()); |
3639 | 3632 |
3640 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 3633 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
3641 __ cmp(edx, Factory::null_value()); | 3634 __ cmp(edx, Factory::null_value()); |
3642 __ j(equal, true_target()); | 3635 __ j(equal, true_target()); |
3643 | 3636 |
3644 // NOTE: it might be an undetectable object | 3637 // It can be an undetectable object. |
3645 __ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset)); | 3638 __ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset)); |
3646 __ and_(edx, 1 << Map::kIsUndetectable); | 3639 __ and_(edx, 1 << Map::kIsUndetectable); |
3647 __ cmp(edx, 1 << Map::kIsUndetectable); | 3640 __ cmp(edx, 1 << Map::kIsUndetectable); |
3648 __ j(equal, false_target()); | 3641 __ j(equal, false_target()); |
3649 | 3642 |
3650 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 3643 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
3651 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 3644 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); |
3652 __ j(less, false_target()); | 3645 __ j(less, false_target()); |
3653 __ cmp(ecx, LAST_JS_OBJECT_TYPE); | 3646 __ cmp(ecx, LAST_JS_OBJECT_TYPE); |
3654 cc_reg_ = less_equal; | 3647 cc_reg_ = less_equal; |
3655 | 3648 |
3656 } else { | 3649 } else { |
3657 // Uncommon case: Typeof testing against a string literal that | 3650 // Uncommon case: typeof testing against a string literal that is |
3658 // is never returned from the typeof operator. | 3651 // never returned from the typeof operator. |
3659 __ jmp(false_target()); | 3652 __ jmp(false_target()); |
3660 } | 3653 } |
3661 return; | 3654 return; |
3662 } | 3655 } |
3663 | 3656 |
3664 Condition cc = no_condition; | 3657 Condition cc = no_condition; |
3665 bool strict = false; | 3658 bool strict = false; |
3666 switch (op) { | 3659 switch (op) { |
3667 case Token::EQ_STRICT: | 3660 case Token::EQ_STRICT: |
3668 strict = true; | 3661 strict = true; |
(...skipping 1480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5149 | 5142 |
5150 // Slow-case: Go through the JavaScript implementation. | 5143 // Slow-case: Go through the JavaScript implementation. |
5151 __ bind(&slow); | 5144 __ bind(&slow); |
5152 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5145 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
5153 } | 5146 } |
5154 | 5147 |
5155 | 5148 |
5156 #undef __ | 5149 #undef __ |
5157 | 5150 |
5158 } } // namespace v8::internal | 5151 } } // namespace v8::internal |
OLD | NEW |