Source/JavaScriptCore: https://bugs.webkit.org/show_bug.cgi?id=119548
[WebKit-https.git] / Source / JavaScriptCore / interpreter / Interpreter.h
1 /*
2  * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #ifndef Interpreter_h
31 #define Interpreter_h
32
33 #include "ArgList.h"
34 #include "JSCJSValue.h"
35 #include "JSCell.h"
36 #include "JSFunction.h"
37 #include "JSObject.h"
38 #include "JSStack.h"
39 #include "LLIntData.h"
40 #include "Opcode.h"
41 #include "SourceProvider.h"
42
43 #include <wtf/HashMap.h>
44 #include <wtf/text/StringBuilder.h>
45
46 namespace JSC {
47
48     class CodeBlock;
49     class EvalExecutable;
50     class ExecutableBase;
51     class FunctionExecutable;
52     class VM;
53     class JSGlobalObject;
54     class LLIntOffsetsExtractor;
55     class ProgramExecutable;
56     class Register;
57     class JSScope;
58     class SamplingTool;
59     class StackIterator;
60     struct CallFrameClosure;
61     struct HandlerInfo;
62     struct Instruction;
63     
64     enum DebugHookID {
65         WillExecuteProgram,
66         DidExecuteProgram,
67         DidEnterCallFrame,
68         DidReachBreakpoint,
69         WillLeaveCallFrame,
70         WillExecuteStatement
71     };
72
73     enum StackFrameCodeType {
74         StackFrameGlobalCode,
75         StackFrameEvalCode,
76         StackFrameFunctionCode,
77         StackFrameNativeCode
78     };
79
80     struct StackFrame {
81         Strong<JSObject> callee;
82         StackFrameCodeType codeType;
83         Strong<ExecutableBase> executable;
84         Strong<UnlinkedCodeBlock> codeBlock;
85         RefPtr<SourceProvider> code;
86         int lineOffset;
87         unsigned firstLineColumnOffset;
88         unsigned characterOffset;
89         unsigned bytecodeOffset;
90         String sourceURL;
91         JS_EXPORT_PRIVATE String toString(CallFrame*);
92         String friendlySourceURL() const
93         {
94             String traceLine;
95
96             switch (codeType) {
97             case StackFrameEvalCode:
98             case StackFrameFunctionCode:
99             case StackFrameGlobalCode:
100                 if (!sourceURL.isEmpty())
101                     traceLine = sourceURL.impl();
102                 break;
103             case StackFrameNativeCode:
104                 traceLine = "[native code]";
105                 break;
106             }
107             return traceLine.isNull() ? emptyString() : traceLine;
108         }
109         String friendlyFunctionName(CallFrame* callFrame) const
110         {
111             String traceLine;
112             JSObject* stackFrameCallee = callee.get();
113
114             switch (codeType) {
115             case StackFrameEvalCode:
116                 traceLine = "eval code";
117                 break;
118             case StackFrameNativeCode:
119                 if (callee)
120                     traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl();
121                 break;
122             case StackFrameFunctionCode:
123                 traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl();
124                 break;
125             case StackFrameGlobalCode:
126                 traceLine = "global code";
127                 break;
128             }
129             return traceLine.isNull() ? emptyString() : traceLine;
130         }
131         JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
132
133     private:
134         void expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
135     };
136
137     class ClearExceptionScope {
138     public:
139         ClearExceptionScope(VM* vm): m_vm(vm)
140         {
141             vm->getExceptionInfo(oldException, oldExceptionStack);
142             vm->clearException();
143         }
144         ~ClearExceptionScope()
145         {
146             m_vm->setExceptionInfo(oldException, oldExceptionStack);
147         }
148     private:
149         JSC::JSValue oldException;
150         RefCountedArray<JSC::StackFrame> oldExceptionStack;
151         VM* m_vm;
152     };
153     
154     class TopCallFrameSetter {
155     public:
156         TopCallFrameSetter(VM& currentVM, CallFrame* callFrame)
157             : vm(currentVM)
158             , oldCallFrame(currentVM.topCallFrame) 
159         {
160             ASSERT(!callFrame->hasHostCallFrameFlag());
161             currentVM.topCallFrame = callFrame;
162         }
163         
164         ~TopCallFrameSetter() 
165         {
166             ASSERT(!oldCallFrame->hasHostCallFrameFlag());
167             vm.topCallFrame = oldCallFrame;
168         }
169     private:
170         VM& vm;
171         CallFrame* oldCallFrame;
172     };
173     
174     class NativeCallFrameTracer {
175     public:
176         ALWAYS_INLINE NativeCallFrameTracer(VM* vm, CallFrame* callFrame)
177         {
178             ASSERT(vm);
179             ASSERT(callFrame);
180             ASSERT(!callFrame->hasHostCallFrameFlag());
181             vm->topCallFrame = callFrame;
182         }
183     };
184
185     class Interpreter {
186         WTF_MAKE_FAST_ALLOCATED;
187         friend class CachedCall;
188         friend class LLIntOffsetsExtractor;
189         friend class JIT;
190         friend class VM;
191
192     public:
193         class ErrorHandlingMode {
194         public:
195             JS_EXPORT_PRIVATE ErrorHandlingMode(ExecState*);
196             JS_EXPORT_PRIVATE ~ErrorHandlingMode();
197         private:
198             Interpreter& m_interpreter;
199         };
200
201         Interpreter(VM &);
202         ~Interpreter();
203         
204         void initialize(bool canUseJIT);
205
206         JSStack& stack() { return m_stack; }
207         
208         Opcode getOpcode(OpcodeID id)
209         {
210             ASSERT(m_initialized);
211 #if ENABLE(COMPUTED_GOTO_OPCODES)
212             return m_opcodeTable[id];
213 #else
214             return id;
215 #endif
216         }
217
218         OpcodeID getOpcodeID(Opcode opcode)
219         {
220             ASSERT(m_initialized);
221 #if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
222             ASSERT(isOpcode(opcode));
223             return m_opcodeIDTable.get(opcode);
224 #else
225             return opcode;
226 #endif
227         }
228         
229         bool isOpcode(Opcode);
230
231         JSValue execute(ProgramExecutable*, CallFrame*, JSObject* thisObj);
232         JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&);
233         JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&);
234         JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, JSScope*);
235
236         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
237         
238         SamplingTool* sampler() { return m_sampler.get(); }
239
240         bool isInErrorHandlingMode() { return m_errorHandlingModeReentry; }
241
242         NEVER_INLINE HandlerInfo* unwind(CallFrame*&, JSValue&, unsigned bytecodeOffset);
243         NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine, int column);
244         JSString* stackTraceAsString(ExecState*, Vector<StackFrame>);
245
246         static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState*);
247         static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState*);
248         static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState*);
249         static EncodedJSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState*);
250
251         void dumpSampleData(ExecState* exec);
252         void startSampling();
253         void stopSampling();
254
255         JS_EXPORT_PRIVATE void dumpCallFrame(CallFrame*);
256
257     private:
258         enum ExecutionFlag { Normal, InitializeAndReturn };
259
260         CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argumentCountIncludingThis, JSScope*);
261         void endRepeatCall(CallFrameClosure&);
262         JSValue execute(CallFrameClosure&);
263
264         void getStackTrace(Vector<StackFrame>& results, size_t maxStackSize = std::numeric_limits<size_t>::max());
265         NEVER_INLINE bool unwindCallFrame(StackIterator&, JSValue);
266
267         void dumpRegisters(CallFrame*);
268         
269         bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
270
271         void enableSampler();
272         int m_sampleEntryDepth;
273         OwnPtr<SamplingTool> m_sampler;
274
275         VM& m_vm;
276         JSStack m_stack;
277         int m_errorHandlingModeReentry;
278         
279 #if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
280         Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling
281         HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
282 #endif
283
284 #if !ASSERT_DISABLED
285         bool m_initialized;
286 #endif
287     };
288
289     JSValue eval(CallFrame*);
290     CallFrame* loadVarargs(CallFrame*, JSStack*, JSValue thisValue, JSValue arguments, int firstFreeRegister);
291
292 } // namespace JSC
293
294 #endif // Interpreter_h