Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(354)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 551080: Refactor GenericBinaryOperation and its helper functions to always return a R... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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(&quotient); 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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698