Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcutil/ComparingCursor.cpp
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
* ComparingCursor.cpp
24
*/
25
26
#include "ComparingCursor.hpp"
27
28
#include "ClassFileOracle.hpp"
29
#include "SRPKeyProducer.hpp"
30
#include "SCQueryFunctions.h"
31
32
#include "ut_j9bcu.h"
33
#include "bcnames.h"
34
#include "pcstack.h"
35
#include "rommeth.h"
36
#include "vrfytbl.h"
37
#include "bytecodewalk.h"
38
39
40
ComparingCursor::ComparingCursor(J9JavaVM *javaVM, SRPOffsetTable *srpOffsetTable,
41
SRPKeyProducer *srpKeyProducer, ClassFileOracle *classFileOracle, U_8 *romClass,
42
bool romClassIsShared, ROMClassCreationContext * context, bool isComparingLambdaFromSCC) :
43
Cursor(0, srpOffsetTable, context),
44
_javaVM(javaVM),
45
_checkRangeInSharedCache(romClassIsShared),
46
_classFileOracle(classFileOracle),
47
_srpKeyProducer(srpKeyProducer),
48
_romClass(romClass),
49
_mode(Cursor::MAIN_CURSOR),
50
_storePointerToVariableInfo(NULL),
51
_basePointerToVariableInfo(NULL),
52
_mainHelper(srpOffsetTable, romClass, context),
53
_lineNumberHelper(srpOffsetTable, romClass, context),
54
_varInfoHelper(srpOffsetTable, romClass, context),
55
_isEqual(true),
56
_isComparingLambdaFromSCC(isComparingLambdaFromSCC)
57
{
58
if (!_checkRangeInSharedCache && (NULL != javaVM)) {
59
/* Enter mutex in order to safely iterate over the segments in getMaximumValidLengthForPtrInSegment(). */
60
omrthread_monitor_enter(javaVM->classMemorySegments->segmentMutex);
61
}
62
63
}
64
65
ComparingCursor::~ComparingCursor()
66
{
67
if (!_checkRangeInSharedCache && (NULL != _javaVM)) {
68
/* Exit mutex that was entered in the constructor. */
69
omrthread_monitor_exit(_javaVM->classMemorySegments->segmentMutex);
70
}
71
}
72
73
UDATA
74
ComparingCursor::getCount()
75
{
76
/* There is no call to getCount for the compare cursor
77
* that is interested in _lineNumberHelper or _varInfoHelper
78
* counts.
79
*/
80
return _mainHelper.getCount();
81
}
82
83
void
84
ComparingCursor::writeU8(U_8 u8Value, DataType dataType)
85
{
86
ComparingCursorHelper * countingcursor = getCountingCursor(dataType);
87
if ( shouldCheckForEquality(dataType) ) {
88
if ( !isRangeValid(sizeof(U_8), dataType) || (u8Value != *(U_8*)(countingcursor->getBaseAddress() + countingcursor->getCount())) ) {
89
markUnEqual();
90
}
91
}
92
countingcursor->writeU8(u8Value, dataType);
93
}
94
95
void
96
ComparingCursor::writeU16(U_16 u16Value, DataType dataType)
97
{
98
ComparingCursorHelper * countingcursor = getCountingCursor(dataType);
99
if ( shouldCheckForEquality(dataType) ) {
100
if ( !isRangeValid(sizeof(U_16), dataType) || (u16Value != *(U_16 *)(countingcursor->getBaseAddress() + countingcursor->getCount())) ) {
101
markUnEqual();
102
}
103
}
104
countingcursor->writeU16(u16Value, dataType);
105
}
106
107
void
108
ComparingCursor::writeU32(U_32 u32Value, DataType dataType)
109
{
110
ComparingCursorHelper * countingcursor = getCountingCursor(dataType);
111
if ( shouldCheckForEquality(dataType, u32Value) ) {
112
U_32 * tmpu32 = (U_32 *)(countingcursor->getBaseAddress() + countingcursor->getCount());
113
if (!isRangeValid(sizeof(U_32), dataType) || (u32Value != *tmpu32)) {
114
markUnEqual();
115
}
116
}
117
countingcursor->writeU32(u32Value, dataType);
118
}
119
120
U_32
121
ComparingCursor::peekU32(DataType dataType) {
122
ComparingCursorHelper * countingcursor = getCountingCursor(dataType);
123
U_32 * tmpptr = (U_32 *)(countingcursor->getBaseAddress() + countingcursor->getCount());
124
return *tmpptr;
125
}
126
127
/* If skip is called on a comparing cursor then this function
128
* must be called to ensure the correct helpers '_count' is
129
* incremented
130
*/
131
void
132
ComparingCursor::skip(UDATA byteCount, DataType dataType)
133
{
134
Cursor * countingcursor = getCountingCursor(dataType);
135
countingcursor->skip(byteCount);
136
}
137
138
void
139
ComparingCursor::writeU64(U_32 u32ValueHigh, U_32 u32ValueLow, DataType dataType)
140
{
141
ComparingCursorHelper * countingcursor = getCountingCursor(dataType);
142
if ( shouldCheckForEquality(dataType) ) {
143
if ( isRangeValid(sizeof(U_64), dataType) ) {
144
#ifdef J9VM_ENV_LITTLE_ENDIAN
145
U_64 u64Value = (U_64(u32ValueLow) << 32) + u32ValueHigh;
146
#else
147
U_64 u64Value = (U_64(u32ValueHigh) << 32) + u32ValueLow;
148
#endif
149
if ( u64Value != *(U_64 *)(countingcursor->getBaseAddress() + countingcursor->getCount()) ) {
150
markUnEqual();
151
}
152
} else {
153
markUnEqual();
154
}
155
}
156
countingcursor->writeU64(u32ValueHigh, u32ValueLow, dataType);
157
}
158
159
void
160
ComparingCursor::writeSRP(UDATA srpKey, DataType dataType)
161
{
162
ComparingCursorHelper * countingcursor = getCountingCursor(dataType);
163
U_8 * currentAddr = countingcursor->getBaseAddress() + countingcursor->getCount();
164
if ( shouldCheckForEquality(dataType) ) {
165
if ( isRangeValid(sizeof(J9SRP), dataType) ) {
166
switch (dataType) {
167
case Cursor::SRP_TO_DEBUG_DATA:
168
case Cursor::SRP_TO_GENERIC:
169
/* ignore this type */
170
break;
171
case Cursor::SRP_TO_LOCAL_VARIABLE_DATA:
172
{
173
/* test that the SRP is valid */
174
void * tmpvardata = SRP_PTR_GET(currentAddr, void *);
175
if ( NULL == tmpvardata ) {
176
if (!isSRPNull(srpKey)) {
177
markUnEqual();
178
}
179
} else if ( (_context->shouldPreserveLocalVariablesInfo() && isSRPNull(srpKey)) || !isRangeValidForPtr((U_8 *)tmpvardata,sizeof(void*)) ) {
180
/* If variable information is not required then this SRP will not be marked during the 'mark & count' phase.
181
* Checking shouldPreserveLocalVariablesInfo() ensure we isSRPNull() only if it could have been marked.
182
*/
183
markUnEqual();
184
}
185
break;
186
}
187
case Cursor::SRP_TO_SOURCE_DEBUG_EXT: {
188
/* test that the SRP is valid */
189
void * debugext = SRP_PTR_GET(currentAddr, void *);
190
191
if ( NULL == debugext ) {
192
if (!isSRPNull(srpKey)) {
193
markUnEqual();
194
}
195
} else if ( isSRPNull(srpKey) || !isRangeValidForPtr((U_8 *)debugext,sizeof(void*)) ) {
196
markUnEqual();
197
}
198
break;
199
}
200
case Cursor::LOCAL_VARIABLE_DATA_SRP_TO_UTF8:
201
case Cursor::OPTINFO_SOURCE_FILE_NAME:
202
case Cursor::SRP_TO_UTF8_CLASS_NAME:
203
case Cursor::SRP_TO_UTF8: {
204
/* test that the UTF8's are identical */
205
J9UTF8 * utf8 = SRP_PTR_GET(currentAddr, J9UTF8 *);
206
207
if ( NULL == utf8 ) {
208
if (!isSRPNull(srpKey)) {
209
markUnEqual();
210
}
211
} else if ( isSRPNull(srpKey) || !isRangeValidForUTF8Ptr(utf8) ) {
212
markUnEqual();
213
} else {
214
U_16 cpIndex = _srpKeyProducer->mapKeyToCfrConstantPoolIndex(srpKey);
215
216
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
217
/**
218
* cpIndex greater than or equal than the cpCount are injected interfaces, which should not be written into
219
* the classfile bytes
220
*/
221
if ( cpIndex >= _classFileOracle->getConstantPoolCount() ) {
222
break;
223
}
224
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
225
226
if ( J9UTF8_LENGTH(utf8) != _classFileOracle->getUTF8Length(cpIndex) ) {
227
markUnEqual();
228
} else if (0 != memcmp(J9UTF8_DATA(utf8), _classFileOracle->getUTF8Data(cpIndex), J9UTF8_LENGTH(utf8))) {
229
markUnEqual();
230
}
231
}
232
break;
233
}
234
case Cursor::SRP_TO_NAME_AND_SIGNATURE: {
235
J9ROMNameAndSignature *nas = SRP_PTR_GET(currentAddr, J9ROMNameAndSignature *);
236
237
if ( NULL == nas ) {
238
if (!isSRPNull(srpKey)) {
239
markUnEqual();
240
}
241
} else if ( isRangeValidForPtr((U_8*)nas, sizeof(J9ROMNameAndSignature)) ) {
242
J9UTF8 *name = SRP_GET(nas->name, J9UTF8 *);
243
J9UTF8 *signature = SRP_GET(nas->signature, J9UTF8 *);
244
245
if ( isSRPNull(srpKey) || !isRangeValidForUTF8Ptr(name) || !isRangeValidForUTF8Ptr(signature) ) {
246
markUnEqual();
247
} else {
248
U_16 cpIndex = _srpKeyProducer->mapKeyToCfrConstantPoolIndex(srpKey);
249
250
if ( (J9UTF8_LENGTH(name) != _classFileOracle->getNameAndSignatureNameUTF8Length(cpIndex)) ||
251
(J9UTF8_LENGTH(signature) != _classFileOracle->getNameAndSignatureSignatureUTF8Length(cpIndex))
252
) {
253
markUnEqual();
254
} else if ( (0 != memcmp(J9UTF8_DATA(name), _classFileOracle->getNameAndSignatureNameUTF8Data(cpIndex), J9UTF8_LENGTH(name))) ||
255
(0 != memcmp(J9UTF8_DATA(signature), _classFileOracle->getNameAndSignatureSignatureUTF8Data(cpIndex), J9UTF8_LENGTH(signature)))
256
) {
257
markUnEqual();
258
}
259
}
260
} else {
261
markUnEqual();
262
}
263
break;
264
}
265
default:
266
Trc_BCU_Assert_ShouldNeverHappen();
267
break;
268
}
269
} else {
270
/* Invalid range. */
271
markUnEqual();
272
}
273
}
274
countingcursor->writeSRP(srpKey, dataType);
275
}
276
277
void
278
ComparingCursor::writeWSRP(UDATA srpKey, DataType dataType)
279
{
280
Cursor * countingcursor = getCountingCursor(dataType);
281
if ( shouldCheckForEquality(dataType) ) {
282
if ( isRangeValid(sizeof(J9WSRP), dataType) ) {
283
switch (dataType) {
284
case Cursor::SRP_TO_GENERIC: /* fall through */
285
case Cursor::SRP_TO_INTERMEDIATE_CLASS_DATA:
286
/* ignore this type */
287
break;
288
default:
289
Trc_BCU_Assert_ShouldNeverHappen();
290
break;
291
}
292
} else {
293
markUnEqual();
294
}
295
}
296
countingcursor->writeWSRP(srpKey, dataType);
297
}
298
299
void
300
ComparingCursor::writeData(U_8* bytes, UDATA length, DataType dataType)
301
{
302
ComparingCursorHelper * countingcursor = getCountingCursor(dataType);
303
U_8 * baseAddress = countingcursor->getBaseAddress();
304
U_8 * currentAddr = baseAddress + countingcursor->getCount();
305
if ( shouldCheckForEquality(dataType) ) {
306
if ( isRangeValid(length, dataType) ) {
307
switch ( dataType ) {
308
case Cursor::INTERMEDIATE_CLASS_DATA: {
309
J9ROMClass *romClass = (J9ROMClass *)baseAddress;
310
if (length != (UDATA)romClass->intermediateClassDataLength) {
311
markUnEqual();
312
} else {
313
U_8* intermediates = J9ROMCLASS_INTERMEDIATECLASSDATA(romClass);
314
if ( 0 != memcmp(bytes, intermediates, length) ) {
315
markUnEqual();
316
}
317
}
318
break;
319
}
320
case Cursor::BYTECODE: {
321
U_8 *code = bytes;
322
U_8 *romClassCode = currentAddr;
323
UDATA codeIndex = 0;
324
325
/*
326
* An exception must be made for JBgenericReturn bytecodes to allow comparison
327
* against ROMClasses that have been added to the shared cache. Such ROMClasses
328
* will have had their return bytecodes "fixed" with fixReturnBytecodes, so any
329
* of the equivalent return bytecodes is allowed to match an attempt to write a
330
* JBgenericReturn.
331
*/
332
333
while (codeIndex < length) {
334
UDATA startCodeIndex = codeIndex;
335
U_8 instruction = code[codeIndex];
336
U_8 romInstruction = romClassCode[codeIndex];
337
338
/* Check if the bytecode matches with a special case for JBgenericReturn. */
339
if (instruction != romInstruction) {
340
if ((JBgenericReturn != instruction) ||
341
(RTV_RETURN != (J9JavaBytecodeVerificationTable[romInstruction] >> 8))
342
) {
343
markUnEqual();
344
break;
345
}
346
}
347
348
if (JBtableswitch == instruction) {
349
codeIndex += 4 - (codeIndex & 3); /* step past instruction + pad */
350
codeIndex += sizeof(I_32); /* default offset */
351
I_32 low = *(I_32 *)&code[codeIndex];
352
codeIndex += sizeof(I_32);
353
I_32 high = *(I_32 *)&code[codeIndex];
354
codeIndex += sizeof(I_32);
355
I_32 noffsets = high - low + 1;
356
codeIndex += noffsets * sizeof(I_32);
357
} else if (JBlookupswitch == instruction) {
358
codeIndex += 4 - (codeIndex & 3); /* step past instruction + pad */
359
codeIndex += sizeof(I_32); /* default offset */
360
I_32 npairs = *(I_32 *)&code[codeIndex];
361
codeIndex += sizeof(I_32);
362
codeIndex += npairs * 2 * sizeof(I_32);
363
} else {
364
UDATA step = (J9JavaInstructionSizeAndBranchActionTable[instruction] & 0x0f);
365
if (0 == step) {
366
/* Bad bytecodes? */
367
markUnEqual();
368
break;
369
}
370
371
codeIndex += step;
372
}
373
374
if (codeIndex > length) {
375
/* Stepped out of range? */
376
markUnEqual();
377
break;
378
}
379
380
/* Check if the instruction payload matches. */
381
UDATA payloadLength = codeIndex - startCodeIndex - 1;
382
if ( (0 != payloadLength) &&
383
(0 != memcmp(code + startCodeIndex + 1, romClassCode + startCodeIndex + 1, payloadLength))
384
) {
385
markUnEqual();
386
break;
387
}
388
}
389
break;
390
}
391
case SRP_TO_INTERMEDIATE_CLASS_DATA:
392
/* ignore this type */
393
break;
394
default:
395
if ( 0 != memcmp(bytes, currentAddr, length) ) {
396
markUnEqual();
397
}
398
break;
399
}
400
}
401
} else {
402
if (dataType == LINE_NUMBER_DATA) {
403
/* If we are here then the line number data needs to be skipped over,
404
* in this case we use the length for the existing rom class.
405
*
406
* The bytes argument is ignored in the call to Cursor::writeData below.
407
*/
408
length = _context->romMethodCompressedLineNumbersLength();
409
}
410
}
411
countingcursor->writeData(bytes, length, dataType);
412
}
413
414
void
415
ComparingCursor::padToAlignment(UDATA byteAlignment, DataType dataType)
416
{
417
Cursor * countingcursor = getCountingCursor(dataType);
418
if ( shouldCheckForEquality(dataType) ) {
419
// TODO
420
}
421
countingcursor->padToAlignment(byteAlignment, dataType);
422
}
423
424
bool
425
ComparingCursor::shouldCheckForEquality(DataType dataType, U_32 u32Value)
426
{
427
if ( !isEqual() ) {
428
return false;
429
}
430
431
switch (dataType) {
432
case SRP_TO_UTF8_CLASS_NAME:
433
if (isComparingLambdaFromSCC()) {
434
/* if the class is a lambda class don't compare the class names because lambda classes might have different index numbers from run to run */
435
return false;
436
}
437
break;
438
case BYTECODE: /* fall through */
439
case GENERIC: /* fall through */
440
case CLASS_FILE_SIZE: /* fall through */
441
if ((CLASS_FILE_SIZE == dataType)
442
&& isComparingLambdaFromSCC()
443
) {
444
/* If comparing a lambda class from the shared cache, class file size comparison is already done in ROMClassBuilder::compareROMClassForEquality(). */
445
return false;
446
}
447
case SRP_TO_DEBUG_DATA: /* fall through */
448
case SRP_TO_GENERIC: /* fall through */
449
case SRP_TO_UTF8: /* fall through */
450
case SRP_TO_NAME_AND_SIGNATURE: /* fall through */
451
case SRP_TO_INTERMEDIATE_CLASS_DATA:
452
/* do nothing -- return true at bottom of function */
453
break;
454
case METHOD_DEBUG_SIZE: /* fall through */
455
case ROM_SIZE: /* fall through */
456
case INTERMEDIATE_CLASS_DATA: /* fall through */
457
case INTERMEDIATE_CLASS_DATA_LENGTH:
458
return false;
459
case ROM_CLASS_MODIFIERS:
460
if (u32Value == (u32Value & _context->romMethodModifiers())) {
461
/*It's ok if the existing rom class has extra debug information and it is not required*/
462
return false;
463
}
464
break;
465
case OPTIONAL_FLAGS:
466
if (u32Value == (u32Value & _context->romClassOptionalFlags())) {
467
/*During compare it is ok if an existing class has more information*/
468
return false;
469
}
470
break;
471
case SRP_TO_SOURCE_DEBUG_EXT: /* fall through */
472
case SOURCE_DEBUG_EXT_LENGTH: /* fall through */
473
case SOURCE_DEBUG_EXT_DATA:
474
if (_context->romClassHasSourceDebugExtension() && !(_classFileOracle->hasSourceDebugExtension() && _context->shouldPreserveSourceDebugExtension())) {
475
/* If the existing rom class contains a source debug extension,
476
* and it is not required by the new class then skip the comparison.
477
*/
478
return false;
479
}
480
break;
481
case OPTINFO_SOURCE_FILE_NAME:
482
if (_context->romClassHasSourceFileName() && !(_classFileOracle->hasSourceFile() && _context->shouldPreserveSourceFileName())) {
483
/* If the existing rom class contains a source filename and isn't needed, then skip the comparison.
484
*/
485
return false;
486
}
487
break;
488
case SRP_TO_LOCAL_VARIABLE_DATA:
489
/* fall through
490
*
491
* The SRP_TO_LOCAL_VARIABLE_DATA is stored in the header of the method debug data.
492
*
493
* If there is no LINE_NUMBER_DATA to be preserved, then the header is also skipped
494
* and this value is not needed.
495
*/
496
case LINE_NUMBER_DATA:
497
if (!(_context->shouldPreserveLineNumbers()) && _context->romMethodHasDebugData()) {
498
/* If line number information doesn't need to be preserved, and there is
499
* existing data then skip the comparison.
500
*/
501
return false;
502
}
503
break;
504
case LOCAL_VARIABLE_COUNT: /* fall through */
505
case LOCAL_VARIABLE_DATA_SRP_TO_UTF8: /* fall through */
506
case LOCAL_VARIABLE_DATA:
507
if (!(_context->shouldPreserveLocalVariablesInfo()) && _context->romMethodHasDebugData()) {
508
/* If variable information doesn't need to be preserved, and there is
509
* existing data then skip the comparison.
510
*/
511
return false;
512
}
513
break;
514
default:
515
Trc_BCU_Assert_ShouldNeverHappen();
516
break;
517
}
518
519
return true;
520
}
521
522
bool
523
ComparingCursor::isRangeValid(UDATA length, DataType dataType)
524
{
525
ComparingCursorHelper * countingcursor = getCountingCursor(dataType);
526
527
if (countingcursor != &(_mainHelper)) {
528
if (_checkRangeInSharedCache) {
529
return j9shr_Query_IsAddressInCache(_javaVM, countingcursor->getBaseAddress() + countingcursor->getCount(), length) ? true : false;
530
}
531
return true;
532
} else {
533
J9ROMClass * rc = (J9ROMClass *)countingcursor->getBaseAddress();
534
return (countingcursor->getCount() + length) <= rc->romSize;
535
}
536
}
537
538
bool
539
ComparingCursor::isRangeValidForPtr(U_8 *ptr, UDATA length)
540
{
541
if (_checkRangeInSharedCache) {
542
return (j9shr_Query_IsAddressInCache(_javaVM, ptr, length) ? true : false);
543
} else {
544
return length < getMaximumValidLengthForPtrInSegment(ptr);
545
}
546
}
547
548
bool
549
ComparingCursor::isRangeValidForUTF8Ptr(J9UTF8 *utf8)
550
{
551
U_8 *ptr = (U_8*)utf8;
552
/*
553
* Need to check the UTF8 to verify that it is either in a J9MemorySegment or in the
554
* SCC.
555
*/
556
if (_checkRangeInSharedCache) {
557
/* Need to check if the header (length field) is in range first, before reading the length
558
* to determine if the rest of the data is in range. Failure to do so results in potentially
559
* dereferencing inaccessible memory.
560
*/
561
return j9shr_Query_IsAddressInCache(_javaVM, utf8, sizeof(J9UTF8))
562
&& j9shr_Query_IsAddressInCache(_javaVM, utf8, J9UTF8_TOTAL_SIZE(utf8));
563
} else {
564
UDATA maxLength = getMaximumValidLengthForPtrInSegment(ptr);
565
566
return J9UTF8_TOTAL_SIZE(utf8) < maxLength;
567
}
568
}
569
570
UDATA
571
ComparingCursor::getMaximumValidLengthForPtrInSegment(U_8 *ptr)
572
{
573
Trc_BCU_Assert_False(_checkRangeInSharedCache);
574
575
if (NULL != _javaVM) {
576
/* There is an AVL tree of class memory segments, use it to efficiently find a potential segment that
577
* could contain the pointer value. */
578
J9MemorySegment *segment = (J9MemorySegment *) avl_search(&(_javaVM->classMemorySegments->avlTreeData), UDATA(ptr));
579
if ( (NULL != segment) && (ptr >= segment->heapBase) && (ptr < segment->heapTop) ) {
580
return UDATA(segment->heapTop) - UDATA(ptr);
581
}
582
583
return 0;
584
}
585
586
/* If _checkRangeInSharedCache is false and _javaVM is NULL, don't validate address ranges. */
587
return UDATA_MAX;
588
}
589
590
void
591
ComparingCursor::notifyDebugDataWriteStart() {
592
/*Inform the context that _romClass should be used to determine if debug data is inline or out of line*/
593
_context->startDebugCompare();
594
/* This method notifies the cursor that writes to the method debug data is about to occur.
595
* The notification occurs just before deciding to write the SRP to debug area
596
*/
597
if (!_context->romMethodDebugDataIsInline()) {
598
/* If the debug data is out of line, then call resetBaseMemoryLocation to
599
* point the compare helpers to the correct memory.
600
*
601
* Calling resetBaseMemoryLocation will also set _count on the helpers
602
* to zero since they are indexing a different memory offset.
603
*/
604
U_8 * lineNumberStartAddr = (U_8 *) _context->romMethodLineNumbersDataStart();
605
U_8 * varTableStartAddr = (U_8 *) _context->romMethodVariableDataStart();
606
_lineNumberHelper.resetBaseMemoryLocation(lineNumberStartAddr);
607
_varInfoHelper.resetBaseMemoryLocation(varTableStartAddr);
608
}
609
}
610
611
void
612
ComparingCursor::notifyVariableTableWriteEnd() {
613
if (_context->shouldWriteDebugDataInline() && !(_context->shouldPreserveLocalVariablesInfo())) {
614
/* This method is required to skip over inline variable table data in an existing rom class during compare.
615
* This is only done if the variable table is not required by the new class, and it is inline.
616
*/
617
J9MethodDebugInfo * debugDataStart = (J9MethodDebugInfo *) _context->romMethodLineNumbersDataStart();
618
void * variableTableStart = _context->romMethodVariableDataStart();
619
if (NULL != variableTableStart) {
620
/*Note: if variableTableStart is null then the variable count is 0 for the existing method*/
621
U_32 existingClassDebugInfoSize = (debugDataStart->srpToVarInfo & ~0x1);
622
U_32 sizeWithoutVariableTable = (U_32)((UDATA)variableTableStart - (UDATA)debugDataStart);
623
U_32 inlineVarInfoToSkip = (existingClassDebugInfoSize - sizeWithoutVariableTable);
624
/*The debug data is inline so increment the count of _mainHelper*/
625
_mainHelper.skip(inlineVarInfoToSkip);
626
}
627
}
628
}
629
630
ComparingCursorHelper *
631
ComparingCursor::getCountingCursor(DataType dataType) {
632
switch (dataType) {
633
case LOCAL_VARIABLE_COUNT:
634
case SRP_TO_LOCAL_VARIABLE_DATA:
635
case LINE_NUMBER_DATA:
636
if (!(_context->shouldWriteDebugDataInline())) {
637
return &_lineNumberHelper;
638
639
}
640
/*If the debug data is inline return _mainHelper*/
641
break;
642
case LOCAL_VARIABLE_DATA_SRP_TO_UTF8:
643
case LOCAL_VARIABLE_DATA:
644
if (!(_context->shouldWriteDebugDataInline())) {
645
return &_varInfoHelper;
646
}
647
/*If the debug data is inline return _mainHelper*/
648
break;
649
default:
650
break;
651
}
652
return &_mainHelper;
653
}
654
655