| Index: src/arm/code-stubs-arm.cc
|
| diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
|
| index c99c5abcd2073cc98a7cd4c0ea19c43c7677d038..b92c25a1fe85dd1efa938706261ffcd04615243b 100644
|
| --- a/src/arm/code-stubs-arm.cc
|
| +++ b/src/arm/code-stubs-arm.cc
|
| @@ -1610,15 +1610,13 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| -// This stub does not handle the inlined cases (Smis, Booleans, undefined).
|
| // The stub returns zero for false, and a non-zero value for true.
|
| void ToBooleanStub::Generate(MacroAssembler* masm) {
|
| // This stub uses VFP3 instructions.
|
| CpuFeatures::Scope scope(VFP3);
|
|
|
| - Label false_result;
|
| - Label not_heap_number;
|
| - Register scratch = r9.is(tos_) ? r7 : r9;
|
| + Label false_result, true_result, not_string;
|
| + const Register map = r9.is(tos_) ? r7 : r9;
|
|
|
| // undefined -> false
|
| __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
| @@ -1648,11 +1646,31 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
|
| __ cmp(tos_, ip);
|
| __ b(eq, &false_result);
|
|
|
| - // HeapNumber => false iff +0, -0, or NaN.
|
| - __ ldr(scratch, FieldMemOperand(tos_, HeapObject::kMapOffset));
|
| - __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
| - __ cmp(scratch, ip);
|
| - __ b(¬_heap_number, ne);
|
| + // Get the map of the heap object.
|
| + __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
|
| +
|
| + // Undetectable -> false.
|
| + __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
|
| + __ tst(ip, Operand(1 << Map::kIsUndetectable));
|
| + __ b(&false_result, ne);
|
| +
|
| + // JavaScript object -> true.
|
| + __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
|
| + // "tos_" is a register and contains a non-zero value. Hence we implicitly
|
| + // return true if the greater than condition is satisfied.
|
| + __ Ret(ge);
|
| +
|
| + // String value -> false iff empty.
|
| + __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
|
| + __ b(¬_string, ge);
|
| + __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset));
|
| + // Return string length as boolean value, i.e. return false iff length is 0.
|
| + __ Ret();
|
| +
|
| + __ bind(¬_string);
|
| + // HeapNumber -> false iff +0, -0, or NaN.
|
| + __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
|
| + __ b(&true_result, ne);
|
| __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset));
|
| __ VFPCompareAndSetFlags(d1, 0.0);
|
| // "tos_" is a register, and contains a non zero value by default.
|
| @@ -1662,41 +1680,10 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
|
| __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs); // for FP_NAN
|
| __ Ret();
|
|
|
| - __ bind(¬_heap_number);
|
| -
|
| - // It can be an undetectable object.
|
| - // Undetectable => false.
|
| - __ ldr(ip, FieldMemOperand(tos_, HeapObject::kMapOffset));
|
| - __ ldrb(scratch, FieldMemOperand(ip, Map::kBitFieldOffset));
|
| - __ and_(scratch, scratch, Operand(1 << Map::kIsUndetectable));
|
| - __ cmp(scratch, Operand(1 << Map::kIsUndetectable));
|
| - __ b(&false_result, eq);
|
| -
|
| - // JavaScript object => true.
|
| - __ ldr(scratch, FieldMemOperand(tos_, HeapObject::kMapOffset));
|
| - __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
|
| - __ cmp(scratch, Operand(FIRST_SPEC_OBJECT_TYPE));
|
| - // "tos_" is a register and contains a non-zero value.
|
| - // Hence we implicitly return true if the greater than
|
| - // condition is satisfied.
|
| - __ Ret(gt);
|
| -
|
| - // Check for string
|
| - __ ldr(scratch, FieldMemOperand(tos_, HeapObject::kMapOffset));
|
| - __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
|
| - __ cmp(scratch, Operand(FIRST_NONSTRING_TYPE));
|
| - // "tos_" is a register and contains a non-zero value.
|
| - // Hence we implicitly return true if the greater than
|
| - // condition is satisfied.
|
| - __ Ret(gt);
|
| -
|
| - // String value => false iff empty, i.e., length is zero
|
| - __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset));
|
| - // If length is zero, "tos_" contains zero ==> false.
|
| - // If length is not zero, "tos_" contains a non-zero value ==> true.
|
| + // Return 1/0 for true/false in tos_.
|
| + __ bind(&true_result);
|
| + __ mov(tos_, Operand(1, RelocInfo::NONE));
|
| __ Ret();
|
| -
|
| - // Return 0 in "tos_" for false .
|
| __ bind(&false_result);
|
| __ mov(tos_, Operand(0, RelocInfo::NONE));
|
| __ Ret();
|
| @@ -3550,12 +3537,24 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
| // Save callee-saved registers (incl. cp and fp), sp, and lr
|
| __ stm(db_w, sp, kCalleeSaved | lr.bit());
|
|
|
| + if (CpuFeatures::IsSupported(VFP3)) {
|
| + CpuFeatures::Scope scope(VFP3);
|
| + // Save callee-saved vfp registers.
|
| + __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
|
| + }
|
| +
|
| // Get address of argv, see stm above.
|
| // r0: code entry
|
| // r1: function
|
| // r2: receiver
|
| // r3: argc
|
| - __ ldr(r4, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize)); // argv
|
| +
|
| + // Setup argv in r4.
|
| + int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
|
| + if (CpuFeatures::IsSupported(VFP3)) {
|
| + offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize;
|
| + }
|
| + __ ldr(r4, MemOperand(sp, offset_to_argv));
|
|
|
| // Push a frame with special values setup to mark it as an entry frame.
|
| // r0: code entry
|
| @@ -3680,6 +3679,13 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
| __ mov(lr, Operand(pc));
|
| }
|
| #endif
|
| +
|
| + if (CpuFeatures::IsSupported(VFP3)) {
|
| + CpuFeatures::Scope scope(VFP3);
|
| + // Restore callee-saved vfp registers.
|
| + __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
|
| + }
|
| +
|
| __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
|
| }
|
|
|
|
|