OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1200 } | 1200 } |
1201 | 1201 |
1202 // Evaluate RHS expression. | 1202 // Evaluate RHS expression. |
1203 Expression* rhs = expr->value(); | 1203 Expression* rhs = expr->value(); |
1204 VisitForValue(rhs, kAccumulator); | 1204 VisitForValue(rhs, kAccumulator); |
1205 | 1205 |
1206 // If we have a compound assignment: Apply operator. | 1206 // If we have a compound assignment: Apply operator. |
1207 if (expr->is_compound()) { | 1207 if (expr->is_compound()) { |
1208 Location saved_location = location_; | 1208 Location saved_location = location_; |
1209 location_ = kAccumulator; | 1209 location_ = kAccumulator; |
1210 EmitBinaryOp(expr->binary_op(), Expression::kValue); | 1210 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1211 ? OVERWRITE_RIGHT |
| 1212 : NO_OVERWRITE; |
| 1213 EmitBinaryOp(expr->binary_op(), Expression::kValue, mode); |
1211 location_ = saved_location; | 1214 location_ = saved_location; |
1212 } | 1215 } |
1213 | 1216 |
1214 // Record source position before possible IC call. | 1217 // Record source position before possible IC call. |
1215 SetSourcePosition(expr->position()); | 1218 SetSourcePosition(expr->position()); |
1216 | 1219 |
1217 // Store the value. | 1220 // Store the value. |
1218 switch (assign_type) { | 1221 switch (assign_type) { |
1219 case VARIABLE: | 1222 case VARIABLE: |
1220 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1223 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
(...skipping 22 matching lines...) Expand all Loading... |
1243 | 1246 |
1244 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1247 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1245 SetSourcePosition(prop->position()); | 1248 SetSourcePosition(prop->position()); |
1246 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1249 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
1247 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1250 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1248 __ Call(ic, RelocInfo::CODE_TARGET); | 1251 __ Call(ic, RelocInfo::CODE_TARGET); |
1249 } | 1252 } |
1250 | 1253 |
1251 | 1254 |
1252 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1255 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1253 Expression::Context context) { | 1256 Expression::Context context, |
| 1257 OverwriteMode mode) { |
1254 __ pop(r1); | 1258 __ pop(r1); |
1255 GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0); | 1259 GenericBinaryOpStub stub(op, mode, r1, r0); |
1256 __ CallStub(&stub); | 1260 __ CallStub(&stub); |
1257 Apply(context, r0); | 1261 Apply(context, r0); |
1258 } | 1262 } |
1259 | 1263 |
1260 | 1264 |
1261 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1265 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
1262 // Invalid left-hand sides are rewritten to have a 'throw | 1266 // Invalid left-hand sides are rewritten to have a 'throw |
1263 // ReferenceError' on the left-hand side. | 1267 // ReferenceError' on the left-hand side. |
1264 if (!expr->IsValidLeftHandSide()) { | 1268 if (!expr->IsValidLeftHandSide()) { |
1265 VisitForEffect(expr); | 1269 VisitForEffect(expr); |
(...skipping 1381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2647 __ b(eq, &no_conversion); | 2651 __ b(eq, &no_conversion); |
2648 __ push(r0); | 2652 __ push(r0); |
2649 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); | 2653 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); |
2650 __ bind(&no_conversion); | 2654 __ bind(&no_conversion); |
2651 Apply(context_, result_register()); | 2655 Apply(context_, result_register()); |
2652 break; | 2656 break; |
2653 } | 2657 } |
2654 | 2658 |
2655 case Token::SUB: { | 2659 case Token::SUB: { |
2656 Comment cmt(masm_, "[ UnaryOperation (SUB)"); | 2660 Comment cmt(masm_, "[ UnaryOperation (SUB)"); |
2657 bool can_overwrite = | 2661 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
2658 (expr->expression()->AsBinaryOperation() != NULL && | |
2659 expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | |
2660 UnaryOverwriteMode overwrite = | 2662 UnaryOverwriteMode overwrite = |
2661 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 2663 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
2662 GenericUnaryOpStub stub(Token::SUB, overwrite); | 2664 GenericUnaryOpStub stub(Token::SUB, overwrite); |
2663 // GenericUnaryOpStub expects the argument to be in the | 2665 // GenericUnaryOpStub expects the argument to be in the |
2664 // accumulator register r0. | 2666 // accumulator register r0. |
2665 VisitForValue(expr->expression(), kAccumulator); | 2667 VisitForValue(expr->expression(), kAccumulator); |
2666 __ CallStub(&stub); | 2668 __ CallStub(&stub); |
2667 Apply(context_, r0); | 2669 Apply(context_, r0); |
2668 break; | 2670 break; |
2669 } | 2671 } |
2670 | 2672 |
2671 case Token::BIT_NOT: { | 2673 case Token::BIT_NOT: { |
2672 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); | 2674 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); |
2673 bool can_overwrite = | 2675 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
2674 (expr->expression()->AsBinaryOperation() != NULL && | |
2675 expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | |
2676 UnaryOverwriteMode overwrite = | 2676 UnaryOverwriteMode overwrite = |
2677 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 2677 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
2678 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); | 2678 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |
2679 // GenericUnaryOpStub expects the argument to be in the | 2679 // GenericUnaryOpStub expects the argument to be in the |
2680 // accumulator register r0. | 2680 // accumulator register r0. |
2681 VisitForValue(expr->expression(), kAccumulator); | 2681 VisitForValue(expr->expression(), kAccumulator); |
2682 // Avoid calling the stub for Smis. | 2682 // Avoid calling the stub for Smis. |
2683 Label smi, done; | 2683 Label smi, done; |
2684 __ BranchOnSmi(result_register(), &smi); | 2684 __ BranchOnSmi(result_register(), &smi); |
2685 // Non-smi: call stub leaving result in accumulator register. | 2685 // Non-smi: call stub leaving result in accumulator register. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2784 break; | 2784 break; |
2785 } | 2785 } |
2786 break; | 2786 break; |
2787 } | 2787 } |
2788 } | 2788 } |
2789 | 2789 |
2790 | 2790 |
2791 // Inline smi case if we are in a loop. | 2791 // Inline smi case if we are in a loop. |
2792 Label stub_call, done; | 2792 Label stub_call, done; |
2793 int count_value = expr->op() == Token::INC ? 1 : -1; | 2793 int count_value = expr->op() == Token::INC ? 1 : -1; |
2794 if (loop_depth() > 0) { | 2794 if (ShouldInlineSmiCase(expr->op())) { |
2795 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); | 2795 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); |
2796 __ b(vs, &stub_call); | 2796 __ b(vs, &stub_call); |
2797 // We could eliminate this smi check if we split the code at | 2797 // We could eliminate this smi check if we split the code at |
2798 // the first smi check before calling ToNumber. | 2798 // the first smi check before calling ToNumber. |
2799 __ BranchOnSmi(r0, &done); | 2799 __ BranchOnSmi(r0, &done); |
2800 __ bind(&stub_call); | 2800 __ bind(&stub_call); |
2801 // Call stub. Undo operation first. | 2801 // Call stub. Undo operation first. |
2802 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); | 2802 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); |
2803 } | 2803 } |
2804 __ mov(r1, Operand(Smi::FromInt(count_value))); | 2804 __ mov(r1, Operand(Smi::FromInt(count_value))); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2991 // the operands is a literal. | 2991 // the operands is a literal. |
2992 Token::Value op = expr->op(); | 2992 Token::Value op = expr->op(); |
2993 Expression* left = expr->left(); | 2993 Expression* left = expr->left(); |
2994 Expression* right = expr->right(); | 2994 Expression* right = expr->right(); |
2995 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { | 2995 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { |
2996 Apply(context_, if_true, if_false); | 2996 Apply(context_, if_true, if_false); |
2997 return; | 2997 return; |
2998 } | 2998 } |
2999 | 2999 |
3000 VisitForValue(expr->left(), kStack); | 3000 VisitForValue(expr->left(), kStack); |
3001 switch (expr->op()) { | 3001 switch (op) { |
3002 case Token::IN: | 3002 case Token::IN: |
3003 VisitForValue(expr->right(), kStack); | 3003 VisitForValue(expr->right(), kStack); |
3004 __ InvokeBuiltin(Builtins::IN, CALL_JS); | 3004 __ InvokeBuiltin(Builtins::IN, CALL_JS); |
3005 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 3005 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
3006 __ cmp(r0, ip); | 3006 __ cmp(r0, ip); |
3007 Split(eq, if_true, if_false, fall_through); | 3007 Split(eq, if_true, if_false, fall_through); |
3008 break; | 3008 break; |
3009 | 3009 |
3010 case Token::INSTANCEOF: { | 3010 case Token::INSTANCEOF: { |
3011 VisitForValue(expr->right(), kStack); | 3011 VisitForValue(expr->right(), kStack); |
3012 InstanceofStub stub; | 3012 InstanceofStub stub; |
3013 __ CallStub(&stub); | 3013 __ CallStub(&stub); |
3014 // The stub returns 0 for true. | 3014 // The stub returns 0 for true. |
3015 __ tst(r0, r0); | 3015 __ tst(r0, r0); |
3016 Split(eq, if_true, if_false, fall_through); | 3016 Split(eq, if_true, if_false, fall_through); |
3017 break; | 3017 break; |
3018 } | 3018 } |
3019 | 3019 |
3020 default: { | 3020 default: { |
3021 VisitForValue(expr->right(), kAccumulator); | 3021 VisitForValue(expr->right(), kAccumulator); |
3022 Condition cc = eq; | 3022 Condition cc = eq; |
3023 bool strict = false; | 3023 bool strict = false; |
3024 switch (expr->op()) { | 3024 switch (op) { |
3025 case Token::EQ_STRICT: | 3025 case Token::EQ_STRICT: |
3026 strict = true; | 3026 strict = true; |
3027 // Fall through | 3027 // Fall through |
3028 case Token::EQ: | 3028 case Token::EQ: |
3029 cc = eq; | 3029 cc = eq; |
3030 __ pop(r1); | 3030 __ pop(r1); |
3031 break; | 3031 break; |
3032 case Token::LT: | 3032 case Token::LT: |
3033 cc = lt; | 3033 cc = lt; |
3034 __ pop(r1); | 3034 __ pop(r1); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3159 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3159 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
3160 __ add(pc, r1, Operand(masm_->CodeObject())); | 3160 __ add(pc, r1, Operand(masm_->CodeObject())); |
3161 } | 3161 } |
3162 | 3162 |
3163 | 3163 |
3164 #undef __ | 3164 #undef __ |
3165 | 3165 |
3166 } } // namespace v8::internal | 3166 } } // namespace v8::internal |
3167 | 3167 |
3168 #endif // V8_TARGET_ARCH_ARM | 3168 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |