Obtain class file version from GenerationState

This commit is contained in:
Michael Bogdanov
2016-04-12 14:44:14 +03:00
committed by Mikhael Bogdanov
parent 77a386a266
commit 96f892d60c
15 changed files with 25 additions and 19 deletions
@@ -150,7 +150,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
} }
v.defineClass(element, v.defineClass(element,
V1_6, state.getClassFileVersion(),
ACC_FINAL | ACC_SUPER | visibilityFlag, ACC_FINAL | ACC_SUPER | visibilityFlag,
asmType.getInternalName(), asmType.getInternalName(),
sw.makeJavaGenericSignature(), sw.makeJavaGenericSignature(),
@@ -211,7 +211,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
v.defineClass( v.defineClass(
myClass, V1_6, myClass,
state.getClassFileVersion(),
access, access,
signature.getName(), signature.getName(),
signature.getJavaGenericSignature(), signature.getJavaGenericSignature(),
@@ -49,7 +49,7 @@ class InterfaceImplBodyCodegen(
override fun generateDeclaration() { override fun generateDeclaration() {
v.defineClass( v.defineClass(
myClass, V1_6, ACC_PUBLIC or ACC_FINAL or ACC_SUPER, myClass, state.classFileVersion, ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
typeMapper.mapDefaultImpls(descriptor).internalName, typeMapper.mapDefaultImpls(descriptor).internalName,
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
) )
@@ -134,7 +134,7 @@ class MultifileClassCodegen(
J_L_OBJECT J_L_OBJECT
state.factory.newVisitor(declarationOrigin, facadeClassType, files).apply { state.factory.newVisitor(declarationOrigin, facadeClassType, files).apply {
defineClass(singleSourceFile, Opcodes.V1_6, FACADE_CLASS_ATTRIBUTES, defineClass(singleSourceFile, state.classFileVersion, FACADE_CLASS_ATTRIBUTES,
facadeClassType.internalName, null, superClassForFacade, ArrayUtil.EMPTY_STRING_ARRAY) facadeClassType.internalName, null, superClassForFacade, ArrayUtil.EMPTY_STRING_ARRAY)
if (singleSourceFile != null) { if (singleSourceFile != null) {
visitSource(singleSourceFile.name, null) visitSource(singleSourceFile.name, null)
@@ -64,7 +64,7 @@ class MultifileClassPartCodegen(
private val staticInitClassBuilder = ClassBuilderOnDemand { private val staticInitClassBuilder = ClassBuilderOnDemand {
state.factory.newVisitor(MultifileClass(file, packageFragment), staticInitClassType, file).apply { state.factory.newVisitor(MultifileClass(file, packageFragment), staticInitClassType, file).apply {
defineClass(file, Opcodes.V1_6, STATE_INITIALIZER_CLASS_ATTRIBUTES, defineClass(file, state.classFileVersion, STATE_INITIALIZER_CLASS_ATTRIBUTES,
staticInitClassType.internalName, null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY) staticInitClassType.internalName, null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY)
visitSource(file.name, null) visitSource(file.name, null)
@@ -119,7 +119,7 @@ class MultifileClassPartCodegen(
} }
override fun generateDeclaration() { override fun generateDeclaration() {
v.defineClass(element, Opcodes.V1_6, partClassAttributes, partType.internalName, null, superClassInternalName, ArrayUtil.EMPTY_STRING_ARRAY) v.defineClass(element, state.classFileVersion, partClassAttributes, partType.internalName, null, superClassInternalName, ArrayUtil.EMPTY_STRING_ARRAY)
v.visitSource(element.name, null) v.visitSource(element.name, null)
generatePropertyMetadataArrayFieldIfNeeded(partType) generatePropertyMetadataArrayFieldIfNeeded(partType)
@@ -62,7 +62,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
@Override @Override
protected void generateDeclaration() { protected void generateDeclaration() {
v.defineClass(element, V1_6, v.defineClass(element, state.getClassFileVersion(),
ACC_PUBLIC | ACC_FINAL | ACC_SUPER, ACC_PUBLIC | ACC_FINAL | ACC_SUPER,
packagePartType.getInternalName(), packagePartType.getInternalName(),
null, null,
@@ -82,7 +82,7 @@ class PropertyReferenceCodegen(
override fun generateDeclaration() { override fun generateDeclaration() {
v.defineClass( v.defineClass(
element, element,
V1_6, state.classFileVersion,
ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForClass(classDescriptor), ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForClass(classDescriptor),
asmType.internalName, asmType.internalName,
null, null,
@@ -97,7 +97,7 @@ public class SamWrapperCodegen {
ClassBuilder cv = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(erasedInterfaceFunction), asmType, file); ClassBuilder cv = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(erasedInterfaceFunction), asmType, file);
cv.defineClass(file, cv.defineClass(file,
V1_6, state.getClassFileVersion(),
ACC_FINAL | ACC_SUPER | visibility, ACC_FINAL | ACC_SUPER | visibility,
asmType.getInternalName(), asmType.getInternalName(),
null, null,
@@ -89,7 +89,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
@Override @Override
protected void generateDeclaration() { protected void generateDeclaration() {
v.defineClass(scriptDeclaration, v.defineClass(scriptDeclaration,
V1_6, state.getClassFileVersion(),
ACC_PUBLIC | ACC_SUPER, ACC_PUBLIC | ACC_SUPER,
classAsmType.getInternalName(), classAsmType.getInternalName(),
null, null,
@@ -65,7 +65,7 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
createClassReader().accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) { createClassReader().accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
@Override @Override
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) { public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name); InlineCodegenUtil.assertVersionNotGreaterThanGeneratedOne(version, name, inliningContext.state);
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces); classBuilder.defineClass(null, version, access, name, signature, superName, interfaces);
} }
@@ -261,7 +261,7 @@ public class InlineCodegen extends CallGenerator {
} }
}); });
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId); return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId, state);
} }
assert functionDescriptor instanceof DeserializedSimpleFunctionDescriptor : "Not a deserialized function: " + functionDescriptor; assert functionDescriptor instanceof DeserializedSimpleFunctionDescriptor : "Not a deserialized function: " + functionDescriptor;
@@ -287,7 +287,8 @@ public class InlineCodegen extends CallGenerator {
} }
}); });
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId);
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId, state);
} }
@NotNull @NotNull
@@ -82,7 +82,8 @@ public class InlineCodegenUtil {
byte[] classData, byte[] classData,
final String methodName, final String methodName,
final String methodDescriptor, final String methodDescriptor,
ClassId classId ClassId classId,
final @NotNull GenerationState state
) { ) {
ClassReader cr = new ClassReader(classData); ClassReader cr = new ClassReader(classData);
final MethodNode[] node = new MethodNode[1]; final MethodNode[] node = new MethodNode[1];
@@ -94,7 +95,7 @@ public class InlineCodegenUtil {
cr.accept(new ClassVisitor(API) { cr.accept(new ClassVisitor(API) {
@Override @Override
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) { public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
assertVersionNotGreaterThanJava6(version, name); assertVersionNotGreaterThanGeneratedOne(version, name, state);
} }
@Override @Override
@@ -140,9 +141,9 @@ public class InlineCodegenUtil {
return new SMAPAndMethodNode(node[0], smap); return new SMAPAndMethodNode(node[0], smap);
} }
public static void assertVersionNotGreaterThanJava6(int version, String internalName) { public static void assertVersionNotGreaterThanGeneratedOne(int version, String internalName, @NotNull GenerationState state) {
// TODO: report a proper diagnostic // TODO: report a proper diagnostic
if (version > Opcodes.V1_6 && !"true".equals(System.getProperty("kotlin.skip.bytecode.version.check"))) { if (version > state.getClassFileVersion() && !"true".equals(System.getProperty("kotlin.skip.bytecode.version.check"))) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Cannot inline bytecode of class " + internalName + " which has version " + version + ". " + "Cannot inline bytecode of class " + internalName + " which has version " + version + ". " +
"This compiler can only inline Java 1.6 bytecode (version " + Opcodes.V1_6 + ")" "This compiler can only inline Java 1.6 bytecode (version " + Opcodes.V1_6 + ")"
@@ -66,7 +66,7 @@ class WhenMappingTransformer(
val fieldNode = transformationInfo.fieldNode val fieldNode = transformationInfo.fieldNode
classReader.accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) { classReader.accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) {
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) { override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name) InlineCodegenUtil.assertVersionNotGreaterThanGeneratedOne(version, name, state)
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces) classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
} }
@@ -48,6 +48,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.org.objectweb.asm.Opcodes
import java.io.File import java.io.File
class GenerationState @JvmOverloads constructor( class GenerationState @JvmOverloads constructor(
@@ -157,6 +158,8 @@ class GenerationState @JvmOverloads constructor(
val rootContext: CodegenContext<*> = RootContext(this) val rootContext: CodegenContext<*> = RootContext(this)
val classFileVersion: Int = Opcodes.V1_6
init { init {
this.interceptedBuilderFactory = builderFactory this.interceptedBuilderFactory = builderFactory
.wrapWith( .wrapWith(
@@ -46,7 +46,7 @@ public class MappingClassesForWhenByEnumCodegen {
ClassBuilder cb = state.getFactory().newVisitor(JvmDeclarationOrigin.NO_ORIGIN, mappingsClass, srcFile); ClassBuilder cb = state.getFactory().newVisitor(JvmDeclarationOrigin.NO_ORIGIN, mappingsClass, srcFile);
cb.defineClass( cb.defineClass(
srcFile, srcFile,
V1_6, state.getClassFileVersion(),
ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_SYNTHETIC, ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_SYNTHETIC,
mappingsClass.getInternalName(), mappingsClass.getInternalName(),
null, null,