5bb4d6496b36241ff99fc82d8f17f8470bb6de93
[WebKit-https.git] / JavaScriptCore / VM / Machine.h
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #ifndef Machine_h
30 #define Machine_h
31
32 #include "ArgList.h"
33 #include "JSCell.h"
34 #include "JSValue.h"
35 #include "Opcode.h"
36 #include "RegisterFile.h"
37 #include <wtf/HashMap.h>
38
39 #if ENABLE(CTI)
40 #include "CTI.h"
41 #endif
42
43 namespace JSC {
44
45     class CodeBlock;
46     class EvalNode;
47     class ExecState;
48     class FunctionBodyNode;
49     class Instruction;
50     class InternalFunction;
51     class JSFunction;
52     class JSGlobalObject;
53     class ProgramNode;
54     class Register;
55     class ScopeChainNode;
56     class SamplingTool;
57
58     enum DebugHookID {
59         WillExecuteProgram,
60         DidExecuteProgram,
61         DidEnterCallFrame,
62         DidReachBreakpoint,
63         WillLeaveCallFrame,
64         WillExecuteStatement
65     };
66
67     enum { MaxReentryDepth = 128 };
68
69     class Machine {
70         friend class CTI;
71     public:
72         Machine();
73         ~Machine();
74         
75         RegisterFile& registerFile() { return m_registerFile; }
76         
77         static Opcode getOpcode(OpcodeID id);
78
79         OpcodeID getOpcodeID(Opcode opcode)
80         {
81             #if HAVE(COMPUTED_GOTO)
82                 ASSERT(isOpcode(opcode));
83                 return m_opcodeIDTable.get(opcode);
84             #else
85                 return opcode;
86             #endif
87         }
88
89         bool isOpcode(Opcode opcode);
90         
91         JSValue* execute(ProgramNode*, ExecState*, ScopeChainNode*, JSObject* thisObj, JSValue** exception);
92         JSValue* execute(FunctionBodyNode*, ExecState*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue** exception);
93         JSValue* execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue** exception);
94
95         JSValue* retrieveArguments(ExecState*, JSFunction*) const;
96         JSValue* retrieveCaller(ExecState*, InternalFunction*) const;
97         void retrieveLastCaller(ExecState* exec, int& lineNumber, int& sourceId, UString& sourceURL, JSValue*& function) const;
98
99         void getArgumentsData(Register* callFrame, JSFunction*&, int& firstParameterIndex, Register*& argv, int& argc);
100         void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; }
101         
102         void startTimeoutCheck()
103         {
104             if (!m_timeoutCheckCount)
105                 resetTimeoutCheck();
106             
107             ++m_timeoutCheckCount;
108         }
109         
110         void stopTimeoutCheck()
111         {
112             --m_timeoutCheckCount;
113         }
114
115         inline void initTimeout()
116         {
117             resetTimeoutCheck();
118             m_timeoutTime = 0;
119             m_timeoutCheckCount = 0;
120         }
121
122         SamplingTool* m_sampler;
123
124 #if ENABLE(CTI)
125 #if COMPILER(MSVC)
126 #define SFX_CALL __cdecl
127 #else
128 #define SFX_CALL
129 #endif
130
131         static void SFX_CALL cti_timeout_check(CTI_ARGS);
132
133         static void SFX_CALL cti_op_end(CTI_ARGS);
134         static JSValue* SFX_CALL cti_op_add(CTI_ARGS);
135         static JSValue* SFX_CALL cti_op_pre_inc(CTI_ARGS);
136         static int SFX_CALL cti_op_loop_if_less(CTI_ARGS);
137         static int SFX_CALL cti_op_loop_if_lesseq(CTI_ARGS);
138         static JSValue* SFX_CALL cti_op_new_object(CTI_ARGS);
139         static void SFX_CALL cti_op_put_by_id(CTI_ARGS);
140         static void SFX_CALL cti_op_put_by_id_second(CTI_ARGS);
141         static void SFX_CALL cti_op_put_by_id_generic(CTI_ARGS);
142         static void SFX_CALL cti_op_put_by_id_fail(CTI_ARGS);
143         static JSValue* SFX_CALL cti_op_get_by_id(CTI_ARGS);
144         static JSValue* SFX_CALL cti_op_get_by_id_second(CTI_ARGS);
145         static JSValue* SFX_CALL cti_op_get_by_id_generic(CTI_ARGS);
146         static JSValue* SFX_CALL cti_op_get_by_id_fail(CTI_ARGS);
147         static JSValue* SFX_CALL cti_op_del_by_id(CTI_ARGS);
148         static JSValue* SFX_CALL cti_op_instanceof(CTI_ARGS);
149         static JSValue* SFX_CALL cti_op_mul(CTI_ARGS);
150         static JSValue* SFX_CALL cti_op_new_func(CTI_ARGS);
151         static void* SFX_CALL cti_op_call_JSFunction(CTI_ARGS);
152         static JSValue* SFX_CALL cti_op_call_NotJSFunction(CTI_ARGS);
153         static void SFX_CALL cti_op_ret_activation(CTI_ARGS);
154         static void SFX_CALL cti_op_ret_profiler(CTI_ARGS);
155         static void SFX_CALL cti_op_ret_scopeChain(CTI_ARGS);
156         static JSValue* SFX_CALL cti_op_new_array(CTI_ARGS);
157         static JSValue* SFX_CALL cti_op_resolve(CTI_ARGS);
158         static JSValue* SFX_CALL cti_op_resolve_global(CTI_ARGS);
159         static void* SFX_CALL cti_op_construct_JSConstruct(CTI_ARGS);
160         static JSValue* SFX_CALL cti_op_construct_NotJSConstruct(CTI_ARGS);
161         static JSValue* SFX_CALL cti_op_get_by_val(CTI_ARGS);
162         static JSValue* SFX_CALL cti_op_resolve_func(CTI_ARGS);
163         static JSValue* SFX_CALL cti_op_sub(CTI_ARGS);
164         static void SFX_CALL cti_op_put_by_val(CTI_ARGS);
165         static void SFX_CALL cti_op_put_by_val_array(CTI_ARGS);
166         static JSValue* SFX_CALL cti_op_lesseq(CTI_ARGS);
167         static int SFX_CALL cti_op_loop_if_true(CTI_ARGS);
168         static JSValue* SFX_CALL cti_op_resolve_base(CTI_ARGS);
169         static JSValue* SFX_CALL cti_op_negate(CTI_ARGS);
170         static JSValue* SFX_CALL cti_op_resolve_skip(CTI_ARGS);
171         static JSValue* SFX_CALL cti_op_div(CTI_ARGS);
172         static JSValue* SFX_CALL cti_op_pre_dec(CTI_ARGS);
173         static int SFX_CALL cti_op_jless(CTI_ARGS);
174         static JSValue* SFX_CALL cti_op_not(CTI_ARGS);
175         static int SFX_CALL cti_op_jtrue(CTI_ARGS);
176         static JSValue* SFX_CALL cti_op_post_inc(CTI_ARGS);
177         static JSValue* SFX_CALL cti_op_eq(CTI_ARGS);
178         static JSValue* SFX_CALL cti_op_lshift(CTI_ARGS);
179         static JSValue* SFX_CALL cti_op_bitand(CTI_ARGS);
180         static JSValue* SFX_CALL cti_op_rshift(CTI_ARGS);
181         static JSValue* SFX_CALL cti_op_bitnot(CTI_ARGS);
182         static JSValue* SFX_CALL cti_op_resolve_with_base(CTI_ARGS);
183         static JSValue* SFX_CALL cti_op_new_func_exp(CTI_ARGS);
184         static JSValue* SFX_CALL cti_op_mod(CTI_ARGS);
185         static JSValue* SFX_CALL cti_op_less(CTI_ARGS);
186         static JSValue* SFX_CALL cti_op_neq(CTI_ARGS);
187         static JSValue* SFX_CALL cti_op_post_dec(CTI_ARGS);
188         static JSValue* SFX_CALL cti_op_urshift(CTI_ARGS);
189         static JSValue* SFX_CALL cti_op_bitxor(CTI_ARGS);
190         static JSValue* SFX_CALL cti_op_new_regexp(CTI_ARGS);
191         static JSValue* SFX_CALL cti_op_bitor(CTI_ARGS);
192         static JSValue* SFX_CALL cti_op_call_eval(CTI_ARGS);
193         static void* SFX_CALL cti_op_throw(CTI_ARGS);
194         static JSPropertyNameIterator* SFX_CALL cti_op_get_pnames(CTI_ARGS);
195         static JSValue* SFX_CALL cti_op_next_pname(CTI_ARGS);
196         static void SFX_CALL cti_op_push_scope(CTI_ARGS);
197         static void SFX_CALL cti_op_pop_scope(CTI_ARGS);
198         static JSValue* SFX_CALL cti_op_typeof(CTI_ARGS);
199         static JSValue* SFX_CALL cti_op_is_undefined(CTI_ARGS);
200         static JSValue* SFX_CALL cti_op_is_boolean(CTI_ARGS);
201         static JSValue* SFX_CALL cti_op_is_number(CTI_ARGS);
202         static JSValue* SFX_CALL cti_op_is_string(CTI_ARGS);
203         static JSValue* SFX_CALL cti_op_is_object(CTI_ARGS);
204         static JSValue* SFX_CALL cti_op_is_function(CTI_ARGS);
205         static JSValue* SFX_CALL cti_op_stricteq(CTI_ARGS);
206         static JSValue* SFX_CALL cti_op_nstricteq(CTI_ARGS);
207         static JSValue* SFX_CALL cti_op_to_jsnumber(CTI_ARGS);
208         static JSValue* SFX_CALL cti_op_in(CTI_ARGS);
209         static JSValue* SFX_CALL cti_op_push_new_scope(CTI_ARGS);
210         static void SFX_CALL cti_op_jmp_scopes(CTI_ARGS);
211         static void SFX_CALL cti_op_put_by_index(CTI_ARGS);
212         static void* SFX_CALL cti_op_switch_imm(CTI_ARGS);
213         static void* SFX_CALL cti_op_switch_char(CTI_ARGS);
214         static void* SFX_CALL cti_op_switch_string(CTI_ARGS);
215         static JSValue* SFX_CALL cti_op_del_by_val(CTI_ARGS);
216         static void SFX_CALL cti_op_put_getter(CTI_ARGS);
217         static void SFX_CALL cti_op_put_setter(CTI_ARGS);
218         static JSValue* SFX_CALL cti_op_new_error(CTI_ARGS);
219         static void SFX_CALL cti_op_debug(CTI_ARGS);
220
221         static void* SFX_CALL cti_vm_throw(CTI_ARGS);
222         static void* SFX_CALL cti_vm_compile(CTI_ARGS);
223         static void SFX_CALL cti_vm_updateScopeChain(CTI_ARGS);
224         
225 #endif // ENABLE(CTI)
226
227         // Default number of ticks before a timeout check should be done.
228         static const int initialTickCountThreshold = 1024;
229
230         bool isJSArray(JSValue* v) { return !JSImmediate::isImmediate(v) && v->asCell()->vptr() == m_jsArrayVptr; }
231         bool isJSString(JSValue* v) { return !JSImmediate::isImmediate(v) && v->asCell()->vptr() == m_jsStringVptr; }
232         
233     private:
234         enum ExecutionFlag { Normal, InitializeAndReturn };
235
236         NEVER_INLINE JSValue* callEval(ExecState* exec, CodeBlock* callingCodeBlock, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile*, Register* r, int argv, int argc, JSValue*& exceptionValue);
237         JSValue* execute(EvalNode*, ExecState*, JSObject* thisObj, int registerOffset, ScopeChainNode*, JSValue** exception);
238
239         ALWAYS_INLINE static void initializeCallFrame(Register* callFrame, CodeBlock*, Instruction*, ScopeChainNode*, Register* r, int returnValueRegister, int argc, JSValue* function);
240
241         ALWAYS_INLINE void setScopeChain(ExecState* exec, ScopeChainNode*&, ScopeChainNode*);
242         NEVER_INLINE void debug(ExecState*, const CodeBlock*, ScopeChainNode*, Register*, DebugHookID, int firstLine, int lastLine);
243
244         NEVER_INLINE bool unwindCallFrame(ExecState*, JSValue*, const Instruction*&, CodeBlock*&, ScopeChainNode*&, Register*&);
245         NEVER_INLINE Instruction* throwException(ExecState*, JSValue*&, const Instruction*, CodeBlock*&, ScopeChainNode*&, Register*&, bool);
246
247         Register* callFrame(ExecState*, InternalFunction*) const;
248
249         JSValue* privateExecute(ExecutionFlag, ExecState* = 0, RegisterFile* = 0, Register* = 0, ScopeChainNode* = 0, CodeBlock* = 0, JSValue** exception = 0);
250
251         void dumpCallFrame(const CodeBlock*, ScopeChainNode*, RegisterFile*, const Register*);
252         void dumpRegisters(const CodeBlock*, RegisterFile*, const Register*);
253
254         JSValue* checkTimeout(JSGlobalObject*);
255         void resetTimeoutCheck();
256
257         void tryCacheGetByID(ExecState*, CodeBlock*, Instruction* vPC, JSValue* baseValue, const Identifier& propertyName, const PropertySlot&);
258         void uncacheGetByID(CodeBlock*, Instruction* vPC);
259         void tryCachePutByID(ExecState* exec, CodeBlock*, Instruction* vPC, JSValue* baseValue, const PutPropertySlot&);
260         void uncachePutByID(CodeBlock*, Instruction* vPC);
261
262 #if ENABLE(CTI)
263         void tryCTICacheGetByID(ExecState*, CodeBlock*, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot&);
264         void tryCTICachePutByID(ExecState*, CodeBlock*, void* returnAddress, JSValue* baseValue, const PutPropertySlot&);
265
266         void* getCTIArrayLengthTrampoline(ExecState*, CodeBlock*);
267         void* getCTIStringLengthTrampoline(ExecState*, CodeBlock*);
268
269         void* m_ctiArrayLengthTrampoline;
270         void* m_ctiStringLengthTrampoline;
271
272         OwnPtr<JITCodeBuffer> m_jitCodeBuffer;
273         JITCodeBuffer* jitCodeBuffer() const { return m_jitCodeBuffer.get(); }
274 #endif
275
276         int m_reentryDepth;
277         unsigned m_timeoutTime;
278         unsigned m_timeAtLastCheckTimeout;
279         unsigned m_timeExecuting;
280         unsigned m_timeoutCheckCount;
281         unsigned m_ticksUntilNextTimeoutCheck;
282
283         RegisterFile m_registerFile;
284         
285         void* m_jsArrayVptr;
286         void* m_jsStringVptr;
287         void* m_jsFunctionVptr;
288
289 #if HAVE(COMPUTED_GOTO)
290         static Opcode s_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
291         HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
292 #endif
293     };
294
295 } // namespace JSC
296
297 #endif // Machine_h