]> git.saurik.com Git - apple/javascriptcore.git/blame - bytecode/CodeOrigin.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / bytecode / CodeOrigin.h
CommitLineData
6fe7ccc8 1/*
93a37866 2 * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
6fe7ccc8
A
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
93a37866
A
29#include "CodeBlockHash.h"
30#include "CodeSpecializationKind.h"
81345200 31#include "JSFunction.h"
6fe7ccc8
A
32#include "ValueRecovery.h"
33#include "WriteBarrier.h"
93a37866 34#include <wtf/BitVector.h>
81345200 35#include <wtf/HashMap.h>
93a37866 36#include <wtf/PrintStream.h>
6fe7ccc8
A
37#include <wtf/StdLibExtras.h>
38#include <wtf/Vector.h>
39
40namespace JSC {
41
42struct InlineCallFrame;
93a37866 43class ExecState;
81345200 44class ScriptExecutable;
6fe7ccc8
A
45class JSFunction;
46
47struct CodeOrigin {
81345200 48 static const unsigned invalidBytecodeIndex = UINT_MAX;
93a37866 49
81345200
A
50 // Bytecode offset that you'd use to re-execute this instruction, and the
51 // bytecode index of the bytecode instruction that produces some result that
52 // you're interested in (used for mapping Nodes whose values you're using
53 // to bytecode instructions that have the appropriate value profile).
54 unsigned bytecodeIndex;
6fe7ccc8
A
55
56 InlineCallFrame* inlineCallFrame;
57
58 CodeOrigin()
81345200 59 : bytecodeIndex(invalidBytecodeIndex)
6fe7ccc8
A
60 , inlineCallFrame(0)
61 {
62 }
63
81345200
A
64 CodeOrigin(WTF::HashTableDeletedValueType)
65 : bytecodeIndex(invalidBytecodeIndex)
66 , inlineCallFrame(deletedMarker())
67 {
68 }
69
70 explicit CodeOrigin(unsigned bytecodeIndex, InlineCallFrame* inlineCallFrame = 0)
6fe7ccc8 71 : bytecodeIndex(bytecodeIndex)
6fe7ccc8
A
72 , inlineCallFrame(inlineCallFrame)
73 {
81345200 74 ASSERT(bytecodeIndex < invalidBytecodeIndex);
6fe7ccc8
A
75 }
76
81345200
A
77 bool isSet() const { return bytecodeIndex != invalidBytecodeIndex; }
78 bool operator!() const { return !isSet(); }
6fe7ccc8 79
81345200 80 bool isHashTableDeletedValue() const
6fe7ccc8 81 {
81345200 82 return bytecodeIndex == invalidBytecodeIndex && !!inlineCallFrame;
6fe7ccc8
A
83 }
84
85 // The inline depth is the depth of the inline stack, so 1 = not inlined,
86 // 2 = inlined one deep, etc.
87 unsigned inlineDepth() const;
88
89 // If the code origin corresponds to inlined code, gives you the heap object that
90 // would have owned the code if it had not been inlined. Otherwise returns 0.
81345200 91 ScriptExecutable* codeOriginOwner() const;
6fe7ccc8 92
81345200 93 int stackOffset() const;
93a37866 94
6fe7ccc8
A
95 static unsigned inlineDepthForCallFrame(InlineCallFrame*);
96
81345200 97 unsigned hash() const;
6fe7ccc8 98 bool operator==(const CodeOrigin& other) const;
6fe7ccc8
A
99 bool operator!=(const CodeOrigin& other) const { return !(*this == other); }
100
81345200
A
101 // This checks if the two code origins correspond to the same stack trace snippets,
102 // but ignore whether the InlineCallFrame's are identical.
103 bool isApproximatelyEqualTo(const CodeOrigin& other) const;
104
105 unsigned approximateHash() const;
106
6fe7ccc8
A
107 // Get the inline stack. This is slow, and is intended for debugging only.
108 Vector<CodeOrigin> inlineStack() const;
93a37866
A
109
110 void dump(PrintStream&) const;
81345200
A
111 void dumpInContext(PrintStream&, DumpContext*) const;
112
113private:
114 static InlineCallFrame* deletedMarker()
115 {
116 return bitwise_cast<InlineCallFrame*>(static_cast<uintptr_t>(1));
117 }
6fe7ccc8
A
118};
119
120struct InlineCallFrame {
81345200
A
121 Vector<ValueRecovery> arguments; // Includes 'this'.
122 WriteBarrier<ScriptExecutable> executable;
123 ValueRecovery calleeRecovery;
6fe7ccc8 124 CodeOrigin caller;
93a37866 125 BitVector capturedVars; // Indexed by the machine call frame's variable numbering.
81345200 126 signed stackOffset : 30;
6fe7ccc8 127 bool isCall : 1;
81345200
A
128 bool isClosureCall : 1; // If false then we know that callee/scope are constants and the DFG won't treat them as variables, i.e. they have to be recovered manually.
129 VirtualRegister argumentsRegister; // This is only set if the code uses arguments. The unmodified arguments register follows the unmodifiedArgumentsRegister() convention (see CodeBlock.h).
130
131 // There is really no good notion of a "default" set of values for
132 // InlineCallFrame's fields. This constructor is here just to reduce confusion if
133 // we forgot to initialize explicitly.
134 InlineCallFrame()
135 : stackOffset(0)
136 , isCall(false)
137 , isClosureCall(false)
138 {
139 }
93a37866
A
140
141 CodeSpecializationKind specializationKind() const { return specializationFromIsCall(isCall); }
81345200
A
142
143 JSFunction* calleeConstant() const
144 {
145 if (calleeRecovery.isConstant())
146 return jsCast<JSFunction*>(calleeRecovery.constant());
147 return 0;
148 }
149
150 void visitAggregate(SlotVisitor& visitor)
151 {
152 visitor.append(&executable);
153 }
93a37866
A
154
155 // Get the callee given a machine call frame to which this InlineCallFrame belongs.
156 JSFunction* calleeForCallFrame(ExecState*) const;
157
81345200 158 CString inferredName() const;
93a37866 159 CodeBlockHash hash() const;
81345200 160 CString hashAsStringIfPossible() const;
93a37866
A
161
162 CodeBlock* baselineCodeBlock() const;
163
81345200
A
164 ptrdiff_t callerFrameOffset() const { return stackOffset * sizeof(Register) + CallFrame::callerFrameOffset(); }
165 ptrdiff_t returnPCOffset() const { return stackOffset * sizeof(Register) + CallFrame::returnPCOffset(); }
166
93a37866
A
167 void dumpBriefFunctionInformation(PrintStream&) const;
168 void dump(PrintStream&) const;
81345200 169 void dumpInContext(PrintStream&, DumpContext*) const;
93a37866
A
170
171 MAKE_PRINT_METHOD(InlineCallFrame, dumpBriefFunctionInformation, briefFunctionInformation);
6fe7ccc8
A
172};
173
81345200 174inline int CodeOrigin::stackOffset() const
6fe7ccc8 175{
93a37866
A
176 if (!inlineCallFrame)
177 return 0;
178
179 return inlineCallFrame->stackOffset;
6fe7ccc8
A
180}
181
81345200
A
182inline unsigned CodeOrigin::hash() const
183{
184 return WTF::IntHash<unsigned>::hash(bytecodeIndex) +
185 WTF::PtrHash<InlineCallFrame*>::hash(inlineCallFrame);
186}
187
6fe7ccc8
A
188inline bool CodeOrigin::operator==(const CodeOrigin& other) const
189{
190 return bytecodeIndex == other.bytecodeIndex
191 && inlineCallFrame == other.inlineCallFrame;
192}
193
81345200 194inline ScriptExecutable* CodeOrigin::codeOriginOwner() const
6fe7ccc8
A
195{
196 if (!inlineCallFrame)
197 return 0;
198 return inlineCallFrame->executable.get();
199}
200
81345200
A
201struct CodeOriginHash {
202 static unsigned hash(const CodeOrigin& key) { return key.hash(); }
203 static bool equal(const CodeOrigin& a, const CodeOrigin& b) { return a == b; }
204 static const bool safeToCompareToEmptyOrDeleted = true;
205};
206
207struct CodeOriginApproximateHash {
208 static unsigned hash(const CodeOrigin& key) { return key.approximateHash(); }
209 static bool equal(const CodeOrigin& a, const CodeOrigin& b) { return a.isApproximatelyEqualTo(b); }
210 static const bool safeToCompareToEmptyOrDeleted = true;
211};
212
6fe7ccc8
A
213} // namespace JSC
214
81345200
A
215namespace WTF {
216
217template<typename T> struct DefaultHash;
218template<> struct DefaultHash<JSC::CodeOrigin> {
219 typedef JSC::CodeOriginHash Hash;
220};
221
222template<typename T> struct HashTraits;
223template<> struct HashTraits<JSC::CodeOrigin> : SimpleClassHashTraits<JSC::CodeOrigin> {
224 static const bool emptyValueIsZero = false;
225};
226
227} // namespace WTF
228
6fe7ccc8
A
229#endif // CodeOrigin_h
230