FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
WebKit/Source/JavaScriptCore/b3/air/AirCode.h at main · WebKit/WebKit · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
WebKit
/
WebKit
Public
Notifications
You must be signed in to change notification settings
Fork
2.1k
Star
10.1k
Code
Pull requests
2.6k
Actions
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
WebKit
/
Source
/
JavaScriptCore
/
b3
/
air
/
AirCode.h
Copy path
More file actions
More file actions
Latest commit
History
History
History
425 lines (341 loc) · 14.2 KB
Breadcrumbs
WebKit
/
Source
/
JavaScriptCore
/
b3
/
air
/
AirCode.h
Copy path
File metadata and controls
425 lines (341 loc) · 14.2 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
/*
* Copyright (C) 2015-2025 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#
pragma
once
#
if
ENABLE(B3_JIT)
#
include
"
AirArg.h
"
#
include
"
AirBasicBlock.h
"
#
include
"
AirDisassembler.h
"
#
include
"
AirSpecial.h
"
#
include
"
AirStackSlot.h
"
#
include
"
AirTmp.h
"
#
include
"
B3SparseCollection.h
"
#
include
"
GPRInfo.h
"
#
include
"
MacroAssembler.h
"
#
include
"
RegisterAtOffsetList.h
"
#
include
"
StackAlignment.h
"
#
include
<
wtf/HashSet.h
>
#
include
<
wtf/IndexMap.h
>
#
include
<
wtf/JSONValues.h
>
#
include
<
wtf/SequesteredMalloc.h
>
#
include
<
wtf/SmallSet.h
>
#
include
<
wtf/TZoneMalloc.h
>
#
include
<
wtf/WeakRandom.h
>
#
include
<
wtf/text/ASCIILiteral.h
>
namespace
JSC
{
class
CCallHelpers
;
namespace
B3
{
class
Procedure
;
class
WasmBoundsCheckValue
;
#
if
!ASSERT_ENABLED
IGNORE_RETURN_TYPE_WARNINGS_BEGIN
#
endif
namespace
Air
{
class
GenerateAndAllocateRegisters
;
class
BlockInsertionSet
;
class
CCallSpecial
;
class
CFG
;
class
Code
;
class
Disassembler
;
typedef
void
WasmBoundsCheckGeneratorFunction
(CCallHelpers&, WasmBoundsCheckValue*, GPRReg);
typedef
SharedTask<WasmBoundsCheckGeneratorFunction> WasmBoundsCheckGenerator;
typedef
void
PrologueGeneratorFunction
(CCallHelpers&, Code&);
typedef
SharedTask<PrologueGeneratorFunction> PrologueGenerator;
inline
constexpr
ASCIILiteral tierName {
"
Air
"
_s };
//
This is an IR that is very close to the bare metal. It requires about 40x more bytes than the
//
generated machine code - for example if you're generating 1MB of machine code, you need about
//
40MB of Air.
class
Code
{
WTF_MAKE_NONCOPYABLE
(Code);
WTF_MAKE_SEQUESTERED_ARENA_ALLOCATED
(Code);
public:
~Code
();
Procedure&
proc
() {
return
m_proc; }
const
Vector<Reg>&
regsInPriorityOrder
(Bank bank)
const
{
switch
(bank) {
case
GP
:
return
m_gpRegsInPriorityOrder;
case
FP
:
return
m_fpRegsInPriorityOrder;
}
ASSERT_NOT_REACHED
();
}
//
This is the set of registers that Air is allowed to emit code to mutate. It's derived from
//
regsInPriorityOrder. Any registers not in this set are said to be "pinned".
RegisterSet
mutableRegs
()
const
{
return
m_mutableRegs.
toRegisterSet
().
includeWholeRegisterWidth
(); }
bool
isPinned
(Reg reg)
const
{
return
pinnedRegisters
().
contains
(reg, IgnoreVectors); }
JS_EXPORT_PRIVATE
void
pinRegister
(Reg);
void
setOptLevel
(
unsigned
optLevel) { m_optLevel = optLevel; }
unsigned
optLevel
()
const
{
return
m_optLevel; }
bool
NODELETE
needsUsedRegisters
()
const
;
JS_EXPORT_PRIVATE
BasicBlock*
addBlock
(
double
frequency =
1
);
//
Note that you can rely on stack slots always getting indices that are larger than the index
//
of any prior stack slot. In fact, all stack slots you create in the future will have an index
//
that is >= stackSlots().size().
JS_EXPORT_PRIVATE
StackSlot*
addStackSlot
(
uint64_t
byteSize, StackSlotKind);
JS_EXPORT_PRIVATE
Special*
addSpecial
(std::unique_ptr<Special>);
//
This is the special you need to make a C call!
CCallSpecial*
cCallSpecial
();
Tmp
newTmp
(Bank bank)
{
switch
(bank) {
case
GP
:
return
Tmp::gpTmpForIndex
(m_numGPTmps++);
case
FP
:
return
Tmp::fpTmpForIndex
(m_numFPTmps++);
}
ASSERT_NOT_REACHED
();
}
unsigned
numTmps
(Bank bank)
{
switch
(bank) {
case
GP
:
return
m_numGPTmps;
case
FP
:
return
m_numFPTmps;
}
ASSERT_NOT_REACHED
();
}
template
<Bank bank,
typename
Func>
void
forEachTmp
(
const
Func& func)
{
unsigned
numTmps =
this
->
numTmps
(bank);
for
(
unsigned
i =
0
; i < numTmps; ++i)
func
(
Tmp::tmpForIndex
(bank, i));
}
template
<
typename
Func>
void
forEachTmp
(
const
Func& func)
{
static_assert
(numBanks ==
2
);
forEachTmp<
GP
>(func);
forEachTmp<
FP
>(func);
}
unsigned
callArgAreaSizeInBytes
()
const
{
return
m_callArgAreaSize; }
//
You can call this before code generation to force a minimum call arg area size.
void
requestCallArgAreaSizeInBytes
(
unsigned
size)
{
m_callArgAreaSize =
std::max
(
m_callArgAreaSize,
static_cast
<
unsigned
>(
WTF
::roundUpToMultipleOf<
stackAlignmentBytes
()>(size)));
}
unsigned
frameSize
()
const
{
ASSERT
(!((m_frameSize +
sizeof
(CallerFrameAndPC)) %
stackAlignmentBytes
()));
return
m_frameSize;
}
//
Only phases that do stack allocation are allowed to set this. Currently, only
//
Air::allocateStack() does this.
void
setFrameSize
(
unsigned
frameSize)
{
//
'aligned SP' + 'functionPrologue' + 'm_frameSize' should yield an aligned SP.
ASSERT
(!((frameSize +
sizeof
(CallerFrameAndPC)) %
stackAlignmentBytes
()));
m_frameSize = frameSize;
}
//
Note that this is not the same thing as proc().numEntrypoints(). This value here may be zero
//
until we lower EntrySwitch.
unsigned
numEntrypoints
()
const
{
return
m_entrypoints.
size
(); }
const
Vector<FrequentedBlock>&
entrypoints
()
const
LIFETIME_BOUND {
return
m_entrypoints; }
const
FrequentedBlock&
entrypoint
(
unsigned
index)
const
{
return
m_entrypoints[index]; }
bool
NODELETE
isEntrypoint
(BasicBlock*)
const
;
//
Note: It is only valid to call this function after LowerEntrySwitch.
std::optional<
unsigned
>
NODELETE
entrypointIndex
(BasicBlock*)
const
;
//
Note: We allow this to be called even before we set m_entrypoints just for convenience to users of this API.
//
However, if you call this before setNumEntrypoints, setNumEntrypoints will overwrite this value.
void
setPrologueForEntrypoint
(
unsigned
entrypointIndex, Ref<PrologueGenerator>&& generator)
{
m_prologueGenerators[entrypointIndex] =
WTF::move
(generator);
}
const
Ref<PrologueGenerator>&
prologueGeneratorForEntrypoint
(
unsigned
entrypointIndex)
{
return
m_prologueGenerators[entrypointIndex];
}
void
setNumEntrypoints
(
unsigned
);
//
This is used by lowerEntrySwitch().
template
<
typename
Vector>
void
setEntrypoints
(Vector&& vector)
{
m_entrypoints = std::forward<Vector>(vector);
RELEASE_ASSERT
(m_entrypoints.
size
() == m_prologueGenerators.
size
());
}
MacroAssembler::Label
entrypointLabel
(
unsigned
index)
const
{
return
m_entrypointLabels[index];
}
//
This is used by generate().
template
<
typename
Vector>
void
setEntrypointLabels
(Vector&& vector)
{
m_entrypointLabels = std::forward<Vector>(vector);
RELEASE_ASSERT
(m_entrypointLabels.
size
() == m_prologueGenerators.
size
());
}
void
setStackIsAllocated
(
bool
value)
{
m_stackIsAllocated = value;
}
bool
stackIsAllocated
()
const
{
return
m_stackIsAllocated; }
//
This sets the callee save registers.
void
setCalleeSaveRegisterAtOffsetList
(RegisterAtOffsetList&&, StackSlot*);
//
This returns the correctly offset list of callee save registers.
RegisterAtOffsetList
calleeSaveRegisterAtOffsetList
()
const
;
//
This just tells you what the callee saves are.
RegisterSet
calleeSaveRegisters
()
const
{
return
m_calleeSaveRegisters; }
//
Recomputes predecessors and deletes unreachable blocks.
JS_EXPORT_PRIVATE
void
resetReachability
();
JS_EXPORT_PRIVATE
void
dump
(PrintStream&)
const
;
unsigned
size
()
const
{
return
m_blocks.
size
(); }
BasicBlock*
at
(
unsigned
index)
const
{
return
m_blocks[index].
get
(); }
BasicBlock*
operator
[](
unsigned
index)
const
{
return
at
(index); }
//
This is used by phases that optimize the block list. You shouldn't use this unless you really know
//
what you're doing.
Vector<std::unique_ptr<BasicBlock>>&
blockList
() LIFETIME_BOUND {
return
m_blocks; }
//
Finds the smallest index' such that at(index') != null and index' >= index.
JS_EXPORT_PRIVATE
unsigned
NODELETE
findFirstBlockIndex
(
unsigned
index)
const
;
//
Finds the smallest index' such that at(index') != null and index' > index.
unsigned
NODELETE
findNextBlockIndex
(
unsigned
index)
const
;
BasicBlock*
NODELETE
findNextBlock
(BasicBlock*)
const
;
class
iterator
{
public:
iterator
()
: m_code(
nullptr
)
, m_index(
0
)
{
}
iterator
(
const
Code& code,
unsigned
index)
: m_code(&code)
, m_index(m_code->
findFirstBlockIndex
(index))
{
}
BasicBlock*
operator
*()
{
return
m_code->
at
(m_index);
}
iterator&
operator
++()
{
m_index = m_code->
findFirstBlockIndex
(m_index +
1
);
return
*
this
;
}
bool
operator
==(
const
iterator& other)
const
{
return
m_index == other.
m_index
;
}
private:
const
Code* m_code;
unsigned
m_index;
};
iterator
begin
()
const
LIFETIME_BOUND {
return
iterator
(*
this
,
0
); }
iterator
end
()
const
LIFETIME_BOUND {
return
iterator
(*
this
,
size
()); }
const
SparseCollection<StackSlot>&
stackSlots
()
const
LIFETIME_BOUND {
return
m_stackSlots; }
SparseCollection<StackSlot>&
stackSlots
() LIFETIME_BOUND {
return
m_stackSlots; }
const
SparseCollection<Special>&
specials
()
const
LIFETIME_BOUND {
return
m_specials; }
SparseCollection<Special>&
specials
() LIFETIME_BOUND {
return
m_specials; }
JS_EXPORT_PRIVATE
void
addFastTmp
(Tmp);
template
<
typename
Functor>
void
forEachFastTmp
(
const
Functor& functor)
const
{
for
(Tmp tmp : m_fastTmps)
functor
(tmp);
}
CFG
&
cfg
()
const
{
return
*m_cfg; }
void
*
addDataSection
(
size_t
);
//
The name has to be a string literal, since we don't do any memory management for the string.
void
setLastPhaseName
(
const
char
* name)
{
m_lastPhaseName = name;
}
const
char
*
lastPhaseName
()
const
{
return
m_lastPhaseName; }
void
setWasmBoundsCheckGenerator
(RefPtr<WasmBoundsCheckGenerator> generator)
{
m_wasmBoundsCheckGenerator = generator;
}
RefPtr<WasmBoundsCheckGenerator>
wasmBoundsCheckGenerator
()
const
{
return
m_wasmBoundsCheckGenerator; }
//
This is a hash of the code. You can use this if you want to put code into a hashtable, but
//
it's mainly for validating the results from JSAir.
unsigned
jsHash
()
const
;
bool
shouldPreserveB3Origins
()
const
{
return
m_preserveB3Origins; }
void
forcePreservationOfB3Origins
() { m_preserveB3Origins =
true
; }
bool
NODELETE
usesSIMD
()
const
;
void
setDisassembler
(std::unique_ptr<Disassembler>&& disassembler)
{
m_disassembler =
WTF::move
(disassembler);
forcePreservationOfB3Origins
();
}
Disassembler*
disassembler
() LIFETIME_BOUND {
return
m_disassembler.
get
(); }
RegisterSet
mutableGPRs
();
ScalarRegisterSet
pinnedRegisters
()
const
{
return
m_pinnedRegs; }
void
emitDefaultPrologue
(CCallHelpers&);
void
emitEpilogue
(CCallHelpers&);
std::unique_ptr<GenerateAndAllocateRegisters> m_generateAndAllocateRegisters;
void
setIonGraphPasses
(Ref<
JSON
::Array>&&);
void
appendIonGraphPass
(ASCIILiteral);
private:
friend
class
::
JSC
::
B3
::Procedure;
friend
class
BlockInsertionSet
;
Code
(Procedure&);
void
setRegsInPriorityOrder
(Bank,
const
Vector<Reg>&);
Vector<Reg>&
regsInPriorityOrderImpl
(Bank bank)
{
switch
(bank) {
case
GP
:
return
m_gpRegsInPriorityOrder;
case
FP
:
return
m_fpRegsInPriorityOrder;
}
ASSERT_NOT_REACHED
();
}
Procedure& m_proc;
//
Some meta-data, like byproducts, is stored in the Procedure.
Vector<Reg> m_gpRegsInPriorityOrder;
Vector<Reg> m_fpRegsInPriorityOrder;
ScalarRegisterSet m_mutableRegs;
ScalarRegisterSet m_pinnedRegs;
SparseCollection<StackSlot> m_stackSlots;
Vector<std::unique_ptr<BasicBlock>> m_blocks;
SparseCollection<Special> m_specials;
std::unique_ptr<
CFG
> m_cfg;
SmallSet<Tmp, DefaultHash<Tmp>, HashTraits<Tmp>,
2
> m_fastTmps;
CCallSpecial* m_cCallSpecial {
nullptr
};
unsigned
m_numGPTmps {
0
};
unsigned
m_numFPTmps {
0
};
unsigned
m_frameSize {
stackAdjustmentForAlignment
() };
unsigned
m_callArgAreaSize {
0
};
unsigned
m_optLevel {
defaultOptLevel
() };
bool
m_stackIsAllocated {
false
};
bool
m_preserveB3Origins {
true
};
RegisterAtOffsetList m_uncorrectedCalleeSaveRegisterAtOffsetList;
RegisterSet m_calleeSaveRegisters;
StackSlot* m_calleeSaveStackSlot {
nullptr
};
Vector<FrequentedBlock> m_entrypoints;
//
This is empty until after lowerEntrySwitch().
Vector<MacroAssembler::Label> m_entrypointLabels;
//
This is empty until code generation.
Vector<Ref<PrologueGenerator>,
1
> m_prologueGenerators;
RefPtr<WasmBoundsCheckGenerator> m_wasmBoundsCheckGenerator;
const
char
* m_lastPhaseName;
std::unique_ptr<Disassembler> m_disassembler;
const
Ref<PrologueGenerator> m_defaultPrologueGenerator;
RefPtr<
JSON
::Array> m_ionGraphPasses;
};
} } }
//
namespace JSC::B3::Air
#
if
!ASSERT_ENABLED
IGNORE_RETURN_TYPE_WARNINGS_END
#
endif
#
endif
//
ENABLE(B3_JIT)
Back
|
FazBrowse Home
|
New Git URL