blob: 07354aba6a69553738bbfe904993ff0b2c89c39a [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.
*/
#include "RuntimeInterface.h"
namespace Jitrino {
InlineInfoMap::Entry* InlineInfoMap::newEntry(Entry* parent, Method_Handle mh, uint16 bcOffset) {
Entry* e = new (memManager) Entry(parent, bcOffset, mh);
return e;
}
void InlineInfoMap::registerEntry(Entry* e, U_32 nativeOffs) {
entryByOffset[nativeOffs] = e;
for (Entry* current = e; current!=NULL; current = current->parentEntry) {
if (std::find(entries.begin(), entries.end(), current)!=entries.end()) {
assert(current!=e); //possible if inlined method has multiple entries, skip this method marker.
} else {
entries.push_back(current);
}
}
}
static U_32 getIndexSize(size_t nEntriesInIndex) {
return (U_32)(2 * nEntriesInIndex * sizeof(U_32) + sizeof(U_32)); //zero ending list of [nativeOffset, entryOffsetInImage] pairs
}
U_32
InlineInfoMap::getImageSize() const {
if (isEmpty()) {
return sizeof(U_32);
}
return getIndexSize(entryByOffset.size()) //index size
+ (U_32)(entries.size() * sizeof(Entry)); //all entries size;
}
/* serialized inline_info layout
nativeOffset1 -> offset to InlineInfoMap::Entry in the image with max inline depth (32bit + 32bit)
nativeOffset2 -> offset to InlineInfoMap::Entry in the image with max inline depth
nativeOffset3 -> offset to InlineInfoMap::Entry in the image with max inline depth
...
0 -> 0
InlineInfoMap::Entry1
InlineInfoMap::Entry2
...
*/
void
InlineInfoMap::write(InlineInfoPtr image)
{
if (isEmpty()) {
*(U_32*)image=0;
return;
}
//write all entries first;
Entry* entriesInImage = (Entry*)((char*)image + getIndexSize(entryByOffset.size()));
Entry* entriesPtr = entriesInImage;
for (StlVector<Entry*>::iterator it = entries.begin(), end = entries.end(); it != end; it++) {
Entry* e = *it;
*entriesPtr = *e;
entriesPtr++;
}
assert(((char*)entriesPtr) == ((char*)image) + getImageSize());
//now update parentEntry reference to written entries
for (U_32 i=0; i < entries.size(); i++) {
Entry* imageChild = entriesInImage + i;
Entry* compileTimeParent = imageChild->parentEntry;
if (compileTimeParent!=NULL) {
size_t parentIdx = std::find(entries.begin(), entries.end(), compileTimeParent) - entries.begin();
assert(parentIdx<entries.size());
Entry* imageParent = entriesInImage + parentIdx;
imageChild->parentEntry = imageParent;
}
}
//now write index header
U_32* header = (U_32*)image;
for (StlMap<U_32, Entry*>::iterator it = entryByOffset.begin(), end = entryByOffset.end(); it!=end; it++) {
U_32 nativeOffset = it->first;
Entry* compileTimeEntry = it->second;
size_t entryIdx = std::find(entries.begin(), entries.end(), compileTimeEntry) - entries.begin();
assert(entryIdx<entries.size());
Entry* imageEntry = entriesInImage + entryIdx;
*header = nativeOffset;
header++;
*header = (U_32)((char*)imageEntry - (char*)image);
header++;
}
*header = 0;
header++;
assert((char*)header == (char*)entriesInImage);
}
const InlineInfoMap::Entry* InlineInfoMap::getEntryWithMaxDepth(InlineInfoPtr ptr, U_32 nativeOffs) {
U_32* header = (U_32*)ptr;
while (*header!=0) {
U_32 nativeOffset = *header;
header++;
U_32 entryOffset = *header;
header++;
if (nativeOffset == nativeOffs) {
Entry* e = (Entry*)((char*)ptr + entryOffset);
return e;
}
}
return NULL;
}
const InlineInfoMap::Entry* InlineInfoMap::getEntry(InlineInfoPtr ptr, U_32 nativeOffs, U_32 inlineDepth) {
const Entry* e = getEntryWithMaxDepth(ptr, nativeOffs);
while (e!=NULL) {
if (e->getInlineDepth() == inlineDepth) {
return e;
}
e = e->parentEntry;
}
return NULL;
}
} //namespace Jitrino