Index: src/arm/code-stubs-arm.cc |
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc |
index 8b0779bcf26fb41621d0b9e606f966f30326eb90..8c6d17e563c3be2d0d098e7b381f28783b9ba135 100644 |
--- a/src/arm/code-stubs-arm.cc |
+++ b/src/arm/code-stubs-arm.cc |
@@ -6007,23 +6007,28 @@ void SubStringStub::Generate(MacroAssembler* masm) { |
STATIC_ASSERT(kSmiTag == 0); |
STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
- // I.e., arithmetic shift right by one un-smi-tags. |
- __ mov(r2, Operand(r2, ASR, 1), SetCC); |
- __ mov(r3, Operand(r3, ASR, 1), SetCC, cc); |
- // If either to or from had the smi tag bit set, then carry is set now. |
- __ b(cs, &runtime); // Either "from" or "to" is not a smi. |
+ // Arithmetic shift right by one un-smi-tags. In this case we rotate right |
+ // instead because we bail out on non-smi values: ROR and ASR are equivalent |
+ // for smis but they set the flags in a way that's easier to optimize. |
+ __ mov(r2, Operand(r2, ROR, 1), SetCC); |
+ __ mov(r3, Operand(r3, ROR, 1), SetCC, cc); |
+ // If either to or from had the smi tag bit set, then C is set now, and N |
+ // has the same value: we rotated by 1, so the bottom bit is now the top bit. |
// We want to bailout to runtime here if From is negative. In that case, the |
// next instruction is not executed and we fall through to bailing out to |
- // runtime. pl is the opposite of mi. |
- // Both r2 and r3 are untagged integers. |
- __ sub(r2, r2, Operand(r3), SetCC, pl); |
- __ b(mi, &runtime); // Fail if from > to. |
+ // runtime. |
+ // Executed if both r2 and r3 are untagged integers. |
+ __ sub(r2, r2, Operand(r3), SetCC, cc); |
+ // One of the above un-smis or the above SUB could have set N==1. |
+ __ b(mi, &runtime); // Either "from" or "to" is not an smi, or from > to. |
// Make sure first argument is a string. |
__ ldr(r0, MemOperand(sp, kStringOffset)); |
STATIC_ASSERT(kSmiTag == 0); |
- __ JumpIfSmi(r0, &runtime); |
- Condition is_string = masm->IsObjectStringType(r0, r1); |
+ // Do a JumpIfSmi, but fold its jump into the subsequent string test. |
+ __ tst(r0, Operand(kSmiTagMask)); |
+ Condition is_string = masm->IsObjectStringType(r0, r1, ne); |
+ ASSERT(is_string == eq); |
__ b(NegateCondition(is_string), &runtime); |
// Short-cut for the case of trivial substring. |