Replace uses of Box<Identifier> with a new CacheableIdentifier class.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Jan 2020 23:55:57 +0000 (23:55 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Jan 2020 23:55:57 +0000 (23:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=205544
<rdar://problem/58041800>

Reviewed by Saam Barati.

JSTests:

* stress/racy-gc-cleanup-of-identifier-after-mutator-stops-running.js: Added.

Source/JavaScriptCore:

The introduction of the use of Box<Identifier> was to get around having to
ref/deref the underlying UniqedStringImpl in Identifiers from the compiler
and GC threads.  However, it proves to be difficult to control when these
Box<Identifier>s get destructed, and requires that we find all the places in
the compier and GC threads where this can happen, and apply keep alive tactics
there to defer destruction of the Box<Identifier> to the mutator thread.

This patch fixes this by replacing uses of Box<Identifier> with
CacheableIdentifier, which is effectively a tagged union of a JSCell* or a
UniquedStringImpl*.  The JSCell*, in this case, can be either a Symbol* or a
JSString* that is backed by an atom string.  The VM runtime ensures that we'll
never try to cache an identifier from a JSCell that is not one of these.  This
CacheableIdentifier can be destructed from the compiler or GC thread.  Since it
doesn't hold a ref of the underlying UniquedStringImpl, it won't try to deref
it on destruction.

Instead, we'll need to visit CacheableIdentifiers during GC scans to keep the
JSCell in it alive, and that JSCell will, in turn, keep the underlying
UniquedStringImpl alive.

This patch also does the following:

1. Add a visitAggregate() method to StructureStubInfo, PolymorphicAccess, and
   AccessCase to visit the CacheableIdentifier's JSCell identifier.  This
   visitAggregate() is called from CodeBlock::stronglyVisitStrongReferences().

   When we write barrier a CodeBlock, it guarantees that its visitAggregate()
   methods is called.  However, it does not guarantee that its propagateTransitions()
   method will be called.  Since the CacheableIdentifier's reference to a cell
   should be a strong reference, visiting it via a StructureStubInfo::visitAggregate()
   method is the right thing to do.
   See https://bugs.webkit.org/show_bug.cgi?id=205544#c7 for an example of why
   propagateTransitions() doesn't always do the job.

   StructureStubInfo::visitWeakReferences() is also inappropriate for this
   because it is only called after all marking is done.  It is also not meant
   to keep cells alive but merely for clearing weak references to dead cells.

2. Also add to visitAggregate() for ModuleNamespaceData's m_identifier in
   GetByStatus::markIfCheap().

3. Remove previously applied keep alive tactics to work around Box<Identifier>
   destruction.  This also retores the allowance to destruct DFG::Plans on a
   compiler thread.

4. Added a JSString:getValueImpl() helper.

5. Added a write barrier in DFG and FTL JITFinalizer's finalizeCommon() to ensure
   that frozen values are scanned by the GC.

   During compilation, the frozen values were previously protected by the Plan.
   After finalization, they should be protected by the CodeBlock.  Hence, we
   should barrier the CodeBlock since the last GC scan of the CodeBlock may have
   happened before the frozen values were registered with the CodeBlock.

GC considerations:
==================
The following also addresses Yusuke's concerns in https://bugs.webkit.org/show_bug.cgi?id=205544#c10.

CacheableIdentifier is only stored as fields in 4 classes/structs:

1. AccessCase::m_identifier
2. GetByIdVariant::m_identifier
3. ModuleNamespaceData::m_identifier
4. StructureStubInfo::m_getByIdSelfIdentifier

AccessCase::m_identifier
========================
While the access case is being created and added in tryCacheGetBy(), the
CacheableIdentifier is still on the stack and protected from the GC.  At the
bottom of tryCacheGetBy(), StructureStubInfo::addAccessCase() is called to add
the access case.

StructureStubInfo::addAccessCase() will barrier the owner CodeBlock at its end,
and CodeBlock::stronglyVisitStrongReferences() will visit the StructureStubInfo,
which in turn visits the AccessCase.  StructureStubInfo::visitAggregate() has
been added for this purpose.

GetByIdVariant::m_identifier
============================
GetByIdVariant is only stored in GetByStatus.  Both GetByIdVariant and GetByStatus
are only created and handled in the DFG/FTL compiler threads.  While the compiler
thread is working with them, they are safe from the GC because the GC won't collect
objects until the compiler thread is at a SafePoint.

At compiler SafePoints, any GetByStatus that needs to be persisted is stored in
DFG::Plan::m_recordedStatuses.  The Plan will visit the m_recordedStatuses in
Plan::checkLivenessAndVisitChildren().

At the end of compilation, Plan::m_recordedStatuses is transferred over to the owner
CodeBlock's DFG::CommonData in Plan::finalizeWithoutNotifyingCallback().
Plan::finalizeWithoutNotifyingCallback() will also barrier the owner CodeBlock at
its end.

Thereafter, CodeBlock::stronglyVisitStrongReferences() will visit the recordedStatuses.

ModuleNamespaceData::m_identifier
=================================
ModuleNamespaceData is only stored in a GetByStatus, and is therefore protected
similarly as the GetByIdVariant::m_identifier case above.

StructureStubInfo::m_getByIdSelfIdentifier
==========================================
StructureStubInfo::initGetByIdSelf() is called from inside tryCacheGetBy().
StructureStubInfo::initGetByIdSelf() will barrier the owner CodeBlock.  The
CacheableIdentifier here is protected in the same way as the AccessCase::m_identifier
case above.

DesiredIdentifiers
==================
The compiler thread may also stash a CacheableIdentifier's uid in its
DesiredIdentifiers.  Normally, the identifiers stashed in DesiredIdentifiers are
from identifiers that the CodeBlock already knows abut and manages (e.g. from
GetByIds).  For uids from a cell-based CacheableIdentifier variable is passed to
a GetByVal, we need kep the cell alive in order to keep the uid alive.  This is
achieved by freezing the cell with freezeStrong() in the op_get_by_val case in
the DFG BytecodeParser.

Reseting a StructureStubInfo while its IC code is still executing on the stack
==============================================================================
The concern is that IC code may call slow path / getter functions that may in turn:

1. reset the IC, and
2. run the GC.

This can be a problem if:

1. there is a scenario where we return from the slow path / getter function
   and run IC code that uses the cell / uid from the CacheableIdentifier.

   This is because the StructureStubInfo is what visits the that cell, which
   in turn its uid alive.  Once the StructureStubInfo is reset, it will no
   longer be associated with any AccessCase or the m_getByIdSelfIdentifier.
   As such they will not be visited, and the CacheableIdentifier may be collected
   by the GC.

   In practice, the generated IC code never uses the cell / uid after it calls
   any slow path / getter function.  I've verified this by auditing the code
   generation in InlineAccess::generateSelfInAccess() and PolymorphicAccess::regenerate().
   Hence, there's no issue with using a collected cell / uid.

2. there is a scenario where a slow path / getter function makes use of the cell / uid
   from the CacheableIdentifier but does not protect it.

   The only 2 slow path functions:
       operationGetByValGeneric()
       operationGetByValOptimize()

   operationGetByValGeneric() does not use any CacheableIdentifier from the StructureStubInfo.

   operationGetByValOptimize() modifies the StructureStubInfo in tryCacheGetBy()
   under the protection of a GCSafeConcurrentJSLocker, and can reset the
   StructureStubInfo.  However, it does not use any CacheableIdentifier after
   that.

   Hence, there's also no GC issue here.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* bytecode/AccessCase.cpp:
(JSC::AccessCase::AccessCase):
(JSC::AccessCase::create):
(JSC::AccessCase::fromStructureStubInfo):
(JSC::AccessCase::commit):
(JSC::AccessCase::canReplace const):
(JSC::AccessCase::dump const):
(JSC::AccessCase::visitAggregate const):
(JSC::AccessCase::generateWithGuard):
(JSC::AccessCase::generateImpl):
* bytecode/AccessCase.h:
(JSC::AccessCase::uid const):
(JSC::AccessCase::identifier const):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::propagateTransitions):
(JSC::CodeBlock::stronglyVisitStrongReferences):
* bytecode/GetByIdVariant.cpp:
(JSC::GetByIdVariant::GetByIdVariant):
(JSC::GetByIdVariant::attemptToMerge):
(JSC::GetByIdVariant::visitAggregate):
(JSC::GetByIdVariant::dumpInContext const):
* bytecode/GetByIdVariant.h:
(JSC::GetByIdVariant::identifier const):
(JSC::GetByIdVariant::overlaps):
* bytecode/GetByStatus.cpp:
(JSC::GetByStatus::computeFromLLInt):
(JSC::GetByStatus::computeFor):
(JSC::GetByStatus::computeForStubInfoWithoutExitSiteFeedback):
(JSC::GetByStatus::visitAggregate):
(JSC::GetByStatus::singleIdentifier const):
* bytecode/GetByStatus.h:
* bytecode/GetterSetterAccessCase.cpp:
(JSC::GetterSetterAccessCase::GetterSetterAccessCase):
(JSC::GetterSetterAccessCase::create):
* bytecode/GetterSetterAccessCase.h:
* bytecode/InstanceOfAccessCase.cpp:
(JSC::InstanceOfAccessCase::InstanceOfAccessCase):
* bytecode/IntrinsicGetterAccessCase.cpp:
(JSC::IntrinsicGetterAccessCase::IntrinsicGetterAccessCase):
(JSC::IntrinsicGetterAccessCase::create):
* bytecode/IntrinsicGetterAccessCase.h:
* bytecode/ModuleNamespaceAccessCase.cpp:
(JSC::ModuleNamespaceAccessCase::ModuleNamespaceAccessCase):
(JSC::ModuleNamespaceAccessCase::create):
* bytecode/ModuleNamespaceAccessCase.h:
* bytecode/PolymorphicAccess.cpp:
(JSC::PolymorphicAccess::visitAggregate):
(JSC::PolymorphicAccess::regenerate):
* bytecode/PolymorphicAccess.h:
* bytecode/ProxyableAccessCase.cpp:
(JSC::ProxyableAccessCase::ProxyableAccessCase):
(JSC::ProxyableAccessCase::create):
* bytecode/ProxyableAccessCase.h:
* bytecode/RecordedStatuses.cpp:
(JSC::RecordedStatuses::visitAggregate):
* bytecode/RecordedStatuses.h:
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::initGetByIdSelf):
(JSC::StructureStubInfo::addAccessCase):
(JSC::StructureStubInfo::visitAggregate):
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::getByIdSelfIdentifier):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseGetById):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGDesiredIdentifiers.cpp:
(JSC::DFG::DesiredIdentifiers::ensure):
(JSC::DFG::DesiredIdentifiers::at const):
(JSC::DFG::DesiredIdentifiers::reallyAdd):
(JSC::DFG::DesiredIdentifiers::processCodeBlockIdentifiersIfNeeded): Deleted.
* dfg/DFGDesiredIdentifiers.h:
* dfg/DFGJITFinalizer.cpp:
(JSC::DFG::JITFinalizer::finalizeCommon):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::~Plan):
(JSC::DFG::Plan::checkLivenessAndVisitChildren):
(JSC::DFG::Plan::cancel):
* dfg/DFGPlan.h:
(JSC::DFG::Plan::keepAliveIdentifier): Deleted.
* dfg/DFGWorklist.cpp:
(JSC::DFG::Worklist::removeAllReadyPlansForVM):
(JSC::DFG::Worklist::removeDeadPlans):
(JSC::DFG::Worklist::removeNonCompilingPlansForVM):
(JSC::DFG::Worklist::deleteCancelledPlansForVM): Deleted.
* dfg/DFGWorklist.h:
* ftl/FTLJITFinalizer.cpp:
(JSC::FTL::JITFinalizer::finalizeCommon):
* jit/JITOperations.cpp:
* jit/Repatch.cpp:
(JSC::tryCacheGetBy):
(JSC::repatchGetBy):
(JSC::tryCacheArrayGetByVal):
(JSC::tryCacheInstanceOf):
* jit/Repatch.h:
* runtime/CacheableIdentifier.cpp: Added.
(JSC::CacheableIdentifier::dump const):
* runtime/CacheableIdentifier.h: Added.
(JSC::CacheableIdentifier::CacheableIdentifier):
(JSC::CacheableIdentifier::isUid const):
(JSC::CacheableIdentifier::isCell const):
(JSC::CacheableIdentifier::isSymbol const):
(JSC::CacheableIdentifier::operator bool const):
* runtime/CacheableIdentifierInlines.h: Added.
(JSC::CacheableIdentifier::CacheableIdentifier):
(JSC::CacheableIdentifier::cell const):
(JSC::CacheableIdentifier::uid const):
(JSC::CacheableIdentifier::isCacheableIdentifierCell):
(JSC::CacheableIdentifier::isSymbolCell const):
(JSC::CacheableIdentifier::isStringCell const):
(JSC::CacheableIdentifier::setCellBits):
(JSC::CacheableIdentifier::setUidBits):
(JSC::CacheableIdentifier::visitAggregate const):
(JSC::CacheableIdentifier::operator== const):
(JSC::CacheableIdentifier::operator!= const):
* runtime/ExceptionHelpers.cpp:
(JSC::functionCallBase):
* runtime/JSString.h:
(JSC::JSString::getValueImpl const):
* runtime/VM.cpp:
(JSC::VM::ensureWatchpointSetForImpureProperty):
(JSC::VM::addImpureProperty):
(JSC::VM::registerWatchpointForImpureProperty): Deleted.
* runtime/VM.h:

Source/WebCore:

* bindings/js/CommonVM.cpp:
(WebCore::addImpureProperty):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@254464 268f45cc-cd09-0410-ab3c-d52691b4dbfc

49 files changed:
JSTests/ChangeLog
JSTests/stress/racy-gc-cleanup-of-identifier-after-mutator-stops-running.js [new file with mode: 0644]
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/bytecode/AccessCase.cpp
Source/JavaScriptCore/bytecode/AccessCase.h
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/GetByIdVariant.cpp
Source/JavaScriptCore/bytecode/GetByIdVariant.h
Source/JavaScriptCore/bytecode/GetByStatus.cpp
Source/JavaScriptCore/bytecode/GetByStatus.h
Source/JavaScriptCore/bytecode/GetterSetterAccessCase.cpp
Source/JavaScriptCore/bytecode/GetterSetterAccessCase.h
Source/JavaScriptCore/bytecode/InstanceOfAccessCase.cpp
Source/JavaScriptCore/bytecode/IntrinsicGetterAccessCase.cpp
Source/JavaScriptCore/bytecode/IntrinsicGetterAccessCase.h
Source/JavaScriptCore/bytecode/ModuleNamespaceAccessCase.cpp
Source/JavaScriptCore/bytecode/ModuleNamespaceAccessCase.h
Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp
Source/JavaScriptCore/bytecode/PolymorphicAccess.h
Source/JavaScriptCore/bytecode/ProxyableAccessCase.cpp
Source/JavaScriptCore/bytecode/ProxyableAccessCase.h
Source/JavaScriptCore/bytecode/RecordedStatuses.cpp
Source/JavaScriptCore/bytecode/RecordedStatuses.h
Source/JavaScriptCore/bytecode/StructureStubInfo.cpp
Source/JavaScriptCore/bytecode/StructureStubInfo.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGDesiredIdentifiers.cpp
Source/JavaScriptCore/dfg/DFGDesiredIdentifiers.h
Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp
Source/JavaScriptCore/dfg/DFGPlan.cpp
Source/JavaScriptCore/dfg/DFGPlan.h
Source/JavaScriptCore/dfg/DFGWorklist.cpp
Source/JavaScriptCore/dfg/DFGWorklist.h
Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/Repatch.cpp
Source/JavaScriptCore/jit/Repatch.h
Source/JavaScriptCore/runtime/CacheableIdentifier.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/CacheableIdentifier.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/CacheableIdentifierInlines.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/JSString.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/CommonVM.cpp

