From f4abb7afc6c3e1d93361e19ed1af62637d2d5df7 Mon Sep 17 00:00:00 2001 From: "palfia@homejinni.com" Date: Fri, 8 Mar 2013 00:42:59 +0000 Subject: [PATCH] MIPS: ES6 symbols: Implement Symbol intrinsic and basic functionality Port r13786 (b5e7a82a) Original commit message: - Add --harmony-symbols flag. - Add Symbol constructor; allow symbols as (unreplaced) return value from constructors. - Introduce %CreateSymbol and %_IsSymbol natives and respective instructions. - Extend 'typeof' code generation to handle symbols. - Extend CompareIC with a UNIQUE_NAMES state that (uniformly) handles internalized strings and symbols. - Property lookup delegates to SymbolDelegate object for symbols, which only carries the toString method. - Extend Object.prototype.toString to recognise symbols. Per the current draft spec, symbols are actually pseudo objects that are frozen with a null prototype and only one property (toString). For simplicity, we do not treat them as proper objects for now, although typeof will return "object". Only property access works as if they were (frozen) objects (via the internal delegate object). (Baseline CL: https://codereview.chromium.org/12223071/) BUG= Review URL: https://codereview.chromium.org/12447009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13871 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/builtins-mips.cc | 6 +++- src/mips/code-stubs-mips.cc | 54 ++++++++++++++++++++++++++++++++ src/mips/full-codegen-mips.cc | 26 +++++++++++++++ src/mips/lithium-codegen-mips.cc | 18 ++++++++--- src/mips/stub-cache-mips.cc | 6 ++++ 5 files changed, 105 insertions(+), 5 deletions(-) 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.