Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcutil/ROMClassCreationContext.hpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2001, 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 ROMCLASSCREATIONCONTEXT_HPP_
24
#define ROMCLASSCREATIONCONTEXT_HPP_
25
26
#include "bcutil_api.h"
27
#include "j9.h"
28
#include "j9comp.h"
29
#include "j9port.h"
30
#include "jvminit.h"
31
#include "rommeth.h"
32
#include "SCQueryFunctions.h"
33
#include "ut_j9bcu.h"
34
35
#include "AllocationStrategy.hpp"
36
#include "BuildResult.hpp"
37
#include "ROMClassCreationPhase.hpp"
38
39
class ROMClassCreationContext
40
{
41
public:
42
ROMClassCreationContext(J9PortLibrary *portLibrary, U_8 *classFileBytes, UDATA classFileSize, UDATA bctFlags, UDATA bcuFlags, J9ROMClass *romClass) :
43
_portLibrary(portLibrary),
44
_javaVM(NULL),
45
_classFileBytes(classFileBytes),
46
_classFileSize(classFileSize),
47
_bctFlags(bctFlags),
48
_bcuFlags(bcuFlags),
49
_findClassFlags(0),
50
_allocationStrategy(NULL),
51
_romClass(romClass),
52
_clazz(NULL),
53
_className(NULL),
54
_classNameLength(0),
55
_hostPackageName(NULL),
56
_hostPackageLength(0),
57
_intermediateClassData(NULL),
58
_intermediateClassDataLength(0),
59
_classLoader(NULL),
60
_cpIndex(0),
61
_loadLocation(0),
62
_dynamicLoadStats(NULL),
63
_sharedStringInternTable(NULL),
64
_classFileBytesReplaced(false),
65
_retransformAllowed(false),
66
_interningEnabled(false),
67
_verboseROMClass(false),
68
_verboseLastBufferSizeExceeded(0),
69
_verboseOutOfMemoryCount(0),
70
_verboseCurrentPhase(ROMClassCreation),
71
_buildResult(OK),
72
_forceDebugDataInLine(false),
73
_doDebugCompare(false),
74
_existingRomMethod(NULL),
75
_reusingIntermediateClassData(false),
76
_creatingIntermediateROMClass(false),
77
_patchMap(NULL)
78
{
79
}
80
81
ROMClassCreationContext(J9PortLibrary *portLibrary, U_8 *classFileBytes, UDATA classFileSize, UDATA bctFlags, UDATA bcuFlags, UDATA findClassFlags, AllocationStrategy *allocationStrategy) :
82
_portLibrary(portLibrary),
83
_javaVM(NULL),
84
_classFileBytes(classFileBytes),
85
_classFileSize(classFileSize),
86
_bctFlags(bctFlags),
87
_bcuFlags(bcuFlags),
88
_findClassFlags(findClassFlags),
89
_allocationStrategy(allocationStrategy),
90
_romClass(NULL),
91
_clazz(NULL),
92
_className(NULL),
93
_classNameLength(0),
94
_hostPackageName(NULL),
95
_hostPackageLength(0),
96
_intermediateClassData(NULL),
97
_intermediateClassDataLength(0),
98
_classLoader(NULL),
99
_cpIndex(0),
100
_loadLocation(0),
101
_dynamicLoadStats(NULL),
102
_sharedStringInternTable(NULL),
103
_classFileBytesReplaced(false),
104
_retransformAllowed(false),
105
_interningEnabled(false),
106
_verboseROMClass(false),
107
_verboseLastBufferSizeExceeded(0),
108
_verboseOutOfMemoryCount(0),
109
_verboseCurrentPhase(ROMClassCreation),
110
_buildResult(OK),
111
_forceDebugDataInLine(false),
112
_doDebugCompare(false),
113
_existingRomMethod(NULL),
114
_reusingIntermediateClassData(false),
115
_creatingIntermediateROMClass(false),
116
_patchMap(NULL)
117
{
118
}
119
120
ROMClassCreationContext(
121
J9PortLibrary *portLibrary, J9JavaVM *javaVM, U_8 *classFileBytes, UDATA classFileSize, UDATA bctFlags, UDATA bcuFlags, UDATA findClassFlags, AllocationStrategy *allocationStrategy,
122
U_8 *className, UDATA classNameLength, U_8 *hostPackageName, UDATA hostPackageLength, U_8 *intermediateClassData, U_32 intermediateClassDataLength, J9ROMClass *romClass, J9Class *clazz,
123
J9ClassLoader *classLoader, bool classFileBytesReplaced, bool creatingIntermediateROMClass, J9TranslationLocalBuffer *localBuffer) :
124
_portLibrary(portLibrary),
125
_javaVM(javaVM),
126
_classFileBytes(classFileBytes),
127
_classFileSize(classFileSize),
128
_bctFlags(bctFlags),
129
_bcuFlags(bcuFlags),
130
_findClassFlags(findClassFlags),
131
_allocationStrategy(allocationStrategy),
132
_romClass(romClass),
133
_clazz(clazz),
134
_className(className),
135
_classNameLength(classNameLength),
136
_hostPackageName(hostPackageName),
137
_hostPackageLength(hostPackageLength),
138
_intermediateClassData(intermediateClassData),
139
_intermediateClassDataLength(intermediateClassDataLength),
140
_classLoader(classLoader),
141
_cpIndex(0),
142
_loadLocation(0),
143
_dynamicLoadStats(NULL),
144
_sharedStringInternTable(NULL),
145
_classFileBytesReplaced(classFileBytesReplaced),
146
#if defined(J9VM_OPT_JVMTI)
147
_retransformAllowed((NULL != javaVM) && (0 != (javaVM->requiredDebugAttributes & J9VM_DEBUG_ATTRIBUTE_ALLOW_RETRANSFORM))),
148
#else
149
_retransformAllowed(false),
150
#endif
151
_interningEnabled(false),
152
_verboseROMClass((NULL != javaVM) && (0 != (javaVM->verboseLevel & VERBOSE_ROMCLASS))),
153
_verboseLastBufferSizeExceeded(0),
154
_verboseOutOfMemoryCount(0),
155
_verboseCurrentPhase(ROMClassCreation),
156
_buildResult(OK),
157
_forceDebugDataInLine(false),
158
_doDebugCompare(false),
159
_existingRomMethod(NULL),
160
_reusingIntermediateClassData(false),
161
_creatingIntermediateROMClass(creatingIntermediateROMClass),
162
_patchMap(NULL)
163
{
164
if ((NULL != _javaVM) && (NULL != _javaVM->dynamicLoadBuffers)) {
165
/* localBuffer should not be NULL */
166
Trc_BCU_Assert_True(NULL != localBuffer);
167
_cpIndex = localBuffer->entryIndex;
168
_loadLocation = localBuffer->loadLocationType;
169
_patchMap = localBuffer->patchMap;
170
_sharedStringInternTable = _javaVM->sharedInvariantInternTable;
171
_interningEnabled = J9_ARE_ALL_BITS_SET(_bcuFlags, BCU_ENABLE_INVARIANT_INTERNING) && J9_ARE_NO_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_ANON);
172
if (0 != (bcuFlags & BCU_VERBOSE)) {
173
_dynamicLoadStats = _javaVM->dynamicLoadBuffers->dynamicLoadStats;
174
}
175
}
176
if (_verboseROMClass) {
177
memset(&_verboseRecords[0], 0, sizeof(_verboseRecords));
178
}
179
}
180
181
bool isCreatingIntermediateROMClass() const { return _creatingIntermediateROMClass; }
182
U_8 *classFileBytes() const { return _classFileBytes; }
183
UDATA classFileSize() const { return _classFileSize; }
184
UDATA findClassFlags() const {return _findClassFlags; }
185
U_8* className() const {return _className; }
186
UDATA classNameLength() const {return _classNameLength; }
187
U_8* hostPackageName() const {return _hostPackageName; }
188
UDATA hostPackageLength() const {return _hostPackageLength; }
189
U_32 bctFlags() const { return (U_32) _bctFlags; } /* Only use this for j9bcutil_readClassFileBytes */
190
AllocationStrategy *allocationStrategy() const { return _allocationStrategy; }
191
bool classFileBytesReplaced() const { return _classFileBytesReplaced; }
192
#if defined(J9VM_OPT_JVMTI)
193
bool isRetransformAllowed() const { return _retransformAllowed; }
194
#else
195
bool isRetransformAllowed() const { return false; }
196
#endif
197
bool isVerbose() const { return _verboseROMClass; }
198
J9ClassLoader *classLoader() const { return _classLoader; }
199
J9JavaVM *javaVM() const { return _javaVM; }
200
J9VMThread *currentVMThread() const { return _javaVM->internalVMFunctions->currentVMThread(_javaVM); }
201
J9PortLibrary *portLibrary() const { return _portLibrary; }
202
UDATA cpIndex() const { return _cpIndex; }
203
UDATA loadLocation() const {return _loadLocation; }
204
J9ClassPatchMap *patchMap() const { return _patchMap; }
205
J9SharedInvariantInternTable *sharedStringInternTable() const { return _sharedStringInternTable; }
206
207
U_8 *intermediateClassData() const { return _intermediateClassData; }
208
U_32 intermediateClassDataLength() const { return _intermediateClassDataLength; }
209
210
U_8 *getIntermediateClassDataFromPreviousROMClass() const { return (NULL != _clazz) ? WSRP_GET(_clazz->romClass->intermediateClassData, U_8*) : NULL; }
211
U_32 getIntermediateClassDataLengthFromPreviousROMClass() const { return (NULL != _clazz) ? _clazz->romClass->intermediateClassDataLength : 0; }
212
213
void setReusingIntermediateClassData() { _reusingIntermediateClassData = true; }
214
bool isReusingIntermediateClassData() const { return _reusingIntermediateClassData; }
215
bool isInterningEnabled() const { return _interningEnabled; }
216
bool isRedefining() const { return J9_FINDCLASS_FLAG_REDEFINING == (_findClassFlags & J9_FINDCLASS_FLAG_REDEFINING); }
217
bool isRetransforming() const { return J9_FINDCLASS_FLAG_RETRANSFORMING == (_findClassFlags & J9_FINDCLASS_FLAG_RETRANSFORMING); }
218
bool isClassLoaderSharedClassesEnabled() const { return NULL != _classLoader && (_classLoader->flags & J9CLASSLOADER_SHARED_CLASSES_ENABLED); }
219
bool isSharedClassesEnabled() const { return (NULL != _javaVM) && (NULL != _javaVM->sharedClassConfig); }
220
bool isSharedClassesCacheFull() const { return (NULL != _javaVM) && j9shr_Query_IsCacheFull(_javaVM); }
221
222
/* Note: Always call isSharedClassesEnabled() before using isSharedClassesBCIEnabled() */
223
bool isSharedClassesBCIEnabled() const { return (0 != _javaVM->sharedClassConfig->isBCIEnabled(_javaVM)); }
224
225
/* Determine if this is the bootclassloader. Allow null JavaVM to get bootstrap behaviour for cfdump */
226
bool isBootstrapLoader() { return (NULL == _javaVM) || (_classLoader == _javaVM->systemClassLoader); }
227
228
/* Only the bootstrap classloader can load classes in the "java" package. */
229
bool shouldCheckPackageName() { return (NULL != _javaVM) && (_classLoader != _javaVM->systemClassLoader); }
230
bool shouldCompareROMClassForEquality() const { return NULL != _romClass; }
231
bool shouldPreserveLineNumbers() const { return 0 == (_bctFlags & (BCT_StripDebugLines|BCT_StripDebugAttributes)); }
232
bool shouldPreserveLocalVariablesInfo() const { return 0 == (_bctFlags & (BCT_StripDebugVars|BCT_StripDebugAttributes)); }
233
bool shouldPreserveSourceFileName() const { return 0 == (_bctFlags & (BCT_StripDebugSource|BCT_StripDebugAttributes)); }
234
bool shouldPreserveSourceDebugExtension() const { return 0 == (_bctFlags & (BCT_StripSourceDebugExtension|BCT_StripDebugAttributes)); }
235
bool isClassUnsafe() const { return J9_FINDCLASS_FLAG_UNSAFE == (_findClassFlags & J9_FINDCLASS_FLAG_UNSAFE); }
236
bool isClassAnon() const { return J9_FINDCLASS_FLAG_ANON == (_findClassFlags & J9_FINDCLASS_FLAG_ANON); }
237
bool alwaysSplitBytecodes() const { return J9_ARE_ANY_BITS_SET(_bctFlags, BCT_AlwaysSplitBytecodes); }
238
bool isClassHidden() const { return J9_FINDCLASS_FLAG_HIDDEN == (_findClassFlags & J9_FINDCLASS_FLAG_HIDDEN);}
239
bool isHiddenClassOptNestmateSet() const { return J9_FINDCLASS_FLAG_CLASS_OPTION_NESTMATE == (_findClassFlags & J9_FINDCLASS_FLAG_CLASS_OPTION_NESTMATE);}
240
bool isHiddenClassOptStrongSet() const { return J9_FINDCLASS_FLAG_CLASS_OPTION_STRONG == (_findClassFlags & J9_FINDCLASS_FLAG_CLASS_OPTION_STRONG);}
241
bool isDoNotShareClassFlagSet() const {return J9_ARE_ALL_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_DO_NOT_SHARE);}
242
243
bool isClassUnmodifiable() const {
244
bool unmodifiable = false;
245
if (NULL != _javaVM) {
246
if ((J2SE_VERSION(_javaVM) >= J2SE_V11)
247
&& (isClassAnon() || isClassHidden())
248
) {
249
unmodifiable = true;
250
} else if (NULL == J9VMJAVALANGOBJECT_OR_NULL(_javaVM)) {
251
/* Object is currently only allowed to be redefined in fast HCR */
252
if (areExtensionsEnabled(_javaVM)) {
253
unmodifiable = true;
254
}
255
}
256
}
257
return unmodifiable;
258
}
259
260
bool isIntermediateClassDataShareable() const {
261
bool shareable = false;
262
U_8 *intermediateData = getIntermediateClassDataFromPreviousROMClass();
263
U_32 intermediateDataLength = getIntermediateClassDataLengthFromPreviousROMClass();
264
if ((NULL != intermediateData)
265
&& (TRUE == j9shr_Query_IsAddressInReadWriteCache(_javaVM, intermediateData, intermediateDataLength))
266
/* J9ROMClass pointing to intermediateData using SRP, so share only when intermediateData is in readWriteCache */
267
) {
268
shareable = true;
269
}
270
return shareable;
271
}
272
273
bool shouldStripIntermediateClassData() const {
274
return (isSharedClassesEnabled()
275
&& isSharedClassesBCIEnabled()
276
&& !classFileBytesReplaced()
277
&& !isRetransformAllowed());
278
}
279
280
bool canRomMethodsBeSorted(UDATA threshold) const {
281
if (!isRedefining() && !isRetransforming()) {
282
if ((NULL != _javaVM) && (_javaVM->romMethodSortThreshold <= threshold)) {
283
return true;
284
}
285
}
286
return false;
287
}
288
289
bool isROMClassShareable() const {
290
/*
291
* Any of the following conditions prevent the sharing of a ROMClass:
292
* - J9_FINDCLASS_FLAG_DO_NOT_SHARE is set for this class
293
* - classloader is not shared classes enabled
294
* - cache is full
295
* - the class is unsafe and isUnsafeClassSharingEnabled returns false (see the function isUnsafeClassShareable() for more details)
296
* - the class is a hidden class and isHiddenClassSharingEnabled() returns false (Java 15 and up, see the function isHiddenClassSharingEnabled() for more details)
297
* - shared cache is BCI enabled and class is modified by BCI agent
298
* - shared cache is BCI enabled and ROMClass being store is intermediate ROMClass
299
* - the class is loaded from a patch path
300
*/
301
if (isSharedClassesEnabled()
302
&& !isDoNotShareClassFlagSet()
303
&& isClassLoaderSharedClassesEnabled()
304
&& (!isClassUnsafe() || isUnsafeClassSharingEnabled())
305
&& (!isClassHidden() || isHiddenClassSharingEnabled())
306
&& !(isSharedClassesBCIEnabled()
307
&& (classFileBytesReplaced() || isCreatingIntermediateROMClass()))
308
&& (LOAD_LOCATION_PATCH_PATH != loadLocation())
309
) {
310
return true;
311
} else {
312
return false;
313
}
314
}
315
316
bool isUnsafeClassSharingEnabled() const {
317
/*
318
* The command line option -XX:[+/-]ShareUnsafeClasses, combined with -XX:[+/-]ShareAnonymousClasses will have 4 different behaviours:
319
* 1. -XX:+ShareAnonymousClasses -XX:+ShareUnsafeClasses, this will share all unsafe classes
320
* 2. -XX:+ShareAnonymousClasses -XX:-ShareUnsafeClasses, this will only share anonymous classes and not other unsafe classes
321
* 3. -XX:-ShareAnonymousClasses -XX:+ShareUnsafeClasses, this will only share unsafe classes that are not anonymous
322
* 4. -XX:-ShareAnonymousClasses -XX:-ShareUnsafeClasses, this will share neither.
323
* The current default behavior is the 1st option.
324
*/
325
bool isEnabled = false;
326
327
bool isAnonDefineClassSharingEnabled = J9_ARE_ALL_BITS_SET(_javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_SHAREANONYMOUSCLASSES);
328
bool isUnsafeDefineClassSharingEnabled = J9_ARE_ALL_BITS_SET(_javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_SHAREUNSAFECLASSES);
329
330
if (isClassAnon()) {
331
/*
332
* Since the class loader shared classes enable flag is set properly and it is checked in the isClassLoaderSharedClassesEnabled() function
333
* before this function is called in isROMClassShareable(). Thus, we can just assert isAnonDefineClassSharingEnabled is true.
334
*/
335
Trc_BCU_Assert_True(isAnonDefineClassSharingEnabled);
336
isEnabled = true;
337
} else if (isUnsafeDefineClassSharingEnabled) {
338
/* Classes loaded by Unsafe.defineClass */
339
isEnabled = true;
340
}
341
return isEnabled;
342
}
343
344
bool isHiddenClassSharingEnabled() const {
345
/*
346
* In java 15 and up, hidden class is introduced to replace unsafe anonymous class, so use existing CML options
347
* -XX:[+/-]ShareAnonymousClasses to control the class sharing behaviour of hidden classes.
348
* The command line option -XX:[+/-]ShareUnsafeClasses, combined with -XX:[+/-]ShareAnonymousClasses will have 4 different behaviours:
349
* 1. -XX:+ShareAnonymousClasses -XX:+ShareUnsafeClasses, this will share all hidden classes
350
* 2. -XX:+ShareAnonymousClasses -XX:-ShareUnsafeClasses, this will only share hidden classes and not other unsafe classes
351
* 3. -XX:-ShareAnonymousClasses -XX:+ShareUnsafeClasses, this will only share unsafe classes that are not hidden classes
352
* 4. -XX:-ShareAnonymousClasses -XX:-ShareUnsafeClasses, this will share neither.
353
* The current default behavior is the 1st option.
354
*/
355
return J9_ARE_ALL_BITS_SET(_javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_SHAREANONYMOUSCLASSES);
356
}
357
358
/*
359
* Returns true if any of the following conditions is true
360
* - BCT_IntermediateDataIsClassfile is set
361
* - class is being redefined and the previous class as J9AccClassIntermediateDataIsClassfile set.
362
*/
363
bool isIntermediateDataAClassfile() const {
364
if (J9_ARE_ALL_BITS_SET(_bctFlags, BCT_IntermediateDataIsClassfile)) {
365
return true;
366
} else if ((NULL != _clazz) && (J9ROMCLASS_IS_INTERMEDIATE_DATA_A_CLASSFILE(_clazz->romClass))) {
367
return true;
368
} else {
369
return false;
370
}
371
}
372
373
bool canPossiblyStoreDebugInfoOutOfLine() const {
374
if (!shouldPreserveLineNumbers() && !shouldPreserveLocalVariablesInfo()) {
375
/*
376
* Can't store debug information out of line, if none of it is going to be stored at all
377
*/
378
return false;
379
}
380
if (isROMClassShareable() && !isSharedClassesCacheFull() ) {
381
/*
382
* shared classes is enabled, and there is the potential to store the class in the cache.
383
*/
384
return true;
385
}
386
if (_allocationStrategy && _allocationStrategy->canStoreDebugDataOutOfLine()) {
387
/*
388
* the allocation strategy permits out of line debug information storage.
389
*/
390
return true;
391
}
392
/*
393
* no reason to store debug information separately
394
*/
395
return false;
396
}
397
398
399
J9ROMClass *romClass() const { return _romClass; }
400
401
BuildResult checkClassName(U_8 *className, U_16 classNameLength)
402
{
403
if (!isRedefining() && !isRetransforming()) {
404
if (NULL != _className) {
405
U_16 classNameLenToCompare0 = (U_16)_classNameLength;
406
U_16 classNameLenToCompare1 = classNameLength;
407
BOOLEAN misMatch = FALSE;
408
if (isClassHidden()) {
409
if (isROMClassShareable()) {
410
U_8* lambdaClass0 = (U_8*)getLastDollarSignOfLambdaClassName((const char*)_className, _classNameLength);
411
U_8* lambdaClass1 = (U_8*)getLastDollarSignOfLambdaClassName((const char*)className, classNameLength);
412
if ((NULL != lambdaClass0)
413
&& (NULL != lambdaClass1)
414
) {
415
/**
416
* Lambda class has class name: HostClassName$$Lambda$<IndexNumber>/0x0000000000000000.
417
* Do not need to compare the IndexNumber as it can be different from run to run.
418
*/
419
classNameLenToCompare0 = (U_16)(lambdaClass0 - _className + 1);
420
classNameLenToCompare1 = (U_16)(lambdaClass1 - className + 1);
421
} else if ((NULL == lambdaClass0) && (NULL == lambdaClass1)) {
422
/* for hidden class className has ROM address appended at the end, _className does not have that */
423
classNameLenToCompare1 = (U_16)_classNameLength;
424
} else {
425
misMatch = TRUE;
426
}
427
} else {
428
/* for hidden class className has ROM address appended at the end, _className does not have that */
429
classNameLenToCompare1 = (U_16)_classNameLength;
430
}
431
}
432
if (misMatch
433
|| !J9UTF8_DATA_EQUALS(_className, classNameLenToCompare0, className, classNameLenToCompare1)
434
) {
435
#define J9WRONGNAME " (wrong name: "
436
PORT_ACCESS_FROM_PORT(_portLibrary);
437
UDATA errorStringSize = _classNameLength + sizeof(J9WRONGNAME) + 1 + classNameLength;
438
U_8 *errorUTF = (U_8 *) j9mem_allocate_memory(errorStringSize, J9MEM_CATEGORY_CLASSES);
439
if (NULL != errorUTF) {
440
U_8 *current = errorUTF;
441
442
memcpy(current, className, classNameLength);
443
current += classNameLength;
444
memcpy(current, J9WRONGNAME, sizeof(J9WRONGNAME) - 1);
445
current += sizeof(J9WRONGNAME) - 1;
446
memcpy(current, _className, _classNameLength);
447
current += _classNameLength;
448
*current++ = (U_8) ')';
449
*current = (U_8) '\0';
450
}
451
recordCFRError(errorUTF);
452
return ClassNameMismatch;
453
#undef J9WRONGNAME
454
}
455
} else if (shouldCheckPackageName() /* classname is null */
456
&& (classNameLength >= 5)
457
&& (0 == memcmp(className, "java/", 5))
458
&& !isClassAnon()
459
) {
460
/*
461
* Non-bootstrap classloaders may not load nto the "java" package.
462
* if classname is not null, the JCL or JNI has already checked it
463
*/
464
return IllegalPackageName;
465
}
466
467
}
468
return OK;
469
}
470
471
/**
472
* Report an invalid annotation error against a particular member (field or method).
473
* This will attempt to construct and set an error message based on the supplied
474
* NLS key. Regardless, an appropriate BuildResult value will be returned.
475
*
476
* @param className UTF8 data representing the class containing the member
477
* @param classNameLength length of UTF8 data representing the class containing the member
478
* @param memberName UTF8 data representing the member with the annotation
479
* @param memberNameLength length of UTF8 data representing the member with the annotation
480
* @param module_name the module portion of the NLS key
481
* @param message_num the message portion of the NLS key
482
* @return the BuildResult value
483
*/
484
BuildResult
485
reportInvalidAnnotation(U_8 *className, U_16 classNameLength, U_8 *memberName, U_16 memberNameLength, U_32 module_name, U_32 message_num)
486
{
487
const char* nlsMessage = NULL;
488
PORT_ACCESS_FROM_PORT(_portLibrary);
489
490
/* Call direct through the port library to circumvent the macro,
491
* which assumes that the key is a single parameter.
492
*/
493
nlsMessage = OMRPORT_FROM_J9PORT(PORTLIB)->nls_lookup_message(OMRPORT_FROM_J9PORT(PORTLIB), J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, module_name, message_num, NULL);
494
if(NULL != nlsMessage) {
495
UDATA messageLength = j9str_printf(PORTLIB, NULL, 0, nlsMessage, memberNameLength, memberName, classNameLength, className);
496
U_8* message = (U_8*)j9mem_allocate_memory(messageLength, OMRMEM_CATEGORY_VM);
497
if(NULL != message) {
498
j9str_printf(PORTLIB, (char*)message, messageLength, nlsMessage, memberNameLength, memberName, classNameLength, className);
499
recordCFRError(message);
500
}
501
}
502
return InvalidAnnotation;
503
}
504
505
506
void recordLoadStart()
507
{
508
Trc_BCU_buildRomClass_Entry(_classNameLength, _className);
509
if (NULL != _dynamicLoadStats) {
510
PORT_ACCESS_FROM_PORT(_portLibrary);
511
_dynamicLoadStats->sunSize = _classFileSize;
512
_dynamicLoadStats->loadStartTime = j9time_usec_clock();
513
}
514
}
515
516
void recordParseClassFileStart()
517
{
518
Trc_BCU_buildRomClass_ParseClassFileStart(_classNameLength, _className, _classLoader);
519
}
520
521
void recordParseClassFileEnd()
522
{
523
Trc_BCU_buildRomClass_ParseClassFileEnd(_classNameLength, _className, _classFileSize, _classLoader);
524
525
}
526
void recordTranslationStart()
527
{
528
Trc_BCU_buildRomClass_TranslateClassFileStart(_classNameLength, _className, _classLoader);
529
if (NULL != _dynamicLoadStats) {
530
PORT_ACCESS_FROM_PORT(_portLibrary);
531
_dynamicLoadStats->loadEndTime = _dynamicLoadStats->translateStartTime = j9time_usec_clock();
532
}
533
}
534
535
void recordTranslationEnd()
536
{
537
J9ROMClass *romClass = this->romClass();
538
Trc_BCU_buildRomClass_TranslateClassFileEnd(J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(romClass)), J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass)), romClass->romSize, _classLoader);
539
if (NULL != _dynamicLoadStats) {
540
PORT_ACCESS_FROM_PORT(_portLibrary);
541
_dynamicLoadStats->romSize = romClass->romSize;
542
_dynamicLoadStats->translateEndTime = j9time_usec_clock();
543
}
544
}
545
546
void recordROMClass(J9ROMClass *romClass)
547
{
548
_romClass = romClass;
549
}
550
551
void recordCFRError(U_8 *cfrError)
552
{
553
if ((NULL != _javaVM) && (NULL != _javaVM->dynamicLoadBuffers)) {
554
_javaVM->dynamicLoadBuffers->classFileError = cfrError;
555
}
556
}
557
558
void freeClassFileBuffer(U_8 *buffer)
559
{
560
PORT_ACCESS_FROM_PORT(_portLibrary);
561
/* It is possible that through the use of recordCFRError that an internally allocated buffer has been let loose
562
* into _javaVM->dynamicLoadBuffers->classFileError, if the internal buffer that is free'd matches the one in
563
* _javaVM->dynamicLoadBuffers->classFileError, then it must be set to NULL to avoid a double free in
564
* j9bcutil_freeTranslationBuffers()*/
565
if ((NULL != _javaVM) && (NULL != _javaVM->dynamicLoadBuffers) && (buffer == _javaVM->dynamicLoadBuffers->classFileError)) {
566
_javaVM->dynamicLoadBuffers->classFileError = NULL;
567
}
568
j9mem_free_memory(buffer);
569
}
570
571
void recordLoadEnd(BuildResult result)
572
{
573
Trc_BCU_buildRomClass_Exit(result);
574
_buildResult = result;
575
}
576
577
void recordPhaseStart(ROMClassCreationPhase phase)
578
{
579
if (_verboseROMClass) {
580
PORT_ACCESS_FROM_PORT(_portLibrary);
581
_verboseRecords[phase].lastStartTime = j9time_usec_clock();
582
_verboseRecords[phase].parentPhase = _verboseCurrentPhase;
583
_verboseCurrentPhase = phase;
584
}
585
}
586
587
void recordPhaseEnd(ROMClassCreationPhase phase, BuildResult buildResult)
588
{
589
if (_verboseROMClass) {
590
PORT_ACCESS_FROM_PORT(_portLibrary);
591
_verboseRecords[phase].accumulatedTime += j9time_usec_clock() - _verboseRecords[phase].lastStartTime;
592
_verboseRecords[phase].buildResult = buildResult;
593
_verboseCurrentPhase = _verboseRecords[phase].parentPhase;
594
}
595
}
596
597
void recordOutOfMemory(UDATA bufferSize)
598
{
599
if (_verboseROMClass) {
600
_verboseLastBufferSizeExceeded = bufferSize;
601
_verboseOutOfMemoryCount++;
602
for (ROMClassCreationPhase phase = ROMClassCreation; phase != ROMClassCreationPhaseCount; ++phase) {
603
_verboseRecords[phase].failureTime = _verboseRecords[phase].accumulatedTime;
604
}
605
}
606
}
607
608
void reportStatistics(J9TranslationLocalBuffer *localBuffer)
609
{
610
if (NULL != _dynamicLoadStats) {
611
if ((NULL != _javaVM) && (NULL != _javaVM->dynamicLoadBuffers) && (NULL != _javaVM->dynamicLoadBuffers->reportStatisticsFunction)) {
612
_javaVM->dynamicLoadBuffers->reportStatisticsFunction(_javaVM, classLoader(), romClass(), localBuffer);
613
}
614
memset(&_dynamicLoadStats->nameLength, 0, sizeof(J9DynamicLoadStats) - sizeof(UDATA) - sizeof(U_8 *));
615
}
616
if (_verboseROMClass) {
617
reportVerboseStatistics();
618
}
619
}
620
621
void forceDebugDataInLine()
622
{
623
_forceDebugDataInLine = true;
624
}
625
626
bool shouldWriteDebugDataInline()
627
{
628
if (_doDebugCompare) {
629
return romMethodDebugDataIsInline();
630
} else {
631
return _forceDebugDataInLine;
632
}
633
}
634
635
void startDebugCompare()
636
{
637
_doDebugCompare = true;
638
}
639
640
void endDebugCompare()
641
{
642
_doDebugCompare = false;
643
}
644
645
/*Methods that find an existing romMethod at offset in _romClass, and then query the method*/
646
U_32 romMethodModifiers()
647
{
648
J9ROMMethod * romMethod = romMethodGetCachedMethod();
649
if (NULL != romMethod) {
650
return romMethod->modifiers;
651
} else {
652
return 0;
653
}
654
}
655
656
bool romMethodHasDebugData()
657
{
658
return (0 != (romMethodModifiers() & J9AccMethodHasDebugInfo));
659
}
660
661
bool romMethodHasLineNumberCountCompressed()
662
{
663
bool retval = false;
664
J9ROMMethod * romMethod = romMethodGetCachedMethod();
665
if (NULL != romMethod) {
666
J9MethodDebugInfo * debuginfo = getMethodDebugInfoFromROMMethod(romMethod);
667
if (NULL != debuginfo) {
668
retval = (0x0 == (debuginfo->lineNumberCount & 0x1));
669
}
670
}
671
return retval;
672
}
673
674
U_32 romMethodCompressedLineNumbersLength()
675
{
676
U_32 retval = 0;
677
J9ROMMethod * romMethod = romMethodGetCachedMethod();
678
if (NULL != romMethod) {
679
J9MethodDebugInfo * debuginfo = getMethodDebugInfoFromROMMethod(romMethod);
680
if (NULL != debuginfo) {
681
if (0x1 == (debuginfo->lineNumberCount & 0x1)) {
682
/*lineNumbersInfoCompressedSize is the U_32 following debuginfo in memory*/
683
retval = *(U_32 *)(debuginfo+1);
684
} else {
685
/*lineNumbersInfoCompressedSize is stored encoded in the lineNumberCount value*/
686
retval = ((debuginfo->lineNumberCount & 0xffff0000) >> 16);
687
}
688
}/*else there is no debug data*/
689
}
690
return retval;
691
}
692
693
void * romMethodLineNumbersDataStart()
694
{
695
J9ROMMethod * romMethod = romMethodGetCachedMethod();
696
if (NULL != romMethod) {
697
return (void *)getMethodDebugInfoFromROMMethod(romMethod);
698
} else {
699
return NULL;
700
}
701
}
702
703
bool romMethodDebugDataIsInline()
704
{
705
bool retval = true;
706
J9ROMMethod * romMethod = romMethodGetCachedMethod();
707
/* romMethodHasDebugData() is called to ensure methodDebugInfoFromROMMethod()
708
* will return a valid address to inspect.
709
*/
710
if ((NULL != romMethod) && (true == romMethodHasDebugData())) {
711
/* methodDebugInfoFromROMMethod() is called instead of getMethodDebugInfoFromROMMethod()
712
* because getMethodDebugInfoFromROMMethod() will follow the srp to 'out of line' debug
713
* data (and cause problems checking "1 ==(debugInfo->srpToVarInfo & 1)")
714
*/
715
J9MethodDebugInfo* debugInfo = methodDebugInfoFromROMMethod(romMethod);
716
retval = (1 ==(debugInfo->srpToVarInfo & 1));
717
}
718
return retval;
719
}
720
721
void romMethodCacheCurrentRomMethod(IDATA offset)
722
{
723
_existingRomMethod = romMethodFromOffset(offset);
724
}
725
726
J9ROMMethod * romMethodGetCachedMethod()
727
{
728
return _existingRomMethod;
729
}
730
731
void * romMethodVariableDataStart()
732
{
733
void * retval = NULL;
734
J9ROMMethod * romMethod = romMethodGetCachedMethod();
735
if (NULL != romMethod) {
736
J9MethodDebugInfo* debugInfo = getMethodDebugInfoFromROMMethod(romMethod);
737
if (NULL != debugInfo) {
738
retval = (void *)getVariableTableForMethodDebugInfo(debugInfo);
739
}
740
}
741
return retval;
742
}
743
744
/*Methods that query _romClass*/
745
U_32 romClassOptionalFlags()
746
{
747
if (NULL != _romClass) {
748
return _romClass->optionalFlags;
749
} else {
750
return 0;
751
}
752
}
753
754
bool romClassHasSourceDebugExtension()
755
{
756
return (0 != (romClassOptionalFlags() & J9_ROMCLASS_OPTINFO_SOURCE_DEBUG_EXTENSION));
757
}
758
759
bool romClassHasSourceFileName()
760
{
761
return (0 != (romClassOptionalFlags() & J9_ROMCLASS_OPTINFO_SOURCE_FILE_NAME));
762
}
763
764
private:
765
void reportVerboseStatistics();
766
void verbosePrintPhase(ROMClassCreationPhase phase, bool *printedPhases, UDATA indent);
767
const char *buildResultString(BuildResult result);
768
769
struct VerboseRecord
770
{
771
UDATA lastStartTime; /* last time this phase started - temporary */
772
UDATA accumulatedTime; /* total time spent in this phase */
773
UDATA failureTime; /* total time wasted in this phase due to later failure */
774
BuildResult buildResult; /* last build result from this phase */
775
ROMClassCreationPhase parentPhase; /* phase in which this phase was last nested */
776
};
777
778
J9PortLibrary *_portLibrary;
779
J9JavaVM * _javaVM;
780
U_8 * _classFileBytes;
781
UDATA _classFileSize;
782
UDATA _bctFlags;
783
UDATA _bcuFlags;
784
UDATA _findClassFlags;
785
AllocationStrategy *_allocationStrategy;
786
J9ROMClass *_romClass;
787
J9Class *_clazz;
788
U_8 *_className;
789
UDATA _classNameLength;
790
U_8* _hostPackageName;
791
UDATA _hostPackageLength;
792
U_8 *_intermediateClassData;
793
U_32 _intermediateClassDataLength;
794
J9ClassLoader *_classLoader;
795
UDATA _cpIndex;
796
UDATA _loadLocation;
797
J9DynamicLoadStats *_dynamicLoadStats;
798
J9SharedInvariantInternTable *_sharedStringInternTable;
799
bool _classFileBytesReplaced;
800
bool _retransformAllowed;
801
bool _interningEnabled;
802
bool _verboseROMClass;
803
UDATA _verboseLastBufferSizeExceeded;
804
UDATA _verboseOutOfMemoryCount;
805
ROMClassCreationPhase _verboseCurrentPhase;
806
BuildResult _buildResult;
807
VerboseRecord _verboseRecords[ROMClassCreationPhaseCount];
808
bool _forceDebugDataInLine;
809
bool _doDebugCompare;
810
J9ROMMethod * _existingRomMethod;
811
bool _reusingIntermediateClassData;
812
bool _creatingIntermediateROMClass;
813
J9ClassPatchMap *_patchMap;
814
815
J9ROMMethod * romMethodFromOffset(IDATA offset);
816
};
817
818
#endif /* ROMCLASSCREATIONCONTEXT_HPP_ */
819
820