Skip to content

Commit 6c47754

Browse files
authored
Handle volatile fields with C atomics (#4354)
* Handle volatile fields with C atomics * Fix pointer casts for volatile field accessors
1 parent 8936bf9 commit 6c47754

File tree

3 files changed

+110
-47
lines changed

3 files changed

+110
-47
lines changed

vm/ByteCodeTranslator/src/cn1_globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <pthread.h>
88
#include <setjmp.h>
99
#include <math.h>
10+
#include <stdatomic.h>
1011

1112
//#define DEBUG_GC_ALLOCATIONS
1213

vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeClass.java

Lines changed: 96 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -694,28 +694,36 @@ public String generateCCode(List<ByteCodeClass> allClasses) {
694694
}
695695
b.append(";\n}\n\n");
696696
} else {
697-
b.append(bf.getCDefinition());
697+
b.append(bf.getCStorageDefinition());
698698
b.append(" STATIC_FIELD_");
699699
b.append(clsName);
700700
b.append("_");
701701
b.append(bf.getFieldName());
702702
b.append(" = 0;\n");
703703

704-
// static getter
704+
// static getter
705705
b.append(bf.getCDefinition());
706706
b.append(" get_static_");
707707
b.append(clsName);
708708
b.append("_");
709709
b.append(bf.getFieldName().replace('$', '_'));
710710
b.append("(CODENAME_ONE_THREAD_STATE) {\n __STATIC_INITIALIZER_");
711711
b.append(bf.getClsName());
712-
b.append("(threadStateData);\n return STATIC_FIELD_");
713-
b.append(bf.getClsName());
714-
b.append("_");
715-
b.append(bf.getFieldName());
716-
b.append(";\n}\n\n");
712+
if (bf.isVolatile()) {
713+
b.append("(threadStateData);\n return atomic_load(&STATIC_FIELD_");
714+
b.append(bf.getClsName());
715+
b.append("_");
716+
b.append(bf.getFieldName());
717+
b.append(");\n}\n\n");
718+
} else {
719+
b.append("(threadStateData);\n return STATIC_FIELD_");
720+
b.append(bf.getClsName());
721+
b.append("_");
722+
b.append(bf.getFieldName());
723+
b.append(";\n}\n\n");
724+
}
717725

718-
// static setter
726+
// static setter
719727
b.append("void set_static_");
720728
b.append(clsName);
721729
b.append("_");
@@ -724,30 +732,31 @@ public String generateCCode(List<ByteCodeClass> allClasses) {
724732
b.append(bf.getCDefinition());
725733
b.append(" __cn1StaticVal) {\n __STATIC_INITIALIZER_");
726734
b.append(bf.getClsName());
727-
if(bf.isObjectType()) {
728-
if(bf.isFinal()) {
729-
b.append("(threadStateData);\n STATIC_FIELD_");
730-
} else {
731-
b.append("(threadStateData);\n STATIC_FIELD_");
732-
}
735+
if (bf.isVolatile()) {
736+
b.append("(threadStateData);\n atomic_store(&STATIC_FIELD_");
737+
b.append(bf.getClsName());
738+
b.append("_");
739+
b.append(bf.getFieldName());
740+
b.append(", __cn1StaticVal);");
733741
} else {
734742
b.append("(threadStateData);\n STATIC_FIELD_");
743+
b.append(bf.getClsName());
744+
b.append("_");
745+
b.append(bf.getFieldName());
746+
b.append(" = __cn1StaticVal;");
735747
}
736-
b.append(bf.getClsName());
737-
b.append("_");
738-
b.append(bf.getFieldName());
739748
if(bf.shouldRemoveFromHeapCollection()) {
740749
if(bf.getType() != null && bf.getType().endsWith("String")) {
741-
b.append(" = __cn1StaticVal;\n removeObjectFromHeapCollection(threadStateData, __cn1StaticVal);\n if(__cn1StaticVal != 0) {\n removeObjectFromHeapCollection(threadStateData, ((struct obj__java_lang_String*)__cn1StaticVal)->java_lang_String_value);\n }\n}\n\n");
750+
b.append("\n removeObjectFromHeapCollection(threadStateData, __cn1StaticVal);\n if(__cn1StaticVal != 0) {\n removeObjectFromHeapCollection(threadStateData, ((struct obj__java_lang_String*)__cn1StaticVal)->java_lang_String_value);\n }\n}\n\n");
742751
} else {
743-
b.append(" = __cn1StaticVal;\n removeObjectFromHeapCollection(threadStateData, __cn1StaticVal);\n}\n\n");
752+
b.append("\n removeObjectFromHeapCollection(threadStateData, __cn1StaticVal);\n}\n\n");
744753
}
745754
} else {
746-
b.append(" = __cn1StaticVal;\n}\n\n");
755+
b.append("\n}\n\n");
747756
}
748757
}
749758
}
750-
}
759+
}
751760

