Scopes that are not under TDZ should still push their variables onto the TDZ stack...
[WebKit-https.git] / Source / JavaScriptCore / bytecode / CodeOrigin.h
1 /*
2  * Copyright (C) 2011-2015 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 #ifndef CodeOrigin_h
27 #define CodeOrigin_h
28
29 #include "CallMode.h"
30 #include "CodeBlockHash.h"
31 #include "CodeSpecializationKind.h"
32 #include "WriteBarrier.h"
33 #include <wtf/BitVector.h>
34 #include <wtf/HashMap.h>
35 #include <wtf/PrintStream.h>
36 #include <wtf/StdLibExtras.h>
37 #include <wtf/Vector.h>
38
39 namespace JSC {
40
41 struct InlineCallFrame;
42 class ExecState;
43 class ScriptExecutable;
44 class JSFunction;
45
46 struct CodeOrigin {
47     static const unsigned invalidBytecodeIndex = UINT_MAX;
48     
49     // Bytecode offset that you'd use to re-execute this instruction, and the
50     // bytecode index of the bytecode instruction that produces some result that
51     // you're interested in (used for mapping Nodes whose values you're using
52     // to bytecode instructions that have the appropriate value profile).
53     unsigned bytecodeIndex;
54     
55     InlineCallFrame* inlineCallFrame;
56     
57     CodeOrigin()
58         : bytecodeIndex(invalidBytecodeIndex)
59         , inlineCallFrame(0)
60     {
61     }
62     
63     CodeOrigin(WTF::HashTableDeletedValueType)
64         : bytecodeIndex(invalidBytecodeIndex)
65         , inlineCallFrame(deletedMarker())
66     {
67     }
68     
69     explicit CodeOrigin(unsigned bytecodeIndex, InlineCallFrame* inlineCallFrame = 0)
70         : bytecodeIndex(bytecodeIndex)
71         , inlineCallFrame(inlineCallFrame)
72     {
73         ASSERT(bytecodeIndex < invalidBytecodeIndex);
74     }
75     
76     bool isSet() const { return bytecodeIndex != invalidBytecodeIndex; }
77     explicit operator bool() const { return isSet(); }
78     
79     bool isHashTableDeletedValue() const
80     {
81         return bytecodeIndex == invalidBytecodeIndex && !!inlineCallFrame;
82     }
83     
84     // The inline depth is the depth of the inline stack, so 1 = not inlined,
85     // 2 = inlined one deep, etc.
86     unsigned inlineDepth() const;
87     
88     // If the code origin corresponds to inlined code, gives you the heap object that
89     // would have owned the code if it had not been inlined. Otherwise returns 0.
90     CodeBlock* codeOriginOwner() const;
91     
92     int stackOffset() const;
93     
94     static unsigned inlineDepthForCallFrame(InlineCallFrame*);
95     
96     unsigned hash() const;
97     bool operator==(const CodeOrigin& other) const;
98     bool operator!=(const CodeOrigin& other) const { return !(*this == other); }
99     
100     // This checks if the two code origins correspond to the same stack trace snippets,
101     // but ignore whether the InlineCallFrame's are identical.
102     bool isApproximatelyEqualTo(const CodeOrigin& other) const;
103     
104     unsigned approximateHash() const;
105
106     template <typename Function>
107     void walkUpInlineStack(const Function&);
108     
109     // Get the inline stack. This is slow, and is intended for debugging only.
110     Vector<CodeOrigin> inlineStack() const;
111     
112     JS_EXPORT_PRIVATE void dump(PrintStream&) const;
113     void dumpInContext(PrintStream&, DumpContext*) const;
114
115 private:
116     static InlineCallFrame* deletedMarker()
117     {
118         return bitwise_cast<InlineCallFrame*>(static_cast<uintptr_t>(1));
119     }
120 };
121
122 inline unsigned CodeOrigin::hash() const
123 {
124     return WTF::IntHash<unsigned>::hash(bytecodeIndex) +
125         WTF::PtrHash<InlineCallFrame*>::hash(inlineCallFrame);
126 }
127
128 inline bool CodeOrigin::operator==(const CodeOrigin& other) const
129 {
130     return bytecodeIndex == other.bytecodeIndex
131         && inlineCallFrame == other.inlineCallFrame;
132 }
133
134 struct CodeOriginHash {
135     static unsigned hash(const CodeOrigin& key) { return key.hash(); }
136     static bool equal(const CodeOrigin& a, const CodeOrigin& b) { return a == b; }
137     static const bool safeToCompareToEmptyOrDeleted = true;
138 };
139
140 struct CodeOriginApproximateHash {
141     static unsigned hash(const CodeOrigin& key) { return key.approximateHash(); }
142     static bool equal(const CodeOrigin& a, const CodeOrigin& b) { return a.isApproximatelyEqualTo(b); }
143     static const bool safeToCompareToEmptyOrDeleted = true;
144 };
145
146 } // namespace JSC
147
148 namespace WTF {
149
150 template<typename T> struct DefaultHash;
151 template<> struct DefaultHash<JSC::CodeOrigin> {
152     typedef JSC::CodeOriginHash Hash;
153 };
154
155 template<typename T> struct HashTraits;
156 template<> struct HashTraits<JSC::CodeOrigin> : SimpleClassHashTraits<JSC::CodeOrigin> {
157     static const bool emptyValueIsZero = false;
158 };
159
160 } // namespace WTF
161
162 #endif // CodeOrigin_h
163