• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <wtf/Platform.h>
30 
31 #if ENABLE(JIT)
32 
33 namespace JSC {
34 
35     class JITStubCall {
36     public:
JITStubCall(JIT * jit,JSObject * (JIT_STUB * stub)(STUB_ARGS_DECLARATION))37         JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
38             : m_jit(jit)
39             , m_stub(reinterpret_cast<void*>(stub))
40             , m_returnType(Cell)
41             , m_stackIndex(stackIndexStart)
42         {
43         }
44 
JITStubCall(JIT * jit,JSPropertyNameIterator * (JIT_STUB * stub)(STUB_ARGS_DECLARATION))45         JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
46             : m_jit(jit)
47             , m_stub(reinterpret_cast<void*>(stub))
48             , m_returnType(Cell)
49             , m_stackIndex(stackIndexStart)
50         {
51         }
52 
JITStubCall(JIT * jit,void * (JIT_STUB * stub)(STUB_ARGS_DECLARATION))53         JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
54             : m_jit(jit)
55             , m_stub(reinterpret_cast<void*>(stub))
56             , m_returnType(VoidPtr)
57             , m_stackIndex(stackIndexStart)
58         {
59         }
60 
JITStubCall(JIT * jit,int (JIT_STUB * stub)(STUB_ARGS_DECLARATION))61         JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
62             : m_jit(jit)
63             , m_stub(reinterpret_cast<void*>(stub))
64             , m_returnType(Int)
65             , m_stackIndex(stackIndexStart)
66         {
67         }
68 
JITStubCall(JIT * jit,bool (JIT_STUB * stub)(STUB_ARGS_DECLARATION))69         JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
70             : m_jit(jit)
71             , m_stub(reinterpret_cast<void*>(stub))
72             , m_returnType(Int)
73             , m_stackIndex(stackIndexStart)
74         {
75         }
76 
JITStubCall(JIT * jit,void (JIT_STUB * stub)(STUB_ARGS_DECLARATION))77         JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
78             : m_jit(jit)
79             , m_stub(reinterpret_cast<void*>(stub))
80             , m_returnType(Void)
81             , m_stackIndex(stackIndexStart)
82         {
83         }
84 
85 #if USE(JSVALUE32_64)
JITStubCall(JIT * jit,EncodedJSValue (JIT_STUB * stub)(STUB_ARGS_DECLARATION))86         JITStubCall(JIT* jit, EncodedJSValue (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
87             : m_jit(jit)
88             , m_stub(reinterpret_cast<void*>(stub))
89             , m_returnType(Value)
90             , m_stackIndex(stackIndexStart)
91         {
92         }
93 #endif
94 
95         // Arguments are added first to last.
96 
skipArgument()97         void skipArgument()
98         {
99             m_stackIndex += stackIndexStep;
100         }
101 
addArgument(JIT::Imm32 argument)102         void addArgument(JIT::Imm32 argument)
103         {
104             m_jit->poke(argument, m_stackIndex);
105             m_stackIndex += stackIndexStep;
106         }
107 
addArgument(JIT::ImmPtr argument)108         void addArgument(JIT::ImmPtr argument)
109         {
110             m_jit->poke(argument, m_stackIndex);
111             m_stackIndex += stackIndexStep;
112         }
113 
addArgument(JIT::RegisterID argument)114         void addArgument(JIT::RegisterID argument)
115         {
116             m_jit->poke(argument, m_stackIndex);
117             m_stackIndex += stackIndexStep;
118         }
119 
addArgument(const JSValue & value)120         void addArgument(const JSValue& value)
121         {
122             m_jit->poke(JIT::Imm32(value.payload()), m_stackIndex);
123             m_jit->poke(JIT::Imm32(value.tag()), m_stackIndex + 1);
124             m_stackIndex += stackIndexStep;
125         }
126 
addArgument(JIT::RegisterID tag,JIT::RegisterID payload)127         void addArgument(JIT::RegisterID tag, JIT::RegisterID payload)
128         {
129             m_jit->poke(payload, m_stackIndex);
130             m_jit->poke(tag, m_stackIndex + 1);
131             m_stackIndex += stackIndexStep;
132         }
133 
134 #if USE(JSVALUE32_64)
addArgument(unsigned srcVirtualRegister)135         void addArgument(unsigned srcVirtualRegister)
136         {
137             if (m_jit->m_codeBlock->isConstantRegisterIndex(srcVirtualRegister)) {
138                 addArgument(m_jit->getConstantOperand(srcVirtualRegister));
139                 return;
140             }
141 
142             m_jit->emitLoad(srcVirtualRegister, JIT::regT1, JIT::regT0);
143             addArgument(JIT::regT1, JIT::regT0);
144         }
145 
getArgument(size_t argumentNumber,JIT::RegisterID tag,JIT::RegisterID payload)146         void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload)
147         {
148             size_t stackIndex = stackIndexStart + (argumentNumber * stackIndexStep);
149             m_jit->peek(payload, stackIndex);
150             m_jit->peek(tag, stackIndex + 1);
151         }
152 #else
addArgument(unsigned src,JIT::RegisterID scratchRegister)153         void addArgument(unsigned src, JIT::RegisterID scratchRegister) // src is a virtual register.
154         {
155             if (m_jit->m_codeBlock->isConstantRegisterIndex(src))
156                 addArgument(JIT::ImmPtr(JSValue::encode(m_jit->m_codeBlock->getConstant(src))));
157             else {
158                 m_jit->loadPtr(JIT::Address(JIT::callFrameRegister, src * sizeof(Register)), scratchRegister);
159                 addArgument(scratchRegister);
160             }
161             m_jit->killLastResultRegister();
162         }
163 #endif
164 
call()165         JIT::Call call()
166         {
167 #if ENABLE(OPCODE_SAMPLING)
168             if (m_jit->m_bytecodeIndex != (unsigned)-1)
169                 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, true);
170 #endif
171 
172             m_jit->restoreArgumentReference();
173             JIT::Call call = m_jit->call();
174             m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeIndex, m_stub));
175 
176 #if ENABLE(OPCODE_SAMPLING)
177             if (m_jit->m_bytecodeIndex != (unsigned)-1)
178                 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, false);
179 #endif
180 
181 #if USE(JSVALUE32_64)
182             m_jit->unmap();
183 #else
184             m_jit->killLastResultRegister();
185 #endif
186             return call;
187         }
188 
189 #if USE(JSVALUE32_64)
call(unsigned dst)190         JIT::Call call(unsigned dst) // dst is a virtual register.
191         {
192             ASSERT(m_returnType == Value || m_returnType == Cell);
193             JIT::Call call = this->call();
194             if (m_returnType == Value)
195                 m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
196             else
197                 m_jit->emitStoreCell(dst, JIT::returnValueRegister);
198             return call;
199         }
200 #else
call(unsigned dst)201         JIT::Call call(unsigned dst) // dst is a virtual register.
202         {
203             ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
204             JIT::Call call = this->call();
205             m_jit->emitPutVirtualRegister(dst);
206             return call;
207         }
208 #endif
209 
call(JIT::RegisterID dst)210         JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
211         {
212 #if USE(JSVALUE32_64)
213             ASSERT(m_returnType == Value || m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
214 #else
215             ASSERT(m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
216 #endif
217             JIT::Call call = this->call();
218             if (dst != JIT::returnValueRegister)
219                 m_jit->move(JIT::returnValueRegister, dst);
220             return call;
221         }
222 
223     private:
224         static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
225         static const size_t stackIndexStart = 1; // Index 0 is reserved for restoreArgumentReference().
226 
227         JIT* m_jit;
228         void* m_stub;
229         enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
230         size_t m_stackIndex;
231     };
232 }
233 
234 #endif // ENABLE(JIT)
235 
236 #endif // JITStubCall_h
237