changeset 2288:8c426c2891c8

client/server: new interface Remote marks classes that should not be serialized, but called remotely
author Lukas Stadler <lukas.stadler@jku.at>
date Mon, 11 Apr 2011 10:37:24 +0200
parents 66ffa0e99cef
children 6190d20bd6d6
files c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/CompilerImpl.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotTypeResolved.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/InvocationSocket.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/VMEntriesNative.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/VMExitsNative.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/logging/CountingProxy.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/logging/LoggingProxy.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/server/CompilationServer.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/server/Remote.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/server/ReplacingStreams.java src/share/vm/c1x/c1x_VMEntries.cpp src/share/vm/c1x/c1x_VMExits.cpp src/share/vm/classfile/vmSymbols.hpp
diffstat 13 files changed, 239 insertions(+), 189 deletions(-) [+]
line wrap: on
line diff
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/CompilerImpl.java	Fri Apr 08 13:47:56 2011 +0200
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/CompilerImpl.java	Mon Apr 11 10:37:24 2011 +0200
@@ -22,7 +22,6 @@
 
 import java.io.*;
 import java.lang.management.*;
-import java.lang.reflect.Proxy;
 import java.net.*;
 
 import com.sun.c1x.*;
@@ -30,15 +29,13 @@
 import com.sun.cri.xir.*;
 import com.sun.hotspot.c1x.logging.*;
 import com.sun.hotspot.c1x.server.*;
-import com.sun.hotspot.c1x.server.ReplacingStreams.ReplacingInputStream;
-import com.sun.hotspot.c1x.server.ReplacingStreams.ReplacingOutputStream;
 
 /**
  * Singleton class holding the instance of the C1XCompiler.
  *
  * @author Thomas Wuerthinger, Lukas Stadler
  */
