mirror of
https://github.com/corda/corda.git
synced 2025-01-18 02:39:51 +00:00
CORDA-1945: properly support double-width interp stack slots in superclasses when synthesising (#3859)
* Fix for CORDA-1945 * Revert irrelevant style change
This commit is contained in:
parent
60d28b412f
commit
4337537791
@ -130,8 +130,8 @@ class ClassCarpenterImpl @JvmOverloads constructor (override val whitelist: Clas
|
||||
*/
|
||||
override fun build(schema: Schema): Class<*> {
|
||||
validateSchema(schema)
|
||||
// Walk up the inheritance hierarchy and then start walking back down once we either hit the top, or
|
||||
// find a class we haven't generated yet.
|
||||
// Walk up the inheritance hierarchy until we hit either the top or a class we've already generated,
|
||||
// then walk back down it generating classes.
|
||||
val hierarchy = ArrayList<Schema>()
|
||||
hierarchy += schema
|
||||
var cursor = schema.superclass
|
||||
@ -306,16 +306,16 @@ class ClassCarpenterImpl @JvmOverloads constructor (override val whitelist: Clas
|
||||
visitInsn(DUP)
|
||||
|
||||
var idx = 0
|
||||
schema.fields.forEach {
|
||||
schema.fields.keys.forEach { key ->
|
||||
visitInsn(DUP)
|
||||
visitIntInsn(BIPUSH, idx)
|
||||
visitTypeInsn(NEW, schema.jvmName)
|
||||
visitInsn(DUP)
|
||||
visitLdcInsn(it.key)
|
||||
visitLdcInsn(key)
|
||||
visitIntInsn(BIPUSH, idx++)
|
||||
visitMethodInsn(INVOKESPECIAL, schema.jvmName, "<init>", "(L$jlString;I)V", false)
|
||||
visitInsn(DUP)
|
||||
visitFieldInsn(PUTSTATIC, schema.jvmName, it.key, "L${schema.jvmName};")
|
||||
visitFieldInsn(PUTSTATIC, schema.jvmName, key, "L${schema.jvmName};")
|
||||
visitInsn(AASTORE)
|
||||
}
|
||||
|
||||
@ -381,20 +381,18 @@ class ClassCarpenterImpl @JvmOverloads constructor (override val whitelist: Clas
|
||||
visitCode()
|
||||
|
||||
// Calculate the super call.
|
||||
val superclassFields = schema.superclass?.fieldsIncludingSuperclasses() ?: emptyMap()
|
||||
visitVarInsn(ALOAD, 0)
|
||||
val sc = schema.superclass
|
||||
var slot = 1
|
||||
if (sc == null) {
|
||||
visitMethodInsn(INVOKESPECIAL, jlObject, "<init>", "()V", false)
|
||||
} else {
|
||||
var slot = 1
|
||||
superclassFields.values.forEach { slot += load(slot, it) }
|
||||
slot = sc.fieldsIncludingSuperclasses().values.fold(slot) { acc, field -> acc + load(acc, field) }
|
||||
val superDesc = sc.descriptorsIncludingSuperclasses().values.joinToString("")
|
||||
visitMethodInsn(INVOKESPECIAL, sc.jvmName, "<init>", "($superDesc)V", false)
|
||||
}
|
||||
|
||||
// Assign the fields from parameters.
|
||||
var slot = 1 + superclassFields.size
|
||||
for ((name, field) in schema.fields) {
|
||||
(field as ClassField).nullTest(this, slot)
|
||||
|
||||
|
@ -129,6 +129,27 @@ class ClassCarpenterTest {
|
||||
assertEquals("B{a=xa, b=xb}", i.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the fix for [Corda-1945](https://r3-cev.atlassian.net/secure/RapidBoard.jspa?rapidView=83&modal=detail&selectedIssue=CORDA-1945)
|
||||
*/
|
||||
@Test
|
||||
fun `superclasses with double-size primitive constructor parameters`() {
|
||||
val schema1 = ClassSchema(
|
||||
"gen.A",
|
||||
mapOf("a" to NonNullableField(Long::class.javaPrimitiveType!!)))
|
||||
|
||||
val schema2 = ClassSchema(
|
||||
"gen.B",
|
||||
mapOf("b" to NonNullableField(String::class.java)),
|
||||
schema1)
|
||||
|
||||
val clazz = cc.build(schema2)
|
||||
val i = clazz.constructors[0].newInstance(1L, "xb") as SimpleFieldAccess
|
||||
assertEquals(1L, i["a"])
|
||||
assertEquals("xb", i["b"])
|
||||
assertEquals("B{a=1, b=xb}", i.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun interfaces() {
|
||||
val schema1 = ClassSchema(
|
||||
|
Loading…
Reference in New Issue
Block a user