| 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 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 } | 1207 } |
| 1208 | 1208 |
| 1209 // Evaluate RHS expression. | 1209 // Evaluate RHS expression. |
| 1210 Expression* rhs = expr->value(); | 1210 Expression* rhs = expr->value(); |
| 1211 VisitForValue(rhs, kAccumulator); | 1211 VisitForValue(rhs, kAccumulator); |
| 1212 | 1212 |
| 1213 // If we have a compound assignment: Apply operator. | 1213 // If we have a compound assignment: Apply operator. |
| 1214 if (expr->is_compound()) { | 1214 if (expr->is_compound()) { |
| 1215 Location saved_location = location_; | 1215 Location saved_location = location_; |
| 1216 location_ = kAccumulator; | 1216 location_ = kAccumulator; |
| 1217 EmitBinaryOp(expr->binary_op(), Expression::kValue); | 1217 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1218 ? OVERWRITE_RIGHT |
| 1219 : NO_OVERWRITE; |
| 1220 EmitBinaryOp(expr->binary_op(), Expression::kValue, mode); |
| 1218 location_ = saved_location; | 1221 location_ = saved_location; |
| 1219 } | 1222 } |
| 1220 | 1223 |
| 1221 // Record source position before possible IC call. | 1224 // Record source position before possible IC call. |
| 1222 SetSourcePosition(expr->position()); | 1225 SetSourcePosition(expr->position()); |
| 1223 | 1226 |
| 1224 // Store the value. | 1227 // Store the value. |
| 1225 switch (assign_type) { | 1228 switch (assign_type) { |
| 1226 case VARIABLE: | 1229 case VARIABLE: |
| 1227 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1230 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1250 | 1253 |
| 1251 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1254 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 1252 SetSourcePosition(prop->position()); | 1255 SetSourcePosition(prop->position()); |
| 1253 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1256 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1254 __ call(ic, RelocInfo::CODE_TARGET); | 1257 __ call(ic, RelocInfo::CODE_TARGET); |
| 1255 __ nop(); | 1258 __ nop(); |
| 1256 } | 1259 } |
| 1257 | 1260 |
| 1258 | 1261 |
| 1259 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1262 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
| 1260 Expression::Context context) { | 1263 Expression::Context context, |
| 1261 __ push(result_register()); | 1264 OverwriteMode mode) { |
| 1262 GenericBinaryOpStub stub(op, | 1265 TypeInfo type = TypeInfo::Unknown(); |
| 1263 NO_OVERWRITE, | 1266 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS, type); |
| 1264 NO_GENERIC_BINARY_FLAGS, | 1267 if (stub.ArgsInRegistersSupported()) { |
| 1265 TypeInfo::Unknown()); | 1268 __ pop(edx); |
| 1266 __ CallStub(&stub); | 1269 stub.GenerateCall(masm_, edx, eax); |
| 1270 } else { |
| 1271 __ push(result_register()); |
| 1272 __ CallStub(&stub); |
| 1273 } |
| 1267 Apply(context, eax); | 1274 Apply(context, eax); |
| 1268 } | 1275 } |
| 1269 | 1276 |
| 1270 | 1277 |
| 1271 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1278 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 1272 // Invalid left-hand sides are rewritten to have a 'throw | 1279 // Invalid left-hand sides are rewritten to have a 'throw |
| 1273 // ReferenceError' on the left-hand side. | 1280 // ReferenceError' on the left-hand side. |
| 1274 if (!expr->IsValidLeftHandSide()) { | 1281 if (!expr->IsValidLeftHandSide()) { |
| 1275 VisitForEffect(expr); | 1282 VisitForEffect(expr); |
| 1276 return; | 1283 return; |
| (...skipping 1367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2644 __ j(zero, &no_conversion); | 2651 __ j(zero, &no_conversion); |
| 2645 __ push(result_register()); | 2652 __ push(result_register()); |
| 2646 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 2653 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
| 2647 __ bind(&no_conversion); | 2654 __ bind(&no_conversion); |
| 2648 Apply(context_, result_register()); | 2655 Apply(context_, result_register()); |
| 2649 break; | 2656 break; |
| 2650 } | 2657 } |
| 2651 | 2658 |
| 2652 case Token::SUB: { | 2659 case Token::SUB: { |
| 2653 Comment cmt(masm_, "[ UnaryOperation (SUB)"); | 2660 Comment cmt(masm_, "[ UnaryOperation (SUB)"); |
| 2654 bool can_overwrite = | 2661 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
| 2655 (expr->expression()->AsBinaryOperation() != NULL && | |
| 2656 expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | |
| 2657 UnaryOverwriteMode overwrite = | 2662 UnaryOverwriteMode overwrite = |
| 2658 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 2663 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
| 2659 GenericUnaryOpStub stub(Token::SUB, overwrite); | 2664 GenericUnaryOpStub stub(Token::SUB, overwrite); |
| 2660 // GenericUnaryOpStub expects the argument to be in the | 2665 // GenericUnaryOpStub expects the argument to be in the |
| 2661 // accumulator register eax. | 2666 // accumulator register eax. |
| 2662 VisitForValue(expr->expression(), kAccumulator); | 2667 VisitForValue(expr->expression(), kAccumulator); |
| 2663 __ CallStub(&stub); | 2668 __ CallStub(&stub); |
| 2664 Apply(context_, eax); | 2669 Apply(context_, eax); |
| 2665 break; | 2670 break; |
| 2666 } | 2671 } |
| 2667 | 2672 |
| 2668 case Token::BIT_NOT: { | 2673 case Token::BIT_NOT: { |
| 2669 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); | 2674 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); |
| 2670 bool can_overwrite = | 2675 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
| 2671 (expr->expression()->AsBinaryOperation() != NULL && | |
| 2672 expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | |
| 2673 UnaryOverwriteMode overwrite = | 2676 UnaryOverwriteMode overwrite = |
| 2674 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 2677 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
| 2675 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); | 2678 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |
| 2676 // GenericUnaryOpStub expects the argument to be in the | 2679 // GenericUnaryOpStub expects the argument to be in the |
| 2677 // accumulator register eax. | 2680 // accumulator register eax. |
| 2678 VisitForValue(expr->expression(), kAccumulator); | 2681 VisitForValue(expr->expression(), kAccumulator); |
| 2679 // Avoid calling the stub for Smis. | 2682 // Avoid calling the stub for Smis. |
| 2680 Label smi, done; | 2683 Label smi, done; |
| 2681 __ test(result_register(), Immediate(kSmiTagMask)); | 2684 __ test(result_register(), Immediate(kSmiTagMask)); |
| 2682 __ j(zero, &smi); | 2685 __ j(zero, &smi); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2743 VisitForValue(prop->obj(), kStack); | 2746 VisitForValue(prop->obj(), kStack); |
| 2744 VisitForValue(prop->key(), kAccumulator); | 2747 VisitForValue(prop->key(), kAccumulator); |
| 2745 __ mov(edx, Operand(esp, 0)); | 2748 __ mov(edx, Operand(esp, 0)); |
| 2746 __ push(eax); | 2749 __ push(eax); |
| 2747 EmitKeyedPropertyLoad(prop); | 2750 EmitKeyedPropertyLoad(prop); |
| 2748 } | 2751 } |
| 2749 } | 2752 } |
| 2750 | 2753 |
| 2751 // Call ToNumber only if operand is not a smi. | 2754 // Call ToNumber only if operand is not a smi. |
| 2752 Label no_conversion; | 2755 Label no_conversion; |
| 2753 __ test(eax, Immediate(kSmiTagMask)); | 2756 if (ShouldInlineSmiCase(expr->op())) { |
| 2754 __ j(zero, &no_conversion); | 2757 __ test(eax, Immediate(kSmiTagMask)); |
| 2758 __ j(zero, &no_conversion); |
| 2759 } |
| 2755 __ push(eax); | 2760 __ push(eax); |
| 2756 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 2761 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
| 2757 __ bind(&no_conversion); | 2762 __ bind(&no_conversion); |
| 2758 | 2763 |
| 2759 // Save result for postfix expressions. | 2764 // Save result for postfix expressions. |
| 2760 if (expr->is_postfix()) { | 2765 if (expr->is_postfix()) { |
| 2761 switch (context_) { | 2766 switch (context_) { |
| 2762 case Expression::kUninitialized: | 2767 case Expression::kUninitialized: |
| 2763 UNREACHABLE(); | 2768 UNREACHABLE(); |
| 2764 case Expression::kEffect: | 2769 case Expression::kEffect: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2779 case KEYED_PROPERTY: | 2784 case KEYED_PROPERTY: |
| 2780 __ mov(Operand(esp, 2 * kPointerSize), eax); | 2785 __ mov(Operand(esp, 2 * kPointerSize), eax); |
| 2781 break; | 2786 break; |
| 2782 } | 2787 } |
| 2783 break; | 2788 break; |
| 2784 } | 2789 } |
| 2785 } | 2790 } |
| 2786 | 2791 |
| 2787 // Inline smi case if we are in a loop. | 2792 // Inline smi case if we are in a loop. |
| 2788 Label stub_call, done; | 2793 Label stub_call, done; |
| 2789 if (loop_depth() > 0) { | 2794 if (ShouldInlineSmiCase(expr->op())) { |
| 2790 if (expr->op() == Token::INC) { | 2795 if (expr->op() == Token::INC) { |
| 2791 __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 2796 __ add(Operand(eax), Immediate(Smi::FromInt(1))); |
| 2792 } else { | 2797 } else { |
| 2793 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 2798 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); |
| 2794 } | 2799 } |
| 2795 __ j(overflow, &stub_call); | 2800 __ j(overflow, &stub_call); |
| 2796 // We could eliminate this smi check if we split the code at | 2801 // We could eliminate this smi check if we split the code at |
| 2797 // the first smi check before calling ToNumber. | 2802 // the first smi check before calling ToNumber. |
| 2798 __ test(eax, Immediate(kSmiTagMask)); | 2803 __ test(eax, Immediate(kSmiTagMask)); |
| 2799 __ j(zero, &done); | 2804 __ j(zero, &done); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3020 __ test(eax, Operand(eax)); | 3025 __ test(eax, Operand(eax)); |
| 3021 // The stub returns 0 for true. | 3026 // The stub returns 0 for true. |
| 3022 Split(zero, if_true, if_false, fall_through); | 3027 Split(zero, if_true, if_false, fall_through); |
| 3023 break; | 3028 break; |
| 3024 } | 3029 } |
| 3025 | 3030 |
| 3026 default: { | 3031 default: { |
| 3027 VisitForValue(expr->right(), kAccumulator); | 3032 VisitForValue(expr->right(), kAccumulator); |
| 3028 Condition cc = no_condition; | 3033 Condition cc = no_condition; |
| 3029 bool strict = false; | 3034 bool strict = false; |
| 3030 switch (expr->op()) { | 3035 switch (op) { |
| 3031 case Token::EQ_STRICT: | 3036 case Token::EQ_STRICT: |
| 3032 strict = true; | 3037 strict = true; |
| 3033 // Fall through | 3038 // Fall through |
| 3034 case Token::EQ: | 3039 case Token::EQ: |
| 3035 cc = equal; | 3040 cc = equal; |
| 3036 __ pop(edx); | 3041 __ pop(edx); |
| 3037 break; | 3042 break; |
| 3038 case Token::LT: | 3043 case Token::LT: |
| 3039 cc = less; | 3044 cc = less; |
| 3040 __ pop(edx); | 3045 __ pop(edx); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3054 case Token::GTE: | 3059 case Token::GTE: |
| 3055 cc = greater_equal; | 3060 cc = greater_equal; |
| 3056 __ pop(edx); | 3061 __ pop(edx); |
| 3057 break; | 3062 break; |
| 3058 case Token::IN: | 3063 case Token::IN: |
| 3059 case Token::INSTANCEOF: | 3064 case Token::INSTANCEOF: |
| 3060 default: | 3065 default: |
| 3061 UNREACHABLE(); | 3066 UNREACHABLE(); |
| 3062 } | 3067 } |
| 3063 | 3068 |
| 3064 // The comparison stub expects the smi vs. smi case to be handled | 3069 // The comparison stub expects the smi vs. smi case to be |
| 3065 // before it is called. | 3070 // handled before it is called. |
| 3066 Label slow_case; | 3071 Label slow_case; |
| 3067 __ mov(ecx, Operand(edx)); | 3072 __ mov(ecx, Operand(edx)); |
| 3068 __ or_(ecx, Operand(eax)); | 3073 __ or_(ecx, Operand(eax)); |
| 3069 __ test(ecx, Immediate(kSmiTagMask)); | 3074 __ test(ecx, Immediate(kSmiTagMask)); |
| 3070 __ j(not_zero, &slow_case, not_taken); | 3075 __ j(not_zero, &slow_case, not_taken); |
| 3071 __ cmp(edx, Operand(eax)); | 3076 __ cmp(edx, Operand(eax)); |
| 3072 __ j(cc, if_true); | 3077 __ j(cc, if_true); |
| 3073 __ jmp(if_false); | 3078 __ jmp(if_false); |
| 3074 | 3079 |
| 3075 __ bind(&slow_case); | 3080 __ bind(&slow_case); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3166 // And return. | 3171 // And return. |
| 3167 __ ret(0); | 3172 __ ret(0); |
| 3168 } | 3173 } |
| 3169 | 3174 |
| 3170 | 3175 |
| 3171 #undef __ | 3176 #undef __ |
| 3172 | 3177 |
| 3173 } } // namespace v8::internal | 3178 } } // namespace v8::internal |
| 3174 | 3179 |
| 3175 #endif // V8_TARGET_ARCH_IA32 | 3180 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |