| Index: src/mips/code-stubs-mips.cc
|
| diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
|
| index 9b4170e0ce5d125d7569087c62d91c12b1548955..1890d7bb746420731d28e16bd195a781011a93fe 100644
|
| --- a/src/mips/code-stubs-mips.cc
|
| +++ b/src/mips/code-stubs-mips.cc
|
| @@ -176,6 +176,19 @@ void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
|
| }
|
|
|
|
|
| +void ToBooleanStub::InitializeInterfaceDescriptor(
|
| + Isolate* isolate,
|
| + CodeStubInterfaceDescriptor* descriptor) {
|
| + static Register registers[] = { a0 };
|
| + 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,
|
| @@ -1500,116 +1513,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) {
|
| - Label patch;
|
| - const Register map = t5.is(tos_) ? t3 : t5;
|
| -
|
| - // 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
|
| - __ And(at, tos_, kSmiTagMask);
|
| - // tos_ contains the correct return value already
|
| - __ Ret(eq, at, Operand(zero_reg));
|
| - } else if (types_.NeedsMap()) {
|
| - // If we need a map later and have a Smi -> patch.
|
| - __ JumpIfSmi(tos_, &patch);
|
| - }
|
| -
|
| - if (types_.NeedsMap()) {
|
| - __ lw(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
|
| -
|
| - if (types_.CanBeUndetectable()) {
|
| - __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
|
| - __ And(at, at, Operand(1 << Map::kIsUndetectable));
|
| - // Undetectable -> false.
|
| - __ Movn(tos_, zero_reg, at);
|
| - __ Ret(ne, at, Operand(zero_reg));
|
| - }
|
| - }
|
| -
|
| - if (types_.Contains(SPEC_OBJECT)) {
|
| - // Spec object -> true.
|
| - __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
|
| - // tos_ contains the correct non-zero return value already.
|
| - __ Ret(ge, at, Operand(FIRST_SPEC_OBJECT_TYPE));
|
| - }
|
| -
|
| - if (types_.Contains(STRING)) {
|
| - // String value -> false iff empty.
|
| - __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
|
| - Label skip;
|
| - __ Branch(&skip, ge, at, Operand(FIRST_NONSTRING_TYPE));
|
| - __ Ret(USE_DELAY_SLOT); // the string length is OK as the return value
|
| - __ lw(tos_, FieldMemOperand(tos_, String::kLengthOffset));
|
| - __ bind(&skip);
|
| - }
|
| -
|
| - if (types_.Contains(HEAP_NUMBER)) {
|
| - // Heap number -> false iff +0, -0, or NaN.
|
| - Label not_heap_number;
|
| - __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
|
| - __ Branch(¬_heap_number, ne, map, Operand(at));
|
| - Label zero_or_nan, number;
|
| - __ ldc1(f2, FieldMemOperand(tos_, HeapNumber::kValueOffset));
|
| - __ BranchF(&number, &zero_or_nan, ne, f2, kDoubleRegZero);
|
| - // "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.
|
| - __ bind(&zero_or_nan);
|
| - __ mov(tos_, zero_reg);
|
| - __ bind(&number);
|
| - __ 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(at, value);
|
| - __ Subu(at, at, tos_); // This is a check for equality for the movz below.
|
| - // 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) {
|
| - __ Movz(tos_, zero_reg, at);
|
| - }
|
| - __ Ret(eq, at, Operand(zero_reg));
|
| - }
|
| -}
|
| -
|
| -
|
| -void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
|
| - __ Move(a3, tos_);
|
| - __ li(a2, Operand(Smi::FromInt(tos_.code())));
|
| - __ li(a1, Operand(Smi::FromInt(types_.ToByte())));
|
| - __ Push(a3, a2, a1);
|
| - // 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
|
|
|