Skip to content

Commit d9609a1

Browse files
Add support for bitfields in StructWrapper
1 parent ab1bdce commit d9609a1

File tree

6 files changed

+178
-67
lines changed

6 files changed

+178
-67
lines changed

espresso/src/com.oracle.truffle.espresso.mokapot/src/structs.c

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#define JNI_STRUCT_MEMBER_LIST(V) \
3434
V(JavaVMAttachArgs, version) \
3535
V(JavaVMAttachArgs, name) \
36-
V(JavaVMAttachArgs, group) \
36+
V(JavaVMAttachArgs, group)
3737

3838
#define JVM_STRUCT_MEMBER_LIST(V) \
3939
V(jdk_version_info, jdk_version)
@@ -172,15 +172,24 @@
172172
V(_jvmtiEventCallbacks, reserved85) \
173173
V(_jvmtiEventCallbacks, SampledObjectAlloc)
174174

175+
#define JMM_STRUCT_BITFIELD_MEMBER_LIST(V) \
176+
V(jmmOptionalSupport, isLowMemoryDetectionSupported) \
177+
V(jmmOptionalSupport, isCompilationTimeMonitoringSupported) \
178+
V(jmmOptionalSupport, isThreadContentionMonitoringSupported) \
179+
V(jmmOptionalSupport, isCurrentThreadCpuTimeSupported) \
180+
V(jmmOptionalSupport, isOtherThreadCpuTimeSupported) \
181+
V(jmmOptionalSupport, isObjectMonitorUsageSupported) \
182+
V(jmmOptionalSupport, isSynchronizerUsageSupported) \
183+
V(jmmOptionalSupport, isThreadAllocatedMemorySupported) \
184+
V(jmmOptionalSupport, isRemoteDiagnosticCommandsSupported)
185+
175186
#define MEMBER_INFO_STRUCT_MEMBER_LIST(V) \
176187
V(member_info, id) \
177188
V(member_info, offset) \
178189
V(member_info, next)
179190

180191
#define JNI_STRUCT_LIST(V) \
181-
V(JavaVMAttachArgs) \
182-
V(JavaVMAttachArgs) \
183-
V(JavaVMAttachArgs) \
192+
V(JavaVMAttachArgs)
184193

185194
#define JVM_STRUCT_LIST(V) \
186195
V(jdk_version_info)
@@ -224,6 +233,8 @@
224233
JVMTI_STRUCT_MEMBER_LIST(V) \
225234
MEMBER_INFO_STRUCT_MEMBER_LIST(V)
226235

