Chromium Code Reviews| Index: runtime/vm/intrinsifier_arm.cc |
| diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc |
| index 25b53b33227af0d9c848ebf7f8e4603ecd4603d2..ef60734ce9d97d1b949cd501c8879eaa9d99ffe1 100644 |
| --- a/runtime/vm/intrinsifier_arm.cc |
| +++ b/runtime/vm/intrinsifier_arm.cc |
| @@ -1597,6 +1597,122 @@ void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { |
| } |
| +void GenerateSubstringMatchesSpecialization(Assembler* assembler, |
| + intptr_t receiver_cid, |
| + intptr_t other_cid, |
| + Label* return_true, |
| + Label* return_false) { |
| + __ SmiUntag(R1); |
| + __ ldr(R8, FieldAddress(R0, String::length_offset())); // this.length |
| + __ SmiUntag(R8); |
| + __ ldr(R9, FieldAddress(R2, String::length_offset())); // other.length |
| + __ SmiUntag(R9); |
| + |
| + // if (other.length == 0) return true; |
| + __ cmp(R9, Operand(0)); |
| + __ b(return_true, EQ); |
| + |
| + // if (start < 0) return false; |
| + __ cmp(R1, Operand(0)); |
| + __ b(return_false, LT); |
| + |
| + // if (start + other.length > this.length) return false; |
| + __ add(R3, R1, Operand(R9)); |
| + __ cmp(R3, Operand(R8)); |
| + __ b(return_false, GT); |
| + |
| + if (receiver_cid == kOneByteStringCid) { |
| + __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag); |
| + __ add(R0, R0, Operand(R1)); |
| + } else { |
| + ASSERT(receiver_cid == kTwoByteStringCid); |
| + __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag); |
| + __ add(R0, R0, Operand(R1)); |
| + __ add(R0, R0, Operand(R1)); |
| + } |
| + if (other_cid == kOneByteStringCid) { |
| + __ AddImmediate(R2, R2, OneByteString::data_offset() - kHeapObjectTag); |
| + } else { |
| + ASSERT(other_cid == kTwoByteStringCid); |
| + __ AddImmediate(R2, R2, TwoByteString::data_offset() - kHeapObjectTag); |
| + } |
| + |
| + // i = 0 |
| + __ LoadImmediate(R3, 0); |
| + |
| + // while (i < len) |
| + Label loop; |
| + __ Bind(&loop); |
| + __ cmp(R3, Operand(R9/*otherlength*/)); |
|
Florian Schneider
2015/11/18 10:26:03
s/otherlength/other.length/
|
| + __ b(return_true, GE); |
| + |
| + if (receiver_cid == kOneByteStringCid) { |
| + __ ldrb(R4, Address(R0, 0)); // this.codeUnitAt(i + start) |
| + } else { |
| + __ ldrh(R4, Address(R0, 0)); // this.codeUnitAt(i + start) |
| + } |
| + if (other_cid == kOneByteStringCid) { |
| + __ ldrb(NOTFP, Address(R2, 0)); // other.codeUnitAt(i) |
| + } else { |
| + __ ldrh(NOTFP, Address(R2, 0)); // other.codeUnitAt(i) |
| + } |
| + __ cmp(R4, Operand(NOTFP)); |
| + __ b(return_false, NE); |
| + |
| + // i++ |
| + __ AddImmediate(R3, R3, 1); |
| + __ AddImmediate(R0, R0, receiver_cid == kOneByteStringCid ? 1 : 2); |
| + __ AddImmediate(R2, R2, other_cid == kOneByteStringCid ? 1 : 2); |
| + __ b(&loop); |
| +} |
| + |
| + |
| +// bool _substringMatches(int start, String other) |
| +// Clobbers ARGS_DESCRIPTOR_REG. Safe because this method has no optional |
|
srdjan
2015/11/18 17:52:54
s/ARGS_DESCRIPTOR_REG/ARGS_DESC_REG/
|
| +// parameters. |
| +void Intrinsifier::StringBaseSubstringMatches(Assembler* assembler) { |
|
srdjan
2015/11/18 17:52:54
You could push R4 (arg_desc) and restore it when r
rmacnak
2015/11/18 22:33:32
Done.
|
| + Label fall_through, return_true, return_false, try_two_byte; |
| + __ ldr(R0, Address(SP, 2 * kWordSize)); // this |
| + __ ldr(R1, Address(SP, 1 * kWordSize)); // start |
| + __ ldr(R2, Address(SP, 0 * kWordSize)); // other |
| + |
| + __ tst(R1, Operand(kSmiTagMask)); |
| + __ b(&fall_through, NE); // Index is not a Smi. |
|
srdjan
2015/11/18 17:52:54
'start' is not a smi
rmacnak
2015/11/18 22:33:32
Done.
|
| + |
| + __ CompareClassId(R2, kOneByteStringCid, R3); |
|
srdjan
2015/11/18 17:52:54
Add somewhere (top of function?):
Supports one-
rmacnak
2015/11/18 22:33:32
Done.
|
| + __ b(&fall_through, NE); |
| + |
| + __ CompareClassId(R0, kOneByteStringCid, R3); |
| + __ b(&try_two_byte, NE); |
| + |
| + GenerateSubstringMatchesSpecialization(assembler, |
| + kOneByteStringCid, |
| + kOneByteStringCid, |
| + &return_true, |
| + &return_false); |
| + |
| + __ Bind(&try_two_byte); |
|
srdjan
2015/11/18 17:52:54
s/try_two_byte/try_two_byte_this/
|
| + __ CompareClassId(R0, kTwoByteStringCid, R3); |
| + __ b(&fall_through, NE); |
| + |
| + GenerateSubstringMatchesSpecialization(assembler, |
| + kTwoByteStringCid, |
| + kOneByteStringCid, |
| + &return_true, |
| + &return_false); |
| + |
| + __ Bind(&return_true); |
| + __ LoadObject(R0, Bool::True()); |
| + __ Ret(); |
| + |
| + __ Bind(&return_false); |
| + __ LoadObject(R0, Bool::False()); |
| + __ Ret(); |
| + |
| + __ Bind(&fall_through); |
| +} |
| + |
| + |
| void Intrinsifier::StringBaseCharAt(Assembler* assembler) { |
| Label fall_through, try_two_byte_string; |