2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "Executable.h"
31 #include "JSFunction.h"
35 // The CallVariant class is meant to encapsulate a callee in a way that is useful for call linking
36 // and inlining. Because JavaScript has closures, and because JSC implements the notion of internal
37 // non-function objects that nevertheless provide call traps, the call machinery wants to see a
38 // callee in one of the following four forms:
40 // JSFunction callee: This means that we expect the callsite to always call a particular function
41 // instance, that is associated with a particular lexical environment. This pinpoints not
42 // just the code that will be called (i.e. the executable) but also the scope within which
45 // Executable callee: This corresponds to a call to a closure. In this case, we know that the
46 // callsite will call a JSFunction, but we do not know which particular JSFunction. We do know
47 // what code will be called - i.e. we know the executable.
49 // InternalFunction callee: JSC supports a special kind of native functions that support bizarre
50 // semantics. These are always singletons. If we know that the callee is an InternalFunction
51 // then we know both the code that will be called and the scope; in fact the "scope" is really
52 // just the InternalFunction itself.
54 // Something else: It's possible call all manner of rubbish in JavaScript. This implicitly supports
55 // bizarre object callees, but it can't really tell you anything interesting about them other
56 // than the fact that they don't fall into any of the above categories.
58 // This class serves as a kind of union over these four things. It does so by just holding a
59 // JSCell*. We determine which of the modes its in by doing type checks on the cell. Note that we
60 // cannot use WriteBarrier<> here because this gets used inside the compiler.
64 explicit CallVariant(JSCell
* callee
= nullptr)
69 CallVariant(WTF::HashTableDeletedValueType
)
70 : m_callee(deletedToken())
74 bool operator!() const { return !m_callee
; }
76 // If this variant refers to a function, change it to refer to its executable.
77 ALWAYS_INLINE CallVariant
despecifiedClosure() const
79 if (m_callee
->type() == JSFunctionType
)
80 return CallVariant(jsCast
<JSFunction
*>(m_callee
)->executable());
84 JSCell
* rawCalleeCell() const { return m_callee
; }
86 InternalFunction
* internalFunction() const
88 return jsDynamicCast
<InternalFunction
*>(m_callee
);
91 JSFunction
* function() const
93 return jsDynamicCast
<JSFunction
*>(m_callee
);
96 bool isClosureCall() const { return !!jsDynamicCast
<ExecutableBase
*>(m_callee
); }
98 ExecutableBase
* executable() const
100 if (JSFunction
* function
= this->function())
101 return function
->executable();
102 return jsDynamicCast
<ExecutableBase
*>(m_callee
);
105 JSCell
* nonExecutableCallee() const
107 RELEASE_ASSERT(!isClosureCall());
111 Intrinsic
intrinsicFor(CodeSpecializationKind kind
) const
113 if (ExecutableBase
* executable
= this->executable())
114 return executable
->intrinsicFor(kind
);
118 FunctionExecutable
* functionExecutable() const
120 if (ExecutableBase
* executable
= this->executable())
121 return jsDynamicCast
<FunctionExecutable
*>(executable
);
125 void dump(PrintStream
& out
) const;
127 bool isHashTableDeletedValue() const
129 return m_callee
== deletedToken();
132 bool operator==(const CallVariant
& other
) const
134 return m_callee
== other
.m_callee
;
137 bool operator!=(const CallVariant
& other
) const
139 return !(*this == other
);
142 bool operator<(const CallVariant
& other
) const
144 return m_callee
< other
.m_callee
;
147 bool operator>(const CallVariant
& other
) const
149 return other
< *this;
152 bool operator<=(const CallVariant
& other
) const
154 return !(*this < other
);
157 bool operator>=(const CallVariant
& other
) const
159 return other
<= *this;
162 unsigned hash() const
164 return WTF::PtrHash
<JSCell
*>::hash(m_callee
);
168 static JSCell
* deletedToken() { return bitwise_cast
<JSCell
*>(static_cast<uintptr_t>(1)); }
173 struct CallVariantHash
{
174 static unsigned hash(const CallVariant
& key
) { return key
.hash(); }
175 static bool equal(const CallVariant
& a
, const CallVariant
& b
) { return a
== b
; }
176 static const bool safeToCompareToEmptyOrDeleted
= true;
179 typedef Vector
<CallVariant
, 1> CallVariantList
;
181 // Returns a new variant list by attempting to either append the given variant or merge it with one
182 // of the variants we already have by despecifying closures.
183 CallVariantList
variantListWithVariant(const CallVariantList
&, CallVariant
);
185 // Returns a new list where every element is despecified, and the list is deduplicated.
186 CallVariantList
despecifiedVariantList(const CallVariantList
&);
192 template<typename T
> struct DefaultHash
;
193 template<> struct DefaultHash
<JSC::CallVariant
> {
194 typedef JSC::CallVariantHash Hash
;
197 template<typename T
> struct HashTraits
;
198 template<> struct HashTraits
<JSC::CallVariant
> : SimpleClassHashTraits
<JSC::CallVariant
> { };
202 #endif // CallVariant_h