]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - interpreter/Interpreter.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / interpreter / Interpreter.h
... / ...
CommitLineData
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
46namespace 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