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 |