Implement try/catch in the DFG.
[WebKit-https.git] / Source / JavaScriptCore / 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             Module,
56             Native
57         };
58
59         size_t index() const { return m_index; }
60         size_t argumentCountIncludingThis() const { return m_argumentCountIncludingThis; }
61         bool callerIsVMEntryFrame() const { return m_callerIsVMEntryFrame; }
62         CallFrame* callerFrame() const { return m_callerFrame; }
63         JSObject* callee() const { return m_callee; }
64         CodeBlock* codeBlock() const { return m_codeBlock; }
65         unsigned bytecodeOffset() const { return m_bytecodeOffset; }
66 #if ENABLE(DFG_JIT)
67         InlineCallFrame* inlineCallFrame() const { return m_inlineCallFrame; }
68 #endif
69
70         bool isJSFrame() const { return !!codeBlock(); }
71 #if ENABLE(DFG_JIT)
72         bool isInlinedFrame() const { return !!m_inlineCallFrame; }
73 #endif
74
75         JS_EXPORT_PRIVATE String functionName();
76         JS_EXPORT_PRIVATE String sourceURL();
77         JS_EXPORT_PRIVATE String toString();
78
79         CodeType codeType() const;
80         JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
81
82         ClonedArguments* createArguments();
83         VMEntryFrame* vmEntryFrame() const { return m_VMEntryFrame; }
84         CallFrame* callFrame() const { return m_callFrame; }
85         
86         JS_EXPORT_PRIVATE void print(int indentLevel);
87
88     private:
89         Frame() { }
90         ~Frame() { }
91
92         void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
93         void setToEnd();
94
95         size_t m_index;
96         size_t m_argumentCountIncludingThis;
97         VMEntryFrame* m_VMEntryFrame;
98         VMEntryFrame* m_CallerVMEntryFrame;
99         CallFrame* m_callerFrame;
100         JSObject* m_callee;
101         CodeBlock* m_codeBlock;
102         unsigned m_bytecodeOffset;
103         bool m_callerIsVMEntryFrame;
104 #if ENABLE(DFG_JIT)
105         InlineCallFrame* m_inlineCallFrame;
106 #endif
107         CallFrame* m_callFrame;
108
109         friend class StackVisitor;
110     };
111
112     enum Status {
113         Continue = 0,
114         Done = 1
115     };
116
117     // StackVisitor::visit() expects a Functor that implements the following method:
118     //     Status operator()(StackVisitor&);
119
120     template <typename Functor>
121     static void visit(CallFrame* startFrame, Functor& functor)
122     {
123         StackVisitor visitor(startFrame);
124         while (visitor->callFrame()) {
125             Status status = functor(visitor);
126             if (status != Continue)
127                 break;
128             visitor.gotoNextFrame();
129         }
130     }
131
132     Frame& operator*() { return m_frame; }
133     ALWAYS_INLINE Frame* operator->() { return &m_frame; }
134     CodeBlock* unwindToMachineCodeBlockFrame();
135
136 private:
137     JS_EXPORT_PRIVATE StackVisitor(CallFrame* startFrame);
138
139     JS_EXPORT_PRIVATE void gotoNextFrame();
140
141     void readFrame(CallFrame*);
142     void readNonInlinedFrame(CallFrame*, CodeOrigin* = 0);
143 #if ENABLE(DFG_JIT)
144     void readInlinedFrame(CallFrame*, CodeOrigin*);
145 #endif
146
147     Frame m_frame;
148 };
149
150 class CallerFunctor {
151 public:
152     CallerFunctor()
153         : m_hasSkippedFirstFrame(false)
154         , m_callerFrame(0)
155     {
156     }
157
158     CallFrame* callerFrame() const { return m_callerFrame; }
159
160     StackVisitor::Status operator()(StackVisitor& visitor)
161     {
162         if (!m_hasSkippedFirstFrame) {
163             m_hasSkippedFirstFrame = true;
164             return StackVisitor::Continue;
165         }
166
167         m_callerFrame = visitor->callFrame();
168         return StackVisitor::Done;
169     }
170     
171 private:
172     bool m_hasSkippedFirstFrame;
173     CallFrame* m_callerFrame;
174 };
175
176 } // namespace JSC
177
178 #endif // StackVisitor_h
179