Use thread-local TC for codegen and relocate translations into the TC
commitb01abd12d38ae754025c22d1662b73edc3a9145f
authorPaul Bissonnette <paulbiss@fb.com>
Mon, 5 Dec 2016 18:11:51 +0000 (5 10:11 -0800)
committerHhvm Bot <hhvm-bot-bot@fb.com>
Wed, 7 Dec 2016 20:39:40 +0000 (7 12:39 -0800)
tree8955bab51faf6e52cbf99e6c52cbe08f583cb993
parent42d4cd79e1aa188d79c8e5c95c4db9c4f8312e5e
Use thread-local TC for codegen and relocate translations into the TC

Summary:
This diff provides the initial scaffolding required for threads to generate
optimized translations within thread-local caches which can be subsequently
relocated into the global TC. The mechanism introduces a metadata for
tracking the prologues and optimized translations for each function which
is retranslated. The `tc::emitTranslation` function has been broken into two
logical pieces:

a) emitTranslation: Emits a translation which may optionally be written to
a thread local buffer. The translation is not written to the SrcDB and will
not yet be live. A struct containing the metadata required to make the
translation live is returned.

b) publishTranslation: Publishes a translation which was previously generated
via emitTranslation, relocating the translation into the TC if necessary. After this
function is called any thread-local structures used to store the associated
translation may be freed.

Additionally a `publishOptFunction` helper is provided which will write regenerate
prologues and emit any associated translations for a function being optimized.

To avoid exhausting the available low memory, while still emitting correct code,
a single region of low memory at the end of the TC is set aside as the "virtual"
address space for thread local caches. Caches themselves are allocated via
malloc into normal memory, but all PIC addresses are computed as though the
base were at the end of the TC. For debuggability this memory is actually reserved
and made unreachable via mprotect, this is not a requirement.

After this diff all opt translations will be first written to a thread-local cache and
then immediately relocated into the TC. Ultimately the goal here will be to perform
all emitTranslation calls in parallel and only later relocate translations via a series
of calls to publishTranslation via a single worker thread which will have also
selected an optimal ordering for the associated translations.

Open questions include:

Should the caches be per function or per thread (per thread was chosen to avoid
thrashing the allocator, however, it will likely result in overcommitting memory for
translations). As these caches need not live within the TC there is no concern about
exhaustion of the low memory available.

Should we perform more granular publishing of optimized translations so that the
client code can choose to interleave translations of different functions. As all dispatch
is performed through the prologue the main advantage here would be to place short
callees immediately adjacent to their calling translations.

Should we defer the allocation of literals? Right now they are allocated into the
local data segment and immediately relocated, perhaps this should be done as part
of the process step.

Should we introduce an opaque address abstraction to replace the need for
toRealAddress() and frontier()? I avoided doing this as my initial refactor attempt
generated a great deal of churn in the JIT, but it would likely help to prevent future
errors. In particular this abstraction would hold both a real and virtual address and
perform all difference calculations relative to the virtual address while yielding any
dereferenced results from the real address. If anyone feels strongly that we should
do it this way first I can prepare a codemod.

Reviewed By: swtaarrs

Differential Revision: D4025890

fbshipit-source-id: 19dea7a05ed379f716037b059bf0d3f3953415c9
35 files changed:
hphp/runtime/base/runtime-option.h
hphp/runtime/vm/jit/code-cache.cpp
hphp/runtime/vm/jit/code-cache.h
hphp/runtime/vm/jit/mcgen-prologue.cpp
hphp/runtime/vm/jit/mcgen-prologue.h
hphp/runtime/vm/jit/mcgen-translate.cpp
hphp/runtime/vm/jit/mcgen-translate.h
hphp/runtime/vm/jit/mcgen.cpp
hphp/runtime/vm/jit/mcgen.h
hphp/runtime/vm/jit/relocation-arm.h
hphp/runtime/vm/jit/relocation-ppc64.cpp
hphp/runtime/vm/jit/relocation-ppc64.h
hphp/runtime/vm/jit/relocation-x64.cpp
hphp/runtime/vm/jit/relocation-x64.h
hphp/runtime/vm/jit/relocation.cpp
hphp/runtime/vm/jit/relocation.h
hphp/runtime/vm/jit/service-request-handlers.cpp
hphp/runtime/vm/jit/service-requests.cpp
hphp/runtime/vm/jit/smashable-instr-x64.cpp
hphp/runtime/vm/jit/stub-alloc.cpp
hphp/runtime/vm/jit/tc-internal.cpp
hphp/runtime/vm/jit/tc-internal.h
hphp/runtime/vm/jit/tc-prologue.cpp
hphp/runtime/vm/jit/tc-record.cpp
hphp/runtime/vm/jit/tc-record.h
hphp/runtime/vm/jit/tc-region.cpp
hphp/runtime/vm/jit/tc-relocate.cpp
hphp/runtime/vm/jit/tc.h
hphp/runtime/vm/jit/vasm-emit.cpp
hphp/runtime/vm/jit/vasm-internal.cpp
hphp/runtime/vm/jit/vasm-x64.cpp
hphp/util/asm-x64.cpp
hphp/util/asm-x64.h
hphp/util/data-block.cpp
hphp/util/data-block.h