38c97af880e7dda28b5a59a41a8eaee26a94ecd1
[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 "Opcode.h"
33 #include "RegisterFile.h"
34 #include <kjs/list.h>
35 #include <wtf/HashMap.h>
36
37 namespace KJS {
38
39     class CodeBlock;
40     class EvalNode;
41     class ExecState;
42     class FunctionBodyNode;
43     class Instruction;
44     class JSFunction;
45     class JSGlobalObject;
46     class ProgramNode;
47     class Register;
48     class ScopeChainNode;
49
50     enum DebugHookID {
51         WillExecuteProgram,
52         DidExecuteProgram,
53         DidEnterCallFrame,
54         DidReachBreakpoint,
55         WillLeaveCallFrame,
56         WillExecuteStatement
57     };
58
59     enum { MaxReentryDepth = 128 };
60
61     class Machine {
62     public:
63         Machine();
64         
65         RegisterFile& registerFile() { return m_registerFile; }
66         
67         Opcode getOpcode(OpcodeID id)
68         {
69             #if HAVE(COMPUTED_GOTO)
70                 return m_opcodeTable[id];
71             #else
72                 return id;
73             #endif
74         }
75
76         OpcodeID getOpcodeID(Opcode opcode)
77         {
78             #if HAVE(COMPUTED_GOTO)
79                 ASSERT(isOpcode(opcode));
80                 return m_opcodeIDTable.get(opcode);
81             #else
82                 return opcode;
83             #endif
84         }
85
86         bool isOpcode(Opcode opcode);
87         
88         JSValue* execute(ProgramNode*, ExecState*, ScopeChainNode*, JSObject* thisObj, JSValue** exception);
89         JSValue* execute(FunctionBodyNode*, ExecState*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue** exception);
90         JSValue* execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue** exception)
91         {
92             return execute(evalNode, exec, thisObj, m_registerFile.size(), scopeChain, exception);
93         }
94
95         JSValue* retrieveArguments(ExecState*, JSFunction*) const;
96         JSValue* retrieveCaller(ExecState*, JSFunction*) const;
97
98         void getArgumentsData(Register* callFrame, JSFunction*&, Register*& argv, int& argc);
99         void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; }
100         
101         void startTimeoutCheck()
102         {
103             if (!m_timeoutCheckCount)
104                 resetTimeoutCheck();
105             
106             ++m_timeoutCheckCount;
107         }
108         
109         void stopTimeoutCheck()
110         {
111             --m_timeoutCheckCount;
112         }
113
114         inline void initTimeout()
115         {
116             resetTimeoutCheck();
117             m_timeoutTime = 0;
118             m_timeoutCheckCount = 0;
119         }
120
121     private:
122         enum ExecutionFlag { Normal, InitializeAndReturn };
123
124         friend NEVER_INLINE JSValue* callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile*, Register* r, int argv, int argc, JSValue*& exceptionValue);
125         JSValue* execute(EvalNode*, ExecState*, JSObject* thisObj, int registerOffset, ScopeChainNode*, JSValue** exception);
126
127         ALWAYS_INLINE void setScopeChain(ExecState* exec, ScopeChainNode*&, ScopeChainNode*);
128         NEVER_INLINE void debug(ExecState*, const Instruction*, const CodeBlock*, ScopeChainNode*, Register*);
129
130         NEVER_INLINE bool unwindCallFrame(ExecState*, JSValue*, const Instruction*&, CodeBlock*&, JSValue**&, ScopeChainNode*&, Register*&);
131         NEVER_INLINE Instruction* throwException(ExecState*, JSValue*, const Instruction*, CodeBlock*&, JSValue**&, ScopeChainNode*&, Register*&);
132
133         Register* callFrame(ExecState*, JSFunction*) const;
134
135         JSValue* privateExecute(ExecutionFlag, ExecState* = 0, RegisterFile* = 0, Register* = 0, ScopeChainNode* = 0, CodeBlock* = 0, JSValue** exception = 0);
136
137         void dumpCallFrame(const CodeBlock*, ScopeChainNode*, RegisterFile*, const Register*);
138         void dumpRegisters(const CodeBlock*, RegisterFile*, const Register*);
139
140         JSValue* checkTimeout(JSGlobalObject*);
141         void resetTimeoutCheck();
142
143         int m_reentryDepth;
144         unsigned m_timeoutTime;
145         unsigned m_timeAtLastCheckTimeout;
146         unsigned m_timeExecuting;
147         unsigned m_timeoutCheckCount;
148         unsigned m_ticksUntilNextTimeoutCheck;
149
150         RegisterFile m_registerFile;
151
152 #if HAVE(COMPUTED_GOTO)
153         Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
154         HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
155 #endif
156     };
157
158 } // namespace KJS
159
160 #endif // Machine_h