| 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 2664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2675 // side, that are easy to test for: the right hand side is a literal, | 2675 // side, that are easy to test for: the right hand side is a literal, |
| 2676 // or the right hand side is a different variable. TakeValue invalidates | 2676 // or the right hand side is a different variable. TakeValue invalidates |
| 2677 // the target, with an implicit promise that it will be written to again | 2677 // the target, with an implicit promise that it will be written to again |
| 2678 // before it is read. | 2678 // before it is read. |
| 2679 if (literal != NULL || (right_var != NULL && right_var != var)) { | 2679 if (literal != NULL || (right_var != NULL && right_var != var)) { |
| 2680 target.TakeValue(); | 2680 target.TakeValue(); |
| 2681 } else { | 2681 } else { |
| 2682 target.GetValue(); | 2682 target.GetValue(); |
| 2683 } | 2683 } |
| 2684 Load(node->value()); | 2684 Load(node->value()); |
| 2685 GenericBinaryOperation(node->binary_op(), | 2685 BinaryOperation expr(node, node->binary_op(), node->target(), |
| 2686 node->type(), | 2686 node->value()); |
| 2687 GenericBinaryOperation(&expr, |
| 2687 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 2688 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
| 2688 } | 2689 } |
| 2689 | 2690 |
| 2690 if (var != NULL && | 2691 if (var != NULL && |
| 2691 var->mode() == Variable::CONST && | 2692 var->mode() == Variable::CONST && |
| 2692 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { | 2693 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { |
| 2693 // Assignment ignored - leave the value on the stack. | 2694 // Assignment ignored - leave the value on the stack. |
| 2694 UnloadReference(&target); | 2695 UnloadReference(&target); |
| 2695 } else { | 2696 } else { |
| 2696 CodeForSourcePosition(node->position()); | 2697 CodeForSourcePosition(node->position()); |
| (...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3533 | 3534 |
| 3534 if (node->left()->IsTrivial()) { | 3535 if (node->left()->IsTrivial()) { |
| 3535 Load(node->right()); | 3536 Load(node->right()); |
| 3536 Result right = frame_->Pop(); | 3537 Result right = frame_->Pop(); |
| 3537 frame_->Push(node->left()); | 3538 frame_->Push(node->left()); |
| 3538 frame_->Push(&right); | 3539 frame_->Push(&right); |
| 3539 } else { | 3540 } else { |
| 3540 Load(node->left()); | 3541 Load(node->left()); |
| 3541 Load(node->right()); | 3542 Load(node->right()); |
| 3542 } | 3543 } |
| 3543 GenericBinaryOperation(node->op(), node->type(), overwrite_mode); | 3544 GenericBinaryOperation(node, overwrite_mode); |
| 3544 } | 3545 } |
| 3545 } | 3546 } |
| 3546 | 3547 |
| 3547 | 3548 |
| 3548 | 3549 |
| 3549 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 3550 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
| 3550 Comment cmnt(masm_, "[ CompareOperation"); | 3551 Comment cmnt(masm_, "[ CompareOperation"); |
| 3551 | 3552 |
| 3552 // Get the expressions from the node. | 3553 // Get the expressions from the node. |
| 3553 Expression* left = node->left(); | 3554 Expression* left = node->left(); |
| (...skipping 2531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6085 // Result is always a number. | 6086 // Result is always a number. |
| 6086 return TypeInfo::Number(); | 6087 return TypeInfo::Number(); |
| 6087 default: | 6088 default: |
| 6088 UNREACHABLE(); | 6089 UNREACHABLE(); |
| 6089 } | 6090 } |
| 6090 UNREACHABLE(); | 6091 UNREACHABLE(); |
| 6091 return TypeInfo::Unknown(); | 6092 return TypeInfo::Unknown(); |
| 6092 } | 6093 } |
| 6093 | 6094 |
| 6094 | 6095 |
| 6095 void CodeGenerator::GenericBinaryOperation(Token::Value op, | 6096 void CodeGenerator::GenericBinaryOperation(BinaryOperation* expr, |
| 6096 StaticType* type, | |
| 6097 OverwriteMode overwrite_mode) { | 6097 OverwriteMode overwrite_mode) { |
| 6098 Comment cmnt(masm_, "[ BinaryOperation"); | 6098 Comment cmnt(masm_, "[ BinaryOperation"); |
| 6099 Token::Value op = expr->op(); |
| 6099 Comment cmnt_token(masm_, Token::String(op)); | 6100 Comment cmnt_token(masm_, Token::String(op)); |
| 6100 | 6101 |
| 6101 if (op == Token::COMMA) { | 6102 if (op == Token::COMMA) { |
| 6102 // Simply discard left value. | 6103 // Simply discard left value. |
| 6103 frame_->Nip(1); | 6104 frame_->Nip(1); |
| 6104 return; | 6105 return; |
| 6105 } | 6106 } |
| 6106 | 6107 |
| 6107 Result right = frame_->Pop(); | 6108 Result right = frame_->Pop(); |
| 6108 Result left = frame_->Pop(); | 6109 Result left = frame_->Pop(); |
| 6109 | 6110 |
| 6110 if (op == Token::ADD) { | 6111 if (op == Token::ADD) { |
| 6111 const bool left_is_string = left.type_info().IsString(); | 6112 const bool left_is_string = left.type_info().IsString(); |
| 6112 const bool right_is_string = right.type_info().IsString(); | 6113 const bool right_is_string = right.type_info().IsString(); |
| 6113 // Make sure constant strings have string type info. | 6114 // Make sure constant strings have string type info. |
| 6114 ASSERT(!(left.is_constant() && left.handle()->IsString()) || | 6115 ASSERT(!(left.is_constant() && left.handle()->IsString()) || |
| 6115 left_is_string); | 6116 left_is_string); |
| 6116 ASSERT(!(right.is_constant() && right.handle()->IsString()) || | 6117 ASSERT(!(right.is_constant() && right.handle()->IsString()) || |
| 6117 right_is_string); | 6118 right_is_string); |
| 6118 if (left_is_string || right_is_string) { | 6119 if (left_is_string || right_is_string) { |
| 6119 frame_->Push(&left); | 6120 frame_->Push(&left); |
| 6120 frame_->Push(&right); | 6121 frame_->Push(&right); |
| 6121 Result answer; | 6122 Result answer; |
| 6122 if (left_is_string) { | 6123 if (left_is_string) { |
| 6123 if (right_is_string) { | 6124 if (right_is_string) { |
| 6124 // TODO(lrn): if both are constant strings | |
| 6125 // -- do a compile time cons, if allocation during codegen is allowed. | |
| 6126 StringAddStub stub(NO_STRING_CHECK_IN_STUB); | 6125 StringAddStub stub(NO_STRING_CHECK_IN_STUB); |
| 6127 answer = frame_->CallStub(&stub, 2); | 6126 answer = frame_->CallStub(&stub, 2); |
| 6128 } else { | 6127 } else { |
| 6129 answer = | 6128 answer = |
| 6130 frame_->InvokeBuiltin(Builtins::STRING_ADD_LEFT, CALL_FUNCTION, 2); | 6129 frame_->InvokeBuiltin(Builtins::STRING_ADD_LEFT, CALL_FUNCTION, 2); |
| 6131 } | 6130 } |
| 6132 } else if (right_is_string) { | 6131 } else if (right_is_string) { |
| 6133 answer = | 6132 answer = |
| 6134 frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2); | 6133 frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2); |
| 6135 } | 6134 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 6154 } | 6153 } |
| 6155 | 6154 |
| 6156 // Get number type of left and right sub-expressions. | 6155 // Get number type of left and right sub-expressions. |
| 6157 TypeInfo operands_type = | 6156 TypeInfo operands_type = |
| 6158 TypeInfo::Combine(left.type_info(), right.type_info()); | 6157 TypeInfo::Combine(left.type_info(), right.type_info()); |
| 6159 | 6158 |
| 6160 TypeInfo result_type = CalculateTypeInfo(operands_type, op, right, left); | 6159 TypeInfo result_type = CalculateTypeInfo(operands_type, op, right, left); |
| 6161 | 6160 |
| 6162 Result answer; | 6161 Result answer; |
| 6163 if (left_is_non_smi_constant || right_is_non_smi_constant) { | 6162 if (left_is_non_smi_constant || right_is_non_smi_constant) { |
| 6163 // Go straight to the slow case, with no smi code. |
| 6164 GenericBinaryOpStub stub(op, | 6164 GenericBinaryOpStub stub(op, |
| 6165 overwrite_mode, | 6165 overwrite_mode, |
| 6166 NO_SMI_CODE_IN_STUB, | 6166 NO_SMI_CODE_IN_STUB, |
| 6167 operands_type); | 6167 operands_type); |
| 6168 answer = stub.GenerateCall(masm_, frame_, &left, &right); | 6168 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
| 6169 } else if (right_is_smi_constant) { | 6169 } else if (right_is_smi_constant) { |
| 6170 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), | 6170 answer = ConstantSmiBinaryOperation(expr, &left, right.handle(), |
| 6171 type, false, overwrite_mode); | 6171 false, overwrite_mode); |
| 6172 } else if (left_is_smi_constant) { | 6172 } else if (left_is_smi_constant) { |
| 6173 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), | 6173 answer = ConstantSmiBinaryOperation(expr, &right, left.handle(), |
| 6174 type, true, overwrite_mode); | 6174 true, overwrite_mode); |
| 6175 } else { | 6175 } else { |
| 6176 // Set the flags based on the operation, type and loop nesting level. | 6176 // Set the flags based on the operation, type and loop nesting level. |
| 6177 // Bit operations always assume they likely operate on Smis. Still only | 6177 // Bit operations always assume they likely operate on Smis. Still only |
| 6178 // generate the inline Smi check code if this operation is part of a loop. | 6178 // generate the inline Smi check code if this operation is part of a loop. |
| 6179 // For all other operations only inline the Smi check code for likely smis | 6179 // For all other operations only inline the Smi check code for likely smis |
| 6180 // if the operation is part of a loop. | 6180 // if the operation is part of a loop. |
| 6181 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { | 6181 if (loop_nesting() > 0 && |
| 6182 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); | 6182 (Token::IsBitOp(op) || |
| 6183 operands_type.IsInteger32() || |
| 6184 expr->type()->IsLikelySmi())) { |
| 6185 answer = LikelySmiBinaryOperation(expr, &left, &right, overwrite_mode); |
| 6183 } else { | 6186 } else { |
| 6184 GenericBinaryOpStub stub(op, | 6187 GenericBinaryOpStub stub(op, |
| 6185 overwrite_mode, | 6188 overwrite_mode, |
| 6186 NO_GENERIC_BINARY_FLAGS, | 6189 NO_GENERIC_BINARY_FLAGS, |
| 6187 operands_type); | 6190 operands_type); |
| 6188 answer = stub.GenerateCall(masm_, frame_, &left, &right); | 6191 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
| 6189 } | 6192 } |
| 6190 } | 6193 } |
| 6191 | 6194 |
| 6192 answer.set_type_info(result_type); | 6195 answer.set_type_info(result_type); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6264 // For mod we don't generate all the Smi code inline. | 6267 // For mod we don't generate all the Smi code inline. |
| 6265 GenericBinaryOpStub stub( | 6268 GenericBinaryOpStub stub( |
| 6266 op_, | 6269 op_, |
| 6267 overwrite_mode_, | 6270 overwrite_mode_, |
| 6268 (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB); | 6271 (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB); |
| 6269 stub.GenerateCall(masm_, src_, value_); | 6272 stub.GenerateCall(masm_, src_, value_); |
| 6270 if (!dst_.is(rax)) __ movq(dst_, rax); | 6273 if (!dst_.is(rax)) __ movq(dst_, rax); |
| 6271 } | 6274 } |
| 6272 | 6275 |
| 6273 | 6276 |
| 6274 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, | 6277 Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr, |
| 6275 Result* operand, | 6278 Result* operand, |
| 6276 Handle<Object> value, | 6279 Handle<Object> value, |
| 6277 StaticType* type, | |
| 6278 bool reversed, | 6280 bool reversed, |
| 6279 OverwriteMode overwrite_mode) { | 6281 OverwriteMode overwrite_mode) { |
| 6280 // NOTE: This is an attempt to inline (a bit) more of the code for | 6282 // NOTE: This is an attempt to inline (a bit) more of the code for |
| 6281 // some possible smi operations (like + and -) when (at least) one | 6283 // some possible smi operations (like + and -) when (at least) one |
| 6282 // of the operands is a constant smi. | 6284 // of the operands is a constant smi. |
| 6283 // Consumes the argument "operand". | 6285 // Consumes the argument "operand". |
| 6284 | |
| 6285 // TODO(199): Optimize some special cases of operations involving a | |
| 6286 // smi literal (multiply by 2, shift by 0, etc.). | |
| 6287 if (IsUnsafeSmi(value)) { | 6286 if (IsUnsafeSmi(value)) { |
| 6288 Result unsafe_operand(value); | 6287 Result unsafe_operand(value); |
| 6289 if (reversed) { | 6288 if (reversed) { |
| 6290 return LikelySmiBinaryOperation(op, &unsafe_operand, operand, | 6289 return LikelySmiBinaryOperation(expr, &unsafe_operand, operand, |
| 6291 overwrite_mode); | 6290 overwrite_mode); |
| 6292 } else { | 6291 } else { |
| 6293 return LikelySmiBinaryOperation(op, operand, &unsafe_operand, | 6292 return LikelySmiBinaryOperation(expr, operand, &unsafe_operand, |
| 6294 overwrite_mode); | 6293 overwrite_mode); |
| 6295 } | 6294 } |
| 6296 } | 6295 } |
| 6297 | 6296 |
| 6298 // Get the literal value. | 6297 // Get the literal value. |
| 6299 Smi* smi_value = Smi::cast(*value); | 6298 Smi* smi_value = Smi::cast(*value); |
| 6300 int int_value = smi_value->value(); | 6299 int int_value = smi_value->value(); |
| 6301 | 6300 |
| 6301 Token::Value op = expr->op(); |
| 6302 Result answer; | 6302 Result answer; |
| 6303 switch (op) { | 6303 switch (op) { |
| 6304 case Token::ADD: { | 6304 case Token::ADD: { |
| 6305 operand->ToRegister(); | 6305 operand->ToRegister(); |
| 6306 frame_->Spill(operand->reg()); | 6306 frame_->Spill(operand->reg()); |
| 6307 DeferredCode* deferred = NULL; | 6307 DeferredCode* deferred = NULL; |
| 6308 if (reversed) { | 6308 if (reversed) { |
| 6309 deferred = new DeferredInlineSmiAddReversed(operand->reg(), | 6309 deferred = new DeferredInlineSmiAddReversed(operand->reg(), |
| 6310 smi_value, | 6310 smi_value, |
| 6311 overwrite_mode); | 6311 overwrite_mode); |
| 6312 } else { | 6312 } else { |
| 6313 deferred = new DeferredInlineSmiAdd(operand->reg(), | 6313 deferred = new DeferredInlineSmiAdd(operand->reg(), |
| 6314 smi_value, | 6314 smi_value, |
| 6315 overwrite_mode); | 6315 overwrite_mode); |
| 6316 } | 6316 } |
| 6317 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 6317 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 6318 __ SmiAddConstant(operand->reg(), | 6318 __ SmiAddConstant(operand->reg(), |
| 6319 operand->reg(), | 6319 operand->reg(), |
| 6320 smi_value, | 6320 smi_value, |
| 6321 deferred->entry_label()); | 6321 deferred->entry_label()); |
| 6322 deferred->BindExit(); | 6322 deferred->BindExit(); |
| 6323 answer = *operand; | 6323 answer = *operand; |
| 6324 break; | 6324 break; |
| 6325 } | 6325 } |
| 6326 | 6326 |
| 6327 case Token::SUB: { | 6327 case Token::SUB: { |
| 6328 if (reversed) { | 6328 if (reversed) { |
| 6329 Result constant_operand(value); | 6329 Result constant_operand(value); |
| 6330 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 6330 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
| 6331 overwrite_mode); | 6331 overwrite_mode); |
| 6332 } else { | 6332 } else { |
| 6333 operand->ToRegister(); | 6333 operand->ToRegister(); |
| 6334 frame_->Spill(operand->reg()); | 6334 frame_->Spill(operand->reg()); |
| 6335 DeferredCode* deferred = new DeferredInlineSmiSub(operand->reg(), | 6335 DeferredCode* deferred = new DeferredInlineSmiSub(operand->reg(), |
| 6336 smi_value, | 6336 smi_value, |
| 6337 overwrite_mode); | 6337 overwrite_mode); |
| 6338 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 6338 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 6339 // A smi currently fits in a 32-bit Immediate. | 6339 // A smi currently fits in a 32-bit Immediate. |
| 6340 __ SmiSubConstant(operand->reg(), | 6340 __ SmiSubConstant(operand->reg(), |
| 6341 operand->reg(), | 6341 operand->reg(), |
| 6342 smi_value, | 6342 smi_value, |
| 6343 deferred->entry_label()); | 6343 deferred->entry_label()); |
| 6344 deferred->BindExit(); | 6344 deferred->BindExit(); |
| 6345 answer = *operand; | 6345 answer = *operand; |
| 6346 } | 6346 } |
| 6347 break; | 6347 break; |
| 6348 } | 6348 } |
| 6349 | 6349 |
| 6350 case Token::SAR: | 6350 case Token::SAR: |
| 6351 if (reversed) { | 6351 if (reversed) { |
| 6352 Result constant_operand(value); | 6352 Result constant_operand(value); |
| 6353 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 6353 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
| 6354 overwrite_mode); | 6354 overwrite_mode); |
| 6355 } else { | 6355 } else { |
| 6356 // Only the least significant 5 bits of the shift value are used. | 6356 // Only the least significant 5 bits of the shift value are used. |
| 6357 // In the slow case, this masking is done inside the runtime call. | 6357 // In the slow case, this masking is done inside the runtime call. |
| 6358 int shift_value = int_value & 0x1f; | 6358 int shift_value = int_value & 0x1f; |
| 6359 operand->ToRegister(); | 6359 operand->ToRegister(); |
| 6360 frame_->Spill(operand->reg()); | 6360 frame_->Spill(operand->reg()); |
| 6361 DeferredInlineSmiOperation* deferred = | 6361 DeferredInlineSmiOperation* deferred = |
| 6362 new DeferredInlineSmiOperation(op, | 6362 new DeferredInlineSmiOperation(op, |
| 6363 operand->reg(), | 6363 operand->reg(), |
| 6364 operand->reg(), | 6364 operand->reg(), |
| 6365 smi_value, | 6365 smi_value, |
| 6366 overwrite_mode); | 6366 overwrite_mode); |
| 6367 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 6367 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 6368 __ SmiShiftArithmeticRightConstant(operand->reg(), | 6368 __ SmiShiftArithmeticRightConstant(operand->reg(), |
| 6369 operand->reg(), | 6369 operand->reg(), |
| 6370 shift_value); | 6370 shift_value); |
| 6371 deferred->BindExit(); | 6371 deferred->BindExit(); |
| 6372 answer = *operand; | 6372 answer = *operand; |
| 6373 } | 6373 } |
| 6374 break; | 6374 break; |
| 6375 | 6375 |
| 6376 case Token::SHR: | 6376 case Token::SHR: |
| 6377 if (reversed) { | 6377 if (reversed) { |
| 6378 Result constant_operand(value); | 6378 Result constant_operand(value); |
| 6379 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 6379 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
| 6380 overwrite_mode); | 6380 overwrite_mode); |
| 6381 } else { | 6381 } else { |
| 6382 // Only the least significant 5 bits of the shift value are used. | 6382 // Only the least significant 5 bits of the shift value are used. |
| 6383 // In the slow case, this masking is done inside the runtime call. | 6383 // In the slow case, this masking is done inside the runtime call. |
| 6384 int shift_value = int_value & 0x1f; | 6384 int shift_value = int_value & 0x1f; |
| 6385 operand->ToRegister(); | 6385 operand->ToRegister(); |
| 6386 answer = allocator()->Allocate(); | 6386 answer = allocator()->Allocate(); |
| 6387 ASSERT(answer.is_valid()); | 6387 ASSERT(answer.is_valid()); |
| 6388 DeferredInlineSmiOperation* deferred = | 6388 DeferredInlineSmiOperation* deferred = |
| 6389 new DeferredInlineSmiOperation(op, | 6389 new DeferredInlineSmiOperation(op, |
| 6390 answer.reg(), | 6390 answer.reg(), |
| 6391 operand->reg(), | 6391 operand->reg(), |
| 6392 smi_value, | 6392 smi_value, |
| 6393 overwrite_mode); | 6393 overwrite_mode); |
| 6394 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 6394 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 6395 __ SmiShiftLogicalRightConstant(answer.reg(), | 6395 __ SmiShiftLogicalRightConstant(answer.reg(), |
| 6396 operand->reg(), | 6396 operand->reg(), |
| 6397 shift_value, | 6397 shift_value, |
| 6398 deferred->entry_label()); | 6398 deferred->entry_label()); |
| 6399 deferred->BindExit(); | 6399 deferred->BindExit(); |
| 6400 operand->Unuse(); | 6400 operand->Unuse(); |
| 6401 } | 6401 } |
| 6402 break; | 6402 break; |
| 6403 | 6403 |
| 6404 case Token::SHL: | 6404 case Token::SHL: |
| 6405 if (reversed) { | 6405 if (reversed) { |
| 6406 Result constant_operand(value); | 6406 Result constant_operand(value); |
| 6407 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 6407 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
| 6408 overwrite_mode); | 6408 overwrite_mode); |
| 6409 } else { | 6409 } else { |
| 6410 // Only the least significant 5 bits of the shift value are used. | 6410 // Only the least significant 5 bits of the shift value are used. |
| 6411 // In the slow case, this masking is done inside the runtime call. | 6411 // In the slow case, this masking is done inside the runtime call. |
| 6412 int shift_value = int_value & 0x1f; | 6412 int shift_value = int_value & 0x1f; |
| 6413 operand->ToRegister(); | 6413 operand->ToRegister(); |
| 6414 if (shift_value == 0) { | 6414 if (shift_value == 0) { |
| 6415 // Spill operand so it can be overwritten in the slow case. | 6415 // Spill operand so it can be overwritten in the slow case. |
| 6416 frame_->Spill(operand->reg()); | 6416 frame_->Spill(operand->reg()); |
| 6417 DeferredInlineSmiOperation* deferred = | 6417 DeferredInlineSmiOperation* deferred = |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6504 deferred->BindExit(); | 6504 deferred->BindExit(); |
| 6505 answer = *operand; | 6505 answer = *operand; |
| 6506 break; // This break only applies if we generated code for MOD. | 6506 break; // This break only applies if we generated code for MOD. |
| 6507 } | 6507 } |
| 6508 // Fall through if we did not find a power of 2 on the right hand side! | 6508 // Fall through if we did not find a power of 2 on the right hand side! |
| 6509 // The next case must be the default. | 6509 // The next case must be the default. |
| 6510 | 6510 |
| 6511 default: { | 6511 default: { |
| 6512 Result constant_operand(value); | 6512 Result constant_operand(value); |
| 6513 if (reversed) { | 6513 if (reversed) { |
| 6514 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 6514 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
| 6515 overwrite_mode); | 6515 overwrite_mode); |
| 6516 } else { | 6516 } else { |
| 6517 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, | 6517 answer = LikelySmiBinaryOperation(expr, operand, &constant_operand, |
| 6518 overwrite_mode); | 6518 overwrite_mode); |
| 6519 } | 6519 } |
| 6520 break; | 6520 break; |
| 6521 } | 6521 } |
| 6522 } | 6522 } |
| 6523 ASSERT(answer.is_valid()); | 6523 ASSERT(answer.is_valid()); |
| 6524 return answer; | 6524 return answer; |
| 6525 } | 6525 } |
| 6526 | 6526 |
| 6527 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, | 6527 Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, |
| 6528 Result* left, | 6528 Result* left, |
| 6529 Result* right, | 6529 Result* right, |
| 6530 OverwriteMode overwrite_mode) { | 6530 OverwriteMode overwrite_mode) { |
| 6531 Token::Value op = expr->op(); |
| 6531 Result answer; | 6532 Result answer; |
| 6532 // Special handling of div and mod because they use fixed registers. | 6533 // Special handling of div and mod because they use fixed registers. |
| 6533 if (op == Token::DIV || op == Token::MOD) { | 6534 if (op == Token::DIV || op == Token::MOD) { |
| 6534 // We need rax as the quotient register, rdx as the remainder | 6535 // We need rax as the quotient register, rdx as the remainder |
| 6535 // register, neither left nor right in rax or rdx, and left copied | 6536 // register, neither left nor right in rax or rdx, and left copied |
| 6536 // to rax. | 6537 // to rax. |
| 6537 Result quotient; | 6538 Result quotient; |
| 6538 Result remainder; | 6539 Result remainder; |
| 6539 bool left_is_in_rax = false; | 6540 bool left_is_in_rax = false; |
| 6540 // Step 1: get rax for quotient. | 6541 // Step 1: get rax for quotient. |
| (...skipping 4490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11031 // Call the function from C++. | 11032 // Call the function from C++. |
| 11032 return FUNCTION_CAST<ModuloFunction>(buffer); | 11033 return FUNCTION_CAST<ModuloFunction>(buffer); |
| 11033 } | 11034 } |
| 11034 | 11035 |
| 11035 #endif | 11036 #endif |
| 11036 | 11037 |
| 11037 | 11038 |
| 11038 #undef __ | 11039 #undef __ |
| 11039 | 11040 |
| 11040 } } // namespace v8::internal | 11041 } } // namespace v8::internal |
| OLD | NEW |