Add sub-controls for Hack array compat runtime checks
[hiphop-php.git] / hphp / runtime / vm / jit / tc.h
blob676beaa89686c85f521afd69931a1d0090459454
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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>
33 #include <memory>
34 #include <string>
35 #include <vector>
37 namespace HPHP { namespace jit {
39 struct AsmInfo;
40 struct FPInvOffset;
41 struct IncomingBranch;
42 struct IRUnit;
43 struct ProfTransRec;
44 struct TransEnv;
45 struct TransLoc;
46 struct Vunit;
48 using OptView = folly::Optional<CodeCache::View>;
50 ////////////////////////////////////////////////////////////////////////////////
52 namespace tc {
54 struct TransRange {
55 TcaRange main;
56 TcaRange cold;
57 TcaRange frozen;
58 TcaRange data;
60 TransLoc loc() const;
63 struct TransMetaInfo {
64 SrcKey sk;
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
68 TransRange range;
69 CGMeta meta;
70 TransRec transRec;
73 struct LocalTCBuffer {
74 LocalTCBuffer() = default;
75 explicit LocalTCBuffer(Address start, size_t initialSize);
76 LocalTCBuffer(LocalTCBuffer&&) = default;
77 LocalTCBuffer& operator=(LocalTCBuffer&&) = default;
79 OptView view();
80 bool valid() const { return m_main.base() != nullptr; }
82 private:
83 CodeBlock m_main;
84 CodeBlock m_cold;
85 CodeBlock m_frozen;
86 DataBlock m_data;
89 struct FuncMetaInfo {
90 enum class Kind : uint8_t {
91 Prologue,
92 Translation,
95 FuncMetaInfo() = default;
96 FuncMetaInfo(Func* f, LocalTCBuffer&& buf)
97 : fid(f->getFuncId())
98 , func(f)
99 , tcBuf(std::move(buf))
102 FuncMetaInfo(FuncMetaInfo&&) = default;
103 FuncMetaInfo& operator=(FuncMetaInfo&&) = default;
105 FuncId fid;
106 Func* func;
107 LocalTCBuffer tcBuf;
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(
146 TransEnv env,
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(
156 TransMetaInfo info,
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
169 * sorted list.
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
183 * prologue.
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.
199 bool canTranslate();
202 * Whether we should emit a translation of kind for func, ignoring the cap on
203 * overall TC size.
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
260 * Pre: processInit()
262 ALWAYS_INLINE const UniqueStubs& ustubs() {
263 extern UniqueStubs g_ustubs;
264 return g_ustubs;
268 * Perform one time process initialization for the structures associated with
269 * this module.
271 void processInit();
274 * Perform process shutdown functions for the TC including joining any
275 * outstanding background threads.
277 void processExit();
279 ////////////////////////////////////////////////////////////////////////////////
282 * Perform TC related request initialization and teardown.
284 void requestInit();
285 void requestExit();
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.
291 * Pre: requestInit()
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:
307 * (1) All prologues
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
318 * translations.
320 * Reclaiming a translation will:
321 * (1) Mark bytes available for reuse in the code-blocks associated with
322 * the translation
323 * (2) Erase any IBs from translation into other SrcRecs
324 * (3) Erase any jump annotations in MCGenerator used to generate optimized
325 * traces
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 ////////////////////////////////////////////////////////////////////////////////
351 struct UsageInfo {
352 std::string name;
353 size_t used;
354 size_t capacity;
355 bool global;
359 * Get UsageInfo data for all the TC code sections, including global data, and
360 * also for RDS.
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
371 * sections.
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);
381 struct TCMemInfo {
382 std::string name;
383 size_t used;
384 size_t allocs;
385 size_t frees;
386 size_t free_size;
387 size_t free_blocks;
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
424 in a random order.
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
430 relocated.
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(
445 const IRUnit* unit,
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(
456 TCA start, TCA end,
457 TCA coldStart, TCA coldEnd,
458 SrcKey sk, int argNum,
459 const GrowableVector<IncomingBranch> &incomingBranches,
460 CGMeta& fixups);
462 ////////////////////////////////////////////////////////////////////////////////
465 * Information about the number of bound calls, branches, and tracked functions
466 * for use in logging.
468 int smashedCalls();
469 int smashedBranches();
470 int recordedFuncs();
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);
502 #endif