/** Return atom as a string literal */ @Pure public synchronized String toUnicodeString() throws java.io.UTFDataFormatException { if (unicodeStringOrJTOCoffset == null) { String s = UTF8Convert.fromUTF8(val); if (VM.runningVM) { s = InternedStrings.internUnfoundString(s); unicodeStringOrJTOCoffset = s; } else if (!VM.writingImage) { s = s.intern(); int offset = Statics.findOrCreateObjectLiteral(s); unicodeStringOrJTOCoffset = offset; } return s; } else if (unicodeStringOrJTOCoffset instanceof String) { return (String) unicodeStringOrJTOCoffset; } else { if (VM.runningVM) { return (String) Statics.getSlotContentsAsObject( Offset.fromIntSignExtend((Integer) unicodeStringOrJTOCoffset)); } else { return UTF8Convert.fromUTF8(val).intern(); } } }
/** Find or create a JTOC offset for this method */ public final synchronized Offset findOrCreateJtocOffset() { if (VM.VerifyAssertions) VM._assert(!isStatic() && !isObjectInitializer()); Offset jtocOffset = getJtocOffset(); ; if (jtocOffset.EQ(Offset.zero())) { jtocOffset = Statics.allocateReferenceSlot(true); Statics.setSlotContents(jtocOffset, getCurrentEntryCodeArray()); synchronized (jtocOffsets) { jtocOffsets.put(this, Integer.valueOf(jtocOffset.toInt())); } } return jtocOffset; }
/** * Change machine code that will be used by future executions of this method (ie. optimized <-> * non-optimized) * * <p>Side effect: updates JTOC or method dispatch tables ("type information blocks") for this * class and its subclasses * * @param compiledMethod new machine code */ public final synchronized void replaceCompiledMethod(CompiledMethod compiledMethod) { if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isInstantiated()); // If we're replacing with a non-null compiledMethod, ensure that is still valid! if (compiledMethod != null) { synchronized (compiledMethod) { if (compiledMethod.isInvalid()) return; } } // Grab version that is being replaced CompiledMethod oldCompiledMethod = currentCompiledMethod; currentCompiledMethod = compiledMethod; // Install the new method in JTOC/TIB. If virtual, will also replace in // all subclasses that inherited the method. getDeclaringClass().updateMethod(this); // Replace constant-ified virtual method in JTOC if necessary Offset jtocOffset = getJtocOffset(); if (jtocOffset.NE(Offset.zero())) { Statics.setSlotContents(jtocOffset, getCurrentEntryCodeArray()); } // Now that we've updated the JTOC/TIB, old version is obsolete if (oldCompiledMethod != null) { CompiledMethods.setCompiledMethodObsolete(oldCompiledMethod); } }
/** * Offset of an atom's string in the JTOC, for string literals * * @return Offset of string literal in JTOC * @throws java.io.UTFDataFormatException */ public synchronized int getStringLiteralOffset() throws java.io.UTFDataFormatException { if (unicodeStringOrJTOCoffset == null) { String s = UTF8Convert.fromUTF8(val); if (VM.runningVM) { s = InternedStrings.internUnfoundString(s); } else { s = s.intern(); } int offset = Statics.findOrCreateObjectLiteral(s); unicodeStringOrJTOCoffset = offset; return offset; } else if (unicodeStringOrJTOCoffset instanceof String) { int offset = Statics.findOrCreateObjectLiteral(unicodeStringOrJTOCoffset); unicodeStringOrJTOCoffset = offset; return offset; } else { return (Integer) unicodeStringOrJTOCoffset; } }
/** Atom as string literal or null if atom hasn't been converted */ private synchronized String toUnicodeStringInternal() { if (unicodeStringOrJTOCoffset == null) { return null; } else if (unicodeStringOrJTOCoffset instanceof String) { return (String) unicodeStringOrJTOCoffset; } else { if (VM.runningVM) { Object result = Statics.getSlotContentsAsObject( Offset.fromIntSignExtend((Integer) unicodeStringOrJTOCoffset)); return (String) result; } else { try { return UTF8Convert.fromUTF8(val).intern(); } catch (UTFDataFormatException e) { throw new Error("Error in UTF data encoding: ", e); } } } }
private static <T> Object readValue( TypeReference type, int[] constantPool, DataInputStream input, ClassLoader classLoader, byte elementValue_tag) throws IOException, ClassNotFoundException { // decode Object value; switch (elementValue_tag) { case 'B': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Byte); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = (byte) Statics.getSlotContentsAsInt(offset); break; } case 'C': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Char); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = (char) Statics.getSlotContentsAsInt(offset); break; } case 'D': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Double); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); long longValue = Statics.getSlotContentsAsLong(offset); value = Double.longBitsToDouble(longValue); break; } case 'F': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Float); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); int intValue = Statics.getSlotContentsAsInt(offset); value = Float.intBitsToFloat(intValue); break; } case 'I': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Int); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = Statics.getSlotContentsAsInt(offset); break; } case 'J': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Long); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = Statics.getSlotContentsAsLong(offset); break; } case 'S': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Short); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = (short) Statics.getSlotContentsAsInt(offset); break; } case 'Z': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Boolean); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = Statics.getSlotContentsAsInt(offset) == 1; break; } case 's': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.JavaLangString); value = RVMClass.getUtf(constantPool, input.readUnsignedShort()).toString(); break; } case 'e': { int typeNameIndex = input.readUnsignedShort(); @SuppressWarnings("unchecked") Class enumType = TypeReference.findOrCreate(classLoader, RVMClass.getUtf(constantPool, typeNameIndex)) .resolve() .getClassForType(); int constNameIndex = input.readUnsignedShort(); //noinspection unchecked value = Enum.valueOf(enumType, RVMClass.getUtf(constantPool, constNameIndex).toString()); break; } case 'c': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.JavaLangClass); int classInfoIndex = input.readUnsignedShort(); // Value should be a class but resolving the class at this point could cause infinite // recursion in class loading TypeReference unresolvedValue = TypeReference.findOrCreate( classLoader, RVMClass.getUtf(constantPool, classInfoIndex)); if (unresolvedValue.peekType() != null) { value = unresolvedValue.peekType().getClassForType(); } else { value = unresolvedValue; } break; } case '@': value = RVMAnnotation.readAnnotation(constantPool, input, classLoader); break; case '[': { int numValues = input.readUnsignedShort(); if (numValues == 0) { if (type != null) { value = Array.newInstance(type.resolve().getClassForType(), 0); } else { value = new Object[0]; } } else { byte innerElementValue_tag = input.readByte(); TypeReference innerType = type == null ? null : type.getArrayElementType(); switch (innerElementValue_tag) { case 'B': { byte[] array = new byte[numValues]; array[0] = (Byte) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Byte) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'C': { char[] array = new char[numValues]; array[0] = (Character) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Character) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'D': { double[] array = new double[numValues]; array[0] = (Double) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Double) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'F': { float[] array = new float[numValues]; array[0] = (Float) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Float) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'I': { int[] array = new int[numValues]; array[0] = (Integer) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Integer) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'J': { long[] array = new long[numValues]; array[0] = (Long) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Long) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'S': { short[] array = new short[numValues]; array[0] = (Short) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Short) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); } value = array; break; } case 'Z': { boolean[] array = new boolean[numValues]; array[0] = (Boolean) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Boolean) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 's': case '@': case 'e': case '[': { Object value1 = readValue(innerType, constantPool, input, classLoader, innerElementValue_tag); value = Array.newInstance(value1.getClass(), numValues); Array.set(value, 0, value1); for (int i = 1; i < numValues; i++) { Array.set(value, i, readValue(innerType, constantPool, input, classLoader)); } break; } case 'c': { Object value1 = readValue(innerType, constantPool, input, classLoader, innerElementValue_tag); Object[] values = new Object[numValues]; values[0] = value1; boolean allClasses = value1 instanceof Class; for (int i = 1; i < numValues; i++) { values[i] = readValue(innerType, constantPool, input, classLoader); if (allClasses && !(values[i] instanceof Class)) { allClasses = false; } } if (allClasses == true) { Class<?>[] newValues = new Class[numValues]; for (int i = 0; i < numValues; i++) { newValues[i] = (Class<?>) values[i]; } value = newValues; } else { value = values; } break; } default: throw new ClassFormatError( "Unknown element_value tag '" + (char) innerElementValue_tag + "'"); } } break; } default: throw new ClassFormatError("Unknown element_value tag '" + (char) elementValue_tag + "'"); } return value; }