236+
#define STRUCT_BITFIELD_MEMBER_LIST_LIST(V)
237+
227238
void add_member_info(member_info** info, char* id, size_t offset) {
228239
member_info* current = malloc(sizeof(struct member_info));
229240
current->id = id;
@@ -263,6 +274,47 @@ JNIEXPORT void JNICALL initializeStructs(void (*notify_member_offset_init)(void
263274
STRUCT_MEMBER_LIST_LIST(MEMBER_INFO__)
264275
#undef MEMBER_INFO__
265276

277+
// from com.oracle.svm.hosted.c.codegen.QueryCodeWriter#visitStructBitfieldInfo
278+
#define MEMBER_INFO__(STRUCT_NAME, MEMBER_NAME) \
279+
{ \
280+
struct _w { \
281+
STRUCT_NAME s; \
282+
jlong pad; \
283+
} w; \
284+
char *p; \
285+
size_t byte_offset; \
286+
unsigned char start_bit = 0, end_bit = 0; \
287+
jlong v; \
288+
jlong all_bits_set = -1; \
289+
memset(&w, 0x0, sizeof(w)); \
290+
w.s.MEMBER_NAME = all_bits_set; \
291+
p = (char*)&w.s; \
292+
byte_offset = 0; \
293+
while (byte_offset < sizeof(w.s) && *(p + byte_offset) == 0) { \
294+
byte_offset++; \
295+
} \
296+
if (byte_offset >= sizeof(w.s)) { \
297+
start_bit = end_bit = -1;\
298+
} else { \
299+
v = *((jlong*) (p + byte_offset)); \
300+
while ((v & 0x1) == 0) { \
301+
start_bit++; \
302+
v = v >> 1; \
303+
} \
304+
end_bit = start_bit; \
305+
while (v != 1) { \
306+
end_bit++; \
307+
v = v >> 1; \
308+
} \
309+
} \
310+
add_member_info(info, #STRUCT_NAME "." #MEMBER_NAME, byte_offset); \
311+
add_member_info(info, #STRUCT_NAME "." #MEMBER_NAME ".StartBit", start_bit); \
312+
add_member_info(info, #STRUCT_NAME "." #MEMBER_NAME ".EndBit", end_bit + 1); \
313+
}
314+
315+
STRUCT_BITFIELD_MEMBER_LIST_LIST(MEMBER_INFO__)
316+
#undef MEMBER_INFO__
317+
266318
#define STRUCT_INFO__(STRUCT_NAME) \
267319
add_member_info(info, #STRUCT_NAME, sizeof(struct STRUCT_NAME));
268320

espresso/src/com.oracle.truffle.espresso.processor/src/com/oracle/truffle/espresso/processor/NativeType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ public enum NativeType {
3939

4040
OBJECT, // word-sized handle
4141
POINTER,
42+
BITFIELD_INT,
4243
}

espresso/src/com.oracle.truffle.espresso.processor/src/com/oracle/truffle/espresso/processor/StructsProcessor.java

Lines changed: 60 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ public class StructsProcessor extends AbstractProcessor {
9393
private static final String STRUCTS_CLASS = "Structs";
9494

9595
// Methods
96-
private static final String GET_INFO = "getInfo";
96+
private static final String GET_STRUCT_SIZE = "getStructSize";
9797
private static final String GET_OFFSET = "getOffset";
98+
private static final String GET_START_BIT = "getStartBit";
99+
private static final String GET_END_BIT = "getEndBit";
98100
private static final String GET = "get";
99101
private static final String PUT = "put";
100102
private static final String GET_UNCACHED = "getUncached";
@@ -229,7 +231,7 @@ private String processStruct(String strName, List<?> memberNamesList, List<?> ty
229231
nativeTypes.add(NativeType.valueOf(type.getSimpleName().toString()));
230232
}
231233

232-
String className = ProcessorUtils.removeUnderscores(strName); // Replace '_j' with 'J'
234+
String className = removeUnderscores(strName); // Replace '_j' with 'J'
233235
// Generate code
234236
String source = generateStruct(strName, members, nativeTypes, length, className);
235237
// Commit and write to files.
@@ -266,13 +268,12 @@ private static String generateStruct(String strName, List<String> members, List<
266268
.withSuperClass(STRUCT_STORAGE_CLASS + "<" + className + "." + wrapperName + ">");
267269

268270
// Generate the fields:
269-
// - One to store the struct size
270271
// - One per member to store their offsets
271-
generateFields(struct, members);
272+
generateFields(struct, members, typesList, length);
272273

273274
// Generate the constructor.
274275
// Use passed MemberOffsetGetter.
275-
generateConstructor(struct, strName, members, className);
276+
generateConstructor(struct, strName, members, typesList, length, className);
276277

277278
// Generate the wrapper structure that will access the native struct java-like.
278279
// It simply wraps a byte buffer around the pointer, and uses offsets in parent class to
@@ -285,20 +286,32 @@ private static String generateStruct(String strName, List<String> members, List<
285286
return structFile.build();
286287
}
287288

288-
private static void generateFields(ClassBuilder struct, List<String> members) {
289-
for (String member : members) {
289+
private static void generateFields(ClassBuilder struct, List<String> members, List<NativeType> typesList, int length) {
290+
for (int i = 0; i < length; i++) {
291+
String member = members.get(i);
292+
NativeType type = typesList.get(i);
290293
struct.withField(new FieldBuilder("int", member).withQualifiers(new ModifierBuilder().asFinal()));
294+
if (type == NativeType.BITFIELD_INT) {
295+
struct.withField(new FieldBuilder("byte", member + "StartBit").withQualifiers(new ModifierBuilder().asFinal()));
296+
struct.withField(new FieldBuilder("byte", member + "EndBit").withQualifiers(new ModifierBuilder().asFinal()));
297+
}
291298
}
292299
}
293300

294-
private static void generateConstructor(ClassBuilder struct, String strName, List<String> members, String className) {
301+
private static void generateConstructor(ClassBuilder struct, String strName, List<String> members, List<NativeType> typesList, int length, String className) {
295302
MethodBuilder constructor = new MethodBuilder(className) //
296303
.withParams(argument(MEMBER_OFFSET_GETTER_CLASS, MEMBER_OFFSET_GETTER_ARG)) //
297304
.asConstructor();
298305

299-
constructor.addBodyLine("super(", call(MEMBER_OFFSET_GETTER_ARG, GET_INFO, new String[]{stringify(strName)}), ");");
300-
for (String member : members) {
306+
constructor.addBodyLine("super(", call(MEMBER_OFFSET_GETTER_ARG, GET_STRUCT_SIZE, new String[]{stringify(strName)}), ");");
307+
for (int i = 0; i < length; i++) {
308+
String member = members.get(i);
309+
NativeType type = typesList.get(i);
301310
constructor.addBodyLine(assignment(member, "(int) " + call(MEMBER_OFFSET_GETTER_ARG, GET_OFFSET, new String[]{stringify(strName), stringify(member)})));
311+
if (type == NativeType.BITFIELD_INT) {
312+
constructor.addBodyLine(assignment(member + "StartBit", "(byte) " + call(MEMBER_OFFSET_GETTER_ARG, GET_START_BIT, new String[]{stringify(strName), stringify(member)})));
313+
constructor.addBodyLine(assignment(member + "EndBit", "(byte) " + call(MEMBER_OFFSET_GETTER_ARG, GET_END_BIT, new String[]{stringify(strName), stringify(member)})));
314+
}
302315
}
303316

304317
struct.withMethod(constructor);
@@ -325,12 +338,17 @@ private static void generateWrapper(ClassBuilder struct, List<String> members, L
325338

326339
MethodBuilder getter = new MethodBuilder(methodName) //
327340
.withModifiers(new ModifierBuilder().asPublic()) //
328-
.withReturnType(argType) //
329-
.addBodyLine("return ", call(null, GET + callSuffix, new String[]{member}), ';');
341+
.withReturnType(argType);
330342
MethodBuilder setter = new MethodBuilder(methodName) //
331343
.withModifiers(new ModifierBuilder().asPublic()) //
332-
.withParams(argument(argType, VALUE)) //
333-
.addBodyLine(call(null, PUT + callSuffix, new String[]{member, VALUE}), ';');
344+
.withParams(argument(argType, VALUE));
345+
if (type == NativeType.BITFIELD_INT) {
346+
getter.addBodyLine("return ", call(null, GET + callSuffix, new String[]{member, member + "StartBit", member + "EndBit"}), ';');
347+
setter.addBodyLine(call(null, PUT + callSuffix, new String[]{member, member + "StartBit", member + "EndBit", VALUE}), ';');
348+
} else {
349+
getter.addBodyLine("return ", call(null, GET + callSuffix, new String[]{member}), ';');
350+
setter.addBodyLine(call(null, PUT + callSuffix, new String[]{member, VALUE}), ';');
351+
}
334352
wrapper.withMethod(getter);
335353
wrapper.withMethod(setter);
336354
}
@@ -399,57 +417,37 @@ private static void generateOptionalMemberInfo(MethodBuilder constructor, List<S
399417
}
400418

401419
private static String nativeTypeToMethodSuffix(NativeType type) {
402-
switch (type) {
403-
case BOOLEAN:
404-
return "Boolean";
405-
case BYTE:
406-
return "Byte";
407-
case CHAR:
408-
return "Char";
409-
case SHORT:
410-
return "Short";
411-
case INT:
412-
return "Int";
413-
case LONG:
414-
return "Long";
415-
case FLOAT:
416-
return "Float";
417-
case DOUBLE:
418-
return "Double";
419-
case OBJECT:
420-
return "Object";
421-
case POINTER:
422-
return "Pointer";
423-
default:
424-
return "";
425-
}
420+
return switch (type) {
421+
case VOID -> "";
422+
case BOOLEAN -> "Boolean";
423+
case BYTE -> "Byte";
424+
case CHAR -> "Char";
425+
case SHORT -> "Short";
426+
case INT -> "Int";
427+
case LONG -> "Long";
428+
case FLOAT -> "Float";
429+
case DOUBLE -> "Double";
430+
case OBJECT -> "Object";
431+
case POINTER -> "Pointer";
432+
case BITFIELD_INT -> "BitFieldInt";
433+
};
426434
}
427435

428436
private static String nativeTypeToArgType(NativeType type) {
429-
switch (type) {
430-
case BOOLEAN:
431-
return "boolean";
432-
case BYTE:
433-
return "byte";
434-
case CHAR:
435-
return "char";
436-
case SHORT:
437-
return "short";
438-
case INT:
439-
return "int";
440-
case LONG:
441-
return "long";
442-
case FLOAT:
443-
return "float";
444-
case DOUBLE:
445-
return "double";
446-
case OBJECT:
447-
return "StaticObject";
448-
case POINTER:
449-
return "TruffleObject";
450-
default:
451-
return "";
452-
}
437+
return switch (type) {
438+
case VOID -> "";
439+
case BOOLEAN -> "boolean";
440+
case BYTE -> "byte";
441+
case CHAR -> "char";
442+
case SHORT -> "short";
443+
case INT -> "int";
444+
case LONG -> "long";
445+
case FLOAT -> "float";
446+
case DOUBLE -> "double";
447+
case OBJECT -> "StaticObject";
448+
case POINTER -> "TruffleObject";
449+
case BITFIELD_INT -> "int";
450+
};
453451
}
454452

455453
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/ffi/NativeType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ public enum NativeType {
4747

4848
OBJECT, // word-sized handle
4949
POINTER,
50+
BITFIELD_INT,
5051
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/structs/MemberOffsetGetter.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,21 @@
2323
package com.oracle.truffle.espresso.vm.structs;
2424

2525
public interface MemberOffsetGetter {
26-
long getInfo(String structName);
26+
long getInfo(String key);
27+
28+
default long getStructSize(String structName) {
29+
return getInfo(structName);
30+
}
2731

2832
default long getOffset(String structName, String memberName) {
2933
return getInfo(structName + "." + memberName);
3034
}
35+
36+
default int getStartBit(String structName, String memberName) {
37+
return Math.toIntExact(getInfo(structName + "." + memberName + ".StartBit"));
38+
}
39+
40+
default int getEndBit(String structName, String memberName) {
41+
return Math.toIntExact(getInfo(structName + "." + memberName + ".EndBit"));
42+
}
3143
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/structs/StructWrapper.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,53 @@ protected void putInt(int offset, int value) {
780780
buffer.putInt(offset, value);
781781
}
782782

783+
protected int getBitFieldInt(int offset, byte startBit, byte endBit) {
784+
assert 0 <= startBit && startBit < 8 : startBit;
785+
assert endBit > 0 : endBit;
786+
assert startBit != endBit : startBit + "!=" + endBit;
787+
assert endBit - startBit <= 32 : startBit + ".." + endBit;
788+
long v = getBits(offset, endBit) >> startBit;
789+
long mask = (1L << (endBit - startBit)) - 1;
790+
return Math.toIntExact(v & mask);
791+
}
792+
793+
private long getBits(int offset, byte endBit) {
794+
long v;
795+
if (endBit <= 8) {
796+
v = buffer.get(offset) & 0xff;
797+
} else if (endBit <= 16) {
798+
v = buffer.getChar(offset);
799+
} else if (endBit <= 32) {
800+
v = buffer.getInt(offset) & 0xffff_ffffL;
801+
} else {
802+
v = buffer.getLong(offset);
803+
}
804+
return v;
805+
}
806+
807+
protected void putBitFieldInt(int offset, byte startBit, byte endBit, int value) {
808+
assert 0 <= startBit && startBit < 8 : startBit;
809+
assert endBit > 0 : endBit;
810+
assert startBit != endBit : startBit + "!=" + endBit;
811+
assert endBit - startBit <= 32 : startBit + ".." + endBit;
812+
long mask = ((1L << (endBit - startBit)) - 1) << startBit;
813+
long v = getBits(offset, endBit);
814+
v = (v & ~mask) | (((long) value << startBit) & mask);
815+
putBits(offset, endBit, v);
816+
}
817+
818+
private void putBits(int offset, byte endBit, long v) {
819+
if (endBit <= 8) {
820+
buffer.put(offset, (byte) v);
821+
} else if (endBit <= 16) {
822+
buffer.putChar(offset, (char) v);
823+
} else if (endBit <= 32) {
824+
buffer.putInt(offset, (int) v);
825+
} else {
826+
buffer.putLong(offset, v);
827+
}
828+
}
829+
783830
protected float getFloat(int offset) {
784831
return buffer.getFloat(offset);
785832
}

0 commit comments

Comments
 (0)