diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc index 8edfe71800..c05fdc275d 100644 --- a/src/mips/builtins-mips.cc +++ b/src/mips/builtins-mips.cc @@ -1102,9 +1102,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // If the type of the result (stored in its map) is less than // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. - __ GetObjectType(v0, a3, a3); + __ GetObjectType(v0, a1, a3); __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); + // Symbols are "objects". + __ lbu(a3, FieldMemOperand(a1, Map::kInstanceTypeOffset)); + __ Branch(&exit, eq, a3, Operand(SYMBOL_TYPE)); + // Throw away the result of the constructor invocation and use the // on-stack receiver as the result. __ bind(&use_receiver); diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index 81ad1efafe..5b3fa394c1 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -7259,6 +7259,60 @@ void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { } +void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { + ASSERT(state_ == CompareIC::UNIQUE_NAME); + ASSERT(GetCondition() == eq); + Label miss; + + // Registers containing left and right operands respectively. + Register left = a1; + Register right = a0; + Register tmp1 = a2; + Register tmp2 = a3; + + // Check that both operands are heap objects. + __ JumpIfEitherSmi(left, right, &miss); + + // Check that both operands are unique names. This leaves the instance + // types loaded in tmp1 and tmp2. + STATIC_ASSERT(kInternalizedTag != 0); + __ lw(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); + __ lw(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); + __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); + __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); + + Label succeed1; + __ And(at, tmp1, Operand(kIsInternalizedMask)); + __ Branch(&succeed1, ne, at, Operand(zero_reg)); + __ Branch(&miss, ne, tmp1, Operand(SYMBOL_TYPE)); + __ bind(&succeed1); + + Label succeed2; + __ And(at, tmp2, Operand(kIsInternalizedMask)); + __ Branch(&succeed2, ne, at, Operand(zero_reg)); + __ Branch(&miss, ne, tmp2, Operand(SYMBOL_TYPE)); + __ bind(&succeed2); + + // Use a0 as result + __ mov(v0, a0); + + // Unique names are compared by identity. + Label done; + __ Branch(&done, ne, left, Operand(right)); + // Make sure a0 is non-zero. At this point input operands are + // guaranteed to be non-zero. + ASSERT(right.is(a0)); + STATIC_ASSERT(EQUAL == 0); + STATIC_ASSERT(kSmiTag == 0); + __ li(v0, Operand(Smi::FromInt(EQUAL))); + __ bind(&done); + __ Ret(); + + __ bind(&miss); + GenerateMiss(masm); +} + + void ICCompareStub::GenerateStrings(MacroAssembler* masm) { ASSERT(state_ == CompareIC::STRING); Label miss; diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index 7f2cf652ef..056e2eef08 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -2780,6 +2780,28 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( } +void FullCodeGenerator::EmitIsSymbol(CallRuntime* expr) { + ZoneList* args = expr->arguments(); + ASSERT(args->length() == 1); + + VisitForAccumulatorValue(args->at(0)); + + Label materialize_true, materialize_false; + Label* if_true = NULL; + Label* if_false = NULL; + Label* fall_through = NULL; + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); + + __ JumpIfSmi(v0, if_false); + __ GetObjectType(v0, a1, a2); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); + Split(eq, a2, Operand(SYMBOL_TYPE), if_true, if_false, fall_through); + + context()->Plug(if_true, if_false); +} + + void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); @@ -4329,6 +4351,10 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, __ LoadRoot(at, Heap::kNullValueRootIndex); __ Branch(if_true, eq, v0, Operand(at)); } + if (FLAG_harmony_symbols) { + __ GetObjectType(v0, v0, a1); + __ Branch(if_true, eq, a1, Operand(SYMBOL_TYPE)); + } // Check for JS objects => true. __ GetObjectType(v0, v0, a1); __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index dfc3d5fdb8..ab08399a3c 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -5803,10 +5803,20 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, __ LoadRoot(at, Heap::kNullValueRootIndex); __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input)); } - // input is an object, it is safe to use GetObjectType in the delay slot. - __ GetObjectType(input, input, scratch); - __ Branch(USE_DELAY_SLOT, false_label, - lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); + if (FLAG_harmony_symbols) { + // input is an object, it is safe to use GetObjectType in the delay slot. + __ GetObjectType(input, input, scratch); + __ Branch(USE_DELAY_SLOT, true_label, eq, scratch, Operand(SYMBOL_TYPE)); + // Still an object, so the InstanceType can be loaded. + __ lbu(scratch, FieldMemOperand(input, Map::kInstanceTypeOffset)); + __ Branch(USE_DELAY_SLOT, false_label, + lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); + } else { + // input is an object, it is safe to use GetObjectType in the delay slot. + __ GetObjectType(input, input, scratch); + __ Branch(USE_DELAY_SLOT, false_label, + lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); + } // Still an object, so the InstanceType can be loaded. __ lbu(scratch, FieldMemOperand(input, Map::kInstanceTypeOffset)); __ Branch(USE_DELAY_SLOT, false_label, diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc index 192c7bfb3f..5dd0e5fa7c 100644 --- a/src/mips/stub-cache-mips.cc +++ b/src/mips/stub-cache-mips.cc @@ -2431,6 +2431,12 @@ void CallStubCompiler::CompileHandlerFrontend(Handle object, a0, holder, a3, a1, t0, name, &miss); break; + case SYMBOL_CHECK: + // Check that the object is a symbol. + __ GetObjectType(a1, a1, a3); + __ Branch(&miss, ne, a3, Operand(SYMBOL_TYPE)); + break; + case NUMBER_CHECK: { Label fast; // Check that the object is a smi or a heap number.