1/*
2 * Copyright (C) 2013-2018 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. ``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.
24 */
25
26#pragma once
27
28#if ENABLE(FTL_JIT)
29
30#include "B3ValueRep.h"
31#include "CodeOrigin.h"
32#include "DFGExitProfile.h"
33#include "DFGNodeOrigin.h"
34#include "DFGOSRExitBase.h"
35#include "FTLAbbreviatedTypes.h"
36#include "FTLExitTimeObjectMaterialization.h"
37#include "FTLExitValue.h"
38#include "FTLFormattedValue.h"
39#include "FTLOSRExitHandle.h"
40#include "FTLStackmapArgumentList.h"
41#include "HandlerInfo.h"
42#include "MethodOfGettingAValueProfile.h"
43#include "Operands.h"
44#include "Reg.h"
45#include "ValueProfile.h"
46#include "VirtualRegister.h"
47
48namespace JSC {
49
50class TrackedReferences;
51
52namespace B3 {
53class StackmapGenerationParams;
54namespace Air {
55struct GenerationContext;
56} // namespace Air
57} // namespace B3
58
59namespace DFG {
60struct NodeOrigin;
61} // namespace DFG;
62
63namespace FTL {
64
65class State;
66struct OSRExitDescriptorImpl;
67struct OSRExitHandle;
68
69struct OSRExitDescriptor {
70 OSRExitDescriptor(
71 DataFormat profileDataFormat, MethodOfGettingAValueProfile,
72 unsigned numberOfArguments, unsigned numberOfLocals);
73
74 // The first argument to the exit call may be a value we wish to profile.
75 // If that's the case, the format will be not Invalid and we'll have a
76 // method of getting a value profile. Note that all of the ExitArgument's
77 // are already aware of this possible off-by-one, so there is no need to
78 // correct them.
79 DataFormat m_profileDataFormat;
80 MethodOfGettingAValueProfile m_valueProfile;
81
82 Operands<ExitValue> m_values;
83 Bag<ExitTimeObjectMaterialization> m_materializations;
84
85 void validateReferences(const TrackedReferences&);
86
87 // Call this once we have a place to emit the OSR exit jump and we have data about how the state
88 // should be recovered. This effectively emits code that does the exit, though the code is really a
89 // patchable jump and we emit the real code lazily. The description of how to emit the real code is
90 // up to the OSRExit object, which this creates. Note that it's OK to drop the OSRExitHandle object
91 // on the ground. It contains information that is mostly not useful if you use this API, since after
92 // this call, the OSRExit is simply ready to go.
93 Ref<OSRExitHandle> emitOSRExit(
94 State&, ExitKind, const DFG::NodeOrigin&, CCallHelpers&, const B3::StackmapGenerationParams&,
95 unsigned offset = 0);
96
97 // In some cases you want an OSRExit to come into existence, but you don't want to emit it right now.
98 // This will emit the OSR exit in a late path. You can't be sure exactly when that will happen, but
99 // you know that it will be done by the time late path emission is done. So, a linker task will
100 // surely happen after that. You can use the OSRExitHandle to retrieve the exit's label.
101 //
102 // This API is meant to be used for things like exception handling, where some patchpoint wants to
103 // have a place to jump to for OSR exit. It doesn't care where that OSR exit is emitted so long as it
104 // eventually gets access to its label.
105 Ref<OSRExitHandle> emitOSRExitLater(
106 State&, ExitKind, const DFG::NodeOrigin&, const B3::StackmapGenerationParams&,
107 unsigned offset = 0);
108
109private:
110 // This is the low-level interface. It will create a handle representing the desire to emit code for
111 // an OSR exit. You can call OSRExitHandle::emitExitThunk() once you have a place to emit it. Note
112 // that the above two APIs are written in terms of this and OSRExitHandle::emitExitThunk().
113 Ref<OSRExitHandle> prepareOSRExitHandle(
114 State&, ExitKind, const DFG::NodeOrigin&, const B3::StackmapGenerationParams&,
115 unsigned offset = 0);
116};
117
118struct OSRExit : public DFG::OSRExitBase {
119 OSRExit(OSRExitDescriptor*, ExitKind, CodeOrigin, CodeOrigin codeOriginForExitProfile, bool wasHoisted);
120
121 OSRExitDescriptor* m_descriptor;
122 MacroAssemblerCodeRef<OSRExitPtrTag> m_code;
123 // This tells us where to place a jump.
124 CodeLocationJump<JSInternalPtrTag> m_patchableJump;
125 Vector<B3::ValueRep> m_valueReps;
126
127 CodeLocationJump<JSInternalPtrTag> codeLocationForRepatch(CodeBlock* ftlCodeBlock) const;
128 void considerAddingAsFrequentExitSite(CodeBlock* profiledCodeBlock)
129 {
130 OSRExitBase::considerAddingAsFrequentExitSite(profiledCodeBlock, ExitFromFTL);
131 }
132};
133
134} } // namespace JSC::FTL
135
136#endif // ENABLE(FTL_JIT)
137