752761
if(isInterface) {
753762
b.append("int **classToInterfaceMap_");
@@ -768,13 +777,24 @@ public String generateCCode(List<ByteCodeClass> allClasses) {
768777
b.append(clsName);
769778
b.append("_");
770779
b.append(fld.getFieldName());
771-
b.append("(JAVA_OBJECT __cn1T) {\n ").append(nullCheck).append(" return (*(struct obj__");
772-
b.append(clsName);
773-
b.append("*)__cn1T).");
774-
b.append(fld.getClsName());
775-
b.append("_");
776-
b.append(fld.getFieldName());
777-
b.append(";\n}\n\n");
780+
b.append("(JAVA_OBJECT __cn1T) {\n ").append(nullCheck).append(" ");
781+
if (fld.isVolatile()) {
782+
b.append("return atomic_load(&((struct obj__");
783+
b.append(clsName);
784+
b.append("*)__cn1T)->");
785+
b.append(fld.getClsName());
786+
b.append("_");
787+
b.append(fld.getFieldName());
788+
b.append(");\n}\n\n");
789+
} else {
790+
b.append("return ((struct obj__");
791+
b.append(clsName);
792+
b.append("*)__cn1T)->");
793+
b.append(fld.getClsName());
794+
b.append("_");
795+
b.append(fld.getFieldName());
796+
b.append(";\n}\n\n");
797+
}
778798

779799
b.append("void set_field_");
780800
b.append(clsName);
@@ -783,16 +803,27 @@ public String generateCCode(List<ByteCodeClass> allClasses) {
783803
b.append("(CODENAME_ONE_THREAD_STATE, ");
784804
b.append(fld.getCDefinition());
785805
if(fld.isObjectType()) {
786-
b.append(" __cn1Val, JAVA_OBJECT __cn1T) {\n ").append(nullCheck).append(" (*(struct obj__");
806+
b.append(" __cn1Val, JAVA_OBJECT __cn1T) {\n ").append(nullCheck).append(" ");
787807
} else {
788-
b.append(" __cn1Val, JAVA_OBJECT __cn1T) {\n ").append(nullCheck).append(" (*(struct obj__");
808+
b.append(" __cn1Val, JAVA_OBJECT __cn1T) {\n ").append(nullCheck).append(" ");
809+
}
810+
if (fld.isVolatile()) {
811+
b.append("atomic_store(&((struct obj__");
812+
b.append(clsName);
813+
b.append("*)__cn1T)->");
814+
b.append(fld.getClsName());
815+
b.append("_");
816+
b.append(fld.getFieldName());
817+
b.append(", __cn1Val);\n}\n\n");
818+
} else {
819+
b.append("((struct obj__");
820+
b.append(clsName);
821+
b.append("*)__cn1T)->");
822+
b.append(fld.getClsName());
823+
b.append("_");
824+
b.append(fld.getFieldName());
825+
b.append(" = __cn1Val;\n}\n\n");
789826
}
790-
b.append(clsName);
791-
b.append("*)__cn1T).");
792-
b.append(fld.getClsName());
793-
b.append("_");
794-
b.append(fld.getFieldName());
795-
b.append(" = __cn1Val;\n}\n\n");
796827
}
797828

798829

@@ -824,10 +855,19 @@ public String generateCCode(List<ByteCodeClass> allClasses) {
824855
b.append("*)objToMark;\n");
825856
for(ByteCodeField fld : fullFieldList) {
826857
if(!fld.isStaticField() && fld.isObjectType() && fld.getClsName().equals(clsName)) {
827-
b.append(" gcMarkObject(threadStateData, objInstance->");
828-
b.append(fld.getClsName());
829-
b.append("_");
830-
b.append(fld.getFieldName());
858+
b.append(" gcMarkObject(threadStateData, ");
859+
if (fld.isVolatile()) {
860+
b.append("atomic_load(&objInstance->");
861+
b.append(fld.getClsName());
862+
b.append("_");
863+
b.append(fld.getFieldName());
864+
b.append(")");
865+
} else {
866+
b.append("objInstance->");
867+
b.append(fld.getClsName());
868+
b.append("_");
869+
b.append(fld.getFieldName());
870+
}
831871
b.append(", force);\n");
832872
}
833873
}
@@ -1196,7 +1236,7 @@ private void addFields(StringBuilder b) {
11961236
for(ByteCodeField bf : fields) {
11971237
if(!bf.isStaticField()) {
11981238
b.append(" ");
1199-
b.append(bf.getCDefinition());
1239+
b.append(bf.getCStorageDefinition());
12001240
b.append(" ");
12011241
b.append(clsName);
12021242
b.append("_");
@@ -1335,7 +1375,7 @@ public String generateCHeader() {
13351375
b.append("();\n");
13361376
if(!(bf.isFinal() && bf.getValue() != null && !writableFields.contains(bf.getFieldName()))) {
13371377
b.append("extern ");
1338-
b.append(bf.getCDefinition());
1378+
b.append(bf.getCStorageDefinition());
13391379
b.append(" STATIC_FIELD_");
13401380
b.append(clsName);
13411381
b.append("_");
@@ -1741,7 +1781,7 @@ public void appendStaticFieldsExtern(StringBuilder b) {
17411781
for(ByteCodeField bf : fields) {
17421782
if(bf.isStaticField() && bf.isObjectType() && !bf.shouldRemoveFromHeapCollection()) {
17431783
b.append("extern ");
1744-
b.append(bf.getCDefinition());
1784+
b.append(bf.getCStorageDefinition());
17451785
b.append(" STATIC_FIELD_");
17461786
b.append(clsName);
17471787
b.append("_");
@@ -1767,10 +1807,19 @@ private boolean isTrulyFinal(ByteCodeField bf) {
17671807
public void appendStaticFieldsMark(StringBuilder b) {
17681808
for(ByteCodeField bf : fields) {
17691809
if(bf.isStaticField() && bf.isObjectType() && !bf.shouldRemoveFromHeapCollection()) {
1770-
b.append(" gcMarkObject(threadStateData, STATIC_FIELD_");
1771-
b.append(clsName);
1772-
b.append("_");
1773-
b.append(bf.getFieldName());
1810+
b.append(" gcMarkObject(threadStateData, ");
1811+
if (bf.isVolatile()) {
1812+
b.append("atomic_load(&STATIC_FIELD_");
1813+
b.append(clsName);
1814+
b.append("_");
1815+
b.append(bf.getFieldName());
1816+
b.append(")");
1817+
} else {
1818+
b.append("STATIC_FIELD_");
1819+
b.append(clsName);
1820+
b.append("_");
1821+
b.append(bf.getFieldName());
1822+
}
17741823
b.append(", JAVA_TRUE);\n");
17751824
}
17761825
}

vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeField.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class ByteCodeField {
4545
private boolean finalField;
4646
private Object value;
4747
private boolean privateField;
48+
private final boolean volatileField;
4849

4950
public ByteCodeField(String clsName, int access, String name, String desc, String signature, Object value) {
5051
this.clsName = clsName;
@@ -55,6 +56,7 @@ public ByteCodeField(String clsName, int access, String name, String desc, Strin
5556
}
5657
staticField = (access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC;
5758
finalField = (access & Opcodes.ACC_FINAL) == Opcodes.ACC_FINAL;
59+
volatileField = (access & Opcodes.ACC_VOLATILE) == Opcodes.ACC_VOLATILE;
5860
fieldName = name.replace('$', '_');
5961

6062
arrayDimensions = 0;
@@ -115,6 +117,13 @@ public String getCDefinition() {
115117
}
116118
return Util.getCType(primitiveType);
117119
}
120+
121+
public String getCStorageDefinition() {
122+
if (volatileField) {
123+
return "_Atomic " + getCDefinition();
124+
}
125+
return getCDefinition();
126+
}
118127

119128
public List<String> getDependentClasses() {
120129
return dependentClasses;
@@ -150,6 +159,10 @@ public String getClsName() {
150159
public boolean isObjectType() {
151160
return arrayDimensions > 0 || primitiveType == null;
152161
}
162+
163+
public boolean isVolatile() {
164+
return volatileField;
165+
}
153166

154167
public boolean isFinal() {
155168
return finalField;

0 commit comments

Comments
 (0)