index 02bc7ca..bcc8ef2 100644 (file)
@@ -1,3 +1,13 @@
+2020-01-13  Mark Lam  <mark.lam@apple.com>
+
+        Replace uses of Box<Identifier> with a new CacheableIdentifier class.
+        https://bugs.webkit.org/show_bug.cgi?id=205544
+        <rdar://problem/58041800>
+
+        Reviewed by Saam Barati.
+
+        * stress/racy-gc-cleanup-of-identifier-after-mutator-stops-running.js: Added.
+
 2020-01-11  Keith Miller  <keith_miller@apple.com>
 
         CheckNeutered needs to claim it reads JSType in clobberize.
diff --git a/JSTests/stress/racy-gc-cleanup-of-identifier-after-mutator-stops-running.js b/JSTests/stress/racy-gc-cleanup-of-identifier-after-mutator-stops-running.js
new file mode 100644 (file)
index 0000000..83552bc
--- /dev/null
@@ -0,0 +1,16 @@
+//@ runDefault("--numberOfGCMarkers=1", "--useDFGJIT=false", "--useLLInt=false")
+
+function foo() {
+    gc();
+    for (let i = 0; i < 100000; i++) {
+        const o = { f: 42 };
+        o[Symbol.split.description];
+    }
+}
+function bar() {
+    for (let i = 0; i < 100; i++)
+        new Uint8Array(200000).subarray();
+}
+
+foo();
+bar();
index 4f2e04d..e1cb0a5 100644 (file)
@@ -785,6 +785,8 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS
     runtime/BytecodeCacheError.h
     runtime/CachePayload.h
     runtime/CacheUpdate.h
+    runtime/CacheableIdentifier.h
+    runtime/CacheableIdentifierInlines.h
     runtime/CachedBytecode.h
     runtime/CachedTypes.h
     runtime/CagedBarrierPtr.h
index faf423d..c6401ac 100644 (file)
@@ -1,3 +1,295 @@
+2020-01-13  Mark Lam  <mark.lam@apple.com>
+
+        Replace uses of Box<Identifier> with a new CacheableIdentifier class.
+        https://bugs.webkit.org/show_bug.cgi?id=205544
+        <rdar://problem/58041800>
+
+        Reviewed by Saam Barati.
+
+        The introduction of the use of Box<Identifier> was to get around having to
+        ref/deref the underlying UniqedStringImpl in Identifiers from the compiler
+        and GC threads.  However, it proves to be difficult to control when these
+        Box<Identifier>s get destructed, and requires that we find all the places in
+        the compier and GC threads where this can happen, and apply keep alive tactics
+        there to defer destruction of the Box<Identifier> to the mutator thread.
+
+        This patch fixes this by replacing uses of Box<Identifier> with
+        CacheableIdentifier, which is effectively a tagged union of a JSCell* or a
+        UniquedStringImpl*.  The JSCell*, in this case, can be either a Symbol* or a
+        JSString* that is backed by an atom string.  The VM runtime ensures that we'll
+        never try to cache an identifier from a JSCell that is not one of these.  This
+        CacheableIdentifier can be destructed from the compiler or GC thread.  Since it
+        doesn't hold a ref of the underlying UniquedStringImpl, it won't try to deref
+        it on destruction.
+
+        Instead, we'll need to visit CacheableIdentifiers during GC scans to keep the
+        JSCell in it alive, and that JSCell will, in turn, keep the underlying
+        UniquedStringImpl alive.
+
+        This patch also does the following:
+
+        1. Add a visitAggregate() method to StructureStubInfo, PolymorphicAccess, and
+           AccessCase to visit the CacheableIdentifier's JSCell identifier.  This
+           visitAggregate() is called from CodeBlock::stronglyVisitStrongReferences().
+
+           When we write barrier a CodeBlock, it guarantees that its visitAggregate()
+           methods is called.  However, it does not guarantee that its propagateTransitions()
+           method will be called.  Since the CacheableIdentifier's reference to a cell
+           should be a strong reference, visiting it via a StructureStubInfo::visitAggregate()
+           method is the right thing to do.
+           See https://bugs.webkit.org/show_bug.cgi?id=205544#c7 for an example of why
+           propagateTransitions() doesn't always do the job.
+
+           StructureStubInfo::visitWeakReferences() is also inappropriate for this
+           because it is only called after all marking is done.  It is also not meant
+           to keep cells alive but merely for clearing weak references to dead cells.
+
+        2. Also add to visitAggregate() for ModuleNamespaceData's m_identifier in
+           GetByStatus::markIfCheap().
+
+        3. Remove previously applied keep alive tactics to work around Box<Identifier>
+           destruction.  This also retores the allowance to destruct DFG::Plans on a
+           compiler thread.
+
+        4. Added a JSString:getValueImpl() helper.
+
+        5. Added a write barrier in DFG and FTL JITFinalizer's finalizeCommon() to ensure
+           that frozen values are scanned by the GC.
+
+           During compilation, the frozen values were previously protected by the Plan.
+           After finalization, they should be protected by the CodeBlock.  Hence, we
+           should barrier the CodeBlock since the last GC scan of the CodeBlock may have
+           happened before the frozen values were registered with the CodeBlock.
+
+        GC considerations:
+        ==================
+        The following also addresses Yusuke's concerns in https://bugs.webkit.org/show_bug.cgi?id=205544#c10.
+
+        CacheableIdentifier is only stored as fields in 4 classes/structs:
+
+        1. AccessCase::m_identifier
+        2. GetByIdVariant::m_identifier
+        3. ModuleNamespaceData::m_identifier
+        4. StructureStubInfo::m_getByIdSelfIdentifier
+
+        AccessCase::m_identifier
+        ========================
+        While the access case is being created and added in tryCacheGetBy(), the
+        CacheableIdentifier is still on the stack and protected from the GC.  At the
+        bottom of tryCacheGetBy(), StructureStubInfo::addAccessCase() is called to add
+        the access case.
+
+        StructureStubInfo::addAccessCase() will barrier the owner CodeBlock at its end,
+        and CodeBlock::stronglyVisitStrongReferences() will visit the StructureStubInfo,
+        which in turn visits the AccessCase.  StructureStubInfo::visitAggregate() has
+        been added for this purpose.
+
+        GetByIdVariant::m_identifier
+        ============================
+        GetByIdVariant is only stored in GetByStatus.  Both GetByIdVariant and GetByStatus
+        are only created and handled in the DFG/FTL compiler threads.  While the compiler
+        thread is working with them, they are safe from the GC because the GC won't collect
+        objects until the compiler thread is at a SafePoint.
+
+        At compiler SafePoints, any GetByStatus that needs to be persisted is stored in
+        DFG::Plan::m_recordedStatuses.  The Plan will visit the m_recordedStatuses in
+        Plan::checkLivenessAndVisitChildren().
+
+        At the end of compilation, Plan::m_recordedStatuses is transferred over to the owner
+        CodeBlock's DFG::CommonData in Plan::finalizeWithoutNotifyingCallback().
+        Plan::finalizeWithoutNotifyingCallback() will also barrier the owner CodeBlock at
+        its end.
+
+        Thereafter, CodeBlock::stronglyVisitStrongReferences() will visit the recordedStatuses.
+
+        ModuleNamespaceData::m_identifier
+        =================================
+        ModuleNamespaceData is only stored in a GetByStatus, and is therefore protected
+        similarly as the GetByIdVariant::m_identifier case above.
+
+        StructureStubInfo::m_getByIdSelfIdentifier
+        ==========================================
+        StructureStubInfo::initGetByIdSelf() is called from inside tryCacheGetBy().
+        StructureStubInfo::initGetByIdSelf() will barrier the owner CodeBlock.  The
+        CacheableIdentifier here is protected in the same way as the AccessCase::m_identifier
+        case above.
+
+        DesiredIdentifiers
+        ==================
+        The compiler thread may also stash a CacheableIdentifier's uid in its
+        DesiredIdentifiers.  Normally, the identifiers stashed in DesiredIdentifiers are
+        from identifiers that the CodeBlock already knows abut and manages (e.g. from
+        GetByIds).  For uids from a cell-based CacheableIdentifier variable is passed to
+        a GetByVal, we need kep the cell alive in order to keep the uid alive.  This is
+        achieved by freezing the cell with freezeStrong() in the op_get_by_val case in
+        the DFG BytecodeParser.
+
+        Reseting a StructureStubInfo while its IC code is still executing on the stack
+        ==============================================================================
+        The concern is that IC code may call slow path / getter functions that may in turn:
+
+        1. reset the IC, and
+        2. run the GC.
+
+        This can be a problem if:
+
+        1. there is a scenario where we return from the slow path / getter function
+           and run IC code that uses the cell / uid from the CacheableIdentifier.
+
+           This is because the StructureStubInfo is what visits the that cell, which
+           in turn its uid alive.  Once the StructureStubInfo is reset, it will no
+           longer be associated with any AccessCase or the m_getByIdSelfIdentifier.
+           As such they will not be visited, and the CacheableIdentifier may be collected
+           by the GC.
+
+           In practice, the generated IC code never uses the cell / uid after it calls
+           any slow path / getter function.  I've verified this by auditing the code
+           generation in InlineAccess::generateSelfInAccess() and PolymorphicAccess::regenerate().
+           Hence, there's no issue with using a collected cell / uid.
+
+        2. there is a scenario where a slow path / getter function makes use of the cell / uid
+           from the CacheableIdentifier but does not protect it.
+
+           The only 2 slow path functions:
+               operationGetByValGeneric()
+               operationGetByValOptimize()
+
+           operationGetByValGeneric() does not use any CacheableIdentifier from the StructureStubInfo.
+
+           operationGetByValOptimize() modifies the StructureStubInfo in tryCacheGetBy()
+           under the protection of a GCSafeConcurrentJSLocker, and can reset the
+           StructureStubInfo.  However, it does not use any CacheableIdentifier after
+           that.
+
+           Hence, there's also no GC issue here.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * bytecode/AccessCase.cpp:
+        (JSC::AccessCase::AccessCase):
+        (JSC::AccessCase::create):
+        (JSC::AccessCase::fromStructureStubInfo):
+        (JSC::AccessCase::commit):
+        (JSC::AccessCase::canReplace const):
+        (JSC::AccessCase::dump const):
+        (JSC::AccessCase::visitAggregate const):
+        (JSC::AccessCase::generateWithGuard):
+        (JSC::AccessCase::generateImpl):
+        * bytecode/AccessCase.h:
+        (JSC::AccessCase::uid const):
+        (JSC::AccessCase::identifier const):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::propagateTransitions):
+        (JSC::CodeBlock::stronglyVisitStrongReferences):
+        * bytecode/GetByIdVariant.cpp:
+        (JSC::GetByIdVariant::GetByIdVariant):
+        (JSC::GetByIdVariant::attemptToMerge):
+        (JSC::GetByIdVariant::visitAggregate):
+        (JSC::GetByIdVariant::dumpInContext const):
+        * bytecode/GetByIdVariant.h:
+        (JSC::GetByIdVariant::identifier const):
+        (JSC::GetByIdVariant::overlaps):
+        * bytecode/GetByStatus.cpp:
+        (JSC::GetByStatus::computeFromLLInt):
+        (JSC::GetByStatus::computeFor):
+        (JSC::GetByStatus::computeForStubInfoWithoutExitSiteFeedback):
+        (JSC::GetByStatus::visitAggregate):
+        (JSC::GetByStatus::singleIdentifier const):
+        * bytecode/GetByStatus.h:
+        * bytecode/GetterSetterAccessCase.cpp:
+        (JSC::GetterSetterAccessCase::GetterSetterAccessCase):
+        (JSC::GetterSetterAccessCase::create):
+        * bytecode/GetterSetterAccessCase.h:
+        * bytecode/InstanceOfAccessCase.cpp:
+        (JSC::InstanceOfAccessCase::InstanceOfAccessCase):
+        * bytecode/IntrinsicGetterAccessCase.cpp:
+        (JSC::IntrinsicGetterAccessCase::IntrinsicGetterAccessCase):
+        (JSC::IntrinsicGetterAccessCase::create):
+        * bytecode/IntrinsicGetterAccessCase.h:
+        * bytecode/ModuleNamespaceAccessCase.cpp:
+        (JSC::ModuleNamespaceAccessCase::ModuleNamespaceAccessCase):
+        (JSC::ModuleNamespaceAccessCase::create):
+        * bytecode/ModuleNamespaceAccessCase.h:
+        * bytecode/PolymorphicAccess.cpp:
+        (JSC::PolymorphicAccess::visitAggregate):
+        (JSC::PolymorphicAccess::regenerate):
+        * bytecode/PolymorphicAccess.h:
+        * bytecode/ProxyableAccessCase.cpp:
+        (JSC::ProxyableAccessCase::ProxyableAccessCase):
+        (JSC::ProxyableAccessCase::create):
+        * bytecode/ProxyableAccessCase.h:
+        * bytecode/RecordedStatuses.cpp:
+        (JSC::RecordedStatuses::visitAggregate):
+        * bytecode/RecordedStatuses.h:
+        * bytecode/StructureStubInfo.cpp:
+        (JSC::StructureStubInfo::initGetByIdSelf):
+        (JSC::StructureStubInfo::addAccessCase):
+        (JSC::StructureStubInfo::visitAggregate):
+        * bytecode/StructureStubInfo.h:
+        (JSC::StructureStubInfo::getByIdSelfIdentifier):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseGetById):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGDesiredIdentifiers.cpp:
+        (JSC::DFG::DesiredIdentifiers::ensure):
+        (JSC::DFG::DesiredIdentifiers::at const):
+        (JSC::DFG::DesiredIdentifiers::reallyAdd):
+        (JSC::DFG::DesiredIdentifiers::processCodeBlockIdentifiersIfNeeded): Deleted.
+        * dfg/DFGDesiredIdentifiers.h:
+        * dfg/DFGJITFinalizer.cpp:
+        (JSC::DFG::JITFinalizer::finalizeCommon):
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::~Plan):
+        (JSC::DFG::Plan::checkLivenessAndVisitChildren):
+        (JSC::DFG::Plan::cancel):
+        * dfg/DFGPlan.h:
+        (JSC::DFG::Plan::keepAliveIdentifier): Deleted.
+        * dfg/DFGWorklist.cpp:
+        (JSC::DFG::Worklist::removeAllReadyPlansForVM):
+        (JSC::DFG::Worklist::removeDeadPlans):
+        (JSC::DFG::Worklist::removeNonCompilingPlansForVM):
+        (JSC::DFG::Worklist::deleteCancelledPlansForVM): Deleted.
+        * dfg/DFGWorklist.h:
+        * ftl/FTLJITFinalizer.cpp:
+        (JSC::FTL::JITFinalizer::finalizeCommon):
+        * jit/JITOperations.cpp:
+        * jit/Repatch.cpp:
+        (JSC::tryCacheGetBy):
+        (JSC::repatchGetBy):
+        (JSC::tryCacheArrayGetByVal):
+        (JSC::tryCacheInstanceOf):
+        * jit/Repatch.h:
+        * runtime/CacheableIdentifier.cpp: Added.
+        (JSC::CacheableIdentifier::dump const):
+        * runtime/CacheableIdentifier.h: Added.
+        (JSC::CacheableIdentifier::CacheableIdentifier):
+        (JSC::CacheableIdentifier::isUid const):
+        (JSC::CacheableIdentifier::isCell const):
+        (JSC::CacheableIdentifier::isSymbol const):
+        (JSC::CacheableIdentifier::operator bool const):
+        * runtime/CacheableIdentifierInlines.h: Added.
+        (JSC::CacheableIdentifier::CacheableIdentifier):
+        (JSC::CacheableIdentifier::cell const):
+        (JSC::CacheableIdentifier::uid const):
+        (JSC::CacheableIdentifier::isCacheableIdentifierCell):
+        (JSC::CacheableIdentifier::isSymbolCell const):
+        (JSC::CacheableIdentifier::isStringCell const):
+        (JSC::CacheableIdentifier::setCellBits):
+        (JSC::CacheableIdentifier::setUidBits):
+        (JSC::CacheableIdentifier::visitAggregate const):
+        (JSC::CacheableIdentifier::operator== const):
+        (JSC::CacheableIdentifier::operator!= const):
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::functionCallBase):
+        * runtime/JSString.h:
+        (JSC::JSString::getValueImpl const):
+        * runtime/VM.cpp:
+        (JSC::VM::ensureWatchpointSetForImpureProperty):
+        (JSC::VM::addImpureProperty):
+        (JSC::VM::registerWatchpointForImpureProperty): Deleted.
+        * runtime/VM.h:
+
 2020-01-13  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] Put JSProxy in IsoSubspace
