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