[EDIT: It has been pointed out that the correct term for what I am talking about is Scalar Replacement. Also it seems that Java 7 already has some code to support it in the JIT compiler. Thanks.]
One of the interesting features of Scala is the ability to use implicit conversions to “add” methods to existing classes. A call to “x.func” will try to convert x to a type with a method func if it doesn’t naturally have one. The problem is that each time this happens it ends up allocating a temporary wrapper object. This is similar to Java idioms like:
long time = new Date().getTime();
In both cases an object is allocated and then is immediately ready to be garbage collected. Whenever I think about this I feel that the JVM could optimize it away. Maybe something like this.
The JVM discovers (during escape analysis, which I think it already does) that the object is short lived and local. It then inlines the small number of method calls (often just one, especially in the case of scala implicit conversions). When it sees that every method call on the object is inlined it inlines the constructor and converts any fields of the class into local variable and removes the allocation entirely.
This wouldn’t be easy. But it doesn’t seem like it would be too incredibly hard. Though I’m not a JVM programmer so I don’t really know.
Maybe I should give it a shot. I’ve never hacked on Hotspot and I’ve always kinda wanted to.
Any thoughts on this?
Posted in
Java,
JVM,
Scala
One of the common complaints that people have about Java is that it lacks the const keyword. Yes, Java has final, but final cannot create a reference to a immutable object only a immutable reference to a mutable object.
The issue is that there is no way to encode the promise that an object will not be mutated in the Java language. The work around for this is to create a wrapper object that throws an exceptions if a mutator method is called. This is how the collection API handles the problem. However this technique provides no compile time checks. There is no way to know at compile time if a given Collection is mutable or immutable.
I have thought about this a bit lately and I have realized that const as it is implemented in C++ is fundamentally a way of defining a sub-interface of the interface to a class. I mean this in the sense that the interface of “const Thing” is a subset of the interface of “Thing”. So in essence “const Thing” can be thought of as a abstract base class of “Thing” (with the exception that casting “const Thing” to “Thing” should be hard or impossible). What I’m getting at is that you could generalize this idea into the idea of a interface subset.
In Java this could be implemented by hand as follows:
public interface ConstThing {
public String getValue();
}
public class Thing implements ConstThing {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public class ConstThingProxy implements ConstThing {
final private Thing subject;
public ConstThingProxy(Thing subject) {
this.subject = subject;
}
public String getValue() {
return subject.getValue();
}
}
// Usage:
public class Client {
public void useMutable(Thing t) {
t.setValue("New");
}
public void useConst(ConstThing t) {
t.getValue();
t.setValue("New"); // <-- Compiler Error
}
public void useConstCast(ConstThing t) {
t.getValue();
((Thing) t).setValue("New");
/*
* No compiler error, but there would be a runtime error if the code
* providing the ConstThing wrapped the reference in a
* ConstThingProxy.
*/
}
}
Obviously this has a number of missing features and is hard to do because the interface must be declared by hand. So the main missing features from this approach are (in rough order of importance):
- There should be an easy way to create this structure of classes. In other words, there should be syntactic sugar for it or something like that.
- There should be a way to make the this reference in a function be an instance of all of the interface subsets that the method it part of. This would allow the compiler to provide warnings or errors if the method references elements of the class that are not part of the interface subset. This is actually a very complex problem, especially when combined with inheritance. I don’t have a solution for it that I am comfortable with.
I may come back to this subject later. For instance I think it would be interesting to see if it can be implemented better in Scala with it’s more expressive type system.
Posted in
Java,
Programming Theory