Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -977,9 +977,12 @@ public String generateCCode(List<ByteCodeClass> allClasses) {
}
}
}
if(baseClassObject != null) {
if(!isInterface) {
List<BytecodeMethod> bm = new ArrayList<BytecodeMethod>(methods);
appendSuperStub(b, bm, baseClassObject);
if(baseClassObject != null) {
appendSuperStub(b, bm, baseClassObject);
}
appendDefaultInterfaceStubs(b, bm);
}
int offset = 0;
if(clsName.equals("java_lang_Class")) {
Expand Down Expand Up @@ -1198,6 +1201,50 @@ private void appendSuperStub(StringBuilder b, List<BytecodeMethod> bm, ByteCodeC
}
BytecodeMethod.setAcceptStaticOnEquals(false);
}

private boolean hasMethodInBaseClass(BytecodeMethod method) {
if(baseClassObject == null) {
return false;
}
if(baseClassObject.methods.contains(method)) {
return true;
}
return baseClassObject.hasMethodInBaseClass(method);
}

private void appendDefaultInterfaceStubs(StringBuilder b, List<BytecodeMethod> bm) {
if(baseInterfacesObject == null) {
return;
}
BytecodeMethod.setAcceptStaticOnEquals(true);
for(ByteCodeClass baseInterface : baseInterfacesObject) {
appendDefaultInterfaceStubs(b, bm, baseInterface);
}
BytecodeMethod.setAcceptStaticOnEquals(false);
}

private void appendDefaultInterfaceStubs(StringBuilder b, List<BytecodeMethod> bm, ByteCodeClass baseInterface) {
if(baseInterface == null) {
return;
}
if(baseClassObject != null && baseClassObject.doesImplement(baseInterface)) {
return;
}
for(BytecodeMethod m : baseInterface.methods) {
if(m.isAbstract() || m.isStatic() || m.isPrivate()) {
continue;
}
if(!bm.contains(m) && !hasMethodInBaseClass(m)) {
m.appendSuperCall(b, clsName);
bm.add(m);
}
}
if(baseInterface.baseInterfacesObject != null) {
for(ByteCodeClass parentInterface : baseInterface.baseInterfacesObject) {
appendDefaultInterfaceStubs(b, bm, parentInterface);
}
}
}

private void appendSuperStubHeader(StringBuilder b, List<BytecodeMethod> bm, ByteCodeClass base) {
BytecodeMethod.setAcceptStaticOnEquals(true);
Expand All @@ -1213,6 +1260,40 @@ private void appendSuperStubHeader(StringBuilder b, List<BytecodeMethod> bm, Byt
}
BytecodeMethod.setAcceptStaticOnEquals(false);
}

private void appendDefaultInterfaceStubHeaders(StringBuilder b, List<BytecodeMethod> bm) {
if(baseInterfacesObject == null) {
return;
}
BytecodeMethod.setAcceptStaticOnEquals(true);
for(ByteCodeClass baseInterface : baseInterfacesObject) {
appendDefaultInterfaceStubHeaders(b, bm, baseInterface);
}
BytecodeMethod.setAcceptStaticOnEquals(false);
}

private void appendDefaultInterfaceStubHeaders(StringBuilder b, List<BytecodeMethod> bm, ByteCodeClass baseInterface) {
if(baseInterface == null) {
return;
}
if(baseClassObject != null && baseClassObject.doesImplement(baseInterface)) {
return;
}
for(BytecodeMethod m : baseInterface.methods) {
if(m.isAbstract() || m.isStatic() || m.isPrivate()) {
continue;
}
if(!bm.contains(m) && !hasMethodInBaseClass(m)) {
m.appendMethodHeader(b, clsName);
bm.add(m);
}
}
if(baseInterface.baseInterfacesObject != null) {
for(ByteCodeClass parentInterface : baseInterface.baseInterfacesObject) {
appendDefaultInterfaceStubHeaders(b, bm, parentInterface);
}
}
}

private void buildInstanceFieldList(List<ByteCodeField> fieldList) {
buildInstanceFieldList(fieldList, true);
Expand Down Expand Up @@ -1363,10 +1444,13 @@ public String generateCHeader() {

appendMethodsToHeader(b);

if(baseClassObject != null) {
if(!isInterface) {
// append super stub
List<BytecodeMethod> bm = new ArrayList<BytecodeMethod>(methods);
appendSuperStubHeader(b, bm, baseClassObject);
if(baseClassObject != null) {
appendSuperStubHeader(b, bm, baseClassObject);
}
appendDefaultInterfaceStubHeaders(b, bm);
}

for(BytecodeMethod m : virtualMethodList) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ void translatesDefaultInterfaceMethodImplementations() throws Exception {
String implCode = impl.generateCCode(classes);
assertTrue(implCode.contains("&com_example_Greeter_greet___R_java_lang_String"),
"Implementing class should point vtable slot to the interface default method implementation");
assertTrue(implCode.contains("com_example_GreeterImpl_greet___R_java_lang_String"),
"Implementing class should emit a concrete stub for default interface methods");
String implHeader = impl.generateCHeader();
assertTrue(implHeader.contains("com_example_GreeterImpl_greet___R_java_lang_String"),
"Implementing class header should declare the default interface stub");
}

@Test
Expand Down
Loading