blob: 86254f4c981184f8f1505fba513b4b163e71ac2a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, Konstantin M. Anisimov, Igor V. Chebykin
*
*/
#include "RuntimeInterface_arch.h"
#include "IpfEncoder.h"
#include "IpfType.h"
#include "IpfOpndManager.h"
using namespace std;
namespace Jitrino {
namespace IPF {
//========================================================================================//
// RuntimeInterface
//========================================================================================//
void RuntimeInterface::unwindStack(MethodDesc *methodDesc,
JitFrameContext *jitFrameContext,
bool isFirst) {
// cout << "IPF::RuntimeInterface::unwindStack " << methodDesc->getName() << endl;
U_8* infoBlock = methodDesc->getInfoBlock(); // get method infoBlock
StackInfo stackInfo = *((StackInfo*) infoBlock); // read StackInfo structure
uint64 sp = jitFrameContext->sp; // get current frame sp
uint64 addr = sp + stackInfo.savedBase; // mem stack offset of first saved gr
U_32 savedGrMask = stackInfo.savedGrMask; // mask of preserved grs saved on stack
U_32 savedFrMask = stackInfo.savedFrMask; // mask of preserved frs saved on stack
U_32 savedBrMask = stackInfo.savedBrMask; // mask of preserved frs saved on stack
// Restore preserved general registers
if(savedGrMask != 0) {
for(U_32 i=0; i<32; i++) {
if((savedGrMask & 1) == 1) {
jitFrameContext->p_gr[i] = (uint64 *)addr;
addr += 8;
}
savedGrMask >>= 1;
}
}
// Restore preserved floating registers
if(savedFrMask != 0) {
for(U_32 i=0; i<32; i++) {
if((savedFrMask & 1) == 1) {
jitFrameContext->p_fp[i] = (uint64 *)addr;
addr += 16;
}
savedFrMask >>= 1;
}
}
// Restore preserved branch registers
if(savedBrMask != 0) {
for(U_32 i=0; i<8; i++) {
if((savedBrMask & 1) == 1) {
jitFrameContext->p_br[i] = (uint64 *)addr;
addr += 8;
}
savedBrMask >>= 1;
}
}
// restore sp
jitFrameContext->sp += stackInfo.memStackSize;
// Restore return pointer
I_32 rpBak = stackInfo.rpBak;
if(rpBak != LOCATION_INVALID) {
if(rpBak >= S_BASE) jitFrameContext->p_eip = (uint64 *)(sp + rpBak - S_BASE);
else jitFrameContext->p_eip = jitFrameContext->p_gr[rpBak];
}
// Restore prs
I_32 prBak = stackInfo.prBak;
if(prBak != LOCATION_INVALID) {
if(prBak >= S_BASE) jitFrameContext->preds = *((uint64 *)(sp + prBak - S_BASE));
else jitFrameContext->preds = *(jitFrameContext->p_gr[prBak]);
}
// Restore pfs
I_32 pfsBak = stackInfo.pfsBak;
if(pfsBak != LOCATION_INVALID) {
if(pfsBak >= S_BASE) jitFrameContext->p_ar_pfs = (uint64 *)(sp + pfsBak - S_BASE);
else jitFrameContext->p_ar_pfs = jitFrameContext->p_gr[pfsBak];
}
// Restore unat
I_32 unatBak = stackInfo.unatBak;
if(unatBak != LOCATION_INVALID) {
if(unatBak >= S_BASE) jitFrameContext->ar_unat = *((uint64 *)(sp + unatBak - S_BASE));
else jitFrameContext->ar_unat = *(jitFrameContext->p_gr[unatBak]);
}
// cout << " sp " << hex << jitFrameContext->sp << dec << " frame size " << stackInfo.memStackSize << endl;
// if(savedGrMask != 0) cout << " savedGrMask " << hex << savedGrMask << dec << endl;
// if(savedFrMask != 0) cout << " savedFrMask " << hex << savedFrMask << dec << endl;
// if(savedBrMask != 0) cout << " savedBrMask " << hex << savedBrMask << dec << endl;
// if(pfsBak != LOCATION_INVALID) cout << " pfsBak " << pfsBak << " " << hex << *(jitFrameContext->p_ar_pfs) << dec << endl;
// if(rpBak != LOCATION_INVALID) cout << " rpBak " << rpBak << " " << hex << *(jitFrameContext->p_eip) << dec << endl;
// if(prBak != LOCATION_INVALID) cout << " prBak " << prBak << " " << hex << jitFrameContext->preds << dec<< endl;
}
//----------------------------------------------------------------------------------------//
void RuntimeInterface::getGCRootSet(MethodDesc *methodDesc,
GCInterface *gcInterface_,
const JitFrameContext *context_,
bool isFirst) {
// cout << "IPF::RuntimeInterface::getGCRootSet" << endl;
gcInterface = gcInterface_;
context = context_;
U_8* infoBlock = methodDesc->getInfoBlock();
U_8* gcInfo = infoBlock + sizeof(StackInfo);
uint64 currIp = *context->p_eip;
U_32 gcSize = *((U_32 *)gcInfo);
// cout << "getGCRootSet for ip " << hex << currIp << dec << " method " << methodDesc->getName() << endl;
U_8* safePoint = findSafePoint(gcInfo, gcSize, currIp);
enumerateRootSet(gcInterface, context, safePoint);
}
//----------------------------------------------------------------------------------------//
U_32 RuntimeInterface::getInlineDepth(InlineInfoPtr ptr, U_32 offset) {
std::cout << "FIXME: IPF::RuntimeInterface::getInlineDepth" << endl;
return 0;
}
//----------------------------------------------------------------------------------------//
Method_Handle RuntimeInterface::getInlinedMethod(InlineInfoPtr ptr,
U_32 offset,
U_32 inline_depth) {
std::cout << "FIXME: IPF::RuntimeInterface::getInlinedMethod" << endl;
return NULL;
}
//----------------------------------------------------------------------------------------//
void RuntimeInterface::fixHandlerContext(MethodDesc *methodDesc, JitFrameContext *context, bool isFirst) {
//std::cout << "FIXME: IPF::RuntimeInterface::fixHandlerContext " << methodDesc->getName() << endl;
}
//----------------------------------------------------------------------------------------//
void* RuntimeInterface::getAddressOfThis(MethodDesc *methodDesc,
const ::JitFrameContext *jitFrameContext,
bool isFirst) {
// cout << "IPF::RuntimeInterface::getAddressOfThis" << endl;
assert(!methodDesc->isStatic());
return jitFrameContext->p_gr[G_INARG_BASE];
}
//----------------------------------------------------------------------------------------//
bool RuntimeInterface::recompiledMethodEvent(MethodDesc *methodDesc,
void *data) {
//std::cout << "IPF::RuntimeInterface::recompiledMethodEvent " << methodDesc->getName() << endl;
char *callAddr = (char *)(~(((uint64)0x4cafe) << 32) & (uint64)data);
char **indirectAddr = (char **)methodDesc->getIndirectAddress();
char *methodAddr = *indirectAddr;
return Encoder::patchCallAddr(callAddr, methodAddr);
}
//----------------------------------------------------------------------------------------//
bool RuntimeInterface::getBcLocationForNative(MethodDesc *methodDesc, POINTER_SIZE_INT native_pc, uint16 *bc_pc) {
std::cout << "FIXME: IPF::RuntimeInterface::getBcLocationForNative " << methodDesc->getName() << endl;
// assert(0);
// return false;
return true;
}
//----------------------------------------------------------------------------------------//
bool RuntimeInterface::getNativeLocationForBc(MethodDesc *methodDesc, uint16 bc_pc, POINTER_SIZE_INT *native_pc) {
std::cout << "FIXME: IPF::RuntimeInterface::getNativeLocationForBc " << methodDesc->getName() << endl;
assert(0);
return false;
}
//----------------------------------------------------------------------------------------//
// GC Root Set
//----------------------------------------------------------------------------------------//
U_8* RuntimeInterface::findSafePoint(U_8* info, U_32 size, uint64 currIp)
{
U_32 offset = ROOT_SET_HEADER_SIZE;
U_8* safePoint = NULL;
U_32 spSize = 0;
uint64 spAddress = 0;
while (offset < size) {
safePoint = info + offset;
spSize = *((U_32 *)safePoint);
spAddress = *((uint64 *)(safePoint + sizeof(U_32)));
if (spAddress == currIp) return safePoint;
offset += spSize;
}
IPF_ERR << " No safe point found";
return NULL;
}
//----------------------------------------------------------------------------------------//
//
void RuntimeInterface::enumerateRootSet(GCInterface* gcInterface,
const JitFrameContext* context,
U_8* safePoint)
{
U_32 size = *((U_32 *)(safePoint));
I_32* ptr = (I_32 *)(safePoint + SAFE_POINT_HEADER_SIZE);
I_32* maxPtr = (I_32 *)(safePoint + size);
while (ptr < maxPtr) {
if (isMptr(*ptr)) reportMptr(*(ptr++), *(ptr++));
else reportBase(*(ptr++));
}
}
//----------------------------------------------------------------------------------------//
void** RuntimeInterface::getContextValue(I_32 location) {
if (location < 0) {
location = - (location + 1); // if location refers mptr - restore it
}
void** ptr = NULL;
if (location >= NUM_G_REG) { // this location points in memory stack
I_32 offset = location - NUM_G_REG; // calc memory stack offset
ptr = (void **)(context->sp + offset); // get pointer on stack value
} else { // general register
ptr = (void **)(context->p_gr[location]); // get pointer on reg value
}
return ptr; // return value
}
//----------------------------------------------------------------------------------------//
void RuntimeInterface::reportMptr(I_32 mptr, I_32 base) {
void **mptrPtr = getContextValue(mptr);
void **basePtr = getContextValue(base);
uint64 *u1 = (uint64 *)basePtr;
uint64 *u2 = (uint64 *)mptrPtr;
assert(*u2 >= *u1);
size_t offset = *u2 - *u1;
// cout << " report mptr: " << - (mptr+1) << flush;
// cout << " " << u2 << flush;
// cout << " " << hex << *u2 << dec << flush;
// cout << " base: " << base << flush;
// cout << " " << u1 << flush;
// cout << " " << hex << *u1 << dec; // << endl;
// cout << " offset " << offset << endl;
gcInterface->enumerateRootManagedReference(mptrPtr, offset);
}
//----------------------------------------------------------------------------------------//
void RuntimeInterface::reportBase(I_32 base) {
void** basePtr = getContextValue(base);
// uint64 *u1 = (uint64 *)basePtr;
// cout << " report base: " << base << flush;
// cout << " " << u1 << flush;
// cout << " " << hex << *u1 << dec << endl;
gcInterface->enumerateRootReference(basePtr);
}
//----------------------------------------------------------------------------------------//
bool RuntimeInterface::isMptr(I_32 ptr) { return ptr < 0; }
} // IPF
} // Jitrino