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 FuncMetaInfo() = default;
91 FuncMetaInfo(Func
* f
, LocalTCBuffer
&& buf
)
94 , tcBuf(std::move(buf
))
97 FuncMetaInfo(FuncMetaInfo
&&) = default;
98 FuncMetaInfo
& operator=(FuncMetaInfo
&&) = default;
103 std::vector
<ProfTransRec
*> prologues
;
104 std::vector
<TransMetaInfo
> translations
;
107 ////////////////////////////////////////////////////////////////////////////////
110 * Returns true iff we already have Eval.JitMaxTranslations translations
111 * recorded in srcRec.
113 bool reachedTranslationLimit(TransKind kind
, SrcKey sk
, const SrcRec
& srcRec
);
116 * Emit machine code for env. Returns folly::none if the global translation
117 * limit has been reached, generates an interp request if vunit is null or
118 * codegen fails. If optDst is set it must be a thread local view and the
119 * code lock will not be acquired while writing to it.
121 * The resulting translation will not yet be live.
123 folly::Optional
<TransMetaInfo
> emitTranslation(
125 OptView optDst
= folly::none
129 * Make a translation generated by emitTranslation live. If the translation was
130 * emitted into a per-thread buffer then optSrcView must be the view into which
131 * it was emitted, it will be relocated at the end of the live TC.
133 folly::Optional
<TransLoc
> publishTranslation(
135 OptView optSrcView
= folly::none
139 * Publish a set of optimized translations associated with a particular
140 * function. It is assumed that these translations have been emitted into per-
141 * thread buffers and will need to be relocated.
143 void publishOptFunction(FuncMetaInfo info
);
146 * Acquires the code and metadata locks once and relocates all functions in
149 void publishSortedOptFunctions(std::vector
<FuncMetaInfo
> infos
);
152 * Emit a new prologue for func-- returns nullptr if the global translation
153 * limit has been reached.
155 TCA
emitFuncPrologue(Func
* func
, int argc
, TransKind kind
);
158 * Emits an optimized prologue for rec.
160 * Smashes the callers of the prologue for rec and updates the cached func
163 TCA
emitFuncPrologueOpt(ProfTransRec
* rec
);
166 * Emit the prologue dispatch for func which contains dvs DV initializers, and
167 * return its start address. The `kind' of translation argument is used to
168 * decide what area of the code cache will be used (hot, main, or prof).
170 TCA
emitFuncBodyDispatch(Func
* func
, const DVFuncletsVec
& dvs
, TransKind kind
);
172 ////////////////////////////////////////////////////////////////////////////////
175 * True iff the global translation limit has not yet been reached.
180 * Whether we should emit a translation of kind for func, ignoring the cap on
183 bool shouldTranslateNoSizeLimit(const Func
* func
, TransKind kind
);
186 * Whether we should emit a translation of kind for func.
188 bool shouldTranslate(const Func
* func
, TransKind kind
);
191 * Whether we are still profiling new functions.
193 bool shouldProfileNewFuncs();
196 * Whether we should try profile-guided optimization when translating `func'.
198 bool profileFunc(const Func
* func
);
201 * Attempt to discard profData via the treadmill if it is no longer needed.
203 void checkFreeProfData();
205 ////////////////////////////////////////////////////////////////////////////////
208 * SrcRec for sk or nullptr if no SrcRec has been created.
210 SrcRec
* findSrcRec(SrcKey sk
);
213 * Create a SrcRec for sk with an sp offset of spOff.
215 void createSrcRec(SrcKey sk
, FPInvOffset spOff
);
217 ////////////////////////////////////////////////////////////////////////////////
220 * Assert ownership of the CodeCache by this thread.
222 * Must be held even if the current thread owns the global write lease.
224 void assertOwnsCodeLock(OptView v
= folly::none
);
227 * Assert ownership of the tc metadata by this thread.
229 * Must be held even if the current thread owns the global write lease.
231 void assertOwnsMetadataLock();
233 ////////////////////////////////////////////////////////////////////////////////
236 * Get the table of unique stubs
240 ALWAYS_INLINE
const UniqueStubs
& ustubs() {
241 extern UniqueStubs g_ustubs
;
246 * Perform one time process initialization for the structures associated with
252 * Perform process shutdown functions for the TC including joining any
253 * outstanding background threads.
257 ////////////////////////////////////////////////////////////////////////////////
260 * Perform TC related request initialization and teardown.
266 * Returns the total size of the TC now and at the beginning of this request,
267 * in bytes. Note that the code may have been emitted by other threads.
271 void codeEmittedThisRequest(size_t& requestEntry
, size_t& now
);
273 ////////////////////////////////////////////////////////////////////////////////
276 * Reclaim all TC space associated with func
278 * Before any space is reclaimed the following actions will be performed:
279 * (1) Smash all prologues
280 * (2) Smash all callers to bind-call unique stubs
281 * (3) Erase all call meta-data for calls into function
283 * After all calls and prologues have been smashed any on-going requests will be
284 * allowed to complete before TC Space will be reclaimed for:
286 * (2) All translations
287 * (3) All anchor translations
289 * This function should only be called from Func::destroy() and may access the
290 * fullname and ID of the function.
292 void reclaimFunction(const Func
* func
);
295 * Allows TC space for translations in trans to be reused in future
298 * Reclaiming a translation will:
299 * (1) Mark bytes available for reuse in the code-blocks associated with
301 * (2) Erase any IBs from translation into other SrcRecs
302 * (3) Erase any jump annotations in MCGenerator used to generate optimized
304 * (4) Erase an metadata about smashed calls in the translation from both the
305 * reuse-tc module and the prof-data module
307 * The translation _must_ be unreachable before reclaimTranslation() is called,
308 * this is generally done by calling reclaimFunction() or performing
309 * replaceOldTranslations() on a SrcRec
311 void reclaimTranslations(GrowableVector
<TransLoc
>&& trans
);
314 * Free an ephemeral stub.
316 void freeTCStub(TCA stub
);
318 ////////////////////////////////////////////////////////////////////////////////
321 * Emit checks for (and hooks into) an attached debugger in front of each
322 * translation in `unit' or for `SrcKey{func, offset, resumed}'.
324 bool addDbgGuards(const Unit
* unit
);
325 bool addDbgGuard(const Func
* func
, Offset offset
, ResumeMode resumeMode
);
327 ////////////////////////////////////////////////////////////////////////////////
337 * Get UsageInfo data for all the TC code sections, including global data, and
340 std::vector
<UsageInfo
> getUsageInfo();
343 * Like getUsageInfo(), but formatted as a pleasant string.
345 std::string
getTCSpace();
348 * Return a string containing the names and start addresses of all TC code
351 std::string
getTCAddrs();
354 * Dump the translation cache to files in RuntimeOption::EvalDumpTCPath
355 * (default: /tmp), returning success.
357 bool dump(bool ignoreLease
= false);
369 * Get per section memory usage data for the TC.
371 std::vector
<TCMemInfo
> getTCMemoryUsage();
373 ////////////////////////////////////////////////////////////////////////////////
376 * Convert between TC addresses and offsets.
378 extern CodeCache
* g_code
;
379 ALWAYS_INLINE TCA
offsetToAddr(uint32_t off
) {
380 return g_code
->toAddr(off
);
382 ALWAYS_INLINE
uint32_t addrToOffset(CTCA addr
) {
383 return g_code
->toOffset(addr
);
387 * Check if `addr' is an address within the TC.
389 bool isValidCodeAddress(TCA addr
);
392 * Check if `addr' is an address within the profile code block in the TC.
394 bool isProfileCodeAddress(TCA addr
);
396 ////////////////////////////////////////////////////////////////////////////////
399 relocate using data from perf.
400 If time is non-negative, its used as the time to run perf record.
401 If time is -1, we pick a random subset of translations, and relocate them
403 If time is -2, we relocate all of the translations.
405 Currently we don't ever relocate anything from frozen (or prof). We also
406 don't relocate the cold portion of translations; but we still need to know
407 where those are in order to relocate back-references to the code that was
410 void liveRelocate(int time
);
412 inline void liveRelocate(bool random
) {
413 return liveRelocate(random
? -1 : 20);
417 * Relocate a new translation to the current frontiers of main and cold. Code
418 * in frozen is not moved.
420 * TODO(t10543562): This can probably be merged with relocateNewTranslation.
422 void relocateTranslation(
424 CodeBlock
& main
, CodeBlock
& main_in
, CodeAddress main_start
,
425 CodeBlock
& cold
, CodeBlock
& cold_in
, CodeAddress cold_start
,
426 CodeBlock
& frozen
, CodeAddress frozen_start
,
427 AsmInfo
* ai
, CGMeta
& meta
431 * Record data for live relocations.
433 void recordPerfRelocMap(
435 TCA coldStart
, TCA coldEnd
,
436 SrcKey sk
, int argNum
,
437 const GrowableVector
<IncomingBranch
> &incomingBranches
,
440 ////////////////////////////////////////////////////////////////////////////////
443 * Information about the number of bound calls, branches, and tracked functions
444 * for use in logging.
447 int smashedBranches();
451 * Record a jmp at address toSmash to SrcRec sr.
453 * When a translation is reclaimed we remove all annotations from all SrcRecs
454 * containing IBs from the translation so that they cannot be inadvertently
455 * smashed in the process of replaceOldTranslations()
457 void recordJump(TCA toSmash
, SrcRec
* sr
);
460 * Insert a jump to destSk at toSmash. If no top translation for destSk exists
461 * no action is performed. On return, the value of smashed indicated whether a
462 * new address was written into the TC.
464 TCA
bindJmp(TCA toSmash
, SrcKey destSk
, TransFlags trflags
, bool& smashed
);
467 * Insert the address for branches to destSk at toSmash. Upon return, the value
468 * of smashed indicates whether an address was written into the TC.
470 TCA
bindAddr(TCA toSmash
, SrcKey destSk
, TransFlags trflags
, bool& smashed
);
473 * Bind a call to start at toSmash, where start is the prologue for callee, when
474 * invoked with nArgs.
476 void bindCall(TCA toSmash
, TCA start
, Func
* callee
, int nArgs
, bool immutable
);