Replace REQ_RETRANSLATE_OPT with a regular C++ call via ustub
[hiphop-php.git] / hphp / runtime / vm / jit / unique-stubs.h
blobe7479f5de35d7bb865e591ff8ce7499574b2fb73
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 #pragma once
19 #include "hphp/runtime/vm/call-flags.h"
20 #include "hphp/runtime/vm/hhbc.h"
22 #include "hphp/runtime/vm/jit/code-cache.h"
23 #include "hphp/runtime/vm/jit/containers.h"
24 #include "hphp/runtime/vm/jit/types.h"
25 #include "hphp/runtime/vm/jit/phys-reg.h"
26 #include "hphp/runtime/vm/jit/srcdb.h"
27 #include "hphp/runtime/vm/jit/stack-offsets.h"
29 #include <string>
30 #include <vector>
32 namespace HPHP {
34 struct ActRec;
35 struct SrcKey;
37 namespace Debug { struct DebugInfo; }
39 namespace jit {
41 ///////////////////////////////////////////////////////////////////////////////
43 constexpr int kNumFreeLocalsHelpers = 7;
46 * Addresses of various unique, long-lived JIT helper routines.
48 * The global set of unique stubs is emitted when we initialize the TC.
50 struct UniqueStubs {
52 * Unique stubs, ABIs, and stack alignment.
54 * A lot of complex control flow occurs amongst the various unique stubs, as
55 * well as between the unique stubs and the TC. This complexity is
56 * exacerbated by the profusion of different ABIs used when entering and
57 * exiting the stubs.
59 * The goal of the documentation in this file is to enumerate all the ways
60 * each stub is reached, as well as to clarify the ABI boundaries they
61 * implement to, if any.
63 * Among the most important ABI invariants in jitted code is this:
65 * - In the body of a PHP function, after the initial instructions of the
66 * func prologue, the native stack pointer is always 16-byte aligned.
68 * This holds even when the register allocator inserts stack spills; we
69 * always offset the native stack pointer in increments of 16.
71 * Many target architectures have 16-byte stack alignment restrictions. On
72 * x64, for example, the stack must be 16-byte aligned before calls, to allow
73 * the compiler to safely use aligned movs, e.g., for saving callee-saved XMM
74 * registers. On AArch64, attempting to address the stack pointer when it is
75 * not 16-byte aligned results in a fault.
77 * Our alignment invariant should be sufficient for architectures with
78 * 16-byte (or looser) alignment constraints. We don't currently support any
79 * higher- order alignment restrictions.
81 * Our other ABI concern is calling convention. HHVM supports three distinct
82 * calling conventions:
83 * - native: C++ helper calls on the targeted architecture
84 * - PHP: calls between PHP functions, as well as to those unique stubs
85 * which play the same role as various parts of PHP functions
86 * - stub: calls to unique stubs that implement helper routines
88 * Maintaining native stack alignment, and appropriately stashing the return
89 * address, is shared between the call, return, and callee prologue
90 * instructions for each convention:
92 * +---------------------+---------+-----------+
93 * | main call instrs | return | prologue |
94 * +---------+---------------------+---------+-----------+
95 * | native | call{,r,m,s} | ret | N/A |
96 * +---------+---------------------+---------+-----------+
97 * | PHP | phpcall | phpret | phplogue |
98 * +---------+---------------------+---------+----------+
99 * | stub | callstub | stubret | stublogue |
100 * +---------+---------------------+---------+-----------+
102 * Further documentation on these calling conventions can be found in
103 * vasm-instr.h, alongside the corresponding instructions.
105 * Each stub is documented below with a (hopefully) exhaustive list of ways
106 * it is reached, as well as the context under which it is reached:
107 * - func guard: pre-phplogue{}; an intermediate state where
108 * addressing the stack and making native calls are
109 * forbidden
110 * - func prologue: implements a phplogue{}
111 * - func body: dominated by a phplogue{}; already ABI-conforming
112 * - stub: implements a stublogue{}
115 /////////////////////////////////////////////////////////////////////////////
116 // Function entry.
119 * Dynamically dispatch to the appropriate func prologue based on the
120 * information in php_call_regs, while repacking arguments as needed.
122 * @reached: callphp from TC
123 * @context: func guard
125 TCA funcPrologueRedispatch;
126 TCA funcPrologueRedispatchUnpack;
129 * Look up or emit a func prologue and jump to it---or, failing that, call
130 * native routines that do the same work.
132 * All entries in the prologue tables of all Funcs are initialized to this
133 * stub, so that we can lazily generate their prologues. If codegen for the
134 * prologue succeeds, we update the prologue table to point to the new
135 * prologue instead of this stub.
137 * @reached: callphpr from TC
138 * callphps from TC
139 * jmp from immutableBindCallStub
140 * jmp from funcPrologueRedispatch
141 * jmp from funcPrologueRedispatchUnpack
142 * @context: func prologue
144 TCA fcallHelperThunk;
145 TCA fcallHelperNoTranslateThunk;
148 * Call EventHook::onFunctionCall() and handle the case where it requests
149 * that we skip the function.
151 * @reached: vinvoke from func prologue
152 * jmp from functionSurprisedOrStackOverflow
153 * @context: stub
155 TCA functionEnterHelper;
158 * Handle either a surprise condition or a stack overflow.
160 * Also gracefully handles spurious wake-ups that result from racing with a
161 * background thread clearing surprise flags.
163 * @reached: vinvoke from func prologue
164 * @context: stub
166 TCA functionSurprisedOrStackOverflow;
169 /////////////////////////////////////////////////////////////////////////////
170 // Function return.
173 * Return from a function when the ActRec was pushed by the interpreter.
175 * The return IP on the ActRec will be set to one of these stubs, so if
176 * someone tries to execute a return instruction, handlePostInterpRet() gets
177 * a chance to translate the code starting at the return address.
179 * Generators need a different stub because the ActRec for a generator is in
180 * the heap.
182 * @reached: phpret from TC
183 * @context: func body (after returning to caller)
185 TCA retHelper;
186 TCA genRetHelper; // version for generator
187 TCA asyncGenRetHelper; // version for async generators
190 * Return from a function when the ActRec was pushed by an inlined call.
192 * This is the same as retHelper, but is kept separate to aid in debugging.
194 * @reached: phpret from TC
195 * @context: func body (after returning to caller)
197 TCA retInlHelper;
200 * Return from a resumed async function.
202 * Store result into the AsyncFunctionWaitHandle, mark it as finished and
203 * unblock its parents. Check whether the first parent is eligible to be
204 * resumed directly (it is an AsyncFunctionWaitHandle in the same context
205 * with a non-null resume address), and do so if possible. Otherwise, jump
206 * to asyncSwitchCtrl. Slow version doesn't try to resume and just returns
207 * to the asio scheduler.
209 * rvmfp() should point to the ActRec of the AsyncFunctionWaitHandle that
210 * is returning, rvmsp() should point to an uninitialized cell on the
211 * stack containing garbage.
213 * @reached: jmp from TC
214 * @context: func body
216 TCA asyncFuncRet;
217 TCA asyncFuncRetSlow;
220 * Async function finish-suspend-and-resume stub.
222 * Check for fast resumables on the AsioContext runnable queue. If one is
223 * found that is ready to run, jump to it directly; otherwise, leave the TC
224 * and return to the scheduler.
226 * rvmfp() should point to the ActRec of the WaitHandle that is suspending.
228 * @reached: jmp from TC
229 * @context: func body
231 TCA asyncSwitchCtrl;
234 /////////////////////////////////////////////////////////////////////////////
235 // Function calls.
238 * Stub for immutable PHP calls.
240 * @reached: callphps from TC
241 * @context: func prologue
243 TCA immutableBindCallStub;
246 /////////////////////////////////////////////////////////////////////////////
247 // Interpreter stubs.
250 * Restart execution based on the value of vmpc. Used, e.g., to resume
251 * execution after an InterpOne.
253 * Expects that all VM registers are synced.
255 * @reached: entry from jit::enterTC
256 * jmp from fcallHelperThunk
257 * call from enterTCHelper
258 * @context: func body
260 TCA resumeHelper;
261 TCA resumeHelperNoTranslate;
264 * Like resumeHelper, but interpret a basic block first to ensure we make
265 * forward progress.
267 * interpHelper expects the correct value of vmpc to be in the first argument
268 * register and syncs it, whereas interpHelperSyncedPC expects vmpc to be
269 * synced a priori. Both stubs will sync the vmsp and vmfp registers to
270 * vmRegs before passing control to the interpreter.
272 * @reached: jmp from TC
273 * @context: func body
275 TCA interpHelper;
276 TCA interpHelperSyncedPC;
277 TCA interpHelperNoTranslate;
280 * Stubs for each bytecode with the CF flag, which InterpOne the bytecode and
281 * then call resumeHelper.
283 * These stubs expect rvmfp() and rvmsp() to be live, and rAsm to contain the
284 * offset to the bytecode to interpret.
286 * @reached: jmp from TC
287 * @context: func body
289 jit::fast_map<Op, TCA> interpOneCFHelpers;
292 /////////////////////////////////////////////////////////////////////////////
293 // DecRefs.
296 * Expensive, generic decref of a value with an unknown (but known to be
297 * refcounted) DataType.
299 * The value to be decref'd should be in the first two argument registers
300 * (data, type). All GP registers are saved around the destructor call.
302 * @reached: callfaststub from TC
303 * @context: stub
305 TCA decRefGeneric;
308 * Perform generic decrefs of locals on function return.
310 * Each freeLocalHelpers[i] is an entry point to a partially-unrolled loop.
311 * freeManyLocalsHelper should be used instead when there are more than
312 * kNumFreeLocalsHelpers locals.
314 * These helpers expect the address of the frame's last local variable (which
315 * has the lowest address) to be passed in the second argument register. The
316 * first argument register is ignored.
318 * @reached: vcall from TC
319 * @context: stub
321 TCA freeLocalsHelpers[kNumFreeLocalsHelpers];
322 TCA freeManyLocalsHelper;
325 /////////////////////////////////////////////////////////////////////////////
326 // Other stubs.
329 * Enter (or reenter) the TC.
331 * This is an assembly stub called from native code to transfer control
332 * (back) to jitted PHP code.
334 * enterTCExit is the address returned to when we leave the TC.
336 void (*enterTCHelper)(TCA start, ActRec* fp, void* tl, TypedValue* sp,
337 ActRec* firstAR);
338 TCA enterTCExit;
341 * Return from this VM nesting level to the previous one.
343 * This has the same effect as a leavetc{} instruction---it pops the address
344 * of enterTCExit off the stack and transfers control to it.
346 * @reached: phpret from TC
347 * jmp from TC
348 * @context: func body
350 TCA callToExit;
353 * Perform dispatch at the end of a catch block.
355 * The endCatchHelper passes the current vmfp() to the unwinder to determine
356 * the catch trace of the return address of the parent frame.
358 * The endCatchStublogueHelper passes the current vmfp() and RIP saved in
359 * the stublogue header. Unwinder uses it to determine the catch trace of
360 * the return adddress belonging to the same logical vmfp().
362 * The endCatchStubloguePrologueHelper initializes the ActRec space pointed
363 * to by the rvmsp() to uninits and continues at endCatchStublogueHelper.
365 * If the unwinder has set state indicating a return address to jump to, we
366 * load vmfp and vmsp and jump there. Otherwise, we call _Unwind_Resume.
368 TCA resumeCPPUnwind;
369 TCA endCatchSkipTeardownHelper;
370 TCA endCatchTeardownThisHelper;
371 TCA endCatchHelper;
372 TCA endCatchHelperPast;
373 TCA endCatchStublogueHelper;
374 TCA endCatchStubloguePrologueHelper;
375 TCA unwinderAsyncRet;
376 TCA unwinderAsyncNullRet;
379 * Throws an exception from the unwinder to enter the itanium unwinder
381 TCA throwExceptionWhileUnwinding;
384 * Service request helper.
386 * Packs service request arguments into a struct on the stack before calling
387 * the C++ service request handler.
389 * @reached: jmp from TC
390 * @context: func body
392 TCA handleSRHelper;
395 * Handle a request to retranslate the current function in optimized mode.
396 * See svcreq::handleRetranslateOpt() for more details.
398 * @reached: jmp from TC
399 * @context: func body
401 TCA handleRetranslateOpt;
403 /////////////////////////////////////////////////////////////////////////////
406 * Emit the full set of unique stubs to `code'.
408 void emitAll(CodeCache& code, Debug::DebugInfo& dbg);
411 * Utility for logging stub addresses during startup and registering the gdb
412 * symbols. It's often useful to know where they were when debugging.
414 void add(const char* name,
415 const CodeCache& code,
416 TCA start,
417 CodeCache::View view,
418 TransLoc loc,
419 Debug::DebugInfo& dbg);
422 * If the given address is within one of the registered stubs, return a
423 * string indicating which stub and how far in it is: "retHelper+0xfa".
425 * Otherwise, return a string representation of the raw address: "0xabcdef".
427 std::string describe(TCA addr) const;
429 private:
431 * Emit all Resumable-related unique stubs to `code'.
433 void emitAllResumable(CodeCache& code, Debug::DebugInfo& dbg);
435 struct StubRange {
436 std::string name;
437 TCA start, end;
439 bool operator<(const StubRange& other) const {
440 return start < other.start;
443 bool contains(TCA address) const {
444 return start <= address && address < end;
448 std::vector<StubRange> m_ranges;
451 ////////////////////////////////////////////////////////////////////////////////
454 * Registers that are live on entry to an interpOneCFHelper.
456 RegSet interp_one_cf_regs();
459 * Emit code to `v' which jumps to interpHelper with the proper arguments.
461 void emitInterpReq(Vout& v, SrcKey sk, SBInvOffset spOff);
462 void emitInterpReqNoTranslate(Vout& v, SrcKey sk, SBInvOffset spOff);
464 ///////////////////////////////////////////////////////////////////////////////
467 * Wrappers around the enterTC*Helper stubs, called from enterTC*().
469 void enterTCImpl(TCA start);
471 ///////////////////////////////////////////////////////////////////////////////