We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / bytecode / InstanceOfStatus.cpp
1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "InstanceOfStatus.h"
28
29 #include "ICStatusUtils.h"
30 #include "InstanceOfAccessCase.h"
31 #include "JSCInlines.h"
32 #include "PolymorphicAccess.h"
33 #include "StructureStubInfo.h"
34
35 namespace JSC {
36
37 void InstanceOfStatus::appendVariant(const InstanceOfVariant& variant)
38 {
39     appendICStatusVariant(m_variants, variant);
40 }
41
42 InstanceOfStatus InstanceOfStatus::computeFor(
43     CodeBlock* codeBlock, ICStatusMap& infoMap, unsigned bytecodeIndex)
44 {
45     ConcurrentJSLocker locker(codeBlock->m_lock);
46     
47     InstanceOfStatus result;
48 #if ENABLE(DFG_JIT)
49     result = computeForStubInfo(locker, infoMap.get(CodeOrigin(bytecodeIndex)).stubInfo);
50
51     if (!result.takesSlowPath()) {
52         UnlinkedCodeBlock* unlinkedCodeBlock = codeBlock->unlinkedCodeBlock();
53         ConcurrentJSLocker locker(unlinkedCodeBlock->m_lock);
54         // We also check for BadType here in case this is "primitive instanceof Foo".
55         if (unlinkedCodeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache))
56             || unlinkedCodeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadConstantCache))
57             || unlinkedCodeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadType)))
58             return TakesSlowPath;
59     }
60 #else
61     UNUSED_PARAM(infoMap);
62     UNUSED_PARAM(bytecodeIndex);
63 #endif
64     
65     return result;
66 }
67
68 #if ENABLE(DFG_JIT)
69 InstanceOfStatus InstanceOfStatus::computeForStubInfo(const ConcurrentJSLocker&, StructureStubInfo* stubInfo)
70 {
71     // FIXME: We wouldn't have to bail for nonCell if we taught MatchStructure how to handle non
72     // cells. If we fixed that then we wouldn't be able to use summary();
73     // https://bugs.webkit.org/show_bug.cgi?id=185784
74     StubInfoSummary summary = StructureStubInfo::summary(stubInfo);
75     if (!isInlineable(summary))
76         return InstanceOfStatus(summary);
77     
78     if (stubInfo->cacheType != CacheType::Stub)
79         return TakesSlowPath; // This is conservative. It could be that we have no information.
80     
81     PolymorphicAccess* list = stubInfo->u.stub;
82     InstanceOfStatus result;
83     for (unsigned listIndex = 0; listIndex < list->size(); ++listIndex) {
84         const AccessCase& access = list->at(listIndex);
85         
86         if (access.type() == AccessCase::InstanceOfGeneric)
87             return TakesSlowPath;
88         
89         if (!access.conditionSet().structuresEnsureValidity())
90             return TakesSlowPath;
91         
92         result.appendVariant(InstanceOfVariant(
93             access.structure(),
94             access.conditionSet(),
95             access.as<InstanceOfAccessCase>().prototype(),
96             access.type() == AccessCase::InstanceOfHit));
97     }
98     
99     return result;
100 }
101 #endif // ENABLE(DFG_JIT)
102
103 JSObject* InstanceOfStatus::commonPrototype() const
104 {
105     JSObject* prototype = nullptr;
106     for (const InstanceOfVariant& variant : m_variants) {
107         if (!prototype) {
108             prototype = variant.prototype();
109             continue;
110         }
111         if (prototype != variant.prototype())
112             return nullptr;
113     }
114     return prototype;
115 }
116
117 void InstanceOfStatus::filter(const StructureSet& structureSet)
118 {
119     if (m_state != Simple)
120         return;
121     filterICStatusVariants(m_variants, structureSet);
122     if (m_variants.isEmpty())
123         m_state = NoInformation;
124 }
125
126 } // namespace JSC
127