2 * Copyright (C) 2011-2013, 2015 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 "DFGOSRExitCompiler.h"
31 #include "CallFrame.h"
32 #include "DFGCommon.h"
33 #include "DFGJITCode.h"
34 #include "DFGOSRExitPreparation.h"
35 #include "LinkBuffer.h"
36 #include "OperandsInlines.h"
37 #include "JSCInlines.h"
38 #include "RepatchBuffer.h"
39 #include <wtf/StringPrintStream.h>
41 namespace JSC
{ namespace DFG
{
43 void OSRExitCompiler::emitRestoreArguments(const Operands
<ValueRecovery
>& operands
)
45 HashMap
<MinifiedID
, int> alreadyAllocatedArguments
; // Maps phantom arguments node ID to operand.
46 for (size_t index
= 0; index
< operands
.size(); ++index
) {
47 const ValueRecovery
& recovery
= operands
[index
];
48 int operand
= operands
.operandForIndex(index
);
50 if (recovery
.technique() != DirectArgumentsThatWereNotCreated
51 && recovery
.technique() != ClonedArgumentsThatWereNotCreated
)
54 MinifiedID id
= recovery
.nodeID();
55 auto iter
= alreadyAllocatedArguments
.find(id
);
56 if (iter
!= alreadyAllocatedArguments
.end()) {
57 JSValueRegs regs
= JSValueRegs::withTwoAvailableRegs(GPRInfo::regT0
, GPRInfo::regT1
);
58 m_jit
.loadValue(CCallHelpers::addressFor(iter
->value
), regs
);
59 m_jit
.storeValue(regs
, CCallHelpers::addressFor(operand
));
63 InlineCallFrame
* inlineCallFrame
=
64 m_jit
.codeBlock()->jitCode()->dfg()->minifiedDFG
.at(id
)->inlineCallFrame();
68 stackOffset
= inlineCallFrame
->stackOffset
;
72 if (!inlineCallFrame
|| inlineCallFrame
->isClosureCall
) {
74 AssemblyHelpers::addressFor(stackOffset
+ JSStack::Callee
),
78 AssemblyHelpers::TrustedImmPtr(inlineCallFrame
->calleeRecovery
.constant().asCell()),
82 if (!inlineCallFrame
|| inlineCallFrame
->isVarargs()) {
84 AssemblyHelpers::payloadFor(stackOffset
+ JSStack::ArgumentCount
),
88 AssemblyHelpers::TrustedImm32(inlineCallFrame
->arguments
.size()),
92 m_jit
.setupArgumentsWithExecState(
93 AssemblyHelpers::TrustedImmPtr(inlineCallFrame
), GPRInfo::regT0
, GPRInfo::regT1
);
94 switch (recovery
.technique()) {
95 case DirectArgumentsThatWereNotCreated
:
96 m_jit
.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast
<void*>(operationCreateDirectArgumentsDuringExit
)), GPRInfo::nonArgGPR0
);
98 case ClonedArgumentsThatWereNotCreated
:
99 m_jit
.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast
<void*>(operationCreateClonedArgumentsDuringExit
)), GPRInfo::nonArgGPR0
);
102 RELEASE_ASSERT_NOT_REACHED();
105 m_jit
.call(GPRInfo::nonArgGPR0
);
106 m_jit
.storeCell(GPRInfo::returnValueGPR
, AssemblyHelpers::addressFor(operand
));
108 alreadyAllocatedArguments
.add(id
, operand
);
114 void compileOSRExit(ExecState
* exec
)
116 SamplingRegion
samplingRegion("DFG OSR Exit Compilation");
118 CodeBlock
* codeBlock
= exec
->codeBlock();
121 ASSERT(codeBlock
->jitType() == JITCode::DFGJIT
);
123 VM
* vm
= &exec
->vm();
125 // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
126 // really be profitable.
127 DeferGCForAWhile
deferGC(vm
->heap
);
129 uint32_t exitIndex
= vm
->osrExitIndex
;
130 OSRExit
& exit
= codeBlock
->jitCode()->dfg()->osrExit
[exitIndex
];
132 prepareCodeOriginForOSRExit(exec
, exit
.m_codeOrigin
);
134 // Compute the value recoveries.
135 Operands
<ValueRecovery
> operands
;
136 codeBlock
->jitCode()->dfg()->variableEventStream
.reconstruct(codeBlock
, exit
.m_codeOrigin
, codeBlock
->jitCode()->dfg()->minifiedDFG
, exit
.m_streamIndex
, operands
);
138 SpeculationRecovery
* recovery
= 0;
139 if (exit
.m_recoveryIndex
!= UINT_MAX
)
140 recovery
= &codeBlock
->jitCode()->dfg()->speculationRecovery
[exit
.m_recoveryIndex
];
143 CCallHelpers
jit(vm
, codeBlock
);
144 OSRExitCompiler
exitCompiler(jit
);
146 jit
.jitAssertHasValidCallFrame();
148 if (vm
->m_perBytecodeProfiler
&& codeBlock
->jitCode()->dfgCommon()->compilation
) {
149 Profiler::Database
& database
= *vm
->m_perBytecodeProfiler
;
150 Profiler::Compilation
* compilation
= codeBlock
->jitCode()->dfgCommon()->compilation
.get();
152 Profiler::OSRExit
* profilerExit
= compilation
->addOSRExit(
153 exitIndex
, Profiler::OriginStack(database
, codeBlock
, exit
.m_codeOrigin
),
154 exit
.m_kind
, exit
.m_kind
== UncountableInvalidation
);
155 jit
.add64(CCallHelpers::TrustedImm32(1), CCallHelpers::AbsoluteAddress(profilerExit
->counterAddress()));
158 exitCompiler
.compileExit(exit
, operands
, recovery
);
160 LinkBuffer
patchBuffer(*vm
, jit
, codeBlock
);
161 exit
.m_code
= FINALIZE_CODE_IF(
162 shouldShowDisassembly() || Options::verboseOSR(),
164 ("DFG OSR exit #%u (%s, %s) from %s, with operands = %s",
165 exitIndex
, toCString(exit
.m_codeOrigin
).data(),
166 exitKindToString(exit
.m_kind
), toCString(*codeBlock
).data(),
167 toCString(ignoringContext
<DumpContext
>(operands
)).data()));
171 RepatchBuffer
repatchBuffer(codeBlock
);
172 repatchBuffer
.relink(exit
.codeLocationForRepatch(codeBlock
), CodeLocationLabel(exit
.m_code
.code()));
175 vm
->osrExitJumpDestination
= exit
.m_code
.code().executableAddress();
180 } } // namespace JSC::DFG
182 #endif // ENABLE(DFG_JIT)