f8862c5c8bfe80321a76288223af0179607bf52b
[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
42 #include <wtf/HashMap.h>
43 #include <wtf/text/StringBuilder.h>
44
45 namespace JSC {
46
47     class CodeBlock;
48     class EvalExecutable;
49     class ExecutableBase;
50     class FunctionExecutable;
51     class VM;
52     class JSGlobalObject;
53     class LLIntOffsetsExtractor;
54     class ProgramExecutable;
55     class Register;
56     class JSScope;
57     class SamplingTool;
58     class StackIterator;
59     struct CallFrameClosure;
60     struct HandlerInfo;
61     struct Instruction;
62     
63     enum DebugHookID {
64         WillExecuteProgram,
65         DidExecuteProgram,
66         DidEnterCallFrame,
67         DidReachBreakpoint,
68         WillLeaveCallFrame,
69         WillExecuteStatement
70     };
71
72     enum StackFrameCodeType {
73         StackFrameGlobalCode,
74         StackFrameEvalCode,
75         StackFrameFunctionCode,
76         StackFrameNativeCode
77     };
78
79     struct StackFrame {
80         Strong<JSObject> callee;
81         StackFrameCodeType codeType;
82         Strong<ExecutableBase> executable;
83         Strong<UnlinkedCodeBlock> codeBlock;
84         RefPtr<SourceProvider> code;
85         int lineOffset;
86         unsigned firstLineColumnOffset;
87         unsigned characterOffset;
88         unsigned bytecodeOffset;
89         String sourceURL;
90         JS_EXPORT_PRIVATE String toString(CallFrame*);
91         String friendlySourceURL() const
92         {
93             String traceLine;
94
95             switch (codeType) {
96             case StackFrameEvalCode:
97             case StackFrameFunctionCode:
98             case StackFrameGlobalCode:
99                 if (!sourceURL.isEmpty())
100                     traceLine = sourceURL.impl();
101                 break;
102             case StackFrameNativeCode:
103                 traceLine = "[native code]";
104                 break;
105             }
106             return traceLine.isNull() ? emptyString() : traceLine;
107         }
108         String friendlyFunctionName(CallFrame* callFrame) const
109         {
110             String traceLine;
111             JSObject* stackFrameCallee = callee.get();
112
113             switch (codeType) {
114             case StackFrameEvalCode:
115                 traceLine = "eval code";
116                 break;
117             case StackFrameNativeCode:
118                 if (callee)
119                     traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl();
120                 break;
121             case StackFrameFunctionCode:
122                 traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl();
123                 break;
124             case StackFrameGlobalCode:
125                 traceLine = "global code";
126                 break;
127             }
128             return traceLine.isNull() ? emptyString() : traceLine;
129         }
130         JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
131
132     private:
133         void expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
134     };
135
136     class TopCallFrameSetter {
137     public:
138         TopCallFrameSetter(VM& currentVM, CallFrame* callFrame)
139             : vm(currentVM)
140             , oldCallFrame(currentVM.topCallFrame) 
141         {
142             ASSERT(!callFrame->hasHostCallFrameFlag());
143             currentVM.topCallFrame = callFrame;
144         }
145         
146         ~TopCallFrameSetter() 
147         {
148             ASSERT(!oldCallFrame->hasHostCallFrameFlag());
149             vm.topCallFrame = oldCallFrame;
150         }
151     private:
152         VM& vm;
153         CallFrame* oldCallFrame;
154     };
155     
156     class NativeCallFrameTracer {
157     public:
158         ALWAYS_INLINE NativeCallFrameTracer(VM* vm, CallFrame* callFrame)
159         {
160             ASSERT(vm);
161             ASSERT(callFrame);
162             ASSERT(!callFrame->hasHostCallFrameFlag());
163             vm->topCallFrame = callFrame;
164         }
165     };
166
167     class Interpreter {
168         WTF_MAKE_FAST_ALLOCATED;
169         friend class CachedCall;
170         friend class LLIntOffsetsExtractor;
171         friend class JIT;
172
173     public:
174         class ErrorHandlingMode {
175         public:
176             JS_EXPORT_PRIVATE ErrorHandlingMode(ExecState*);
177             JS_EXPORT_PRIVATE ~ErrorHandlingMode();
178         private:
179             Interpreter& m_interpreter;
180         };
181
182         Interpreter(VM &);
183         ~Interpreter();
184         
185         void initialize(bool canUseJIT);
186
187         JSStack& stack() { return m_stack; }
188         
189         Opcode getOpcode(OpcodeID id)
190         {
191             ASSERT(m_initialized);
192 #if ENABLE(COMPUTED_GOTO_OPCODES)
193             return m_opcodeTable[id];
194 #else
195             return id;
196 #endif
197         }
198
199         OpcodeID getOpcodeID(Opcode opcode)
200         {
201             ASSERT(m_initialized);
202 #if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
203             ASSERT(isOpcode(opcode));
204             return m_opcodeIDTable.get(opcode);
205 #else
206             return opcode;
207 #endif
208         }
209         
210         bool isOpcode(Opcode);
211
212         JSValue execute(ProgramExecutable*, CallFrame*, JSObject* thisObj);
213         JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&);
214         JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&);
215         JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, JSScope*);
216
217         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
218         
219         SamplingTool* sampler() { return m_sampler.get(); }
220
221         bool isInErrorHandlingMode() { return m_errorHandlingModeReentry; }
222
223         NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset);
224         NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine, int column);
225         static void addStackTraceIfNecessary(CallFrame*, JSValue error);
226         JSString* stackTraceAsString(ExecState*, Vector<StackFrame>);
227
228         static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState*);
229         static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState*);
230         static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState*);
231         static EncodedJSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState*);
232
233         void dumpSampleData(ExecState* exec);
234         void startSampling();
235         void stopSampling();
236
237         JS_EXPORT_PRIVATE void dumpCallFrame(CallFrame*);
238
239     private:
240         enum ExecutionFlag { Normal, InitializeAndReturn };
241
242         CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argumentCountIncludingThis, JSScope*);
243         void endRepeatCall(CallFrameClosure&);
244         JSValue execute(CallFrameClosure&);
245
246         void getStackTrace(Vector<StackFrame>& results, size_t maxStackSize = std::numeric_limits<size_t>::max());
247         NEVER_INLINE bool unwindCallFrame(StackIterator&, JSValue);
248
249         void dumpRegisters(CallFrame*);
250         
251         bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
252
253         void enableSampler();
254         int m_sampleEntryDepth;
255         OwnPtr<SamplingTool> m_sampler;
256
257         VM& m_vm;
258         JSStack m_stack;
259         int m_errorHandlingModeReentry;
260         
261 #if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
262         Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling
263         HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
264 #endif
265
266 #if !ASSERT_DISABLED
267         bool m_initialized;
268 #endif
269     };
270
271     JSValue eval(CallFrame*);
272     CallFrame* loadVarargs(CallFrame*, JSStack*, JSValue thisValue, JSValue arguments, int firstFreeRegister);
273
274 } // namespace JSC
275
276 #endif // Interpreter_h