Skip to content

Commit a25b67d

Browse files
committed
Move constant initialization into nested classes
1 parent ecf0b55 commit a25b67d

File tree

3 files changed

+95
-68
lines changed

3 files changed

+95
-68
lines changed

build.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
description="Compile Java sources.">
4242
<javac srcdir="${jsrc}" destdir="${build}" includeJavaRuntime="yes"
4343
includeAntRuntime="false"
44-
debug="true" source="1.8" target="1.8"/>
44+
debug="true" release="17"/>
4545
</target>
4646

4747
<target name="compile-clojure"
@@ -99,7 +99,7 @@
9999
unless="maven.test.skip">
100100
<mkdir dir="${test-classes}"/>
101101
<javac srcdir="${jtestsrc}" destdir="${test-classes}" includeJavaRuntime="yes"
102-
debug="true" source="1.8" target="1.8" includeantruntime="no"/>
102+
debug="true" release="17" includeantruntime="no"/>
103103
<echo>Direct linking = ${directlinking}</echo>
104104
<java classname="clojure.lang.Compile"
105105
classpath="${test-classes}:${test}:${build}:${cljsrc}:${maven.test.classpath}"

pom.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,7 @@
105105
<artifactId>maven-compiler-plugin</artifactId>
106106
<version>3.13.0</version>
107107
<configuration>
108-
<source>1.8</source>
109-
<target>1.8</target>
108+
<release>17</release>
110109
<encoding>UTF-8</encoding>
111110
</configuration>
112111
</plugin>

src/jvm/clojure/lang/Compiler.java

Lines changed: 92 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4786,6 +4786,7 @@ public final int constantsID(){
47864786

47874787
private DynamicClassLoader loader;
47884788
private byte[] bytecode;
4789+
Map<String, byte[]> constFieldBytecode;
47894790

47904791
public ObjExpr(Object tag){
47914792
this.tag = tag;
@@ -4824,7 +4825,7 @@ void compile(String superName, String[] interfaceNames, boolean oneTimeUse) thro
48244825
ClassVisitor cv = cw;
48254826
// ClassVisitor cv = new TraceClassVisitor(new CheckClassAdapter(cw), new PrintWriter(System.out));
48264827
//ClassVisitor cv = new TraceClassVisitor(cw, new PrintWriter(System.out));
4827-
cv.visit(V1_8, ACC_PUBLIC + ACC_SUPER + ACC_FINAL, internalName, null,superName,interfaceNames);
4828+
cv.visit(V17, ACC_PUBLIC + ACC_SUPER + ACC_FINAL, internalName, null,superName,interfaceNames);
48284829
// superName != null ? superName :
48294830
// (isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFunction"), null);
48304831
String source = (String) SOURCE.deref();
@@ -5096,14 +5097,7 @@ void compile(String superName, String[] interfaceNames, boolean oneTimeUse) thro
50965097
emitStatics(cv);
50975098
emitMethods(cv);
50985099

5099-
//static fields for constants
5100-
for(int i = 0; i < constants.count(); i++)
5101-
{
5102-
if(usedConstants.contains(i))
5103-
cv.visitField(ACC_PUBLIC + ACC_FINAL
5104-
+ ACC_STATIC, constantName(i), constantType(i).getDescriptor(),
5105-
null, null);
5106-
}
5100+
emitConstantFields(cv);
51075101

51085102
//static fields for lookup sites
51095103
for(int i = 0; i < keywordCallsites.count(); i++)
@@ -5124,11 +5118,6 @@ void compile(String superName, String[] interfaceNames, boolean oneTimeUse) thro
51245118
clinitgen.visitCode();
51255119
clinitgen.visitLineNumber(line, clinitgen.mark());
51265120

5127-
if(constants.count() > 0)
5128-
{
5129-
emitConstants(clinitgen);
5130-
}
5131-
51325121
if(keywordCallsites.count() > 0)
51335122
emitKeywordCallsites(clinitgen);
51345123

@@ -5183,8 +5172,16 @@ void compile(String superName, String[] interfaceNames, boolean oneTimeUse) thro
51835172
cv.visitEnd();
51845173

51855174
bytecode = cw.toByteArray();
5186-
if(RT.booleanCast(COMPILE_FILES.deref()))
5175+
if(RT.booleanCast(COMPILE_FILES.deref())) {
51875176
writeClassFile(internalName, bytecode);
5177+
if (constFieldBytecode != null) {
5178+
for (Map.Entry<String, byte[]> entry : constFieldBytecode.entrySet()) {
5179+
String constName = entry.getKey();
5180+
byte[] constBytecode = entry.getValue();
5181+
writeClassFile(constName, constBytecode);
5182+
}
5183+
}
5184+
}
51885185
// else
51895186
// getCompiledClass();
51905187
}
@@ -5438,6 +5435,62 @@ else if(value instanceof Pattern)
54385435
}
54395436
}
54405437

