]>
git.saurik.com Git - apple/javascriptcore.git/blob - jit/SpecializedThunkJIT.h
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
, ExecutablePool
* pool
)
41 : m_expectedArgCount(expectedArgCount
)
42 , m_globalData(globalData
)
45 // Check that we have the expected number of arguments
46 m_failures
.append(branch32(NotEqual
, Address(callFrameRegister
, RegisterFile::ArgumentCount
* (int)sizeof(Register
)), Imm32(expectedArgCount
+ 1)));
49 void loadDoubleArgument(int argument
, FPRegisterID dst
, RegisterID scratch
)
51 unsigned src
= argumentToVirtualRegister(argument
);
52 m_failures
.append(emitLoadDouble(src
, dst
, scratch
));
55 void loadCellArgument(int argument
, RegisterID dst
)
57 unsigned src
= argumentToVirtualRegister(argument
);
58 m_failures
.append(emitLoadJSCell(src
, dst
));
61 void loadJSStringArgument(int argument
, RegisterID dst
)
63 loadCellArgument(argument
, dst
);
64 m_failures
.append(branchPtr(NotEqual
, Address(dst
, 0), ImmPtr(m_globalData
->jsStringVPtr
)));
65 m_failures
.append(branchTest32(NonZero
, Address(dst
, OBJECT_OFFSETOF(JSString
, m_fiberCount
))));
68 void loadInt32Argument(int argument
, RegisterID dst
, Jump
& failTarget
)
70 unsigned src
= argumentToVirtualRegister(argument
);
71 failTarget
= emitLoadInt32(src
, dst
);
74 void loadInt32Argument(int argument
, RegisterID dst
)
76 Jump conversionFailed
;
77 loadInt32Argument(argument
, dst
, conversionFailed
);
78 m_failures
.append(conversionFailed
);
81 void appendFailure(const Jump
& failure
)
83 m_failures
.append(failure
);
86 void returnJSValue(RegisterID src
)
90 loadPtr(Address(callFrameRegister
, RegisterFile::CallerFrame
* (int)sizeof(Register
)), callFrameRegister
);
94 void returnDouble(FPRegisterID src
)
97 moveDoubleToPtr(src
, regT0
);
98 subPtr(tagTypeNumberRegister
, regT0
);
99 #elif USE(JSVALUE32_64)
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
);
105 ASSERT_NOT_REACHED();
106 m_failures
.append(jump());
108 loadPtr(Address(callFrameRegister
, RegisterFile::CallerFrame
* (int)sizeof(Register
)), callFrameRegister
);
112 void returnInt32(RegisterID src
)
117 loadPtr(Address(callFrameRegister
, RegisterFile::CallerFrame
* (int)sizeof(Register
)), callFrameRegister
);
121 void returnJSCell(RegisterID src
)
126 loadPtr(Address(callFrameRegister
, RegisterFile::CallerFrame
* (int)sizeof(Register
)), callFrameRegister
);
130 PassRefPtr
<NativeExecutable
> finalize()
132 LinkBuffer
patchBuffer(this, m_pool
.get(), 0);
133 patchBuffer
.link(m_failures
, CodeLocationLabel(m_globalData
->jitStubs
->ctiNativeCallThunk()->generatedJITCode().addressForCall()));
134 return adoptRef(new NativeExecutable(patchBuffer
.finalizeCode()));
138 int argumentToVirtualRegister(unsigned argument
)
140 return -static_cast<int>(RegisterFile::CallFrameHeaderSize
+ (m_expectedArgCount
- argument
));
143 void tagReturnAsInt32()
146 orPtr(tagTypeNumberRegister
, regT0
);
147 #elif USE(JSVALUE32_64)
148 move(Imm32(JSValue::Int32Tag
), regT1
);
150 signExtend32ToPtr(regT0
, regT0
);
151 // If we can't tag the result, give up and jump to the slow case
152 m_failures
.append(branchAddPtr(Overflow
, regT0
, regT0
));
153 addPtr(Imm32(JSImmediate::TagTypeNumber
), regT0
);
157 void tagReturnAsJSCell()
159 #if USE(JSVALUE32_64)
160 move(Imm32(JSValue::CellTag
), regT1
);
164 int m_expectedArgCount
;
165 JSGlobalData
* m_globalData
;
166 RefPtr
<ExecutablePool
> m_pool
;
167 MacroAssembler::JumpList m_failures
;
172 #endif // ENABLE(JIT)
174 #endif // SpecializedThunkJIT_h