WebKit Bugzilla
Attachment 340788 Details for
Bug 185803
: [DFG] InById should be converted to MatchStructure
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-185803-20180520083624.patch (text/plain), 27.86 KB, created by
Yusuke Suzuki
on 2018-05-19 16:36:25 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2018-05-19 16:36:25 PDT
Size:
27.86 KB
patch
obsolete
>Subversion Revision: 232000 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 8228176e72b5a333221358c4f3bea8410ceaf0da..2a4e1e803e6038af8f40c64869134f11c7251f4f 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,51 @@ >+2018-05-19 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [DFG] InById should be converted to MatchStructure >+ https://bugs.webkit.org/show_bug.cgi?id=185803 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ MatchStructure is introduced for instanceof optimization. But this node >+ is also useful for InById node. This patch converts InById to MatchStructure >+ node with CheckStructures if possible by using InByIdStatus. >+ >+ * Sources.txt: >+ * bytecode/InByIdStatus.cpp: Added. >+ (JSC::InByIdStatus::appendVariant): >+ (JSC::InByIdStatus::computeFor): >+ (JSC::InByIdStatus::hasExitSite): >+ (JSC::InByIdStatus::computeForStubInfo): >+ (JSC::InByIdStatus::computeForStubInfoWithoutExitSiteFeedback): >+ (JSC::InByIdStatus::filter): >+ (JSC::InByIdStatus::dump const): >+ * bytecode/InByIdStatus.h: Added. >+ (JSC::InByIdStatus::InByIdStatus): >+ (JSC::InByIdStatus::state const): >+ (JSC::InByIdStatus::isSet const): >+ (JSC::InByIdStatus::operator bool const): >+ (JSC::InByIdStatus::isSimple const): >+ (JSC::InByIdStatus::numVariants const): >+ (JSC::InByIdStatus::variants const): >+ (JSC::InByIdStatus::at const): >+ (JSC::InByIdStatus::operator[] const): >+ (JSC::InByIdStatus::takesSlowPath const): >+ * bytecode/InByIdVariant.cpp: Added. >+ (JSC::InByIdVariant::InByIdVariant): >+ (JSC::InByIdVariant::attemptToMerge): >+ (JSC::InByIdVariant::dump const): >+ (JSC::InByIdVariant::dumpInContext const): >+ * bytecode/InByIdVariant.h: Added. >+ (JSC::InByIdVariant::isSet const): >+ (JSC::InByIdVariant::operator bool const): >+ (JSC::InByIdVariant::structureSet const): >+ (JSC::InByIdVariant::structureSet): >+ (JSC::InByIdVariant::conditionSet const): >+ (JSC::InByIdVariant::offset const): >+ (JSC::InByIdVariant::isHit const): >+ * bytecode/PolyProtoAccessChain.h: >+ * dfg/DFGByteCodeParser.cpp: >+ (JSC::DFG::ByteCodeParser::parseBlock): >+ > 2018-05-18 Filip Pizlo <fpizlo@apple.com> > > DFG should inline InstanceOf ICs >diff --git a/Source/JavaScriptCore/Sources.txt b/Source/JavaScriptCore/Sources.txt >index 6ad1a45d7f597f6162da91a4e0d9493a3821a3f2..880691b2df3b2ff7b2bebd7569587dcb426ce7ba 100644 >--- a/Source/JavaScriptCore/Sources.txt >+++ b/Source/JavaScriptCore/Sources.txt >@@ -219,6 +219,8 @@ bytecode/FunctionCodeBlock.cpp > bytecode/GetByIdStatus.cpp > bytecode/GetByIdVariant.cpp > bytecode/GetterSetterAccessCase.cpp >+bytecode/InByIdStatus.cpp >+bytecode/InByIdVariant.cpp > bytecode/InlineAccess.cpp > bytecode/InlineCallFrame.cpp > bytecode/InlineCallFrameSet.cpp >diff --git a/Source/JavaScriptCore/bytecode/InByIdStatus.cpp b/Source/JavaScriptCore/bytecode/InByIdStatus.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..8b310fb99b416bd41ff6d2bef7d63eab8193793d >--- /dev/null >+++ b/Source/JavaScriptCore/bytecode/InByIdStatus.cpp >@@ -0,0 +1,237 @@ >+/* >+ * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com>. >+ * >+ * 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 "InByIdStatus.h" >+ >+#include "CodeBlock.h" >+#include "ComplexGetStatus.h" >+#include "ICStatusUtils.h" >+#include "JSCInlines.h" >+#include "PolymorphicAccess.h" >+#include "StructureStubInfo.h" >+#include <wtf/ListDump.h> >+ >+namespace JSC { >+ >+bool InByIdStatus::appendVariant(const InByIdVariant& variant) >+{ >+ return appendICStatusVariant(m_variants, variant); >+} >+ >+InByIdStatus InByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, UniquedStringImpl* uid) >+{ >+ ConcurrentJSLocker locker(profiledBlock->m_lock); >+ >+ InByIdStatus result; >+ >+#if ENABLE(DFG_JIT) >+ result = computeForStubInfoWithoutExitSiteFeedback(locker, map.get(CodeOrigin(bytecodeIndex)), uid); >+ >+ if (!result.takesSlowPath() && hasExitSite(profiledBlock, bytecodeIndex)) >+ return InByIdStatus(TakesSlowPath); >+#else >+ UNUSED_PARAM(map); >+#endif >+ >+ return result; >+} >+ >+InByIdStatus InByIdStatus::computeFor( >+ CodeBlock* profiledBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, >+ StubInfoMap& dfgMap, CodeOrigin codeOrigin, UniquedStringImpl* uid) >+{ >+#if ENABLE(DFG_JIT) >+ if (dfgBlock) { >+ CallLinkStatus::ExitSiteData exitSiteData; >+ { >+ ConcurrentJSLocker locker(profiledBlock->m_lock); >+ exitSiteData = CallLinkStatus::computeExitSiteData( >+ profiledBlock, codeOrigin.bytecodeIndex); >+ } >+ >+ InByIdStatus result; >+ { >+ ConcurrentJSLocker locker(dfgBlock->m_lock); >+ result = computeForStubInfoWithoutExitSiteFeedback(locker, dfgMap.get(codeOrigin), uid); >+ } >+ >+ if (result.takesSlowPath()) >+ return result; >+ >+ if (hasExitSite(profiledBlock, codeOrigin.bytecodeIndex)) >+ return InByIdStatus(TakesSlowPath); >+ >+ if (result.isSet()) >+ return result; >+ } >+#else >+ UNUSED_PARAM(dfgBlock); >+ UNUSED_PARAM(dfgMap); >+#endif >+ >+ return computeFor(profiledBlock, baselineMap, codeOrigin.bytecodeIndex, uid); >+} >+ >+#if ENABLE(DFG_JIT) >+bool InByIdStatus::hasExitSite(CodeBlock* profiledBlock, unsigned bytecodeIndex) >+{ >+ UnlinkedCodeBlock* unlinkedCodeBlock = profiledBlock->unlinkedCodeBlock(); >+ ConcurrentJSLocker locker(unlinkedCodeBlock->m_lock); >+ return unlinkedCodeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache)) >+ || unlinkedCodeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadConstantCache)); >+} >+ >+InByIdStatus InByIdStatus::computeForStubInfo(const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CodeOrigin codeOrigin, UniquedStringImpl* uid) >+{ >+ InByIdStatus result = InByIdStatus::computeForStubInfoWithoutExitSiteFeedback(locker, stubInfo, uid); >+ >+ if (!result.takesSlowPath() && InByIdStatus::hasExitSite(profiledBlock, codeOrigin.bytecodeIndex)) >+ return InByIdStatus(TakesSlowPath); >+ return result; >+} >+ >+InByIdStatus InByIdStatus::computeForStubInfoWithoutExitSiteFeedback(const ConcurrentJSLocker&, StructureStubInfo* stubInfo, UniquedStringImpl* uid) >+{ >+ if (!stubInfo || !stubInfo->everConsidered) >+ return InByIdStatus(NoInformation); >+ >+ if (stubInfo->tookSlowPath) >+ return InByIdStatus(TakesSlowPath); >+ >+ // Finally figure out if we can derive an access strategy. >+ InByIdStatus result; >+ result.m_state = Simple; >+ switch (stubInfo->cacheType) { >+ case CacheType::Unset: >+ return InByIdStatus(NoInformation); >+ >+ case CacheType::InByIdSelf: { >+ Structure* structure = stubInfo->u.byIdSelf.baseObjectStructure.get(); >+ if (structure->takesSlowPathInDFGForImpureProperty()) >+ return InByIdStatus(TakesSlowPath); >+ unsigned attributes; >+ InByIdVariant variant; >+ variant.m_offset = structure->getConcurrently(uid, attributes); >+ if (!isValidOffset(variant.m_offset)) >+ return InByIdStatus(TakesSlowPath); >+ if (attributes & PropertyAttribute::CustomAccessor) >+ return InByIdStatus(TakesSlowPath); >+ >+ variant.m_structureSet.add(structure); >+ bool didAppend = result.appendVariant(variant); >+ ASSERT_UNUSED(didAppend, didAppend); >+ return result; >+ } >+ >+ case CacheType::Stub: { >+ PolymorphicAccess* list = stubInfo->u.stub; >+ for (unsigned listIndex = 0; listIndex < list->size(); ++listIndex) { >+ const AccessCase& access = list->at(listIndex); >+ if (access.viaProxy()) >+ return InByIdStatus(TakesSlowPath); >+ >+ if (access.usesPolyProto()) >+ return InByIdStatus(TakesSlowPath); >+ >+ Structure* structure = access.structure(); >+ if (!structure) { >+ // The null structure cases arise due to array.length. We have no way of creating a >+ // InByIdVariant for those, and we don't really have to since the DFG handles those >+ // cases in FixupPhase using value profiling. That's a bit awkward - we shouldn't >+ // have to use value profiling to discover something that the AccessCase could have >+ // told us. But, it works well enough. So, our only concern here is to not >+ // crash on null structure. >+ return InByIdStatus(TakesSlowPath); >+ } >+ >+ ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(structure, access.conditionSet(), uid); >+ switch (complexGetStatus.kind()) { >+ case ComplexGetStatus::ShouldSkip: >+ continue; >+ >+ case ComplexGetStatus::TakesSlowPath: >+ return InByIdStatus(TakesSlowPath); >+ >+ case ComplexGetStatus::Inlineable: { >+ switch (access.type()) { >+ case AccessCase::InHit: >+ case AccessCase::InMiss: >+ break; >+ default: >+ return InByIdStatus(TakesSlowPath); >+ } >+ >+ InByIdVariant variant( >+ StructureSet(structure), complexGetStatus.offset(), >+ complexGetStatus.conditionSet()); >+ >+ if (!result.appendVariant(variant)) >+ return InByIdStatus(TakesSlowPath); >+ break; >+ } >+ } >+ } >+ >+ return result; >+ } >+ >+ default: >+ return InByIdStatus(TakesSlowPath); >+ } >+ >+ RELEASE_ASSERT_NOT_REACHED(); >+ return InByIdStatus(); >+} >+#endif >+ >+void InByIdStatus::filter(const StructureSet& structureSet) >+{ >+ if (m_state != Simple) >+ return; >+ filterICStatusVariants(m_variants, structureSet); >+ if (m_variants.isEmpty()) >+ m_state = NoInformation; >+} >+ >+void InByIdStatus::dump(PrintStream& out) const >+{ >+ out.print("("); >+ switch (m_state) { >+ case NoInformation: >+ out.print("NoInformation"); >+ break; >+ case Simple: >+ out.print("Simple"); >+ break; >+ case TakesSlowPath: >+ out.print("TakesSlowPath"); >+ break; >+ } >+ out.print(", ", listDump(m_variants), ")"); >+} >+ >+} // namespace JSC >+ >diff --git a/Source/JavaScriptCore/bytecode/InByIdStatus.h b/Source/JavaScriptCore/bytecode/InByIdStatus.h >new file mode 100644 >index 0000000000000000000000000000000000000000..6615dfcdf8f4cb1607eb414508d051f5d7ef8018 >--- /dev/null >+++ b/Source/JavaScriptCore/bytecode/InByIdStatus.h >@@ -0,0 +1,98 @@ >+/* >+ * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com>. >+ * >+ * 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 "CallLinkStatus.h" >+#include "CodeOrigin.h" >+#include "ConcurrentJSLock.h" >+#include "InByIdVariant.h" >+ >+namespace JSC { >+ >+class AccessCase; >+class CodeBlock; >+class StructureStubInfo; >+ >+typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap; >+ >+class InByIdStatus { >+public: >+ enum State { >+ // It's uncached so we have no information. >+ NoInformation, >+ // It's cached for a simple access to a known object property with >+ // a possible structure chain and a possible specific value. >+ Simple, >+ // It's known to often take slow path. >+ TakesSlowPath, >+ }; >+ >+ InByIdStatus() = default; >+ >+ InByIdStatus(State state, const InByIdVariant& variant = InByIdVariant()) >+ : m_state(state) >+ { >+ ASSERT((state == Simple) == variant.isSet()); >+ m_variants.append(variant); >+ } >+ >+ static InByIdStatus computeFor(CodeBlock*, StubInfoMap&, unsigned bytecodeIndex, UniquedStringImpl* uid); >+ static InByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin, UniquedStringImpl* uid); >+ >+#if ENABLE(DFG_JIT) >+ static InByIdStatus computeForStubInfo(const ConcurrentJSLocker&, CodeBlock* baselineBlock, StructureStubInfo*, CodeOrigin, UniquedStringImpl* uid); >+#endif >+ >+ State state() const { return m_state; } >+ >+ bool isSet() const { return m_state != NoInformation; } >+ explicit operator bool() const { return isSet(); } >+ bool isSimple() const { return m_state == Simple; } >+ >+ size_t numVariants() const { return m_variants.size(); } >+ const Vector<InByIdVariant, 1>& variants() const { return m_variants; } >+ const InByIdVariant& at(size_t index) const { return m_variants[index]; } >+ const InByIdVariant& operator[](size_t index) const { return at(index); } >+ >+ bool takesSlowPath() const { return m_state == TakesSlowPath; } >+ >+ // Attempts to reduce the set of variants to fit the given structure set. This may be approximate. >+ void filter(const StructureSet&); >+ >+ void dump(PrintStream&) const; >+ >+private: >+#if ENABLE(DFG_JIT) >+ static bool hasExitSite(CodeBlock*, unsigned bytecodeIndex); >+ static InByIdStatus computeForStubInfoWithoutExitSiteFeedback(const ConcurrentJSLocker&, StructureStubInfo*, UniquedStringImpl* uid); >+#endif >+ bool appendVariant(const InByIdVariant&); >+ >+ State m_state { NoInformation }; >+ Vector<InByIdVariant, 1> m_variants; >+}; >+ >+} // namespace JSC >diff --git a/Source/JavaScriptCore/bytecode/InByIdVariant.cpp b/Source/JavaScriptCore/bytecode/InByIdVariant.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..626a5d3332990244ab7b81dcbf5ee59b561500bc >--- /dev/null >+++ b/Source/JavaScriptCore/bytecode/InByIdVariant.cpp >@@ -0,0 +1,85 @@ >+/* >+ * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com>. >+ * >+ * 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 "InByIdVariant.h" >+ >+#include "JSCInlines.h" >+#include <wtf/ListDump.h> >+ >+namespace JSC { >+ >+InByIdVariant::InByIdVariant(const StructureSet& structureSet, PropertyOffset offset, const ObjectPropertyConditionSet& conditionSet) >+ : m_structureSet(structureSet) >+ , m_conditionSet(conditionSet) >+ , m_offset(offset) >+{ >+ if (!structureSet.size()) { >+ ASSERT(offset == invalidOffset); >+ ASSERT(conditionSet.isEmpty()); >+ } >+} >+ >+bool InByIdVariant::attemptToMerge(const InByIdVariant& other) >+{ >+ if (m_offset != other.m_offset) >+ return false; >+ >+ if (m_conditionSet.isEmpty() != other.m_conditionSet.isEmpty()) >+ return false; >+ >+ ObjectPropertyConditionSet mergedConditionSet; >+ if (!m_conditionSet.isEmpty()) { >+ mergedConditionSet = m_conditionSet.mergedWith(other.m_conditionSet); >+ if (!mergedConditionSet.isValid() || !mergedConditionSet.hasOneSlotBaseCondition()) >+ return false; >+ } >+ m_conditionSet = mergedConditionSet; >+ >+ m_structureSet.merge(other.m_structureSet); >+ >+ return true; >+} >+ >+void InByIdVariant::dump(PrintStream& out) const >+{ >+ dumpInContext(out, 0); >+} >+ >+void InByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const >+{ >+ if (!isSet()) { >+ out.print("<empty>"); >+ return; >+ } >+ >+ out.print( >+ "<", inContext(structureSet(), context), ", ", inContext(m_conditionSet, context)); >+ out.print(", offset = ", offset()); >+ out.print(">"); >+} >+ >+} // namespace JSC >+ >diff --git a/Source/JavaScriptCore/bytecode/InByIdVariant.h b/Source/JavaScriptCore/bytecode/InByIdVariant.h >new file mode 100644 >index 0000000000000000000000000000000000000000..b7898a36878719c28b7fc916b73ac6f9e76f2c45 >--- /dev/null >+++ b/Source/JavaScriptCore/bytecode/InByIdVariant.h >@@ -0,0 +1,69 @@ >+/* >+ * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com>. >+ * >+ * 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 "ObjectPropertyConditionSet.h" >+#include "PropertyOffset.h" >+#include "StructureSet.h" >+ >+namespace JSC { >+namespace DOMJIT { >+class GetterSetter; >+} >+ >+class InByIdStatus; >+struct DumpContext; >+ >+class InByIdVariant { >+public: >+ InByIdVariant(const StructureSet& = StructureSet(), PropertyOffset = invalidOffset, const ObjectPropertyConditionSet& = ObjectPropertyConditionSet()); >+ >+ bool isSet() const { return !!m_structureSet.size(); } >+ explicit operator bool() const { return isSet(); } >+ const StructureSet& structureSet() const { return m_structureSet; } >+ StructureSet& structureSet() { return m_structureSet; } >+ >+ // A non-empty condition set means that this is a prototype in-hit/in-miss. >+ const ObjectPropertyConditionSet& conditionSet() const { return m_conditionSet; } >+ >+ PropertyOffset offset() const { return m_offset; } >+ >+ bool isHit() const { return offset() != invalidOffset; } >+ >+ bool attemptToMerge(const InByIdVariant& other); >+ >+ void dump(PrintStream&) const; >+ void dumpInContext(PrintStream&, DumpContext*) const; >+ >+private: >+ friend class InByIdStatus; >+ >+ StructureSet m_structureSet; >+ ObjectPropertyConditionSet m_conditionSet; >+ PropertyOffset m_offset; >+}; >+ >+} // namespace JSC >diff --git a/Source/JavaScriptCore/bytecode/PolyProtoAccessChain.h b/Source/JavaScriptCore/bytecode/PolyProtoAccessChain.h >index 52ab76e85574fd6887fb68f6f45c3dc3029db934..b49e4e242e52f081315e48fb1e1bcc297e528ae0 100644 >--- a/Source/JavaScriptCore/bytecode/PolyProtoAccessChain.h >+++ b/Source/JavaScriptCore/bytecode/PolyProtoAccessChain.h >@@ -29,6 +29,7 @@ > > namespace JSC { > >+class JSCell; > class JSGlobalObject; > class JSObject; > class PropertySlot; >diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >index fa097f32c666ed3f33fdbc4bbe38c15442b4d6e1..0c7738b4680fa68019a086024ddf3294df6be9cd 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -48,6 +48,7 @@ > #include "FunctionCodeBlock.h" > #include "GetByIdStatus.h" > #include "Heap.h" >+#include "InByIdStatus.h" > #include "InstanceOfStatus.h" > #include "JSCInlines.h" > #include "JSFixedArray.h" >@@ -6402,10 +6403,33 @@ void ByteCodeParser::parseBlock(unsigned limit) > case op_in_by_id: { > Node* base = get(VirtualRegister(currentInstruction[2].u.operand)); > unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand]; >- set(VirtualRegister(currentInstruction[1].u.operand), >- addToGraph(InById, OpInfo(identifierNumber), base)); >+ UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber]; >+ >+ InByIdStatus status = InByIdStatus::computeFor( >+ m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock, >+ m_inlineStackTop->m_stubInfos, m_dfgStubInfos, >+ currentCodeOrigin(), uid); >+ >+ if (status.isSimple()) { >+ MatchStructureData* data = m_graph.m_matchStructureData.add(); >+ for (const InByIdVariant& variant : status.variants()) { >+ check(variant.conditionSet()); >+ for (Structure* structure : variant.structureSet()) { >+ MatchStructureVariant matchVariant; >+ matchVariant.structure = m_graph.registerStructure(structure); >+ matchVariant.result = variant.isHit(); >+ >+ data->variants.append(matchVariant); >+ } >+ } >+ >+ Node* match = addToGraph(MatchStructure, OpInfo(data), base); >+ set(VirtualRegister(currentInstruction[1].u.operand), match); >+ NEXT_OPCODE(op_in_by_id); >+ } >+ >+ set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(InById, OpInfo(identifierNumber), base)); > NEXT_OPCODE(op_in_by_id); >- break; > } > > case op_get_enumerable_length: { >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index 72f9954fad476b4d3cd7c2a0def5544fcfe4b577..94e8adbde8ede7e79b8a6ff7c302aa8bacd44921 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,20 @@ >+2018-05-19 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [DFG] InById should be converted to MatchStructure >+ https://bugs.webkit.org/show_bug.cgi?id=185803 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * stress/in-by-id-constant.js: Added. >+ (shouldBe): >+ (test1): >+ * stress/in-by-id-match-invalid.js: Added. >+ (shouldBe): >+ (test1): >+ * stress/in-by-id-match.js: Added. >+ (shouldBe): >+ (test1): >+ > 2018-05-19 Yusuke Suzuki <utatane.tea@gmail.com> > > [JSC] JSC should have consistent InById IC >diff --git a/JSTests/stress/in-by-id-constant.js b/JSTests/stress/in-by-id-constant.js >new file mode 100644 >index 0000000000000000000000000000000000000000..9319ea83c76d7884cb10a9887b9f6ce801afad43 >--- /dev/null >+++ b/JSTests/stress/in-by-id-constant.js >@@ -0,0 +1,33 @@ >+function shouldBe(actual, expected) { >+ if (actual !== expected) >+ throw new Error('bad value: ' + actual); >+} >+ >+function test1(obj) >+{ >+ return "hello" in obj >+} >+noInline(test1); >+ >+let array = [ >+ [{ >+ hello: 42 >+ }, true], >+ [{ >+ hello: 42, >+ world: 43 >+ }, true], >+ [{ >+ __proto__: { >+ hello: 44 >+ } >+ }, true] >+]; >+for (let i = 0; i < 1e5; ++i) { >+ for (let [obj, result] of array) >+ shouldBe(test1(obj), result); >+} >+ >+// OSRExits. >+for (let i = 0; i < 1e5; ++i) >+ shouldBe(test1({}), false); >diff --git a/JSTests/stress/in-by-id-match-invalid.js b/JSTests/stress/in-by-id-match-invalid.js >new file mode 100644 >index 0000000000000000000000000000000000000000..51755e212ea6f0eb9e0b4eac0b3bdf50f15a9cc2 >--- /dev/null >+++ b/JSTests/stress/in-by-id-match-invalid.js >@@ -0,0 +1,30 @@ >+function shouldBe(actual, expected) { >+ if (actual !== expected) >+ throw new Error('bad value: ' + actual); >+} >+ >+function test1(obj) >+{ >+ return "hello" in obj >+} >+noInline(test1); >+ >+let object1 = { >+ hello: 42 >+}; >+let object2 = { >+ cocoa: 44 >+}; >+for (let i = 0; i < 1e5; ++i) { >+ shouldBe(test1(object1), true); >+ shouldBe(test1(object2), false); >+} >+object2.hello = 44; >+for (let i = 0; i < 1e5; ++i) { >+ shouldBe(test1(object1), true); >+ shouldBe(test1(object2), true); >+} >+ >+// OSRExits. >+for (let i = 0; i < 1e5; ++i) >+ shouldBe(test1({}), false); >diff --git a/JSTests/stress/in-by-id-match.js b/JSTests/stress/in-by-id-match.js >new file mode 100644 >index 0000000000000000000000000000000000000000..62ccc31ccfe10abbaf8358a5e090da1014c31c3f >--- /dev/null >+++ b/JSTests/stress/in-by-id-match.js >@@ -0,0 +1,32 @@ >+function shouldBe(actual, expected) { >+ if (actual !== expected) >+ throw new Error('bad value: ' + actual); >+} >+ >+function test1(obj) >+{ >+ return "hello" in obj >+} >+noInline(test1); >+ >+let array = [ >+ [{ >+ hello: 42 >+ }, true], >+ [{ >+ world: 43 >+ }, false], >+ [{ >+ __proto__: { >+ hello: 44 >+ } >+ }, true] >+]; >+for (let i = 0; i < 1e5; ++i) { >+ for (let [obj, result] of array) >+ shouldBe(test1(obj), result); >+} >+ >+// OSRExits. >+for (let i = 0; i < 1e5; ++i) >+ shouldBe(test1({}), false);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 185803
:
340787
|
340788
|
340789
|
340793
|
341571