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 | |
48 | namespace JSC { |
49 | |
50 | class TrackedReferences; |
51 | |
52 | namespace B3 { |
53 | class StackmapGenerationParams; |
54 | namespace Air { |
55 | struct GenerationContext; |
56 | } // namespace Air |
57 | } // namespace B3 |
58 | |
59 | namespace DFG { |
60 | struct NodeOrigin; |
61 | } // namespace DFG; |
62 | |
63 | namespace FTL { |
64 | |
65 | class State; |
66 | struct OSRExitDescriptorImpl; |
67 | struct OSRExitHandle; |
68 | |
69 | struct 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 | |
109 | private: |
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 | |
118 | struct 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 | |