Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add code to patch unresolved trampolines for x86-64 #11426

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions runtime/compiler/compile/J9Compilation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ J9::Compilation::Compilation(int32_t id,
_remoteCompilation(false),
_serializedRuntimeAssumptions(getTypedAllocator<SerializedRuntimeAssumption>(self()->allocator())),
_clientData(NULL),
_methodsRequiringTrampolines(getTypedAllocator<J9Method *>(self()->allocator())),
#endif /* defined(J9VM_OPT_JITSERVER) */
_osrProhibitedOverRangeOfTrees(false)
{
Expand Down
8 changes: 8 additions & 0 deletions runtime/compiler/compile/J9Compilation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector
TR::list<SerializedRuntimeAssumption*>& getSerializedRuntimeAssumptions() { return _serializedRuntimeAssumptions; }
ClientSessionData *getClientData() const { return _clientData; }
void setClientData(ClientSessionData *clientData) { _clientData = clientData; }

TR::list<J9Method *>& getMethodsRequiringTrampolines() { return _methodsRequiringTrampolines; }
#endif /* defined(J9VM_OPT_JITSERVER) */

TR::SymbolValidationManager *getSymbolValidationManager() { return _symbolValidationManager; }
Expand Down Expand Up @@ -430,6 +432,12 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector
// Client session data for the client that requested this out-of-process
// compilation (at the JITServer); unused (always NULL) at the client side
ClientSessionData *_clientData;

// This list contains RAM method pointers of resolved methods
// that require method trampolines.
// It needs to be sent to the client at the end of compilation
// so that trampolines can be reserved there.
TR::list<J9Method *> _methodsRequiringTrampolines;
#endif /* defined(J9VM_OPT_JITSERVER) */

TR::SymbolValidationManager *_symbolValidationManager;
Expand Down
12 changes: 11 additions & 1 deletion runtime/compiler/control/JITClientCompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include "net/ClientStream.hpp"
#include "optimizer/J9TransformUtil.hpp"
#include "runtime/CodeCacheExceptions.hpp"
#include "runtime/CodeCache.hpp"
#include "runtime/CodeCacheManager.hpp"
#include "runtime/J9VMAccess.hpp"
#include "runtime/JITClientSession.hpp"
#include "runtime/JITServerIProfiler.hpp"
Expand Down Expand Up @@ -514,6 +516,7 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes
vmInfo._helperAddresses[i] = runtimeHelperValue((TR_RuntimeHelper) i);
#endif
vmInfo._isHotReferenceFieldRequired = TR::Compiler->om.isHotReferenceFieldRequired();
vmInfo._needsMethodTrampolines = TR::CodeCacheManager::instance()->codeCacheConfig().needsMethodTrampolines();

client->write(response, vmInfo, listOfCacheDescriptors);
}
Expand Down Expand Up @@ -3285,6 +3288,7 @@ remoteCompile(
std::vector<TR_ResolvedJ9Method*> resolvedMirrorMethodsPersistIPInfo;
TR_OptimizationPlan modifiedOptPlan;
std::vector<SerializedRuntimeAssumption> serializedRuntimeAssumptions;
std::vector<J9Method *> methodsRequiringTrampolines;
try
{
// Release VM access just before sending the compilation request
Expand Down Expand Up @@ -3316,7 +3320,7 @@ remoteCompile(
{
auto recv = client->getRecvData<std::string, std::string, CHTableCommitData, std::vector<TR_OpaqueClassBlock*>,
std::string, std::string, std::vector<TR_ResolvedJ9Method*>,
TR_OptimizationPlan, std::vector<SerializedRuntimeAssumption>, bool>();
TR_OptimizationPlan, std::vector<SerializedRuntimeAssumption>, bool, std::vector<J9Method *>>();
statusCode = compilationOK;
codeCacheStr = std::get<0>(recv);
dataCacheStr = std::get<1>(recv);
Expand All @@ -3327,6 +3331,7 @@ remoteCompile(
resolvedMirrorMethodsPersistIPInfo = std::get<6>(recv);
modifiedOptPlan = std::get<7>(recv);
serializedRuntimeAssumptions = std::get<8>(recv);
methodsRequiringTrampolines = std::get<10>(recv);

compInfoPT->getCompilationInfo()->setServerHasLowPhysicalMemory(std::get<9>(recv));
}
Expand Down Expand Up @@ -3470,6 +3475,11 @@ remoteCompile(
} // end switch (it->getKind())
}
metaData->runtimeAssumptionList = *(compiler->getMetadataAssumptionList());

for (auto& it : methodsRequiringTrampolines)
{
compInfoPT->reloRuntime()->codeCache()->reserveResolvedTrampoline((TR_OpaqueMethodBlock *) it, true);
}
}

if (!compiler->getOption(TR_DisableCHOpts) && !useAotCompilation)
Expand Down
14 changes: 13 additions & 1 deletion runtime/compiler/control/JITServerCompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,25 @@ outOfProcessCompilationEnd(
bool serverHasLowMemory = (freePhysicalMemorySizeB != OMRPORT_MEMINFO_NOT_AVAILABLE &&
freePhysicalMemorySizeB <= (uint64_t)TR::Options::getSafeReservePhysicalMemoryValue() + 4 * TR::Options::getScratchSpaceLowerBound());

// Send methods requring resolved trampolines in this compilation to the client
std::vector<J9Method *> methodsRequiringTrampolines;
if (comp->getMethodsRequiringTrampolines().size() > 0)
{
methodsRequiringTrampolines.reserve(comp->getMethodsRequiringTrampolines().size());
for (auto it : comp->getMethodsRequiringTrampolines())
{
methodsRequiringTrampolines.push_back(it);
}
}

entry->_stream->finishCompilation(codeCacheStr, dataCacheStr, chTableData,
std::vector<TR_OpaqueClassBlock*>(classesThatShouldNotBeNewlyExtended->begin(), classesThatShouldNotBeNewlyExtended->end()),
logFileStr, svmSymbolToIdStr,
(resolvedMirrorMethodsPersistIPInfo) ?
std::vector<TR_ResolvedJ9Method*>(resolvedMirrorMethodsPersistIPInfo->begin(), resolvedMirrorMethodsPersistIPInfo->end()) :
std::vector<TR_ResolvedJ9Method*>(),
*entry->_optimizationPlan, serializedRuntimeAssumptions, serverHasLowMemory
*entry->_optimizationPlan, serializedRuntimeAssumptions, serverHasLowMemory,
methodsRequiringTrampolines
);
compInfoPT->clearPerCompilationCaches();

Expand Down
2 changes: 1 addition & 1 deletion runtime/compiler/env/VMJ9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5333,7 +5333,7 @@ TR_J9VMBase::reserveTrampolineIfNecessary(TR::Compilation * comp, TR::SymbolRefe

// AOT compiles create a relocation at the snippet do do the trampoline reservation
// would be better to implement this code via a virtual function that's empty for TR_J9SharedCacheVM
if (!isAOT_DEPRECATED_DO_NOT_USE())
if (!isAOT_DEPRECATED_DO_NOT_USE() && !comp->isOutOfProcessCompilation())
{
bool hadClassUnloadMonitor;
bool hadVMAccess = releaseClassUnloadMonitorAndAcquireVMaccessIfNeeded(comp, &hadClassUnloadMonitor);
Expand Down
13 changes: 11 additions & 2 deletions runtime/compiler/env/VMJ9Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1817,9 +1817,18 @@ TR_J9ServerVM::getClassFromCP(J9ConstantPool *cp)
}

void
TR_J9ServerVM::reserveTrampolineIfNecessary(TR::Compilation *, TR::SymbolReference *symRef, bool inBinaryEncoding)
TR_J9ServerVM::reserveTrampolineIfNecessary(TR::Compilation *comp, TR::SymbolReference *symRef, bool inBinaryEncoding)
{
// Not necessary in JITServer server mode
// We only need to reserve trampolines on the client when
// we need a resolved trampoline for non-AOT compilation
JITServer::ServerStream *stream = _compInfoPT->getMethodBeingCompiled()->_stream;
if (!comp->compileRelocatableCode()
&& _compInfoPT->getClientData()->getOrCacheVMInfo(stream)->_needsMethodTrampolines
&& !symRef->isUnresolved())
{
J9Method *ramMethod = (J9Method *) symRef->getSymbol()->castToResolvedMethodSymbol()->getResolvedMethod()->getPersistentIdentifier();
comp->getMethodsRequiringTrampolines().push_front(ramMethod);
}
}

intptr_t
Expand Down
2 changes: 2 additions & 0 deletions runtime/compiler/runtime/J9CodeCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ J9::CodeCache::adjustTrampolineReservation(TR_OpaqueMethodBlock *method,
void *cp,
int32_t cpIndex)
{
fprintf(stderr, "method=%p cp=%p cpIndex=%d\n", method, cp, cpIndex);
OMR::CodeCacheHashEntry *unresolvedEntry;
OMR::CodeCacheHashEntry *resolvedEntry;

Expand Down Expand Up @@ -581,6 +582,7 @@ J9::CodeCache::adjustTrampolineReservation(TR_OpaqueMethodBlock *method,
}
else if (unresolvedEntry && !resolvedEntry)
{
fprintf(stderr, "resolving trampoline for method=%p\n", method);
// Move the unresolved entry to the resolved table.
self()->resolveHashEntry(unresolvedEntry, method);
}
Expand Down
1 change: 1 addition & 0 deletions runtime/compiler/runtime/JITClientSession.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ class ClientSessionData
void *_helperAddresses[TR_numRuntimeHelpers];
#endif
bool _isHotReferenceFieldRequired;
bool _needsMethodTrampolines;
}; // struct VMInfo

/**
Expand Down
9 changes: 8 additions & 1 deletion runtime/compiler/x/codegen/CallSnippet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ uint8_t *TR::X86CallSnippet::emitSnippetBody()
needToSetCodeLocation = false;

if (cg()->hasCodeCacheSwitched() &&
(methodSymRef->getReferenceNumber()>=TR_AMD64numRuntimeHelpers))
(methodSymRef->getReferenceNumber()>=TR_AMD64numRuntimeHelpers))
{
fej9->reserveTrampolineIfNecessary(comp, methodSymRef, true);
}
Expand Down Expand Up @@ -917,6 +917,13 @@ uint8_t *TR::X86CallSnippet::emitSnippetBody()
TR_ConstantPool,
cg()),
__FILE__, __LINE__, getNode());

cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,
*(uint8_t **)cursor,
getNode() ? (uint8_t *)(uintptr_t)getNode()->getInlinedSiteIndex() : (uint8_t *)-1,
TR_Trampolines,
cg()),
__FILE__, __LINE__, getNode());
cursor += sizeof(intptr_t);

// DD cpIndex
Expand Down
30 changes: 30 additions & 0 deletions runtime/compiler/x/runtime/X86Unresolveds.nasm
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,7 @@ executeSnippetCode:
DECLARE_EXTERN jitResolvedFieldIsVolatile

DECLARE_EXTERN mcc_callPointPatching_unwrapper
DECLARE_EXTERN mcc_reservationAdjustment_unwrapper


; interpreterUnresolved{Static|Special}Glue
Expand Down Expand Up @@ -931,6 +932,20 @@ interpreterUnresolvedStaticGlue:
shl rax, 16
xor rax, 0bf48h ; REX+MOV bytes
mov qword [rsi-5], rax ; Replaced current call with "mov rdi, 0x0000aabbccddeeff"

; Call to adjust trampoline reservations, since this callsite is now resolved
mov edx, dword [rsi + 20]
push rdx ; descriptor+24: CP index
mov rdx, qword [rsi + 12]
push rdx ; descriptor+16: CP address
push rdi ; descriptor+8: RAM method
push rsi ; descriptor+0: compiled method PC
MoveHelper rax, mcc_reservationAdjustment_unwrapper ; p1) rax = helper
lea rsi, [rsp] ; p2) rsi = EA of descriptor
lea rdx, [rsp] ; p3) rdx = EA of return value
call jitCallCFunction
add rsp, 32 ; tear down descriptor

jmp interpreterStaticAndSpecialGlue ; The next instruction is always "jmp interpreterStaticAndSpecialGlue",
; jump to its target directly.
.skippatching:
Expand Down Expand Up @@ -963,6 +978,20 @@ interpreterUnresolvedSpecialGlue:
shl rax, 16
xor rax, 0bf48h ; REX+MOV bytes
mov qword [rsi-5], rax ; Replaced current call with "mov rdi, 0x0000aabbccddeeff"

; Call to adjust trampoline reservations, since this callsite is now resolved
mov edx, dword [rsi + 20]
push rdx ; descriptor+24: CP index
mov rdx, qword [rsi + 12]
push rdx ; descriptor+16: CP address
push rdi ; descriptor+8: RAM method
push rsi ; descriptor+0: compiled method PC
MoveHelper rax, mcc_reservationAdjustment_unwrapper ; p1) rax = helper
lea rsi, [rsp] ; p2) rsi = EA of descriptor
lea rdx, [rsp] ; p3) rdx = EA of return value
call jitCallCFunction
add rsp, 32 ; tear down descriptor

jmp interpreterStaticAndSpecialGlue ; The next instruction is always "jmp interpreterStaticAndSpecialGlue",
; jump to its target directly.

Expand Down Expand Up @@ -991,6 +1020,7 @@ interpreterStaticAndSpecialGlue:

mov rsi, qword [rsp] ; rsi = RA in mainline code
sub rsi, 5

push 0 ; descriptor+24: 0
push rcx ; descriptor+16: compiled method PC
push rsi ; descriptor+8: call site
Expand Down