2 * Copyright (C) 2013 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. ``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.
27 #include "ArityCheckFailReturnThunks.h"
31 #include "AssemblyHelpers.h"
32 #include "LinkBuffer.h"
33 #include "JSCInlines.h"
34 #include "StackAlignment.h"
38 ArityCheckFailReturnThunks::ArityCheckFailReturnThunks()
43 ArityCheckFailReturnThunks::~ArityCheckFailReturnThunks() { }
45 CodeLocationLabel
* ArityCheckFailReturnThunks::returnPCsFor(
46 VM
& vm
, unsigned numExpectedArgumentsIncludingThis
)
48 ASSERT(numExpectedArgumentsIncludingThis
>= 1);
50 numExpectedArgumentsIncludingThis
= WTF::roundUpToMultipleOf(
51 stackAlignmentRegisters(), numExpectedArgumentsIncludingThis
);
54 ConcurrentJITLocker
locker(m_lock
);
55 if (numExpectedArgumentsIncludingThis
< m_nextSize
)
56 return m_returnPCArrays
.last().get();
59 ASSERT(!isCompilationThread());
61 numExpectedArgumentsIncludingThis
= std::max(numExpectedArgumentsIncludingThis
, m_nextSize
* 2);
63 AssemblyHelpers
jit(&vm
, 0);
65 Vector
<AssemblyHelpers::Label
> labels
;
67 for (unsigned size
= m_nextSize
; size
<= numExpectedArgumentsIncludingThis
; size
+= stackAlignmentRegisters()) {
68 labels
.append(jit
.label());
71 AssemblyHelpers::Address(
72 AssemblyHelpers::stackPointerRegister
,
73 (JSStack::ArgumentCount
- JSStack::CallerFrameAndPCSize
) * sizeof(Register
) +
77 AssemblyHelpers::TrustedImm32(
78 JSStack::CallFrameHeaderSize
- JSStack::CallerFrameAndPCSize
+ size
- 1),
79 GPRInfo::regT4
, GPRInfo::regT2
);
80 jit
.lshift32(AssemblyHelpers::TrustedImm32(3), GPRInfo::regT2
);
81 jit
.addPtr(AssemblyHelpers::stackPointerRegister
, GPRInfo::regT2
);
82 jit
.loadPtr(GPRInfo::regT2
, GPRInfo::regT2
);
85 AssemblyHelpers::TrustedImm32(size
* sizeof(Register
)),
86 AssemblyHelpers::stackPointerRegister
);
88 // Thunks like ours want to use the return PC to figure out where things
89 // were saved. So, we pay it forward.
92 AssemblyHelpers::Address(
93 AssemblyHelpers::stackPointerRegister
,
94 (JSStack::ArgumentCount
- JSStack::CallerFrameAndPCSize
) * sizeof(Register
) +
97 jit
.jump(GPRInfo::regT2
);
100 LinkBuffer
linkBuffer(vm
, jit
, GLOBAL_THUNK_ID
);
102 unsigned returnPCsSize
= numExpectedArgumentsIncludingThis
/ stackAlignmentRegisters() + 1;
103 std::unique_ptr
<CodeLocationLabel
[]> returnPCs
=
104 std::make_unique
<CodeLocationLabel
[]>(returnPCsSize
);
105 for (unsigned size
= 0; size
<= numExpectedArgumentsIncludingThis
; size
+= stackAlignmentRegisters()) {
106 unsigned index
= size
/ stackAlignmentRegisters();
107 RELEASE_ASSERT(index
< returnPCsSize
);
108 if (size
< m_nextSize
)
109 returnPCs
[index
] = m_returnPCArrays
.last()[index
];
111 returnPCs
[index
] = linkBuffer
.locationOf(labels
[(size
- m_nextSize
) / stackAlignmentRegisters()]);
114 CodeLocationLabel
* result
= returnPCs
.get();
117 ConcurrentJITLocker
locker(m_lock
);
118 m_returnPCArrays
.append(WTF::move(returnPCs
));
119 m_refs
.append(FINALIZE_CODE(linkBuffer
, ("Arity check fail return thunks for up to numArgs = %u", numExpectedArgumentsIncludingThis
)));
120 m_nextSize
= numExpectedArgumentsIncludingThis
+ stackAlignmentRegisters();
126 CodeLocationLabel
ArityCheckFailReturnThunks::returnPCFor(VM
& vm
, unsigned slotsToAdd
)
128 return returnPCsFor(vm
, slotsToAdd
)[slotsToAdd
/ stackAlignmentRegisters()];
133 #endif // ENABLE(JIT)