Path: blob/master/runtime/compiler/il/J9SymbolReference.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2021 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 "il/J9SymbolReference.hpp"2324#include <stdint.h>25#include "compile/Compilation.hpp"26#include "compile/Method.hpp"27#include "env/CompilerEnv.hpp"28#include "env/VMAccessCriticalSection.hpp"29#include "il/ParameterSymbol.hpp"30#include "il/StaticSymbol.hpp"31#include "il/Symbol.hpp"32#include "il/SymbolReference.hpp"33#include "env/KnownObjectTable.hpp"34#include "runtime/RuntimeAssumptions.hpp"35#include "env/CHTable.hpp"36#include "env/PersistentCHTable.hpp"37#include "env/VMJ9.h"3839namespace J940{4142SymbolReference::SymbolReference(43TR::SymbolReferenceTable *symRefTab,44TR::Symbol *sym,45mcount_t owningMethodIndex,46int32_t cpIndex,47int32_t unresolvedIndex,48TR::KnownObjectTable::Index knownObjectIndex)49{50self()->init(symRefTab,51symRefTab->assignSymRefNumber(self()),52sym,530, // Offset 054owningMethodIndex,55cpIndex,56unresolvedIndex);5758_knownObjectIndex = knownObjectIndex;5960if (sym->isResolvedMethod())61symRefTab->comp()->registerResolvedMethodSymbolReference(self());6263//Check for init method64if (sym->isMethod() &&65sym->castToMethodSymbol()->getMethod()->isConstructor())66{67self()->setInitMethod();68}6970symRefTab->checkImmutable(self());71}727374static char * dataTypeToSig[] = {0,"B","Z","C","S","I","J","F","D",0,0,0};7576/**77* This method is used when _cpIndex is to be used for resolution.78* For any other purpose, use getCPIndex().79*80* This method explicitly clears unused higher order bits in _cpIndex to81* avoid undesired sign extension.82*/83uint32_t84SymbolReference::getCPIndexForVM()85{86uint32_t index = (uint32_t) self()->getCPIndex();87return index & 0x3FFFF; // return lower order 18 bits88}8990bool91SymbolReference::isClassArray(TR::Compilation * c)92{93TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();94if (sym == NULL || self()->isUnresolved())95return false;9697return TR::Compiler->cls.isClassArray(c, (TR_OpaqueClassBlock *) sym->getStaticAddress());98}99100bool101SymbolReference::isClassFinal(TR::Compilation * c)102{103TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();104if (sym == NULL || self()->isUnresolved())105return false;106107return TR::Compiler->cls.isClassFinal(c, (TR_OpaqueClassBlock *) sym->getStaticAddress());108}109110bool111SymbolReference::isClassAbstract(TR::Compilation * c)112{113TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();114if (sym == NULL || self()->isUnresolved())115return false;116117return TR::Compiler->cls.isAbstractClass(c, (TR_OpaqueClassBlock *) sym->getStaticAddress());118}119120bool121SymbolReference::isClassInterface(TR::Compilation * c)122{123TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();124if (sym == NULL || self()->isUnresolved())125return false;126127return TR::Compiler->cls.isInterfaceClass(c, (TR_OpaqueClassBlock *) sym->getStaticAddress());128}129130// resolved final class that is not an array returns TRUE131bool132SymbolReference::isNonArrayFinal(TR::Compilation * c)133{134TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();135if (sym == NULL || self()->isUnresolved())136{137return false;138}139return !self()->isClassArray(c) && self()->isClassFinal(c);140}141142int32_t143SymbolReference::classDepth(TR::Compilation * c)144{145TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();146if (sym == NULL || self()->isUnresolved())147{148return -1;149}150return (int32_t)TR::Compiler->cls.classDepthOf((TR_OpaqueClassBlock *) sym->getStaticAddress());151}152153154char *155prependNumParensToSig(const char *name, int32_t &len, int32_t numParens, TR_AllocationKind allocKind)156{157TR::Compilation * comp = TR::comp();158char * sig;159160len += numParens;161sig = (char *)comp->trMemory()->allocateMemory(len, allocKind);162int32_t i = 0;163while (i < numParens)164{165sig[i] = '[';166i++;167}168memcpy(sig+i,name,len-numParens);169170return sig;171}172173174const char *175SymbolReference::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bool *isFixed)176{177TR::Compilation * comp = TR::comp();178bool allowForAOT = comp->getOption(TR_UseSymbolValidationManager);179180TR_PersistentClassInfo * persistentClassInfo = NULL;181switch (_symbol->getKind())182{183case TR::Symbol::IsParameter:184return _symbol->castToParmSymbol()->getTypeSignature(len);185186case TR::Symbol::IsShadow:187persistentClassInfo =188(comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL :189comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp, allowForAOT);190if (persistentClassInfo &&191persistentClassInfo->getFieldInfo() &&192persistentClassInfo->getFieldInfo()->getFirst() &&193!self()->isUnresolved() &&194!_symbol->isArrayShadowSymbol() &&195!_symbol->isArrayletShadowSymbol())196{197TR_PersistentFieldInfo *fieldInfo = NULL;198if (_symbol->isPrivate() ||199_symbol->isFinal())200fieldInfo = persistentClassInfo->getFieldInfo()->find(comp, _symbol, self());201202if (fieldInfo &&203fieldInfo->isTypeInfoValid() &&204(fieldInfo->getNumChars() > 0) &&205performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",206fieldInfo->getClassPointer(), _symbol))207{208if (isFixed)209*isFixed = true;210len = fieldInfo->getNumChars();211return fieldInfo->getClassPointer();212}213214if (fieldInfo &&215fieldInfo->isBigDecimalType() &&216performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",217"Ljava/math/BigDecimal;", _symbol))218{219len = 22;220return "Ljava/math/BigDecimal;";221}222223if (fieldInfo &&224fieldInfo->isBigIntegerType() &&225performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",226"Ljava/math/BigInteger;", _symbol))227{228len = 22;229return "Ljava/math/BigInteger;";230}231}232233return (_cpIndex > 0 ? self()->getOwningMethod(comp)->fieldSignatureChars(_cpIndex, len) : 0);234235case TR::Symbol::IsStatic:236if (_symbol->isStatic() && _symbol->isFinal() && !self()->isUnresolved())237{238TR::StaticSymbol * symbol = _symbol->castToStaticSymbol();239TR::DataType type = symbol->getDataType();240TR_OpaqueClassBlock * classOfStatic = self()->getOwningMethod(comp)->classOfStatic(_cpIndex, allowForAOT);241242bool isClassInitialized = false;243TR_PersistentClassInfo * classInfo =244(comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL :245comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(classOfStatic, comp, allowForAOT);246if (classInfo && classInfo->isInitialized())247{248if (classInfo->getFieldInfo() && !classInfo->cannotTrustStaticFinal())249isClassInitialized = true;250}251252if ((classOfStatic != comp->getSystemClassPointer() &&253isClassInitialized &&254(type == TR::Address)))255{256TR::VMAccessCriticalSection vmAccessCriticalSection(comp->fej9(),257TR::VMAccessCriticalSection::tryToAcquireVMAccess,258comp);259if (vmAccessCriticalSection.hasVMAccess())260{261uintptr_t objectStaticAddress = (uintptr_t)symbol->getStaticAddress();262uintptr_t objectRef = comp->fej9()->getStaticReferenceFieldAtAddress(objectStaticAddress);263if (objectRef != 0)264{265TR_OpaqueClassBlock *classOfObject = comp->fej9()->getObjectClass(objectRef);266const char * s = TR::Compiler->cls.classNameChars(comp, classOfObject, len);267if (s && (s[0] != '['))268{269s = TR::Compiler->cls.classNameToSignature(s, len, comp);270}271else272{273int32_t numParens = 0;274while (s && (s[0] == '[') && (s[1] == 'L' || s[1] == 'Q'))275{276numParens++;277classOfObject = comp->fe()->getComponentClassFromArrayClass(classOfObject);278s = TR::Compiler->cls.classNameChars(comp, classOfObject, len);279}280s = TR::Compiler->cls.classNameToSignature(s, len, comp);281s = prependNumParensToSig(s, len, numParens);282}283284if (isFixed)285*isFixed = true;286return s;287}288}289}290}291292if (_symbol->isClassObject())293{294const char * sig = TR::Compiler->cls.classNameChars(comp, self(), len);295if (!sig)296{297len = 18;298return "Ljava/lang/Object;";299}300return TR::Compiler->cls.classNameToSignature(sig, len, comp, allocKind);301}302303if (_symbol->isConstString())304{305len = 18;306return "Ljava/lang/String;";307}308if (_symbol->isConstMethodType())309{310len = 21;311return "Ljava/lang/invoke/MethodType;";312}313if (_symbol->isConstMethodHandle())314{315len = 23;316return "Ljava/lang/invoke/MethodHandle;";317}318if (_symbol->isConstantDynamic())319{320TR::StaticSymbol * symbol = _symbol->castToStaticSymbol();321int32_t condySigLength;322char *returnType = symbol->getConstantDynamicClassSignature(condySigLength);323len = condySigLength;324return returnType;325}326if (_symbol->isNonSpecificConstObject())327{328TR::StaticSymbol * symbol = _symbol->castToStaticSymbol();329uintptr_t objectLocation = (uintptr_t)symbol->getStaticAddress();330TR_OpaqueClassBlock *clazz = comp->fej9()->getObjectClassAt(objectLocation);331char *type = comp->fej9()->getClassSignature(clazz, comp->trMemory());332len = strlen(type);333return type;334}335if (_symbol->isConst())336{337len = 1;338return dataTypeToSig[_symbol->getDataType()];339}340341persistentClassInfo =342(comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL :343comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp, allowForAOT);344if (persistentClassInfo &&345persistentClassInfo->getFieldInfo() &&346persistentClassInfo->getFieldInfo()->getFirst() &&347!self()->isUnresolved() &&348!_symbol->isArrayShadowSymbol() &&349!_symbol->isArrayletShadowSymbol())350{351TR_PersistentFieldInfo *fieldInfo = NULL;352if (_symbol->isPrivate() ||353_symbol->isFinal())354fieldInfo = persistentClassInfo->getFieldInfo()->find(comp, _symbol, self());355356if (fieldInfo &&357fieldInfo->isTypeInfoValid() &&358(fieldInfo->getNumChars() > 0) &&359performTransformation(comp, "O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",360fieldInfo->getClassPointer(), _symbol))361{362if (isFixed)363*isFixed = true;364len = fieldInfo->getNumChars();365return fieldInfo->getClassPointer();366}367368if (fieldInfo &&369fieldInfo->isBigDecimalType() &&370performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",371"Ljava/math/BigDecimal;", _symbol))372{373len = 22;374return "Ljava/math/BigDecimal;";375}376377if (fieldInfo &&378fieldInfo->isBigIntegerType() &&379performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",380"Ljava/math/BigInteger;", _symbol))381{382len = 22;383return "Ljava/math/BigInteger;";384}385}386387return self()->getOwningMethod(comp)->staticSignatureChars(_cpIndex, len);388389case TR::Symbol::IsMethod:390case TR::Symbol::IsResolvedMethod:391{392TR::Method * method = _symbol->castToMethodSymbol()->getMethod();393if (method)394{395char * sig = method->signatureChars();396char *returnType = strchr(sig,')')+1;397len = method->signatureLength() - (returnType-sig);398return returnType;399}400return 0;401}402403case TR::Symbol::IsAutomatic:404if (_symbol->isLocalObject())405{406// todo:407}408return 0;409410case TR::Symbol::IsMethodMetaData:411case TR::Symbol::IsLabel:412default:413return 0;414}415}416417}418419420