Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/env/CHTable.hpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
23
#ifndef CHTABLE_INCL
24
#define CHTABLE_INCL
25
26
#include <stddef.h>
27
#include <stdint.h>
28
#include "compile/Compilation.hpp"
29
#include "compile/CompilationTypes.hpp"
30
#include "compile/VirtualGuard.hpp"
31
#include "env/RuntimeAssumptionTable.hpp"
32
#include "env/TRMemory.hpp"
33
#include "env/jittypes.h"
34
#include "infra/Link.hpp"
35
#include "runtime/RuntimeAssumptions.hpp"
36
#if defined(J9VM_OPT_JITSERVER)
37
#include "env/JITServerCHTable.hpp"
38
#endif
39
40
class TR_FrontEnd;
41
class TR_OpaqueClassBlock;
42
class TR_OpaqueMethodBlock;
43
class TR_PersistentArrayFieldInfo;
44
class TR_PersistentCHTable;
45
class TR_ResolvedMethod;
46
class TR_VirtualGuard;
47
namespace TR { class Node; }
48
namespace TR { class Symbol; }
49
namespace TR { class SymbolReference; }
50
template <class T> class List;
51
template <class T> class TR_Array;
52
template <class T> class TR_ScratchList;
53
54
class TR_VirtualGuardSite
55
{
56
public:
57
TR_ALLOC(TR_Memory::VirtualGuardSiteInfo);
58
TR_VirtualGuardSite() : _location(0), _location2(0), _destination(0) {}
59
60
uint8_t* getLocation() { return _location; }
61
uint8_t* getLocation2() { return _location2; }
62
uint8_t* &getDestination() { return _destination; }
63
64
void setLocation(uint8_t *location) { _location = location; }
65
void setLocation2(uint8_t *location2) { _location2 = location2; }
66
void setDestination(uint8_t *dest) { _destination = dest; }
67
68
private:
69
uint8_t *_location;
70
uint8_t *_location2; // used when ordered pair relocations are needed
71
uint8_t *_destination;
72
};
73
74
class TR_AOTGuardSite : public TR_VirtualGuardSite
75
{
76
public:
77
TR_ALLOC(TR_Memory::VirtualGuardSiteInfo);
78
TR_AOTGuardSite() : TR_VirtualGuardSite(), _guardType(TR_NoGuard), _virtualGuard(NULL), _node(NULL), _aconstNode(NULL) {}
79
TR_AOTGuardSite(TR_VirtualGuardKind type, TR_VirtualGuard *virtualGuard, TR::Node *node, TR::Node *aconstNode=NULL) : TR_VirtualGuardSite(), _guardType(type), _virtualGuard(virtualGuard), _node(node), _aconstNode(node) {}
80
81
void setType(TR_VirtualGuardKind type) { _guardType = type; }
82
TR_VirtualGuardKind getType() { return _guardType; }
83
84
void setGuard(TR_VirtualGuard *virtualGuard) { _virtualGuard = virtualGuard; }
85
TR_VirtualGuard * getGuard() { return _virtualGuard; }
86
87
void setNode(TR::Node *node) { _node = node; }
88
TR::Node *getNode() { return _node; }
89
90
void setAconstNode(TR::Node *aconstNode) { _aconstNode = aconstNode; }
91
TR::Node *getAconstNode() { return _aconstNode; }
92
93
private:
94
TR_VirtualGuardKind _guardType;
95
TR_VirtualGuard *_virtualGuard;
96
TR::Node *_node;
97
TR::Node *_aconstNode;
98
};
99
100
class TR_PatchNOPedGuardSiteOnClassExtend : public TR::PatchNOPedGuardSite
101
{
102
protected:
103
TR_PatchNOPedGuardSiteOnClassExtend(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz,
104
uint8_t *loc, uint8_t *dest)
105
: TR::PatchNOPedGuardSite(pm, (uintptr_t)clazz, RuntimeAssumptionOnClassExtend,
106
loc, dest) {}
107
public:
108
static TR_PatchNOPedGuardSiteOnClassExtend *make(
109
TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);
110
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassExtend; }
111
};
112
113
class TR_PatchNOPedGuardSiteOnMethodOverride : public TR::PatchNOPedGuardSite
114
{
115
protected:
116
TR_PatchNOPedGuardSiteOnMethodOverride(TR_PersistentMemory *pm, TR_OpaqueMethodBlock *method,
117
uint8_t *loc, uint8_t *dest)
118
: TR::PatchNOPedGuardSite(pm, (uintptr_t)method, RuntimeAssumptionOnMethodOverride,
119
loc, dest) {}
120
public:
121
static TR_PatchNOPedGuardSiteOnMethodOverride *make(
122
TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueMethodBlock *method, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);
123
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnMethodOverride; }
124
};
125
126
class TR_PatchNOPedGuardSiteOnClassPreInitialize : public TR::PatchNOPedGuardSite
127
{
128
public:
129
static TR_PatchNOPedGuardSiteOnClassPreInitialize *make(
130
TR_FrontEnd *fe, TR_PersistentMemory *, char *sig, uint32_t sigLen, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);
131
static uintptr_t hashCode(char *sig, uint32_t sigLen);
132
133
/** \copydoc OMR::RuntimeAssumption::reclaim()
134
* See base class documentation for more details.
135
*/
136
virtual void reclaim();
137
138
virtual bool matches(uintptr_t key) { return false; }
139
virtual bool matches(char *sig, uint32_t sigLen);
140
virtual uintptr_t hashCode() { return hashCode((char*)getKey(), _sigLen); }
141
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassPreInitialize; }
142
143
private:
144
TR_PatchNOPedGuardSiteOnClassPreInitialize(TR_PersistentMemory *pm, char *sig, uint32_t sigLen,
145
uint8_t *loc, uint8_t *dest)
146
: TR::PatchNOPedGuardSite(pm, (uintptr_t)sig, RuntimeAssumptionOnClassPreInitialize,
147
loc, dest), _sigLen(sigLen) {}
148
uint32_t _sigLen;
149
};
150
151
class TR_PatchNOPedGuardSiteOnClassRedefinition: public TR::PatchNOPedGuardSite
152
{
153
protected:
154
TR_PatchNOPedGuardSiteOnClassRedefinition(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz,
155
uint8_t *loc, uint8_t *dest)
156
: TR::PatchNOPedGuardSite(pm, (uintptr_t)clazz, RuntimeAssumptionOnClassRedefinitionNOP, loc, dest) {}
157
public:
158
static TR_PatchNOPedGuardSiteOnClassRedefinition *make(
159
TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);
160
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassRedefinitionNOP; }
161
void setKey(uintptr_t newKey) {_key = newKey;}
162
};
163
164
class TR_PatchMultipleNOPedGuardSitesOnClassRedefinition : public TR::PatchMultipleNOPedGuardSites
165
{
166
protected:
167
TR_PatchMultipleNOPedGuardSitesOnClassRedefinition(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, TR::PatchSites *sites)
168
: TR::PatchMultipleNOPedGuardSites(pm, (uintptr_t)clazz, RuntimeAssumptionOnClassRedefinitionNOP, sites) {}
169
public:
170
static TR_PatchMultipleNOPedGuardSitesOnClassRedefinition *make(
171
TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, TR::PatchSites *sites, OMR::RuntimeAssumption **sentinel);
172
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassRedefinitionNOP; }
173
void setKey(uintptr_t newKey) {_key = newKey;}
174
};
175
176
class TR_PatchNOPedGuardSiteOnStaticFinalFieldModification : public TR::PatchNOPedGuardSite
177
{
178
protected:
179
TR_PatchNOPedGuardSiteOnStaticFinalFieldModification(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz,
180
uint8_t *loc, uint8_t *dest)
181
: TR::PatchNOPedGuardSite(pm, (uintptr_t)clazz, RuntimeAssumptionOnStaticFinalFieldModification, loc, dest) {}
182
public:
183
static TR_PatchNOPedGuardSiteOnStaticFinalFieldModification *make(
184
TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);
185
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnStaticFinalFieldModification; }
186
};
187
188
class TR_PatchMultipleNOPedGuardSitesOnStaticFinalFieldModification : public TR::PatchMultipleNOPedGuardSites
189
{
190
protected:
191
TR_PatchMultipleNOPedGuardSitesOnStaticFinalFieldModification(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, TR::PatchSites *sites)
192
: TR::PatchMultipleNOPedGuardSites(pm, (uintptr_t)clazz, RuntimeAssumptionOnStaticFinalFieldModification, sites) {}
193
public:
194
static TR_PatchMultipleNOPedGuardSitesOnStaticFinalFieldModification *make(
195
TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, TR::PatchSites *sites, OMR::RuntimeAssumption **sentinel);
196
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnStaticFinalFieldModification; }
197
};
198
199
class TR_PatchNOPedGuardSiteOnMutableCallSiteChange : public TR::PatchNOPedGuardSite
200
{
201
protected:
202
TR_PatchNOPedGuardSiteOnMutableCallSiteChange(TR_PersistentMemory *pm, uintptr_t key,
203
uint8_t *loc, uint8_t *dest)
204
: TR::PatchNOPedGuardSite(pm, key, RuntimeAssumptionOnMutableCallSiteChange, loc, dest) {}
205
public:
206
static TR_PatchNOPedGuardSiteOnMutableCallSiteChange *make(
207
TR_FrontEnd *fe, TR_PersistentMemory *pm, uintptr_t KEY_WILL_GO_HERE, uint8_t *loc, uint8_t *dest, OMR::RuntimeAssumption **sentinel);
208
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnMutableCallSiteChange; }
209
};
210
211
class TR_PatchNOPedGuardSiteOnMethodBreakPoint : public TR::PatchNOPedGuardSite
212
{
213
protected:
214
TR_PatchNOPedGuardSiteOnMethodBreakPoint(TR_PersistentMemory *pm, TR_OpaqueMethodBlock *j9method,
215
uint8_t *location, uint8_t *destination)
216
: TR::PatchNOPedGuardSite(pm, (uintptr_t)j9method, RuntimeAssumptionOnMethodBreakPoint, location, destination) {}
217
218
public:
219
static TR_PatchNOPedGuardSiteOnMethodBreakPoint *make(
220
TR_FrontEnd *fe, TR_PersistentMemory * pm, TR_OpaqueMethodBlock *j9method, uint8_t *location, uint8_t *destination,
221
OMR::RuntimeAssumption **sentinel);
222
223
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnMethodBreakPoint; }
224
};
225
226
class TR_PatchJNICallSite : public OMR::ValueModifyRuntimeAssumption
227
{
228
protected:
229
TR_PatchJNICallSite(TR_PersistentMemory *pm, uintptr_t key, uint8_t *pc)
230
: OMR::ValueModifyRuntimeAssumption(pm, key), _pc(pc) {}
231
232
public:
233
TR_PERSISTENT_ALLOC_THROW(TR_Memory::CallSiteInfo)
234
static TR_PatchJNICallSite *make(
235
TR_FrontEnd *fe, TR_PersistentMemory * pm, uintptr_t key, uint8_t *pc, OMR::RuntimeAssumption **sentinel);
236
237
virtual void dumpInfo();
238
239
virtual void compensate(TR_FrontEnd *vm, bool isSMP, void *newAddress);
240
virtual bool equals(OMR::RuntimeAssumption &other)
241
{
242
TR_PatchJNICallSite *site = other.asPJNICSite();
243
return site != 0 && getPc() == site->getPc();
244
}
245
virtual uint8_t *getFirstAssumingPC() { return getPc(); }
246
virtual uint8_t *getLastAssumingPC() { return getPc(); }
247
248
virtual TR_PatchJNICallSite *asPJNICSite() { return this; }
249
uint8_t *getPc() { return _pc; }
250
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnRegisterNative; }
251
252
private:
253
uint8_t *_pc;
254
};
255
256
class TR_PreXRecompile : public OMR::LocationRedirectRuntimeAssumption
257
{
258
protected:
259
TR_PreXRecompile(TR_PersistentMemory *pm, uintptr_t key, TR_RuntimeAssumptionKind kind, uint8_t *startPC)
260
: OMR::LocationRedirectRuntimeAssumption(pm, key), _startPC(startPC) {}
261
262
public:
263
264
// NOTE: this function should be the first non-inline function in the class
265
// to make sure that the compiler puts the vtable in codegen.dev
266
virtual void dumpInfo();
267
268
virtual void compensate(TR_FrontEnd *vm, bool isSMP, void *newAddress);
269
virtual bool equals(OMR::RuntimeAssumption &o1)
270
{
271
TR_PreXRecompile *a = o1.asPXRecompile();
272
return (a != 0) && _startPC == a->_startPC;
273
}
274
275
virtual TR_PreXRecompile *asPXRecompile() { return this; }
276
virtual uint8_t *getFirstAssumingPC() { return getStartPC(); }
277
virtual uint8_t *getLastAssumingPC() { return getStartPC(); }
278
uint8_t *getStartPC() { return _startPC; }
279
280
281
private:
282
uint8_t *_startPC;
283
};
284
285
class TR_PreXRecompileOnClassExtend : public TR_PreXRecompile
286
{
287
protected:
288
TR_PreXRecompileOnClassExtend(TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *startPC)
289
: TR_PreXRecompile(pm, (uintptr_t)clazz, RuntimeAssumptionOnClassExtend, startPC) {}
290
public:
291
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnClassExtend; }
292
static TR_PreXRecompileOnClassExtend *make(
293
TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueClassBlock *clazz, uint8_t *startPC, OMR::RuntimeAssumption **sentinel);
294
};
295
296
class TR_PreXRecompileOnMethodOverride : public TR_PreXRecompile
297
{
298
protected:
299
TR_PreXRecompileOnMethodOverride(TR_PersistentMemory *pm, TR_OpaqueMethodBlock *method, uint8_t *startPC)
300
: TR_PreXRecompile(pm, (uintptr_t)method, RuntimeAssumptionOnMethodOverride, startPC) {}
301
public:
302
virtual TR_RuntimeAssumptionKind getAssumptionKind() { return RuntimeAssumptionOnMethodOverride; }
303
static TR_PreXRecompileOnMethodOverride *make(
304
TR_FrontEnd *fe, TR_PersistentMemory *pm, TR_OpaqueMethodBlock *method, uint8_t *startPC, OMR::RuntimeAssumption **sentinel);
305
};
306
307
class TR_CHTable
308
{
309
public:
310
311
/**
312
* VisitTracker class keeps a record of visited classes, and reset their
313
* visited status flags once visiting finish.
314
* Usage:
315
* {
316
* CHTableCriticalSection lock(...);
317
* VisitTracker tracker(...);
318
* Work on CHTable entries and call VisitTracker::visit() with each entry
319
* }
320
* Note that VisitTracker MUST be used inside CHTableCriticalSection
321
*
322
* A typical work flow is:
323
* 1) Enter CHTable critical section
324
* 2) Work on CHTable entries marking some of them visited
325
* 3) Loop through the list of entries with visited flags set and clear them
326
* 4) Leave CHTable critical section
327
*
328
* Note that exception may occur during Step 2.
329
* Previously (RTC 118937), visited classes were tracked by a list inside
330
* J9::Compilation, and the exception handler resets visited status flags when
331
* an exception occurred.
332
*
333
* This worked perfectly when longjmp was used: when longjmp was issued, the
334
* code is still inside CHTable critical section, and hence resetting/modifying
335
* visited status flags was safe.
336
*
337
* However, this does not work with C++ exception handling and RAII managing
338
* entering/leaving of critical sections. The code looks like following:
339
* {
340
* CHTableCriticalSection lock(...);
341
* 2) Work on CHTable entries marking some of them visited
342
* 3) Loop through the list of entries with visited flags set and clear them
343
* }
344
* Note that Steps 1&4 are replaced by CHTableCriticalSection, which enters the
345
* critical section in its constructor and leaves in its destructor. When an
346
* exception occurs in Step 2, C++ executes CHTableCriticalSection's destructor
347
* before executing the exception handler; and hence the exception handling code
348
* is outside of CHTable critical section. In short, resetting/modifying visited
349
* status flags in the exception handler is NOT safe.
350
*
351
* To solve the above mentioned issue, VisitTracker is introduced. It resets
352
* visited status flags in its destructor. The code becomes:
353
* {
354
* CHTableCriticalSection lock(...);
355
* VisitTracker tracker(...);
356
* 2) Work on CHTable entries marking some of them visited
357
* }
358
* When an exception occurred in Step 2, before executing the exception handler,
359
* C++ first executes VisitTracker's destructor and then CHTableCriticalSection's
360
* destructor. Therefore, visited status flags are reset inside CHTable critical
361
* section, which is safe.
362
*
363
*/
364
class VisitTracker
365
{
366
public:
367
368
VisitTracker(TR_Memory* m) : _classes(m) {}
369
~VisitTracker()
370
{
371
auto it = iterator();
372
for (auto info = it.getFirst(); info; info = it.getNext())
373
info->resetVisited();
374
_classes.deleteAll();
375
}
376
void visit(TR_PersistentClassInfo* info)
377
{
378
_classes.add(info); // this could throw std::bad_alloc and take us to the exception handler, before which the destructor is called
379
info->setVisited(); // it's important to set the visited flag *after* adding to marked list
380
}
381
ListIterator<TR_PersistentClassInfo> iterator()
382
{
383
return ListIterator<TR_PersistentClassInfo>(&_classes);
384
}
385
386
private:
387
TR_ScratchList<TR_PersistentClassInfo> _classes;
388
};
389
390
TR_ALLOC(TR_Memory::CHTable)
391
TR_CHTable(TR_Memory * trMemory) :
392
_preXMethods(0),
393
_classes(0),
394
_classesThatShouldNotBeNewlyExtended(0),
395
_trMemory(trMemory)
396
{
397
}
398
399
// register the class' extend event to trigger a recompile
400
bool recompileOnClassExtend (TR::Compilation *c, TR_OpaqueClassBlock * classId);
401
402
// register the class' extend event to trigger a recompile
403
bool recompileOnNewClassExtend (TR::Compilation *c, TR_OpaqueClassBlock * classId);
404
405
// register the method's override event to trigger a recompile
406
bool recompileOnMethodOverride(TR::Compilation *c, TR_ResolvedMethod *method);
407
408
void cleanupNewlyExtendedInfo(TR::Compilation *comp);
409
410
bool canSkipCommit(TR::Compilation *comp);
411
412
// Commit the CHTable into the persistent table. This method must be called
413
// with the class table mutex in hand.
414
// If an unrecoverable problem has occurred - this method will return false
415
// which will result in the failure of the current compilation
416
//
417
bool commit(TR::Compilation *comp);
418
419
void commitVirtualGuard(TR_VirtualGuard *info, List<TR_VirtualGuardSite> &sites,
420
TR_PersistentCHTable *table, TR::Compilation *comp);
421
void commitOSRVirtualGuards(TR::Compilation *comp, TR::list<TR_VirtualGuard*> &vguards);
422
#if defined(J9VM_OPT_JITSERVER)
423
CHTableCommitData computeDataForCHTableCommit(TR::Compilation *comp);
424
#endif
425
426
TR_Array<TR_OpaqueClassBlock *> *getClasses() { return _classes;}
427
TR_Array<TR_OpaqueClassBlock *> *getClassesThatShouldNotBeNewlyExtended() { return _classesThatShouldNotBeNewlyExtended;}
428
429
TR_Memory * trMemory() { return _trMemory; }
430
TR_StackMemory trStackMemory() { return _trMemory; }
431
TR_HeapMemory trHeapMemory() { return _trMemory; }
432
433
private:
434
435
friend class TR_Debug;
436
437
TR_Array<TR_ResolvedMethod*> * _preXMethods;
438
TR_Array<TR_OpaqueClassBlock *> * _classes;
439
TR_Array<TR_OpaqueClassBlock *> * _classesThatShouldNotBeNewlyExtended;
440
TR_Memory * _trMemory;
441
};
442
443
444
445
// IMPORTANT NOTE
446
//
447
// The following classes contains volatile information about the class hierarchy.
448
// The class table mutex must be acquired before accessing the following datastructures
449
//
450
// During compilation, any class hierarchy assumptions are added into the TR_CHTable.
451
// As the last step at codegen time, TR_CHTable locks the classtable, commits all the information
452
// into the Persistent table.
453
//
454
// At runtime, whenever a class is extended, or method is overridden, one of the methods:
455
// methodGotOverridden() or classGotExtended is invoked by the class loader. It is not necessary
456
// to lock the class table, since the class loader already holds the lock.
457
//
458
459
// TR_SubClassVisitor is an abstract class which when extended can be used to walk a class's subclasses.
460
// It deals with acquiring the class table mutex, visiting classes only once (in the case where you start from
461
// an interface class), avoiding walking all subclasses when it's not necessary and tracing what's being walked.
462
//
463
// To use the walker create a subclass of TR_SubclassVisitor and implement a method to override the
464
// visitSubclass pure virtual method.
465
//
466
//
467
class TR_SubclassVisitor
468
{
469
public:
470
TR_SubclassVisitor(TR::Compilation * comp);
471
472
void visit(TR_OpaqueClassBlock *, bool locked = false);
473
474
virtual bool visitSubclass(TR_PersistentClassInfo *) = 0;
475
476
void setTracing(bool t) { _trace = t; }
477
478
void stopTheWalk() { _stopTheWalk = true; }
479
int32_t depth() { return _depth; }
480
481
protected:
482
TR_FrontEnd * fe() { return _comp->fe(); }
483
TR::Compilation * comp() { return _comp; }
484
485
TR_Memory * trMemory() { return _comp->trMemory(); }
486
TR_StackMemory trStackMemory() { return _comp->trStackMemory(); }
487
TR_HeapMemory trHeapMemory() { return _comp->trHeapMemory(); }
488
489
void visitSubclasses(TR_PersistentClassInfo *, TR_CHTable::VisitTracker& visited);
490
491
TR::Compilation * _comp;
492
int32_t _depth;
493
bool _mightVisitAClassMoreThanOnce;
494
bool _stopTheWalk;
495
bool _trace;
496
};
497
498
#define INVALID 0
499
#define VALID_BUT_NOT_ALWAYS_INITIALIZED 1
500
#define VALID_AND_ALWAYS_INITIALIZED 2
501
#define VALID_AND_INITIALIZED_STATICALLY 3
502
#define VALIDITY_FLAGS 3
503
504
#define IMMUTABLE_FLAG 4
505
#define NOT_READ_FLAG 8
506
#define BIG_DECIMAL_ASSUMPTION_FLAG 16
507
#define BIG_INTEGER_ASSUMPTION_FLAG 32
508
#define BIG_DECIMAL_TYPE_FLAG 64
509
#define BIG_INTEGER_TYPE_FLAG 128
510
511
class TR_PersistentFieldInfo : public TR_Link<TR_PersistentFieldInfo>
512
{
513
public:
514
TR_PersistentFieldInfo(char *sig,
515
int32_t sigLength = -1,
516
TR_PersistentFieldInfo *next = NULL,
517
uint8_t b = VALID_BUT_NOT_ALWAYS_INITIALIZED,
518
char *c = 0,
519
int32_t numChars = -1)
520
521
: TR_Link<TR_PersistentFieldInfo>(next),
522
_signature(sig),
523
_signatureLength(sigLength),
524
_isTypeInfoValid(b),
525
_numChars(numChars),
526
_classPointer(c),
527
_canMorph(true)
528
{
529
_isTypeInfoValid |= IMMUTABLE_FLAG;
530
_isTypeInfoValid |= NOT_READ_FLAG;
531
_isTypeInfoValid |= BIG_INTEGER_TYPE_FLAG;
532
_isTypeInfoValid |= BIG_DECIMAL_TYPE_FLAG;
533
}
534
535
void copyData(TR_PersistentFieldInfo *other)
536
{
537
_isTypeInfoValid = other->getFlags();
538
setFieldSignature(other->getFieldSignature());
539
setFieldSignatureLength(other->getFieldSignatureLength());
540
setClassPointer(other->getClassPointer());
541
setNumChars(other->getNumChars());
542
setCanChangeToArray(other->canChangeToArray());
543
}
544
545
546
char *getFieldSignature() {return _signature;}
547
void setFieldSignature(char *sig) {_signature = sig;}
548
549
int32_t getFieldSignatureLength() {return _signatureLength;}
550
void setFieldSignatureLength(int32_t length) {_signatureLength = length;}
551
552
// Downcast
553
//
554
virtual TR_PersistentArrayFieldInfo *asPersistentArrayFieldInfo() {return NULL;}
555
556
#ifdef DEBUG
557
virtual void dumpInfo(TR_FrontEnd *vm, TR::FILE *);
558
#endif
559
560
const char *getClassPointer() {return _classPointer;}
561
void setClassPointer(const char *c) {_classPointer = c;}
562
int32_t getNumChars() {return _numChars;}
563
void setNumChars(int32_t n) {_numChars = n;}
564
565
uint8_t getFlags() {return _isTypeInfoValid; }
566
567
uint8_t isTypeInfoValid() {return (_isTypeInfoValid & (VALIDITY_FLAGS));}
568
void setIsTypeInfoValid(uint8_t b)
569
{
570
uint8_t temp = b;
571
572
if (isImmutable())
573
temp = (temp | IMMUTABLE_FLAG);
574
575
if (isNotRead())
576
temp = (temp | NOT_READ_FLAG);
577
578
if (isBigDecimalType())
579
temp = (temp | BIG_DECIMAL_TYPE_FLAG);
580
581
if (hasBigDecimalAssumption())
582
temp = (temp | BIG_DECIMAL_ASSUMPTION_FLAG);
583
584
if (isBigIntegerType())
585
temp = (temp | BIG_INTEGER_TYPE_FLAG);
586
587
if (hasBigIntegerAssumption())
588
temp = (temp | BIG_INTEGER_ASSUMPTION_FLAG);
589
590
_isTypeInfoValid = temp;
591
}
592
593
bool isImmutable()
594
{
595
if ((_isTypeInfoValid & IMMUTABLE_FLAG))
596
return true;
597
return false;
598
}
599
600
void setImmutable(bool b)
601
{
602
if (b)
603
_isTypeInfoValid |= IMMUTABLE_FLAG;
604
else
605
_isTypeInfoValid &= ~(IMMUTABLE_FLAG);
606
}
607
608
bool isNotRead()
609
{
610
if ((_isTypeInfoValid & NOT_READ_FLAG))
611
return true;
612
return false;
613
}
614
615
void setNotRead(bool b)
616
{
617
if (b)
618
_isTypeInfoValid |= NOT_READ_FLAG;
619
else
620
_isTypeInfoValid &= ~(NOT_READ_FLAG);
621
}
622
623
bool isBigDecimalType()
624
{
625
if ((_isTypeInfoValid & BIG_DECIMAL_TYPE_FLAG))
626
return true;
627
return false;
628
}
629
630
void setBigDecimalType(bool b)
631
{
632
if (b)
633
_isTypeInfoValid |= BIG_DECIMAL_TYPE_FLAG;
634
else
635
_isTypeInfoValid &= ~(BIG_DECIMAL_TYPE_FLAG);
636
}
637
638
bool isBigIntegerType()
639
{
640
if ((_isTypeInfoValid & BIG_INTEGER_TYPE_FLAG))
641
return true;
642
return false;
643
}
644
645
void setBigIntegerType(bool b)
646
{
647
if (b)
648
_isTypeInfoValid |= BIG_INTEGER_TYPE_FLAG;
649
else
650
_isTypeInfoValid &= ~(BIG_INTEGER_TYPE_FLAG);
651
}
652
653
bool hasBigDecimalAssumption()
654
{
655
if ((_isTypeInfoValid & BIG_DECIMAL_ASSUMPTION_FLAG))
656
return true;
657
return false;
658
}
659
660
void setBigDecimalAssumption(bool b)
661
{
662
if (b)
663
_isTypeInfoValid |= BIG_DECIMAL_ASSUMPTION_FLAG;
664
else
665
_isTypeInfoValid &= ~(BIG_DECIMAL_ASSUMPTION_FLAG);
666
}
667
668
bool hasBigIntegerAssumption()
669
{
670
if ((_isTypeInfoValid & BIG_INTEGER_ASSUMPTION_FLAG))
671
return true;
672
return false;
673
}
674
675
void setBigIntegerAssumption(bool b)
676
{
677
if (b)
678
_isTypeInfoValid |= BIG_INTEGER_ASSUMPTION_FLAG;
679
else
680
_isTypeInfoValid &= ~(BIG_INTEGER_ASSUMPTION_FLAG);
681
}
682
683
bool canChangeToArray() {return _canMorph;}
684
void setCanChangeToArray(bool v) {_canMorph = v;}
685
686
protected:
687
688
char * _signature;
689
const char * _classPointer;
690
int32_t _signatureLength;
691
int32_t _numChars;
692
uint8_t _isTypeInfoValid;
693
bool _canMorph;
694
};
695
696
697
class TR_PersistentArrayFieldInfo : public TR_PersistentFieldInfo
698
{
699
public:
700
TR_PersistentArrayFieldInfo(char *sig,
701
int32_t sigLength = -1,
702
TR_PersistentArrayFieldInfo *next = NULL,
703
int32_t numDimensions = -1,
704
int32_t *dimensionInfo = NULL,
705
uint8_t b1 = VALID_BUT_NOT_ALWAYS_INITIALIZED,
706
uint8_t b2 = VALID_BUT_NOT_ALWAYS_INITIALIZED,
707
char *c = "",
708
int32_t numChars = -1)
709
: TR_PersistentFieldInfo(sig, sigLength, next, b2, c, numChars),
710
_numDimensions(numDimensions),
711
_dimensionInfo(dimensionInfo),
712
_isDimensionInfoValid(b1)
713
{
714
}
715
716
int32_t getNumDimensions() {return _numDimensions;}
717
void setNumDimensions(int32_t d) {_numDimensions = d;}
718
719
int32_t *getDimensionInfo() {return _dimensionInfo;}
720
void setDimensionInfo(int32_t *info) {_dimensionInfo = info;}
721
int32_t getDimensionInfo(int32_t i) {return _dimensionInfo[i];}
722
void setDimensionInfo(int32_t i, int32_t value) {_dimensionInfo[i] = value;}
723
724
uint8_t isDimensionInfoValid() {return _isDimensionInfoValid;}
725
void setIsDimensionInfoValid(uint8_t b) {_isDimensionInfoValid = b;}
726
727
void prepareArrayFieldInfo(int32_t, TR::Compilation *);
728
729
virtual TR_PersistentArrayFieldInfo *asPersistentArrayFieldInfo() {return this;}
730
731
#ifdef DEBUG
732
virtual void dumpInfo(TR_FrontEnd *vm, TR::FILE *);
733
#endif
734
735
private:
736
int32_t * _dimensionInfo;
737
int32_t _numDimensions;
738
uint8_t _isDimensionInfoValid;
739
};
740
741
class TR_PersistentClassInfoForFields : public TR_LinkHead<TR_PersistentFieldInfo>
742
{
743
public:
744
TR_PersistentFieldInfo * find(TR::Compilation *, TR::Symbol *, TR::SymbolReference *);
745
TR_PersistentFieldInfo * findFieldInfo(TR::Compilation *, TR::Node * & node, bool canBeArrayShadow);
746
};
747
748
class TR_ClassQueries
749
{
750
public:
751
static void getSubClasses (TR_PersistentClassInfo *clazz,
752
TR_ScratchList<TR_PersistentClassInfo> &list,
753
TR_FrontEnd *vm, bool locked = false);
754
static int32_t collectImplementorsCapped(TR_PersistentClassInfo *clazz,
755
TR_ResolvedMethod **implArray,
756
int32_t maxCount,
757
int32_t slotOrIndex,
758
TR_ResolvedMethod *callerMethod,
759
TR::Compilation *comp,
760
bool locked = false,
761
TR_YesNoMaybe useGetResolvedInterfaceMethod = TR_maybe);
762
static int32_t collectCompiledImplementorsCapped(TR_PersistentClassInfo *clazz,
763
TR_ResolvedMethod **implArray,
764
int32_t maxCount,
765
int32_t slotOrIndex,
766
TR_ResolvedMethod *callerMethod,
767
TR::Compilation *comp,
768
TR_Hotness hotness,
769
bool locked = false,
770
TR_YesNoMaybe useGetResolvedInterfaceMethod = TR_maybe);
771
772
static void collectLeafs (TR_PersistentClassInfo *clazz,
773
TR_ScratchList<TR_PersistentClassInfo> &list,
774
TR::Compilation *comp,
775
bool locked = false);
776
777
static void collectAllNonIFSubClasses(TR_PersistentClassInfo *clazz,
778
TR_ScratchList<TR_PersistentClassInfo> &leafs,
779
TR::Compilation *comp,
780
bool locked = false);
781
782
static void collectAllSubClasses (TR_PersistentClassInfo *clazz,
783
TR_ScratchList<TR_PersistentClassInfo> *leafs,
784
TR::Compilation *comp, bool locked = false);
785
786
static int32_t countAllNonIFSubClassesWithDepth(TR_PersistentClassInfo *clazz,
787
TR::Compilation *comp,
788
int32_t maxCount, bool locked = false);
789
790
static void addAnAssumptionForEachSubClass (TR_PersistentCHTable *table,
791
TR_PersistentClassInfo *clazz,
792
List<TR_VirtualGuardSite> &,
793
TR::Compilation *comp);
794
795
private:
796
static void collectLeafsLocked(TR_PersistentClassInfo* clazz,
797
TR_ScratchList<TR_PersistentClassInfo>& leafs,
798
TR_CHTable::VisitTracker& marked);
799
static void collectAllSubClassesLocked(TR_PersistentClassInfo* clazz,
800
TR_ScratchList<TR_PersistentClassInfo>* leafs,
801
TR_CHTable::VisitTracker& marked);
802
};
803
804
#endif
805
806
807