< prev index next > src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
Print this page
/*
- * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
/** Access to files. */
private final JavaFileManager fileManager;
/** The tags and constants used in compressed stackmap. */
static final int SAME_FRAME_SIZE = 64;
+ static final int ASSERT_UNSET_FIELDS = 246;
static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
static final int SAME_FRAME_EXTENDED = 251;
static final int FULL_FRAME = 255;
static final int MAX_LOCAL_LENGTH_DIFF = 4;
public static String flagNames(long flags) {
StringBuilder sbuf = new StringBuilder();
int i = 0;
long f = flags & StandardFlags;
while (f != 0) {
- if ((f & 1) != 0) {
+ if ((f & 1) != 0 && flagName[i] != "") {
sbuf.append(" ");
sbuf.append(flagName[i]);
}
f = f >> 1;
i++;
return sbuf.toString();
}
//where
private static final String[] flagName = {
"PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL",
- "SUPER", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE",
+ // the empty position should be for synchronized but right now we don't have any test checking it
+ "", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE",
"ABSTRACT", "STRICTFP"};
/* ****************************************************************
* Output routines
******************************************************************/
void writeInnerClasses() {
int alenIdx = writeAttr(names.InnerClasses);
databuf.appendChar(poolWriter.innerClasses.size());
for (ClassSymbol inner : poolWriter.innerClasses) {
inner.markAbstractIfNeeded(types);
- int flags = adjustFlags(inner.flags_field);
+ int flags = adjustFlags(inner, inner.flags_field);
if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
- flags &= ~STRICTFP; //inner classes should not have the strictfp flag set.
if (dumpInnerClassModifiers) {
PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
pw.println("INNERCLASS " + inner.name);
pw.println("---" + flagNames(flags));
}
databuf.appendChar(flags);
}
endAttr(alenIdx);
}
+ /** Write out "LoadableDescriptors" attribute by enumerating the value classes encountered in field/method descriptors during this compilation.
+ */
+ void writeLoadableDescriptorsAttribute() {
+ int alenIdx = writeAttr(names.LoadableDescriptors);
+ databuf.appendChar(poolWriter.loadableDescriptors.size());
+ for (Symbol c : poolWriter.loadableDescriptors) {
+ databuf.appendChar(poolWriter.putDescriptor(c));
+ }
+ endAttr(alenIdx);
+ }
+
int writeRecordAttribute(ClassSymbol csym) {
int alenIdx = writeAttr(names.Record);
Scope s = csym.members();
databuf.appendChar(csym.getRecordComponents().size());
for (VarSymbol v: csym.getRecordComponents()) {
}
/** Write field symbol, entering all references into constant pool.
*/
void writeField(VarSymbol v) {
- int flags = adjustFlags(v.flags());
+ int flags = adjustFlags(v, v.flags());
databuf.appendChar(flags);
if (dumpFieldModifiers) {
PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
pw.println("FIELD " + v.name);
pw.println("---" + flagNames(v.flags()));
}
databuf.appendChar(poolWriter.putName(v.name));
databuf.appendChar(poolWriter.putDescriptor(v));
+ Type fldType = v.erasure(types);
+ if (fldType.requiresLoadableDescriptors(v.owner)) {
+ poolWriter.enterLoadableDescriptorsClass(fldType.tsym);
+ if (preview.isPreview(Source.Feature.VALUE_CLASSES)) {
+ preview.markUsesPreview(null);
+ }
+ }
int acountIdx = beginAttrs();
int acount = 0;
if (v.getConstValue() != null) {
int alenIdx = writeAttr(names.ConstantValue);
databuf.appendChar(poolWriter.putConstant(v.getConstValue()));
}
/** Write method symbol, entering all references into constant pool.
*/
void writeMethod(MethodSymbol m) {
- int flags = adjustFlags(m.flags());
+ int flags = adjustFlags(m, m.flags());
databuf.appendChar(flags);
if (dumpMethodModifiers) {
PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
pw.println("METHOD " + m.name);
pw.println("---" + flagNames(m.flags()));
}
databuf.appendChar(poolWriter.putName(m.name));
databuf.appendChar(poolWriter.putDescriptor(m));
+ MethodType mtype = (MethodType) m.externalType(types);
+ for (Type t : mtype.getParameterTypes()) {
+ if (t.requiresLoadableDescriptors(m.owner)) {
+ poolWriter.enterLoadableDescriptorsClass(t.tsym);
+ if (preview.isPreview(Source.Feature.VALUE_CLASSES)) {
+ preview.markUsesPreview(null);
+ }
+ }
+ }
+ Type returnType = mtype.getReturnType();
+ if (returnType.requiresLoadableDescriptors(m.owner)) {
+ poolWriter.enterLoadableDescriptorsClass(returnType.tsym);
+ if (preview.isPreview(Source.Feature.VALUE_CLASSES)) {
+ preview.markUsesPreview(null);
+ }
+ }
int acountIdx = beginAttrs();
int acount = 0;
if (m.code != null) {
int alenIdx = writeAttr(names.Code);
writeCode(m.code);
break;
case JSR202: {
Assert.checkNull(code.stackMapBuffer);
for (int i=0; i<nframes; i++) {
if (debugstackmap) System.out.print(" " + i + ":");
- StackMapTableFrame frame = code.stackMapTableBuffer[i];
+ StackMapTableEntry frame = code.stackMapTableBuffer[i];
frame.write(this);
if (debugstackmap) System.out.println();
}
break;
}
throw new AssertionError();
}
}
/** An entry in the JSR202 StackMapTable */
- abstract static class StackMapTableFrame {
- abstract int getFrameType();
+ abstract static class StackMapTableEntry {
+ abstract int getEntryType();
+ int pc;
+
+ StackMapTableEntry(int pc) {
+ this.pc = pc;
+ }
void write(ClassWriter writer) {
- int frameType = getFrameType();
- writer.databuf.appendByte(frameType);
- if (writer.debugstackmap) System.out.print(" frame_type=" + frameType);
+ int entryType = getEntryType();
+ writer.databuf.appendByte(entryType);
+ if (writer.debugstackmap) System.out.println(" frame_type=" + entryType + " bytecode offset " + pc);
}
- static class SameFrame extends StackMapTableFrame {
+ static class SameFrame extends StackMapTableEntry {
final int offsetDelta;
- SameFrame(int offsetDelta) {
+ SameFrame(int pc, int offsetDelta) {
+ super(pc);
this.offsetDelta = offsetDelta;
}
- int getFrameType() {
+ int getEntryType() {
return (offsetDelta < SAME_FRAME_SIZE) ? offsetDelta : SAME_FRAME_EXTENDED;
}
@Override
void write(ClassWriter writer) {
super.write(writer);
- if (getFrameType() == SAME_FRAME_EXTENDED) {
+ if (getEntryType() == SAME_FRAME_EXTENDED) {
writer.databuf.appendChar(offsetDelta);
if (writer.debugstackmap){
System.out.print(" offset_delta=" + offsetDelta);
}
}
}
}
- static class SameLocals1StackItemFrame extends StackMapTableFrame {
+ static class SameLocals1StackItemFrame extends StackMapTableEntry {
final int offsetDelta;
final Type stack;
- SameLocals1StackItemFrame(int offsetDelta, Type stack) {
+ SameLocals1StackItemFrame(int pc, int offsetDelta, Type stack) {
+ super(pc);
this.offsetDelta = offsetDelta;
this.stack = stack;
}
- int getFrameType() {
+ int getEntryType() {
return (offsetDelta < SAME_FRAME_SIZE) ?
(SAME_FRAME_SIZE + offsetDelta) :
SAME_LOCALS_1_STACK_ITEM_EXTENDED;
}
@Override
void write(ClassWriter writer) {
super.write(writer);
- if (getFrameType() == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
+ if (getEntryType() == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
writer.databuf.appendChar(offsetDelta);
if (writer.debugstackmap) {
System.out.print(" offset_delta=" + offsetDelta);
}
}
}
writer.writeStackMapType(stack);
}
}
- static class ChopFrame extends StackMapTableFrame {
+ static class ChopFrame extends StackMapTableEntry {
final int frameType;
final int offsetDelta;
- ChopFrame(int frameType, int offsetDelta) {
+ ChopFrame(int pc, int frameType, int offsetDelta) {
+ super(pc);
this.frameType = frameType;
this.offsetDelta = offsetDelta;
}
- int getFrameType() { return frameType; }
+ int getEntryType() { return frameType; }
@Override
void write(ClassWriter writer) {
super.write(writer);
writer.databuf.appendChar(offsetDelta);
if (writer.debugstackmap) {
System.out.print(" offset_delta=" + offsetDelta);
}
}
}
- static class AppendFrame extends StackMapTableFrame {
+ static class AppendFrame extends StackMapTableEntry {
final int frameType;
final int offsetDelta;
final Type[] locals;
- AppendFrame(int frameType, int offsetDelta, Type[] locals) {
+ AppendFrame(int pc, int frameType, int offsetDelta, Type[] locals) {
+ super(pc);
this.frameType = frameType;
this.offsetDelta = offsetDelta;
this.locals = locals;
}
- int getFrameType() { return frameType; }
+ int getEntryType() { return frameType; }
@Override
void write(ClassWriter writer) {
super.write(writer);
writer.databuf.appendChar(offsetDelta);
if (writer.debugstackmap) {
writer.writeStackMapType(locals[i]);
}
}
}
- static class FullFrame extends StackMapTableFrame {
+ static class FullFrame extends StackMapTableEntry {
final int offsetDelta;
final Type[] locals;
final Type[] stack;
- FullFrame(int offsetDelta, Type[] locals, Type[] stack) {
+ FullFrame(int pc, int offsetDelta, Type[] locals, Type[] stack) {
+ super(pc);
this.offsetDelta = offsetDelta;
this.locals = locals;
this.stack = stack;
}
- int getFrameType() { return FULL_FRAME; }
+ int getEntryType() { return FULL_FRAME; }
@Override
void write(ClassWriter writer) {
super.write(writer);
writer.databuf.appendChar(offsetDelta);
writer.databuf.appendChar(locals.length);
writer.writeStackMapType(stack[i]);
}
}
}
+ static class AssertUnsetFields extends StackMapTableEntry {
+ Set<VarSymbol> unsetFields;
+
+ AssertUnsetFields(int pc, Set<VarSymbol> unsetFields) {
+ super(pc);
+ this.unsetFields = unsetFields;
+ }
+
+ int getEntryType() { return ASSERT_UNSET_FIELDS; }
+
+ @Override
+ void write(ClassWriter writer) {
+ super.write(writer);
+ writer.databuf.appendChar(unsetFields.size());
+ if (writer.debugstackmap) {
+ System.out.println(" # writing: AssertUnsetFields stackmap entry with " + unsetFields.size() + " fields");
+ }
+ for (VarSymbol vsym : unsetFields) {
+ int index = writer.poolWriter.putNameAndType(vsym);
+ writer.databuf.appendChar(index);
+ if (writer.debugstackmap) {
+ System.out.println(" #writing unset field: " + index + ", with name: " + vsym.name.toString());
+ }
+ }
+ }
+ }
+
/** Compare this frame with the previous frame and produce
* an entry of compressed stack map frame. */
- static StackMapTableFrame getInstance(Code.StackMapFrame this_frame,
- int prev_pc,
- Type[] prev_locals,
- Types types) {
+ static StackMapTableEntry getInstance(Code.StackMapFrame this_frame,
+ Code.StackMapFrame prevFrame,
+ Types types,
+ int pc) {
Type[] locals = this_frame.locals;
Type[] stack = this_frame.stack;
- int offset_delta = this_frame.pc - prev_pc - 1;
+ int offset_delta = this_frame.pc - prevFrame.pc - 1;
if (stack.length == 1) {
- if (locals.length == prev_locals.length
- && compare(prev_locals, locals, types) == 0) {
- return new SameLocals1StackItemFrame(offset_delta, stack[0]);
+ if (locals.length == prevFrame.locals.length
+ && compare(prevFrame.locals, locals, types) == 0) {
+ return new SameLocals1StackItemFrame(pc, offset_delta, stack[0]);
}
} else if (stack.length == 0) {
- int diff_length = compare(prev_locals, locals, types);
+ int diff_length = compare(prevFrame.locals, locals, types);
if (diff_length == 0) {
- return new SameFrame(offset_delta);
+ return new SameFrame(pc, offset_delta);
} else if (-MAX_LOCAL_LENGTH_DIFF < diff_length && diff_length < 0) {
// APPEND
Type[] local_diff = new Type[-diff_length];
- for (int i=prev_locals.length, j=0; i<locals.length; i++,j++) {
+ for (int i=prevFrame.locals.length, j=0; i<locals.length; i++,j++) {
local_diff[j] = locals[i];
}
- return new AppendFrame(SAME_FRAME_EXTENDED - diff_length,
+ return new AppendFrame(pc, SAME_FRAME_EXTENDED - diff_length,
offset_delta,
local_diff);
} else if (0 < diff_length && diff_length < MAX_LOCAL_LENGTH_DIFF) {
// CHOP
- return new ChopFrame(SAME_FRAME_EXTENDED - diff_length,
+ return new ChopFrame(pc, SAME_FRAME_EXTENDED - diff_length,
offset_delta);
}
}
// FULL_FRAME
- return new FullFrame(offset_delta, locals, stack);
+ return new FullFrame(pc, offset_delta, locals, stack);
}
static boolean isInt(Type t) {
return (t.getTag().isStrictSubRangeOf(INT) || t.hasTag(BOOLEAN));
}
int flags;
if (c.owner.kind == MDL) {
flags = ACC_MODULE;
} else {
- flags = adjustFlags(c.flags() & ~DEFAULT);
+ long originalFlags = c.flags();
+ flags = adjustFlags(c, c.flags() & ~(DEFAULT | STRICTFP));
if ((flags & PROTECTED) != 0) flags |= PUBLIC;
- flags = flags & ClassFlags & ~STRICTFP;
- if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
+ flags = flags & ClassFlags;
+ flags |= (originalFlags & IDENTITY_TYPE) != 0 ? ACC_IDENTITY : flags;
}
if (dumpClassModifiers) {
PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
pw.println();
if (!poolWriter.innerClasses.isEmpty()) {
writeInnerClasses();
acount++;
}
+ if (!poolWriter.loadableDescriptors.isEmpty()) {
+ writeLoadableDescriptorsAttribute();
+ acount++;
+ }
+
endAttrs(acountIdx, acount);
out.write(poolbuf.elems, 0, poolbuf.length);
poolWriter.writePool(out);
i += hook.applyAsInt(sym);
}
return i;
}
- int adjustFlags(final long flags) {
+ int adjustFlags(Symbol sym, final long flags) {
int result = (int)flags;
// Elide strictfp bit in class files
if (target.obsoleteAccStrict())
result &= ~STRICTFP;
result |= ACC_BRIDGE;
if ((flags & VARARGS) != 0)
result |= ACC_VARARGS;
if ((flags & DEFAULT) != 0)
result &= ~ABSTRACT;
+ if ((flags & IDENTITY_TYPE) != 0) {
+ result |= ACC_IDENTITY;
+ }
+ if (sym.kind == VAR) {
+ if ((flags & STRICT) != 0) {
+ result |= ACC_STRICT;
+ }
+ }
return result;
}
long getLastModified(FileObject filename) {
return filename.getLastModified();
< prev index next >