index 2d745f2..d07e5b8 100644 (file)
                FE7497E6209001B10003565B /* JSCPtrTag.h in Headers */ = {isa = PBXBuildFile; fileRef = FE7497E5209001B00003565B /* JSCPtrTag.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FE7C41961B97FC4B00F4D598 /* PingPongStackOverflowTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEDA50D41B97F442009A3B4F /* PingPongStackOverflowTest.cpp */; };
                FE80C1971D775CDD008510C0 /* CatchScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE80C1961D775B27008510C0 /* CatchScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               FE8DE54B23AC1DAD005C9142 /* CacheableIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = FE8DE54A23AC1DAD005C9142 /* CacheableIdentifier.h */; };
+               FE8DE54D23AC1E86005C9142 /* CacheableIdentifierInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FE8DE54C23AC1E86005C9142 /* CacheableIdentifierInlines.h */; };
                FE99B2491C24C3D300C82159 /* JITNegGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE99B2481C24B6D300C82159 /* JITNegGenerator.h */; };
                FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861E182B7A0400F6D851 /* Breakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FEA08621182B7A0400F6D851 /* DebuggerPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FE80C1961D775B27008510C0 /* CatchScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CatchScope.h; sourceTree = "<group>"; };
                FE80C1981D775FB4008510C0 /* CatchScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CatchScope.cpp; sourceTree = "<group>"; };
                FE80C19A1D7768FD008510C0 /* ExceptionEventLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExceptionEventLocation.cpp; sourceTree = "<group>"; };
+               FE8DE54A23AC1DAD005C9142 /* CacheableIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CacheableIdentifier.h; sourceTree = "<group>"; };
+               FE8DE54C23AC1E86005C9142 /* CacheableIdentifierInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CacheableIdentifierInlines.h; sourceTree = "<group>"; };
+               FE8DE54E23AC3A8E005C9142 /* CacheableIdentifier.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CacheableIdentifier.cpp; sourceTree = "<group>"; };
                FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMInlines.h; sourceTree = "<group>"; };
                FE98B5B61BB9AE110073E7A6 /* JITSubGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITSubGenerator.h; sourceTree = "<group>"; };
                FE99B2471C24B6D300C82159 /* JITNegGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITNegGenerator.cpp; sourceTree = "<group>"; };
                                0FB7F38C15ED8E3800F167B2 /* ButterflyInlines.h */,
                                1435952022A521CA00E8086D /* BytecodeCacheError.cpp */,
                                1435951F22A521CA00E8086D /* BytecodeCacheError.h */,
+                               FE8DE54E23AC3A8E005C9142 /* CacheableIdentifier.cpp */,
+                               FE8DE54A23AC1DAD005C9142 /* CacheableIdentifier.h */,
+                               FE8DE54C23AC1E86005C9142 /* CacheableIdentifierInlines.h */,
                                148B1419225DD1E900D6E998 /* CachedBytecode.cpp */,
                                144CA34F221F037900817789 /* CachedBytecode.h */,
                                14DAFA4521E3B871004B68F7 /* CachedTypes.cpp */,
                                0F5CF9841E9D537700C18692 /* AirLowerStackArgs.h in Headers */,
                                0F40E4A71C497F7400A577FA /* AirOpcode.h in Headers */,
                                0F40E4A81C497F7400A577FA /* AirOpcodeGenerated.h in Headers */,
+                               FE8DE54B23AC1DAD005C9142 /* CacheableIdentifier.h in Headers */,
                                0F40E4A91C497F7400A577FA /* AirOpcodeUtils.h in Headers */,
                                0FB387901BFBC44D00E3AB1E /* AirOptimizeBlockOrder.h in Headers */,
                                0F9CABC91DB54A7A0008E83B /* AirPadInterference.h in Headers */,
                                658D3A5619638268003C45D6 /* VMEntryRecord.h in Headers */,
                                FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */,
                                0F5AE2C41DF4F2800066EFE1 /* VMInlines.h in Headers */,
+                               FE8DE54D23AC1E86005C9142 /* CacheableIdentifierInlines.h in Headers */,
                                FE3022D71E42857300BAC493 /* VMInspector.h in Headers */,
                                FEC5797323105B5100BCA83F /* VMInspectorInlines.h in Headers */,
                                FE6F56DE1E64EAD600D17801 /* VMTraps.h in Headers */,
index 6ad431b..3cbf487 100644 (file)
@@ -729,6 +729,7 @@ runtime/BytecodeCacheError.cpp
 runtime/CallData.cpp
 runtime/CachePayload.cpp
 runtime/CacheUpdate.cpp
+runtime/CacheableIdentifier.cpp
 runtime/CachedBytecode.cpp
 runtime/CachedTypes.cpp
 runtime/CatchScope.cpp
index 823603a..71da86d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +29,7 @@
 #if ENABLE(JIT)
 
 #include "CCallHelpers.h"
+#include "CacheableIdentifierInlines.h"
 #include "CallLinkInfo.h"
 #include "DOMJITGetterSetter.h"
 #include "DirectArguments.h"
@@ -56,18 +57,18 @@ static constexpr bool verbose = false;
 
 DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(AccessCase);
 
