| 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 5012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5023 OverwriteMode overwrite_mode) { | 5023 OverwriteMode overwrite_mode) { |
| 5024 Comment cmnt(masm_, "[ BinaryOperation"); | 5024 Comment cmnt(masm_, "[ BinaryOperation"); |
| 5025 Comment cmnt_token(masm_, Token::String(op)); | 5025 Comment cmnt_token(masm_, Token::String(op)); |
| 5026 | 5026 |
| 5027 if (op == Token::COMMA) { | 5027 if (op == Token::COMMA) { |
| 5028 // Simply discard left value. | 5028 // Simply discard left value. |
| 5029 frame_->Nip(1); | 5029 frame_->Nip(1); |
| 5030 return; | 5030 return; |
| 5031 } | 5031 } |
| 5032 | 5032 |
| 5033 // Set the flags based on the operation, type and loop nesting level. | |
| 5034 GenericBinaryFlags flags; | |
| 5035 switch (op) { | |
| 5036 case Token::BIT_OR: | |
| 5037 case Token::BIT_AND: | |
| 5038 case Token::BIT_XOR: | |
| 5039 case Token::SHL: | |
| 5040 case Token::SHR: | |
| 5041 case Token::SAR: | |
| 5042 // Bit operations always assume they likely operate on Smis. Still only | |
| 5043 // generate the inline Smi check code if this operation is part of a loop. | |
| 5044 flags = (loop_nesting() > 0) | |
| 5045 ? NO_SMI_CODE_IN_STUB | |
| 5046 : NO_GENERIC_BINARY_FLAGS; | |
| 5047 break; | |
| 5048 | |
| 5049 default: | |
| 5050 // By default only inline the Smi check code for likely smis if this | |
| 5051 // operation is part of a loop. | |
| 5052 flags = ((loop_nesting() > 0) && type->IsLikelySmi()) | |
| 5053 ? NO_SMI_CODE_IN_STUB | |
| 5054 : NO_GENERIC_BINARY_FLAGS; | |
| 5055 break; | |
| 5056 } | |
| 5057 | |
| 5058 Result right = frame_->Pop(); | 5033 Result right = frame_->Pop(); |
| 5059 Result left = frame_->Pop(); | 5034 Result left = frame_->Pop(); |
| 5060 | 5035 |
| 5061 if (op == Token::ADD) { | 5036 if (op == Token::ADD) { |
| 5062 bool left_is_string = left.is_constant() && left.handle()->IsString(); | 5037 bool left_is_string = left.is_constant() && left.handle()->IsString(); |
| 5063 bool right_is_string = right.is_constant() && right.handle()->IsString(); | 5038 bool right_is_string = right.is_constant() && right.handle()->IsString(); |
| 5064 if (left_is_string || right_is_string) { | 5039 if (left_is_string || right_is_string) { |
| 5065 frame_->Push(&left); | 5040 frame_->Push(&left); |
| 5066 frame_->Push(&right); | 5041 frame_->Push(&right); |
| 5067 Result answer; | 5042 Result answer; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5081 frame_->Push(&answer); | 5056 frame_->Push(&answer); |
| 5082 return; | 5057 return; |
| 5083 } | 5058 } |
| 5084 // Neither operand is known to be a string. | 5059 // Neither operand is known to be a string. |
| 5085 } | 5060 } |
| 5086 | 5061 |
| 5087 bool left_is_smi = left.is_constant() && left.handle()->IsSmi(); | 5062 bool left_is_smi = left.is_constant() && left.handle()->IsSmi(); |
| 5088 bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi(); | 5063 bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi(); |
| 5089 bool right_is_smi = right.is_constant() && right.handle()->IsSmi(); | 5064 bool right_is_smi = right.is_constant() && right.handle()->IsSmi(); |
| 5090 bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi(); | 5065 bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi(); |
| 5091 bool generate_no_smi_code = false; // No smi code at all, inline or in stub. | |
| 5092 | 5066 |
| 5093 if (left_is_smi && right_is_smi) { | 5067 if (left_is_smi && right_is_smi) { |
| 5094 // Compute the constant result at compile time, and leave it on the frame. | 5068 // Compute the constant result at compile time, and leave it on the frame. |
| 5095 int left_int = Smi::cast(*left.handle())->value(); | 5069 int left_int = Smi::cast(*left.handle())->value(); |
| 5096 int right_int = Smi::cast(*right.handle())->value(); | 5070 int right_int = Smi::cast(*right.handle())->value(); |
| 5097 if (FoldConstantSmis(op, left_int, right_int)) return; | 5071 if (FoldConstantSmis(op, left_int, right_int)) return; |
| 5098 } | 5072 } |
| 5099 | 5073 |
| 5074 Result answer; |
| 5100 if (left_is_non_smi || right_is_non_smi) { | 5075 if (left_is_non_smi || right_is_non_smi) { |
| 5101 // Set flag so that we go straight to the slow case, with no smi code. | 5076 // Go straight to the slow case, with no smi code |
| 5102 generate_no_smi_code = true; | |
| 5103 } else if (right_is_smi) { | |
| 5104 ConstantSmiBinaryOperation(op, &left, right.handle(), | |
| 5105 type, false, overwrite_mode); | |
| 5106 return; | |
| 5107 } else if (left_is_smi) { | |
| 5108 ConstantSmiBinaryOperation(op, &right, left.handle(), | |
| 5109 type, true, overwrite_mode); | |
| 5110 return; | |
| 5111 } | |
| 5112 | |
| 5113 if ((flags & NO_SMI_CODE_IN_STUB) != 0 && !generate_no_smi_code) { | |
| 5114 LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); | |
| 5115 } else { | |
| 5116 frame_->Push(&left); | 5077 frame_->Push(&left); |
| 5117 frame_->Push(&right); | 5078 frame_->Push(&right); |
| 5118 // If we know the arguments aren't smis, use the binary operation stub | 5079 GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB); |
| 5119 // that does not check for the fast smi case. | 5080 answer = frame_->CallStub(&stub, 2); |
| 5120 // The same stub is used for NO_SMI_CODE and SMI_CODE_INLINED. | 5081 } else if (right_is_smi) { |
| 5121 if (generate_no_smi_code) { | 5082 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), |
| 5122 flags = NO_SMI_CODE_IN_STUB; | 5083 type, false, overwrite_mode); |
| 5084 } else if (left_is_smi) { |
| 5085 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), |
| 5086 type, true, overwrite_mode); |
| 5087 } else { |
| 5088 // Set the flags based on the operation, type and loop nesting level. |
| 5089 // Bit operations always assume they likely operate on Smis. Still only |
| 5090 // generate the inline Smi check code if this operation is part of a loop. |
| 5091 // For all other operations only inline the Smi check code for likely smis |
| 5092 // if the operation is part of a loop. |
| 5093 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { |
| 5094 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); |
| 5095 } else { |
| 5096 frame_->Push(&left); |
| 5097 frame_->Push(&right); |
| 5098 GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS); |
| 5099 answer = frame_->CallStub(&stub, 2); |
| 5123 } | 5100 } |
| 5124 GenericBinaryOpStub stub(op, overwrite_mode, flags); | |
| 5125 Result answer = frame_->CallStub(&stub, 2); | |
| 5126 frame_->Push(&answer); | |
| 5127 } | 5101 } |
| 5102 frame_->Push(&answer); |
| 5128 } | 5103 } |
| 5129 | 5104 |
| 5130 | 5105 |
| 5131 // Emit a LoadIC call to get the value from receiver and leave it in | 5106 // Emit a LoadIC call to get the value from receiver and leave it in |
| 5132 // dst. The receiver register is restored after the call. | 5107 // dst. The receiver register is restored after the call. |
| 5133 class DeferredReferenceGetNamedValue: public DeferredCode { | 5108 class DeferredReferenceGetNamedValue: public DeferredCode { |
| 5134 public: | 5109 public: |
| 5135 DeferredReferenceGetNamedValue(Register dst, | 5110 DeferredReferenceGetNamedValue(Register dst, |
| 5136 Register receiver, | 5111 Register receiver, |
| 5137 Handle<String> name) | 5112 Handle<String> name) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5198 // For mod we don't generate all the Smi code inline. | 5173 // For mod we don't generate all the Smi code inline. |
| 5199 GenericBinaryOpStub stub( | 5174 GenericBinaryOpStub stub( |
| 5200 op_, | 5175 op_, |
| 5201 overwrite_mode_, | 5176 overwrite_mode_, |
| 5202 (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB); | 5177 (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB); |
| 5203 stub.GenerateCall(masm_, src_, value_); | 5178 stub.GenerateCall(masm_, src_, value_); |
| 5204 if (!dst_.is(rax)) __ movq(dst_, rax); | 5179 if (!dst_.is(rax)) __ movq(dst_, rax); |
| 5205 } | 5180 } |
| 5206 | 5181 |
| 5207 | 5182 |
| 5208 void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, | 5183 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, |
| 5209 Result* operand, | 5184 Result* operand, |
| 5210 Handle<Object> value, | 5185 Handle<Object> value, |
| 5211 StaticType* type, | 5186 StaticType* type, |
| 5212 bool reversed, | 5187 bool reversed, |
| 5213 OverwriteMode overwrite_mode) { | 5188 OverwriteMode overwrite_mode) { |
| 5214 // NOTE: This is an attempt to inline (a bit) more of the code for | 5189 // NOTE: This is an attempt to inline (a bit) more of the code for |
| 5215 // some possible smi operations (like + and -) when (at least) one | 5190 // some possible smi operations (like + and -) when (at least) one |
| 5216 // of the operands is a constant smi. | 5191 // of the operands is a constant smi. |
| 5217 // Consumes the argument "operand". | 5192 // Consumes the argument "operand". |
| 5218 | 5193 |
| 5219 // TODO(199): Optimize some special cases of operations involving a | 5194 // TODO(199): Optimize some special cases of operations involving a |
| 5220 // smi literal (multiply by 2, shift by 0, etc.). | 5195 // smi literal (multiply by 2, shift by 0, etc.). |
| 5221 if (IsUnsafeSmi(value)) { | 5196 if (IsUnsafeSmi(value)) { |
| 5222 Result unsafe_operand(value); | 5197 Result unsafe_operand(value); |
| 5223 if (reversed) { | 5198 if (reversed) { |
| 5224 LikelySmiBinaryOperation(op, &unsafe_operand, operand, | 5199 return LikelySmiBinaryOperation(op, &unsafe_operand, operand, |
| 5225 overwrite_mode); | 5200 overwrite_mode); |
| 5226 } else { | 5201 } else { |
| 5227 LikelySmiBinaryOperation(op, operand, &unsafe_operand, | 5202 return LikelySmiBinaryOperation(op, operand, &unsafe_operand, |
| 5228 overwrite_mode); | 5203 overwrite_mode); |
| 5229 } | 5204 } |
| 5230 ASSERT(!operand->is_valid()); | |
| 5231 return; | |
| 5232 } | 5205 } |
| 5233 | 5206 |
| 5234 // Get the literal value. | 5207 // Get the literal value. |
| 5235 Smi* smi_value = Smi::cast(*value); | 5208 Smi* smi_value = Smi::cast(*value); |
| 5236 int int_value = smi_value->value(); | 5209 int int_value = smi_value->value(); |
| 5237 | 5210 |
| 5211 Result answer; |
| 5238 switch (op) { | 5212 switch (op) { |
| 5239 case Token::ADD: { | 5213 case Token::ADD: { |
| 5240 operand->ToRegister(); | 5214 operand->ToRegister(); |
| 5241 frame_->Spill(operand->reg()); | 5215 frame_->Spill(operand->reg()); |
| 5242 DeferredCode* deferred = NULL; | 5216 DeferredCode* deferred = NULL; |
| 5243 if (reversed) { | 5217 if (reversed) { |
| 5244 deferred = new DeferredInlineSmiAddReversed(operand->reg(), | 5218 deferred = new DeferredInlineSmiAddReversed(operand->reg(), |
| 5245 smi_value, | 5219 smi_value, |
| 5246 overwrite_mode); | 5220 overwrite_mode); |
| 5247 } else { | 5221 } else { |
| 5248 deferred = new DeferredInlineSmiAdd(operand->reg(), | 5222 deferred = new DeferredInlineSmiAdd(operand->reg(), |
| 5249 smi_value, | 5223 smi_value, |
| 5250 overwrite_mode); | 5224 overwrite_mode); |
| 5251 } | 5225 } |
| 5252 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 5226 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 5253 __ SmiAddConstant(operand->reg(), | 5227 __ SmiAddConstant(operand->reg(), |
| 5254 operand->reg(), | 5228 operand->reg(), |
| 5255 smi_value, | 5229 smi_value, |
| 5256 deferred->entry_label()); | 5230 deferred->entry_label()); |
| 5257 deferred->BindExit(); | 5231 deferred->BindExit(); |
| 5258 frame_->Push(operand); | 5232 answer = *operand; |
| 5259 break; | 5233 break; |
| 5260 } | 5234 } |
| 5261 | 5235 |
| 5262 case Token::SUB: { | 5236 case Token::SUB: { |
| 5263 if (reversed) { | 5237 if (reversed) { |
| 5264 Result constant_operand(value); | 5238 Result constant_operand(value); |
| 5265 LikelySmiBinaryOperation(op, &constant_operand, operand, | 5239 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 5266 overwrite_mode); | 5240 overwrite_mode); |
| 5267 } else { | 5241 } else { |
| 5268 operand->ToRegister(); | 5242 operand->ToRegister(); |
| 5269 frame_->Spill(operand->reg()); | 5243 frame_->Spill(operand->reg()); |
| 5270 DeferredCode* deferred = new DeferredInlineSmiSub(operand->reg(), | 5244 DeferredCode* deferred = new DeferredInlineSmiSub(operand->reg(), |
| 5271 smi_value, | 5245 smi_value, |
| 5272 overwrite_mode); | 5246 overwrite_mode); |
| 5273 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 5247 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 5274 // A smi currently fits in a 32-bit Immediate. | 5248 // A smi currently fits in a 32-bit Immediate. |
| 5275 __ SmiSubConstant(operand->reg(), | 5249 __ SmiSubConstant(operand->reg(), |
| 5276 operand->reg(), | 5250 operand->reg(), |
| 5277 smi_value, | 5251 smi_value, |
| 5278 deferred->entry_label()); | 5252 deferred->entry_label()); |
| 5279 deferred->BindExit(); | 5253 deferred->BindExit(); |
| 5280 frame_->Push(operand); | 5254 answer = *operand; |
| 5281 } | 5255 } |
| 5282 break; | 5256 break; |
| 5283 } | 5257 } |
| 5284 | 5258 |
| 5285 case Token::SAR: | 5259 case Token::SAR: |
| 5286 if (reversed) { | 5260 if (reversed) { |
| 5287 Result constant_operand(value); | 5261 Result constant_operand(value); |
| 5288 LikelySmiBinaryOperation(op, &constant_operand, operand, | 5262 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 5289 overwrite_mode); | 5263 overwrite_mode); |
| 5290 } else { | 5264 } else { |
| 5291 // Only the least significant 5 bits of the shift value are used. | 5265 // Only the least significant 5 bits of the shift value are used. |
| 5292 // In the slow case, this masking is done inside the runtime call. | 5266 // In the slow case, this masking is done inside the runtime call. |
| 5293 int shift_value = int_value & 0x1f; | 5267 int shift_value = int_value & 0x1f; |
| 5294 operand->ToRegister(); | 5268 operand->ToRegister(); |
| 5295 frame_->Spill(operand->reg()); | 5269 frame_->Spill(operand->reg()); |
| 5296 DeferredInlineSmiOperation* deferred = | 5270 DeferredInlineSmiOperation* deferred = |
| 5297 new DeferredInlineSmiOperation(op, | 5271 new DeferredInlineSmiOperation(op, |
| 5298 operand->reg(), | 5272 operand->reg(), |
| 5299 operand->reg(), | 5273 operand->reg(), |
| 5300 smi_value, | 5274 smi_value, |
| 5301 overwrite_mode); | 5275 overwrite_mode); |
| 5302 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 5276 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 5303 __ SmiShiftArithmeticRightConstant(operand->reg(), | 5277 __ SmiShiftArithmeticRightConstant(operand->reg(), |
| 5304 operand->reg(), | 5278 operand->reg(), |
| 5305 shift_value); | 5279 shift_value); |
| 5306 deferred->BindExit(); | 5280 deferred->BindExit(); |
| 5307 frame_->Push(operand); | 5281 answer = *operand; |
| 5308 } | 5282 } |
| 5309 break; | 5283 break; |
| 5310 | 5284 |
| 5311 case Token::SHR: | 5285 case Token::SHR: |
| 5312 if (reversed) { | 5286 if (reversed) { |
| 5313 Result constant_operand(value); | 5287 Result constant_operand(value); |
| 5314 LikelySmiBinaryOperation(op, &constant_operand, operand, | 5288 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 5315 overwrite_mode); | 5289 overwrite_mode); |
| 5316 } else { | 5290 } else { |
| 5317 // Only the least significant 5 bits of the shift value are used. | 5291 // Only the least significant 5 bits of the shift value are used. |
| 5318 // In the slow case, this masking is done inside the runtime call. | 5292 // In the slow case, this masking is done inside the runtime call. |
| 5319 int shift_value = int_value & 0x1f; | 5293 int shift_value = int_value & 0x1f; |
| 5320 operand->ToRegister(); | 5294 operand->ToRegister(); |
| 5321 Result answer = allocator()->Allocate(); | 5295 answer = allocator()->Allocate(); |
| 5322 ASSERT(answer.is_valid()); | 5296 ASSERT(answer.is_valid()); |
| 5323 DeferredInlineSmiOperation* deferred = | 5297 DeferredInlineSmiOperation* deferred = |
| 5324 new DeferredInlineSmiOperation(op, | 5298 new DeferredInlineSmiOperation(op, |
| 5325 answer.reg(), | 5299 answer.reg(), |
| 5326 operand->reg(), | 5300 operand->reg(), |
| 5327 smi_value, | 5301 smi_value, |
| 5328 overwrite_mode); | 5302 overwrite_mode); |
| 5329 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 5303 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 5330 __ SmiShiftLogicalRightConstant(answer.reg(), | 5304 __ SmiShiftLogicalRightConstant(answer.reg(), |
| 5331 operand->reg(), | 5305 operand->reg(), |
| 5332 shift_value, | 5306 shift_value, |
| 5333 deferred->entry_label()); | 5307 deferred->entry_label()); |
| 5334 deferred->BindExit(); | 5308 deferred->BindExit(); |
| 5335 operand->Unuse(); | 5309 operand->Unuse(); |
| 5336 frame_->Push(&answer); | |
| 5337 } | 5310 } |
| 5338 break; | 5311 break; |
| 5339 | 5312 |
| 5340 case Token::SHL: | 5313 case Token::SHL: |
| 5341 if (reversed) { | 5314 if (reversed) { |
| 5342 Result constant_operand(value); | 5315 Result constant_operand(value); |
| 5343 LikelySmiBinaryOperation(op, &constant_operand, operand, | 5316 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 5344 overwrite_mode); | 5317 overwrite_mode); |
| 5345 } else { | 5318 } else { |
| 5346 // Only the least significant 5 bits of the shift value are used. | 5319 // Only the least significant 5 bits of the shift value are used. |
| 5347 // In the slow case, this masking is done inside the runtime call. | 5320 // In the slow case, this masking is done inside the runtime call. |
| 5348 int shift_value = int_value & 0x1f; | 5321 int shift_value = int_value & 0x1f; |
| 5349 operand->ToRegister(); | 5322 operand->ToRegister(); |
| 5350 if (shift_value == 0) { | 5323 if (shift_value == 0) { |
| 5351 // Spill operand so it can be overwritten in the slow case. | 5324 // Spill operand so it can be overwritten in the slow case. |
| 5352 frame_->Spill(operand->reg()); | 5325 frame_->Spill(operand->reg()); |
| 5353 DeferredInlineSmiOperation* deferred = | 5326 DeferredInlineSmiOperation* deferred = |
| 5354 new DeferredInlineSmiOperation(op, | 5327 new DeferredInlineSmiOperation(op, |
| 5355 operand->reg(), | 5328 operand->reg(), |
| 5356 operand->reg(), | 5329 operand->reg(), |
| 5357 smi_value, | 5330 smi_value, |
| 5358 overwrite_mode); | 5331 overwrite_mode); |
| 5359 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 5332 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 5360 deferred->BindExit(); | 5333 deferred->BindExit(); |
| 5361 frame_->Push(operand); | 5334 answer = *operand; |
| 5362 } else { | 5335 } else { |
| 5363 // Use a fresh temporary for nonzero shift values. | 5336 // Use a fresh temporary for nonzero shift values. |
| 5364 Result answer = allocator()->Allocate(); | 5337 answer = allocator()->Allocate(); |
| 5365 ASSERT(answer.is_valid()); | 5338 ASSERT(answer.is_valid()); |
| 5366 DeferredInlineSmiOperation* deferred = | 5339 DeferredInlineSmiOperation* deferred = |
| 5367 new DeferredInlineSmiOperation(op, | 5340 new DeferredInlineSmiOperation(op, |
| 5368 answer.reg(), | 5341 answer.reg(), |
| 5369 operand->reg(), | 5342 operand->reg(), |
| 5370 smi_value, | 5343 smi_value, |
| 5371 overwrite_mode); | 5344 overwrite_mode); |
| 5372 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 5345 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); |
| 5373 __ SmiShiftLeftConstant(answer.reg(), | 5346 __ SmiShiftLeftConstant(answer.reg(), |
| 5374 operand->reg(), | 5347 operand->reg(), |
| 5375 shift_value, | 5348 shift_value, |
| 5376 deferred->entry_label()); | 5349 deferred->entry_label()); |
| 5377 deferred->BindExit(); | 5350 deferred->BindExit(); |
| 5378 operand->Unuse(); | 5351 operand->Unuse(); |
| 5379 frame_->Push(&answer); | |
| 5380 } | 5352 } |
| 5381 } | 5353 } |
| 5382 break; | 5354 break; |
| 5383 | 5355 |
| 5384 case Token::BIT_OR: | 5356 case Token::BIT_OR: |
| 5385 case Token::BIT_XOR: | 5357 case Token::BIT_XOR: |
| 5386 case Token::BIT_AND: { | 5358 case Token::BIT_AND: { |
| 5387 operand->ToRegister(); | 5359 operand->ToRegister(); |
| 5388 frame_->Spill(operand->reg()); | 5360 frame_->Spill(operand->reg()); |
| 5389 if (reversed) { | 5361 if (reversed) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5404 if (int_value != 0) { | 5376 if (int_value != 0) { |
| 5405 __ SmiXorConstant(operand->reg(), operand->reg(), smi_value); | 5377 __ SmiXorConstant(operand->reg(), operand->reg(), smi_value); |
| 5406 } | 5378 } |
| 5407 } else { | 5379 } else { |
| 5408 ASSERT(op == Token::BIT_OR); | 5380 ASSERT(op == Token::BIT_OR); |
| 5409 if (int_value != 0) { | 5381 if (int_value != 0) { |
| 5410 __ SmiOrConstant(operand->reg(), operand->reg(), smi_value); | 5382 __ SmiOrConstant(operand->reg(), operand->reg(), smi_value); |
| 5411 } | 5383 } |
| 5412 } | 5384 } |
| 5413 deferred->BindExit(); | 5385 deferred->BindExit(); |
| 5414 frame_->Push(operand); | 5386 answer = *operand; |
| 5415 break; | 5387 break; |
| 5416 } | 5388 } |
| 5417 | 5389 |
| 5418 // Generate inline code for mod of powers of 2 and negative powers of 2. | 5390 // Generate inline code for mod of powers of 2 and negative powers of 2. |
| 5419 case Token::MOD: | 5391 case Token::MOD: |
| 5420 if (!reversed && | 5392 if (!reversed && |
| 5421 int_value != 0 && | 5393 int_value != 0 && |
| 5422 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { | 5394 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { |
| 5423 operand->ToRegister(); | 5395 operand->ToRegister(); |
| 5424 frame_->Spill(operand->reg()); | 5396 frame_->Spill(operand->reg()); |
| 5425 DeferredCode* deferred = | 5397 DeferredCode* deferred = |
| 5426 new DeferredInlineSmiOperation(op, | 5398 new DeferredInlineSmiOperation(op, |
| 5427 operand->reg(), | 5399 operand->reg(), |
| 5428 operand->reg(), | 5400 operand->reg(), |
| 5429 smi_value, | 5401 smi_value, |
| 5430 overwrite_mode); | 5402 overwrite_mode); |
| 5431 // Check for negative or non-Smi left hand side. | 5403 // Check for negative or non-Smi left hand side. |
| 5432 __ JumpIfNotPositiveSmi(operand->reg(), deferred->entry_label()); | 5404 __ JumpIfNotPositiveSmi(operand->reg(), deferred->entry_label()); |
| 5433 if (int_value < 0) int_value = -int_value; | 5405 if (int_value < 0) int_value = -int_value; |
| 5434 if (int_value == 1) { | 5406 if (int_value == 1) { |
| 5435 __ Move(operand->reg(), Smi::FromInt(0)); | 5407 __ Move(operand->reg(), Smi::FromInt(0)); |
| 5436 } else { | 5408 } else { |
| 5437 __ SmiAndConstant(operand->reg(), | 5409 __ SmiAndConstant(operand->reg(), |
| 5438 operand->reg(), | 5410 operand->reg(), |
| 5439 Smi::FromInt(int_value - 1)); | 5411 Smi::FromInt(int_value - 1)); |
| 5440 } | 5412 } |
| 5441 deferred->BindExit(); | 5413 deferred->BindExit(); |
| 5442 frame_->Push(operand); | 5414 answer = *operand; |
| 5443 break; // This break only applies if we generated code for MOD. | 5415 break; // This break only applies if we generated code for MOD. |
| 5444 } | 5416 } |
| 5445 // Fall through if we did not find a power of 2 on the right hand side! | 5417 // Fall through if we did not find a power of 2 on the right hand side! |
| 5446 // The next case must be the default. | 5418 // The next case must be the default. |
| 5447 | 5419 |
| 5448 default: { | 5420 default: { |
| 5449 Result constant_operand(value); | 5421 Result constant_operand(value); |
| 5450 if (reversed) { | 5422 if (reversed) { |
| 5451 LikelySmiBinaryOperation(op, &constant_operand, operand, | 5423 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 5452 overwrite_mode); | 5424 overwrite_mode); |
| 5453 } else { | 5425 } else { |
| 5454 LikelySmiBinaryOperation(op, operand, &constant_operand, | 5426 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, |
| 5455 overwrite_mode); | 5427 overwrite_mode); |
| 5456 } | 5428 } |
| 5457 break; | 5429 break; |
| 5458 } | 5430 } |
| 5459 } | 5431 } |
| 5460 ASSERT(!operand->is_valid()); | 5432 ASSERT(answer.is_valid()); |
| 5433 return answer; |
| 5461 } | 5434 } |
| 5462 | 5435 |
| 5463 void CodeGenerator::LikelySmiBinaryOperation(Token::Value op, | 5436 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, |
| 5464 Result* left, | 5437 Result* left, |
| 5465 Result* right, | 5438 Result* right, |
| 5466 OverwriteMode overwrite_mode) { | 5439 OverwriteMode overwrite_mode) { |
| 5440 Result answer; |
| 5467 // Special handling of div and mod because they use fixed registers. | 5441 // Special handling of div and mod because they use fixed registers. |
| 5468 if (op == Token::DIV || op == Token::MOD) { | 5442 if (op == Token::DIV || op == Token::MOD) { |
| 5469 // We need rax as the quotient register, rdx as the remainder | 5443 // We need rax as the quotient register, rdx as the remainder |
| 5470 // register, neither left nor right in rax or rdx, and left copied | 5444 // register, neither left nor right in rax or rdx, and left copied |
| 5471 // to rax. | 5445 // to rax. |
| 5472 Result quotient; | 5446 Result quotient; |
| 5473 Result remainder; | 5447 Result remainder; |
| 5474 bool left_is_in_rax = false; | 5448 bool left_is_in_rax = false; |
| 5475 // Step 1: get rax for quotient. | 5449 // Step 1: get rax for quotient. |
| 5476 if ((left->is_register() && left->reg().is(rax)) || | 5450 if ((left->is_register() && left->reg().is(rax)) || |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5538 left->reg(), | 5512 left->reg(), |
| 5539 right->reg(), | 5513 right->reg(), |
| 5540 overwrite_mode); | 5514 overwrite_mode); |
| 5541 __ JumpIfNotBothSmi(left->reg(), right->reg(), deferred->entry_label()); | 5515 __ JumpIfNotBothSmi(left->reg(), right->reg(), deferred->entry_label()); |
| 5542 | 5516 |
| 5543 if (op == Token::DIV) { | 5517 if (op == Token::DIV) { |
| 5544 __ SmiDiv(rax, left->reg(), right->reg(), deferred->entry_label()); | 5518 __ SmiDiv(rax, left->reg(), right->reg(), deferred->entry_label()); |
| 5545 deferred->BindExit(); | 5519 deferred->BindExit(); |
| 5546 left->Unuse(); | 5520 left->Unuse(); |
| 5547 right->Unuse(); | 5521 right->Unuse(); |
| 5548 frame_->Push("ient); | 5522 answer = quotient; |
| 5549 } else { | 5523 } else { |
| 5550 ASSERT(op == Token::MOD); | 5524 ASSERT(op == Token::MOD); |
| 5551 __ SmiMod(rdx, left->reg(), right->reg(), deferred->entry_label()); | 5525 __ SmiMod(rdx, left->reg(), right->reg(), deferred->entry_label()); |
| 5552 deferred->BindExit(); | 5526 deferred->BindExit(); |
| 5553 left->Unuse(); | 5527 left->Unuse(); |
| 5554 right->Unuse(); | 5528 right->Unuse(); |
| 5555 frame_->Push(&remainder); | 5529 answer = remainder; |
| 5556 } | 5530 } |
| 5557 return; | 5531 ASSERT(answer.is_valid()); |
| 5532 return answer; |
| 5558 } | 5533 } |
| 5559 | 5534 |
| 5560 // Special handling of shift operations because they use fixed | 5535 // Special handling of shift operations because they use fixed |
| 5561 // registers. | 5536 // registers. |
| 5562 if (op == Token::SHL || op == Token::SHR || op == Token::SAR) { | 5537 if (op == Token::SHL || op == Token::SHR || op == Token::SAR) { |
| 5563 // Move left out of rcx if necessary. | 5538 // Move left out of rcx if necessary. |
| 5564 if (left->is_register() && left->reg().is(rcx)) { | 5539 if (left->is_register() && left->reg().is(rcx)) { |
| 5565 *left = allocator_->Allocate(); | 5540 *left = allocator_->Allocate(); |
| 5566 ASSERT(left->is_valid()); | 5541 ASSERT(left->is_valid()); |
| 5567 __ movq(left->reg(), rcx); | 5542 __ movq(left->reg(), rcx); |
| 5568 } | 5543 } |
| 5569 right->ToRegister(rcx); | 5544 right->ToRegister(rcx); |
| 5570 left->ToRegister(); | 5545 left->ToRegister(); |
| 5571 ASSERT(left->is_register() && !left->reg().is(rcx)); | 5546 ASSERT(left->is_register() && !left->reg().is(rcx)); |
| 5572 ASSERT(right->is_register() && right->reg().is(rcx)); | 5547 ASSERT(right->is_register() && right->reg().is(rcx)); |
| 5573 | 5548 |
| 5574 // We will modify right, it must be spilled. | 5549 // We will modify right, it must be spilled. |
| 5575 frame_->Spill(rcx); | 5550 frame_->Spill(rcx); |
| 5576 | 5551 |
| 5577 // Use a fresh answer register to avoid spilling the left operand. | 5552 // Use a fresh answer register to avoid spilling the left operand. |
| 5578 Result answer = allocator_->Allocate(); | 5553 answer = allocator_->Allocate(); |
| 5579 ASSERT(answer.is_valid()); | 5554 ASSERT(answer.is_valid()); |
| 5580 // Check that both operands are smis using the answer register as a | 5555 // Check that both operands are smis using the answer register as a |
| 5581 // temporary. | 5556 // temporary. |
| 5582 DeferredInlineBinaryOperation* deferred = | 5557 DeferredInlineBinaryOperation* deferred = |
| 5583 new DeferredInlineBinaryOperation(op, | 5558 new DeferredInlineBinaryOperation(op, |
| 5584 answer.reg(), | 5559 answer.reg(), |
| 5585 left->reg(), | 5560 left->reg(), |
| 5586 rcx, | 5561 rcx, |
| 5587 overwrite_mode); | 5562 overwrite_mode); |
| 5588 __ movq(answer.reg(), left->reg()); | 5563 __ movq(answer.reg(), left->reg()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5607 rcx, | 5582 rcx, |
| 5608 deferred->entry_label()); | 5583 deferred->entry_label()); |
| 5609 break; | 5584 break; |
| 5610 } | 5585 } |
| 5611 default: | 5586 default: |
| 5612 UNREACHABLE(); | 5587 UNREACHABLE(); |
| 5613 } | 5588 } |
| 5614 deferred->BindExit(); | 5589 deferred->BindExit(); |
| 5615 left->Unuse(); | 5590 left->Unuse(); |
| 5616 right->Unuse(); | 5591 right->Unuse(); |
| 5617 frame_->Push(&answer); | 5592 ASSERT(answer.is_valid()); |
| 5618 return; | 5593 return answer; |
| 5619 } | 5594 } |
| 5620 | 5595 |
| 5621 // Handle the other binary operations. | 5596 // Handle the other binary operations. |
| 5622 left->ToRegister(); | 5597 left->ToRegister(); |
| 5623 right->ToRegister(); | 5598 right->ToRegister(); |
| 5624 // A newly allocated register answer is used to hold the answer. The | 5599 // A newly allocated register answer is used to hold the answer. The |
| 5625 // registers containing left and right are not modified so they don't | 5600 // registers containing left and right are not modified so they don't |
| 5626 // need to be spilled in the fast case. | 5601 // need to be spilled in the fast case. |
| 5627 Result answer = allocator_->Allocate(); | 5602 answer = allocator_->Allocate(); |
| 5628 ASSERT(answer.is_valid()); | 5603 ASSERT(answer.is_valid()); |
| 5629 | 5604 |
| 5630 // Perform the smi tag check. | 5605 // Perform the smi tag check. |
| 5631 DeferredInlineBinaryOperation* deferred = | 5606 DeferredInlineBinaryOperation* deferred = |
| 5632 new DeferredInlineBinaryOperation(op, | 5607 new DeferredInlineBinaryOperation(op, |
| 5633 answer.reg(), | 5608 answer.reg(), |
| 5634 left->reg(), | 5609 left->reg(), |
| 5635 right->reg(), | 5610 right->reg(), |
| 5636 overwrite_mode); | 5611 overwrite_mode); |
| 5637 __ JumpIfNotBothSmi(left->reg(), right->reg(), deferred->entry_label()); | 5612 __ JumpIfNotBothSmi(left->reg(), right->reg(), deferred->entry_label()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5671 __ SmiXor(answer.reg(), left->reg(), right->reg()); | 5646 __ SmiXor(answer.reg(), left->reg(), right->reg()); |
| 5672 break; | 5647 break; |
| 5673 | 5648 |
| 5674 default: | 5649 default: |
| 5675 UNREACHABLE(); | 5650 UNREACHABLE(); |
| 5676 break; | 5651 break; |
| 5677 } | 5652 } |
| 5678 deferred->BindExit(); | 5653 deferred->BindExit(); |
| 5679 left->Unuse(); | 5654 left->Unuse(); |
| 5680 right->Unuse(); | 5655 right->Unuse(); |
| 5681 frame_->Push(&answer); | 5656 ASSERT(answer.is_valid()); |
| 5657 return answer; |
| 5682 } | 5658 } |
| 5683 | 5659 |
| 5684 | 5660 |
| 5685 #undef __ | 5661 #undef __ |
| 5686 #define __ ACCESS_MASM(masm) | 5662 #define __ ACCESS_MASM(masm) |
| 5687 | 5663 |
| 5688 | 5664 |
| 5689 Handle<String> Reference::GetName() { | 5665 Handle<String> Reference::GetName() { |
| 5690 ASSERT(type_ == NAMED); | 5666 ASSERT(type_ == NAMED); |
| 5691 Property* property = expression_->AsProperty(); | 5667 Property* property = expression_->AsProperty(); |
| (...skipping 2709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8401 // Call the function from C++. | 8377 // Call the function from C++. |
| 8402 return FUNCTION_CAST<ModuloFunction>(buffer); | 8378 return FUNCTION_CAST<ModuloFunction>(buffer); |
| 8403 } | 8379 } |
| 8404 | 8380 |
| 8405 #endif | 8381 #endif |
| 8406 | 8382 |
| 8407 | 8383 |
| 8408 #undef __ | 8384 #undef __ |
| 8409 | 8385 |
| 8410 } } // namespace v8::internal | 8386 } } // namespace v8::internal |
| OLD | NEW |