Path: blob/master/runtime/compiler/env/J2IThunk.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2022 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "env/J2IThunk.hpp"2324#include "env/CompilerEnv.hpp"25#include "codegen/CodeGenerator.hpp"26#include "infra/Array.hpp"27#include "infra/Monitor.hpp"28#include "env/IO.hpp"29#include "infra/CriticalSection.hpp"30#include "env/j9method.h"31#include "env/VMJ9.h"32#include "env/VerboseLog.hpp"3334#if defined(OSX) && defined(AARCH64)35#include <pthread.h> // for pthread_jit_write_protect_np36#endif3738static int32_t39computeSignatureLength(char *signature)40{41char *currentArgument;42for (currentArgument = signature+1; currentArgument[0] != ')'; currentArgument = nextSignatureArgument(currentArgument))43{}44currentArgument = nextSignatureArgument(currentArgument+1);45return currentArgument - signature;46}474849TR_J2IThunk *50TR_J2IThunk::allocate(51int16_t codeSize,52char *signature,53TR::CodeGenerator *cg,54TR_J2IThunkTable *thunkTable)55{56int16_t terseSignatureBufLength = thunkTable->terseSignatureLength(signature)+1;57int16_t totalSize = (int16_t)sizeof(TR_J2IThunk) + codeSize + terseSignatureBufLength;58TR_J2IThunk *result;59#if defined(J9VM_OPT_JITSERVER)60if (cg->comp()->isOutOfProcessCompilation())61{62// Don't need to use code cache because the entire thunk will be copied and sent to the client63result = (TR_J2IThunk*)cg->comp()->trMemory()->allocateMemory(totalSize, heapAlloc);64}65else66#endif /* defined(J9VM_OPT_JITSERVER) */67{68result = (TR_J2IThunk*)cg->allocateCodeMemory(totalSize, true, false);69}70#if defined(OSX) && defined(AARCH64)71pthread_jit_write_protect_np(0);72#endif73result->_codeSize = codeSize;74result->_totalSize = totalSize;75thunkTable->getTerseSignature(result->terseSignature(), terseSignatureBufLength, signature);76#if defined(OSX) && defined(AARCH64)77pthread_jit_write_protect_np(1);78#endif79return result;80}818283TR_J2IThunkTable::TR_J2IThunkTable(TR_PersistentMemory *m, char *name):84_name(name),85_monitor(TR::Monitor::create(name)),86_nodes(m)87{88_nodes.setSize(1); // Initially just the root node89}909192int16_t93TR_J2IThunkTable::terseSignatureLength(char *signature)94{95int16_t numArgs = 0;96for (char *currentArgument = signature+1; currentArgument[0] != ')'; currentArgument = nextSignatureArgument(currentArgument))97numArgs++;98return numArgs+1; // +1 for return type char99}100101102void TR_J2IThunkTable::getTerseSignature(char *buf, int16_t bufLength, char *signature)103{104int16_t i=0;105char *currentArgument;106for (currentArgument = signature+1; currentArgument[0] != ')'; currentArgument = nextSignatureArgument(currentArgument))107buf[i++] = terseTypeChar(currentArgument);108TR_ASSERT(i <= bufLength-2, "Must have room for return type and null terminator");109buf[i++] = terseTypeChar(currentArgument+1); // return type110buf[i++] = 0; // null terminator111}112113114char TR_J2IThunkTable::terseTypeChar(char *type)115{116switch (type[0])117{118case '[':119case 'L':120case 'Q':121return TR::Compiler->target.is64Bit()? 'L' : 'I';122case 'Z':123case 'B':124case 'S':125case 'C':126return 'I';127default:128return type[0];129}130}131132133TR_J2IThunkTable::Node *134TR_J2IThunkTable::Node::get(135char *terseSignature,136TR_PersistentArray<Node> &nodeArray,137bool createIfMissing)138{139Node *result = NULL;140if (terseSignature[0] == 0)141{142// We've reached the matching node143result = this;144}145else146{147int32_t typeIndex = typeCharIndex(terseSignature[0]);148ChildIndex childIndex = _children[typeIndex];149if (!childIndex && createIfMissing)150{151_children[typeIndex] = childIndex = nodeArray.size();152Node emptyNode = {0};153154// CAREFUL! The following call can realloc the node array, including the155// receiver of this very method we're in. Don't access "this" anymore156// in this function after this point!157//158nodeArray.add(emptyNode);159}160if (childIndex)161result = nodeArray[childIndex].get(terseSignature+1, nodeArray, createIfMissing);162else163result = NULL;164}165return result;166}167168169TR_J2IThunk *170TR_J2IThunkTable::findThunk(171char *signature,172TR_FrontEnd *fe,173bool isForCurrentRun)174{175char terseSignature[260]; // 256 args + 1 return type + null terminator176getTerseSignature(terseSignature, sizeof(terseSignature), signature);177return findThunkFromTerseSignature(terseSignature, fe, isForCurrentRun);178}179180181TR_J2IThunk *182TR_J2IThunkTable::getThunk(char *signature, TR_FrontEnd *fe, bool isForCurrentRun)183{184TR_J2IThunk *result = findThunk(signature, fe, isForCurrentRun);185if (!result)186{187char terseSignature[260]; // 256 args + 1 return type + null terminator188dumpTo(fe, TR::IO::Stderr);189getTerseSignature(terseSignature, sizeof(terseSignature), signature);190trfprintf(TR::IO::Stderr, "\nERROR: Failed to find J2I thunk for %s signature %.*s\n", terseSignature, computeSignatureLength(signature), signature);191TR_ASSERT(result != NULL, "Expected a J2I thunk for %s signature %.*s", terseSignature, computeSignatureLength(signature), signature);192}193return result;194}195196197TR_J2IThunk *198TR_J2IThunkTable::findThunkFromTerseSignature(199char *terseSignature,200TR_FrontEnd *fe,201bool isForCurrentRun)202{203TR_J9VMBase *fej9 = (TR_J9VMBase *)(fe);204TR_J2IThunk *returnThunk = NULL;205206if (fej9->isAOT_DEPRECATED_DO_NOT_USE() && !isForCurrentRun)207{208// Must use persistent thunks for compiles that will persist209return (TR_J2IThunk *)fej9->findPersistentJ2IThunk(terseSignature);210}211else212{213OMR::CriticalSection critialSection(_monitor);214215Node *match = root()->get(terseSignature, _nodes, false);216returnThunk = match ? match->_thunk : NULL;217}218219return returnThunk;220}221222223void224TR_J2IThunkTable::addThunk(225TR_J2IThunk *thunk,226TR_FrontEnd *fe, bool227isForCurrentRun)228{229TR_J9VMBase *fej9 = (TR_J9VMBase *)(fe);230231if (fej9->isAOT_DEPRECATED_DO_NOT_USE() && !isForCurrentRun)232{233// Must use persistent thunks for compiles that will persist234fej9->persistJ2IThunk(thunk);235if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJ2IThunks))236TR_VerboseLog::writeLineLocked(TR_Vlog_J2I,"persist %s @%p", thunk->terseSignature(), thunk);237}238else239{240OMR::CriticalSection criticalSection(_monitor);241242Node *match = root()->get(thunk->terseSignature(), _nodes, true);243match->_thunk = thunk;244245// This assume must be in the monitor or else another thread could break it246TR_ASSERT(findThunkFromTerseSignature(thunk->terseSignature(), fe, isForCurrentRun) == thunk, "TR_J2IThunkTable: setThunk must cause findThunk(%s) to return %p", thunk->terseSignature(), thunk);247if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJ2IThunks))248TR_VerboseLog::writeLineLocked(TR_Vlog_J2I,"add %s @%p", thunk->terseSignature(), thunk);249}250}251252253void254TR_J2IThunkTable::Node::dumpTo(255TR_FrontEnd *fe,256TR::FILE *file,257TR_PersistentArray<Node> &nodeArray,258int indent)259{260static const char typeChars[] = "VIJFDL";261if (_thunk)262trfprintf(file, " %s @%p\n", _thunk->terseSignature(), _thunk);263else264trfprintf(file, "\n");265for (int32_t typeIndex = 0; typeIndex < NUM_TYPE_CHARS; typeIndex++)266{267if (_children[typeIndex])268{269trfprintf(file, "%*s%c @%d:", indent*3, "", typeChars[typeIndex], _children[typeIndex]);270nodeArray[_children[typeIndex]].dumpTo(fe, file, nodeArray, indent+1);271}272}273}274275276void277TR_J2IThunkTable::dumpTo(TR_FrontEnd *fe, TR::FILE *file)278{279OMR::CriticalSection criticalSection(_monitor);280trfprintf(file, "J2IThunkTable \"%s\":", _name);281root()->dumpTo(fe, file, _nodes, 1);282}283284285