-AccessCase::AccessCase(VM& vm, JSCell* owner, AccessType type, const Identifier& identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
+AccessCase::AccessCase(VM& vm, JSCell* owner, AccessType type, CacheableIdentifier identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
     : m_type(type)
     , m_offset(offset)
     , m_polyProtoAccessChain(WTFMove(prototypeAccessChain))
-    , m_identifier(Box<Identifier>::create(identifier))
+    , m_identifier(identifier)
 {
     m_structure.setMayBeNull(vm, owner, structure);
     m_conditionSet = conditionSet;
     RELEASE_ASSERT(m_conditionSet.isValid());
 }
 
-std::unique_ptr<AccessCase> AccessCase::create(VM& vm, JSCell* owner, AccessType type, const Identifier& identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
+std::unique_ptr<AccessCase> AccessCase::create(VM& vm, JSCell* owner, AccessType type, CacheableIdentifier identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
 {
     switch (type) {
     case InHit:
@@ -106,7 +107,7 @@ std::unique_ptr<AccessCase> AccessCase::create(VM& vm, JSCell* owner, AccessType
 }
 
 std::unique_ptr<AccessCase> AccessCase::create(
-    VM& vm, JSCell* owner, const Identifier& identifier, PropertyOffset offset, Structure* oldStructure, Structure* newStructure,
+    VM& vm, JSCell* owner, CacheableIdentifier identifier, PropertyOffset offset, Structure* oldStructure, Structure* newStructure,
     const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
 {
     RELEASE_ASSERT(oldStructure == newStructure->previousID());
@@ -127,7 +128,7 @@ AccessCase::~AccessCase()
 }
 
 std::unique_ptr<AccessCase> AccessCase::fromStructureStubInfo(
-    VM& vm, JSCell* owner, const Identifier& identifier, StructureStubInfo& stubInfo)
+    VM& vm, JSCell* owner, CacheableIdentifier identifier, StructureStubInfo& stubInfo)
 {
     switch (stubInfo.cacheType()) {
     case CacheType::GetByIdSelf:
@@ -136,18 +137,22 @@ std::unique_ptr<AccessCase> AccessCase::fromStructureStubInfo(
 
     case CacheType::PutByIdReplace:
         RELEASE_ASSERT(stubInfo.hasConstantIdentifier);
+        ASSERT(!identifier.isCell());
         return AccessCase::create(vm, owner, Replace, identifier, stubInfo.u.byIdSelf.offset, stubInfo.u.byIdSelf.baseObjectStructure.get());
 
     case CacheType::InByIdSelf:
         RELEASE_ASSERT(stubInfo.hasConstantIdentifier);
+        ASSERT(!identifier.isCell());
         return AccessCase::create(vm, owner, InHit, identifier, stubInfo.u.byIdSelf.offset, stubInfo.u.byIdSelf.baseObjectStructure.get());
 
     case CacheType::ArrayLength:
         RELEASE_ASSERT(stubInfo.hasConstantIdentifier);
+        ASSERT(!identifier.isCell());
         return AccessCase::create(vm, owner, AccessCase::ArrayLength, identifier);
 
     case CacheType::StringLength:
         RELEASE_ASSERT(stubInfo.hasConstantIdentifier);
+        ASSERT(!identifier.isCell());
         return AccessCase::create(vm, owner, AccessCase::StringLength, identifier);
 
     default:
@@ -182,11 +187,11 @@ Vector<WatchpointSet*, 2> AccessCase::commit(VM& vm)
     Vector<WatchpointSet*, 2> result;
     Structure* structure = this->structure();
 
-    if (!m_identifier->isNull()) {
+    if (m_identifier) {
         if ((structure && structure->needImpurePropertyWatchpoint())
             || m_conditionSet.needImpurePropertyWatchpoint()
             || (m_polyProtoAccessChain && m_polyProtoAccessChain->needImpurePropertyWatchpoint()))
-            result.append(vm.ensureWatchpointSetForImpureProperty(*m_identifier));
+            result.append(vm.ensureWatchpointSetForImpureProperty(m_identifier.uid()));
     }
 
     if (additionalSet())
@@ -552,7 +557,7 @@ bool AccessCase::canReplace(const AccessCase& other) const
     // Note that if A->guardedByStructureCheck() && B->guardedByStructureCheck() then
     // A->canReplace(B) == B->canReplace(A).
 
-    if (*m_identifier != *other.m_identifier)
+    if (m_identifier != other.m_identifier)
         return false;
     
     switch (type()) {
@@ -650,7 +655,7 @@ void AccessCase::dump(PrintStream& out) const
 
     out.print(comma, m_state);
 
-    out.print(comma, "ident = '", *m_identifier, "'");
+    out.print(comma, "ident = '", m_identifier, "'");
     if (isValidOffset(m_offset))
         out.print(comma, "offset = ", m_offset);
 
@@ -712,6 +717,11 @@ bool AccessCase::propagateTransitions(SlotVisitor& visitor) const
     return result;
 }
 
+void AccessCase::visitAggregate(SlotVisitor& visitor) const
+{
+    m_identifier.visitAggregate(visitor);
+}
+
 void AccessCase::generateWithGuard(
     AccessGenerationState& state, CCallHelpers::JumpList& fallThrough)
 {
@@ -730,7 +740,7 @@ void AccessCase::generateWithGuard(
     GPRReg scratchGPR = state.scratchGPR;
 
     if (requiresIdentifierNameMatch() && !stubInfo.hasConstantIdentifier) {
-        RELEASE_ASSERT(!m_identifier->isNull());
+        RELEASE_ASSERT(m_identifier);
         GPRReg propertyGPR = state.u.propertyGPR;
         // non-rope string check done inside polymorphic access.
 
@@ -1668,7 +1678,7 @@ void AccessCase::generateImpl(AccessGenerationState& state)
             // FIXME: Revisit JSGlobalObject.
             // https://bugs.webkit.org/show_bug.cgi?id=203204
             if (m_type == CustomValueGetter || m_type == CustomAccessorGetter) {
-                RELEASE_ASSERT(!m_identifier->isNull());
+                RELEASE_ASSERT(m_identifier);
                 jit.setupArguments<PropertySlot::GetValueFunc>(
                     CCallHelpers::TrustedImmPtr(codeBlock->globalObject()),
                     CCallHelpers::CellValue(baseForCustom),
index 5fa2e0c..bc2a658 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #if ENABLE(JIT)
 
+#include "CacheableIdentifier.h"
 #include "JSFunctionInlines.h"
 #include "ObjectPropertyConditionSet.h"
 #include "PolyProtoAccessChain.h"
-#include <wtf/Box.h>
 #include <wtf/CommaPrinter.h>
 
 namespace JSC {
@@ -142,14 +142,14 @@ public:
         return std::unique_ptr<AccessCaseType>(new AccessCaseType(arguments...));
     }
 
-    static std::unique_ptr<AccessCase> create(VM&, JSCell* owner, AccessType, const Identifier&, PropertyOffset = invalidOffset,
+    static std::unique_ptr<AccessCase> create(VM&, JSCell* owner, AccessType, CacheableIdentifier, PropertyOffset = invalidOffset,
         Structure* = nullptr, const ObjectPropertyConditionSet& = ObjectPropertyConditionSet(), std::unique_ptr<PolyProtoAccessChain> = nullptr);
 
     // This create method should be used for transitions.
-    static std::unique_ptr<AccessCase> create(VM&, JSCell* owner, const Identifier&, PropertyOffset, Structure* oldStructure,
+    static std::unique_ptr<AccessCase> create(VM&, JSCell* owner, CacheableIdentifier, PropertyOffset, Structure* oldStructure,
         Structure* newStructure, const ObjectPropertyConditionSet&, std::unique_ptr<PolyProtoAccessChain>);
     
-    static std::unique_ptr<AccessCase> fromStructureStubInfo(VM&, JSCell* owner, const Identifier&, StructureStubInfo&);
+    static std::unique_ptr<AccessCase> fromStructureStubInfo(VM&, JSCell* owner, CacheableIdentifier, StructureStubInfo&);
 
     AccessType type() const { return m_type; }
     State state() const { return m_state; }
@@ -235,9 +235,8 @@ public:
 
     static TypedArrayType toTypedArrayType(AccessType);
 
-    UniquedStringImpl* uid() const { return m_identifier->impl(); }
-    Box<Identifier> identifier() const { return m_identifier; }
-
+    UniquedStringImpl* uid() const { return m_identifier.uid(); }
+    CacheableIdentifier identifier() const { return m_identifier; }
 
 #if ASSERT_ENABLED
     void checkConsistency(StructureStubInfo&);
@@ -246,7 +245,7 @@ public:
 #endif
     
 protected:
-    AccessCase(VM&, JSCell* owner, AccessType, const Identifier&, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, std::unique_ptr<PolyProtoAccessChain>);
+    AccessCase(VM&, JSCell* owner, AccessType, CacheableIdentifier, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, std::unique_ptr<PolyProtoAccessChain>);
     AccessCase(AccessCase&&) = default;
     AccessCase(const AccessCase& other)
         : m_type(other.m_type)
@@ -271,6 +270,7 @@ private:
     template<typename Functor>
     void forEachDependentCell(const Functor&) const;
 
+    void visitAggregate(SlotVisitor&) const;
     bool visitWeak(VM&) const;
     bool propagateTransitions(SlotVisitor&) const;
 
@@ -313,7 +313,7 @@ private:
 
     std::unique_ptr<PolyProtoAccessChain> m_polyProtoAccessChain;
 
-    Box<Identifier> m_identifier; // We use this indirection so the concurrent compiler can concurrently ref this Box.
+    CacheableIdentifier m_identifier;
 };
 
 } // namespace JSC
index 4e4790d..78eb4f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -1101,8 +1101,6 @@ BytecodeIndex CodeBlock::bytecodeIndexForExit(BytecodeIndex exitIndex) const
 
 void CodeBlock::propagateTransitions(const ConcurrentJSLocker&, SlotVisitor& visitor)
 {
-    UNUSED_PARAM(visitor);
-
     VM& vm = *m_vm;
 
     if (jitType() == JITType::InterpreterThunk) {
@@ -1653,12 +1651,17 @@ void CodeBlock::stronglyVisitStrongReferences(const ConcurrentJSLocker& locker,
     if (auto* jitData = m_jitData.get()) {
         for (ByValInfo* byValInfo : jitData->m_byValInfos)
             visitor.append(byValInfo->cachedSymbol);
+        for (StructureStubInfo* stubInfo : jitData->m_stubInfos)
+            stubInfo->visitAggregate(visitor);
     }
 #endif
 
 #if ENABLE(DFG_JIT)
-    if (JITCode::isOptimizingJIT(jitType()))
+    if (JITCode::isOptimizingJIT(jitType())) {
+        DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
+        dfgCommon->recordedStatuses.visitAggregate(visitor);
         visitOSRExitTargets(locker, visitor);
+    }
 #endif
 }
 
index 2461689..2633362 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "GetByIdVariant.h"
 
+#include "CacheableIdentifierInlines.h"
 #include "CallLinkStatus.h"
 #include "JSCInlines.h"
 #include <wtf/ListDump.h>
@@ -33,7 +34,7 @@
 namespace JSC {
 
 GetByIdVariant::GetByIdVariant(
-    Box<Identifier> identifier,
+    CacheableIdentifier identifier,
     const StructureSet& structureSet, PropertyOffset offset,
     const ObjectPropertyConditionSet& conditionSet,
     std::unique_ptr<CallLinkStatus> callLinkStatus,
@@ -110,7 +111,7 @@ bool GetByIdVariant::attemptToMerge(const GetByIdVariant& other)
     if (!!m_identifier != !!other.m_identifier)
         return false;
 
-    if (m_identifier && (*m_identifier != *other.m_identifier))
+    if (m_identifier && (m_identifier != other.m_identifier))
         return false;
 
     if (m_offset != other.m_offset)
@@ -156,6 +157,11 @@ bool GetByIdVariant::attemptToMerge(const GetByIdVariant& other)
     return true;
 }
 
+void GetByIdVariant::visitAggregate(SlotVisitor& visitor)
+{
+    m_identifier.visitAggregate(visitor);
+}
+
 void GetByIdVariant::markIfCheap(SlotVisitor& visitor)
 {
     m_structureSet.markIfCheap(visitor);
@@ -182,7 +188,7 @@ void GetByIdVariant::dump(PrintStream& out) const
 void GetByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const
 {
     out.print("<");
-    out.print("id='", m_identifier ? m_identifier->impl() : StringImpl::empty(), "', ");
+    out.print("id='", m_identifier, "', ");
     if (!isSet()) {
         out.print("empty>");
         return;
index 83d978f..42c013d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "CacheableIdentifier.h"
 #include "CallLinkStatus.h"
 #include "ObjectPropertyConditionSet.h"
 #include "PropertyOffset.h"
@@ -44,7 +45,7 @@ class GetByIdVariant {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     GetByIdVariant(
-        Box<Identifier>,
+        CacheableIdentifier,
         const StructureSet& structureSet = StructureSet(), PropertyOffset offset = invalidOffset,
         const ObjectPropertyConditionSet& = ObjectPropertyConditionSet(),
         std::unique_ptr<CallLinkStatus> = nullptr,
@@ -76,20 +77,21 @@ public:
 
     bool attemptToMerge(const GetByIdVariant& other);
     
+    void visitAggregate(SlotVisitor&);
     void markIfCheap(SlotVisitor&);
     bool finalize(VM&);
     
     void dump(PrintStream&) const;
     void dumpInContext(PrintStream&, DumpContext*) const;
 
-    Box<Identifier> identifier() const { return m_identifier; }
+    CacheableIdentifier identifier() const { return m_identifier; }
 
     bool overlaps(const GetByIdVariant& other)
     {
         if (!!m_identifier != !!other.m_identifier)
             return true;
         if (m_identifier) {
-            if (m_identifier->impl() != other.m_identifier->impl())
+            if (m_identifier != other.m_identifier)
                 return false;
         }
         return structureSet().overlaps(other.structureSet());
@@ -107,7 +109,7 @@ private:
     JSFunction* m_intrinsicFunction;
     FunctionPtr<OperationPtrTag> m_customAccessorGetter;
     std::unique_ptr<DOMAttributeAnnotation> m_domAttribute;
-    Box<Identifier> m_identifier; // We use this indirection to allow ref/deref in the concurrent compiler.
+    CacheableIdentifier m_identifier;
 };
 
 } // namespace JSC
index ac7b7d3..53f3586 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,6 +27,7 @@
 #include "GetByStatus.h"
 
 #include "BytecodeStructs.h"
+#include "CacheableIdentifierInlines.h"
 #include "CodeBlock.h"
 #include "ComplexGetStatus.h"
 #include "GetterSetterAccessCase.h"
@@ -52,7 +53,7 @@ bool GetByStatus::appendVariant(const GetByIdVariant& variant)
     return appendICStatusVariant(m_variants, variant);
 }
 
-GetByStatus GetByStatus::computeFromLLInt(CodeBlock* profiledBlock, BytecodeIndex bytecodeIndex, TrackIdentifiers trackIdentifiers)
+GetByStatus GetByStatus::computeFromLLInt(CodeBlock* profiledBlock, BytecodeIndex bytecodeIndex)
 {
     VM& vm = profiledBlock->vm();
     
@@ -91,8 +92,6 @@ GetByStatus GetByStatus::computeFromLLInt(CodeBlock* profiledBlock, BytecodeInde
     }
     }
 
-    ASSERT_UNUSED(trackIdentifiers, trackIdentifiers == TrackIdentifiers::No); // We could make this work in the future, but nobody needs it right now.
-
     if (!structureID)
         return GetByStatus(NoInformation, false);
 
@@ -113,7 +112,7 @@ GetByStatus GetByStatus::computeFromLLInt(CodeBlock* profiledBlock, BytecodeInde
     return result;
 }
 
-GetByStatus GetByStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, BytecodeIndex bytecodeIndex, ExitFlag didExit, CallLinkStatus::ExitSiteData callExitSiteData, TrackIdentifiers trackIdentifiers, IdentifierKeepAlive& keepAlive)
+GetByStatus GetByStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, BytecodeIndex bytecodeIndex, ExitFlag didExit, CallLinkStatus::ExitSiteData callExitSiteData)
 {
     ConcurrentJSLocker locker(profiledBlock->m_lock);
 
@@ -121,7 +120,7 @@ GetByStatus GetByStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map,
 
 #if ENABLE(DFG_JIT)
     result = computeForStubInfoWithoutExitSiteFeedback(
-        locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)).stubInfo, callExitSiteData, trackIdentifiers, keepAlive);
+        locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)).stubInfo, callExitSiteData);
     
     if (didExit)
         return result.slowVersion();
@@ -129,11 +128,10 @@ GetByStatus GetByStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map,
     UNUSED_PARAM(map);
     UNUSED_PARAM(didExit);
     UNUSED_PARAM(callExitSiteData);
-    UNUSED_PARAM(keepAlive);
 #endif
 
     if (!result)
-        return computeFromLLInt(profiledBlock, bytecodeIndex, trackIdentifiers);
+        return computeFromLLInt(profiledBlock, bytecodeIndex);
     
     return result;
 }
@@ -168,7 +166,7 @@ GetByStatus::GetByStatus(const ModuleNamespaceAccessCase& accessCase)
 }
 
 GetByStatus GetByStatus::computeForStubInfoWithoutExitSiteFeedback(
-    const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CallLinkStatus::ExitSiteData callExitSiteData, TrackIdentifiers trackIdentifiers, IdentifierKeepAlive& keepAlive)
+    const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CallLinkStatus::ExitSiteData callExitSiteData)
 {
     StubInfoSummary summary = StructureStubInfo::summary(stubInfo);
     if (!isInlineable(summary))
@@ -186,12 +184,9 @@ GetByStatus GetByStatus::computeForStubInfoWithoutExitSiteFeedback(
         Structure* structure = stubInfo->u.byIdSelf.baseObjectStructure.get();
         if (structure->takesSlowPathInDFGForImpureProperty())
             return GetByStatus(JSC::slowVersion(summary), *stubInfo);
-        Box<Identifier> identifier = stubInfo->getByIdSelfIdentifier();
-        keepAlive(identifier);
-        UniquedStringImpl* uid = identifier->impl();
+        CacheableIdentifier identifier = stubInfo->getByIdSelfIdentifier();
+        UniquedStringImpl* uid = identifier.uid();
         RELEASE_ASSERT(uid);
-        if (trackIdentifiers == TrackIdentifiers::No)
-            identifier = nullptr;
         GetByIdVariant variant(WTFMove(identifier));
         unsigned attributes;
         variant.m_offset = structure->getConcurrently(uid, attributes);
@@ -212,7 +207,6 @@ GetByStatus GetByStatus::computeForStubInfoWithoutExitSiteFeedback(
             const AccessCase& access = list->at(0);
             switch (access.type()) {
             case AccessCase::ModuleNamespaceLoad:
-                keepAlive(access.identifier());
                 return GetByStatus(access.as<ModuleNamespaceAccessCase>());
             default:
                 break;
@@ -296,12 +290,7 @@ GetByStatus GetByStatus::computeForStubInfoWithoutExitSiteFeedback(
                 } }
 
                 ASSERT((AccessCase::Miss == access.type() || access.isCustom()) == (access.offset() == invalidOffset));
-                Box<Identifier> identifier;
-                if (trackIdentifiers == TrackIdentifiers::Yes) {
-                    identifier = access.identifier();
-                    keepAlive(identifier);
-                }
-                GetByIdVariant variant(identifier, StructureSet(structure), complexGetStatus.offset(),
+                GetByIdVariant variant(access.identifier(), StructureSet(structure), complexGetStatus.offset(),
                     complexGetStatus.conditionSet(), WTFMove(callLinkStatus),
                     intrinsicFunction,
                     customAccessorGetter,
@@ -336,7 +325,7 @@ GetByStatus GetByStatus::computeForStubInfoWithoutExitSiteFeedback(
 
 GetByStatus GetByStatus::computeFor(
     CodeBlock* profiledBlock, ICStatusMap& baselineMap,
-    ICStatusContextStack& icContextStack, CodeOrigin codeOrigin, TrackIdentifiers trackIdentifiers, IdentifierKeepAlive& keepAlive)
+    ICStatusContextStack& icContextStack, CodeOrigin codeOrigin)
 {
     BytecodeIndex bytecodeIndex = codeOrigin.bytecodeIndex();
     CallLinkStatus::ExitSiteData callExitSiteData = CallLinkStatus::computeExitSiteData(profiledBlock, bytecodeIndex);
@@ -351,7 +340,7 @@ GetByStatus GetByStatus::computeFor(
                 // inlined and not-inlined.
                 GetByStatus baselineResult = computeFor(
                     profiledBlock, baselineMap, bytecodeIndex, didExit,
-                    callExitSiteData, trackIdentifiers, keepAlive);
+                    callExitSiteData);
                 baselineResult.merge(result);
                 return baselineResult;
             }
@@ -365,7 +354,7 @@ GetByStatus GetByStatus::computeFor(
             {
                 ConcurrentJSLocker locker(context->optimizedCodeBlock->m_lock);
                 result = computeForStubInfoWithoutExitSiteFeedback(
-                    locker, context->optimizedCodeBlock, status.stubInfo, callExitSiteData, trackIdentifiers, keepAlive);
+                    locker, context->optimizedCodeBlock, status.stubInfo, callExitSiteData);
             }
             if (result.isSet())
                 return bless(result);
@@ -375,7 +364,7 @@ GetByStatus GetByStatus::computeFor(
             return bless(*status.getStatus);
     }
     
-    return computeFor(profiledBlock, baselineMap, bytecodeIndex, didExit, callExitSiteData, trackIdentifiers, keepAlive);
+    return computeFor(profiledBlock, baselineMap, bytecodeIndex, didExit, callExitSiteData);
 }
 
 GetByStatus GetByStatus::computeFor(const StructureSet& set, UniquedStringImpl* uid)
@@ -514,6 +503,14 @@ void GetByStatus::filter(const StructureSet& set)
         m_state = NoInformation;
 }
 
+void GetByStatus::visitAggregate(SlotVisitor& visitor)
+{
+    if (isModuleNamespace())
+        m_moduleNamespaceData->m_identifier.visitAggregate(visitor);
+    for (GetByIdVariant& variant : m_variants)
+        variant.visitAggregate(visitor);
+}
+
 void GetByStatus::markIfCheap(SlotVisitor& visitor)
 {
     for (GetByIdVariant& variant : m_variants)
@@ -535,28 +532,22 @@ bool GetByStatus::finalize(VM& vm)
     return true;
 }
 
-Box<Identifier> GetByStatus::singleIdentifier() const
+CacheableIdentifier GetByStatus::singleIdentifier() const
 {
-    if (isModuleNamespace()) {
-        Box<Identifier> result = m_moduleNamespaceData->m_identifier;
-        if (!result || result->isNull())
-            return nullptr;
-        return result;
-    }
+    if (isModuleNamespace())
+        return m_moduleNamespaceData->m_identifier;
 
     if (m_variants.isEmpty())
         return nullptr;
 
-    Box<Identifier> result = m_variants.first().identifier();
+    CacheableIdentifier result = m_variants.first().identifier();
     if (!result)
         return nullptr;
-    if (result->isNull())
-        return nullptr;
     for (size_t i = 1; i < m_variants.size(); ++i) {
-        Box<Identifier> uid = m_variants[i].identifier();
-        if (!uid)
+        CacheableIdentifier identifier = m_variants[i].identifier();
+        if (!identifier)
             return nullptr;
-        if (*uid != *result)
+        if (identifier != result)
             return nullptr;
     }
     return result;
index 6c22f03..f9dd02b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "CacheableIdentifier.h"
 #include "CallLinkStatus.h"
 #include "CodeOrigin.h"
 #include "ConcurrentJSLock.h"
@@ -66,11 +67,6 @@ public:
         ObservedSlowPathAndMakesCalls ,
     };
 
-    enum class TrackIdentifiers : uint8_t {
-        No,  // Used for get_by_id
-        Yes, // Used for get_by_val
-    };
-
     GetByStatus()
         : m_state(NoInformation)
     {
@@ -91,13 +87,7 @@ public:
     {
     }
 
-    // If we use a Box<Identifier> in the compiler thread, we need to keep the
-    // Identifier alive and only deref it in the mutator thread later. This
-    // ensures that the compiler thread doesn't race against the mutator in
-    // adjusting the Identifier's refCount.
-    using IdentifierKeepAlive = std::function<void(Box<Identifier>)>;
-
-    static GetByStatus computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& dfgContextStack, CodeOrigin, TrackIdentifiers, IdentifierKeepAlive&);
+    static GetByStatus computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& dfgContextStack, CodeOrigin);
     static GetByStatus computeFor(const StructureSet&, UniquedStringImpl*);
 
     State state() const { return m_state; }
@@ -128,6 +118,7 @@ public:
     JSModuleEnvironment* moduleEnvironment() const { return m_moduleNamespaceData->m_moduleEnvironment; }
     ScopeOffset scopeOffset() const { return m_moduleNamespaceData->m_scopeOffset; }
     
+    void visitAggregate(SlotVisitor&);
     void markIfCheap(SlotVisitor&);
     bool finalize(VM&); // Return true if this gets to live.
 
@@ -135,7 +126,7 @@ public:
 
     void dump(PrintStream&) const;
 
-    Box<Identifier> singleIdentifier() const;
+    CacheableIdentifier singleIdentifier() const;
     
 private:
     void merge(const GetByStatus&);
@@ -143,16 +134,16 @@ private:
 #if ENABLE(JIT)
     GetByStatus(const ModuleNamespaceAccessCase&);
     static GetByStatus computeForStubInfoWithoutExitSiteFeedback(
-        const ConcurrentJSLocker&, CodeBlock* profiledBlock, StructureStubInfo*, CallLinkStatus::ExitSiteData, TrackIdentifiers, IdentifierKeepAlive&);
+        const ConcurrentJSLocker&, CodeBlock* profiledBlock, StructureStubInfo*, CallLinkStatus::ExitSiteData);
 #endif
-    static GetByStatus computeFromLLInt(CodeBlock*, BytecodeIndex, TrackIdentifiers);
-    static GetByStatus computeFor(CodeBlock*, ICStatusMap&, BytecodeIndex, ExitFlag, CallLinkStatus::ExitSiteData, TrackIdentifiers, IdentifierKeepAlive&);
+    static GetByStatus computeFromLLInt(CodeBlock*, BytecodeIndex);
+    static GetByStatus computeFor(CodeBlock*, ICStatusMap&, BytecodeIndex, ExitFlag, CallLinkStatus::ExitSiteData);
 
     struct ModuleNamespaceData {
         JSModuleNamespaceObject* m_moduleNamespaceObject { nullptr };
         JSModuleEnvironment* m_moduleEnvironment { nullptr };
         ScopeOffset m_scopeOffset { };
-        Box<Identifier> m_identifier;
+        CacheableIdentifier m_identifier;
     };
 
     Vector<GetByIdVariant, 1> m_variants;
index 0548d54..97bdfde 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -42,15 +42,14 @@ namespace GetterSetterAccessCaseInternal {
 static constexpr bool verbose = false;
 }
 
-GetterSetterAccessCase::GetterSetterAccessCase(VM& vm, JSCell* owner, AccessType accessType, const Identifier& identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet, JSObject* customSlotBase, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
+GetterSetterAccessCase::GetterSetterAccessCase(VM& vm, JSCell* owner, AccessType accessType, CacheableIdentifier identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet, JSObject* customSlotBase, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
     : Base(vm, owner, accessType, identifier, offset, structure, conditionSet, viaProxy, additionalSet, WTFMove(prototypeAccessChain))
 {
     m_customSlotBase.setMayBeNull(vm, owner, customSlotBase);
 }
 
-
 std::unique_ptr<AccessCase> GetterSetterAccessCase::create(
-    VM& vm, JSCell* owner, AccessType type, const Identifier& identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet,
+    VM& vm, JSCell* owner, AccessType type, CacheableIdentifier identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet,
     bool viaProxy, WatchpointSet* additionalSet, FunctionPtr<OperationPtrTag> customGetter, JSObject* customSlotBase,
     Optional<DOMAttributeAnnotation> domAttribute, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
 {
@@ -69,7 +68,7 @@ std::unique_ptr<AccessCase> GetterSetterAccessCase::create(
     return result;
 }
 
-std::unique_ptr<AccessCase> GetterSetterAccessCase::create(VM& vm, JSCell* owner, AccessType type, Structure* structure, const Identifier& identifier, PropertyOffset offset,
+std::unique_ptr<AccessCase> GetterSetterAccessCase::create(VM& vm, JSCell* owner, AccessType type, Structure* structure, CacheableIdentifier identifier, PropertyOffset offset,
     const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain, FunctionPtr<OperationPtrTag> customSetter,
     JSObject* customSlotBase)
 {
index 26e863b..26d25cf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -54,11 +54,11 @@ public:
     void emitDOMJITGetter(AccessGenerationState&, const DOMJIT::GetterSetter*, GPRReg baseForGetGPR);
 
     static std::unique_ptr<AccessCase> create(
-        VM&, JSCell* owner, AccessType, const Identifier&, PropertyOffset, Structure*,
+        VM&, JSCell* owner, AccessType, CacheableIdentifier, PropertyOffset, Structure*,
         const ObjectPropertyConditionSet&, bool viaProxy, WatchpointSet* additionalSet, FunctionPtr<OperationPtrTag> customGetter,
         JSObject* customSlotBase, Optional<DOMAttributeAnnotation>, std::unique_ptr<PolyProtoAccessChain>);
 
-    static std::unique_ptr<AccessCase> create(VM&, JSCell* owner, AccessType, Structure*, const Identifier&, PropertyOffset,
+    static std::unique_ptr<AccessCase> create(VM&, JSCell* owner, AccessType, Structure*, CacheableIdentifier, PropertyOffset,
         const ObjectPropertyConditionSet&, std::unique_ptr<PolyProtoAccessChain>,
         FunctionPtr<OperationPtrTag> customSetter = nullptr, JSObject* customSlotBase = nullptr);
 
@@ -70,7 +70,7 @@ public:
     FunctionPtr<OperationPtrTag> customAccessor() const { return m_customAccessor; }
 
 private:
-    GetterSetterAccessCase(VM&, JSCell*, AccessType, const Identifier&, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, bool viaProxy, WatchpointSet* additionalSet, JSObject* customSlotBase, std::unique_ptr<PolyProtoAccessChain>);
+    GetterSetterAccessCase(VM&, JSCell*, AccessType, CacheableIdentifier, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, bool viaProxy, WatchpointSet* additionalSet, JSObject* customSlotBase, std::unique_ptr<PolyProtoAccessChain>);
 
     GetterSetterAccessCase(const GetterSetterAccessCase&);
 
index 0979127..fdfbb0d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -59,7 +59,7 @@ InstanceOfAccessCase::~InstanceOfAccessCase()
 InstanceOfAccessCase::InstanceOfAccessCase(
     VM& vm, JSCell* owner, AccessType accessType, Structure* structure,
     const ObjectPropertyConditionSet& conditionSet, JSObject* prototype)
-    : Base(vm, owner, accessType, Identifier(), invalidOffset, structure, conditionSet, nullptr)
+    : Base(vm, owner, accessType, nullptr, invalidOffset, structure, conditionSet, nullptr)
     , m_prototype(vm, owner, prototype)
 {
 }
index d689323..133f4fb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 namespace JSC {
 
-IntrinsicGetterAccessCase::IntrinsicGetterAccessCase(VM& vm, JSCell* owner, const Identifier& identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, JSFunction* intrinsicFunction, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
+IntrinsicGetterAccessCase::IntrinsicGetterAccessCase(VM& vm, JSCell* owner, CacheableIdentifier identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, JSFunction* intrinsicFunction, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
     : Base(vm, owner, IntrinsicGetter, identifier, offset, structure, conditionSet, WTFMove(prototypeAccessChain))
 {
     m_intrinsicFunction.set(vm, owner, intrinsicFunction);
 }
 
-std::unique_ptr<AccessCase> IntrinsicGetterAccessCase::create(VM& vm, JSCell* owner, const Identifier& identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, JSFunction* intrinsicFunction, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
+std::unique_ptr<AccessCase> IntrinsicGetterAccessCase::create(VM& vm, JSCell* owner, CacheableIdentifier identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, JSFunction* intrinsicFunction, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
 {
     return std::unique_ptr<AccessCase>(new IntrinsicGetterAccessCase(vm, owner, identifier, offset, structure, conditionSet, intrinsicFunction, WTFMove(prototypeAccessChain)));
 }
index 377d311..696dab4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -42,14 +42,14 @@ public:
     static bool canEmitIntrinsicGetter(JSFunction*, Structure*);
     void emitIntrinsicGetter(AccessGenerationState&);
 
-    static std::unique_ptr<AccessCase> create(VM&, JSCell*, const Identifier&, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, JSFunction* intrinsicFunction, std::unique_ptr<PolyProtoAccessChain>);
+    static std::unique_ptr<AccessCase> create(VM&, JSCell*, CacheableIdentifier, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, JSFunction* intrinsicFunction, std::unique_ptr<PolyProtoAccessChain>);
 
     std::unique_ptr<AccessCase> clone() const override;
 
     ~IntrinsicGetterAccessCase();
 
 private:
-    IntrinsicGetterAccessCase(VM&, JSCell*, const Identifier&, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, JSFunction* intrinsicFunction, std::unique_ptr<PolyProtoAccessChain>);
+    IntrinsicGetterAccessCase(VM&, JSCell*, CacheableIdentifier, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, JSFunction* intrinsicFunction, std::unique_ptr<PolyProtoAccessChain>);
 
     WriteBarrier<JSFunction> m_intrinsicFunction;
 };
index f273fcb..50ab68b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,7 +38,7 @@
 
 namespace JSC {
 
-ModuleNamespaceAccessCase::ModuleNamespaceAccessCase(VM& vm, JSCell* owner, const Identifier& identifier, JSModuleNamespaceObject* moduleNamespaceObject, JSModuleEnvironment* moduleEnvironment, ScopeOffset scopeOffset)
+ModuleNamespaceAccessCase::ModuleNamespaceAccessCase(VM& vm, JSCell* owner, CacheableIdentifier identifier, JSModuleNamespaceObject* moduleNamespaceObject, JSModuleEnvironment* moduleEnvironment, ScopeOffset scopeOffset)
     : Base(vm, owner, ModuleNamespaceLoad, identifier, invalidOffset, nullptr, ObjectPropertyConditionSet(), nullptr)
     , m_scopeOffset(scopeOffset)
 {
@@ -45,7 +46,7 @@ ModuleNamespaceAccessCase::ModuleNamespaceAccessCase(VM& vm, JSCell* owner, cons
     m_moduleEnvironment.set(vm, owner, moduleEnvironment);
 }
 
-std::unique_ptr<AccessCase> ModuleNamespaceAccessCase::create(VM& vm, JSCell* owner, const Identifier& identifier, JSModuleNamespaceObject* moduleNamespaceObject, JSModuleEnvironment* moduleEnvironment, ScopeOffset scopeOffset)
+std::unique_ptr<AccessCase> ModuleNamespaceAccessCase::create(VM& vm, JSCell* owner, CacheableIdentifier identifier, JSModuleNamespaceObject* moduleNamespaceObject, JSModuleEnvironment* moduleEnvironment, ScopeOffset scopeOffset)
 {
     return std::unique_ptr<AccessCase>(new ModuleNamespaceAccessCase(vm, owner, identifier, moduleNamespaceObject, moduleEnvironment, scopeOffset));
 }
index 79566d9..5ecc4b3 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -43,7 +44,7 @@ public:
     JSModuleEnvironment* moduleEnvironment() const { return m_moduleEnvironment.get(); }
     ScopeOffset scopeOffset() const { return m_scopeOffset; }
 
-    static std::unique_ptr<AccessCase> create(VM&, JSCell* owner, const Identifier&, JSModuleNamespaceObject*, JSModuleEnvironment*, ScopeOffset);
+    static std::unique_ptr<AccessCase> create(VM&, JSCell* owner, CacheableIdentifier, JSModuleNamespaceObject*, JSModuleEnvironment*, ScopeOffset);
 
     std::unique_ptr<AccessCase> clone() const override;
 
@@ -52,7 +53,7 @@ public:
     ~ModuleNamespaceAccessCase();
 
 private:
-    ModuleNamespaceAccessCase(VM&, JSCell* owner, const Identifier&, JSModuleNamespaceObject*, JSModuleEnvironment*, ScopeOffset);
+    ModuleNamespaceAccessCase(VM&, JSCell* owner, CacheableIdentifier, JSModuleNamespaceObject*, JSModuleEnvironment*, ScopeOffset);
 
     WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
     WriteBarrier<JSModuleEnvironment> m_moduleEnvironment;
index cb57809..93bf10c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,6 +30,7 @@
 
 #include "BinarySwitch.h"
 #include "CCallHelpers.h"
+#include "CacheableIdentifierInlines.h"
 #include "CodeBlock.h"
 #include "FullCodeOrigin.h"
 #include "Heap.h"
@@ -352,6 +353,12 @@ bool PolymorphicAccess::propagateTransitions(SlotVisitor& visitor) const
     return result;
 }
 
+void PolymorphicAccess::visitAggregate(SlotVisitor& visitor)
+{
+    for (unsigned i = 0; i < size(); ++i)
+        at(i).visitAggregate(visitor);
+}
+
 void PolymorphicAccess::dump(PrintStream& out) const
 {
     out.print(RawPointer(this), ":[");
@@ -472,7 +479,6 @@ AccessGenerationResult PolymorphicAccess::regenerate(
     state.preservedReusedRegisterState =
         allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
 
-    
     bool generatedFinalCode = false;
 
     // If the resulting set of cases is so big that we would stop caching and this is InstanceOf,
@@ -481,7 +487,7 @@ AccessGenerationResult PolymorphicAccess::regenerate(
         && stubInfo.accessType == AccessType::InstanceOf) {
         while (!cases.isEmpty())
             m_list.append(cases.takeLast());
-        cases.append(AccessCase::create(vm, codeBlock, AccessCase::InstanceOfGeneric, Identifier()));
+        cases.append(AccessCase::create(vm, codeBlock, AccessCase::InstanceOfGeneric, nullptr));
         generatedFinalCode = true;
     }
 
index 7c4f832..264391a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -151,6 +151,8 @@ public:
     const AccessCase& at(unsigned i) const { return *m_list[i]; }
     const AccessCase& operator[](unsigned i) const { return *m_list[i]; }
 
+    void visitAggregate(SlotVisitor&);
+
     // If this returns false then we are requesting a reset of the owning StructureStubInfo.
     bool visitWeak(VM&) const;
     
index 136a9ff..499c4e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,7 +30,7 @@
 
 namespace JSC {
 
-ProxyableAccessCase::ProxyableAccessCase(VM& vm, JSCell* owner, AccessType accessType, const Identifier& identifier, PropertyOffset offset, Structure* structure,
+ProxyableAccessCase::ProxyableAccessCase(VM& vm, JSCell* owner, AccessType accessType, CacheableIdentifier identifier, PropertyOffset offset, Structure* structure,
     const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
     : Base(vm, owner, accessType, identifier, offset, structure, conditionSet, WTFMove(prototypeAccessChain))
     , m_additionalSet(additionalSet)
@@ -38,7 +38,7 @@ ProxyableAccessCase::ProxyableAccessCase(VM& vm, JSCell* owner, AccessType acces
     m_viaProxy = viaProxy;
 }
 
-std::unique_ptr<AccessCase> ProxyableAccessCase::create(VM& vm, JSCell* owner, AccessType type, const Identifier& identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
+std::unique_ptr<AccessCase> ProxyableAccessCase::create(VM& vm, JSCell* owner, AccessType type, CacheableIdentifier identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
 {
     ASSERT(type == Load || type == Miss || type == GetGetter);
     return std::unique_ptr<AccessCase>(new ProxyableAccessCase(vm, owner, type, identifier, offset, structure, conditionSet, viaProxy, additionalSet, WTFMove(prototypeAccessChain)));
index ec5184e..3e73761 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,7 +37,7 @@ public:
 
     WatchpointSet* additionalSet() const override { return m_additionalSet.get(); }
 
-    static std::unique_ptr<AccessCase> create(VM&, JSCell*, AccessType, const Identifier&, PropertyOffset, Structure*, const ObjectPropertyConditionSet& = ObjectPropertyConditionSet(),
+    static std::unique_ptr<AccessCase> create(VM&, JSCell*, AccessType, CacheableIdentifier, PropertyOffset, Structure*, const ObjectPropertyConditionSet& = ObjectPropertyConditionSet(),
         bool viaProxy = false, WatchpointSet* additionalSet = nullptr, std::unique_ptr<PolyProtoAccessChain> = nullptr);
 
     void dumpImpl(PrintStream&, CommaPrinter&) const override;
@@ -46,7 +46,7 @@ public:
     ~ProxyableAccessCase();
 
 protected:
-    ProxyableAccessCase(VM&, JSCell*, AccessType, const Identifier&, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, bool viaProxy, WatchpointSet* additionalSet, std::unique_ptr<PolyProtoAccessChain>);
+    ProxyableAccessCase(VM&, JSCell*, AccessType, CacheableIdentifier, PropertyOffset, Structure*, const ObjectPropertyConditionSet&, bool viaProxy, WatchpointSet* additionalSet, std::unique_ptr<PolyProtoAccessChain>);
 
 private:
     RefPtr<WatchpointSet> m_additionalSet;
index 653eca1..c9484b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -75,6 +75,12 @@ InByIdStatus* RecordedStatuses::addInByIdStatus(const CodeOrigin& codeOrigin, co
     return result;
 }
 
+void RecordedStatuses::visitAggregate(SlotVisitor& slotVisitor)
+{
+    for (auto& pair : gets)
+        pair.second->visitAggregate(slotVisitor);
+}
+
 void RecordedStatuses::markIfCheap(SlotVisitor& slotVisitor)
 {
     for (auto& pair : gets)
index 7d33c8b..b355e9b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -48,7 +48,8 @@ struct RecordedStatuses {
     PutByIdStatus* addPutByIdStatus(const CodeOrigin&, const PutByIdStatus&);
     InByIdStatus* addInByIdStatus(const CodeOrigin&, const InByIdStatus&);
     
-    void markIfCheap(SlotVisitor& slotVisitor);
+    void visitAggregate(SlotVisitor&);
+    void markIfCheap(SlotVisitor&);
     
     void finalizeWithoutDeleting(VM&);
     void finalize(VM&);
index f648b53..794b279 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "StructureStubInfo.h"
 
+#include "CacheableIdentifierInlines.h"
 #include "JSObject.h"
 #include "JSCInlines.h"
 #include "PolymorphicAccess.h"
@@ -62,11 +63,12 @@ StructureStubInfo::~StructureStubInfo()
 {
 }
 
-void StructureStubInfo::initGetByIdSelf(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset, const Identifier& identifier)
+void StructureStubInfo::initGetByIdSelf(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset, CacheableIdentifier identifier)
 {
     ASSERT(hasConstantIdentifier);
     setCacheType(CacheType::GetByIdSelf);
-    m_getByIdSelfIdentifier = Box<Identifier>::create(identifier);
+    m_getByIdSelfIdentifier = identifier;
+    codeBlock->vm().heap.writeBarrier(codeBlock);
     
     u.byIdSelf.baseObjectStructure.set(
         codeBlock->vm(), codeBlock, baseObjectStructure);
@@ -138,7 +140,7 @@ void StructureStubInfo::aboutToDie()
 }
 
 AccessGenerationResult StructureStubInfo::addAccessCase(
-    const GCSafeConcurrentJSLocker& locker, CodeBlock* codeBlock, const Identifier& ident, std::unique_ptr<AccessCase> accessCase)
+    const GCSafeConcurrentJSLocker& locker, CodeBlock* codeBlock, CacheableIdentifier ident, std::unique_ptr<AccessCase> accessCase)
 {
     checkConsistency();
 
@@ -194,6 +196,7 @@ AccessGenerationResult StructureStubInfo::addAccessCase(
             u.stub = access.release();
         }
         
+        ASSERT(m_cacheType == CacheType::Stub);
         RELEASE_ASSERT(!result.generatedSomeCode());
         
         // If we didn't buffer any cases then bail. If this made no changes then we'll just try again
@@ -279,6 +282,27 @@ void StructureStubInfo::reset(CodeBlock* codeBlock)
     setCacheType(CacheType::Unset);
 }
 
+void StructureStubInfo::visitAggregate(SlotVisitor& visitor)
+{
+    switch (m_cacheType) {
+    case CacheType::Unset:
+    case CacheType::ArrayLength:
+    case CacheType::StringLength:
+    case CacheType::PutByIdReplace:
+    case CacheType::InByIdSelf:
+        return;
+    case CacheType::GetByIdSelf:
+        m_getByIdSelfIdentifier.visitAggregate(visitor);
+        return;
+    case CacheType::Stub:
+        u.stub->visitAggregate(visitor);
+        return;
+    }
+    
+    RELEASE_ASSERT_NOT_REACHED();
+    return;
+}
+
 void StructureStubInfo::visitWeakReferences(CodeBlock* codeBlock)
 {
     VM& vm = codeBlock->vm();
index f4e51cf..62cea08 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "CacheableIdentifier.h"
 #include "CodeBlock.h"
 #include "CodeOrigin.h"
 #include "Instruction.h"
@@ -74,19 +75,21 @@ public:
     StructureStubInfo(AccessType);
     ~StructureStubInfo();
 
-    void initGetByIdSelf(CodeBlock*, Structure* baseObjectStructure, PropertyOffset, const Identifier&);
+    void initGetByIdSelf(CodeBlock*, Structure* baseObjectStructure, PropertyOffset, CacheableIdentifier);
     void initArrayLength();
     void initStringLength();
     void initPutByIdReplace(CodeBlock*, Structure* baseObjectStructure, PropertyOffset);
     void initInByIdSelf(CodeBlock*, Structure* baseObjectStructure, PropertyOffset);
 
-    AccessGenerationResult addAccessCase(const GCSafeConcurrentJSLocker&, CodeBlock*, const Identifier&, std::unique_ptr<AccessCase>);
+    AccessGenerationResult addAccessCase(const GCSafeConcurrentJSLocker&, CodeBlock*, CacheableIdentifier, std::unique_ptr<AccessCase>);
 
     void reset(CodeBlock*);
 
     void deref();
     void aboutToDie();
 
+    void visitAggregate(SlotVisitor&);
+
     // Check if the stub has weak references that are dead. If it does, then it resets itself,
     // either entirely or just enough to ensure that those dead pointers don't get used anymore.
     void visitWeakReferences(CodeBlock*);
@@ -171,7 +174,7 @@ public:
 
     CodeOrigin codeOrigin;
 private:
-    Box<Identifier> m_getByIdSelfIdentifier;
+    CacheableIdentifier m_getByIdSelfIdentifier;
 public:
 
     union {
@@ -182,7 +185,7 @@ public:
         PolymorphicAccess* stub;
     } u;
 
-    Box<Identifier> getByIdSelfIdentifier()
+    CacheableIdentifier getByIdSelfIdentifier()
     {
         RELEASE_ASSERT(m_cacheType == CacheType::GetByIdSelf);
         return m_getByIdSelfIdentifier;
index 7215965..93be0ed 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,6 +34,7 @@
 #include "BuiltinNames.h"
 #include "BytecodeGenerator.h"
 #include "BytecodeUseDef.h"
+#include "CacheableIdentifierInlines.h"
 #include "CallLinkStatus.h"
 #include "CodeBlock.h"
 #include "CodeBlockWithJITType.h"
@@ -4831,13 +4832,10 @@ void ByteCodeParser::parseGetById(const Instruction* currentInstruction)
     else if (Op::opcodeID == op_get_by_id_direct)
         type = AccessType::GetByIdDirect;
     
-    GetByStatus::IdentifierKeepAlive keepAlive = [&] (Box<Identifier> identifier) {
-        m_graph.m_plan.keepAliveIdentifier(WTFMove(identifier));
-    };
     GetByStatus getByStatus = GetByStatus::computeFor(
         m_inlineStackTop->m_profiledBlock,
         m_inlineStackTop->m_baselineMap, m_icContextStack,
-        currentCodeOrigin(), GetByStatus::TrackIdentifiers::No, keepAlive);
+        currentCodeOrigin());
 
     handleGetById(
         bytecode.m_dst, prediction, base, identifierNumber, getByStatus, type, opcodeLength);
@@ -5738,10 +5736,7 @@ void ByteCodeParser::parseBlock(unsigned limit)
             Node* base = get(bytecode.m_base);
             Node* property = get(bytecode.m_property);
             bool shouldCompileAsGetById = false;
-            GetByStatus::IdentifierKeepAlive keepAlive = [&] (Box<Identifier> identifier) {
-                m_graph.m_plan.keepAliveIdentifier(WTFMove(identifier));
-            };
-            GetByStatus getByStatus = GetByStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_inlineStackTop->m_baselineMap, m_icContextStack, currentCodeOrigin(), GetByStatus::TrackIdentifiers::Yes, keepAlive);
+            GetByStatus getByStatus = GetByStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_inlineStackTop->m_baselineMap, m_icContextStack, currentCodeOrigin());
 
             unsigned identifierNumber = 0;
 
@@ -5752,10 +5747,18 @@ void ByteCodeParser::parseBlock(unsigned limit)
                 // FIXME: In the future, we should be able to do something like MultiGetByOffset in a multi identifier mode.
                 // That way, we could both switch on multiple structures and multiple identifiers (or int 32 properties).
                 // https://bugs.webkit.org/show_bug.cgi?id=204216
-                if (Box<Identifier> impl = getByStatus.singleIdentifier()) {
-                    identifierNumber = m_graph.identifiers().ensure(impl);
+                if (CacheableIdentifier identifier = getByStatus.singleIdentifier()) {
+                    UniquedStringImpl* uid = identifier.uid();
+                    identifierNumber = m_graph.identifiers().ensure(identifier.uid());
+                    if (identifier.isCell()) {
+                        FrozenValue* frozen = m_graph.freezeStrong(identifier.cell());
+                        if (identifier.isSymbolCell())
+                            addToGraph(CheckCell, OpInfo(frozen), property);
+                        else
+                            addToGraph(CheckIdent, OpInfo(uid), property);
+                    } else
+                        addToGraph(CheckIdent, OpInfo(uid), property);
                     shouldCompileAsGetById = true;
-                    addToGraph(CheckIdent, OpInfo(impl->impl()), property);
                 }
             }
 
index 5cd9319..0b8f884 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -55,7 +55,7 @@ unsigned DesiredIdentifiers::numberOfIdentifiers()
     return m_codeBlock->numberOfIdentifiers() + m_addedIdentifiers.size();
 }
 
-void DesiredIdentifiers::processCodeBlockIdentifiersIfNeeded()
+unsigned DesiredIdentifiers::ensure(UniquedStringImpl* rep)
 {
     if (!m_didProcessIdentifiers) {
         // Do this now instead of the constructor so that we don't pay the price on the main
@@ -64,11 +64,6 @@ void DesiredIdentifiers::processCodeBlockIdentifiersIfNeeded()
             m_identifierNumberForName.add(m_codeBlock->identifier(index).impl(), index);
         m_didProcessIdentifiers = true;
     }
-}
-
-unsigned DesiredIdentifiers::ensure(UniquedStringImpl* rep)
-{
-    processCodeBlockIdentifiersIfNeeded();
 
     auto addResult = m_identifierNumberForName.add(rep, numberOfIdentifiers());
     unsigned result = addResult.iterator->value;
@@ -79,45 +74,20 @@ unsigned DesiredIdentifiers::ensure(UniquedStringImpl* rep)
     return result;
 }
 
-unsigned DesiredIdentifiers::ensure(Box<Identifier> rep)
-{
-    processCodeBlockIdentifiersIfNeeded();
-
-    UniquedStringImpl* impl = rep->impl();
-    auto addResult = m_identifierNumberForName.add(impl, numberOfIdentifiers());
-    unsigned result = addResult.iterator->value;
-    if (addResult.isNewEntry) {
-        m_addedIdentifiers.append(WTFMove(rep));
-        ASSERT(at(result) == impl);
-    }
-    return result;
-}
-
 UniquedStringImpl* DesiredIdentifiers::at(unsigned index) const
 {
     UniquedStringImpl* result;
     if (index < m_codeBlock->numberOfIdentifiers())
         result = m_codeBlock->identifier(index).impl();
-    else {
-        const auto& variant = m_addedIdentifiers[index - m_codeBlock->numberOfIdentifiers()];
-        if (WTF::holds_alternative<UniquedStringImpl*>(variant))
-            result = WTF::get<UniquedStringImpl*>(variant);
-        else
-            result = WTF::get<Box<Identifier>>(variant)->impl();
-    }
+    else
+        result = m_addedIdentifiers[index - m_codeBlock->numberOfIdentifiers()];
     ASSERT(result->hasAtLeastOneRef());
     return result;
 }
 
 void DesiredIdentifiers::reallyAdd(VM& vm, CommonData* commonData)
 {
-    for (const auto& variant : m_addedIdentifiers) {
-        UniquedStringImpl* rep;
-        if (WTF::holds_alternative<UniquedStringImpl*>(variant))
-            rep = WTF::get<UniquedStringImpl*>(variant);
-        else
-            rep = WTF::get<Box<Identifier>>(variant)->impl();
-
+    for (auto rep : m_addedIdentifiers) {
         ASSERT(rep->hasAtLeastOneRef());
         Identifier uid = Identifier::fromUid(vm, rep);
         {
index f7c98a4..9bd865e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,7 +29,6 @@
 
 #include "Identifier.h"
 #include <wtf/HashMap.h>
-#include <wtf/Variant.h>
 #include <wtf/text/UniquedStringImpl.h>
 
 namespace JSC {
@@ -49,7 +48,6 @@ public:
     
     unsigned numberOfIdentifiers();
     unsigned ensure(UniquedStringImpl*);
-    unsigned ensure(Box<Identifier>);
     
     UniquedStringImpl* at(unsigned index) const;
     
@@ -61,7 +59,7 @@ private:
     void processCodeBlockIdentifiersIfNeeded();
 
     CodeBlock* m_codeBlock;
-    Vector<Variant<UniquedStringImpl*, Box<Identifier>>> m_addedIdentifiers;
+    Vector<UniquedStringImpl*> m_addedIdentifiers;
     HashMap<UniquedStringImpl*, unsigned> m_identifierNumberForName;
     bool m_didProcessIdentifiers;
 };
index 8e467ee..3582695 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -81,22 +81,28 @@ bool JITFinalizer::finalizeFunction()
 
 void JITFinalizer::finalizeCommon()
 {
+    CodeBlock* codeBlock = m_plan.codeBlock();
+
     // Some JIT finalizers may have added more constants. Shrink-to-fit those things now.
     {
-        ConcurrentJSLocker locker(m_plan.codeBlock()->m_lock);
-        m_plan.codeBlock()->constants().shrinkToFit();
-        m_plan.codeBlock()->constantsSourceCodeRepresentation().shrinkToFit();
+        ConcurrentJSLocker locker(codeBlock->m_lock);
+        codeBlock->constants().shrinkToFit();
+        codeBlock->constantsSourceCodeRepresentation().shrinkToFit();
     }
 
 #if ENABLE(FTL_JIT)
-    m_jitCode->optimizeAfterWarmUp(m_plan.codeBlock());
+    m_jitCode->optimizeAfterWarmUp(codeBlock);
 #endif // ENABLE(FTL_JIT)
 
     if (UNLIKELY(m_plan.compilation()))
-        m_plan.vm()->m_perBytecodeProfiler->addCompilation(m_plan.codeBlock(), *m_plan.compilation());
+        m_plan.vm()->m_perBytecodeProfiler->addCompilation(codeBlock, *m_plan.compilation());
 
     if (!m_plan.willTryToTierUp())
-        m_plan.codeBlock()->baselineVersion()->m_didFailFTLCompilation = true;
+        codeBlock->baselineVersion()->m_didFailFTLCompilation = true;
+
+    // The codeBlock is now responsible for keeping many things alive (e.g. frozen values)
+    // that were previously kept alive by the plan.
+    m_plan.vm()->heap.writeBarrier(codeBlock);
 }
 
 } } // namespace JSC::DFG
index 3aece84..d800079 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -79,7 +79,6 @@
 #include "ProfilerDatabase.h"
 #include "TrackedReferences.h"
 #include "VMInlines.h"
-#include <wtf/Threading.h>
 
 #if ENABLE(FTL_JIT)
 #include "FTLCapabilities.h"
@@ -155,7 +154,6 @@ Plan::Plan(CodeBlock* passedCodeBlock, CodeBlock* profiledDFGCodeBlock,
 
 Plan::~Plan()
 {
-    RELEASE_ASSERT(unnukedVM()->currentThreadIsHoldingAPILock());
 }
 
 bool Plan::computeCompileTimes() const
@@ -657,6 +655,7 @@ void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor)
             visitor.appendUnbarriered(value.value());
     }
 
+    m_recordedStatuses.visitAggregate(visitor);
     m_recordedStatuses.markIfCheap(visitor);
 
     visitor.appendUnbarriered(m_codeBlock);
@@ -696,22 +695,6 @@ bool Plan::isKnownToBeLiveDuringGC()
 void Plan::cancel()
 {
     RELEASE_ASSERT(m_stage != Cancelled);
-
-    // When we cancel a plan, there's a chance that the compiler thread may have
-    // already ref'ed it and is working on it. This results in a race where the
-    // compiler thread may hold the last reference to the plan. We require that
-    // the plan is only destructed on the mutator thread because we piggy back
-    // on the plan to ensure certain other objects are only destructed on the
-    // mutator thread. For example, see Plan::m_identifiersKeptAliveForCleanUp.
-    //
-    // To ensure that the plan is destructed on the mutator and not the compiler
-    // thread, the compiler thread will enqueue any cancelled plan it sees in
-    // the worklist's m_cancelledPlansPendingDestruction. The mutator will later
-    // delete the cancelled plans in m_cancelledPlansPendingDestruction.
-    // However, a mutator should only delete cancelled plans that belong to its
-    // VM. Hence, a cancelled plan needs to keep its m_vm pointer to let the
-    // mutator know which VM it belongs to.
-    // Ref: See Worklist::deleteCancelledPlansForVM().
     ASSERT(m_vm);
 
     // Nuke the VM pointer so that pointer comparisons against it will fail.
index 8233730..cefb4db 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -38,7 +38,6 @@
 #include "Operands.h"
 #include "ProfilerCompilation.h"
 #include "RecordedStatuses.h"
-#include <wtf/Box.h>
 #include <wtf/HashMap.h>
 #include <wtf/ThreadSafeRefCounted.h>
 
@@ -117,12 +116,6 @@ public:
     DeferredCompilationCallback* callback() const { return m_callback.get(); }
     void setCallback(Ref<DeferredCompilationCallback>&& callback) { m_callback = WTFMove(callback); }
 
-    void keepAliveIdentifier(Box<Identifier> identifier)
-    {
-        if (identifier)
-            m_identifiersKeptAliveForCleanUp.append(WTFMove(identifier));
-    }
-
 private:
     bool computeCompileTimes() const;
     bool reportCompileTimes() const;
@@ -181,7 +174,6 @@ private:
     Stage m_stage;
 
     RefPtr<DeferredCompilationCallback> m_callback;
-    Vector<Box<Identifier>, 16> m_identifiersKeptAliveForCleanUp;
 
     MonotonicTime m_timeBeforeFTL;
 };
index f2a2de5..e14eb2a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -100,10 +100,8 @@ protected:
         LockHolder locker(m_data.m_rightToRun);
         {
             LockHolder locker(*m_worklist.m_lock);
-            if (m_plan->stage() == Plan::Cancelled) {
-                m_worklist.m_cancelledPlansPendingDestruction.append(WTFMove(m_plan));
+            if (m_plan->stage() == Plan::Cancelled)
                 return WorkResult::Continue;
-            }
             m_plan->notifyCompiling();
         }
         
@@ -125,10 +123,8 @@ protected:
         
         {
             LockHolder locker(*m_worklist.m_lock);
-            if (m_plan->stage() == Plan::Cancelled) {
-                m_worklist.m_cancelledPlansPendingDestruction.append(WTFMove(m_plan));
+            if (m_plan->stage() == Plan::Cancelled)
                 return WorkResult::Continue;
-            }
             
             m_plan->notifyReady();
             
@@ -304,47 +300,10 @@ void Worklist::waitUntilAllPlansForVMAreReady(VM& vm)
     }
 }
 
-void Worklist::deleteCancelledPlansForVM(LockHolder&, VM& vm)
-{
-    RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
-    HashSet<RefPtr<Plan>> removedPlans;
-
-    // The following scenario can occur:
-    // 1. The DFG thread started compiling a plan.
-    // 2. The GC thread cancels the plan, and adds it to m_cancelledPlansPendingDestruction.
-    // 3. The DFG thread finishes compiling, and discovers that the thread is cancelled.
-    //    To avoid destructing the plan in the DFG thread, it adds it to
-    //    m_cancelledPlansPendingDestruction.
-    // 4. The above occurs before the mutator runs deleteCancelledPlansForVM().
-    //
-    // Hence, the same cancelled plan can appear in m_cancelledPlansPendingDestruction
-    // more than once. This is why we need to filter the cancelled plans through
-    // the removedPlans HashSet before we do the refCount check below.
-
-    for (size_t i = 0; i < m_cancelledPlansPendingDestruction.size(); ++i) {
-        RefPtr<Plan> plan = m_cancelledPlansPendingDestruction[i];
-        if (plan->unnukedVM() != &vm)
-            continue;
-        m_cancelledPlansPendingDestruction[i--] = m_cancelledPlansPendingDestruction.last();
-        m_cancelledPlansPendingDestruction.removeLast();
-        removedPlans.add(WTFMove(plan));
-    }
-
-    while (!removedPlans.isEmpty()) {
-        RefPtr<Plan> plan = removedPlans.takeAny();
-        ASSERT(plan->stage() == Plan::Cancelled);
-        if (plan->refCount() > 1)
-            m_cancelledPlansPendingDestruction.append(WTFMove(plan));
-    }
-}
-
 void Worklist::removeAllReadyPlansForVM(VM& vm, Vector<RefPtr<Plan>, 8>& myReadyPlans)
 {
     DeferGC deferGC(vm.heap);
     LockHolder locker(*m_lock);
-    ASSERT(vm.currentThreadIsHoldingAPILock());
-
-    deleteCancelledPlansForVM(locker, vm);
     for (size_t i = 0; i < m_readyPlans.size(); ++i) {
         RefPtr<Plan> plan = m_readyPlans[i];
         if (plan->vm() != &vm)
@@ -447,8 +406,6 @@ void Worklist::removeDeadPlans(VM& vm)
     {
         LockHolder locker(*m_lock);
         HashSet<CompilationKey> deadPlanKeys;
-        bool isInMutator = vm.currentThreadIsHoldingAPILock();
-
         for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
             Plan* plan = iter->value.get();
             if (plan->vm() != &vm)
@@ -462,12 +419,8 @@ void Worklist::removeDeadPlans(VM& vm)
             deadPlanKeys.add(plan->key());
         }
         if (!deadPlanKeys.isEmpty()) {
-            for (HashSet<CompilationKey>::iterator iter = deadPlanKeys.begin(); iter != deadPlanKeys.end(); ++iter) {
-                RefPtr<Plan> plan = m_plans.take(*iter);
-                plan->cancel();
-                if (!isInMutator)
-                    m_cancelledPlansPendingDestruction.append(WTFMove(plan));
-            }
+            for (HashSet<CompilationKey>::iterator iter = deadPlanKeys.begin(); iter != deadPlanKeys.end(); ++iter)
+                m_plans.take(*iter)->cancel();
             Deque<RefPtr<Plan>> newQueue;
             while (!m_queue.isEmpty()) {
                 RefPtr<Plan> plan = m_queue.takeFirst();
@@ -503,9 +456,6 @@ void Worklist::removeNonCompilingPlansForVM(VM& vm)
     LockHolder locker(*m_lock);
     HashSet<CompilationKey> deadPlanKeys;
     Vector<RefPtr<Plan>> deadPlans;
-    ASSERT(vm.currentThreadIsHoldingAPILock());
-
-    deleteCancelledPlansForVM(locker, vm);
     for (auto& entry : m_plans) {
         Plan* plan = entry.value.get();
         if (plan->vm() != &vm)
index 744d60f..1e28fed 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -93,7 +93,6 @@ private:
     static void threadFunction(void* argument);
     
     void removeAllReadyPlansForVM(VM&, Vector<RefPtr<Plan>, 8>&);
-    void deleteCancelledPlansForVM(LockHolder&, VM&);
 
     void dump(const AbstractLocker&, PrintStream&) const;
     
@@ -114,7 +113,6 @@ private:
     // Used to quickly find which plans have been compiled and are ready to
     // be completed.
     Vector<RefPtr<Plan>, 16> m_readyPlans;
-    Vector<RefPtr<Plan>, 4> m_cancelledPlansPendingDestruction;
     Ref<AutomaticThreadCondition> m_planEnqueued;
     Condition m_planCompiled;
 
index 1946e78..856b5b5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -71,24 +71,29 @@ bool JITFinalizer::finalizeFunction()
 
 bool JITFinalizer::finalizeCommon()
 {
+    CodeBlock* codeBlock = m_plan.codeBlock();
     bool dumpDisassembly = shouldDumpDisassembly() || Options::asyncDisassembly();
-    
+
     MacroAssemblerCodeRef<JSEntryPtrTag> b3CodeRef =
         FINALIZE_CODE_IF(dumpDisassembly, *b3CodeLinkBuffer, JSEntryPtrTag,
-            "FTL B3 code for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock(), JITType::FTLJIT)).data());
+            "FTL B3 code for %s", toCString(CodeBlockWithJITType(codeBlock, JITType::FTLJIT)).data());
 
     MacroAssemblerCodeRef<JSEntryPtrTag> arityCheckCodeRef = entrypointLinkBuffer
         ? FINALIZE_CODE_IF(dumpDisassembly, *entrypointLinkBuffer, JSEntryPtrTag,
-            "FTL entrypoint thunk for %s with B3 generated code at %p", toCString(CodeBlockWithJITType(m_plan.codeBlock(), JITType::FTLJIT)).data(), function)
+            "FTL entrypoint thunk for %s with B3 generated code at %p", toCString(CodeBlockWithJITType(codeBlock, JITType::FTLJIT)).data(), function)
         : MacroAssemblerCodeRef<JSEntryPtrTag>::createSelfManagedCodeRef(b3CodeRef.code());
 
     jitCode->initializeB3Code(b3CodeRef);
     jitCode->initializeArityCheckEntrypoint(arityCheckCodeRef);
 
-    m_plan.codeBlock()->setJITCode(*jitCode);
+    codeBlock->setJITCode(*jitCode);
 
     if (UNLIKELY(m_plan.compilation()))
-        m_plan.vm()->m_perBytecodeProfiler->addCompilation(m_plan.codeBlock(), *m_plan.compilation());
+        m_plan.vm()->m_perBytecodeProfiler->addCompilation(codeBlock, *m_plan.compilation());
+
+    // The codeBlock is now responsible for keeping many things alive (e.g. frozen values)
+    // that were previously kept alive by the plan.
+    m_plan.vm()->heap.writeBarrier(codeBlock);
 
     return true;
 }
index 8cb55fb..6ff8802 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,6 +30,7 @@
 
 #include "ArithProfile.h"
 #include "ArrayConstructor.h"
+#include "CacheableIdentifierInlines.h"
 #include "CommonSlowPaths.h"
 #include "DFGCompilationMode.h"
 #include "DFGDriver.h"
@@ -2028,7 +2029,7 @@ EncodedJSValue JIT_OPERATION operationGetByValOptimize(JSGlobalObject* globalObj
         }
     }
 
-    if (baseValue.isCell() && isStringOrSymbol(subscript)) {
+    if (baseValue.isCell() && CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
         const Identifier propertyName = subscript.toPropertyKey(globalObject);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
         if (subscript.isSymbol() || !parseIndex(propertyName)) {
@@ -2037,7 +2038,7 @@ EncodedJSValue JIT_OPERATION operationGetByValOptimize(JSGlobalObject* globalObj
                 LOG_IC((ICEvent::OperationGetByValOptimize, baseValue.classInfoOrNull(vm), propertyName, baseValue == slot.slotBase())); 
                 
                 if (stubInfo->considerCaching(vm, codeBlock, baseValue.structureOrNull(), propertyName.impl()))
-                    repatchGetBy(globalObject, codeBlock, baseValue, propertyName, slot, *stubInfo, GetByKind::NormalByVal);
+                    repatchGetBy(globalObject, codeBlock, baseValue, subscript.asCell(), slot, *stubInfo, GetByKind::NormalByVal);
                 return found ? slot.getValue(globalObject, propertyName) : jsUndefined();
             }));
         }
index 0726f4e..5918883 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,6 +30,7 @@
 
 #include "BinarySwitch.h"
 #include "CCallHelpers.h"
+#include "CacheableIdentifierInlines.h"
 #include "CallFrameShuffler.h"
 #include "DFGOperations.h"
 #include "DFGSpeculativeJIT.h"
@@ -178,7 +179,7 @@ inline FunctionPtr<CFunctionPtrTag> appropriateGetByFunction(GetByKind kind)
     RELEASE_ASSERT_NOT_REACHED();
 }
 
-static InlineCacheAction tryCacheGetBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo, GetByKind kind)
+static InlineCacheAction tryCacheGetBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, CacheableIdentifier propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo, GetByKind kind)
 {
     VM& vm = globalObject->vm();
     AccessGenerationResult result;
@@ -268,7 +269,7 @@ static InlineCacheAction tryCacheGetBy(JSGlobalObject* globalObject, CodeBlock*
 
                 bool generatedCodeInline = InlineAccess::generateSelfPropertyAccess(stubInfo, structure, slot.cachedOffset());
                 if (generatedCodeInline) {
-                    LOG_IC((ICEvent::GetBySelfPatch, structure->classInfo(), propertyName, slot.slotBase() == baseValue));
+                    LOG_IC((ICEvent::GetBySelfPatch, structure->classInfo(), Identifier::fromUid(vm, propertyName.uid()), slot.slotBase() == baseValue));
                     structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
                     ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation, appropriateOptimizingGetByFunction(kind));
                     stubInfo.initGetByIdSelf(codeBlock, structure, slot.cachedOffset(), propertyName);
@@ -319,7 +320,7 @@ static InlineCacheAction tryCacheGetBy(JSGlobalObject* globalObject, CodeBlock*
                         prototypeAccessChain = PolyProtoAccessChain::create(globalObject, baseCell, slot);
                         if (!prototypeAccessChain)
                             return GiveUpOnCache;
-                        RELEASE_ASSERT(slot.isCacheableCustom() || prototypeAccessChain->slotBaseStructure(structure)->get(vm, propertyName) == offset);
+                        RELEASE_ASSERT(slot.isCacheableCustom() || prototypeAccessChain->slotBaseStructure(structure)->get(vm, propertyName.uid()) == offset);
                     } else {
                         // We use ObjectPropertyConditionSet instead for faster accesses.
                         prototypeAccessChain = nullptr;
@@ -328,16 +329,16 @@ static InlineCacheAction tryCacheGetBy(JSGlobalObject* globalObject, CodeBlock*
                         // https://bugs.webkit.org/show_bug.cgi?id=185215
                         if (slot.isUnset()) {
                             conditionSet = generateConditionsForPropertyMiss(
-                                vm, codeBlock, globalObject, structure, propertyName.impl());
+                                vm, codeBlock, globalObject, structure, propertyName.uid());
                         } else if (!slot.isCacheableCustom()) {
                             conditionSet = generateConditionsForPrototypePropertyHit(
                                 vm, codeBlock, globalObject, structure, slot.slotBase(),
-                                propertyName.impl());
+                                propertyName.uid());
                             RELEASE_ASSERT(!conditionSet.isValid() || conditionSet.slotBaseCondition().offset() == offset);
                         } else {
                             conditionSet = generateConditionsForPrototypePropertyHitCustom(
                                 vm, codeBlock, globalObject, structure, slot.slotBase(),
-                                propertyName.impl(), slot.attributes());
+                                propertyName.uid(), slot.attributes());
                         }
 
                         if (!conditionSet.isValid())
@@ -393,12 +394,12 @@ static InlineCacheAction tryCacheGetBy(JSGlobalObject* globalObject, CodeBlock*
             }
         }
 
-        LOG_IC((ICEvent::GetByAddAccessCase, baseValue.classInfoOrNull(vm), propertyName, slot.slotBase() == baseValue));
+        LOG_IC((ICEvent::GetByAddAccessCase, baseValue.classInfoOrNull(vm), Identifier::fromUid(vm, propertyName.uid()), slot.slotBase() == baseValue));
 
         result = stubInfo.addAccessCase(locker, codeBlock, propertyName, WTFMove(newCase));
 
         if (result.generatedSomeCode()) {
-            LOG_IC((ICEvent::GetByReplaceWithJump, baseValue.classInfoOrNull(vm), propertyName, slot.slotBase() == baseValue));
+            LOG_IC((ICEvent::GetByReplaceWithJump, baseValue.classInfoOrNull(vm), Identifier::fromUid(vm, propertyName.uid()), slot.slotBase() == baseValue));
             
             RELEASE_ASSERT(result.code());
             InlineAccess::rewireStubAsJump(stubInfo, CodeLocationLabel<JITStubRoutinePtrTag>(result.code()));
@@ -410,7 +411,7 @@ static InlineCacheAction tryCacheGetBy(JSGlobalObject* globalObject, CodeBlock*
     return result.shouldGiveUpNow() ? GiveUpOnCache : RetryCacheLater;
 }
 
-void repatchGetBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo, GetByKind kind)
+void repatchGetBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, CacheableIdentifier propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo, GetByKind kind)
 {
     SuperSamplerScope superSamplerScope(false);
     
@@ -494,7 +495,7 @@ static InlineCacheAction tryCacheArrayGetByVal(JSGlobalObject* globalObject, Cod
             }
         }
 
-        result = stubInfo.addAccessCase(locker, codeBlock, Identifier(), AccessCase::create(vm, codeBlock, accessType, Identifier()));
+        result = stubInfo.addAccessCase(locker, codeBlock, nullptr, AccessCase::create(vm, codeBlock, accessType, nullptr));
 
         if (result.generatedSomeCode()) {
             LOG_IC((ICEvent::GetByReplaceWithJump, baseValue.classInfoOrNull(vm), Identifier()));
@@ -884,7 +885,7 @@ static InlineCacheAction tryCacheInstanceOf(
         
         LOG_IC((ICEvent::InstanceOfAddAccessCase, structure->classInfo(), Identifier()));
         
-        result = stubInfo.addAccessCase(locker, codeBlock, Identifier(), WTFMove(newCase));
+        result = stubInfo.addAccessCase(locker, codeBlock, nullptr, WTFMove(newCase));
         
         if (result.generatedSomeCode()) {
             LOG_IC((ICEvent::InstanceOfReplaceWithJump, structure->classInfo(), Identifier()));
index fdda8a7..6f0f264 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,6 +27,7 @@
 
 #if ENABLE(JIT)
 
+#include "CacheableIdentifier.h"
 #include "CallVariant.h"
 #include "PutKind.h"
 
@@ -41,7 +42,7 @@ enum class GetByKind {
 };
 
 void repatchArrayGetByVal(JSGlobalObject*, CodeBlock*, JSValue base, JSValue index, StructureStubInfo&);
-void repatchGetBy(JSGlobalObject*, CodeBlock*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&, GetByKind);
+void repatchGetBy(JSGlobalObject*, CodeBlock*, JSValue, CacheableIdentifier, const PropertySlot&, StructureStubInfo&, GetByKind);
 void repatchPutByID(JSGlobalObject*, CodeBlock*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
 void repatchInByID(JSGlobalObject*, CodeBlock*, JSObject*, const Identifier&, bool wasFound, const PropertySlot&, StructureStubInfo&);
 void repatchInstanceOf(JSGlobalObject*, CodeBlock*, JSValue value, JSValue prototype, StructureStubInfo&, bool wasFound);
diff --git a/Source/JavaScriptCore/runtime/CacheableIdentifier.cpp b/Source/JavaScriptCore/runtime/CacheableIdentifier.cpp
new file mode 100644 (file)
index 0000000..4d256a8
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CacheableIdentifier.h"
+
+#include "CacheableIdentifierInlines.h"
+#include <wtf/PrintStream.h>
+
+namespace JSC {
+
+void CacheableIdentifier::dump(PrintStream& out) const
+{
+    out.print(m_bits ? uid() : StringImpl::empty());
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/CacheableIdentifier.h b/Source/JavaScriptCore/runtime/CacheableIdentifier.h
new file mode 100644 (file)
index 0000000..e507653
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSCJSValue.h"
+
+namespace WTF {
+
+class PrintStream;
+class UniquedStringImpl;
+
+} // namespace WTF
+
+using WTF::PrintStream;
+using WTF::UniquedStringImpl;
+
+namespace JSC {
+
+class Identifier;
+class JSCell;
+class SlotVisitor;
+
+class CacheableIdentifier {
+public:
+    CacheableIdentifier() = default;
+    inline CacheableIdentifier(const Identifier&);
+    inline CacheableIdentifier(JSCell* identifier);
+
+    CacheableIdentifier(const CacheableIdentifier&) = default;
+    CacheableIdentifier(CacheableIdentifier&&) = default;
+
+    CacheableIdentifier(std::nullptr_t)
+        : m_bits(0)
+    { }
+
+    bool isUid() const { return m_bits & s_uidTag; }
+    bool isCell() const { return !isUid(); }
+    inline bool isSymbolCell() const;
+    inline bool isStringCell() const;
+
+    bool isSymbol() const { return m_bits && uid()->isSymbol(); }
+
+    inline JSCell* cell() const;
+    UniquedStringImpl* uid() const;
+
+    explicit operator bool() const { return m_bits; }
+
+    CacheableIdentifier& operator=(const CacheableIdentifier&) = default;
+    CacheableIdentifier& operator=(CacheableIdentifier&&) = default;
+
+    bool operator==(const CacheableIdentifier& other) const;
+    bool operator!=(const CacheableIdentifier& other) const;
+    bool operator==(const Identifier& other) const;
+
+    static inline bool isCacheableIdentifierCell(JSCell*);
+    static inline bool isCacheableIdentifierCell(JSValue);
+
+    inline void visitAggregate(SlotVisitor&) const;
+
+    JS_EXPORT_PRIVATE void dump(PrintStream&) const;
+
+private:
+    inline void setCellBits(JSCell*);
+    inline void setUidBits(UniquedStringImpl*);
+
+    // CacheableIdentifier can either hold a cell pointer or a uid. To discern which
+    // it is holding, we tag the low bit if we have a uid. We choose to tag the uid
+    // instead of the cell because this keeps the bits of the cell pointer form
+    // unpolluted, and therefore, it can be scanned by our conservative GC to keep the
+    // cell alive when the CacheableIdentifier is on the stack.
+    static constexpr uintptr_t s_uidTag = 1;
+    uintptr_t m_bits;
+};
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/CacheableIdentifierInlines.h b/Source/JavaScriptCore/runtime/CacheableIdentifierInlines.h
new file mode 100644 (file)
index 0000000..ffb3eb9
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CacheableIdentifier.h"
+
+#include "Identifier.h"
+#include "JSCJSValueInlines.h"
+#include "JSCell.h"
+#include "VM.h"
+#include <wtf/text/UniquedStringImpl.h>
+
+namespace JSC {
+
+inline CacheableIdentifier::CacheableIdentifier(const Identifier& identifier)
+{
+    setUidBits(identifier.impl());
+}
+
+inline CacheableIdentifier::CacheableIdentifier(JSCell* identifier)
+{
+    setCellBits(identifier);
+}
+
+inline JSCell* CacheableIdentifier::cell() const
+{
+    ASSERT(isCell());
+    return bitwise_cast<JSCell*>(m_bits);
+}
+
+inline UniquedStringImpl* CacheableIdentifier::uid() const
+{
+    if (!m_bits)
+        return nullptr;
+    if (isUid())
+        return bitwise_cast<UniquedStringImpl*>(m_bits & ~s_uidTag);
+    if (isSymbolCell())
+        return &jsCast<Symbol*>(cell())->uid();
+    ASSERT(isStringCell());
+    JSString* string = jsCast<JSString*>(cell());
+    return bitwise_cast<UniquedStringImpl*>(string->getValueImpl());
+}
+
+inline bool CacheableIdentifier::isCacheableIdentifierCell(JSCell* cell)
+{
+    if (cell->isSymbol())
+        return true;
+    if (!cell->isString())
+        return false;
+    JSString* string = jsCast<JSString*>(cell);
+    if (const StringImpl* impl = string->tryGetValueImpl())
+        return impl->isAtom();
+    return false;
+}
+
+inline bool CacheableIdentifier::isCacheableIdentifierCell(JSValue value)
+{
+    if (!value.isCell())
+        return false;
+    return isCacheableIdentifierCell(value.asCell());
+}
+
+inline bool CacheableIdentifier::isSymbolCell() const
+{
+    return isCell() && cell()->isSymbol();
+}
+
+inline bool CacheableIdentifier::isStringCell() const
+{
+    return isCell() && cell()->isString();
+}
+
+inline void CacheableIdentifier::setCellBits(JSCell* cell)
+{
+    RELEASE_ASSERT(isCacheableIdentifierCell(cell));
+    m_bits = bitwise_cast<uintptr_t>(cell);
+}
+
+inline void CacheableIdentifier::setUidBits(UniquedStringImpl* uid)
+{
+    m_bits = bitwise_cast<uintptr_t>(uid) | s_uidTag;
+}
+
+inline void CacheableIdentifier::visitAggregate(SlotVisitor& visitor) const
+{
+    if (m_bits && isCell())
+        visitor.appendUnbarriered(cell());
+}
+
+
+inline bool CacheableIdentifier::operator==(const CacheableIdentifier& other) const
+{
+    return uid() == other.uid();
+}
+
+inline bool CacheableIdentifier::operator!=(const CacheableIdentifier& other) const
+{
+    return uid() != other.uid();
+}
+
+inline bool CacheableIdentifier::operator==(const Identifier& other) const
+{
+    return uid() == other.impl();
+}
+
+} // namespace JSC
index 3656e59..af98d4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -130,7 +130,7 @@ static String functionCallBase(const String& sourceText)
     if (sourceLength < 2 || sourceText[idx] != ')') {
         // For function calls that have many new lines in between their open parenthesis
         // and their closing parenthesis, the text range passed into the message appender 
-        // will not inlcude the text in between these parentheses, it will just be the desired
+        // will not include the text in between these parentheses, it will just be the desired
         // text that precedes the parentheses.
         return String();
     }
index 7494a1b..e0dd96f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003-2019 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2020 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -189,6 +189,7 @@ public:
     inline bool equal(JSGlobalObject*, JSString* other) const;
     const String& value(JSGlobalObject*) const;
     inline const String& tryGetValue(bool allocationAllowed = true) const;
+    const StringImpl* getValueImpl() const;
     const StringImpl* tryGetValueImpl() const;
     ALWAYS_INLINE unsigned length() const;
 
@@ -703,6 +704,12 @@ ALWAYS_INLINE unsigned JSString::length() const
     return bitwise_cast<StringImpl*>(pointer)->length();
 }
 
+inline const StringImpl* JSString::getValueImpl() const
+{
+    ASSERT(!isRope());
+    return bitwise_cast<StringImpl*>(m_fiber);
+}
+
 inline const StringImpl* JSString::tryGetValueImpl() const
 {
     uintptr_t pointer = m_fiber;
index 4bd549b..d390847 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1152,20 +1152,15 @@ void VM::dumpRegExpTrace()
 }
 #endif
 
-WatchpointSet* VM::ensureWatchpointSetForImpureProperty(const Identifier& propertyName)
+WatchpointSet* VM::ensureWatchpointSetForImpureProperty(UniquedStringImpl* propertyName)
 {
-    auto result = m_impurePropertyWatchpointSets.add(propertyName.string(), nullptr);
+    auto result = m_impurePropertyWatchpointSets.add(propertyName, nullptr);
     if (result.isNewEntry)
         result.iterator->value = adoptRef(new WatchpointSet(IsWatched));
     return result.iterator->value.get();
 }
 
-void VM::registerWatchpointForImpureProperty(const Identifier& propertyName, Watchpoint* watchpoint)
-{
-    ensureWatchpointSetForImpureProperty(propertyName)->add(watchpoint);
-}
-
-void VM::addImpureProperty(const String& propertyName)
+void VM::addImpureProperty(UniquedStringImpl* propertyName)
 {
     if (RefPtr<WatchpointSet> watchpointSet = m_impurePropertyWatchpointSets.take(propertyName))
         watchpointSet->fireAll(*this, "Impure property added");
index d1c8713..7da32a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1030,11 +1030,10 @@ public:
 
     void shrinkFootprintWhenIdle();
 
-    WatchpointSet* ensureWatchpointSetForImpureProperty(const Identifier&);
-    void registerWatchpointForImpureProperty(const Identifier&, Watchpoint*);
+    WatchpointSet* ensureWatchpointSetForImpureProperty(UniquedStringImpl*);
     
     // FIXME: Use AtomString once it got merged with Identifier.
-    JS_EXPORT_PRIVATE void addImpureProperty(const String&);
+    JS_EXPORT_PRIVATE void addImpureProperty(UniquedStringImpl*);
     
     InlineWatchpointSet& primitiveGigacageEnabled() { return m_primitiveGigacageEnabled; }
 
@@ -1208,7 +1207,7 @@ private:
     bool m_shouldBuildPCToCodeOriginMapping { false };
     std::unique_ptr<CodeCache> m_codeCache;
     std::unique_ptr<BuiltinExecutables> m_builtinExecutables;
-    HashMap<String, RefPtr<WatchpointSet>> m_impurePropertyWatchpointSets;
+    HashMap<RefPtr<UniquedStringImpl>, RefPtr<WatchpointSet>> m_impurePropertyWatchpointSets;
     std::unique_ptr<TypeProfiler> m_typeProfiler;
     std::unique_ptr<TypeProfilerLog> m_typeProfilerLog;
     unsigned m_typeProfilerEnabledCount;
index e3a5d5f..903668b 100644 (file)
@@ -1,3 +1,14 @@
+2020-01-13  Mark Lam  <mark.lam@apple.com>
+
+        Replace uses of Box<Identifier> with a new CacheableIdentifier class.
+        https://bugs.webkit.org/show_bug.cgi?id=205544
+        <rdar://problem/58041800>
+
+        Reviewed by Saam Barati.
+
+        * bindings/js/CommonVM.cpp:
+        (WebCore::addImpureProperty):
+
 2020-01-13  Ross Kirsling  <ross.kirsling@sony.com>
 
         Unreviewed build fix for PlayStation and clang-cl.
index cbf3d0b..9f2ca5f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -88,7 +88,7 @@ Frame* lexicalFrameFromCommonVM()
 
 void addImpureProperty(const AtomString& propertyName)
 {
-    commonVM().addImpureProperty(propertyName);
+    commonVM().addImpureProperty(propertyName.impl());
 }
 
 } // namespace WebCore