• 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 "MacroAssemblerCodeRef.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(stub)
40             , m_returnType(Cell)
41             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
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(stub)
48             , m_returnType(Cell)
49             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
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(stub)
56             , m_returnType(VoidPtr)
57             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
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(stub)
64             , m_returnType(Int)
65             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
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(stub)
72             , m_returnType(Int)
73             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
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(stub)
80             , m_returnType(Void)
81             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
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(stub)
89             , m_returnType(Value)
90             , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
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::TrustedImm32 argument)102         void addArgument(JIT::TrustedImm32 argument)
103         {
104             m_jit->poke(argument, m_stackIndex);
105             m_stackIndex += stackIndexStep;
106         }
107 
addArgument(JIT::TrustedImmPtr argument)108         void addArgument(JIT::TrustedImmPtr 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 
120 #if USE(JSVALUE32_64)
addArgument(const JSValue & value)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 
addArgument(JIT::RegisterID tag,JIT::RegisterID payload)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)
addArgument(unsigned srcVirtualRegister)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 
getArgument(size_t argumentNumber,JIT::RegisterID tag,JIT::RegisterID payload)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
addArgument(unsigned src,JIT::RegisterID scratchRegister)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 
call()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             JIT::Call call = m_jit->call();
176             m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeOffset, m_stub.value()));
177 
178 #if ENABLE(OPCODE_SAMPLING)
179             if (m_jit->m_bytecodeOffset != (unsigned)-1)
180                 m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, false);
181 #endif
182 
183 #if USE(JSVALUE32_64)
184             m_jit->unmap();
185 #else
186             m_jit->killLastResultRegister();
187 #endif
188             return call;
189         }
190 
191 #if USE(JSVALUE32_64)
call(unsigned dst)192         JIT::Call call(unsigned dst) // dst is a virtual register.
193         {
194             ASSERT(m_returnType == Value || m_returnType == Cell);
195             JIT::Call call = this->call();
196             if (m_returnType == Value)
197                 m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
198             else
199                 m_jit->emitStoreCell(dst, JIT::returnValueRegister);
200             return call;
201         }
202 #else
call(unsigned dst)203         JIT::Call call(unsigned dst) // dst is a virtual register.
204         {
205             ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
206             JIT::Call call = this->call();
207             m_jit->emitPutVirtualRegister(dst);
208             return call;
209         }
210 #endif
211 
call(JIT::RegisterID dst)212         JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
213         {
214 #if USE(JSVALUE32_64)
215             ASSERT(m_returnType == Value || m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
216 #else
217             ASSERT(m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
218 #endif
219             JIT::Call call = this->call();
220             if (dst != JIT::returnValueRegister)
221                 m_jit->move(JIT::returnValueRegister, dst);
222             return call;
223         }
224 
225     private:
226         static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
227 
228         JIT* m_jit;
229         FunctionPtr m_stub;
230         enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
231         size_t m_stackIndex;
232     };
233 }
234 
235 #endif // ENABLE(JIT)
236 
237 #endif // JITStubCall_h
238