src/macosx/native/jobjc/src/core/java/com/apple/jobjc/Coder.java

Print this page


   1 /*
   2  * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package com.apple.jobjc;
  26 
  27 import java.io.StringWriter;
  28 import java.lang.reflect.Method;
  29 
  30 import com.apple.jobjc.JObjCRuntime.Width;
  31 import com.apple.jobjc.PrimitiveCoder.BoolCoder;
  32 import com.apple.jobjc.PrimitiveCoder.DoubleCoder;
  33 import com.apple.jobjc.PrimitiveCoder.FloatCoder;
  34 import com.apple.jobjc.PrimitiveCoder.SCharCoder;
  35 import com.apple.jobjc.PrimitiveCoder.SIntCoder;
  36 import com.apple.jobjc.PrimitiveCoder.SLongLongCoder;
  37 import com.apple.jobjc.PrimitiveCoder.SShortCoder;
  38 import javax.tools.annotation.GenerateNativeHeader;
  39 
  40 public abstract class Coder<T> {
  41     private static native long getNativeFFITypePtrForCode(final int code);
  42 
  43     static final int FFI_VOID        = 0;
  44     static final int FFI_PTR        = FFI_VOID+1;
  45 
  46     static final int FFI_SINT8        = FFI_PTR+1;
  47     static final int FFI_UINT8        = FFI_SINT8+1;
  48     static final int FFI_SINT16        = FFI_UINT8+1;
  49     static final int FFI_UINT16        = FFI_SINT16+1;
  50     static final int FFI_SINT32        = FFI_UINT16+1;
  51     static final int FFI_UINT32        = FFI_SINT32+1;
  52     static final int FFI_SINT64        = FFI_UINT32+1;
  53     static final int FFI_UINT64        = FFI_SINT64+1;
  54 
  55     static final int FFI_FLOAT        = FFI_UINT64+1;
  56     static final int FFI_DOUBLE        = FFI_FLOAT+1;
  57     static final int FFI_LONGDOUBLE    = FFI_DOUBLE+1;
  58 
  59     private static long[] ffiCodesToFFITypePtrs;
  60     static{
  61         System.loadLibrary("JObjC");
  62         ffiCodesToFFITypePtrs = new long[FFI_LONGDOUBLE + 1];
  63         for (int i = 0; i < FFI_LONGDOUBLE + 1; i++) ffiCodesToFFITypePtrs[i] = getNativeFFITypePtrForCode(i);
  64     }
  65 
  66     long getFFITypePtr() {
  67         return ffiCodesToFFITypePtrs[getTypeCode()];
  68     }
  69 
  70     // runtime coding
  71     public abstract void push(final JObjCRuntime runtime, final long addr, final T x);
  72     public abstract T pop(final JObjCRuntime runtime, final long addr);
  73 
  74     public void push(final NativeArgumentBuffer args, final T x){
  75         push(args.runtime, args.argValuesPtr, x);
  76         args.didPutArgValue(sizeof());
  77     }


 126             try {
 127                 Method m = cls.getDeclaredMethod("getStructCoder");
 128                 m.setAccessible(true);
 129                 return (Coder) m.invoke(null);
 130             } catch (Exception e) {
 131                 throw new RuntimeException(e);
 132             }
 133         }
 134 
 135         throw new RuntimeException("Could not find suitable coder for " + cls);
 136     }
 137 
 138     static public Coder getCoderAtRuntime(Object inst){
 139         if(inst == null)              return PointerCoder.INST;
 140         if(inst instanceof Struct)    return ((Struct) inst).getCoder();
 141         return getCoderAtRuntimeForType(inst.getClass());
 142     }
 143 
 144     //
 145 
 146     /* No native methods here, but the constants are needed in the supporting JNI code */
 147     @GenerateNativeHeader
 148     public static final class VoidCoder extends Coder<Object>{
 149         public static final VoidCoder INST = new VoidCoder();
 150         public VoidCoder(){ super(FFI_VOID, "v", Void.class, void.class); }
 151         @Override public int sizeof(Width w) { return -1; }
 152         @Override public Object pop(JObjCRuntime runtime, long addr) { throw new RuntimeException("Trying to pop a Void."); }
 153         @Override public void push(JObjCRuntime runtime, long addr, Object x) { throw new RuntimeException("Trying to push a Void."); }
 154     }
 155 
 156     /* No native methods here, but the constants are needed in the supporting JNI code */
 157     @GenerateNativeHeader
 158     public static final class UnknownCoder extends Coder<Object> {
 159         public static final UnknownCoder INST = new UnknownCoder();
 160         public UnknownCoder(){ super(-1, "?", null, null); }
 161         @Override public int sizeof(Width w) { return -1; }
 162         @Override public void push(JObjCRuntime runtime, long addr, Object x) { throw new RuntimeException("Coder not implemented");}
 163         @Override public Object pop(JObjCRuntime runtime, long addr) { throw new RuntimeException("Coder not implemented"); }
 164     }
 165 
 166     /* No native methods here, but the constants are needed in the supporting JNI code */
 167     @GenerateNativeHeader
 168     public static final class PrimitivePointerCoder extends Coder<Long> {
 169         public static final PrimitivePointerCoder INST = new PrimitivePointerCoder();
 170         public PrimitivePointerCoder(){ super(Coder.FFI_PTR, "^?", Long.class, long.class); }
 171         @Override public int sizeof(Width w) { return JObjCRuntime.PTR_LEN; }
 172 
 173         public void push(JObjCRuntime runtime, long addr, long x) {
 174             if(JObjCRuntime.IS64)
 175                 runtime.unsafe.putLong(addr, x);
 176             else
 177                 runtime.unsafe.putInt(addr, (int) x);
 178         }
 179 
 180         public void push(final JObjCRuntime runtime, final NativeArgumentBuffer argBuf, final long ptr) {
 181             push(runtime, argBuf.argValuesPtr, ptr);
 182             argBuf.didPutArgValue(sizeof());
 183         }
 184 
 185         public long popPtr(final JObjCRuntime runtime, final long addr) {
 186             return JObjCRuntime.IS64 ? runtime.unsafe.getLong(addr) : runtime.unsafe.getInt(addr);
 187         }
 188 
 189         public long popPtr(final JObjCRuntime runtime, final NativeArgumentBuffer argBuf) {
 190             return popPtr(runtime, argBuf.retValPtr);
 191         }
 192 
 193         @Override public Long pop(JObjCRuntime runtime, long addr) { return popPtr(runtime, addr); }
 194         @Override public void push(JObjCRuntime runtime, long addr, Long x) { push(runtime, addr, (long) x); }
 195     }
 196 
 197     /* No native methods here, but the constants are needed in the supporting JNI code */
 198     @GenerateNativeHeader
 199     public static final class PointerCoder extends Coder<Pointer> {
 200         public static final PointerCoder INST = new PointerCoder();
 201         public PointerCoder(){ super(FFI_PTR, "^?", Pointer.class); }
 202         @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
 203 
 204         @Override public Pointer pop(JObjCRuntime runtime, long addr) {
 205             return new Pointer(PrimitivePointerCoder.INST.popPtr(runtime, addr));
 206         }
 207         @Override public void push(JObjCRuntime runtime, long addr, Pointer x) {
 208             PrimitivePointerCoder.INST.push(runtime, addr, x == null ? 0 : x.ptr);
 209         }
 210     }
 211 
 212     /* No native methods here, but the constants are needed in the supporting JNI code */
 213     @GenerateNativeHeader
 214     public static final class SELCoder extends Coder<SEL> {
 215         public static final SELCoder INST = new SELCoder();
 216         public SELCoder(){ super(FFI_PTR, ":", SEL.class); }
 217         @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
 218 
 219         @Override public void push(JObjCRuntime runtime, long addr, SEL x) {
 220             PrimitivePointerCoder.INST.push(runtime, addr, x == null ? 0 : x.selPtr);
 221         }
 222         @Override public SEL pop(JObjCRuntime runtime, long addr) {
 223             return new SEL(PrimitivePointerCoder.INST.popPtr(runtime, addr));
 224         }
 225     }
 226 
 227     /* No native methods here, but the constants are needed in the supporting JNI code */
 228     @GenerateNativeHeader
 229     public static abstract class StructCoder extends Coder<Struct> {
 230         private final FFIType ffiType;
 231         final int sizeof;
 232 
 233         public StructCoder(final int sizeof, final Coder... elementCoders){
 234             super(-1, objCEncoding(elementCoders), null);
 235             this.ffiType = new FFIType(elementCoders);
 236             this.sizeof = sizeof;
 237         }
 238 
 239         @Override public int sizeof(Width w) { return sizeof; }
 240 
 241         private static String objCEncoding(final Coder[] elementCoders) {
 242             StringWriter str = new StringWriter();
 243             str.append("{?=");
 244             for(Coder c : elementCoders)
 245                 str.append(c.getObjCEncoding());
 246             str.append("}");
 247             return str.toString();
 248         }


 250         @Override long getFFITypePtr() { return ffiType.getPtr(); }
 251 
 252         @Override public void push(NativeArgumentBuffer argBuf, Struct x) {
 253             // Just point to the instance on the heap instead of copying it onto the arg buf.
 254             argBuf.doPutArgPtr(x.raw.bufferPtr);
 255         }
 256 
 257         @Override public void push(JObjCRuntime rt, long addr, Struct x) {
 258             rt.unsafe.copyMemory(x.raw.bufferPtr, addr, sizeof);
 259         }
 260 
 261         protected abstract Struct newInstance(JObjCRuntime runtime);
 262 
 263         @Override public Struct pop(final JObjCRuntime runtime, final long addr) {
 264             Struct s = newInstance(runtime);
 265             runtime.unsafe.copyMemory(addr, s.raw.bufferPtr, sizeof);
 266             return s;
 267         }
 268     }
 269 
 270     /* No native methods here, but the constants are needed in the supporting JNI code */
 271     @GenerateNativeHeader
 272     public static final class IDCoder extends Coder<ID>{
 273         public static final IDCoder INST = new IDCoder();
 274         public IDCoder(){ super(FFI_PTR, "@", ID.class); }
 275         @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
 276 
 277         public <T extends ID> T newID(final JObjCRuntime runtime, final long objPtr) {
 278             return (T) ID.getObjCObjectFor(runtime, objPtr);
 279         }
 280 
 281         @Override public ID pop(final JObjCRuntime runtime, final long addr) {
 282             return newID(runtime, PrimitivePointerCoder.INST.popPtr(runtime, addr));
 283         }
 284 
 285         @Override public void push(final JObjCRuntime runtime, final long addr, final ID x) {
 286             PointerCoder.INST.push(runtime, addr, x);
 287         }
 288     }
 289 
 290     /* No native methods here, but the constants are needed in the supporting JNI code */
 291     @GenerateNativeHeader
 292     public static final class NSClassCoder extends Coder<NSClass>{
 293         public static final NSClassCoder INST = new NSClassCoder();
 294         public NSClassCoder(){ super(FFI_PTR, "#", NSClass.class); }
 295         @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
 296 
 297         @Override public NSClass pop(JObjCRuntime runtime, long addr) {
 298             final long clsPtr = PrimitivePointerCoder.INST.popPtr(runtime, addr);
 299             if (clsPtr == 0) return null;
 300             return NSClass.getObjCClassFor(runtime, clsPtr);
 301         }
 302         @Override public void push(JObjCRuntime runtime, long addr, NSClass x) {
 303             PointerCoder.INST.push(runtime, addr, x);
 304         }
 305     }
 306 }
   1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package com.apple.jobjc;
  26 
  27 import java.io.StringWriter;
  28 import java.lang.reflect.Method;
  29 
  30 import com.apple.jobjc.JObjCRuntime.Width;
  31 import com.apple.jobjc.PrimitiveCoder.BoolCoder;
  32 import com.apple.jobjc.PrimitiveCoder.DoubleCoder;
  33 import com.apple.jobjc.PrimitiveCoder.FloatCoder;
  34 import com.apple.jobjc.PrimitiveCoder.SCharCoder;
  35 import com.apple.jobjc.PrimitiveCoder.SIntCoder;
  36 import com.apple.jobjc.PrimitiveCoder.SLongLongCoder;
  37 import com.apple.jobjc.PrimitiveCoder.SShortCoder;
  38 import java.lang.annotation.Native;
  39 
  40 public abstract class Coder<T> {
  41     private static native long getNativeFFITypePtrForCode(final int code);
  42 
  43     @Native static final int FFI_VOID        = 0;
  44     @Native static final int FFI_PTR        = FFI_VOID+1;
  45 
  46     @Native static final int FFI_SINT8        = FFI_PTR+1;
  47     @Native static final int FFI_UINT8        = FFI_SINT8+1;
  48     @Native static final int FFI_SINT16        = FFI_UINT8+1;
  49     @Native static final int FFI_UINT16        = FFI_SINT16+1;
  50     @Native static final int FFI_SINT32        = FFI_UINT16+1;
  51     @Native static final int FFI_UINT32        = FFI_SINT32+1;
  52     @Native static final int FFI_SINT64        = FFI_UINT32+1;
  53     @Native static final int FFI_UINT64        = FFI_SINT64+1;
  54 
  55     @Native static final int FFI_FLOAT        = FFI_UINT64+1;
  56     @Native static final int FFI_DOUBLE        = FFI_FLOAT+1;
  57     @Native static final int FFI_LONGDOUBLE    = FFI_DOUBLE+1;
  58 
  59     private static long[] ffiCodesToFFITypePtrs;
  60     static{
  61         System.loadLibrary("JObjC");
  62         ffiCodesToFFITypePtrs = new long[FFI_LONGDOUBLE + 1];
  63         for (int i = 0; i < FFI_LONGDOUBLE + 1; i++) ffiCodesToFFITypePtrs[i] = getNativeFFITypePtrForCode(i);
  64     }
  65 
  66     long getFFITypePtr() {
  67         return ffiCodesToFFITypePtrs[getTypeCode()];
  68     }
  69 
  70     // runtime coding
  71     public abstract void push(final JObjCRuntime runtime, final long addr, final T x);
  72     public abstract T pop(final JObjCRuntime runtime, final long addr);
  73 
  74     public void push(final NativeArgumentBuffer args, final T x){
  75         push(args.runtime, args.argValuesPtr, x);
  76         args.didPutArgValue(sizeof());
  77     }


 126             try {
 127                 Method m = cls.getDeclaredMethod("getStructCoder");
 128                 m.setAccessible(true);
 129                 return (Coder) m.invoke(null);
 130             } catch (Exception e) {
 131                 throw new RuntimeException(e);
 132             }
 133         }
 134 
 135         throw new RuntimeException("Could not find suitable coder for " + cls);
 136     }
 137 
 138     static public Coder getCoderAtRuntime(Object inst){
 139         if(inst == null)              return PointerCoder.INST;
 140         if(inst instanceof Struct)    return ((Struct) inst).getCoder();
 141         return getCoderAtRuntimeForType(inst.getClass());
 142     }
 143 
 144     //
 145 


 146     public static final class VoidCoder extends Coder<Object>{
 147         public static final VoidCoder INST = new VoidCoder();
 148         public VoidCoder(){ super(FFI_VOID, "v", Void.class, void.class); }
 149         @Override public int sizeof(Width w) { return -1; }
 150         @Override public Object pop(JObjCRuntime runtime, long addr) { throw new RuntimeException("Trying to pop a Void."); }
 151         @Override public void push(JObjCRuntime runtime, long addr, Object x) { throw new RuntimeException("Trying to push a Void."); }
 152     }
 153 


 154     public static final class UnknownCoder extends Coder<Object> {
 155         public static final UnknownCoder INST = new UnknownCoder();
 156         public UnknownCoder(){ super(-1, "?", null, null); }
 157         @Override public int sizeof(Width w) { return -1; }
 158         @Override public void push(JObjCRuntime runtime, long addr, Object x) { throw new RuntimeException("Coder not implemented");}
 159         @Override public Object pop(JObjCRuntime runtime, long addr) { throw new RuntimeException("Coder not implemented"); }
 160     }
 161 


 162     public static final class PrimitivePointerCoder extends Coder<Long> {
 163         public static final PrimitivePointerCoder INST = new PrimitivePointerCoder();
 164         public PrimitivePointerCoder(){ super(Coder.FFI_PTR, "^?", Long.class, long.class); }
 165         @Override public int sizeof(Width w) { return JObjCRuntime.PTR_LEN; }
 166 
 167         public void push(JObjCRuntime runtime, long addr, long x) {
 168             if(JObjCRuntime.IS64)
 169                 runtime.unsafe.putLong(addr, x);
 170             else
 171                 runtime.unsafe.putInt(addr, (int) x);
 172         }
 173 
 174         public void push(final JObjCRuntime runtime, final NativeArgumentBuffer argBuf, final long ptr) {
 175             push(runtime, argBuf.argValuesPtr, ptr);
 176             argBuf.didPutArgValue(sizeof());
 177         }
 178 
 179         public long popPtr(final JObjCRuntime runtime, final long addr) {
 180             return JObjCRuntime.IS64 ? runtime.unsafe.getLong(addr) : runtime.unsafe.getInt(addr);
 181         }
 182 
 183         public long popPtr(final JObjCRuntime runtime, final NativeArgumentBuffer argBuf) {
 184             return popPtr(runtime, argBuf.retValPtr);
 185         }
 186 
 187         @Override public Long pop(JObjCRuntime runtime, long addr) { return popPtr(runtime, addr); }
 188         @Override public void push(JObjCRuntime runtime, long addr, Long x) { push(runtime, addr, (long) x); }
 189     }
 190 


 191     public static final class PointerCoder extends Coder<Pointer> {
 192         public static final PointerCoder INST = new PointerCoder();
 193         public PointerCoder(){ super(FFI_PTR, "^?", Pointer.class); }
 194         @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
 195 
 196         @Override public Pointer pop(JObjCRuntime runtime, long addr) {
 197             return new Pointer(PrimitivePointerCoder.INST.popPtr(runtime, addr));
 198         }
 199         @Override public void push(JObjCRuntime runtime, long addr, Pointer x) {
 200             PrimitivePointerCoder.INST.push(runtime, addr, x == null ? 0 : x.ptr);
 201         }
 202     }
 203 


 204     public static final class SELCoder extends Coder<SEL> {
 205         public static final SELCoder INST = new SELCoder();
 206         public SELCoder(){ super(FFI_PTR, ":", SEL.class); }
 207         @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
 208 
 209         @Override public void push(JObjCRuntime runtime, long addr, SEL x) {
 210             PrimitivePointerCoder.INST.push(runtime, addr, x == null ? 0 : x.selPtr);
 211         }
 212         @Override public SEL pop(JObjCRuntime runtime, long addr) {
 213             return new SEL(PrimitivePointerCoder.INST.popPtr(runtime, addr));
 214         }
 215     }
 216 


 217     public static abstract class StructCoder extends Coder<Struct> {
 218         private final FFIType ffiType;
 219         final int sizeof;
 220 
 221         public StructCoder(final int sizeof, final Coder... elementCoders){
 222             super(-1, objCEncoding(elementCoders), null);
 223             this.ffiType = new FFIType(elementCoders);
 224             this.sizeof = sizeof;
 225         }
 226 
 227         @Override public int sizeof(Width w) { return sizeof; }
 228 
 229         private static String objCEncoding(final Coder[] elementCoders) {
 230             StringWriter str = new StringWriter();
 231             str.append("{?=");
 232             for(Coder c : elementCoders)
 233                 str.append(c.getObjCEncoding());
 234             str.append("}");
 235             return str.toString();
 236         }


 238         @Override long getFFITypePtr() { return ffiType.getPtr(); }
 239 
 240         @Override public void push(NativeArgumentBuffer argBuf, Struct x) {
 241             // Just point to the instance on the heap instead of copying it onto the arg buf.
 242             argBuf.doPutArgPtr(x.raw.bufferPtr);
 243         }
 244 
 245         @Override public void push(JObjCRuntime rt, long addr, Struct x) {
 246             rt.unsafe.copyMemory(x.raw.bufferPtr, addr, sizeof);
 247         }
 248 
 249         protected abstract Struct newInstance(JObjCRuntime runtime);
 250 
 251         @Override public Struct pop(final JObjCRuntime runtime, final long addr) {
 252             Struct s = newInstance(runtime);
 253             runtime.unsafe.copyMemory(addr, s.raw.bufferPtr, sizeof);
 254             return s;
 255         }
 256     }
 257 


 258     public static final class IDCoder extends Coder<ID>{
 259         public static final IDCoder INST = new IDCoder();
 260         public IDCoder(){ super(FFI_PTR, "@", ID.class); }
 261         @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
 262 
 263         public <T extends ID> T newID(final JObjCRuntime runtime, final long objPtr) {
 264             return (T) ID.getObjCObjectFor(runtime, objPtr);
 265         }
 266 
 267         @Override public ID pop(final JObjCRuntime runtime, final long addr) {
 268             return newID(runtime, PrimitivePointerCoder.INST.popPtr(runtime, addr));
 269         }
 270 
 271         @Override public void push(final JObjCRuntime runtime, final long addr, final ID x) {
 272             PointerCoder.INST.push(runtime, addr, x);
 273         }
 274     }
 275 


 276     public static final class NSClassCoder extends Coder<NSClass>{
 277         public static final NSClassCoder INST = new NSClassCoder();
 278         public NSClassCoder(){ super(FFI_PTR, "#", NSClass.class); }
 279         @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
 280 
 281         @Override public NSClass pop(JObjCRuntime runtime, long addr) {
 282             final long clsPtr = PrimitivePointerCoder.INST.popPtr(runtime, addr);
 283             if (clsPtr == 0) return null;
 284             return NSClass.getObjCClassFor(runtime, clsPtr);
 285         }
 286         @Override public void push(JObjCRuntime runtime, long addr, NSClass x) {
 287             PointerCoder.INST.push(runtime, addr, x);
 288         }
 289     }
 290 }