mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
The Java backend was sometimes generating code like this to initialise RTTI
Branches: main
The Java backend was sometimes generating code like this to initialise RTTI
data structures:
foo_type_info.init(...,
/* cast */ new TypeInfo_Struct(bar_type_ctor_info), ...);
bar_type_ctor_info.init(...);
where `bar_type_ctor_info' is actually a type_info.
The problem is that the fields of the non-initialised `bar_type_ctor_info'
would be copied into the new TypeInfo_Struct object. The "cast" is of course
also unnecessary as the bar is already a TypeInfo_Struct.
This patch attempts to fix the problem in two ways:
1. Don't allocate a new TypeInfo_Struct object to emulate the "cast" unless the
value is actually a TypeCtorInfo_Struct, avoiding the problem of copying
uninitialised fields. Currently this is implemented by a runtime check because
the MLDS `cast' operation doesn't record the original type of the value being
cast.
2. Instead of relying on mlds_to_rtti.m to return a list of RTTI data
structures where sub-structures appear before the structures that reference
them, explicitly perform a topological sort. This should be more robust.
Unrelated change: use pre-allocated PseudoTypeInfo instances for common
variable numbers (1 through 5).
compiler/rtti_to_mlds.m:
Add a function to order a list of RTTI definitions as above.
Use cons instead of list.append in some places now that we can.
compiler/mlds_to_java.m:
Call the function to order RTTI definitions before outputing
the initialisations.
Call TypeInfo_Struct.maybe_new instead of allocating new
TypeInfo_Structs.
Generate code that uses pre-allocated PseudoTypeInfo instances.
java/runtime/TypeInfo_Struct.java:
Add a `maybe_new' method for "casting" TypeCtorInfo_Structs to
TypeInfos or returning the argument unchanged.
Delete a copy constructor; now unused.
Add some assertions.
java/runtime/PseudoTypeInfo.java:
Add static instances of PseudoTypeInfo.
tests/hard_coded/Mmakefile:
tests/hard_coded/java_rtti_bug.exp:
tests/hard_coded/java_rtti_bug.m:
Add test case.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (C) 2001-2004 The University of Melbourne.
|
||||
// Copyright (C) 2001-2004, 2009 The University of Melbourne.
|
||||
// This file may only be copied under the terms of the GNU Library General
|
||||
// Public License - see the file COPYING.LIB in the Mercury distribution.
|
||||
//
|
||||
@@ -26,6 +26,14 @@ public class PseudoTypeInfo {
|
||||
public PseudoTypeInfo(int n) { variable_number = n; }
|
||||
protected PseudoTypeInfo() { variable_number = -1; }
|
||||
|
||||
// Adding or removing members requires corresponding changes in
|
||||
// mlds_to_java.m.
|
||||
public static final PseudoTypeInfo K1 = new PseudoTypeInfo(1);
|
||||
public static final PseudoTypeInfo K2 = new PseudoTypeInfo(2);
|
||||
public static final PseudoTypeInfo K3 = new PseudoTypeInfo(3);
|
||||
public static final PseudoTypeInfo K4 = new PseudoTypeInfo(4);
|
||||
public static final PseudoTypeInfo K5 = new PseudoTypeInfo(5);
|
||||
|
||||
// XXX This should be renamed `equals'
|
||||
public boolean unify(PseudoTypeInfo ti) {
|
||||
if (this.getClass() == TypeInfo_Struct.class &&
|
||||
@@ -36,3 +44,5 @@ public class PseudoTypeInfo {
|
||||
return variable_number == ti.variable_number;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: set ts=8 sts=8 sw=8 noet:
|
||||
|
||||
@@ -18,22 +18,36 @@ public class TypeInfo_Struct extends PseudoTypeInfo {
|
||||
public TypeInfo_Struct(TypeCtorInfo_Struct tc)
|
||||
{
|
||||
type_ctor = tc;
|
||||
sanity_check();
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
// XXX Rather than invoking this constructor, and allocating a new
|
||||
// type_info object on the heap, we should generate code which
|
||||
// just copies the pointer,
|
||||
public TypeInfo_Struct(TypeInfo_Struct ti)
|
||||
public static TypeInfo_Struct maybe_new(final Object obj)
|
||||
{
|
||||
type_ctor = ti.type_ctor;
|
||||
args = ti.args;
|
||||
// In at least one place in the standard library we make up a
|
||||
// TypeInfo out of thin air to satisfy the compiler.
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
if (obj instanceof TypeCtorInfo_Struct) {
|
||||
return new TypeInfo_Struct((TypeCtorInfo_Struct) obj);
|
||||
}
|
||||
if (obj instanceof TypeInfo_Struct) {
|
||||
return (TypeInfo_Struct) obj;
|
||||
}
|
||||
throw new java.lang.Error(
|
||||
"expected TypeInfo_Struct or TypeCtorInfo_Struct");
|
||||
}
|
||||
|
||||
public void init(TypeCtorInfo_Struct tc, PseudoTypeInfo[] as)
|
||||
{
|
||||
type_ctor = tc;
|
||||
args = as;
|
||||
type_ctor = tc;
|
||||
args = as;
|
||||
|
||||
// We may be in the middle of initialising a cyclic data
|
||||
// structure, so unfortunately, we can't actually sanity check
|
||||
// the arguments here.
|
||||
assert tc != null;
|
||||
// sanity_check();
|
||||
}
|
||||
|
||||
public TypeInfo_Struct copy()
|
||||
@@ -43,6 +57,7 @@ public class TypeInfo_Struct extends PseudoTypeInfo {
|
||||
if (args != null) {
|
||||
ti.args = args.clone();
|
||||
}
|
||||
ti.sanity_check();
|
||||
return ti;
|
||||
}
|
||||
|
||||
@@ -119,4 +134,27 @@ public class TypeInfo_Struct extends PseudoTypeInfo {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sanity_check() {
|
||||
assert type_ctor != null;
|
||||
|
||||
if (args == null) {
|
||||
return;
|
||||
}
|
||||
for (PseudoTypeInfo pti : args) {
|
||||
if (pti instanceof TypeInfo_Struct) {
|
||||
TypeInfo_Struct ti = (TypeInfo_Struct) pti;
|
||||
assert ti.type_ctor != null;
|
||||
assert ti.variable_number == -1;
|
||||
} else if (pti instanceof TypeCtorInfo_Struct) {
|
||||
TypeCtorInfo_Struct tc =
|
||||
(TypeCtorInfo_Struct) pti;
|
||||
assert tc.variable_number == -1;
|
||||
} else {
|
||||
assert pti.variable_number != -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: set ts=8 sw=8 sts=8 noet:
|
||||
|
||||
Reference in New Issue
Block a user