initial import
[vuplus_webkit] / Source / JavaScriptCore / jit / JITStubCall.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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef JITStubCall_h
27 #define JITStubCall_h
28
29 #include "MacroAssemblerCodeRef.h"
30
31 #if ENABLE(JIT)
32
33 namespace JSC {
34
35     class JITStubCall {
36     public:
37         JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
38             : m_jit(jit)
39             , m_stub(stub)
40             , m_returnType(Cell)
41             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
42         {
43         }
44
45         JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
46             : m_jit(jit)
47             , m_stub(stub)
48             , m_returnType(Cell)
49             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
50         {
51         }
52
53         JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
54             : m_jit(jit)
55             , m_stub(stub)
56             , m_returnType(VoidPtr)
57             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
58         {
59         }
60
61         JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
62             : m_jit(jit)
63             , m_stub(stub)
64             , m_returnType(Int)
65             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
66         {
67         }
68
69         JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
70             : m_jit(jit)
71             , m_stub(stub)
72             , m_returnType(Int)
73             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
74         {
75         }
76
77         JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
78             : m_jit(jit)
79             , m_stub(stub)
80             , m_returnType(Void)
81             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
82         {
83         }
84
85 #if USE(JSVALUE32_64)
86         JITStubCall(JIT* jit, EncodedJSValue (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
87             : m_jit(jit)
88             , m_stub(stub)
89             , m_returnType(Value)
90             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
91         {
92         }
93 #endif
94
95         // Arguments are added first to last.
96
97         void skipArgument()
98         {
99             m_stackIndex += stackIndexStep;
100         }
101
102         void addArgument(JIT::TrustedImm32 argument)
103         {
104             m_jit->poke(argument, m_stackIndex);
105             m_stackIndex += stackIndexStep;
106         }
107
108         void addArgument(JIT::TrustedImmPtr argument)
109         {
110             m_jit->poke(argument, m_stackIndex);
111             m_stackIndex += stackIndexStep;
112         }
113
114         void addArgument(JIT::RegisterID argument)
115         {
116             m_jit->poke(argument, m_stackIndex);
117             m_stackIndex += stackIndexStep;
118         }
119         
120 #if USE(JSVALUE32_64)
121         void addArgument(const JSValue& value)
122         {
123             m_jit->poke(JIT::Imm32(value.payload()), m_stackIndex);
124             m_jit->poke(JIT::Imm32(value.tag()), m_stackIndex + 1);
125             m_stackIndex += stackIndexStep;
126         }
127 #endif
128
129         void addArgument(JIT::RegisterID tag, JIT::RegisterID payload)
130         {
131             m_jit->poke(payload, m_stackIndex);
132             m_jit->poke(tag, m_stackIndex + 1);
133             m_stackIndex += stackIndexStep;
134         }
135
136 #if USE(JSVALUE32_64)
137         void addArgument(unsigned srcVirtualRegister)
138         {
139             if (m_jit->m_codeBlock->isConstantRegisterIndex(srcVirtualRegister)) {
140                 addArgument(m_jit->getConstantOperand(srcVirtualRegister));
141                 return;
142             }
143
144             m_jit->emitLoad(srcVirtualRegister, JIT::regT1, JIT::regT0);
145             addArgument(JIT::regT1, JIT::regT0);
146         }
147
148         void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload)
149         {
150             size_t stackIndex = JITSTACKFRAME_ARGS_INDEX + (argumentNumber * stackIndexStep);
151             m_jit->peek(payload, stackIndex);
152             m_jit->peek(tag, stackIndex + 1);
153         }
154 #else
155         void addArgument(unsigned src, JIT::RegisterID scratchRegister) // src is a virtual register.
156         {
157             if (m_jit->m_codeBlock->isConstantRegisterIndex(src))
158                 addArgument(JIT::ImmPtr(JSValue::encode(m_jit->m_codeBlock->getConstant(src))));
159             else {
160                 m_jit->loadPtr(JIT::Address(JIT::callFrameRegister, src * sizeof(Register)), scratchRegister);
161                 addArgument(scratchRegister);
162             }
163             m_jit->killLastResultRegister();
164         }
165 #endif
166
167         JIT::Call call()
168         {
169 #if ENABLE(OPCODE_SAMPLING)
170             if (m_jit->m_bytecodeOffset != (unsigned)-1)
171                 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, true);
172 #endif
173
174             m_jit->restoreArgumentReference();
175             m_jit->updateTopCallFrame();
176             JIT::Call call = m_jit->call();
177             m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeOffset, m_stub.value()));
178
179 #if ENABLE(OPCODE_SAMPLING)
180             if (m_jit->m_bytecodeOffset != (unsigned)-1)
181                 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, false);
182 #endif
183
184 #if USE(JSVALUE32_64)
185             m_jit->unmap();
186 #else
187             m_jit->killLastResultRegister();
188 #endif
189             return call;
190         }
191
192 #if USE(JSVALUE32_64)
193         JIT::Call call(unsigned dst) // dst is a virtual register.
194         {
195             ASSERT(m_returnType == Value || m_returnType == Cell);
196             JIT::Call call = this->call();
197             if (m_returnType == Value)
198                 m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
199             else
200                 m_jit->emitStoreCell(dst, JIT::returnValueRegister);
201             return call;
202         }
203 #else
204         JIT::Call call(unsigned dst) // dst is a virtual register.
205         {
206             ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
207             JIT::Call call = this->call();
208             m_jit->emitPutVirtualRegister(dst);
209             return call;
210         }
211 #endif
212
213         JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
214         {
215 #if USE(JSVALUE32_64)
216             ASSERT(m_returnType == Value || m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
217 #else
218             ASSERT(m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
219 #endif
220             JIT::Call call = this->call();
221             if (dst != JIT::returnValueRegister)
222                 m_jit->move(JIT::returnValueRegister, dst);
223             return call;
224         }
225
226     private:
227         static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
228
229         JIT* m_jit;
230         FunctionPtr m_stub;
231         enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
232         size_t m_stackIndex;
233     };
234 }
235
236 #endif // ENABLE(JIT)
237
238 #endif // JITStubCall_h