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 |