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