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 2754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2765 String::cast(*right_side.handle())->length() == 1 && | 2765 String::cast(*right_side.handle())->length() == 1 && |
2766 String::cast(*right_side.handle())->IsAsciiRepresentation()); | 2766 String::cast(*right_side.handle())->IsAsciiRepresentation()); |
2767 } | 2767 } |
2768 | 2768 |
2769 if (left_side_constant_smi || right_side_constant_smi) { | 2769 if (left_side_constant_smi || right_side_constant_smi) { |
2770 bool is_loop_condition = (node->AsExpression() != NULL) && | 2770 bool is_loop_condition = (node->AsExpression() != NULL) && |
2771 node->AsExpression()->is_loop_condition(); | 2771 node->AsExpression()->is_loop_condition(); |
2772 ConstantSmiComparison(cc, strict, dest, &left_side, &right_side, | 2772 ConstantSmiComparison(cc, strict, dest, &left_side, &right_side, |
2773 left_side_constant_smi, right_side_constant_smi, | 2773 left_side_constant_smi, right_side_constant_smi, |
2774 is_loop_condition); | 2774 is_loop_condition); |
2775 } else if (cc == equal && | |
2776 (left_side_constant_null || right_side_constant_null)) { | |
2777 // To make null checks efficient, we check if either the left side or | |
2778 // the right side is the constant 'null'. | |
2779 // If so, we optimize the code by inlining a null check instead of | |
2780 // calling the (very) general runtime routine for checking equality. | |
2781 Result operand = left_side_constant_null ? right_side : left_side; | |
2782 right_side.Unuse(); | |
2783 left_side.Unuse(); | |
2784 operand.ToRegister(); | |
2785 __ cmp(operand.reg(), Factory::null_value()); | |
2786 if (strict) { | |
2787 operand.Unuse(); | |
2788 dest->Split(equal); | |
2789 } else { | |
2790 // The 'null' value is only equal to 'undefined' if using non-strict | |
2791 // comparisons. | |
2792 dest->true_target()->Branch(equal); | |
2793 __ cmp(operand.reg(), Factory::undefined_value()); | |
2794 dest->true_target()->Branch(equal); | |
2795 __ test(operand.reg(), Immediate(kSmiTagMask)); | |
2796 dest->false_target()->Branch(equal); | |
2797 | |
2798 // It can be an undetectable object. | |
2799 // Use a scratch register in preference to spilling operand.reg(). | |
2800 Result temp = allocator()->Allocate(); | |
2801 ASSERT(temp.is_valid()); | |
2802 __ mov(temp.reg(), | |
2803 FieldOperand(operand.reg(), HeapObject::kMapOffset)); | |
2804 __ test_b(FieldOperand(temp.reg(), Map::kBitFieldOffset), | |
2805 1 << Map::kIsUndetectable); | |
2806 temp.Unuse(); | |
2807 operand.Unuse(); | |
2808 dest->Split(not_zero); | |
2809 } | |
2810 } else if (left_side_constant_1_char_string || | 2775 } else if (left_side_constant_1_char_string || |
2811 right_side_constant_1_char_string) { | 2776 right_side_constant_1_char_string) { |
2812 if (left_side_constant_1_char_string && right_side_constant_1_char_string) { | 2777 if (left_side_constant_1_char_string && right_side_constant_1_char_string) { |
2813 // Trivial case, comparing two constants. | 2778 // Trivial case, comparing two constants. |
2814 int left_value = String::cast(*left_side.handle())->Get(0); | 2779 int left_value = String::cast(*left_side.handle())->Get(0); |
2815 int right_value = String::cast(*right_side.handle())->Get(0); | 2780 int right_value = String::cast(*right_side.handle())->Get(0); |
2816 switch (cc) { | 2781 switch (cc) { |
2817 case less: | 2782 case less: |
2818 dest->Goto(left_value < right_value); | 2783 dest->Goto(left_value < right_value); |
2819 break; | 2784 break; |
(...skipping 2994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5814 // For a compound assignment the right-hand side is a binary operation | 5779 // For a compound assignment the right-hand side is a binary operation |
5815 // between the current property value and the actual right-hand side. | 5780 // between the current property value and the actual right-hand side. |
5816 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 5781 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
5817 Load(node->value()); | 5782 Load(node->value()); |
5818 | 5783 |
5819 // Perform the binary operation. | 5784 // Perform the binary operation. |
5820 bool overwrite_value = | 5785 bool overwrite_value = |
5821 (node->value()->AsBinaryOperation() != NULL && | 5786 (node->value()->AsBinaryOperation() != NULL && |
5822 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5787 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5823 // Construct the implicit binary operation. | 5788 // Construct the implicit binary operation. |
5824 BinaryOperation expr(node, node->binary_op(), node->target(), | 5789 BinaryOperation expr(node->binary_op(), node->target(), node->value()); |
5825 node->value()); | 5790 expr.CopyAnalysisResultsFrom(node); |
5826 GenericBinaryOperation(&expr, | 5791 GenericBinaryOperation(&expr, |
5827 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 5792 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
5828 } else { | 5793 } else { |
5829 // For non-compound assignment just load the right-hand side. | 5794 // For non-compound assignment just load the right-hand side. |
5830 Load(node->value()); | 5795 Load(node->value()); |
5831 } | 5796 } |
5832 | 5797 |
5833 // Perform the assignment. | 5798 // Perform the assignment. |
5834 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { | 5799 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { |
5835 CodeForSourcePosition(node->position()); | 5800 CodeForSourcePosition(node->position()); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5906 frame()->Dup(); | 5871 frame()->Dup(); |
5907 } | 5872 } |
5908 Result value = EmitNamedLoad(name, var != NULL); | 5873 Result value = EmitNamedLoad(name, var != NULL); |
5909 frame()->Push(&value); | 5874 frame()->Push(&value); |
5910 Load(node->value()); | 5875 Load(node->value()); |
5911 | 5876 |
5912 bool overwrite_value = | 5877 bool overwrite_value = |
5913 (node->value()->AsBinaryOperation() != NULL && | 5878 (node->value()->AsBinaryOperation() != NULL && |
5914 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5879 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5915 // Construct the implicit binary operation. | 5880 // Construct the implicit binary operation. |
5916 BinaryOperation expr(node, node->binary_op(), node->target(), | 5881 BinaryOperation expr(node->binary_op(), node->target(), node->value()); |
5917 node->value()); | 5882 expr.CopyAnalysisResultsFrom(node); |
5918 GenericBinaryOperation(&expr, | 5883 GenericBinaryOperation(&expr, |
5919 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 5884 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
5920 } else { | 5885 } else { |
5921 // For non-compound assignment just load the right-hand side. | 5886 // For non-compound assignment just load the right-hand side. |
5922 Load(node->value()); | 5887 Load(node->value()); |
5923 } | 5888 } |
5924 | 5889 |
5925 // Stack layout: | 5890 // Stack layout: |
5926 // [tos] : value | 5891 // [tos] : value |
5927 // [tos+1] : receiver (only materialized if non-trivial) | 5892 // [tos+1] : receiver (only materialized if non-trivial) |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6008 frame()->PushElementAt(1); | 5973 frame()->PushElementAt(1); |
6009 frame()->PushElementAt(1); | 5974 frame()->PushElementAt(1); |
6010 Result value = EmitKeyedLoad(); | 5975 Result value = EmitKeyedLoad(); |
6011 frame()->Push(&value); | 5976 frame()->Push(&value); |
6012 Load(node->value()); | 5977 Load(node->value()); |
6013 | 5978 |
6014 // Perform the binary operation. | 5979 // Perform the binary operation. |
6015 bool overwrite_value = | 5980 bool overwrite_value = |
6016 (node->value()->AsBinaryOperation() != NULL && | 5981 (node->value()->AsBinaryOperation() != NULL && |
6017 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5982 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
6018 BinaryOperation expr(node, node->binary_op(), node->target(), | 5983 BinaryOperation expr(node->binary_op(), node->target(), node->value()); |
6019 node->value()); | 5984 expr.CopyAnalysisResultsFrom(node); |
6020 GenericBinaryOperation(&expr, | 5985 GenericBinaryOperation(&expr, |
6021 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 5986 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
6022 } else { | 5987 } else { |
6023 // For non-compound assignment just load the right-hand side. | 5988 // For non-compound assignment just load the right-hand side. |
6024 Load(node->value()); | 5989 Load(node->value()); |
6025 } | 5990 } |
6026 | 5991 |
6027 // Stack layout: | 5992 // Stack layout: |
6028 // [tos] : value | 5993 // [tos] : value |
6029 // [tos+1] : key | 5994 // [tos+1] : key |
(...skipping 3123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9153 Load(right); | 9118 Load(right); |
9154 } | 9119 } |
9155 } else { | 9120 } else { |
9156 if (!left_already_loaded) Load(left); | 9121 if (!left_already_loaded) Load(left); |
9157 Load(right); | 9122 Load(right); |
9158 } | 9123 } |
9159 Comparison(node, cc, strict, destination()); | 9124 Comparison(node, cc, strict, destination()); |
9160 } | 9125 } |
9161 | 9126 |
9162 | 9127 |
| 9128 void CodeGenerator::VisitCompareToNull(CompareToNull* node) { |
| 9129 ASSERT(!in_safe_int32_mode()); |
| 9130 Comment cmnt(masm_, "[ CompareToNull"); |
| 9131 |
| 9132 Load(node->expression()); |
| 9133 Result operand = frame_->Pop(); |
| 9134 operand.ToRegister(); |
| 9135 __ cmp(operand.reg(), Factory::null_value()); |
| 9136 if (node->is_strict()) { |
| 9137 operand.Unuse(); |
| 9138 destination()->Split(equal); |
| 9139 } else { |
| 9140 // The 'null' value is only equal to 'undefined' if using non-strict |
| 9141 // comparisons. |
| 9142 destination()->true_target()->Branch(equal); |
| 9143 __ cmp(operand.reg(), Factory::undefined_value()); |
| 9144 destination()->true_target()->Branch(equal); |
| 9145 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 9146 destination()->false_target()->Branch(equal); |
| 9147 |
| 9148 // It can be an undetectable object. |
| 9149 // Use a scratch register in preference to spilling operand.reg(). |
| 9150 Result temp = allocator()->Allocate(); |
| 9151 ASSERT(temp.is_valid()); |
| 9152 __ mov(temp.reg(), |
| 9153 FieldOperand(operand.reg(), HeapObject::kMapOffset)); |
| 9154 __ test_b(FieldOperand(temp.reg(), Map::kBitFieldOffset), |
| 9155 1 << Map::kIsUndetectable); |
| 9156 temp.Unuse(); |
| 9157 operand.Unuse(); |
| 9158 destination()->Split(not_zero); |
| 9159 } |
| 9160 } |
| 9161 |
| 9162 |
9163 #ifdef DEBUG | 9163 #ifdef DEBUG |
9164 bool CodeGenerator::HasValidEntryRegisters() { | 9164 bool CodeGenerator::HasValidEntryRegisters() { |
9165 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) | 9165 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) |
9166 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) | 9166 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) |
9167 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) | 9167 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) |
9168 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0)) | 9168 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0)) |
9169 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0)); | 9169 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0)); |
9170 } | 9170 } |
9171 #endif | 9171 #endif |
9172 | 9172 |
(...skipping 5334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14507 masm.GetCode(&desc); | 14507 masm.GetCode(&desc); |
14508 // Call the function from C++. | 14508 // Call the function from C++. |
14509 return FUNCTION_CAST<MemCopyFunction>(buffer); | 14509 return FUNCTION_CAST<MemCopyFunction>(buffer); |
14510 } | 14510 } |
14511 | 14511 |
14512 #undef __ | 14512 #undef __ |
14513 | 14513 |
14514 } } // namespace v8::internal | 14514 } } // namespace v8::internal |
14515 | 14515 |
14516 #endif // V8_TARGET_ARCH_IA32 | 14516 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |