1 | /* |
2 | * Copyright (C) 2008-2018 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 | #pragma once |
31 | |
32 | #include "ArgList.h" |
33 | #include "JSCJSValue.h" |
34 | #include "JSObject.h" |
35 | #include "Opcode.h" |
36 | #include "StackAlignment.h" |
37 | #include <wtf/HashMap.h> |
38 | |
39 | #if ENABLE(C_LOOP) |
40 | #include "CLoopStack.h" |
41 | #endif |
42 | |
43 | |
44 | namespace JSC { |
45 | |
46 | class CodeBlock; |
47 | class EvalExecutable; |
48 | class FunctionExecutable; |
49 | class VM; |
50 | class JSFunction; |
51 | class JSGlobalObject; |
52 | class JSModuleEnvironment; |
53 | class JSModuleRecord; |
54 | class ; |
55 | class ProgramExecutable; |
56 | class ModuleProgramExecutable; |
57 | class Register; |
58 | class JSScope; |
59 | class SourceCode; |
60 | class StackFrame; |
61 | struct CallFrameClosure; |
62 | struct HandlerInfo; |
63 | struct Instruction; |
64 | struct ProtoCallFrame; |
65 | |
66 | enum DebugHookType { |
67 | WillExecuteProgram, |
68 | DidExecuteProgram, |
69 | DidEnterCallFrame, |
70 | DidReachBreakpoint, |
71 | WillLeaveCallFrame, |
72 | WillExecuteStatement, |
73 | WillExecuteExpression, |
74 | }; |
75 | |
76 | enum StackFrameCodeType { |
77 | StackFrameGlobalCode, |
78 | StackFrameEvalCode, |
79 | StackFrameModuleCode, |
80 | StackFrameFunctionCode, |
81 | StackFrameNativeCode |
82 | }; |
83 | |
84 | class Interpreter { |
85 | WTF_MAKE_FAST_ALLOCATED; |
86 | friend class CachedCall; |
87 | friend class LLIntOffsetsExtractor; |
88 | friend class JIT; |
89 | friend class VM; |
90 | |
91 | public: |
92 | Interpreter(VM &); |
93 | ~Interpreter(); |
94 | |
95 | #if ENABLE(C_LOOP) |
96 | CLoopStack& cloopStack() { return m_cloopStack; } |
97 | #endif |
98 | |
99 | static inline Opcode getOpcode(OpcodeID); |
100 | |
101 | static inline OpcodeID getOpcodeID(Opcode); |
102 | |
103 | #if !ASSERT_DISABLED |
104 | static bool isOpcode(Opcode); |
105 | #endif |
106 | |
107 | JSValue executeProgram(const SourceCode&, CallFrame*, JSObject* thisObj); |
108 | JSValue executeModuleProgram(ModuleProgramExecutable*, CallFrame*, JSModuleEnvironment*); |
109 | JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&); |
110 | JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&, JSValue newTarget); |
111 | JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, JSScope*); |
112 | |
113 | void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); |
114 | |
115 | NEVER_INLINE HandlerInfo* unwind(VM&, CallFrame*&, Exception*); |
116 | void notifyDebuggerOfExceptionToBeThrown(VM&, CallFrame*, Exception*); |
117 | NEVER_INLINE void debug(CallFrame*, DebugHookType); |
118 | static String stackTraceAsString(VM&, const Vector<StackFrame>&); |
119 | |
120 | void getStackTrace(JSCell* owner, Vector<StackFrame>& results, size_t framesToSkip = 0, size_t maxStackSize = std::numeric_limits<size_t>::max()); |
121 | |
122 | private: |
123 | enum ExecutionFlag { Normal, InitializeAndReturn }; |
124 | |
125 | static JSValue checkedReturn(JSValue returnValue) |
126 | { |
127 | ASSERT(returnValue); |
128 | return returnValue; |
129 | } |
130 | |
131 | static JSObject* checkedReturn(JSObject* returnValue) |
132 | { |
133 | ASSERT(returnValue); |
134 | return returnValue; |
135 | } |
136 | |
137 | CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, ProtoCallFrame*, JSFunction*, int argumentCountIncludingThis, JSScope*, const ArgList&); |
138 | |
139 | JSValue execute(CallFrameClosure&); |
140 | |
141 | VM& m_vm; |
142 | #if ENABLE(C_LOOP) |
143 | CLoopStack m_cloopStack; |
144 | #endif |
145 | |
146 | #if ENABLE(COMPUTED_GOTO_OPCODES) |
147 | #if !USE(LLINT_EMBEDDED_OPCODE_ID) || !ASSERT_DISABLED |
148 | static HashMap<Opcode, OpcodeID>& opcodeIDTable(); // Maps Opcode => OpcodeID. |
149 | #endif // !USE(LLINT_EMBEDDED_OPCODE_ID) || !ASSERT_DISABLED |
150 | #endif // ENABLE(COMPUTED_GOTO_OPCODES) |
151 | }; |
152 | |
153 | JSValue eval(CallFrame*); |
154 | |
155 | inline CallFrame* calleeFrameForVarargs(CallFrame* callFrame, unsigned numUsedStackSlots, unsigned argumentCountIncludingThis) |
156 | { |
157 | // We want the new frame to be allocated on a stack aligned offset with a stack |
158 | // aligned size. Align the size here. |
159 | argumentCountIncludingThis = WTF::roundUpToMultipleOf( |
160 | stackAlignmentRegisters(), |
161 | argumentCountIncludingThis + CallFrame::headerSizeInRegisters) - CallFrame::headerSizeInRegisters; |
162 | |
163 | // Align the frame offset here. |
164 | unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf( |
165 | stackAlignmentRegisters(), |
166 | numUsedStackSlots + argumentCountIncludingThis + CallFrame::headerSizeInRegisters); |
167 | return CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset); |
168 | } |
169 | |
170 | unsigned sizeOfVarargs(CallFrame* exec, JSValue arguments, uint32_t firstVarArgOffset); |
171 | static const unsigned maxArguments = 0x10000; |
172 | unsigned sizeFrameForVarargs(CallFrame* exec, VM&, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset); |
173 | unsigned sizeFrameForForwardArguments(CallFrame* exec, VM&, unsigned numUsedStackSlots); |
174 | void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, JSValue source, uint32_t offset, uint32_t length); |
175 | void setupVarargsFrame(CallFrame* execCaller, CallFrame* execCallee, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length); |
176 | void setupVarargsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length); |
177 | void setupForwardArgumentsFrame(CallFrame* execCaller, CallFrame* execCallee, uint32_t length); |
178 | void setupForwardArgumentsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, uint32_t length); |
179 | |
180 | } // namespace JSC |
181 | |
182 | namespace WTF { |
183 | |
184 | class PrintStream; |
185 | |
186 | void printInternal(PrintStream&, JSC::DebugHookType); |
187 | |
188 | } // namespace WTF |
189 | |