5438+
void emitConstantFields(ClassVisitor cv) throws IOException {
5439+
if (constants.count() > 0) {
5440+
Map<String, byte[]> tempFieldBytecode = new HashMap<>();
5441+
final int INITS_PER = 100;
5442+
int numInits = constants.count() / INITS_PER;
5443+
if (constants.count() % INITS_PER != 0)
5444+
++numInits;
5445+
5446+
for (int n = 0; n < numInits; n++) {
5447+
int containerStart = n * INITS_PER;
5448+
Type inner_type = constantContainer(containerStart);
5449+
5450+
cv.visitInnerClass(inner_type.getInternalName(),
5451+
objtype.getInternalName(),
5452+
constantContainerName(containerStart),
5453+
ACC_STATIC + ACC_FINAL);
5454+
5455+
ClassWriter inner_cw = classWriter();
5456+
ClassVisitor inner_cv = inner_cw;
5457+
inner_cv.visit(V17, ACC_PUBLIC + ACC_SUPER, inner_type.getInternalName(), null, "java/lang/Object", null);
5458+
5459+
//static fields for constants
5460+
for (int i = n * INITS_PER; i < constants.count() && i < (n + 1) * INITS_PER; i++) {
5461+
if (usedConstants.contains(i))
5462+
inner_cv.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, constantName(i), constantType(i).getDescriptor(),
5463+
null, null);
5464+
}
5465+
5466+
GeneratorAdapter clinitgen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC,
5467+
Method.getMethod("void <clinit> ()"),
5468+
null,
5469+
null,
5470+
inner_cv);
5471+
5472+
clinitgen.visitCode();
5473+
try {
5474+
Var.pushThreadBindings(RT.map(RT.PRINT_DUP, RT.T));
5475+
5476+
for (int i = n * INITS_PER; i < constants.count() && i < (n + 1) * INITS_PER; i++) {
5477+
if (usedConstants.contains(i)) {
5478+
emitValue(constants.nth(i), clinitgen);
5479+
clinitgen.checkCast(constantType(i));
5480+
clinitgen.putStatic(constantContainer(i), constantName(i), constantType(i));
5481+
}
5482+
}
5483+
} finally {
5484+
Var.popThreadBindings();
5485+
}
5486+
clinitgen.returnValue();
5487+
clinitgen.endMethod();
5488+
inner_cv.visitEnd();
5489+
tempFieldBytecode.put(inner_type.getInternalName(), inner_cw.toByteArray());
5490+
}
5491+
constFieldBytecode = tempFieldBytecode;
5492+
}
5493+
}
54415494

