| 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 |