https://bugs.webkit.org/show_bug.cgi?id=59847
[WebKit-https.git] / Source / JavaScriptCore / jit / SpecializedThunkJIT.h
1 /*
2  * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef SpecializedThunkJIT_h
27 #define SpecializedThunkJIT_h
28
29 #if ENABLE(JIT)
30
31 #include "Executable.h"
32 #include "JSInterfaceJIT.h"
33 #include "LinkBuffer.h"
34
35 namespace JSC {
36
37     class SpecializedThunkJIT : public JSInterfaceJIT {
38     public:
39         static const int ThisArgument = -1;
40         SpecializedThunkJIT(int expectedArgCount, JSGlobalData* globalData, ExecutablePool* pool)
41             : m_expectedArgCount(expectedArgCount)
42             , m_globalData(globalData)
43             , m_pool(pool)
44         {
45             // Check that we have the expected number of arguments
46             m_failures.append(branch32(NotEqual, Address(callFrameRegister, RegisterFile::ArgumentCount * (int)sizeof(Register)), TrustedImm32(expectedArgCount + 1)));
47         }
48         
49         void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch)
50         {
51             unsigned src = argumentToVirtualRegister(argument);
52             m_failures.append(emitLoadDouble(src, dst, scratch));
53         }
54         
55         void loadCellArgument(int argument, RegisterID dst)
56         {
57             unsigned src = argumentToVirtualRegister(argument);
58             m_failures.append(emitLoadJSCell(src, dst));
59         }
60         
61         void loadJSStringArgument(int argument, RegisterID dst)
62         {
63             loadCellArgument(argument, dst);
64             m_failures.append(branchPtr(NotEqual, Address(dst, 0), TrustedImmPtr(m_globalData->jsStringVPtr)));
65             m_failures.append(branchTest32(NonZero, Address(dst, OBJECT_OFFSETOF(JSString, m_fiberCount))));
66         }
67         
68         void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget)
69         {
70             unsigned src = argumentToVirtualRegister(argument);
71             failTarget = emitLoadInt32(src, dst);
72         }
73         
74         void loadInt32Argument(int argument, RegisterID dst)
75         {
76             Jump conversionFailed;
77             loadInt32Argument(argument, dst, conversionFailed);
78             m_failures.append(conversionFailed);
79         }
80         
81         void appendFailure(const Jump& failure)
82         {
83             m_failures.append(failure);
84         }
85
86         void returnJSValue(RegisterID src)
87         {
88             if (src != regT0)
89                 move(src, regT0);
90             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
91             ret();
92         }
93         
94         void returnDouble(FPRegisterID src)
95         {
96 #if USE(JSVALUE64)
97             moveDoubleToPtr(src, regT0);
98             subPtr(tagTypeNumberRegister, regT0);
99 #else
100             storeDouble(src, Address(stackPointerRegister, -(int)sizeof(double)));
101             loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - sizeof(double)), regT1);
102             loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - sizeof(double)), regT0);
103 #endif
104             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
105             ret();
106         }
107
108         void returnInt32(RegisterID src)
109         {
110             if (src != regT0)
111                 move(src, regT0);
112             tagReturnAsInt32();
113             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
114             ret();
115         }
116
117         void returnJSCell(RegisterID src)
118         {
119             if (src != regT0)
120                 move(src, regT0);
121             tagReturnAsJSCell();
122             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
123             ret();
124         }
125         
126         MacroAssemblerCodePtr finalize(MacroAssemblerCodePtr fallback)
127         {
128             LinkBuffer patchBuffer(this, m_pool.get());
129             patchBuffer.link(m_failures, CodeLocationLabel(fallback));
130             return patchBuffer.finalizeCode().m_code;
131         }
132         
133     private:
134         int argumentToVirtualRegister(unsigned argument)
135         {
136             return -static_cast<int>(RegisterFile::CallFrameHeaderSize + (m_expectedArgCount - argument));
137         }
138
139         void tagReturnAsInt32()
140         {
141 #if USE(JSVALUE64)
142             orPtr(tagTypeNumberRegister, regT0);
143 #else
144             move(TrustedImm32(JSValue::Int32Tag), regT1);
145 #endif
146         }
147
148         void tagReturnAsJSCell()
149         {
150 #if USE(JSVALUE32_64)
151             move(TrustedImm32(JSValue::CellTag), regT1);
152 #endif
153         }
154         
155         int m_expectedArgCount;
156         JSGlobalData* m_globalData;
157         RefPtr<ExecutablePool> m_pool;
158         MacroAssembler::JumpList m_failures;
159     };
160
161 }
162
163 #endif // ENABLE(JIT)
164
165 #endif // SpecializedThunkJIT_h