2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef SpecializedThunkJIT_h
27 #define SpecializedThunkJIT_h
31 #include "Executable.h"
32 #include "JSInterfaceJIT.h"
33 #include "LinkBuffer.h"
37 class SpecializedThunkJIT
: public JSInterfaceJIT
{
39 static const int ThisArgument
= -1;
40 SpecializedThunkJIT(int expectedArgCount
, JSGlobalData
* globalData
)
41 : m_expectedArgCount(expectedArgCount
)
42 , m_globalData(globalData
)
44 // Check that we have the expected number of arguments
45 m_failures
.append(branch32(NotEqual
, payloadFor(RegisterFile::ArgumentCount
), TrustedImm32(expectedArgCount
+ 1)));
48 void loadDoubleArgument(int argument
, FPRegisterID dst
, RegisterID scratch
)
50 unsigned src
= CallFrame::argumentOffset(argument
);
51 m_failures
.append(emitLoadDouble(src
, dst
, scratch
));
54 void loadCellArgument(int argument
, RegisterID dst
)
56 unsigned src
= CallFrame::argumentOffset(argument
);
57 m_failures
.append(emitLoadJSCell(src
, dst
));
60 void loadJSStringArgument(int argument
, RegisterID dst
)
62 loadCellArgument(argument
, dst
);
63 m_failures
.append(branchPtr(NotEqual
, Address(dst
, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info
)));
66 void loadInt32Argument(int argument
, RegisterID dst
, Jump
& failTarget
)
68 unsigned src
= CallFrame::argumentOffset(argument
);
69 failTarget
= emitLoadInt32(src
, dst
);
72 void loadInt32Argument(int argument
, RegisterID dst
)
74 Jump conversionFailed
;
75 loadInt32Argument(argument
, dst
, conversionFailed
);
76 m_failures
.append(conversionFailed
);
79 void appendFailure(const Jump
& failure
)
81 m_failures
.append(failure
);
84 void returnJSValue(RegisterID src
)
88 loadPtr(payloadFor(RegisterFile::CallerFrame
, callFrameRegister
), callFrameRegister
);
92 void returnDouble(FPRegisterID src
)
95 moveDoubleToPtr(src
, regT0
);
96 Jump zero
= branchTestPtr(Zero
, regT0
);
97 subPtr(tagTypeNumberRegister
, regT0
);
100 move(tagTypeNumberRegister
, regT0
);
103 storeDouble(src
, Address(stackPointerRegister
, -(int)sizeof(double)));
104 loadPtr(Address(stackPointerRegister
, OBJECT_OFFSETOF(JSValue
, u
.asBits
.tag
) - sizeof(double)), regT1
);
105 loadPtr(Address(stackPointerRegister
, OBJECT_OFFSETOF(JSValue
, u
.asBits
.payload
) - sizeof(double)), regT0
);
106 Jump lowNonZero
= branchTestPtr(NonZero
, regT1
);
107 Jump highNonZero
= branchTestPtr(NonZero
, regT0
);
108 move(TrustedImm32(0), regT0
);
109 move(TrustedImm32(Int32Tag
), regT1
);
110 lowNonZero
.link(this);
111 highNonZero
.link(this);
113 loadPtr(payloadFor(RegisterFile::CallerFrame
, callFrameRegister
), callFrameRegister
);
117 void returnInt32(RegisterID src
)
122 loadPtr(payloadFor(RegisterFile::CallerFrame
, callFrameRegister
), callFrameRegister
);
126 void returnJSCell(RegisterID src
)
131 loadPtr(payloadFor(RegisterFile::CallerFrame
, callFrameRegister
), callFrameRegister
);
135 MacroAssemblerCodeRef
finalize(JSGlobalData
& globalData
, MacroAssemblerCodePtr fallback
)
137 LinkBuffer
patchBuffer(globalData
, this, GLOBAL_THUNK_ID
);
138 patchBuffer
.link(m_failures
, CodeLocationLabel(fallback
));
139 for (unsigned i
= 0; i
< m_calls
.size(); i
++)
140 patchBuffer
.link(m_calls
[i
].first
, m_calls
[i
].second
);
141 return patchBuffer
.finalizeCode();
144 // Assumes that the target function uses fpRegister0 as the first argument
145 // and return value. Like any sensible architecture would.
146 void callDoubleToDouble(FunctionPtr function
)
148 m_calls
.append(std::make_pair(call(), function
));
153 void tagReturnAsInt32()
156 orPtr(tagTypeNumberRegister
, regT0
);
158 move(TrustedImm32(JSValue::Int32Tag
), regT1
);
162 void tagReturnAsJSCell()
164 #if USE(JSVALUE32_64)
165 move(TrustedImm32(JSValue::CellTag
), regT1
);
169 int m_expectedArgCount
;
170 JSGlobalData
* m_globalData
;
171 MacroAssembler::JumpList m_failures
;
172 Vector
<std::pair
<Call
, FunctionPtr
> > m_calls
;
177 #endif // ENABLE(JIT)
179 #endif // SpecializedThunkJIT_h