finally blocks should not set the exception stack trace when re-throwing the exception.
[WebKit-https.git] / Source / JavaScriptCore / interpreter / Interpreter.h
1 /*
2  * Copyright (C) 2008, 2013, 2015 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 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 "JSObject.h"
37 #include "JSStack.h"
38 #include "LLIntData.h"
39 #include "Opcode.h"
40 #include "SourceProvider.h"
41 #include "StackAlignment.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 JSFunction;
54     class JSGlobalObject;
55     class LLIntOffsetsExtractor;
56     class ProgramExecutable;
57     class Register;
58     class JSScope;
59     class SamplingTool;
60     struct CallFrameClosure;
61     struct HandlerInfo;
62     struct Instruction;
63     struct ProtoCallFrame;
64
65     enum DebugHookID {
66         WillExecuteProgram,
67         DidExecuteProgram,
68         DidEnterCallFrame,
69         DidReachBreakpoint,
70         WillLeaveCallFrame,
71         WillExecuteStatement
72     };
73
74     enum StackFrameCodeType {
75         StackFrameGlobalCode,
76         StackFrameEvalCode,
77         StackFrameFunctionCode,
78         StackFrameNativeCode
79     };
80
81     struct StackFrame {
82         Strong<JSObject> callee;
83         StackFrameCodeType codeType;
84         Strong<ScriptExecutable> executable;
85         Strong<UnlinkedCodeBlock> codeBlock;
86         RefPtr<SourceProvider> code;
87         int lineOffset;
88         unsigned firstLineColumnOffset;
89         unsigned characterOffset;
90         unsigned bytecodeOffset;
91         String sourceURL;
92         JS_EXPORT_PRIVATE String toString(CallFrame*);
93         String friendlySourceURL() const;
94         String friendlyFunctionName(CallFrame*) const;
95         JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
96
97     private:
98         void expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
99     };
100
101     class SuspendExceptionScope {
102     public:
103         SuspendExceptionScope(VM* vm)
104             : m_vm(vm)
105         {
106             oldException = vm->exception();
107             vm->clearException();
108         }
109         ~SuspendExceptionScope()
110         {
111             m_vm->setException(oldException);
112         }
113     private:
114         Exception* oldException;
115         VM* m_vm;
116     };
117     
118     class TopCallFrameSetter {
119     public:
120         TopCallFrameSetter(VM& currentVM, CallFrame* callFrame)
121             : vm(currentVM)
122             , oldCallFrame(currentVM.topCallFrame) 
123         {
124             currentVM.topCallFrame = callFrame;
125         }
126         
127         ~TopCallFrameSetter() 
128         {
129             vm.topCallFrame = oldCallFrame;
130         }
131     private:
132         VM& vm;
133         CallFrame* oldCallFrame;
134     };
135     
136     class NativeCallFrameTracer {
137     public:
138         ALWAYS_INLINE NativeCallFrameTracer(VM* vm, CallFrame* callFrame)
139         {
140             ASSERT(vm);
141             ASSERT(callFrame);
142             vm->topCallFrame = callFrame;
143         }
144     };
145
146     class NativeCallFrameTracerWithRestore {
147     public:
148         ALWAYS_INLINE NativeCallFrameTracerWithRestore(VM* vm, VMEntryFrame* vmEntryFrame, CallFrame* callFrame)
149             : m_vm(vm)
150         {
151             ASSERT(vm);
152             ASSERT(callFrame);
153             m_savedTopVMEntryFrame = vm->topVMEntryFrame;
154             m_savedTopCallFrame = vm->topCallFrame;
155             vm->topVMEntryFrame = vmEntryFrame;
156             vm->topCallFrame = callFrame;
157         }
158
159         ALWAYS_INLINE ~NativeCallFrameTracerWithRestore()
160         {
161             m_vm->topVMEntryFrame = m_savedTopVMEntryFrame;
162             m_vm->topCallFrame = m_savedTopCallFrame;
163         }
164
165     private:
166         VM* m_vm;
167         VMEntryFrame* m_savedTopVMEntryFrame;
168         CallFrame* m_savedTopCallFrame;
169     };
170
171     class Interpreter {
172         WTF_MAKE_FAST_ALLOCATED;
173         friend class CachedCall;
174         friend class LLIntOffsetsExtractor;
175         friend class JIT;
176         friend class VM;
177
178     public:
179         Interpreter(VM &);
180         ~Interpreter();
181         
182         void initialize(bool canUseJIT);
183
184         JSStack& stack() { return m_stack; }
185         
186         Opcode getOpcode(OpcodeID id)
187         {
188             ASSERT(m_initialized);
189 #if ENABLE(COMPUTED_GOTO_OPCODES)
190             return m_opcodeTable[id];
191 #else
192             return id;
193 #endif
194         }
195
196         OpcodeID getOpcodeID(Opcode opcode)
197         {
198             ASSERT(m_initialized);
199 #if ENABLE(COMPUTED_GOTO_OPCODES)
200             ASSERT(isOpcode(opcode));
201             return m_opcodeIDTable.get(opcode);
202 #else
203             return opcode;
204 #endif
205         }
206         
207         bool isOpcode(Opcode);
208
209         JSValue execute(ProgramExecutable*, CallFrame*, JSObject* thisObj);
210         JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&);
211         JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&);
212         JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, JSScope*);
213
214         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
215         
216         SamplingTool* sampler() { return m_sampler.get(); }
217
218         NEVER_INLINE HandlerInfo* unwind(VMEntryFrame*&, CallFrame*&, Exception*);
219         NEVER_INLINE void debug(CallFrame*, DebugHookID);
220         JSString* stackTraceAsString(ExecState*, Vector<StackFrame>);
221
222         static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState*);
223         static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState*);
224         static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState*);
225         static EncodedJSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState*);
226
227         void dumpSampleData(ExecState* exec);
228         void startSampling();
229         void stopSampling();
230
231         JS_EXPORT_PRIVATE void dumpCallFrame(CallFrame*);
232
233         void getStackTrace(Vector<StackFrame>& results, size_t maxStackSize = std::numeric_limits<size_t>::max());
234
235     private:
236         enum ExecutionFlag { Normal, InitializeAndReturn };
237
238         CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, ProtoCallFrame*, JSFunction*, int argumentCountIncludingThis, JSScope*, JSValue*);
239
240         JSValue execute(CallFrameClosure&);
241
242
243
244         void dumpRegisters(CallFrame*);
245         
246         bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
247
248         void enableSampler();
249         int m_sampleEntryDepth;
250         std::unique_ptr<SamplingTool> m_sampler;
251
252         VM& m_vm;
253         JSStack m_stack;
254         int m_errorHandlingModeReentry;
255         
256 #if ENABLE(COMPUTED_GOTO_OPCODES)
257         Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling
258         HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
259 #endif
260
261 #if !ASSERT_DISABLED
262         bool m_initialized;
263 #endif
264     };
265
266     JSValue eval(CallFrame*);
267
268     inline CallFrame* calleeFrameForVarargs(CallFrame* callFrame, unsigned numUsedStackSlots, unsigned argumentCountIncludingThis)
269     {
270         unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(
271             stackAlignmentRegisters(),
272             numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
273         return CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
274     }
275
276     unsigned sizeOfVarargs(CallFrame* exec, JSValue arguments, uint32_t firstVarArgOffset);
277     static const unsigned maxArguments = 0x10000;
278     unsigned sizeFrameForVarargs(CallFrame* exec, JSStack*, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset);
279     void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, JSValue source, uint32_t offset, uint32_t length);
280     void setupVarargsFrame(CallFrame* execCaller, CallFrame* execCallee, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
281     void setupVarargsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
282     
283 } // namespace JSC
284
285 #endif // Interpreter_h