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

Side by Side Diff: src/ia32/codegen-ia32.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 | « no previous file | src/x64/codegen-x64.cc » ('j') | 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 2414 matching lines...) Expand 10 before | Expand all | Expand 10 after
2425 // If either side is a constant of some sort, we can probably optimize the 2425 // If either side is a constant of some sort, we can probably optimize the
2426 // comparison. 2426 // comparison.
2427 bool left_side_constant_smi = false; 2427 bool left_side_constant_smi = false;
2428 bool left_side_constant_null = false; 2428 bool left_side_constant_null = false;
2429 bool left_side_constant_1_char_string = false; 2429 bool left_side_constant_1_char_string = false;
2430 if (left_side.is_constant()) { 2430 if (left_side.is_constant()) {
2431 left_side_constant_smi = left_side.handle()->IsSmi(); 2431 left_side_constant_smi = left_side.handle()->IsSmi();
2432 left_side_constant_null = left_side.handle()->IsNull(); 2432 left_side_constant_null = left_side.handle()->IsNull();
2433 left_side_constant_1_char_string = 2433 left_side_constant_1_char_string =
2434 (left_side.handle()->IsString() && 2434 (left_side.handle()->IsString() &&
2435 (String::cast(*left_side.handle())->length() == 1)); 2435 String::cast(*left_side.handle())->length() == 1 &&
2436 String::cast(*left_side.handle())->IsAsciiRepresentation());
2436 } 2437 }
2437 bool right_side_constant_smi = false; 2438 bool right_side_constant_smi = false;
2438 bool right_side_constant_null = false; 2439 bool right_side_constant_null = false;
2439 bool right_side_constant_1_char_string = false; 2440 bool right_side_constant_1_char_string = false;
2440 if (right_side.is_constant()) { 2441 if (right_side.is_constant()) {
2441 right_side_constant_smi = right_side.handle()->IsSmi(); 2442 right_side_constant_smi = right_side.handle()->IsSmi();
2442 right_side_constant_null = right_side.handle()->IsNull(); 2443 right_side_constant_null = right_side.handle()->IsNull();
2443 right_side_constant_1_char_string = 2444 right_side_constant_1_char_string =
2444 (right_side.handle()->IsString() && 2445 (right_side.handle()->IsString() &&
2445 (String::cast(*right_side.handle())->length() == 1)); 2446 String::cast(*right_side.handle())->length() == 1 &&
2447 String::cast(*right_side.handle())->IsAsciiRepresentation());
2446 } 2448 }
2447 2449
2448 if (left_side_constant_smi || right_side_constant_smi) { 2450 if (left_side_constant_smi || right_side_constant_smi) {
2449 if (left_side_constant_smi && right_side_constant_smi) { 2451 if (left_side_constant_smi && right_side_constant_smi) {
2450 // Trivial case, comparing two constants. 2452 // Trivial case, comparing two constants.
2451 int left_value = Smi::cast(*left_side.handle())->value(); 2453 int left_value = Smi::cast(*left_side.handle())->value();
2452 int right_value = Smi::cast(*right_side.handle())->value(); 2454 int right_value = Smi::cast(*right_side.handle())->value();
2453 switch (cc) { 2455 switch (cc) {
2454 case less: 2456 case less:
2455 dest->Goto(left_value < right_value); 2457 dest->Goto(left_value < right_value);
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
2624 left_side.ToRegister(); 2626 left_side.ToRegister();
2625 2627
2626 // Here we split control flow to the stub call and inlined cases 2628 // Here we split control flow to the stub call and inlined cases
2627 // before finally splitting it to the control destination. We use 2629 // before finally splitting it to the control destination. We use
2628 // a jump target and branching to duplicate the virtual frame at 2630 // a jump target and branching to duplicate the virtual frame at
2629 // the first split. We manually handle the off-frame references 2631 // the first split. We manually handle the off-frame references
2630 // by reconstituting them on the non-fall-through path. 2632 // by reconstituting them on the non-fall-through path.
2631 JumpTarget is_not_string, is_string; 2633 JumpTarget is_not_string, is_string;
2632 Register left_reg = left_side.reg(); 2634 Register left_reg = left_side.reg();
2633 Handle<Object> right_val = right_side.handle(); 2635 Handle<Object> right_val = right_side.handle();
2636 ASSERT(StringShape(String::cast(*right_val)).IsSymbol());
2634 __ test(left_side.reg(), Immediate(kSmiTagMask)); 2637 __ test(left_side.reg(), Immediate(kSmiTagMask));
2635 is_not_string.Branch(zero, &left_side); 2638 is_not_string.Branch(zero, &left_side);
2636 Result temp = allocator_->Allocate(); 2639 Result temp = allocator_->Allocate();
2637 ASSERT(temp.is_valid()); 2640 ASSERT(temp.is_valid());
2638 __ mov(temp.reg(), 2641 __ mov(temp.reg(),
2639 FieldOperand(left_side.reg(), HeapObject::kMapOffset)); 2642 FieldOperand(left_side.reg(), HeapObject::kMapOffset));
2640 __ movzx_b(temp.reg(), 2643 __ movzx_b(temp.reg(),
2641 FieldOperand(temp.reg(), Map::kInstanceTypeOffset)); 2644 FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
2642 // If we are testing for equality then make use of the symbol shortcut. 2645 // If we are testing for equality then make use of the symbol shortcut.
2643 // Check if the right left hand side has the same type as the left hand 2646 // Check if the right left hand side has the same type as the left hand
2644 // side (which is always a symbol). 2647 // side (which is always a symbol).
2645 if (cc == equal) { 2648 if (cc == equal) {
2646 Label not_a_symbol; 2649 Label not_a_symbol;
2647 ASSERT(kSymbolTag != 0); 2650 ASSERT(kSymbolTag != 0);
2648 // Ensure that no non-strings have the symbol bit set. 2651 // Ensure that no non-strings have the symbol bit set.
2649 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE); 2652 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
2650 __ test(temp.reg(), Immediate(kIsSymbolMask)); // Test the symbol bit. 2653 __ test(temp.reg(), Immediate(kIsSymbolMask)); // Test the symbol bit.
2651 __ j(zero, &not_a_symbol); 2654 __ j(zero, &not_a_symbol);
2652 // They are symbols, so do identity compare. 2655 // They are symbols, so do identity compare.
2653 __ cmp(left_side.reg(), right_side.handle()); 2656 __ cmp(left_side.reg(), right_side.handle());
2654 dest->true_target()->Branch(equal); 2657 dest->true_target()->Branch(equal);
2655 dest->false_target()->Branch(not_equal); 2658 dest->false_target()->Branch(not_equal);
2656 __ bind(&not_a_symbol); 2659 __ bind(&not_a_symbol);
2657 } 2660 }
2658 // If the receiver is not a string of the type we handle call the stub. 2661 // Call the compare stub if the left side is not a flat ascii string.
2659 __ and_(temp.reg(), 2662 __ and_(temp.reg(),
2660 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); 2663 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
2661 __ cmp(temp.reg(), kStringTag | kSeqStringTag | kAsciiStringTag); 2664 __ cmp(temp.reg(), kStringTag | kSeqStringTag | kAsciiStringTag);
2662 temp.Unuse(); 2665 temp.Unuse();
2663 is_string.Branch(equal, &left_side); 2666 is_string.Branch(equal, &left_side);
2664 2667
2665 // Setup and call the compare stub. 2668 // Setup and call the compare stub.
2666 is_not_string.Bind(&left_side); 2669 is_not_string.Bind(&left_side);
2667 CompareStub stub(cc, strict, kCantBothBeNaN); 2670 CompareStub stub(cc, strict, kCantBothBeNaN);
2668 Result result = frame_->CallStub(&stub, &left_side, &right_side); 2671 Result result = frame_->CallStub(&stub, &left_side, &right_side);
2669 result.ToRegister(); 2672 result.ToRegister();
2670 __ cmp(result.reg(), 0); 2673 __ cmp(result.reg(), 0);
2671 result.Unuse(); 2674 result.Unuse();
2672 dest->true_target()->Branch(cc); 2675 dest->true_target()->Branch(cc);
2673 dest->false_target()->Jump(); 2676 dest->false_target()->Jump();
2674 2677
2675 is_string.Bind(&left_side); 2678 is_string.Bind(&left_side);
2676 // Here we know we have a sequential ASCII string. 2679 // left_side is a sequential ASCII string.
2677 left_side = Result(left_reg); 2680 left_side = Result(left_reg);
2678 right_side = Result(right_val); 2681 right_side = Result(right_val);
2679 Result temp2 = allocator_->Allocate(); 2682 Result temp2 = allocator_->Allocate();
2680 ASSERT(temp2.is_valid()); 2683 ASSERT(temp2.is_valid());
2681 // Test string equality and comparison. 2684 // Test string equality and comparison.
2682 if (cc == equal) { 2685 if (cc == equal) {
2683 Label comparison_done; 2686 Label comparison_done;
2684 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2687 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2685 Immediate(1)); 2688 Immediate(1));
2686 __ j(not_equal, &comparison_done); 2689 __ j(not_equal, &comparison_done);
2687 uint8_t char_value = 2690 uint8_t char_value =
2688 static_cast<uint8_t>(String::cast(*right_side.handle())->Get(0)); 2691 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
2689 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize), 2692 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
2690 char_value); 2693 char_value);
2691 __ bind(&comparison_done); 2694 __ bind(&comparison_done);
2692 } else { 2695 } else {
2693 __ mov(temp2.reg(), 2696 __ mov(temp2.reg(),
2694 FieldOperand(left_side.reg(), String::kLengthOffset)); 2697 FieldOperand(left_side.reg(), String::kLengthOffset));
2695 __ sub(Operand(temp2.reg()), Immediate(1)); 2698 __ sub(Operand(temp2.reg()), Immediate(1));
2696 Label comparison; 2699 Label comparison;
2697 // If the length is 0 then our subtraction gave -1 which compares less 2700 // If the length is 0 then the subtraction gave -1 which compares less
2698 // than any character. 2701 // than any character.
2699 __ j(negative, &comparison); 2702 __ j(negative, &comparison);
2700 // Otherwise load the first character. 2703 // Otherwise load the first character.
2701 __ movzx_b(temp2.reg(), 2704 __ movzx_b(temp2.reg(),
2702 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize)); 2705 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize));
2703 __ bind(&comparison); 2706 __ bind(&comparison);
2704 // Compare the first character of the string with out constant 2707 // Compare the first character of the string with the
2705 // 1-character string. 2708 // constant 1-character string.
2706 uint8_t char_value = 2709 uint8_t char_value =
2707 static_cast<uint8_t>(String::cast(*right_side.handle())->Get(0)); 2710 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
2708 __ cmp(Operand(temp2.reg()), Immediate(char_value)); 2711 __ cmp(Operand(temp2.reg()), Immediate(char_value));
2709 Label characters_were_different; 2712 Label characters_were_different;
2710 __ j(not_equal, &characters_were_different); 2713 __ j(not_equal, &characters_were_different);
2711 // If the first character is the same then the long string sorts after 2714 // If the first character is the same then the long string sorts after
2712 // the short one. 2715 // the short one.
2713 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2716 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2714 Immediate(1)); 2717 Immediate(1));
2715 __ bind(&characters_were_different); 2718 __ bind(&characters_were_different);
2716 } 2719 }
2717 temp2.Unuse(); 2720 temp2.Unuse();
(...skipping 10082 matching lines...) Expand 10 before | Expand all | Expand 10 after
12800 12803
12801 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 12804 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
12802 // tagged as a small integer. 12805 // tagged as a small integer.
12803 __ bind(&runtime); 12806 __ bind(&runtime);
12804 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 12807 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
12805 } 12808 }
12806 12809
12807 #undef __ 12810 #undef __
12808 12811
12809 } } // namespace v8::internal 12812 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/x64/codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698