Changeset 203895 in webkit


Ignore:
Timestamp:
Jul 29, 2016 12:15:01 AM (8 years ago)
Author:
Yusuke Suzuki
Message:

JSC::Symbol should be hash-consed
https://bugs.webkit.org/show_bug.cgi?id=158908

Reviewed by Filip Pizlo.

Previously, SymbolImpls held by symbols represent identity of symbols.
When we check the equality between symbols, we need to load SymbolImpls of symbols and compare them.

This patch performs hash-consing onto the symbols. We cache symbols in per-VM's SymbolImpl-keyed WeakGCMap.
When creating a new symbol from SymbolImpl, we first query to this map and reuse the previously created symbol
if it is found. This ensures that one-on-one correspondence between SymbolImpl and symbol. So now, we can use
pointer-comparison to query the equality of symbols.

This change drops SymbolImpl loads when checking the equality. Furthermore, we can use DFG CheckCell to symbol
when we would like to ensure that the given value is the expected symbol. This cleans up GetByVal's symbol-keyd
caching. Then, we changed CheckIdent to CheckStringIdent since it only checks the string case now. The symbol
case is handled by CheckCell.

Additionally, this patch also cleans up Map / Set implementation since we can use the logic for JSCell to symbols.

The performance effects in the related benchmarks are the followings.

baseline patch

bigswitch-indirect-symbol-or-undefined 85.6214+-1.0063 63.0522+-0.8615 definitely 1.3579x faster
bigswitch-indirect-symbol 84.9653+-0.6258 80.4900+-0.8008 definitely 1.0556x faster
fold-put-by-val-with-symbol-to-multi-put-by-offset

9.4396+-0.3726 9.2941+-0.3311 might be 1.0157x faster

inlined-put-by-val-with-symbol-transition

49.5477+-0.2401 ? 49.7533+-0.3369 ?

get-by-val-with-symbol-self-or-proto 11.9740+-0.0798 ? 12.1706+-0.2723 ? might be 1.0164x slower
get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple

4.1364+-0.0841 4.0872+-0.0925 might be 1.0120x faster

put-by-val-with-symbol 11.3709+-0.0223 11.3613+-0.0264
get-by-val-with-symbol-proto-or-self 11.8984+-0.0706 ? 11.9030+-0.0787 ?
polymorphic-put-by-val-with-symbol 31.4176+-0.0558 31.3825+-0.0447
implicit-bigswitch-indirect-symbol 61.3115+-0.6577 58.0098+-0.1212 definitely 1.0569x faster
get-by-val-with-symbol-bimorphic-check-structure-elimination-simple

3.3139+-0.0565 2.9947+-0.0732 definitely 1.1066x faster

get-by-val-with-symbol-chain-from-try-block

2.2316+-0.0179 2.2137+-0.0210

get-by-val-with-symbol-bimorphic-check-structure-elimination

10.6031+-0.2216 10.0939+-0.1977 definitely 1.0504x faster

get-by-val-with-symbol-check-structure-elimination

8.5576+-0.1521 7.7107+-0.1308 definitely 1.1098x faster

put-by-val-with-symbol-slightly-polymorphic

3.1957+-0.0538 2.9181+-0.0708 definitely 1.0951x faster

put-by-val-with-symbol-replace-and-transition

11.8253+-0.0757 11.6590+-0.0351 definitely 1.0143x faster

<geometric> 13.3911+-0.0527 12.7376+-0.0457 definitely 1.0513x faster

  • bytecode/ByValInfo.h:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::stronglyVisitStrongReferences):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasUidOperand):

  • dfg/DFGNodeType.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileSymbolEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleSymbolEquality):
(JSC::DFG::SpeculativeJIT::compileCheckStringIdent):
(JSC::DFG::SpeculativeJIT::extractStringImplFromBinarySymbols): Deleted.
(JSC::DFG::SpeculativeJIT::compileCheckIdent): Deleted.
(JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality): Deleted.

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality):
(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality):
(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLAbstractHeapRepository.h:
  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckStringIdent):
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckIdent): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::lowSymbolUID): Deleted.

  • jit/JIT.h:
  • jit/JITOperations.cpp:

(JSC::tryGetByValOptimize):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitGetByValWithCachedId):
(JSC::JIT::emitPutByValWithCachedId):
(JSC::JIT::emitByValIdentifierCheck):
(JSC::JIT::privateCompileGetByValWithCachedId):
(JSC::JIT::privateCompilePutByValWithCachedId):
(JSC::JIT::emitIdentifierCheck): Deleted.

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emitGetByValWithCachedId):
(JSC::JIT::emitPutByValWithCachedId):

  • runtime/JSCJSValue.cpp:

(JSC::JSValue::dumpInContextAssumingStructure):

  • runtime/JSCJSValueInlines.h:

(JSC::JSValue::equalSlowCaseInline):
(JSC::JSValue::strictEqualSlowCaseInline): Deleted.

  • runtime/JSFunction.cpp:

(JSC::JSFunction::setFunctionName):

  • runtime/MapData.h:
  • runtime/MapDataInlines.h:

(JSC::JSIterator>::clear): Deleted.
(JSC::JSIterator>::find): Deleted.
(JSC::JSIterator>::add): Deleted.
(JSC::JSIterator>::remove): Deleted.
(JSC::JSIterator>::replaceAndPackBackingStore): Deleted.

  • runtime/Symbol.cpp:

(JSC::Symbol::finishCreation):
(JSC::Symbol::create):

  • runtime/Symbol.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:
  • tests/stress/symbol-equality-over-gc.js: Added.

