/** * @param ec * @see org.jnode.vm.x86.compiler.l1a.Item#release(EmitterContext) */ private void cleanup(EmitterContext ec) { // assertCondition(!ec.getVStack().contains(this), "Cannot release while // on vstack"); final X86RegisterPool pool = ec.getGPRPool(); switch (getKind()) { case Kind.GPR: pool.release(gpr); if (VmUtils.verifyAssertions()) VmUtils._assert(pool.isFree(gpr), "reg is free"); break; case Kind.LOCAL: // nothing to do break; case Kind.CONSTANT: // nothing to do break; case Kind.FPUSTACK: // nothing to do break; case Kind.STACK: // nothing to do break; default: throw new IllegalArgumentException("Invalid item kind"); } this.gpr = null; setKind((byte) 0); }
/** * Load this item to a general purpose register. * * @param ec */ final void loadToGPR(EmitterContext ec) { if (!isGPR()) { X86Register r = ec.getGPRPool().request(JvmType.INT); if (r == null) { ec.getVStack().push(ec); r = ec.getGPRPool().request(JvmType.INT); } if (VmUtils.verifyAssertions()) VmUtils._assert(r != null, "r != null"); loadTo(ec, (X86Register.GPR) r); } }
/** * Load this item into a register that is suitable for BITS8 mode. * * @param ec */ final void loadToBITS8GPR(EmitterContext ec) { if (!isGPR() || !gpr.isSuitableForBits8()) { final X86RegisterPool pool = ec.getGPRPool(); X86Register r = pool.request(JvmType.INT, this, true); if (r == null) { ec.getVStack().push(ec); r = ec.getGPRPool().request(JvmType.INT, this, true); } if (VmUtils.verifyAssertions()) VmUtils._assert(r != null, "r != null"); loadTo(ec, (X86Register.GPR) r); } }
protected final void initialize(EmitterContext ec, byte kind, X86Register reg, short local) { super.initialize( kind, local, ((reg instanceof X86Register.XMM) ? (X86Register.XMM) reg : null)); this.gpr = (reg instanceof X86Register.GPR) ? (X86Register.GPR) reg : null; if (VmUtils.verifyAssertions()) { switch (kind) { case Kind.GPR: VmUtils._assert((this.gpr != null), "kind == register implies that reg != null"); break; } verifyState(ec); } }
/** * Gets the bytecode of a native code replacement method. * * @param method * @param cl * @return the bytecode */ private static VmByteCode getNativeCodeReplacement( VmMethod method, VmClassLoader cl, boolean verbose) { final String className = method.getDeclaringClass().getName(); final String nativeClassName = VmUtils.getNativeClassName(className); final VmType nativeType; try { nativeType = cl.loadClass(nativeClassName, false); } catch (ClassNotFoundException ex) { if (verbose) { BootLogInstance.get().error("Native class replacement (" + nativeClassName + ") not found"); } return null; } String signature = method.getSignature(); if (!method.isStatic()) { signature = '(' + Signature.toSignature(method.getDeclaringClass()) + signature.substring(1); } final VmMethod nativeMethod = nativeType.getNativeMethodReplacement(method.getName(), signature); if (nativeMethod == null) { if (verbose) { BootLogInstance.get().error("Native method replacement (" + method + ") not found"); } return null; } if (!nativeMethod.isStatic()) { throw new ClassFormatError("Native method replacement must be static"); } return nativeMethod.getBytecode(); }
/** @see org.jnode.vm.x86.compiler.l1a.Item#load(EmitterContext) */ final void load(EmitterContext ec) { if (!isGPR()) { final X86RegisterPool pool = ec.getGPRPool(); X86Register r = pool.request(getType(), this); if (r == null) { final VirtualStack vstack = ec.getVStack(); vstack.push(ec); r = pool.request(getType(), this); } if (VmUtils.verifyAssertions()) VmUtils._assert(r != null, "r != null"); loadTo(ec, (X86Register.GPR) r); } if (VmUtils.verifyAssertions()) { verifyState(ec); } }
/** * Gets the compiled code of a given stackframe. * * @param sf Stackframe pointer * @return The compiled code */ final VmCompiledCode getCompiledCode(Address sf) { final int ccid = sf.loadInt(getMethodIdOffset(sf)); if (ccid == 0) { return null; } else { return VmUtils.getVm().getCompiledMethods().get(ccid); } }
/** * @see org.jnode.vm.x86.compiler.l1a.Item#spill(EmitterContext, * org.jnode.assembler.x86.X86Register) */ final void spill(EmitterContext ec, X86Register reg) { if (VmUtils.verifyAssertions()) { VmUtils._assert( isGPR() && (this.gpr.getNr() == reg.getNr()), "spill1 gpr=" + gpr + ", reg=" + reg); } final X86RegisterPool pool = ec.getGPRPool(); X86Register r = pool.request(getType()); if (r == null) { ec.getVStack().push(ec); if (getKind() == Kind.STACK) { return; } r = pool.request(getType()); if (VmUtils.verifyAssertions()) VmUtils._assert(r != null, "r != null"); } loadTo(ec, (X86Register.GPR) r); pool.transferOwnerTo(r, this); if (VmUtils.verifyAssertions()) { verifyState(ec); } }
/** * Gets the method of a given stackframe. * * @param sf Stackframe pointer * @return The method */ @KernelSpace final VmMethod getMethod(Address sf) { final int ccid = sf.loadInt(getMethodIdOffset(sf)); if (ccid == 0) { return null; } else { final VmCompiledCode cc = VmUtils.getVm().getCompiledMethods().get(ccid); if (cc == null) { // (This can happen if an exception is thrown while a frame // for a 'native' method call is on the stack. A panic is not a // good idea. It is better to generate a stack trace with a missing // method name.) // Unsafe.die("Unknown ccid found on stack"); return null; } else { return cc.getMethod(); } } }
/** * Read the method table * * @param data * @param rejectNatives * @param cls * @param cp * @param statics * @param cl */ private static void readMethods( ByteBuffer data, boolean rejectNatives, VmType cls, VmCP cp, VmStatics statics, VmClassLoader cl) { final int mcount = data.getChar(); if (mcount > 0) { final VmMethod[] mtable = new VmMethod[mcount]; for (int i = 0; i < mcount; i++) { final int modifiers = data.getChar(); final String name = cp.getUTF8(data.getChar()); final String signature = cp.getUTF8(data.getChar()); final boolean isStatic = ((modifiers & Modifier.ACC_STATIC) != 0); final VmMethod mts; final boolean isSpecial = name.equals("<init>"); // final int staticsIdx = statics.allocMethod(); if (isStatic || isSpecial) { if (isSpecial) { mts = new VmSpecialMethod(name, signature, modifiers, cls); } else { mts = new VmStaticMethod(name, signature, modifiers, cls); } } else { mts = new VmInstanceMethod(name, signature, modifiers, cls); } // statics.setMethod(staticsIdx, mts); mtable[i] = mts; // Read methods attributes final int acount = data.getChar(); VmAnnotation[] rVisAnn = null; VmAnnotation[] rInvisAnn = null; for (int a = 0; a < acount; a++) { String attrName = cp.getUTF8(data.getChar()); int length = data.getInt(); if (VmArray.equals(CodeAttrName, attrName)) { mts.setBytecode(readCode(data, cls, cp, mts)); } else if (VmArray.equals(ExceptionsAttrName, attrName)) { mts.setExceptions(readExceptions(data, cls, cp)); } else if (VmArray.equals(RuntimeVisibleAnnotationsAttrName, attrName)) { byte[] buf = new byte[length]; data.slice().get(buf); mts.setRawAnnotations(buf); // todo will get obsolate with openjdk based annotation support // rVisAnn = readRuntimeAnnotations(data, cp, true, cl); rVisAnn = readRuntimeAnnotations2(data, cp, true, cl, cls); } else if (VmArray.equals(RuntimeInvisibleAnnotationsAttrName, attrName)) { rInvisAnn = readRuntimeAnnotations(data, cp, false, cl); } else if (VmArray.equals(RuntimeVisibleParameterAnnotationsAttrName, attrName)) { byte[] buf = new byte[length]; data.slice().get(buf); mts.setRawParameterAnnotations(buf); // todo will get obsolate with openjdk based annotation support readRuntimeParameterAnnotations(data, cp, true, cl); } else if (VmArray.equals(RuntimeInvisibleParameterAnnotationsAttrName, attrName)) { readRuntimeParameterAnnotations(data, cp, false, cl); } else if (VmArray.equals(AnnotationDefaultAttrName, attrName)) { // todo will get obsolate with openjdk based annotation support byte[] buf = new byte[length]; data.slice().get(buf); mts.setRawAnnotationDefault(buf); Class r_class; VmType vtm = mts.getReturnType(); if (vtm.isPrimitive()) { r_class = getClassForJvmType(vtm.getJvmType()); } else { try { r_class = Class.forName(vtm.getName(), false, vtm.getLoader().asClassLoader()); } catch (ClassNotFoundException cnf) { throw new RuntimeException(cnf); } } Object defo = AnnotationParser.parseMemberValue( r_class, data, new VmConstantPool(cls), VmUtils.isRunningVm() ? cls.asClass() : cls.asClassDuringBootstrap()); mts.setAnnotationDefault(defo); } else { skip(data, length); } } mts.setRuntimeAnnotations(rVisAnn); if (rVisAnn != null) { mts.addPragmaFlags(getMethodPragmaFlags(rVisAnn, cls.getName())); } if (rInvisAnn != null) { mts.addPragmaFlags(getMethodPragmaFlags(rInvisAnn, cls.getName())); } if ((modifiers & Modifier.ACC_NATIVE) != 0) { final VmByteCode bc = getNativeCodeReplacement(mts, cl, rejectNatives); if (bc != null) { mts.setModifier(false, Modifier.ACC_NATIVE); mts.setBytecode(bc); } else { if (rejectNatives) { throw new ClassFormatError("Native method " + mts); } } } } cls.setMethodTable(mtable); } }
/** * load item with register reg. Assumes that reg is properly allocated * * @param ec current emitter context * @param reg register to load the item to */ final void loadTo(EmitterContext ec, X86Register.GPR reg) { if (VmUtils.verifyAssertions()) VmUtils._assert(reg != null, "Reg != null"); final X86Assembler os = ec.getStream(); final X86RegisterPool pool = ec.getGPRPool(); final VirtualStack stack = ec.getVStack(); final X86CompilerHelper helper = ec.getHelper(); if (VmUtils.verifyAssertions()) { VmUtils._assert(!pool.isFree(reg), "reg not free"); } switch (getKind()) { case Kind.GPR: if (this.gpr != reg) { os.writeMOV(reg.getSize(), reg, this.gpr); cleanup(ec); } break; case Kind.LOCAL: os.writeMOV(reg.getSize(), reg, helper.BP, getOffsetToFP(ec)); break; case Kind.CONSTANT: loadToConstant(ec, os, reg); break; case Kind.FPUSTACK: // Make sure this item is on top of the FPU stack FPUHelper.fxch(os, stack.fpuStack, this); stack.fpuStack.pop(this); // Convert & move to new space on normal stack os.writeLEA(helper.SP, helper.SP, -helper.SLOTSIZE); popFromFPU(os, helper.SP, 0); os.writePOP(reg); break; case Kind.STACK: // TODO: make sure 'this' is on top of stack // TODO: implemen it for 64 bits if (!stack.operandStack.isTos(this)) { int stack_loc = stack.operandStack.stackLocation(this); if (stack_loc < 0) throw new StackException("Item not found on stack"); stack.operandStack.makeTop(stack_loc); // todo test it os.writeMOV( org.jnode.vm.x86.compiler.X86CompilerConstants.BITS32, reg, helper.SP, helper.SLOTSIZE); os.writeXCHG( helper.SP, org.jnode.vm.x86.compiler.X86CompilerConstants.BITS32 * stack_loc, reg); os.writeMOV( org.jnode.vm.x86.compiler.X86CompilerConstants.BITS32, helper.SP, helper.SLOTSIZE, reg); } if (VirtualStack.checkOperandStack) { stack.operandStack.pop(this); } os.writePOP(reg); break; default: throw new IllegalArgumentException("Invalid item kind"); } setKind(Kind.GPR); this.gpr = reg; }
/** * Gets the register the is used by this item. * * @return The register that contains this item */ final X86Register.GPR getRegister() { if (VmUtils.verifyAssertions()) VmUtils._assert(isGPR(), "Must be register"); return gpr; }
/** * Gets the constant value of this item. * * @return */ final long getValue() { if (VmUtils.verifyAssertions()) { VmUtils._assert(isConstant(), "kind == Kind.CONSTANT"); } return value; }
/** * Gets the MSB part of the constant value of this item. * * @return */ final int getMsbValue() { if (VmUtils.verifyAssertions()) { VmUtils._assert(isConstant(), "kind == Kind.CONSTANT"); } return (int) ((value >>> 32) & 0xFFFFFFFFL); }
/** * Gets (creates if needed) a compiled code id. * * @return a compiled code id. */ public final int getCompiledCodeId() { if (ccId < 0) { ccId = VmUtils.getVm().getCompiledMethods().createId(); } return ccId; }