WebAssembly: Wasm::IndexOrName has a raw pointer to Name
[WebKit-https.git] / Source / JavaScriptCore / interpreter / StackVisitor.h
1 /*
2  * Copyright (C) 2013-2017 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 #pragma once
27
28 #include "CalleeBits.h"
29 #include "VMEntryRecord.h"
30 #include "WasmIndexOrName.h"
31 #include <functional>
32 #include <wtf/Indenter.h>
33 #include <wtf/text/WTFString.h>
34
35 namespace JSC {
36
37 struct CodeOrigin;
38 struct InlineCallFrame;
39
40 class CodeBlock;
41 class ExecState;
42 class JSCell;
43 class JSFunction;
44 class ClonedArguments;
45 class Register;
46 class RegisterAtOffsetList;
47
48 typedef ExecState CallFrame;
49
50 class StackVisitor {
51 public:
52     class Frame {
53     public:
54         enum CodeType {
55             Global,
56             Eval,
57             Function,
58             Module,
59             Native,
60             Wasm
61         };
62
63         size_t index() const { return m_index; }
64         size_t argumentCountIncludingThis() const { return m_argumentCountIncludingThis; }
65         bool callerIsEntryFrame() const { return m_callerIsEntryFrame; }
66         CallFrame* callerFrame() const { return m_callerFrame; }
67         CalleeBits callee() const { return m_callee; }
68         CodeBlock* codeBlock() const { return m_codeBlock; }
69         unsigned bytecodeOffset() const { return m_bytecodeOffset; }
70         InlineCallFrame* inlineCallFrame() const {
71 #if ENABLE(DFG_JIT)
72             return m_inlineCallFrame;
73 #else
74             return nullptr;
75 #endif
76         }
77
78         bool isNativeFrame() const { return !codeBlock() && !isWasmFrame(); }
79         bool isInlinedFrame() const { return !!inlineCallFrame(); }
80         bool isWasmFrame() const { return m_isWasmFrame; }
81         Wasm::IndexOrName const wasmFunctionIndexOrName()
82         {
83             ASSERT(isWasmFrame());
84             return m_wasmFunctionIndexOrName;
85         }
86
87         JS_EXPORT_PRIVATE String functionName() const;
88         JS_EXPORT_PRIVATE String sourceURL() const;
89         JS_EXPORT_PRIVATE String toString() const;
90
91         JS_EXPORT_PRIVATE intptr_t sourceID();
92
93         CodeType codeType() const;
94         bool hasLineAndColumnInfo() const;
95         JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column) const;
96
97         RegisterAtOffsetList* calleeSaveRegisters();
98
99         ClonedArguments* createArguments();
100         CallFrame* callFrame() const { return m_callFrame; }
101         
102         void dump(PrintStream&, Indenter = Indenter()) const;
103         void dump(PrintStream&, Indenter, std::function<void(PrintStream&)> prefix) const;
104
105     private:
106         Frame() { }
107         ~Frame() { }
108
109         void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) const;
110         void setToEnd();
111
112 #if ENABLE(DFG_JIT)
113         InlineCallFrame* m_inlineCallFrame;
114 #endif
115         CallFrame* m_callFrame;
116         EntryFrame* m_entryFrame;
117         EntryFrame* m_callerEntryFrame;
118         CallFrame* m_callerFrame;
119         CalleeBits m_callee;
120         CodeBlock* m_codeBlock;
121         size_t m_index;
122         size_t m_argumentCountIncludingThis;
123         unsigned m_bytecodeOffset;
124         bool m_callerIsEntryFrame : 1;
125         bool m_isWasmFrame : 1;
126         Wasm::IndexOrName m_wasmFunctionIndexOrName;
127
128         friend class StackVisitor;
129     };
130
131     enum Status {
132         Continue = 0,
133         Done = 1
134     };
135
136     // StackVisitor::visit() expects a Functor that implements the following method:
137     //     Status operator()(StackVisitor&) const;
138
139     template <typename Functor>
140     static void visit(CallFrame* startFrame, VM* vm, const Functor& functor)
141     {
142         StackVisitor visitor(startFrame, vm);
143         while (visitor->callFrame()) {
144             Status status = functor(visitor);
145             if (status != Continue)
146                 break;
147             visitor.gotoNextFrame();
148         }
149     }
150
151     Frame& operator*() { return m_frame; }
152     ALWAYS_INLINE Frame* operator->() { return &m_frame; }
153     void unwindToMachineCodeBlockFrame();
154
155 private:
156     JS_EXPORT_PRIVATE StackVisitor(CallFrame* startFrame, VM*);
157
158     JS_EXPORT_PRIVATE void gotoNextFrame();
159
160     void readFrame(CallFrame*);
161     void readNonInlinedFrame(CallFrame*, CodeOrigin* = 0);
162 #if ENABLE(DFG_JIT)
163     void readInlinedFrame(CallFrame*, CodeOrigin*);
164 #endif
165
166     Frame m_frame;
167 };
168
169 class CallerFunctor {
170 public:
171     CallerFunctor()
172         : m_hasSkippedFirstFrame(false)
173         , m_callerFrame(0)
174     {
175     }
176
177     CallFrame* callerFrame() const { return m_callerFrame; }
178
179     StackVisitor::Status operator()(StackVisitor& visitor) const
180     {
181         if (!m_hasSkippedFirstFrame) {
182             m_hasSkippedFirstFrame = true;
183             return StackVisitor::Continue;
184         }
185
186         m_callerFrame = visitor->callFrame();
187         return StackVisitor::Done;
188     }
189     
190 private:
191     mutable bool m_hasSkippedFirstFrame;
192     mutable CallFrame* m_callerFrame;
193 };
194
195 } // namespace JSC