2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_JIT_TC_H_
18 #define incl_HPHP_JIT_TC_H_
20 #include "hphp/runtime/vm/func.h"
21 #include "hphp/runtime/vm/resumable.h"
22 #include "hphp/runtime/vm/jit/cg-meta.h"
23 #include "hphp/runtime/vm/jit/code-cache.h"
24 #include "hphp/runtime/vm/jit/ir-opcode.h"
25 #include "hphp/runtime/vm/jit/srcdb.h"
26 #include "hphp/runtime/vm/jit/stack-offsets.h"
27 #include "hphp/runtime/vm/jit/types.h"
28 #include "hphp/runtime/vm/jit/unique-stubs.h"
29 #include "hphp/util/growable-vector.h"
31 #include <folly/Optional.h>
37 namespace HPHP
{ namespace jit
{
41 struct IncomingBranch
;
48 using OptView
= folly::Optional
<CodeCache::View
>;
50 ////////////////////////////////////////////////////////////////////////////////
63 struct TransMetaInfo
{
65 CodeCache::View emitView
; // View code was emitted into (may be thread local)
66 TransKind viewKind
; // TransKind used to select code view
67 TransKind transKind
; // TransKind used for translation
73 struct LocalTCBuffer
{
74 LocalTCBuffer() = default;
75 explicit LocalTCBuffer(Address start
, size_t initialSize
);
76 LocalTCBuffer(LocalTCBuffer
&&) = default;
77 LocalTCBuffer
& operator=(LocalTCBuffer
&&) = default;
80 bool valid() const { return m_main
.base() != nullptr; }
90 enum class Kind
: uint8_t {
95 FuncMetaInfo() = default;
96 FuncMetaInfo(Func
* f
, LocalTCBuffer
&& buf
)
99 , tcBuf(std::move(buf
))
102 FuncMetaInfo(FuncMetaInfo
&&) = default;
103 FuncMetaInfo
& operator=(FuncMetaInfo
&&) = default;
109 void add(ProfTransRec
* p
) {
110 prologues
.emplace_back(p
);
111 order
.emplace_back(Kind::Prologue
);
114 void add(TransMetaInfo
&& t
) {
115 translations
.emplace_back(std::move(t
));
116 order
.emplace_back(Kind::Translation
);
119 // We rebuild a variant type here because using boosts fails on opensource
120 // builds because it at some point requires a copy construction.
121 // This vector has one entry per prologue/translation stored in the two
122 // vectors above, and it encodes the order in which they should be published.
123 std::vector
<Kind
> order
;
125 std::vector
<ProfTransRec
*> prologues
;
126 std::vector
<TransMetaInfo
> translations
;
129 ////////////////////////////////////////////////////////////////////////////////
132 * Returns true iff we already have Eval.JitMaxTranslations translations
133 * recorded in srcRec.
135 bool reachedTranslationLimit(TransKind kind
, SrcKey sk
, const SrcRec
& srcRec
);
138 * Emit machine code for env. Returns folly::none if the global translation
139 * limit has been reached, generates an interp request if vunit is null or
140 * codegen fails. If optDst is set it must be a thread local view and the
141 * code lock will not be acquired while writing to it.
143 * The resulting translation will not yet be live.
145 folly::Optional
<TransMetaInfo
> emitTranslation(
147 OptView optDst
= folly::none
151 * Make a translation generated by emitTranslation live. If the translation was
152 * emitted into a per-thread buffer then optSrcView must be the view into which
153 * it was emitted, it will be relocated at the end of the live TC.
155 folly::Optional
<TransLoc
> publishTranslation(
157 OptView optSrcView
= folly::none
161 * Publish a set of optimized translations associated with a particular
162 * function. It is assumed that these translations have been emitted into per-
163 * thread buffers and will need to be relocated.
165 void publishOptFunction(FuncMetaInfo info
);
168 * Acquires the code and metadata locks once and relocates all functions in
171 void publishSortedOptFunctions(std::vector
<FuncMetaInfo
> infos
);
174 * Emit a new prologue for func-- returns nullptr if the global translation
175 * limit has been reached.
177 TCA
emitFuncPrologue(Func
* func
, int argc
, TransKind kind
);
180 * Emits an optimized prologue for rec.
182 * Smashes the callers of the prologue for rec and updates the cached func
185 TCA
emitFuncPrologueOpt(ProfTransRec
* rec
);
188 * Emit the prologue dispatch for func which contains dvs DV initializers, and
189 * return its start address. The `kind' of translation argument is used to
190 * decide what area of the code cache will be used (hot, main, or prof).
192 TCA
emitFuncBodyDispatch(Func
* func
, const DVFuncletsVec
& dvs
, TransKind kind
);
194 ////////////////////////////////////////////////////////////////////////////////
197 * True iff the global translation limit has not yet been reached.
202 * Whether we should emit a translation of kind for func, ignoring the cap on
205 bool shouldTranslateNoSizeLimit(const Func
* func
, TransKind kind
);
208 * Whether we should emit a translation of kind for func.
210 bool shouldTranslate(const Func
* func
, TransKind kind
);
213 * Whether we are still profiling new functions.
215 bool shouldProfileNewFuncs();
218 * Whether we should try profile-guided optimization when translating `func'.
220 bool profileFunc(const Func
* func
);
223 * Attempt to discard profData via the treadmill if it is no longer needed.
225 void checkFreeProfData();
227 ////////////////////////////////////////////////////////////////////////////////
230 * SrcRec for sk or nullptr if no SrcRec has been created.
232 SrcRec
* findSrcRec(SrcKey sk
);
235 * Create a SrcRec for sk with an sp offset of spOff.
237 void createSrcRec(SrcKey sk
, FPInvOffset spOff
);
239 ////////////////////////////////////////////////////////////////////////////////
242 * Assert ownership of the CodeCache by this thread.
244 * Must be held even if the current thread owns the global write lease.
246 void assertOwnsCodeLock(OptView v
= folly::none
);
249 * Assert ownership of the tc metadata by this thread.
251 * Must be held even if the current thread owns the global write lease.
253 void assertOwnsMetadataLock();
255 ////////////////////////////////////////////////////////////////////////////////
258 * Get the table of unique stubs
262 ALWAYS_INLINE
const UniqueStubs
& ustubs() {
263 extern UniqueStubs g_ustubs
;
268 * Perform one time process initialization for the structures associated with
274 * Perform process shutdown functions for the TC including joining any
275 * outstanding background threads.
279 ////////////////////////////////////////////////////////////////////////////////
282 * Perform TC related request initialization and teardown.
288 * Returns the total size of the TC now and at the beginning of this request,
289 * in bytes. Note that the code may have been emitted by other threads.
293 void codeEmittedThisRequest(size_t& requestEntry
, size_t& now
);
295 ////////////////////////////////////////////////////////////////////////////////
298 * Reclaim all TC space associated with func
300 * Before any space is reclaimed the following actions will be performed:
301 * (1) Smash all prologues
302 * (2) Smash all callers to bind-call unique stubs
303 * (3) Erase all call meta-data for calls into function
305 * After all calls and prologues have been smashed any on-going requests will be
306 * allowed to complete before TC Space will be reclaimed for:
308 * (2) All translations
309 * (3) All anchor translations
311 * This function should only be called from Func::destroy() and may access the
312 * fullname and ID of the function.
314 void reclaimFunction(const Func
* func
);
317 * Allows TC space for translations in trans to be reused in future
320 * Reclaiming a translation will:
321 * (1) Mark bytes available for reuse in the code-blocks associated with
323 * (2) Erase any IBs from translation into other SrcRecs
324 * (3) Erase any jump annotations in MCGenerator used to generate optimized
326 * (4) Erase an metadata about smashed calls in the translation from both the
327 * reuse-tc module and the prof-data module
329 * The translation _must_ be unreachable before reclaimTranslation() is called,
330 * this is generally done by calling reclaimFunction() or performing
331 * replaceOldTranslations() on a SrcRec
333 void reclaimTranslations(GrowableVector
<TransLoc
>&& trans
);
336 * Free an ephemeral stub.
338 void freeTCStub(TCA stub
);
340 ////////////////////////////////////////////////////////////////////////////////
343 * Emit checks for (and hooks into) an attached debugger in front of each
344 * translation in `unit' or for `SrcKey{func, offset, resumed}'.
346 bool addDbgGuards(const Unit
* unit
);
347 bool addDbgGuard(const Func
* func
, Offset offset
, ResumeMode resumeMode
);
349 ////////////////////////////////////////////////////////////////////////////////
359 * Get UsageInfo data for all the TC code sections, including global data, and
362 std::vector
<UsageInfo
> getUsageInfo();
365 * Like getUsageInfo(), but formatted as a pleasant string.
367 std::string
getTCSpace();
370 * Return a string containing the names and start addresses of all TC code
373 std::string
getTCAddrs();
376 * Dump the translation cache to files in RuntimeOption::EvalDumpTCPath
377 * (default: /tmp), returning success.
379 bool dump(bool ignoreLease
= false);
391 * Get per section memory usage data for the TC.
393 std::vector
<TCMemInfo
> getTCMemoryUsage();
395 ////////////////////////////////////////////////////////////////////////////////
398 * Convert between TC addresses and offsets.
400 extern CodeCache
* g_code
;
401 ALWAYS_INLINE TCA
offsetToAddr(uint32_t off
) {
402 return g_code
->toAddr(off
);
404 ALWAYS_INLINE
uint32_t addrToOffset(CTCA addr
) {
405 return g_code
->toOffset(addr
);
409 * Check if `addr' is an address within the TC.
411 bool isValidCodeAddress(TCA addr
);
414 * Check if `addr' is an address within the profile code block in the TC.
416 bool isProfileCodeAddress(TCA addr
);
418 ////////////////////////////////////////////////////////////////////////////////
421 relocate using data from perf.
422 If time is non-negative, its used as the time to run perf record.
423 If time is -1, we pick a random subset of translations, and relocate them
425 If time is -2, we relocate all of the translations.
427 Currently we don't ever relocate anything from frozen (or prof). We also
428 don't relocate the cold portion of translations; but we still need to know
429 where those are in order to relocate back-references to the code that was
432 void liveRelocate(int time
);
434 inline void liveRelocate(bool random
) {
435 return liveRelocate(random
? -1 : 20);
439 * Relocate a new translation to the current frontiers of main and cold. Code
440 * in frozen is not moved.
442 * TODO(t10543562): This can probably be merged with relocateNewTranslation.
444 void relocateTranslation(
446 CodeBlock
& main
, CodeBlock
& main_in
, CodeAddress main_start
,
447 CodeBlock
& cold
, CodeBlock
& cold_in
, CodeAddress cold_start
,
448 CodeBlock
& frozen
, CodeAddress frozen_start
,
449 AsmInfo
* ai
, CGMeta
& meta
453 * Record data for live relocations.
455 void recordPerfRelocMap(
457 TCA coldStart
, TCA coldEnd
,
458 SrcKey sk
, int argNum
,
459 const GrowableVector
<IncomingBranch
> &incomingBranches
,
462 ////////////////////////////////////////////////////////////////////////////////
465 * Information about the number of bound calls, branches, and tracked functions
466 * for use in logging.
469 int smashedBranches();
473 * Record a jmp at address toSmash to SrcRec sr.
475 * When a translation is reclaimed we remove all annotations from all SrcRecs
476 * containing IBs from the translation so that they cannot be inadvertently
477 * smashed in the process of replaceOldTranslations()
479 void recordJump(TCA toSmash
, SrcRec
* sr
);
482 * Insert a jump to destSk at toSmash. If no top translation for destSk exists
483 * no action is performed. On return, the value of smashed indicated whether a
484 * new address was written into the TC.
486 TCA
bindJmp(TCA toSmash
, SrcKey destSk
, TransFlags trflags
, bool& smashed
);
489 * Insert the address for branches to destSk at toSmash. Upon return, the value
490 * of smashed indicates whether an address was written into the TC.
492 TCA
bindAddr(TCA toSmash
, SrcKey destSk
, TransFlags trflags
, bool& smashed
);
495 * Bind a call to start at toSmash, where start is the prologue for callee, when
496 * invoked with nArgs.
498 void bindCall(TCA toSmash
, TCA start
, Func
* callee
, int nArgs
, bool immutable
);