54425495
void emitConstants(GeneratorAdapter clinitgen){
54435496
try
@@ -5500,6 +5553,10 @@ synchronized Class getCompiledClass(){
55005553
// else
55015554
{
55025555
loader = (DynamicClassLoader) LOADER.deref();
5556+
if (constFieldBytecode != null)
5557+
constFieldBytecode.forEach((constName, constBytecode) -> {
5558+
loader.defineClass(constName.replace("/", "."), constBytecode, src);
5559+
});
55035560
compiledClass = loader.defineClass(name, bytecode, src);
55045561
}
55055562
return compiledClass;
@@ -5650,7 +5707,7 @@ private void emitLocal(GeneratorAdapter gen, LocalBinding lb, boolean clear){
56505707
{
56515708
// System.out.println("use: " + rep);
56525709
}
5653-
}
5710+
}
56545711
}
56555712
else
56565713
{
@@ -5722,9 +5779,18 @@ public void emitKeyword(GeneratorAdapter gen, Keyword k){
57225779

57235780
public void emitConstant(GeneratorAdapter gen, int id){
57245781
usedConstants = (IPersistentSet) usedConstants.cons(id);
5725-
gen.getStatic(objtype, constantName(id), constantType(id));
5782+
gen.getStatic(constantContainer(id), constantName(id), constantType(id));
5783+
}
5784+
5785+
public static final int INITS_PER = 100;
5786+
5787+
public Type constantContainer(int id) {
5788+
return Type.getObjectType(objtype.getInternalName() + "$" + constantContainerName(id));
57265789
}
57275790

5791+
public String constantContainerName(int id) {
5792+
return "ID_" + (id / INITS_PER);
5793+
}
57285794

57295795
String constantName(int id){
57305796
return CONST_PREFIX + id;
@@ -8308,7 +8374,7 @@ CONSTANT_IDS, new IdentityHashMap(),
83088374
objx.objtype = Type.getObjectType(objx.internalName);
83098375
ClassWriter cw = classWriter();
83108376
ClassVisitor cv = cw;
8311-
cv.visit(V1_8, ACC_PUBLIC + ACC_SUPER, objx.internalName, null, "java/lang/Object", null);
8377+
cv.visit(V17, ACC_PUBLIC + ACC_SUPER, objx.internalName, null, "java/lang/Object", null);
83128378

83138379
//static load method
83148380
GeneratorAdapter gen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC,
@@ -8332,48 +8398,7 @@ CONSTANT_IDS, new IdentityHashMap(),
83328398
gen.returnValue();
83338399
gen.endMethod();
83348400

8335-
//static fields for constants
8336-
for(int i = 0; i < objx.constants.count(); i++)
8337-
{
8338-
if(objx.usedConstants.contains(i))
8339-
cv.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, objx.constantName(i), objx.constantType(i).getDescriptor(),
8340-
null, null);
8341-
}
8342-
8343-
final int INITS_PER = 100;
8344-
int numInits = objx.constants.count() / INITS_PER;
8345-
if(objx.constants.count() % INITS_PER != 0)
8346-
++numInits;
8347-
8348-
for(int n = 0;n<numInits;n++)
8349-
{
8350-
GeneratorAdapter clinitgen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC,
8351-
Method.getMethod("void __init" + n + "()"),
8352-
null,
8353-
null,
8354-
cv);
8355-
clinitgen.visitCode();
8356-
try
8357-
{
8358-
Var.pushThreadBindings(RT.map(RT.PRINT_DUP, RT.T));
8359-
8360-
for(int i = n*INITS_PER; i < objx.constants.count() && i < (n+1)*INITS_PER; i++)
8361-
{
8362-
if(objx.usedConstants.contains(i))
8363-
{
8364-
objx.emitValue(objx.constants.nth(i), clinitgen);
8365-
clinitgen.checkCast(objx.constantType(i));
8366-
clinitgen.putStatic(objx.objtype, objx.constantName(i), objx.constantType(i));
8367-
}
8368-
}
8369-
}
8370-
finally
8371-
{
8372-
Var.popThreadBindings();
8373-
}
8374-
clinitgen.returnValue();
8375-
clinitgen.endMethod();
8376-
}
8401+
objx.emitConstantFields(cv);
83778402

83788403
//static init for constants, keywords and vars
83798404
GeneratorAdapter clinitgen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC,
@@ -8391,8 +8416,6 @@ CONSTANT_IDS, new IdentityHashMap(),
83918416
// {
83928417
// objx.emitConstants(clinitgen);
83938418
// }
8394-
for(int n = 0;n<numInits;n++)
8395-
clinitgen.invokeStatic(objx.objtype, Method.getMethod("void __init" + n + "()"));
83968419

83978420
clinitgen.push(objx.internalName.replace('/','.'));
83988421
clinitgen.invokeStatic(RT_TYPE, Method.getMethod("Class classForName(String)"));
@@ -8418,7 +8441,12 @@ CONSTANT_IDS, new IdentityHashMap(),
84188441
//end of class
84198442
cv.visitEnd();
84208443

8421-
writeClassFile(objx.internalName, cw.toByteArray());
8444+
for (Map.Entry<String, byte[]> entry : objx.constFieldBytecode.entrySet()) {
8445+
String constName = entry.getKey();
8446+
byte[] constBytecode = entry.getValue();
8447+
writeClassFile(constName, constBytecode);
8448+
}
8449+
writeClassFile(objx.internalName, cw.toByteArray());
84228450
}
84238451
catch(LispReader.ReaderException e)
84248452
{
@@ -8628,7 +8656,7 @@ VAR_CALLSITES, emptyVarCallSites(),
86288656
static Class compileStub(String superName, NewInstanceExpr ret, String[] interfaceNames, Object frm){
86298657
ClassWriter cw = classWriter();
86308658
ClassVisitor cv = cw;
8631-
cv.visit(V1_8, ACC_PUBLIC + ACC_SUPER, COMPILE_STUB_PREFIX + "/" + ret.internalName,
8659+
cv.visit(V17, ACC_PUBLIC + ACC_SUPER, COMPILE_STUB_PREFIX + "/" + ret.internalName,
86328660
null,superName,interfaceNames);
86338661

86348662
//instance fields for closed-overs

0 commit comments

Comments
 (0)