]> git.saurik.com Git - apple/javascriptcore.git/blob - interpreter/StackVisitor.h
0036a789c58e19ae13b0d4abfb75583e9bb46734
[apple/javascriptcore.git] / interpreter / StackVisitor.h
1 /*
2 * Copyright (C) 2013, 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 StackVisitor_h
27 #define StackVisitor_h
28
29 #include "VMEntryRecord.h"
30 #include <wtf/text/WTFString.h>
31
32 namespace JSC {
33
34 struct CodeOrigin;
35 struct InlineCallFrame;
36
37 class CodeBlock;
38 class ExecState;
39 class JSFunction;
40 class JSObject;
41 class JSScope;
42 class ClonedArguments;
43 class Register;
44
45 typedef ExecState CallFrame;
46
47 class StackVisitor {
48 public:
49 class Frame {
50 public:
51 enum CodeType {
52 Global,
53 Eval,
54 Function,
55 Native
56 };
57
58 size_t index() const { return m_index; }
59 size_t argumentCountIncludingThis() const { return m_argumentCountIncludingThis; }
60 bool callerIsVMEntryFrame() const { return m_callerIsVMEntryFrame; }
61 CallFrame* callerFrame() const { return m_callerFrame; }
62 JSObject* callee() const { return m_callee; }
63 CodeBlock* codeBlock() const { return m_codeBlock; }
64 unsigned bytecodeOffset() const { return m_bytecodeOffset; }
65 #if ENABLE(DFG_JIT)
66 InlineCallFrame* inlineCallFrame() const { return m_inlineCallFrame; }
67 #endif
68
69 bool isJSFrame() const { return !!codeBlock(); }
70 #if ENABLE(DFG_JIT)
71 bool isInlinedFrame() const { return !!m_inlineCallFrame; }
72 #endif
73
74 JS_EXPORT_PRIVATE String functionName();
75 JS_EXPORT_PRIVATE String sourceURL();
76 JS_EXPORT_PRIVATE String toString();
77
78 CodeType codeType() const;
79 JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
80
81 ClonedArguments* createArguments();
82 VMEntryFrame* vmEntryFrame() const { return m_VMEntryFrame; }
83 CallFrame* callFrame() const { return m_callFrame; }
84
85 JS_EXPORT_PRIVATE void print(int indentLevel);
86
87 private:
88 Frame() { }
89 ~Frame() { }
90
91 void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
92 void setToEnd();
93
94 size_t m_index;
95 size_t m_argumentCountIncludingThis;
96 VMEntryFrame* m_VMEntryFrame;
97 VMEntryFrame* m_CallerVMEntryFrame;
98 CallFrame* m_callerFrame;
99 JSObject* m_callee;
100 CodeBlock* m_codeBlock;
101 unsigned m_bytecodeOffset;
102 bool m_callerIsVMEntryFrame;
103 #if ENABLE(DFG_JIT)
104 InlineCallFrame* m_inlineCallFrame;
105 #endif
106 CallFrame* m_callFrame;
107
108 friend class StackVisitor;
109 };
110
111 enum Status {
112 Continue = 0,
113 Done = 1
114 };
115
116 // StackVisitor::visit() expects a Functor that implements the following method:
117 // Status operator()(StackVisitor&);
118
119 template <typename Functor>
120 static void visit(CallFrame* startFrame, Functor& functor)
121 {
122 StackVisitor visitor(startFrame);
123 while (visitor->callFrame()) {
124 Status status = functor(visitor);
125 if (status != Continue)
126 break;
127 visitor.gotoNextFrame();
128 }
129 }
130
131 Frame& operator*() { return m_frame; }
132 ALWAYS_INLINE Frame* operator->() { return &m_frame; }
133
134 private:
135 JS_EXPORT_PRIVATE StackVisitor(CallFrame* startFrame);
136
137 JS_EXPORT_PRIVATE void gotoNextFrame();
138
139 void readFrame(CallFrame*);
140 void readNonInlinedFrame(CallFrame*, CodeOrigin* = 0);
141 #if ENABLE(DFG_JIT)
142 void readInlinedFrame(CallFrame*, CodeOrigin*);
143 #endif
144
145 Frame m_frame;
146 };
147
148 class CallerFunctor {
149 public:
150 CallerFunctor()
151 : m_hasSkippedFirstFrame(false)
152 , m_callerFrame(0)
153 {
154 }
155
156 CallFrame* callerFrame() const { return m_callerFrame; }
157
158 StackVisitor::Status operator()(StackVisitor& visitor)
159 {
160 if (!m_hasSkippedFirstFrame) {
161 m_hasSkippedFirstFrame = true;
162 return StackVisitor::Continue;
163 }
164
165 m_callerFrame = visitor->callFrame();
166 return StackVisitor::Done;
167 }
168
169 private:
170 bool m_hasSkippedFirstFrame;
171 CallFrame* m_callerFrame;
172 };
173
174 } // namespace JSC
175
176 #endif // StackVisitor_h
177