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