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

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

Issue 1627014: Port optimized comparison of a string to a constant single character string t... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 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/ia32/codegen-ia32.cc ('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 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 5223 matching lines...) Expand 10 before | Expand all | Expand 10 after
5234 cc = ReverseCondition(cc); 5234 cc = ReverseCondition(cc);
5235 left_side = frame_->Pop(); 5235 left_side = frame_->Pop();
5236 right_side = frame_->Pop(); 5236 right_side = frame_->Pop();
5237 } else { 5237 } else {
5238 right_side = frame_->Pop(); 5238 right_side = frame_->Pop();
5239 left_side = frame_->Pop(); 5239 left_side = frame_->Pop();
5240 } 5240 }
5241 ASSERT(cc == less || cc == equal || cc == greater_equal); 5241 ASSERT(cc == less || cc == equal || cc == greater_equal);
5242 5242
5243 // If either side is a constant smi, optimize the comparison. 5243 // If either side is a constant smi, optimize the comparison.
5244 bool left_side_constant_smi = 5244 bool left_side_constant_smi = false;
5245 left_side.is_constant() && left_side.handle()->IsSmi(); 5245 bool left_side_constant_null = false;
5246 bool right_side_constant_smi = 5246 bool left_side_constant_1_char_string = false;
5247 right_side.is_constant() && right_side.handle()->IsSmi(); 5247 if (left_side.is_constant()) {
5248 bool left_side_constant_null = 5248 left_side_constant_smi = left_side.handle()->IsSmi();
5249 left_side.is_constant() && left_side.handle()->IsNull(); 5249 left_side_constant_null = left_side.handle()->IsNull();
5250 bool right_side_constant_null = 5250 left_side_constant_1_char_string =
5251 right_side.is_constant() && right_side.handle()->IsNull(); 5251 (left_side.handle()->IsString() &&
5252 String::cast(*left_side.handle())->length() == 1 &&
5253 String::cast(*left_side.handle())->IsAsciiRepresentation());
5254 }
5255 bool right_side_constant_smi = false;
5256 bool right_side_constant_null = false;
5257 bool right_side_constant_1_char_string = false;
5258 if (right_side.is_constant()) {
5259 right_side_constant_smi = right_side.handle()->IsSmi();
5260 right_side_constant_null = right_side.handle()->IsNull();
5261 right_side_constant_1_char_string =
5262 (right_side.handle()->IsString() &&
5263 String::cast(*right_side.handle())->length() == 1 &&
5264 String::cast(*right_side.handle())->IsAsciiRepresentation());
5265 }
5252 5266
5253 if (left_side_constant_smi || right_side_constant_smi) { 5267 if (left_side_constant_smi || right_side_constant_smi) {
5254 if (left_side_constant_smi && right_side_constant_smi) { 5268 if (left_side_constant_smi && right_side_constant_smi) {
5255 // Trivial case, comparing two constants. 5269 // Trivial case, comparing two constants.
5256 int left_value = Smi::cast(*left_side.handle())->value(); 5270 int left_value = Smi::cast(*left_side.handle())->value();
5257 int right_value = Smi::cast(*right_side.handle())->value(); 5271 int right_value = Smi::cast(*right_side.handle())->value();
5258 switch (cc) { 5272 switch (cc) {
5259 case less: 5273 case less:
5260 dest->Goto(left_value < right_value); 5274 dest->Goto(left_value < right_value);
5261 break; 5275 break;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
5381 Result temp = allocator()->Allocate(); 5395 Result temp = allocator()->Allocate();
5382 ASSERT(temp.is_valid()); 5396 ASSERT(temp.is_valid());
5383 __ movq(temp.reg(), 5397 __ movq(temp.reg(),
5384 FieldOperand(operand.reg(), HeapObject::kMapOffset)); 5398 FieldOperand(operand.reg(), HeapObject::kMapOffset));
5385 __ testb(FieldOperand(temp.reg(), Map::kBitFieldOffset), 5399 __ testb(FieldOperand(temp.reg(), Map::kBitFieldOffset),
5386 Immediate(1 << Map::kIsUndetectable)); 5400 Immediate(1 << Map::kIsUndetectable));
5387 temp.Unuse(); 5401 temp.Unuse();
5388 operand.Unuse(); 5402 operand.Unuse();
5389 dest->Split(not_zero); 5403 dest->Split(not_zero);
5390 } 5404 }
5405 } else if (left_side_constant_1_char_string ||
5406 right_side_constant_1_char_string) {
5407 if (left_side_constant_1_char_string && right_side_constant_1_char_string) {
5408 // Trivial case, comparing two constants.
5409 int left_value = String::cast(*left_side.handle())->Get(0);
5410 int right_value = String::cast(*right_side.handle())->Get(0);
5411 switch (cc) {
5412 case less:
5413 dest->Goto(left_value < right_value);
5414 break;
5415 case equal:
5416 dest->Goto(left_value == right_value);
5417 break;
5418 case greater_equal:
5419 dest->Goto(left_value >= right_value);
5420 break;
5421 default:
5422 UNREACHABLE();
5423 }
5424 } else {
5425 // Only one side is a constant 1 character string.
5426 // If left side is a constant 1-character string, reverse the operands.
5427 // Since one side is a constant string, conversion order does not matter.
5428 if (left_side_constant_1_char_string) {
5429 Result temp = left_side;
5430 left_side = right_side;
5431 right_side = temp;
5432 cc = ReverseCondition(cc);
5433 // This may reintroduce greater or less_equal as the value of cc.
5434 // CompareStub and the inline code both support all values of cc.
5435 }
5436 // Implement comparison against a constant string, inlining the case
5437 // where both sides are strings.
5438 left_side.ToRegister();
5439
5440 // Here we split control flow to the stub call and inlined cases
5441 // before finally splitting it to the control destination. We use
5442 // a jump target and branching to duplicate the virtual frame at
5443 // the first split. We manually handle the off-frame references
5444 // by reconstituting them on the non-fall-through path.
5445 JumpTarget is_not_string, is_string;
5446 Register left_reg = left_side.reg();
5447 Handle<Object> right_val = right_side.handle();
5448 ASSERT(StringShape(String::cast(*right_val)).IsSymbol());
5449 Condition is_smi = masm()->CheckSmi(left_reg);
5450 is_not_string.Branch(is_smi, &left_side);
5451 Result temp = allocator_->Allocate();
5452 ASSERT(temp.is_valid());
5453 __ movq(temp.reg(),
5454 FieldOperand(left_reg, HeapObject::kMapOffset));
5455 __ movzxbl(temp.reg(),
5456 FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
5457 // If we are testing for equality then make use of the symbol shortcut.
5458 // Check if the left hand side has the same type as the right hand
5459 // side (which is always a symbol).
5460 if (cc == equal) {
5461 Label not_a_symbol;
5462 ASSERT(kSymbolTag != 0);
5463 // Ensure that no non-strings have the symbol bit set.
5464 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
5465 __ testb(temp.reg(), Immediate(kIsSymbolMask)); // Test the symbol bit.
5466 __ j(zero, &not_a_symbol);
5467 // They are symbols, so do identity compare.
5468 __ Cmp(left_reg, right_side.handle());
5469 dest->true_target()->Branch(equal);
5470 dest->false_target()->Branch(not_equal);
5471 __ bind(&not_a_symbol);
5472 }
5473 // Call the compare stub if the left side is not a flat ascii string.
5474 __ andb(temp.reg(),
5475 Immediate(kIsNotStringMask |
5476 kStringRepresentationMask |
5477 kStringEncodingMask));
5478 __ cmpb(temp.reg(),
5479 Immediate(kStringTag | kSeqStringTag | kAsciiStringTag));
5480 temp.Unuse();
5481 is_string.Branch(equal, &left_side);
5482
5483 // Setup and call the compare stub.
5484 is_not_string.Bind(&left_side);
5485 CompareStub stub(cc, strict, kCantBothBeNaN);
5486 Result result = frame_->CallStub(&stub, &left_side, &right_side);
5487 result.ToRegister();
5488 __ SmiCompare(result.reg(), Smi::FromInt(0));
5489 result.Unuse();
5490 dest->true_target()->Branch(cc);
5491 dest->false_target()->Jump();
5492
5493 is_string.Bind(&left_side);
5494 // left_side is a sequential ASCII string.
5495 ASSERT(left_side.reg().is(left_reg));
5496 right_side = Result(right_val);
5497 Result temp2 = allocator_->Allocate();
5498 ASSERT(temp2.is_valid());
5499 // Test string equality and comparison.
5500 if (cc == equal) {
5501 Label comparison_done;
5502 __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset),
5503 Immediate(1));
5504 __ j(not_equal, &comparison_done);
5505 uint8_t char_value =
5506 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
5507 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
5508 Immediate(char_value));
5509 __ bind(&comparison_done);
5510 } else {
5511 __ movl(temp2.reg(),
5512 FieldOperand(left_side.reg(), String::kLengthOffset));
5513 __ subl(temp2.reg(), Immediate(1));
5514 Label comparison;
5515 // If the length is 0 then the subtraction gave -1 which compares less
5516 // than any character.
5517 __ j(negative, &comparison);
5518 // Otherwise load the first character.
5519 __ movzxbl(temp2.reg(),
5520 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize));
5521 __ bind(&comparison);
5522 // Compare the first character of the string with the
5523 // constant 1-character string.
5524 uint8_t char_value =
5525 static_cast<uint8_t>(String::cast(*right_side.handle())->Get(0));
5526 __ cmpb(temp2.reg(), Immediate(char_value));
5527 Label characters_were_different;
5528 __ j(not_equal, &characters_were_different);
5529 // If the first character is the same then the long string sorts after
5530 // the short one.
5531 __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset),
5532 Immediate(1));
5533 __ bind(&characters_were_different);
5534 }
5535 temp2.Unuse();
5536 left_side.Unuse();
5537 right_side.Unuse();
5538 dest->Split(cc);
5539 }
5391 } else { // Neither side is a constant Smi or null. 5540 } else { // Neither side is a constant Smi or null.
5392 // If either side is a non-smi constant, skip the smi check. 5541 // If either side is a non-smi constant, skip the smi check.
5393 bool known_non_smi = 5542 bool known_non_smi =
5394 (left_side.is_constant() && !left_side.handle()->IsSmi()) || 5543 (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
5395 (right_side.is_constant() && !right_side.handle()->IsSmi()); 5544 (right_side.is_constant() && !right_side.handle()->IsSmi());
5396 left_side.ToRegister(); 5545 left_side.ToRegister();
5397 right_side.ToRegister(); 5546 right_side.ToRegister();
5398 5547
5399 if (known_non_smi) { 5548 if (known_non_smi) {
5400 // When non-smi, call out to the compare stub. 5549 // When non-smi, call out to the compare stub.
(...skipping 4803 matching lines...) Expand 10 before | Expand all | Expand 10 after
10204 // Call the function from C++. 10353 // Call the function from C++.
10205 return FUNCTION_CAST<ModuloFunction>(buffer); 10354 return FUNCTION_CAST<ModuloFunction>(buffer);
10206 } 10355 }
10207 10356
10208 #endif 10357 #endif
10209 10358
10210 10359
10211 #undef __ 10360 #undef __
10212 10361
10213 } } // namespace v8::internal 10362 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698