(shouldBe):
(test):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
33 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r203853 r203895  
     12016-07-28  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        JSC::Symbol should be hash-consed
     4        https://bugs.webkit.org/show_bug.cgi?id=158908
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Previously, SymbolImpls held by symbols represent identity of symbols.
     9        When we check the equality between symbols, we need to load SymbolImpls of symbols and compare them.
     10
     11        This patch performs hash-consing onto the symbols. We cache symbols in per-VM's SymbolImpl-keyed WeakGCMap.
     12        When creating a new symbol from SymbolImpl, we first query to this map and reuse the previously created symbol
     13        if it is found. This ensures that one-on-one correspondence between SymbolImpl and symbol. So now, we can use
     14        pointer-comparison to query the equality of symbols.
     15
     16        This change drops SymbolImpl loads when checking the equality. Furthermore, we can use DFG CheckCell to symbol
     17        when we would like to ensure that the given value is the expected symbol. This cleans up GetByVal's symbol-keyd
     18        caching. Then, we changed CheckIdent to CheckStringIdent since it only checks the string case now. The symbol
     19        case is handled by CheckCell.
     20
     21        Additionally, this patch also cleans up Map / Set implementation since we can use the logic for JSCell to symbols.
     22
     23        The performance effects in the related benchmarks are the followings.
     24
     25                                                               baseline                   patch
     26
     27            bigswitch-indirect-symbol-or-undefined         85.6214+-1.0063     ^     63.0522+-0.8615        ^ definitely 1.3579x faster
     28            bigswitch-indirect-symbol                      84.9653+-0.6258     ^     80.4900+-0.8008        ^ definitely 1.0556x faster
     29            fold-put-by-val-with-symbol-to-multi-put-by-offset
     30                                                            9.4396+-0.3726            9.2941+-0.3311          might be 1.0157x faster
     31            inlined-put-by-val-with-symbol-transition
     32                                                           49.5477+-0.2401     ?     49.7533+-0.3369        ?
     33            get-by-val-with-symbol-self-or-proto           11.9740+-0.0798     ?     12.1706+-0.2723        ? might be 1.0164x slower
     34            get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple
     35                                                            4.1364+-0.0841            4.0872+-0.0925          might be 1.0120x faster
     36            put-by-val-with-symbol                         11.3709+-0.0223           11.3613+-0.0264
     37            get-by-val-with-symbol-proto-or-self           11.8984+-0.0706     ?     11.9030+-0.0787        ?
     38            polymorphic-put-by-val-with-symbol             31.4176+-0.0558           31.3825+-0.0447
     39            implicit-bigswitch-indirect-symbol             61.3115+-0.6577     ^     58.0098+-0.1212        ^ definitely 1.0569x faster
     40            get-by-val-with-symbol-bimorphic-check-structure-elimination-simple
     41                                                            3.3139+-0.0565     ^      2.9947+-0.0732        ^ definitely 1.1066x faster
     42            get-by-val-with-symbol-chain-from-try-block
     43                                                            2.2316+-0.0179            2.2137+-0.0210
     44            get-by-val-with-symbol-bimorphic-check-structure-elimination
     45                                                           10.6031+-0.2216     ^     10.0939+-0.1977        ^ definitely 1.0504x faster
     46            get-by-val-with-symbol-check-structure-elimination
     47                                                            8.5576+-0.1521     ^      7.7107+-0.1308        ^ definitely 1.1098x faster
     48            put-by-val-with-symbol-slightly-polymorphic
     49                                                            3.1957+-0.0538     ^      2.9181+-0.0708        ^ definitely 1.0951x faster
     50            put-by-val-with-symbol-replace-and-transition
     51                                                           11.8253+-0.0757     ^     11.6590+-0.0351        ^ definitely 1.0143x faster
     52
     53            <geometric>                                    13.3911+-0.0527     ^     12.7376+-0.0457        ^ definitely 1.0513x faster
     54
     55        * bytecode/ByValInfo.h:
     56        * bytecode/CodeBlock.cpp:
     57        (JSC::CodeBlock::stronglyVisitStrongReferences):
     58        * dfg/DFGAbstractInterpreterInlines.h:
     59        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     60        * dfg/DFGByteCodeParser.cpp:
     61        (JSC::DFG::ByteCodeParser::parseBlock):
     62        * dfg/DFGClobberize.h:
     63        (JSC::DFG::clobberize):
     64        * dfg/DFGConstantFoldingPhase.cpp:
     65        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     66        * dfg/DFGDoesGC.cpp:
     67        (JSC::DFG::doesGC):
     68        * dfg/DFGFixupPhase.cpp:
     69        (JSC::DFG::FixupPhase::fixupNode):
     70        * dfg/DFGNode.h:
     71        (JSC::DFG::Node::hasUidOperand):
     72        * dfg/DFGNodeType.h:
     73        * dfg/DFGPredictionPropagationPhase.cpp:
     74        * dfg/DFGSafeToExecute.h:
     75        (JSC::DFG::safeToExecute):
     76        * dfg/DFGSpeculativeJIT.cpp:
     77        (JSC::DFG::SpeculativeJIT::compileSymbolEquality):
     78        (JSC::DFG::SpeculativeJIT::compilePeepHoleSymbolEquality):
     79        (JSC::DFG::SpeculativeJIT::compileCheckStringIdent):
     80        (JSC::DFG::SpeculativeJIT::extractStringImplFromBinarySymbols): Deleted.
     81        (JSC::DFG::SpeculativeJIT::compileCheckIdent): Deleted.
     82        (JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality): Deleted.
     83        * dfg/DFGSpeculativeJIT.h:
     84        * dfg/DFGSpeculativeJIT32_64.cpp:
     85        (JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality):
     86        (JSC::DFG::SpeculativeJIT::compile):
     87        * dfg/DFGSpeculativeJIT64.cpp:
     88        (JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality):
     89        (JSC::DFG::SpeculativeJIT::compile):
     90        * ftl/FTLAbstractHeapRepository.h:
     91        * ftl/FTLCapabilities.cpp:
     92        (JSC::FTL::canCompile):
     93        * ftl/FTLLowerDFGToB3.cpp:
     94        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     95        (JSC::FTL::DFG::LowerDFGToB3::compileCheckStringIdent):
     96        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
     97        (JSC::FTL::DFG::LowerDFGToB3::compileCheckIdent): Deleted.
     98        (JSC::FTL::DFG::LowerDFGToB3::lowSymbolUID): Deleted.
     99        * jit/JIT.h:
     100        * jit/JITOperations.cpp:
     101        (JSC::tryGetByValOptimize):
     102        * jit/JITPropertyAccess.cpp:
     103        (JSC::JIT::emitGetByValWithCachedId):
     104        (JSC::JIT::emitPutByValWithCachedId):
     105        (JSC::JIT::emitByValIdentifierCheck):
     106        (JSC::JIT::privateCompileGetByValWithCachedId):
     107        (JSC::JIT::privateCompilePutByValWithCachedId):
     108        (JSC::JIT::emitIdentifierCheck): Deleted.
     109        * jit/JITPropertyAccess32_64.cpp:
     110        (JSC::JIT::emitGetByValWithCachedId):
     111        (JSC::JIT::emitPutByValWithCachedId):
     112        * runtime/JSCJSValue.cpp:
     113        (JSC::JSValue::dumpInContextAssumingStructure):
     114        * runtime/JSCJSValueInlines.h:
     115        (JSC::JSValue::equalSlowCaseInline):
     116        (JSC::JSValue::strictEqualSlowCaseInline): Deleted.
     117        * runtime/JSFunction.cpp:
     118        (JSC::JSFunction::setFunctionName):
     119        * runtime/MapData.h:
     120        * runtime/MapDataInlines.h:
     121        (JSC::JSIterator>::clear): Deleted.
     122        (JSC::JSIterator>::find): Deleted.
     123        (JSC::JSIterator>::add): Deleted.
     124        (JSC::JSIterator>::remove): Deleted.
     125        (JSC::JSIterator>::replaceAndPackBackingStore): Deleted.
     126        * runtime/Symbol.cpp:
     127        (JSC::Symbol::finishCreation):
     128        (JSC::Symbol::create):
     129        * runtime/Symbol.h:
     130        * runtime/VM.cpp:
     131        (JSC::VM::VM):
     132        * runtime/VM.h:
     133        * tests/stress/symbol-equality-over-gc.js: Added.
     134        (shouldBe):
     135        (test):
     136
    11372016-07-28  Mark Lam  <mark.lam@apple.com>
    2138
  • trunk/Source/JavaScriptCore/bytecode/ByValInfo.h

    r199303 r203895  
    3636namespace JSC {
    3737
     38class Symbol;
     39
    3840#if ENABLE(JIT)
    3941
     
    233235    RefPtr<JITStubRoutine> stubRoutine;
    234236    Identifier cachedId;
     237    WriteBarrier<Symbol> cachedSymbol;
    235238    StructureStubInfo* stubInfo;
    236239    bool tookSlowPath : 1;
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r203697 r203895  
    31023102    for (unsigned i = 0; i < m_objectAllocationProfiles.size(); ++i)
    31033103        m_objectAllocationProfiles[i].visitAggregate(visitor);
     3104
     3105    for (ByValInfo* byValInfo : m_byValInfos)
     3106        visitor.append(&byValInfo->cachedSymbol);
    31043107
    31053108#if ENABLE(DFG_JIT)
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r203364 r203895  
    13991399
    14001400            if (node->op() == CompareEq && leftConst.isSymbol() && rightConst.isSymbol()) {
    1401                 setConstant(node, jsBoolean(asSymbol(leftConst)->privateName() == asSymbol(rightConst)->privateName()));
     1401                setConstant(node, jsBoolean(asSymbol(leftConst) == asSymbol(rightConst)));
    14021402                break;
    14031403            }
     
    26272627    }
    26282628
    2629     case CheckIdent: {
     2629    case CheckStringIdent: {
    26302630        AbstractValue& value = forNode(node->child1());
    26312631        UniquedStringImpl* uid = node->uidOperand();
    2632         ASSERT(uid->isSymbol() ? !(value.m_type & ~SpecSymbol) : !(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
     2632        ASSERT(!(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
    26332633
    26342634        JSValue childConstant = value.value();
    26352635        if (childConstant) {
    2636             if (uid->isSymbol()) {
    2637                 ASSERT(childConstant.isSymbol());
    2638                 if (asSymbol(childConstant)->privateName().uid() == uid) {
    2639                     m_state.setFoundConstants(true);
    2640                     break;
    2641                 }
    2642             } else {
    2643                 ASSERT(childConstant.isString());
    2644                 if (asString(childConstant)->tryGetValueImpl() == uid) {
    2645                     m_state.setFoundConstants(true);
    2646                     break;
    2647                 }
    2648             }
    2649         }
    2650 
    2651         filter(value, uid->isSymbol() ? SpecSymbol : SpecStringIdent);
     2636            ASSERT(childConstant.isString());
     2637            if (asString(childConstant)->tryGetValueImpl() == uid) {
     2638                m_state.setFoundConstants(true);
     2639                break;
     2640            }
     2641        }
     2642
     2643        filter(value, SpecStringIdent);
    26522644        break;
    26532645    }
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r203808 r203895  
    40644064                // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
    40654065                // At that time, there is no information.
    4066                 if (byValInfo && byValInfo->stubInfo && !byValInfo->tookSlowPath && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)) {
     4066                if (byValInfo && byValInfo->stubInfo && !byValInfo->tookSlowPath && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent) && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
    40674067                    compiledAsGetById = true;
    40684068                    identifierNumber = m_graph.identifiers().ensure(byValInfo->cachedId.impl());
    40694069                    UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
    40704070
    4071                     addToGraph(CheckIdent, OpInfo(uid), property);
     4071                    if (Symbol* symbol = byValInfo->cachedSymbol.get()) {
     4072                        FrozenValue* frozen = m_graph.freezeStrong(symbol);
     4073                        addToGraph(CheckCell, OpInfo(frozen), property);
     4074                    } else {
     4075                        ASSERT(!uid->isSymbol());
     4076                        addToGraph(CheckStringIdent, OpInfo(uid), property);
     4077                    }
    40724078
    40734079                    getByIdStatus = GetByIdStatus::computeForStubInfo(
     
    41114117                // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
    41124118                // At that time, there is no information.
    4113                 if (byValInfo && byValInfo->stubInfo && !byValInfo->tookSlowPath && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)) {
     4119                if (byValInfo && byValInfo->stubInfo && !byValInfo->tookSlowPath && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent) && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
    41144120                    compiledAsPutById = true;
    41154121                    unsigned identifierNumber = m_graph.identifiers().ensure(byValInfo->cachedId.impl());
    41164122                    UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
    41174123
    4118                     addToGraph(CheckIdent, OpInfo(uid), property);
     4124                    if (Symbol* symbol = byValInfo->cachedSymbol.get()) {
     4125                        FrozenValue* frozen = m_graph.freezeStrong(symbol);
     4126                        addToGraph(CheckCell, OpInfo(frozen), property);
     4127                    } else {
     4128                        ASSERT(!uid->isSymbol());
     4129                        addToGraph(CheckStringIdent, OpInfo(uid), property);
     4130                    }
    41194131
    41204132                    PutByIdStatus putByIdStatus = PutByIdStatus::computeForStubInfo(
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r203364 r203895  
    345345        return;
    346346
    347     case CheckIdent:
    348         def(PureValue(CheckIdent, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->uidOperand()));
     347    case CheckStringIdent:
     348        def(PureValue(CheckStringIdent, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->uidOperand()));
    349349        return;
    350350
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r203808 r203895  
    253253            }
    254254
    255             case CheckIdent: {
     255            case CheckStringIdent: {
    256256                UniquedStringImpl* uid = node->uidOperand();
    257257                const UniquedStringImpl* constantUid = nullptr;
     
    259259                JSValue childConstant = m_state.forNode(node->child1()).value();
    260260                if (childConstant) {
    261                     if (uid->isSymbol()) {
    262                         if (childConstant.isSymbol())
    263                             constantUid = asSymbol(childConstant)->privateName().uid();
    264                     } else {
    265                         if (childConstant.isString()) {
    266                             if (const auto* impl = asString(childConstant)->tryGetValueImpl()) {
    267                                 // Edge filtering requires that a value here should be StringIdent.
    268                                 // However, a constant value propagated in DFG is not filtered.
    269                                 // So here, we check the propagated value is actually an atomic string.
    270                                 // And if it's not, we just ignore.
    271                                 if (impl->isAtomic())
    272                                     constantUid = static_cast<const UniquedStringImpl*>(impl);
    273                             }
     261                    if (childConstant.isString()) {
     262                        if (const auto* impl = asString(childConstant)->tryGetValueImpl()) {
     263                            // Edge filtering requires that a value here should be StringIdent.
     264                            // However, a constant value propagated in DFG is not filtered.
     265                            // So here, we check the propagated value is actually an atomic string.
     266                            // And if it's not, we just ignore.
     267                            if (impl->isAtomic())
     268                                constantUid = static_cast<const UniquedStringImpl*>(impl);
    274269                        }
    275270                    }
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r203364 r203895  
    130130    case CheckCell:
    131131    case CheckNotEmpty:
    132     case CheckIdent:
     132    case CheckStringIdent:
    133133    case RegExpExec:
    134134    case RegExpTest:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r203491 r203895  
    12151215        }
    12161216
    1217         case CheckIdent: {
    1218             UniquedStringImpl* uid = node->uidOperand();
    1219             if (uid->isSymbol())
    1220                 fixEdge<SymbolUse>(node->child1());
    1221             else
    1222                 fixEdge<StringIdentUse>(node->child1());
     1217        case CheckStringIdent: {
     1218            fixEdge<StringIdentUse>(node->child1());
    12231219            break;
    12241220        }
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r203808 r203895  
    15201520    bool hasUidOperand()
    15211521    {
    1522         return op() == CheckIdent;
     1522        return op() == CheckStringIdent;
    15231523    }
    15241524
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r203364 r203895  
    240240    macro(CheckBadCell, NodeMustGenerate) \
    241241    macro(CheckInBounds, NodeMustGenerate) \
    242     macro(CheckIdent, NodeMustGenerate) \
     242    macro(CheckStringIdent, NodeMustGenerate) \
    243243    macro(CheckTypeInfoFlags, NodeMustGenerate) /* Takes an OpInfo with the flags you want to test are set */\
    244244    \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r203364 r203895  
    10461046        case CheckCell:
    10471047        case CheckNotEmpty:
    1048         case CheckIdent:
     1048        case CheckStringIdent:
    10491049        case CheckBadCell:
    10501050        case PutStructure:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r203364 r203895  
    226226    case CheckBadCell:
    227227    case CheckNotEmpty:
    228     case CheckIdent:
     228    case CheckStringIdent:
    229229    case RegExpExec:
    230230    case RegExpTest:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r203697 r203895  
    53115311}
    53125312
    5313 template<typename Functor>
    5314 void SpeculativeJIT::extractStringImplFromBinarySymbols(Edge leftSymbolEdge, Edge rightSymbolEdge, const Functor& functor)
    5315 {
    5316     SpeculateCellOperand left(this, leftSymbolEdge);
    5317     SpeculateCellOperand right(this, rightSymbolEdge);
    5318     GPRTemporary leftTemp(this);
    5319     GPRTemporary rightTemp(this);
     5313void SpeculativeJIT::compileSymbolEquality(Node* node)
     5314{
     5315    SpeculateCellOperand left(this, node->child1());
     5316    SpeculateCellOperand right(this, node->child2());
     5317    GPRTemporary result(this, Reuse, left, right);
    53205318
    53215319    GPRReg leftGPR = left.gpr();
    53225320    GPRReg rightGPR = right.gpr();
    5323     GPRReg leftTempGPR = leftTemp.gpr();
    5324     GPRReg rightTempGPR = rightTemp.gpr();
    5325 
    5326     speculateSymbol(leftSymbolEdge, leftGPR);
    5327     speculateSymbol(rightSymbolEdge, rightGPR);
    5328 
    5329     m_jit.loadPtr(JITCompiler::Address(leftGPR, Symbol::offsetOfPrivateName()), leftTempGPR);
    5330     m_jit.loadPtr(JITCompiler::Address(rightGPR, Symbol::offsetOfPrivateName()), rightTempGPR);
    5331 
    5332     functor(leftTempGPR, rightTempGPR);
    5333 }
    5334 
    5335 void SpeculativeJIT::compileSymbolEquality(Node* node)
    5336 {
    5337     extractStringImplFromBinarySymbols(node->child1(), node->child2(), [&] (GPRReg leftStringImpl, GPRReg rightStringImpl) {
    5338         m_jit.comparePtr(JITCompiler::Equal, leftStringImpl, rightStringImpl, leftStringImpl);
    5339         unblessedBooleanResult(leftStringImpl, node);
    5340     });
     5321    GPRReg resultGPR = result.gpr();
     5322
     5323    speculateSymbol(node->child1(), leftGPR);
     5324    speculateSymbol(node->child2(), rightGPR);
     5325
     5326    m_jit.comparePtr(JITCompiler::Equal, leftGPR, rightGPR, resultGPR);
     5327    unblessedBooleanResult(resultGPR, node);
    53415328}
    53425329
    53435330void SpeculativeJIT::compilePeepHoleSymbolEquality(Node* node, Node* branchNode)
    53445331{
     5332    SpeculateCellOperand left(this, node->child1());
     5333    SpeculateCellOperand right(this, node->child2());
     5334
     5335    GPRReg leftGPR = left.gpr();
     5336    GPRReg rightGPR = right.gpr();
     5337
     5338    speculateSymbol(node->child1(), leftGPR);
     5339    speculateSymbol(node->child2(), rightGPR);
     5340
    53455341    BasicBlock* taken = branchNode->branchData()->taken.block;
    53465342    BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
    53475343
    5348     extractStringImplFromBinarySymbols(node->child1(), node->child2(), [&] (GPRReg leftStringImpl, GPRReg rightStringImpl) {
    5349         if (taken == nextBlock()) {
    5350             branchPtr(JITCompiler::NotEqual, leftStringImpl, rightStringImpl, notTaken);
    5351             jump(taken);
    5352         } else {
    5353             branchPtr(JITCompiler::Equal, leftStringImpl, rightStringImpl, taken);
    5354             jump(notTaken);
    5355         }
    5356     });
     5344    if (taken == nextBlock()) {
     5345        branchPtr(JITCompiler::NotEqual, leftGPR, rightGPR, notTaken);
     5346        jump(taken);
     5347    } else {
     5348        branchPtr(JITCompiler::Equal, leftGPR, rightGPR, taken);
     5349        jump(notTaken);
     5350    }
    53575351}
    53585352
     
    59985992}
    59995993
    6000 void SpeculativeJIT::compileCheckIdent(Node* node)
    6001 {
    6002     SpeculateCellOperand operand(this, node->child1());
     5994void SpeculativeJIT::compileCheckStringIdent(Node* node)
     5995{
     5996    SpeculateCellOperand string(this, node->child1());
     5997    GPRTemporary storage(this);
     5998
     5999    GPRReg stringGPR = string.gpr();
     6000    GPRReg storageGPR = storage.gpr();
     6001
     6002    speculateString(node->child1(), stringGPR);
     6003    speculateStringIdentAndLoadStorage(node->child1(), stringGPR, storageGPR);
     6004
    60036005    UniquedStringImpl* uid = node->uidOperand();
    6004     if (uid->isSymbol()) {
    6005         speculateSymbol(node->child1(), operand.gpr());
    6006         speculationCheck(
    6007             BadIdent, JSValueSource(), nullptr,
    6008             m_jit.branchPtr(
    6009                 JITCompiler::NotEqual,
    6010                 JITCompiler::Address(operand.gpr(), Symbol::offsetOfPrivateName()),
    6011                 TrustedImmPtr(uid)));
    6012     } else {
    6013         speculateString(node->child1(), operand.gpr());
    6014         speculateStringIdent(node->child1(), operand.gpr());
    6015         speculationCheck(
    6016             BadIdent, JSValueSource(), nullptr,
    6017             m_jit.branchPtr(
    6018                 JITCompiler::NotEqual,
    6019                 JITCompiler::Address(operand.gpr(), JSString::offsetOfValue()),
    6020                 TrustedImmPtr(uid)));
    6021     }
     6006    speculationCheck(
     6007        BadIdent, JSValueSource(), nullptr,
     6008        m_jit.branchPtr(JITCompiler::NotEqual, storageGPR, TrustedImmPtr(uid)));
    60226009    noResult(node);
    60236010}
     
    83218308}
    83228309
    8323 void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
    8324 {
    8325     SpeculateCellOperand symbol(this, symbolEdge);
    8326     JSValueOperand untyped(this, untypedEdge);
    8327     GPRTemporary leftTemp(this);
    8328     GPRTemporary rightTemp(this);
    8329    
    8330     GPRReg symbolGPR = symbol.gpr();
    8331     JSValueRegs untypedRegs = untyped.jsValueRegs();
    8332     GPRReg leftTempGPR = leftTemp.gpr();
    8333     GPRReg rightTempGPR = rightTemp.gpr();
    8334    
    8335     speculateSymbol(symbolEdge, symbolGPR);
    8336    
    8337     JITCompiler::Jump notCell = m_jit.branchIfNotCell(untypedRegs);
    8338     JITCompiler::Jump isSymbol = m_jit.branchIfSymbol(untypedRegs.payloadGPR());
    8339    
    8340     notCell.link(&m_jit);
    8341     m_jit.move(TrustedImm32(0), leftTempGPR);
    8342     JITCompiler::Jump done = m_jit.jump();
    8343    
    8344     isSymbol.link(&m_jit);
    8345     m_jit.loadPtr(JITCompiler::Address(symbolGPR, Symbol::offsetOfPrivateName()), leftTempGPR);
    8346     m_jit.loadPtr(JITCompiler::Address(untypedRegs.payloadGPR(), Symbol::offsetOfPrivateName()), rightTempGPR);
    8347     m_jit.comparePtr(JITCompiler::Equal, leftTempGPR, rightTempGPR, leftTempGPR);
    8348    
    8349     done.link(&m_jit);
    8350     unblessedBooleanResult(leftTempGPR, node);
    8351 }
    8352 
    83538310} } // namespace JSC::DFG
    83548311
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r203699 r203895  
    23492349    void compileMiscStrictEq(Node*);
    23502350
    2351     template<typename Functor>
    2352     void extractStringImplFromBinarySymbols(Edge leftSymbolEdge, Edge rightSymbolEdge, const Functor&);
    23532351    void compileSymbolEquality(Node*);
    23542352    void compilePeepHoleSymbolEquality(Node*, Node* branchNode);
     
    24372435
    24382436    void compileCheckTypeInfoFlags(Node*);
    2439     void compileCheckIdent(Node*);
     2437    void compileCheckStringIdent(Node*);
    24402438   
    24412439    void compileValueRep(Node*);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r203544 r203895  
    15241524   
    15251525    jump(notTaken);
     1526}
     1527
     1528void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
     1529{
     1530    SpeculateCellOperand symbol(this, symbolEdge);
     1531    JSValueOperand untyped(this, untypedEdge);
     1532
     1533    GPRReg symbolGPR = symbol.gpr();
     1534    GPRReg untypedGPR = untyped.payloadGPR();
     1535
     1536    speculateSymbol(symbolEdge, symbolGPR);
     1537
     1538    GPRTemporary resultPayload(this, Reuse, symbol);
     1539    GPRReg resultPayloadGPR = resultPayload.gpr();
     1540
     1541    MacroAssembler::Jump untypedCellJump = m_jit.branchIfCell(untyped.jsValueRegs());
     1542
     1543    m_jit.move(TrustedImm32(0), resultPayloadGPR);
     1544    MacroAssembler::Jump untypedNotCellJump = m_jit.jump();
     1545
     1546    // At this point we know that we can perform a straight-forward equality comparison on pointer
     1547    // values because we are doing strict equality.
     1548    untypedCellJump.link(&m_jit);
     1549    m_jit.compare32(MacroAssembler::Equal, symbolGPR, untypedGPR, resultPayloadGPR);
     1550
     1551    untypedNotCellJump.link(&m_jit);
     1552    booleanResult(resultPayloadGPR, node);
    15261553}
    15271554
     
    43334360    }
    43344361
    4335     case CheckIdent:
    4336         compileCheckIdent(node);
     4362    case CheckStringIdent:
     4363        compileCheckStringIdent(node);
    43374364        break;
    43384365
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r203364 r203895  
    16061606   
    16071607    jump(notTaken);
     1608}
     1609
     1610void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
     1611{
     1612    SpeculateCellOperand symbol(this, symbolEdge);
     1613    JSValueOperand untyped(this, untypedEdge);
     1614    GPRTemporary result(this, Reuse, symbol, untyped);
     1615
     1616    GPRReg symbolGPR = symbol.gpr();
     1617    GPRReg untypedGPR = untyped.gpr();
     1618    GPRReg resultGPR = result.gpr();
     1619
     1620    speculateSymbol(symbolEdge, symbolGPR);
     1621
     1622    // At this point we know that we can perform a straight-forward equality comparison on pointer
     1623    // values because we are doing strict equality.
     1624    m_jit.compare64(MacroAssembler::Equal, symbolGPR, untypedGPR, resultGPR);
     1625    unblessedBooleanResult(resultGPR, node);
    16081626}
    16091627
     
    42824300    }
    42834301
    4284     case CheckIdent:
    4285         compileCheckIdent(node);
     4302    case CheckStringIdent:
     4303        compileCheckStringIdent(node);
    42864304        break;
    42874305
  • trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h

    r200981 r203895  
    103103    macro(Structure_globalObject, Structure::globalObjectOffset()) \
    104104    macro(Structure_prototype, Structure::prototypeOffset()) \
    105     macro(Structure_structureID, Structure::structureIDOffset()) \
    106     macro(Symbol_privateName, Symbol::offsetOfPrivateName())
     105    macro(Structure_structureID, Structure::structureIDOffset())
    107106
    108107#define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r203491 r203895  
    129129    case CheckBadCell:
    130130    case CheckNotEmpty:
    131     case CheckIdent:
     131    case CheckStringIdent:
    132132    case CheckWatchdogTimer:
    133133    case StringCharCodeAt:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r203812 r203895  
    603603            compileCheckBadCell();
    604604            break;
    605         case CheckIdent:
    606             compileCheckIdent();
     605        case CheckStringIdent:
     606            compileCheckStringIdent();
    607607            break;
    608608        case GetExecutable:
     
    24782478    }
    24792479
    2480     void compileCheckIdent()
     2480    void compileCheckStringIdent()
    24812481    {
    24822482        UniquedStringImpl* uid = m_node->uidOperand();
    2483         if (uid->isSymbol()) {
    2484             LValue stringImpl = lowSymbolUID(m_node->child1());
    2485             speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
    2486         } else {
    2487             LValue string = lowStringIdent(m_node->child1());
    2488             LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
    2489             speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
    2490         }
     2483        LValue string = lowStringIdent(m_node->child1());
     2484        LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
     2485        speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
    24912486    }
    24922487
     
    50405035
    50415036        if (m_node->isBinaryUseKind(SymbolUse)) {
    5042             LValue leftStringImpl = lowSymbolUID(m_node->child1());
    5043             LValue rightStringImpl = lowSymbolUID(m_node->child2());
    5044             setBoolean(m_out.equal(leftStringImpl, rightStringImpl));
     5037            LValue leftSymbol = lowSymbol(m_node->child1());
     5038            LValue rightSymbol = lowSymbol(m_node->child2());
     5039            setBoolean(m_out.equal(leftSymbol, rightSymbol));
    50455040            return;
    50465041        }
     
    50535048                std::swap(symbolEdge, untypedEdge);
    50545049           
    5055             LValue leftStringImpl = lowSymbolUID(symbolEdge);
     5050            LValue leftSymbol = lowSymbol(symbolEdge);
    50565051            LValue untypedValue = lowJSValue(untypedEdge);
    5057            
    5058             LBasicBlock isCellCase = m_out.newBlock();
    5059             LBasicBlock isSymbolCase = m_out.newBlock();
    5060             LBasicBlock continuation = m_out.newBlock();
    5061            
    5062             ValueFromBlock notSymbolResult = m_out.anchor(m_out.booleanFalse);
    5063             m_out.branch(
    5064                 isCell(untypedValue, provenType(untypedEdge)),
    5065                 unsure(isCellCase), unsure(continuation));
    5066            
    5067             LBasicBlock lastNext = m_out.appendTo(isCellCase, isSymbolCase);
    5068             m_out.branch(
    5069                 isSymbol(untypedValue, provenType(untypedEdge)),
    5070                 unsure(isSymbolCase), unsure(continuation));
    5071            
    5072             m_out.appendTo(isSymbolCase, continuation);
    5073             ValueFromBlock symbolResult =
    5074                 m_out.anchor(
    5075                     m_out.equal(
    5076                         m_out.loadPtr(untypedValue, m_heaps.Symbol_privateName),
    5077                         leftStringImpl));
    5078             m_out.jump(continuation);
    5079            
    5080             m_out.appendTo(continuation, lastNext);
    5081             setBoolean(m_out.phi(Int32, notSymbolResult, symbolResult));
     5052
     5053            setBoolean(m_out.equal(leftSymbol, untypedValue));
    50825054            return;
    50835055        }
     
    98739845    }
    98749846   
    9875     LValue lowSymbolUID(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
    9876     {
    9877         if (Symbol* symbol = edge->dynamicCastConstant<Symbol*>())
    9878             return m_out.constIntPtr(symbol->privateName().uid());
    9879         LValue symbol = lowSymbol(edge, mode);
    9880         // FIXME: We could avoid this load if we had hash-consed Symbols.
    9881         // https://bugs.webkit.org/show_bug.cgi?id=158908
    9882         return m_out.loadPtr(symbol, m_heaps.Symbol_privateName);
    9883     }
    9884 
    98859847    LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
    98869848    {
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r203699 r203895  
    396396
    397397        // Identifier check helper for GetByVal and PutByVal.
    398         void emitIdentifierCheck(RegisterID cell, RegisterID scratch, const Identifier&, JumpList& slowCases);
    399 
    400         JITGetByIdGenerator emitGetByValWithCachedId(Instruction*, const Identifier&, Jump& fastDoneCase, Jump& slowDoneCase, JumpList& slowCases);
    401         JITPutByIdGenerator emitPutByValWithCachedId(Instruction*, PutKind, const Identifier&, JumpList& doneCases, JumpList& slowCases);
     398        void emitByValIdentifierCheck(ByValInfo*, RegisterID cell, RegisterID scratch, const Identifier&, JumpList& slowCases);
     399
     400        JITGetByIdGenerator emitGetByValWithCachedId(ByValInfo*, Instruction*, const Identifier&, Jump& fastDoneCase, Jump& slowDoneCase, JumpList& slowCases);
     401        JITPutByIdGenerator emitPutByValWithCachedId(ByValInfo*, Instruction*, PutKind, const Identifier&, JumpList& doneCases, JumpList& slowCases);
    402402
    403403        enum FinalObjectMode { MayBeFinal, KnownNotFinal };
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r203786 r203895  
    613613    if (baseValue.isObject() && isStringOrSymbol(subscript)) {
    614614        const Identifier propertyName = subscript.toPropertyKey(exec);
    615         if (!subscript.isString() || !parseIndex(propertyName)) {
     615        if (subscript.isSymbol() || !parseIndex(propertyName)) {
    616616            ASSERT(exec->bytecodeOffset());
    617617            ASSERT(!byValInfo->stubRoutine);
     
    625625                }
    626626            } else {
     627                CodeBlock* codeBlock = exec->codeBlock();
     628                ConcurrentJITLocker locker(codeBlock->m_lock);
    627629                byValInfo->seen = true;
    628630                byValInfo->cachedId = propertyName;
     631                if (subscript.isSymbol())
     632                    byValInfo->cachedSymbol.set(vm, codeBlock, asSymbol(subscript));
    629633                optimizationResult = OptimizationResult::SeenOnce;
    630634            }
     
    691695    } else if (isStringOrSymbol(subscript)) {
    692696        const Identifier propertyName = subscript.toPropertyKey(exec);
    693         Optional<uint32_t> index = parseIndex(propertyName);
    694 
    695         if (!subscript.isString() || !index) {
     697        if (subscript.isSymbol() || !parseIndex(propertyName)) {
    696698            ASSERT(exec->bytecodeOffset());
    697699            ASSERT(!byValInfo->stubRoutine);
     
    705707                }
    706708            } else {
     709                CodeBlock* codeBlock = exec->codeBlock();
     710                ConcurrentJITLocker locker(codeBlock->m_lock);
    707711                byValInfo->seen = true;
    708712                byValInfo->cachedId = propertyName;
     713                if (subscript.isSymbol())
     714                    byValInfo->cachedSymbol.set(vm, codeBlock, asSymbol(subscript));
    709715                optimizationResult = OptimizationResult::SeenOnce;
    710716            }
     
    16871693    if (baseValue.isObject() && isStringOrSymbol(subscript)) {
    16881694        const Identifier propertyName = subscript.toPropertyKey(exec);
    1689         if (!subscript.isString() || !parseIndex(propertyName)) {
     1695        if (subscript.isSymbol() || !parseIndex(propertyName)) {
    16901696            ASSERT(exec->bytecodeOffset());
    16911697            ASSERT(!byValInfo->stubRoutine);
     
    16991705                }
    17001706            } else {
     1707                CodeBlock* codeBlock = exec->codeBlock();
     1708                ConcurrentJITLocker locker(codeBlock->m_lock);
    17011709                byValInfo->seen = true;
    17021710                byValInfo->cachedId = propertyName;
     1711                if (subscript.isSymbol())
     1712                    byValInfo->cachedSymbol.set(vm, codeBlock, asSymbol(subscript));
    17031713                optimizationResult = OptimizationResult::SeenOnce;
    17041714            }
    1705 
    17061715        }
    17071716    }
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r202982 r203895  
    210210}
    211211
    212 JITGetByIdGenerator JIT::emitGetByValWithCachedId(Instruction* currentInstruction, const Identifier& propertyName, Jump& fastDoneCase, Jump& slowDoneCase, JumpList& slowCases)
     212JITGetByIdGenerator JIT::emitGetByValWithCachedId(ByValInfo* byValInfo, Instruction* currentInstruction, const Identifier& propertyName, Jump& fastDoneCase, Jump& slowDoneCase, JumpList& slowCases)
    213213{
    214214    // base: regT0
     
    219219
    220220    slowCases.append(emitJumpIfNotJSCell(regT1));
    221     emitIdentifierCheck(regT1, regT3, propertyName, slowCases);
     221    emitByValIdentifierCheck(byValInfo, regT1, regT3, propertyName, slowCases);
    222222
    223223    JITGetByIdGenerator gen(
     
    429429}
    430430
    431 JITPutByIdGenerator JIT::emitPutByValWithCachedId(Instruction* currentInstruction, PutKind putKind, const Identifier& propertyName, JumpList& doneCases, JumpList& slowCases)
     431JITPutByIdGenerator JIT::emitPutByValWithCachedId(ByValInfo* byValInfo, Instruction* currentInstruction, PutKind putKind, const Identifier& propertyName, JumpList& doneCases, JumpList& slowCases)
    432432{
    433433    // base: regT0
     
    439439
    440440    slowCases.append(emitJumpIfNotJSCell(regT1));
    441     emitIdentifierCheck(regT1, regT1, propertyName, slowCases);
     441    emitByValIdentifierCheck(byValInfo, regT1, regT1, propertyName, slowCases);
    442442
    443443    // Write barrier breaks the registers. So after issuing the write barrier,
     
    12541254}
    12551255
    1256 void JIT::emitIdentifierCheck(RegisterID cell, RegisterID scratch, const Identifier& propertyName, JumpList& slowCases)
    1257 {
    1258     if (propertyName.isSymbol()) {
    1259         slowCases.append(branchStructure(NotEqual, Address(cell, JSCell::structureIDOffset()), m_vm->symbolStructure.get()));
    1260         loadPtr(Address(cell, Symbol::offsetOfPrivateName()), scratch);
    1261     } else {
     1256void JIT::emitByValIdentifierCheck(ByValInfo* byValInfo, RegisterID cell, RegisterID scratch, const Identifier& propertyName, JumpList& slowCases)
     1257{
     1258    if (propertyName.isSymbol())
     1259        slowCases.append(branchPtr(NotEqual, cell, TrustedImmPtr(byValInfo->cachedSymbol.get())));
     1260    else {
    12621261        slowCases.append(branchStructure(NotEqual, Address(cell, JSCell::structureIDOffset()), m_vm->stringStructure.get()));
    12631262        loadPtr(Address(cell, JSString::offsetOfValue()), scratch);
    1264     }
    1265     slowCases.append(branchPtr(NotEqual, scratch, TrustedImmPtr(propertyName.impl())));
     1263        slowCases.append(branchPtr(NotEqual, scratch, TrustedImmPtr(propertyName.impl())));
     1264    }
    12661265}
    12671266
     
    13261325    JumpList slowCases;
    13271326
    1328     JITGetByIdGenerator gen = emitGetByValWithCachedId(currentInstruction, propertyName, fastDoneCase, slowDoneCase, slowCases);
     1327    JITGetByIdGenerator gen = emitGetByValWithCachedId(byValInfo, currentInstruction, propertyName, fastDoneCase, slowDoneCase, slowCases);
    13291328
    13301329    ConcurrentJITLocker locker(m_codeBlock->m_lock);
     
    14151414    JumpList slowCases;
    14161415
    1417     JITPutByIdGenerator gen = emitPutByValWithCachedId(currentInstruction, putKind, propertyName, doneCases, slowCases);
     1416    JITPutByIdGenerator gen = emitPutByValWithCachedId(byValInfo, currentInstruction, putKind, propertyName, doneCases, slowCases);
    14181417
    14191418    ConcurrentJITLocker locker(m_codeBlock->m_lock);
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r202214 r203895  
    280280}
    281281
    282 JITGetByIdGenerator JIT::emitGetByValWithCachedId(Instruction* currentInstruction, const Identifier& propertyName, Jump& fastDoneCase, Jump& slowDoneCase, JumpList& slowCases)
     282JITGetByIdGenerator JIT::emitGetByValWithCachedId(ByValInfo* byValInfo, Instruction* currentInstruction, const Identifier& propertyName, Jump& fastDoneCase, Jump& slowDoneCase, JumpList& slowCases)
    283283{
    284284    int dst = currentInstruction[1].u.operand;
     
    289289
    290290    slowCases.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag)));
    291     emitIdentifierCheck(regT2, regT4, propertyName, slowCases);
     291    emitByValIdentifierCheck(byValInfo, regT2, regT4, propertyName, slowCases);
    292292
    293293    JITGetByIdGenerator gen(
     
    486486}
    487487
    488 JITPutByIdGenerator JIT::emitPutByValWithCachedId(Instruction* currentInstruction, PutKind putKind, const Identifier& propertyName, JumpList& doneCases, JumpList& slowCases)
     488JITPutByIdGenerator JIT::emitPutByValWithCachedId(ByValInfo* byValInfo, Instruction* currentInstruction, PutKind putKind, const Identifier& propertyName, JumpList& doneCases, JumpList& slowCases)
    489489{
    490490    // base: tag(regT1), payload(regT0)
     
    495495
    496496    slowCases.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag)));
    497     emitIdentifierCheck(regT2, regT2, propertyName, slowCases);
     497    emitByValIdentifierCheck(byValInfo, regT2, regT2, propertyName, slowCases);
    498498
    499499    // Write barrier breaks the registers. So after issuing the write barrier,
  • trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp

    r202890 r203895  
    253253                out.print(" (unresolved)");
    254254            out.print(": ", impl);
    255         } else if (structure->classInfo()->isSubClassOf(Structure::info()))
     255        } else if (structure->classInfo()->isSubClassOf(Symbol::info()))
     256            out.print("Symbol: ", RawPointer(asCell()));
     257        else if (structure->classInfo()->isSubClassOf(Structure::info()))
    256258            out.print("Structure: ", inContext(*jsCast<Structure*>(asCell()), context));
    257259        else {
  • trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h

    r202890 r203895  
    942942        if (sym1 || sym2) {
    943943            if (sym1 && sym2)
    944                 return asSymbol(v1)->privateName() == asSymbol(v2)->privateName();
     944                return asSymbol(v1) == asSymbol(v2);
    945945            return false;
    946946        }
     
    971971    if (v1.asCell()->isString() && v2.asCell()->isString())
    972972        return WTF::equal(*asString(v1)->value(exec).impl(), *asString(v2)->value(exec).impl());
    973     if (v1.asCell()->isSymbol() && v2.asCell()->isSymbol())
    974         return asSymbol(v1)->privateName() == asSymbol(v2)->privateName();
    975 
    976973    return v1 == v2;
    977974}
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r202890 r203895  
    576576            name = emptyString();
    577577        else
    578             name = makeString("[", String(asSymbol(value)->privateName().uid()), ']');
     578            name = makeString('[', String(uid), ']');
    579579    } else {
    580580        VM& vm = exec->vm();
  • trunk/Source/JavaScriptCore/runtime/MapData.h

    r198212 r203895  
    120120    typedef HashMap<EncodedJSValue, int32_t, EncodedJSValueHash, EncodedJSValueHashTraits, IndexTraits> ValueKeyedMap;
    121121    typedef HashMap<StringImpl*, int32_t, typename WTF::DefaultHash<StringImpl*>::Hash, WTF::HashTraits<StringImpl*>, IndexTraits> StringKeyedMap;
    122     typedef HashMap<SymbolImpl*, int32_t, typename WTF::PtrHash<SymbolImpl*>, WTF::HashTraits<SymbolImpl*>, IndexTraits> SymbolKeyedMap;
    123122
    124123    ALWAYS_INLINE Entry* find(ExecState*, KeyType);
     
    135134    ValueKeyedMap m_valueKeyedTable;
    136135    StringKeyedMap m_stringKeyedTable;
    137     SymbolKeyedMap m_symbolKeyedTable;
    138136    int32_t m_capacity;
    139137    int32_t m_size;
  • trunk/Source/JavaScriptCore/runtime/MapDataInlines.h

    r198212 r203895  
    4444    m_valueKeyedTable.clear();
    4545    m_stringKeyedTable.clear();
    46     m_symbolKeyedTable.clear();
    4746    m_capacity = 0;
    4847    m_size = 0;
     
    6362        return &m_entries.get()[iter->value];
    6463    }
    65     if (key.value.isSymbol()) {
    66         auto iter = m_symbolKeyedTable.find(asSymbol(key.value)->privateName().uid());
    67         if (iter == m_symbolKeyedTable.end())
    68             return 0;
    69         return &m_entries.get()[iter->value];
    70     }
    7164    if (key.value.isCell()) {
    7265        auto iter = m_cellKeyedTable.find(key.value.asCell());
     
    121114    if (key.value.isString())
    122115        return add(exec, owner, m_stringKeyedTable, asString(key.value)->value(exec).impl(), key);
    123     if (key.value.isSymbol())
    124         return add(exec, owner, m_symbolKeyedTable, asSymbol(key.value)->privateName().uid(), key);
    125116    if (key.value.isCell())
    126117        return add(exec, owner, m_cellKeyedTable, key.value.asCell(), key);
     
    146137        location = iter->value;
    147138        m_stringKeyedTable.remove(iter);
    148     }  else if (key.value.isSymbol()) {
    149         auto iter = m_symbolKeyedTable.find(asSymbol(key.value)->privateName().uid());
    150         if (iter == m_symbolKeyedTable.end())
    151             return false;
    152         location = iter->value;
    153         m_symbolKeyedTable.remove(iter);
    154139    } else if (key.value.isCell()) {
    155140        auto iter = m_cellKeyedTable.find(key.value.asCell());
     
    201186    for (auto ptr = m_stringKeyedTable.begin(); ptr != m_stringKeyedTable.end(); ++ptr)
    202187        ptr->value = m_entries.get()[ptr->value].key().get().asInt32();
    203     for (auto ptr = m_symbolKeyedTable.begin(); ptr != m_symbolKeyedTable.end(); ++ptr)
    204         ptr->value = m_entries.get()[ptr->value].key().get().asInt32();
    205188
    206189    ASSERT((m_size - newEnd) == m_deletedCount);
  • trunk/Source/JavaScriptCore/runtime/Symbol.cpp

    r202890 r203895  
    11/*
    22 * Copyright (C) 2012 Apple Inc. All rights reserved.
    3  * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
     3 * Copyright (C) 2015-2016 Yusuke Suzuki <utatane.tea@gmail.com>.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    5454}
    5555
     56void Symbol::finishCreation(VM& vm)
     57{
     58    Base::finishCreation(vm);
     59    ASSERT(inherits(info()));
     60
     61    vm.symbolImplToSymbolMap.set(m_privateName.uid(), this);
     62}
     63
    5664inline SymbolObject* SymbolObject::create(VM& vm, JSGlobalObject* globalObject, Symbol* symbol)
    5765{
     
    94102}
    95103
     104Symbol* Symbol::create(VM& vm)
     105{
     106    Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm);
     107    symbol->finishCreation(vm);
     108    return symbol;
     109}
     110
     111Symbol* Symbol::create(ExecState* exec, JSString* description)
     112{
     113    VM& vm = exec->vm();
     114    String desc = description->value(exec);
     115    Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm, desc);
     116    symbol->finishCreation(vm);
     117    return symbol;
     118}
     119
     120Symbol* Symbol::create(VM& vm, SymbolImpl& uid)
     121{
     122    if (Symbol* symbol = vm.symbolImplToSymbolMap.get(&uid))
     123        return symbol;
     124
     125    Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm, uid);
     126    symbol->finishCreation(vm);
     127    return symbol;
     128}
     129
    96130} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/Symbol.h

    r199686 r203895  
    22 * Copyright (C) 2012 Apple Inc. All rights reserved.
    33 * Copyright (C) 2014 Apple Inc. All rights reserved.
    4  * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
     4 * Copyright (C) 2015-2016 Yusuke Suzuki <utatane.tea@gmail.com>.
    55 *
    66 * Redistribution and use in source and binary forms, with or without
     
    2929#define Symbol_h
    3030
    31 #include "JSCell.h"
    3231#include "JSString.h"
    3332#include "PrivateName.h"
     
    4948    }
    5049
    51     static Symbol* create(VM& vm)
    52     {
    53         Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm);
    54         symbol->finishCreation(vm);
    55         return symbol;
    56     }
    57 
    58     static Symbol* create(ExecState* exec, JSString* description)
    59     {
    60         VM& vm = exec->vm();
    61         String desc = description->value(exec);
    62         Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm, desc);
    63         symbol->finishCreation(vm);
    64         return symbol;
    65     }
    66 
    67     static Symbol* create(VM& vm, SymbolImpl& uid)
    68     {
    69         Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm, uid);
    70         symbol->finishCreation(vm);
    71         return symbol;
    72     }
     50    static Symbol* create(VM&);
     51    static Symbol* create(ExecState*, JSString* description);
     52    static Symbol* create(VM&, SymbolImpl& uid);
    7353
    7454    const PrivateName& privateName() const { return m_privateName; }
     
    8060    double toNumber(ExecState*) const;
    8161
    82     static size_t offsetOfPrivateName() { return OBJECT_OFFSETOF(Symbol, m_privateName); }
    83 
    8462protected:
    8563    static void destroy(JSCell*);
     
    8967    Symbol(VM&, SymbolImpl& uid);
    9068
    91     void finishCreation(VM& vm)
    92     {
    93         Base::finishCreation(vm);
    94         ASSERT(inherits(info()));
    95     }
     69    void finishCreation(VM&);
    9670
    9771    PrivateName m_privateName;
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r203808 r203895  
    166166    , customGetterSetterFunctionMap(*this)
    167167    , stringCache(*this)
     168    , symbolImplToSymbolMap(*this)
    168169    , prototypeMap(*this)
    169170    , interpreter(0)
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r203808 r203895  
    109109class RegExp;
    110110#endif
     111class Symbol;
    111112class UnlinkedCodeBlock;
    112113class UnlinkedEvalCodeBlock;
     
    337338    WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; }
    338339
     340    WeakGCMap<SymbolImpl*, Symbol, PtrHash<SymbolImpl*>> symbolImplToSymbolMap;
     341
    339342    enum class DeletePropertyMode {
    340343        // Default behaviour of deleteProperty, matching the spec.
Note: See TracChangeset for help on using the changeset viewer.