📄 bytecodes.c
字号:
NOTIMPLEMENTED(JSR) /* Jump and stack return *//***** JSR AND RET ARE NOT NEEDED IN KVMSELECT(JSR) pushStackAsType(BYTE*, (ip + 3)); ip += getShort(ip + 1);DONE(0)*****/#endif/* --------------------------------------------------------------------- */#if STANDARDBYTECODESNOTIMPLEMENTED(RET) /* Return from subroutine *//***** JSR AND RET ARE NOT NEEDED IN KVMSELECT(RET) unsigned int index = ip[1]; ip = *(BYTE**)&lp[index];DONE(0)*****/#endif/* --------------------------------------------------------------------- */#if STANDARDBYTECODESSELECT(TABLESWITCH) /* Access jump table by index and jump */ long index = popStack(); /* Align instruction pointer to the next 32-bit word boundary */ unsigned char *base = (unsigned char *) (((long)ip + 4) & ~3); long lowValue = getAlignedCell(base + 4); long highValue = getAlignedCell(base + 8); if ((index < lowValue) || (index > highValue)) { ip += getAlignedCell(base); /* default value */ } else { ip += getAlignedCell(base + CELL*(index-lowValue+3)); }DONE_R#endif/* --------------------------------------------------------------------- */#if STANDARDBYTECODESSELECT(LOOKUPSWITCH) /* Access jump table by key match and jump */ struct pair { cell value; cell offset; }; long key = popStack(); cell *base = (cell *)(((long)ip + 4) & ~3); long numberOfPairs = getAlignedCell(base + 1); long delta = numberOfPairs - 1; struct pair *firstPair = (struct pair *)(base + 2); for (;;) { /* ASSERT: The item we are looking for, if it is in the table, * is in between firstPair and firstPair + delta, inclusive. */ if (delta < 0) { /* Item not found, use default at base */ break; } else { long halfDelta = (delta >> 1); struct pair *middlePair = firstPair + halfDelta; /* Don't use cell. It's unsigned */ long middleValue = getAlignedCell(&middlePair->value); if (middleValue < key) { /* Item is second half of the table */ firstPair = middlePair + 1; delta = delta - halfDelta - 1; } else if (middleValue > key) { /* Item is at the beginning of the table. */ delta = halfDelta - 1; } else { /* We have it. Set base to point to the location of the * offset. */ base = &middlePair->offset; break; } } } /* base points at the offset by which we increment the ip */ ip += getAlignedCell(base);DONE_R#endif/* --------------------------------------------------------------------- */#if STANDARDBYTECODESSELECT6(IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, RETURN) /* Return from method */ BYTE* previousIp = fp->previousIp; OBJECT synchronized = fp->syncObject; TRACE_METHOD_EXIT(fp->thisMethod); if (synchronized != NULL) { char* exitError; if (monitorExit(synchronized, &exitError) == MonitorStatusError) { exception = exitError; goto handleException; } } /* Special case where we are killing a thread */ if (previousIp == KILLTHREAD) { VMSAVE stopThread(); VMRESTORE if (areAliveThreads()) { goto reschedulePoint; } else { return; /* Must be the end of the program */ } } /* Regular case where we pop the stack frame and return data */ if ((TOKEN & 1) == 0) { /* The even ones are all the return of a single value */ cell data = topStack; POP_FRAME pushStack(data); } else if (TOKEN == RETURN) { POP_FRAME } else { /* We don't care whether it's little or big endian. . . */ long t2 = sp[0]; long t1 = sp[-1]; POP_FRAME pushStack(t1); pushStack(t2); } goto reschedulePoint;DONEX#endif/* --------------------------------------------------------------------- */#if INFREQUENTSTANDARDBYTECODESSELECT(GETSTATIC) /* Get static field from class */ /* Get the CONSTANT_Fieldref index */ unsigned int cpIndex; FIELD field; int currentToken = TOKEN; /* Get the constant pool index */ cpIndex = getUShort(ip + 1); /* Resolve constant pool reference */ VMSAVE field = resolveFieldReference(cp_global, cpIndex, TRUE, currentToken, fp_global->thisMethod->ofClass); VMRESTORE /* * If the class in question has not been initialized, do it now. * The system used in KVM is to push a special frame onto the * callers stack which is used to execute the CUSTOMCODE bytecode. * This is done repeatedly using an internal finite state machine * until all the stages are complete. When the class is initialized * the frame will be popped off and the calling frame will then * execute this bytecode again because the ip was not incremented. */ if (field && field->ofClass->status == CLASS_ERROR) { goto handleJavaLangError; } if (field && !CLASS_INITIALIZED(field->ofClass)) { VMSAVE /* Push class initialization frame */ initializeClass(field->ofClass); VMRESTORE goto reschedulePoint; } if (field) { void *location = field->u.staticAddress;#if ENABLEFASTBYTECODES REPLACE_BYTECODE(ip, ((field->accessFlags & ACC_DOUBLE) ? GETSTATIC2_FAST : (field->accessFlags & ACC_POINTER) ? GETSTATICP_FAST : GETSTATIC_FAST))#endif /* Load either one or two cells depending on field type */ if (field->accessFlags & ACC_DOUBLE) { oneMore; COPY_LONG(sp, location); oneMore; } else { pushStack(*(cell *)location); } } else { fatalSlotError(cp, cpIndex); }DONE(3)#endif/* --------------------------------------------------------------------- */#if INFREQUENTSTANDARDBYTECODESSELECT(PUTSTATIC) /* Set static field in class */ /* Get the CONSTANT_Fieldref index */ unsigned int cpIndex; FIELD field; int currentToken = TOKEN; /* Get the constant pool index */ cpIndex = getUShort(ip + 1); /* Resolve constant pool reference */ VMSAVE field = resolveFieldReference(cp_global, cpIndex, TRUE, currentToken, fp_global->thisMethod->ofClass); VMRESTORE /* * If the class in question has not been initialized, do it now. * The system used in KVM is to push a special frame onto the * callers stack which is used to execute the CUSTOMCODE bytecode. * This is done repeatedly using an internal finite state machine * until all the stages are complete. When the class is initialized * the frame will be popped off and the calling frame will then * execute this bytecode again because the ip was not incremented. */ if (field && field->ofClass->status == CLASS_ERROR) { goto handleJavaLangError; } if (field && !CLASS_INITIALIZED(field->ofClass)) { VMSAVE/* Push class initialization frame */ initializeClass(field->ofClass); VMRESTORE goto reschedulePoint; } if (field) { void *location = field->u.staticAddress;#if ENABLEFASTBYTECODES REPLACE_BYTECODE(ip, ((field->accessFlags & ACC_DOUBLE) ? PUTSTATIC2_FAST : PUTSTATIC_FAST))#endif /* Store either one or two cells depending on field type */ if (field->accessFlags & ACC_DOUBLE) { oneLess; COPY_LONG(location, sp); oneLess; } else *(cell *)location = popStack(); } else { fatalSlotError(cp, cpIndex); /* RAISE_EXCEPTION(NoSuchFieldError); */ }DONE(3)#endif/* --------------------------------------------------------------------- */#if INFREQUENTSTANDARDBYTECODESSELECT(GETFIELD) /* Get field (instance variable) from object */ /* Get the CONSTANT_Fieldref index */ unsigned int cpIndex; FIELD field; int currentToken = TOKEN; /* Get the constant pool index */ cpIndex = getUShort(ip + 1); /* Resolve constant pool reference */ VMSAVE field = resolveFieldReference(cp_global, cpIndex, FALSE, currentToken, fp_global->thisMethod->ofClass); VMRESTORE if (field) { /* Get slot index */ int offset = field->u.offset;#if ENABLEFASTBYTECODES REPLACE_BYTECODE(ip, ((field->accessFlags & ACC_DOUBLE) ? GETFIELD2_FAST : (field->accessFlags & ACC_POINTER) ? GETFIELDP_FAST : GETFIELD_FAST)) putShort(ip + 1, offset); goto reschedulePoint;#else INSTANCE instance = popStackAsType(INSTANCE); CHECK_NOT_NULL(instance); /* Load either one or two cells depending on field type */ if (field->accessFlags & ACC_DOUBLE) { pushStack(instance->data[offset].cell); pushStack(instance->data[offset + 1].cell); } else { pushStack(instance->data[offset].cell); }#endif } else { fatalSlotError(cp, cpIndex); }DONE(3)#endif/* --------------------------------------------------------------------- */#if INFREQUENTSTANDARDBYTECODESSELECT(PUTFIELD) /* Set field in object */ /* Get the CONSTANT_Fieldref index */ unsigned int cpIndex; FIELD field; int currentToken = TOKEN; /* Get the constant pool index */ cpIndex = getUShort(ip + 1); /* Resolve constant pool reference */ VMSAVE field = resolveFieldReference(cp_global, cpIndex, FALSE, currentToken, fp_global->thisMethod->ofClass); VMRESTORE if (field) { /* Get slot index */ int offset = field->u.offset;#if ENABLEFASTBYTECODES /* If feasible, replace the current bytecode sequence * with a faster one */ REPLACE_BYTECODE(ip, ((field->accessFlags & ACC_DOUBLE) ? PUTFIELD2_FAST : PUTFIELD_FAST)) putShort(ip + 1, offset); goto reschedulePoint;#else /* Store either one or two cells depending on field type */ if (field->accessFlags & ACC_DOUBLE) { cell first = popStack(); cell second = popStack(); INSTANCE instance = popStackAsType(INSTANCE); CHECK_NOT_NULL(instance); instance->data[offset].cell = second; instance->data[offset + 1].cell = first; } else { cell data = popStack(); INSTANCE instance = popStackAsType(INSTANCE); CHECK_NOT_NULL(instance) instance->data[offset].cell = data; }#endif } else { fatalSlotError(cp, cpIndex); }DONE(3)#endif/* --------------------------------------------------------------------- */#if INFREQUENTSTANDARDBYTECODESSELECT(INVOKEVIRTUAL) /* Invoke instance method; dispatch based on dynamic class */ /* Get the CONSTANT_Methodref index */ unsigned int cpIndex; METHOD cpMethod; /* Get the constant pool index */ cpIndex = getUShort(ip + 1); /* Resolve constant pool reference */ VMSAVE cpMethod = resolveMethodReference(cp_global, cpIndex, FALSE, fp_global->thisMethod->ofClass); VMRESTORE if (cpMethod) { CLASS dynamicClass; /* Calculate the number of parameters from signature */ int argCount = cpMethod->argCount; /* Get this */ thisObject = *(OBJECT*)(sp-argCount+1); CHECK_NOT_NULL(thisObject); /* Get the dynamic class of the object */ dynamicClass = thisObject->ofClass; /* Find the actual method */ VMSAVE thisMethod = lookupDynamicMethod(dynamicClass, cpMethod); VMRESTORE if (thisMethod) {#if ENABLEFASTBYTECODES if ( (cpMethod->accessFlags & (ACC_PRIVATE | ACC_FINAL)) || (cpMethod->ofClass->clazz.accessFlags & ACC_FINAL) ) { REPLACE_BYTECODE(ip, INVOKESPECIAL_FAST) } else { int iCacheIndex; /* Replace the current bytecode sequence */ CREATE_CACHE_ENTRY((cell*)thisMethod, ip) REPLACE_BYTECODE(ip, INVOKEVIRTUAL_FAST) putShort(ip + 1, iCacheIndex); }#endif /* ENABLEFASTBYTECODES */ TRACE_METHOD_ENTRY(thisMethod, "virtual"); CALL_VIRTUAL_METHOD } else { fatalSlotError(cp, cpIndex); } } else { fatalSlotError(cp, cpIndex); }DONE(0)#endif/* --------------------------------------------------------------------- */#if INFREQUENTSTANDARDBYTECODESSELECT(INVOKESPECIAL) /* Invoke instance method; special handling for superclass, */ /* private and instance initialization method invocations */ /* Get the CONSTANT_Methodref index */ unsigned int cpIndex; /* Get the constant pool index */ cpIndex = getUShort(ip + 1); /* Resolve constant pool reference */ VMSAVE thisMethod = resolveMethodReference(cp_global, cpIndex, FALSE, fp_global->thisMethod->ofClass); VMRESTORE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -