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 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 } | 1211 } |
1212 | 1212 |
1213 // Evaluate RHS expression. | 1213 // Evaluate RHS expression. |
1214 Expression* rhs = expr->value(); | 1214 Expression* rhs = expr->value(); |
1215 VisitForValue(rhs, kAccumulator); | 1215 VisitForValue(rhs, kAccumulator); |
1216 | 1216 |
1217 // If we have a compound assignment: Apply operator. | 1217 // If we have a compound assignment: Apply operator. |
1218 if (expr->is_compound()) { | 1218 if (expr->is_compound()) { |
1219 Location saved_location = location_; | 1219 Location saved_location = location_; |
1220 location_ = kAccumulator; | 1220 location_ = kAccumulator; |
1221 EmitBinaryOp(expr->binary_op(), Expression::kValue); | 1221 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1222 ? OVERWRITE_RIGHT |
| 1223 : NO_OVERWRITE; |
| 1224 EmitBinaryOp(expr->binary_op(), Expression::kValue, mode); |
1222 location_ = saved_location; | 1225 location_ = saved_location; |
1223 } | 1226 } |
1224 | 1227 |
1225 // Record source position before possible IC call. | 1228 // Record source position before possible IC call. |
1226 SetSourcePosition(expr->position()); | 1229 SetSourcePosition(expr->position()); |
1227 | 1230 |
1228 // Store the value. | 1231 // Store the value. |
1229 switch (assign_type) { | 1232 switch (assign_type) { |
1230 case VARIABLE: | 1233 case VARIABLE: |
1231 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1234 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
(...skipping 22 matching lines...) Expand all Loading... |
1254 | 1257 |
1255 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1258 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1256 SetSourcePosition(prop->position()); | 1259 SetSourcePosition(prop->position()); |
1257 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1260 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1258 __ Call(ic, RelocInfo::CODE_TARGET); | 1261 __ Call(ic, RelocInfo::CODE_TARGET); |
1259 __ nop(); | 1262 __ nop(); |
1260 } | 1263 } |
1261 | 1264 |
1262 | 1265 |
1263 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1266 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1264 Expression::Context context) { | 1267 Expression::Context context, |
1265 __ push(result_register()); | 1268 OverwriteMode mode) { |
1266 GenericBinaryOpStub stub(op, | 1269 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS); |
1267 NO_OVERWRITE, | 1270 if (stub.ArgsInRegistersSupported()) { |
1268 NO_GENERIC_BINARY_FLAGS); | 1271 __ pop(rdx); |
1269 __ CallStub(&stub); | 1272 stub.GenerateCall(masm_, rdx, rax); |
| 1273 } else { |
| 1274 __ push(result_register()); |
| 1275 __ CallStub(&stub); |
| 1276 } |
1270 Apply(context, rax); | 1277 Apply(context, rax); |
1271 } | 1278 } |
1272 | 1279 |
1273 | 1280 |
1274 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1281 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
1275 // Invalid left-hand sides are rewritten to have a 'throw | 1282 // Invalid left-hand sides are rewritten to have a 'throw |
1276 // ReferenceError' on the left-hand side. | 1283 // ReferenceError' on the left-hand side. |
1277 if (!expr->IsValidLeftHandSide()) { | 1284 if (!expr->IsValidLeftHandSide()) { |
1278 VisitForEffect(expr); | 1285 VisitForEffect(expr); |
1279 return; | 1286 return; |
(...skipping 1359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2639 __ j(is_smi, &no_conversion); | 2646 __ j(is_smi, &no_conversion); |
2640 __ push(result_register()); | 2647 __ push(result_register()); |
2641 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 2648 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
2642 __ bind(&no_conversion); | 2649 __ bind(&no_conversion); |
2643 Apply(context_, result_register()); | 2650 Apply(context_, result_register()); |
2644 break; | 2651 break; |
2645 } | 2652 } |
2646 | 2653 |
2647 case Token::SUB: { | 2654 case Token::SUB: { |
2648 Comment cmt(masm_, "[ UnaryOperation (SUB)"); | 2655 Comment cmt(masm_, "[ UnaryOperation (SUB)"); |
2649 bool can_overwrite = | 2656 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
2650 (expr->expression()->AsBinaryOperation() != NULL && | |
2651 expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | |
2652 UnaryOverwriteMode overwrite = | 2657 UnaryOverwriteMode overwrite = |
2653 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 2658 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
2654 GenericUnaryOpStub stub(Token::SUB, overwrite); | 2659 GenericUnaryOpStub stub(Token::SUB, overwrite); |
2655 // GenericUnaryOpStub expects the argument to be in the | 2660 // GenericUnaryOpStub expects the argument to be in the |
2656 // accumulator register rax. | 2661 // accumulator register rax. |
2657 VisitForValue(expr->expression(), kAccumulator); | 2662 VisitForValue(expr->expression(), kAccumulator); |
2658 __ CallStub(&stub); | 2663 __ CallStub(&stub); |
2659 Apply(context_, rax); | 2664 Apply(context_, rax); |
2660 break; | 2665 break; |
2661 } | 2666 } |
2662 | 2667 |
2663 case Token::BIT_NOT: { | 2668 case Token::BIT_NOT: { |
2664 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); | 2669 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); |
2665 bool can_overwrite = | 2670 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
2666 (expr->expression()->AsBinaryOperation() != NULL && | |
2667 expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | |
2668 UnaryOverwriteMode overwrite = | 2671 UnaryOverwriteMode overwrite = |
2669 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 2672 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
2670 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); | 2673 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |
2671 // GenericUnaryOpStub expects the argument to be in the | 2674 // GenericUnaryOpStub expects the argument to be in the |
2672 // accumulator register rax. | 2675 // accumulator register rax. |
2673 VisitForValue(expr->expression(), kAccumulator); | 2676 VisitForValue(expr->expression(), kAccumulator); |
2674 // Avoid calling the stub for Smis. | 2677 // Avoid calling the stub for Smis. |
2675 Label smi, done; | 2678 Label smi, done; |
2676 Condition is_smi = masm_->CheckSmi(result_register()); | 2679 Condition is_smi = masm_->CheckSmi(result_register()); |
2677 __ j(is_smi, &smi); | 2680 __ j(is_smi, &smi); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2773 case KEYED_PROPERTY: | 2776 case KEYED_PROPERTY: |
2774 __ movq(Operand(rsp, 2 * kPointerSize), rax); | 2777 __ movq(Operand(rsp, 2 * kPointerSize), rax); |
2775 break; | 2778 break; |
2776 } | 2779 } |
2777 break; | 2780 break; |
2778 } | 2781 } |
2779 } | 2782 } |
2780 | 2783 |
2781 // Inline smi case if we are in a loop. | 2784 // Inline smi case if we are in a loop. |
2782 Label stub_call, done; | 2785 Label stub_call, done; |
2783 if (loop_depth() > 0) { | 2786 if (ShouldInlineSmiCase(expr->op())) { |
2784 if (expr->op() == Token::INC) { | 2787 if (expr->op() == Token::INC) { |
2785 __ SmiAddConstant(rax, rax, Smi::FromInt(1)); | 2788 __ SmiAddConstant(rax, rax, Smi::FromInt(1)); |
2786 } else { | 2789 } else { |
2787 __ SmiSubConstant(rax, rax, Smi::FromInt(1)); | 2790 __ SmiSubConstant(rax, rax, Smi::FromInt(1)); |
2788 } | 2791 } |
2789 __ j(overflow, &stub_call); | 2792 __ j(overflow, &stub_call); |
2790 // We could eliminate this smi check if we split the code at | 2793 // We could eliminate this smi check if we split the code at |
2791 // the first smi check before calling ToNumber. | 2794 // the first smi check before calling ToNumber. |
2792 is_smi = masm_->CheckSmi(rax); | 2795 is_smi = masm_->CheckSmi(rax); |
2793 __ j(is_smi, &done); | 2796 __ j(is_smi, &done); |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2988 // the operands is a literal. | 2991 // the operands is a literal. |
2989 Token::Value op = expr->op(); | 2992 Token::Value op = expr->op(); |
2990 Expression* left = expr->left(); | 2993 Expression* left = expr->left(); |
2991 Expression* right = expr->right(); | 2994 Expression* right = expr->right(); |
2992 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { | 2995 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { |
2993 Apply(context_, if_true, if_false); | 2996 Apply(context_, if_true, if_false); |
2994 return; | 2997 return; |
2995 } | 2998 } |
2996 | 2999 |
2997 VisitForValue(expr->left(), kStack); | 3000 VisitForValue(expr->left(), kStack); |
2998 switch (expr->op()) { | 3001 switch (op) { |
2999 case Token::IN: | 3002 case Token::IN: |
3000 VisitForValue(expr->right(), kStack); | 3003 VisitForValue(expr->right(), kStack); |
3001 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 3004 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
3002 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 3005 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
3003 Split(equal, if_true, if_false, fall_through); | 3006 Split(equal, if_true, if_false, fall_through); |
3004 break; | 3007 break; |
3005 | 3008 |
3006 case Token::INSTANCEOF: { | 3009 case Token::INSTANCEOF: { |
3007 VisitForValue(expr->right(), kStack); | 3010 VisitForValue(expr->right(), kStack); |
3008 InstanceofStub stub; | 3011 InstanceofStub stub; |
3009 __ CallStub(&stub); | 3012 __ CallStub(&stub); |
3010 __ testq(rax, rax); | 3013 __ testq(rax, rax); |
3011 // The stub returns 0 for true. | 3014 // The stub returns 0 for true. |
3012 Split(zero, if_true, if_false, fall_through); | 3015 Split(zero, if_true, if_false, fall_through); |
3013 break; | 3016 break; |
3014 } | 3017 } |
3015 | 3018 |
3016 default: { | 3019 default: { |
3017 VisitForValue(expr->right(), kAccumulator); | 3020 VisitForValue(expr->right(), kAccumulator); |
3018 Condition cc = no_condition; | 3021 Condition cc = no_condition; |
3019 bool strict = false; | 3022 bool strict = false; |
3020 switch (expr->op()) { | 3023 switch (op) { |
3021 case Token::EQ_STRICT: | 3024 case Token::EQ_STRICT: |
3022 strict = true; | 3025 strict = true; |
3023 // Fall through. | 3026 // Fall through. |
3024 case Token::EQ: | 3027 case Token::EQ: |
3025 cc = equal; | 3028 cc = equal; |
3026 __ pop(rdx); | 3029 __ pop(rdx); |
3027 break; | 3030 break; |
3028 case Token::LT: | 3031 case Token::LT: |
3029 cc = less; | 3032 cc = less; |
3030 __ pop(rdx); | 3033 __ pop(rdx); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3158 __ ret(0); | 3161 __ ret(0); |
3159 } | 3162 } |
3160 | 3163 |
3161 | 3164 |
3162 #undef __ | 3165 #undef __ |
3163 | 3166 |
3164 | 3167 |
3165 } } // namespace v8::internal | 3168 } } // namespace v8::internal |
3166 | 3169 |
3167 #endif // V8_TARGET_ARCH_X64 | 3170 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |