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

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

Issue 546087: Implement inline string compare on ARM. (Closed)
Patch Set: Further optimization of ARM version 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
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-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 3558 matching lines...) Expand 10 before | Expand all | Expand 10 after
3569 frame_->EmitPush(r0); 3569 frame_->EmitPush(r0);
3570 } 3570 }
3571 3571
3572 3572
3573 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { 3573 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) {
3574 ASSERT_EQ(2, args->length()); 3574 ASSERT_EQ(2, args->length());
3575 3575
3576 Load(args->at(0)); 3576 Load(args->at(0));
3577 Load(args->at(1)); 3577 Load(args->at(1));
3578 3578
3579 frame_->CallRuntime(Runtime::kStringCompare, 2); 3579 StringCompareStub stub;
3580 frame_->CallStub(&stub, 2);
3580 frame_->EmitPush(r0); 3581 frame_->EmitPush(r0);
3581 } 3582 }
3582 3583
3583 3584
3584 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { 3585 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) {
3585 ASSERT_EQ(4, args->length()); 3586 ASSERT_EQ(4, args->length());
3586 3587
3587 Load(args->at(0)); 3588 Load(args->at(0));
3588 Load(args->at(1)); 3589 Load(args->at(1));
3589 Load(args->at(2)); 3590 Load(args->at(2));
(...skipping 1492 matching lines...) Expand 10 before | Expand all | Expand 10 after
5082 __ tst(r3, Operand(kIsSymbolMask)); 5083 __ tst(r3, Operand(kIsSymbolMask));
5083 __ b(eq, slow); 5084 __ b(eq, slow);
5084 5085
5085 // Both are symbols. We already checked they weren't the same pointer 5086 // Both are symbols. We already checked they weren't the same pointer
5086 // so they are not equal. 5087 // so they are not equal.
5087 __ mov(r0, Operand(1)); // Non-zero indicates not equal. 5088 __ mov(r0, Operand(1)); // Non-zero indicates not equal.
5088 __ mov(pc, Operand(lr)); // Return. 5089 __ mov(pc, Operand(lr)); // Return.
5089 } 5090 }
5090 5091
5091 5092
5092 // On entry r0 and r1 are the things to be compared. On exit r0 is 0, 5093 // On entry r0 (rhs) and r1 (lhs) are the values to be compared.
5093 // positive or negative to indicate the result of the comparison. 5094 // On exit r0 is 0, positive or negative to indicate the result of
5095 // the comparison.
5094 void CompareStub::Generate(MacroAssembler* masm) { 5096 void CompareStub::Generate(MacroAssembler* masm) {
5095 Label slow; // Call builtin. 5097 Label slow; // Call builtin.
5096 Label not_smis, both_loaded_as_doubles, lhs_not_nan; 5098 Label not_smis, both_loaded_as_doubles, lhs_not_nan;
5097 5099
5098 // NOTICE! This code is only reached after a smi-fast-case check, so 5100 // NOTICE! This code is only reached after a smi-fast-case check, so
5099 // it is certain that at least one operand isn't a smi. 5101 // it is certain that at least one operand isn't a smi.
5100 5102
5101 // Handle the case where the objects are identical. Either returns the answer 5103 // Handle the case where the objects are identical. Either returns the answer
5102 // or goes to slow. Only falls through if the objects were not identical. 5104 // or goes to slow. Only falls through if the objects were not identical.
5103 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_); 5105 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
5161 __ bind(&not_smis); 5163 __ bind(&not_smis);
5162 // At this point we know we are dealing with two different objects, 5164 // At this point we know we are dealing with two different objects,
5163 // and neither of them is a Smi. The objects are in r0 and r1. 5165 // and neither of them is a Smi. The objects are in r0 and r1.
5164 if (strict_) { 5166 if (strict_) {
5165 // This returns non-equal for some object types, or falls through if it 5167 // This returns non-equal for some object types, or falls through if it
5166 // was not lucky. 5168 // was not lucky.
5167 EmitStrictTwoHeapObjectCompare(masm); 5169 EmitStrictTwoHeapObjectCompare(masm);
5168 } 5170 }
5169 5171
5170 Label check_for_symbols; 5172 Label check_for_symbols;
5173 Label flat_string_check;
5171 // Check for heap-number-heap-number comparison. Can jump to slow case, 5174 // Check for heap-number-heap-number comparison. Can jump to slow case,
5172 // or load both doubles into r0, r1, r2, r3 and jump to the code that handles 5175 // or load both doubles into r0, r1, r2, r3 and jump to the code that handles
5173 // that case. If the inputs are not doubles then jumps to check_for_symbols. 5176 // that case. If the inputs are not doubles then jumps to check_for_symbols.
5174 // In this case r2 will contain the type of r0. Never falls through. 5177 // In this case r2 will contain the type of r0. Never falls through.
5175 EmitCheckForTwoHeapNumbers(masm, 5178 EmitCheckForTwoHeapNumbers(masm,
5176 &both_loaded_as_doubles, 5179 &both_loaded_as_doubles,
5177 &check_for_symbols, 5180 &check_for_symbols,
5178 &slow); 5181 &flat_string_check);
5179 5182
5180 __ bind(&check_for_symbols); 5183 __ bind(&check_for_symbols);
5181 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of 5184 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of
5182 // symbols. 5185 // symbols.
5183 if (cc_ == eq && !strict_) { 5186 if (cc_ == eq && !strict_) {
5184 // Either jumps to slow or returns the answer. Assumes that r2 is the type 5187 // Either jumps to slow or returns the answer. Assumes that r2 is the type
5185 // of r0 on entry. 5188 // of r0 on entry.
5186 EmitCheckForSymbols(masm, &slow); 5189 EmitCheckForSymbols(masm, &flat_string_check);
5187 } 5190 }
5188 5191
5192 // Check for both being sequential ASCII strings, and inline if that is the
5193 // case.
5194 __ bind(&flat_string_check);
5195
5196 __ JumpIfNonSmisNotBothSequentialAsciiStrings(r0, r1, r2, r3, &slow);
5197
5198 __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
5199 StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
5200 r1,
5201 r0,
5202 r2,
5203 r3,
5204 r4,
5205 r5);
5206 // Never falls through to here.
5207
5189 __ bind(&slow); 5208 __ bind(&slow);
5209
5190 __ push(r1); 5210 __ push(r1);
5191 __ push(r0); 5211 __ push(r0);
5192 // Figure out which native to call and setup the arguments. 5212 // Figure out which native to call and setup the arguments.
5193 Builtins::JavaScript native; 5213 Builtins::JavaScript native;
5194 if (cc_ == eq) { 5214 if (cc_ == eq) {
5195 native = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 5215 native = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
5196 } else { 5216 } else {
5197 native = Builtins::COMPARE; 5217 native = Builtins::COMPARE;
5198 int ncr; // NaN compare result 5218 int ncr; // NaN compare result
5199 if (cc_ == lt || cc_ == le) { 5219 if (cc_ == lt || cc_ == le) {
(...skipping 1530 matching lines...) Expand 10 before | Expand all | Expand 10 after
6730 6750
6731 int CompareStub::MinorKey() { 6751 int CompareStub::MinorKey() {
6732 // Encode the three parameters in a unique 16 bit value. 6752 // Encode the three parameters in a unique 16 bit value.
6733 ASSERT((static_cast<unsigned>(cc_) >> 26) < (1 << 16)); 6753 ASSERT((static_cast<unsigned>(cc_) >> 26) < (1 << 16));
6734 int nnn_value = (never_nan_nan_ ? 2 : 0); 6754 int nnn_value = (never_nan_nan_ ? 2 : 0);
6735 if (cc_ != eq) nnn_value = 0; // Avoid duplicate stubs. 6755 if (cc_ != eq) nnn_value = 0; // Avoid duplicate stubs.
6736 return (static_cast<unsigned>(cc_) >> 26) | nnn_value | (strict_ ? 1 : 0); 6756 return (static_cast<unsigned>(cc_) >> 26) | nnn_value | (strict_ ? 1 : 0);
6737 } 6757 }
6738 6758
6739 6759
6760
6761
6762 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
6763 Register left,
6764 Register right,
6765 Register scratch1,
6766 Register scratch2,
6767 Register scratch3,
6768 Register scratch4) {
6769 Label compare_lengths;
6770 // Find minimum length and length difference.
6771 __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset));
6772 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
6773 __ sub(scratch3, scratch1, Operand(scratch2), SetCC);
6774 Register length_delta = scratch3;
6775 __ mov(scratch1, scratch2, LeaveCC, gt);
6776 Register min_length = scratch1;
6777 __ tst(min_length, Operand(min_length));
6778 __ b(eq, &compare_lengths);
6779
6780 // Setup registers so that we only need to increment one register
6781 // in the loop.
6782 __ add(scratch2, min_length,
6783 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
6784 __ add(left, left, Operand(scratch2));
6785 __ add(right, right, Operand(scratch2));
6786 // Registers left and right points to the min_length character of strings.
6787 __ rsb(min_length, min_length, Operand(-1));
6788 Register index = min_length;
6789 // Index starts at -min_length.
6790
6791 {
6792 // Compare loop.
6793 Label loop;
6794 __ bind(&loop);
6795 // Compare characters.
6796 __ add(index, index, Operand(1), SetCC);
6797 __ ldrb(scratch2, MemOperand(left, index), ne);
6798 __ ldrb(scratch4, MemOperand(right, index), ne);
6799 // Skip to compare lengths with eq condition true.
6800 __ b(eq, &compare_lengths);
6801 __ cmp(scratch2, scratch4);
6802 __ b(eq, &loop);
6803 // Fallthrough with eq condition false.
6804 }
6805 // Compare lengths - strings up to min-length are equal.
6806 __ bind(&compare_lengths);
6807 ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
6808 // Use zero length_delta as result.
6809 __ mov(r0, Operand(length_delta), SetCC, eq);
6810 // Fall through to here if characters compare not-equal.
6811 __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt);
6812 __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt);
6813 __ Ret();
6814 }
6815
6816
6817 void StringCompareStub::Generate(MacroAssembler* masm) {
6818 Label runtime;
6819
6820 // Stack frame on entry.
6821 // sp[0]: return address
6822 // sp[4]: right string
6823 // sp[8]: left string
6824
6825 __ ldr(r0, MemOperand(sp, 2 * kPointerSize)); // left
6826 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); // right
6827
6828 Label not_same;
6829 __ cmp(r0, r1);
6830 __ b(ne, &not_same);
6831 ASSERT_EQ(0, EQUAL);
6832 ASSERT_EQ(0, kSmiTag);
6833 __ mov(r0, Operand(Smi::FromInt(EQUAL)));
6834 __ IncrementCounter(&Counters::string_compare_native, 1, r1, r2);
6835 __ add(sp, sp, Operand(2 * kPointerSize));
6836 __ Ret();
6837
6838 __ bind(&not_same);
6839
6840 // Check that both objects are sequential ascii strings.
6841 __ JumpIfNotBothSequentialAsciiStrings(r0, r1, r2, r3, &runtime);
6842
6843 // Compare flat ascii strings natively. Remove arguments from stack first.
6844 __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
6845 __ add(sp, sp, Operand(2 * kPointerSize));
6846 GenerateCompareFlatAsciiStrings(masm, r0, r1, r2, r3, r4, r5);
6847
6848 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
6849 // tagged as a small integer.
6850 __ bind(&runtime);
6851 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1);
6852 }
6853
6854
6740 #undef __ 6855 #undef __
6741 6856
6742 } } // namespace v8::internal 6857 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698