Skip to content

Commit

Permalink
Cycle Detection
Browse files Browse the repository at this point in the history
Add Cycle Detection for Constant Dynamic to check cycles that might
appear in the arguments of a Bootstrap Method of a condy.

Dependent on:

PR#1533

PR#1858

Related Issue: eclipse-openj9#1275

Signed-off-by: Charles_Zheng <[email protected]>
  • Loading branch information
Charles_Zheng authored and Charles_Zheng committed Aug 30, 2018
1 parent c59c710 commit 4f50167
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 2 deletions.
1 change: 1 addition & 0 deletions runtime/oti/j9consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ extern "C" {
#define J9_EXTENDED_RUNTIME_DISABLE_FAST_CLASS_HASH_TABLE 0x20000000
#define J9_EXTENDED_RUNTIME_JIT_INLINE_WATCHES 0x40000000
#define J9_EXTENDED_RUNTIME_REDUCE_CPU_MONITOR_OVERHEAD 0x80000000
#define J9_EXTENDED_RUNTIME_CYCLE_DETECTION 0x100000000

/* TODO: Define this until the JIT removes it */
#define J9_EXTENDED_RUNTIME_ALLOW_GET_CALLER_CLASS 0
Expand Down
2 changes: 2 additions & 0 deletions runtime/oti/jvminit.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ enum INIT_STAGE {
#define VMOPT_XXDISABLEJITWATCH "-XX:-JITInlineWatches"
#define VMOPT_XXENABLEALWAYSSPLITBYTECODES "-XX:+AlwaysSplitBytecodes"
#define VMOPT_XXDISABLEALWAYSSPLITBYTECODES "-XX:-AlwaysSplitBytecodes"
#define VMOPT_XXENABLECYCLEDETECTION "-XX:+CycleDetection"
#define VMOPT_XXDISABLECYCLEDETECTION "-XX:-CycleDetection"

#define VMOPT_XX_NOSUBALLOC32BITMEM "-XXnosuballoc32bitmem"

Expand Down
4 changes: 4 additions & 0 deletions runtime/vm/jvminit.c
Original file line number Diff line number Diff line change
Expand Up @@ -2955,6 +2955,10 @@ processVMArgsFromFirstToLast(J9JavaVM * vm)
vm->runtimeFlags |= J9_RUNTIME_ALWAYS_SPLIT_BYTECODES;
} else if (0 == strcmp(testString, VMOPT_XXDISABLEALWAYSSPLITBYTECODES)) {
vm->runtimeFlags &= ~(UDATA)J9_RUNTIME_ALWAYS_SPLIT_BYTECODES;
} else if (0 == strcmp(testString, VMOPT_XXENABLECYCLEDETECTION)) {
vm->extendedRuntimeFlags |= (UDATA)J9_EXTENDED_RUNTIME_CYCLE_DETECTION;
} else if (0 == strcmp(testString, VMOPT_XXDISABLECYCLEDETECTION)) {
vm->extendedRuntimeFlags &= ~(UDATA)J9_EXTENDED_RUNTIME_CYCLE_DETECTION;
}
/* -Xbootclasspath and -Xbootclasspath/p are not supported from Java 9 onwards */
if (J2SE_VERSION(vm) >= J2SE_19) {
Expand Down
69 changes: 67 additions & 2 deletions runtime/vm/resolvesupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@
#include "VMHelpers.hpp"

#define MAX_STACK_SLOTS 255
#define BSM_ARGUMENT_SIZE 2
#define BSM_ARGUMENT_COUNT_OFFSET 1
#define BSM_ARGUMENTS_OFFSET 2

static void checkForDecompile(J9VMThread *currentThread, J9ROMMethodRef *romMethodRef, UDATA jitFlags);
static bool finalFieldSetAllowed(J9VMThread *currentThread, bool isStatic, J9Method *method, J9Class *fieldClass, J9Class *callerClass, J9ROMFieldShape *field, UDATA jitFlags);

static bool isCycleDetected(J9ConstantPool *ramCP, U_16 *bsmDataOriginal, U_16 *visited, U_16 cpIndex, bool *resolved, int stackIndex);

/**
* @brief In class files with version 53 or later, setting of final fields is only allowed from initializer methods.
Expand Down Expand Up @@ -77,7 +80,6 @@ finalFieldSetAllowed(J9VMThread *currentThread, bool isStatic, J9Method *method,
return legal;
}


/**
* @brief Check to see if a resolved method name matches the -XXdecomp: value from the command line
* and if so, force all running methods to be decompiled
Expand Down Expand Up @@ -1984,6 +1986,27 @@ resolveConstantDynamic(J9VMThread *vmThread, J9ConstantPool *ramCP, UDATA cpInde
/* clear the J9DescriptionCpPrimitiveType flag with mask to get bsmIndex */
U_32 bsmIndex = (romConstantRef->bsmIndexAndCpType >> J9DescriptionCpTypeShift) & J9DescriptionCpBsmIndexMask;
J9ROMNameAndSignature* nameAndSig = SRP_PTR_GET(&romConstantRef->nameAndSignature, J9ROMNameAndSignature*);
U_16 cpIndex_16 = (U_16) cpIndex;

/* Enable Cycle Detection with "-XX:+CycleDetection" and disable with "-XX:-CycleDetection" at runtime */
if ((NULL != vm)
&& (J9_ARE_ALL_BITS_SET(vm->extendedRuntimeFlags,
J9_EXTENDED_RUNTIME_CYCLE_DETECTION))) {
/* Cycle Detection implementation*/
U_32 CPSize = romClass->ramConstantPoolCount;
/* Implement a stack array here to track visited status */
U_16 *visited = new U_16[CPSize];
int stackIndex = 0;
/* Implement a boolean array to check if cycle detection is resolved */
bool *resolvedArr = new bool[CPSize];
for (U_32 i = 0; i < CPSize; i++) {
resolvedArr[i] = false;
}
if (isCycleDetected(ramCP, bsmData, visited, cpIndex_16, resolvedArr, stackIndex)) {
setCurrentExceptionUTF(vmThread, J9VMCONSTANTPOOL_JAVALANGSTACKOVERFLOWERROR,
"Cycle Detection error: Cycle detected.");
}
}

/* Walk bsmData - skip all bootstrap methods before bsmIndex */
for (U_32 i = 0; i < bsmIndex; i++) {
Expand All @@ -2001,6 +2024,7 @@ resolveConstantDynamic(J9VMThread *vmThread, J9ConstantPool *ramCP, UDATA cpInde

j9object_t exceptionObject = NULL;
if (NULL != vmThread->currentException) {
/* Allocate the exception object in tenure */
exceptionObject = vmThread->currentException;
} else if (NULL == value) {
/* Java.lang.void is used as a special flag to indicate null reference */
Expand Down Expand Up @@ -2073,3 +2097,44 @@ resolveInvokeDynamic(J9VMThread *vmThread, J9ConstantPool *ramCP, UDATA callSite

return methodHandle;
}

static bool
isCycleDetected(J9ConstantPool *ramCP, U_16 *bsmDataOriginal, U_16 *visited, U_16 cpIndex, bool *resolved, int stackIndex)
{
/* Check if the condy is resolved */
if (resolved[cpIndex] == true) {
return false;
}
/* Look through the stack to check if the condy is visited */
if (stackIndex > 0) {
for (int i = stackIndex - 1; i >= 0; i--) {
if (visited[i] == cpIndex) {
return true;
}
}
}
visited[stackIndex++] = cpIndex;
J9ROMConstantDynamicRef *romConstantRef = (J9ROMConstantDynamicRef*)(J9_ROM_CP_FROM_CP(ramCP) + cpIndex);
U_32 bsmIndex = (romConstantRef->bsmIndexAndCpType >> J9DescriptionCpTypeShift) & J9DescriptionCpBsmIndexMask;
U_16 *bsmData = bsmDataOriginal;
for (U_32 i = 0; i < bsmIndex; i++) {
bsmData += bsmData[1] + 2;
}
U_16 bsmArgCount = bsmData[1];
U_32 *bsmArgs = (U_32*) (bsmData + BSM_ARGUMENTS_OFFSET);

/* Check all bsm arguments for cycle detection */
for (U_16 i = 0; i < bsmArgCount; i++) {
int bsmArgsIndex = i * BSM_ARGUMENT_SIZE;
U_16 index = bsmArgs[bsmArgsIndex];
U_16 cpType = J9_CP_TYPE(J9ROMCLASS_CPSHAPEDESCRIPTION(J9_CLASS_FROM_CP(ramCP)->romClass), index);
if (cpType == J9CPTYPE_CONSTANT_DYNAMIC) {
if (isCycleDetected(ramCP, bsmDataOriginal, visited, index, resolved, stackIndex)) {
return true;
}
}
}
stackIndex--;
resolved[cpIndex] = true;
return false;
}

0 comments on commit 4f50167

Please sign in to comment.