-public final class CompilerImpl implements Compiler {
+public final class CompilerImpl implements Compiler, Remote {
 
     private static Compiler theInstance;
     private static boolean PrintGCStats = false;
@@ -50,8 +47,27 @@
 
     public static Compiler getInstance() {
         if (theInstance == null) {
-            theInstance = new CompilerImpl(null);
-            Runtime.getRuntime().addShutdownHook(new ShutdownThread());
+            // remote compilation (will not create a C1XCompiler)
+            String remote = System.getProperty("c1x.remote");
+            if (remote != null) {
+                try {
+                    System.out.println("C1X compiler started in client/server mode, server: " + remote);
+                    Socket socket = new Socket(remote, 1199);
+                    ReplacingStreams streams = new ReplacingStreams(socket.getOutputStream(), socket.getInputStream());
+                    streams.getInvocation().sendResult(new VMEntriesNative());
+
+                    theInstance = (Compiler) streams.getInvocation().waitForResult();
+                } catch (IOException e1) {
+                    System.out.println("Connection to compilation server FAILED.");
+                    throw new RuntimeException(e1);
+                } catch (ClassNotFoundException e2) {
+                    System.out.println("Connection to compilation server FAILED.");
+                    throw new RuntimeException(e2);
+                }
+            } else {
+                theInstance = new CompilerImpl(null);
+                Runtime.getRuntime().addShutdownHook(new ShutdownThread());
+            }
         }
         return theInstance;
     }
@@ -96,6 +112,7 @@
     public static Compiler initializeServer(VMEntries entries) {
         assert theInstance == null;
         theInstance = new CompilerImpl(entries);
+        Runtime.getRuntime().addShutdownHook(new ShutdownThread());
         return theInstance;
     }
 
@@ -110,31 +127,6 @@
     }
 
     private CompilerImpl(VMEntries entries) {
-        // remote compilation (will not create a C1XCompiler)
-        String remote = System.getProperty("c1x.remote");
-        if (remote != null) {
-            try {
-                System.out.println("C1X compiler started in client/server mode, server: " + remote);
-                Socket socket = new Socket(remote, 1199);
-                ReplacingStreams streams = new ReplacingStreams();
-
-                ReplacingOutputStream output = streams.new ReplacingOutputStream(new BufferedOutputStream(socket.getOutputStream()));
-                // required, because creating an ObjectOutputStream writes a header, but doesn't flush the stream
-                output.flush();
-                ReplacingInputStream input = streams.new ReplacingInputStream(new BufferedInputStream(socket.getInputStream()));
-                input.setCompiler(this);
-
-                InvocationSocket invocation = new InvocationSocket(output, input);
-                vmEntries = new VMEntriesNative();
-                vmExits = (VMExits) Proxy.newProxyInstance(VMExits.class.getClassLoader(), new Class<?>[] { VMExits.class}, invocation);
-                invocation.setDelegate(vmEntries);
-                compiler = null;
-                return;
-            } catch (IOException t) {
-                System.out.println("Connection to compilation server FAILED.");
-                throw new RuntimeException(t);
-            }
-        }
 
         // initialize VMEntries
         if (entries == null)
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotTypeResolved.java	Fri Apr 08 13:47:56 2011 +0200
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotTypeResolved.java	Mon Apr 11 10:37:24 2011 +0200
@@ -20,50 +20,10 @@
  */
 package com.sun.hotspot.c1x;
 
-import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
-
-public interface HotSpotTypeResolved extends RiType {
-
-    public int accessFlags();
-
-    public RiType arrayOf();
-
-    public RiType componentType();
-
-    public RiType uniqueConcreteSubtype();
-
-    public RiType exactType();
-
-    public CiConstant getEncoding(Representation r);
-
-    public CiKind getRepresentationKind(Representation r);
-
-    public boolean hasFinalizableSubclass();
+import com.sun.hotspot.c1x.server.*;
 
-    public boolean hasFinalizer();
-
-    public boolean hasSubclass();
-
-    public boolean isArrayClass();
-
-    public boolean isInitialized();
-
-    public boolean isInstance(Object obj);
-
-    public boolean isInstanceClass();
-
-    public boolean isInterface();
-
-    public boolean isResolved();
-
-    public boolean isSubtypeOf(RiType other);
-
-    public Class<?> javaClass();
-
-    public CiKind kind();
-
-    public RiMethod resolveMethodImpl(RiMethod method);
+public interface HotSpotTypeResolved extends RiType, Remote {
 
     public String toString();
 
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/InvocationSocket.java	Fri Apr 08 13:47:56 2011 +0200
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/InvocationSocket.java	Mon Apr 11 10:37:24 2011 +0200
@@ -34,36 +34,24 @@
  *
  * @author Lukas Stadler
  */
-public class InvocationSocket implements InvocationHandler {
+public class InvocationSocket {
 
     private final ObjectOutputStream output;
     private final ObjectInputStream input;
-    private Object delegate;
-    private DelegateCallback callback;
 
     public InvocationSocket(ObjectOutputStream output, ObjectInputStream input) {
         this.output = output;
         this.input = input;
     }
 
-    public void setDelegate(Object delegate) {
-        this.delegate = delegate;
-    }
-
-    public static interface DelegateCallback {
-        public Object getDelegate();
-    }
-
-    public void setDelegateCallback(DelegateCallback callback) {
-        this.callback = callback;
-    }
-
     private static class Invocation implements Serializable {
 
+        public Object receiver;
         public String methodName;
         public Object[] args;
 
-        public Invocation(String methodName, Object[] args) {
+        public Invocation(Object receiver, String methodName, Object[] args) {
+            this.receiver = receiver;
             this.methodName = methodName;
             this.args = args;
         }
@@ -78,18 +66,29 @@
         }
     }
 
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        try {
-            Logger.startScope("invoking remote " + method.getName());
-            output.writeObject(new Invocation(method.getName(), args));
-            output.flush();
-            return waitForResult();
-        } catch (Throwable t) {
-            t.printStackTrace();
-            throw t;
-        } finally {
-            Logger.endScope("");
+    public class Handler implements InvocationHandler {
+        private Object receiver;
+
+        public Handler(Object receiver) {
+            this.receiver = receiver;
+        }
+
+        @Override
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            if (!method.getDeclaringClass().isInterface()) {
+                return method.invoke(receiver, args);
+            }
+            try {
+                //Logger.startScope("invoking remote " + method.getName());
+                output.writeObject(new Invocation(receiver, method.getName(), args));
+                output.flush();
+                return waitForResult();
+            } catch (Throwable t) {
+                t.printStackTrace();
+                throw t;
+            } finally {
+                //Logger.endScope("");
+            }
         }
     }
 
@@ -104,17 +103,14 @@
                 throw new RuntimeException((Throwable) in);
             }
 
-            if (delegate == null) {
-                delegate = callback.getDelegate();
-                callback = null;
-            }
-
             Invocation invoke = (Invocation) in;
             Method method = null;
-            for (Method m : delegate.getClass().getDeclaredMethods()) {
-                if (invoke.methodName.equals(m.getName())) {
-                    method = m;
-                    break;
+            for (Class<?> clazz = invoke.receiver.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
+                for (Method m : clazz.getDeclaredMethods()) {
+                    if (invoke.methodName.equals(m.getName())) {
+                        method = m;
+                        break;
+                    }
                 }
             }
             if (method == null) {
@@ -125,11 +121,20 @@
             } else {
                 Object result;
                 try {
-                    Logger.startScope("invoking local " + invoke.methodName);
                     if (invoke.args == null) {
-                        result = method.invoke(delegate);
+                        //Logger.startScope("invoking local " + invoke.methodName);
+                        result = method.invoke(invoke.receiver);
                     } else {
-                        result = method.invoke(delegate, invoke.args);
+                        /*
+                        StringBuilder str = new StringBuilder();
+                        str.append("invoking local " + invoke.methodName + "(");
+                        for (int i = 0; i < invoke.args.length; i++) {
+                            str.append(i == 0 ? "" : ", ");
+                            str.append(Logger.pretty(invoke.args[i]));
+                        }
+                        str.append(")");
+                        Logger.startScope(str.toString());*/
+                        result = method.invoke(invoke.receiver, invoke.args);
                     }
                     result = new Result(result);
                 } catch (IllegalArgumentException e) {
@@ -145,7 +150,7 @@
                     e.getCause().printStackTrace();
                     result = e.getCause();
                 } finally {
-                    Logger.endScope("");
+                    //Logger.endScope("");
                 }
                 output.writeObject(result);
                 output.flush();
@@ -153,4 +158,9 @@
         }
     }
 
+    public void sendResult(Object obj) throws IOException {
+        output.writeObject(new Result(obj));
+        output.flush();
+    }
+
 }
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/VMEntriesNative.java	Fri Apr 08 13:47:56 2011 +0200
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/VMEntriesNative.java	Mon Apr 11 10:37:24 2011 +0200
@@ -23,13 +23,14 @@
 
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
+import com.sun.hotspot.c1x.server.*;
 
 /**
  * Entries into the HotSpot VM from Java code.
  *
  * @author Thomas Wuerthinger, Lukas Stadler
  */
-public class VMEntriesNative implements VMEntries {
+public class VMEntriesNative implements VMEntries, Remote {
 
     // Checkstyle: stop
     @Override
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/VMExitsNative.java	Fri Apr 08 13:47:56 2011 +0200
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/VMExitsNative.java	Mon Apr 11 10:37:24 2011 +0200
@@ -30,13 +30,14 @@
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 import com.sun.hotspot.c1x.logging.*;
+import com.sun.hotspot.c1x.server.*;
 
 /**
  * Exits from the HotSpot VM into Java code.
  *
  * @author Thomas Wuerthinger, Lukas Stadler
  */
-public class VMExitsNative implements VMExits {
+public class VMExitsNative implements VMExits, Remote {
 
     public static final boolean LogCompiledMethods = false;
     public static boolean compileMethods = true;
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/logging/CountingProxy.java	Fri Apr 08 13:47:56 2011 +0200
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/logging/CountingProxy.java	Mon Apr 11 10:37:24 2011 +0200
@@ -23,6 +23,8 @@
 import java.lang.reflect.*;
 import java.util.*;
 
+import com.sun.hotspot.c1x.server.*;
+
 /**
  * A java.lang.reflect proxy that hierarchically logs all method invocations along with their parameters and return
  * values.
@@ -66,7 +68,8 @@
     }
 
     public static <T> T getProxy(Class<T> interf, T delegate) {
-        Object obj = Proxy.newProxyInstance(interf.getClassLoader(), new Class[] {interf}, new CountingProxy<T>(delegate));
+        Class<?>[] interfaces = ReplacingStreams.getAllInterfaces(delegate.getClass());
+        Object obj = Proxy.newProxyInstance(interf.getClassLoader(), interfaces, new CountingProxy<T>(delegate));
         return interf.cast(obj);
     }
 
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/logging/LoggingProxy.java	Fri Apr 08 13:47:56 2011 +0200
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/logging/LoggingProxy.java	Mon Apr 11 10:37:24 2011 +0200
@@ -22,6 +22,8 @@
 
 import java.lang.reflect.*;
 
+import com.sun.hotspot.c1x.server.*;
+
 /**
  * A java.lang.reflect proxy that hierarchically logs all method invocations along with their parameters and return values.
  *
@@ -64,8 +66,12 @@
         return result;
     }
 
+    /**
+     * The object returned by this method will implement all interfaces that are implemented by delegate.
+     */
     public static <T> T getProxy(Class<T> interf, T delegate) {
-        Object obj = Proxy.newProxyInstance(interf.getClassLoader(), new Class[] {interf}, new LoggingProxy<T>(delegate));
+        Class<?>[] interfaces = ReplacingStreams.getAllInterfaces(delegate.getClass());
+        Object obj = Proxy.newProxyInstance(interf.getClassLoader(), interfaces, new LoggingProxy<T>(delegate));
         return interf.cast(obj);
     }
 }
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/server/CompilationServer.java	Fri Apr 08 13:47:56 2011 +0200
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/server/CompilationServer.java	Mon Apr 11 10:37:24 2011 +0200
@@ -21,18 +21,13 @@
 package com.sun.hotspot.c1x.server;
 
 import java.io.*;
-import java.lang.reflect.Proxy;
 import java.net.*;
-import java.rmi.registry.*;
 
 import javax.net.*;
 
 import com.sun.hotspot.c1x.*;
 import com.sun.hotspot.c1x.Compiler;
-import com.sun.hotspot.c1x.InvocationSocket.DelegateCallback;
 import com.sun.hotspot.c1x.logging.*;
-import com.sun.hotspot.c1x.server.ReplacingStreams.ReplacingInputStream;
-import com.sun.hotspot.c1x.server.ReplacingStreams.ReplacingOutputStream;
 
 /**
  * Server side of the client/server compilation model.
@@ -41,9 +36,6 @@
  */
 public class CompilationServer {
 
-    private ReplacingOutputStream output;
-    private ReplacingInputStream input;
-
     public static void main(String[] args) throws Exception {
         new CompilationServer().run();
     }
@@ -52,28 +44,19 @@
         ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(1199);
         do {
             Socket socket = null;
-            ReplacingStreams streams = new ReplacingStreams();
             try {
                 Logger.log("Compilation server ready, waiting for client to connect...");
                 socket = serverSocket.accept();
                 Logger.log("Connected to " + socket.getRemoteSocketAddress());
 
-                output = streams.new ReplacingOutputStream(new BufferedOutputStream(socket.getOutputStream()));
-                // required, because creating an ObjectOutputStream writes a header, but doesn't flush the stream
-                output.flush();
-                input = streams.new ReplacingInputStream(new BufferedInputStream(socket.getInputStream()));
+                ReplacingStreams streams = new ReplacingStreams(socket.getOutputStream(), socket.getInputStream());
 
-                final InvocationSocket invocation = new InvocationSocket(output, input);
-                invocation.setDelegateCallback(new DelegateCallback() {
-                    public Object getDelegate() {
-                        VMEntries entries = (VMEntries) Proxy.newProxyInstance(VMEntries.class.getClassLoader(), new Class<?>[] { VMEntries.class}, invocation);
-                        Compiler compiler = CompilerImpl.initializeServer(entries);
-                        input.setCompiler(compiler);
-                        return compiler.getVMExits();
-                    }
-                });
+                VMEntries entries = (VMEntries) streams.getInvocation().waitForResult();
+                Compiler compiler = CompilerImpl.initializeServer(entries);
 
-                invocation.waitForResult();
+                streams.getInvocation().sendResult(compiler);
+
+                streams.getInvocation().waitForResult();
             } catch (IOException e) {
                 e.printStackTrace();
                 if (socket != null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/server/Remote.java	Mon Apr 11 10:37:24 2011 +0200
@@ -0,0 +1,6 @@
+package com.sun.hotspot.c1x.server;
+
+
+public interface Remote {
+
+}
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/server/ReplacingStreams.java	Fri Apr 08 13:47:56 2011 +0200
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/server/ReplacingStreams.java	Mon Apr 11 10:37:24 2011 +0200
@@ -21,40 +21,79 @@
 package com.sun.hotspot.c1x.server;
 
 import java.io.*;
+import java.lang.reflect.*;
 import java.util.*;
 
 import com.sun.cri.ci.*;
+import com.sun.hotspot.c1x.*;
 import com.sun.hotspot.c1x.Compiler;
 
 public class ReplacingStreams {
-    IdentityHashMap<Object, Long> objectMap = new IdentityHashMap<Object, Long>();
-    ArrayList<Object> objectList = new ArrayList<Object>();
+
+    private IdentityHashMap<Object, Placeholder> objectMap = new IdentityHashMap<Object, Placeholder>();
+    private ArrayList<Object> objectList = new ArrayList<Object>();
 
-    public static class Container implements Serializable {
+    private ReplacingOutputStream output;
+    private ReplacingInputStream input;
+
+    private InvocationSocket invocation;
 
-        public final Class<?> clazz;
-        public final Object[] values;
+    public ReplacingStreams(OutputStream outputStream, InputStream inputStream) throws IOException {
+        output = new ReplacingOutputStream(new BufferedOutputStream(outputStream));
+        // required, because creating an ObjectOutputStream writes a header, but doesn't flush the stream
+        output.flush();
+        input = new ReplacingInputStream(new BufferedInputStream(inputStream));
+        invocation = new InvocationSocket(output, input);
 
-        public Container(Class<?> clazz, Object... values) {
-            this.clazz = clazz;
-            this.values = values;
-        }
+        addStaticObject(CiValue.IllegalValue);
     }
 
-    public static enum PlaceholderType {
-        CI_CONSTANT_CONTENTS, RI_TYPE
+    public void setInvocationSocket(InvocationSocket invocation) {
+        this.invocation = invocation;
+    }
+
+    public ReplacingOutputStream getOutput() {
+        return output;
+    }
+
+    public ReplacingInputStream getInput() {
+        return input;
+    }
+
+    public InvocationSocket getInvocation() {
+        return invocation;
+    }
+
+    private void addStaticObject(Object obj) {
+        int id = objectList.size();
+        objectList.add(obj);
+        objectMap.put(obj, new Placeholder(id));
     }
 
     public static class Placeholder implements Serializable {
 
         public final int id;
-        public final PlaceholderType type;
 
-        public Placeholder(int id, PlaceholderType type) {
+        public Placeholder(int id) {
             this.id = id;
-            this.type = type;
         }
 
+        @Override
+        public String toString() {
+            return "#<" + id + ">";
+        }
+    }
+
+    public static class NewRemoteCallPlaceholder implements Serializable {
+
+        public final Class<?>[] interfaces;
+
+        public NewRemoteCallPlaceholder(Class<?>[] interfaces) {
+            this.interfaces = interfaces;
+        }
+    }
+
+    public static class NewDummyPlaceholder implements Serializable {
     }
 
     /**
@@ -75,33 +114,30 @@
 
         @Override
         protected Object resolveObject(Object obj) throws IOException {
-            if (obj instanceof Container) {
-                Container c = (Container) obj;
-                if (c.clazz == CiConstant.class) {
-                    return CiConstant.forBoxed((CiKind) c.values[0], c.values[1]);
-                } else if (c.clazz == CiValue.class) {
-                    return CiValue.IllegalValue;
-                } else if (c.clazz == Compiler.class) {
-                    assert compiler != null;
-                    return compiler;
-                }
-                throw new RuntimeException("unexpected container class: " + c.clazz);
-            } /*else if (obj instanceof Placeholder) {
-                Placeholder ph = (Placeholder)obj;
-                if (ph.id >= objectList.size()) {
-                    assert ph.id == objectList.size();
-                    switch (ph.type) {
-                        case CI_CONSTANT_CONTENTS:
-                            objectList.add(ph);
-                            break;
-                        case RI_TYPE:
-                            objectList.add(e)
-                            break;
-                    }
-                }
-                return objectList.get(ph.id);
+            // see ReplacingInputStream.replaceObject for details on when these types of objects are created
+
+            if (obj instanceof Placeholder) {
+                Placeholder placeholder = (Placeholder) obj;
+                obj = objectList.get(placeholder.id);
+                return obj;
+            }
 
-            }*/
+            if (obj instanceof NewRemoteCallPlaceholder) {
+                NewRemoteCallPlaceholder newPlaceholder = (NewRemoteCallPlaceholder) obj;
+                Placeholder placeholder = new Placeholder(objectList.size());
+                obj = Proxy.newProxyInstance(getClass().getClassLoader(), newPlaceholder.interfaces, invocation.new Handler(placeholder));
+                objectMap.put(obj, placeholder);
+                objectList.add(obj);
+                return obj;
+            }
+
+            if (obj instanceof NewDummyPlaceholder) {
+                obj = new Placeholder(objectList.size());
+                objectMap.put(obj, (Placeholder) obj);
+                objectList.add(obj);
+                return obj;
+            }
+
             return obj;
         }
     }
@@ -118,17 +154,58 @@
 
         @Override
         protected Object replaceObject(Object obj) throws IOException {
-            Class<? extends Object> clazz = obj.getClass();
-            if (clazz == CiConstant.class) {
-                CiConstant o = (CiConstant) obj;
-                return new Container(clazz, o.kind, o.boxedValue());
-            } else if (obj == CiValue.IllegalValue) {
-                return new Container(CiValue.class);
-            } else if (obj instanceof Compiler) {
-                return new Container(Compiler.class);
+            // is the object a known instance?
+            Placeholder placeholder = objectMap.get(obj);
+            if (placeholder != null) {
+                return placeholder;
+            }
+
+            // is the object an instance of a class that will always be executed remotely?
+            if (obj instanceof Remote) {
+                return createRemoteCallPlaceholder(obj);
+            }
+
+            // is the object a constant of object type?
+            if (obj.getClass() == CiConstant.class) {
+                System.out.println("CiConstant " + obj);
+                CiConstant constant = (CiConstant) obj;
+                // don't replace if the object already is a placeholder
+                if (constant.kind == CiKind.Object && !(constant.asObject() instanceof Placeholder) && constant.asObject() != null) {
+                    return CiConstant.forObject(createDummyPlaceholder(constant.asObject()));
+                }
             }
             return obj;
         }
     }
 
+    public static Class<?>[] getAllInterfaces(Class<?> clazz) {
+        HashSet<Class< ? >> interfaces = new HashSet<Class<?>>();
+        getAllInterfaces(clazz, interfaces);
+        return interfaces.toArray(new Class<?>[interfaces.size()]);
+    }
+
+    private static void getAllInterfaces(Class<?> clazz, HashSet<Class<?>> interfaces) {
+        for (Class< ? > iface : clazz.getInterfaces()) {
+            if (!interfaces.contains(iface)) {
+                interfaces.add(iface);
+                getAllInterfaces(iface, interfaces);
+            }
+        }
+        if (clazz.getSuperclass() != null) {
+            getAllInterfaces(clazz.getSuperclass(), interfaces);
+        }
+    }
+
+    private Object createRemoteCallPlaceholder(Object obj) {
+        // collect all interfaces that this object's class implements (proxies only support interfaces)
+        objectMap.put(obj, new Placeholder(objectList.size()));
+        objectList.add(obj);
+        return new NewRemoteCallPlaceholder(getAllInterfaces(obj.getClass()));
+    }
+
+    public Object createDummyPlaceholder(Object obj) {
+        objectMap.put(obj, new Placeholder(objectList.size()));
+        objectList.add(obj);
+        return new NewDummyPlaceholder();
+    }
 }
--- a/src/share/vm/c1x/c1x_VMEntries.cpp	Fri Apr 08 13:47:56 2011 +0200
+++ b/src/share/vm/c1x/c1x_VMEntries.cpp	Mon Apr 11 10:37:24 2011 +0200
@@ -352,6 +352,8 @@
 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1constantPool(JNIEnv *, jobject, jobject klass) {
   VM_ENTRY_MARK;
 
+  instanceOop(JNIHandles::resolve(klass))->print_value();
+
   assert(JNIHandles::resolve(klass) != NULL, "");
   constantPoolOop constantPool = ((instanceKlass*)java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))->klass_part())->constants();
   return JNIHandles::make_local(VMExits::createRiConstantPool(VmIds::add<constantPoolOop>(constantPool), THREAD));
--- a/src/share/vm/c1x/c1x_VMExits.cpp	Fri Apr 08 13:47:56 2011 +0200
+++ b/src/share/vm/c1x/c1x_VMExits.cpp	Mon Apr 11 10:37:24 2011 +0200
@@ -223,9 +223,16 @@
 oop VMExits::createCiConstantObject(Handle object, TRAPS) {
   JavaValue result(T_OBJECT);
   JavaCallArguments args;
+  /*
   args.push_oop(instance());
   args.push_oop(object);
   JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantObject_name(), vmSymbols::createCiConstantObject_signature(), &args, THREAD);
   check_pending_exception("Error while calling createCiConstantObject");
+  */
+
+
+  KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_cri_ci_CiConstant(), SystemDictionary::java_system_loader(), NULL, Thread::current());
+  JavaCalls::call_static(&result, klass(), vmSymbols::forObject_name(), vmSymbols::forObject_signature(), object, THREAD);
+  check_pending_exception("Error while calling CiConstant.forObject");
   return (oop) result.get_jobject();
 }
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Apr 08 13:47:56 2011 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Apr 11 10:37:24 2011 +0200
@@ -329,6 +329,8 @@
   template(getVMExits_signature,                      "()Lcom/sun/hotspot/c1x/VMExits;")                                \
   template(getInstance_name,                          "getInstance")                                                    \
   template(getInstance_signature,                     "()Lcom/sun/hotspot/c1x/Compiler;")                               \
+  template(forObject_name,                            "forObject")                                                      \
+  template(forObject_signature,                       "(Ljava/lang/Object;)Lcom/sun/cri/ci/CiConstant;")                \
                                                                                                                         \
   /* common method and field names */                                                             \
   template(object_initializer_name,                   "<init>")                                   \