Index: src/arm/code-stubs-arm.cc |
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc |
index 201ecb26ff5ee483e56ed53bafd6094a89ba1abe..186ea7bcfba012d23ce7d06a5c5d334ad5599606 100644 |
--- a/src/arm/code-stubs-arm.cc |
+++ b/src/arm/code-stubs-arm.cc |
@@ -175,6 +175,19 @@ void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
} |
+void ToBooleanStub::InitializeInterfaceDescriptor( |
+ Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor) { |
+ static Register registers[] = { r0 }; |
+ descriptor->register_param_count_ = 1; |
+ descriptor->register_params_ = registers; |
+ descriptor->deoptimization_handler_ = |
+ FUNCTION_ADDR(ToBooleanIC_Miss); |
+ descriptor->SetMissHandler( |
+ ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate)); |
+} |
+ |
+ |
#define __ ACCESS_MASM(masm) |
static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
@@ -1207,116 +1220,6 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
} |
-// The stub expects its argument in the tos_ register and returns its result in |
-// it, too: zero for false, and a non-zero value for true. |
-void ToBooleanStub::Generate(MacroAssembler* masm) { |
- // This stub overrides SometimesSetsUpAFrame() to return false. That means |
- // we cannot call anything that could cause a GC from this stub. |
- Label patch; |
- const Register map = r9.is(tos_) ? r7 : r9; |
- |
- // undefined -> false. |
- CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); |
- |
- // Boolean -> its value. |
- CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false); |
- CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true); |
- |
- // 'null' -> false. |
- CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false); |
- |
- if (types_.Contains(SMI)) { |
- // Smis: 0 -> false, all other -> true |
- __ SmiTst(tos_); |
- // tos_ contains the correct return value already |
- __ Ret(eq); |
- } else if (types_.NeedsMap()) { |
- // If we need a map later and have a Smi -> patch. |
- __ JumpIfSmi(tos_, &patch); |
- } |
- |
- if (types_.NeedsMap()) { |
- __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset)); |
- |
- if (types_.CanBeUndetectable()) { |
- __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
- __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
- // Undetectable -> false. |
- __ mov(tos_, Operand::Zero(), LeaveCC, ne); |
- __ Ret(ne); |
- } |
- } |
- |
- if (types_.Contains(SPEC_OBJECT)) { |
- // Spec object -> true. |
- __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); |
- // tos_ contains the correct non-zero return value already. |
- __ Ret(ge); |
- } |
- |
- if (types_.Contains(STRING)) { |
- // String value -> false iff empty. |
- __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
- __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset), lt); |
- __ Ret(lt); // the string length is OK as the return value |
- } |
- |
- if (types_.Contains(HEAP_NUMBER)) { |
- // Heap number -> false iff +0, -0, or NaN. |
- Label not_heap_number; |
- __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
- __ b(ne, ¬_heap_number); |
- |
- __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); |
- __ VFPCompareAndSetFlags(d1, 0.0); |
- // "tos_" is a register, and contains a non zero value by default. |
- // Hence we only need to overwrite "tos_" with zero to return false for |
- // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. |
- __ mov(tos_, Operand::Zero(), LeaveCC, eq); // for FP_ZERO |
- __ mov(tos_, Operand::Zero(), LeaveCC, vs); // for FP_NAN |
- __ Ret(); |
- __ bind(¬_heap_number); |
- } |
- |
- __ bind(&patch); |
- GenerateTypeTransition(masm); |
-} |
- |
- |
-void ToBooleanStub::CheckOddball(MacroAssembler* masm, |
- Type type, |
- Heap::RootListIndex value, |
- bool result) { |
- if (types_.Contains(type)) { |
- // If we see an expected oddball, return its ToBoolean value tos_. |
- __ LoadRoot(ip, value); |
- __ cmp(tos_, ip); |
- // The value of a root is never NULL, so we can avoid loading a non-null |
- // value into tos_ when we want to return 'true'. |
- if (!result) { |
- __ mov(tos_, Operand::Zero(), LeaveCC, eq); |
- } |
- __ Ret(eq); |
- } |
-} |
- |
- |
-void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) { |
- if (!tos_.is(r3)) { |
- __ mov(r3, Operand(tos_)); |
- } |
- __ mov(r2, Operand(Smi::FromInt(tos_.code()))); |
- __ mov(r1, Operand(Smi::FromInt(types_.ToByte()))); |
- __ Push(r3, r2, r1); |
- // Patch the caller to an appropriate specialized stub and return the |
- // operation result to the caller of the stub. |
- __ TailCallExternalReference( |
- ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()), |
- 3, |
- 1); |
-} |
- |
- |
void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
// We don't allow a GC during a store buffer overflow so there is no need to |
// store the registers in any particular way, but we do have to store and |