| Index: src/arm/code-stubs-arm.cc
|
| ===================================================================
|
| --- src/arm/code-stubs-arm.cc (revision 5457)
|
| +++ src/arm/code-stubs-arm.cc (working copy)
|
| @@ -930,6 +930,24 @@
|
| Label slow; // Call builtin.
|
| Label not_smis, both_loaded_as_doubles, lhs_not_nan;
|
|
|
| + if (include_smi_compare_) {
|
| + Label not_two_smis, smi_done;
|
| + __ orr(r2, r1, r0);
|
| + __ tst(r2, Operand(kSmiTagMask));
|
| + __ b(ne, ¬_two_smis);
|
| + __ sub(r0, r1, r0);
|
| + __ b(vc, &smi_done);
|
| + // Correct the sign in case of overflow.
|
| + __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
|
| + __ bind(&smi_done);
|
| + __ Ret();
|
| + __ bind(¬_two_smis);
|
| + } else if (FLAG_debug_code) {
|
| + __ orr(r2, r1, r0);
|
| + __ tst(r2, Operand(kSmiTagMask));
|
| + __ Assert(nz, "CompareStub: unexpected smi operands.");
|
| + }
|
| +
|
| // NOTICE! This code is only reached after a smi-fast-case check, so
|
| // it is certain that at least one operand isn't a smi.
|
|
|
| @@ -2288,7 +2306,7 @@
|
| __ push(r0);
|
| __ TailCallRuntime(Runtime::kStackGuard, 1, 1);
|
|
|
| - __ StubReturn(1);
|
| + __ Ret();
|
| }
|
|
|
|
|
| @@ -2299,32 +2317,37 @@
|
| __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
|
|
| if (op_ == Token::SUB) {
|
| - // Check whether the value is a smi.
|
| - Label try_float;
|
| - __ tst(r0, Operand(kSmiTagMask));
|
| - __ b(ne, &try_float);
|
| + if (include_smi_code_) {
|
| + // Check whether the value is a smi.
|
| + Label try_float;
|
| + __ tst(r0, Operand(kSmiTagMask));
|
| + __ b(ne, &try_float);
|
|
|
| - // Go slow case if the value of the expression is zero
|
| - // to make sure that we switch between 0 and -0.
|
| - if (negative_zero_ == kStrictNegativeZero) {
|
| - // If we have to check for zero, then we can check for the max negative
|
| - // smi while we are at it.
|
| - __ bic(ip, r0, Operand(0x80000000), SetCC);
|
| - __ b(eq, &slow);
|
| - __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
|
| - __ StubReturn(1);
|
| - } else {
|
| - // The value of the expression is a smi and 0 is OK for -0. Try
|
| - // optimistic subtraction '0 - value'.
|
| - __ rsb(r0, r0, Operand(0, RelocInfo::NONE), SetCC);
|
| - __ StubReturn(1, vc);
|
| - // We don't have to reverse the optimistic neg since the only case
|
| - // where we fall through is the minimum negative Smi, which is the case
|
| - // where the neg leaves the register unchanged.
|
| - __ jmp(&slow); // Go slow on max negative Smi.
|
| + // Go slow case if the value of the expression is zero
|
| + // to make sure that we switch between 0 and -0.
|
| + if (negative_zero_ == kStrictNegativeZero) {
|
| + // If we have to check for zero, then we can check for the max negative
|
| + // smi while we are at it.
|
| + __ bic(ip, r0, Operand(0x80000000), SetCC);
|
| + __ b(eq, &slow);
|
| + __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
|
| + __ Ret();
|
| + } else {
|
| + // The value of the expression is a smi and 0 is OK for -0. Try
|
| + // optimistic subtraction '0 - value'.
|
| + __ rsb(r0, r0, Operand(0, RelocInfo::NONE), SetCC);
|
| + __ Ret(vc);
|
| + // We don't have to reverse the optimistic neg since the only case
|
| + // where we fall through is the minimum negative Smi, which is the case
|
| + // where the neg leaves the register unchanged.
|
| + __ jmp(&slow); // Go slow on max negative Smi.
|
| + }
|
| + __ bind(&try_float);
|
| + } else if (FLAG_debug_code) {
|
| + __ tst(r0, Operand(kSmiTagMask));
|
| + __ Assert(ne, "Unexpected smi operand.");
|
| }
|
|
|
| - __ bind(&try_float);
|
| __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
|
| __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
| __ cmp(r1, heap_number_map);
|
| @@ -2344,6 +2367,19 @@
|
| __ mov(r0, Operand(r1));
|
| }
|
| } else if (op_ == Token::BIT_NOT) {
|
| + if (include_smi_code_) {
|
| + Label non_smi;
|
| + __ BranchOnNotSmi(r0, &non_smi);
|
| + __ mvn(r0, Operand(r0));
|
| + // Bit-clear inverted smi-tag.
|
| + __ bic(r0, r0, Operand(kSmiTagMask));
|
| + __ Ret();
|
| + __ bind(&non_smi);
|
| + } else if (FLAG_debug_code) {
|
| + __ tst(r0, Operand(kSmiTagMask));
|
| + __ Assert(ne, "Unexpected smi operand.");
|
| + }
|
| +
|
| // Check if the operand is a heap number.
|
| __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
|
| __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
| @@ -2391,7 +2427,7 @@
|
| }
|
|
|
| __ bind(&done);
|
| - __ StubReturn(1);
|
| + __ Ret();
|
|
|
| // Handle the slow case by jumping to the JavaScript builtin.
|
| __ bind(&slow);
|
| @@ -3499,6 +3535,11 @@
|
| include_number_compare_name = "_NO_NUMBER";
|
| }
|
|
|
| + const char* include_smi_compare_name = "";
|
| + if (!include_smi_compare_) {
|
| + include_smi_compare_name = "_NO_SMI";
|
| + }
|
| +
|
| OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
| "CompareStub_%s%s%s%s%s%s",
|
| cc_name,
|
| @@ -3506,7 +3547,8 @@
|
| rhs_name,
|
| strict_name,
|
| never_nan_nan_name,
|
| - include_number_compare_name);
|
| + include_number_compare_name,
|
| + include_smi_compare_name);
|
| return name_;
|
| }
|
|
|
| @@ -3522,7 +3564,8 @@
|
| | RegisterField::encode(lhs_.is(r0))
|
| | StrictField::encode(strict_)
|
| | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
|
| - | IncludeNumberCompareField::encode(include_number_compare_);
|
| + | IncludeNumberCompareField::encode(include_number_compare_)
|
| + | IncludeSmiCompareField::encode(include_smi_compare_);
|
| }
|
|
|
|
|
| @@ -4144,17 +4187,21 @@
|
|
|
|
|
| // Check bounds and smi-ness.
|
| - __ ldr(r7, MemOperand(sp, kToOffset));
|
| - __ ldr(r6, MemOperand(sp, kFromOffset));
|
| + Register to = r6;
|
| + Register from = r7;
|
| + __ Ldrd(to, from, MemOperand(sp, kToOffset));
|
| + STATIC_ASSERT(kFromOffset == kToOffset + 4);
|
| STATIC_ASSERT(kSmiTag == 0);
|
| STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
|
| // I.e., arithmetic shift right by one un-smi-tags.
|
| - __ mov(r2, Operand(r7, ASR, 1), SetCC);
|
| - __ mov(r3, Operand(r6, ASR, 1), SetCC, cc);
|
| - // If either r2 or r6 had the smi tag bit set, then carry is set now.
|
| + __ mov(r2, Operand(to, ASR, 1), SetCC);
|
| + __ mov(r3, Operand(from, 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.
|
| __ b(mi, &runtime); // From is negative.
|
|
|
| + // Both to and from are smis.
|
| +
|
| __ sub(r2, r2, Operand(r3), SetCC);
|
| __ b(mi, &runtime); // Fail if from > to.
|
| // Special handling of sub-strings of length 1 and 2. One character strings
|
| @@ -4165,8 +4212,8 @@
|
|
|
| // r2: length
|
| // r3: from index (untaged smi)
|
| - // r6: from (smi)
|
| - // r7: to (smi)
|
| + // r6 (a.k.a. to): to (smi)
|
| + // r7 (a.k.a. from): from offset (smi)
|
|
|
| // Make sure first argument is a sequential (or flat) string.
|
| __ ldr(r5, MemOperand(sp, kStringOffset));
|
| @@ -4178,10 +4225,10 @@
|
|
|
| // r1: instance type
|
| // r2: length
|
| - // r3: from index (untaged smi)
|
| + // r3: from index (untagged smi)
|
| // r5: string
|
| - // r6: from (smi)
|
| - // r7: to (smi)
|
| + // r6 (a.k.a. to): to (smi)
|
| + // r7 (a.k.a. from): from offset (smi)
|
| Label seq_string;
|
| __ and_(r4, r1, Operand(kStringRepresentationMask));
|
| STATIC_ASSERT(kSeqStringTag < kConsStringTag);
|
| @@ -4207,17 +4254,18 @@
|
| // r2: length
|
| // r3: from index (untaged smi)
|
| // r5: string
|
| - // r6: from (smi)
|
| - // r7: to (smi)
|
| + // r6 (a.k.a. to): to (smi)
|
| + // r7 (a.k.a. from): from offset (smi)
|
| __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset));
|
| - __ cmp(r4, Operand(r7));
|
| + __ cmp(r4, Operand(to));
|
| __ b(lt, &runtime); // Fail if to > length.
|
| + to = no_reg;
|
|
|
| // r1: instance type.
|
| // r2: result string length.
|
| // r3: from index (untaged smi)
|
| // r5: string.
|
| - // r6: from offset (smi)
|
| + // r7 (a.k.a. from): from offset (smi)
|
| // Check for flat ascii string.
|
| Label non_ascii_flat;
|
| __ tst(r1, Operand(kStringEncodingMask));
|
| @@ -4259,12 +4307,12 @@
|
| // r0: result string.
|
| // r2: result string length.
|
| // r5: string.
|
| - // r6: from offset (smi)
|
| + // r7 (a.k.a. from): from offset (smi)
|
| // Locate first character of result.
|
| __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
|
| // Locate 'from' character of string.
|
| __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
|
| - __ add(r5, r5, Operand(r6, ASR, 1));
|
| + __ add(r5, r5, Operand(from, ASR, 1));
|
|
|
| // r0: result string.
|
| // r1: first character of result string.
|
| @@ -4280,7 +4328,7 @@
|
| __ bind(&non_ascii_flat);
|
| // r2: result string length.
|
| // r5: string.
|
| - // r6: from offset (smi)
|
| + // r7 (a.k.a. from): from offset (smi)
|
| // Check for flat two byte string.
|
|
|
| // Allocate the result.
|
| @@ -4292,18 +4340,19 @@
|
| // Locate first character of result.
|
| __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
| // Locate 'from' character of string.
|
| - __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
| + __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
| // As "from" is a smi it is 2 times the value which matches the size of a two
|
| // byte character.
|
| - __ add(r5, r5, Operand(r6));
|
| + __ add(r5, r5, Operand(from));
|
| + from = no_reg;
|
|
|
| // r0: result string.
|
| // r1: first character of result.
|
| // r2: result length.
|
| // r5: first character of string to copy.
|
| STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
|
| - StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
|
| - DEST_ALWAYS_ALIGNED);
|
| + StringHelper::GenerateCopyCharactersLong(
|
| + masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED);
|
| __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
|
| __ add(sp, sp, Operand(3 * kPointerSize));
|
| __ Ret();
|
| @@ -4379,8 +4428,7 @@
|
| // Stack frame on entry.
|
| // sp[0]: right string
|
| // sp[4]: left string
|
| - __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // left
|
| - __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // right
|
| + __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1.
|
|
|
| Label not_same;
|
| __ cmp(r0, r1);
|
| @@ -4395,12 +4443,12 @@
|
| __ bind(¬_same);
|
|
|
| // Check that both objects are sequential ascii strings.
|
| - __ JumpIfNotBothSequentialAsciiStrings(r0, r1, r2, r3, &runtime);
|
| + __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime);
|
|
|
| // Compare flat ascii strings natively. Remove arguments from stack first.
|
| __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
|
| __ add(sp, sp, Operand(2 * kPointerSize));
|
| - GenerateCompareFlatAsciiStrings(masm, r0, r1, r2, r3, r4, r5);
|
| + GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5);
|
|
|
| // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
|
| // tagged as a small integer.
|
|
|