#include "bcvcfr.h"
#include "j9bcvnls.h"
#include "cfrerrnls.h"
#include "cfreader.h"
#include "bcnames.h"
#include "pcstack.h"
#include "j9protos.h"
#include "j9consts.h"
#include "omrthread.h"
#include "jvminit.h"
#include "vrfyconvert.h"
#include "bcverify.h"
#include "bcverify_internal.h"
#include "vrfytbl.h"
#include "j9cp.h"
#include "ut_j9bcverify.h"
static IDATA verifyBytecodes (J9BytecodeVerificationData * verifyData);
static IDATA matchStack (J9BytecodeVerificationData * verifyData, J9BranchTargetStack *liveStack, J9BranchTargetStack * targetStack, UDATA inlineMatch);
static IDATA findAndMatchStack (J9BytecodeVerificationData *verifyData, IDATA targetPC, IDATA currentPC);
static IDATA verifyExceptions (J9BytecodeVerificationData *verifyData);
static J9BranchTargetStack * nextStack (J9BytecodeVerificationData *verifyData, UDATA *nextMapIndex, IDATA *nextStackPC);
static IDATA nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMethod, IDATA lastPC);
static void storeArgumentErrorData (J9BytecodeVerificationData * verifyData, U_32 errorCurrentFramePosition, U_16 errorArgumentIndex);
static void storeMethodInfo (J9BytecodeVerificationData * verifyData, J9UTF8* errorClassString, J9UTF8* errorMethodString, J9UTF8* errorSignatureString, IDATA currentPC);
J9Class *
j9rtv_verifierGetRAMClass( J9BytecodeVerificationData *verifyData, J9ClassLoader* classLoader, U_8 *className, UDATA nameLength, IDATA *reasonCode)
{
J9Class *found = NULL;
JavaVM* jniVM = (JavaVM*)verifyData->javaVM;
J9ThreadEnv* threadEnv = NULL;
J9JavaVM *vm = verifyData->vmStruct->javaVM;
(*jniVM)->GetEnv(jniVM, (void**)&threadEnv, J9THREAD_VERSION_1_1);
#ifdef J9VM_THR_PREEMPTIVE
threadEnv->monitor_enter(vm->classTableMutex);
#endif
Trc_RTV_j9rtv_verifierGetRAMClass_Entry(verifyData->vmStruct, classLoader, nameLength, className);
found = vm->internalVMFunctions->hashClassTableAt (classLoader, className, nameLength);
#ifdef J9VM_THR_PREEMPTIVE
threadEnv->monitor_exit(vm->classTableMutex);
#endif
if (!found) {
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_CLASS_RELATIONSHIP_VERIFIER) && (verifyData->romClass->majorVersion >= 51)) {
*reasonCode = BCV_ERR_CLASS_RELATIONSHIP_RECORD_REQUIRED;
return NULL;
} else {
J9BytecodeVerificationData savedVerifyData;
UDATA *currentAlloc;
UDATA *internalBufferStart;
UDATA *internalBufferEnd;
J9VMThread *tmpVMC = verifyData->vmStruct;
Trc_RTV_j9rtv_verifierGetRAMClass_notFound(verifyData->vmStruct);
memcpy(&savedVerifyData, verifyData, sizeof(savedVerifyData));
verifyData->vmStruct = NULL;
if (BCV_ERR_INSUFFICIENT_MEMORY == allocateVerifyBuffers (tmpVMC->javaVM->portLibrary, verifyData)) {
Trc_RTV_j9rtv_verifierGetRAMClass_OutOfMemoryException(verifyData->vmStruct, classLoader, nameLength, className);
*reasonCode = BCV_ERR_INSUFFICIENT_MEMORY;
return NULL;
}
#ifdef J9VM_THR_PREEMPTIVE
threadEnv->monitor_exit(verifyData->verifierMutex);
#endif
found = tmpVMC->javaVM->internalVMFunctions->internalFindClassUTF8(
tmpVMC,
className,
nameLength,
classLoader,
J9_FINDCLASS_FLAG_THROW_ON_FAIL);
if (NULL == found) {
*reasonCode = BCV_ERR_INACCESSIBLE_CLASS;
}
#ifdef J9VM_THR_PREEMPTIVE
threadEnv->monitor_enter(verifyData->verifierMutex);
#endif
freeVerifyBuffers (tmpVMC->javaVM->portLibrary, verifyData);
currentAlloc = verifyData->currentAlloc;
internalBufferStart = verifyData->internalBufferStart;
internalBufferEnd = verifyData->internalBufferEnd;
memcpy(verifyData, &savedVerifyData, sizeof(savedVerifyData));
verifyData->currentAlloc = currentAlloc;
verifyData->internalBufferStart = internalBufferStart;
verifyData->internalBufferEnd = internalBufferEnd;
}
} else {
Trc_RTV_j9rtv_verifierGetRAMClass_found(verifyData->vmStruct);
}
Trc_RTV_j9rtv_verifierGetRAMClass_Exit(verifyData->vmStruct);
return found;
}
IDATA
j9rtv_verifyBytecodes (J9BytecodeVerificationData *verifyData)
{
J9ROMClass *romClass = verifyData->romClass;
J9ROMMethod *romMethod = verifyData->romMethod;
UDATA oldState = verifyData->vmStruct->omrVMThread->vmState;
IDATA result = BCV_SUCCESS;
verifyData->vmStruct->omrVMThread->vmState = J9VMSTATE_RTVERIFY;
Trc_RTV_j9rtv_verifyBytecodes_Entry(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass)));
if (romMethod->modifiers & CFR_ACC_HAS_EXCEPTION_INFO) {
result = verifyExceptions (verifyData);
}
if (BCV_SUCCESS == result) {
result = verifyBytecodes (verifyData);
}
if (BCV_SUCCESS != result) {
if (BCV_ERR_INSUFFICIENT_MEMORY == result) {
Trc_RTV_j9rtv_verifyBytecodes_OutOfMemoryException(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass)));
verifyData->errorModule = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__MODULE;
verifyData->errorCode = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
} else {
verifyData->errorModule = J9NLS_BCV_ERR_NOT_THROWABLE__MODULE;
verifyData->errorCode = J9NLS_BCV_ERR_NOT_THROWABLE__ID;
}
Trc_RTV_j9rtv_verifyBytecodes_VerifyError(verifyData->vmStruct, verifyData->errorCode, verifyData->errorPC);
}
verifyData->vmStruct->omrVMThread->vmState = oldState;
Trc_RTV_j9rtv_verifyBytecodes_Exit(verifyData->vmStruct);
return result;
}
static IDATA
findAndMatchStack (J9BytecodeVerificationData *verifyData, IDATA targetPC, IDATA currentPC)
{
U_32 *bytecodeMap = verifyData->bytecodeMap;
J9BranchTargetStack *liveStack = (J9BranchTargetStack *) verifyData->liveStack;
J9BranchTargetStack *targetStack;
UDATA stackIndex;
IDATA rc = BCV_SUCCESS;
Trc_RTV_findAndMatchStack_Entry(verifyData->vmStruct, currentPC, targetPC);
if (bytecodeMap[targetPC] & BRANCH_TARGET) {
stackIndex = bytecodeMap[targetPC] >> BRANCH_INDEX_SHIFT;
targetStack = BCV_INDEX_STACK (stackIndex);
if (targetPC < currentPC) {
if (TRUE == liveStack->uninitializedThis) {
if (TRUE != targetStack->uninitializedThis) {
rc = BCV_FAIL;
goto exit;
}
}
}
rc = matchStack (verifyData, liveStack, targetStack, FALSE);
} else {
Trc_RTV_findAndMatchStack_StackNotFound(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
targetPC);
rc = BCV_FAIL;
verifyData->errorDetailCode = BCV_ERR_EXPECT_STACKMAP_FRAME;
verifyData->errorTempData = targetPC;
}
exit:
if (verifyData->errorDetailCode < 0) {
liveStack->pc = (UDATA)currentPC;
}
Trc_RTV_findAndMatchStack_Exit(verifyData->vmStruct, rc);
return rc;
}
static IDATA
matchStack(J9BytecodeVerificationData * verifyData, J9BranchTargetStack *liveStack, J9BranchTargetStack * targetStack, UDATA inlineMatch)
{
UDATA *livePtr = liveStack->stackElements;
UDATA *liveTop = RELOAD_STACKTOP(liveStack);
UDATA *targetPtr = targetStack->stackElements;
UDATA *targetTop = RELOAD_STACKTOP(targetStack);
UDATA size = liveStack->stackTopIndex;
IDATA rc = BCV_SUCCESS;
IDATA reasonCode = 0;
Trc_RTV_matchStack_Entry(verifyData->vmStruct, inlineMatch);
if (size != (UDATA) targetStack->stackTopIndex) {
Trc_RTV_matchStack_DepthMismatchException(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
size, targetStack->stackTopIndex);
rc = BCV_FAIL;
verifyData->errorDetailCode = BCV_ERR_STACK_SIZE_MISMATCH;
livePtr = (size > 0) ? (liveTop - 1) : liveTop;
goto _errorLocation;
}
if (liveStack->uninitializedThis && !targetStack->uninitializedThis) {
rc = BCV_FAIL;
goto _finished;
}
while (livePtr != liveTop) {
if (*livePtr != *targetPtr) {
if ((*targetPtr & BCV_BASE_OR_SPECIAL) == 0) {
rc = isClassCompatible (verifyData, *livePtr, *targetPtr, &reasonCode);
if (FALSE == rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
Trc_RTV_matchStack_OutOfMemoryException(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
rc = BCV_ERR_INSUFFICIENT_MEMORY;
goto _finished;
} else {
Trc_RTV_matchStack_IncompatibleClassException(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
(livePtr - liveStack->stackElements), *livePtr, *targetPtr);
rc = BCV_FAIL;
goto _incompatibleType;
}
}
} else if (*targetPtr != BCV_BASE_TYPE_TOP) {
if ((*targetPtr & BCV_SPECIAL_INIT) && verifyData->createdStackMap) {
} else {
Trc_RTV_matchStack_PrimitiveOrSpecialMismatchException(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
(livePtr - liveStack->stackElements), *livePtr, *targetPtr);
rc = BCV_FAIL;
goto _incompatibleType;
}
}
}
livePtr++;
targetPtr++;
}
if (inlineMatch) {
Trc_RTV_matchStack_InlineMatchEvent(verifyData->vmStruct);
livePtr = liveStack->stackElements;
targetPtr = targetStack->stackElements;
memcpy (livePtr, targetPtr, size * sizeof(UDATA));
if (((UDATA)TRUE == liveStack->uninitializedThis) || ((UDATA)TRUE == targetStack->uninitializedThis)) {
liveStack->uninitializedThis = targetStack->uninitializedThis = TRUE;
}
}
rc = BCV_SUCCESS;
_finished:
Trc_RTV_matchStack_Exit(verifyData->vmStruct, rc);
return rc;
_incompatibleType:
verifyData->errorDetailCode = BCV_ERR_FRAMES_INCOMPATIBLE_TYPE;
verifyData->errorTargetType = *targetPtr;
_errorLocation:
verifyData->errorCurrentFramePosition = (U_32)(livePtr - liveStack->stackElements);
verifyData->errorTargetFrameIndex = (U_32)BCV_STACK_INDEX(targetStack);
goto _finished;
}
static IDATA
verifyBytecodes (J9BytecodeVerificationData * verifyData)
{
#define CHECK_END \
if (pc > length) { \
errorType = J9NLS_BCV_ERR_UNEXPECTED_EOF__ID; \
verboseErrorCode = BCV_ERR_UNEXPECTED_EOF; \
index = (UDATA)-1; \
goto _miscError; \
}
J9ROMClass * romClass = verifyData->romClass;
J9ROMMethod * romMethod = verifyData->romMethod;
J9BranchTargetStack *liveStack;
J9BranchTargetStack *currentMapData = NULL;
UDATA nextMapIndex = 0;
IDATA start = 0;
UDATA pc, length, index;
J9ROMConstantPoolItem *constantPool;
J9ROMConstantPoolItem *info;
J9ROMStringRef *classRef;
J9UTF8 *utf8string;
U_8 *code, *temp, *bcIndex;
UDATA returnChar;
UDATA bc = 0;
UDATA i;
UDATA inconsistentStack = FALSE;
UDATA inconsistentStack2 = FALSE;
UDATA type, type1, type2, arrayType, temp1, temp2, temp3, popCount, receiver, cpIndex;
UDATA action = RTV_NOP;
UDATA *stackBase, *stackTop, *temps;
UDATA *ptr;
IDATA target;
IDATA i1, i2;
U_8 *className;
UDATA classIndex, maxStack;
UDATA wideIndex = FALSE;
IDATA nextStackPC;
IDATA nextExceptionStartPC;
IDATA rc = 0;
U_8 returnBytecode;
UDATA errorModule = J9NLS_BCV_ERR_BYTECODES_INVALID__MODULE;
U_16 errorType;
I_16 offset16;
I_32 offset32;
UDATA argCount;
UDATA checkIfInsideException = romMethod->modifiers & J9AccMethodHasExceptionInfo;
UDATA tempStoreChange;
J9ExceptionInfo *exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
J9ExceptionHandler *handler;
J9UTF8 *catchName;
UDATA catchClass;
J9SRP *callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(romClass);
UDATA* originalStackTop;
UDATA originalStackZeroEntry;
BOOLEAN isInitMethod;
IDATA verboseErrorCode = 0;
UDATA errorTargetType = (UDATA)-1;
UDATA errorStackIndex = (UDATA)-1;
UDATA errorTempData = (UDATA)-1;
BOOLEAN isNextStack = FALSE;
Trc_RTV_verifyBytecodes_Entry(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)));
pc = 0;
liveStack = (J9BranchTargetStack *) verifyData->liveStack;
stackTop = &(liveStack->stackElements[0]);
isInitMethod = liveStack->uninitializedThis = buildStackFromMethodSignature (verifyData, &stackTop, &argCount);
code = J9_BYTECODE_START_FROM_ROM_METHOD(romMethod);
length = (UDATA) J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
maxStack = J9_MAX_STACK_FROM_ROM_METHOD(romMethod);
if (argCount != romMethod->argCount) {
errorType = J9NLS_BCV_ERR_ARGUMENTS_INCOMPATIBLE__ID;
verboseErrorCode = BCV_ERR_ARGUMENTS_MISMATCH;
errorTempData = argCount;
goto _miscError;
}
SAVE_STACKTOP(liveStack, stackTop);
liveStack->stackBaseIndex = liveStack->stackTopIndex;
liveStack->stackElements[liveStack->stackBaseIndex] = BCV_BASE_TYPE_TOP;
RELOAD_LIVESTACK;
returnBytecode = getReturnBytecode (romClass, romMethod, &temp1);
bcIndex = code;
constantPool = J9_ROM_CP_FROM_ROM_CLASS(romClass);
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
nextExceptionStartPC = nextExceptionStart (verifyData, romMethod, -1);
while (pc < length) {
if (inconsistentStack) {
_inconsistentStack:
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
_inconsistentStack2:
storeVerifyErrorData(verifyData, BCV_ERR_INCOMPATIBLE_TYPE, (U_32)errorStackIndex, errorTargetType, errorTempData, start);
goto _verifyError;
}
if ((UDATA) (stackTop - stackBase) > maxStack) {
errorType = J9NLS_BCV_ERR_STACK_OVERFLOW__ID;
verboseErrorCode = BCV_ERR_STACK_OVERFLOW;
errorStackIndex = stackBase - liveStack->stackElements;
if (maxStack > 0) {
errorStackIndex += maxStack - 1;
}
goto _miscError;
}
if (pc == (UDATA) nextStackPC) {
SAVE_STACKTOP(liveStack, stackTop);
rc = matchStack (verifyData, liveStack, currentMapData, TRUE);
if (BCV_SUCCESS != rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
liveStack->pc = pc;
goto _mapError;
}
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
}
if (pc == (UDATA) nextExceptionStartPC) {
handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
SAVE_STACKTOP(liveStack, stackTop);
originalStackTop = stackTop;
originalStackZeroEntry = liveStack->stackElements[liveStack->stackBaseIndex];
for (i = exceptionInfo->catchCount; i; i--, handler++) {
if (handler->startPC == pc) {
if (handler->exceptionClassIndex) {
catchName = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)(&constantPool [handler->exceptionClassIndex]));
catchClass = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(catchName), J9UTF8_LENGTH(catchName), 0, 0);
} else {
catchClass = BCV_JAVA_LANG_THROWABLE_INDEX;
catchClass <<= BCV_CLASS_INDEX_SHIFT;
}
stackTop = &(liveStack->stackElements[liveStack->stackBaseIndex]);
PUSH(catchClass);
SAVE_STACKTOP(liveStack, stackTop);
rc = findAndMatchStack (verifyData, handler->handlerPC, start);
if (BCV_SUCCESS != rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
goto _mapError;
}
}
}
liveStack->stackElements[liveStack->stackBaseIndex] = originalStackZeroEntry;
stackTop = originalStackTop;
nextExceptionStartPC = nextExceptionStart (verifyData, romMethod, nextExceptionStartPC);
}
bcIndex = code + pc;
bc = *bcIndex;
start = pc;
pc += (J9JavaInstructionSizeAndBranchActionTable[bc] & 7);
CHECK_END;
if ((stackTop - (JavaStackActionTable[bc] & 7)) < stackBase) {
errorType = J9NLS_BCV_ERR_STACK_UNDERFLOW__ID;
verboseErrorCode = BCV_ERR_STACK_UNDERFLOW;
errorStackIndex = (stackTop - liveStack->stackElements) - 1;
if ((stackTop <= stackBase) && !isNextStack) {
errorStackIndex = stackBase - liveStack->stackElements;
}
goto _miscError;
}
isNextStack = FALSE;
type1 = (UDATA) J9JavaBytecodeVerificationTable[bc];
action = type1 >> 8;
type2 = (type1 >> 4) & 0xF;
type1 = (UDATA) decodeTable[type1 & 0xF];
type2 = (UDATA) decodeTable[type2];
switch (action) {
case RTV_NOP:
break;
case RTV_WIDE_LOAD_TEMP_PUSH:
wideIndex = TRUE;
case RTV_LOAD_TEMP_PUSH:
index = type2 & 0x7;
if (type2 == 0) {
index = PARAM_8(bcIndex, 1);
if (wideIndex) {
index = PARAM_16(bcIndex, 1);
wideIndex = FALSE;
}
}
if (temps[index] != type1) {
if ((type1 != BCV_GENERIC_OBJECT) || (temps[index] & BCV_TAG_BASE_TYPE_OR_TOP)) {
inconsistentStack = TRUE;
errorTargetType = type1;
errorStackIndex = index;
goto _inconsistentStack;
}
}
if (type1 == BCV_GENERIC_OBJECT) {
PUSH(temps[index]);
break;
}
if (type1 & BCV_WIDE_TYPE_MASK) {
CHECK_TEMP((index + 1), BCV_BASE_TYPE_TOP);
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_TOP;
errorTempData = type1;
errorStackIndex = index + 1;
goto _inconsistentStack;
}
}
case RTV_PUSH_CONSTANT:
_pushConstant:
PUSH(type1);
if (type1 & BCV_WIDE_TYPE_MASK) {
PUSH(BCV_BASE_TYPE_TOP);
}
break;
case RTV_PUSH_CONSTANT_POOL_ITEM:
switch (bc) {
case JBldc:
case JBldcw:
if (bc == JBldc) {
index = PARAM_8(bcIndex, 1);
} else {
index = PARAM_16(bcIndex, 1);
}
stackTop = pushLdcType(verifyData, romClass, index, stackTop);
break;
case JBldc2lw:
PUSH_LONG_CONSTANT;
break;
case JBldc2dw:
PUSH_DOUBLE_CONSTANT;
break;
}
break;
case RTV_ARRAY_FETCH_PUSH:
POP_TOS_INTEGER;
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_INT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
arrayType = POP;
if (arrayType != BCV_BASE_TYPE_NULL) {
if (bc == JBaaload) {
inconsistentStack |= arrayType & BCV_BASE_OR_SPECIAL;
inconsistentStack |= (arrayType & BCV_ARITY_MASK) == 0;
if (inconsistentStack) {
errorTargetType = (UDATA)(BCV_GENERIC_OBJECT | (1 << BCV_ARITY_SHIFT));
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
type1 = arrayType - 0x01000000;
PUSH(type1);
break;
} else {
type = (UDATA) J9JavaBytecodeArrayTypeTable[bc - JBiaload];
CHECK_BOOL_ARRAY(JBbaload, bc, type);
if (inconsistentStack) {
errorTargetType = type;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
}
goto _pushConstant;
break;
case RTV_WIDE_POP_STORE_TEMP:
wideIndex = TRUE;
case RTV_POP_STORE_TEMP:
index = type2 & 0x7;
if (type2 == 0) {
index = PARAM_8(bcIndex, 1);
if (wideIndex) {
index = PARAM_16(bcIndex, 1);
wideIndex = FALSE;
}
}
POP_TOS_TYPE( type, type1 );
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_TOP;
errorTempData = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
goto _inconsistentStack;
}
tempStoreChange = FALSE;
if (type != type1) {
if ((type1 != BCV_GENERIC_OBJECT) || (type & BCV_TAG_BASE_TYPE_OR_TOP)) {
inconsistentStack = TRUE;
errorTargetType = type1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
if (type1 & BCV_WIDE_TYPE_MASK) {
tempStoreChange = (temps[index + 1] != BCV_BASE_TYPE_TOP);
STORE_TEMP((index + 1), BCV_BASE_TYPE_TOP);
}
tempStoreChange |= (type != temps[index]);
STORE_TEMP(index, type);
if (checkIfInsideException && tempStoreChange) {
handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
SAVE_STACKTOP(liveStack, stackTop);
originalStackTop = stackTop;
originalStackZeroEntry = liveStack->stackElements[liveStack->stackBaseIndex];
for (i = exceptionInfo->catchCount; i; i--, handler++) {
if (((UDATA) start >= handler->startPC) && ((UDATA) start < handler->endPC)) {
#ifdef DEBUG_BCV
printf("exception map change check at startPC: %d\n", handler->startPC);
#endif
if (handler->exceptionClassIndex) {
catchName = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)(&constantPool [handler->exceptionClassIndex]));
catchClass = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(catchName), J9UTF8_LENGTH(catchName), 0, 0);
} else {
catchClass = BCV_JAVA_LANG_THROWABLE_INDEX;
catchClass <<= BCV_CLASS_INDEX_SHIFT;
}
stackTop = &(liveStack->stackElements[liveStack->stackBaseIndex]);
PUSH(catchClass);
SAVE_STACKTOP(liveStack, stackTop);
rc = findAndMatchStack (verifyData, handler->handlerPC, start);
if (BCV_SUCCESS != rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
goto _mapError;
}
}
}
liveStack->stackElements[liveStack->stackBaseIndex] = originalStackZeroEntry;
stackTop = originalStackTop;
}
break;
case RTV_ARRAY_STORE:
POP_TOS_TYPE( type, type1 );
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_TOP;
errorTempData = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
goto _inconsistentStack;
}
POP_TOS_INTEGER;
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_INT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
arrayType = POP;
if (arrayType != BCV_BASE_TYPE_NULL) {
if (bc == JBaastore) {
inconsistentStack |= (arrayType | type) & BCV_BASE_OR_SPECIAL;
if (inconsistentStack) {
errorTargetType = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 2;
goto _inconsistentStack;
}
inconsistentStack |= (arrayType & BCV_ARITY_MASK) == 0;
if (inconsistentStack) {
errorTargetType = type1 | (1 << BCV_ARITY_SHIFT);
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
} else {
inconsistentStack |= (type != type1);
if (inconsistentStack) {
errorTargetType = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 2;
goto _inconsistentStack;
}
type2 = (UDATA) J9JavaBytecodeArrayTypeTable[bc - JBiastore];
CHECK_BOOL_ARRAY(JBbastore, bc, type2);
if (inconsistentStack) {
errorTargetType = type2;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
}
break;
case RTV_INCREMENT:
index = PARAM_8(bcIndex, 1);
if (bc == JBiincw) {
index = PARAM_16(bcIndex, 1);
}
CHECK_TEMP_INTEGER(index);
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_INT;
errorStackIndex = index;
goto _inconsistentStack;
}
break;
case RTV_POP_2_PUSH:
POP_TOS_TYPE_EQUAL( type, type1 );
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_TOP;
errorTempData = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
goto _inconsistentStack;
} else if (inconsistentStack2) {
errorTargetType = type1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
POP_TOS_TYPE_EQUAL( type, type1 );
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_TOP;
errorTempData = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
goto _inconsistentStack;
} else if (inconsistentStack2) {
errorTargetType = type1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
goto _pushConstant;
break;
case RTV_POP_X_PUSH_X:
if (type2) {
POP_TOS_INTEGER;
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_INT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
POP_TOS_TYPE_EQUAL( type, type1 );
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_TOP;
errorTempData = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
goto _inconsistentStack;
} else if (inconsistentStack2) {
errorTargetType = type1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
goto _pushConstant;
break;
case RTV_POP_X_PUSH_Y:
POP_TOS_TYPE_EQUAL( type, type1 );
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_TOP;
errorTempData = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
goto _inconsistentStack;
} else if (inconsistentStack2) {
errorTargetType = type1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
type1 = type2;
goto _pushConstant;
break;
case RTV_BRANCH:
popCount = type2 - 8;
for (i = 0; i < popCount; i++) {
if (type1 == BCV_GENERIC_OBJECT) {
type = POP;
if (J9_ARE_NO_BITS_SET(type, BCV_SPECIAL)) {
IDATA reasonCode = 0;
rc = isClassCompatible (verifyData, type, BCV_GENERIC_OBJECT, &reasonCode);
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
inconsistentStack |= (FALSE == rc);
if (inconsistentStack) {
errorTargetType = BCV_GENERIC_OBJECT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
} else {
POP_TOS_INTEGER;
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_INT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
}
if (bc == JBgotow) {
offset32 = (I_32) PARAM_32(bcIndex, 1);
target = start + offset32;
} else {
offset16 = (I_16) PARAM_16(bcIndex, 1);
target = start + offset16;
}
SAVE_STACKTOP(liveStack, stackTop);
rc = findAndMatchStack (verifyData, target, start);
if (BCV_SUCCESS != rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
goto _mapError;
}
if (popCount == 0) {
goto _newStack;
}
break;
case RTV_RETURN:
utf8string = J9ROMMETHOD_SIGNATURE(romMethod);
temp = &J9UTF8_DATA(utf8string)[J9UTF8_LENGTH(utf8string) - 2];
returnChar = (UDATA) temp[1];
if (temp[0] != ')') {
returnChar = 0;
className = J9UTF8_DATA(utf8string);
while (*className++ != ')');
temp1 = parseObjectOrArrayName(verifyData, className);
}
switch (bc) {
case JBreturn0:
case JBsyncReturn0:
case JBreturnFromConstructor:
inconsistentStack |= (returnChar != 'V');
if (inconsistentStack) {
_illegalPrimitiveReturn:
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_RETURN_TYPE;
goto _miscError;
}
break;
case JBreturn1:
case JBreturnB:
case JBreturnC:
case JBreturnS:
case JBreturnZ:
case JBsyncReturn1:
if (returnChar) {
U_32 returnType = 0;
if ((returnChar < 'A') || (returnChar > 'Z')) {
inconsistentStack = TRUE;
goto _illegalPrimitiveReturn;
}
type = (UDATA) oneArgTypeCharConversion[returnChar - 'A'];
POP_TOS(type);
if (BCV_BASE_TYPE_INT == type){
switch(bc) {
case JBreturnB:
returnType = BCV_BASE_TYPE_BYTE_BIT;
break;
case JBreturnC:
returnType = BCV_BASE_TYPE_CHAR_BIT;
break;
case JBreturnS:
returnType = BCV_BASE_TYPE_SHORT_BIT;
break;
case JBreturnZ:
returnType = BCV_BASE_TYPE_BOOL_BIT;
break;
case JBreturn1:
case JBsyncReturn1:
returnType = BCV_BASE_TYPE_INT_BIT;
break;
default:
Trc_RTV_j9rtv_verifyBytecodes_Unreachable(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
__LINE__);
break;
}
inconsistentStack |= returnType != baseTypeCharConversion[returnChar - 'A'];
}
if (inconsistentStack) {
errorTargetType = type;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
} else {
IDATA reasonCode = 0;
POP_TOS_OBJECT(type);
if (inconsistentStack) {
errorTargetType = BCV_GENERIC_OBJECT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
rc = isClassCompatible(verifyData, type, temp1, &reasonCode);
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
inconsistentStack |= (FALSE == rc);
if (inconsistentStack) {
errorTargetType = temp1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
break;
case JBreturn2:
case JBsyncReturn2:
if ((returnChar < 'A') || (returnChar > 'Z')) {
inconsistentStack = TRUE;
goto _illegalPrimitiveReturn;
}
type = (UDATA) argTypeCharConversion[returnChar - 'A'];
POP_TOS_2(type);
if (inconsistentStack) {
errorTargetType = type;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
break;
case JBgenericReturn:
if (returnChar) {
if ((returnChar < 'A') || (returnChar > 'Z')) {
inconsistentStack = TRUE;
goto _illegalPrimitiveReturn;
}
if (returnChar != 'V') {
type = (UDATA) argTypeCharConversion[returnChar - 'A'];
if ((returnChar == 'J') || (returnChar == 'D')) {
POP_TOS(BCV_BASE_TYPE_TOP);
if (inconsistentStack) {
errorTempData = ('J' == returnChar) ? BCV_BASE_TYPE_LONG : BCV_BASE_TYPE_DOUBLE;
errorTargetType = BCV_BASE_TYPE_TOP;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
POP_TOS(type);
if (inconsistentStack) {
errorTargetType = type;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
} else {
IDATA reasonCode = 0;
POP_TOS_OBJECT(type);
if (inconsistentStack) {
errorTargetType = BCV_GENERIC_OBJECT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
rc = isClassCompatible(verifyData, type, temp1, &reasonCode);
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
inconsistentStack |= (FALSE == rc);
if (inconsistentStack) {
errorTargetType = temp1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
if ((stackTop == stackBase)
&& ((argCount != 1) || (returnBytecode != JBreturnFromConstructor) || (J9ROMCLASS_SUPERCLASSNAME(romClass) != NULL))
&& (FALSE == verifyData->romClassInSharedClasses)
) {
*bcIndex = returnBytecode;
}
break;
}
if (isInitMethod) {
if (liveStack->uninitializedThis == (UDATA)TRUE){
errorType = J9NLS_BCV_ERR_INIT_NOT_CALL_INIT__ID;
verboseErrorCode = BCV_ERR_INIT_NOT_CALL_INIT;
errorStackIndex = (stackTop - liveStack->stackElements) - 1;
if (stackTop <= stackBase) {
errorStackIndex = stackBase - liveStack->stackElements;
}
goto _miscError;
}
}
goto _newStack;
break;
case RTV_STATIC_FIELD_ACCESS:
{
IDATA reasonCode = 0;
UDATA *receiverPtr = NULL;
index = PARAM_16(bcIndex, 1);
info = &constantPool[index];
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMFIELDREF_NAMEANDSIGNATURE((J9ROMFieldRef *) info))));
receiver = BCV_BASE_TYPE_NULL;
if ((bc & 1)
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
|| (bc == JBwithfield)
#endif
) {
type = POP;
if ((*J9UTF8_DATA(utf8string) == 'D') || (*J9UTF8_DATA(utf8string) == 'J')) {
inconsistentStack |= (type != BCV_BASE_TYPE_TOP);
if (inconsistentStack) {
errorTempData = ('J' == *J9UTF8_DATA(utf8string)) ? BCV_BASE_TYPE_LONG : BCV_BASE_TYPE_DOUBLE;
errorTargetType = BCV_BASE_TYPE_TOP;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
type = POP;
}
pushFieldType(verifyData, utf8string, stackTop);
if (*stackTop & BCV_TAG_BASE_TYPE_OR_TOP) {
inconsistentStack |= (*stackTop != type);
} else {
rc = isClassCompatible(verifyData, type, *stackTop, &reasonCode);
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
inconsistentStack |= (FALSE == rc);
}
if (inconsistentStack) {
errorTargetType = *stackTop;
errorStackIndex = stackTop - liveStack->stackElements;
PUSH(type);
goto _inconsistentStack;
}
if (bc == JBputfield) {
receiver = POP;
receiverPtr = stackTop;
}
} else {
if (bc == JBgetfield) {
receiver = POP;
receiverPtr = stackTop;
}
stackTop = pushFieldType(verifyData, utf8string, stackTop);
}
rc = isFieldAccessCompatible (verifyData, (J9ROMFieldRef *) info, bc, receiver, &reasonCode);
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
inconsistentStack |= (FALSE == rc);
if (inconsistentStack) {
constantPool = (J9ROMConstantPoolItem *) (romClass + 1);
utf8string = J9ROMCLASSREF_NAME((J9ROMClassRef *) &constantPool[((J9ROMFieldRef *) info)->classRefCPIndex]);
errorTargetType = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
if (NULL != receiverPtr) {
stackTop = receiverPtr;
}
*stackTop = receiver;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
if (receiver != BCV_BASE_TYPE_NULL) {
utf8string = J9ROMCLASSREF_NAME((J9ROMClassRef *) &constantPool[((J9ROMFieldRef *) info)->classRefCPIndex]);
rc = isProtectedAccessPermitted (verifyData, utf8string, receiver, (void *) info, TRUE, &reasonCode);
if (FALSE == rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
errorType = J9NLS_BCV_ERR_BAD_ACCESS_PROTECTED__ID;
verboseErrorCode = BCV_ERR_BAD_ACCESS_PROTECTED;
goto _miscError;
}
}
break;
}
case RTV_SEND:
if ((bc == JBinvokehandle) || (bc == JBinvokehandlegeneric)) {
IDATA reasonCode = 0;
index = PARAM_16(bcIndex, 1);
info = &constantPool[index];
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
rc = j9rtv_verifyArguments(verifyData, utf8string, &stackTop);
CHECK_STACK_UNDERFLOW;
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
inconsistentStack |= (BCV_SUCCESS != rc);
if (inconsistentStack) {
if (verifyData->errorDetailCode < 0) {
J9UTF8 * utf8ClassString = J9ROMCLASSREF_NAME((J9ROMClassRef *) &constantPool[((J9ROMMethodRef *) info)->classRefCPIndex]);
J9UTF8 * utf8MethodString = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_NAME(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
storeMethodInfo(verifyData, utf8ClassString, utf8MethodString, utf8string, start);
}
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
goto _verifyError;
}
type = POP;
rc = isClassCompatibleByName(verifyData, type, (U_8 *)"java/lang/invoke/MethodHandle", sizeof("java/lang/invoke/MethodHandle") - 1, &reasonCode);
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
if ((JBinvokehandle == bc) && (FALSE == rc)) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
rc = isClassCompatibleByName(verifyData, type, (U_8 *)"java/lang/invoke/VarHandle", sizeof("java/lang/invoke/VarHandle") - 1, &reasonCode);
}
#endif
if (FALSE == rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
errorType = J9NLS_BCV_ERR_RECEIVER_NOT_COMPATIBLE__ID;
errorTargetType = (UDATA)(BCV_JAVA_LANG_INVOKE_METHODHANDLE_INDEX << BCV_CLASS_INDEX_SHIFT);
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack2;
}
stackTop = pushReturnType(verifyData, utf8string, stackTop);
break;
}
if (bc == JBinvokedynamic) {
index = PARAM_16(bcIndex, 1);
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(SRP_PTR_GET(callSiteData + index, J9ROMNameAndSignature*))));
rc = j9rtv_verifyArguments(verifyData, utf8string, &stackTop);
CHECK_STACK_UNDERFLOW;
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
inconsistentStack |= (BCV_SUCCESS != rc);
if (inconsistentStack) {
if (verifyData->errorDetailCode < 0) {
J9UTF8 * utf8ClassString = J9ROMCLASS_CLASSNAME(romClass);
J9UTF8 * utf8MethodString = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_NAME(SRP_PTR_GET(callSiteData + index, J9ROMNameAndSignature*))));
storeMethodInfo(verifyData, utf8ClassString, utf8MethodString, utf8string, start);
}
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
goto _verifyError;
}
stackTop = pushReturnType(verifyData, utf8string, stackTop);
break;
}
if (bc == JBinvokeinterface2) {
bcIndex += 2;
bc = JBinvokeinterface;
}
index = PARAM_16(bcIndex, 1);
if (JBinvokestaticsplit == bc) {
index = *(U_16 *)(J9ROMCLASS_STATICSPLITMETHODREFINDEXES(romClass) + index);
} else if (JBinvokespecialsplit == bc) {
index = *(U_16 *)(J9ROMCLASS_SPECIALSPLITMETHODREFINDEXES(romClass) + index);
}
info = &constantPool[index];
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
cpIndex = ((J9ROMMethodRef *) info)->classRefCPIndex;
classRef = (J9ROMStringRef *) &constantPool[cpIndex];
rc = j9rtv_verifyArguments(verifyData, utf8string, &stackTop);
CHECK_STACK_UNDERFLOW;
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
inconsistentStack |= (BCV_SUCCESS != rc);
if (inconsistentStack) {
if (verifyData->errorDetailCode < 0) {
J9UTF8 * utf8ClassString = J9ROMSTRINGREF_UTF8DATA(classRef);
J9UTF8 * utf8MethodString = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_NAME(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
storeMethodInfo(verifyData, utf8ClassString, utf8MethodString, utf8string, start);
}
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
goto _verifyError;
}
if ((JBinvokestatic != bc)
&& (JBinvokestaticsplit != bc)
) {
IDATA reasonCode = 0;
type = POP;
switch (bc) {
case JBinvokespecial:
case JBinvokespecialsplit:
CHECK_STACK_UNDERFLOW;
if (J9UTF8_DATA(J9ROMNAMEANDSIGNATURE_NAME(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info)))[0] == '<') {
if ((type & BCV_SPECIAL) == 0) {
errorType = J9NLS_BCV_ERR_BAD_INIT__ID;
errorTargetType = BCV_SPECIAL_INIT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack2;
} else {
temp1 = getSpecialType(verifyData, type, code);
if (temp1 & BCV_SPECIAL_INIT) {
errorType = J9NLS_BCV_ERR_ARGUMENTS_INCOMPATIBLE__ID;
verboseErrorCode = BCV_ERR_BAD_INIT_OBJECT;
errorTempData = temp1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
if (type & BCV_SPECIAL_NEW) {
utf8string = J9ROMSTRINGREF_UTF8DATA(classRef);
classIndex = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
if (classIndex != temp1) {
errorType = J9NLS_BCV_ERR_WRONG_INIT_METHOD__ID;
errorTargetType = temp1;
*stackTop = classIndex;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack2;
}
}
if (type & BCV_SPECIAL_INIT) {
UDATA superClassIndex = 0;
utf8string = J9ROMSTRINGREF_UTF8DATA(classRef);
classIndex = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
utf8string = J9ROMCLASS_SUPERCLASSNAME(romClass);
superClassIndex = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
if ((classIndex != temp1) && (classIndex != superClassIndex)) {
errorType = J9NLS_BCV_ERR_WRONG_INIT_METHOD__ID;
errorTargetType = temp1;
*stackTop = classIndex;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack2;
}
}
ptr = temps;
while (ptr != stackTop) {
if (*ptr == type) {
*ptr = temp1;
}
ptr++;
}
if (type & BCV_SPECIAL_INIT) {
liveStack->uninitializedThis = FALSE;
}
type = temp1;
}
} else {
J9ROMNameAndSignature *nas = J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info);
J9UTF8 *name = J9ROMNAMEANDSIGNATURE_NAME(nas);
J9UTF8 *sig = J9ROMNAMEANDSIGNATURE_SIGNATURE(nas);
if (!methodIsFinalInObject(J9UTF8_LENGTH(name), J9UTF8_DATA(name), J9UTF8_LENGTH(sig), J9UTF8_DATA(sig))) {
utf8string = J9ROMCLASS_CLASSNAME(romClass);
classIndex = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
utf8string = J9ROMSTRINGREF_UTF8DATA(classRef);
if ((FALSE == isClassCompatibleByName(verifyData, classIndex, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), &reasonCode))
|| (FALSE == isClassCompatible(verifyData, type, classIndex, &reasonCode))
) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
errorType = J9NLS_BCV_ERR_BAD_INVOKESPECIAL__ID;
verboseErrorCode = BCV_ERR_BAD_INVOKESPECIAL;
goto _miscError;
}
}
}
case JBinvokevirtual:
rc = isProtectedAccessPermitted (verifyData, J9ROMSTRINGREF_UTF8DATA(classRef), type,
J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info), FALSE, &reasonCode);
if (FALSE == rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
errorType = J9NLS_BCV_ERR_BAD_ACCESS_PROTECTED__ID;
verboseErrorCode = BCV_ERR_BAD_ACCESS_PROTECTED;
goto _miscError;
}
break;
}
if (bc != JBinvokeinterface) {
utf8string = J9ROMSTRINGREF_UTF8DATA(classRef);
rc = isClassCompatibleByName (verifyData, type, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), &reasonCode);
if (FALSE == rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
errorType = J9NLS_BCV_ERR_RECEIVER_NOT_COMPATIBLE__ID;
errorTargetType = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack2;
}
} else {
if ((BCV_TAG_BASE_TYPE_OR_TOP == (type & BCV_TAG_MASK))
|| J9_ARE_ANY_BITS_SET(type, BCV_SPECIAL)
) {
errorType = J9NLS_BCV_ERR_RECEIVER_NOT_COMPATIBLE__ID;
errorTargetType = BCV_GENERIC_OBJECT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack2;
}
}
}
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
stackTop = pushReturnType(verifyData, utf8string, stackTop);
break;
case RTV_PUSH_NEW:
switch (bc) {
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
case JBaconst_init:
index = PARAM_16(bcIndex, 1);
info = &constantPool[index];
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
stackTop = pushClassType(verifyData, utf8string, stackTop);
break;
#endif
case JBnew:
case JBnewdup:
index = PARAM_16(bcIndex, 1);
info = &constantPool[index];
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
stackTop = pushClassType(verifyData, utf8string, stackTop);
type = POP;
if (J9_ARE_ANY_BITS_SET(type, BCV_ARITY_MASK)) {
errorType = J9NLS_BCV_ERR_BC_NEW_ARRAY__ID;
verboseErrorCode = BCV_ERR_NEW_OJBECT_MISMATCH;
errorTempData = ((type & BCV_ARITY_MASK) >> BCV_ARITY_SHIFT);
goto _miscError;
}
PUSH(BCV_SPECIAL_NEW | (start << BCV_CLASS_INDEX_SHIFT));
break;
case JBnewarray:
POP_TOS_INTEGER;
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_INT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
index = PARAM_8(bcIndex, 1);
type = (UDATA) newArrayParamConversion[index];
PUSH(type);
break;
case JBanewarray:
POP_TOS_INTEGER;
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_INT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
index = PARAM_16(bcIndex, 1);
info = &constantPool[index];
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
stackTop = pushClassType(verifyData, utf8string, stackTop);
type = POP;
if ((type & BCV_ARITY_MASK) == BCV_ARITY_MASK) {
errorType = J9NLS_BCV_ERR_ARRAY_TYPE_MISMATCH__ID;
verboseErrorCode = BCV_ERR_ARRAY_ARITY_OVERFLOW;
errorTempData = (type & BCV_ARITY_MASK);
goto _miscError;
}
PUSH(( (UDATA)1 << BCV_ARITY_SHIFT) + type);
break;
case JBmultianewarray:
index = PARAM_16(bcIndex, 1);
i1 = PARAM_8(bcIndex, 3);
if (i1 == 0) {
errorType = J9NLS_BCV_ERR_ARRAY_DIMENSION_MISMATCH__ID;
verboseErrorCode = BCV_ERR_ARRAY_DIMENSION_MISMATCH;
errorTempData = i1;
goto _miscError;
}
if ((stackTop - i1) < stackBase) {
errorType = J9NLS_BCV_ERR_STACK_UNDERFLOW__ID;
verboseErrorCode = BCV_ERR_STACK_UNDERFLOW;
errorStackIndex = (stackTop - liveStack->stackElements) - 1;
if (stackTop <= stackBase) {
errorStackIndex = stackBase - liveStack->stackElements;
}
goto _miscError;
}
for (i2 = 0; i2 < i1; i2++) {
POP_TOS_INTEGER;
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_INT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
}
info = &constantPool[index];
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
stackTop = pushClassType(verifyData, utf8string, stackTop);
type = POP;
if (type & BCV_TAG_BASE_ARRAY_OR_NULL) {
i1--;
}
if ((type >> BCV_ARITY_SHIFT) < (UDATA) i1) {
errorType = J9NLS_BCV_ERR_ARRAY_DIMENSION_MISMATCH__ID;
verboseErrorCode = BCV_ERR_ARRAY_DIMENSION_MISMATCH;
errorTempData = (type >> BCV_ARITY_SHIFT);
goto _miscError;
}
PUSH(type);
break;
}
break;
case RTV_MISC:
{
IDATA reasonCode = 0;
switch (bc) {
case JBathrow:
POP_TOS_OBJECT(type);
rc = isClassCompatible(verifyData, type, (UDATA) (BCV_JAVA_LANG_THROWABLE_INDEX << BCV_CLASS_INDEX_SHIFT), &reasonCode);
if (FALSE == rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
goto _outOfMemoryError;
}
errorType = J9NLS_BCV_ERR_NOT_THROWABLE__ID;
errorTargetType = (UDATA)(BCV_JAVA_LANG_THROWABLE_INDEX << BCV_CLASS_INDEX_SHIFT);
errorStackIndex = stackTop - liveStack->stackElements;
if (BCV_ERR_INTERNAL_ERROR == rc) {
goto _compatibleError;
} else {
goto _inconsistentStack2;
}
}
goto _newStack;
break;
case JBarraylength:
POP_TOS_ARRAY(type);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_INVALID_ARRAY_REFERENCE;
errorTempData = type;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
PUSH_INTEGER_CONSTANT;
break;
case JBtableswitch:
case JBlookupswitch:
POP_TOS_INTEGER;
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_INT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
index = (UDATA) ((4 - (pc & 3)) & 3);
pc += index;
bcIndex += index;
pc += 8;
CHECK_END;
offset32 = (I_32) PARAM_32(bcIndex, 1);
bcIndex += 4;
target = offset32 + start;
SAVE_STACKTOP(liveStack, stackTop);
rc = findAndMatchStack (verifyData, target, start);
if (BCV_SUCCESS != rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
goto _mapError;
}
if (bc == JBtableswitch) {
i1 = (I_32) PARAM_32(bcIndex, 1);
bcIndex += 4;
pc += 4;
i2 = (I_32) PARAM_32(bcIndex, 1);
bcIndex += 4;
pc += ((I_32)i2 - (I_32)i1 + 1) * 4;
CHECK_END;
bcIndex += (((I_32)i2 - (I_32)i1) * 4);
i2 = (I_32)i2 - (I_32)i1 + 1;
for (i1 = 0; (I_32)i1 < (I_32)i2; i1++) {
offset32 = (I_32) PARAM_32(bcIndex, 1);
bcIndex -= 4;
target = offset32 + start;
rc = findAndMatchStack (verifyData, target, start);
if (BCV_SUCCESS != rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
goto _mapError;
}
}
} else {
BOOLEAN firstKey = TRUE;
I_32 currentKey = 0;
I_32 nextKey = 0;
i2 = (I_32) PARAM_32(bcIndex, 1);
bcIndex += 4;
pc += (I_32)i2 * 8;
CHECK_END;
for (i1 = 0; (I_32)i1 < (I_32)i2; i1++) {
nextKey = (I_32) PARAM_32(bcIndex, 1);
bcIndex += 4;
if (!firstKey) {
if (nextKey <= currentKey) {
verboseErrorCode = BCV_ERR_BYTECODE_ERROR;
storeVerifyErrorData(verifyData, (I_16)verboseErrorCode, (U_32)errorStackIndex, (UDATA)-1, (UDATA)-1, start);
errorType = J9NLS_CFR_ERR_BC_SWITCH_NOT_SORTED__ID;
errorModule = J9NLS_CFR_ERR_BC_SWITCH_NOT_SORTED__MODULE;
goto _verifyError;
}
} else {
firstKey = FALSE;
}
currentKey = nextKey;
offset32 = (I_32) PARAM_32(bcIndex, 1);
bcIndex += 4;
target = offset32 + start;
rc = findAndMatchStack (verifyData, target, start);
if (BCV_SUCCESS != rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
goto _outOfMemoryError;
}
goto _mapError;
}
}
}
goto _newStack;
break;
case JBmonitorenter:
case JBmonitorexit:
POP_TOS_OBJECT_IN_MONITOR(type);
if (inconsistentStack) {
errorTargetType = BCV_GENERIC_OBJECT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
break;
case JBcheckcast:
index = PARAM_16(bcIndex, 1);
POP_TOS_OBJECT(type);
if (inconsistentStack) {
errorTargetType = BCV_GENERIC_OBJECT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
info = &constantPool[index];
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
stackTop = pushClassType(verifyData, utf8string, stackTop);
break;
case JBinstanceof:
POP_TOS_OBJECT(type);
if (inconsistentStack) {
errorTargetType = BCV_GENERIC_OBJECT;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
PUSH_INTEGER_CONSTANT;
break;
}
break;
}
case RTV_POP_2_PUSH_INT:
POP_TOS_TYPE_EQUAL( type, type1 );
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_TOP;
errorTempData = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
goto _inconsistentStack;
} else if (inconsistentStack2) {
errorTargetType = type1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
POP_TOS_TYPE_EQUAL( type, type1 );
if (inconsistentStack) {
errorTargetType = BCV_BASE_TYPE_TOP;
errorTempData = type1;
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
goto _inconsistentStack;
} else if (inconsistentStack2) {
errorTargetType = type1;
errorStackIndex = stackTop - liveStack->stackElements;
goto _inconsistentStack;
}
PUSH_INTEGER_CONSTANT;
break;
case RTV_BYTECODE_POP:
POP_TOS_SINGLE(type);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
break;
case RTV_BYTECODE_POP2:
POP_TOS_PAIR(temp1, temp2);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements + 1;
goto _miscError;
}
break;
case RTV_BYTECODE_DUP:
POP_TOS_SINGLE(type);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
PUSH(type);
PUSH(type);
break;
case RTV_BYTECODE_DUPX1:
POP_TOS_SINGLE(type);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
POP_TOS_SINGLE(temp1);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
PUSH(type);
PUSH(temp1);
PUSH(type);
break;
case RTV_BYTECODE_DUPX2:
POP_TOS_SINGLE(type);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
POP_TOS_PAIR(temp1, temp2);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements + 1;
goto _miscError;
}
PUSH(type);
PUSH(temp2);
PUSH(temp1);
PUSH(type);
break;
case RTV_BYTECODE_DUP2:
POP_TOS_PAIR(temp1, temp2);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements + 1;
goto _miscError;
}
PUSH(temp2);
PUSH(temp1);
PUSH(temp2);
PUSH(temp1);
break;
case RTV_BYTECODE_DUP2X1:
POP_TOS_PAIR(type, temp1);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements + 1;
goto _miscError;
}
POP_TOS_SINGLE(temp2);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
PUSH(temp1);
PUSH(type);
PUSH(temp2);
PUSH(temp1);
PUSH(type);
break;
case RTV_BYTECODE_DUP2X2:
POP_TOS_PAIR(type, temp1);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements + 1;
goto _miscError;
}
POP_TOS_PAIR(temp2, temp3);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements + 1;
goto _miscError;
}
PUSH(temp1);
PUSH(type);
PUSH(temp3);
PUSH(temp2);
PUSH(temp1);
PUSH(type);
break;
case RTV_BYTECODE_SWAP:
POP_TOS_SINGLE(type);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
POP_TOS_SINGLE(temp1);
if (inconsistentStack) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
errorStackIndex = stackTop - liveStack->stackElements;
goto _miscError;
}
PUSH(type);
PUSH(temp1);
break;
default:
errorType = J9NLS_BCV_ERR_BC_UNKNOWN__ID;
verboseErrorCode = BCV_ERR_BAD_BYTECODE;
goto _miscError;
}
continue;
_newStack:
if (pc < length) {
if ((UDATA) nextStackPC < length) {
if (pc != (UDATA) nextStackPC) {
if (J9ROMCLASS_HAS_VERIFY_DATA(romClass) && (!verifyData->ignoreStackMaps)) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_WRONG_STACKMAP_FRAME;
errorTempData = nextStackPC;
start = pc;
goto _miscError;
} else {
pc = nextStackPC;
}
}
SAVE_STACKTOP(liveStack, stackTop);
memcpy((UDATA *) liveStack, (UDATA *) currentMapData, verifyData->stackSize);
isNextStack = TRUE;
RELOAD_LIVESTACK;
liveStack->uninitializedThis = currentMapData->uninitializedThis;
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
} else {
if (J9ROMCLASS_HAS_VERIFY_DATA(romClass) && (!verifyData->ignoreStackMaps)) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_NO_STACKMAP_FRAME;
errorTempData = (UDATA)nextStackPC;
goto _miscError;
} else {
if ((action != RTV_RETURN)
&& (bc !=JBathrow)
&& (bc !=JBtableswitch)
&& (bc !=JBlookupswitch)
&& (bc !=JBgoto)
&& (bc !=JBgotow)
) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_DEAD_CODE;
goto _miscError;
}
pc = length;
}
}
}
}
if ((action != RTV_RETURN)
&& (bc !=JBathrow)
&& (bc !=JBtableswitch)
&& (bc !=JBlookupswitch)
&& (bc !=JBgoto)
&& (bc !=JBgotow)
) {
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
verboseErrorCode = BCV_ERR_DEAD_CODE;
goto _miscError;
}
Trc_RTV_verifyBytecodes_Exit(verifyData->vmStruct);
return BCV_SUCCESS;
#undef CHECK_END
errorType = J9NLS_BCV_ERR_UNEXPECTED_EOF__ID;
goto _verifyError;
_mapError:
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
_compatibleError:
if (rc == BCV_ERR_INTERNAL_ERROR) {
errorType = J9NLS_BCV_ERR_CLASS_LOAD_FAILED__ID;
}
_verifyError:
if ((stackTop < stackBase) && (J9NLS_BCV_ERR_STACK_UNDERFLOW__ID == errorType)) {
errorStackIndex = stackBase - liveStack->stackElements;
storeVerifyErrorData(verifyData, BCV_ERR_STACK_UNDERFLOW, (U_32)errorStackIndex, (UDATA)-1, (UDATA)-1, start);
}
Trc_RTV_verifyBytecodes_VerifyError(verifyData->vmStruct,
errorType,
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
start);
Trc_RTV_verifyBytecodes_VerifyErrorBytecode(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
errorType, start, start, *(code + start));
BUILD_VERIFY_ERROR(errorModule, errorType);
return BCV_ERR_INTERNAL_ERROR;
_miscError:
storeVerifyErrorData(verifyData, (I_16)verboseErrorCode, (U_32)errorStackIndex, (UDATA)-1, errorTempData, start);
goto _verifyError;
_outOfMemoryError:
errorType = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
Trc_RTV_verifyBytecodes_OutOfMemoryException(verifyData->vmStruct,
errorType,
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
start);
BUILD_VERIFY_ERROR(errorModule, errorType);
return BCV_ERR_INSUFFICIENT_MEMORY;
}
static IDATA
verifyExceptions (J9BytecodeVerificationData *verifyData)
{
J9ROMMethod *romMethod = verifyData->romMethod;
J9ROMClass *romClass = verifyData->romClass;
J9ExceptionInfo *exceptionInfo;
J9ExceptionHandler *handler;
J9ROMConstantPoolItem *romConstantPool;
J9UTF8 *catchName;
UDATA i, catchClass;
IDATA rc = BCV_SUCCESS;
IDATA reasonCode = 0;
Trc_RTV_verifyExceptions_Entry(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)));
exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
romConstantPool = J9_ROM_CP_FROM_ROM_CLASS(verifyData->romClass);
for (i = 0; i < exceptionInfo->catchCount; i++, handler++) {
if (handler->exceptionClassIndex) {
IDATA tempRC = 0;
catchName = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)(&romConstantPool [handler->exceptionClassIndex]));
catchClass = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(catchName), J9UTF8_LENGTH(catchName), 0, 0);
tempRC = isClassCompatible (verifyData, catchClass, (UDATA) (BCV_JAVA_LANG_THROWABLE_INDEX << BCV_CLASS_INDEX_SHIFT), &reasonCode);
if (FALSE == tempRC) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
Trc_RTV_verifyExceptions_OutOfMemoryException(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)));
rc = BCV_ERR_INSUFFICIENT_MEMORY;
break;
} else {
Trc_RTV_verifyExceptions_VerifyError(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
i, J9UTF8_LENGTH(catchName), J9UTF8_DATA(catchName));
rc = BCV_FAIL;
break;
}
}
}
}
Trc_RTV_verifyExceptions_Exit(verifyData->vmStruct);
return rc;
}
IDATA
j9rtv_verifyArguments (J9BytecodeVerificationData *verifyData, J9UTF8 * utf8string, UDATA ** pStackTop)
{
IDATA argCount, index;
UDATA arity, objectType, baseType;
UDATA *stackTop;
U_8 *signature;
U_16 length;
U_8 *string;
IDATA rc;
IDATA mrc = BCV_SUCCESS;
BOOLEAN boolType = FALSE;
J9BranchTargetStack *liveStack = (J9BranchTargetStack *) verifyData->liveStack;
Trc_RTV_j9rtv_verifyArguments_Entry(verifyData->vmStruct, J9UTF8_LENGTH(utf8string), J9UTF8_DATA(utf8string));
stackTop = *pStackTop;
argCount = (IDATA) getSendSlotsFromSignature(J9UTF8_DATA(utf8string));
if ((IDATA)(stackTop - liveStack->stackElements) < argCount) {
stackTop = liveStack->stackElements;
} else {
stackTop = stackTop - argCount;
}
signature = J9UTF8_DATA(utf8string) + 1;
for (index = 0; index < argCount; index++) {
arity = 0;
objectType = 0;
boolType = FALSE;
if (*signature == '[') {
while (*signature == '[') {
signature++;
arity++;
}
}
if (IS_REF_OR_VAL_SIGNATURE(*signature) || arity) {
IDATA reasonCode = 0;
if (IS_REF_OR_VAL_SIGNATURE(*signature)) {
signature++;
string = signature;
while (*signature++ != ';');
length = (U_16) (signature - string - 1);
objectType = convertClassNameToStackMapType(verifyData, string, length, 0, arity);
} else {
if ((*signature < 'A') || (*signature > 'Z')) {
Trc_RTV_j9rtv_verifyArguments_Unreachable(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
__LINE__);
mrc = BCV_FAIL;
break;
}
objectType = (UDATA) baseTypeCharConversion[*signature - 'A'];
signature++;
if (!objectType) {
Trc_RTV_j9rtv_verifyArguments_Unreachable(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
__LINE__);
mrc = BCV_FAIL;
break;
}
arity--;
objectType |= BCV_TAG_BASE_ARRAY_OR_NULL;
}
objectType |= (arity << BCV_ARITY_SHIFT);
rc = isClassCompatible (verifyData, stackTop[index], objectType, &reasonCode);
if (FALSE == rc) {
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
Trc_RTV_j9rtv_verifyArguments_OutOfMemoryException(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
mrc = BCV_ERR_INSUFFICIENT_MEMORY;
break;
} else if (BCV_ERR_INACCESSIBLE_CLASS == reasonCode) {
Trc_RTV_j9rtv_verifyArguments_InaccessibleClass(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
mrc = BCV_ERR_INACCESSIBLE_CLASS;
break;
} else {
Trc_RTV_j9rtv_verifyArguments_ObjectMismatch(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
index, J9UTF8_LENGTH(utf8string), J9UTF8_DATA(utf8string), stackTop[index]);
mrc = BCV_FAIL;
verifyData->errorDetailCode = BCV_ERR_INCOMPATIBLE_TYPE;
verifyData->errorTargetType = objectType;
break;
}
}
} else {
if ((*signature < 'A') || (*signature > 'Z')) {
Trc_RTV_j9rtv_verifyArguments_Unreachable(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
__LINE__);
mrc = BCV_FAIL;
break;
}
baseType = (UDATA) argTypeCharConversion[*signature - 'A'];
if ('Z' == *signature) {
boolType = TRUE;
}
signature++;
if (!baseType) {
Trc_RTV_j9rtv_verifyArguments_Unreachable(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
__LINE__);
mrc = BCV_FAIL;
break;
}
if (stackTop[index] != baseType) {
Trc_RTV_j9rtv_verifyArguments_PrimitiveMismatch(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
index, J9UTF8_LENGTH(utf8string), J9UTF8_DATA(utf8string), stackTop[index]);
mrc = BCV_FAIL;
verifyData->errorDetailCode = BCV_ERR_INCOMPATIBLE_TYPE;
verifyData->errorTargetType = (TRUE == boolType) ? BCV_BASE_TYPE_BOOL : baseType;
break;
}
if (baseType & BCV_WIDE_TYPE_MASK) {
index++;
if (stackTop[index] != BCV_BASE_TYPE_TOP) {
Trc_RTV_j9rtv_verifyArguments_WidePrimitiveMismatch(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
index, J9UTF8_LENGTH(utf8string), J9UTF8_DATA(utf8string));
mrc = BCV_FAIL;
verifyData->errorDetailCode = BCV_ERR_INCOMPATIBLE_TYPE;
verifyData->errorTargetType = (TRUE == boolType) ? BCV_BASE_TYPE_BOOL : baseType;
break;
}
}
}
}
if (verifyData->errorDetailCode < 0) {
storeArgumentErrorData(verifyData, (U_32)(&stackTop[index] - liveStack->stackElements), (U_16)index);
}
*pStackTop = stackTop;
Trc_RTV_j9rtv_verifyArguments_Exit(verifyData->vmStruct, mrc);
return mrc;
}
static J9BranchTargetStack *
nextStack (J9BytecodeVerificationData *verifyData, UDATA *nextMapIndex, IDATA *nextStackPC)
{
J9BranchTargetStack * returnStack = NULL;
*nextStackPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(verifyData->romMethod);
while (*nextMapIndex < (UDATA) verifyData->stackMapsCount) {
returnStack = BCV_INDEX_STACK (*nextMapIndex);
(*nextMapIndex)++;
if (returnStack->stackBaseIndex != -1) {
*nextStackPC = returnStack->pc;
break;
}
}
Trc_RTV_nextStack_Result(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
verifyData->stackMapsCount, *nextMapIndex, *nextStackPC,
J9_BYTECODE_SIZE_FROM_ROM_METHOD(verifyData->romMethod));
return returnStack;
}
static IDATA
nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMethod, IDATA lastPC)
{
IDATA nextPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
if (romMethod->modifiers & CFR_ACC_HAS_EXCEPTION_INFO) {
J9ExceptionInfo *exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
J9ExceptionHandler *handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
UDATA i;
for (i = exceptionInfo->catchCount; i; i--, handler++) {
if (((IDATA) handler->startPC) > lastPC) {
if (handler->startPC < (UDATA) nextPC) {
nextPC = handler->startPC;
}
}
}
Trc_RTV_nextExceptionStart_Result(verifyData->vmStruct,
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
exceptionInfo->catchCount, lastPC, nextPC,
J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod));
}
return nextPC;
}
static void
storeArgumentErrorData (J9BytecodeVerificationData * verifyData, U_32 errorCurrentFramePosition, U_16 errorArgumentIndex)
{
verifyData->errorCurrentFramePosition = errorCurrentFramePosition;
verifyData->errorArgumentIndex = errorArgumentIndex;
}
static void
storeMethodInfo (J9BytecodeVerificationData * verifyData, J9UTF8* errorClassString, J9UTF8* errorMethodString, J9UTF8* errorSignatureString, IDATA currentPC)
{
J9BranchTargetStack *liveStack = (J9BranchTargetStack *) verifyData->liveStack;
verifyData->errorClassString = errorClassString;
verifyData->errorMethodString = errorMethodString;
verifyData->errorSignatureString = errorSignatureString;
liveStack->pc = (UDATA)currentPC;
}