Templatize CodePtr/Refs/FunctionPtrs with PtrTags.
[WebKit-https.git] / Source / JavaScriptCore / bytecode / GetByIdVariant.cpp
1 /*
2  * Copyright (C) 2014-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 "GetByIdVariant.h"
28
29 #include "CallLinkStatus.h"
30 #include "JSCInlines.h"
31 #include <wtf/ListDump.h>
32
33 namespace JSC {
34
35 GetByIdVariant::GetByIdVariant(
36     const StructureSet& structureSet, PropertyOffset offset,
37     const ObjectPropertyConditionSet& conditionSet,
38     std::unique_ptr<CallLinkStatus> callLinkStatus,
39     JSFunction* intrinsicFunction,
40     FunctionPtr<OperationPtrTag> customAccessorGetter,
41     std::optional<DOMAttributeAnnotation> domAttribute)
42     : m_structureSet(structureSet)
43     , m_conditionSet(conditionSet)
44     , m_offset(offset)
45     , m_callLinkStatus(WTFMove(callLinkStatus))
46     , m_intrinsicFunction(intrinsicFunction)
47     , m_customAccessorGetter(customAccessorGetter)
48     , m_domAttribute(domAttribute)
49 {
50     if (!structureSet.size()) {
51         ASSERT(offset == invalidOffset);
52         ASSERT(conditionSet.isEmpty());
53     }
54     if (intrinsicFunction)
55         ASSERT(intrinsic() != NoIntrinsic);
56 }
57                      
58 GetByIdVariant::~GetByIdVariant() { }
59
60 GetByIdVariant::GetByIdVariant(const GetByIdVariant& other)
61     : GetByIdVariant()
62 {
63     *this = other;
64 }
65
66 GetByIdVariant& GetByIdVariant::operator=(const GetByIdVariant& other)
67 {
68     m_structureSet = other.m_structureSet;
69     m_conditionSet = other.m_conditionSet;
70     m_offset = other.m_offset;
71     m_intrinsicFunction = other.m_intrinsicFunction;
72     m_customAccessorGetter = other.m_customAccessorGetter;
73     m_domAttribute = other.m_domAttribute;
74     if (other.m_callLinkStatus)
75         m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
76     else
77         m_callLinkStatus = nullptr;
78     return *this;
79 }
80
81 inline bool GetByIdVariant::canMergeIntrinsicStructures(const GetByIdVariant& other) const
82 {
83     if (m_intrinsicFunction != other.m_intrinsicFunction)
84         return false;
85     switch (intrinsic()) {
86     case TypedArrayByteLengthIntrinsic: {
87         // We can merge these sets as long as the element size of the two sets is the same.
88         TypedArrayType thisType = (*m_structureSet.begin())->classInfo()->typedArrayStorageType;
89         TypedArrayType otherType = (*other.m_structureSet.begin())->classInfo()->typedArrayStorageType;
90
91         ASSERT(isTypedView(thisType) && isTypedView(otherType));
92
93         return logElementSize(thisType) == logElementSize(otherType);
94     }
95
96     default:
97         return true;
98     }
99     RELEASE_ASSERT_NOT_REACHED();
100 }
101
102 bool GetByIdVariant::attemptToMerge(const GetByIdVariant& other)
103 {
104     if (m_offset != other.m_offset)
105         return false;
106     if (m_callLinkStatus || other.m_callLinkStatus)
107         return false;
108
109     if (!canMergeIntrinsicStructures(other))
110         return false;
111
112     if (m_customAccessorGetter != other.m_customAccessorGetter)
113         return false;
114
115     if (m_domAttribute || other.m_domAttribute) {
116         if (!(m_domAttribute && other.m_domAttribute))
117             return false;
118         if (*m_domAttribute != *other.m_domAttribute)
119             return false;
120     }
121
122     if (m_conditionSet.isEmpty() != other.m_conditionSet.isEmpty())
123         return false;
124     
125     ObjectPropertyConditionSet mergedConditionSet;
126     if (!m_conditionSet.isEmpty()) {
127         mergedConditionSet = m_conditionSet.mergedWith(other.m_conditionSet);
128         if (!mergedConditionSet.isValid() || !mergedConditionSet.hasOneSlotBaseCondition())
129             return false;
130     }
131     m_conditionSet = mergedConditionSet;
132     
133     m_structureSet.merge(other.m_structureSet);
134     
135     return true;
136 }
137
138 void GetByIdVariant::dump(PrintStream& out) const
139 {
140     dumpInContext(out, 0);
141 }
142
143 void GetByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const
144 {
145     if (!isSet()) {
146         out.print("<empty>");
147         return;
148     }
149     
150     out.print(
151         "<", inContext(structureSet(), context), ", ", inContext(m_conditionSet, context));
152     out.print(", offset = ", offset());
153     if (m_callLinkStatus)
154         out.print(", call = ", *m_callLinkStatus);
155     if (m_intrinsicFunction)
156         out.print(", intrinsic = ", *m_intrinsicFunction);
157     if (m_customAccessorGetter)
158         out.print(", customaccessorgetter = ", RawPointer(m_customAccessorGetter.executableAddress()));
159     if (m_domAttribute) {
160         out.print(", domclass = ", RawPointer(m_domAttribute->classInfo));
161         if (m_domAttribute->domJIT)
162             out.print(", domjit = ", RawPointer(m_domAttribute->domJIT));
163     }
164     out.print(">");
165 }
166
167 } // namespace JSC
168