Path: blob/master/runtime/compiler/env/CHTable.hpp
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#ifndef CHTABLE_INCL23#define CHTABLE_INCL2425#include <stddef.h>26#include <stdint.h>27#include "compile/Compilation.hpp"28#include "compile/CompilationTypes.hpp"29#include "compile/VirtualGuard.hpp"30#include "env/RuntimeAssumptionTable.hpp"31#include "env/TRMemory.hpp"32#include "env/jittypes.h"33#include "infra/Link.hpp"34#include "runtime/RuntimeAssumptions.hpp"35#if defined(J9VM_OPT_JITSERVER)36#include "env/JITServerCHTable.hpp"37#endif3839class TR_FrontEnd;40class TR_OpaqueClassBlock;41class TR_OpaqueMethodBlock;42class TR_PersistentArrayFieldInfo;43class TR_PersistentCHTable;44class TR_ResolvedMethod;45class TR_VirtualGuard;46namespace TR { class Node; }47namespace TR { class Symbol; }48namespace TR { class SymbolReference; }49template <class T> class List;50template <class T> class TR_Array;51template <class T> class TR_ScratchList;5253class TR_VirtualGuardSite54{55public:56TR_ALLOC(TR_Memory::VirtualGuardSiteInfo);57TR_VirtualGuardSite() : _location(0), _location2(0), _destination(0) {}5859uint8_t* getLocation() { return _location; }60uint8_t* getLocation2() { return _location2; }61uint8_t* &getDestination() { return _destination; }6263void setLocation(uint8_t *location) { _location = location; }64void setLocation2(uint8_t *location2) { _location2 = location2; }65void setDestination(uint8_t *dest) { _destination = dest; }6667private:68uint8_t *_location;69uint8_t *_location2; // used when ordered pair relocations are needed70uint8_t *_destination;71};7273class TR_AOTGuardSite : public TR_VirtualGuardSite74{75public:76TR_ALLOC(TR_Memory::VirtualGuardSiteInfo);77TR_AOTGuardSite() : TR_VirtualGuardSite(), _guardType(TR_NoGuard), _virtualGuard(NULL), _node(NULL), _aconstNode(NULL) {}78TR_AOTGuardSite(TR_VirtualGuardKind type, TR_VirtualGuard *virtualGuard, TR::Node *node, TR::Node *aconstNode=NULL) : TR_VirtualGuardSite(), _guardType(type), _virtualGuard(virtualGuard), _node(node), _aconstNode(node) {}7980void setType(TR_VirtualGuardKind type) { _guardType = type; }81TR_VirtualGuardKind getType() { return _guardType; }8283void setGuard(TR_VirtualGuard *virtualGuard) { _virtualGuard = virtualGuard; }84TR_VirtualGuard * getGuard() { return _virtualGuard; }8586void setNode(TR::Node *node) { _node = node; }87TR::Node *getNode() { return _node; }8889void setAconstNode(TR::Node *aconstNode) { _aconstNode = aconstNode; }90TR::Node *getAconstNode() { return _aconstNode; }9192private:93TR_VirtualGuardKind _guardType;94TR_VirtualGuard *_virtualGuard;95TR::Node *_node;96TR::Node *_aconstNode;97};9899class TR_PatchNOPedGuardSiteOnClassExtend : public TR::PatchNOPedGuardSite100{101protected:102TR_PatchNOPedGuardSiteOnClassExtend(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz,103uint8_t *loc, uint8_t *dest)104: TR::PatchNOPedGuardSite(pm, (uintptr_t)clazz, RuntimeAssumptionOnClassExtend,105loc, dest) {}106public:107static TR_PatchNOPedGuardSiteOnClassExtend *make(108TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);109virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassExtend; }110};111112class TR_PatchNOPedGuardSiteOnMethodOverride : public TR::PatchNOPedGuardSite113{114protected:115TR_PatchNOPedGuardSiteOnMethodOverride(TR_PersistentMemory *pm, TR_OpaqueMethodBlock *method,116uint8_t *loc, uint8_t *dest)117: TR::PatchNOPedGuardSite(pm, (uintptr_t)method, RuntimeAssumptionOnMethodOverride,118loc, dest) {}119public:120static TR_PatchNOPedGuardSiteOnMethodOverride *make(121TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueMethodBlock *method, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);122virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnMethodOverride; }123};124125class TR_PatchNOPedGuardSiteOnClassPreInitialize : public TR::PatchNOPedGuardSite126{127public:128static TR_PatchNOPedGuardSiteOnClassPreInitialize *make(129TR_FrontEnd *fe, TR_PersistentMemory *, char *sig, uint32_t sigLen, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);130static uintptr_t hashCode(char *sig, uint32_t sigLen);131132/** \copydoc OMR::RuntimeAssumption::reclaim()133* See base class documentation for more details.134*/135virtual void reclaim();136137virtual bool matches(uintptr_t key) { return false; }138virtual bool matches(char *sig, uint32_t sigLen);139virtual uintptr_t hashCode() { return hashCode((char*)getKey(), _sigLen); }140virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassPreInitialize; }141142private:143TR_PatchNOPedGuardSiteOnClassPreInitialize(TR_PersistentMemory *pm, char *sig, uint32_t sigLen,144uint8_t *loc, uint8_t *dest)145: TR::PatchNOPedGuardSite(pm, (uintptr_t)sig, RuntimeAssumptionOnClassPreInitialize,146loc, dest), _sigLen(sigLen) {}147uint32_t _sigLen;148};149150class TR_PatchNOPedGuardSiteOnClassRedefinition: public TR::PatchNOPedGuardSite151{152protected:153TR_PatchNOPedGuardSiteOnClassRedefinition(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz,154uint8_t *loc, uint8_t *dest)155: TR::PatchNOPedGuardSite(pm, (uintptr_t)clazz, RuntimeAssumptionOnClassRedefinitionNOP, loc, dest) {}156public:157static TR_PatchNOPedGuardSiteOnClassRedefinition *make(158TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);159virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassRedefinitionNOP; }160void setKey(uintptr_t newKey) {_key = newKey;}161};162163class TR_PatchMultipleNOPedGuardSitesOnClassRedefinition : public TR::PatchMultipleNOPedGuardSites164{165protected:166TR_PatchMultipleNOPedGuardSitesOnClassRedefinition(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, TR::PatchSites *sites)167: TR::PatchMultipleNOPedGuardSites(pm, (uintptr_t)clazz, RuntimeAssumptionOnClassRedefinitionNOP, sites) {}168public:169static TR_PatchMultipleNOPedGuardSitesOnClassRedefinition *make(170TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, TR::PatchSites *sites, OMR::RuntimeAssumption **sentinel);171virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassRedefinitionNOP; }172void setKey(uintptr_t newKey) {_key = newKey;}173};174175class TR_PatchNOPedGuardSiteOnStaticFinalFieldModification : public TR::PatchNOPedGuardSite176{177protected:178TR_PatchNOPedGuardSiteOnStaticFinalFieldModification(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz,179uint8_t *loc, uint8_t *dest)180: TR::PatchNOPedGuardSite(pm, (uintptr_t)clazz, RuntimeAssumptionOnStaticFinalFieldModification, loc, dest) {}181public:182static TR_PatchNOPedGuardSiteOnStaticFinalFieldModification *make(183TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);184virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnStaticFinalFieldModification; }185};186187class TR_PatchMultipleNOPedGuardSitesOnStaticFinalFieldModification : public TR::PatchMultipleNOPedGuardSites188{189protected:190TR_PatchMultipleNOPedGuardSitesOnStaticFinalFieldModification(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, TR::PatchSites *sites)191: TR::PatchMultipleNOPedGuardSites(pm, (uintptr_t)clazz, RuntimeAssumptionOnStaticFinalFieldModification, sites) {}192public:193static TR_PatchMultipleNOPedGuardSitesOnStaticFinalFieldModification *make(194TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, TR::PatchSites *sites, OMR::RuntimeAssumption **sentinel);195virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnStaticFinalFieldModification; }196};197198class TR_PatchNOPedGuardSiteOnMutableCallSiteChange : public TR::PatchNOPedGuardSite199{200protected:201TR_PatchNOPedGuardSiteOnMutableCallSiteChange(TR_PersistentMemory *pm, uintptr_t key,202uint8_t *loc, uint8_t *dest)203: TR::PatchNOPedGuardSite(pm, key, RuntimeAssumptionOnMutableCallSiteChange, loc, dest) {}204public:205static TR_PatchNOPedGuardSiteOnMutableCallSiteChange *make(206TR_FrontEnd *fe, TR_PersistentMemory *pm, uintptr_t KEY_WILL_GO_HERE, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);207virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnMutableCallSiteChange; }208};209210class TR_PatchNOPedGuardSiteOnMethodBreakPoint : public TR::PatchNOPedGuardSite211{212protected:213TR_PatchNOPedGuardSiteOnMethodBreakPoint(TR_PersistentMemory *pm, TR_OpaqueMethodBlock *j9method,214uint8_t *location, uint8_t *destination)215: TR::PatchNOPedGuardSite(pm, (uintptr_t)j9method, RuntimeAssumptionOnMethodBreakPoint, location, destination) {}216217public:218static TR_PatchNOPedGuardSiteOnMethodBreakPoint *make(219TR_FrontEnd *fe, TR_PersistentMemory * pm, TR_OpaqueMethodBlock *j9method, uint8_t *location, uint8_t *destination,220OMR::RuntimeAssumption **sentinel);221222virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnMethodBreakPoint; }223};224225class TR_PatchJNICallSite : public OMR::ValueModifyRuntimeAssumption226{227protected:228TR_PatchJNICallSite(TR_PersistentMemory *pm, uintptr_t key, uint8_t *pc)229: OMR::ValueModifyRuntimeAssumption(pm, key), _pc(pc) {}230231public:232TR_PERSISTENT_ALLOC_THROW(TR_Memory::CallSiteInfo)233static TR_PatchJNICallSite *make(234TR_FrontEnd *fe, TR_PersistentMemory * pm, uintptr_t key, uint8_t *pc, OMR::RuntimeAssumption **sentinel);235236virtual void dumpInfo();237238virtual void compensate(TR_FrontEnd *vm, bool isSMP, void *newAddress);239virtual bool equals(OMR::RuntimeAssumption &other)240{241TR_PatchJNICallSite *site = other.asPJNICSite();242return site != 0 && getPc() == site->getPc();243}244virtual uint8_t *getFirstAssumingPC() { return getPc(); }245virtual uint8_t *getLastAssumingPC() { return getPc(); }246247virtual TR_PatchJNICallSite *asPJNICSite() { return this; }248uint8_t *getPc() { return _pc; }249virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnRegisterNative; }250251private:252uint8_t *_pc;253};254255class TR_PreXRecompile : public OMR::LocationRedirectRuntimeAssumption256{257protected:258TR_PreXRecompile(TR_PersistentMemory *pm, uintptr_t key, TR_RuntimeAssumptionKind kind, uint8_t *startPC)259: OMR::LocationRedirectRuntimeAssumption(pm, key), _startPC(startPC) {}260261public:262263// NOTE: this function should be the first non-inline function in the class264// to make sure that the compiler puts the vtable in codegen.dev265virtual void dumpInfo();266267virtual void compensate(TR_FrontEnd *vm, bool isSMP, void *newAddress);268virtual bool equals(OMR::RuntimeAssumption &o1)269{270TR_PreXRecompile *a = o1.asPXRecompile();271return (a != 0) && _startPC == a->_startPC;272}273274virtual TR_PreXRecompile *asPXRecompile() { return this; }275virtual uint8_t *getFirstAssumingPC() { return getStartPC(); }276virtual uint8_t *getLastAssumingPC() { return getStartPC(); }277uint8_t *getStartPC() { return _startPC; }278279280private:281uint8_t *_startPC;282};283284class TR_PreXRecompileOnClassExtend : public TR_PreXRecompile285{286protected:287TR_PreXRecompileOnClassExtend(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *startPC)288: TR_PreXRecompile(pm, (uintptr_t)clazz, RuntimeAssumptionOnClassExtend, startPC) {}289public:290virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassExtend; }291static TR_PreXRecompileOnClassExtend *make(292TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *startPC, OMR::RuntimeAssumption **sentinel);293};294295class TR_PreXRecompileOnMethodOverride : public TR_PreXRecompile296{297protected:298TR_PreXRecompileOnMethodOverride(TR_PersistentMemory *pm, TR_OpaqueMethodBlock *method, uint8_t *startPC)299: TR_PreXRecompile(pm, (uintptr_t)method, RuntimeAssumptionOnMethodOverride, startPC) {}300public:301virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnMethodOverride; }302static TR_PreXRecompileOnMethodOverride *make(303TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueMethodBlock *method, uint8_t *startPC, OMR::RuntimeAssumption **sentinel);304};305306class TR_CHTable307{308public:309310/**311* VisitTracker class keeps a record of visited classes, and reset their312* visited status flags once visiting finish.313* Usage:314* {315* CHTableCriticalSection lock(...);316* VisitTracker tracker(...);317* Work on CHTable entries and call VisitTracker::visit() with each entry318* }319* Note that VisitTracker MUST be used inside CHTableCriticalSection320*321* A typical work flow is:322* 1) Enter CHTable critical section323* 2) Work on CHTable entries marking some of them visited324* 3) Loop through the list of entries with visited flags set and clear them325* 4) Leave CHTable critical section326*327* Note that exception may occur during Step 2.328* Previously (RTC 118937), visited classes were tracked by a list inside329* J9::Compilation, and the exception handler resets visited status flags when330* an exception occurred.331*332* This worked perfectly when longjmp was used: when longjmp was issued, the333* code is still inside CHTable critical section, and hence resetting/modifying334* visited status flags was safe.335*336* However, this does not work with C++ exception handling and RAII managing337* entering/leaving of critical sections. The code looks like following:338* {339* CHTableCriticalSection lock(...);340* 2) Work on CHTable entries marking some of them visited341* 3) Loop through the list of entries with visited flags set and clear them342* }343* Note that Steps 1&4 are replaced by CHTableCriticalSection, which enters the344* critical section in its constructor and leaves in its destructor. When an345* exception occurs in Step 2, C++ executes CHTableCriticalSection's destructor346* before executing the exception handler; and hence the exception handling code347* is outside of CHTable critical section. In short, resetting/modifying visited348* status flags in the exception handler is NOT safe.349*350* To solve the above mentioned issue, VisitTracker is introduced. It resets351* visited status flags in its destructor. The code becomes:352* {353* CHTableCriticalSection lock(...);354* VisitTracker tracker(...);355* 2) Work on CHTable entries marking some of them visited356* }357* When an exception occurred in Step 2, before executing the exception handler,358* C++ first executes VisitTracker's destructor and then CHTableCriticalSection's359* destructor. Therefore, visited status flags are reset inside CHTable critical360* section, which is safe.361*362*/363class VisitTracker364{365public:366367VisitTracker(TR_Memory* m) : _classes(m) {}368~VisitTracker()369{370auto it = iterator();371for (auto info = it.getFirst(); info; info = it.getNext())372info->resetVisited();373_classes.deleteAll();374}375void visit(TR_PersistentClassInfo* info)376{377_classes.add(info); // this could throw std::bad_alloc and take us to the exception handler, before which the destructor is called378info->setVisited(); // it's important to set the visited flag *after* adding to marked list379}380ListIterator<TR_PersistentClassInfo> iterator()381{382return ListIterator<TR_PersistentClassInfo>(&_classes);383}384385private:386TR_ScratchList<TR_PersistentClassInfo> _classes;387};388389TR_ALLOC(TR_Memory::CHTable)390TR_CHTable(TR_Memory * trMemory) :391_preXMethods(0),392_classes(0),393_classesThatShouldNotBeNewlyExtended(0),394_trMemory(trMemory)395{396}397398// register the class' extend event to trigger a recompile399bool recompileOnClassExtend (TR::Compilation *c, TR_OpaqueClassBlock * classId);400401// register the class' extend event to trigger a recompile402bool recompileOnNewClassExtend (TR::Compilation *c, TR_OpaqueClassBlock * classId);403404// register the method's override event to trigger a recompile405bool recompileOnMethodOverride(TR::Compilation *c, TR_ResolvedMethod *method);406407void cleanupNewlyExtendedInfo(TR::Compilation *comp);408409bool canSkipCommit(TR::Compilation *comp);410411// Commit the CHTable into the persistent table. This method must be called412// with the class table mutex in hand.413// If an unrecoverable problem has occurred - this method will return false414// which will result in the failure of the current compilation415//416bool commit(TR::Compilation *comp);417418void commitVirtualGuard(TR_VirtualGuard *info, List<TR_VirtualGuardSite> &sites,419TR_PersistentCHTable *table, TR::Compilation *comp);420void commitOSRVirtualGuards(TR::Compilation *comp, TR::list<TR_VirtualGuard*> &vguards);421#if defined(J9VM_OPT_JITSERVER)422CHTableCommitData computeDataForCHTableCommit(TR::Compilation *comp);423#endif424425TR_Array<TR_OpaqueClassBlock *> *getClasses() { return _classes;}426TR_Array<TR_OpaqueClassBlock *> *getClassesThatShouldNotBeNewlyExtended() { return _classesThatShouldNotBeNewlyExtended;}427428TR_Memory * trMemory() { return _trMemory; }429TR_StackMemory trStackMemory() { return _trMemory; }430TR_HeapMemory trHeapMemory() { return _trMemory; }431432private:433434friend class TR_Debug;435436TR_Array<TR_ResolvedMethod*> * _preXMethods;437TR_Array<TR_OpaqueClassBlock *> * _classes;438TR_Array<TR_OpaqueClassBlock *> * _classesThatShouldNotBeNewlyExtended;439TR_Memory * _trMemory;440};441442443444// IMPORTANT NOTE445//446// The following classes contains volatile information about the class hierarchy.447// The class table mutex must be acquired before accessing the following datastructures448//449// During compilation, any class hierarchy assumptions are added into the TR_CHTable.450// As the last step at codegen time, TR_CHTable locks the classtable, commits all the information451// into the Persistent table.452//453// At runtime, whenever a class is extended, or method is overridden, one of the methods:454// methodGotOverridden() or classGotExtended is invoked by the class loader. It is not necessary455// to lock the class table, since the class loader already holds the lock.456//457458// TR_SubClassVisitor is an abstract class which when extended can be used to walk a class's subclasses.459// It deals with acquiring the class table mutex, visiting classes only once (in the case where you start from460// an interface class), avoiding walking all subclasses when it's not necessary and tracing what's being walked.461//462// To use the walker create a subclass of TR_SubclassVisitor and implement a method to override the463// visitSubclass pure virtual method.464//465//466class TR_SubclassVisitor467{468public:469TR_SubclassVisitor(TR::Compilation * comp);470471void visit(TR_OpaqueClassBlock *, bool locked = false);472473virtual bool visitSubclass(TR_PersistentClassInfo *) = 0;474475void setTracing(bool t) { _trace = t; }476477void stopTheWalk() { _stopTheWalk = true; }478int32_t depth() { return _depth; }479480protected:481TR_FrontEnd * fe() { return _comp->fe(); }482TR::Compilation * comp() { return _comp; }483484TR_Memory * trMemory() { return _comp->trMemory(); }485TR_StackMemory trStackMemory() { return _comp->trStackMemory(); }486TR_HeapMemory trHeapMemory() { return _comp->trHeapMemory(); }487488void visitSubclasses(TR_PersistentClassInfo *, TR_CHTable::VisitTracker& visited);489490TR::Compilation * _comp;491int32_t _depth;492bool _mightVisitAClassMoreThanOnce;493bool _stopTheWalk;494bool _trace;495};496497#define INVALID 0498#define VALID_BUT_NOT_ALWAYS_INITIALIZED 1499#define VALID_AND_ALWAYS_INITIALIZED 2500#define VALID_AND_INITIALIZED_STATICALLY 3501#define VALIDITY_FLAGS 3502503#define IMMUTABLE_FLAG 4504#define NOT_READ_FLAG 8505#define BIG_DECIMAL_ASSUMPTION_FLAG 16506#define BIG_INTEGER_ASSUMPTION_FLAG 32507#define BIG_DECIMAL_TYPE_FLAG 64508#define BIG_INTEGER_TYPE_FLAG 128509510class TR_PersistentFieldInfo : public TR_Link<TR_PersistentFieldInfo>511{512public:513TR_PersistentFieldInfo(char *sig,514int32_t sigLength = -1,515TR_PersistentFieldInfo *next = NULL,516uint8_t b = VALID_BUT_NOT_ALWAYS_INITIALIZED,517char *c = 0,518int32_t numChars = -1)519520: TR_Link<TR_PersistentFieldInfo>(next),521_signature(sig),522_signatureLength(sigLength),523_isTypeInfoValid(b),524_numChars(numChars),525_classPointer(c),526_canMorph(true)527{528_isTypeInfoValid |= IMMUTABLE_FLAG;529_isTypeInfoValid |= NOT_READ_FLAG;530_isTypeInfoValid |= BIG_INTEGER_TYPE_FLAG;531_isTypeInfoValid |= BIG_DECIMAL_TYPE_FLAG;532}533534void copyData(TR_PersistentFieldInfo *other)535{536_isTypeInfoValid = other->getFlags();537setFieldSignature(other->getFieldSignature());538setFieldSignatureLength(other->getFieldSignatureLength());539setClassPointer(other->getClassPointer());540setNumChars(other->getNumChars());541setCanChangeToArray(other->canChangeToArray());542}543544545char *getFieldSignature() {return _signature;}546void setFieldSignature(char *sig) {_signature = sig;}547548int32_t getFieldSignatureLength() {return _signatureLength;}549void setFieldSignatureLength(int32_t length) {_signatureLength = length;}550551// Downcast552//553virtual TR_PersistentArrayFieldInfo *asPersistentArrayFieldInfo() {return NULL;}554555#ifdef DEBUG556virtual void dumpInfo(TR_FrontEnd *vm, TR::FILE *);557#endif558559const char *getClassPointer() {return _classPointer;}560void setClassPointer(const char *c) {_classPointer = c;}561int32_t getNumChars() {return _numChars;}562void setNumChars(int32_t n) {_numChars = n;}563564uint8_t getFlags() {return _isTypeInfoValid; }565566uint8_t isTypeInfoValid() {return (_isTypeInfoValid & (VALIDITY_FLAGS));}567void setIsTypeInfoValid(uint8_t b)568{569uint8_t temp = b;570571if (isImmutable())572temp = (temp | IMMUTABLE_FLAG);573574if (isNotRead())575temp = (temp | NOT_READ_FLAG);576577if (isBigDecimalType())578temp = (temp | BIG_DECIMAL_TYPE_FLAG);579580if (hasBigDecimalAssumption())581temp = (temp | BIG_DECIMAL_ASSUMPTION_FLAG);582583if (isBigIntegerType())584temp = (temp | BIG_INTEGER_TYPE_FLAG);585586if (hasBigIntegerAssumption())587temp = (temp | BIG_INTEGER_ASSUMPTION_FLAG);588589_isTypeInfoValid = temp;590}591592bool isImmutable()593{594if ((_isTypeInfoValid & IMMUTABLE_FLAG))595return true;596return false;597}598599void setImmutable(bool b)600{601if (b)602_isTypeInfoValid |= IMMUTABLE_FLAG;603else604_isTypeInfoValid &= ~(IMMUTABLE_FLAG);605}606607bool isNotRead()608{609if ((_isTypeInfoValid & NOT_READ_FLAG))610return true;611return false;612}613614void setNotRead(bool b)615{616if (b)617_isTypeInfoValid |= NOT_READ_FLAG;618else619_isTypeInfoValid &= ~(NOT_READ_FLAG);620}621622bool isBigDecimalType()623{624if ((_isTypeInfoValid & BIG_DECIMAL_TYPE_FLAG))625return true;626return false;627}628629void setBigDecimalType(bool b)630{631if (b)632_isTypeInfoValid |= BIG_DECIMAL_TYPE_FLAG;633else634_isTypeInfoValid &= ~(BIG_DECIMAL_TYPE_FLAG);635}636637bool isBigIntegerType()638{639if ((_isTypeInfoValid & BIG_INTEGER_TYPE_FLAG))640return true;641return false;642}643644void setBigIntegerType(bool b)645{646if (b)647_isTypeInfoValid |= BIG_INTEGER_TYPE_FLAG;648else649_isTypeInfoValid &= ~(BIG_INTEGER_TYPE_FLAG);650}651652bool hasBigDecimalAssumption()653{654if ((_isTypeInfoValid & BIG_DECIMAL_ASSUMPTION_FLAG))655return true;656return false;657}658659void setBigDecimalAssumption(bool b)660{661if (b)662_isTypeInfoValid |= BIG_DECIMAL_ASSUMPTION_FLAG;663else664_isTypeInfoValid &= ~(BIG_DECIMAL_ASSUMPTION_FLAG);665}666667bool hasBigIntegerAssumption()668{669if ((_isTypeInfoValid & BIG_INTEGER_ASSUMPTION_FLAG))670return true;671return false;672}673674void setBigIntegerAssumption(bool b)675{676if (b)677_isTypeInfoValid |= BIG_INTEGER_ASSUMPTION_FLAG;678else679_isTypeInfoValid &= ~(BIG_INTEGER_ASSUMPTION_FLAG);680}681682bool canChangeToArray() {return _canMorph;}683void setCanChangeToArray(bool v) {_canMorph = v;}684685protected:686687char * _signature;688const char * _classPointer;689int32_t _signatureLength;690int32_t _numChars;691uint8_t _isTypeInfoValid;692bool _canMorph;693};694695696class TR_PersistentArrayFieldInfo : public TR_PersistentFieldInfo697{698public:699TR_PersistentArrayFieldInfo(char *sig,700int32_t sigLength = -1,701TR_PersistentArrayFieldInfo *next = NULL,702int32_t numDimensions = -1,703int32_t *dimensionInfo = NULL,704uint8_t b1 = VALID_BUT_NOT_ALWAYS_INITIALIZED,705uint8_t b2 = VALID_BUT_NOT_ALWAYS_INITIALIZED,706char *c = "",707int32_t numChars = -1)708: TR_PersistentFieldInfo(sig, sigLength, next, b2, c, numChars),709_numDimensions(numDimensions),710_dimensionInfo(dimensionInfo),711_isDimensionInfoValid(b1)712{713}714715int32_t getNumDimensions() {return _numDimensions;}716void setNumDimensions(int32_t d) {_numDimensions = d;}717718int32_t *getDimensionInfo() {return _dimensionInfo;}719void setDimensionInfo(int32_t *info) {_dimensionInfo = info;}720int32_t getDimensionInfo(int32_t i) {return _dimensionInfo[i];}721void setDimensionInfo(int32_t i, int32_t value) {_dimensionInfo[i] = value;}722723uint8_t isDimensionInfoValid() {return _isDimensionInfoValid;}724void setIsDimensionInfoValid(uint8_t b) {_isDimensionInfoValid = b;}725726void prepareArrayFieldInfo(int32_t, TR::Compilation *);727728virtual TR_PersistentArrayFieldInfo *asPersistentArrayFieldInfo() {return this;}729730#ifdef DEBUG731virtual void dumpInfo(TR_FrontEnd *vm, TR::FILE *);732#endif733734private:735int32_t * _dimensionInfo;736int32_t _numDimensions;737uint8_t _isDimensionInfoValid;738};739740class TR_PersistentClassInfoForFields : public TR_LinkHead<TR_PersistentFieldInfo>741{742public:743TR_PersistentFieldInfo * find(TR::Compilation *, TR::Symbol *, TR::SymbolReference *);744TR_PersistentFieldInfo * findFieldInfo(TR::Compilation *, TR::Node * & node, bool canBeArrayShadow);745};746747class TR_ClassQueries748{749public:750static void getSubClasses (TR_PersistentClassInfo *clazz,751TR_ScratchList<TR_PersistentClassInfo> &list,752TR_FrontEnd *vm, bool locked = false);753static int32_t collectImplementorsCapped(TR_PersistentClassInfo *clazz,754TR_ResolvedMethod **implArray,755int32_t maxCount,756int32_t slotOrIndex,757TR_ResolvedMethod *callerMethod,758TR::Compilation *comp,759bool locked = false,760TR_YesNoMaybe useGetResolvedInterfaceMethod = TR_maybe);761static int32_t collectCompiledImplementorsCapped(TR_PersistentClassInfo *clazz,762TR_ResolvedMethod **implArray,763int32_t maxCount,764int32_t slotOrIndex,765TR_ResolvedMethod *callerMethod,766TR::Compilation *comp,767TR_Hotness hotness,768bool locked = false,769TR_YesNoMaybe useGetResolvedInterfaceMethod = TR_maybe);770771static void collectLeafs (TR_PersistentClassInfo *clazz,772TR_ScratchList<TR_PersistentClassInfo> &list,773TR::Compilation *comp,774bool locked = false);775776static void collectAllNonIFSubClasses(TR_PersistentClassInfo *clazz,777TR_ScratchList<TR_PersistentClassInfo> &leafs,778TR::Compilation *comp,779bool locked = false);780781static void collectAllSubClasses (TR_PersistentClassInfo *clazz,782TR_ScratchList<TR_PersistentClassInfo> *leafs,783TR::Compilation *comp, bool locked = false);784785static int32_t countAllNonIFSubClassesWithDepth(TR_PersistentClassInfo *clazz,786TR::Compilation *comp,787int32_t maxCount, bool locked = false);788789static void addAnAssumptionForEachSubClass (TR_PersistentCHTable *table,790TR_PersistentClassInfo *clazz,791List<TR_VirtualGuardSite> &,792TR::Compilation *comp);793794private:795static void collectLeafsLocked(TR_PersistentClassInfo* clazz,796TR_ScratchList<TR_PersistentClassInfo>& leafs,797TR_CHTable::VisitTracker& marked);798static void collectAllSubClassesLocked(TR_PersistentClassInfo* clazz,799TR_ScratchList<TR_PersistentClassInfo>* leafs,800TR_CHTable::VisitTracker& marked);801};802803#endif804805806807