Showing the changes to java (1415 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,444 @@ | ||
| 1 | +./pkg/inferno/awt/iImageConsumer.java | |
| 2 | +./pkg/java/applet/Applet.java | |
| 3 | +./pkg/java/applet/AppletContext.java | |
| 4 | +./pkg/java/applet/AppletStub.java | |
| 5 | +./pkg/java/applet/AudioClip.java | |
| 6 | +./pkg/java/awt/AWTError.java | |
| 7 | +./pkg/java/awt/AWTEvent.java | |
| 8 | +./pkg/java/awt/AWTEventMulticaster.java | |
| 9 | +./pkg/java/awt/AWTException.java | |
| 10 | +./pkg/java/awt/Adjustable.java | |
| 11 | +./pkg/java/awt/BorderLayout.java | |
| 12 | +./pkg/java/awt/Button.java | |
| 13 | +./pkg/java/awt/Canvas.java | |
| 14 | +./pkg/java/awt/CardLayout.java | |
| 15 | +./pkg/java/awt/Checkbox.java | |
| 16 | +./pkg/java/awt/CheckboxGroup.java | |
| 17 | +./pkg/java/awt/CheckboxMenuItem.java | |
| 18 | +./pkg/java/awt/Choice.java | |
| 19 | +./pkg/java/awt/Color.java | |
| 20 | +./pkg/java/awt/Component.java | |
| 21 | +./pkg/java/awt/Container.java | |
| 22 | +./pkg/java/awt/Cursor.java | |
| 23 | +./pkg/java/awt/Dialog.java | |
| 24 | +./pkg/java/awt/Dimension.java | |
| 25 | +./pkg/java/awt/Event.java | |
| 26 | +./pkg/java/awt/EventDispatchThread.java | |
| 27 | +./pkg/java/awt/EventQueue.java | |
| 28 | +./pkg/java/awt/FileDialog.java | |
| 29 | +./pkg/java/awt/FlowLayout.java | |
| 30 | +./pkg/java/awt/Font.java | |
| 31 | +./pkg/java/awt/FontMetrics.java | |
| 32 | +./pkg/java/awt/Frame.java | |
| 33 | +./pkg/java/awt/Graphics.java | |
| 34 | +./pkg/java/awt/GridBagConstraints.java | |
| 35 | +./pkg/java/awt/GridBagLayout.java | |
| 36 | +./pkg/java/awt/GridLayout.java | |
| 37 | +./pkg/java/awt/IllegalComponentStateEx..a | |
| 38 | +./pkg/java/awt/Image.java | |
| 39 | +./pkg/java/awt/Insets.java | |
| 40 | +./pkg/java/awt/ItemSelectable.java | |
| 41 | +./pkg/java/awt/Label.java | |
| 42 | +./pkg/java/awt/LayoutManager.java | |
| 43 | +./pkg/java/awt/LayoutManager2.java | |
| 44 | +./pkg/java/awt/List.java | |
| 45 | +./pkg/java/awt/MediaTracker.java | |
| 46 | +./pkg/java/awt/Menu.java | |
| 47 | +./pkg/java/awt/MenuBar.java | |
| 48 | +./pkg/java/awt/MenuComponent.java | |
| 49 | +./pkg/java/awt/MenuContainer.java | |
| 50 | +./pkg/java/awt/MenuItem.java | |
| 51 | +./pkg/java/awt/MenuShortcut.java | |
| 52 | +./pkg/java/awt/Panel.java | |
| 53 | +./pkg/java/awt/Point.java | |
| 54 | +./pkg/java/awt/Polygon.java | |
| 55 | +./pkg/java/awt/PopupMenu.java | |
| 56 | +./pkg/java/awt/PrintGraphics.java | |
| 57 | +./pkg/java/awt/PrintJob.java | |
| 58 | +./pkg/java/awt/Rectangle.java | |
| 59 | +./pkg/java/awt/ScrollPane.java | |
| 60 | +./pkg/java/awt/Scrollbar.java | |
| 61 | +./pkg/java/awt/Shape.java | |
| 62 | +./pkg/java/awt/SystemColor.java | |
| 63 | +./pkg/java/awt/TextArea.java | |
| 64 | +./pkg/java/awt/TextComponent.java | |
| 65 | +./pkg/java/awt/TextField.java | |
| 66 | +./pkg/java/awt/Toolkit.java | |
| 67 | +./pkg/java/awt/Window.java | |
| 68 | +./pkg/java/awt/datatransfer/Clipboard.java | |
| 69 | +./pkg/java/awt/datatransfer/ClipboardOwner.java | |
| 70 | +./pkg/java/awt/datatransfer/DataFlavor.java | |
| 71 | +./pkg/java/awt/datatransfer/StringSelection.java | |
| 72 | +./pkg/java/awt/datatransfer/Transferable.java | |
| 73 | +./pkg/java/awt/datatransfer/UnsupportedFlavorExcept..a | |
| 74 | +./pkg/java/awt/event/ActionEvent.java | |
| 75 | +./pkg/java/awt/event/ActionListener.java | |
| 76 | +./pkg/java/awt/event/AdjustmentEvent.java | |
| 77 | +./pkg/java/awt/event/AdjustmentListener.java | |
| 78 | +./pkg/java/awt/event/ComponentAdapter.java | |
| 79 | +./pkg/java/awt/event/ComponentEvent.java | |
| 80 | +./pkg/java/awt/event/ComponentListener.java | |
| 81 | +./pkg/java/awt/event/ContainerAdapter.java | |
| 82 | +./pkg/java/awt/event/ContainerEvent.java | |
| 83 | +./pkg/java/awt/event/ContainerListener.java | |
| 84 | +./pkg/java/awt/event/FocusAdapter.java | |
| 85 | +./pkg/java/awt/event/FocusEvent.java | |
| 86 | +./pkg/java/awt/event/FocusListener.java | |
| 87 | +./pkg/java/awt/event/InputEvent.java | |
| 88 | +./pkg/java/awt/event/ItemEvent.java | |
| 89 | +./pkg/java/awt/event/ItemListener.java | |
| 90 | +./pkg/java/awt/event/KeyAdapter.java | |
| 91 | +./pkg/java/awt/event/KeyEvent.java | |
| 92 | +./pkg/java/awt/event/KeyListener.java | |
| 93 | +./pkg/java/awt/event/MouseAdapter.java | |
| 94 | +./pkg/java/awt/event/MouseEvent.java | |
| 95 | +./pkg/java/awt/event/MouseListener.java | |
| 96 | +./pkg/java/awt/event/MouseMotionAdapter.java | |
| 97 | +./pkg/java/awt/event/MouseMotionListener.java | |
| 98 | +./pkg/java/awt/event/PaintEvent.java | |
| 99 | +./pkg/java/awt/event/TextEvent.java | |
| 100 | +./pkg/java/awt/event/TextListener.java | |
| 101 | +./pkg/java/awt/event/WindowAdapter.java | |
| 102 | +./pkg/java/awt/event/WindowEvent.java | |
| 103 | +./pkg/java/awt/event/WindowListener.java | |
| 104 | +./pkg/java/awt/image/AreaAveragingScaleFilte..a | |
| 105 | +./pkg/java/awt/image/ColorModel.java | |
| 106 | +./pkg/java/awt/image/CropImageFilter.java | |
| 107 | +./pkg/java/awt/image/DirectColorModel.java | |
| 108 | +./pkg/java/awt/image/FilteredImageSource.java | |
| 109 | +./pkg/java/awt/image/ImageConsumer.java | |
| 110 | +./pkg/java/awt/image/ImageFilter.java | |
| 111 | +./pkg/java/awt/image/ImageObserver.java | |
| 112 | +./pkg/java/awt/image/ImageProducer.java | |
| 113 | +./pkg/java/awt/image/IndexColorModel.java | |
| 114 | +./pkg/java/awt/image/MemoryImageSource.java | |
| 115 | +./pkg/java/awt/image/PixelGrabber.java | |
| 116 | +./pkg/java/awt/image/RGBImageFilter.java | |
| 117 | +./pkg/java/awt/image/ReplicateScaleFilter.java | |
| 118 | +./pkg/java/awt/peer/ActiveEvent.java | |
| 119 | +./pkg/java/awt/peer/ButtonPeer.java | |
| 120 | +./pkg/java/awt/peer/CanvasPeer.java | |
| 121 | +./pkg/java/awt/peer/CheckboxMenuItemPeer.java | |
| 122 | +./pkg/java/awt/peer/CheckboxPeer.java | |
| 123 | +./pkg/java/awt/peer/ChoicePeer.java | |
| 124 | +./pkg/java/awt/peer/ComponentPeer.java | |
| 125 | +./pkg/java/awt/peer/ContainerPeer.java | |
| 126 | +./pkg/java/awt/peer/DialogPeer.java | |
| 127 | +./pkg/java/awt/peer/FileDialogPeer.java | |
| 128 | +./pkg/java/awt/peer/FontPeer.java | |
| 129 | +./pkg/java/awt/peer/FramePeer.java | |
| 130 | +./pkg/java/awt/peer/LabelPeer.java | |
| 131 | +./pkg/java/awt/peer/LightweightPeer.java | |
| 132 | +./pkg/java/awt/peer/ListPeer.java | |
| 133 | +./pkg/java/awt/peer/MenuBarPeer.java | |
| 134 | +./pkg/java/awt/peer/MenuComponentPeer.java | |
| 135 | +./pkg/java/awt/peer/MenuItemPeer.java | |
| 136 | +./pkg/java/awt/peer/MenuPeer.java | |
| 137 | +./pkg/java/awt/peer/PanelPeer.java | |
| 138 | +./pkg/java/awt/peer/PopupMenuPeer.java | |
| 139 | +./pkg/java/awt/peer/ScrollPanePeer.java | |
| 140 | +./pkg/java/awt/peer/ScrollbarPeer.java | |
| 141 | +./pkg/java/awt/peer/TextAreaPeer.java | |
| 142 | +./pkg/java/awt/peer/TextComponentPeer.java | |
| 143 | +./pkg/java/awt/peer/TextFieldPeer.java | |
| 144 | +./pkg/java/awt/peer/WindowPeer.java | |
| 145 | +./pkg/java/beans/BeanDescriptor.java | |
| 146 | +./pkg/java/beans/BeanInfo.java | |
| 147 | +./pkg/java/beans/Beans.java | |
| 148 | +./pkg/java/beans/Customizer.java | |
| 149 | +./pkg/java/beans/EventSetDescriptor.java | |
| 150 | +./pkg/java/beans/FeatureDescriptor.java | |
| 151 | +./pkg/java/beans/IndexedPropertyDescript..a | |
| 152 | +./pkg/java/beans/IntrospectionException.java | |
| 153 | +./pkg/java/beans/Introspector.java | |
| 154 | +./pkg/java/beans/MethodDescriptor.java | |
| 155 | +./pkg/java/beans/ParameterDescriptor.java | |
| 156 | +./pkg/java/beans/PropertyChangeEvent.java | |
| 157 | +./pkg/java/beans/PropertyChangeListener.java | |
| 158 | +./pkg/java/beans/PropertyChangeSupport.java | |
| 159 | +./pkg/java/beans/PropertyDescriptor.java | |
| 160 | +./pkg/java/beans/PropertyEditor.java | |
| 161 | +./pkg/java/beans/PropertyEditorManager.java | |
| 162 | +./pkg/java/beans/PropertyEditorSupport.java | |
| 163 | +./pkg/java/beans/PropertyVetoException.java | |
| 164 | +./pkg/java/beans/SimpleBeanInfo.java | |
| 165 | +./pkg/java/beans/VetoableChangeListener.java | |
| 166 | +./pkg/java/beans/VetoableChangeSupport.java | |
| 167 | +./pkg/java/beans/Visibility.java | |
| 168 | +./pkg/java/io/BufferedInputStream.java | |
| 169 | +./pkg/java/io/BufferedOutputStream.java | |
| 170 | +./pkg/java/io/BufferedReader.java | |
| 171 | +./pkg/java/io/BufferedWriter.java | |
| 172 | +./pkg/java/io/ByteArrayInputStream.java | |
| 173 | +./pkg/java/io/ByteArrayOutputStream.java | |
| 174 | +./pkg/java/io/CharArrayReader.java | |
| 175 | +./pkg/java/io/CharArrayWriter.java | |
| 176 | +./pkg/java/io/CharConversionException..a | |
| 177 | +./pkg/java/io/DataInput.java | |
| 178 | +./pkg/java/io/DataInputStream.java | |
| 179 | +./pkg/java/io/DataOutput.java | |
| 180 | +./pkg/java/io/DataOutputStream.java | |
| 181 | +./pkg/java/io/EOFException.java | |
| 182 | +./pkg/java/io/Externalizable.java | |
| 183 | +./pkg/java/io/File.java | |
| 184 | +./pkg/java/io/FileDescriptor.java | |
| 185 | +./pkg/java/io/FileInputStream.java | |
| 186 | +./pkg/java/io/FileNotFoundException.java | |
| 187 | +./pkg/java/io/FileOutputStream.java | |
| 188 | +./pkg/java/io/FileReader.java | |
| 189 | +./pkg/java/io/FileWriter.java | |
| 190 | +./pkg/java/io/FilenameFilter.java | |
| 191 | +./pkg/java/io/FilterInputStream.java | |
| 192 | +./pkg/java/io/FilterOutputStream.java | |
| 193 | +./pkg/java/io/FilterReader.java | |
| 194 | +./pkg/java/io/FilterWriter.java | |
| 195 | +./pkg/java/io/IOException.java | |
| 196 | +./pkg/java/io/InputStream.java | |
| 197 | +./pkg/java/io/InputStreamReader.java | |
| 198 | +./pkg/java/io/InterruptedIOException.java | |
| 199 | +./pkg/java/io/InvalidClassException.java | |
| 200 | +./pkg/java/io/InvalidObjectException.java | |
| 201 | +./pkg/java/io/LineNumberInputStream.java | |
| 202 | +./pkg/java/io/LineNumberReader.java | |
| 203 | +./pkg/java/io/NotActiveException.java | |
| 204 | +./pkg/java/io/NotSerializableExceptio..a | |
| 205 | +./pkg/java/io/ObjectInput.java | |
| 206 | +./pkg/java/io/ObjectInputStream.java | |
| 207 | +./pkg/java/io/ObjectInputValidation.java | |
| 208 | +./pkg/java/io/ObjectOutput.java | |
| 209 | +./pkg/java/io/ObjectOutputStream.java | |
| 210 | +./pkg/java/io/ObjectStreamClass.java | |
| 211 | +./pkg/java/io/ObjectStreamConstants.java | |
| 212 | +./pkg/java/io/ObjectStreamException.java | |
| 213 | +./pkg/java/io/ObjectStreamField.java | |
| 214 | +./pkg/java/io/OptionalDataException.java | |
| 215 | +./pkg/java/io/OutputStream.java | |
| 216 | +./pkg/java/io/OutputStreamWriter.java | |
| 217 | +./pkg/java/io/PipedInputStream.java | |
| 218 | +./pkg/java/io/PipedOutputStream.java | |
| 219 | +./pkg/java/io/PipedReader.java | |
| 220 | +./pkg/java/io/PipedWriter.java | |
| 221 | +./pkg/java/io/PrintStream.java | |
| 222 | +./pkg/java/io/PrintWriter.java | |
| 223 | +./pkg/java/io/PushbackInputStream.java | |
| 224 | +./pkg/java/io/PushbackReader.java | |
| 225 | +./pkg/java/io/RandomAccessFile.java | |
| 226 | +./pkg/java/io/Reader.java | |
| 227 | +./pkg/java/io/SequenceInputStream.java | |
| 228 | +./pkg/java/io/Serializable.java | |
| 229 | +./pkg/java/io/StreamCorruptedExceptio..a | |
| 230 | +./pkg/java/io/StreamTokenizer.java | |
| 231 | +./pkg/java/io/StringBufferInputStream..a | |
| 232 | +./pkg/java/io/StringReader.java | |
| 233 | +./pkg/java/io/StringWriter.java | |
| 234 | +./pkg/java/io/SyncFailedException.java | |
| 235 | +./pkg/java/io/UTFDataFormatException.java | |
| 236 | +./pkg/java/io/UnsupportedEncodingExce..a | |
| 237 | +./pkg/java/io/WriteAbortedException.java | |
| 238 | +./pkg/java/io/Writer.java | |
| 239 | +./pkg/java/lang/AbstractMethodError.java | |
| 240 | +./pkg/java/lang/ArithmeticException.java | |
| 241 | +./pkg/java/lang/ArrayIndexOutOfBoundsEx..a | |
| 242 | +./pkg/java/lang/ArrayStoreException.java | |
| 243 | +./pkg/java/lang/Boolean.java | |
| 244 | +./pkg/java/lang/Byte.java | |
| 245 | +./pkg/java/lang/Character.java | |
| 246 | +./pkg/java/lang/Class.java | |
| 247 | +./pkg/java/lang/ClassCastException.java | |
| 248 | +./pkg/java/lang/ClassCircularityError.java | |
| 249 | +./pkg/java/lang/ClassFormatError.java | |
| 250 | +./pkg/java/lang/ClassLoader.java | |
| 251 | +./pkg/java/lang/ClassNotFoundException.java | |
| 252 | +./pkg/java/lang/CloneNotSupportedExcept..a | |
| 253 | +./pkg/java/lang/Cloneable.java | |
| 254 | +./pkg/java/lang/Compiler.java | |
| 255 | +./pkg/java/lang/Double.java | |
| 256 | +./pkg/java/lang/Error.java | |
| 257 | +./pkg/java/lang/Exception.java | |
| 258 | +./pkg/java/lang/Float.java | |
| 259 | +./pkg/java/lang/IllegalAccessError.java | |
| 260 | +./pkg/java/lang/IllegalAccessException.java | |
| 261 | +./pkg/java/lang/IllegalArgumentExceptio..a | |
| 262 | +./pkg/java/lang/IllegalMonitorStateExce..a | |
| 263 | +./pkg/java/lang/IllegalStateException.java | |
| 264 | +./pkg/java/lang/IllegalThreadStateExcep..a | |
| 265 | +./pkg/java/lang/IncompatibleClassChange..a | |
| 266 | +./pkg/java/lang/IndexOutOfBoundsExcepti..a | |
| 267 | +./pkg/java/lang/InfernoProcess.java | |
| 268 | +./pkg/java/lang/InstantiationError.java | |
| 269 | +./pkg/java/lang/InstantiationException.java | |
| 270 | +./pkg/java/lang/Integer.java | |
| 271 | +./pkg/java/lang/InternalError.java | |
| 272 | +./pkg/java/lang/InterruptedException.java | |
| 273 | +./pkg/java/lang/LinkageError.java | |
| 274 | +./pkg/java/lang/Long.java | |
| 275 | +./pkg/java/lang/Math.java | |
| 276 | +./pkg/java/lang/NegativeArraySizeExcept..a | |
| 277 | +./pkg/java/lang/NoClassDefFoundError.java | |
| 278 | +./pkg/java/lang/NoSuchFieldError.java | |
| 279 | +./pkg/java/lang/NoSuchFieldException.java | |
| 280 | +./pkg/java/lang/NoSuchMethodError.java | |
| 281 | +./pkg/java/lang/NoSuchMethodException.java | |
| 282 | +./pkg/java/lang/NullPointerException.java | |
| 283 | +./pkg/java/lang/Number.java | |
| 284 | +./pkg/java/lang/NumberFormatException.java | |
| 285 | +./pkg/java/lang/Object.java | |
| 286 | +./pkg/java/lang/OutOfMemoryError.java | |
| 287 | +./pkg/java/lang/Process.java | |
| 288 | +./pkg/java/lang/Runnable.java | |
| 289 | +./pkg/java/lang/Runtime.java | |
| 290 | +./pkg/java/lang/RuntimeException.java | |
| 291 | +./pkg/java/lang/SecurityException.java | |
| 292 | +./pkg/java/lang/SecurityManager.java | |
| 293 | +./pkg/java/lang/Short.java | |
| 294 | +./pkg/java/lang/StackOverflowError.java | |
| 295 | +./pkg/java/lang/String.java | |
| 296 | +./pkg/java/lang/StringBuffer.java | |
| 297 | +./pkg/java/lang/StringIndexOutOfBoundsE..a | |
| 298 | +./pkg/java/lang/System.java | |
| 299 | +./pkg/java/lang/Thread.java | |
| 300 | +./pkg/java/lang/ThreadDeath.java | |
| 301 | +./pkg/java/lang/ThreadGroup.java | |
| 302 | +./pkg/java/lang/Throwable.java | |
| 303 | +./pkg/java/lang/UnknownError.java | |
| 304 | +./pkg/java/lang/UnsatisfiedLinkError.java | |
| 305 | +./pkg/java/lang/VerifyError.java | |
| 306 | +./pkg/java/lang/VirtualMachineError.java | |
| 307 | +./pkg/java/lang/Void.java | |
| 308 | +./pkg/java/lang/reflect/Array.java | |
| 309 | +./pkg/java/lang/reflect/Constructor.java | |
| 310 | +./pkg/java/lang/reflect/Field.java | |
| 311 | +./pkg/java/lang/reflect/InvocationTargetExcepti..a | |
| 312 | +./pkg/java/lang/reflect/Member.java | |
| 313 | +./pkg/java/lang/reflect/Method.java | |
| 314 | +./pkg/java/lang/reflect/Modifier.java | |
| 315 | +./pkg/java/net/BindException.java | |
| 316 | +./pkg/java/net/ConnectException.java | |
| 317 | +./pkg/java/net/ContentHandler.java | |
| 318 | +./pkg/java/net/ContentHandlerFactory.java | |
| 319 | +./pkg/java/net/DatagramPacket.java | |
| 320 | +./pkg/java/net/DatagramSocket.java | |
| 321 | +./pkg/java/net/DatagramSocketImpl.java | |
| 322 | +./pkg/java/net/FileNameMap.java | |
| 323 | +./pkg/java/net/HttpURLConnection.java | |
| 324 | +./pkg/java/net/InetAddress.java | |
| 325 | +./pkg/java/net/MalformedURLException.java | |
| 326 | +./pkg/java/net/MulticastSocket.java | |
| 327 | +./pkg/java/net/NoRouteToHostException.java | |
| 328 | +./pkg/java/net/PlainDatagramSocketImpl..a | |
| 329 | +./pkg/java/net/PlainSocketImpl.java | |
| 330 | +./pkg/java/net/ProtocolException.java | |
| 331 | +./pkg/java/net/ServerSocket.java | |
| 332 | +./pkg/java/net/Socket.java | |
| 333 | +./pkg/java/net/SocketException.java | |
| 334 | +./pkg/java/net/SocketImpl.java | |
| 335 | +./pkg/java/net/SocketImplFactory.java | |
| 336 | +./pkg/java/net/SocketInputStream.java | |
| 337 | +./pkg/java/net/SocketOptions.java | |
| 338 | +./pkg/java/net/SocketOutputStream.java | |
| 339 | +./pkg/java/net/URL.java | |
| 340 | +./pkg/java/net/URLConnection.java | |
| 341 | +./pkg/java/net/URLEncoder.java | |
| 342 | +./pkg/java/net/URLStreamHandler.java | |
| 343 | +./pkg/java/net/URLStreamHandlerFactory..a | |
| 344 | +./pkg/java/net/UnknownHostException.java | |
| 345 | +./pkg/java/net/UnknownServiceException..a | |
| 346 | +./pkg/java/security/DigestException.java | |
| 347 | +./pkg/java/security/DigestOutputStream.java | |
| 348 | +./pkg/java/security/MessageDigest.java | |
| 349 | +./pkg/java/security/NoSuchAlgorithmExceptio..a | |
| 350 | +./pkg/java/security/NoSuchProviderException..a | |
| 351 | +./pkg/java/security/Provider.java | |
| 352 | +./pkg/java/security/Security.java | |
| 353 | +./pkg/java/util/BitSet.java | |
| 354 | +./pkg/java/util/Date.java | |
| 355 | +./pkg/java/util/Dictionary.java | |
| 356 | +./pkg/java/util/EmptyStackException.java | |
| 357 | +./pkg/java/util/Enumeration.java | |
| 358 | +./pkg/java/util/EventListener.java | |
| 359 | +./pkg/java/util/EventObject.java | |
| 360 | +./pkg/java/util/Hashtable.java | |
| 361 | +./pkg/java/util/NoSuchElementException.java | |
| 362 | +./pkg/java/util/Observable.java | |
| 363 | +./pkg/java/util/Observer.java | |
| 364 | +./pkg/java/util/Properties.java | |
| 365 | +./pkg/java/util/Random.java | |
| 366 | +./pkg/java/util/Stack.java | |
| 367 | +./pkg/java/util/StringTokenizer.java | |
| 368 | +./pkg/java/util/Vector.java | |
| 369 | +./pkg/java/util/zip/CRC32.java | |
| 370 | +./pkg/java/util/zip/CheckedInputStream.java | |
| 371 | +./pkg/java/util/zip/CheckedOutputStream.java | |
| 372 | +./pkg/java/util/zip/Checksum.java | |
| 373 | +./pkg/java/util/zip/DataFormatException.java | |
| 374 | +./pkg/java/util/zip/GZIPInputStream.java | |
| 375 | +./pkg/java/util/zip/Inflater.java | |
| 376 | +./pkg/java/util/zip/InflaterInputStream.java | |
| 377 | +./pkg/java/util/zip/ZipConstants.java | |
| 378 | +./pkg/java/util/zip/ZipEntry.java | |
| 379 | +./pkg/java/util/zip/ZipException.java | |
| 380 | +./pkg/java/util/zip/ZipInputStream.java | |
| 381 | +./pkg/sun/awt/AWTFinalizeable.java | |
| 382 | +./pkg/sun/awt/AWTFinalizer.java | |
| 383 | +./pkg/sun/awt/DrawingSurface.java | |
| 384 | +./pkg/sun/awt/DrawingSurfaceInfo.java | |
| 385 | +./pkg/sun/awt/PhysicalDrawingSurface.java | |
| 386 | +./pkg/sun/awt/image/ByteArrayImageSource.java | |
| 387 | +./pkg/sun/awt/image/FileImageSource.java | |
| 388 | +./pkg/sun/awt/image/GifImageDecoder.java | |
| 389 | +./pkg/sun/awt/image/Image.java | |
| 390 | +./pkg/sun/awt/image/ImageConsumerQueue.java | |
| 391 | +./pkg/sun/awt/image/ImageDecoder.java | |
| 392 | +./pkg/sun/awt/image/ImageFetchable.java | |
| 393 | +./pkg/sun/awt/image/ImageFetcher.java | |
| 394 | +./pkg/sun/awt/image/ImageFormatException.java | |
| 395 | +./pkg/sun/awt/image/ImageRepresentation.java | |
| 396 | +./pkg/sun/awt/image/ImageWatched.java | |
| 397 | +./pkg/sun/awt/image/InputStreamImageSource.java | |
| 398 | +./pkg/sun/awt/image/OffScreenImageSource.java | |
| 399 | +./pkg/sun/awt/image/PixelStore.java | |
| 400 | +./pkg/sun/awt/image/PixelStore32.java | |
| 401 | +./pkg/sun/awt/image/PixelStore8.java | |
| 402 | +./pkg/sun/awt/image/URLImageSource.java | |
| 403 | +./pkg/sun/awt/image/XbmImageDecoder.java | |
| 404 | +./pkg/sun/io/ByteToCharConverter.java | |
| 405 | +./pkg/sun/io/CharToByteConverter.java | |
| 406 | +./pkg/sun/io/ConversionBufferFullExc..a | |
| 407 | +./pkg/sun/io/MalformedInputException..a | |
| 408 | +./pkg/sun/io/UnknownCharacterExcepti..a | |
| 409 | +./pkg/sun/misc/REException.java | |
| 410 | +./pkg/sun/misc/Ref.java | |
| 411 | +./pkg/sun/misc/Regexp.java | |
| 412 | +./pkg/sun/misc/RegexpPool.java | |
| 413 | +./pkg/sun/misc/RegexpTarget.java | |
| 414 | +./pkg/sun/net/NetworkClient.java | |
| 415 | +./pkg/sun/net/ProgressData.java | |
| 416 | +./pkg/sun/net/ProgressEntry.java | |
| 417 | +./pkg/sun/net/TransferProtocolClient.java | |
| 418 | +./pkg/sun/net/URLCanonicalizer.java | |
| 419 | +./pkg/sun/net/www/ApplicationLaunchExcept..a | |
| 420 | +./pkg/sun/net/www/HeaderParser.java | |
| 421 | +./pkg/sun/net/www/MessageHeader.java | |
| 422 | +./pkg/sun/net/www/MeteredStream.java | |
| 423 | +./pkg/sun/net/www/MimeLauncher.java | |
| 424 | +./pkg/sun/net/www/URLConnection.java | |
| 425 | +./pkg/sun/net/www/http/HttpClient.java | |
| 426 | +./pkg/sun/net/www/http/KeepAliveCache.java | |
| 427 | +./pkg/sun/net/www/http/KeepAliveStream.java | |
| 428 | +./pkg/sun/net/www/protocol/http/AuthenticationInfo.java | |
| 429 | +./pkg/sun/net/www/protocol/http/Handler.java | |
| 430 | +./pkg/sun/net/www/protocol/http/HttpAuthenticator.java | |
| 431 | +./pkg/sun/net/www/protocol/http/HttpURLConnection.java | |
| 432 | +./pkg/sun/security/provider/SHA.java | |
| 433 | +./pkg/sun/security/provider/Sun.java | |
| 434 | +./pkg/sunw/awt/ActionInputPreferred.java | |
| 435 | +./pkg/sunw/awt/DoubleBuffering.java | |
| 436 | +./pkg/sunw/awt/KeyboardInputPreferred.java | |
| 437 | +./pkg/sunw/awt/NoInputPreferred.java | |
| 438 | +./pkg/sunw/awt/PositionalInputPreferre..a | |
| 439 | +./pkg/sunw/lang/UnsupportedOperationExc..a | |
| 440 | +./pkg/sunw/util/DefaultTimer.java | |
| 441 | +./pkg/sunw/util/PTimer.java | |
| 442 | +./pkg/sunw/util/PTimerSpec.java | |
| 443 | +./pkg/sunw/util/PTimerWentOffEvent.java | |
| 444 | +./pkg/sunw/util/PTimerWentOffListener.java | |
| @@ -0,0 +1,39 @@ | ||
| 1 | +Java is a registered trademark of Sun Microsystems Inc. in the USA and other countries. | |
| 2 | + | |
| 3 | +This software includes: | |
| 4 | + | |
| 5 | + 1. empty source files corresponding to Java source files that were marked as proprietary to Sun Microsystems Inc. | |
| 6 | + The original source file names were kept to allow the source to be replaced by equivalent source that | |
| 7 | + is no longer secret. | |
| 8 | + The full list of files that were cleared can be found in the file Javalist. | |
| 9 | + | |
| 10 | + 2. Java, C and Limbo source files for which rights to reproduce and relicence were acquired by | |
| 11 | + Vita Nuova Holdings Limited at 1 March 2000, under the Inferno licence agreement. | |
| 12 | + | |
| 13 | +The files are made available on the following terms: | |
| 14 | + | |
| 15 | +This copyright NOTICE applies to all files in this directory and | |
| 16 | +subdirectories, unless another copyright notice appears in a given | |
| 17 | +file or subdirectory. If you take substantial code from this software to use in | |
| 18 | +other programs, you must somehow include with it an appropriate | |
| 19 | +copyright notice that includes the copyright notice and the other | |
| 20 | +notices below. It is fine (and often tidier) to do that in a separate | |
| 21 | +file such as NOTICE, LICENCE or COPYING. | |
| 22 | + | |
| 23 | +Copyright © 1996-1999 Lucent Technologies Inc. | |
| 24 | +Portions Copyright © 1999-2000 Vita Nuova Limited | |
| 25 | +Portions Copyright © 2000-2007 Vita Nuova Holdings Limited | |
| 26 | + | |
| 27 | +This program is free software; you can redistribute it and/or modify | |
| 28 | +it under the terms of the GNU General Public License as published by | |
| 29 | +the Free Software Foundation; either version 2 of the License, or | |
| 30 | +(at your option) any later version. | |
| 31 | + | |
| 32 | +This program is distributed in the hope that it will be useful, | |
| 33 | +but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 34 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 35 | +GNU General Public License for more details. | |
| 36 | + | |
| 37 | +You should have received a copy of the GNU General Public License | |
| 38 | +along with this program; if not, write to the Free Software | |
| 39 | +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
Binary file not shown.
| @@ -0,0 +1,50 @@ | ||
| 1 | +Arg: adt | |
| 2 | +{ | |
| 3 | + argv: list of string; | |
| 4 | + c: int; | |
| 5 | + opts: string; | |
| 6 | + | |
| 7 | + init: fn(argv: list of string): ref Arg; | |
| 8 | + opt: fn(arg: self ref Arg): int; | |
| 9 | + arg: fn(arg: self ref Arg): string; | |
| 10 | +}; | |
| 11 | + | |
| 12 | +Arg.init(argv: list of string): ref Arg | |
| 13 | +{ | |
| 14 | + if(argv != nil) | |
| 15 | + argv = tl argv; | |
| 16 | + return ref Arg(argv, 0, nil); | |
| 17 | +} | |
| 18 | + | |
| 19 | +Arg.opt(arg: self ref Arg): int | |
| 20 | +{ | |
| 21 | + if(arg.opts != ""){ | |
| 22 | + arg.c = arg.opts[0]; | |
| 23 | + arg.opts = arg.opts[1:]; | |
| 24 | + return arg.c; | |
| 25 | + } | |
| 26 | + if(arg.argv == nil) | |
| 27 | + return arg.c = 0; | |
| 28 | + arg.opts = hd arg.argv; | |
| 29 | + if(len arg.opts < 2 || arg.opts[0] != '-') | |
| 30 | + return arg.c = 0; | |
| 31 | + arg.argv = tl arg.argv; | |
| 32 | + if(arg.opts == "--") | |
| 33 | + return arg.c = 0; | |
| 34 | + arg.c = arg.opts[1]; | |
| 35 | + arg.opts = arg.opts[2:]; | |
| 36 | + return arg.c; | |
| 37 | +} | |
| 38 | + | |
| 39 | +Arg.arg(arg: self ref Arg): string | |
| 40 | +{ | |
| 41 | + s := arg.opts; | |
| 42 | + arg.opts = ""; | |
| 43 | + if(s != "") | |
| 44 | + return s; | |
| 45 | + if(arg.argv == nil) | |
| 46 | + return ""; | |
| 47 | + s = hd arg.argv; | |
| 48 | + arg.argv = tl arg.argv; | |
| 49 | + return s; | |
| 50 | +} | |
| @@ -0,0 +1,319 @@ | ||
| 1 | +# | |
| 2 | +# Dis opcode mnemonics. Keep in sync with interp/tab.h! | |
| 3 | +# | |
| 4 | + | |
| 5 | +#MAXDIS: con INEWAZ+1; | |
| 6 | + | |
| 7 | +instname := array [MAXDIS] of { | |
| 8 | + "nop", | |
| 9 | + "alt", | |
| 10 | + "nbalt", | |
| 11 | + "goto", | |
| 12 | + "call", | |
| 13 | + "frame", | |
| 14 | + "spawn", | |
| 15 | + "runt", | |
| 16 | + "load", | |
| 17 | + "mcall", | |
| 18 | + "mspawn", | |
| 19 | + "mframe", | |
| 20 | + "ret", | |
| 21 | + "jmp", | |
| 22 | + "case", | |
| 23 | + "exit", | |
| 24 | + "new", | |
| 25 | + "newa", | |
| 26 | + "newcb", | |
| 27 | + "newcw", | |
| 28 | + "newcf", | |
| 29 | + "newcp", | |
| 30 | + "newcm", | |
| 31 | + "newcmp", | |
| 32 | + "send", | |
| 33 | + "recv", | |
| 34 | + "consb", | |
| 35 | + "consw", | |
| 36 | + "consp", | |
| 37 | + "consf", | |
| 38 | + "consm", | |
| 39 | + "consmp", | |
| 40 | + "headb", | |
| 41 | + "headw", | |
| 42 | + "headp", | |
| 43 | + "headf", | |
| 44 | + "headm", | |
| 45 | + "headmp", | |
| 46 | + "tail", | |
| 47 | + "lea", | |
| 48 | + "indx", | |
| 49 | + "movp", | |
| 50 | + "movm", | |
| 51 | + "movmp", | |
| 52 | + "movb", | |
| 53 | + "movw", | |
| 54 | + "movf", | |
| 55 | + "cvtbw", | |
| 56 | + "cvtwb", | |
| 57 | + "cvtfw", | |
| 58 | + "cvtwf", | |
| 59 | + "cvtca", | |
| 60 | + "cvtac", | |
| 61 | + "cvtwc", | |
| 62 | + "cvtcw", | |
| 63 | + "cvtfc", | |
| 64 | + "cvtcf", | |
| 65 | + "addb", | |
| 66 | + "addw", | |
| 67 | + "addf", | |
| 68 | + "subb", | |
| 69 | + "subw", | |
| 70 | + "subf", | |
| 71 | + "mulb", | |
| 72 | + "mulw", | |
| 73 | + "mulf", | |
| 74 | + "divb", | |
| 75 | + "divw", | |
| 76 | + "divf", | |
| 77 | + "modw", | |
| 78 | + "modb", | |
| 79 | + "andb", | |
| 80 | + "andw", | |
| 81 | + "orb", | |
| 82 | + "orw", | |
| 83 | + "xorb", | |
| 84 | + "xorw", | |
| 85 | + "shlb", | |
| 86 | + "shlw", | |
| 87 | + "shrb", | |
| 88 | + "shrw", | |
| 89 | + "insc", | |
| 90 | + "indc", | |
| 91 | + "addc", | |
| 92 | + "lenc", | |
| 93 | + "lena", | |
| 94 | + "lenl", | |
| 95 | + "beqb", | |
| 96 | + "bneb", | |
| 97 | + "bltb", | |
| 98 | + "bleb", | |
| 99 | + "bgtb", | |
| 100 | + "bgeb", | |
| 101 | + "beqw", | |
| 102 | + "bnew", | |
| 103 | + "bltw", | |
| 104 | + "blew", | |
| 105 | + "bgtw", | |
| 106 | + "bgew", | |
| 107 | + "beqf", | |
| 108 | + "bnef", | |
| 109 | + "bltf", | |
| 110 | + "blef", | |
| 111 | + "bgtf", | |
| 112 | + "bgef", | |
| 113 | + "beqc", | |
| 114 | + "bnec", | |
| 115 | + "bltc", | |
| 116 | + "blec", | |
| 117 | + "bgtc", | |
| 118 | + "bgec", | |
| 119 | + "slicea", | |
| 120 | + "slicela", | |
| 121 | + "slicec", | |
| 122 | + "indw", | |
| 123 | + "indf", | |
| 124 | + "indb", | |
| 125 | + "negf", | |
| 126 | + "movl", | |
| 127 | + "addl", | |
| 128 | + "subl", | |
| 129 | + "divl", | |
| 130 | + "modl", | |
| 131 | + "mull", | |
| 132 | + "andl", | |
| 133 | + "orl", | |
| 134 | + "xorl", | |
| 135 | + "shll", | |
| 136 | + "shrl", | |
| 137 | + "bnel", | |
| 138 | + "bltl", | |
| 139 | + "blel", | |
| 140 | + "bgtl", | |
| 141 | + "bgel", | |
| 142 | + "beql", | |
| 143 | + "cvtlf", | |
| 144 | + "cvtfl", | |
| 145 | + "cvtlw", | |
| 146 | + "cvtwl", | |
| 147 | + "cvtlc", | |
| 148 | + "cvtcl", | |
| 149 | + "headl", | |
| 150 | + "consl", | |
| 151 | + "newcl", | |
| 152 | + "casec", | |
| 153 | + "indl", | |
| 154 | + "movpc", | |
| 155 | + "tcmp", | |
| 156 | + "mnewz", | |
| 157 | + "cvtrf", | |
| 158 | + "cvtfr", | |
| 159 | + "cvtws", | |
| 160 | + "cvtsw", | |
| 161 | + "lsrw", | |
| 162 | + "lsrl", | |
| 163 | + "eclr", | |
| 164 | + "newz", | |
| 165 | + "newaz", | |
| 166 | + "raise", | |
| 167 | +}; | |
| 168 | + | |
| 169 | +# | |
| 170 | +# %A format conversion. | |
| 171 | +# | |
| 172 | + | |
| 173 | +addrconv(a: ref Addr): string | |
| 174 | +{ | |
| 175 | + s := ""; | |
| 176 | + case int a.mode { | |
| 177 | + int Aimm => | |
| 178 | + s = "$" + string a.ival; | |
| 179 | + int Afp => | |
| 180 | + s = string a.offset + "(fp)"; | |
| 181 | + int Amp => | |
| 182 | + s = string a.offset + "(mp)"; | |
| 183 | + int Afpind => | |
| 184 | + s = string a.offset + "(" + string a.ival + "(fp))"; | |
| 185 | + int Ampind => | |
| 186 | + s = string a.offset + "(" + string a.ival + "(mp))"; | |
| 187 | + } | |
| 188 | + return s; | |
| 189 | +} | |
| 190 | + | |
| 191 | +# | |
| 192 | +# %I format conversion. | |
| 193 | +# | |
| 194 | + | |
| 195 | +instconv(in: ref Inst): string | |
| 196 | +{ | |
| 197 | + op := ""; | |
| 198 | + if(in.op < byte MAXDIS) | |
| 199 | + op = instname[int in.op]; | |
| 200 | + else | |
| 201 | + op = "??"; | |
| 202 | + s := "\t" + op + "\t"; | |
| 203 | + comma := ""; | |
| 204 | + if(in.s.mode != Anone) { | |
| 205 | + s += addrconv(in.s); | |
| 206 | + comma = ","; | |
| 207 | + } | |
| 208 | + if(in.m.mode != Anone) { | |
| 209 | + s += comma; | |
| 210 | + s += addrconv(in.m); | |
| 211 | + comma = ","; | |
| 212 | + } | |
| 213 | + if(in.d.mode != Anone) | |
| 214 | + s += comma; | |
| 215 | + s += addrconv(in.d); | |
| 216 | + return s; | |
| 217 | +} | |
| 218 | + | |
| 219 | +ehtable(c: ref Code) | |
| 220 | +{ | |
| 221 | + i: int; | |
| 222 | + s: string; | |
| 223 | + h: ref Handler; | |
| 224 | + | |
| 225 | + if(c.nex == 0) | |
| 226 | + return; | |
| 227 | + bout.puts("#\tException Table\n"); | |
| 228 | + for(i = 0; i < c.nex; i++) { | |
| 229 | + h = c.ex[i]; | |
| 230 | + if(h.catch_type == 0) | |
| 231 | + s = "*"; | |
| 232 | + else | |
| 233 | + s = CLASSNAME(h.catch_type); | |
| 234 | + bout.puts("#\t" + string h.start_pc + " " + string h.end_pc | |
| 235 | + + " " + string h.handler_pc + " " + s + "\n"); | |
| 236 | + } | |
| 237 | +} | |
| 238 | + | |
| 239 | +putinst(i: ref Inst) | |
| 240 | +{ | |
| 241 | + while(i != nil) { | |
| 242 | + if(i.pc % 10 == 0) | |
| 243 | + bout.puts("#" + string i.pc + "\n"); | |
| 244 | + bout.puts(instconv(i) + "\n"); | |
| 245 | + i = i.next; | |
| 246 | + } | |
| 247 | +} | |
| 248 | + | |
| 249 | +clinitclone: ref Inst; # generated <clinit>, <clone> methods | |
| 250 | + | |
| 251 | +# | |
| 252 | +# Emit assembly instructions for a method. | |
| 253 | +# | |
| 254 | + | |
| 255 | +asminst() | |
| 256 | +{ | |
| 257 | + i: ref Inst; | |
| 258 | + j: ref Jinst; | |
| 259 | + n, jix: int; | |
| 260 | + c: ref Code; | |
| 261 | + | |
| 262 | + if(verbose == 0) { | |
| 263 | + putinst(ihead); | |
| 264 | + return; | |
| 265 | + } | |
| 266 | + | |
| 267 | + # -v option | |
| 268 | + | |
| 269 | + for(n = 0; n < class.methods_count; n++) { | |
| 270 | + bout.puts("#Method: " + pcode[n].name + pcode[n].sig + "\n"); | |
| 271 | + if(pcode[n].code == nil) | |
| 272 | + continue; | |
| 273 | + ehtable(pcode[n].code); | |
| 274 | + c = pcode[n].code; | |
| 275 | + jix = 0; | |
| 276 | + while(jix < c.code_length) { | |
| 277 | + j = c.j[jix]; | |
| 278 | + bout.puts("#J" + string j.pc + "\t" + jinstconv(j) + "\n"); | |
| 279 | + for(i = j.dis; i != nil && i.j == j; i = i.next) { | |
| 280 | + if(i.pc % 10 == 0) | |
| 281 | + bout.puts("#" + string i.pc + "\n"); | |
| 282 | + bout.puts(instconv(i) + "\n"); | |
| 283 | + } | |
| 284 | + jix += j.size; | |
| 285 | + } | |
| 286 | + } | |
| 287 | + | |
| 288 | + if(clinitclone != nil) { | |
| 289 | + bout.puts("#Method: <clinit|clone>()V\n"); | |
| 290 | + putinst(clinitclone); | |
| 291 | + } | |
| 292 | +} | |
| 293 | + | |
| 294 | +sblinst(bsym: ref Bufio->Iobuf) | |
| 295 | +{ | |
| 296 | + i: ref Inst; | |
| 297 | + n, curline, lastline, lastchar, blockid: int; | |
| 298 | + | |
| 299 | + if(itail != nil) | |
| 300 | + n = itail.pc + 1; | |
| 301 | + else | |
| 302 | + n = 0; | |
| 303 | + bsym.puts(string n + "\n"); | |
| 304 | + curline = 1; | |
| 305 | + lastline = -1; | |
| 306 | + lastchar = 6; | |
| 307 | + blockid = -1; | |
| 308 | + for(i = ihead; i != nil; i = i.next) { | |
| 309 | + if(i.j != nil) | |
| 310 | + curline = i.j.line; | |
| 311 | + if(curline != lastline) { | |
| 312 | + lastline = curline; | |
| 313 | + lastchar = 6; | |
| 314 | + blockid++; | |
| 315 | + bsym.puts(string curline + "."); | |
| 316 | + } | |
| 317 | + bsym.puts("1," + string lastchar++ + " " + string blockid + "\n"); | |
| 318 | + } | |
| 319 | +} | |
| @@ -0,0 +1,326 @@ | ||
| 1 | +roots: array of ref BB; # root basic blocks | |
| 2 | +nr: int; # number of root basic blocks | |
| 3 | +maxr: int; # maximum number of roots | |
| 4 | + | |
| 5 | +setflags(pc: int, flags: byte) | |
| 6 | +{ | |
| 7 | + j: ref Jinst; | |
| 8 | + | |
| 9 | + j = code.j[pc]; | |
| 10 | + if(j.bb == nil) { | |
| 11 | + j.bb = ref BB(j, nil, 0, nil, byte 0, byte BB_PRESIM, 0, nil, 0, nil); | |
| 12 | + # record root basic blocks | |
| 13 | + if(int (flags & (BB_ENTRY | BB_FINALLY | BB_HANDLER))) { | |
| 14 | + if(nr >= maxr) { | |
| 15 | + oldmaxr := maxr; | |
| 16 | + maxr += ALLOCINCR; | |
| 17 | + newroots := array [maxr] of ref BB; | |
| 18 | + for(i := 0; i < oldmaxr; i++) | |
| 19 | + newroots[i] = roots[i]; | |
| 20 | + roots = newroots; | |
| 21 | + } | |
| 22 | + roots[nr] = j.bb; | |
| 23 | + nr += 1; | |
| 24 | + } | |
| 25 | + } | |
| 26 | + j.bb.flags |= flags; | |
| 27 | +} | |
| 28 | + | |
| 29 | +# | |
| 30 | +# Verify that the target of a jump is valid. | |
| 31 | +# | |
| 32 | + | |
| 33 | +verifyjump(j: ref Jinst, offset: int) | |
| 34 | +{ | |
| 35 | + dst: int; | |
| 36 | + | |
| 37 | + dst = j.pc + offset; | |
| 38 | + if(dst < 0 || dst >= code.code_length || code.j[dst] == nil) | |
| 39 | + verifyerror(j); | |
| 40 | +} | |
| 41 | + | |
| 42 | +# | |
| 43 | +# Mark the instructions of a method that are basic block leaders. | |
| 44 | +# | |
| 45 | + | |
| 46 | +markldrs() | |
| 47 | +{ | |
| 48 | + j: ref Jinst; | |
| 49 | + jpi: ref Jinst.Pi; | |
| 50 | + jpt1: ref Jinst.Pt1; | |
| 51 | + jpt2: ref Jinst.Pt2; | |
| 52 | + jpw: ref Jinst.Pw; | |
| 53 | + i: int; | |
| 54 | + pc, pcnext: int; | |
| 55 | + | |
| 56 | + # first instruction is a leader | |
| 57 | + setflags(0, BB_LDR | BB_ENTRY); | |
| 58 | + | |
| 59 | + # exception handler entry points are leaders | |
| 60 | + for(i = 0; i < code.nex; i++) | |
| 61 | + setflags(code.ex[i].handler_pc, BB_LDR | BB_HANDLER); | |
| 62 | + | |
| 63 | + pc = 0; | |
| 64 | + while(pc < code.code_length) { | |
| 65 | + j = code.j[pc]; | |
| 66 | + pcnext = pc+j.size; | |
| 67 | + pick jp := j { | |
| 68 | + Pi => | |
| 69 | + jpi = jp; | |
| 70 | + Pt1 => | |
| 71 | + jpt1 = jp; | |
| 72 | + Pt2 => | |
| 73 | + jpt2 = jp; | |
| 74 | + Pw => | |
| 75 | + jpw = jp; | |
| 76 | + } | |
| 77 | + case int j.op { | |
| 78 | + Jwide => | |
| 79 | + if(int jpw.w.op == Jret && pcnext < code.code_length) | |
| 80 | + setflags(pcnext, BB_LDR); | |
| 81 | + Jret or | |
| 82 | + Jireturn or | |
| 83 | + Jlreturn or | |
| 84 | + Jfreturn or | |
| 85 | + Jdreturn or | |
| 86 | + Jareturn or | |
| 87 | + Jreturn or | |
| 88 | + Jathrow => | |
| 89 | + if(pcnext < code.code_length) | |
| 90 | + setflags(pcnext, BB_LDR); | |
| 91 | + Jifeq or | |
| 92 | + Jifne or | |
| 93 | + Jiflt or | |
| 94 | + Jifge or | |
| 95 | + Jifgt or | |
| 96 | + Jifle or | |
| 97 | + Jif_icmpeq or | |
| 98 | + Jif_icmpne or | |
| 99 | + Jif_icmplt or | |
| 100 | + Jif_icmpge or | |
| 101 | + Jif_icmpgt or | |
| 102 | + Jif_icmple or | |
| 103 | + Jif_acmpeq or | |
| 104 | + Jif_acmpne or | |
| 105 | + Jifnull or | |
| 106 | + Jifnonnull => | |
| 107 | + verifyjump(j, jpi.i); | |
| 108 | + setflags(pc+jpi.i, BB_LDR); | |
| 109 | + setflags(pcnext, BB_LDR); | |
| 110 | + Jgoto or | |
| 111 | + Jgoto_w => | |
| 112 | + verifyjump(j, jpi.i); | |
| 113 | + setflags(pc+jpi.i, BB_LDR); | |
| 114 | + if(pcnext < code.code_length) | |
| 115 | + setflags(pcnext, BB_LDR); | |
| 116 | + Jjsr or | |
| 117 | + Jjsr_w => | |
| 118 | + # target of jsr is leader, jsr successor isn't | |
| 119 | + verifyjump(j, jpi.i); | |
| 120 | + setflags(pc+jpi.i, BB_LDR | BB_FINALLY); | |
| 121 | + finallyentry(pc+jpi.i); | |
| 122 | + Jtableswitch => | |
| 123 | + for(i = 0; i < jpt1.t1.hb - jpt1.t1.lb + 1; i++) { | |
| 124 | + verifyjump(j, jpt1.t1.tbl[i]); | |
| 125 | + setflags(pc+jpt1.t1.tbl[i], BB_LDR); | |
| 126 | + } | |
| 127 | + verifyjump(j, jpt1.t1.dflt); | |
| 128 | + setflags(pc+jpt1.t1.dflt, BB_LDR); | |
| 129 | + if(pcnext < code.code_length) | |
| 130 | + setflags(pcnext, BB_LDR); | |
| 131 | + Jlookupswitch => | |
| 132 | + for(i = 0; i < jpt2.t2.np; i++) { | |
| 133 | + verifyjump(j, jpt2.t2.tbl[2*i+1]); | |
| 134 | + setflags(pc+jpt2.t2.tbl[2*i+1], BB_LDR); | |
| 135 | + } | |
| 136 | + verifyjump(j, jpt2.t2.dflt); | |
| 137 | + setflags(pc+jpt2.t2.dflt, BB_LDR); | |
| 138 | + if(pcnext < code.code_length) | |
| 139 | + setflags(pcnext, BB_LDR); | |
| 140 | + } | |
| 141 | + pc = pcnext; | |
| 142 | + } | |
| 143 | +} | |
| 144 | + | |
| 145 | +# | |
| 146 | +# Link basic block bb to its successors. | |
| 147 | +# | |
| 148 | + | |
| 149 | +linksucc(bb: ref BB) | |
| 150 | +{ | |
| 151 | + i: int; | |
| 152 | + pc: int; | |
| 153 | + je: ref Jinst; | |
| 154 | + jpi: ref Jinst.Pi; | |
| 155 | + jpt1: ref Jinst.Pt1; | |
| 156 | + jpt2: ref Jinst.Pt2; | |
| 157 | + jpw: ref Jinst.Pw; | |
| 158 | + | |
| 159 | + bb.nsucc = 0; | |
| 160 | + bb.succ = nil; | |
| 161 | + je = bb.je; | |
| 162 | + pc = je.pc; | |
| 163 | + | |
| 164 | + pick jp := je { | |
| 165 | + Pi => | |
| 166 | + jpi = jp; | |
| 167 | + Pt1 => | |
| 168 | + jpt1 = jp; | |
| 169 | + Pt2 => | |
| 170 | + jpt2 = jp; | |
| 171 | + Pw => | |
| 172 | + jpw = jp; | |
| 173 | + } | |
| 174 | + | |
| 175 | + case int je.op { | |
| 176 | + Jwide => | |
| 177 | + if(int jpw.w.op != Jret && pc+je.size < code.code_length) { | |
| 178 | + bb.nsucc = 1; | |
| 179 | + bb.succ = array [1] of ref BB; | |
| 180 | + bb.succ[0] = code.j[pc+je.size].bb; | |
| 181 | + } | |
| 182 | + * => | |
| 183 | + if(pc+je.size < code.code_length) { | |
| 184 | + bb.nsucc = 1; | |
| 185 | + bb.succ = array [1] of ref BB; | |
| 186 | + bb.succ[0] = code.j[pc+je.size].bb; | |
| 187 | + } | |
| 188 | + Jret or | |
| 189 | + Jireturn or | |
| 190 | + Jlreturn or | |
| 191 | + Jfreturn or | |
| 192 | + Jdreturn or | |
| 193 | + Jareturn or | |
| 194 | + Jreturn or | |
| 195 | + Jathrow => | |
| 196 | + ; | |
| 197 | + Jifeq or | |
| 198 | + Jifne or | |
| 199 | + Jiflt or | |
| 200 | + Jifge or | |
| 201 | + Jifgt or | |
| 202 | + Jifle or | |
| 203 | + Jif_icmpeq or | |
| 204 | + Jif_icmpne or | |
| 205 | + Jif_icmplt or | |
| 206 | + Jif_icmpge or | |
| 207 | + Jif_icmpgt or | |
| 208 | + Jif_icmple or | |
| 209 | + Jif_acmpeq or | |
| 210 | + Jif_acmpne or | |
| 211 | + Jifnull or | |
| 212 | + Jifnonnull => | |
| 213 | + bb.nsucc = 2; | |
| 214 | + bb.succ = array [2] of ref BB; | |
| 215 | + bb.succ[0] = code.j[pc+jpi.i].bb; # branch target | |
| 216 | + bb.succ[1] = code.j[pc+je.size].bb; # fall through | |
| 217 | + Jgoto or | |
| 218 | + Jgoto_w => | |
| 219 | + bb.nsucc = 1; | |
| 220 | + bb.succ = array [1] of ref BB; | |
| 221 | + bb.succ[0] = code.j[pc+jpi.i].bb; | |
| 222 | + Jtableswitch => | |
| 223 | + bb.nsucc = jpt1.t1.hb - jpt1.t1.lb + 2; | |
| 224 | + bb.succ = array [bb.nsucc] of ref BB; | |
| 225 | + for(i = 0; i < bb.nsucc-1; i++) | |
| 226 | + bb.succ[i] = code.j[pc+jpt1.t1.tbl[i]].bb; | |
| 227 | + bb.succ[i] = code.j[pc+jpt1.t1.dflt].bb; | |
| 228 | + Jlookupswitch => | |
| 229 | + bb.nsucc = jpt2.t2.np + 1; | |
| 230 | + bb.succ = array [bb.nsucc] of ref BB; | |
| 231 | + for(i = 0; i < bb.nsucc-1; i++) | |
| 232 | + bb.succ[i] = code.j[pc+jpt2.t2.tbl[2*i+1]].bb; | |
| 233 | + bb.succ[i] = code.j[pc+jpt2.t2.dflt].bb; | |
| 234 | + } | |
| 235 | +} | |
| 236 | + | |
| 237 | +# | |
| 238 | +# Build the basic block control flow graph. | |
| 239 | +# | |
| 240 | + | |
| 241 | +flowgraph() | |
| 242 | +{ | |
| 243 | + js, je: ref Jinst; | |
| 244 | + pc, pcnext: int; | |
| 245 | + | |
| 246 | + markldrs(); | |
| 247 | + | |
| 248 | + pc = 0; | |
| 249 | + while(pc < code.code_length) { | |
| 250 | + js = code.j[pc]; | |
| 251 | + if(js.bb == nil) | |
| 252 | + fatal("flowgraph: nil bb"); | |
| 253 | + # find last instruction in basic block | |
| 254 | + je = js; | |
| 255 | + while() { | |
| 256 | + pcnext = je.pc + je.size; | |
| 257 | + if(pcnext >= code.code_length | |
| 258 | + || code.j[pcnext].bb != nil) # hence a leader | |
| 259 | + break; | |
| 260 | + je = code.j[pcnext]; | |
| 261 | + je.bb = js.bb; | |
| 262 | + } | |
| 263 | + js.bb.je = je; | |
| 264 | + linksucc(js.bb); | |
| 265 | + pc = pcnext; | |
| 266 | + } | |
| 267 | + finallyalloc(); | |
| 268 | +} | |
| 269 | + | |
| 270 | +# | |
| 271 | +# Free basic block structures after each method is translated. | |
| 272 | +# | |
| 273 | + | |
| 274 | +bbfree() | |
| 275 | +{ | |
| 276 | + j: ref Jinst; | |
| 277 | + jix: int; | |
| 278 | + | |
| 279 | + jix = 0; | |
| 280 | + while(jix < code.code_length) { | |
| 281 | + j = code.j[jix]; | |
| 282 | + if(j.bb.je == j) { | |
| 283 | + j.bb.succ = nil; | |
| 284 | + j.bb = nil; | |
| 285 | + } | |
| 286 | + jix += j.size; | |
| 287 | + } | |
| 288 | + roots = nil; | |
| 289 | + nr = 0; | |
| 290 | + maxr = 0; | |
| 291 | +} | |
| 292 | + | |
| 293 | +# | |
| 294 | +# The following stuff is used during method simulation. | |
| 295 | +# | |
| 296 | + | |
| 297 | +SSIZE: con 128; | |
| 298 | +bbstack := array [SSIZE] of ref BB; | |
| 299 | +bbtos: int; | |
| 300 | + | |
| 301 | +bbput(bb: ref BB) | |
| 302 | +{ | |
| 303 | + if(bbtos == SSIZE) | |
| 304 | + fatal("bbstack overflow"); | |
| 305 | + bb.state = BB_ACTIVE; | |
| 306 | + bb.flags |= BB_REACHABLE; | |
| 307 | + bbstack[bbtos++] = bb; | |
| 308 | +} | |
| 309 | + | |
| 310 | +bbget(): ref BB | |
| 311 | +{ | |
| 312 | + ret: ref BB; | |
| 313 | + | |
| 314 | + if(bbtos != 0) | |
| 315 | + ret = bbstack[--bbtos]; | |
| 316 | + return ret; | |
| 317 | +} | |
| 318 | + | |
| 319 | +bbinit() | |
| 320 | +{ | |
| 321 | + i: int; | |
| 322 | + | |
| 323 | + bbtos = 0; | |
| 324 | + for(i = 0; i < nr; i++) | |
| 325 | + bbput(roots[i]); | |
| 326 | +} | |
| @@ -0,0 +1,186 @@ | ||
| 1 | +# | |
| 2 | +# Manage module data relocation and instruction patch information. | |
| 3 | +# | |
| 4 | + | |
| 5 | +dreloc: ref Ipatch; | |
| 6 | +Ipatchtid: int; | |
| 7 | + | |
| 8 | +setIpatchtid() | |
| 9 | +{ | |
| 10 | + Ipatchtid = descid(1, 0, array [1] of { byte 0 }); | |
| 11 | +} | |
| 12 | + | |
| 13 | +# | |
| 14 | +# Add an instruction patch directive to ip. | |
| 15 | +# (flag == SAVEINST) <=> runtime relocation: Inst* needed later | |
| 16 | +# (flag == !SAVEINST) <=> other: pinfo expected in sequential order | |
| 17 | +# | |
| 18 | + | |
| 19 | +addIpatch(ip: ref Ipatch, i: ref Inst, operand: int, patchkind: int, flag: int) | |
| 20 | +{ | |
| 21 | + j: int; | |
| 22 | + | |
| 23 | + if(ip.n >= ip.max) { | |
| 24 | + oldmax := ip.max; | |
| 25 | + ip.max += ALLOCINCR; | |
| 26 | + newippinfo := array [ip.max] of int; | |
| 27 | + for(j = 0; j < oldmax; j++) | |
| 28 | + newippinfo[j] = ip.pinfo[j]; | |
| 29 | + ip.pinfo = newippinfo; | |
| 30 | + if(flag == SAVEINST) { | |
| 31 | + newipi := array [ip.max] of ref Inst; | |
| 32 | + for(j = 0; j < oldmax; j++) | |
| 33 | + newipi[j] = ip.i[j]; | |
| 34 | + ip.i = newipi; | |
| 35 | + } | |
| 36 | + } | |
| 37 | + ip.pinfo[ip.n] = (i.pc << 8) | operand | patchkind; | |
| 38 | + if(flag == SAVEINST) | |
| 39 | + ip.i[ip.n] = i; | |
| 40 | + ip.n += 1; | |
| 41 | +} | |
| 42 | + | |
| 43 | +operand := array [] of { | |
| 44 | + "?", | |
| 45 | + "src", # PSRC >> 2 | |
| 46 | + "dst", # PDST >> 2 | |
| 47 | + "mid" # PMID >> 2 | |
| 48 | +}; | |
| 49 | + | |
| 50 | +mode := array [] of { | |
| 51 | + "$x", # PIMM | |
| 52 | + "x(reg)", # PSIND | |
| 53 | + "n(x(reg))", # PDIND1 | |
| 54 | + "x(n(reg))" # PDIND2 | |
| 55 | +}; | |
| 56 | + | |
| 57 | +ba: array of byte; | |
| 58 | +nba: int; | |
| 59 | +HIGHBIT: con byte 16r80; | |
| 60 | + | |
| 61 | +sizeba(sz: int) | |
| 62 | +{ | |
| 63 | + if(sz > len ba) { | |
| 64 | + newba := array [sz] of byte; | |
| 65 | + for(i := 0; i < nba; i++) | |
| 66 | + newba[i] = ba[i]; | |
| 67 | + ba = newba; | |
| 68 | + } | |
| 69 | +} | |
| 70 | + | |
| 71 | +fillba(ip: ref Ipatch) | |
| 72 | +{ | |
| 73 | + i: int; | |
| 74 | + pclast, pcnext, delta, skip: int; | |
| 75 | + | |
| 76 | + sizeba(2*ip.n); | |
| 77 | + pclast = 0; | |
| 78 | + for(i = 0; i < ip.n; i++) { | |
| 79 | + pcnext = ip.pinfo[i] >> 8; | |
| 80 | + delta = pcnext-pclast; | |
| 81 | + sizeba(nba + delta/1024 + 2); | |
| 82 | + while(delta > 7) { | |
| 83 | + if(delta > 1024) | |
| 84 | + skip = 1024; | |
| 85 | + else | |
| 86 | + skip = delta & int 16rfffffff8; | |
| 87 | + ba[nba++] = byte(256 - (skip >> 3)); | |
| 88 | + delta -= skip; | |
| 89 | + } | |
| 90 | + ba[nba++] = byte((delta << 4) | (ip.pinfo[i] & 16rf)); | |
| 91 | + pclast = pcnext; | |
| 92 | + } | |
| 93 | +} | |
| 94 | + | |
| 95 | +# | |
| 96 | +# Write Ipatch information to .s file. | |
| 97 | +# | |
| 98 | + | |
| 99 | +asmIpatch(off: int, ip: ref Ipatch) | |
| 100 | +{ | |
| 101 | + i: int; | |
| 102 | + reloff: int; # relative offset for array elements | |
| 103 | + pc: int; | |
| 104 | + | |
| 105 | + if(ip == nil || ip.n == 0) | |
| 106 | + return; | |
| 107 | + | |
| 108 | + fillba(ip); | |
| 109 | + | |
| 110 | + reloff = 0; | |
| 111 | + asmarray(off, Ipatchtid, nba, reloff); | |
| 112 | + pc = 0; | |
| 113 | + for(i = 0; i < nba; i++) { | |
| 114 | + bout.puts("\tbyte\t@mp+" + string reloff + "," + string ba[i]); | |
| 115 | + if(int(ba[i] & HIGHBIT)) | |
| 116 | + pc += (256 - int ba[i]) << 3; | |
| 117 | + else | |
| 118 | + pc += int ba[i] >> 4; | |
| 119 | + bout.puts("\t# " + string pc); | |
| 120 | + if(!int(ba[i] & HIGHBIT)) { | |
| 121 | + bout.puts(", " + operand[(int ba[i] >> 2) & 16r3] | |
| 122 | + + ", " + mode[int ba[i] & 16r3]); | |
| 123 | + } | |
| 124 | + bout.putc('\n'); | |
| 125 | + reloff += 1; | |
| 126 | + } | |
| 127 | + bout.puts("\tapop\n"); | |
| 128 | + | |
| 129 | + ba = nil; | |
| 130 | + nba = 0; | |
| 131 | +} | |
| 132 | + | |
| 133 | +# | |
| 134 | +# Write Ipatch information to .dis file. | |
| 135 | +# | |
| 136 | + | |
| 137 | +disIpatch(off: int, ip: ref Ipatch) | |
| 138 | +{ | |
| 139 | + i: int; | |
| 140 | + reloff: int; # relative offset for array elements | |
| 141 | + | |
| 142 | + if(ip == nil || ip.n == 0) | |
| 143 | + return; | |
| 144 | + | |
| 145 | + fillba(ip); | |
| 146 | + | |
| 147 | + disarray(off, Ipatchtid, nba); | |
| 148 | + reloff = 0; | |
| 149 | + for(i = 0; i < nba; i++) { | |
| 150 | + disbyte(reloff, ba[i]); | |
| 151 | + reloff += 1; | |
| 152 | + } | |
| 153 | + disapop(); | |
| 154 | + | |
| 155 | + ba = nil; | |
| 156 | + nba = 0; | |
| 157 | +} | |
| 158 | + | |
| 159 | +# | |
| 160 | +# Add instruction patch information to dreloc. | |
| 161 | +# | |
| 162 | + | |
| 163 | +addDreloc(i: ref Inst, operand: int, patchkind: int) | |
| 164 | +{ | |
| 165 | + if(dreloc == nil) | |
| 166 | + dreloc = ref Ipatch(0, 0, nil, nil); | |
| 167 | + addIpatch(dreloc, i, operand, patchkind, !SAVEINST); | |
| 168 | +} | |
| 169 | + | |
| 170 | +# | |
| 171 | +# Write Dreloc information to .s file. | |
| 172 | +# | |
| 173 | + | |
| 174 | +asmDreloc(off: int) | |
| 175 | +{ | |
| 176 | + asmIpatch(off, dreloc); | |
| 177 | +} | |
| 178 | + | |
| 179 | +# | |
| 180 | +# Write Dreloc information to .dis file. | |
| 181 | +# | |
| 182 | + | |
| 183 | +disDreloc(off: int) | |
| 184 | +{ | |
| 185 | + disIpatch(off, dreloc); | |
| 186 | +} | |
| @@ -0,0 +1,104 @@ | ||
| 1 | +# | |
| 2 | +# 'desc' assembly directives. | |
| 3 | +# | |
| 4 | + | |
| 5 | +Desc: adt { | |
| 6 | + id: int; # Dis type identifier | |
| 7 | + ln: int; # length, in bytes, of mapped object | |
| 8 | + map: array of byte; # bit map of pointers | |
| 9 | + nmap: int; # number of bytes in map | |
| 10 | + next: cyclic ref Desc; | |
| 11 | +}; | |
| 12 | + | |
| 13 | +dlist: ref Desc; | |
| 14 | +dtail: ref Desc; | |
| 15 | +id: int = 0; # reserve id == 0 for Module Data type descriptor | |
| 16 | + | |
| 17 | +# | |
| 18 | +# Allocate a Desc adt. | |
| 19 | +# | |
| 20 | + | |
| 21 | +newDesc(id: int, ln: int, nmap: int, map: array of byte): ref Desc | |
| 22 | +{ | |
| 23 | + return ref Desc(id, ln, map, nmap, nil); | |
| 24 | +} | |
| 25 | + | |
| 26 | +mapeq(a, b: array of byte, n: int): int | |
| 27 | +{ | |
| 28 | + while(n-- > 0) { | |
| 29 | + if(a[n] != b[n]) | |
| 30 | + return 0; | |
| 31 | + } | |
| 32 | + return 1; | |
| 33 | +} | |
| 34 | + | |
| 35 | +# | |
| 36 | +# Save a type descriptor; reuse existing descriptor if identical. | |
| 37 | +# | |
| 38 | + | |
| 39 | +descid(ln: int, nmap: int, map: array of byte): int | |
| 40 | +{ | |
| 41 | + d: ref Desc; | |
| 42 | + | |
| 43 | + for(d = dlist; d != nil; d = d.next) { | |
| 44 | + if(d.ln == ln && d.nmap == nmap && mapeq(d.map, map, nmap)) | |
| 45 | + return d.id; | |
| 46 | + } | |
| 47 | + | |
| 48 | + id += 1; | |
| 49 | + d = newDesc(id, ln, nmap, map); | |
| 50 | + if(dlist == nil) | |
| 51 | + dlist = d; | |
| 52 | + else | |
| 53 | + dtail.next = d; | |
| 54 | + dtail = d; | |
| 55 | + | |
| 56 | + return d.id; | |
| 57 | +} | |
| 58 | + | |
| 59 | +# | |
| 60 | +# Save type descriptor for module data. | |
| 61 | +# | |
| 62 | + | |
| 63 | +mpdescid(ln: int, nmap: int, map: array of byte) | |
| 64 | +{ | |
| 65 | + d: ref Desc; | |
| 66 | + | |
| 67 | + d = newDesc(0, ln, nmap, map); | |
| 68 | + d.next = dlist; | |
| 69 | + dlist = d; | |
| 70 | +} | |
| 71 | + | |
| 72 | +# | |
| 73 | +# Emit assembly 'desc' directives. | |
| 74 | +# | |
| 75 | + | |
| 76 | +asmdesc() | |
| 77 | +{ | |
| 78 | + d: ref Desc; | |
| 79 | + i: int; | |
| 80 | + | |
| 81 | + for(d = dlist; d != nil; d = d.next) { | |
| 82 | + bout.puts("\tdesc\t$" + string d.id + "," + string d.ln + ",\""); | |
| 83 | + for(i = 0; i < d.nmap; i++) | |
| 84 | + bout.puts(hex(int d.map[i], 2)); | |
| 85 | + bout.puts("\"\n"); | |
| 86 | + } | |
| 87 | +} | |
| 88 | + | |
| 89 | +disndesc() | |
| 90 | +{ | |
| 91 | + discon(id+1); | |
| 92 | +} | |
| 93 | + | |
| 94 | +disdesc() | |
| 95 | +{ | |
| 96 | + d: ref Desc; | |
| 97 | + | |
| 98 | + for(d = dlist; d != nil; d = d.next) { | |
| 99 | + discon(d.id); | |
| 100 | + discon(d.ln); | |
| 101 | + discon(d.nmap); | |
| 102 | + bout.write(d.map, d.nmap); | |
| 103 | + } | |
| 104 | +} | |
| @@ -0,0 +1,284 @@ | ||
| 1 | +ihead: ref Inst; # first instruction generated for .class file | |
| 2 | +itail: ref Inst; # last instruction (for appending to list) | |
| 3 | + | |
| 4 | +cache: array of byte; # module data cache | |
| 5 | +ncached: int; # number of bytes in cache | |
| 6 | +ndatum: int; # number of non-string basic datums in cache | |
| 7 | +startoff: int; # offset of first datum in cache | |
| 8 | +lastoff: int; # 1 past last byte offset in cache | |
| 9 | +lastkind: int = -1; # last kind of datum put in cache | |
| 10 | +lencache: int; # capacity of cache | |
| 11 | + | |
| 12 | +# | |
| 13 | +# Generate Dis object file (.dis). | |
| 14 | +# | |
| 15 | + | |
| 16 | +discon(val: int) | |
| 17 | +{ | |
| 18 | + if(val >= -64 && val <= 63) { | |
| 19 | + bout.putb(byte(val & ~16r80)); | |
| 20 | + return; | |
| 21 | + } | |
| 22 | + if(val >= -8192 && val <= 8191) { | |
| 23 | + bout.putb(byte(((val>>8) & ~16rC0) | 16r80)); | |
| 24 | + bout.putb(byte val); | |
| 25 | + return; | |
| 26 | + } | |
| 27 | + if(notimmable(val)) | |
| 28 | + fatal("discon: overflow 16r" + hex(val, 0)); | |
| 29 | + bout.putb(byte((val>>24) | 16rC0)); | |
| 30 | + bout.putb(byte(val>>16)); | |
| 31 | + bout.putb(byte(val>>8)); | |
| 32 | + bout.putb(byte val); | |
| 33 | +} | |
| 34 | + | |
| 35 | +disword(w: int) | |
| 36 | +{ | |
| 37 | + bout.putb(byte(w >> 24)); | |
| 38 | + bout.putb(byte(w >> 16)); | |
| 39 | + bout.putb(byte(w >> 8)); | |
| 40 | + bout.putb(byte w); | |
| 41 | +} | |
| 42 | + | |
| 43 | +disdata(kind: int, n: int) | |
| 44 | +{ | |
| 45 | + if(n < DMAX && n != 0) | |
| 46 | + bout.putb(byte((kind << DBYTE) | n)); | |
| 47 | + else{ | |
| 48 | + bout.putb(byte(kind << DBYTE)); | |
| 49 | + discon(n); | |
| 50 | + } | |
| 51 | +} | |
| 52 | + | |
| 53 | +disflush(kind: int, off: int, size: int) | |
| 54 | +{ | |
| 55 | + if(kind != lastkind || off != lastoff){ | |
| 56 | + if(lastkind != -1 && ncached){ | |
| 57 | + disdata(lastkind, ndatum); | |
| 58 | + discon(startoff); | |
| 59 | + bout.write(cache, ncached); | |
| 60 | + } | |
| 61 | + startoff = off; | |
| 62 | + lastkind = kind; | |
| 63 | + ncached = 0; | |
| 64 | + ndatum = 0; | |
| 65 | + } | |
| 66 | + lastoff = off + size; | |
| 67 | + while(kind >= 0 && ncached + size >= len cache){ | |
| 68 | + c := array[ncached + 1024] of byte; | |
| 69 | + c[0:] = cache; | |
| 70 | + cache = c; | |
| 71 | + } | |
| 72 | +} | |
| 73 | + | |
| 74 | +disbyte(off: int, v: byte) | |
| 75 | +{ | |
| 76 | + disflush(DEFB, off, 1); | |
| 77 | + cache[ncached++] = v; | |
| 78 | + ndatum++; | |
| 79 | +} | |
| 80 | + | |
| 81 | +disint(off: int, v: int) | |
| 82 | +{ | |
| 83 | + disflush(DEFW, off, IBY2WD); | |
| 84 | + cache[ncached++] = byte(v >> 24); | |
| 85 | + cache[ncached++] = byte(v >> 16); | |
| 86 | + cache[ncached++] = byte(v >> 8); | |
| 87 | + cache[ncached++] = byte v; | |
| 88 | + ndatum++; | |
| 89 | +} | |
| 90 | + | |
| 91 | +dislong(off: int, v: big) | |
| 92 | +{ | |
| 93 | + iv: int; | |
| 94 | + | |
| 95 | + disflush(DEFL, off, IBY2LG); | |
| 96 | + iv = int(v >> 32); | |
| 97 | + cache[ncached++] = byte(iv >> 24); | |
| 98 | + cache[ncached++] = byte(iv >> 16); | |
| 99 | + cache[ncached++] = byte(iv >> 8); | |
| 100 | + cache[ncached++] = byte iv; | |
| 101 | + iv = int v; | |
| 102 | + cache[ncached++] = byte(iv >> 24); | |
| 103 | + cache[ncached++] = byte(iv >> 16); | |
| 104 | + cache[ncached++] = byte(iv >> 8); | |
| 105 | + cache[ncached++] = byte iv; | |
| 106 | + ndatum++; | |
| 107 | +} | |
| 108 | + | |
| 109 | +disreal(off: int, v: real) | |
| 110 | +{ | |
| 111 | + disflush(DEFF, off, IBY2LG); | |
| 112 | + bv := math->realbits64(v); | |
| 113 | + iv := int(bv >> 32); | |
| 114 | + cache[ncached++] = byte(iv >> 24); | |
| 115 | + cache[ncached++] = byte(iv >> 16); | |
| 116 | + cache[ncached++] = byte(iv >> 8); | |
| 117 | + cache[ncached++] = byte(iv); | |
| 118 | + iv = int bv; | |
| 119 | + cache[ncached++] = byte(iv >> 24); | |
| 120 | + cache[ncached++] = byte(iv >> 16); | |
| 121 | + cache[ncached++] = byte(iv >> 8); | |
| 122 | + cache[ncached++] = byte(iv); | |
| 123 | + ndatum++; | |
| 124 | +} | |
| 125 | + | |
| 126 | +disstring(offset: int, s: string) | |
| 127 | +{ | |
| 128 | + disflush(-1, -1, 0); | |
| 129 | + d := array of byte s; | |
| 130 | + disdata(DEFS, len d); | |
| 131 | + discon(offset); | |
| 132 | + bout.write(d, len d); | |
| 133 | +} | |
| 134 | + | |
| 135 | +# | |
| 136 | +# Begin an array initializer. | |
| 137 | +# | |
| 138 | + | |
| 139 | +disarray(off: int, tid: int, nelt: int) | |
| 140 | +{ | |
| 141 | + disflush(-1, -1, 0); | |
| 142 | + disdata(DEFA, 1); # 1 is ignored | |
| 143 | + discon(off); | |
| 144 | + disword(tid); | |
| 145 | + disword(nelt); | |
| 146 | + disdata(DIND, 1); # 1 is ignored | |
| 147 | + discon(off); | |
| 148 | + disword(0); | |
| 149 | +} | |
| 150 | + | |
| 151 | +# | |
| 152 | +# Terminate an array initializer. | |
| 153 | +# | |
| 154 | + | |
| 155 | +disapop() | |
| 156 | +{ | |
| 157 | + disflush(-1, -1, 0); | |
| 158 | + disdata(DAPOP, 1); # 1 is ignored | |
| 159 | + discon(0); | |
| 160 | +} | |
| 161 | + | |
| 162 | +# | |
| 163 | +# Put number of instructions into .dis Header. | |
| 164 | +# | |
| 165 | + | |
| 166 | +disninst() | |
| 167 | +{ | |
| 168 | + i: int; | |
| 169 | + | |
| 170 | + if(itail != nil) | |
| 171 | + i = itail.pc + 1; | |
| 172 | + else | |
| 173 | + i = 0; | |
| 174 | + discon(i); | |
| 175 | +} | |
| 176 | + | |
| 177 | +dismode := array [int Aend] of { | |
| 178 | + byte AXXX, # Anone | |
| 179 | + byte AIMM, # Aimm | |
| 180 | + byte AMP, # Amp | |
| 181 | + byte (AMP|AIND), # Ampind | |
| 182 | + byte AFP, # Afp | |
| 183 | + byte (AFP|AIND) # Afpind | |
| 184 | +}; | |
| 185 | + | |
| 186 | +disregmode := array [int Aend] of { | |
| 187 | + byte AXNON, # Anone | |
| 188 | + byte AXIMM, # Aimm | |
| 189 | + byte AXINM, # Amp | |
| 190 | + byte AXNON, # Ampind | |
| 191 | + byte AXINF, # Afp | |
| 192 | + byte AXNON # Afpind | |
| 193 | +}; | |
| 194 | + | |
| 195 | +MAXCON: con 4; | |
| 196 | +MAXADDR: con 2*MAXCON; | |
| 197 | +MAXINST: con 3*MAXCON+2; | |
| 198 | +NIBUF: con 1024; | |
| 199 | + | |
| 200 | +ibuf: array of byte; | |
| 201 | +nibuf: int; | |
| 202 | + | |
| 203 | +disbcon(val: int) | |
| 204 | +{ | |
| 205 | + if(val >= -64 && val <= 63){ | |
| 206 | + ibuf[nibuf++] = byte(val & ~16r80); | |
| 207 | + return; | |
| 208 | + } | |
| 209 | + if(val >= -8192 && val <= 8191){ | |
| 210 | + ibuf[nibuf++] = byte(val>>8 & ~16rC0 | 16r80); | |
| 211 | + ibuf[nibuf++] = byte val; | |
| 212 | + return; | |
| 213 | + } | |
| 214 | + if(notimmable(val)) | |
| 215 | + fatal("disbcon: overflow 16r" + hex(val, 0)); | |
| 216 | + ibuf[nibuf++] = byte(val>>24 | 16rC0); | |
| 217 | + ibuf[nibuf++] = byte(val>>16); | |
| 218 | + ibuf[nibuf++] = byte(val>>8); | |
| 219 | + ibuf[nibuf++] = byte val; | |
| 220 | +} | |
| 221 | + | |
| 222 | +disaddr(a: ref Addr) | |
| 223 | +{ | |
| 224 | + val: int; | |
| 225 | + | |
| 226 | + val = 0; | |
| 227 | + case int a.mode { | |
| 228 | + int Aimm => | |
| 229 | + val = a.ival; | |
| 230 | + int Afp or | |
| 231 | + int Amp => | |
| 232 | + val = a.offset; | |
| 233 | + int Afpind or | |
| 234 | + int Ampind => | |
| 235 | + disbcon(a.ival); | |
| 236 | + val = a.offset; | |
| 237 | + } | |
| 238 | + disbcon(val); | |
| 239 | +} | |
| 240 | + | |
| 241 | +disinst() | |
| 242 | +{ | |
| 243 | + i: ref Inst; | |
| 244 | + | |
| 245 | + ibuf = array [NIBUF] of byte; | |
| 246 | + nibuf = 0; | |
| 247 | + for(i = ihead; i != nil; i = i.next){ | |
| 248 | + if(nibuf >= NIBUF-MAXINST){ | |
| 249 | + bout.write(ibuf, nibuf); | |
| 250 | + nibuf = 0; | |
| 251 | + } | |
| 252 | + ibuf[nibuf++] = i.op; | |
| 253 | + o := dismode[int i.s.mode] << SRC; | |
| 254 | + o |= dismode[int i.d.mode] << DST; | |
| 255 | + o |= disregmode[int i.m.mode]; | |
| 256 | + ibuf[nibuf++] = o; | |
| 257 | + if(i.m.mode != Anone) | |
| 258 | + disaddr(i.m); | |
| 259 | + if(i.s.mode != Anone) | |
| 260 | + disaddr(i.s); | |
| 261 | + if(i.d.mode != Anone) | |
| 262 | + disaddr(i.d); | |
| 263 | + } | |
| 264 | + if(nibuf > 0) | |
| 265 | + bout.write(ibuf, nibuf); | |
| 266 | + ibuf = nil; | |
| 267 | +} | |
| 268 | + | |
| 269 | +disout() | |
| 270 | +{ | |
| 271 | + discon(XMAGIC); | |
| 272 | + discon(DONTCOMPILE); # runtime "hints" | |
| 273 | + disstackext(); # minimum stack extent size | |
| 274 | + disninst(); | |
| 275 | + disnvar(); | |
| 276 | + disndesc(); | |
| 277 | + disnlinks(); | |
| 278 | + disentry(); | |
| 279 | + disinst(); | |
| 280 | + disdesc(); | |
| 281 | + disvar(); | |
| 282 | + dismod(); | |
| 283 | + dislinks(); | |
| 284 | +} | |
| @@ -0,0 +1,35 @@ | ||
| 1 | +# | |
| 2 | +# 'entry' assembly directive. | |
| 3 | +# | |
| 4 | + | |
| 5 | +pc: int = -1; | |
| 6 | +tid: int = -1; | |
| 7 | + | |
| 8 | +# | |
| 9 | +# Set the entry point; entry is the beginning of "main". | |
| 10 | +# | |
| 11 | + | |
| 12 | +setentry(l: int, i: int) | |
| 13 | +{ | |
| 14 | + if(pc != -1) | |
| 15 | + verifyerrormess("main overloaded"); | |
| 16 | + pc = l; | |
| 17 | + tid = i; | |
| 18 | +} | |
| 19 | + | |
| 20 | +# | |
| 21 | +# Emit 'entry' assembly directive. | |
| 22 | +# | |
| 23 | + | |
| 24 | +asmentry() | |
| 25 | +{ | |
| 26 | + if(pc == -1) | |
| 27 | + return; | |
| 28 | + bout.puts("\tentry\t" + string pc + ", " + string tid + "\n"); | |
| 29 | +} | |
| 30 | + | |
| 31 | +disentry() | |
| 32 | +{ | |
| 33 | + discon(pc); | |
| 34 | + discon(tid); | |
| 35 | +} | |
| @@ -0,0 +1,112 @@ | ||
| 1 | +# | |
| 2 | +# Maintain information about 'finally' blocks. | |
| 3 | +# | |
| 4 | + | |
| 5 | +Finally: adt { | |
| 6 | + npc: int; # Java pc of finally entry (jsr target) | |
| 7 | + xpc: int; # Java pc of finally exit (ret) | |
| 8 | + n: int; # number of jsr slots in gototbl | |
| 9 | + gototbl: array of int; # goto jump table | |
| 10 | + off: int; # mp offset to gototbl | |
| 11 | + next: cyclic ref Finally; | |
| 12 | +}; | |
| 13 | + | |
| 14 | +finally: ref Finally; # linked list of finally block records | |
| 15 | + | |
| 16 | +# | |
| 17 | +# Get record for finally block whose entry point is pc. | |
| 18 | +# | |
| 19 | + | |
| 20 | +getfinally(pc: int): ref Finally | |
| 21 | +{ | |
| 22 | + f: ref Finally; | |
| 23 | + | |
| 24 | + for(f = finally; f != nil; f = f.next) { | |
| 25 | + if(f.npc == pc) | |
| 26 | + return f; | |
| 27 | + } | |
| 28 | + return nil; | |
| 29 | +} | |
| 30 | + | |
| 31 | +# | |
| 32 | +# Count jsr's to the finally block whose entry point is pc. | |
| 33 | +# | |
| 34 | + | |
| 35 | +finallyentry(pc: int) | |
| 36 | +{ | |
| 37 | + f: ref Finally; | |
| 38 | + | |
| 39 | + f = getfinally(pc); | |
| 40 | + if(f == nil) { | |
| 41 | + f = ref Finally(pc, 0, 0, nil, 0, finally); | |
| 42 | + finally = f; | |
| 43 | + } | |
| 44 | + f.n += 1; | |
| 45 | +} | |
| 46 | + | |
| 47 | +# | |
| 48 | +# Allocate the gototbl's and pass them to mdata.c. | |
| 49 | +# | |
| 50 | + | |
| 51 | +finallyalloc() | |
| 52 | +{ | |
| 53 | + f: ref Finally; | |
| 54 | + | |
| 55 | + for(f = finally; f != nil; f = f.next) { | |
| 56 | + f.gototbl = array [f.n] of { * => 0 }; | |
| 57 | + f.off = mpgoto(f.n, f.gototbl); | |
| 58 | + } | |
| 59 | +} | |
| 60 | + | |
| 61 | +# | |
| 62 | +# Fix up operands of a Dis movw that implements Java jsr/jsr_w. | |
| 63 | +# | |
| 64 | + | |
| 65 | +jsrfixup(s: ref Addr, d: ref Addr, dispc: int, javapc: int) | |
| 66 | +{ | |
| 67 | + f: ref Finally; | |
| 68 | + i: int; | |
| 69 | + | |
| 70 | + f = getfinally(javapc); | |
| 71 | + for(i = 0; i < f.n; i++) { | |
| 72 | + if(f.gototbl[i] == 0) { | |
| 73 | + f.gototbl[i] = dispc; | |
| 74 | + break; | |
| 75 | + } | |
| 76 | + } | |
| 77 | + if(i == f.n) | |
| 78 | + fatal("jsrfixup: " + string dispc + ", " + string javapc); | |
| 79 | + s.ival = i; | |
| 80 | + d.offset = f.off + f.n*IBY2WD; | |
| 81 | +} | |
| 82 | + | |
| 83 | +# | |
| 84 | +# Fix up operands of a Dis goto that implements Java ret. | |
| 85 | +# | |
| 86 | + | |
| 87 | +retfixup(s: ref Addr, d: ref Addr, retpc: int) | |
| 88 | +{ | |
| 89 | + fi, f: ref Finally; | |
| 90 | + | |
| 91 | + f = nil; | |
| 92 | + for(fi = finally; fi != nil; fi = fi.next) { | |
| 93 | + if(fi.xpc == 0 && fi.npc < retpc | |
| 94 | + && (f == nil || f.npc < fi.npc)) { | |
| 95 | + f = fi; | |
| 96 | + } | |
| 97 | + } | |
| 98 | + if(f == nil) | |
| 99 | + fatal("retfixup: " + string retpc); | |
| 100 | + f.xpc = retpc; # claim this finally block for this 'ret' | |
| 101 | + s.offset = f.off + f.n*IBY2WD; | |
| 102 | + d.offset = f.off; | |
| 103 | +} | |
| 104 | + | |
| 105 | +# | |
| 106 | +# Free finally information after each method is translated. | |
| 107 | +# | |
| 108 | + | |
| 109 | +finallyfree() | |
| 110 | +{ | |
| 111 | + finally = nil; | |
| 112 | +} | |
| @@ -0,0 +1,475 @@ | ||
| 1 | +# | |
| 2 | +# Manage method frame. | |
| 3 | +# | |
| 4 | + | |
| 5 | +# | |
| 6 | +# Local variables (including function parameters). | |
| 7 | +# | |
| 8 | + | |
| 9 | +Local: adt { # local variable | |
| 10 | + dtype: byte; # type of local (DIS_[BWLP]) | |
| 11 | + offset: int; # fp offset of this local | |
| 12 | + next: cyclic ref Local; # for locals that are reused | |
| 13 | +}; | |
| 14 | + | |
| 15 | +frameoff: int; # tracks growth of frame | |
| 16 | +maxframe: int; # size of largest frame | |
| 17 | +locals: array of ref Local; # local variables | |
| 18 | +nlocals: int; # number of locals (in the Java sense) | |
| 19 | + | |
| 20 | +# | |
| 21 | +# fp temporaries. | |
| 22 | +# | |
| 23 | + | |
| 24 | +Fp: adt { | |
| 25 | + dtype: byte; | |
| 26 | + refcnt: int; | |
| 27 | +}; | |
| 28 | + | |
| 29 | +tmpslwm: int; # lowest temporary fp offset | |
| 30 | +tmpssz: int; # size of tmps array | |
| 31 | +tmps: array of Fp; # temporary arena | |
| 32 | + | |
| 33 | +# | |
| 34 | +# Resize the locals array. | |
| 35 | +# | |
| 36 | +# Since the Java VM reuses local variables (e.g., perhaps using | |
| 37 | +# the same slot for an int and an Object reference), max_locals | |
| 38 | +# doesn't always give the number of Dis locals to allow for. | |
| 39 | +# | |
| 40 | + | |
| 41 | +resizelocals(ix: int) | |
| 42 | +{ | |
| 43 | + oldsz: int; | |
| 44 | + | |
| 45 | + oldsz = nlocals; | |
| 46 | + while(ix >= nlocals) | |
| 47 | + nlocals += ALLOCINCR; | |
| 48 | + newlocals := array [nlocals] of ref Local; | |
| 49 | + for(i := 0; i < oldsz; i++) | |
| 50 | + newlocals[i] = locals[i]; | |
| 51 | + for(i = oldsz; i < nlocals; i++) | |
| 52 | + newlocals[i] = ref Local(byte 0, 0, nil); | |
| 53 | + locals = newlocals; | |
| 54 | +} | |
| 55 | + | |
| 56 | +# | |
| 57 | +# Reserve a frame cell for a local variable of the given type. | |
| 58 | +# The Java VM reuses local variables. | |
| 59 | +# | |
| 60 | + | |
| 61 | +reservelocal(dtype: byte, ix: int) | |
| 62 | +{ | |
| 63 | + l: ref Local; | |
| 64 | + | |
| 65 | + if(ix >= nlocals) | |
| 66 | + resizelocals(ix); | |
| 67 | + if(locals[ix].dtype == dtype) | |
| 68 | + return; | |
| 69 | + if(locals[ix].dtype == DIS_X) # not yet reserved | |
| 70 | + l = locals[ix]; | |
| 71 | + else { # check reuse list | |
| 72 | + for(l = locals[ix].next; l != nil; l = l.next) { | |
| 73 | + if(dtype == l.dtype) | |
| 74 | + return; | |
| 75 | + } | |
| 76 | + l = ref Local(byte 0, 0, nil); | |
| 77 | + l.next = locals[ix].next; | |
| 78 | + locals[ix].next = l; | |
| 79 | + } | |
| 80 | + l.dtype = dtype; | |
| 81 | + frameoff = align(frameoff, cellsize[int dtype]); | |
| 82 | + l.offset = frameoff; | |
| 83 | + frameoff += cellsize[int dtype]; | |
| 84 | +} | |
| 85 | + | |
| 86 | +# | |
| 87 | +# Map the signature parameter types into 'locals' array. | |
| 88 | +# | |
| 89 | + | |
| 90 | +mapmethodsig(sig: string, isstatic: int) | |
| 91 | +{ | |
| 92 | + index: int; | |
| 93 | + | |
| 94 | + index = 0; | |
| 95 | + if(isstatic == 0) { | |
| 96 | + reservelocal(DIS_P, index); # this pointer | |
| 97 | + index += 1; | |
| 98 | + } | |
| 99 | + sig = sig[1:]; # skip '(' | |
| 100 | + while(sig[0] != ')') { | |
| 101 | + case sig[0] { | |
| 102 | + 'Z' or | |
| 103 | + 'B' or | |
| 104 | + 'C' or | |
| 105 | + 'S' or | |
| 106 | + 'I' => | |
| 107 | + reservelocal(DIS_W, index); | |
| 108 | + index += 1; | |
| 109 | + 'F' => | |
| 110 | + reservelocal(DIS_L, index); | |
| 111 | + index += 1; | |
| 112 | + 'J' or | |
| 113 | + 'D' => | |
| 114 | + reservelocal(DIS_L, index); | |
| 115 | + index += 2; | |
| 116 | + 'L' or | |
| 117 | + '[' => | |
| 118 | + reservelocal(DIS_P, index); | |
| 119 | + index += 1; | |
| 120 | + } | |
| 121 | + sig = nextjavatype(sig); | |
| 122 | + } | |
| 123 | +} | |
| 124 | + | |
| 125 | +# | |
| 126 | +# Map references to local variables in the Java bytecode into 'locals' array. | |
| 127 | +# | |
| 128 | + | |
| 129 | +maplocalrefs() | |
| 130 | +{ | |
| 131 | + j: ref Jinst; | |
| 132 | + jpi: ref Jinst.Pi; | |
| 133 | + jpw: ref Jinst.Pw; | |
| 134 | + jpx1c: ref Jinst.Px1c; | |
| 135 | + jix: int; | |
| 136 | + | |
| 137 | + jix = 0; | |
| 138 | + while(jix < code.code_length) { | |
| 139 | + j = code.j[jix]; | |
| 140 | + pick jp := j { | |
| 141 | + Pi => | |
| 142 | + jpi = jp; | |
| 143 | + Px1c => | |
| 144 | + jpx1c = jp; | |
| 145 | + Pw => | |
| 146 | + jpw = jp; | |
| 147 | + } | |
| 148 | + case int j.op { | |
| 149 | + Jiinc => | |
| 150 | + reservelocal(DIS_W, jpx1c.x1c.ix); | |
| 151 | + Jiload or | |
| 152 | + Jistore => | |
| 153 | + reservelocal(DIS_W, jpi.i); | |
| 154 | + Jiload_0 or | |
| 155 | + Jistore_0 => | |
| 156 | + reservelocal(DIS_W, 0); | |
| 157 | + Jiload_1 or | |
| 158 | + Jistore_1 => | |
| 159 | + reservelocal(DIS_W, 1); | |
| 160 | + Jiload_2 or | |
| 161 | + Jistore_2 => | |
| 162 | + reservelocal(DIS_W, 2); | |
| 163 | + Jiload_3 or | |
| 164 | + Jistore_3 => | |
| 165 | + reservelocal(DIS_W, 3); | |
| 166 | + Jlload or | |
| 167 | + Jlstore or | |
| 168 | + Jfload or | |
| 169 | + Jfstore or | |
| 170 | + Jdload or | |
| 171 | + Jdstore => | |
| 172 | + reservelocal(DIS_L, jpi.i); | |
| 173 | + Jlload_0 or | |
| 174 | + Jlstore_0 or | |
| 175 | + Jfload_0 or | |
| 176 | + Jfstore_0 or | |
| 177 | + Jdload_0 or | |
| 178 | + Jdstore_0 => | |
| 179 | + reservelocal(DIS_L, 0); | |
| 180 | + Jlload_1 or | |
| 181 | + Jlstore_1 or | |
| 182 | + Jfload_1 or | |
| 183 | + Jfstore_1 or | |
| 184 | + Jdload_1 or | |
| 185 | + Jdstore_1 => | |
| 186 | + reservelocal(DIS_L, 1); | |
| 187 | + Jlload_2 or | |
| 188 | + Jlstore_2 or | |
| 189 | + Jfload_2 or | |
| 190 | + Jfstore_2 or | |
| 191 | + Jdload_2 or | |
| 192 | + Jdstore_2 => | |
| 193 | + reservelocal(DIS_L, 2); | |
| 194 | + Jlload_3 or | |
| 195 | + Jlstore_3 or | |
| 196 | + Jfload_3 or | |
| 197 | + Jfstore_3 or | |
| 198 | + Jdload_3 or | |
| 199 | + Jdstore_3 => | |
| 200 | + reservelocal(DIS_L, 3); | |
| 201 | + Jret or | |
| 202 | + Jaload or | |
| 203 | + Jastore => | |
| 204 | + reservelocal(DIS_P, jpi.i); | |
| 205 | + Jaload_0 or | |
| 206 | + Jastore_0 => | |
| 207 | + reservelocal(DIS_P, 0); | |
| 208 | + Jaload_1 or | |
| 209 | + Jastore_1 => | |
| 210 | + reservelocal(DIS_P, 1); | |
| 211 | + Jaload_2 or | |
| 212 | + Jastore_2 => | |
| 213 | + reservelocal(DIS_P, 2); | |
| 214 | + Jaload_3 or | |
| 215 | + Jastore_3 => | |
| 216 | + reservelocal(DIS_P, 3); | |
| 217 | + Jwide => # repeat from above | |
| 218 | + case int jpw.w.op { | |
| 219 | + Jiinc or | |
| 220 | + Jiload or | |
| 221 | + Jistore => | |
| 222 | + reservelocal(DIS_W, jpw.w.ix); | |
| 223 | + Jlload or | |
| 224 | + Jlstore or | |
| 225 | + Jfload or | |
| 226 | + Jfstore or | |
| 227 | + Jdload or | |
| 228 | + Jdstore => | |
| 229 | + reservelocal(DIS_L, jpw.w.ix); | |
| 230 | + Jaload or | |
| 231 | + Jastore or | |
| 232 | + Jret => | |
| 233 | + reservelocal(DIS_P, jpw.w.ix); | |
| 234 | + } | |
| 235 | + } | |
| 236 | + jix += j.size; | |
| 237 | + } | |
| 238 | +} | |
| 239 | + | |
| 240 | +# | |
| 241 | +# Prepare a method's frame prior to translating its code. | |
| 242 | +# | |
| 243 | + | |
| 244 | +openframe(sig: string, isstatic: int) | |
| 245 | +{ | |
| 246 | + frameoff = REGSIZE; | |
| 247 | + # 'code' can == nil; e.g, when generating <clinit> for an interface | |
| 248 | + if(code != nil) | |
| 249 | + nlocals = code.max_locals; | |
| 250 | + else | |
| 251 | + nlocals = 2; | |
| 252 | + locals = array [nlocals] of { * => ref Local(byte 0, 0, nil) }; | |
| 253 | + mapmethodsig(sig, isstatic); | |
| 254 | + if(code != nil) | |
| 255 | + maplocalrefs(); | |
| 256 | + frameoff = align(frameoff, IBY2WD); | |
| 257 | + tmpslwm = frameoff; | |
| 258 | + tmpssz = frameoff; | |
| 259 | + tmps = array [tmpssz] of { * => (byte 0, 0) }; | |
| 260 | +} | |
| 261 | + | |
| 262 | +# | |
| 263 | +# Return fp index of a local variable. | |
| 264 | +# | |
| 265 | + | |
| 266 | +localix(dtype: byte, ix: int): int | |
| 267 | +{ | |
| 268 | + l: ref Local; | |
| 269 | + | |
| 270 | + if(dtype == locals[ix].dtype) | |
| 271 | + return locals[ix].offset; | |
| 272 | + for(l = locals[ix].next; l != nil; l = l.next) { | |
| 273 | + if(dtype == l.dtype) | |
| 274 | + return l.offset; | |
| 275 | + } | |
| 276 | + fatal("localix: " + string dtype + ", " + string ix); | |
| 277 | + return 0; | |
| 278 | +} | |
| 279 | + | |
| 280 | +# fp temporary management starts here | |
| 281 | + | |
| 282 | +incref(off: int) | |
| 283 | +{ | |
| 284 | + if(off >= tmpslwm) # if <, then local variable | |
| 285 | + tmps[off-tmpslwm].refcnt++; | |
| 286 | +} | |
| 287 | + | |
| 288 | +acqreg(a: ref Addr) | |
| 289 | +{ | |
| 290 | + case int a.mode { | |
| 291 | + int Anone or | |
| 292 | + int Aimm or | |
| 293 | + int Amp or | |
| 294 | + int Ampind => | |
| 295 | + ; | |
| 296 | + int Afp => | |
| 297 | + incref(a.offset); | |
| 298 | + int Afpind => | |
| 299 | + incref(a.ival); | |
| 300 | + } | |
| 301 | +} | |
| 302 | + | |
| 303 | +# | |
| 304 | +# Reserve the fp temporaries referenced by a StkSnap of some basic block. | |
| 305 | +# | |
| 306 | + | |
| 307 | +reservereg(s: array of ref StkSnap, sz: int) | |
| 308 | +{ | |
| 309 | + i: int; | |
| 310 | + | |
| 311 | + for(i = 0; i < sz; i++) | |
| 312 | + acqreg(code.j[s[i].pc[0]].dst); | |
| 313 | +} | |
| 314 | + | |
| 315 | +# | |
| 316 | +# Get fp offset of the next available register of the given type. | |
| 317 | +# | |
| 318 | + | |
| 319 | +getoff(dtype: byte): int | |
| 320 | +{ | |
| 321 | + off: int; | |
| 322 | + stride: int; | |
| 323 | + | |
| 324 | + if(dtype == DIS_L) { | |
| 325 | + stride = IBY2LG; | |
| 326 | + off = tmpslwm % IBY2LG; | |
| 327 | + } else { | |
| 328 | + stride = IBY2WD; | |
| 329 | + off = 0; | |
| 330 | + } | |
| 331 | + while(off < tmpssz) { | |
| 332 | + if(tmps[off].refcnt == 0 | |
| 333 | + && (tmps[off].dtype == dtype || tmps[off].dtype == DIS_X)) { | |
| 334 | + return off; | |
| 335 | + } | |
| 336 | + off += stride; | |
| 337 | + } | |
| 338 | + return off; | |
| 339 | +} | |
| 340 | + | |
| 341 | +# | |
| 342 | +# Get a register (fp offset thereof) of the appropriate type. | |
| 343 | +# | |
| 344 | + | |
| 345 | +getreg(dtype: byte): int | |
| 346 | +{ | |
| 347 | + off: int; | |
| 348 | + oldsz: int; | |
| 349 | + | |
| 350 | + off = getoff(dtype); | |
| 351 | + if(off >= tmpssz) { # increase size of temporary arena | |
| 352 | + oldsz = tmpssz; | |
| 353 | + tmpssz += ALLOCINCR*IBY2LG; | |
| 354 | + newtmps := array [tmpssz] of Fp; | |
| 355 | + for(i := 0; i < oldsz; i++) | |
| 356 | + newtmps[i] = tmps[i]; | |
| 357 | + for(i = oldsz; i < tmpssz; i++) | |
| 358 | + newtmps[i] = Fp(byte 0, 0); | |
| 359 | + tmps = newtmps; | |
| 360 | + } | |
| 361 | + tmps[off].dtype = dtype; | |
| 362 | + if(dtype == DIS_L) # also reserve next word | |
| 363 | + tmps[off+IBY2WD].dtype = dtype; | |
| 364 | + tmps[off].refcnt = 1; | |
| 365 | + if(tmpslwm+off+cellsize[int dtype] > frameoff) | |
| 366 | + frameoff = tmpslwm+off+cellsize[int dtype]; | |
| 367 | + return tmpslwm+off; | |
| 368 | +} | |
| 369 | + | |
| 370 | +decref(off: int) | |
| 371 | +{ | |
| 372 | + if(off >= tmpslwm) { # if <, then local variable | |
| 373 | + if(--tmps[off-tmpslwm].refcnt < 0) | |
| 374 | + fatal("decref: refcnt < 0"); | |
| 375 | + } | |
| 376 | +} | |
| 377 | + | |
| 378 | +# | |
| 379 | +# "Free" register used by a. | |
| 380 | +# | |
| 381 | + | |
| 382 | +relreg(a: ref Addr) | |
| 383 | +{ | |
| 384 | + # don't mess with exception object | |
| 385 | + if(code != nil && a == code.j[code.code_length].dst) | |
| 386 | + return; | |
| 387 | + case int a.mode { | |
| 388 | + int Anone or | |
| 389 | + int Aimm or | |
| 390 | + int Amp or | |
| 391 | + int Ampind => | |
| 392 | + ; | |
| 393 | + int Afp => | |
| 394 | + decref(a.offset); | |
| 395 | + int Afpind => | |
| 396 | + decref(a.ival); | |
| 397 | + } | |
| 398 | +} | |
| 399 | + | |
| 400 | +# | |
| 401 | +# Mark all temporary fp registers as available. Leave typing as is. | |
| 402 | +# | |
| 403 | + | |
| 404 | +clearreg() | |
| 405 | +{ | |
| 406 | + i: int; | |
| 407 | + | |
| 408 | + i = 0; | |
| 409 | + while(i < frameoff-tmpslwm) { | |
| 410 | + tmps[i].refcnt = 0; | |
| 411 | + i += IBY2WD; | |
| 412 | + } | |
| 413 | +} | |
| 414 | + | |
| 415 | +# | |
| 416 | +# Calculate the type descriptor for a frame. | |
| 417 | +# | |
| 418 | + | |
| 419 | +framedesc(): int | |
| 420 | +{ | |
| 421 | + ln, id, i: int; | |
| 422 | + map: array of byte; | |
| 423 | + l: ref Local; | |
| 424 | + | |
| 425 | + ln = frameoff / (8*IBY2WD) + (frameoff % (8*IBY2WD) != 0); | |
| 426 | + map = array [ln] of { * => byte 0 }; | |
| 427 | + #setbit(map, REFSYSEX); # slot for 'ref Sys->Exception' | |
| 428 | + setbit(map, EXOBJ); # slot for exception object | |
| 429 | + for(i = 0; i < nlocals; i++) { | |
| 430 | + if(locals[i].dtype == DIS_P) | |
| 431 | + setbit(map, locals[i].offset); | |
| 432 | + for(l = locals[i].next; l != nil; l = l.next) { | |
| 433 | + if(l.dtype == DIS_P) | |
| 434 | + setbit(map, l.offset); | |
| 435 | + } | |
| 436 | + } | |
| 437 | + i = 0; | |
| 438 | + while(i < frameoff-tmpslwm) { | |
| 439 | + if(tmps[i].dtype == DIS_P) | |
| 440 | + setbit(map, tmpslwm+i); | |
| 441 | + i += IBY2WD; | |
| 442 | + } | |
| 443 | + id = descid(frameoff, ln, map); | |
| 444 | + return id; | |
| 445 | +} | |
| 446 | + | |
| 447 | +# | |
| 448 | +# Dispense with a frame. | |
| 449 | +# | |
| 450 | + | |
| 451 | +closeframe(): int | |
| 452 | +{ | |
| 453 | + tid: int; | |
| 454 | + | |
| 455 | + # frame size is always a multiple of 8 | |
| 456 | + frameoff = align(frameoff, IBY2LG); | |
| 457 | + if(frameoff > maxframe) | |
| 458 | + maxframe = frameoff; | |
| 459 | + tid = framedesc(); | |
| 460 | + locals = nil; | |
| 461 | + frameoff = 0; | |
| 462 | + tmpslwm = 0; | |
| 463 | + tmpssz = 0; | |
| 464 | + tmps = nil; | |
| 465 | + return tid; | |
| 466 | +} | |
| 467 | + | |
| 468 | +# | |
| 469 | +# Minimum stack extent size. | |
| 470 | +# | |
| 471 | + | |
| 472 | +disstackext() | |
| 473 | +{ | |
| 474 | + discon(10*maxframe); | |
| 475 | +} | |
| @@ -0,0 +1,42 @@ | ||
| 1 | +implement J2d; | |
| 2 | + | |
| 3 | +include "sys.m"; | |
| 4 | +include "bufio.m"; | |
| 5 | +include "draw.m"; | |
| 6 | +include "keyring.m"; | |
| 7 | +include "math.m"; | |
| 8 | +include "string.m"; | |
| 9 | +include "isa.m"; | |
| 10 | + | |
| 11 | +include "java.m"; | |
| 12 | +include "javaisa.m"; | |
| 13 | +include "reloc.m"; | |
| 14 | + | |
| 15 | +J2d: module { | |
| 16 | + init: fn(nil: ref Draw->Context, argv: list of string); | |
| 17 | +}; | |
| 18 | + | |
| 19 | +include "arg.m"; | |
| 20 | +include "main.b"; | |
| 21 | +include "loader.b"; | |
| 22 | +include "javadas.b"; | |
| 23 | +include "bb.b"; | |
| 24 | +include "datarloc.b"; | |
| 25 | +include "ltreloc.b"; | |
| 26 | +include "rtreloc.b"; | |
| 27 | +include "mdata.b"; | |
| 28 | +include "simjvm.b"; | |
| 29 | +include "module.b"; | |
| 30 | +include "entry.b"; | |
| 31 | +include "desc.b"; | |
| 32 | +include "links.b"; | |
| 33 | +include "patch.b"; | |
| 34 | +include "frame.b"; | |
| 35 | +include "unify.b"; | |
| 36 | +include "javatbl.b"; | |
| 37 | +include "finally.b"; | |
| 38 | +include "xlate.b"; | |
| 39 | +include "asm.b"; | |
| 40 | +include "dis.b"; | |
| 41 | +include "sbl.b"; | |
| 42 | +include "util.b"; | |
| @@ -0,0 +1,343 @@ | ||
| 1 | +# Java constant pool tags | |
| 2 | + | |
| 3 | +CON_Utf8: con 1; | |
| 4 | +# CON_Unicode: con 2; # obsolete | |
| 5 | +CON_Integer: con 3; | |
| 6 | +CON_Float: con 4; | |
| 7 | +CON_Long: con 5; | |
| 8 | +CON_Double: con 6; | |
| 9 | +CON_Class: con 7; | |
| 10 | +CON_String: con 8; | |
| 11 | +CON_Fieldref: con 9; | |
| 12 | +CON_Methodref: con 10; | |
| 13 | +CON_InterfaceMref: con 11; | |
| 14 | +CON_NameAndType: con 12; | |
| 15 | +# since 49.0 | |
| 16 | +CON_MethodHandle: con 15; | |
| 17 | +CON_MethodType: con 16; | |
| 18 | +CON_InvokeDynamic: con 18; | |
| 19 | + | |
| 20 | +# Java access flags | |
| 21 | + | |
| 22 | +ACC_PUBLIC: con 16r0001; | |
| 23 | +ACC_PRIVATE: con 16r0002; | |
| 24 | +ACC_PROTECTED: con 16r0004; | |
| 25 | +ACC_STATIC: con 16r0008; | |
| 26 | +ACC_FINAL: con 16r0010; | |
| 27 | +ACC_SUPER: con 16r0020; | |
| 28 | +ACC_SYNCHRONIZED: con 16r0020; # sic | |
| 29 | +ACC_VOLATILE: con 16r0040; | |
| 30 | +ACC_TRANSIENT: con 16r0080; | |
| 31 | +ACC_NATIVE: con 16r0100; | |
| 32 | +ACC_INTERFACE: con 16r0200; | |
| 33 | +ACC_ABSTRACT: con 16r0400; | |
| 34 | + | |
| 35 | +_MUSTCOMPILE: con MUSTCOMPILE<<16; | |
| 36 | +_DONTCOMPILE: con DONTCOMPILE<<16; | |
| 37 | + | |
| 38 | +# basic block flags | |
| 39 | + | |
| 40 | +BB_LDR, # set for all leaders | |
| 41 | +BB_ENTRY, # method entry point | |
| 42 | +BB_FINALLY, # finally block entry point | |
| 43 | +BB_HANDLER, # EH entry point | |
| 44 | +BB_REACHABLE: con byte(1 << iota); # reachable basic block */ | |
| 45 | + | |
| 46 | +# basic block states | |
| 47 | + | |
| 48 | +BB_PRESIM, # not simulated yet | |
| 49 | +BB_ACTIVE, # simulating or being unified | |
| 50 | +BB_POSTSIM, # simulated | |
| 51 | +BB_POSTUNIFY: con byte(1 << iota); # unified | |
| 52 | + | |
| 53 | +# Dis operand classification | |
| 54 | + | |
| 55 | +Anone, | |
| 56 | +Aimm, | |
| 57 | +Amp, | |
| 58 | +Ampind, | |
| 59 | +Afp, | |
| 60 | +Afpind, | |
| 61 | +Aend: con byte iota; | |
| 62 | + | |
| 63 | +# Dis n(fp) types | |
| 64 | + | |
| 65 | +DIS_X, # not yet typed | |
| 66 | +DIS_W, # 'B', 'Z', 'C', 'S', 'I' | |
| 67 | +DIS_L, # 'F', 'J', 'D' | |
| 68 | +DIS_P: con byte iota; # 'L', '[' | |
| 69 | + | |
| 70 | +# inferno/vm/Array | |
| 71 | + | |
| 72 | +ARY_DATA: con IBY2WD; # Array data (Dis array) | |
| 73 | +ARY_NDIM: con 2*IBY2WD; # number of dimensions | |
| 74 | +ARY_ADT: con 3*IBY2WD; # 'ref Class' of element type | |
| 75 | +ARY_ETYPE: con 4*IBY2WD; # primitive element type code | |
| 76 | + | |
| 77 | +# java/lang/String | |
| 78 | + | |
| 79 | +STR_DISSTR: con IBY2WD; # offset to Dis string in a String | |
| 80 | + | |
| 81 | +# miscellaneous | |
| 82 | + | |
| 83 | +#REFSYSEX: con 24; # 24(fp) is a 'ref Sys->Exception' | |
| 84 | +EXOBJ: con 28; # 28(fp) is exception object | |
| 85 | +THISOFF: con 32; # 32(fp) is "this" pointer | |
| 86 | +REGSIZE: con 32; # 32(fp) is first usable frame cell | |
| 87 | +Hashsize: con 31; | |
| 88 | +ALLOCINCR: con 16; | |
| 89 | + | |
| 90 | +Const_ci: adt { | |
| 91 | + name_index: int; | |
| 92 | +}; | |
| 93 | + | |
| 94 | +Const_fmiref: adt { | |
| 95 | + class_index: int; | |
| 96 | + name_type_index: int; | |
| 97 | +}; | |
| 98 | + | |
| 99 | +Const_nat: adt { | |
| 100 | + name_index: int; | |
| 101 | + sig_index: int; | |
| 102 | +}; | |
| 103 | + | |
| 104 | +Const_utf8: adt { | |
| 105 | + ln: int; | |
| 106 | + utf8: string; | |
| 107 | +}; | |
| 108 | + | |
| 109 | +# since 49.0 | |
| 110 | + | |
| 111 | +Const_methodhandle: adt { | |
| 112 | + ref_kind: int; | |
| 113 | + ref_index: int; | |
| 114 | +}; | |
| 115 | + | |
| 116 | +Const_methodtype: adt { | |
| 117 | + descriptor_index: int; | |
| 118 | +}; | |
| 119 | + | |
| 120 | +Const_invokedyn: adt { | |
| 121 | + bs_method_attr_index: int; | |
| 122 | + name_type_index: int; | |
| 123 | +}; | |
| 124 | + | |
| 125 | +Const: adt { | |
| 126 | + pick { | |
| 127 | + # CONSTANT_[Float|Double]_info | |
| 128 | + Ptdouble => | |
| 129 | + tdouble: real; | |
| 130 | + # CONSTANT_Long_info | |
| 131 | + Ptvlong => | |
| 132 | + tvlong: big; | |
| 133 | + # CONSTANT_Integer_info | |
| 134 | + Ptint => | |
| 135 | + tint: int; | |
| 136 | + # CONSTANT_String_info | |
| 137 | + Pstring_index => | |
| 138 | + string_index: int; | |
| 139 | + # CONSTANT_Class_info | |
| 140 | + Pci => | |
| 141 | + ci: ref Const_ci; | |
| 142 | + # CONSTANT_[Fieldref|Methodref|InterfaceMethodref]_info | |
| 143 | + Pfmiref => | |
| 144 | + fmiref: ref Const_fmiref; | |
| 145 | + # CONSTANT_NameAndType | |
| 146 | + Pnat => | |
| 147 | + nat: ref Const_nat; | |
| 148 | + # CONSTANT_Utf8_info | |
| 149 | + Putf8 => | |
| 150 | + utf8: ref Const_utf8; | |
| 151 | + | |
| 152 | + # since 49.0 | |
| 153 | + | |
| 154 | + # CONSTANT_MethodHandle_info | |
| 155 | + Pmethodhandle => | |
| 156 | + mh: ref Const_methodhandle; | |
| 157 | + # CONSTANT_MethodType_info | |
| 158 | + Pmethodtype => | |
| 159 | + mt: ref Const_methodtype; | |
| 160 | + # CONSTANT_InvokeDynamic_info | |
| 161 | + Pinvokedyn => | |
| 162 | + invokedyn: ref Const_invokedyn; | |
| 163 | + } | |
| 164 | +}; | |
| 165 | + | |
| 166 | +Attr: adt { # attribute_info | |
| 167 | + name: int; | |
| 168 | + ln: int; | |
| 169 | + info: array of byte; | |
| 170 | +}; | |
| 171 | + | |
| 172 | +Field: adt { # field_info | |
| 173 | + access_flags: int; | |
| 174 | + name_index: int; | |
| 175 | + sig_index: int; | |
| 176 | + attr_count: int; | |
| 177 | + attr_info: array of ref Attr; # ConstantValue attributes | |
| 178 | +}; | |
| 179 | + | |
| 180 | +Method: adt { # method_info | |
| 181 | + access_flags: int; | |
| 182 | + name_index: int; | |
| 183 | + sig_index: int; | |
| 184 | + attr_count: int; | |
| 185 | + attr_info: array of ref Attr; # Code, Exceptions attributes | |
| 186 | +}; | |
| 187 | + | |
| 188 | +Class: adt { # ClassFile | |
| 189 | +# magic int; # 0xcafebabe | |
| 190 | + min: int; | |
| 191 | + maj: int; | |
| 192 | + cp_count: int; | |
| 193 | + cps: array of ref Const; | |
| 194 | + cts: array of byte; | |
| 195 | + access_flags: int; | |
| 196 | + this_class: int; | |
| 197 | + super_class: int; | |
| 198 | + interfaces_count: int; | |
| 199 | + interfaces: array of int; | |
| 200 | + fields_count: int; | |
| 201 | + fields: array of ref Field; | |
| 202 | + methods_count: int; | |
| 203 | + methods: array of ref Method; | |
| 204 | + source_file: int; | |
| 205 | +}; | |
| 206 | + | |
| 207 | +Addr: adt { # Dis operand | |
| 208 | + mode: byte; # Anone, Aimm, Amp, etc. | |
| 209 | + ival: int; # immediate, $ival | |
| 210 | + offset: int; # single indirect, offset(fp) | |
| 211 | + # double indirect, offset(ival(fp)) | |
| 212 | +}; | |
| 213 | + | |
| 214 | +Jinst_x1c: adt { # iinc | |
| 215 | + ix: int; | |
| 216 | + icon: int; | |
| 217 | +}; | |
| 218 | + | |
| 219 | +Jinst_x2c0: adt { # invokeinterface | |
| 220 | + ix: int; | |
| 221 | + narg: int; | |
| 222 | + zero: int; | |
| 223 | +}; | |
| 224 | + | |
| 225 | +Jinst_x2d: adt { # multianewarray | |
| 226 | + ix: int; | |
| 227 | + dim: int; | |
| 228 | +}; | |
| 229 | + | |
| 230 | +Jinst_t1: adt { # tableswitch | |
| 231 | + dflt: int; | |
| 232 | + lb: int; | |
| 233 | + hb: int; | |
| 234 | + tbl: array of int; | |
| 235 | +}; | |
| 236 | + | |
| 237 | +Jinst_t2: adt { # lookupswitch | |
| 238 | + dflt: int; | |
| 239 | + np: int; | |
| 240 | + tbl: array of int; | |
| 241 | +}; | |
| 242 | + | |
| 243 | +Jinst_w: adt { # wide | |
| 244 | + op: byte; | |
| 245 | + ix: int; | |
| 246 | + icon: int; | |
| 247 | +}; | |
| 248 | + | |
| 249 | +Jinst: adt { # Java instruction | |
| 250 | + op: byte; # op code | |
| 251 | + jtype: byte; # Java type of dst ('I', '[', etc.) | |
| 252 | + pc: int; # pc offset | |
| 253 | + pcdis: int; # pc offset counted in dis instructions | |
| 254 | + line: int; # source line number | |
| 255 | + size: int; # size of this instruction | |
| 256 | + dis: cyclic ref Inst; # Dis code for this instruction | |
| 257 | + bb: cyclic ref BB; # the instruction's basic block | |
| 258 | + nsrc: int; # 0 or more source operands | |
| 259 | + src: array of int; # the source operands | |
| 260 | + dst: ref Addr; # usual destination operand | |
| 261 | + movsrc: ref Addr; # source operand if mov generated for load | |
| 262 | + pick { | |
| 263 | + Pz => | |
| 264 | + dummy: int; # Z | |
| 265 | + Pi => | |
| 266 | + i: int; # AT, X1, X2, B2, B4, V1, V2 | |
| 267 | + Px1c => | |
| 268 | + x1c: ref Jinst_x1c; # iinc | |
| 269 | + Px2c0 => | |
| 270 | + x2c0: ref Jinst_x2c0; # invokeinterface | |
| 271 | + Px2d => | |
| 272 | + x2d: ref Jinst_x2d; # multianewarray | |
| 273 | + Pt1 => | |
| 274 | + t1: ref Jinst_t1; # tableswitch | |
| 275 | + Pt2 => | |
| 276 | + t2: ref Jinst_t2; # lookupswitch | |
| 277 | + Pw => | |
| 278 | + w: ref Jinst_w; # wide | |
| 279 | + } | |
| 280 | +}; | |
| 281 | + | |
| 282 | +Handler: adt { # exception_table entry | |
| 283 | + start_pc: int; | |
| 284 | + end_pc: int; | |
| 285 | + handler_pc: int; | |
| 286 | + catch_type: int; | |
| 287 | +}; | |
| 288 | + | |
| 289 | +Code: adt { # one Java method | |
| 290 | + max_stack: int; | |
| 291 | + max_locals: int; | |
| 292 | + code_length: int; | |
| 293 | + j: array of ref Jinst; | |
| 294 | + nex: int; | |
| 295 | + ex: array of ref Handler; | |
| 296 | +}; | |
| 297 | + | |
| 298 | +PCode: adt { | |
| 299 | + code: ref Code; | |
| 300 | + name: string; | |
| 301 | + sig: string; | |
| 302 | +}; | |
| 303 | + | |
| 304 | +StkSnap: adt { # snapshot of simulated Java VM stack | |
| 305 | + jtype: byte; | |
| 306 | + npc: int; | |
| 307 | + pc: array of int; | |
| 308 | +}; | |
| 309 | + | |
| 310 | +BB: adt { # basic block | |
| 311 | + js: ref Jinst; # first instruction in basic block | |
| 312 | + je: cyclic ref Jinst; # last instruction in basic block | |
| 313 | + nsucc: int; # number of successors | |
| 314 | + succ: cyclic array of ref BB; # successors | |
| 315 | + flags: byte; # basic block leader flags | |
| 316 | + state: byte; # BB_PRESIM, etc. | |
| 317 | + entrysz: int; # size of saved entry stack | |
| 318 | + entrystk: array of ref StkSnap; # snapshot of entry stack | |
| 319 | + exitsz: int; # size of saved exit stack | |
| 320 | + exitstk: array of ref StkSnap; # snapshot of exit stack | |
| 321 | +}; | |
| 322 | + | |
| 323 | +Inst: adt { # Dis instruction | |
| 324 | + op: byte; # op code | |
| 325 | + s: ref Addr; # source | |
| 326 | + m: ref Addr; # middle | |
| 327 | + d: ref Addr; # destination | |
| 328 | + pc: int; # 0-based instruction offset | |
| 329 | + j: ref Jinst; | |
| 330 | + next: cyclic ref Inst; | |
| 331 | +}; | |
| 332 | + | |
| 333 | +# Bytecode Behaviors for Method Handles (see section 5.4.3.5 of jvm 1.7 specs) | |
| 334 | +REF_getfield: con 1; | |
| 335 | +REF_getstatic: con 2; | |
| 336 | +REF_putfield: con 3; | |
| 337 | +REF_putstatic: con 4; | |
| 338 | +REF_invokevirtual: con 5; | |
| 339 | +REF_invokestatic: con 6; | |
| 340 | +REF_invokespecial: con 7; | |
| 341 | +REF_newinvokespecial: con 8; | |
| 342 | +REF_invokeinterface: con 9; | |
| 343 | + | |
| @@ -0,0 +1,585 @@ | ||
| 1 | +# | |
| 2 | +# Java bytecode disassembler. | |
| 3 | +# | |
| 4 | + | |
| 5 | +# Java operand classifications | |
| 6 | + | |
| 7 | +AT, # unsigned byte (newarray) | |
| 8 | +B2, # 2-byte signed branch offset | |
| 9 | +B4, # 4-byte signed branch offset | |
| 10 | +X1, # 1-byte unsigned index (ldc) | |
| 11 | +X1C, # iinc | |
| 12 | +X2, # 2-byte unsigned index | |
| 13 | +X2C0, # invokeinterface | |
| 14 | +X2D, # multianewarray | |
| 15 | +T1, # tableswitch | |
| 16 | +T2, # lookupswitch | |
| 17 | +V1, # 1-byte signed value (bipush) | |
| 18 | +V2, # 2-byte signed value (sipush) | |
| 19 | +W, # wide | |
| 20 | +Z: con iota; # zero operands | |
| 21 | + | |
| 22 | +Jmnemon: adt { | |
| 23 | + op: string; | |
| 24 | + kind: int; | |
| 25 | +}; | |
| 26 | + | |
| 27 | +# | |
| 28 | +# Java bytecode mnemonics. | |
| 29 | +# | |
| 30 | + | |
| 31 | +tab: array of Jmnemon = array [MAXJAVA] of { | |
| 32 | + ("nop", Z), | |
| 33 | + ("aconst_null", Z), | |
| 34 | + ("iconst_m1", Z), | |
| 35 | + ("iconst_0", Z), | |
| 36 | + ("iconst_1", Z), | |
| 37 | + ("iconst_2", Z), | |
| 38 | + ("iconst_3", Z), | |
| 39 | + ("iconst_4", Z), | |
| 40 | + ("iconst_5", Z), | |
| 41 | + ("lconst_0", Z), | |
| 42 | + ("lconst_1", Z), | |
| 43 | + ("fconst_0", Z), | |
| 44 | + ("fconst_1", Z), | |
| 45 | + ("fconst_2", Z), | |
| 46 | + ("dconst_0", Z), | |
| 47 | + ("dconst_1", Z), | |
| 48 | + ("bipush", V1), | |
| 49 | + ("sipush", V2), | |
| 50 | + ("ldc", X1), | |
| 51 | + ("ldc_w", X2), | |
| 52 | + ("ldc2_w", X2), | |
| 53 | + ("iload", X1), | |
| 54 | + ("lload", X1), | |
| 55 | + ("fload", X1), | |
| 56 | + ("dload", X1), | |
| 57 | + ("aload", X1), | |
| 58 | + ("iload_0", Z), | |
| 59 | + ("iload_1", Z), | |
| 60 | + ("iload_2", Z), | |
| 61 | + ("iload_3", Z), | |
| 62 | + ("lload_0", Z), | |
| 63 | + ("lload_1", Z), | |
| 64 | + ("lload_2", Z), | |
| 65 | + ("lload_3", Z), | |
| 66 | + ("fload_0", Z), | |
| 67 | + ("fload_1", Z), | |
| 68 | + ("fload_2", Z), | |
| 69 | + ("fload_3", Z), | |
| 70 | + ("dload_0", Z), | |
| 71 | + ("dload_1", Z), | |
| 72 | + ("dload_2", Z), | |
| 73 | + ("dload_3", Z), | |
| 74 | + ("aload_0", Z), | |
| 75 | + ("aload_1", Z), | |
| 76 | + ("aload_2", Z), | |
| 77 | + ("aload_3", Z), | |
| 78 | + ("iaload", Z), | |
| 79 | + ("laload", Z), | |
| 80 | + ("faload", Z), | |
| 81 | + ("daload", Z), | |
| 82 | + ("aaload", Z), | |
| 83 | + ("baload", Z), | |
| 84 | + ("caload", Z), | |
| 85 | + ("saload", Z), | |
| 86 | + ("istore", X1), | |
| 87 | + ("lstore", X1), | |
| 88 | + ("fstore", X1), | |
| 89 | + ("dstore", X1), | |
| 90 | + ("astore", X1), | |
| 91 | + ("istore_0", Z), | |
| 92 | + ("istore_1", Z), | |
| 93 | + ("istore_2", Z), | |
| 94 | + ("istore_3", Z), | |
| 95 | + ("lstore_0", Z), | |
| 96 | + ("lstore_1", Z), | |
| 97 | + ("lstore_2", Z), | |
| 98 | + ("lstore_3", Z), | |
| 99 | + ("fstore_0", Z), | |
| 100 | + ("fstore_1", Z), | |
| 101 | + ("fstore_2", Z), | |
| 102 | + ("fstore_3", Z), | |
| 103 | + ("dstore_0", Z), | |
| 104 | + ("dstore_1", Z), | |
| 105 | + ("dstore_2", Z), | |
| 106 | + ("dstore_3", Z), | |
| 107 | + ("astore_0", Z), | |
| 108 | + ("astore_1", Z), | |
| 109 | + ("astore_2", Z), | |
| 110 | + ("astore_3", Z), | |
| 111 | + ("iastore", Z), | |
| 112 | + ("lastore", Z), | |
| 113 | + ("fastore", Z), | |
| 114 | + ("dastore", Z), | |
| 115 | + ("aastore", Z), | |
| 116 | + ("bastore", Z), | |
| 117 | + ("castore", Z), | |
| 118 | + ("sastore", Z), | |
| 119 | + ("pop", Z), | |
| 120 | + ("pop2", Z), | |
| 121 | + ("dup", Z), | |
| 122 | + ("dup_x1", Z), | |
| 123 | + ("dup_x2", Z), | |
| 124 | + ("dup2", Z), | |
| 125 | + ("dup2_x1", Z), | |
| 126 | + ("dup2_x2", Z), | |
| 127 | + ("swap", Z), | |
| 128 | + ("iadd", Z), | |
| 129 | + ("ladd", Z), | |
| 130 | + ("fadd", Z), | |
| 131 | + ("dadd", Z), | |
| 132 | + ("isub", Z), | |
| 133 | + ("lsub", Z), | |
| 134 | + ("fsub", Z), | |
| 135 | + ("dsub", Z), | |
| 136 | + ("imul", Z), | |
| 137 | + ("lmul", Z), | |
| 138 | + ("fmul", Z), | |
| 139 | + ("dmul", Z), | |
| 140 | + ("idiv", Z), | |
| 141 | + ("ldiv", Z), | |
| 142 | + ("fdiv", Z), | |
| 143 | + ("ddiv", Z), | |
| 144 | + ("irem", Z), | |
| 145 | + ("lrem", Z), | |
| 146 | + ("frem", Z), | |
| 147 | + ("drem", Z), | |
| 148 | + ("ineg", Z), | |
| 149 | + ("lneg", Z), | |
| 150 | + ("fneg", Z), | |
| 151 | + ("dneg", Z), | |
| 152 | + ("ishl", Z), | |
| 153 | + ("lshl", Z), | |
| 154 | + ("ishr", Z), | |
| 155 | + ("lshr", Z), | |
| 156 | + ("iushr", Z), | |
| 157 | + ("lushr", Z), | |
| 158 | + ("iand", Z), | |
| 159 | + ("land", Z), | |
| 160 | + ("ior", Z), | |
| 161 | + ("lor", Z), | |
| 162 | + ("ixor", Z), | |
| 163 | + ("lxor", Z), | |
| 164 | + ("iinc", X1C), | |
| 165 | + ("i2l", Z), | |
| 166 | + ("i2f", Z), | |
| 167 | + ("i2d", Z), | |
| 168 | + ("l2i", Z), | |
| 169 | + ("l2f", Z), | |
| 170 | + ("l2d", Z), | |
| 171 | + ("f2i", Z), | |
| 172 | + ("f2l", Z), | |
| 173 | + ("f2d", Z), | |
| 174 | + ("d2i", Z), | |
| 175 | + ("d2l", Z), | |
| 176 | + ("d2f", Z), | |
| 177 | + ("i2b", Z), | |
| 178 | + ("i2c", Z), | |
| 179 | + ("i2s", Z), | |
| 180 | + ("lcmp", Z), | |
| 181 | + ("fcmpl", Z), | |
| 182 | + ("fcmpg", Z), | |
| 183 | + ("dcmpl", Z), | |
| 184 | + ("dcmpg", Z), | |
| 185 | + ("ifeq", B2), | |
| 186 | + ("ifne", B2), | |
| 187 | + ("iflt", B2), | |
| 188 | + ("ifge", B2), | |
| 189 | + ("ifgt", B2), | |
| 190 | + ("ifle", B2), | |
| 191 | + ("if_icmpeq", B2), | |
| 192 | + ("if_icmpne", B2), | |
| 193 | + ("if_icmplt", B2), | |
| 194 | + ("if_icmpge", B2), | |
| 195 | + ("if_icmpgt", B2), | |
| 196 | + ("if_icmple", B2), | |
| 197 | + ("if_acmpeq", B2), | |
| 198 | + ("if_acmpne", B2), | |
| 199 | + ("goto", B2), | |
| 200 | + ("jsr", B2), | |
| 201 | + ("ret", X1), | |
| 202 | + ("tableswitch", T1), | |
| 203 | + ("lookupswitch", T2), | |
| 204 | + ("ireturn", Z), | |
| 205 | + ("lreturn", Z), | |
| 206 | + ("freturn", Z), | |
| 207 | + ("dreturn", Z), | |
| 208 | + ("areturn", Z), | |
| 209 | + ("return", Z), | |
| 210 | + ("getstatic", X2), | |
| 211 | + ("putstatic", X2), | |
| 212 | + ("getfield", X2), | |
| 213 | + ("putfield", X2), | |
| 214 | + ("invokevirtual", X2), | |
| 215 | + ("invokespecial", X2), | |
| 216 | + ("invokestatic", X2), | |
| 217 | + ("invokeinterface", X2C0), | |
| 218 | + ("xxxunusedxxx", Z), | |
| 219 | + ("new", X2), | |
| 220 | + ("newarray", AT), | |
| 221 | + ("anewarray", X2), | |
| 222 | + ("arraylength", Z), | |
| 223 | + ("athrow", Z), | |
| 224 | + ("checkcast", X2), | |
| 225 | + ("instanceof", X2), | |
| 226 | + ("monitorenter", Z), | |
| 227 | + ("monitorexit", Z), | |
| 228 | + ("wide", W), | |
| 229 | + ("multianewarray", X2D), | |
| 230 | + ("ifnull", B2), | |
| 231 | + ("ifnonnull", B2), | |
| 232 | + ("goto_w", B4), | |
| 233 | + ("jsr_w", B4), | |
| 234 | +}; | |
| 235 | + | |
| 236 | +# | |
| 237 | +# %J format conversion. | |
| 238 | +# | |
| 239 | + | |
| 240 | +jinstconv(j: ref Jinst): string | |
| 241 | +{ | |
| 242 | + t: Jmnemon; | |
| 243 | + i: int; | |
| 244 | + | |
| 245 | + t = tab[int j.op]; | |
| 246 | + s := t.op; | |
| 247 | + if(t.kind != Z) | |
| 248 | + s += " "; | |
| 249 | + pick jp := j { | |
| 250 | + Pz => | |
| 251 | + ; | |
| 252 | + Pi => | |
| 253 | + s += string jp.i; | |
| 254 | + Px1c => | |
| 255 | + s += string jp.x1c.ix + "," + string jp.x1c.icon; | |
| 256 | + Px2c0 => | |
| 257 | + s += string jp.x2c0.ix + "," + string jp.x2c0.narg; | |
| 258 | + s += "," + string jp.x2c0.zero; | |
| 259 | + Px2d => | |
| 260 | + s += string jp.x2d.ix + "," + string jp.x2d.dim; | |
| 261 | + Pt1 => | |
| 262 | + s += string jp.t1.dflt + "," + string jp.t1.lb; | |
| 263 | + s += "," + string jp.t1.hb; | |
| 264 | + if(jp.t1.tbl != nil) { | |
| 265 | + for(i = 0; i < jp.t1.hb - jp.t1.lb + 1; i++) | |
| 266 | + s += "," + string jp.t1.tbl[i]; | |
| 267 | + } | |
| 268 | + Pt2 => | |
| 269 | + s += string jp.t2.dflt + "," + string jp.t2.np; | |
| 270 | + if(jp.t2.tbl != nil) { | |
| 271 | + for(i = 0; i < 2*jp.t2.np; i++) | |
| 272 | + s += "," + string jp.t2.tbl[i]; | |
| 273 | + } | |
| 274 | + Pw => | |
| 275 | + s += string jp.w.op + "," + string jp.w.ix; | |
| 276 | + if(int jp.w.op == Jiinc) | |
| 277 | + s += "," + string jp.w.icon; | |
| 278 | + } | |
| 279 | + return s; | |
| 280 | +} | |
| 281 | + | |
| 282 | +# | |
| 283 | +# Verify an exception handler. | |
| 284 | +# | |
| 285 | + | |
| 286 | +verifyehpc(c: ref Code, pc: int) | |
| 287 | +{ | |
| 288 | + if(pc >= c.code_length || c.j[pc] == nil) | |
| 289 | + verifyerrormess("handler pc"); | |
| 290 | +} | |
| 291 | + | |
| 292 | +verifyhandler(c: ref Code, h: ref Handler) | |
| 293 | +{ | |
| 294 | + verifyehpc(c, h.start_pc); | |
| 295 | + | |
| 296 | + if(h.end_pc != c.code_length) | |
| 297 | + verifyehpc(c, h.end_pc); | |
| 298 | + | |
| 299 | + verifyehpc(c, h.handler_pc); | |
| 300 | + | |
| 301 | + if(h.catch_type != 0) | |
| 302 | + verifycpindex(nil, h.catch_type, 1 << CON_Class); | |
| 303 | +} | |
| 304 | + | |
| 305 | +# | |
| 306 | +# Disassemble code for a method. | |
| 307 | +# | |
| 308 | + | |
| 309 | +javadas(a: ref Attr): ref Code | |
| 310 | +{ | |
| 311 | + c: ref Code; | |
| 312 | + h, h1, h2: ref Handler; | |
| 313 | + pc, codelen: int; | |
| 314 | + l, i, k, n, nat, nln, CON_bits: int; | |
| 315 | + op: byte; | |
| 316 | + | |
| 317 | + uSet(a.info); | |
| 318 | + c = ref Code(0, 0, 0, nil, 0, nil); | |
| 319 | + c.max_stack = u2(); | |
| 320 | + c.max_locals = u2(); | |
| 321 | + c.code_length = u4(); | |
| 322 | + if(c.code_length == 0 || c.code_length > 65535) | |
| 323 | + verifyerrormess("code_length"); | |
| 324 | + # +1 is for exception object | |
| 325 | + c.j = array [c.code_length+1] of ref Jinst; | |
| 326 | + c.j[c.code_length] = ref Jinst.Pi; | |
| 327 | + c.j[c.code_length].dst = ref Addr; | |
| 328 | + | |
| 329 | + pc = 0; | |
| 330 | + codelen = c.code_length; | |
| 331 | + while(codelen > 0) { | |
| 332 | + op = u1(); | |
| 333 | + case int tab[int op].kind { | |
| 334 | + Z => | |
| 335 | + j := ref Jinst.Pz; | |
| 336 | + j.op = op; | |
| 337 | + l = 1; | |
| 338 | + c.j[pc] = j; | |
| 339 | + V1 => | |
| 340 | + j := ref Jinst.Pi; | |
| 341 | + j.op = op; | |
| 342 | + j.i = (int u1() << 24) >> 24; # sign-extend | |
| 343 | + l = 2; | |
| 344 | + c.j[pc] = j; | |
| 345 | + B2 or | |
| 346 | + V2 => | |
| 347 | + j := ref Jinst.Pi; | |
| 348 | + j.op = op; | |
| 349 | + j.i = (u2() << 16) >> 16; # sign-extend | |
| 350 | + l = 3; | |
| 351 | + c.j[pc] = j; | |
| 352 | + B4 => | |
| 353 | + j := ref Jinst.Pi; | |
| 354 | + j.op = op; | |
| 355 | + j.i = u4(); | |
| 356 | + l = 5; | |
| 357 | + c.j[pc] = j; | |
| 358 | + X1 => | |
| 359 | + j := ref Jinst.Pi; | |
| 360 | + j.op = op; | |
| 361 | + j.i = int u1(); | |
| 362 | + if(int j.op == Jldc) { | |
| 363 | + CON_bits = 1 << CON_Integer | 1 << CON_Float | 1 << CON_String; | |
| 364 | + verifycpindex(j, j.i, CON_bits); | |
| 365 | + } | |
| 366 | + l = 2; | |
| 367 | + c.j[pc] = j; | |
| 368 | + X2 => | |
| 369 | + j := ref Jinst.Pi; | |
| 370 | + j.op = op; | |
| 371 | + j.i = u2(); | |
| 372 | + case int j.op { | |
| 373 | + Jldc_w => | |
| 374 | + CON_bits = 1 << CON_Integer | 1 << CON_Float | 1 << CON_String; | |
| 375 | + if (class.maj >= 50) | |
| 376 | + CON_bits |= 1 << CON_Class; | |
| 377 | + if (class.maj >= 51) | |
| 378 | + CON_bits |= 1 << CON_MethodType | 1 << CON_MethodHandle; | |
| 379 | + Jldc2_w => | |
| 380 | + CON_bits = 1 << CON_Long | 1 << CON_Double; | |
| 381 | + if (class.maj >= 50) | |
| 382 | + CON_bits |= 1 << CON_Class; | |
| 383 | + if (class.maj >= 51) | |
| 384 | + CON_bits |= 1 << CON_MethodType | 1 << CON_MethodHandle; | |
| 385 | + if(j.i == class.cp_count-1) | |
| 386 | + verifyerror(j); | |
| 387 | + Jgetstatic or | |
| 388 | + Jputstatic or | |
| 389 | + Jgetfield or | |
| 390 | + Jputfield => | |
| 391 | + CON_bits = 1 << CON_Fieldref; | |
| 392 | + Jinvokevirtual or | |
| 393 | + Jinvokespecial or | |
| 394 | + Jinvokestatic => | |
| 395 | + CON_bits = 1 << CON_Methodref; | |
| 396 | + Jnew or | |
| 397 | + Janewarray or | |
| 398 | + Jcheckcast or | |
| 399 | + Jinstanceof => | |
| 400 | + CON_bits = 1 << CON_Class; | |
| 401 | + } | |
| 402 | + verifycpindex(j, j.i, CON_bits); | |
| 403 | + l = 3; | |
| 404 | + c.j[pc] = j; | |
| 405 | + X1C => | |
| 406 | + j := ref Jinst.Px1c; | |
| 407 | + j.op = op; | |
| 408 | + j.x1c = ref Jinst_x1c; | |
| 409 | + j.x1c.ix = int u1(); | |
| 410 | + j.x1c.icon = (int u1() << 24) >> 24; # sign-extend | |
| 411 | + l = 3; | |
| 412 | + c.j[pc] = j; | |
| 413 | + X2D => | |
| 414 | + j := ref Jinst.Px2d; | |
| 415 | + j.op = op; | |
| 416 | + j.x2d = ref Jinst_x2d; | |
| 417 | + j.x2d.ix = u2(); | |
| 418 | + j.x2d.dim = int u1(); | |
| 419 | + verifycpindex(j, j.x2d.ix, 1 << CON_Class); | |
| 420 | + if(j.x2d.dim < 1) | |
| 421 | + verifyerror(j); | |
| 422 | + l = 4; | |
| 423 | + c.j[pc] = j; | |
| 424 | + AT => | |
| 425 | + j := ref Jinst.Pi; | |
| 426 | + j.op = op; | |
| 427 | + j.i = int u1(); | |
| 428 | + if(j.i < T_BOOLEAN || j.i > T_LONG) | |
| 429 | + verifyerror(j); | |
| 430 | + l = 2; | |
| 431 | + c.j[pc] = j; | |
| 432 | + T1 => | |
| 433 | + j := ref Jinst.Pt1; | |
| 434 | + j.op = op; | |
| 435 | + j.t1 = ref Jinst_t1; | |
| 436 | + if((pc+1)%4) # <0-3 byte pad> | |
| 437 | + n = 4-(pc+1)%4; | |
| 438 | + else | |
| 439 | + n = 0; | |
| 440 | + l = n; | |
| 441 | + while(n--) | |
| 442 | + u1(); | |
| 443 | + j.t1.dflt = u4(); | |
| 444 | + j.t1.lb = u4(); | |
| 445 | + j.t1.hb = u4(); | |
| 446 | + if(j.t1.lb > j.t1.hb) | |
| 447 | + verifyerror(j); | |
| 448 | + n = j.t1.hb - j.t1.lb + 1; | |
| 449 | + j.t1.tbl = array [n] of int; | |
| 450 | + for(i = 0; i < n; i++) | |
| 451 | + j.t1.tbl[i] = u4(); | |
| 452 | + l += 13 + n * 4; | |
| 453 | + c.j[pc] = j; | |
| 454 | + T2 => | |
| 455 | + j := ref Jinst.Pt2; | |
| 456 | + j.op = op; | |
| 457 | + j.t2 = ref Jinst_t2; | |
| 458 | + if((pc+1)%4) # <0-3 byte pad> | |
| 459 | + n = 4-(pc+1)%4; | |
| 460 | + else | |
| 461 | + n = 0; | |
| 462 | + l = n; | |
| 463 | + while(n--) | |
| 464 | + u1(); | |
| 465 | + j.t2.dflt = u4(); | |
| 466 | + j.t2.np = u4(); | |
| 467 | + n = j.t2.np; | |
| 468 | + if(n < 0) | |
| 469 | + verifyerror(j); | |
| 470 | + j.t2.tbl = array [n*2] of int; | |
| 471 | + for(i = 0; i < n*2; i++) | |
| 472 | + j.t2.tbl[i] = u4(); | |
| 473 | + for(i = 2; i < n*2; i += 2) { | |
| 474 | + if(j.t2.tbl[i-2] > j.t2.tbl[i]) | |
| 475 | + verifyerror(j); | |
| 476 | + } | |
| 477 | + l += 9 + n * 8; | |
| 478 | + c.j[pc] = j; | |
| 479 | + W => | |
| 480 | + j := ref Jinst.Pw; | |
| 481 | + j.op = op; | |
| 482 | + j.w = ref Jinst_w; | |
| 483 | + j.w.op = u1(); | |
| 484 | + j.w.ix = u2(); | |
| 485 | + case int j.w.op { | |
| 486 | + Jiload or | |
| 487 | + Jlload or | |
| 488 | + Jfload or | |
| 489 | + Jdload or | |
| 490 | + Jaload or | |
| 491 | + Jistore or | |
| 492 | + Jlstore or | |
| 493 | + Jfstore or | |
| 494 | + Jdstore or | |
| 495 | + Jastore or | |
| 496 | + Jret => | |
| 497 | + l = 4; | |
| 498 | + Jiinc => | |
| 499 | + j.w.icon = (u2() << 16) >> 16; # sign-extend | |
| 500 | + l = 6; | |
| 501 | + * => | |
| 502 | + verifyerror(j); | |
| 503 | + } | |
| 504 | + c.j[pc] = j; | |
| 505 | + X2C0 => | |
| 506 | + j := ref Jinst.Px2c0; | |
| 507 | + j.op = op; | |
| 508 | + j.x2c0 = ref Jinst_x2c0; | |
| 509 | + j.x2c0.ix = u2(); | |
| 510 | + j.x2c0.narg = int u1(); | |
| 511 | + j.x2c0.zero = int u1(); # must be 0 | |
| 512 | + verifycpindex(j, j.x2c0.ix, 1 << CON_InterfaceMref); | |
| 513 | + if(j.x2c0.narg < 1 || j.x2c0.zero != 0) | |
| 514 | + verifyerror(j); | |
| 515 | + l = 5; | |
| 516 | + c.j[pc] = j; | |
| 517 | + * => | |
| 518 | + verifyerrormess("illegal opcode"); | |
| 519 | + } | |
| 520 | + c.j[pc].pc = pc; | |
| 521 | + c.j[pc].line = 0; | |
| 522 | + c.j[pc].size = l; | |
| 523 | + c.j[pc].nsrc = 0; | |
| 524 | + c.j[pc].dst = ref Addr(byte 0, 0, 0); | |
| 525 | + c.j[pc].movsrc = ref Addr(byte 0, 0, 0); | |
| 526 | + codelen -= l; | |
| 527 | + pc += l; | |
| 528 | + } | |
| 529 | + if(codelen != 0) | |
| 530 | + verifyerrormess("code_length"); | |
| 531 | + | |
| 532 | + c.nex = u2(); | |
| 533 | + if(c.nex > 0) { | |
| 534 | + c.ex = array [c.nex] of ref Handler; | |
| 535 | + for(i = 0; i < c.nex; i++) { | |
| 536 | + c.ex[i] = ref Handler(0, 0, 0, 0); | |
| 537 | + h = c.ex[i]; | |
| 538 | + h.start_pc = u2(); | |
| 539 | + h.end_pc = u2(); | |
| 540 | + h.handler_pc = u2(); | |
| 541 | + h.catch_type = u2(); | |
| 542 | + verifyhandler(c, h); | |
| 543 | + # | |
| 544 | + # sort nested try blocks that have same start_pc, | |
| 545 | + # outer-most go first (see cvtehinfo() [xlate.c]) | |
| 546 | + # | |
| 547 | + for(k = i; k > 0; k--) { | |
| 548 | + h1 = c.ex[k]; | |
| 549 | + h2 = c.ex[k-1]; | |
| 550 | + if(h1.start_pc == h2.start_pc | |
| 551 | + && h1.end_pc > h2.end_pc) { | |
| 552 | + c.ex[k] = h2; | |
| 553 | + c.ex[k-1] = h1; | |
| 554 | + } | |
| 555 | + } | |
| 556 | + } | |
| 557 | + } | |
| 558 | + | |
| 559 | + if(gensbl == 0) | |
| 560 | + return c; | |
| 561 | + | |
| 562 | + # interpret LineNumberTable attributes */ | |
| 563 | + nat = u2(); | |
| 564 | + for(i = 0; i < nat; i++) { | |
| 565 | + at := getattr(); | |
| 566 | + if(STRING(at.name) == "LineNumberTable") { | |
| 567 | + nln = (int at.info[0] << 8) | int at.info[1]; | |
| 568 | + for(k = 2; k < nln*4+2; k += 4) { | |
| 569 | + pc = (int at.info[k] << 8) | int at.info[k+1]; | |
| 570 | + c.j[pc].line = (int at.info[k+2] << 8) | int at.info[k+3]; | |
| 571 | + } | |
| 572 | + } | |
| 573 | + } | |
| 574 | + pc = 0; | |
| 575 | + n = 0; | |
| 576 | + while(pc < c.code_length) { | |
| 577 | + if(c.j[pc].line == 0) | |
| 578 | + c.j[pc].line = n; | |
| 579 | + else | |
| 580 | + n = c.j[pc].line; | |
| 581 | + pc += c.j[pc].size; | |
| 582 | + } | |
| 583 | + | |
| 584 | + return c; | |
| 585 | +} | |
| @@ -0,0 +1,219 @@ | ||
| 1 | +# | |
| 2 | +# Java VM instruction set | |
| 3 | +# | |
| 4 | + | |
| 5 | +Jnop, | |
| 6 | +Jaconst_null, | |
| 7 | +Jiconst_m1, | |
| 8 | +Jiconst_0, | |
| 9 | +Jiconst_1, | |
| 10 | +Jiconst_2, | |
| 11 | +Jiconst_3, | |
| 12 | +Jiconst_4, | |
| 13 | +Jiconst_5, | |
| 14 | +Jlconst_0, | |
| 15 | +Jlconst_1, | |
| 16 | +Jfconst_0, | |
| 17 | +Jfconst_1, | |
| 18 | +Jfconst_2, | |
| 19 | +Jdconst_0, | |
| 20 | +Jdconst_1, | |
| 21 | +Jbipush, | |
| 22 | +Jsipush, | |
| 23 | +Jldc, | |
| 24 | +Jldc_w, | |
| 25 | +Jldc2_w, | |
| 26 | +Jiload, | |
| 27 | +Jlload, | |
| 28 | +Jfload, | |
| 29 | +Jdload, | |
| 30 | +Jaload, | |
| 31 | +Jiload_0, | |
| 32 | +Jiload_1, | |
| 33 | +Jiload_2, | |
| 34 | +Jiload_3, | |
| 35 | +Jlload_0, | |
| 36 | +Jlload_1, | |
| 37 | +Jlload_2, | |
| 38 | +Jlload_3, | |
| 39 | +Jfload_0, | |
| 40 | +Jfload_1, | |
| 41 | +Jfload_2, | |
| 42 | +Jfload_3, | |
| 43 | +Jdload_0, | |
| 44 | +Jdload_1, | |
| 45 | +Jdload_2, | |
| 46 | +Jdload_3, | |
| 47 | +Jaload_0, | |
| 48 | +Jaload_1, | |
| 49 | +Jaload_2, | |
| 50 | +Jaload_3, | |
| 51 | +Jiaload, | |
| 52 | +Jlaload, | |
| 53 | +Jfaload, | |
| 54 | +Jdaload, | |
| 55 | +Jaaload, | |
| 56 | +Jbaload, | |
| 57 | +Jcaload, | |
| 58 | +Jsaload, | |
| 59 | +Jistore, | |
| 60 | +Jlstore, | |
| 61 | +Jfstore, | |
| 62 | +Jdstore, | |
| 63 | +Jastore, | |
| 64 | +Jistore_0, | |
| 65 | +Jistore_1, | |
| 66 | +Jistore_2, | |
| 67 | +Jistore_3, | |
| 68 | +Jlstore_0, | |
| 69 | +Jlstore_1, | |
| 70 | +Jlstore_2, | |
| 71 | +Jlstore_3, | |
| 72 | +Jfstore_0, | |
| 73 | +Jfstore_1, | |
| 74 | +Jfstore_2, | |
| 75 | +Jfstore_3, | |
| 76 | +Jdstore_0, | |
| 77 | +Jdstore_1, | |
| 78 | +Jdstore_2, | |
| 79 | +Jdstore_3, | |
| 80 | +Jastore_0, | |
| 81 | +Jastore_1, | |
| 82 | +Jastore_2, | |
| 83 | +Jastore_3, | |
| 84 | +Jiastore, | |
| 85 | +Jlastore, | |
| 86 | +Jfastore, | |
| 87 | +Jdastore, | |
| 88 | +Jaastore, | |
| 89 | +Jbastore, | |
| 90 | +Jcastore, | |
| 91 | +Jsastore, | |
| 92 | +Jpop, | |
| 93 | +Jpop2, | |
| 94 | +Jdup, | |
| 95 | +Jdup_x1, | |
| 96 | +Jdup_x2, | |
| 97 | +Jdup2, | |
| 98 | +Jdup2_x1, | |
| 99 | +Jdup2_x2, | |
| 100 | +Jswap, | |
| 101 | +Jiadd, | |
| 102 | +Jladd, | |
| 103 | +Jfadd, | |
| 104 | +Jdadd, | |
| 105 | +Jisub, | |
| 106 | +Jlsub, | |
| 107 | +Jfsub, | |
| 108 | +Jdsub, | |
| 109 | +Jimul, | |
| 110 | +Jlmul, | |
| 111 | +Jfmul, | |
| 112 | +Jdmul, | |
| 113 | +Jidiv, | |
| 114 | +Jldiv, | |
| 115 | +Jfdiv, | |
| 116 | +Jddiv, | |
| 117 | +Jirem, | |
| 118 | +Jlrem, | |
| 119 | +Jfrem, | |
| 120 | +Jdrem, | |
| 121 | +Jineg, | |
| 122 | +Jlneg, | |
| 123 | +Jfneg, | |
| 124 | +Jdneg, | |
| 125 | +Jishl, | |
| 126 | +Jlshl, | |
| 127 | +Jishr, | |
| 128 | +Jlshr, | |
| 129 | +Jiushr, | |
| 130 | +Jlushr, | |
| 131 | +Jiand, | |
| 132 | +Jland, | |
| 133 | +Jior, | |
| 134 | +Jlor, | |
| 135 | +Jixor, | |
| 136 | +Jlxor, | |
| 137 | +Jiinc, | |
| 138 | +Ji2l, | |
| 139 | +Ji2f, | |
| 140 | +Ji2d, | |
| 141 | +Jl2i, | |
| 142 | +Jl2f, | |
| 143 | +Jl2d, | |
| 144 | +Jf2i, | |
| 145 | +Jf2l, | |
| 146 | +Jf2d, | |
| 147 | +Jd2i, | |
| 148 | +Jd2l, | |
| 149 | +Jd2f, | |
| 150 | +Ji2b, | |
| 151 | +Ji2c, | |
| 152 | +Ji2s, | |
| 153 | +Jlcmp, | |
| 154 | +Jfcmpl, | |
| 155 | +Jfcmpg, | |
| 156 | +Jdcmpl, | |
| 157 | +Jdcmpg, | |
| 158 | +Jifeq, | |
| 159 | +Jifne, | |
| 160 | +Jiflt, | |
| 161 | +Jifge, | |
| 162 | +Jifgt, | |
| 163 | +Jifle, | |
| 164 | +Jif_icmpeq, | |
| 165 | +Jif_icmpne, | |
| 166 | +Jif_icmplt, | |
| 167 | +Jif_icmpge, | |
| 168 | +Jif_icmpgt, | |
| 169 | +Jif_icmple, | |
| 170 | +Jif_acmpeq, | |
| 171 | +Jif_acmpne, | |
| 172 | +Jgoto, | |
| 173 | +Jjsr, | |
| 174 | +Jret, | |
| 175 | +Jtableswitch, | |
| 176 | +Jlookupswitch, | |
| 177 | +Jireturn, | |
| 178 | +Jlreturn, | |
| 179 | +Jfreturn, | |
| 180 | +Jdreturn, | |
| 181 | +Jareturn, | |
| 182 | +Jreturn, | |
| 183 | +Jgetstatic, | |
| 184 | +Jputstatic, | |
| 185 | +Jgetfield, | |
| 186 | +Jputfield, | |
| 187 | +Jinvokevirtual, | |
| 188 | +Jinvokespecial, | |
| 189 | +Jinvokestatic, | |
| 190 | +Jinvokeinterface, | |
| 191 | +Jxxxunusedxxx, | |
| 192 | +Jnew, | |
| 193 | +Jnewarray, | |
| 194 | +Janewarray, | |
| 195 | +Jarraylength, | |
| 196 | +Jathrow, | |
| 197 | +Jcheckcast, | |
| 198 | +Jinstanceof, | |
| 199 | +Jmonitorenter, | |
| 200 | +Jmonitorexit, | |
| 201 | +Jwide, | |
| 202 | +Jmultianewarray, | |
| 203 | +Jifnull, | |
| 204 | +Jifnonnull, | |
| 205 | +Jgoto_w, | |
| 206 | +Jjsr_w: con iota; | |
| 207 | + | |
| 208 | +MAXJAVA: con Jjsr_w+1; | |
| 209 | + | |
| 210 | +# newarray element types (Java VM Specification page 320) | |
| 211 | + | |
| 212 | +T_BOOLEAN, | |
| 213 | +T_CHAR, | |
| 214 | +T_FLOAT, | |
| 215 | +T_DOUBLE, | |
| 216 | +T_BYTE, | |
| 217 | +T_SHORT, | |
| 218 | +T_INT, | |
| 219 | +T_LONG: con iota+4; | |
| @@ -0,0 +1,233 @@ | ||
| 1 | +XLOAD: con 16r1 << 0; | |
| 2 | +XSTORE: con 16r1 << 1; | |
| 3 | + | |
| 4 | +javatbl := array [MAXJAVA] of { | |
| 5 | + byte 0, # Jnop | |
| 6 | + byte XLOAD, # Jaconst_null | |
| 7 | + byte XLOAD, # Jiconst_m1 | |
| 8 | + byte XLOAD, # Jiconst_0 | |
| 9 | + byte XLOAD, # Jiconst_1 | |
| 10 | + byte XLOAD, # Jiconst_2 | |
| 11 | + byte XLOAD, # Jiconst_3 | |
| 12 | + byte XLOAD, # Jiconst_4 | |
| 13 | + byte XLOAD, # Jiconst_5 | |
| 14 | + byte XLOAD, # Jlconst_0 | |
| 15 | + byte XLOAD, # Jlconst_1 | |
| 16 | + byte XLOAD, # Jfconst_0 | |
| 17 | + byte XLOAD, # Jfconst_1 | |
| 18 | + byte XLOAD, # Jfconst_2 | |
| 19 | + byte XLOAD, # Jdconst_0 | |
| 20 | + byte XLOAD, # Jdconst_1 | |
| 21 | + byte XLOAD, # Jbipush | |
| 22 | + byte XLOAD, # Jsipush | |
| 23 | + byte XLOAD, # Jldc | |
| 24 | + byte XLOAD, # Jldc_w | |
| 25 | + byte XLOAD, # Jldc2_w | |
| 26 | + byte XLOAD, # Jiload | |
| 27 | + byte XLOAD, # Jlload | |
| 28 | + byte XLOAD, # Jfload | |
| 29 | + byte XLOAD, # Jdload | |
| 30 | + byte XLOAD, # Jaload | |
| 31 | + byte XLOAD, # Jiload_0 | |
| 32 | + byte XLOAD, # Jiload_1 | |
| 33 | + byte XLOAD, # Jiload_2 | |
| 34 | + byte XLOAD, # Jiload_3 | |
| 35 | + byte XLOAD, # Jlload_0 | |
| 36 | + byte XLOAD, # Jlload_1 | |
| 37 | + byte XLOAD, # Jlload_2 | |
| 38 | + byte XLOAD, # Jlload_3 | |
| 39 | + byte XLOAD, # Jfload_0 | |
| 40 | + byte XLOAD, # Jfload_1 | |
| 41 | + byte XLOAD, # Jfload_2 | |
| 42 | + byte XLOAD, # Jfload_3 | |
| 43 | + byte XLOAD, # Jdload_0 | |
| 44 | + byte XLOAD, # Jdload_1 | |
| 45 | + byte XLOAD, # Jdload_2 | |
| 46 | + byte XLOAD, # Jdload_3 | |
| 47 | + byte XLOAD, # Jaload_0 | |
| 48 | + byte XLOAD, # Jaload_1 | |
| 49 | + byte XLOAD, # Jaload_2 | |
| 50 | + byte XLOAD, # Jaload_3 | |
| 51 | + byte 0, # Jiaload | |
| 52 | + byte 0, # Jlaload | |
| 53 | + byte 0, # Jfaload | |
| 54 | + byte 0, # Jdaload | |
| 55 | + byte 0, # Jaaload | |
| 56 | + byte 0, # Jbaload | |
| 57 | + byte 0, # Jcaload | |
| 58 | + byte 0, # Jsaload | |
| 59 | + byte XSTORE, # Jistore | |
| 60 | + byte XSTORE, # Jlstore | |
| 61 | + byte XSTORE, # Jfstore | |
| 62 | + byte XSTORE, # Jdstore | |
| 63 | + byte XSTORE, # Jastore | |
| 64 | + byte XSTORE, # Jistore_0 | |
| 65 | + byte XSTORE, # Jistore_1 | |
| 66 | + byte XSTORE, # Jistore_2 | |
| 67 | + byte XSTORE, # Jistore_3 | |
| 68 | + byte XSTORE, # Jlstore_0 | |
| 69 | + byte XSTORE, # Jlstore_1 | |
| 70 | + byte XSTORE, # Jlstore_2 | |
| 71 | + byte XSTORE, # Jlstore_3 | |
| 72 | + byte XSTORE, # Jfstore_0 | |
| 73 | + byte XSTORE, # Jfstore_1 | |
| 74 | + byte XSTORE, # Jfstore_2 | |
| 75 | + byte XSTORE, # Jfstore_3 | |
| 76 | + byte XSTORE, # Jdstore_0 | |
| 77 | + byte XSTORE, # Jdstore_1 | |
| 78 | + byte XSTORE, # Jdstore_2 | |
| 79 | + byte XSTORE, # Jdstore_3 | |
| 80 | + byte XSTORE, # Jastore_0 | |
| 81 | + byte XSTORE, # Jastore_1 | |
| 82 | + byte XSTORE, # Jastore_2 | |
| 83 | + byte XSTORE, # Jastore_3 | |
| 84 | + byte 0, # Jiastore | |
| 85 | + byte 0, # Jlastore | |
| 86 | + byte 0, # Jfastore | |
| 87 | + byte 0, # Jdastore | |
| 88 | + byte 0, # Jaastore | |
| 89 | + byte 0, # Jbastore | |
| 90 | + byte 0, # Jcastore | |
| 91 | + byte 0, # Jsastore | |
| 92 | + byte 0, # Jpop | |
| 93 | + byte 0, # Jpop2 | |
| 94 | + byte 0, # Jdup | |
| 95 | + byte 0, # Jdup_x1 | |
| 96 | + byte 0, # Jdup_x2 | |
| 97 | + byte 0, # Jdup2 | |
| 98 | + byte 0, # Jdup2_x1 | |
| 99 | + byte 0, # Jdup2_x2 | |
| 100 | + byte 0, # Jswap | |
| 101 | + byte 0, # Jiadd | |
| 102 | + byte 0, # Jladd | |
| 103 | + byte 0, # Jfadd | |
| 104 | + byte 0, # Jdadd | |
| 105 | + byte 0, # Jisub | |
| 106 | + byte 0, # Jlsub | |
| 107 | + byte 0, # Jfsub | |
| 108 | + byte 0, # Jdsub | |
| 109 | + byte 0, # Jimul | |
| 110 | + byte 0, # Jlmul | |
| 111 | + byte 0, # Jfmul | |
| 112 | + byte 0, # Jdmul | |
| 113 | + byte 0, # Jidiv | |
| 114 | + byte 0, # Jldiv | |
| 115 | + byte 0, # Jfdiv | |
| 116 | + byte 0, # Jddiv | |
| 117 | + byte 0, # Jirem | |
| 118 | + byte 0, # Jlrem | |
| 119 | + byte 0, # Jfrem | |
| 120 | + byte 0, # Jdrem | |
| 121 | + byte 0, # Jineg | |
| 122 | + byte 0, # Jlneg | |
| 123 | + byte 0, # Jfneg | |
| 124 | + byte 0, # Jdneg | |
| 125 | + byte 0, # Jishl | |
| 126 | + byte 0, # Jlshl | |
| 127 | + byte 0, # Jishr | |
| 128 | + byte 0, # Jlshr | |
| 129 | + byte 0, # Jiushr | |
| 130 | + byte 0, # Jlushr | |
| 131 | + byte 0, # Jiand | |
| 132 | + byte 0, # Jland | |
| 133 | + byte 0, # Jior | |
| 134 | + byte 0, # Jlor | |
| 135 | + byte 0, # Jixor | |
| 136 | + byte 0, # Jlxor | |
| 137 | + byte 0, # Jiinc | |
| 138 | + byte 0, # Ji2l | |
| 139 | + byte 0, # Ji2f | |
| 140 | + byte 0, # Ji2d | |
| 141 | + byte 0, # Jl2i | |
| 142 | + byte 0, # Jl2f | |
| 143 | + byte 0, # Jl2d | |
| 144 | + byte 0, # Jf2i | |
| 145 | + byte 0, # Jf2l | |
| 146 | + byte 0, # Jf2d | |
| 147 | + byte 0, # Jd2i | |
| 148 | + byte 0, # Jd2l | |
| 149 | + byte 0, # Jd2f | |
| 150 | + byte 0, # Ji2b | |
| 151 | + byte 0, # Ji2c | |
| 152 | + byte 0, # Ji2s | |
| 153 | + byte 0, # Jlcmp | |
| 154 | + byte 0, # Jfcmpl | |
| 155 | + byte 0, # Jfcmpg | |
| 156 | + byte 0, # Jdcmpl | |
| 157 | + byte 0, # Jdcmpg | |
| 158 | + byte 0, # Jifeq | |
| 159 | + byte 0, # Jifne | |
| 160 | + byte 0, # Jiflt | |
| 161 | + byte 0, # Jifge | |
| 162 | + byte 0, # Jifgt | |
| 163 | + byte 0, # Jifle | |
| 164 | + byte 0, # Jif_icmpeq | |
| 165 | + byte 0, # Jif_icmpne | |
| 166 | + byte 0, # Jif_icmplt | |
| 167 | + byte 0, # Jif_icmpge | |
| 168 | + byte 0, # Jif_icmpgt | |
| 169 | + byte 0, # Jif_icmple | |
| 170 | + byte 0, # Jif_acmpeq | |
| 171 | + byte 0, # Jif_acmpne | |
| 172 | + byte 0, # Jgoto | |
| 173 | + byte 0, # Jjsr | |
| 174 | + byte 0, # Jret | |
| 175 | + byte 0, # Jtableswitch | |
| 176 | + byte 0, # Jlookupswitch | |
| 177 | + byte 0, # Jireturn | |
| 178 | + byte 0, # Jlreturn | |
| 179 | + byte 0, # Jfreturn | |
| 180 | + byte 0, # Jdreturn | |
| 181 | + byte 0, # Jareturn | |
| 182 | + byte 0, # Jreturn | |
| 183 | + byte 0, # Jgetstatic | |
| 184 | + byte 0, # Jputstatic | |
| 185 | + byte 0, # Jgetfield | |
| 186 | + byte 0, # Jputfield | |
| 187 | + byte 0, # Jinvokevirtual | |
| 188 | + byte 0, # Jinvokespecial | |
| 189 | + byte 0, # Jinvokestatic | |
| 190 | + byte 0, # Jinvokeinterface | |
| 191 | + byte 0, # Jxxxunusedxxx | |
| 192 | + byte 0, # Jnew | |
| 193 | + byte 0, # Jnewarray | |
| 194 | + byte 0, # Janewarray | |
| 195 | + byte 0, # Jarraylength | |
| 196 | + byte 0, # Jathrow | |
| 197 | + byte 0, # Jcheckcast | |
| 198 | + byte 0, # Jinstanceof | |
| 199 | + byte 0, # Jmonitorenter | |
| 200 | + byte 0, # Jmonitorexit | |
| 201 | + byte 0, # Jwide | |
| 202 | + byte 0, # Jmultianewarray | |
| 203 | + byte 0, # Jifnull | |
| 204 | + byte 0, # Jifnonnull | |
| 205 | + byte 0, # Jgoto_w | |
| 206 | + byte 0, # Jjsr_w | |
| 207 | +}; | |
| 208 | + | |
| 209 | +opcode(j: ref Jinst): int | |
| 210 | +{ | |
| 211 | + ret: byte; | |
| 212 | + | |
| 213 | + if(j.op == byte Jwide) { | |
| 214 | + pick jp := j { | |
| 215 | + Pw => | |
| 216 | + ret = jp.w.op; | |
| 217 | + * => | |
| 218 | + badpick("opcode"); | |
| 219 | + } | |
| 220 | + } else | |
| 221 | + ret = j.op; | |
| 222 | + return int ret; | |
| 223 | +} | |
| 224 | + | |
| 225 | +isload(j: ref Jinst): int | |
| 226 | +{ | |
| 227 | + return int javatbl[opcode(j)] & XLOAD; | |
| 228 | +} | |
| 229 | + | |
| 230 | +isstore(j: ref Jinst): int | |
| 231 | +{ | |
| 232 | + return int javatbl[opcode(j)] & XSTORE; | |
| 233 | +} | |
| @@ -0,0 +1,141 @@ | ||
| 1 | +# | |
| 2 | +# Manage .dis Link Section. | |
| 3 | +# | |
| 4 | + | |
| 5 | +Link: adt { | |
| 6 | + id: int; # dis type identifier | |
| 7 | + pc: int; # method entry pc | |
| 8 | + sig: int; # MD5 signature | |
| 9 | + name: string; # method name | |
| 10 | + next: cyclic ref Link; | |
| 11 | +}; | |
| 12 | + | |
| 13 | +links: ref Link; | |
| 14 | +last: ref Link; | |
| 15 | +nlinks: int; | |
| 16 | + | |
| 17 | +# | |
| 18 | +# Create a Link entry; one for each method defined in the class. | |
| 19 | +# | |
| 20 | + | |
| 21 | +xtrnlink(id: int, pc: int, name: string, sig: string) | |
| 22 | +{ | |
| 23 | + l: ref Link; | |
| 24 | + | |
| 25 | + l = ref Link(id, pc, 1247901281, name + sig, nil); | |
| 26 | + if(name == "main") | |
| 27 | + setentry(pc, id); | |
| 28 | + if(links == nil) | |
| 29 | + links = l; | |
| 30 | + else | |
| 31 | + last.next = l; | |
| 32 | + last = l; | |
| 33 | + nlinks += 1; | |
| 34 | +} | |
| 35 | + | |
| 36 | +# | |
| 37 | +# Functions for patching frame & call instructions. | |
| 38 | +# | |
| 39 | + | |
| 40 | +FCPatch: adt { | |
| 41 | + frame: ref Inst; | |
| 42 | + call: ref Inst; | |
| 43 | + name: string; | |
| 44 | + sig: string; | |
| 45 | + next: cyclic ref FCPatch; | |
| 46 | +}; | |
| 47 | + | |
| 48 | +fcplist: ref FCPatch; | |
| 49 | + | |
| 50 | +# | |
| 51 | +# Record a frame/call pair for later patching. | |
| 52 | +# | |
| 53 | + | |
| 54 | +addfcpatch(frame: ref Inst, call: ref Inst, name: string, sig: string) | |
| 55 | +{ | |
| 56 | + fcp: ref FCPatch; | |
| 57 | + | |
| 58 | + fcp = ref FCPatch(frame, call, name, sig, fcplist); | |
| 59 | + fcplist = fcp; | |
| 60 | +} | |
| 61 | + | |
| 62 | +getLink(name: string, sig: string): ref Link | |
| 63 | +{ | |
| 64 | + l: ref Link; | |
| 65 | + nlen: int; | |
| 66 | + | |
| 67 | + nlen = len name; | |
| 68 | + l = links; | |
| 69 | + while(l != nil) { | |
| 70 | + if(len l.name == nlen + len sig | |
| 71 | + && l.name[0:nlen] == name && l.name[nlen:] == sig) { | |
| 72 | + return l; | |
| 73 | + } | |
| 74 | + l = l.next; | |
| 75 | + } | |
| 76 | + fatal("getLink: " + name + ", " + sig); | |
| 77 | + return nil; | |
| 78 | +} | |
| 79 | + | |
| 80 | +# | |
| 81 | +# Patch frame/call pairs. | |
| 82 | +# | |
| 83 | + | |
| 84 | +dofcpatch() | |
| 85 | +{ | |
| 86 | + fcp: ref FCPatch; | |
| 87 | + l: ref Link; | |
| 88 | + | |
| 89 | + fcp = fcplist; | |
| 90 | + while(fcp != nil) { | |
| 91 | + l = getLink(fcp.name, fcp.sig); | |
| 92 | + fcp.frame.s.ival = l.id; | |
| 93 | + fcp.call.d.ival = l.pc; | |
| 94 | + fcp = fcp.next; | |
| 95 | + } | |
| 96 | +} | |
| 97 | + | |
| 98 | +# | |
| 99 | +# Emit assembly 'link' directives. | |
| 100 | +# | |
| 101 | + | |
| 102 | +asmlinks() | |
| 103 | +{ | |
| 104 | + l: ref Link; | |
| 105 | + | |
| 106 | + for(l = links; l != nil; l = l.next) { | |
| 107 | + bout.puts("\tlink\t" + string l.id + "," + string l.pc | |
| 108 | + + ",0x" + hex(l.sig, 0) + ",\"" + l.name + "\"\n"); | |
| 109 | + } | |
| 110 | +} | |
| 111 | + | |
| 112 | +sbllinks(bsym: ref Bufio->Iobuf) | |
| 113 | +{ | |
| 114 | + l: ref Link; | |
| 115 | + | |
| 116 | + bsym.puts(string nlinks + "\n"); | |
| 117 | + for(l = links; l != nil; l = l.next) { | |
| 118 | + bsym.puts(string l.pc + ":" + l.name + "\n"); | |
| 119 | + bsym.puts("0\n"); # args | |
| 120 | + bsym.puts("0\n"); # locals | |
| 121 | + bsym.puts("n\n"); # return type | |
| 122 | + } | |
| 123 | +} | |
| 124 | + | |
| 125 | +disnlinks() | |
| 126 | +{ | |
| 127 | + discon(nlinks); | |
| 128 | +} | |
| 129 | + | |
| 130 | +dislinks() | |
| 131 | +{ | |
| 132 | + l: ref Link; | |
| 133 | + | |
| 134 | + for(l = links; l != nil; l = l.next) { | |
| 135 | + discon(l.pc); | |
| 136 | + discon(l.id); | |
| 137 | + disword(l.sig); | |
| 138 | + bout.puts(l.name); | |
| 139 | + bout.putb(byte 0); | |
| 140 | + } | |
| 141 | +} | |
| @@ -0,0 +1,691 @@ | ||
| 1 | +# | |
| 2 | +# Class loader. | |
| 3 | +# | |
| 4 | + | |
| 5 | +class: ref Class; # class under translation | |
| 6 | +pcode: array of PCode; # pointers to byte code of defined methods | |
| 7 | +THISCLASS: string; | |
| 8 | +SUPERCLASS: string; | |
| 9 | + | |
| 10 | +STRING(i: int): string | |
| 11 | +{ | |
| 12 | + pick cp := class.cps[i] { | |
| 13 | + Putf8 => | |
| 14 | + return cp.utf8.utf8; | |
| 15 | + * => | |
| 16 | + badpick("STRING"); | |
| 17 | + } | |
| 18 | + return nil; | |
| 19 | +} | |
| 20 | + | |
| 21 | +CLASSNAME(i: int): string | |
| 22 | +{ | |
| 23 | + pick cp := class.cps[i] { | |
| 24 | + Pci => | |
| 25 | + return STRING(cp.ci.name_index); | |
| 26 | + * => | |
| 27 | + badpick("CLASSNAME"); | |
| 28 | + } | |
| 29 | + return nil; | |
| 30 | +} | |
| 31 | + | |
| 32 | +u8(): big | |
| 33 | +{ | |
| 34 | + b1, b2: big; | |
| 35 | + | |
| 36 | + b1 = big u4() << 32; | |
| 37 | + b2 = big u4() & 16rffffffff; | |
| 38 | + return b1 | b2; | |
| 39 | +} | |
| 40 | + | |
| 41 | +# | |
| 42 | +# Bytecode verification. | |
| 43 | +# | |
| 44 | + | |
| 45 | +verifyutf8index(index: int) | |
| 46 | +{ | |
| 47 | + verifycpindex(nil, index, 1 << CON_Utf8); | |
| 48 | + if(STRING(index) == nil) | |
| 49 | + verifyerrormess("nil name or descriptor"); | |
| 50 | +} | |
| 51 | + | |
| 52 | +verifyclassindex(index: int) | |
| 53 | +{ | |
| 54 | + verifycpindex(nil, index, 1 << CON_Class); | |
| 55 | + pick cp := class.cps[index] { | |
| 56 | + Pci => | |
| 57 | + verifyutf8index(cp.ci.name_index); | |
| 58 | + * => | |
| 59 | + badpick("verifyclassindex"); | |
| 60 | + } | |
| 61 | +} | |
| 62 | + | |
| 63 | +verifyfielddesc(name_index: int, sig_index: int) | |
| 64 | +{ | |
| 65 | + sig: string; | |
| 66 | + ftype: int; | |
| 67 | + | |
| 68 | + verifyutf8index(name_index); | |
| 69 | + verifyutf8index(sig_index); | |
| 70 | + sig = STRING(sig_index); | |
| 71 | + ftype = sig[0]; | |
| 72 | + sig = nextjavatype(sig); | |
| 73 | + if(ftype == 'V' || sig != nil) | |
| 74 | + verifyerrormess("field descriptor"); | |
| 75 | +} | |
| 76 | + | |
| 77 | +verifymethoddesc(name_index: int, sig_index: int) | |
| 78 | +{ | |
| 79 | + name, sig: string; | |
| 80 | + rtype: int; | |
| 81 | + wargs: int; | |
| 82 | + | |
| 83 | + verifyutf8index(name_index); | |
| 84 | + name = STRING(name_index); | |
| 85 | + verifyutf8index(sig_index); | |
| 86 | + sig = STRING(sig_index); | |
| 87 | + | |
| 88 | + # check special <method> names | |
| 89 | + if(name[0] == '<') { | |
| 90 | + if(name == "<init>") | |
| 91 | + ; | |
| 92 | + else if(name == "<clinit>") { | |
| 93 | + if(sig != "()V") | |
| 94 | + verifyerrormess("<clinit> signature"); | |
| 95 | + return; | |
| 96 | + } else | |
| 97 | + verifyerrormess("<method> name"); | |
| 98 | + } | |
| 99 | + | |
| 100 | + # check signature | |
| 101 | + if(sig[0] != '(') | |
| 102 | + verifyerrormess("method descriptor"); | |
| 103 | + sig = sig[1:]; | |
| 104 | + wargs = 0; | |
| 105 | + while(sig[0] != ')') { | |
| 106 | + wargs++; | |
| 107 | + if(sig[0] == 'J' || sig[0] == 'D') | |
| 108 | + wargs++; | |
| 109 | + sig = nextjavatype(sig); | |
| 110 | + } | |
| 111 | + sig = sig[1:]; | |
| 112 | + rtype = sig[0]; | |
| 113 | + sig = nextjavatype(sig); | |
| 114 | + if(wargs > 255 || sig != nil || (name[0] == '<' && rtype != 'V')) | |
| 115 | + verifyerrormess("method descriptor"); | |
| 116 | +} | |
| 117 | + | |
| 118 | +verifycpindexes() | |
| 119 | +{ | |
| 120 | + i: int; | |
| 121 | + nameindex, sigindex, natindex: int; | |
| 122 | + | |
| 123 | + for(i = 1; i < class.cp_count; i++) { | |
| 124 | + pick cp := class.cps[i] { | |
| 125 | + Pci => | |
| 126 | + verifyutf8index(cp.ci.name_index); | |
| 127 | + Pfmiref => | |
| 128 | + verifyclassindex(cp.fmiref.class_index); | |
| 129 | + natindex = cp.fmiref.name_type_index; | |
| 130 | + verifycpindex(nil, natindex, 1 << CON_NameAndType); | |
| 131 | + pick cpnat := class.cps[natindex] { | |
| 132 | + Pnat => | |
| 133 | + nameindex = cpnat.nat.name_index; | |
| 134 | + sigindex = cpnat.nat.sig_index; | |
| 135 | + * => | |
| 136 | + badpick("verifycpindexes (inner)"); | |
| 137 | + } | |
| 138 | + if(int class.cts[i] == CON_Fieldref) | |
| 139 | + verifyfielddesc(nameindex, sigindex); | |
| 140 | + else | |
| 141 | + verifymethoddesc(nameindex, sigindex); | |
| 142 | + Pstring_index => | |
| 143 | + verifycpindex(nil, cp.string_index, 1 << CON_Utf8); | |
| 144 | + Ptint => | |
| 145 | + ; | |
| 146 | + Pnat => | |
| 147 | + # CON_NameAndType is verified through | |
| 148 | + # CON_Fieldref, CON_Methodref, CON_InterfaceMref | |
| 149 | + ; | |
| 150 | + Putf8 => | |
| 151 | + ; | |
| 152 | + Ptvlong => | |
| 153 | + i++; | |
| 154 | + Ptdouble => | |
| 155 | + if(int class.cts[i] == CON_Double) # else CON_Float | |
| 156 | + i++; | |
| 157 | + # since 49.0 | |
| 158 | + Pmethodhandle => | |
| 159 | + case cp.mh.ref_kind { | |
| 160 | + # TODO: implement all ref_kinds handling | |
| 161 | + * => | |
| 162 | + verifyerrormess("bad method_handle ref_kind"); | |
| 163 | + } | |
| 164 | + Pmethodtype => | |
| 165 | + verifycpindex(nil, cp.mt.descriptor_index, 1 << CON_Utf8); | |
| 166 | + Pinvokedyn => | |
| 167 | + # TODO: verify bs_method_attr_index field | |
| 168 | + verifycpindex(nil, cp.invokedyn.name_type_index, 1 << CON_NameAndType); | |
| 169 | + * => | |
| 170 | + badpick("verifycpindexes (outer)"); | |
| 171 | + } | |
| 172 | + } | |
| 173 | +} | |
| 174 | + | |
| 175 | +CLASSMUTEX: con ACC_FINAL|ACC_ABSTRACT; | |
| 176 | + | |
| 177 | +verifyclassflags() | |
| 178 | +{ | |
| 179 | + bad: int; | |
| 180 | + | |
| 181 | + if(class.access_flags & ACC_INTERFACE) { | |
| 182 | + if(SUPERCLASS != "java/lang/Object") | |
| 183 | + verifyerrormess("superclass"); | |
| 184 | + # java bug: ACC_ABSTRACT should be set ??? | |
| 185 | + # bad = (class.access_flags & ACC_ABSTRACT) != ACC_ABSTRACT; | |
| 186 | + bad = 0; | |
| 187 | + bad += (class.access_flags & ACC_FINAL) != 0; | |
| 188 | + } else { | |
| 189 | + bad = (class.access_flags & CLASSMUTEX) == CLASSMUTEX; | |
| 190 | + } | |
| 191 | + if(bad) | |
| 192 | + verifyerrormess("access_flags"); | |
| 193 | +} | |
| 194 | + | |
| 195 | +multippp(flag: int): int | |
| 196 | +{ | |
| 197 | + ret: int; | |
| 198 | + | |
| 199 | + case flag & (ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED) { | |
| 200 | + 0 or | |
| 201 | + ACC_PUBLIC or | |
| 202 | + ACC_PRIVATE or | |
| 203 | + ACC_PROTECTED => | |
| 204 | + ret = 0; | |
| 205 | + * => | |
| 206 | + ret = 1; | |
| 207 | + } | |
| 208 | + return ret; | |
| 209 | +} | |
| 210 | + | |
| 211 | +IFACEFIELD: con ACC_PUBLIC|ACC_STATIC|ACC_FINAL; | |
| 212 | +_IFACEFIELD: con ACC_PRIVATE|ACC_PROTECTED|ACC_VOLATILE|ACC_TRANSIENT; | |
| 213 | +FIELDMUTEX: con ACC_FINAL|ACC_VOLATILE; | |
| 214 | +CVATTRTAGS: con ((1<<CON_Integer)|(1<<CON_Long)|(1<<CON_Float)|(1<<CON_Double)|(1<<CON_String)); | |
| 215 | + | |
| 216 | +verifyfield(fp: ref Field) | |
| 217 | +{ | |
| 218 | + bad, n: int; | |
| 219 | + c: int; | |
| 220 | + | |
| 221 | + verifyfielddesc(fp.name_index, fp.sig_index); | |
| 222 | + if(class.access_flags & ACC_INTERFACE) { | |
| 223 | + bad = (fp.access_flags & _IFACEFIELD) != 0; | |
| 224 | + bad += (fp.access_flags & IFACEFIELD) != IFACEFIELD; | |
| 225 | + } else { | |
| 226 | + bad = multippp(fp.access_flags); | |
| 227 | + bad += (fp.access_flags & FIELDMUTEX) == FIELDMUTEX; | |
| 228 | + } | |
| 229 | + if(bad) | |
| 230 | + verifyerrormess("access_flags"); | |
| 231 | + | |
| 232 | + # verify ConstantValue attribute | |
| 233 | + n = CVattrindex(fp); | |
| 234 | + if(n == 0) | |
| 235 | + return; | |
| 236 | + verifycpindex(nil, n, CVATTRTAGS); | |
| 237 | + c = STRING(fp.sig_index)[0]; | |
| 238 | + pick cp := class.cps[n] { | |
| 239 | + Ptdouble => | |
| 240 | + if(int class.cts[n] == CON_Float) | |
| 241 | + bad = (c != 'F'); | |
| 242 | + else | |
| 243 | + bad = (c != 'D'); | |
| 244 | + Ptvlong => | |
| 245 | + bad = (c != 'J'); | |
| 246 | + Ptint => | |
| 247 | + case c { | |
| 248 | + 'Z' or | |
| 249 | + 'B' or | |
| 250 | + 'C' or | |
| 251 | + 'S' or | |
| 252 | + 'I' => | |
| 253 | + bad = 0; | |
| 254 | + * => | |
| 255 | + bad = 1; | |
| 256 | + } | |
| 257 | + Pstring_index => | |
| 258 | + bad = (c != 'L'); | |
| 259 | + * => | |
| 260 | + bad = 1; | |
| 261 | + } | |
| 262 | + if(bad) | |
| 263 | + verifyerrormess("ConstantValue attribute"); | |
| 264 | +} | |
| 265 | + | |
| 266 | +IFACEMETHOD: con ACC_PUBLIC|ACC_ABSTRACT; | |
| 267 | +_IFACEMETHOD: con ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE; | |
| 268 | +_INITFLAGS: con ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE|ACC_ABSTRACT; | |
| 269 | +# java bug: ACC_SYNCHRONIZED wrongly allowed with ACC_ABSTRACT ??? | |
| 270 | +#METHODMUTEX: con ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE; | |
| 271 | +METHODMUTEX: con ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_NATIVE; | |
| 272 | + | |
| 273 | +verifymethod(mp: ref Method) | |
| 274 | +{ | |
| 275 | + bad: int; | |
| 276 | + name: string; | |
| 277 | + | |
| 278 | + verifymethoddesc(mp.name_index, mp.sig_index); | |
| 279 | + name = STRING(mp.name_index); | |
| 280 | + if(name == "<clinit>") | |
| 281 | + return; | |
| 282 | + if(class.access_flags & ACC_INTERFACE) { | |
| 283 | + bad = (mp.access_flags & _IFACEMETHOD) != 0; | |
| 284 | + bad += (mp.access_flags & IFACEMETHOD) != IFACEMETHOD; | |
| 285 | + } else { | |
| 286 | + bad = multippp(mp.access_flags); | |
| 287 | + if(name == "<init>") | |
| 288 | + bad += (mp.access_flags & _INITFLAGS) != 0; | |
| 289 | + if(mp.access_flags & ACC_ABSTRACT) | |
| 290 | + bad += (mp.access_flags & METHODMUTEX) != 0; | |
| 291 | + } | |
| 292 | + if(bad) | |
| 293 | + verifyerrormess("access_flags"); | |
| 294 | + # | |
| 295 | + # Code attribute verified during disassembly | |
| 296 | + # ignore Exceptions attribute for now | |
| 297 | + # | |
| 298 | +} | |
| 299 | + | |
| 300 | +# | |
| 301 | +# Parse a byte stream into a Class stucture. | |
| 302 | +# | |
| 303 | + | |
| 304 | +byte2Class(text: array of byte) | |
| 305 | +{ | |
| 306 | + i, j: int; | |
| 307 | + fp: ref Field; | |
| 308 | + mp: ref Method; | |
| 309 | + | |
| 310 | + uSet(text); | |
| 311 | + class = ref Class(0, 0, 0, nil, nil, 0, 0, 0, 0, nil, 0, nil, 0, nil, 0); | |
| 312 | + | |
| 313 | + if(u4() != int 16rCAFEBABE) | |
| 314 | + verifyerrormess("magic"); | |
| 315 | + | |
| 316 | + class.min = u2(); | |
| 317 | + class.maj = u2(); | |
| 318 | + | |
| 319 | + class.cp_count = u2(); | |
| 320 | + class.cps = array [class.cp_count] of ref Const; | |
| 321 | + class.cts = array [class.cp_count] of { * => byte 0 }; | |
| 322 | + | |
| 323 | + for(i = 1; i < class.cp_count; i++) { | |
| 324 | + class.cts[i] = byte u1(); | |
| 325 | + case int class.cts[i] { | |
| 326 | + CON_Class => | |
| 327 | + cp := ref Const.Pci; | |
| 328 | + cp.ci = ref Const_ci; | |
| 329 | + cp.ci.name_index = u2(); | |
| 330 | + class.cps[i] = cp; | |
| 331 | + CON_Fieldref or | |
| 332 | + CON_Methodref or | |
| 333 | + CON_InterfaceMref => | |
| 334 | + cp := ref Const.Pfmiref; | |
| 335 | + cp.fmiref = ref Const_fmiref; | |
| 336 | + cp.fmiref.class_index = u2(); | |
| 337 | + cp.fmiref.name_type_index = u2(); | |
| 338 | + class.cps[i] = cp; | |
| 339 | + CON_String => | |
| 340 | + cp := ref Const.Pstring_index; | |
| 341 | + cp.string_index = u2(); | |
| 342 | + class.cps[i] = cp; | |
| 343 | + CON_Integer => | |
| 344 | + cp := ref Const.Ptint; | |
| 345 | + cp.tint = u4(); | |
| 346 | + class.cps[i] = cp; | |
| 347 | + CON_Float => | |
| 348 | + cp := ref Const.Ptdouble; | |
| 349 | + cp.tdouble = math->bits32real(u4()); | |
| 350 | + class.cps[i] = cp; | |
| 351 | + CON_Long => | |
| 352 | + cp := ref Const.Ptvlong; | |
| 353 | + cp.tvlong = u8(); | |
| 354 | + class.cps[i] = cp; | |
| 355 | + i++; | |
| 356 | + CON_Double => | |
| 357 | + cp := ref Const.Ptdouble; | |
| 358 | + cp.tdouble = math->bits64real(u8()); | |
| 359 | + class.cps[i] = cp; | |
| 360 | + i++; | |
| 361 | + CON_NameAndType => | |
| 362 | + cp := ref Const.Pnat; | |
| 363 | + cp.nat = ref Const_nat; | |
| 364 | + cp.nat.name_index = u2(); | |
| 365 | + cp.nat.sig_index = u2(); | |
| 366 | + class.cps[i] = cp; | |
| 367 | + CON_Utf8 => | |
| 368 | + cp := ref Const.Putf8; | |
| 369 | + cp.utf8 = ref Const_utf8; | |
| 370 | + cp.utf8.ln = u2(); | |
| 371 | + # null char represented as 16rC080 in String literals | |
| 372 | + a := uPtr(cp.utf8.ln); | |
| 373 | + (src, dst) := (0, 0); | |
| 374 | + while(src < cp.utf8.ln) { | |
| 375 | + if(src+1 < cp.utf8.ln && a[src] == byte 16rC0 | |
| 376 | + && a[src+1] == byte 16r80) { | |
| 377 | + a[dst] = byte 0; | |
| 378 | + src++; | |
| 379 | + } else | |
| 380 | + a[dst] = a[src]; | |
| 381 | + src++; | |
| 382 | + dst++; | |
| 383 | + } | |
| 384 | + cp.utf8.utf8 = string a[0:dst]; | |
| 385 | + uN(cp.utf8.ln); | |
| 386 | + class.cps[i] = cp; | |
| 387 | + # since 49.0 | |
| 388 | + CON_MethodHandle => | |
| 389 | + verifyerrormess("MethodHandles are not implemented"); | |
| 390 | + cp := ref Const.Pmethodhandle; | |
| 391 | + cp.mh = ref Const_methodhandle; | |
| 392 | + cp.mh.ref_kind = int u1(); | |
| 393 | + cp.mh.ref_index = u2(); | |
| 394 | + class.cps[i] = cp; | |
| 395 | + CON_MethodType => | |
| 396 | + verifyerrormess("MethodTypes are not implemented"); | |
| 397 | + cp := ref Const.Pmethodtype; | |
| 398 | + cp.mt = ref Const_methodtype; | |
| 399 | + cp.mt.descriptor_index = u2(); | |
| 400 | + class.cps[i] = cp; | |
| 401 | + CON_InvokeDynamic => | |
| 402 | + verifyerrormess("InvokeDynamics are not implemented"); | |
| 403 | + cp := ref Const.Pinvokedyn; | |
| 404 | + cp.invokedyn = ref Const_invokedyn; | |
| 405 | + cp.invokedyn.bs_method_attr_index = u2(); | |
| 406 | + cp.invokedyn.name_type_index = u2(); | |
| 407 | + class.cps[i] = cp; | |
| 408 | + * => | |
| 409 | + verifyerrormess("constant pool tag"); | |
| 410 | + } | |
| 411 | + } | |
| 412 | + | |
| 413 | + verifycpindexes(); # verify after all are established | |
| 414 | + | |
| 415 | + class.access_flags = u2(); # verify after [THIS|SUPER]CLASS set | |
| 416 | + | |
| 417 | + class.this_class = u2(); | |
| 418 | + verifyclassindex(class.this_class); | |
| 419 | + THISCLASS = CLASSNAME(class.this_class); | |
| 420 | + | |
| 421 | + class.super_class = u2(); | |
| 422 | + if(class.super_class) { | |
| 423 | + verifyclassindex(class.super_class); | |
| 424 | + SUPERCLASS = CLASSNAME(class.super_class); | |
| 425 | + } else if(THISCLASS != "java/lang/Object") | |
| 426 | + verifyerrormess("superclass"); | |
| 427 | + | |
| 428 | + verifyclassflags(); | |
| 429 | + | |
| 430 | + # for compatibility with JavaSoft VM | |
| 431 | + if(len THISCLASS > len "inferno/vm/" | |
| 432 | + && THISCLASS[0:len "inferno/vm/"] == "inferno/vm/") { | |
| 433 | + # | |
| 434 | + # ACC_ABSTRACT & ACC_FINAL are both set in JVM, | |
| 435 | + # but a class can't be declared that way | |
| 436 | + # | |
| 437 | + class.access_flags |= ACC_ABSTRACT; | |
| 438 | + # | |
| 439 | + # ACC_SUPER not set in JVM, but javac sets it | |
| 440 | + # for inferno/vm/Array | |
| 441 | + # | |
| 442 | + class.access_flags &= ~ACC_SUPER; | |
| 443 | + } else if(class.access_flags & ACC_INTERFACE) { | |
| 444 | + # interfaces are implicitly abstract | |
| 445 | + class.access_flags |= ACC_ABSTRACT; | |
| 446 | + } | |
| 447 | + | |
| 448 | + class.interfaces_count = u2(); | |
| 449 | + if(class.interfaces_count > 0) | |
| 450 | + class.interfaces = array [class.interfaces_count] of int; | |
| 451 | + for(i = 0; i < class.interfaces_count; i++) { | |
| 452 | + class.interfaces[i] = u2(); | |
| 453 | + verifyclassindex(class.interfaces[i]); | |
| 454 | + } | |
| 455 | + | |
| 456 | + class.fields_count = u2(); | |
| 457 | + if(class.fields_count > 0) | |
| 458 | + class.fields = array [class.fields_count] of ref Field; | |
| 459 | + for(i = 0; i < class.fields_count; i++) { | |
| 460 | + class.fields[i] = ref Field(0, 0, 0, 0, nil); | |
| 461 | + fp = class.fields[i]; | |
| 462 | + fp.access_flags = u2(); | |
| 463 | + fp.name_index = u2(); | |
| 464 | + fp.sig_index = u2(); | |
| 465 | + fp.attr_count = u2(); | |
| 466 | + if(fp.attr_count > 0) | |
| 467 | + fp.attr_info = array [fp.attr_count] of ref Attr; | |
| 468 | + for(j = 0; j < fp.attr_count; j++) | |
| 469 | + fp.attr_info[j] = getattr(); | |
| 470 | + verifyfield(fp); | |
| 471 | + } | |
| 472 | + | |
| 473 | + class.methods_count = u2(); | |
| 474 | + if(class.methods_count > 0) { | |
| 475 | + class.methods = array [class.methods_count] of ref Method; | |
| 476 | + pcode = array [class.methods_count] of PCode; | |
| 477 | + } | |
| 478 | + for(i = 0; i < class.methods_count; i++) { | |
| 479 | + class.methods[i] = ref Method(0, 0, 0, 0, nil); | |
| 480 | + mp = class.methods[i]; | |
| 481 | + mp.access_flags = u2(); | |
| 482 | + mp.name_index = u2(); | |
| 483 | + mp.sig_index = u2(); | |
| 484 | + mp.attr_count = u2(); | |
| 485 | + if(mp.attr_count > 0) | |
| 486 | + mp.attr_info = array [mp.attr_count] of ref Attr; | |
| 487 | + for(j = 0; j < mp.attr_count; j++) | |
| 488 | + mp.attr_info[j] = getattr(); | |
| 489 | + verifymethod(mp); | |
| 490 | + } | |
| 491 | + | |
| 492 | + # get SourceFile attribute | |
| 493 | + i = u2(); | |
| 494 | + for(j = 0; j < i; j++) { | |
| 495 | + a := getattr(); | |
| 496 | + if(STRING(a.name) == "SourceFile") { | |
| 497 | + class.source_file = (int a.info[0] << 8) | int a.info[1]; | |
| 498 | + verifyutf8index(class.source_file); | |
| 499 | + break; | |
| 500 | + } | |
| 501 | + } | |
| 502 | +} | |
| 503 | + | |
| 504 | +# | |
| 505 | +# Return Class structure for named class. | |
| 506 | +# | |
| 507 | + | |
| 508 | +ClassLoader(name: string) | |
| 509 | +{ | |
| 510 | + fd := sys->open(name, Sys->OREAD); | |
| 511 | + if(fd == nil) | |
| 512 | + fatal("ClassLoader: can't open " + name + ": " + sprint("%r")); | |
| 513 | + | |
| 514 | + (i, dir) := sys->fstat(fd); | |
| 515 | + if(i < 0) | |
| 516 | + fatal("ClassLoader: can't stat " + name + ": " + sprint("%r")); | |
| 517 | + | |
| 518 | + bytecode := array [int dir.length] of byte; | |
| 519 | + if(sys->read(fd, bytecode, int dir.length) != int dir.length) | |
| 520 | + fatal("ClassLoader: read " + name + ": " + sprint("%r")); | |
| 521 | + | |
| 522 | + byte2Class(bytecode); | |
| 523 | + | |
| 524 | + fd = nil; | |
| 525 | + bytecode = nil; | |
| 526 | +} | |
| 527 | + | |
| 528 | +# | |
| 529 | +# Print access flag mnemonics. | |
| 530 | +# | |
| 531 | + | |
| 532 | +accessflags(flags: int, isclass: int) | |
| 533 | +{ | |
| 534 | + if(flags == 0) | |
| 535 | + return; | |
| 536 | + bout.putc('\t'); | |
| 537 | + if(flags & ACC_PUBLIC) | |
| 538 | + bout.puts("|public"); | |
| 539 | + if(flags & ACC_PRIVATE) | |
| 540 | + bout.puts("|private"); | |
| 541 | + if(flags & ACC_PROTECTED) | |
| 542 | + bout.puts("|protected"); | |
| 543 | + if(flags & ACC_STATIC) | |
| 544 | + bout.puts("|static"); | |
| 545 | + if(flags & ACC_FINAL) | |
| 546 | + bout.puts("|final"); | |
| 547 | + if(flags & ACC_SUPER) { # ACC_SYNCHRONIZED == ACC_SUPER | |
| 548 | + if(isclass) | |
| 549 | + bout.puts("|super"); | |
| 550 | + else | |
| 551 | + bout.puts("|synchronized"); | |
| 552 | + } | |
| 553 | + if(flags & ACC_VOLATILE) | |
| 554 | + bout.puts("|volatile"); | |
| 555 | + if(flags & ACC_TRANSIENT) | |
| 556 | + bout.puts("|transient"); | |
| 557 | + if(flags & ACC_NATIVE) | |
| 558 | + bout.puts("|native"); | |
| 559 | + if(flags & ACC_INTERFACE) | |
| 560 | + bout.puts("|interface"); | |
| 561 | + if(flags & ACC_ABSTRACT) | |
| 562 | + bout.puts("|abstract"); | |
| 563 | + bout.putc('|'); | |
| 564 | +} | |
| 565 | + | |
| 566 | +# | |
| 567 | +# Print out the constant pool (-c option). | |
| 568 | +# | |
| 569 | + | |
| 570 | +dumpcpool() | |
| 571 | +{ | |
| 572 | + i, n: int; | |
| 573 | + fp: ref Field; | |
| 574 | + mp: ref Method; | |
| 575 | + | |
| 576 | + bout.puts("# -- Constant Pool Start --\n"); | |
| 577 | + bout.puts("# minor: " + string class.min + "\n"); | |
| 578 | + bout.puts("# major: " + string class.maj + "\n"); | |
| 579 | + | |
| 580 | + bout.puts("# constant pool count: " + string class.cp_count + "\n"); | |
| 581 | + | |
| 582 | + for(i = 1; i < class.cp_count; i++) { | |
| 583 | + bout.puts("# " + string i + " "); | |
| 584 | + pick cp := class.cps[i] { | |
| 585 | + Ptdouble => | |
| 586 | + if(int class.cts[i] == CON_Float) | |
| 587 | + bout.puts("Float " + string cp.tdouble + "\n"); | |
| 588 | + else { | |
| 589 | + bout.puts("Double " + string cp.tdouble + "\n"); | |
| 590 | + i++; | |
| 591 | + } | |
| 592 | + Ptvlong => | |
| 593 | + bout.puts("Long " + string cp.tvlong + "\n"); | |
| 594 | + i++; | |
| 595 | + Ptint => | |
| 596 | + bout.puts("Int " + string cp.tint + "\n"); | |
| 597 | + Pstring_index => | |
| 598 | + bout.puts("String " + string cp.string_index); | |
| 599 | + bout.puts("\t\""); | |
| 600 | + pstring(STRING(cp.string_index)); | |
| 601 | + bout.puts("\"\n"); | |
| 602 | + Pci => | |
| 603 | + bout.puts("Class " + string cp.ci.name_index); | |
| 604 | + bout.puts("\t\"" + STRING(cp.ci.name_index) + "\"\n"); | |
| 605 | + Pfmiref => | |
| 606 | + case int class.cts[i] { | |
| 607 | + CON_Fieldref => | |
| 608 | + bout.puts("Field"); | |
| 609 | + CON_Methodref => | |
| 610 | + bout.puts("Method"); | |
| 611 | + CON_InterfaceMref => | |
| 612 | + bout.puts("InterfaceMethod"); | |
| 613 | + } | |
| 614 | + bout.puts(" Ref " + string cp.fmiref.class_index + " " | |
| 615 | + + string cp.fmiref.name_type_index + "\n"); | |
| 616 | + Pnat => | |
| 617 | + bout.puts("N&T " + string cp.nat.name_index + " " | |
| 618 | + + string cp.nat.sig_index); | |
| 619 | + bout.puts("\t\"" + STRING(cp.nat.name_index) + "\", \"" | |
| 620 | + + STRING(cp.nat.sig_index) + "\"\n"); | |
| 621 | + Putf8 => | |
| 622 | + bout.puts("utf8 \""); | |
| 623 | + pstring(cp.utf8.utf8); | |
| 624 | + bout.puts("\"\n"); | |
| 625 | + # since 49.0 | |
| 626 | + Pmethodhandle => | |
| 627 | + bout.puts("niy\n"); | |
| 628 | + Pmethodtype => | |
| 629 | + bout.puts("niy\n"); | |
| 630 | + Pinvokedyn => | |
| 631 | + bout.puts("niy\n"); | |
| 632 | + * => | |
| 633 | + badpick("dumpcpool"); | |
| 634 | + } | |
| 635 | + } | |
| 636 | + | |
| 637 | + bout.puts("# access flags: " + string class.access_flags); | |
| 638 | + accessflags(class.access_flags, 1); | |
| 639 | + bout.putc('\n'); | |
| 640 | + | |
| 641 | + bout.puts("# this_class: " + string class.this_class + "\t\"" | |
| 642 | + + THISCLASS + "\"\n"); | |
| 643 | + bout.puts("# super_class: " + string class.super_class); | |
| 644 | + if(SUPERCLASS != nil) | |
| 645 | + bout.puts("\t\"" + SUPERCLASS + "\""); | |
| 646 | + bout.putc('\n'); | |
| 647 | + | |
| 648 | + bout.puts("# interfaces: " + string class.interfaces_count + "\n"); | |
| 649 | + for(i = 0; i < class.interfaces_count; i++) { | |
| 650 | + bout.puts("#\t" + CLASSNAME(class.interfaces[i]) + "\n"); | |
| 651 | + } | |
| 652 | + | |
| 653 | + bout.puts("# fields: " + string class.fields_count + "\n"); | |
| 654 | + for(i = 0; i < class.fields_count; i++) { | |
| 655 | + fp = class.fields[i]; | |
| 656 | + bout.puts("#\t" + STRING(fp.name_index) | |
| 657 | + + ": " + STRING(fp.sig_index)); | |
| 658 | + accessflags(fp.access_flags, 0); | |
| 659 | + bout.putc('\n'); | |
| 660 | + n = CVattrindex(fp); | |
| 661 | + if(n == 0) | |
| 662 | + continue; | |
| 663 | + bout.puts("#\t\tConstantValue: "); | |
| 664 | + pick cp := class.cps[n] { | |
| 665 | + Ptdouble => | |
| 666 | + if(int class.cts[n] == CON_Float) | |
| 667 | + bout.puts("Float " + string cp.tdouble + "\n"); | |
| 668 | + else # CON_Double | |
| 669 | + bout.puts("Double " + string cp.tdouble + "\n"); | |
| 670 | + Ptvlong => | |
| 671 | + bout.puts("Long " + string cp.tvlong + "\n"); | |
| 672 | + Ptint => | |
| 673 | + bout.puts("Int " + string cp.tint + "\n"); | |
| 674 | + Pstring_index => | |
| 675 | + bout.puts("String \"" + STRING(cp.string_index) + "\"\n"); | |
| 676 | + } | |
| 677 | + } | |
| 678 | + | |
| 679 | + bout.puts("# methods: " + string class.methods_count + "\n"); | |
| 680 | + for(i = 0; i < class.methods_count; i++) { | |
| 681 | + mp = class.methods[i]; | |
| 682 | + bout.puts("# " + string i + " Method " + string mp.name_index | |
| 683 | + + " sig " + string mp.sig_index); | |
| 684 | + bout.puts("\t" + STRING(mp.name_index) + STRING(mp.sig_index)); | |
| 685 | + accessflags(mp.access_flags, 0); | |
| 686 | + bout.putc('\n'); | |
| 687 | + } | |
| 688 | + | |
| 689 | + bout.puts("# class attribute ignored\n"); | |
| 690 | + bout.puts("# -- Constant Pool End --\n"); | |
| 691 | +} | |
| @@ -0,0 +1,367 @@ | ||
| 1 | +# | |
| 2 | +# Manage load-time resolution information. | |
| 3 | +# | |
| 4 | + | |
| 5 | +LTHash: adt { | |
| 6 | + cr: ref Creloc; | |
| 7 | + next: cyclic ref LTHash; | |
| 8 | +}; | |
| 9 | + | |
| 10 | +doclinitinits: int; | |
| 11 | +lttbl := array [Hashsize] of ref LTHash; # hash table of ref'd classes | |
| 12 | +thisclass: ref Creloc; # class under translation | |
| 13 | +nltclasses: int; # no. of classes referenced | |
| 14 | + | |
| 15 | +# | |
| 16 | +# Allocate a Creloc structure. | |
| 17 | +# | |
| 18 | + | |
| 19 | +newCreloc(s: string): ref Creloc | |
| 20 | +{ | |
| 21 | + nltclasses += 1; | |
| 22 | + return ref Creloc(s, nil, nil, 0); | |
| 23 | +} | |
| 24 | + | |
| 25 | +ltappend(cr: ref Creloc, fr: ref Freloc) | |
| 26 | +{ | |
| 27 | + if(cr.fr == nil) | |
| 28 | + cr.fr = fr; | |
| 29 | + else | |
| 30 | + cr.tail.next = fr; | |
| 31 | + cr.tail = fr; | |
| 32 | +} | |
| 33 | + | |
| 34 | +ltprepend(cr: ref Creloc, fr: ref Freloc) | |
| 35 | +{ | |
| 36 | + if(cr.fr == nil) | |
| 37 | + cr.tail = fr; | |
| 38 | + fr.next = cr.fr; | |
| 39 | + cr.fr = fr; | |
| 40 | +} | |
| 41 | + | |
| 42 | +# | |
| 43 | +# Add Freloc entry. | |
| 44 | +# | |
| 45 | + | |
| 46 | +addFreloc(cr: ref Creloc, field: string, sig: string, flags: int): ref Freloc | |
| 47 | +{ | |
| 48 | + fr: ref Freloc; | |
| 49 | + | |
| 50 | + fr = ref Freloc(field, sig, flags, nil, nil); | |
| 51 | + fr.ipatch = ref Ipatch(0, 0, nil, nil); | |
| 52 | + if(field[0] == '@') # these must go first in the list ! | |
| 53 | + ltprepend(cr, fr); | |
| 54 | + else | |
| 55 | + ltappend(cr, fr); | |
| 56 | + cr.n += 1; | |
| 57 | + return fr; | |
| 58 | +} | |
| 59 | + | |
| 60 | +# | |
| 61 | +# Add Creloc entry for classname. | |
| 62 | +# | |
| 63 | + | |
| 64 | +addCreloc(classname: string): ref Creloc | |
| 65 | +{ | |
| 66 | + h: int; | |
| 67 | + he: ref LTHash; | |
| 68 | + | |
| 69 | + h = hashval(classname); | |
| 70 | + he = ref LTHash(newCreloc(classname), lttbl[h]); | |
| 71 | + lttbl[h] = he; | |
| 72 | + return he.cr; | |
| 73 | +} | |
| 74 | + | |
| 75 | +# | |
| 76 | +# Get Creloc entry for classname. | |
| 77 | +# | |
| 78 | + | |
| 79 | +getCreloc(classname: string): ref Creloc | |
| 80 | +{ | |
| 81 | + he: ref LTHash; | |
| 82 | + | |
| 83 | + for(he = lttbl[hashval(classname)]; he != nil; he = he.next) { | |
| 84 | + if(classname == he.cr.classname) | |
| 85 | + return he.cr; | |
| 86 | + } | |
| 87 | + return addCreloc(classname); | |
| 88 | +} | |
| 89 | + | |
| 90 | +# | |
| 91 | +# Get Freloc entry. Ignore signature if nil. | |
| 92 | +# | |
| 93 | + | |
| 94 | +getFreloc(cr: ref Creloc, field: string, sig: string, flags: int): ref Freloc | |
| 95 | +{ | |
| 96 | + fr: ref Freloc; | |
| 97 | + lowflags: int; | |
| 98 | + | |
| 99 | + lowflags = 0; | |
| 100 | + for(fr = cr.fr; fr != nil; fr = fr.next) { | |
| 101 | + if(fr.field == field && (sig == nil || fr.sig == sig)) { | |
| 102 | + if(fr.flags >> 16 == 0) { | |
| 103 | + fr.flags |= flags; | |
| 104 | + return fr; | |
| 105 | + } else if(fr.flags >> 16 == flags >> 16) | |
| 106 | + return fr; | |
| 107 | + lowflags = fr.flags & 16rffff; | |
| 108 | + } | |
| 109 | + } | |
| 110 | + | |
| 111 | + return addFreloc(cr, field, sig, flags|lowflags); | |
| 112 | +} | |
| 113 | + | |
| 114 | +# | |
| 115 | +# Seed Creloc for this class. | |
| 116 | +# | |
| 117 | + | |
| 118 | +thisCreloc() | |
| 119 | +{ | |
| 120 | + i, haveclinit: int; | |
| 121 | + fp: ref Field; | |
| 122 | + mp: ref Method; | |
| 123 | + | |
| 124 | + thisclass = addCreloc(THISCLASS); | |
| 125 | + | |
| 126 | + # class access_flags here for the benefit of interfaces | |
| 127 | + addFreloc(thisclass, RCLASS, nil, class.access_flags|compileflag); | |
| 128 | + | |
| 129 | + # data | |
| 130 | + for(i = 0; i < class.fields_count; i++) { | |
| 131 | + fp = class.fields[i]; | |
| 132 | + addFreloc(thisclass, STRING(fp.name_index), | |
| 133 | + STRING(fp.sig_index), fp.access_flags); | |
| 134 | + if((fp.access_flags & ACC_STATIC) && CVattrindex(fp)) | |
| 135 | + doclinitinits = 1; | |
| 136 | + } | |
| 137 | + | |
| 138 | + # methods | |
| 139 | + haveclinit = 0; | |
| 140 | + for(i = 0; i < class.methods_count; i++) { | |
| 141 | + mp = class.methods[i]; | |
| 142 | + addFreloc(thisclass, STRING(mp.name_index), | |
| 143 | + STRING(mp.sig_index), mp.access_flags); | |
| 144 | + if(STRING(mp.name_index) == "<clinit>") | |
| 145 | + haveclinit = 1; | |
| 146 | + } | |
| 147 | + if(doclinitinits && haveclinit == 0) | |
| 148 | + addFreloc(thisclass, "<clinit>", "()V", ACC_STATIC); | |
| 149 | + if((class.access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) == 0) | |
| 150 | + addFreloc(thisclass, "<clone>", "()V", ACC_STATIC); | |
| 151 | +} | |
| 152 | + | |
| 153 | +# | |
| 154 | +# Add instruction patch information to Freloc fr. | |
| 155 | +# | |
| 156 | + | |
| 157 | +LTIpatch(fr: ref Freloc, i: ref Inst, operand: int, patchkind: int) | |
| 158 | +{ | |
| 159 | + addIpatch(fr.ipatch, i, operand, patchkind, !SAVEINST); | |
| 160 | +} | |
| 161 | + | |
| 162 | +# | |
| 163 | +# Size of Module Data space taken by load-time relocation information. | |
| 164 | +# Includes nil terminator. | |
| 165 | +# | |
| 166 | + | |
| 167 | +LTrelocsize(): int | |
| 168 | +{ | |
| 169 | + return align((9 + 2*(nltclasses-1)) * IBY2WD, 32); | |
| 170 | +} | |
| 171 | + | |
| 172 | +# | |
| 173 | +# Fix type descriptor for relocation information. | |
| 174 | +# | |
| 175 | + | |
| 176 | +Freloctid, Ifacetid: int; | |
| 177 | + | |
| 178 | +LTrelocdesc(map: array of byte) | |
| 179 | +{ | |
| 180 | + i, bit: int; | |
| 181 | + | |
| 182 | + Freloctid = descid(4*IBY2WD, 1, array [1] of { byte 16rd0 }); | |
| 183 | + setIpatchtid(); # force type id for patch info | |
| 184 | + Ifacetid = descid(IBY2WD, 1, array [1] of { byte 16r80 }); | |
| 185 | + | |
| 186 | + setbit(map, 8); # Class name | |
| 187 | + setbit(map, 12); # Superclass name | |
| 188 | + setbit(map, 16); # Interfaces | |
| 189 | + setbit(map, 20); # Class relocation | |
| 190 | + setbit(map, 28); # Data relocation | |
| 191 | + # | |
| 192 | + # even i: Class name | |
| 193 | + # odd i: Class relocation | |
| 194 | + # | |
| 195 | + bit = 32; | |
| 196 | + for(i = 0; i < (nltclasses-1)*2; i++) { | |
| 197 | + setbit(map, bit); | |
| 198 | + bit += 4; | |
| 199 | + } | |
| 200 | + setbit(map, bit); # nil | |
| 201 | +} | |
| 202 | + | |
| 203 | +# | |
| 204 | +# Write Freloc array to .s file. | |
| 205 | +# | |
| 206 | + | |
| 207 | +asmFreloc(off: int, cr: ref Creloc) | |
| 208 | +{ | |
| 209 | + fr: ref Freloc; | |
| 210 | + reloff: int; # relative offset for array elements | |
| 211 | + | |
| 212 | + reloff = 0; | |
| 213 | + asmarray(off, Freloctid, cr.n, reloff); # cr.n != 0, always | |
| 214 | + for(fr = cr.fr; fr != nil; fr = fr.next) { | |
| 215 | + asmstring(reloff, fr.field); | |
| 216 | + reloff += IBY2WD; | |
| 217 | + if(fr.sig != nil) | |
| 218 | + asmstring(reloff, fr.sig); | |
| 219 | + reloff += IBY2WD; | |
| 220 | + asmint(reloff, fr.flags); | |
| 221 | + reloff += IBY2WD; | |
| 222 | + asmIpatch(reloff, fr.ipatch); | |
| 223 | + reloff += IBY2WD; | |
| 224 | + } | |
| 225 | + bout.puts("\tapop\n"); | |
| 226 | +} | |
| 227 | + | |
| 228 | +# | |
| 229 | +# Write Creloc's (except for this_class) to .s file. | |
| 230 | +# | |
| 231 | + | |
| 232 | +asmCreloc(off: int): int | |
| 233 | +{ | |
| 234 | + he: ref LTHash; | |
| 235 | + i: int; | |
| 236 | + | |
| 237 | + for(i = 0; i < Hashsize; i++) { | |
| 238 | + for(he = lttbl[i]; he != nil; he = he.next) { | |
| 239 | + if(he.cr == thisclass) | |
| 240 | + continue; | |
| 241 | + asmstring(off, he.cr.classname); | |
| 242 | + off += IBY2WD; | |
| 243 | + asmFreloc(off, he.cr); | |
| 244 | + off += IBY2WD; | |
| 245 | + } | |
| 246 | + } | |
| 247 | + off += IBY2WD; # skip past nil | |
| 248 | + return off; | |
| 249 | +} | |
| 250 | + | |
| 251 | +JVNO: con '4'; | |
| 252 | +JMAGIC: con ('J'<<24)|('a'<<16)|('v'<<8)|'a'; | |
| 253 | +JVERSION: con ('S'<<24)|('u'<<16)|('x'<<8)|JVNO; | |
| 254 | + | |
| 255 | +# | |
| 256 | +# Write Creloc for this_class to .s file. | |
| 257 | +# | |
| 258 | + | |
| 259 | +asmthisCreloc(off: int): int | |
| 260 | +{ | |
| 261 | + i: int; | |
| 262 | + reloff: int; # relative offset for array elements | |
| 263 | + | |
| 264 | + asmint(off, JMAGIC); | |
| 265 | + off += IBY2WD; | |
| 266 | + asmint(off, JVERSION); | |
| 267 | + off += IBY2WD; | |
| 268 | + asmstring(off, THISCLASS); | |
| 269 | + off += IBY2WD; | |
| 270 | + if(SUPERCLASS != nil) # Object has no superclass | |
| 271 | + asmstring(off, SUPERCLASS); | |
| 272 | + off += IBY2WD; | |
| 273 | + if(class.interfaces_count > 0) { | |
| 274 | + reloff = 0; | |
| 275 | + asmarray(off, Ifacetid, class.interfaces_count, reloff); | |
| 276 | + for(i = 0; i < class.interfaces_count; i++) { | |
| 277 | + asmstring(reloff, CLASSNAME(class.interfaces[i])); | |
| 278 | + reloff += IBY2WD; | |
| 279 | + } | |
| 280 | + bout.puts("\tapop\n"); | |
| 281 | + } | |
| 282 | + off += IBY2WD; | |
| 283 | + asmFreloc(off, thisclass); | |
| 284 | + off += IBY2WD; | |
| 285 | + return off; | |
| 286 | +} | |
| 287 | + | |
| 288 | +# | |
| 289 | +# Write Freloc array to .dis file. | |
| 290 | +# | |
| 291 | + | |
| 292 | +disFreloc(off: int, cr: ref Creloc) | |
| 293 | +{ | |
| 294 | + fr: ref Freloc; | |
| 295 | + reloff: int; # relative offset for array elements | |
| 296 | + | |
| 297 | + reloff = 0; | |
| 298 | + disarray(off, Freloctid, cr.n); | |
| 299 | + for(fr = cr.fr; fr != nil; fr = fr.next) { | |
| 300 | + disstring(reloff, fr.field); | |
| 301 | + reloff += IBY2WD; | |
| 302 | + if(fr.sig != nil) | |
| 303 | + disstring(reloff, fr.sig); | |
| 304 | + reloff += IBY2WD; | |
| 305 | + disint(reloff, fr.flags); | |
| 306 | + reloff += IBY2WD; | |
| 307 | + disIpatch(reloff, fr.ipatch); | |
| 308 | + reloff += IBY2WD; | |
| 309 | + } | |
| 310 | + disapop(); | |
| 311 | +} | |
| 312 | + | |
| 313 | +# | |
| 314 | +# Write Creloc's (except for this_class) to .dis file. | |
| 315 | +# | |
| 316 | + | |
| 317 | +disCreloc(off: int): int | |
| 318 | +{ | |
| 319 | + he: ref LTHash; | |
| 320 | + i: int; | |
| 321 | + | |
| 322 | + for(i = 0; i < Hashsize; i++) { | |
| 323 | + for(he = lttbl[i]; he != nil; he = he.next) { | |
| 324 | + if(he.cr == thisclass) | |
| 325 | + continue; | |
| 326 | + disstring(off, he.cr.classname); | |
| 327 | + off += IBY2WD; | |
| 328 | + disFreloc(off, he.cr); | |
| 329 | + off += IBY2WD; | |
| 330 | + } | |
| 331 | + } | |
| 332 | + off += IBY2WD; # skip past nil | |
| 333 | + return off; | |
| 334 | +} | |
| 335 | + | |
| 336 | +# | |
| 337 | +# Write Creloc for this_class to .dis file. | |
| 338 | +# | |
| 339 | + | |
| 340 | +disthisCreloc(off: int): int | |
| 341 | +{ | |
| 342 | + i: int; | |
| 343 | + reloff: int; # relative offset for array elements | |
| 344 | + | |
| 345 | + disint(off, JMAGIC); | |
| 346 | + off += IBY2WD; | |
| 347 | + disint(off, JVERSION); | |
| 348 | + off += IBY2WD; | |
| 349 | + disstring(off, THISCLASS); | |
| 350 | + off += IBY2WD; | |
| 351 | + if(SUPERCLASS != nil) # Object has no superclass | |
| 352 | + disstring(off, SUPERCLASS); | |
| 353 | + off += IBY2WD; | |
| 354 | + if(class.interfaces_count > 0) { | |
| 355 | + reloff = 0; | |
| 356 | + disarray(off, Ifacetid, class.interfaces_count); | |
| 357 | + for(i = 0; i < class.interfaces_count; i++) { | |
| 358 | + disstring(reloff, CLASSNAME(class.interfaces[i])); | |
| 359 | + reloff += IBY2WD; | |
| 360 | + } | |
| 361 | + disapop(); | |
| 362 | + } | |
| 363 | + off += IBY2WD; | |
| 364 | + disFreloc(off, thisclass); | |
| 365 | + off += IBY2WD; | |
| 366 | + return off; | |
| 367 | +} | |
| @@ -0,0 +1,179 @@ | ||
| 1 | +bufio: Bufio; | |
| 2 | +math: Math; | |
| 3 | +sys: Sys; | |
| 4 | +str: String; | |
| 5 | + | |
| 6 | +Iobuf: import bufio; | |
| 7 | +fprint, print, sprint: import sys; | |
| 8 | + | |
| 9 | +gendis: int = 1; # generate .dis rather than .s (default) | |
| 10 | +fabort: int; # -f: cause broken thread on fatal error | |
| 11 | +emitcpool: int; # -p: emit constant pool (with -S only) | |
| 12 | +gensbl: int; # -g: generate .sbl file | |
| 13 | +compileflag: int; # -c (MUSTCOMPILE) & -C (DONTCOMPILE) | |
| 14 | +verbose: int; # -v: emit Java instructions (with -S only) | |
| 15 | +bout: ref Bufio->Iobuf; | |
| 16 | +ofile: string; | |
| 17 | + | |
| 18 | +usage() | |
| 19 | +{ | |
| 20 | + print("usage: j2d [-cgpvCS] [-o outfile] file.class\n"); | |
| 21 | + exit; | |
| 22 | +} | |
| 23 | + | |
| 24 | +# | |
| 25 | +# Translate .class file (in) into .s or .dis (out). | |
| 26 | +# | |
| 27 | + | |
| 28 | +translate(in: string, out: string) | |
| 29 | +{ | |
| 30 | + ClassLoader(in); | |
| 31 | + | |
| 32 | + bout = bufio->create(out, Bufio->OWRITE, 8r644); | |
| 33 | + if(bout == nil) | |
| 34 | + fatal("can't open " + out + ": " + sprint("%r")); | |
| 35 | + | |
| 36 | + if(emitcpool != 0) | |
| 37 | + dumpcpool(); | |
| 38 | + | |
| 39 | + thisCreloc(); | |
| 40 | + xlate(); | |
| 41 | + mpdesc(); | |
| 42 | + # Patch frame/call for invokespecial/invokestatic. | |
| 43 | + dofcpatch(); | |
| 44 | + # Patch instructions for run-time resolution. | |
| 45 | + doRTpatch(); | |
| 46 | + | |
| 47 | + if(gendis == 0) { # generate .s file | |
| 48 | + asminst(); | |
| 49 | + asmentry(); | |
| 50 | + asmdesc(); | |
| 51 | + asmvar(); | |
| 52 | + asmmod(); | |
| 53 | + asmlinks(); | |
| 54 | + } else | |
| 55 | + disout(); # generate .dis file | |
| 56 | + | |
| 57 | + if(gensbl) # generate .sbl file | |
| 58 | + sblout(out); | |
| 59 | + | |
| 60 | + bout.close(); | |
| 61 | +} | |
| 62 | + | |
| 63 | +MAXUNENCODED: con Sys->NAMEMAX - 7; | |
| 64 | +ENCODEDLEN: con 21; | |
| 65 | + | |
| 66 | +encoding := array [] of { | |
| 67 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | |
| 68 | + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | |
| 69 | + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', | |
| 70 | + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', | |
| 71 | + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', | |
| 72 | + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', | |
| 73 | + 'w', 'x', 'y', 'z', '0', '1', '2', '3', | |
| 74 | + '4', '5', '6', '7', '8', '9', '+', '-', | |
| 75 | +}; | |
| 76 | + | |
| 77 | +encodename(name: string): string | |
| 78 | +{ | |
| 79 | + d := array [Keyring->MD5dlen] of byte; | |
| 80 | + kr := load Keyring Keyring->PATH; | |
| 81 | + kr->md5(array of byte name, len name, d, nil); | |
| 82 | + e := array[ENCODEDLEN] of byte; | |
| 83 | + v := 0; | |
| 84 | + n := 0; | |
| 85 | + r := 0; | |
| 86 | + for(i := 0; i < ENCODEDLEN; i++) { | |
| 87 | + if(r < 6) { | |
| 88 | + v |= int d[n++] << r; | |
| 89 | + r += 8; | |
| 90 | + } | |
| 91 | + e[i] = byte encoding[v & 16r3F]; | |
| 92 | + v >>= 6; | |
| 93 | + r -= 6; | |
| 94 | + } | |
| 95 | + return string e; | |
| 96 | +} | |
| 97 | + | |
| 98 | +# | |
| 99 | +# Construct output filename. | |
| 100 | +# | |
| 101 | + | |
| 102 | +mkfileext(file: string, ext: string): string | |
| 103 | +{ | |
| 104 | + n := len file; | |
| 105 | + if(n <= 6 || file[n-6:] != ".class") | |
| 106 | + usage(); | |
| 107 | + else | |
| 108 | + n -= 6; | |
| 109 | + if(n > MAXUNENCODED) { | |
| 110 | + file = encodename(file); | |
| 111 | + n = ENCODEDLEN; | |
| 112 | + } | |
| 113 | + return file[:n] + ext; | |
| 114 | +} | |
| 115 | + | |
| 116 | +init(nil: ref Draw->Context, argv: list of string) | |
| 117 | +{ | |
| 118 | + ext, s: string; | |
| 119 | + | |
| 120 | + sys = load Sys Sys->PATH; | |
| 121 | + math = load Math Math->PATH; | |
| 122 | + bufio = load Bufio Bufio->PATH; | |
| 123 | + if(bufio == nil) | |
| 124 | + fatal("can't load " + Bufio->PATH + ": " + sprint("%r")); | |
| 125 | + str = load String String->PATH; | |
| 126 | + if(str == nil) | |
| 127 | + fatal("can't load " + String->PATH + ": " + sprint("%r")); | |
| 128 | + | |
| 129 | + arg := Arg.init(argv); | |
| 130 | + while(c := arg.opt()) { | |
| 131 | + case c { | |
| 132 | + 'C' => | |
| 133 | + compileflag |= _DONTCOMPILE; | |
| 134 | + 'S' => | |
| 135 | + gendis = 0; | |
| 136 | + 'c' => | |
| 137 | + compileflag |= _MUSTCOMPILE; | |
| 138 | + 'g' => | |
| 139 | + gensbl = 1; | |
| 140 | + 'f' => | |
| 141 | + fabort = 1; | |
| 142 | + 'p' => | |
| 143 | + emitcpool = 1; | |
| 144 | + 'o' => | |
| 145 | + ofile = arg.arg(); | |
| 146 | + 'v' => | |
| 147 | + verbose = 1; | |
| 148 | + * => | |
| 149 | + usage(); | |
| 150 | + } | |
| 151 | + } | |
| 152 | + argv = arg.argv; | |
| 153 | + arg = nil; | |
| 154 | + | |
| 155 | + if(len argv != 1) | |
| 156 | + usage(); | |
| 157 | + ifile := hd argv; | |
| 158 | + if(compileflag == (_MUSTCOMPILE|_DONTCOMPILE)) { | |
| 159 | + print("j2d: warning: -c and -C are mutually exclusive, ignoring\n"); | |
| 160 | + compileflag = 0; | |
| 161 | + } | |
| 162 | + if((verbose != 0 || emitcpool != 0) && gendis != 0) { | |
| 163 | + print("j2d: warning: -p/-v only allowed with -S, ignoring\n"); | |
| 164 | + emitcpool = 0; | |
| 165 | + verbose = 0; | |
| 166 | + } | |
| 167 | + if(ofile != nil) | |
| 168 | + translate(ifile, ofile); | |
| 169 | + else { | |
| 170 | + if(gendis == 0) | |
| 171 | + ext = ".s"; | |
| 172 | + else | |
| 173 | + ext = ".dis"; | |
| 174 | + (nil, s) = str->splitr(ifile, "/"); | |
| 175 | + ofile = mkfileext(s, ext); | |
| 176 | + translate(ifile, ofile); | |
| 177 | + } | |
| 178 | + reset(); | |
| 179 | +} | |
| @@ -0,0 +1,461 @@ | ||
| 1 | +# | |
| 2 | +# Manage module Data Section. | |
| 3 | +# | |
| 4 | + | |
| 5 | +MP_INT, | |
| 6 | +MP_LONG, | |
| 7 | +MP_REAL, | |
| 8 | +MP_STRING, | |
| 9 | +MP_CASE, | |
| 10 | +MP_GOTO: con iota; | |
| 11 | + | |
| 12 | +Datum_v: adt { | |
| 13 | + ival: big; # MP_[INT|LONG] | |
| 14 | + rval: real; # MP_REAL | |
| 15 | + next: cyclic ref Datum.Pv; | |
| 16 | +}; | |
| 17 | + | |
| 18 | +Datum_c: adt { # MP_CASE | |
| 19 | + n: int; # number of cases in jmptbl | |
| 20 | + jmptbl: array of int; # 3 words per case, plus default | |
| 21 | +}; | |
| 22 | + | |
| 23 | +Datum_g: adt { # MP_GOTO (for finally blocks) | |
| 24 | + n: int; # number of entries in gototbl | |
| 25 | + gototbl:array of int; | |
| 26 | +}; | |
| 27 | + | |
| 28 | +Datum: adt { | |
| 29 | + kind: byte; # MP_INT, etc. | |
| 30 | + offset: int; # byte offset in Data Section | |
| 31 | + next: cyclic ref Datum; | |
| 32 | + pick { | |
| 33 | + Pv => | |
| 34 | + v: ref Datum_v; # MP_[INT|LONG|REAL] | |
| 35 | + Ps => | |
| 36 | + s: string; # MP_STRING | |
| 37 | + Pc => | |
| 38 | + c: ref Datum_c; # MP_CASE | |
| 39 | + Pg => | |
| 40 | + g: ref Datum_g; # MP_GOTO | |
| 41 | + } | |
| 42 | +}; | |
| 43 | + | |
| 44 | +Hentry: adt { | |
| 45 | + md: ref Datum.Ps; | |
| 46 | + next: cyclic ref Hentry; | |
| 47 | +}; | |
| 48 | + | |
| 49 | +htable := array [Hashsize] of ref Hentry; | |
| 50 | +mpoff: int; | |
| 51 | + | |
| 52 | +mplist: ref Datum; | |
| 53 | +mptail: ref Datum; | |
| 54 | +llist: ref Datum.Pv; | |
| 55 | +rlist: ref Datum.Pv; | |
| 56 | + | |
| 57 | +# | |
| 58 | +# Append a module datum to mplist. | |
| 59 | +# | |
| 60 | + | |
| 61 | +append(md: ref Datum) | |
| 62 | +{ | |
| 63 | + if(mplist == nil) | |
| 64 | + mplist = md; | |
| 65 | + else | |
| 66 | + mptail.next = md; | |
| 67 | + mptail = md; | |
| 68 | +} | |
| 69 | + | |
| 70 | +# | |
| 71 | +# Add a 'byte', int 'word', or 'long'. | |
| 72 | +# | |
| 73 | + | |
| 74 | +mpintegral(kind: int, ival: big): int | |
| 75 | +{ | |
| 76 | + size: int; | |
| 77 | + | |
| 78 | + md := ref Datum.Pv; | |
| 79 | + md.v = ref Datum_v; | |
| 80 | + md.v.ival = ival; | |
| 81 | + case kind { | |
| 82 | + MP_INT => | |
| 83 | + md.kind = byte MP_INT; | |
| 84 | + size = IBY2WD; | |
| 85 | + mpoff = align(mpoff, IBY2WD); | |
| 86 | + MP_LONG => | |
| 87 | + md.kind = byte MP_LONG; | |
| 88 | + size = IBY2LG; | |
| 89 | + mpoff = align(mpoff, IBY2LG); | |
| 90 | + md.v.next = llist; | |
| 91 | + llist = md; | |
| 92 | + } | |
| 93 | + md.offset = mpoff; | |
| 94 | + mpoff += size; | |
| 95 | + append(md); | |
| 96 | + return md.offset; | |
| 97 | +} | |
| 98 | + | |
| 99 | +# | |
| 100 | +# Add a 'word' (int). | |
| 101 | +# | |
| 102 | + | |
| 103 | +mpint(ival: int): int | |
| 104 | +{ | |
| 105 | + return mpintegral(MP_INT, big ival); | |
| 106 | +} | |
| 107 | + | |
| 108 | +# | |
| 109 | +# Add a 'long'. | |
| 110 | +# | |
| 111 | + | |
| 112 | +mplong(lval: big): int | |
| 113 | +{ | |
| 114 | + md: ref Datum.Pv; | |
| 115 | + | |
| 116 | + for(md = llist; md != nil; md = md.v.next) { | |
| 117 | + if(lval == md.v.ival) | |
| 118 | + return md.offset; | |
| 119 | + } | |
| 120 | + return mpintegral(MP_LONG, lval); | |
| 121 | +} | |
| 122 | + | |
| 123 | +# | |
| 124 | +# Add a 'real'. | |
| 125 | +# | |
| 126 | + | |
| 127 | +mpreal(rval: real): int | |
| 128 | +{ | |
| 129 | + md: ref Datum.Pv; | |
| 130 | + | |
| 131 | + for(md = rlist; md != nil; md = md.v.next) { | |
| 132 | + # distinguish 0.0 from -0.0 | |
| 133 | + if(rval == md.v.rval | |
| 134 | + && math->realbits64(rval) == math->realbits64(md.v.rval)) | |
| 135 | + return md.offset; | |
| 136 | + } | |
| 137 | + md = ref Datum.Pv; | |
| 138 | + md.kind = byte MP_REAL; | |
| 139 | + md.v = ref Datum_v; | |
| 140 | + md.v.rval = rval; | |
| 141 | + md.v.next = rlist; | |
| 142 | + rlist = md; | |
| 143 | + mpoff = align(mpoff, IBY2FT); | |
| 144 | + md.offset = mpoff; | |
| 145 | + mpoff += IBY2FT; | |
| 146 | + append(md); | |
| 147 | + return md.offset; | |
| 148 | +} | |
| 149 | + | |
| 150 | +# | |
| 151 | +# Add a 'case' jump table. | |
| 152 | +# | |
| 153 | + | |
| 154 | +mpcase(sz: int, jt: array of int): int | |
| 155 | +{ | |
| 156 | + md := ref Datum.Pc; | |
| 157 | + md.kind = byte MP_CASE; | |
| 158 | + mpoff = align(mpoff, IBY2WD); | |
| 159 | + md.offset = mpoff; | |
| 160 | + mpoff += (sz*3+2)*IBY2WD; | |
| 161 | + md.c = ref Datum_c; | |
| 162 | + md.c.n = sz; | |
| 163 | + md.c.jmptbl = jt; | |
| 164 | + append(md); | |
| 165 | + return md.offset; | |
| 166 | +} | |
| 167 | + | |
| 168 | +# | |
| 169 | +# Add a 'goto' jump table; used for implementing finally blocks. | |
| 170 | +# | |
| 171 | + | |
| 172 | +mpgoto(n: int, gototbl: array of int): int | |
| 173 | +{ | |
| 174 | + md := ref Datum.Pg; | |
| 175 | + md.kind = byte MP_GOTO; | |
| 176 | + mpoff = align(mpoff, IBY2WD); | |
| 177 | + md.offset = mpoff; | |
| 178 | + mpoff += (n+2)*IBY2WD; | |
| 179 | + md.g = ref Datum_g; | |
| 180 | + md.g.n = n; | |
| 181 | + md.g.gototbl = gototbl; | |
| 182 | + append(md); | |
| 183 | + return md.offset+IBY2WD; | |
| 184 | +} | |
| 185 | + | |
| 186 | +# | |
| 187 | +# Hash table lookup function. | |
| 188 | +# | |
| 189 | + | |
| 190 | +htlook(s: string): ref Hentry | |
| 191 | +{ | |
| 192 | + he: ref Hentry; | |
| 193 | + | |
| 194 | + for(he = htable[hashval(s)]; he != nil; he = he.next) | |
| 195 | + if(s == he.md.s) | |
| 196 | + return he; | |
| 197 | + return nil; | |
| 198 | +} | |
| 199 | + | |
| 200 | +# | |
| 201 | +# Hash table enter function. | |
| 202 | +# | |
| 203 | + | |
| 204 | +htenter(md: ref Datum.Ps): ref Hentry | |
| 205 | +{ | |
| 206 | + h: int; | |
| 207 | + he: ref Hentry; | |
| 208 | + | |
| 209 | + h = hashval(md.s); | |
| 210 | + he = ref Hentry(md, htable[h]); | |
| 211 | + htable[h] = he; | |
| 212 | + return he; | |
| 213 | +} | |
| 214 | + | |
| 215 | +# | |
| 216 | +# Add a 'string'. | |
| 217 | +# | |
| 218 | + | |
| 219 | +mpstring(s: string): int | |
| 220 | +{ | |
| 221 | + he: ref Hentry; | |
| 222 | + md: ref Datum.Ps; | |
| 223 | + | |
| 224 | + if((he = htlook(s)) != nil) | |
| 225 | + return he.md.offset; | |
| 226 | + md = ref Datum.Ps; | |
| 227 | + md.kind = byte MP_STRING; | |
| 228 | + md.s = s; | |
| 229 | + mpoff = align(mpoff, IBY2WD); | |
| 230 | + md.offset = mpoff; | |
| 231 | + mpoff += IBY2WD; | |
| 232 | + append(md); | |
| 233 | + htenter(md); | |
| 234 | + return md.offset; | |
| 235 | +} | |
| 236 | + | |
| 237 | +# | |
| 238 | +# Calculate the type descriptor for the Module Data section. | |
| 239 | +# | |
| 240 | + | |
| 241 | +mpdesc() | |
| 242 | +{ | |
| 243 | + md: ref Datum; | |
| 244 | + ltsize, rtsize, ln, mdsize: int; | |
| 245 | + map: array of byte; | |
| 246 | + | |
| 247 | + ltsize = LTrelocsize(); # link-time reloc data | |
| 248 | + mpoff = align(mpoff, IBY2WD); | |
| 249 | + rtsize = RTrelocsize(); # run-time reloc data | |
| 250 | + mdsize = ltsize + mpoff + rtsize; | |
| 251 | + ln = mdsize / (8*IBY2WD) + (mdsize % (8*IBY2WD) != 0); | |
| 252 | + map = array [ln] of { * => byte 0 }; | |
| 253 | + LTrelocdesc(map); | |
| 254 | + for(md = mplist; md != nil; md = md.next) { | |
| 255 | + if(int md.kind == MP_STRING) | |
| 256 | + setbit(map, ltsize + md.offset); | |
| 257 | + } | |
| 258 | + RTrelocdesc(map, ltsize + mpoff); | |
| 259 | + RTfixoff(ltsize + mpoff); | |
| 260 | + mpdescid(mdsize, ln, map); | |
| 261 | +} | |
| 262 | + | |
| 263 | +asmprefix(off: int, s: string) | |
| 264 | +{ | |
| 265 | + bout.puts("\t" + s + "\t@mp+" + string off + ","); | |
| 266 | +} | |
| 267 | + | |
| 268 | +# | |
| 269 | +# Begin an array initializer. | |
| 270 | +# | |
| 271 | + | |
| 272 | +asmarray(off: int, tid: int, nelt: int, reloff: int) | |
| 273 | +{ | |
| 274 | + asmprefix(off, "array"); | |
| 275 | + bout.puts("$" + string tid + "," + string nelt + "\n"); | |
| 276 | + asmprefix(off, "indir"); | |
| 277 | + bout.puts(string reloff + "\n"); | |
| 278 | +} | |
| 279 | + | |
| 280 | +asmint(off: int, val: int) | |
| 281 | +{ | |
| 282 | + asmprefix(off, "word"); | |
| 283 | + bout.puts(string val + "\n"); | |
| 284 | +} | |
| 285 | + | |
| 286 | +asmlong(off: int, val: big) | |
| 287 | +{ | |
| 288 | + asmprefix(off, "long"); | |
| 289 | + bout.puts(string val + "\n"); | |
| 290 | +} | |
| 291 | + | |
| 292 | +asmreal(off: int, val: real) | |
| 293 | +{ | |
| 294 | + asmprefix(off, "real"); | |
| 295 | + bout.puts(string val + "\n"); | |
| 296 | +} | |
| 297 | + | |
| 298 | +asmstring(off: int, s: string) | |
| 299 | +{ | |
| 300 | + asmprefix(off, "string"); | |
| 301 | + bout.putc('"'); | |
| 302 | + pstring(s); | |
| 303 | + bout.puts("\"\n"); | |
| 304 | +} | |
| 305 | + | |
| 306 | +asmcase(off: int, md: ref Datum.Pc) | |
| 307 | +{ | |
| 308 | + i: int; | |
| 309 | + | |
| 310 | + asmprefix(off, "word"); | |
| 311 | + bout.puts(string md.c.n); | |
| 312 | + for(i = 0; i < md.c.n; i++) { | |
| 313 | + bout.puts("," + string md.c.jmptbl[i*3]); | |
| 314 | + bout.puts("," + string md.c.jmptbl[i*3+1]); | |
| 315 | + bout.puts("," + string md.c.jmptbl[i*3+2]); | |
| 316 | + } | |
| 317 | + bout.puts("," + string md.c.jmptbl[md.c.n*3] + "\n"); | |
| 318 | +} | |
| 319 | + | |
| 320 | +asmgoto(off: int, md: ref Datum.Pg) | |
| 321 | +{ | |
| 322 | + i: int; | |
| 323 | + | |
| 324 | + asmprefix(off, "word"); | |
| 325 | + bout.puts(string md.g.n); | |
| 326 | + for(i = 0; i < md.g.n; i++) | |
| 327 | + bout.puts("," + string md.g.gototbl[i]); | |
| 328 | + bout.putc('\n'); | |
| 329 | +} | |
| 330 | + | |
| 331 | +# | |
| 332 | +# Write Module Data to .s file. | |
| 333 | +# | |
| 334 | + | |
| 335 | +asmvar() | |
| 336 | +{ | |
| 337 | + md: ref Datum; | |
| 338 | + ltsize, rtsize, off: int; | |
| 339 | + | |
| 340 | + ltsize = LTrelocsize(); | |
| 341 | + rtsize = RTrelocsize(); | |
| 342 | + bout.puts("\tvar\t@mp," + string(ltsize + mpoff + rtsize) + "\n"); | |
| 343 | + off = asmthisCreloc(0); | |
| 344 | + asmint(off, mpoff + rtsize); | |
| 345 | + off += IBY2WD; | |
| 346 | + asmDreloc(off); | |
| 347 | + off += IBY2WD; | |
| 348 | + off = asmCreloc(off); | |
| 349 | + off = align(off, 32); | |
| 350 | + if(off != ltsize) | |
| 351 | + fatal("asmvar: off " + string off + ", " + string ltsize); | |
| 352 | + | |
| 353 | + for(md = mplist; md != nil; md = md.next) { | |
| 354 | + off = ltsize + md.offset; | |
| 355 | + pick mdp := md { | |
| 356 | + Pv => | |
| 357 | + case int mdp.kind { | |
| 358 | + MP_INT => | |
| 359 | + asmint(off, int mdp.v.ival); | |
| 360 | + MP_LONG => | |
| 361 | + asmlong(off, mdp.v.ival); | |
| 362 | + MP_REAL => | |
| 363 | + asmreal(off, mdp.v.rval); | |
| 364 | + } | |
| 365 | + Ps => | |
| 366 | + asmstring(off, mdp.s); | |
| 367 | + Pc => | |
| 368 | + asmcase(off, mdp); | |
| 369 | + Pg => | |
| 370 | + asmgoto(off, mdp); | |
| 371 | + * => | |
| 372 | + badpick("asmvar"); | |
| 373 | + } | |
| 374 | + } | |
| 375 | + asmRTClass(ltsize + mpoff); | |
| 376 | +} | |
| 377 | + | |
| 378 | +# | |
| 379 | +# Put Module Data size into .dis Header. | |
| 380 | +# | |
| 381 | + | |
| 382 | +disnvar() | |
| 383 | +{ | |
| 384 | + discon(LTrelocsize() + mpoff + RTrelocsize()); | |
| 385 | +} | |
| 386 | + | |
| 387 | +discase(off: int, md: ref Datum.Pc) | |
| 388 | +{ | |
| 389 | + i: int; | |
| 390 | + | |
| 391 | + disint(off, md.c.n); | |
| 392 | + off += IBY2WD; | |
| 393 | + for(i = 0; i < md.c.n; i++) { | |
| 394 | + disint(off, md.c.jmptbl[i*3]); | |
| 395 | + off += IBY2WD; | |
| 396 | + disint(off, md.c.jmptbl[i*3+1]); | |
| 397 | + off += IBY2WD; | |
| 398 | + disint(off, md.c.jmptbl[i*3+2]); | |
| 399 | + off += IBY2WD; | |
| 400 | + } | |
| 401 | + disint(off, md.c.jmptbl[md.c.n*3]); | |
| 402 | +} | |
| 403 | + | |
| 404 | +disgoto(off: int, md: ref Datum.Pg) | |
| 405 | +{ | |
| 406 | + i: int; | |
| 407 | + | |
| 408 | + disint(off, md.g.n); | |
| 409 | + for(i = 0; i < md.g.n; i++) { | |
| 410 | + off += IBY2WD; | |
| 411 | + disint(off, md.g.gototbl[i]); | |
| 412 | + } | |
| 413 | +} | |
| 414 | + | |
| 415 | +# | |
| 416 | +# Write Module Data to .dis file. | |
| 417 | +# | |
| 418 | + | |
| 419 | +disvar() | |
| 420 | +{ | |
| 421 | + md: ref Datum; | |
| 422 | + ltsize, rtsize, off: int; | |
| 423 | + | |
| 424 | + ltsize = LTrelocsize(); | |
| 425 | + rtsize = RTrelocsize(); | |
| 426 | + off = disthisCreloc(0); | |
| 427 | + disint(off, mpoff + rtsize); | |
| 428 | + off += IBY2WD; | |
| 429 | + disDreloc(off); | |
| 430 | + off += IBY2WD; | |
| 431 | + off = disCreloc(off); | |
| 432 | + off = align(off, 32); | |
| 433 | + if(off != ltsize) | |
| 434 | + fatal("disvar: off " + string off + ", ltsize " + string ltsize); | |
| 435 | + | |
| 436 | + for(md = mplist; md != nil; md = md.next) { | |
| 437 | + off = ltsize + md.offset; | |
| 438 | + pick mdp := md { | |
| 439 | + Pv => | |
| 440 | + case int mdp.kind { | |
| 441 | + MP_INT => | |
| 442 | + disint(off, int mdp.v.ival); | |
| 443 | + MP_LONG => | |
| 444 | + dislong(off, mdp.v.ival); | |
| 445 | + MP_REAL => | |
| 446 | + disreal(off, mdp.v.rval); | |
| 447 | + } | |
| 448 | + Ps => | |
| 449 | + disstring(off, mdp.s); | |
| 450 | + Pc => | |
| 451 | + discase(off, mdp); | |
| 452 | + Pg => | |
| 453 | + disgoto(off, mdp); | |
| 454 | + * => | |
| 455 | + badpick("disvar"); | |
| 456 | + } | |
| 457 | + } | |
| 458 | + disRTClass(ltsize + mpoff); | |
| 459 | + disflush(-1, -1, 0); | |
| 460 | + bout.putb(byte 0); | |
| 461 | +} | |
| @@ -0,0 +1,49 @@ | ||
| 1 | +<../../../mkconfig | |
| 2 | + | |
| 3 | +TARG=j2d.dis\ | |
| 4 | + | |
| 5 | +MODULES=\ | |
| 6 | + java.m\ | |
| 7 | + javaisa.m\ | |
| 8 | + reloc.m\ | |
| 9 | + $ROOT/appl/cmd/limbo/arg.m\ | |
| 10 | + $ROOT/appl/cmd/limbo/isa.m\ | |
| 11 | + asm.b\ | |
| 12 | + bb.b\ | |
| 13 | + datarloc.b\ | |
| 14 | + desc.b\ | |
| 15 | + dis.b\ | |
| 16 | + entry.b\ | |
| 17 | + finally.b\ | |
| 18 | + frame.b\ | |
| 19 | + j2d.b\ | |
| 20 | + javadas.b\ | |
| 21 | + javatbl.b\ | |
| 22 | + links.b\ | |
| 23 | + loader.b\ | |
| 24 | + ltreloc.b\ | |
| 25 | + main.b\ | |
| 26 | + mdata.b\ | |
| 27 | + module.b\ | |
| 28 | + patch.b\ | |
| 29 | + rtreloc.b\ | |
| 30 | + sbl.b\ | |
| 31 | + simjvm.b\ | |
| 32 | + unify.b\ | |
| 33 | + util.b\ | |
| 34 | + xlate.b\ | |
| 35 | + | |
| 36 | +SYSMODULES=\ | |
| 37 | + bufio.m\ | |
| 38 | + draw.m\ | |
| 39 | + keyring.m\ | |
| 40 | + math.m\ | |
| 41 | + string.m\ | |
| 42 | + sys.m\ | |
| 43 | + | |
| 44 | +DISBIN=$ROOT/java/dis/java | |
| 45 | + | |
| 46 | +<$ROOT/mkfiles/mkdis | |
| 47 | + | |
| 48 | +LIMBOFLAGS=-I$MODDIR\ | |
| 49 | + -I$ROOT/appl/cmd/limbo\ | |
| @@ -0,0 +1,18 @@ | ||
| 1 | +# | |
| 2 | +# Emit 'module' assembly directive. | |
| 3 | +# | |
| 4 | + | |
| 5 | +asmmod() | |
| 6 | +{ | |
| 7 | + bout.puts("\tmodule\t" + THISCLASS + "\n"); | |
| 8 | +} | |
| 9 | + | |
| 10 | +dismod() | |
| 11 | +{ | |
| 12 | + name := array of byte THISCLASS; | |
| 13 | + n := len name; | |
| 14 | + if(n > Sys->NAMEMAX-1) | |
| 15 | + n = Sys->NAMEMAX-1; | |
| 16 | + bout.write(name, n); | |
| 17 | + bout.putb(byte 0); | |
| 18 | +} | |
| @@ -0,0 +1,114 @@ | ||
| 1 | +# | |
| 2 | +# Patch operands, etc. that reference pc offsets. | |
| 3 | +# | |
| 4 | + | |
| 5 | +P_CASE, | |
| 6 | +P_OTHER: con iota+1; | |
| 7 | + | |
| 8 | +Patch: adt { | |
| 9 | + kind: byte; # P_xxx | |
| 10 | + i: ref Inst; | |
| 11 | + n: int; # number of cases in ... | |
| 12 | + jmptbl: array of int; # ... case jump table | |
| 13 | + next: cyclic ref Patch; | |
| 14 | +}; | |
| 15 | + | |
| 16 | +plist: ref Patch; | |
| 17 | + | |
| 18 | +# | |
| 19 | +# Allocate a Patch structure. | |
| 20 | +# | |
| 21 | + | |
| 22 | +newPatch(kind: int, i: ref Inst): ref Patch | |
| 23 | +{ | |
| 24 | + p: ref Patch; | |
| 25 | + | |
| 26 | + p = ref Patch(byte kind, i, 0, nil, plist); | |
| 27 | + plist = p; | |
| 28 | + return p; | |
| 29 | +} | |
| 30 | + | |
| 31 | +# | |
| 32 | +# Record non-case branch instruction for later patching. | |
| 33 | +# | |
| 34 | + | |
| 35 | +patchop(i: ref Inst) | |
| 36 | +{ | |
| 37 | + newPatch(P_OTHER, i); | |
| 38 | +} | |
| 39 | + | |
| 40 | +# | |
| 41 | +# Record case jump table for later patching. | |
| 42 | +# | |
| 43 | + | |
| 44 | +patchcase(i: ref Inst, n: int, jmptbl: array of int) | |
| 45 | +{ | |
| 46 | + p: ref Patch; | |
| 47 | + | |
| 48 | + p = newPatch(P_CASE, i); | |
| 49 | + p.n = n; | |
| 50 | + p.jmptbl = jmptbl; | |
| 51 | +} | |
| 52 | + | |
| 53 | +# | |
| 54 | +# Calculate patch address; Java branches are relative. | |
| 55 | +# | |
| 56 | + | |
| 57 | +patchaddr(i: ref Inst, pc: int): int | |
| 58 | +{ | |
| 59 | + j: ref Jinst; | |
| 60 | + span, srcjpc, dstjpc: int; | |
| 61 | + | |
| 62 | + span = pc; | |
| 63 | + srcjpc = i.j.pc; | |
| 64 | + dstjpc = srcjpc + span; | |
| 65 | + j = code.j[dstjpc]; | |
| 66 | + | |
| 67 | + # account for no-op's (dup, swap, pop, etc.), elided loads/stores | |
| 68 | + while(j.dis == nil) { | |
| 69 | + dstjpc += j.size; | |
| 70 | + j = code.j[dstjpc]; | |
| 71 | + } | |
| 72 | + | |
| 73 | + return j.dis.pc; | |
| 74 | +} | |
| 75 | + | |
| 76 | +# | |
| 77 | +# Patch branch instructions and case jump tables of a method. | |
| 78 | +# | |
| 79 | + | |
| 80 | +patchmethod(startpc: int) | |
| 81 | +{ | |
| 82 | + p: ref Patch; | |
| 83 | + i: ref Inst; | |
| 84 | + jt: array of int; | |
| 85 | + n: int; | |
| 86 | + | |
| 87 | + for(p = plist; p != nil; p = p.next) { | |
| 88 | + i = p.i; | |
| 89 | + if(int p.kind == P_CASE) { | |
| 90 | + jt = p.jmptbl; | |
| 91 | + for(n = 0; n < p.n; n++) | |
| 92 | + jt[n*3+2] = patchaddr(i, jt[n*3+2]); | |
| 93 | + jt[p.n*3] = patchaddr(i, jt[p.n*3]); | |
| 94 | + } else { # P_OTHER | |
| 95 | + i.d.ival = patchaddr(i, i.d.ival); | |
| 96 | + # | |
| 97 | + # jmp $start_of_method -> jmp $start_of_method+1 | |
| 98 | + # skip (re-)allocation of Sys->Exception object | |
| 99 | + # | |
| 100 | + # no more Sys->Exception objects, we killed them all | |
| 101 | + #if(i.d.ival == startpc && int i.op == IJMP && code.nex != 0) | |
| 102 | + # i.d.ival += 1; | |
| 103 | + } | |
| 104 | + } | |
| 105 | +} | |
| 106 | + | |
| 107 | +# | |
| 108 | +# Clear the patch list after each method. | |
| 109 | +# | |
| 110 | + | |
| 111 | +patchfree() | |
| 112 | +{ | |
| 113 | + plist = nil; | |
| 114 | +} | |
| @@ -0,0 +1,78 @@ | ||
| 1 | +Rgetputfield: con 16r1 << 16; | |
| 2 | +Rgetputstatic: con 16r2 << 16; | |
| 3 | +Rinvokeinterface: con 16r3 << 16; | |
| 4 | +Rinvokespecial: con 16r4 << 16; | |
| 5 | +Rinvokestatic: con 16r5 << 16; | |
| 6 | +Rinvokevirtual: con 16r6 << 16; | |
| 7 | + | |
| 8 | +Rstaticmp: con 16r8 << 16; | |
| 9 | +Rspecialmp: con 16r10 << 16; | |
| 10 | + | |
| 11 | +PSRC: con 16r1 << 2; # patch source operand | |
| 12 | +PDST: con 16r2 << 2; # destination | |
| 13 | +PMID: con 16r3 << 2; # middle | |
| 14 | + | |
| 15 | +PIMM: con 16r0; # patch immediate operand | |
| 16 | +PSIND: con 16r1; # single indirect offset | |
| 17 | +PDIND1: con 16r2; # 1st offset of double indirect | |
| 18 | +PDIND2: con 16r3; # 2nd offset | |
| 19 | + | |
| 20 | +SAVEINST: con 1; # save 'ref Inst' for patching | |
| 21 | + | |
| 22 | +# special fields | |
| 23 | +RCLASS: con "@Class"; | |
| 24 | +RADT: con "@adt"; | |
| 25 | +RJEX: con "@jex"; | |
| 26 | +RMP: con "@mp"; | |
| 27 | +RNP: con "@np"; | |
| 28 | +ROBJ: con "@obj"; | |
| 29 | +RSYS: con "@sys"; | |
| 30 | + | |
| 31 | +# special class name | |
| 32 | +RLOADER: con "@Loader"; | |
| 33 | + | |
| 34 | +Ipatch: adt { | |
| 35 | + n: int; # no. of significant elts. in pinfo & i | |
| 36 | + max: int; # number of elements pinfo & i can hold | |
| 37 | + pinfo: array of int; # operand patch directives | |
| 38 | + i: array of ref Inst; # instructions to patch (runtime relocation) | |
| 39 | +}; | |
| 40 | + | |
| 41 | +# | |
| 42 | +# Load-time relocation. | |
| 43 | +# | |
| 44 | + | |
| 45 | +Freloc: adt { | |
| 46 | + field: string; # field name | |
| 47 | + sig: string; # Java type signature | |
| 48 | + flags: int; # access flags | |
| 49 | + ipatch: ref Ipatch; # instruction patch information | |
| 50 | + next: cyclic ref Freloc; | |
| 51 | +}; | |
| 52 | + | |
| 53 | +Creloc: adt { | |
| 54 | + classname: string; | |
| 55 | + fr: ref Freloc; | |
| 56 | + tail: ref Freloc; | |
| 57 | + n: int; # number of elements in 'fr' | |
| 58 | +}; | |
| 59 | + | |
| 60 | +# | |
| 61 | +# Run-time relocation. | |
| 62 | +# | |
| 63 | + | |
| 64 | +RTReloc: adt { | |
| 65 | + field: string; # field name | |
| 66 | + sig: string; # Java type signature | |
| 67 | + flags: int; # access flags | |
| 68 | + ipatch: ref Ipatch; # instruction patch information | |
| 69 | + next: cyclic ref RTReloc; | |
| 70 | +}; | |
| 71 | + | |
| 72 | +RTClass: adt { | |
| 73 | + classname: string; | |
| 74 | + rtr: ref RTReloc; | |
| 75 | + tail: ref RTReloc; | |
| 76 | + n: int; # number of elements in 'rtr' | |
| 77 | + off: int; # Module Data offset | |
| 78 | +}; | |
| @@ -0,0 +1,389 @@ | ||
| 1 | +# | |
| 2 | +# Manage run-time resolution information. | |
| 3 | +# | |
| 4 | + | |
| 5 | +LTLOAD: con 6; | |
| 6 | + | |
| 7 | +ltload := array [LTLOAD] of { | |
| 8 | + "java/lang/Class", | |
| 9 | + "java/lang/Object", | |
| 10 | + "java/lang/String", | |
| 11 | + "java/lang/StringBuffer", | |
| 12 | + "inferno/vm/Array", | |
| 13 | + "java/io/Serializable" | |
| 14 | +}; | |
| 15 | + | |
| 16 | +dortload(name: string): int | |
| 17 | +{ | |
| 18 | + i: int; | |
| 19 | + | |
| 20 | + if(name == nil || name == THISCLASS || name == SUPERCLASS) | |
| 21 | + return 0; | |
| 22 | + for(i = 0; i < LTLOAD; i++) { | |
| 23 | + if(name == ltload[i]) | |
| 24 | + return 0; | |
| 25 | + } | |
| 26 | + return 1; | |
| 27 | +} | |
| 28 | + | |
| 29 | +RTHash: adt { | |
| 30 | + rtc: ref RTClass; | |
| 31 | + next: cyclic ref RTHash; | |
| 32 | +}; | |
| 33 | + | |
| 34 | +rttbl := array [Hashsize] of ref RTHash; # hash table of ref'd classes | |
| 35 | +nrtclasses: int; # no. of classes referenced | |
| 36 | + | |
| 37 | +rtappend(rtc: ref RTClass, rtr: ref RTReloc) | |
| 38 | +{ | |
| 39 | + if(rtc.rtr == nil) | |
| 40 | + rtc.rtr = rtr; | |
| 41 | + else | |
| 42 | + rtc.tail.next = rtr; | |
| 43 | + rtc.tail = rtr; | |
| 44 | +} | |
| 45 | + | |
| 46 | +rtprepend(rtc: ref RTClass, rtr: ref RTReloc) | |
| 47 | +{ | |
| 48 | + if(rtc.rtr == nil) | |
| 49 | + rtc.tail = rtr; | |
| 50 | + rtr.next = rtc.rtr; | |
| 51 | + rtc.rtr = rtr; | |
| 52 | +} | |
| 53 | + | |
| 54 | +# | |
| 55 | +# Add RTReloc entry. | |
| 56 | +# | |
| 57 | + | |
| 58 | +addRTReloc(rtc: ref RTClass, field: string, sig: string, flags: int): ref RTReloc | |
| 59 | +{ | |
| 60 | + rtr: ref RTReloc; | |
| 61 | + | |
| 62 | + rtr = ref RTReloc(field, sig, flags, nil, nil); | |
| 63 | + rtr.ipatch = ref Ipatch(0, 0, nil, nil); | |
| 64 | + if(field[0] == '@') # these must go first in the list ! | |
| 65 | + rtprepend(rtc, rtr); | |
| 66 | + else | |
| 67 | + rtappend(rtc, rtr); | |
| 68 | + rtc.n += 1; | |
| 69 | + return rtr; | |
| 70 | +} | |
| 71 | + | |
| 72 | +# | |
| 73 | +# Allocate a RTClass structure. | |
| 74 | +# | |
| 75 | + | |
| 76 | +newRTClass(s: string): ref RTClass | |
| 77 | +{ | |
| 78 | + rtc: ref RTClass; | |
| 79 | + | |
| 80 | + rtc = ref RTClass(s, nil, nil, 0, 0); | |
| 81 | + nrtclasses += 1; | |
| 82 | + # want the order: @mp, @np, @adt, @Class | |
| 83 | + addRTReloc(rtc, RCLASS, nil, 0); | |
| 84 | + addRTReloc(rtc, RADT, nil, 0); | |
| 85 | + addRTReloc(rtc, RNP, nil, 0); | |
| 86 | + addRTReloc(rtc, RMP, nil, 0); | |
| 87 | + return rtc; | |
| 88 | +} | |
| 89 | + | |
| 90 | +# | |
| 91 | +# Add RTClass entry for classname. | |
| 92 | +# | |
| 93 | + | |
| 94 | +addRTClass(classname: string): ref RTClass | |
| 95 | +{ | |
| 96 | + h: int; | |
| 97 | + he: ref RTHash; | |
| 98 | + | |
| 99 | + h = hashval(classname); | |
| 100 | + he = ref RTHash(newRTClass(classname), rttbl[h]); | |
| 101 | + rttbl[h] = he; | |
| 102 | + return he.rtc; | |
| 103 | +} | |
| 104 | + | |
| 105 | +# | |
| 106 | +# Get RTClass entry for classname. | |
| 107 | +# | |
| 108 | + | |
| 109 | +getRTClass(classname: string): ref RTClass | |
| 110 | +{ | |
| 111 | + he: ref RTHash; | |
| 112 | + | |
| 113 | + for(he = rttbl[hashval(classname)]; he != nil; he = he.next) { | |
| 114 | + if(classname == he.rtc.classname) | |
| 115 | + return he.rtc; | |
| 116 | + } | |
| 117 | + return addRTClass(classname); | |
| 118 | +} | |
| 119 | + | |
| 120 | +# | |
| 121 | +# Get RTReloc entry. Ignore signature if nil. | |
| 122 | +# | |
| 123 | + | |
| 124 | +getRTReloc(rtc: ref RTClass, field: string, sig: string, flags: int): ref RTReloc | |
| 125 | +{ | |
| 126 | + rtr: ref RTReloc; | |
| 127 | + lowflags: int; | |
| 128 | + | |
| 129 | + lowflags = 0; | |
| 130 | + for(rtr = rtc.rtr; rtr != nil; rtr = rtr.next) { | |
| 131 | + if(rtr.field == field && (sig == nil || rtr.sig == sig)) { | |
| 132 | + if(rtr.flags >> 16 == 0) { | |
| 133 | + rtr.flags |= flags; | |
| 134 | + return rtr; | |
| 135 | + } else if(rtr.flags >> 16 == flags >> 16) | |
| 136 | + return rtr; | |
| 137 | + lowflags = rtr.flags & 16rffff; | |
| 138 | + } | |
| 139 | + } | |
| 140 | + | |
| 141 | + return addRTReloc(rtc, field, sig, flags|lowflags); | |
| 142 | +} | |
| 143 | + | |
| 144 | +# | |
| 145 | +# Add instruction patch information to RTReloc rtr. | |
| 146 | +# | |
| 147 | + | |
| 148 | +RTIpatch(rtr: ref RTReloc, i: ref Inst, operand: int, patchkind: int) | |
| 149 | +{ | |
| 150 | + addDreloc(i, operand, patchkind); | |
| 151 | + addIpatch(rtr.ipatch, i, operand, patchkind, SAVEINST); | |
| 152 | +} | |
| 153 | + | |
| 154 | +# | |
| 155 | +# Fix RTClass and RTReloc 'off' fields to prepare for instruction patch. | |
| 156 | +# | |
| 157 | + | |
| 158 | +RTfixoff(off: int) | |
| 159 | +{ | |
| 160 | + he: ref RTHash; | |
| 161 | + i: int; | |
| 162 | + | |
| 163 | + if(nrtclasses > 0) { | |
| 164 | + for(i = 0; i < Hashsize; i++) { | |
| 165 | + for(he = rttbl[i]; he != nil; he = he.next) { | |
| 166 | + he.rtc.off = off; | |
| 167 | + off += he.rtc.n * IBY2WD; | |
| 168 | + } | |
| 169 | + } | |
| 170 | + } | |
| 171 | +} | |
| 172 | + | |
| 173 | +# | |
| 174 | +# Patch instructions for run-time relocation. | |
| 175 | +# | |
| 176 | + | |
| 177 | +doRTpatch() | |
| 178 | +{ | |
| 179 | + a: ref Addr; | |
| 180 | + he: ref RTHash; | |
| 181 | + ip: ref Ipatch; | |
| 182 | + rtr: ref RTReloc; | |
| 183 | + i, j: int; | |
| 184 | + off, ltsize: int; | |
| 185 | + | |
| 186 | + if(nrtclasses == 0) | |
| 187 | + return; | |
| 188 | + | |
| 189 | + ltsize = LTrelocsize(); | |
| 190 | + for(i = 0; i < Hashsize; i++) { | |
| 191 | + for(he = rttbl[i]; he != nil; he = he.next) { | |
| 192 | + off = he.rtc.off - ltsize; | |
| 193 | + for(rtr = he.rtc.rtr; rtr != nil; rtr = rtr.next) { | |
| 194 | + ip = rtr.ipatch; | |
| 195 | + for(j = 0; j < ip.n; j++) { | |
| 196 | + case(ip.pinfo[j] & (16r3 << 2)) { | |
| 197 | + PSRC => | |
| 198 | + a = ip.i[j].s; | |
| 199 | + PDST => | |
| 200 | + a = ip.i[j].d; | |
| 201 | + PMID => | |
| 202 | + a = ip.i[j].m; | |
| 203 | + } | |
| 204 | + case (ip.pinfo[j] & 16r3) { | |
| 205 | + PIMM or | |
| 206 | + PDIND1 => | |
| 207 | + a.ival = off; | |
| 208 | + PSIND or | |
| 209 | + PDIND2 => | |
| 210 | + a.offset = off; | |
| 211 | + } | |
| 212 | + } | |
| 213 | + off += IBY2WD; | |
| 214 | + } | |
| 215 | + } | |
| 216 | + } | |
| 217 | +} | |
| 218 | + | |
| 219 | +# | |
| 220 | +# Size of Module Data space taken by run-time relocation information. | |
| 221 | +# | |
| 222 | + | |
| 223 | +RTrelocsize(): int | |
| 224 | +{ | |
| 225 | + i: int; | |
| 226 | + n: int; | |
| 227 | + he: ref RTHash; | |
| 228 | + | |
| 229 | + n = 0; | |
| 230 | + if(nrtclasses > 0) { | |
| 231 | + for(i = 0; i < Hashsize; i++) { | |
| 232 | + for(he = rttbl[i]; he != nil; he = he.next) | |
| 233 | + n += he.rtc.n; | |
| 234 | + } | |
| 235 | + } | |
| 236 | + return n * IBY2WD; | |
| 237 | +} | |
| 238 | + | |
| 239 | +# | |
| 240 | +# Fix type descriptor for run-time relocation information. | |
| 241 | +# | |
| 242 | + | |
| 243 | +RTReloctid: int; | |
| 244 | + | |
| 245 | +RTrelocdesc(map: array of byte, off: int) | |
| 246 | +{ | |
| 247 | + i: int; | |
| 248 | + he: ref RTHash; | |
| 249 | + rtr: ref RTReloc; | |
| 250 | + | |
| 251 | + if(nrtclasses == 0) | |
| 252 | + return; | |
| 253 | + | |
| 254 | + RTReloctid = descid(3*IBY2WD, 1, array [1] of { byte 16rc0 }); | |
| 255 | + | |
| 256 | + for(i = 0; i < Hashsize; i++) { | |
| 257 | + for(he = rttbl[i]; he != nil; he = he.next) { | |
| 258 | + setbit(map, off); # @mp cell | |
| 259 | + off += 4; | |
| 260 | + setbit(map, off); # @np cell | |
| 261 | + off += 4; | |
| 262 | + setbit(map, off); # @adt cell | |
| 263 | + off += 8; | |
| 264 | + rtr = he.rtc.rtr.next.next.next.next; | |
| 265 | + while(rtr != nil) { | |
| 266 | + if(rtr.flags & (Rspecialmp | Rstaticmp)) | |
| 267 | + setbit(map, off); | |
| 268 | + off += 4; | |
| 269 | + rtr = rtr.next; | |
| 270 | + } | |
| 271 | + } | |
| 272 | + } | |
| 273 | +} | |
| 274 | + | |
| 275 | +# | |
| 276 | +# Write RTReloc array to .s file. | |
| 277 | +# | |
| 278 | + | |
| 279 | +asmRTReloc(off: int, rtc: ref RTClass) | |
| 280 | +{ | |
| 281 | + rtr: ref RTReloc; | |
| 282 | + reloff: int; # relative offset for array elements | |
| 283 | + | |
| 284 | + if(rtc.n <= 4) | |
| 285 | + return; | |
| 286 | + | |
| 287 | + reloff = 0; | |
| 288 | + asmarray(off, RTReloctid, rtc.n - 4, reloff); | |
| 289 | + # skip @mp @np @adt @Class | |
| 290 | + rtr = rtc.rtr.next.next.next.next; | |
| 291 | + while(rtr != nil) { | |
| 292 | + asmstring(reloff, rtr.field); | |
| 293 | + reloff += IBY2WD; | |
| 294 | + if(rtr.sig != nil) | |
| 295 | + asmstring(reloff, rtr.sig); | |
| 296 | + reloff += IBY2WD; | |
| 297 | + asmint(reloff, rtr.flags); | |
| 298 | + reloff += IBY2WD; | |
| 299 | + rtr = rtr.next; | |
| 300 | + } | |
| 301 | + bout.puts("\tapop\n"); | |
| 302 | +} | |
| 303 | + | |
| 304 | +# | |
| 305 | +# Write RTClass information to .s file. | |
| 306 | +# | |
| 307 | + | |
| 308 | +asmRTClass(off: int): int | |
| 309 | +{ | |
| 310 | + he: ref RTHash; | |
| 311 | + i: int; | |
| 312 | + ltsize: int; | |
| 313 | + | |
| 314 | + if(nrtclasses > 0) { | |
| 315 | + ltsize = LTrelocsize(); | |
| 316 | + for(i = 0; i < Hashsize; i++) { | |
| 317 | + for(he = rttbl[i]; he != nil; he = he.next) { | |
| 318 | + off += IBY2WD; # @mp cell | |
| 319 | + asmstring(off, he.rtc.classname); | |
| 320 | + off += IBY2WD; | |
| 321 | + asmRTReloc(off, he.rtc); | |
| 322 | + off += IBY2WD; | |
| 323 | + asmint(off, he.rtc.off - ltsize); | |
| 324 | + off += IBY2WD; | |
| 325 | + # account for fields beyond @Class | |
| 326 | + off += (he.rtc.n - 4) * IBY2WD; | |
| 327 | + } | |
| 328 | + } | |
| 329 | + } | |
| 330 | + return off; | |
| 331 | +} | |
| 332 | + | |
| 333 | +# | |
| 334 | +# Write RTReloc array to .dis file. | |
| 335 | +# | |
| 336 | + | |
| 337 | +disRTReloc(off: int, rtc: ref RTClass) | |
| 338 | +{ | |
| 339 | + rtr: ref RTReloc; | |
| 340 | + reloff: int; # relative offset for array elements | |
| 341 | + | |
| 342 | + if(rtc.n <= 4) | |
| 343 | + return; | |
| 344 | + | |
| 345 | + reloff = 0; | |
| 346 | + disarray(off, RTReloctid, rtc.n - 4); | |
| 347 | + # skip @mp @np @adt @Class | |
| 348 | + rtr = rtc.rtr.next.next.next.next; | |
| 349 | + while(rtr != nil) { | |
| 350 | + disstring(reloff, rtr.field); | |
| 351 | + reloff += IBY2WD; | |
| 352 | + if(rtr.sig != nil) | |
| 353 | + disstring(reloff, rtr.sig); | |
| 354 | + reloff += IBY2WD; | |
| 355 | + disint(reloff, rtr.flags); | |
| 356 | + reloff += IBY2WD; | |
| 357 | + rtr = rtr.next; | |
| 358 | + } | |
| 359 | + disapop(); | |
| 360 | +} | |
| 361 | + | |
| 362 | +# | |
| 363 | +# Write RTClass information to .dis file. | |
| 364 | +# | |
| 365 | + | |
| 366 | +disRTClass(off: int): int | |
| 367 | +{ | |
| 368 | + he: ref RTHash; | |
| 369 | + i: int; | |
| 370 | + ltsize: int; | |
| 371 | + | |
| 372 | + if(nrtclasses > 0) { | |
| 373 | + ltsize = LTrelocsize(); | |
| 374 | + for(i = 0; i < Hashsize; i++) { | |
| 375 | + for(he = rttbl[i]; he != nil; he = he.next) { | |
| 376 | + off += IBY2WD; # @mp cell | |
| 377 | + disstring(off, he.rtc.classname); | |
| 378 | + off += IBY2WD; | |
| 379 | + disRTReloc(off, he.rtc); | |
| 380 | + off += IBY2WD; | |
| 381 | + disint(off, he.rtc.off - ltsize); | |
| 382 | + off += IBY2WD; | |
| 383 | + # account for fields beyond @Class | |
| 384 | + off += (he.rtc.n - 4) * IBY2WD; | |
| 385 | + } | |
| 386 | + } | |
| 387 | + } | |
| 388 | + return off; | |
| 389 | +} | |
| @@ -0,0 +1,43 @@ | ||
| 1 | +# | |
| 2 | +# Generate symbol table file (.sbl). | |
| 3 | +# | |
| 4 | + | |
| 5 | +SBLVERSION: con "limbo .sbl 2.0"; | |
| 6 | +EXT: con ".sbl"; | |
| 7 | + | |
| 8 | +sblout(out: string) | |
| 9 | +{ | |
| 10 | + n: int; | |
| 11 | + sym: string; | |
| 12 | + bsym: ref Bufio->Iobuf; | |
| 13 | + | |
| 14 | + n = len out; | |
| 15 | + if(n > 2 && out[n-1] == 's') { # .s or .dis file ? | |
| 16 | + if(out[n-2] == '.') | |
| 17 | + n -= 2; | |
| 18 | + else if(n > 4 && out[n-2] == 'i' | |
| 19 | + && out[n-3] == 'd' && out[n-4] == '.') | |
| 20 | + n -= 4; | |
| 21 | + } | |
| 22 | + sym = out[0:n] + EXT; | |
| 23 | + | |
| 24 | + bsym = bufio->create(sym, Bufio->OWRITE, 8r644); | |
| 25 | + if(bsym == nil) | |
| 26 | + fatal("can't open " + sym + ": " + sprint("%r")); | |
| 27 | + | |
| 28 | + bsym.puts(SBLVERSION + "\n"); | |
| 29 | + bsym.puts(THISCLASS + "\n"); | |
| 30 | + bsym.puts("1\n"); | |
| 31 | + s: string; | |
| 32 | + if(class.source_file) | |
| 33 | + s = STRING(class.source_file) + "\n"; | |
| 34 | + else | |
| 35 | + s = THISCLASS + ".java\n"; | |
| 36 | + bsym.puts(s); | |
| 37 | + sblinst(bsym); # Dis instructions | |
| 38 | + bsym.puts("0\n"); # adts | |
| 39 | + sbllinks(bsym); # functions | |
| 40 | + bsym.puts("0\n"); # globals | |
| 41 | + | |
| 42 | + bsym.close(); | |
| 43 | +} | |
| @@ -0,0 +1,1329 @@ | ||
| 1 | +# | |
| 2 | +# "Simulate" the Java VM on a method. | |
| 3 | +# | |
| 4 | + | |
| 5 | +Result: adt { | |
| 6 | + jtype: byte; | |
| 7 | + pc: int; | |
| 8 | +}; | |
| 9 | + | |
| 10 | +jvmstack: array of ref Result; # simulated JVM stack | |
| 11 | +jvmtos: int; # number of items in jvmstack | |
| 12 | +jvmwords: int; # number of words that would be on JVM stack | |
| 13 | +rettype: int; # return type of simulated method | |
| 14 | + | |
| 15 | +jvmpop(): ref Result | |
| 16 | +{ | |
| 17 | + r: ref Result; | |
| 18 | + | |
| 19 | + if(jvmtos == 0) | |
| 20 | + verifyerrormess("stack underflow"); | |
| 21 | + r = jvmstack[--jvmtos]; | |
| 22 | + if(r.jtype == byte 'J' || r.jtype == byte 'D') | |
| 23 | + jvmwords -= 2; | |
| 24 | + else | |
| 25 | + jvmwords -= 1; | |
| 26 | + if(jvmwords < 0) | |
| 27 | + verifyerrormess("stack underflow"); | |
| 28 | + return r; | |
| 29 | +} | |
| 30 | + | |
| 31 | +jvmpush(r: ref Result) | |
| 32 | +{ | |
| 33 | + if(r.jtype == byte 'J' || r.jtype == byte 'D') | |
| 34 | + jvmwords += 2; | |
| 35 | + else | |
| 36 | + jvmwords += 1; | |
| 37 | + if(jvmwords > code.max_stack) | |
| 38 | + verifyerrormess("stack overflow"); | |
| 39 | + jvmstack[jvmtos++] = r; | |
| 40 | +} | |
| 41 | + | |
| 42 | +# | |
| 43 | +# Initialize jvmstack to process basic block bb. | |
| 44 | +# | |
| 45 | + | |
| 46 | +jvminit(bb: ref BB) | |
| 47 | +{ | |
| 48 | + i: int; | |
| 49 | + r: ref Result; | |
| 50 | + s: array of ref StkSnap; | |
| 51 | + | |
| 52 | + jvmtos = 0; | |
| 53 | + jvmwords = 0; | |
| 54 | + if(int (bb.flags & (BB_FINALLY | BB_HANDLER))) { | |
| 55 | + r = ref Result(byte 'L', code.code_length); | |
| 56 | + jvmpush(r); # push a dummy | |
| 57 | + return; | |
| 58 | + } | |
| 59 | + | |
| 60 | + # set jvmstack to bb.entrystk | |
| 61 | + s = bb.entrystk; | |
| 62 | + for(i = 0; i < bb.entrysz; i++) { | |
| 63 | + r = ref Result(s[i].jtype, s[i].pc[0]); | |
| 64 | + jvmpush(r); | |
| 65 | + } | |
| 66 | +} | |
| 67 | + | |
| 68 | +typecheck(r: ref Result, jtype: byte) | |
| 69 | +{ | |
| 70 | + # assumes 'L' and '[' are interchangeable | |
| 71 | + if(r.jtype != jtype && (int r.jtype + int jtype) != 'L' + '[') | |
| 72 | + verifyerror(code.j[r.pc]); | |
| 73 | +} | |
| 74 | + | |
| 75 | +jvmtype(jtype: int): byte | |
| 76 | +{ | |
| 77 | + case jtype { | |
| 78 | + 'Z' or | |
| 79 | + 'B' or | |
| 80 | + 'C' or | |
| 81 | + 'S' => | |
| 82 | + jtype = 'I'; | |
| 83 | + } | |
| 84 | + return byte jtype; | |
| 85 | +} | |
| 86 | + | |
| 87 | +srcalloc(j: ref Jinst, n: int) | |
| 88 | +{ | |
| 89 | + j.nsrc = n; | |
| 90 | + j.src = array [n] of int; | |
| 91 | +} | |
| 92 | + | |
| 93 | +iconst(j: ref Jinst, ival: int) | |
| 94 | +{ | |
| 95 | + r: ref Result; | |
| 96 | + | |
| 97 | + addrimm(j.dst, ival); | |
| 98 | + r = ref Result(byte 'I', j.pc); | |
| 99 | + j.jtype = byte 'I'; | |
| 100 | + jvmpush(r); | |
| 101 | +} | |
| 102 | + | |
| 103 | +mpconst(j: ref Jinst, jtype: int, off: int) | |
| 104 | +{ | |
| 105 | + r: ref Result; | |
| 106 | + | |
| 107 | + addrsind(j.dst, Amp, off); | |
| 108 | + r = ref Result(byte jtype, j.pc); | |
| 109 | + j.jtype = byte jtype; | |
| 110 | + jvmpush(r); | |
| 111 | +} | |
| 112 | + | |
| 113 | +verifyindex(j: ref Jinst, jtype: int, ix: int) | |
| 114 | +{ | |
| 115 | + n: int; | |
| 116 | + | |
| 117 | + case jtype { | |
| 118 | + 'I' or | |
| 119 | + 'F' or | |
| 120 | + 'L' => | |
| 121 | + n = code.max_locals-1; | |
| 122 | + 'J' or | |
| 123 | + 'D' => | |
| 124 | + n = code.max_locals-2; | |
| 125 | + } | |
| 126 | + if(ix > n) | |
| 127 | + verifyerror(j); | |
| 128 | +} | |
| 129 | + | |
| 130 | +getfpoff(jtype: int, ix: int): int | |
| 131 | +{ | |
| 132 | + off: int; | |
| 133 | + | |
| 134 | + case jtype { | |
| 135 | + 'I' => | |
| 136 | + off = localix(DIS_W, ix); | |
| 137 | + 'J' or | |
| 138 | + 'F' or | |
| 139 | + 'D' => | |
| 140 | + off = localix(DIS_L, ix); | |
| 141 | + 'L' => | |
| 142 | + off = localix(DIS_P, ix); | |
| 143 | + } | |
| 144 | + return off; | |
| 145 | +} | |
| 146 | + | |
| 147 | +javaload(j: ref Jinst, jtype: int, ix: int) | |
| 148 | +{ | |
| 149 | + r: ref Result; | |
| 150 | + | |
| 151 | + verifyindex(j, jtype, ix); | |
| 152 | + addrsind(j.dst, Afp, getfpoff(jtype, ix)); | |
| 153 | + r = ref Result(byte jtype, j.pc); | |
| 154 | + j.jtype = byte jtype; | |
| 155 | + jvmpush(r); | |
| 156 | +} | |
| 157 | + | |
| 158 | +javastore(j: ref Jinst, jtype: int, ix: int) | |
| 159 | +{ | |
| 160 | + r: ref Result; | |
| 161 | + | |
| 162 | + verifyindex(j, jtype, ix); | |
| 163 | + | |
| 164 | + srcalloc(j, 1); | |
| 165 | + | |
| 166 | + r = jvmpop(); | |
| 167 | + typecheck(r, byte jtype); | |
| 168 | + j.src[0] = r.pc; | |
| 169 | + | |
| 170 | + addrsind(j.dst, Afp, getfpoff(jtype, ix)); | |
| 171 | +} | |
| 172 | + | |
| 173 | +arrayload(j: ref Jinst, jtype: int) | |
| 174 | +{ | |
| 175 | + r: ref Result; | |
| 176 | + | |
| 177 | + srcalloc(j, 2); | |
| 178 | + | |
| 179 | + r = jvmpop(); | |
| 180 | + typecheck(r, byte 'I'); | |
| 181 | + j.src[1] = r.pc; | |
| 182 | + | |
| 183 | + r = jvmpop(); | |
| 184 | + typecheck(r, byte '['); | |
| 185 | + j.src[0] = r.pc; | |
| 186 | + | |
| 187 | + addrsind(j.dst, Afp, -1); | |
| 188 | + r = ref Result(byte jtype, j.pc); | |
| 189 | + j.jtype = byte jtype; | |
| 190 | + jvmpush(r); | |
| 191 | +} | |
| 192 | + | |
| 193 | +arraystore(j: ref Jinst, jtype: int) | |
| 194 | +{ | |
| 195 | + r: ref Result; | |
| 196 | + | |
| 197 | + srcalloc(j, 3); | |
| 198 | + | |
| 199 | + r = jvmpop(); | |
| 200 | + typecheck(r, byte jtype); | |
| 201 | + j.src[2] = r.pc; | |
| 202 | + | |
| 203 | + r = jvmpop(); | |
| 204 | + typecheck(r, byte 'I'); | |
| 205 | + j.src[1] = r.pc; | |
| 206 | + | |
| 207 | + r = jvmpop(); | |
| 208 | + typecheck(r, byte '['); | |
| 209 | + j.src[0] = r.pc; | |
| 210 | + | |
| 211 | +} | |
| 212 | + | |
| 213 | +binop(j: ref Jinst, loptype: int, roptype: int, dsttype: int) | |
| 214 | +{ | |
| 215 | + r: ref Result; | |
| 216 | + | |
| 217 | + srcalloc(j, 2); | |
| 218 | + | |
| 219 | + r = jvmpop(); | |
| 220 | + typecheck(r, byte roptype); | |
| 221 | + j.src[1] = r.pc; | |
| 222 | + | |
| 223 | + r = jvmpop(); | |
| 224 | + typecheck(r, byte loptype); | |
| 225 | + j.src[0] = r.pc; | |
| 226 | + | |
| 227 | + addrsind(j.dst, Afp, -1); | |
| 228 | + r = ref Result(byte dsttype, j.pc); | |
| 229 | + j.jtype = byte dsttype; | |
| 230 | + jvmpush(r); | |
| 231 | +} | |
| 232 | + | |
| 233 | +unop(j: ref Jinst, srctype: int, dsttype: int) | |
| 234 | +{ | |
| 235 | + r: ref Result; | |
| 236 | + | |
| 237 | + srcalloc(j, 1); | |
| 238 | + | |
| 239 | + r = jvmpop(); | |
| 240 | + typecheck(r, byte srctype); | |
| 241 | + j.src[0] = r.pc; | |
| 242 | + | |
| 243 | + addrsind(j.dst, Afp, -1); | |
| 244 | + r = ref Result(byte dsttype, j.pc); | |
| 245 | + j.jtype = byte dsttype; | |
| 246 | + jvmpush(r); | |
| 247 | +} | |
| 248 | + | |
| 249 | +# | |
| 250 | +# If the local variable being stored into corresponds to a local | |
| 251 | +# that is on the stack, then an explicit mov_ MUST be generated | |
| 252 | +# for the load instruction that put it on the stack. | |
| 253 | +# | |
| 254 | + | |
| 255 | +storechk(six: int, stype: int) | |
| 256 | +{ | |
| 257 | + i, lix: int; | |
| 258 | + ltype: byte; | |
| 259 | + j: ref Jinst; | |
| 260 | + jpi: ref Jinst.Pi; | |
| 261 | + jpw: ref Jinst.Pw; | |
| 262 | + | |
| 263 | + for(i = 0; i < jvmtos; i++) { | |
| 264 | + j = code.j[jvmstack[i].pc]; | |
| 265 | + lix = -1; | |
| 266 | + pick jp := j { | |
| 267 | + Pi => | |
| 268 | + jpi = jp; | |
| 269 | + Pw => | |
| 270 | + jpw = jp; | |
| 271 | + } | |
| 272 | + case int j.op { | |
| 273 | + Jiload or | |
| 274 | + Jlload or | |
| 275 | + Jfload or | |
| 276 | + Jdload or | |
| 277 | + Jaload => | |
| 278 | + lix = jpi.i; | |
| 279 | + Jiload_0 or | |
| 280 | + Jlload_0 or | |
| 281 | + Jfload_0 or | |
| 282 | + Jdload_0 or | |
| 283 | + Jaload_0 => | |
| 284 | + lix = 0; | |
| 285 | + Jiload_1 or | |
| 286 | + Jlload_1 or | |
| 287 | + Jfload_1 or | |
| 288 | + Jdload_1 or | |
| 289 | + Jaload_1 => | |
| 290 | + lix = 1; | |
| 291 | + Jiload_2 or | |
| 292 | + Jlload_2 or | |
| 293 | + Jfload_2 or | |
| 294 | + Jdload_2 or | |
| 295 | + Jaload_2 => | |
| 296 | + lix = 2; | |
| 297 | + Jiload_3 or | |
| 298 | + Jlload_3 or | |
| 299 | + Jfload_3 or | |
| 300 | + Jdload_3 or | |
| 301 | + Jaload_3 => | |
| 302 | + lix = 3; | |
| 303 | + Jwide => | |
| 304 | + case int jpw.w.op { | |
| 305 | + Jiload or | |
| 306 | + Jlload or | |
| 307 | + Jfload or | |
| 308 | + Jdload or | |
| 309 | + Jaload => | |
| 310 | + lix = jpw.w.ix; | |
| 311 | + } | |
| 312 | + } | |
| 313 | + ltype = byte '-'; | |
| 314 | + case int j.op { | |
| 315 | + Jiload or | |
| 316 | + Jiload_0 or | |
| 317 | + Jiload_1 or | |
| 318 | + Jiload_2 or | |
| 319 | + Jiload_3 => | |
| 320 | + ltype = byte 'I'; | |
| 321 | + Jlload or | |
| 322 | + Jlload_0 or | |
| 323 | + Jlload_1 or | |
| 324 | + Jlload_2 or | |
| 325 | + Jlload_3 => | |
| 326 | + ltype = byte 'J'; | |
| 327 | + Jfload or | |
| 328 | + Jfload_0 or | |
| 329 | + Jfload_1 or | |
| 330 | + Jfload_2 or | |
| 331 | + Jfload_3 => | |
| 332 | + ltype = byte 'F'; | |
| 333 | + Jdload or | |
| 334 | + Jdload_0 or | |
| 335 | + Jdload_1 or | |
| 336 | + Jdload_2 or | |
| 337 | + Jdload_3 => | |
| 338 | + ltype = byte 'D'; | |
| 339 | + Jaload or | |
| 340 | + Jaload_0 or | |
| 341 | + Jaload_1 or | |
| 342 | + Jaload_2 or | |
| 343 | + Jaload_3 => | |
| 344 | + ltype = byte 'L'; | |
| 345 | + Jwide => | |
| 346 | + case int jpw.w.op { | |
| 347 | + Jiload => | |
| 348 | + ltype = byte 'I'; | |
| 349 | + Jlload => | |
| 350 | + ltype = byte 'J'; | |
| 351 | + Jfload => | |
| 352 | + ltype = byte 'F'; | |
| 353 | + Jdload => | |
| 354 | + ltype = byte 'D'; | |
| 355 | + Jaload => | |
| 356 | + ltype = byte 'L'; | |
| 357 | + } | |
| 358 | + } | |
| 359 | + if(lix == six && ltype == byte stype && j.movsrc.mode == byte Anone) { | |
| 360 | + *j.movsrc = *j.dst; | |
| 361 | + addrsind(j.dst, Afp, -1); | |
| 362 | + } | |
| 363 | + } | |
| 364 | +} | |
| 365 | + | |
| 366 | +useone(j: ref Jinst, jtype: int) | |
| 367 | +{ | |
| 368 | + r: ref Result; | |
| 369 | + | |
| 370 | + srcalloc(j, 1); | |
| 371 | + | |
| 372 | + r = jvmpop(); | |
| 373 | + typecheck(r, byte jtype); | |
| 374 | + j.src[0] = r.pc; | |
| 375 | +} | |
| 376 | + | |
| 377 | +usetwo(j: ref Jinst, loptype: byte, roptype: byte) | |
| 378 | +{ | |
| 379 | + r: ref Result; | |
| 380 | + | |
| 381 | + srcalloc(j, 2); | |
| 382 | + | |
| 383 | + r = jvmpop(); | |
| 384 | + typecheck(r, roptype); | |
| 385 | + j.src[1] = r.pc; | |
| 386 | + | |
| 387 | + r = jvmpop(); | |
| 388 | + typecheck(r, loptype); | |
| 389 | + j.src[0] = r.pc; | |
| 390 | +} | |
| 391 | + | |
| 392 | +javanew(j: ref Jinst.Pi) | |
| 393 | +{ | |
| 394 | + r: ref Result; | |
| 395 | + name: string; | |
| 396 | + | |
| 397 | + name = CLASSNAME(j.i); | |
| 398 | + if(name[0] == '[') | |
| 399 | + verifyerror(j); | |
| 400 | + | |
| 401 | + addrsind(j.dst, Afp, -1); | |
| 402 | + r = ref Result(byte 'L', j.pc); | |
| 403 | + j.jtype = byte 'L'; | |
| 404 | + jvmpush(r); | |
| 405 | +} | |
| 406 | + | |
| 407 | +checkdim(j: ref Jinst, ix: int): int | |
| 408 | +{ | |
| 409 | + ndim: int; | |
| 410 | + name: string; | |
| 411 | + | |
| 412 | + ndim = 0; | |
| 413 | + name = CLASSNAME(ix); | |
| 414 | + while(name[ndim] == '[') | |
| 415 | + ndim++; | |
| 416 | + if(ndim > 255) | |
| 417 | + verifyerror(j); | |
| 418 | + return ndim; | |
| 419 | +} | |
| 420 | + | |
| 421 | +anewarray(j: ref Jinst.Pi) | |
| 422 | +{ | |
| 423 | + checkdim(j, j.i); | |
| 424 | + unop(j, 'I', '['); | |
| 425 | +} | |
| 426 | + | |
| 427 | +multianewarray(j: ref Jinst.Px2d) | |
| 428 | +{ | |
| 429 | + r: ref Result; | |
| 430 | + i, ndim: int; | |
| 431 | + | |
| 432 | + ndim = checkdim(j, j.x2d.ix); | |
| 433 | + if(ndim == 0 || j.x2d.dim > ndim) | |
| 434 | + verifyerror(j); | |
| 435 | + | |
| 436 | + srcalloc(j, j.x2d.dim); | |
| 437 | + for(i = j.x2d.dim-1; i >= 0; i--) { | |
| 438 | + r = jvmpop(); | |
| 439 | + typecheck(r, byte 'I'); | |
| 440 | + j.src[i] = r.pc; | |
| 441 | + } | |
| 442 | + | |
| 443 | + addrsind(j.dst, Afp, -1); | |
| 444 | + r = ref Result(byte '[', j.pc); | |
| 445 | + j.jtype = byte '['; | |
| 446 | + jvmpush(r); | |
| 447 | +} | |
| 448 | + | |
| 449 | +getname(j: ref Jinst): string | |
| 450 | +{ | |
| 451 | + ix: int; | |
| 452 | + | |
| 453 | + pick jp := j { | |
| 454 | + Pi => | |
| 455 | + ix = jp.i; | |
| 456 | + Px2c0 => | |
| 457 | + ix = jp.x2c0.ix; | |
| 458 | + * => | |
| 459 | + badpick("getname[Pi|Px2c0]"); | |
| 460 | + } | |
| 461 | + pick c := class.cps[ix] { | |
| 462 | + Pfmiref => | |
| 463 | + pick n := class.cps[c.fmiref.name_type_index] { | |
| 464 | + Pnat => | |
| 465 | + return STRING(n.nat.name_index); | |
| 466 | + * => | |
| 467 | + badpick("getname[Pnat]"); | |
| 468 | + } | |
| 469 | + * => | |
| 470 | + badpick("getname[Pfmiref]"); | |
| 471 | + } | |
| 472 | + return nil; | |
| 473 | +} | |
| 474 | + | |
| 475 | +getsig(j: ref Jinst): string | |
| 476 | +{ | |
| 477 | + ix: int; | |
| 478 | + | |
| 479 | + pick jp := j { | |
| 480 | + Pi => | |
| 481 | + ix = jp.i; | |
| 482 | + Px2c0 => | |
| 483 | + ix = jp.x2c0.ix; | |
| 484 | + * => | |
| 485 | + badpick("getsig[Pi|Px2c0]"); | |
| 486 | + } | |
| 487 | + pick c := class.cps[ix] { | |
| 488 | + Pfmiref => | |
| 489 | + pick n := class.cps[c.fmiref.name_type_index] { | |
| 490 | + Pnat => | |
| 491 | + return STRING(n.nat.sig_index); | |
| 492 | + * => | |
| 493 | + badpick("getsig[Pnat]"); | |
| 494 | + } | |
| 495 | + * => | |
| 496 | + badpick("getsig[Pfmiref]"); | |
| 497 | + } | |
| 498 | + return nil; | |
| 499 | +} | |
| 500 | + | |
| 501 | +getfs(j: ref Jinst) | |
| 502 | +{ | |
| 503 | + r: ref Result; | |
| 504 | + sig: string; | |
| 505 | + | |
| 506 | + sig = getsig(j); | |
| 507 | + if(int j.op == Jgetfield) | |
| 508 | + useone(j, 'L'); | |
| 509 | + addrsind(j.dst, Afp, -1); | |
| 510 | + r = ref Result(jvmtype(sig[0]), j.pc); | |
| 511 | + j.jtype = jvmtype(sig[0]); | |
| 512 | + jvmpush(r); | |
| 513 | +} | |
| 514 | + | |
| 515 | +putfs(j: ref Jinst) | |
| 516 | +{ | |
| 517 | + sig: string; | |
| 518 | + | |
| 519 | + sig = getsig(j); | |
| 520 | + if(int j.op == Jputstatic) | |
| 521 | + useone(j, int jvmtype(sig[0])); | |
| 522 | + else | |
| 523 | + usetwo(j, byte 'L', jvmtype(sig[0])); | |
| 524 | +} | |
| 525 | + | |
| 526 | +invoke(j: ref Jinst) | |
| 527 | +{ | |
| 528 | + name, sig, savesig: string; | |
| 529 | + i, nargs, wargs: int; | |
| 530 | + args: array of ref Result; | |
| 531 | + rv: ref Result; | |
| 532 | + | |
| 533 | + name = getname(j); | |
| 534 | + if(name[0] == '<' && (name != "<init>" || int j.op != Jinvokespecial)) | |
| 535 | + verifyerror(j); | |
| 536 | + | |
| 537 | + # count arguments | |
| 538 | + sig = getsig(j); | |
| 539 | + nargs = 0; | |
| 540 | + wargs = 0; | |
| 541 | + sig = sig[1:]; # skip '(' | |
| 542 | + savesig = sig; | |
| 543 | + while(sig[0] != ')') { | |
| 544 | + nargs++; | |
| 545 | + wargs++; | |
| 546 | + if(sig[0] == 'J' || sig[0] == 'D') | |
| 547 | + wargs++; | |
| 548 | + sig = nextjavatype(sig); | |
| 549 | + } | |
| 550 | + if(int j.op != Jinvokestatic) { | |
| 551 | + nargs++; | |
| 552 | + wargs++; | |
| 553 | + } | |
| 554 | + if(wargs > 255) | |
| 555 | + verifyerror(j); | |
| 556 | + pick jp := j { | |
| 557 | + Px2c0 => | |
| 558 | + if(jp.x2c0.narg != wargs) | |
| 559 | + verifyerror(j); | |
| 560 | + } | |
| 561 | + | |
| 562 | + # collect and typecheck arguments | |
| 563 | + if(nargs > 0) { | |
| 564 | + srcalloc(j, nargs); | |
| 565 | + args = array [nargs] of ref Result; | |
| 566 | + for(i = nargs-1; i >= 0; i--) { | |
| 567 | + args[i] = jvmpop(); | |
| 568 | + j.src[i] = args[i].pc; | |
| 569 | + } | |
| 570 | + i = 0; | |
| 571 | + if(int j.op != Jinvokestatic) { | |
| 572 | + typecheck(args[0], byte 'L'); | |
| 573 | + i++; | |
| 574 | + } | |
| 575 | + sig = savesig; | |
| 576 | + while(sig[0] != ')') { | |
| 577 | + typecheck(args[i], jvmtype(sig[0])); | |
| 578 | + i++; | |
| 579 | + sig = nextjavatype(sig); | |
| 580 | + } | |
| 581 | + args = nil; | |
| 582 | + } | |
| 583 | + | |
| 584 | + # return type | |
| 585 | + if(sig[1] != 'V') { # skip ')' | |
| 586 | + addrsind(j.dst, Afp, -1); | |
| 587 | + rv = ref Result(jvmtype(sig[1]), j.pc); | |
| 588 | + j.jtype = jvmtype(sig[1]); | |
| 589 | + jvmpush(rv); | |
| 590 | + } | |
| 591 | +} | |
| 592 | + | |
| 593 | +javareturn(j: ref Jinst) | |
| 594 | +{ | |
| 595 | + jtype: int; | |
| 596 | + | |
| 597 | + case int j.op { | |
| 598 | + Jireturn => | |
| 599 | + jtype = 'I'; | |
| 600 | + Jlreturn => | |
| 601 | + jtype = 'J'; | |
| 602 | + Jfreturn => | |
| 603 | + jtype = 'F'; | |
| 604 | + Jdreturn => | |
| 605 | + jtype = 'D'; | |
| 606 | + Jareturn => | |
| 607 | + jtype = 'L'; | |
| 608 | + Jreturn => | |
| 609 | + jtype = 'V'; | |
| 610 | + } | |
| 611 | + if(jtype != rettype && jtype + rettype != 'L' + '[') | |
| 612 | + verifyerror(j); | |
| 613 | + if(int j.op != Jreturn) | |
| 614 | + useone(j, jtype); | |
| 615 | +} | |
| 616 | + | |
| 617 | +ldc(j: ref Jinst) | |
| 618 | +{ | |
| 619 | + pick jp := j { | |
| 620 | + Pi => | |
| 621 | + ix = jp.i; | |
| 622 | + * => | |
| 623 | + badpick("ldc[1]"); | |
| 624 | + } | |
| 625 | + | |
| 626 | + pick c := class.cps[ix] { | |
| 627 | + Ptdouble => | |
| 628 | + jtype: int; | |
| 629 | + if(int class.cts[ix] == CON_Float) | |
| 630 | + jtype = 'F'; | |
| 631 | + else | |
| 632 | + jtype = 'D'; | |
| 633 | + mpconst(j, jtype, mpreal(c.tdouble)); | |
| 634 | + Ptvlong => | |
| 635 | + mpconst(j, 'J', mplong(c.tvlong)); | |
| 636 | + Ptint => | |
| 637 | + if(notimmable(c.tint)) | |
| 638 | + mpconst(j, 'I', mpint(c.tint)); | |
| 639 | + else | |
| 640 | + iconst(j, c.tint); | |
| 641 | + Pstring_index => | |
| 642 | + mpconst(j, 'L', mpstring(STRING(c.string_index))); | |
| 643 | + *j.movsrc = *j.dst; | |
| 644 | + addrsind(j.dst, Afp, -1); | |
| 645 | + Pci => | |
| 646 | + if (class.maj < 50) | |
| 647 | + badpick("ldc[2]"); | |
| 648 | + # TODO: is this actually correct? | |
| 649 | + mpconst(j, 'L', mpstring(STRING(c.ci.name_index))); | |
| 650 | + *j.movsrc = *j.dst; | |
| 651 | + addrsind(j.dst, Afp, -1); | |
| 652 | + * => | |
| 653 | + badpick("ldc[2]"); | |
| 654 | + } | |
| 655 | +} | |
| 656 | + | |
| 657 | +oneword(j: ref Jinst, jtype: byte) | |
| 658 | +{ | |
| 659 | + if(jtype == byte 'J' || jtype == byte 'D') | |
| 660 | + verifyerror(j); | |
| 661 | +} | |
| 662 | + | |
| 663 | +javapop(j: ref Jinst) | |
| 664 | +{ | |
| 665 | + r1, r2: ref Result; | |
| 666 | + n: int; | |
| 667 | + | |
| 668 | + r1 = jvmpop(); | |
| 669 | + n = 1; | |
| 670 | + case int j.op { | |
| 671 | + Jpop => | |
| 672 | + oneword(j, r1.jtype); | |
| 673 | + Jpop2 => | |
| 674 | + if(r1.jtype != byte 'J' && r1.jtype != byte 'D') { | |
| 675 | + r2 = jvmpop(); | |
| 676 | + n = 2; | |
| 677 | + oneword(j, r2.jtype); | |
| 678 | + } | |
| 679 | + } | |
| 680 | + srcalloc(j, n); | |
| 681 | + j.src[0] = r1.pc; | |
| 682 | + if(n == 2) # pop2 | |
| 683 | + j.src[1] = r2.pc; | |
| 684 | +} | |
| 685 | + | |
| 686 | +javadup(j: ref Jinst) | |
| 687 | +{ | |
| 688 | + w1, w2, w3, w4: ref Result; | |
| 689 | + n: int; # number of stack items duplicated | |
| 690 | + | |
| 691 | + n = 1; | |
| 692 | + case int j.op { | |
| 693 | + Jdup => | |
| 694 | + w1 = jvmpop(); | |
| 695 | + oneword(j, w1.jtype); | |
| 696 | + jvmpush(w1); | |
| 697 | + jvmpush(w1); | |
| 698 | + Jdup_x1 => | |
| 699 | + w1 = jvmpop(); | |
| 700 | + oneword(j, w1.jtype); | |
| 701 | + w2 = jvmpop(); | |
| 702 | + oneword(j, w2.jtype); | |
| 703 | + jvmpush(w1); | |
| 704 | + jvmpush(w2); | |
| 705 | + jvmpush(w1); | |
| 706 | + Jdup_x2 => | |
| 707 | + w1 = jvmpop(); | |
| 708 | + oneword(j, w1.jtype); | |
| 709 | + w2 = jvmpop(); | |
| 710 | + if(w2.jtype == byte 'J' || w2.jtype == byte 'D') { | |
| 711 | + jvmpush(w1); | |
| 712 | + } else { | |
| 713 | + w3 = jvmpop(); | |
| 714 | + oneword(j, w3.jtype); | |
| 715 | + jvmpush(w1); | |
| 716 | + jvmpush(w3); | |
| 717 | + } | |
| 718 | + jvmpush(w2); | |
| 719 | + jvmpush(w1); | |
| 720 | + Jdup2 => | |
| 721 | + w1 = jvmpop(); | |
| 722 | + if(w1.jtype == byte 'J' || w1.jtype == byte 'D') { | |
| 723 | + jvmpush(w1); | |
| 724 | + } else { | |
| 725 | + n = 2; | |
| 726 | + w2 = jvmpop(); | |
| 727 | + oneword(j, w2.jtype); | |
| 728 | + jvmpush(w2); | |
| 729 | + jvmpush(w1); | |
| 730 | + jvmpush(w2); | |
| 731 | + } | |
| 732 | + jvmpush(w1); | |
| 733 | + Jdup2_x1 => | |
| 734 | + w1 = jvmpop(); | |
| 735 | + if(w1.jtype == byte 'J' || w1.jtype == byte 'D') { | |
| 736 | + w3 = jvmpop(); | |
| 737 | + oneword(j, w3.jtype); | |
| 738 | + jvmpush(w1); | |
| 739 | + jvmpush(w3); | |
| 740 | + } else { | |
| 741 | + n = 2; | |
| 742 | + w2 = jvmpop(); | |
| 743 | + oneword(j, w2.jtype); | |
| 744 | + w3 = jvmpop(); | |
| 745 | + oneword(j, w3.jtype); | |
| 746 | + jvmpush(w2); | |
| 747 | + jvmpush(w1); | |
| 748 | + jvmpush(w3); | |
| 749 | + jvmpush(w2); | |
| 750 | + } | |
| 751 | + jvmpush(w1); | |
| 752 | + Jdup2_x2 => | |
| 753 | + w1 = jvmpop(); | |
| 754 | + if(w1.jtype != byte 'J' && w1.jtype != byte 'D') { | |
| 755 | + n = 2; | |
| 756 | + w2 = jvmpop(); | |
| 757 | + oneword(j, w2.jtype); | |
| 758 | + } | |
| 759 | + w3 = jvmpop(); | |
| 760 | + if(w3.jtype != byte 'J' && w3.jtype != byte 'D') { | |
| 761 | + w4 = jvmpop(); | |
| 762 | + oneword(j, w4.jtype); | |
| 763 | + } | |
| 764 | + | |
| 765 | + if(w1.jtype != byte 'J' && w1.jtype != byte 'D') | |
| 766 | + jvmpush(w2); | |
| 767 | + jvmpush(w1); | |
| 768 | + if(w3.jtype != byte 'J' && w3.jtype != byte 'D') | |
| 769 | + jvmpush(w4); | |
| 770 | + jvmpush(w3); | |
| 771 | + if(w1.jtype != byte 'J' && w1.jtype != byte 'D') | |
| 772 | + jvmpush(w2); | |
| 773 | + jvmpush(w1); | |
| 774 | + } | |
| 775 | + srcalloc(j, n); | |
| 776 | + j.src[0] = w1.pc; | |
| 777 | + if(n == 2) | |
| 778 | + j.src[1] = w2.pc; | |
| 779 | +} | |
| 780 | + | |
| 781 | +javaswap(j: ref Jinst) | |
| 782 | +{ | |
| 783 | + w1, w2: ref Result; | |
| 784 | + | |
| 785 | + w1 = jvmpop(); | |
| 786 | + oneword(j, w1.jtype); | |
| 787 | + w2 = jvmpop(); | |
| 788 | + oneword(j, w2.jtype); | |
| 789 | + jvmpush(w1); | |
| 790 | + jvmpush(w2); | |
| 791 | +} | |
| 792 | + | |
| 793 | +simjinst(j: ref Jinst) | |
| 794 | +{ | |
| 795 | + jpi: ref Jinst.Pi; | |
| 796 | + jpx1c: ref Jinst.Px1c; | |
| 797 | + jpx2d: ref Jinst.Px2d; | |
| 798 | + jpw: ref Jinst.Pw; | |
| 799 | + | |
| 800 | + pick jp := j { | |
| 801 | + Pi => | |
| 802 | + jpi = jp; | |
| 803 | + Px1c => | |
| 804 | + jpx1c = jp; | |
| 805 | + Px2d => | |
| 806 | + jpx2d = jp; | |
| 807 | + Pw => | |
| 808 | + jpw = jp; | |
| 809 | + } | |
| 810 | + | |
| 811 | + case int j.op { | |
| 812 | + Jnop => | |
| 813 | + ; | |
| 814 | + Jaconst_null => | |
| 815 | + mpconst(j, 'L', 0); | |
| 816 | + Jiconst_m1 => | |
| 817 | + iconst(j, -1); | |
| 818 | + Jiconst_0 => | |
| 819 | + iconst(j, 0); | |
| 820 | + Jiconst_1 => | |
| 821 | + iconst(j, 1); | |
| 822 | + Jiconst_2 => | |
| 823 | + iconst(j, 2); | |
| 824 | + Jiconst_3 => | |
| 825 | + iconst(j, 3); | |
| 826 | + Jiconst_4 => | |
| 827 | + iconst(j, 4); | |
| 828 | + Jiconst_5 => | |
| 829 | + iconst(j, 5); | |
| 830 | + Jlconst_0 => | |
| 831 | + mpconst(j, 'J', mplong(big 0)); | |
| 832 | + Jlconst_1 => | |
| 833 | + mpconst(j, 'J', mplong(big 1)); | |
| 834 | + Jfconst_0 => | |
| 835 | + mpconst(j, 'F', mpreal(0.0)); | |
| 836 | + Jfconst_1 => | |
| 837 | + mpconst(j, 'F', mpreal(1.0)); | |
| 838 | + Jfconst_2 => | |
| 839 | + mpconst(j, 'F', mpreal(2.0)); | |
| 840 | + Jdconst_0 => | |
| 841 | + mpconst(j, 'D', mpreal(0.0)); | |
| 842 | + Jdconst_1 => | |
| 843 | + mpconst(j, 'D', mpreal(1.0)); | |
| 844 | + Jbipush or | |
| 845 | + Jsipush => | |
| 846 | + iconst(j, jpi.i); | |
| 847 | + Jldc or | |
| 848 | + Jldc_w or | |
| 849 | + Jldc2_w => | |
| 850 | + ldc(j); | |
| 851 | + Jiload => | |
| 852 | + javaload(j, 'I', jpi.i); | |
| 853 | + Jlload => | |
| 854 | + javaload(j, 'J', jpi.i); | |
| 855 | + Jfload => | |
| 856 | + javaload(j, 'F', jpi.i); | |
| 857 | + Jdload => | |
| 858 | + javaload(j, 'D', jpi.i); | |
| 859 | + Jaload => | |
| 860 | + javaload(j, 'L', jpi.i); | |
| 861 | + Jiload_0 => | |
| 862 | + javaload(j, 'I', 0); | |
| 863 | + Jiload_1 => | |
| 864 | + javaload(j, 'I', 1); | |
| 865 | + Jiload_2 => | |
| 866 | + javaload(j, 'I', 2); | |
| 867 | + Jiload_3 => | |
| 868 | + javaload(j, 'I', 3); | |
| 869 | + Jlload_0 => | |
| 870 | + javaload(j, 'J', 0); | |
| 871 | + Jlload_1 => | |
| 872 | + javaload(j, 'J', 1); | |
| 873 | + Jlload_2 => | |
| 874 | + javaload(j, 'J', 2); | |
| 875 | + Jlload_3 => | |
| 876 | + javaload(j, 'J', 3); | |
| 877 | + Jfload_0 => | |
| 878 | + javaload(j, 'F', 0); | |
| 879 | + Jfload_1 => | |
| 880 | + javaload(j, 'F', 1); | |
| 881 | + Jfload_2 => | |
| 882 | + javaload(j, 'F', 2); | |
| 883 | + Jfload_3 => | |
| 884 | + javaload(j, 'F', 3); | |
| 885 | + Jdload_0 => | |
| 886 | + javaload(j, 'D', 0); | |
| 887 | + Jdload_1 => | |
| 888 | + javaload(j, 'D', 1); | |
| 889 | + Jdload_2 => | |
| 890 | + javaload(j, 'D', 2); | |
| 891 | + Jdload_3 => | |
| 892 | + javaload(j, 'D', 3); | |
| 893 | + Jaload_0 => | |
| 894 | + javaload(j, 'L', 0); | |
| 895 | + Jaload_1 => | |
| 896 | + javaload(j, 'L', 1); | |
| 897 | + Jaload_2 => | |
| 898 | + javaload(j, 'L', 2); | |
| 899 | + Jaload_3 => | |
| 900 | + javaload(j, 'L', 3); | |
| 901 | + Jbaload or | |
| 902 | + Jcaload or | |
| 903 | + Jsaload or | |
| 904 | + Jiaload => | |
| 905 | + arrayload(j, 'I'); | |
| 906 | + Jlaload => | |
| 907 | + arrayload(j, 'J'); | |
| 908 | + Jfaload => | |
| 909 | + arrayload(j, 'F'); | |
| 910 | + Jdaload => | |
| 911 | + arrayload(j, 'D'); | |
| 912 | + Jaaload => | |
| 913 | + arrayload(j, 'L'); | |
| 914 | + Jistore => | |
| 915 | + storechk(jpi.i, 'I'); | |
| 916 | + javastore(j, 'I', jpi.i); | |
| 917 | + Jlstore => | |
| 918 | + storechk(jpi.i, 'J'); | |
| 919 | + javastore(j, 'J', jpi.i); | |
| 920 | + Jfstore => | |
| 921 | + storechk(jpi.i, 'F'); | |
| 922 | + javastore(j, 'F', jpi.i); | |
| 923 | + Jdstore => | |
| 924 | + storechk(jpi.i, 'D'); | |
| 925 | + javastore(j, 'D', jpi.i); | |
| 926 | + Jastore => # could be start of finally block or handler | |
| 927 | + storechk(jpi.i, 'L'); | |
| 928 | + javastore(j, 'L', jpi.i); | |
| 929 | + Jistore_0 => | |
| 930 | + storechk(0, 'I'); | |
| 931 | + javastore(j, 'I', 0); | |
| 932 | + Jistore_1 => | |
| 933 | + storechk(1, 'I'); | |
| 934 | + javastore(j, 'I', 1); | |
| 935 | + Jistore_2 => | |
| 936 | + storechk(2, 'I'); | |
| 937 | + javastore(j, 'I', 2); | |
| 938 | + Jistore_3 => | |
| 939 | + storechk(3, 'I'); | |
| 940 | + javastore(j, 'I', 3); | |
| 941 | + Jlstore_0 => | |
| 942 | + storechk(0, 'J'); | |
| 943 | + javastore(j, 'J', 0); | |
| 944 | + Jlstore_1 => | |
| 945 | + storechk(1, 'J'); | |
| 946 | + javastore(j, 'J', 1); | |
| 947 | + Jlstore_2 => | |
| 948 | + storechk(2, 'J'); | |
| 949 | + javastore(j, 'J', 2); | |
| 950 | + Jlstore_3 => | |
| 951 | + storechk(3, 'J'); | |
| 952 | + javastore(j, 'J', 3); | |
| 953 | + Jfstore_0 => | |
| 954 | + storechk(0, 'F'); | |
| 955 | + javastore(j, 'F', 0); | |
| 956 | + Jfstore_1 => | |
| 957 | + storechk(1, 'F'); | |
| 958 | + javastore(j, 'F', 1); | |
| 959 | + Jfstore_2 => | |
| 960 | + storechk(2, 'F'); | |
| 961 | + javastore(j, 'F', 2); | |
| 962 | + Jfstore_3 => | |
| 963 | + storechk(3, 'F'); | |
| 964 | + javastore(j, 'F', 3); | |
| 965 | + Jdstore_0 => | |
| 966 | + storechk(0, 'D'); | |
| 967 | + javastore(j, 'D', 0); | |
| 968 | + Jdstore_1 => | |
| 969 | + storechk(1, 'D'); | |
| 970 | + javastore(j, 'D', 1); | |
| 971 | + Jdstore_2 => | |
| 972 | + storechk(2, 'D'); | |
| 973 | + javastore(j, 'D', 2); | |
| 974 | + Jdstore_3 => | |
| 975 | + storechk(3, 'D'); | |
| 976 | + javastore(j, 'D', 3); | |
| 977 | + Jastore_0 => # could be start of finally block or handler | |
| 978 | + storechk(0, 'L'); | |
| 979 | + javastore(j, 'L', 0); | |
| 980 | + Jastore_1 => | |
| 981 | + storechk(1, 'L'); | |
| 982 | + javastore(j, 'L', 1); | |
| 983 | + Jastore_2 => | |
| 984 | + storechk(2, 'L'); | |
| 985 | + javastore(j, 'L', 2); | |
| 986 | + Jastore_3 => | |
| 987 | + storechk(3, 'L'); | |
| 988 | + javastore(j, 'L', 3); | |
| 989 | + Jbastore or | |
| 990 | + Jcastore or | |
| 991 | + Jsastore or | |
| 992 | + Jiastore => | |
| 993 | + arraystore(j, 'I'); | |
| 994 | + Jlastore => | |
| 995 | + arraystore(j, 'J'); | |
| 996 | + Jfastore => | |
| 997 | + arraystore(j, 'F'); | |
| 998 | + Jdastore => | |
| 999 | + arraystore(j, 'D'); | |
| 1000 | + Jaastore => | |
| 1001 | + arraystore(j, 'L'); | |
| 1002 | + Jpop or | |
| 1003 | + Jpop2 => | |
| 1004 | + javapop(j); | |
| 1005 | + Jdup or | |
| 1006 | + Jdup_x1 or | |
| 1007 | + Jdup_x2 or | |
| 1008 | + Jdup2 or | |
| 1009 | + Jdup2_x1 or | |
| 1010 | + Jdup2_x2 => | |
| 1011 | + javadup(j); | |
| 1012 | + Jswap => | |
| 1013 | + javaswap(j); | |
| 1014 | + Jiadd or | |
| 1015 | + Jisub or | |
| 1016 | + Jimul or | |
| 1017 | + Jidiv or | |
| 1018 | + Jirem or | |
| 1019 | + Jishl or | |
| 1020 | + Jishr or | |
| 1021 | + Jiushr or | |
| 1022 | + Jiand or | |
| 1023 | + Jior or | |
| 1024 | + Jixor => | |
| 1025 | + binop(j, 'I', 'I', 'I'); | |
| 1026 | + Jladd or | |
| 1027 | + Jlsub or | |
| 1028 | + Jlmul or | |
| 1029 | + Jldiv or | |
| 1030 | + Jlrem or | |
| 1031 | + Jland or | |
| 1032 | + Jlor or | |
| 1033 | + Jlxor => | |
| 1034 | + binop(j, 'J', 'J', 'J'); | |
| 1035 | + Jfadd or | |
| 1036 | + Jfsub or | |
| 1037 | + Jfmul or | |
| 1038 | + Jfdiv or | |
| 1039 | + Jfrem => | |
| 1040 | + binop(j, 'F', 'F', 'F'); | |
| 1041 | + Jdadd or | |
| 1042 | + Jdsub or | |
| 1043 | + Jdmul or | |
| 1044 | + Jddiv or | |
| 1045 | + Jdrem => | |
| 1046 | + binop(j, 'D', 'D', 'D'); | |
| 1047 | + Jineg => | |
| 1048 | + unop(j, 'I', 'I'); | |
| 1049 | + Jlneg => | |
| 1050 | + unop(j, 'J', 'J'); | |
| 1051 | + Jfneg => | |
| 1052 | + unop(j, 'F', 'F'); | |
| 1053 | + Jdneg => | |
| 1054 | + unop(j, 'D', 'D'); | |
| 1055 | + Jlshl or | |
| 1056 | + Jlshr or | |
| 1057 | + Jlushr => | |
| 1058 | + binop(j, 'J', 'I', 'J'); | |
| 1059 | + Jiinc => | |
| 1060 | + verifyindex(j, 'I', jpx1c.x1c.ix); | |
| 1061 | + storechk(jpx1c.x1c.ix, 'I'); | |
| 1062 | + Ji2l => | |
| 1063 | + unop(j, 'I', 'J'); | |
| 1064 | + Ji2f => | |
| 1065 | + unop(j, 'I', 'F'); | |
| 1066 | + Ji2d => | |
| 1067 | + unop(j, 'I', 'D'); | |
| 1068 | + Jl2i => | |
| 1069 | + unop(j, 'J', 'I'); | |
| 1070 | + Jl2f => | |
| 1071 | + unop(j, 'J', 'F'); | |
| 1072 | + Jl2d => | |
| 1073 | + unop(j, 'J', 'D'); | |
| 1074 | + Jf2i => | |
| 1075 | + unop(j, 'F', 'I'); | |
| 1076 | + Jf2l => | |
| 1077 | + unop(j, 'F', 'J'); | |
| 1078 | + Jf2d => | |
| 1079 | + unop(j, 'F', 'D'); | |
| 1080 | + Jd2i => | |
| 1081 | + unop(j, 'D', 'I'); | |
| 1082 | + Jd2l => | |
| 1083 | + unop(j, 'D', 'J'); | |
| 1084 | + Jd2f => | |
| 1085 | + unop(j, 'D', 'F'); | |
| 1086 | + Ji2b or | |
| 1087 | + Ji2c or | |
| 1088 | + Ji2s => | |
| 1089 | + unop(j, 'I', 'I'); | |
| 1090 | + Jlcmp => | |
| 1091 | + binop(j, 'J', 'J', 'I'); | |
| 1092 | + Jfcmpl or | |
| 1093 | + Jfcmpg => | |
| 1094 | + binop(j, 'F', 'F', 'I'); | |
| 1095 | + Jdcmpl or | |
| 1096 | + Jdcmpg => | |
| 1097 | + binop(j, 'D', 'D', 'I'); | |
| 1098 | + Jifeq or | |
| 1099 | + Jifne or | |
| 1100 | + Jiflt or | |
| 1101 | + Jifge or | |
| 1102 | + Jifgt or | |
| 1103 | + Jifle => | |
| 1104 | + useone(j, 'I'); | |
| 1105 | + Jif_icmpeq or | |
| 1106 | + Jif_icmpne or | |
| 1107 | + Jif_icmplt or | |
| 1108 | + Jif_icmpge or | |
| 1109 | + Jif_icmpgt or | |
| 1110 | + Jif_icmple => | |
| 1111 | + usetwo(j, byte 'I', byte 'I'); | |
| 1112 | + Jif_acmpeq or | |
| 1113 | + Jif_acmpne => | |
| 1114 | + usetwo(j, byte 'L', byte 'L'); | |
| 1115 | + Jgoto or | |
| 1116 | + Jgoto_w or | |
| 1117 | + Jjsr or # no push; not following ... | |
| 1118 | + Jjsr_w => # ... these branches | |
| 1119 | + ; | |
| 1120 | + Jret => | |
| 1121 | + verifyindex(j, 'L', jpi.i); | |
| 1122 | + Jtableswitch or | |
| 1123 | + Jlookupswitch => | |
| 1124 | + useone(j, 'I'); | |
| 1125 | + Jireturn or | |
| 1126 | + Jlreturn or | |
| 1127 | + Jfreturn or | |
| 1128 | + Jdreturn or | |
| 1129 | + Jareturn or | |
| 1130 | + Jreturn => | |
| 1131 | + javareturn(j); | |
| 1132 | + Jgetfield or | |
| 1133 | + Jgetstatic => | |
| 1134 | + getfs(j); | |
| 1135 | + Jputfield or | |
| 1136 | + Jputstatic => | |
| 1137 | + putfs(j); | |
| 1138 | + Jinvokevirtual or | |
| 1139 | + Jinvokespecial or | |
| 1140 | + Jinvokestatic or | |
| 1141 | + Jinvokeinterface => | |
| 1142 | + invoke(j); | |
| 1143 | + Jxxxunusedxxx => | |
| 1144 | + ; | |
| 1145 | + Jnew => | |
| 1146 | + javanew(jpi); | |
| 1147 | + Jnewarray => | |
| 1148 | + unop(j, 'I', '['); | |
| 1149 | + Janewarray => | |
| 1150 | + anewarray(jpi); | |
| 1151 | + Jarraylength => | |
| 1152 | + unop(j, '[', 'I'); | |
| 1153 | + Jathrow => | |
| 1154 | + useone(j, 'L'); | |
| 1155 | + Jcheckcast => | |
| 1156 | + unop(j, 'L', 'L'); | |
| 1157 | + Jinstanceof => | |
| 1158 | + unop(j, 'L', 'I'); | |
| 1159 | + Jmonitorenter or | |
| 1160 | + Jmonitorexit => | |
| 1161 | + useone(j, 'L'); | |
| 1162 | + Jwide => | |
| 1163 | + case int jpw.w.op { | |
| 1164 | + Jiload => | |
| 1165 | + javaload(j, 'I', jpw.w.ix); | |
| 1166 | + Jlload => | |
| 1167 | + javaload(j, 'J', jpw.w.ix); | |
| 1168 | + Jfload => | |
| 1169 | + javaload(j, 'F', jpw.w.ix); | |
| 1170 | + Jdload => | |
| 1171 | + javaload(j, 'D', jpw.w.ix); | |
| 1172 | + Jaload => | |
| 1173 | + javaload(j, 'L', jpw.w.ix); | |
| 1174 | + Jistore => | |
| 1175 | + storechk(jpw.w.ix, 'I'); | |
| 1176 | + javastore(j, 'I', jpw.w.ix); | |
| 1177 | + Jlstore => | |
| 1178 | + storechk(jpw.w.ix, 'J'); | |
| 1179 | + javastore(j, 'J', jpw.w.ix); | |
| 1180 | + Jfstore => | |
| 1181 | + storechk(jpw.w.ix, 'F'); | |
| 1182 | + javastore(j, 'F', jpw.w.ix); | |
| 1183 | + Jdstore => | |
| 1184 | + storechk(jpw.w.ix, 'D'); | |
| 1185 | + javastore(j, 'D', jpw.w.ix); | |
| 1186 | + Jastore => | |
| 1187 | + storechk(jpw.w.ix, 'L'); | |
| 1188 | + javastore(j, 'L', jpw.w.ix); | |
| 1189 | + Jret => | |
| 1190 | + verifyindex(j, 'L', jpw.w.ix); | |
| 1191 | + Jiinc => | |
| 1192 | + verifyindex(j, 'I', jpw.w.ix); | |
| 1193 | + storechk(jpw.w.ix, 'I'); | |
| 1194 | + } | |
| 1195 | + Jmultianewarray => | |
| 1196 | + multianewarray(jpx2d); | |
| 1197 | + Jifnull or | |
| 1198 | + Jifnonnull => | |
| 1199 | + useone(j, 'L'); | |
| 1200 | + } | |
| 1201 | +} | |
| 1202 | + | |
| 1203 | +# | |
| 1204 | +# Take snapshot of current stack. | |
| 1205 | +# | |
| 1206 | + | |
| 1207 | +snapstack(): array of ref StkSnap | |
| 1208 | +{ | |
| 1209 | + s: array of ref StkSnap; | |
| 1210 | + i: int; | |
| 1211 | + | |
| 1212 | + s = array [jvmtos] of ref StkSnap; | |
| 1213 | + for(i = 0; i < jvmtos; i++) { | |
| 1214 | + s[i] = ref StkSnap(byte 0, 0, nil); | |
| 1215 | + s[i].jtype = jvmstack[i].jtype; | |
| 1216 | + s[i].npc = 1; | |
| 1217 | + s[i].pc = array [1] of int; | |
| 1218 | + s[i].pc[0] = jvmstack[i].pc; | |
| 1219 | + } | |
| 1220 | + return s; | |
| 1221 | +} | |
| 1222 | + | |
| 1223 | +# | |
| 1224 | +# Merge current stack into bb.entrystk. | |
| 1225 | +# | |
| 1226 | + | |
| 1227 | +stackmerge(bb: ref BB) | |
| 1228 | +{ | |
| 1229 | + s: ref StkSnap; | |
| 1230 | + i, j: int; | |
| 1231 | + pct: int; | |
| 1232 | + jtype1, jtype2: byte; | |
| 1233 | + | |
| 1234 | + if(jvmtos == 0) { | |
| 1235 | + if(bb.entrysz != 0) | |
| 1236 | + verifyerrormess("stack merge"); | |
| 1237 | + return; | |
| 1238 | + } | |
| 1239 | + if(bb.entrystk == nil) { | |
| 1240 | + bb.entrysz = jvmtos; | |
| 1241 | + bb.entrystk = snapstack(); | |
| 1242 | + return; | |
| 1243 | + } | |
| 1244 | + # true stack merge | |
| 1245 | + if(bb.entrysz != jvmtos) | |
| 1246 | + verifyerrormess("stack merge"); | |
| 1247 | +outer: for(i = 0; i < jvmtos; i++) { | |
| 1248 | + jtype1 = jvmstack[i].jtype; | |
| 1249 | + jtype2 = bb.entrystk[i].jtype; | |
| 1250 | + if(jtype1 != jtype2 && (int jtype1 + int jtype2) != 'L' + '[') | |
| 1251 | + verifyerrormess("stack merge"); | |
| 1252 | + s = bb.entrystk[i]; | |
| 1253 | + for(j = 0; j < s.npc; j++) { | |
| 1254 | + if(s.pc[j] == jvmstack[i].pc) | |
| 1255 | + continue outer; | |
| 1256 | + } | |
| 1257 | + newpc := array [s.npc+1] of int; | |
| 1258 | + for(k := 0; k < s.npc; k++) | |
| 1259 | + newpc[k] = s.pc[k]; | |
| 1260 | + s.pc = newpc; | |
| 1261 | + s.pc[s.npc++] = jvmstack[i].pc; | |
| 1262 | + # percolate into sorted order | |
| 1263 | + for(j = s.npc-1; j > 0; j--) { | |
| 1264 | + if(s.pc[j-1] > s.pc[j]) { | |
| 1265 | + pct = s.pc[j-1]; | |
| 1266 | + s.pc[j-1] = s.pc[j]; | |
| 1267 | + s.pc[j] = pct; | |
| 1268 | + } else | |
| 1269 | + break; | |
| 1270 | + } | |
| 1271 | + } | |
| 1272 | +} | |
| 1273 | + | |
| 1274 | +# | |
| 1275 | +# Simulate the instructions in a basic block. | |
| 1276 | +# | |
| 1277 | + | |
| 1278 | +simbb(bb: ref BB) | |
| 1279 | +{ | |
| 1280 | + i: int; | |
| 1281 | + j: ref Jinst; | |
| 1282 | + pc: int; | |
| 1283 | + | |
| 1284 | + if(bb.state == BB_POSTSIM) | |
| 1285 | + fatal("simbb: BB_POSTSIM"); | |
| 1286 | + | |
| 1287 | + jvminit(bb); | |
| 1288 | + pc = bb.js.pc; | |
| 1289 | + while(pc <= bb.je.pc) { | |
| 1290 | + j = code.j[pc]; | |
| 1291 | + simjinst(j); | |
| 1292 | + pc += j.size; | |
| 1293 | + } | |
| 1294 | + bb.state = BB_POSTSIM; | |
| 1295 | + | |
| 1296 | + if(jvmtos != 0) { | |
| 1297 | + bb.exitsz = jvmtos; | |
| 1298 | + bb.exitstk = snapstack(); | |
| 1299 | + } | |
| 1300 | + | |
| 1301 | + for(i = 0; i < bb.nsucc; i++) { | |
| 1302 | + stackmerge(bb.succ[i]); | |
| 1303 | + if(bb.succ[i].state == BB_PRESIM) | |
| 1304 | + bbput(bb.succ[i]); | |
| 1305 | + } | |
| 1306 | +} | |
| 1307 | + | |
| 1308 | +# | |
| 1309 | +# Simulate the Java VM on each of the method's basic blocks. | |
| 1310 | +# | |
| 1311 | + | |
| 1312 | +simjvm(sig: string) | |
| 1313 | +{ | |
| 1314 | + bb: ref BB; | |
| 1315 | + ix: int; | |
| 1316 | + | |
| 1317 | + ix = 1; # skip '(' | |
| 1318 | + while(sig[ix] != ')') | |
| 1319 | + ix++; | |
| 1320 | + rettype = int jvmtype(sig[ix+1]); | |
| 1321 | + | |
| 1322 | + jvmstack = array [code.max_stack] of ref Result; | |
| 1323 | + | |
| 1324 | + bbinit(); | |
| 1325 | + while((bb = bbget()) != nil) | |
| 1326 | + simbb(bb); | |
| 1327 | + | |
| 1328 | + jvmstack = nil; | |
| 1329 | +} | |
| @@ -0,0 +1,98 @@ | ||
| 1 | +# | |
| 2 | +# "Unify" results that are produced in one basic block and consumed | |
| 3 | +# in another. I.e., ensure that producers and consumers access results | |
| 4 | +# through consistent fp offsets. | |
| 5 | +# | |
| 6 | + | |
| 7 | +pushsucc(bb: ref BB) | |
| 8 | +{ | |
| 9 | + i: int; | |
| 10 | + | |
| 11 | + for(i = 0; i < bb.nsucc; i++) { | |
| 12 | + if(bb.succ[i].state == BB_POSTSIM) | |
| 13 | + bbput(bb.succ[i]); | |
| 14 | + } | |
| 15 | +} | |
| 16 | + | |
| 17 | +pass1(s: ref StkSnap): int | |
| 18 | +{ | |
| 19 | + j: ref Jinst; | |
| 20 | + i: int; | |
| 21 | + fpoff: int; | |
| 22 | + | |
| 23 | + fpoff = -1; | |
| 24 | + for(i = 0; i < s.npc; i++) { | |
| 25 | + j = code.j[s.pc[i]]; | |
| 26 | + if((isload(j) && j.movsrc.mode != byte Anone) | |
| 27 | + || (!isload(j) && j.dst.offset != -1)) { | |
| 28 | + if(fpoff == -1) | |
| 29 | + fpoff = j.dst.offset; | |
| 30 | + else if(fpoff != j.dst.offset) | |
| 31 | + fatal("pass1: can't"); | |
| 32 | + } | |
| 33 | + } | |
| 34 | + if(fpoff == -1) | |
| 35 | + fpoff = getreg(j2dtype(s.jtype)); | |
| 36 | + return fpoff; | |
| 37 | +} | |
| 38 | + | |
| 39 | +pass2(s: ref StkSnap, fpoff: int) | |
| 40 | +{ | |
| 41 | + j: ref Jinst; | |
| 42 | + i: int; | |
| 43 | + | |
| 44 | + for(i = 0; i < s.npc; i++) { | |
| 45 | + j = code.j[s.pc[i]]; | |
| 46 | + if(isload(j) && j.movsrc.mode == byte Anone) { | |
| 47 | + *j.movsrc = *j.dst; | |
| 48 | + j.dst.mode = byte Afp; | |
| 49 | + } | |
| 50 | + j.dst.offset = fpoff; | |
| 51 | + } | |
| 52 | +} | |
| 53 | + | |
| 54 | +unifybb(bb: ref BB) | |
| 55 | +{ | |
| 56 | + s: ref StkSnap; | |
| 57 | + n, m: int; | |
| 58 | + | |
| 59 | + if(bb.state == BB_POSTUNIFY) | |
| 60 | + fatal("unifybb: BB_POSTUNIFY"); | |
| 61 | + | |
| 62 | + if(bb.entrystk == nil) { | |
| 63 | + pushsucc(bb); | |
| 64 | + return; | |
| 65 | + } | |
| 66 | + | |
| 67 | + clearreg(); | |
| 68 | + reservereg(bb.entrystk, bb.entrysz); | |
| 69 | + reservereg(bb.exitstk, bb.exitsz); | |
| 70 | + | |
| 71 | + for(n = 0; n < bb.entrysz; n++) { | |
| 72 | + s = bb.entrystk[n]; | |
| 73 | + for(m = 0; m < s.npc; m++) { | |
| 74 | + reservereg(code.j[s.pc[m]].bb.entrystk, | |
| 75 | + code.j[s.pc[m]].bb.entrysz); | |
| 76 | + } | |
| 77 | + } | |
| 78 | + | |
| 79 | + for(n = 0; n < bb.entrysz; n++) { | |
| 80 | + s = bb.entrystk[n]; | |
| 81 | + if(s.npc == 1) | |
| 82 | + dstreg(code.j[s.pc[0]].dst, j2dtype(s.jtype)); | |
| 83 | + else | |
| 84 | + pass2(s, pass1(s)); | |
| 85 | + } | |
| 86 | + | |
| 87 | + bb.state = BB_POSTUNIFY; | |
| 88 | + pushsucc(bb); | |
| 89 | +} | |
| 90 | + | |
| 91 | +unify() | |
| 92 | +{ | |
| 93 | + bb: ref BB; | |
| 94 | + | |
| 95 | + bbinit(); | |
| 96 | + while((bb = bbget()) != nil) | |
| 97 | + unifybb(bb); | |
| 98 | +} | |
| @@ -0,0 +1,432 @@ | ||
| 1 | +# | |
| 2 | +# Utility functions. | |
| 3 | +# | |
| 4 | + | |
| 5 | +codeix: array of byte; | |
| 6 | +ix: int; | |
| 7 | + | |
| 8 | +uSet(x: array of byte) | |
| 9 | +{ | |
| 10 | + codeix = x; | |
| 11 | + ix = 0; | |
| 12 | +} | |
| 13 | + | |
| 14 | +boundscheck(n: int) | |
| 15 | +{ | |
| 16 | + if(ix+n-1 >= len codeix) | |
| 17 | + verifyerrormess("Attribute bounds"); | |
| 18 | +} | |
| 19 | + | |
| 20 | +uPtr(i: int): array of byte | |
| 21 | +{ | |
| 22 | + boundscheck(i); | |
| 23 | + return codeix[ix:ix+i]; | |
| 24 | +} | |
| 25 | + | |
| 26 | +uN(i: int) | |
| 27 | +{ | |
| 28 | + ix += i; | |
| 29 | +} | |
| 30 | + | |
| 31 | +u1(): byte | |
| 32 | +{ | |
| 33 | + boundscheck(1); | |
| 34 | + return codeix[ix++]; | |
| 35 | +} | |
| 36 | + | |
| 37 | +u2(): int | |
| 38 | +{ | |
| 39 | + l: int; | |
| 40 | + | |
| 41 | + boundscheck(2); | |
| 42 | + l = (int(codeix[ix])<<8) | int(codeix[ix+1]); | |
| 43 | + ix += 2; | |
| 44 | + return l; | |
| 45 | +} | |
| 46 | + | |
| 47 | +u4(): int | |
| 48 | +{ | |
| 49 | + l: int; | |
| 50 | + | |
| 51 | + boundscheck(4); | |
| 52 | + l = (int(codeix[ix])<<24) | (int(codeix[ix+1])<<16) | |
| 53 | + | (int(codeix[ix+2])<<8) | int(codeix[ix+3]); | |
| 54 | + ix += 4; | |
| 55 | + return l; | |
| 56 | +} | |
| 57 | + | |
| 58 | +getattr(): ref Attr | |
| 59 | +{ | |
| 60 | + a := ref Attr(0, 0, nil); | |
| 61 | + a.name = u2(); | |
| 62 | + verifycpindex(nil, a.name, 1 << CON_Utf8); | |
| 63 | + a.ln = u4(); | |
| 64 | + boundscheck(a.ln); | |
| 65 | + a.info = array [a.ln] of byte; | |
| 66 | + a.info[:] = codeix[ix:ix+a.ln]; | |
| 67 | + ix += a.ln; | |
| 68 | + return a; | |
| 69 | +} | |
| 70 | + | |
| 71 | +# | |
| 72 | +# Get the constantvalue_index of a ConstantValue attribute. | |
| 73 | +# | |
| 74 | + | |
| 75 | +CVattrindex(fp: ref Field): int | |
| 76 | +{ | |
| 77 | + i: int; | |
| 78 | + a: ref Attr; | |
| 79 | + | |
| 80 | + for(i = 0; i < fp.attr_count; i++) { | |
| 81 | + a = fp.attr_info[i]; | |
| 82 | + if(STRING(a.name) != "ConstantValue") | |
| 83 | + continue; | |
| 84 | + if(a.ln != 2) | |
| 85 | + verifyerrormess("ConstantValue attribute"); | |
| 86 | + return ((int a.info[0])<<8) | int a.info[1]; | |
| 87 | + } | |
| 88 | + return 0; | |
| 89 | +} | |
| 90 | + | |
| 91 | +# | |
| 92 | +# Align 'off' on an 'align'-byte boundary ('align' is a power of 2). | |
| 93 | +# | |
| 94 | + | |
| 95 | +align(off: int, align: int): int | |
| 96 | +{ | |
| 97 | + align--; | |
| 98 | + return (off + align) & ~align; | |
| 99 | +} | |
| 100 | + | |
| 101 | +# | |
| 102 | +# Set 'offset' bit in type descriptor 'map'. | |
| 103 | +# | |
| 104 | + | |
| 105 | +setbit(map: array of byte, offset: int) | |
| 106 | +{ | |
| 107 | + map[offset / (8*IBY2WD)] |= byte(1 << (7 - (offset / IBY2WD % 8))); | |
| 108 | +} | |
| 109 | + | |
| 110 | +# | |
| 111 | +# Trivial hash function from asm. | |
| 112 | +# | |
| 113 | + | |
| 114 | +hashval(s: string): int | |
| 115 | +{ | |
| 116 | + h, i: int; | |
| 117 | + | |
| 118 | + h = 0; | |
| 119 | + for(i = 0; i < len s; i++) | |
| 120 | + h = h*3 + s[i]; | |
| 121 | + if(h < 0) | |
| 122 | + h = -h; | |
| 123 | + return h % Hashsize; | |
| 124 | +} | |
| 125 | + | |
| 126 | +# | |
| 127 | +# Advance to the next Java type in a method descriptor. | |
| 128 | +# | |
| 129 | + | |
| 130 | +nextjavatype(s: string): string | |
| 131 | +{ | |
| 132 | + nlb: int; | |
| 133 | + | |
| 134 | + nlb = 0; | |
| 135 | + while(1) { | |
| 136 | + case s[0] { | |
| 137 | + 'L' => | |
| 138 | + (nil, s) = str->splitl(s, ";"); | |
| 139 | + return s[1:]; | |
| 140 | + 'V' or | |
| 141 | + 'Z' or | |
| 142 | + 'B' or | |
| 143 | + 'C' or | |
| 144 | + 'S' or | |
| 145 | + 'I' or | |
| 146 | + 'J' or | |
| 147 | + 'F' or | |
| 148 | + 'D' => | |
| 149 | + return s[1:]; | |
| 150 | + '[' => | |
| 151 | + if(++nlb < 256) | |
| 152 | + s = s[1:]; | |
| 153 | + else | |
| 154 | + s[0] = 'X'; # force verifyerrormess() | |
| 155 | + * => | |
| 156 | + verifyerrormess("field/method descriptor"); | |
| 157 | + } | |
| 158 | + } | |
| 159 | +} | |
| 160 | + | |
| 161 | +j2dtype(jtype: byte): byte | |
| 162 | +{ | |
| 163 | + dtype: byte; | |
| 164 | + | |
| 165 | + case int jtype { | |
| 166 | + 'Z' or | |
| 167 | + 'B' or | |
| 168 | + 'C' or | |
| 169 | + 'S' or | |
| 170 | + 'I' => | |
| 171 | + dtype = byte DIS_W; | |
| 172 | + 'J' or | |
| 173 | + 'F' or | |
| 174 | + 'D' => | |
| 175 | + dtype = byte DIS_L; | |
| 176 | + 'L' or | |
| 177 | + '[' => | |
| 178 | + dtype = byte DIS_P; | |
| 179 | + } | |
| 180 | + return dtype; | |
| 181 | +} | |
| 182 | + | |
| 183 | +# | |
| 184 | +# $i operands | |
| 185 | +# | |
| 186 | + | |
| 187 | +addrimm(a: ref Addr, ival: int) | |
| 188 | +{ | |
| 189 | + a.mode = byte Aimm; | |
| 190 | + a.ival = ival; | |
| 191 | +} | |
| 192 | + | |
| 193 | +# | |
| 194 | +# Is an int too big to be an immediate operand? | |
| 195 | +# | |
| 196 | + | |
| 197 | +notimmable(val: int): int | |
| 198 | +{ | |
| 199 | + return val < 0 && ((val >> 29) & 7) != 7 || val > 0 && (val >> 29) != 0; | |
| 200 | +} | |
| 201 | + | |
| 202 | +# | |
| 203 | +# i(fp) and i(mp) operands | |
| 204 | +# | |
| 205 | + | |
| 206 | +addrsind(a: ref Addr, mode: byte, off: int) | |
| 207 | +{ | |
| 208 | + a.mode = mode; | |
| 209 | + a.offset = off; | |
| 210 | +} | |
| 211 | + | |
| 212 | +# | |
| 213 | +# i(j(fp)) and i(j(mp)) operands | |
| 214 | +# | |
| 215 | + | |
| 216 | +addrdind(a: ref Addr, mode: byte, fi: int, si: int) | |
| 217 | +{ | |
| 218 | + a.mode = mode; | |
| 219 | + a.ival = fi; | |
| 220 | + a.offset = si; | |
| 221 | +} | |
| 222 | + | |
| 223 | +# | |
| 224 | +# Assign a register to a destination operand if not already done so. | |
| 225 | +# | |
| 226 | + | |
| 227 | +dstreg(a: ref Addr, dtype: byte) | |
| 228 | +{ | |
| 229 | + if(a.mode == Afp && a.offset == -1) | |
| 230 | + a.offset = getreg(dtype); | |
| 231 | +} | |
| 232 | + | |
| 233 | +# | |
| 234 | +# Print a string. | |
| 235 | +# | |
| 236 | + | |
| 237 | +pstring(s: string) | |
| 238 | +{ | |
| 239 | + slen, c: int; | |
| 240 | + | |
| 241 | + slen = len s; | |
| 242 | + for(i := 0; i < slen; i++) { | |
| 243 | + c = s[i]; | |
| 244 | + if(c == '\n') | |
| 245 | + bout.puts("\\n"); | |
| 246 | + else if(c == '\t') | |
| 247 | + bout.puts("\\t"); | |
| 248 | + else if(c == '"') | |
| 249 | + bout.puts("\\\""); | |
| 250 | + else if(c == '\\') | |
| 251 | + bout.puts("\\\\"); | |
| 252 | + else | |
| 253 | + bout.putc(c); | |
| 254 | + } | |
| 255 | +} | |
| 256 | + | |
| 257 | +# | |
| 258 | +# Die. | |
| 259 | +# | |
| 260 | + | |
| 261 | +fatal(msg: string) | |
| 262 | +{ | |
| 263 | + print("fatal j2d error: %s\n", msg); | |
| 264 | + if(bout != nil) | |
| 265 | + sys->remove(ofile); | |
| 266 | + reset(); | |
| 267 | + if(fabort) { | |
| 268 | + j: ref Jinst; | |
| 269 | + if(j.dst == nil); # abort | |
| 270 | + } | |
| 271 | + raise "fail:fail"; | |
| 272 | + #exit; | |
| 273 | +} | |
| 274 | + | |
| 275 | +# | |
| 276 | +# Bytecode verification. | |
| 277 | +# | |
| 278 | + | |
| 279 | +# | |
| 280 | +# Verify a constant pool index. | |
| 281 | +# | |
| 282 | + | |
| 283 | +verifycpindex(j: ref Jinst, ix: int, CON_bits: int) | |
| 284 | +{ | |
| 285 | + if(ix > 0 && ix < class.cp_count && ((1 << int class.cts[ix]) & CON_bits)) | |
| 286 | + return; | |
| 287 | + | |
| 288 | + if(j != nil) | |
| 289 | + verifyerror(j); | |
| 290 | + else | |
| 291 | + verifyerrormess("constant pool index"); | |
| 292 | +} | |
| 293 | + | |
| 294 | +verifyerror(j: ref Jinst) | |
| 295 | +{ | |
| 296 | + fatal("VerifyError: " + jinstconv(j)); | |
| 297 | +} | |
| 298 | + | |
| 299 | +verifyerrormess(mess: string) | |
| 300 | +{ | |
| 301 | + fatal("VerifyError: " + mess); | |
| 302 | +} | |
| 303 | + | |
| 304 | +badpick(s: string) | |
| 305 | +{ | |
| 306 | + fatal("bad pick in " + s); | |
| 307 | +} | |
| 308 | + | |
| 309 | +hex(v, n: int): string | |
| 310 | +{ | |
| 311 | + return sprint("%.*ux", n, v); | |
| 312 | +} | |
| 313 | + | |
| 314 | +# | |
| 315 | +# Size of frame cell of given type. | |
| 316 | +# | |
| 317 | + | |
| 318 | +cellsize := array [int DIS_P + 1] of { | |
| 319 | + 0, # DIS_X | |
| 320 | + IBY2WD, # DIS_W | |
| 321 | + IBY2LG, # DIS_L | |
| 322 | + IBY2WD, # DIS_P | |
| 323 | +}; | |
| 324 | + | |
| 325 | +# | |
| 326 | +# enable consecutive runs of J2d->init() without having to reload | |
| 327 | +# | |
| 328 | + | |
| 329 | +reset() | |
| 330 | +{ | |
| 331 | + i: int; | |
| 332 | + | |
| 333 | + # asm.b | |
| 334 | + clinitclone = nil; | |
| 335 | + | |
| 336 | + # bb.b | |
| 337 | + roots = nil; | |
| 338 | + nr = 0; | |
| 339 | + maxr = 0; | |
| 340 | + | |
| 341 | + # datarloc.b | |
| 342 | + dreloc = nil; | |
| 343 | + Ipatchtid = 0; | |
| 344 | + | |
| 345 | + # desc.b | |
| 346 | + dlist = nil; | |
| 347 | + dtail = nil; | |
| 348 | + id = 0; | |
| 349 | + | |
| 350 | + # dis.b | |
| 351 | + ihead = nil; | |
| 352 | + itail = nil; | |
| 353 | + cache = nil; | |
| 354 | + ncached = 0; | |
| 355 | + ndatum = 0; | |
| 356 | + startoff = 0; | |
| 357 | + lastoff = 0; | |
| 358 | + lastkind = -1; | |
| 359 | + lencache = 0; | |
| 360 | + ibuf = nil; | |
| 361 | + nibuf = 0; | |
| 362 | + | |
| 363 | + # entry.b | |
| 364 | + pc = -1; | |
| 365 | + tid = -1; | |
| 366 | + | |
| 367 | + # finally.b | |
| 368 | + finally = nil; | |
| 369 | + | |
| 370 | + # frame.b | |
| 371 | + frameoff = 0; | |
| 372 | + maxframe = 0; | |
| 373 | + locals = nil; | |
| 374 | + nlocals = 0; | |
| 375 | + tmpslwm = 0; | |
| 376 | + tmpssz = 0; | |
| 377 | + tmps = nil; | |
| 378 | + | |
| 379 | + # links.b | |
| 380 | + links = nil; | |
| 381 | + nlinks = 0; | |
| 382 | + fcplist = nil; | |
| 383 | + | |
| 384 | + # loader.b | |
| 385 | + pcode = nil; | |
| 386 | + THISCLASS = nil; | |
| 387 | + SUPERCLASS = nil; | |
| 388 | + | |
| 389 | + # ltreloc.b | |
| 390 | + doclinitinits = 0; | |
| 391 | + for(i = 0; i < Hashsize; i++) | |
| 392 | + lttbl[i] = nil; | |
| 393 | + thisclass = nil; | |
| 394 | + nltclasses = 0; | |
| 395 | + Freloctid = 0; | |
| 396 | + Ifacetid = 0; | |
| 397 | + | |
| 398 | + # main.b | |
| 399 | + gendis = 1; | |
| 400 | + fabort = 0; | |
| 401 | + emitcpool = 0; | |
| 402 | + verbose = 0; | |
| 403 | + bout = nil; | |
| 404 | + | |
| 405 | + # mdata.b | |
| 406 | + for(i = 0; i < Hashsize; i++) | |
| 407 | + htable[i] = nil; | |
| 408 | + mpoff = 0; | |
| 409 | + mplist = nil; | |
| 410 | + mptail = nil; | |
| 411 | + llist = nil; | |
| 412 | + rlist = nil; | |
| 413 | + | |
| 414 | + # patch.b | |
| 415 | + plist = nil; | |
| 416 | + | |
| 417 | + # rtreloc.b | |
| 418 | + for(i = 0; i < Hashsize; i++) | |
| 419 | + rttbl[i] = nil; | |
| 420 | + nrtclasses = 0; | |
| 421 | + RTReloctid = 0; | |
| 422 | + | |
| 423 | + # xlate.b | |
| 424 | + code = nil; | |
| 425 | + pcdis = 0; | |
| 426 | + callunrescue = 0; | |
| 427 | + rtcache = nil; | |
| 428 | + rtncache = 0; | |
| 429 | + rtnmax = 0; | |
| 430 | + ehinst = nil; | |
| 431 | + trylist = nil; | |
| 432 | +} | |
| @@ -0,0 +1,2996 @@ | ||
| 1 | +pcdis: int; | |
| 2 | +callunrescue: int; | |
| 3 | +J: ref Jinst; | |
| 4 | +M: ref Method; | |
| 5 | +code: ref Code; # method under translation | |
| 6 | + | |
| 7 | +trylevel: fn(pc: int): int; | |
| 8 | +unrescue: fn(n: int); | |
| 9 | + | |
| 10 | +# | |
| 11 | +# Allocate a Dis instruction. | |
| 12 | +# | |
| 13 | + | |
| 14 | +newi(op: int): ref Inst | |
| 15 | +{ | |
| 16 | + i: ref Inst; | |
| 17 | + | |
| 18 | + i = ref Inst(byte op, nil, nil, nil, pcdis, J, nil); | |
| 19 | + i.s = ref Addr(byte 0, 0, 0); | |
| 20 | + i.m = ref Addr(byte 0, 0, 0); | |
| 21 | + i.d = ref Addr(byte 0, 0, 0); | |
| 22 | + pcdis += 1; | |
| 23 | + if(J != nil && J.dis == nil) | |
| 24 | + J.dis = i; | |
| 25 | + if(ihead == nil) | |
| 26 | + ihead = i; | |
| 27 | + if(itail != nil) | |
| 28 | + itail.next = i; | |
| 29 | + itail = i; | |
| 30 | + return i; | |
| 31 | +} | |
| 32 | + | |
| 33 | +# | |
| 34 | +# Allocate a Dis instruction and record for branch-address patching. | |
| 35 | +# | |
| 36 | + | |
| 37 | +newibap(op: int): ref Inst | |
| 38 | +{ | |
| 39 | + i: ref Inst; | |
| 40 | + | |
| 41 | + i = newi(op); | |
| 42 | + patchop(i); | |
| 43 | + return i; | |
| 44 | +} | |
| 45 | + | |
| 46 | +# | |
| 47 | +# Turn single indirection off fp into double indirection. | |
| 48 | +# | |
| 49 | + | |
| 50 | +sind2dind(a: ref Addr, s: int) | |
| 51 | +{ | |
| 52 | + if(a.mode == byte Afp) { | |
| 53 | + a.mode = byte Afpind; | |
| 54 | + a.ival = a.offset; | |
| 55 | + a.offset = s; | |
| 56 | + } else if(a.mode == byte Amp && a.offset == 0) | |
| 57 | + ; # verifyerror(J); # can't reject prior to runtime | |
| 58 | + else | |
| 59 | + fatal("sind2dind: " + string a.mode + " not Afp"); | |
| 60 | +} | |
| 61 | + | |
| 62 | +# | |
| 63 | +# Middle operands that match destination operands are redundant. | |
| 64 | +# | |
| 65 | + | |
| 66 | +middstcmp(i: ref Inst) | |
| 67 | +{ | |
| 68 | + m, d: ref Addr; | |
| 69 | + | |
| 70 | + m = i.m; | |
| 71 | + d = i.d; | |
| 72 | + if(m.mode == Afp && m.mode == d.mode && m.offset == d.offset) { | |
| 73 | + m.mode = Anone; | |
| 74 | + m.offset = 0; | |
| 75 | + } | |
| 76 | +} | |
| 77 | + | |
| 78 | +# | |
| 79 | +# For instructions that may reference Module Data. | |
| 80 | +# | |
| 81 | + | |
| 82 | +datareloc(i: ref Inst) | |
| 83 | +{ | |
| 84 | + if(i.op == byte IMOVP && i.s.mode == byte Amp && i.s.offset == 0) | |
| 85 | + return; # don't relocate reference to nil | |
| 86 | + if(i.s.mode == byte Amp) | |
| 87 | + addDreloc(i, PSRC, PSIND); | |
| 88 | + if(i.m.mode == byte Amp) | |
| 89 | + addDreloc(i, PMID, PSIND); | |
| 90 | +} | |
| 91 | + | |
| 92 | +movinst(jtype: int): int | |
| 93 | +{ | |
| 94 | + movi: int; | |
| 95 | + | |
| 96 | + case jtype { | |
| 97 | + 'Z' or | |
| 98 | + 'B' => | |
| 99 | + if(J.op == byte Jgetfield || J.op == byte Jgetstatic) | |
| 100 | + movi = ICVTBW; | |
| 101 | + else if(J.op == byte Jputfield || J.op == byte Jputstatic) | |
| 102 | + movi = ICVTWB; | |
| 103 | + else | |
| 104 | + movi = IMOVW; | |
| 105 | + 'C' or | |
| 106 | + 'S' or | |
| 107 | + 'I' => | |
| 108 | + movi = IMOVW; | |
| 109 | + 'J' => | |
| 110 | + movi = IMOVL; | |
| 111 | + 'F' or | |
| 112 | + 'D' => | |
| 113 | + movi = IMOVF; | |
| 114 | + 'L' or | |
| 115 | + '[' => | |
| 116 | + movi = IMOVP; | |
| 117 | + } | |
| 118 | + return movi; | |
| 119 | +} | |
| 120 | + | |
| 121 | +FieldInfo: adt { | |
| 122 | + classname: string; | |
| 123 | + fieldname: string; | |
| 124 | + sig: string; | |
| 125 | + flags: int; | |
| 126 | +}; | |
| 127 | + | |
| 128 | +getfldinfo(): ref FieldInfo | |
| 129 | +{ | |
| 130 | + i: int; | |
| 131 | + m: ref Method; | |
| 132 | + fi: ref FieldInfo = ref FieldInfo(nil, nil, nil, 0); | |
| 133 | + ix: int; | |
| 134 | + | |
| 135 | + pick jp := J { | |
| 136 | + Pi => | |
| 137 | + ix = jp.i; | |
| 138 | + Px2c0 => | |
| 139 | + ix = jp.x2c0.ix; | |
| 140 | + * => | |
| 141 | + badpick("getfldinfo[Pi|Px2c0]"); | |
| 142 | + } | |
| 143 | + | |
| 144 | + pick c := class.cps[ix] { | |
| 145 | + Pfmiref => | |
| 146 | + fi.classname = CLASSNAME(c.fmiref.class_index); | |
| 147 | + pick n := class.cps[c.fmiref.name_type_index] { | |
| 148 | + Pnat => | |
| 149 | + fi.fieldname = STRING(n.nat.name_index); | |
| 150 | + fi.sig = STRING(n.nat.sig_index); | |
| 151 | + * => | |
| 152 | + badpick("getfldinfo[Pnat]"); | |
| 153 | + } | |
| 154 | + * => | |
| 155 | + badpick("getfldinfo[Pfmiref]"); | |
| 156 | + } | |
| 157 | + fi.flags = 0; | |
| 158 | + if(fi.classname != THISCLASS) | |
| 159 | + return fi; | |
| 160 | + for(i = 0; i < class.methods_count; i++) { | |
| 161 | + m = class.methods[i]; | |
| 162 | + if(fi.fieldname == STRING(m.name_index) | |
| 163 | + && fi.sig == STRING(m.sig_index)) { | |
| 164 | + fi.flags = m.access_flags; | |
| 165 | + break; | |
| 166 | + } | |
| 167 | + } | |
| 168 | + return fi; | |
| 169 | +} | |
| 170 | + | |
| 171 | +# | |
| 172 | +# mframe instruction for a call to a Loader entry point. | |
| 173 | +# | |
| 174 | + | |
| 175 | +loadermframe(frm: ref Freloc, frf: ref Freloc): ref Inst | |
| 176 | +{ | |
| 177 | + imframe: ref Inst; | |
| 178 | + | |
| 179 | + imframe = newi(IMFRAME); | |
| 180 | + addrsind(imframe.s, Amp, 0); | |
| 181 | + addrimm(imframe.m, 0); | |
| 182 | + addrsind(imframe.d, Afp, getreg(DIS_W)); | |
| 183 | + LTIpatch(frm, imframe, PSRC, PSIND); | |
| 184 | + LTIpatch(frf, imframe, PMID, PIMM); | |
| 185 | + | |
| 186 | + return imframe; | |
| 187 | +} | |
| 188 | + | |
| 189 | +# | |
| 190 | +# mcall instruction for a call to a Loader entry point. | |
| 191 | +# | |
| 192 | + | |
| 193 | +loadermcall(imframe: ref Inst, frf: ref Freloc, frm: ref Freloc): ref Inst | |
| 194 | +{ | |
| 195 | + imcall: ref Inst; | |
| 196 | + | |
| 197 | + imcall = newi(IMCALL); | |
| 198 | + *imcall.s = *imframe.d; | |
| 199 | + *imcall.m = *imframe.m; | |
| 200 | + *imcall.d = *imframe.s; | |
| 201 | + LTIpatch(frf, imcall, PMID, PIMM); | |
| 202 | + LTIpatch(frm, imcall, PDST, PSIND); | |
| 203 | + | |
| 204 | + return imcall; | |
| 205 | +} | |
| 206 | + | |
| 207 | +# | |
| 208 | +# Call "rtload" for run-time resolution. | |
| 209 | +# | |
| 210 | + | |
| 211 | +rtcache: array of string; | |
| 212 | +rtncache: int; | |
| 213 | +rtnmax: int; | |
| 214 | + | |
| 215 | +callrtload(rtc: ref RTClass, classname: string) | |
| 216 | +{ | |
| 217 | + j: int; | |
| 218 | + imframe, i: ref Inst; | |
| 219 | + cr: ref Creloc; | |
| 220 | + frm, frf: ref Freloc; | |
| 221 | + rtr: ref RTReloc; | |
| 222 | + | |
| 223 | + # rtload() already called for classname in this basic block ? | |
| 224 | + for(j = 0; j < rtncache; j++) { | |
| 225 | + if(rtcache[j] == classname) | |
| 226 | + return; | |
| 227 | + } | |
| 228 | + if(rtncache >= rtnmax) { | |
| 229 | + oldrtnmax := rtnmax; | |
| 230 | + rtnmax += ALLOCINCR; | |
| 231 | + newrtcache := array [rtnmax] of string; | |
| 232 | + for(k := 0; k < oldrtnmax; k++) | |
| 233 | + newrtcache[k] = rtcache[k]; | |
| 234 | + rtcache = newrtcache; | |
| 235 | + } | |
| 236 | + rtcache[rtncache++] = classname; | |
| 237 | + | |
| 238 | + rtr = getRTReloc(rtc, RMP, nil, 0); | |
| 239 | + cr = getCreloc(RLOADER); | |
| 240 | + frm = getFreloc(cr, RMP, nil, 0); | |
| 241 | + frf = getFreloc(cr, "rtload", nil, 0); | |
| 242 | + | |
| 243 | + i = newi(IBNEW); | |
| 244 | + addrsind(i.s, Amp, 0); | |
| 245 | + addrsind(i.m, Amp, 0); | |
| 246 | + addrimm(i.d, i.pc+4); | |
| 247 | + RTIpatch(rtr, i, PSRC, PSIND); | |
| 248 | + | |
| 249 | + imframe = loadermframe(frm, frf); | |
| 250 | + | |
| 251 | + i = newi(ILEA); | |
| 252 | + addrsind(i.s, Amp, 0); | |
| 253 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE); | |
| 254 | + RTIpatch(rtr, i, PSRC, PSIND); | |
| 255 | + | |
| 256 | + loadermcall(imframe, frf, frm); | |
| 257 | + relreg(imframe.d); | |
| 258 | +} | |
| 259 | + | |
| 260 | +# | |
| 261 | +# Sign-extend an 8-bit unsigned char (Dis byte) to a 32-bit int. | |
| 262 | +# | |
| 263 | + | |
| 264 | +signextend(dst: ref Addr) | |
| 265 | +{ | |
| 266 | + i: ref Inst; | |
| 267 | + | |
| 268 | + i = newi(ISHLW); | |
| 269 | + addrimm(i.s, 24); | |
| 270 | + # *i.m = *dst; # redundant | |
| 271 | + *i.d = *dst; | |
| 272 | + | |
| 273 | + i = newi(ISHRW); | |
| 274 | + addrimm(i.s, 24); | |
| 275 | + # *i.m = *dst; # redundant | |
| 276 | + *i.d = *dst; | |
| 277 | +} | |
| 278 | + | |
| 279 | +# | |
| 280 | +# addw instruction for run-time relocated getstatic & putstatic. | |
| 281 | +# | |
| 282 | + | |
| 283 | +rtstaticadd(fi: ref FieldInfo, rtc: ref RTClass): ref Addr | |
| 284 | +{ | |
| 285 | + i: ref Inst; | |
| 286 | + | |
| 287 | + i = newi(IADDW); | |
| 288 | + addrdind(i.s, Ampind, 0, 0); | |
| 289 | + addrsind(i.m, Amp, 0); | |
| 290 | + addrsind(i.d, Afp, getreg(DIS_W)); | |
| 291 | + | |
| 292 | + RTIpatch(getRTReloc(rtc, RMP, nil, 0), i, PSRC, PDIND1); | |
| 293 | + RTIpatch(getRTReloc(rtc, fi.fieldname, fi.sig, Rgetputstatic), | |
| 294 | + i, PMID, PSIND); | |
| 295 | + | |
| 296 | + return i.d; | |
| 297 | +} | |
| 298 | + | |
| 299 | +# | |
| 300 | +# Run-time relocated getstatic. | |
| 301 | +# | |
| 302 | + | |
| 303 | +rtgetstatic(fi: ref FieldInfo) | |
| 304 | +{ | |
| 305 | + a: ref Addr; | |
| 306 | + i: ref Inst; | |
| 307 | + rtc: ref RTClass; | |
| 308 | + | |
| 309 | + rtc = getRTClass(fi.classname); | |
| 310 | + callrtload(rtc, fi.classname); | |
| 311 | + a = rtstaticadd(fi, rtc); | |
| 312 | + | |
| 313 | + i = newi(movinst(fi.sig[0])); | |
| 314 | + *i.s = *a; | |
| 315 | + sind2dind(i.s, 0); | |
| 316 | + relreg(a); | |
| 317 | + dstreg(J.dst, j2dtype(J.jtype)); | |
| 318 | + *i.d = *J.dst; | |
| 319 | + | |
| 320 | + if(fi.sig[0] == 'B') | |
| 321 | + signextend(i.d); | |
| 322 | +} | |
| 323 | + | |
| 324 | +# | |
| 325 | +# Run-time relocated putstatic. | |
| 326 | +# | |
| 327 | + | |
| 328 | +rtputstatic(fi: ref FieldInfo) | |
| 329 | +{ | |
| 330 | + a: ref Addr; | |
| 331 | + i: ref Inst; | |
| 332 | + rtc: ref RTClass; | |
| 333 | + | |
| 334 | + rtc = getRTClass(fi.classname); | |
| 335 | + callrtload(rtc, fi.classname); | |
| 336 | + a = rtstaticadd(fi, rtc); | |
| 337 | + | |
| 338 | + i = newi(movinst(fi.sig[0])); | |
| 339 | + *i.s = *code.j[J.src[0]].dst; | |
| 340 | + relreg(code.j[J.src[0]].dst); | |
| 341 | + *i.d = *a; | |
| 342 | + sind2dind(i.d, 0); | |
| 343 | + relreg(a); | |
| 344 | + datareloc(i); | |
| 345 | +} | |
| 346 | + | |
| 347 | +# | |
| 348 | +# addw instruction for load-time relocated getstatic & putstatic. | |
| 349 | +# | |
| 350 | + | |
| 351 | +ltstaticadd(fi: ref FieldInfo): ref Addr | |
| 352 | +{ | |
| 353 | + i: ref Inst; | |
| 354 | + cr: ref Creloc; | |
| 355 | + | |
| 356 | + i = newi(IADDW); | |
| 357 | + addrdind(i.s, Ampind, 0, 0); | |
| 358 | + addrimm(i.m, 0); | |
| 359 | + addrsind(i.d, Afp, getreg(DIS_W)); | |
| 360 | + | |
| 361 | + cr = getCreloc(fi.classname); | |
| 362 | + LTIpatch(getFreloc(cr, RMP, nil, 0), i, PSRC, PDIND1); | |
| 363 | + LTIpatch(getFreloc(cr, fi.fieldname, fi.sig, Rgetputstatic), | |
| 364 | + i, PMID, PIMM); | |
| 365 | + | |
| 366 | + return i.d; | |
| 367 | +} | |
| 368 | + | |
| 369 | +# | |
| 370 | +# Load-time relocated getstatic. | |
| 371 | +# | |
| 372 | + | |
| 373 | +getstatic() | |
| 374 | +{ | |
| 375 | + i: ref Inst; | |
| 376 | + a: ref Addr; | |
| 377 | + fi: ref FieldInfo; | |
| 378 | + | |
| 379 | + fi = getfldinfo(); | |
| 380 | + if(dortload(fi.classname)) { | |
| 381 | + rtgetstatic(fi); | |
| 382 | + return; | |
| 383 | + } | |
| 384 | + | |
| 385 | + a = ltstaticadd(fi); | |
| 386 | + | |
| 387 | + i = newi(movinst(fi.sig[0])); | |
| 388 | + *i.s = *a; | |
| 389 | + sind2dind(i.s, 0); | |
| 390 | + relreg(a); | |
| 391 | + dstreg(J.dst, j2dtype(J.jtype)); | |
| 392 | + *i.d = *J.dst; | |
| 393 | + | |
| 394 | + if(fi.sig[0] == 'B') | |
| 395 | + signextend(i.d); | |
| 396 | +} | |
| 397 | + | |
| 398 | +# | |
| 399 | +# Load-time relocated putstatic. | |
| 400 | +# | |
| 401 | + | |
| 402 | +putstatic() | |
| 403 | +{ | |
| 404 | + i: ref Inst; | |
| 405 | + a: ref Addr; | |
| 406 | + fi: ref FieldInfo; | |
| 407 | + | |
| 408 | + fi = getfldinfo(); | |
| 409 | + if(dortload(fi.classname)) { | |
| 410 | + rtputstatic(fi); | |
| 411 | + return; | |
| 412 | + } | |
| 413 | + | |
| 414 | + a = ltstaticadd(fi); | |
| 415 | + | |
| 416 | + i = newi(movinst(fi.sig[0])); | |
| 417 | + *i.s = *code.j[J.src[0]].dst; | |
| 418 | + relreg(code.j[J.src[0]].dst); | |
| 419 | + *i.d = *a; | |
| 420 | + sind2dind(i.d, 0); | |
| 421 | + relreg(a); | |
| 422 | + datareloc(i); | |
| 423 | +} | |
| 424 | + | |
| 425 | +# | |
| 426 | +# addw instruction for run-time relocated getfield & putfield. | |
| 427 | +# | |
| 428 | + | |
| 429 | +rtfieldadd(fi: ref FieldInfo, rtc: ref RTClass, a: ref Addr): ref Addr | |
| 430 | +{ | |
| 431 | + i: ref Inst; | |
| 432 | + | |
| 433 | + i = newi(IADDW); | |
| 434 | + *i.s = *a; | |
| 435 | + addrsind(i.m, Amp, 0); | |
| 436 | + addrsind(i.d, Afp, getreg(DIS_W)); | |
| 437 | + | |
| 438 | + RTIpatch(getRTReloc(rtc, fi.fieldname, fi.sig, Rgetputfield), | |
| 439 | + i, PMID, PSIND); | |
| 440 | + | |
| 441 | + return i.d; | |
| 442 | +} | |
| 443 | + | |
| 444 | +# | |
| 445 | +# Run-time relocated getfield. | |
| 446 | +# | |
| 447 | + | |
| 448 | +rtgetfield(fi: ref FieldInfo) | |
| 449 | +{ | |
| 450 | + a: ref Addr; | |
| 451 | + i: ref Inst; | |
| 452 | + rtc: ref RTClass; | |
| 453 | + | |
| 454 | + rtc = getRTClass(fi.classname); | |
| 455 | + callrtload(rtc, fi.classname); | |
| 456 | + a = rtfieldadd(fi, rtc, code.j[J.src[0]].dst); | |
| 457 | + relreg(code.j[J.src[0]].dst); | |
| 458 | + | |
| 459 | + i = newi(movinst(fi.sig[0])); | |
| 460 | + *i.s = *a; | |
| 461 | + sind2dind(i.s, 0); | |
| 462 | + relreg(a); | |
| 463 | + dstreg(J.dst, j2dtype(J.jtype)); | |
| 464 | + *i.d = *J.dst; | |
| 465 | + | |
| 466 | + if(fi.sig[0] == 'B') | |
| 467 | + signextend(i.d); | |
| 468 | +} | |
| 469 | + | |
| 470 | +# | |
| 471 | +# Run-time relocated putfield. | |
| 472 | +# | |
| 473 | + | |
| 474 | +rtputfield(fi: ref FieldInfo) | |
| 475 | +{ | |
| 476 | + a: ref Addr; | |
| 477 | + i: ref Inst; | |
| 478 | + rtc: ref RTClass; | |
| 479 | + | |
| 480 | + rtc = getRTClass(fi.classname); | |
| 481 | + callrtload(rtc, fi.classname); | |
| 482 | + a = rtfieldadd(fi, rtc, code.j[J.src[0]].dst); | |
| 483 | + relreg(code.j[J.src[0]].dst); | |
| 484 | + | |
| 485 | + i = newi(movinst(fi.sig[0])); | |
| 486 | + *i.s = *code.j[J.src[1]].dst; | |
| 487 | + relreg(code.j[J.src[1]].dst); | |
| 488 | + *i.d = *a; | |
| 489 | + relreg(a); | |
| 490 | + sind2dind(i.d, 0); | |
| 491 | + datareloc(i); | |
| 492 | +} | |
| 493 | + | |
| 494 | +# | |
| 495 | +# Load-time relocated getfield. | |
| 496 | +# | |
| 497 | + | |
| 498 | +getfield() | |
| 499 | +{ | |
| 500 | + i: ref Inst; | |
| 501 | + cr: ref Creloc; | |
| 502 | + fi: ref FieldInfo; | |
| 503 | + | |
| 504 | + fi = getfldinfo(); | |
| 505 | + if(dortload(fi.classname)) { | |
| 506 | + rtgetfield(fi); | |
| 507 | + return; | |
| 508 | + } | |
| 509 | + | |
| 510 | + i = newi(movinst(fi.sig[0])); | |
| 511 | + *i.s = *code.j[J.src[0]].dst; | |
| 512 | + sind2dind(i.s, 0); | |
| 513 | + relreg(code.j[J.src[0]].dst); | |
| 514 | + dstreg(J.dst, j2dtype(J.jtype)); | |
| 515 | + *i.d = *J.dst; | |
| 516 | + | |
| 517 | + cr = getCreloc(fi.classname); | |
| 518 | + LTIpatch(getFreloc(cr, fi.fieldname, fi.sig, Rgetputfield), | |
| 519 | + i, PSRC, PDIND2); | |
| 520 | + | |
| 521 | + if(fi.sig[0] == 'B') | |
| 522 | + signextend(i.d); | |
| 523 | +} | |
| 524 | + | |
| 525 | +# | |
| 526 | +# Load-time relocated putfield. | |
| 527 | +# | |
| 528 | + | |
| 529 | +putfield() | |
| 530 | +{ | |
| 531 | + i: ref Inst; | |
| 532 | + cr: ref Creloc; | |
| 533 | + fi: ref FieldInfo; | |
| 534 | + | |
| 535 | + fi = getfldinfo(); | |
| 536 | + if(dortload(fi.classname)) { | |
| 537 | + rtputfield(fi); | |
| 538 | + return; | |
| 539 | + } | |
| 540 | + | |
| 541 | + i = newi(movinst(fi.sig[0])); | |
| 542 | + *i.s = *code.j[J.src[1]].dst; | |
| 543 | + relreg(code.j[J.src[1]].dst); | |
| 544 | + *i.d = *code.j[J.src[0]].dst; | |
| 545 | + relreg(code.j[J.src[0]].dst); | |
| 546 | + sind2dind(i.d, 0); | |
| 547 | + datareloc(i); | |
| 548 | + | |
| 549 | + cr = getCreloc(fi.classname); | |
| 550 | + LTIpatch(getFreloc(cr, fi.fieldname, fi.sig, Rgetputfield), | |
| 551 | + i, PDST, PDIND2); | |
| 552 | +} | |
| 553 | + | |
| 554 | +# | |
| 555 | +# Push function arguments. | |
| 556 | +# | |
| 557 | + | |
| 558 | +pushargs(calltype: int, calleeframe: int, sig: string) | |
| 559 | +{ | |
| 560 | + i: ref Inst; | |
| 561 | + frameoff: int; | |
| 562 | + arg, size: int; | |
| 563 | + | |
| 564 | + frameoff = REGSIZE; | |
| 565 | + arg = 0; | |
| 566 | + if(calltype != Rinvokestatic) { | |
| 567 | + i = newi(IMOVP); # this pointer | |
| 568 | + *i.s = *code.j[J.src[arg]].dst; | |
| 569 | + addrdind(i.d, Afpind, calleeframe, frameoff); | |
| 570 | + frameoff += IBY2WD; | |
| 571 | + arg++; | |
| 572 | + } | |
| 573 | + | |
| 574 | + sig = sig[1:]; # skip '(' | |
| 575 | + while(sig[0] != ')') { | |
| 576 | + i = newi(movinst(sig[0])); | |
| 577 | + *i.s = *code.j[J.src[arg]].dst; | |
| 578 | + size = cellsize[int j2dtype(byte sig[0])]; | |
| 579 | + frameoff = align(frameoff, size); | |
| 580 | + addrdind(i.d, Afpind, calleeframe, frameoff); | |
| 581 | + datareloc(i); | |
| 582 | + frameoff += size; | |
| 583 | + sig = nextjavatype(sig); | |
| 584 | + arg++; | |
| 585 | + } | |
| 586 | + | |
| 587 | + # return value | |
| 588 | + if(sig[1] != 'V') { # skip ')' | |
| 589 | + i = newi(ILEA); | |
| 590 | + dstreg(J.dst, j2dtype(J.jtype)); | |
| 591 | + *i.s = *J.dst; | |
| 592 | + addrdind(i.d, Afpind, calleeframe, REGRET*IBY2WD); | |
| 593 | + } | |
| 594 | +} | |
| 595 | + | |
| 596 | +# | |
| 597 | +# Run-time relocated invokespecial and invokestatic. | |
| 598 | +# | |
| 599 | + | |
| 600 | +rtinvokess(fi: ref FieldInfo, calltype: int, mpflag: int) | |
| 601 | +{ | |
| 602 | + n: int; | |
| 603 | + imframe, imcall: ref Inst; | |
| 604 | + rtc: ref RTClass; | |
| 605 | + rtr1, rtr2: ref RTReloc; | |
| 606 | + | |
| 607 | + rtc = getRTClass(fi.classname); | |
| 608 | + callrtload(rtc, fi.classname); | |
| 609 | + | |
| 610 | + imframe = newi(IMFRAME); | |
| 611 | + addrsind(imframe.s, Amp, 0); | |
| 612 | + addrsind(imframe.m, Amp, 0); | |
| 613 | + addrsind(imframe.d, Afp, getreg(DIS_W)); | |
| 614 | + | |
| 615 | + rtr1 = getRTReloc(rtc, fi.fieldname, fi.sig, calltype|mpflag); | |
| 616 | + rtr2 = getRTReloc(rtc, fi.fieldname, fi.sig, calltype); | |
| 617 | + RTIpatch(rtr1, imframe, PSRC, PSIND); | |
| 618 | + RTIpatch(rtr2, imframe, PMID, PSIND); | |
| 619 | + | |
| 620 | + # push arguments into callee's frame, handle return type | |
| 621 | + pushargs(calltype, imframe.d.offset, fi.sig); | |
| 622 | + | |
| 623 | + imcall = newi(IMCALL); | |
| 624 | + *imcall.s = *imframe.d; | |
| 625 | + *imcall.m = *imframe.m; | |
| 626 | + *imcall.d = *imframe.s; | |
| 627 | + | |
| 628 | + RTIpatch(rtr1, imcall, PDST, PSIND); | |
| 629 | + RTIpatch(rtr2, imcall, PMID, PSIND); | |
| 630 | + | |
| 631 | + for(n = 0; n < J.nsrc; n++) | |
| 632 | + relreg(code.j[J.src[n]].dst); | |
| 633 | + relreg(imframe.d); | |
| 634 | +} | |
| 635 | + | |
| 636 | +# | |
| 637 | +# Load-time relocated invokespecial and invokestatic. | |
| 638 | +# | |
| 639 | + | |
| 640 | +invokess(calltype: int, mpflag: int) | |
| 641 | +{ | |
| 642 | + n: int; | |
| 643 | + imframe, imcall: ref Inst; | |
| 644 | + cr: ref Creloc; | |
| 645 | + frf, frm: ref Freloc; | |
| 646 | + fi: ref FieldInfo; | |
| 647 | + | |
| 648 | + fi = getfldinfo(); | |
| 649 | + if(dortload(fi.classname)) { | |
| 650 | + rtinvokess(fi, calltype, mpflag); | |
| 651 | + return; | |
| 652 | + } | |
| 653 | + cr = getCreloc(fi.classname); | |
| 654 | + # fi.flags set only if fi.classname == this_class | |
| 655 | + if(fi.flags & (ACC_PRIVATE | ACC_STATIC)) { | |
| 656 | + if(fi.flags & ACC_NATIVE) | |
| 657 | + frm = getFreloc(cr, RNP, nil, 0); | |
| 658 | + else | |
| 659 | + frm = nil; # frame/call | |
| 660 | + } else { | |
| 661 | + # force @mp, @np into the list for cr | |
| 662 | + getFreloc(cr, RMP, nil, 0); | |
| 663 | + getFreloc(cr, RNP, nil, 0); | |
| 664 | + frm = getFreloc(cr, fi.fieldname, fi.sig, calltype|mpflag); | |
| 665 | + } | |
| 666 | + | |
| 667 | + if(frm == nil) { | |
| 668 | + imframe = newi(IFRAME); | |
| 669 | + addrimm(imframe.s, 0); | |
| 670 | + } else { | |
| 671 | + imframe = newi(IMFRAME); | |
| 672 | + addrsind(imframe.s, Amp, 0); | |
| 673 | + addrimm(imframe.m, 0); | |
| 674 | + LTIpatch(frm, imframe, PSRC, PSIND); | |
| 675 | + frf = getFreloc(cr, fi.fieldname, fi.sig, calltype); | |
| 676 | + LTIpatch(frf, imframe, PMID, PIMM); | |
| 677 | + } | |
| 678 | + addrsind(imframe.d, Afp, getreg(DIS_W)); | |
| 679 | + | |
| 680 | + # push arguments into callee's frame, handle return type | |
| 681 | + pushargs(calltype, imframe.d.offset, fi.sig); | |
| 682 | + | |
| 683 | + if(frm == nil) { | |
| 684 | + imcall = newi(ICALL); | |
| 685 | + addfcpatch(imframe, imcall, fi.fieldname, fi.sig); | |
| 686 | + } else { | |
| 687 | + imcall = newi(IMCALL); | |
| 688 | + *imcall.m = *imframe.m; | |
| 689 | + LTIpatch(frf, imcall, PMID, PIMM); | |
| 690 | + LTIpatch(frm, imcall, PDST, PSIND); | |
| 691 | + } | |
| 692 | + *imcall.s = *imframe.d; | |
| 693 | + *imcall.d = *imframe.s; | |
| 694 | + | |
| 695 | + for(n = 0; n < J.nsrc; n++) | |
| 696 | + relreg(code.j[J.src[n]].dst); | |
| 697 | + relreg(imframe.d); | |
| 698 | +} | |
| 699 | + | |
| 700 | +# | |
| 701 | +# Load-time relocated invokeinterface. | |
| 702 | +# Resolve all interfaces at load-time. | |
| 703 | +# | |
| 704 | + | |
| 705 | +invokei() | |
| 706 | +{ | |
| 707 | + n: int; | |
| 708 | + cr: ref Creloc; | |
| 709 | + frm, frf, frfi: ref Freloc; | |
| 710 | + fi: ref FieldInfo; | |
| 711 | + # | |
| 712 | + # call Loader.getinterface() with these | |
| 713 | + # | |
| 714 | + imframe1, imovw1, imovp, imovw2, ilea, imcall1: ref Inst; | |
| 715 | + # | |
| 716 | + # call interface method with these | |
| 717 | + # | |
| 718 | + iaddw, imovw3, imframe2, imcall2: ref Inst; | |
| 719 | + | |
| 720 | + cr = getCreloc(RLOADER); | |
| 721 | + frm = getFreloc(cr, RMP, nil, 0); | |
| 722 | + frf = getFreloc(cr, "getinterface", nil, 0); | |
| 723 | + | |
| 724 | + # call Loader.getinterface | |
| 725 | + | |
| 726 | + imframe1 = loadermframe(frm, frf); | |
| 727 | + | |
| 728 | + imovw1 = newi(IMOVW); | |
| 729 | + *imovw1.s = *code.j[J.src[0]].dst; # this pointer | |
| 730 | + sind2dind(imovw1.s, 0); | |
| 731 | + addrsind(imovw1.d, Afp, getreg(DIS_W)); | |
| 732 | + | |
| 733 | + imovp = newi(IMOVP); | |
| 734 | + *imovp.s = *imovw1.d; | |
| 735 | + sind2dind(imovp.s, 4); | |
| 736 | + addrdind(imovp.d, Afpind, imframe1.d.offset, REGSIZE); | |
| 737 | + | |
| 738 | + imovw2 = newi(IMOVW); | |
| 739 | + addrimm(imovw2.s, 0); | |
| 740 | + addrdind(imovw2.d, Afpind, imframe1.d.offset, REGSIZE+IBY2WD); | |
| 741 | + | |
| 742 | + fi = getfldinfo(); | |
| 743 | + frfi = getFreloc(getCreloc(fi.classname), fi.fieldname, | |
| 744 | + fi.sig, Rinvokeinterface); | |
| 745 | + LTIpatch(frfi, imovw2, PSRC, PIMM); | |
| 746 | + | |
| 747 | + ilea = newi(ILEA); | |
| 748 | + addrsind(ilea.s, Afp, getreg(DIS_W)); | |
| 749 | + addrdind(ilea.d, Afpind, imframe1.d.offset, REGRET*IBY2WD); | |
| 750 | + | |
| 751 | + imcall1 = loadermcall(imframe1, frf, frm); | |
| 752 | + | |
| 753 | + # call interface method | |
| 754 | + | |
| 755 | + iaddw = newi(IADDW); | |
| 756 | + *iaddw.s = *imovw1.d; | |
| 757 | + *iaddw.m = *ilea.s; | |
| 758 | + *iaddw.d = *imovw1.d; | |
| 759 | + | |
| 760 | + imovw3 = newi(IMOVW); | |
| 761 | + *imovw3.s = *iaddw.d; | |
| 762 | + sind2dind(imovw3.s, 4); | |
| 763 | + *imovw3.d = *ilea.s; | |
| 764 | + | |
| 765 | + imframe2 = newi(IMFRAME); | |
| 766 | + *imframe2.s = *iaddw.d; | |
| 767 | + sind2dind(imframe2.s, 0); | |
| 768 | + *imframe2.m = *imovw3.d; | |
| 769 | + *imframe2.d = *imframe1.d; | |
| 770 | + | |
| 771 | + # push arguments into callee's frame, handle return type | |
| 772 | + pushargs(Rinvokeinterface, imframe2.d.offset, fi.sig); | |
| 773 | + | |
| 774 | + imcall2 = newi(IMCALL); | |
| 775 | + *imcall2.s = *imframe2.d; | |
| 776 | + *imcall2.m = *imframe2.m; | |
| 777 | + *imcall2.d = *imframe2.s; | |
| 778 | + | |
| 779 | + for(n = 0; n < J.nsrc; n++) | |
| 780 | + relreg(code.j[J.src[n]].dst); | |
| 781 | + relreg(imframe1.d); | |
| 782 | + relreg(imovw1.d); | |
| 783 | + relreg(ilea.s); | |
| 784 | +} | |
| 785 | + | |
| 786 | +# | |
| 787 | +# Run-time relocated invokevirtual. | |
| 788 | +# | |
| 789 | + | |
| 790 | +rtinvokev(fi: ref FieldInfo) | |
| 791 | +{ | |
| 792 | + n: int; | |
| 793 | + iaddw, imovw1, imovw2, imframe, imcall: ref Inst; | |
| 794 | + rtc: ref RTClass; | |
| 795 | + | |
| 796 | + rtc = getRTClass(fi.classname); | |
| 797 | + callrtload(rtc, fi.classname); | |
| 798 | + | |
| 799 | + imovw1 = newi(IMOVW); | |
| 800 | + *imovw1.s = *code.j[J.src[0]].dst; # this pointer | |
| 801 | + sind2dind(imovw1.s, 0); | |
| 802 | + addrsind(imovw1.d, Afp, getreg(DIS_W)); | |
| 803 | + | |
| 804 | + iaddw = newi(IADDW); | |
| 805 | + *iaddw.s = *imovw1.d; | |
| 806 | + addrsind(iaddw.m, Amp, 0); | |
| 807 | + *iaddw.d = *imovw1.d; | |
| 808 | + | |
| 809 | + RTIpatch(getRTReloc(rtc, fi.fieldname, fi.sig, Rinvokevirtual), | |
| 810 | + iaddw, PMID, PSIND); | |
| 811 | + | |
| 812 | + imovw2 = newi(IMOVW); | |
| 813 | + *imovw2.s = *iaddw.d; | |
| 814 | + sind2dind(imovw2.s, 4); | |
| 815 | + addrsind(imovw2.d, Afp, getreg(DIS_W)); | |
| 816 | + | |
| 817 | + imframe = newi(IMFRAME); | |
| 818 | + *imframe.s = *imovw1.d; | |
| 819 | + sind2dind(imframe.s, 0); | |
| 820 | + *imframe.m = *imovw2.d; | |
| 821 | + addrsind(imframe.d, Afp, getreg(DIS_W)); | |
| 822 | + | |
| 823 | + # push arguments into callee's frame, handle return type | |
| 824 | + pushargs(Rinvokevirtual, imframe.d.offset, fi.sig); | |
| 825 | + | |
| 826 | + imcall = newi(IMCALL); | |
| 827 | + *imcall.s = *imframe.d; | |
| 828 | + *imcall.m = *imframe.m; | |
| 829 | + *imcall.d = *imframe.s; | |
| 830 | + | |
| 831 | + for(n = 0; n < J.nsrc; n++) | |
| 832 | + relreg(code.j[J.src[n]].dst); | |
| 833 | + relreg(imovw1.d); | |
| 834 | + relreg(imovw2.d); | |
| 835 | + relreg(imframe.d); | |
| 836 | +} | |
| 837 | + | |
| 838 | +# | |
| 839 | +# Load-time relocated invokevirtual. | |
| 840 | +# | |
| 841 | + | |
| 842 | +invokev() | |
| 843 | +{ | |
| 844 | + n: int; | |
| 845 | + imovw1, imovw2, imframe, imcall: ref Inst; | |
| 846 | + cr: ref Creloc; | |
| 847 | + fr: ref Freloc; | |
| 848 | + fi: ref FieldInfo; | |
| 849 | + | |
| 850 | + fi = getfldinfo(); | |
| 851 | + if(dortload(fi.classname)) { | |
| 852 | + rtinvokev(fi); | |
| 853 | + return; | |
| 854 | + } | |
| 855 | + cr = getCreloc(fi.classname); | |
| 856 | + fr = getFreloc(cr, fi.fieldname, fi.sig, Rinvokevirtual); | |
| 857 | + | |
| 858 | + imovw1 = newi(IMOVW); | |
| 859 | + *imovw1.s = *code.j[J.src[0]].dst; # this pointer | |
| 860 | + sind2dind(imovw1.s, 0); | |
| 861 | + addrsind(imovw1.d, Afp, getreg(DIS_W)); | |
| 862 | + | |
| 863 | + imovw2 = newi(IMOVW); | |
| 864 | + *imovw2.s = *imovw1.d; | |
| 865 | + sind2dind(imovw2.s, 4); | |
| 866 | + addrsind(imovw2.d, Afp, getreg(DIS_W)); | |
| 867 | + LTIpatch(fr, imovw2, PSRC, PDIND2); | |
| 868 | + | |
| 869 | + imframe = newi(IMFRAME); | |
| 870 | + *imframe.s = *imovw1.d; | |
| 871 | + sind2dind(imframe.s, 0); | |
| 872 | + *imframe.m = *imovw2.d; | |
| 873 | + addrsind(imframe.d, Afp, getreg(DIS_W)); | |
| 874 | + LTIpatch(fr, imframe, PSRC, PDIND2); | |
| 875 | + | |
| 876 | + # push arguments into callee's frame, handle return type | |
| 877 | + pushargs(Rinvokevirtual, imframe.d.offset, fi.sig); | |
| 878 | + | |
| 879 | + imcall = newi(IMCALL); | |
| 880 | + *imcall.s = *imframe.d; | |
| 881 | + *imcall.m = *imframe.m; | |
| 882 | + *imcall.d = *imframe.s; | |
| 883 | + LTIpatch(fr, imcall, PDST, PDIND2); | |
| 884 | + | |
| 885 | + for(n = 0; n < J.nsrc; n++) | |
| 886 | + relreg(code.j[J.src[n]].dst); | |
| 887 | + relreg(imovw1.d); | |
| 888 | + relreg(imovw2.d); | |
| 889 | + relreg(imframe.d); | |
| 890 | +} | |
| 891 | + | |
| 892 | +# | |
| 893 | +# Run-time relocated new. | |
| 894 | +# | |
| 895 | + | |
| 896 | +rtnew(fi: ref FieldInfo) | |
| 897 | +{ | |
| 898 | + i1, i2: ref Inst; | |
| 899 | + rtc: ref RTClass; | |
| 900 | + rtr: ref RTReloc; | |
| 901 | + | |
| 902 | + rtc = getRTClass(fi.classname); | |
| 903 | + callrtload(rtc, fi.classname); | |
| 904 | + | |
| 905 | + i1 = newi(IMNEWZ); | |
| 906 | + addrsind(i1.s, Amp, 0); | |
| 907 | + addrsind(i1.m, Amp, 0); | |
| 908 | + dstreg(J.dst, DIS_P); | |
| 909 | + *i1.d = *J.dst; | |
| 910 | + | |
| 911 | + rtr = getRTReloc(rtc, RCLASS, nil, 0); | |
| 912 | + RTIpatch(rtr, i1, PMID, PSIND); | |
| 913 | + rtr = getRTReloc(rtc, RMP, nil, 0); | |
| 914 | + RTIpatch(rtr, i1, PSRC, PSIND); | |
| 915 | + | |
| 916 | + i2 = newi(IMOVP); | |
| 917 | + addrdind(i2.s, Ampind, 0, 0); | |
| 918 | + *i2.d = *i1.d; | |
| 919 | + sind2dind(i2.d, 0); | |
| 920 | + | |
| 921 | + RTIpatch(rtr, i2, PSRC, PDIND1); | |
| 922 | +} | |
| 923 | + | |
| 924 | +# | |
| 925 | +# Load-time relocated new. | |
| 926 | +# | |
| 927 | + | |
| 928 | +xjavanew(name: string, a: ref Addr) | |
| 929 | +{ | |
| 930 | + i1, i2: ref Inst; | |
| 931 | + cr: ref Creloc; | |
| 932 | + frc, frm: ref Freloc; | |
| 933 | + fi: ref FieldInfo; | |
| 934 | + | |
| 935 | + if(dortload(name)) { | |
| 936 | + fi = ref FieldInfo(name, nil, nil, 0); | |
| 937 | + rtnew(fi); | |
| 938 | + return; | |
| 939 | + } | |
| 940 | + cr = getCreloc(name); | |
| 941 | + frc = getFreloc(cr, RCLASS, nil, 0); | |
| 942 | + frm = getFreloc(cr, RMP, nil, 0); | |
| 943 | + | |
| 944 | + if(name == THISCLASS) { | |
| 945 | + i1 = newi(INEWZ); | |
| 946 | + addrimm(i1.s, 0); | |
| 947 | + LTIpatch(frc, i1, PSRC, PIMM); | |
| 948 | + } else { | |
| 949 | + i1 = newi(IMNEWZ); | |
| 950 | + addrsind(i1.s, Amp, 0); | |
| 951 | + LTIpatch(frm, i1, PSRC, PSIND); | |
| 952 | + addrimm(i1.m, 0); | |
| 953 | + LTIpatch(frc, i1, PMID, PIMM); | |
| 954 | + } | |
| 955 | + dstreg(a, DIS_P); | |
| 956 | + *i1.d = *a; | |
| 957 | + | |
| 958 | + i2 = newi(IMOVP); | |
| 959 | + addrdind(i2.s, Ampind, 0, 0); | |
| 960 | + LTIpatch(frm, i2, PSRC, PDIND1); | |
| 961 | + *i2.d = *i1.d; | |
| 962 | + sind2dind(i2.d, 0); | |
| 963 | +} | |
| 964 | + | |
| 965 | +# | |
| 966 | +# Java newarray | |
| 967 | +# | |
| 968 | + | |
| 969 | +newarray() | |
| 970 | +{ | |
| 971 | + i: ref Inst; | |
| 972 | + n, tid: int; | |
| 973 | + ix: int; | |
| 974 | + | |
| 975 | + pick jp := J { | |
| 976 | + Pi => | |
| 977 | + ix = jp.i; | |
| 978 | + * => | |
| 979 | + badpick("newarray"); | |
| 980 | + } | |
| 981 | + | |
| 982 | + case ix { | |
| 983 | + T_BOOLEAN or | |
| 984 | + T_BYTE => | |
| 985 | + n = 1; | |
| 986 | + T_CHAR or | |
| 987 | + T_SHORT or | |
| 988 | + T_INT => | |
| 989 | + n = IBY2WD; | |
| 990 | + T_LONG or | |
| 991 | + T_FLOAT or | |
| 992 | + T_DOUBLE => | |
| 993 | + n = IBY2LG; | |
| 994 | + } | |
| 995 | + if(n == 1) | |
| 996 | + tid = descid(n, 0, array [1] of { byte 0 }); | |
| 997 | + else | |
| 998 | + tid = descid(n, 1, array [1] of { byte 0 }); | |
| 999 | + | |
| 1000 | + xjavanew("inferno/vm/Array", J.dst); | |
| 1001 | + i = newi(INEWAZ); | |
| 1002 | + *i.s = *code.j[J.src[0]].dst; | |
| 1003 | + relreg(code.j[J.src[0]].dst); | |
| 1004 | + addrimm(i.m, tid); | |
| 1005 | + *i.d = *J.dst; | |
| 1006 | + sind2dind(i.d, ARY_DATA); | |
| 1007 | + datareloc(i); | |
| 1008 | + | |
| 1009 | + i = newi(IMOVW); | |
| 1010 | + addrimm(i.s, 1); | |
| 1011 | + *i.d = *J.dst; | |
| 1012 | + sind2dind(i.d, ARY_NDIM); | |
| 1013 | + | |
| 1014 | + i = newi(IMOVW); | |
| 1015 | + addrimm(i.s, ix); | |
| 1016 | + *i.d = *J.dst; | |
| 1017 | + sind2dind(i.d, ARY_ETYPE); | |
| 1018 | +} | |
| 1019 | + | |
| 1020 | +ArrayInfo: adt { | |
| 1021 | + ndim: int; # number of dimensions | |
| 1022 | + etype: int; # element type code (if primitive) | |
| 1023 | + ename: string; # element type name (if non-primitive) | |
| 1024 | +}; | |
| 1025 | + | |
| 1026 | +# | |
| 1027 | +# Glean array information. s may name a Class, Interface, or Array type. | |
| 1028 | +# Used by xanewarray, xmultianewarray, checkcast, instanceof. | |
| 1029 | +# | |
| 1030 | + | |
| 1031 | +getaryinfo(s: string): ref ArrayInfo | |
| 1032 | +{ | |
| 1033 | + n: int; | |
| 1034 | + ai: ref ArrayInfo = ref ArrayInfo(0, 0, nil); | |
| 1035 | + | |
| 1036 | + while(s[0] == '[') { | |
| 1037 | + ai.ndim++; | |
| 1038 | + s = s[1:]; | |
| 1039 | + } | |
| 1040 | + | |
| 1041 | + if(ai.ndim > 0) { | |
| 1042 | + case s[0] { | |
| 1043 | + 'Z' => | |
| 1044 | + ai.etype = T_BOOLEAN; | |
| 1045 | + 'B' => | |
| 1046 | + ai.etype = T_BYTE; | |
| 1047 | + 'C' => | |
| 1048 | + ai.etype = T_CHAR; | |
| 1049 | + 'S' => | |
| 1050 | + ai.etype = T_SHORT; | |
| 1051 | + 'I' => | |
| 1052 | + ai.etype = T_INT; | |
| 1053 | + 'F' => | |
| 1054 | + ai.etype = T_FLOAT; | |
| 1055 | + 'J' => | |
| 1056 | + ai.etype = T_LONG; | |
| 1057 | + 'D' => | |
| 1058 | + ai.etype = T_DOUBLE; | |
| 1059 | + 'L' => | |
| 1060 | + ; # ai.etype = 0; # above | |
| 1061 | + } | |
| 1062 | + } | |
| 1063 | + if(ai.etype == 0) { | |
| 1064 | + n = len s + 1; | |
| 1065 | + if(ai.ndim > 0) { # e.g., s == "LX.Y.Z;" | |
| 1066 | + s = s[1:]; | |
| 1067 | + n -= 2; | |
| 1068 | + } | |
| 1069 | + ai.ename = s[0:n-1]; | |
| 1070 | + } | |
| 1071 | + return ai; | |
| 1072 | +} | |
| 1073 | + | |
| 1074 | +# | |
| 1075 | +# Java anewarray | |
| 1076 | +# | |
| 1077 | + | |
| 1078 | +xanewarray() | |
| 1079 | +{ | |
| 1080 | + i: ref Inst; | |
| 1081 | + rtflag: int; | |
| 1082 | + rtc: ref RTClass; | |
| 1083 | + ai: ref ArrayInfo; | |
| 1084 | + ix: int; | |
| 1085 | + | |
| 1086 | + pick jp := J { | |
| 1087 | + Pi => | |
| 1088 | + ix = jp.i; | |
| 1089 | + * => | |
| 1090 | + badpick("xanewarray"); | |
| 1091 | + } | |
| 1092 | + | |
| 1093 | + ai = getaryinfo(CLASSNAME(ix)); | |
| 1094 | + rtflag = 0; | |
| 1095 | + if(dortload(ai.ename)) { | |
| 1096 | + rtflag = 1; | |
| 1097 | + rtc = getRTClass(ai.ename); | |
| 1098 | + callrtload(rtc, ai.ename); | |
| 1099 | + } | |
| 1100 | + | |
| 1101 | + xjavanew("inferno/vm/Array", J.dst); | |
| 1102 | + i = newi(INEWA); | |
| 1103 | + *i.s = *code.j[J.src[0]].dst; | |
| 1104 | + relreg(code.j[J.src[0]].dst); | |
| 1105 | + addrimm(i.m, descid(IBY2WD, 1, array [1] of { byte 16r80 })); | |
| 1106 | + *i.d = *J.dst; | |
| 1107 | + sind2dind(i.d, ARY_DATA); | |
| 1108 | + datareloc(i); | |
| 1109 | + | |
| 1110 | + i = newi(IMOVW); | |
| 1111 | + addrimm(i.s, ai.ndim+1); | |
| 1112 | + *i.d = *J.dst; | |
| 1113 | + sind2dind(i.d, ARY_NDIM); | |
| 1114 | + | |
| 1115 | + if(ai.etype == 0) { | |
| 1116 | + i = newi(IMOVP); | |
| 1117 | + addrsind(i.s, Amp, 0); | |
| 1118 | + if(rtflag == 1) { | |
| 1119 | + RTIpatch(getRTReloc(rtc, RADT, nil, 0), i, PSRC, PSIND); | |
| 1120 | + } else { | |
| 1121 | + LTIpatch(getFreloc(getCreloc(ai.ename), RADT, nil, 0), | |
| 1122 | + i, PSRC, PSIND); | |
| 1123 | + } | |
| 1124 | + *i.d = *J.dst; | |
| 1125 | + sind2dind(i.d, ARY_ADT); | |
| 1126 | + } else { | |
| 1127 | + i = newi(IMOVW); | |
| 1128 | + addrimm(i.s, ai.etype); | |
| 1129 | + *i.d = *J.dst; | |
| 1130 | + sind2dind(i.d, ARY_ETYPE); | |
| 1131 | + } | |
| 1132 | +} | |
| 1133 | + | |
| 1134 | +# | |
| 1135 | +# Java multianewarray | |
| 1136 | +# | |
| 1137 | + | |
| 1138 | +xmultianewarray() | |
| 1139 | +{ | |
| 1140 | + imframe, iindw, i: ref Inst; | |
| 1141 | + n, rtflag: int; | |
| 1142 | + rtc: ref RTClass; | |
| 1143 | + cr: ref Creloc; | |
| 1144 | + frm, frf: ref Freloc; | |
| 1145 | + ai: ref ArrayInfo; | |
| 1146 | + jpx2d: ref Jinst.Px2d; | |
| 1147 | + | |
| 1148 | + pick jp := J { | |
| 1149 | + Px2d => | |
| 1150 | + jpx2d = jp; | |
| 1151 | + * => | |
| 1152 | + badpick("xmultianewarray"); | |
| 1153 | + } | |
| 1154 | + | |
| 1155 | + ai = getaryinfo(CLASSNAME(jpx2d.x2d.ix)); | |
| 1156 | + rtflag = 0; | |
| 1157 | + if(dortload(ai.ename)) { | |
| 1158 | + rtflag = 1; | |
| 1159 | + rtc = getRTClass(ai.ename); | |
| 1160 | + callrtload(rtc, ai.ename); | |
| 1161 | + } | |
| 1162 | + | |
| 1163 | + cr = getCreloc(RLOADER); | |
| 1164 | + frm = getFreloc(cr, RMP, nil, 0); | |
| 1165 | + frf = getFreloc(cr, "multianewarray", nil, 0); | |
| 1166 | + | |
| 1167 | + imframe = loadermframe(frm, frf); | |
| 1168 | + | |
| 1169 | + # 1st arg: number of dimensions | |
| 1170 | + | |
| 1171 | + i = newi(IMOVW); | |
| 1172 | + addrimm(i.s, ai.ndim); | |
| 1173 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE); | |
| 1174 | + | |
| 1175 | + # 2nd arg: @adt reloc if ref element type, nil otherwise | |
| 1176 | + | |
| 1177 | + i = newi(IMOVP); | |
| 1178 | + addrsind(i.s, Amp, 0); | |
| 1179 | + if(ai.etype == 0) { | |
| 1180 | + if(rtflag == 1) { | |
| 1181 | + RTIpatch(getRTReloc(rtc, RADT, nil, 0), i, PSRC, PSIND); | |
| 1182 | + } else { | |
| 1183 | + LTIpatch(getFreloc(getCreloc(ai.ename), RADT, nil, 0), | |
| 1184 | + i, PSRC, PSIND); | |
| 1185 | + } | |
| 1186 | + } | |
| 1187 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE+IBY2WD); | |
| 1188 | + | |
| 1189 | + # 3rd arg: element type | |
| 1190 | + | |
| 1191 | + i = newi(IMOVW); | |
| 1192 | + addrimm(i.s, ai.etype); | |
| 1193 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE+2*IBY2WD); | |
| 1194 | + | |
| 1195 | + # 4th arg: array of dimensionality information | |
| 1196 | + | |
| 1197 | + i = newi(INEWA); | |
| 1198 | + addrimm(i.s, jpx2d.x2d.dim); | |
| 1199 | + addrimm(i.m, descid(IBY2WD, 1, array [1] of { byte 0 })); | |
| 1200 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE+3*IBY2WD); | |
| 1201 | + | |
| 1202 | + iindw = newi(IINDW); | |
| 1203 | + addrdind(iindw.s, Afpind, imframe.d.offset, REGSIZE+3*IBY2WD); | |
| 1204 | + addrsind(iindw.m, Afp, getreg(DIS_W)); | |
| 1205 | + addrimm(iindw.d, 0); | |
| 1206 | + | |
| 1207 | + for(n = 0; n < jpx2d.x2d.dim; n++) { | |
| 1208 | + i = newi(IMOVW); | |
| 1209 | + *i.s = *code.j[J.src[n]].dst; | |
| 1210 | + relreg(code.j[J.src[n]].dst); | |
| 1211 | + *i.d = *iindw.m; | |
| 1212 | + sind2dind(i.d, n*IBY2WD); | |
| 1213 | + } | |
| 1214 | + relreg(iindw.m); | |
| 1215 | + | |
| 1216 | + i = newi(ILEA); | |
| 1217 | + dstreg(J.dst, DIS_P); | |
| 1218 | + *i.s = *J.dst; | |
| 1219 | + addrdind(i.d, Afpind, imframe.d.offset, REGRET*IBY2WD); | |
| 1220 | + | |
| 1221 | + loadermcall(imframe, frf, frm); | |
| 1222 | + relreg(imframe.d); | |
| 1223 | +} | |
| 1224 | + | |
| 1225 | +arraylength() | |
| 1226 | +{ | |
| 1227 | + i: ref Inst; | |
| 1228 | + | |
| 1229 | + i = newi(ILENA); | |
| 1230 | + *i.s = *code.j[J.src[0]].dst; | |
| 1231 | + relreg(code.j[J.src[0]].dst); | |
| 1232 | + sind2dind(i.s, ARY_DATA); | |
| 1233 | + dstreg(J.dst, DIS_W); | |
| 1234 | + *i.d = *J.dst; | |
| 1235 | +} | |
| 1236 | + | |
| 1237 | +arrayindex(index: int): ref Addr | |
| 1238 | +{ | |
| 1239 | + i: ref Inst; | |
| 1240 | + | |
| 1241 | + i = newi(index); | |
| 1242 | + *i.s = *code.j[J.src[0]].dst; | |
| 1243 | + relreg(code.j[J.src[0]].dst); | |
| 1244 | + sind2dind(i.s, ARY_DATA); | |
| 1245 | + *i.d = *code.j[J.src[1]].dst; | |
| 1246 | + relreg(code.j[J.src[1]].dst); | |
| 1247 | + addrsind(i.m, Afp, getreg(DIS_W)); | |
| 1248 | + | |
| 1249 | + return i.m; | |
| 1250 | +} | |
| 1251 | + | |
| 1252 | +# | |
| 1253 | +# Load an array element. | |
| 1254 | +# | |
| 1255 | + | |
| 1256 | +xarrayload(inst1: int, inst2: int, dtype: byte) | |
| 1257 | +{ | |
| 1258 | + a: ref Addr; | |
| 1259 | + i: ref Inst; | |
| 1260 | + | |
| 1261 | + a = arrayindex(inst1); | |
| 1262 | + i = newi(inst2); | |
| 1263 | + *i.s = *a; | |
| 1264 | + sind2dind(i.s, 0); | |
| 1265 | + relreg(a); | |
| 1266 | + dstreg(J.dst, dtype); | |
| 1267 | + *i.d = *J.dst; | |
| 1268 | + if(inst2 == ICVTBW) # loading from a byte array | |
| 1269 | + signextend(i.d); | |
| 1270 | +} | |
| 1271 | + | |
| 1272 | +# | |
| 1273 | +# Call Loader.aastorecheck() to do runtime checks for aastore. | |
| 1274 | +# | |
| 1275 | + | |
| 1276 | +aastore() | |
| 1277 | +{ | |
| 1278 | + imframe, imovp, imcall: ref Inst; | |
| 1279 | + cr: ref Creloc; | |
| 1280 | + frm, frf: ref Freloc; | |
| 1281 | + | |
| 1282 | + cr = getCreloc(RLOADER); | |
| 1283 | + frm = getFreloc(cr, RMP, nil, 0); | |
| 1284 | + frf = getFreloc(cr, "aastorecheck", nil, 0); | |
| 1285 | + | |
| 1286 | + imframe = loadermframe(frm, frf); | |
| 1287 | + | |
| 1288 | + imovp = newi(IMOVP); | |
| 1289 | + *imovp.s = *code.j[J.src[2]].dst; | |
| 1290 | + addrdind(imovp.d, Afpind, imframe.d.offset, REGSIZE); | |
| 1291 | + | |
| 1292 | + imovp = newi(IMOVP); | |
| 1293 | + *imovp.s = *code.j[J.src[0]].dst; | |
| 1294 | + addrdind(imovp.d, Afpind, imframe.d.offset, REGSIZE+IBY2WD); | |
| 1295 | + | |
| 1296 | + imcall = loadermcall(imframe, frf, frm); | |
| 1297 | + relreg(imframe.d); | |
| 1298 | +} | |
| 1299 | + | |
| 1300 | +# | |
| 1301 | +# Store an array element. | |
| 1302 | +# | |
| 1303 | + | |
| 1304 | +xarraystore(inst1: int, inst2: int) | |
| 1305 | +{ | |
| 1306 | + a: ref Addr; | |
| 1307 | + i: ref Inst; | |
| 1308 | + | |
| 1309 | + a = arrayindex(inst1); | |
| 1310 | + i = newi(inst2); | |
| 1311 | + *i.s = *code.j[J.src[2]].dst; | |
| 1312 | + relreg(code.j[J.src[2]].dst); | |
| 1313 | + *i.d = *a; | |
| 1314 | + sind2dind(i.d, 0); | |
| 1315 | + relreg(a); | |
| 1316 | + datareloc(i); | |
| 1317 | +} | |
| 1318 | + | |
| 1319 | +# | |
| 1320 | +# monitorenter, monitorexit, athrow. Also used for synchronized methods. | |
| 1321 | +# | |
| 1322 | + | |
| 1323 | +mon_or_throw(op: int, flags: int, syncblock: int) | |
| 1324 | +{ | |
| 1325 | + loaderfn: string; | |
| 1326 | + imframe, i: ref Inst; | |
| 1327 | + cr: ref Creloc; | |
| 1328 | + frm, frf, fro: ref Freloc; | |
| 1329 | + | |
| 1330 | + case op { | |
| 1331 | + Jathrow => | |
| 1332 | + loaderfn = "throw"; | |
| 1333 | + Jmonitorenter => | |
| 1334 | + loaderfn = "monitorenter"; | |
| 1335 | + Jmonitorexit => | |
| 1336 | + loaderfn = "monitorexit"; | |
| 1337 | + } | |
| 1338 | + | |
| 1339 | + cr = getCreloc(RLOADER); | |
| 1340 | + frm = getFreloc(cr, RMP, nil, 0); | |
| 1341 | + frf = getFreloc(cr, loaderfn, nil, 0); | |
| 1342 | + | |
| 1343 | + imframe = loadermframe(frm, frf); | |
| 1344 | + | |
| 1345 | + i = newi(IMOVP); | |
| 1346 | + if(op == Jathrow || syncblock) { # throw or synchronized block | |
| 1347 | + *i.s = *code.j[J.src[0]].dst; | |
| 1348 | + relreg(code.j[J.src[0]].dst); | |
| 1349 | + } else if(flags & ACC_STATIC) { # synchronized class method | |
| 1350 | + addrsind(i.s, Amp, 0); | |
| 1351 | + fro = getFreloc(getCreloc(THISCLASS), ROBJ, nil, 0); | |
| 1352 | + LTIpatch(fro, i, PSRC, PSIND); | |
| 1353 | + } else # synchronized instance method | |
| 1354 | + addrsind(i.s, Afp, THISOFF); | |
| 1355 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE); | |
| 1356 | + | |
| 1357 | + loadermcall(imframe, frf, frm); | |
| 1358 | + relreg(imframe.d); | |
| 1359 | + | |
| 1360 | + # for jit: so mcall has an instruction for its return address | |
| 1361 | + if(op == Jathrow && J.pc+1 == code.code_length) { | |
| 1362 | + i = newi(IJMP); | |
| 1363 | + addrimm(i.d, 0); | |
| 1364 | + } | |
| 1365 | +} | |
| 1366 | + | |
| 1367 | +xjavaload(op: int) | |
| 1368 | +{ | |
| 1369 | + i: ref Inst; | |
| 1370 | + | |
| 1371 | + if(J.movsrc.mode != Anone) { # marked for explicit mov | |
| 1372 | + i = newi(op); | |
| 1373 | + *i.s = *J.movsrc; | |
| 1374 | + dstreg(J.dst, j2dtype(J.jtype)); | |
| 1375 | + *i.d = *J.dst; | |
| 1376 | + datareloc(i); | |
| 1377 | + } | |
| 1378 | +} | |
| 1379 | + | |
| 1380 | +xjavastore(op: int) | |
| 1381 | +{ | |
| 1382 | + i: ref Inst; | |
| 1383 | + | |
| 1384 | + if(op == IMOVP && J.bb.js == J && int (J.bb.flags & BB_FINALLY)) | |
| 1385 | + ; # astore instruction at the start of a finally block | |
| 1386 | + else if(J.dst.mode != Anone) { # marked for explicit mov | |
| 1387 | + i = newi(op); | |
| 1388 | + *i.s = *code.j[J.src[0]].dst; | |
| 1389 | + relreg(code.j[J.src[0]].dst); | |
| 1390 | + *i.d = *J.dst; | |
| 1391 | + datareloc(i); | |
| 1392 | + } | |
| 1393 | +} | |
| 1394 | + | |
| 1395 | +# | |
| 1396 | +# Check immediate middle operands that are too big. | |
| 1397 | +# | |
| 1398 | + | |
| 1399 | +midcheck(a: ref Addr) | |
| 1400 | +{ | |
| 1401 | + if(a.mode == Aimm && (a.ival > 16r7fff || a.ival < -16r8000)) { | |
| 1402 | + a.mode = Amp; | |
| 1403 | + a.offset = mpint(a.ival); | |
| 1404 | + } | |
| 1405 | +} | |
| 1406 | + | |
| 1407 | +# | |
| 1408 | +# Coerce a 64-bit real to a 32-bit real (and back). | |
| 1409 | +# | |
| 1410 | + | |
| 1411 | +real64to32(a: ref Addr) | |
| 1412 | +{ | |
| 1413 | + i1, i2: ref Inst; | |
| 1414 | + | |
| 1415 | + i1 = newi(ICVTFR); | |
| 1416 | + *i1.s = *a; | |
| 1417 | + addrsind(i1.d, Afp, getreg(DIS_W)); | |
| 1418 | + | |
| 1419 | + i2 = newi(ICVTRF); | |
| 1420 | + *i2.s = *i1.d; | |
| 1421 | + *i2.d = *i1.s; | |
| 1422 | + | |
| 1423 | + relreg(i1.d); | |
| 1424 | +} | |
| 1425 | + | |
| 1426 | +xbinop(op: int, dtype: byte, cvtreal: int) | |
| 1427 | +{ | |
| 1428 | + i: ref Inst; | |
| 1429 | + | |
| 1430 | + i = newi(op); | |
| 1431 | + *i.s = *code.j[J.src[1]].dst; | |
| 1432 | + relreg(code.j[J.src[1]].dst); | |
| 1433 | + *i.m = *code.j[J.src[0]].dst; | |
| 1434 | + relreg(code.j[J.src[0]].dst); | |
| 1435 | + midcheck(i.m); | |
| 1436 | + dstreg(J.dst, dtype); | |
| 1437 | + *i.d = *J.dst; | |
| 1438 | + middstcmp(i); | |
| 1439 | + datareloc(i); | |
| 1440 | + | |
| 1441 | + if(cvtreal) | |
| 1442 | + real64to32(i.d); | |
| 1443 | +} | |
| 1444 | + | |
| 1445 | +shift(op: int, dtype: byte) | |
| 1446 | +{ | |
| 1447 | + iaddw, i: ref Inst; | |
| 1448 | + | |
| 1449 | + iaddw = newi(IANDW); | |
| 1450 | + *iaddw.s = *code.j[J.src[1]].dst; | |
| 1451 | + relreg(code.j[J.src[1]].dst); | |
| 1452 | + if(dtype == DIS_W) # ishl, ishr, iushr | |
| 1453 | + addrimm(iaddw.m, 31); | |
| 1454 | + else # lshl, lshr, lushr | |
| 1455 | + addrimm(iaddw.m, 63); | |
| 1456 | + addrsind(iaddw.d, Afp, getreg(DIS_W)); | |
| 1457 | + datareloc(iaddw); | |
| 1458 | + | |
| 1459 | + i = newi(op); | |
| 1460 | + *i.s = *iaddw.d; | |
| 1461 | + relreg(iaddw.d); | |
| 1462 | + *i.m = *code.j[J.src[0]].dst; | |
| 1463 | + relreg(code.j[J.src[0]].dst); | |
| 1464 | + midcheck(i.m); | |
| 1465 | + dstreg(J.dst, dtype); | |
| 1466 | + *i.d = *J.dst; | |
| 1467 | + middstcmp(i); | |
| 1468 | + datareloc(i); | |
| 1469 | +} | |
| 1470 | + | |
| 1471 | +cvt(op: int, dtype: byte, cvtreal: int) | |
| 1472 | +{ | |
| 1473 | + i: ref Inst; | |
| 1474 | + | |
| 1475 | + i = newi(op); | |
| 1476 | + *i.s = *code.j[J.src[0]].dst; | |
| 1477 | + relreg(code.j[J.src[0]].dst); | |
| 1478 | + dstreg(J.dst, dtype); | |
| 1479 | + *i.d = *J.dst; | |
| 1480 | + datareloc(i); | |
| 1481 | + | |
| 1482 | + if(cvtreal) | |
| 1483 | + real64to32(i.d); | |
| 1484 | +} | |
| 1485 | + | |
| 1486 | +i2c() | |
| 1487 | +{ | |
| 1488 | + i: ref Inst; | |
| 1489 | + | |
| 1490 | + i = newi(IANDW); | |
| 1491 | + *i.s = *code.j[J.src[0]].dst; | |
| 1492 | + relreg(code.j[J.src[0]].dst); | |
| 1493 | + addrsind(i.m, Amp, mpint(16rffff)); | |
| 1494 | + dstreg(J.dst, DIS_W); | |
| 1495 | + *i.d = *J.dst; | |
| 1496 | + datareloc(i); | |
| 1497 | +} | |
| 1498 | + | |
| 1499 | +# | |
| 1500 | +# i2b, i2s. | |
| 1501 | +# | |
| 1502 | + | |
| 1503 | +i2bs(shift: int) | |
| 1504 | +{ | |
| 1505 | + i1, i2: ref Inst; | |
| 1506 | + | |
| 1507 | + i1 = newi(ISHLW); | |
| 1508 | + addrimm(i1.s, shift); | |
| 1509 | + *i1.m = *code.j[J.src[0]].dst; | |
| 1510 | + relreg(code.j[J.src[0]].dst); | |
| 1511 | + midcheck(i1.m); | |
| 1512 | + dstreg(J.dst, DIS_W); | |
| 1513 | + *i1.d = *J.dst; | |
| 1514 | + middstcmp(i1); | |
| 1515 | + datareloc(i1); | |
| 1516 | + | |
| 1517 | + i2 = newi(ISHRW); | |
| 1518 | + addrimm(i2.s, shift); | |
| 1519 | + # *i2.m = *i1.d; # redundant | |
| 1520 | + *i2.d = *i1.d; | |
| 1521 | +} | |
| 1522 | + | |
| 1523 | +# | |
| 1524 | +# ineg, lneg, fneg, dneg | |
| 1525 | +# | |
| 1526 | + | |
| 1527 | +neg(op: int, dtype: byte) | |
| 1528 | +{ | |
| 1529 | + i: ref Inst; | |
| 1530 | + | |
| 1531 | + i = newi(op); | |
| 1532 | + *i.s = *code.j[J.src[0]].dst; | |
| 1533 | + relreg(code.j[J.src[0]].dst); | |
| 1534 | + if(op == ISUBW) # ineg | |
| 1535 | + addrimm(i.m, 0); | |
| 1536 | + else if(op == ISUBL) # lneg | |
| 1537 | + addrsind(i.m, Amp, mplong(big 0)); | |
| 1538 | + dstreg(J.dst, dtype); | |
| 1539 | + *i.d = *J.dst; | |
| 1540 | + datareloc(i); | |
| 1541 | +} | |
| 1542 | + | |
| 1543 | +iinc(val: int, ix: int) | |
| 1544 | +{ | |
| 1545 | + i: ref Inst; | |
| 1546 | + | |
| 1547 | + i = newi(IADDW); | |
| 1548 | + addrimm(i.s, val); | |
| 1549 | + addrsind(i.d, Afp, localix(DIS_W, ix)); | |
| 1550 | +} | |
| 1551 | + | |
| 1552 | +# | |
| 1553 | +# For javaif and javagoto, compute difference of try nesting | |
| 1554 | +# level between source PC and destination PC. | |
| 1555 | +# J.pc is source PC | |
| 1556 | +# J.u.i is destination PC (relative from J.pc) | |
| 1557 | +# | |
| 1558 | + | |
| 1559 | +tldiff(): int | |
| 1560 | +{ | |
| 1561 | + tls, tld: int; | |
| 1562 | + ix: int; | |
| 1563 | + | |
| 1564 | + pick jp := J { | |
| 1565 | + Pi => | |
| 1566 | + ix = jp.i; | |
| 1567 | + * => | |
| 1568 | + badpick("tldiff"); | |
| 1569 | + } | |
| 1570 | + | |
| 1571 | + tld = 0; | |
| 1572 | + tls = trylevel(J.pc); | |
| 1573 | + if(tls > 0) | |
| 1574 | + tld = trylevel(J.pc+ix); | |
| 1575 | + return tls-tld; | |
| 1576 | +} | |
| 1577 | + | |
| 1578 | +# | |
| 1579 | +# Java if_acmp<cond>, if_icmp<cond>, if<cond>, ifnonnull, ifnull. | |
| 1580 | +# | |
| 1581 | + | |
| 1582 | +CMPNULL, # compare against null: ifnonnull, ifnull | |
| 1583 | +CMPZERO, # compare against 0: if<cond> | |
| 1584 | +CMP2OP: con iota; # general compare: if_acmp<cond>, if_icmp<cond> | |
| 1585 | + | |
| 1586 | +javaif(op: int, cmpkind: int) | |
| 1587 | +{ | |
| 1588 | + i: ref Inst; | |
| 1589 | + n: int; | |
| 1590 | + ix: int; | |
| 1591 | + | |
| 1592 | + pick jp := J { | |
| 1593 | + Pi => | |
| 1594 | + ix = jp.i; | |
| 1595 | + * => | |
| 1596 | + badpick("javaif"); | |
| 1597 | + } | |
| 1598 | + | |
| 1599 | + #n = tldiff(); | |
| 1600 | + #if(n > 0) { | |
| 1601 | + # # complement the test when calling Sys.unrescue() | |
| 1602 | + # case op { | |
| 1603 | + # IBEQW => | |
| 1604 | + # op = IBNEW; | |
| 1605 | + # IBNEW => | |
| 1606 | + # op = IBEQW; | |
| 1607 | + # IBLTW => | |
| 1608 | + # op = IBGEW; | |
| 1609 | + # IBLEW => | |
| 1610 | + # op = IBGTW; | |
| 1611 | + # IBGTW => | |
| 1612 | + # op = IBLEW; | |
| 1613 | + # IBGEW => | |
| 1614 | + # op = IBLTW; | |
| 1615 | + # } | |
| 1616 | + # i = newi(op); | |
| 1617 | + # addrimm(i.d, pcdis + 2*n + 1); | |
| 1618 | + #} else { | |
| 1619 | + i = newibap(op); | |
| 1620 | + addrimm(i.d, ix); | |
| 1621 | + #} | |
| 1622 | + | |
| 1623 | + *i.s = *code.j[J.src[0]].dst; | |
| 1624 | + relreg(code.j[J.src[0]].dst); | |
| 1625 | + | |
| 1626 | + case cmpkind { | |
| 1627 | + CMPNULL => | |
| 1628 | + addrsind(i.m, Amp, 0); | |
| 1629 | + CMPZERO => | |
| 1630 | + addrimm(i.m, 0); | |
| 1631 | + datareloc(i); | |
| 1632 | + CMP2OP => | |
| 1633 | + *i.m = *code.j[J.src[1]].dst; | |
| 1634 | + relreg(code.j[J.src[1]].dst); | |
| 1635 | + midcheck(i.m); | |
| 1636 | + datareloc(i); | |
| 1637 | + } | |
| 1638 | + | |
| 1639 | + #if(n > 0) { | |
| 1640 | + # unrescue(n); | |
| 1641 | + # callunrescue = 0; | |
| 1642 | + # i = newibap(IJMP); | |
| 1643 | + # addrimm(i.d, ix); | |
| 1644 | + #} | |
| 1645 | +} | |
| 1646 | + | |
| 1647 | +# | |
| 1648 | +# Java goto and goto_w. | |
| 1649 | +# | |
| 1650 | + | |
| 1651 | +javagoto() | |
| 1652 | +{ | |
| 1653 | + i: ref Inst; | |
| 1654 | + n: int; | |
| 1655 | + ix: int; | |
| 1656 | + | |
| 1657 | + pick jp := J { | |
| 1658 | + Pi => | |
| 1659 | + ix = jp.i; | |
| 1660 | + * => | |
| 1661 | + badpick("javagoto"); | |
| 1662 | + } | |
| 1663 | + | |
| 1664 | + #n = tldiff(); | |
| 1665 | + #if(n > 0) { | |
| 1666 | + # unrescue(n); | |
| 1667 | + # callunrescue = 0; | |
| 1668 | + #} | |
| 1669 | + i = newibap(IJMP); | |
| 1670 | + addrimm(i.d, ix); | |
| 1671 | +} | |
| 1672 | + | |
| 1673 | +# | |
| 1674 | +# Java return instructions. | |
| 1675 | +# | |
| 1676 | + | |
| 1677 | +xjavareturn(op: int) | |
| 1678 | +{ | |
| 1679 | + i: ref Inst; | |
| 1680 | + | |
| 1681 | + if(op != 0) { # if op == 0, then return void | |
| 1682 | + i = newi(op); | |
| 1683 | + *i.s = *code.j[J.src[0]].dst; | |
| 1684 | + relreg(code.j[J.src[0]].dst); | |
| 1685 | + addrdind(i.d, Afpind, REGRET*IBY2WD, 0); | |
| 1686 | + datareloc(i); | |
| 1687 | + } | |
| 1688 | + | |
| 1689 | + if(M.access_flags & ACC_SYNCHRONIZED) | |
| 1690 | + mon_or_throw(Jmonitorexit, M.access_flags, 0); | |
| 1691 | + | |
| 1692 | + newi(IRET); | |
| 1693 | +} | |
| 1694 | + | |
| 1695 | +# | |
| 1696 | +# pop & pop2 | |
| 1697 | +# | |
| 1698 | + | |
| 1699 | +xjavapop() | |
| 1700 | +{ | |
| 1701 | + relreg(code.j[J.src[0]].dst); | |
| 1702 | + if(J.nsrc == 2) # pop2 | |
| 1703 | + relreg(code.j[J.src[1]].dst); | |
| 1704 | +} | |
| 1705 | + | |
| 1706 | +# | |
| 1707 | +# dup, dup2, etc. | |
| 1708 | +# | |
| 1709 | + | |
| 1710 | +xjavadup() | |
| 1711 | +{ | |
| 1712 | + acqreg(code.j[J.src[0]].dst); | |
| 1713 | + if(J.nsrc == 2) | |
| 1714 | + acqreg(code.j[J.src[1]].dst); | |
| 1715 | +} | |
| 1716 | + | |
| 1717 | +xldc() | |
| 1718 | +{ | |
| 1719 | + i: ref Inst; | |
| 1720 | + ix: int; | |
| 1721 | + | |
| 1722 | + pick jp := J { | |
| 1723 | + Pi => | |
| 1724 | + ix = jp.i; | |
| 1725 | + * => | |
| 1726 | + badpick("xldc[1]"); | |
| 1727 | + } | |
| 1728 | + | |
| 1729 | + case int class.cts[ix] { | |
| 1730 | + CON_Integer => | |
| 1731 | + xjavaload(IMOVW); | |
| 1732 | + CON_Float or | |
| 1733 | + CON_Double => | |
| 1734 | + xjavaload(IMOVF); | |
| 1735 | + CON_Long => | |
| 1736 | + xjavaload(IMOVL); | |
| 1737 | + CON_String => | |
| 1738 | + xjavanew("java/lang/String", J.dst); | |
| 1739 | + i = newi(IMOVP); | |
| 1740 | + *i.s = *J.movsrc; | |
| 1741 | + *i.d = *J.dst; | |
| 1742 | + sind2dind(i.d, STR_DISSTR); | |
| 1743 | + addDreloc(i, PSRC, PSIND); | |
| 1744 | + CON_Class => | |
| 1745 | + # TODO: stub! | |
| 1746 | + xjavaload(IMOVW); | |
| 1747 | + * => | |
| 1748 | + badpick("xldc[2]"); | |
| 1749 | + } | |
| 1750 | +} | |
| 1751 | + | |
| 1752 | +# | |
| 1753 | +# Java jsr and jsr_w. | |
| 1754 | +# ix is relative Java pc offset of finally block entry point. | |
| 1755 | +# | |
| 1756 | + | |
| 1757 | +jsr(ix: int) | |
| 1758 | +{ | |
| 1759 | + i: ref Inst; | |
| 1760 | + | |
| 1761 | + i = newi(IMOVW); | |
| 1762 | + addrimm(i.s, 0); | |
| 1763 | + addrsind(i.d, Amp, 0); | |
| 1764 | + jsrfixup(i.s, i.d, i.pc+2, J.pc+ix); | |
| 1765 | + addDreloc(i, PDST, PSIND); | |
| 1766 | + | |
| 1767 | + i = newibap(IJMP); | |
| 1768 | + addrimm(i.d, ix); | |
| 1769 | +} | |
| 1770 | + | |
| 1771 | +# | |
| 1772 | +# Java ret and wide ret. | |
| 1773 | +# | |
| 1774 | + | |
| 1775 | +ret() | |
| 1776 | +{ | |
| 1777 | + i: ref Inst; | |
| 1778 | + | |
| 1779 | + i = newi(IGOTO); | |
| 1780 | + addrsind(i.s, Amp, 0); | |
| 1781 | + addrsind(i.d, Amp, 0); | |
| 1782 | + retfixup(i.s, i.d, J.pc); | |
| 1783 | + addDreloc(i, PSRC, PSIND); | |
| 1784 | + addDreloc(i, PDST, PSIND); | |
| 1785 | +} | |
| 1786 | + | |
| 1787 | +tableswitch() | |
| 1788 | +{ | |
| 1789 | + i: ref Inst; | |
| 1790 | + j, k, n, lb: int; | |
| 1791 | + jt: array of int; | |
| 1792 | + jpt1: ref Jinst.Pt1; | |
| 1793 | + | |
| 1794 | + pick jp := J { | |
| 1795 | + Pt1 => | |
| 1796 | + jpt1 = jp; | |
| 1797 | + * => | |
| 1798 | + badpick("tableswitch"); | |
| 1799 | + } | |
| 1800 | + | |
| 1801 | + n = jpt1.t1.hb - jpt1.t1.lb + 1; | |
| 1802 | + jt = array [n*3+1] of int; | |
| 1803 | + j = 0; | |
| 1804 | + k = 0; | |
| 1805 | + lb = jpt1.t1.lb; | |
| 1806 | + while(j < n) { | |
| 1807 | + jt[k++] = lb; | |
| 1808 | + jt[k++] = ++lb; | |
| 1809 | + jt[k++] = jpt1.t1.tbl[j]; | |
| 1810 | + j++; | |
| 1811 | + } | |
| 1812 | + jt[k] = jpt1.t1.dflt; | |
| 1813 | + i = newi(ICASE); | |
| 1814 | + *i.s = *code.j[J.src[0]].dst; | |
| 1815 | + relreg(code.j[J.src[0]].dst); | |
| 1816 | + addrsind(i.d, Amp, mpcase(n, jt)); | |
| 1817 | + patchcase(i, n, jt); | |
| 1818 | + addDreloc(i, PDST, PSIND); | |
| 1819 | +} | |
| 1820 | + | |
| 1821 | +lookupswitch() | |
| 1822 | +{ | |
| 1823 | + i: ref Inst; | |
| 1824 | + j, k: int; | |
| 1825 | + jt: array of int; | |
| 1826 | + jpt2: ref Jinst.Pt2; | |
| 1827 | + | |
| 1828 | + pick jp := J { | |
| 1829 | + Pt2 => | |
| 1830 | + jpt2 = jp; | |
| 1831 | + * => | |
| 1832 | + badpick("lookupswitch"); | |
| 1833 | + } | |
| 1834 | + | |
| 1835 | + jt = array [jpt2.t2.np*3+1] of int; | |
| 1836 | + j = 0; | |
| 1837 | + k = 0; | |
| 1838 | + while(j < jpt2.t2.np*2) { | |
| 1839 | + jt[k++] = jpt2.t2.tbl[j]; | |
| 1840 | + jt[k++] = jpt2.t2.tbl[j]+1; | |
| 1841 | + jt[k++] = jpt2.t2.tbl[j+1]; | |
| 1842 | + j += 2; | |
| 1843 | + } | |
| 1844 | + jt[k] = jpt2.t2.dflt; | |
| 1845 | + i = newi(ICASE); | |
| 1846 | + *i.s = *code.j[J.src[0]].dst; | |
| 1847 | + relreg(code.j[J.src[0]].dst); | |
| 1848 | + addrsind(i.d, Amp, mpcase(jpt2.t2.np, jt)); | |
| 1849 | + patchcase(i, jpt2.t2.np, jt); | |
| 1850 | + addDreloc(i, PDST, PSIND); | |
| 1851 | +} | |
| 1852 | + | |
| 1853 | +# | |
| 1854 | +# Call a library routine. Supports lcmp, [df]cmp[gl], [df]rem. | |
| 1855 | +# | |
| 1856 | + | |
| 1857 | +jmath(jname: string, movinst: int, dtype: byte) | |
| 1858 | +{ | |
| 1859 | + imframe, i: ref Inst; | |
| 1860 | + cr: ref Creloc; | |
| 1861 | + frm, frf: ref Freloc; | |
| 1862 | + | |
| 1863 | + cr = getCreloc(RLOADER); | |
| 1864 | + frm = getFreloc(cr, RMP, nil, 0); | |
| 1865 | + frf = getFreloc(cr, jname, nil, 0); | |
| 1866 | + | |
| 1867 | + imframe = loadermframe(frm, frf); | |
| 1868 | + | |
| 1869 | + i = newi(movinst); | |
| 1870 | + *i.s = *code.j[J.src[0]].dst; | |
| 1871 | + relreg(code.j[J.src[0]].dst); | |
| 1872 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE); | |
| 1873 | + datareloc(i); | |
| 1874 | + | |
| 1875 | + if(jname[1] != '2') { # d2i or d2l ? | |
| 1876 | + i = newi(movinst); | |
| 1877 | + *i.s = *code.j[J.src[1]].dst; | |
| 1878 | + relreg(code.j[J.src[1]].dst); | |
| 1879 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE+IBY2LG); | |
| 1880 | + datareloc(i); | |
| 1881 | + } | |
| 1882 | + | |
| 1883 | + i = newi(ILEA); | |
| 1884 | + dstreg(J.dst, dtype); | |
| 1885 | + *i.s = *J.dst; | |
| 1886 | + addrdind(i.d, Afpind, imframe.d.offset, REGRET*IBY2WD); | |
| 1887 | + | |
| 1888 | + loadermcall(imframe, frf, frm); | |
| 1889 | + relreg(imframe.d); | |
| 1890 | +} | |
| 1891 | + | |
| 1892 | +# | |
| 1893 | +# checkcast & instanceof | |
| 1894 | +# | |
| 1895 | + | |
| 1896 | +rtti() | |
| 1897 | +{ | |
| 1898 | + loaderfn: string; | |
| 1899 | + imframe, i: ref Inst; | |
| 1900 | + rtflag: int; | |
| 1901 | + rtc: ref RTClass; | |
| 1902 | + cr: ref Creloc; | |
| 1903 | + frm, frf: ref Freloc; | |
| 1904 | + ai: ref ArrayInfo; | |
| 1905 | + ix: int; | |
| 1906 | + | |
| 1907 | + pick jp := J { | |
| 1908 | + Pi => | |
| 1909 | + ix = jp.i; | |
| 1910 | + * => | |
| 1911 | + badpick("rtti"); | |
| 1912 | + } | |
| 1913 | + | |
| 1914 | + ai = getaryinfo(CLASSNAME(ix)); | |
| 1915 | + rtflag = 0; | |
| 1916 | + if(dortload(ai.ename)) { | |
| 1917 | + rtflag = 1; | |
| 1918 | + rtc = getRTClass(ai.ename); | |
| 1919 | + callrtload(rtc, ai.ename); | |
| 1920 | + } | |
| 1921 | + | |
| 1922 | + if(J.op == byte Jcheckcast) { | |
| 1923 | + if(ai.ndim > 0) { | |
| 1924 | + if(ai.etype > 0) | |
| 1925 | + loaderfn = "pcheckcast"; | |
| 1926 | + else | |
| 1927 | + loaderfn = "acheckcast"; | |
| 1928 | + } else | |
| 1929 | + loaderfn = "checkcast"; | |
| 1930 | + } else { | |
| 1931 | + if(ai.ndim > 0) { | |
| 1932 | + if(ai.etype > 0) | |
| 1933 | + loaderfn = "pinstanceof"; | |
| 1934 | + else | |
| 1935 | + loaderfn = "ainstanceof"; | |
| 1936 | + } else | |
| 1937 | + loaderfn = "instanceof"; | |
| 1938 | + } | |
| 1939 | + | |
| 1940 | + cr = getCreloc(RLOADER); | |
| 1941 | + frm = getFreloc(cr, RMP, nil, 0); | |
| 1942 | + frf = getFreloc(cr, loaderfn, nil, 0); | |
| 1943 | + | |
| 1944 | + imframe = loadermframe(frm, frf); | |
| 1945 | + | |
| 1946 | + # pass object as first argument | |
| 1947 | + | |
| 1948 | + i = newi(IMOVP); | |
| 1949 | + *i.s = *code.j[J.src[0]].dst; | |
| 1950 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE); | |
| 1951 | + | |
| 1952 | + # second argument | |
| 1953 | + | |
| 1954 | + if(ai.etype == 0) { | |
| 1955 | + i = newi(IMOVP); | |
| 1956 | + addrsind(i.s, Amp, 0); | |
| 1957 | + if(rtflag == 1) { | |
| 1958 | + RTIpatch(getRTReloc(rtc, RADT, nil, 0), i, PSRC, PSIND); | |
| 1959 | + } else { | |
| 1960 | + LTIpatch(getFreloc(getCreloc(ai.ename), RADT, nil, 0), | |
| 1961 | + i, PSRC, PSIND); | |
| 1962 | + } | |
| 1963 | + } else { | |
| 1964 | + i = newi(IMOVW); | |
| 1965 | + addrimm(i.s, ai.etype); | |
| 1966 | + } | |
| 1967 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE+IBY2WD); | |
| 1968 | + | |
| 1969 | + # third argument, if present | |
| 1970 | + | |
| 1971 | + if(ai.ndim > 0) { | |
| 1972 | + i = newi(IMOVW); | |
| 1973 | + addrimm(i.s, ai.ndim); | |
| 1974 | + addrdind(i.d, Afpind, imframe.d.offset, REGSIZE+2*IBY2WD); | |
| 1975 | + } | |
| 1976 | + | |
| 1977 | + if(J.op == byte Jinstanceof) { | |
| 1978 | + i = newi(ILEA); | |
| 1979 | + dstreg(J.dst, DIS_W); | |
| 1980 | + *i.s = *J.dst; | |
| 1981 | + addrdind(i.d, Afpind, imframe.d.offset, REGRET*IBY2WD); | |
| 1982 | + } | |
| 1983 | + | |
| 1984 | + loadermcall(imframe, frf, frm); | |
| 1985 | + relreg(imframe.d); | |
| 1986 | + | |
| 1987 | + if(J.op == byte Jcheckcast) { | |
| 1988 | + i = newi(IMOVP); | |
| 1989 | + *i.s = *code.j[J.src[0]].dst; | |
| 1990 | + relreg(code.j[J.src[0]].dst); | |
| 1991 | + dstreg(J.dst, DIS_P); | |
| 1992 | + *i.d = *J.dst; | |
| 1993 | + datareloc(i); | |
| 1994 | + } else | |
| 1995 | + relreg(code.j[J.src[0]].dst); | |
| 1996 | +} | |
| 1997 | + | |
| 1998 | +# | |
| 1999 | +# Exception handling. | |
| 2000 | +# | |
| 2001 | + | |
| 2002 | +Catch: adt { | |
| 2003 | + exname: string; | |
| 2004 | + handler_pc: int; | |
| 2005 | + next: cyclic ref Catch; | |
| 2006 | +}; | |
| 2007 | + | |
| 2008 | +Try: adt { | |
| 2009 | + start_pc: int; | |
| 2010 | + end_pc: int; | |
| 2011 | + any_pc: int; | |
| 2012 | + catch: ref Catch; | |
| 2013 | + next: cyclic ref Try; | |
| 2014 | +}; | |
| 2015 | + | |
| 2016 | +EHInst: adt { | |
| 2017 | + i: ref Inst; | |
| 2018 | + next: cyclic ref EHInst; | |
| 2019 | +}; | |
| 2020 | + | |
| 2021 | +ehinst: ref EHInst; | |
| 2022 | +trylist: ref Try; | |
| 2023 | +distrylist: ref Try; | |
| 2024 | + | |
| 2025 | +# | |
| 2026 | +# Save an EH branch instruction for later patching. | |
| 2027 | +# | |
| 2028 | + | |
| 2029 | +saveehinst(i: ref Inst) | |
| 2030 | +{ | |
| 2031 | + ehi: ref EHInst; | |
| 2032 | + | |
| 2033 | + ehi = ref EHInst(i, ehinst); | |
| 2034 | + ehinst = ehi; | |
| 2035 | +} | |
| 2036 | + | |
| 2037 | +# | |
| 2038 | +# Patch an EH branch instruction. | |
| 2039 | +# Java PCs in exception tables are absolute, not relative. | |
| 2040 | +# | |
| 2041 | + | |
| 2042 | +patchehinst() | |
| 2043 | +{ | |
| 2044 | + ehi: ref EHInst; | |
| 2045 | + i: ref Inst; | |
| 2046 | + j: ref Jinst; | |
| 2047 | + jix: int; | |
| 2048 | + | |
| 2049 | + for(ehi = ehinst; ehi != nil; ehi = ehi.next) { | |
| 2050 | + i = ehi.i; | |
| 2051 | + jix = i.d.ival; | |
| 2052 | + j = code.j[jix]; | |
| 2053 | + while(j.dis == nil) { | |
| 2054 | + jix += j.size; | |
| 2055 | + j = code.j[jix]; | |
| 2056 | + } | |
| 2057 | + i.d.ival = j.dis.pc; | |
| 2058 | + } | |
| 2059 | + ehinst = nil; | |
| 2060 | +} | |
| 2061 | + | |
| 2062 | +# | |
| 2063 | +# Convert handler information into a more convenient form. | |
| 2064 | +# | |
| 2065 | + | |
| 2066 | +cvtehinfo() | |
| 2067 | +{ | |
| 2068 | + i: int; | |
| 2069 | + t: ref Try; | |
| 2070 | + c: ref Catch; | |
| 2071 | + h: ref Handler; | |
| 2072 | + | |
| 2073 | + if(code.nex == 0) | |
| 2074 | + return; | |
| 2075 | + | |
| 2076 | + # process in reverse to maintain order of try & catch blocks | |
| 2077 | + for(i = code.nex-1; i >= 0; i--) { | |
| 2078 | + h = code.ex[i]; | |
| 2079 | + if(trylist == nil | |
| 2080 | + || (t.start_pc != h.start_pc || t.end_pc != h.end_pc)) { | |
| 2081 | + t = ref Try(h.start_pc, h.end_pc, 0, nil, trylist); | |
| 2082 | + trylist = t; | |
| 2083 | + } | |
| 2084 | + if(h.catch_type == 0) { | |
| 2085 | + t.any_pc = h.handler_pc; | |
| 2086 | + } else { | |
| 2087 | + c = ref Catch(CLASSNAME(h.catch_type), h.handler_pc, t.catch); | |
| 2088 | + t.catch = c; | |
| 2089 | + } | |
| 2090 | + } | |
| 2091 | +} | |
| 2092 | + | |
| 2093 | +# | |
| 2094 | +# At what try nesting level is the given Java pc at. | |
| 2095 | +# 0 means not within a try block. | |
| 2096 | +# | |
| 2097 | + | |
| 2098 | +trylevel(pc: int): int | |
| 2099 | +{ | |
| 2100 | + level: int; | |
| 2101 | + t: ref Try; | |
| 2102 | + | |
| 2103 | + level = 0; | |
| 2104 | + for(t = trylist; t != nil; t = t.next) { | |
| 2105 | + if(pc >= t.start_pc && pc < t.end_pc) | |
| 2106 | + level += 1; | |
| 2107 | + } | |
| 2108 | + return level; | |
| 2109 | +} | |
| 2110 | + | |
| 2111 | +# | |
| 2112 | +# Install an exception handler: call sys.rescue("*", nil). | |
| 2113 | +# | |
| 2114 | + | |
| 2115 | +rescue(): ref Addr | |
| 2116 | +{ | |
| 2117 | + print("rescue()\n"); | |
| 2118 | + #imframe, i: ref Inst; | |
| 2119 | + #cr: ref Creloc; | |
| 2120 | + #frm, frf: ref Freloc; | |
| 2121 | +# | |
| 2122 | + #cr = getCreloc(RLOADER); | |
| 2123 | + #frm = getFreloc(cr, RSYS, nil, 0); | |
| 2124 | + #frf = getFreloc(cr, "rescue", nil, 0); | |
| 2125 | +# | |
| 2126 | + #imframe = loadermframe(frm, frf); | |
| 2127 | +# | |
| 2128 | + #i = newi(IMOVP); | |
| 2129 | + #addrsind(i.s, Amp, mpstring("*")); | |
| 2130 | + #addrdind(i.d, Afpind, imframe.d.offset, REGSIZE); | |
| 2131 | + #addDreloc(i, PSRC, PSIND); | |
| 2132 | +# | |
| 2133 | + #i = newi(IMOVP); | |
| 2134 | + #addrsind(i.s, Afp, REFSYSEX); | |
| 2135 | + #addrdind(i.d, Afpind, imframe.d.offset, REGSIZE+IBY2WD); | |
| 2136 | +# | |
| 2137 | + #i = newi(ILEA); | |
| 2138 | + #addrsind(i.s, Afp, getreg(DIS_W)); | |
| 2139 | + #addrdind(i.d, Afpind, imframe.d.offset, REGRET*IBY2WD); | |
| 2140 | +# | |
| 2141 | + #loadermcall(imframe, frf, frm); | |
| 2142 | + #relreg(imframe.d); | |
| 2143 | +# | |
| 2144 | + #return i.s; | |
| 2145 | + return nil; | |
| 2146 | +} | |
| 2147 | + | |
| 2148 | +# | |
| 2149 | +# Uninstall one or more exception handlers: call sys.unrescue() n times. | |
| 2150 | +# | |
| 2151 | + | |
| 2152 | +unrescue(n: int) | |
| 2153 | +{ | |
| 2154 | + print("unrescue()\n"); | |
| 2155 | + #imframe: ref Inst; | |
| 2156 | + #cr: ref Creloc; | |
| 2157 | + #frm, frf: ref Freloc; | |
| 2158 | +# | |
| 2159 | + #cr = getCreloc(RLOADER); | |
| 2160 | + #frm = getFreloc(cr, RSYS, nil, 0); | |
| 2161 | + #frf = getFreloc(cr, "unrescue", nil, 0); | |
| 2162 | +# | |
| 2163 | + #while(n > 0) { | |
| 2164 | + # imframe = loadermframe(frm, frf); | |
| 2165 | + # loadermcall(imframe, frf, frm); | |
| 2166 | + # relreg(imframe.d); | |
| 2167 | + # n--; | |
| 2168 | + #} | |
| 2169 | +} | |
| 2170 | + | |
| 2171 | +# | |
| 2172 | +# Current handler doesn't catch current exception. | |
| 2173 | +# Call sys.raise(@jex) to propagate (rethrow) the exception. | |
| 2174 | +# | |
| 2175 | + | |
| 2176 | +rethrow(): ref Inst | |
| 2177 | +{ | |
| 2178 | + print("rethrow()\n"); | |
| 2179 | + #imframe, i: ref Inst; | |
| 2180 | + #cr: ref Creloc; | |
| 2181 | + #frm, frf: ref Freloc; | |
| 2182 | +# | |
| 2183 | + #cr = getCreloc(RLOADER); | |
| 2184 | + #frm = getFreloc(cr, RSYS, nil, 0); | |
| 2185 | + #frf = getFreloc(cr, "raise", nil, 0); | |
| 2186 | +# | |
| 2187 | + #if(M.access_flags & ACC_SYNCHRONIZED && trylevel(J.pc) == 1) | |
| 2188 | + # mon_or_throw(Jmonitorexit, M.access_flags, 0); | |
| 2189 | +# | |
| 2190 | + #imframe = loadermframe(frm, frf); | |
| 2191 | +# | |
| 2192 | + #i = newi(IMOVP); | |
| 2193 | + #addrsind(i.s, Amp, 0); | |
| 2194 | + #addrdind(i.d, Afpind, imframe.d.offset, REGSIZE); | |
| 2195 | + #LTIpatch(getFreloc(cr, RJEX, nil, 0), i, PSRC, PSIND); | |
| 2196 | +# | |
| 2197 | + #i = loadermcall(imframe, frf, frm); | |
| 2198 | + #relreg(imframe.d); | |
| 2199 | +# | |
| 2200 | + #return i; | |
| 2201 | + return nil; | |
| 2202 | +} | |
| 2203 | + | |
| 2204 | +# | |
| 2205 | +# Retrieve thrown object prior to jumping to exception handler. | |
| 2206 | +# | |
| 2207 | + | |
| 2208 | +catch() | |
| 2209 | +{ | |
| 2210 | + print("catch()\n"); | |
| 2211 | + #imframe, i: ref Inst; | |
| 2212 | + #cr: ref Creloc; | |
| 2213 | + #frm, frf: ref Freloc; | |
| 2214 | +# | |
| 2215 | + #cr = getCreloc(RLOADER); | |
| 2216 | + #frm = getFreloc(cr, RMP, nil, 0); | |
| 2217 | + #frf = getFreloc(cr, "culprit", nil, 0); | |
| 2218 | +# | |
| 2219 | + #imframe = loadermframe(frm, frf); | |
| 2220 | +# | |
| 2221 | + #i = newi(IMOVP); | |
| 2222 | + #addrsind(i.s, Afp, REFSYSEX); | |
| 2223 | + #addrdind(i.d, Afpind, imframe.d.offset, REGSIZE); | |
| 2224 | +# | |
| 2225 | + #i = newi(ILEA); | |
| 2226 | + #addrsind(i.s, Afp, EXOBJ); # put in known location | |
| 2227 | + #addrdind(i.d, Afpind, imframe.d.offset, REGRET*IBY2WD); | |
| 2228 | +# | |
| 2229 | + #loadermcall(imframe, frf, frm); | |
| 2230 | + #relreg(imframe.d); | |
| 2231 | +} | |
| 2232 | + | |
| 2233 | +# | |
| 2234 | +# Does thrown object match handler for exception class exname ? | |
| 2235 | +# | |
| 2236 | + | |
| 2237 | +chkhandler(exname: string): ref Addr | |
| 2238 | +{ | |
| 2239 | + print("chkhandler()\n"); | |
| 2240 | + #imframe, i: ref Inst; | |
| 2241 | + #rtc: ref RTClass; | |
| 2242 | + #cr: ref Creloc; | |
| 2243 | + #frm, frf: ref Freloc; | |
| 2244 | +# | |
| 2245 | + #rtc = getRTClass(exname); | |
| 2246 | + #callrtload(rtc, exname); | |
| 2247 | +# | |
| 2248 | + #cr = getCreloc(RLOADER); | |
| 2249 | + #frm = getFreloc(cr, RMP, nil, 0); | |
| 2250 | + #frf = getFreloc(cr, "instanceof", nil, 0); | |
| 2251 | +# | |
| 2252 | + #imframe = loadermframe(frm, frf); | |
| 2253 | +# | |
| 2254 | + #i = newi(IMOVP); | |
| 2255 | + #addrsind(i.s, Afp, EXOBJ); | |
| 2256 | + #addrdind(i.d, Afpind, imframe.d.offset, REGSIZE); | |
| 2257 | +# | |
| 2258 | + #i = newi(IMOVP); | |
| 2259 | + #addrsind(i.s, Amp, 0); | |
| 2260 | + #RTIpatch(getRTReloc(rtc, RADT, nil, 0), i, PSRC, PSIND); | |
| 2261 | + #addrdind(i.d, Afpind, imframe.d.offset, REGSIZE+IBY2WD); | |
| 2262 | +# | |
| 2263 | + #i = newi(ILEA); | |
| 2264 | + #addrsind(i.s, Afp, getreg(DIS_W)); | |
| 2265 | + #addrdind(i.d, Afpind, imframe.d.offset, REGRET*IBY2WD); | |
| 2266 | +# | |
| 2267 | + #loadermcall(imframe, frf, frm); | |
| 2268 | + #relreg(imframe.d); | |
| 2269 | +# | |
| 2270 | + #return i.s; | |
| 2271 | + return nil; | |
| 2272 | +} | |
| 2273 | + | |
| 2274 | +# | |
| 2275 | +# Start of a try block. Install exception handler for try block t. | |
| 2276 | +# | |
| 2277 | + | |
| 2278 | +trystart(t: ref Try) | |
| 2279 | +{ | |
| 2280 | + print("trystart()\n"); | |
| 2281 | + ibeqw, i: ref Inst; | |
| 2282 | + a: ref Addr; | |
| 2283 | + c: ref Catch; | |
| 2284 | + | |
| 2285 | + a = rescue(); | |
| 2286 | + | |
| 2287 | + #ibeqw = newi(IBEQW); | |
| 2288 | + #*ibeqw.s = *a; | |
| 2289 | + #relreg(a); | |
| 2290 | + #addrimm(ibeqw.m, 0); # Sys.HANDLER == 0 | |
| 2291 | + #addrimm(ibeqw.d, 0); | |
| 2292 | + | |
| 2293 | + # code executed when sys.rescue() "returns" Sys.EXCEPTION | |
| 2294 | + | |
| 2295 | + unrescue(1); | |
| 2296 | + | |
| 2297 | + catch(); | |
| 2298 | + | |
| 2299 | + for(c = t.catch; c != nil; c = c.next) { | |
| 2300 | + a = chkhandler(c.exname); | |
| 2301 | + i = newi(IBEQW); | |
| 2302 | + *i.s = *a; | |
| 2303 | + relreg(a); | |
| 2304 | + addrimm(i.m, 1); | |
| 2305 | + addrimm(i.d, c.handler_pc); | |
| 2306 | + saveehinst(i); | |
| 2307 | + } | |
| 2308 | + | |
| 2309 | + if(t.any_pc > 0) { | |
| 2310 | + i = newi(IJMP); | |
| 2311 | + addrimm(i.d, t.any_pc); | |
| 2312 | + saveehinst(i); | |
| 2313 | + } #else | |
| 2314 | + # i = rethrow(); | |
| 2315 | + | |
| 2316 | + #ibeqw.d.ival = i.pc+1; | |
| 2317 | + | |
| 2318 | + # | |
| 2319 | + # rtload()'s done in Sys.EXCEPTION branch are not valid | |
| 2320 | + # for normal flow (Sys.HANDLER branch) | |
| 2321 | + # | |
| 2322 | + rtncache = 0; | |
| 2323 | +} | |
| 2324 | + | |
| 2325 | +# | |
| 2326 | +# At the start or end of a try block ? | |
| 2327 | +# | |
| 2328 | + | |
| 2329 | +tryhandling() | |
| 2330 | +{ | |
| 2331 | + #print("tryhandling()\n"); | |
| 2332 | + #t: ref Try; | |
| 2333 | +# | |
| 2334 | + #for(t = trylist; t != nil; t = t.next) { | |
| 2335 | + # # > 1 try block can have the same start_pc | |
| 2336 | + # if(t.start_pc == J.pc) | |
| 2337 | + # trystart(t); | |
| 2338 | + # # try block may consist of just 1 bytecode | |
| 2339 | + # if(t.end_pc == J.pc+J.size) | |
| 2340 | + # callunrescue = 1; | |
| 2341 | + #} | |
| 2342 | +} | |
| 2343 | + | |
| 2344 | +# | |
| 2345 | +# Generate Dis assembly code for one method. | |
| 2346 | +# | |
| 2347 | + | |
| 2348 | +java2dis() | |
| 2349 | +{ | |
| 2350 | + jnext: ref Jinst; | |
| 2351 | + jix: int; | |
| 2352 | + | |
| 2353 | + jix = 0; | |
| 2354 | + while(jix < code.code_length) { | |
| 2355 | + J = code.j[jix]; | |
| 2356 | + J.pcdis = pcdis; | |
| 2357 | + if(J.bb.js == J) { # start of a basic block ? | |
| 2358 | + # ignore unreachable code | |
| 2359 | + if((J.bb.flags & BB_REACHABLE) == byte 0) { | |
| 2360 | + jix = J.bb.je.pc + J.bb.je.size; | |
| 2361 | + continue; | |
| 2362 | + } | |
| 2363 | + # initialize fp temporary pool | |
| 2364 | + clearreg(); | |
| 2365 | + reservereg(J.bb.entrystk, J.bb.entrysz); | |
| 2366 | + reservereg(J.bb.exitstk, J.bb.exitsz); | |
| 2367 | + # flush run-time load cache | |
| 2368 | + rtncache = 0; | |
| 2369 | + } | |
| 2370 | + | |
| 2371 | + # start of a synchronized method ? | |
| 2372 | + if(J.pc == 0 && M.access_flags & ACC_SYNCHRONIZED) | |
| 2373 | + mon_or_throw(Jmonitorenter, M.access_flags, 0); | |
| 2374 | + | |
| 2375 | + #tryhandling(); | |
| 2376 | + | |
| 2377 | + if(jix+J.size < code.code_length) | |
| 2378 | + jnext = code.j[jix+J.size]; | |
| 2379 | + else | |
| 2380 | + jnext = nil; | |
| 2381 | + # "optimize" loads and stores | |
| 2382 | + if(jnext != nil && isstore(jnext) && jnext.bb.js != jnext) { | |
| 2383 | + if(J.dst.mode == Afp && J.dst.offset == -1) { | |
| 2384 | + *J.dst = *jnext.dst; | |
| 2385 | + # mark jnext so mov not generated for it | |
| 2386 | + jnext.dst.mode = Anone; | |
| 2387 | + } else if(isload(J) && J.movsrc.mode == Anone) { | |
| 2388 | + *J.movsrc = *J.dst; | |
| 2389 | + *J.dst = *jnext.dst; | |
| 2390 | + # mark jnext so mov not generated for it | |
| 2391 | + jnext.dst.mode = Anone; | |
| 2392 | + } | |
| 2393 | + } | |
| 2394 | + | |
| 2395 | + jpi: ref Jinst.Pi; | |
| 2396 | + jpx1c: ref Jinst.Px1c; | |
| 2397 | + jpw: ref Jinst.Pw; | |
| 2398 | + | |
| 2399 | + pick jp := J { | |
| 2400 | + Pi => | |
| 2401 | + jpi = jp; | |
| 2402 | + Px1c => | |
| 2403 | + jpx1c = jp; | |
| 2404 | + Pw => | |
| 2405 | + jpw = jp; | |
| 2406 | + } | |
| 2407 | + | |
| 2408 | + case int J.op { | |
| 2409 | + Jnop => | |
| 2410 | + ; | |
| 2411 | + Jaconst_null => | |
| 2412 | + xjavaload(IMOVP); | |
| 2413 | + Jiconst_m1 or | |
| 2414 | + Jiconst_0 or | |
| 2415 | + Jiconst_1 or | |
| 2416 | + Jiconst_2 or | |
| 2417 | + Jiconst_3 or | |
| 2418 | + Jiconst_4 or | |
| 2419 | + Jiconst_5 or | |
| 2420 | + Jbipush or | |
| 2421 | + Jsipush => | |
| 2422 | + xjavaload(IMOVW); | |
| 2423 | + Jlconst_0 or | |
| 2424 | + Jlconst_1 => | |
| 2425 | + xjavaload(IMOVL); | |
| 2426 | + Jfconst_0 or | |
| 2427 | + Jdconst_0 or | |
| 2428 | + Jfconst_1 or | |
| 2429 | + Jdconst_1 or | |
| 2430 | + Jfconst_2 => | |
| 2431 | + xjavaload(IMOVF); | |
| 2432 | + Jldc or | |
| 2433 | + Jldc_w or | |
| 2434 | + Jldc2_w => | |
| 2435 | + xldc(); | |
| 2436 | + Jiload or | |
| 2437 | + Jiload_0 or | |
| 2438 | + Jiload_1 or | |
| 2439 | + Jiload_2 or | |
| 2440 | + Jiload_3 => | |
| 2441 | + xjavaload(IMOVW); | |
| 2442 | + Jlload or | |
| 2443 | + Jlload_0 or | |
| 2444 | + Jlload_1 or | |
| 2445 | + Jlload_2 or | |
| 2446 | + Jlload_3 => | |
| 2447 | + xjavaload(IMOVL); | |
| 2448 | + Jfload or | |
| 2449 | + Jdload or | |
| 2450 | + Jfload_0 or | |
| 2451 | + Jdload_0 or | |
| 2452 | + Jfload_1 or | |
| 2453 | + Jdload_1 or | |
| 2454 | + Jfload_2 or | |
| 2455 | + Jdload_2 or | |
| 2456 | + Jfload_3 or | |
| 2457 | + Jdload_3 => | |
| 2458 | + xjavaload(IMOVF); | |
| 2459 | + Jaload or | |
| 2460 | + Jaload_0 or | |
| 2461 | + Jaload_1 or | |
| 2462 | + Jaload_2 or | |
| 2463 | + Jaload_3 => | |
| 2464 | + xjavaload(IMOVP); | |
| 2465 | + Jbaload => | |
| 2466 | + xarrayload(IINDB, ICVTBW, DIS_W); | |
| 2467 | + Jcaload or | |
| 2468 | + Jsaload or | |
| 2469 | + Jiaload => | |
| 2470 | + xarrayload(IINDW, IMOVW, DIS_W); | |
| 2471 | + Jlaload => | |
| 2472 | + xarrayload(IINDL, IMOVL, DIS_L); | |
| 2473 | + Jfaload or | |
| 2474 | + Jdaload => | |
| 2475 | + xarrayload(IINDF, IMOVF, DIS_L); | |
| 2476 | + Jaaload => | |
| 2477 | + xarrayload(IINDX, IMOVP, DIS_P); | |
| 2478 | + Jistore or | |
| 2479 | + Jistore_0 or | |
| 2480 | + Jistore_1 or | |
| 2481 | + Jistore_2 or | |
| 2482 | + Jistore_3 => | |
| 2483 | + xjavastore(IMOVW); | |
| 2484 | + Jlstore or | |
| 2485 | + Jlstore_0 or | |
| 2486 | + Jlstore_1 or | |
| 2487 | + Jlstore_2 or | |
| 2488 | + Jlstore_3 => | |
| 2489 | + xjavastore(IMOVL); | |
| 2490 | + Jfstore or | |
| 2491 | + Jdstore or | |
| 2492 | + Jfstore_0 or | |
| 2493 | + Jdstore_0 or | |
| 2494 | + Jfstore_1 or | |
| 2495 | + Jdstore_1 or | |
| 2496 | + Jfstore_2 or | |
| 2497 | + Jdstore_2 or | |
| 2498 | + Jfstore_3 or | |
| 2499 | + Jdstore_3 => | |
| 2500 | + xjavastore(IMOVF); | |
| 2501 | + Jastore or | |
| 2502 | + Jastore_0 or | |
| 2503 | + Jastore_1 or | |
| 2504 | + Jastore_2 or | |
| 2505 | + Jastore_3 => | |
| 2506 | + xjavastore(IMOVP); | |
| 2507 | + Jbastore => | |
| 2508 | + xarraystore(IINDB, ICVTWB); | |
| 2509 | + Jcastore or | |
| 2510 | + Jsastore or | |
| 2511 | + Jiastore => | |
| 2512 | + xarraystore(IINDW, IMOVW); | |
| 2513 | + Jlastore => | |
| 2514 | + xarraystore(IINDL, IMOVL); | |
| 2515 | + Jfastore or | |
| 2516 | + Jdastore => | |
| 2517 | + xarraystore(IINDF, IMOVF); | |
| 2518 | + Jaastore => | |
| 2519 | + aastore(); | |
| 2520 | + xarraystore(IINDX, IMOVP); | |
| 2521 | + Jpop or | |
| 2522 | + Jpop2 => | |
| 2523 | + xjavapop(); | |
| 2524 | + Jdup or | |
| 2525 | + Jdup_x1 or | |
| 2526 | + Jdup_x2 or | |
| 2527 | + Jdup2 or | |
| 2528 | + Jdup2_x1 or | |
| 2529 | + Jdup2_x2 => | |
| 2530 | + xjavadup(); | |
| 2531 | + Jswap => | |
| 2532 | + ; | |
| 2533 | + Jiadd => | |
| 2534 | + xbinop(IADDW, DIS_W, 0); | |
| 2535 | + Jisub => | |
| 2536 | + xbinop(ISUBW, DIS_W, 0); | |
| 2537 | + Jimul => | |
| 2538 | + xbinop(IMULW, DIS_W, 0); | |
| 2539 | + Jidiv => | |
| 2540 | + xbinop(IDIVW, DIS_W, 0); | |
| 2541 | + Jishl => | |
| 2542 | + shift(ISHLW, DIS_W); | |
| 2543 | + Jishr => | |
| 2544 | + shift(ISHRW, DIS_W); | |
| 2545 | + Jiushr => | |
| 2546 | + shift(ILSRW, DIS_W); | |
| 2547 | + Jirem => | |
| 2548 | + xbinop(IMODW, DIS_W, 0); | |
| 2549 | + Jiand => | |
| 2550 | + xbinop(IANDW, DIS_W, 0); | |
| 2551 | + Jior => | |
| 2552 | + xbinop(IORW, DIS_W, 0); | |
| 2553 | + Jixor => | |
| 2554 | + xbinop(IXORW, DIS_W, 0); | |
| 2555 | + Jladd => | |
| 2556 | + xbinop(IADDL, DIS_L, 0); | |
| 2557 | + Jlsub => | |
| 2558 | + xbinop(ISUBL, DIS_L, 0); | |
| 2559 | + Jlmul => | |
| 2560 | + xbinop(IMULL, DIS_L, 0); | |
| 2561 | + Jldiv => | |
| 2562 | + xbinop(IDIVL, DIS_L, 0); | |
| 2563 | + Jlrem => | |
| 2564 | + xbinop(IMODL, DIS_L, 0); | |
| 2565 | + Jland => | |
| 2566 | + xbinop(IANDL, DIS_L, 0); | |
| 2567 | + Jlor => | |
| 2568 | + xbinop(IORL, DIS_L, 0); | |
| 2569 | + Jlxor => | |
| 2570 | + xbinop(IXORL, DIS_L, 0); | |
| 2571 | + Jfadd => | |
| 2572 | + xbinop(IADDF, DIS_L, 1); | |
| 2573 | + Jdadd => | |
| 2574 | + xbinop(IADDF, DIS_L, 0); | |
| 2575 | + Jfsub => | |
| 2576 | + xbinop(ISUBF, DIS_L, 1); | |
| 2577 | + Jdsub => | |
| 2578 | + xbinop(ISUBF, DIS_L, 0); | |
| 2579 | + Jfmul => | |
| 2580 | + xbinop(IMULF, DIS_L, 1); | |
| 2581 | + Jdmul => | |
| 2582 | + xbinop(IMULF, DIS_L, 0); | |
| 2583 | + Jfdiv => | |
| 2584 | + xbinop(IDIVF, DIS_L, 1); | |
| 2585 | + Jddiv => | |
| 2586 | + xbinop(IDIVF, DIS_L, 0); | |
| 2587 | + Jfrem or | |
| 2588 | + Jdrem => | |
| 2589 | + jmath("drem", IMOVF, DIS_L); | |
| 2590 | + Jineg => | |
| 2591 | + neg(ISUBW, DIS_W); | |
| 2592 | + Jlneg => | |
| 2593 | + neg(ISUBL, DIS_L); | |
| 2594 | + Jfneg or | |
| 2595 | + Jdneg => | |
| 2596 | + neg(INEGF, DIS_L); | |
| 2597 | + Jlshl => | |
| 2598 | + shift(ISHLL, DIS_L); | |
| 2599 | + Jlshr => | |
| 2600 | + shift(ISHRL, DIS_L); | |
| 2601 | + Jlushr => | |
| 2602 | + shift(ILSRL, DIS_L); | |
| 2603 | + Jiinc => | |
| 2604 | + iinc(jpx1c.x1c.icon, jpx1c.x1c.ix); | |
| 2605 | + Ji2l => | |
| 2606 | + cvt(ICVTWL, DIS_L, 0); | |
| 2607 | + Ji2f => | |
| 2608 | + cvt(ICVTWF, DIS_L, 1); | |
| 2609 | + Ji2d => | |
| 2610 | + cvt(ICVTWF, DIS_L, 0); | |
| 2611 | + Jl2i => | |
| 2612 | + cvt(ICVTLW, DIS_W, 0); | |
| 2613 | + Jl2f => | |
| 2614 | + cvt(ICVTLF, DIS_L, 1); | |
| 2615 | + Jl2d => | |
| 2616 | + cvt(ICVTLF, DIS_L, 0); | |
| 2617 | + Jf2i or | |
| 2618 | + Jd2i => | |
| 2619 | + jmath("d2i", IMOVF, DIS_W); | |
| 2620 | + Jf2l or | |
| 2621 | + Jd2l => | |
| 2622 | + jmath("d2l", IMOVF, DIS_L); | |
| 2623 | + Jf2d => | |
| 2624 | + cvt(IMOVF, DIS_L, 0); | |
| 2625 | + Jd2f => | |
| 2626 | + cvt(IMOVF, DIS_L, 1); | |
| 2627 | + Ji2b => | |
| 2628 | + i2bs(24); | |
| 2629 | + Ji2c => | |
| 2630 | + i2c(); | |
| 2631 | + Ji2s => | |
| 2632 | + i2bs(16); | |
| 2633 | + Jlcmp => | |
| 2634 | + jmath("lcmp", IMOVL, DIS_W); | |
| 2635 | + Jfcmpl or | |
| 2636 | + Jdcmpl => | |
| 2637 | + jmath("dcmpl", IMOVF, DIS_W); | |
| 2638 | + Jfcmpg or | |
| 2639 | + Jdcmpg => | |
| 2640 | + jmath("dcmpg", IMOVF, DIS_W); | |
| 2641 | + Jifeq => | |
| 2642 | + javaif(IBEQW, CMPZERO); | |
| 2643 | + Jifne => | |
| 2644 | + javaif(IBNEW, CMPZERO); | |
| 2645 | + Jiflt => | |
| 2646 | + javaif(IBLTW, CMPZERO); | |
| 2647 | + Jifge => | |
| 2648 | + javaif(IBGEW, CMPZERO); | |
| 2649 | + Jifgt => | |
| 2650 | + javaif(IBGTW, CMPZERO); | |
| 2651 | + Jifle => | |
| 2652 | + javaif(IBLEW, CMPZERO); | |
| 2653 | + Jif_acmpeq or | |
| 2654 | + Jif_icmpeq => | |
| 2655 | + javaif(IBEQW, CMP2OP); | |
| 2656 | + Jif_acmpne or | |
| 2657 | + Jif_icmpne => | |
| 2658 | + javaif(IBNEW, CMP2OP); | |
| 2659 | + Jif_icmplt => | |
| 2660 | + javaif(IBLTW, CMP2OP); | |
| 2661 | + Jif_icmpge => | |
| 2662 | + javaif(IBGEW, CMP2OP); | |
| 2663 | + Jif_icmpgt => | |
| 2664 | + javaif(IBGTW, CMP2OP); | |
| 2665 | + Jif_icmple => | |
| 2666 | + javaif(IBLEW, CMP2OP); | |
| 2667 | + Jgoto or | |
| 2668 | + Jgoto_w => | |
| 2669 | + javagoto(); | |
| 2670 | + Jjsr or | |
| 2671 | + Jjsr_w => | |
| 2672 | + jsr(jpi.i); | |
| 2673 | + Jret => | |
| 2674 | + ret(); | |
| 2675 | + Jtableswitch => | |
| 2676 | + tableswitch(); | |
| 2677 | + Jlookupswitch => | |
| 2678 | + lookupswitch(); | |
| 2679 | + Jireturn => | |
| 2680 | + xjavareturn(IMOVW); | |
| 2681 | + Jlreturn => | |
| 2682 | + xjavareturn(IMOVL); | |
| 2683 | + Jfreturn or | |
| 2684 | + Jdreturn => | |
| 2685 | + xjavareturn(IMOVF); | |
| 2686 | + Jareturn => | |
| 2687 | + xjavareturn(IMOVP); | |
| 2688 | + Jreturn => | |
| 2689 | + xjavareturn(0); | |
| 2690 | + Jgetfield => | |
| 2691 | + getfield(); | |
| 2692 | + Jgetstatic => | |
| 2693 | + getstatic(); | |
| 2694 | + Jputfield => | |
| 2695 | + putfield(); | |
| 2696 | + Jputstatic => | |
| 2697 | + putstatic(); | |
| 2698 | + Jinvokevirtual => | |
| 2699 | + invokev(); | |
| 2700 | + Jinvokespecial => | |
| 2701 | + invokess(Rinvokespecial, Rspecialmp); | |
| 2702 | + Jinvokestatic => | |
| 2703 | + invokess(Rinvokestatic, Rstaticmp); | |
| 2704 | + Jinvokeinterface => | |
| 2705 | + invokei(); | |
| 2706 | + Jxxxunusedxxx => | |
| 2707 | + ; | |
| 2708 | + Jnew => | |
| 2709 | + xjavanew(CLASSNAME(jpi.i), jpi.dst); | |
| 2710 | + Jnewarray => | |
| 2711 | + newarray(); | |
| 2712 | + Janewarray => | |
| 2713 | + xanewarray(); | |
| 2714 | + Jarraylength => | |
| 2715 | + arraylength(); | |
| 2716 | + Jcheckcast or | |
| 2717 | + Jinstanceof => | |
| 2718 | + rtti(); | |
| 2719 | + Jathrow or | |
| 2720 | + Jmonitorenter or | |
| 2721 | + Jmonitorexit => | |
| 2722 | + if(J.op == byte Jathrow | |
| 2723 | + && M.access_flags & ACC_SYNCHRONIZED | |
| 2724 | + && trylevel(J.pc) == 0) { | |
| 2725 | + mon_or_throw(Jmonitorexit, M.access_flags, 0); | |
| 2726 | + } | |
| 2727 | + mon_or_throw(int J.op, 0, 1); | |
| 2728 | + Jwide => | |
| 2729 | + case int jpw.w.op { | |
| 2730 | + Jiload => | |
| 2731 | + xjavaload(IMOVW); | |
| 2732 | + Jlload => | |
| 2733 | + xjavaload(IMOVL); | |
| 2734 | + Jfload or | |
| 2735 | + Jdload => | |
| 2736 | + xjavaload(IMOVF); | |
| 2737 | + Jaload => | |
| 2738 | + xjavaload(IMOVP); | |
| 2739 | + Jistore => | |
| 2740 | + xjavastore(IMOVW); | |
| 2741 | + Jlstore => | |
| 2742 | + xjavastore(IMOVL); | |
| 2743 | + Jfstore or | |
| 2744 | + Jdstore => | |
| 2745 | + xjavastore(IMOVF); | |
| 2746 | + Jastore => | |
| 2747 | + xjavastore(IMOVP); | |
| 2748 | + Jret => | |
| 2749 | + ret(); | |
| 2750 | + Jiinc => | |
| 2751 | + iinc(jpw.w.icon, jpw.w.ix); | |
| 2752 | + } | |
| 2753 | + Jmultianewarray => | |
| 2754 | + xmultianewarray(); | |
| 2755 | + Jifnull => | |
| 2756 | + javaif(IBEQW, CMPNULL); | |
| 2757 | + Jifnonnull => | |
| 2758 | + javaif(IBNEW, CMPNULL); | |
| 2759 | + } | |
| 2760 | + if(callunrescue == 1) { | |
| 2761 | + #unrescue(1); | |
| 2762 | + callunrescue = 0; | |
| 2763 | + } | |
| 2764 | + jix += J.size; | |
| 2765 | + } | |
| 2766 | + # handle exception handlers | |
| 2767 | + for(t := trylist; t != nil; t = t.next) { | |
| 2768 | + # just convert pc's and append the entries to global distrylist | |
| 2769 | + | |
| 2770 | + } | |
| 2771 | + J = nil; | |
| 2772 | +} | |
| 2773 | + | |
| 2774 | +# | |
| 2775 | +# If there are exception handlers, then allocate a 'ref Sys->Exception' | |
| 2776 | +# to pass to Sys->rescue() and Loader->culprit(). | |
| 2777 | +# Not needed anymore | |
| 2778 | +# | |
| 2779 | + | |
| 2780 | +#ref_sys_except() | |
| 2781 | +#{ | |
| 2782 | +# i: ref Inst; | |
| 2783 | +# | |
| 2784 | +# if(code.nex == 0) | |
| 2785 | +# return; | |
| 2786 | +# | |
| 2787 | +# i = newi(INEW); | |
| 2788 | +# addrimm(i.s, descid(3*IBY2WD, 1, array [1] of { byte 16rc0 })); | |
| 2789 | +# addrsind(i.d, Afp, REFSYSEX); | |
| 2790 | +#} | |
| 2791 | + | |
| 2792 | +# | |
| 2793 | +# Generate initialization code for 'static final' fields that have | |
| 2794 | +# ConstantValue attributes. | |
| 2795 | +# | |
| 2796 | + | |
| 2797 | +clinitinits(): ref Inst | |
| 2798 | +{ | |
| 2799 | + movi: int; | |
| 2800 | + j, ix, offset, value: int; | |
| 2801 | + sig: string; | |
| 2802 | + a: ref Addr; | |
| 2803 | + as: ref Addr; | |
| 2804 | + fp: ref Field; | |
| 2805 | + fi: ref FieldInfo; | |
| 2806 | + i, reti: ref Inst; | |
| 2807 | + | |
| 2808 | + as = ref Addr(Afp, 0, 0); | |
| 2809 | + fi = ref FieldInfo(THISCLASS, nil, nil, 0); | |
| 2810 | + reti = nil; | |
| 2811 | + | |
| 2812 | + for(j = 0; j < class.fields_count; j++) { | |
| 2813 | + fp = class.fields[j]; | |
| 2814 | + if((fp.access_flags & ACC_STATIC) && (ix = CVattrindex(fp))) { | |
| 2815 | + sig = STRING(fp.sig_index); | |
| 2816 | + pick cp := class.cps[ix] { | |
| 2817 | + Ptint => | |
| 2818 | + if(cp.tint == 0) | |
| 2819 | + continue; | |
| 2820 | + if(sig[0] == 'Z' || sig[0] == 'B') | |
| 2821 | + movi = ICVTWB; | |
| 2822 | + else | |
| 2823 | + movi = IMOVW; | |
| 2824 | + if(notimmable(cp.tint)) | |
| 2825 | + offset = mpint(cp.tint); | |
| 2826 | + else { | |
| 2827 | + offset = -1; | |
| 2828 | + value = cp.tint; | |
| 2829 | + } | |
| 2830 | + Ptvlong => | |
| 2831 | + if(cp.tvlong == big 0) | |
| 2832 | + continue; | |
| 2833 | + movi = IMOVL; | |
| 2834 | + offset = mplong(cp.tvlong); | |
| 2835 | + Ptdouble => | |
| 2836 | + if(cp.tdouble == 0.0) | |
| 2837 | + continue; | |
| 2838 | + movi = IMOVF; | |
| 2839 | + offset = mpreal(cp.tdouble); | |
| 2840 | + Pstring_index => | |
| 2841 | + movi = IMOVP; | |
| 2842 | + offset = mpstring(STRING(cp.string_index)); | |
| 2843 | + break; | |
| 2844 | + * => | |
| 2845 | + badpick("clinitinits"); | |
| 2846 | + } | |
| 2847 | + fi.fieldname = STRING(fp.name_index); | |
| 2848 | + fi.sig = sig; | |
| 2849 | + a = ltstaticadd(fi); | |
| 2850 | + if(reti == nil) | |
| 2851 | + reti = itail; | |
| 2852 | + if(movi == IMOVP) { | |
| 2853 | + as.offset = -1; | |
| 2854 | + xjavanew("java/lang/String", as); | |
| 2855 | + i = newi(IMOVP); | |
| 2856 | + addrsind(i.s, Amp, offset); | |
| 2857 | + *i.d = *as; | |
| 2858 | + sind2dind(i.d, STR_DISSTR); | |
| 2859 | + addDreloc(i, PSRC, PSIND); | |
| 2860 | + } | |
| 2861 | + i = newi(movi); | |
| 2862 | + if(movi == IMOVP) { | |
| 2863 | + *i.s = *as; | |
| 2864 | + relreg(as); | |
| 2865 | + } else if(offset >= 0) { | |
| 2866 | + addrsind(i.s, Amp, offset); | |
| 2867 | + addDreloc(i, PSRC, PSIND); | |
| 2868 | + } else | |
| 2869 | + addrimm(i.s, value); | |
| 2870 | + *i.d = *a; | |
| 2871 | + sind2dind(i.d, 0); | |
| 2872 | + relreg(a); | |
| 2873 | + } | |
| 2874 | + } | |
| 2875 | + return reti; | |
| 2876 | +} | |
| 2877 | + | |
| 2878 | +# | |
| 2879 | +# Cook up a <clinit> static method. | |
| 2880 | +# | |
| 2881 | + | |
| 2882 | +genclinit() | |
| 2883 | +{ | |
| 2884 | + savepc: int; | |
| 2885 | + | |
| 2886 | + savepc = pcdis; | |
| 2887 | + openframe("()V", ACC_STATIC); | |
| 2888 | + clinitclone = clinitinits(); # save for -v option | |
| 2889 | + newi(IRET); | |
| 2890 | + xtrnlink(closeframe(), savepc, "<clinit>", "()V"); | |
| 2891 | +} | |
| 2892 | + | |
| 2893 | +# | |
| 2894 | +# Cook up link entry and body for <clone> static method. | |
| 2895 | +# | |
| 2896 | + | |
| 2897 | +genclone(): ref Inst | |
| 2898 | +{ | |
| 2899 | + i, clone: ref Inst; | |
| 2900 | + fr: ref Freloc; | |
| 2901 | + | |
| 2902 | + xtrnlink(descid(40, 2, array [2] of { byte 0, byte 16rc0 }), pcdis, "<clone>", "()V"); | |
| 2903 | + | |
| 2904 | + # | |
| 2905 | + # new @Class, 36(fp) | |
| 2906 | + # movmp 0(32(fp)), @Class, 0(36(fp)) | |
| 2907 | + # movp 36(fp), 0(16(fp)) | |
| 2908 | + # ret | |
| 2909 | + # | |
| 2910 | + | |
| 2911 | + fr = getFreloc(getCreloc(THISCLASS), RCLASS, nil, 0); | |
| 2912 | + | |
| 2913 | + i = newi(INEW); | |
| 2914 | + addrimm(i.s, 0); | |
| 2915 | + LTIpatch(fr, i, PSRC, PIMM); | |
| 2916 | + addrsind(i.d, Afp, 36); | |
| 2917 | + clone = i; # save for -v option | |
| 2918 | + | |
| 2919 | + i = newi(IMOVMP); | |
| 2920 | + addrdind(i.s, Afpind, 32, 0); | |
| 2921 | + addrimm(i.m, 0); | |
| 2922 | + LTIpatch(fr, i, PMID, PIMM); | |
| 2923 | + addrdind(i.d, Afpind, 36, 0); | |
| 2924 | + | |
| 2925 | + i = newi(IMOVP); | |
| 2926 | + addrsind(i.s, Afp, 36); | |
| 2927 | + addrdind(i.d, Afpind, 16, 0); | |
| 2928 | + | |
| 2929 | + newi(IRET); | |
| 2930 | + | |
| 2931 | + return clone; | |
| 2932 | +} | |
| 2933 | + | |
| 2934 | +# | |
| 2935 | +# Translate the methods in class cl. | |
| 2936 | +# | |
| 2937 | + | |
| 2938 | +xlate() | |
| 2939 | +{ | |
| 2940 | + i, j, n: int; | |
| 2941 | + savepcdis: int; | |
| 2942 | + a: ref Attr; | |
| 2943 | + clone: ref Inst; | |
| 2944 | + m: ref Method; | |
| 2945 | + name, sig: string; | |
| 2946 | + | |
| 2947 | + n = 0; | |
| 2948 | + for(i = 0; i < class.methods_count; i++) { | |
| 2949 | + m = class.methods[i]; | |
| 2950 | + name = STRING(m.name_index); | |
| 2951 | + pcode[n].name = name; | |
| 2952 | + sig = STRING(m.sig_index); | |
| 2953 | + pcode[n].sig = sig; | |
| 2954 | + for(j = 0; j < m.attr_count; j++) { | |
| 2955 | + a = m.attr_info[j]; | |
| 2956 | + if(STRING(a.name) == "Code") { | |
| 2957 | + M = m; | |
| 2958 | + code = javadas(a); | |
| 2959 | + pcode[n].code = code; | |
| 2960 | + cvtehinfo(); | |
| 2961 | + # exception object TODO: needs fix | |
| 2962 | + addrsind(code.j[code.code_length].dst, Afp, EXOBJ); | |
| 2963 | + #addrsind(code.j[code.code_length].dst, Afp, 0); | |
| 2964 | + openframe(sig, m.access_flags&ACC_STATIC); | |
| 2965 | + savepcdis = pcdis; | |
| 2966 | + flowgraph(); | |
| 2967 | + simjvm(sig); | |
| 2968 | + unify(); | |
| 2969 | + J = code.j[0]; | |
| 2970 | + #ref_sys_except(); | |
| 2971 | + if(doclinitinits && name == "<clinit>") { | |
| 2972 | + clinitinits(); | |
| 2973 | + doclinitinits = 0; | |
| 2974 | + } | |
| 2975 | + java2dis(); | |
| 2976 | + bbfree(); | |
| 2977 | + xtrnlink(closeframe(), savepcdis, name, sig); | |
| 2978 | + patchmethod(savepcdis); | |
| 2979 | + patchehinst(); | |
| 2980 | + patchfree(); | |
| 2981 | + finallyfree(); | |
| 2982 | + trylist = nil; | |
| 2983 | + } | |
| 2984 | + } | |
| 2985 | + n += 1; | |
| 2986 | + } | |
| 2987 | + | |
| 2988 | + if(doclinitinits) | |
| 2989 | + genclinit(); | |
| 2990 | + | |
| 2991 | + if((class.access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) == 0) { | |
| 2992 | + clone = genclone(); | |
| 2993 | + if(clinitclone == nil) | |
| 2994 | + clinitclone = clone; | |
| 2995 | + } | |
| 2996 | +} | |
| @@ -0,0 +1,53 @@ | ||
| 1 | +#0 | |
| 2 | + movp 32(fp),0(16(fp)) | |
| 3 | + ret | |
| 4 | + desc $0,0,"" | |
| 5 | + desc $1,40,"0080" | |
| 6 | + var @mp,0 | |
| 7 | + module Cast | |
| 8 | +# cast to JObject | |
| 9 | + link 1,0,0xaaaaaaaa,"FromJArray" | |
| 10 | + link 1,0,0xaaaaaaaa,"FromJClass" | |
| 11 | + link 1,0,0xaaaaaaaa,"FromJString" | |
| 12 | +# cast JArray* to JArray | |
| 13 | + link 1,0,0xaaaaaaaa,"ByteToJArray" | |
| 14 | + link 1,0,0xaaaaaaaa,"IntToJArray" | |
| 15 | + link 1,0,0xaaaaaaaa,"BigToJArray" | |
| 16 | + link 1,0,0xaaaaaaaa,"RealToJArray" | |
| 17 | + link 1,0,0xaaaaaaaa,"ClassToJArray" | |
| 18 | + link 1,0,0xaaaaaaaa,"StringToJArray" | |
| 19 | + link 1,0,0xaaaaaaaa,"ObjectToJArray" | |
| 20 | +# cast JArray to JArray* | |
| 21 | + link 1,0,0xaaaaaaaa,"JArrayToByte" | |
| 22 | + link 1,0,0xaaaaaaaa,"JArrayToInt" | |
| 23 | + link 1,0,0xaaaaaaaa,"JArrayToBig" | |
| 24 | + link 1,0,0xaaaaaaaa,"JArrayToReal" | |
| 25 | + link 1,0,0xaaaaaaaa,"JArrayToClass" | |
| 26 | + link 1,0,0xaaaaaaaa,"JArrayToString" | |
| 27 | + link 1,0,0xaaaaaaaa,"JArrayToObject" | |
| 28 | + | |
| 29 | +# cast from JObject | |
| 30 | + link 1,0,0xaaaaaaaa,"ToJArray" | |
| 31 | + link 1,0,0xaaaaaaaa,"ToJArrayB" | |
| 32 | + link 1,0,0xaaaaaaaa,"ToJArrayC" | |
| 33 | + link 1,0,0xaaaaaaaa,"ToJArrayS" | |
| 34 | + link 1,0,0xaaaaaaaa,"ToJArrayI" | |
| 35 | + link 1,0,0xaaaaaaaa,"ToJArrayJ" | |
| 36 | + link 1,0,0xaaaaaaaa,"ToJArrayF" | |
| 37 | + link 1,0,0xaaaaaaaa,"ToJArrayD" | |
| 38 | + link 1,0,0xaaaaaaaa,"ToJArrayZ" | |
| 39 | + link 1,0,0xaaaaaaaa,"ToJArrayJString" | |
| 40 | + link 1,0,0xaaaaaaaa,"ToJArrayJObject" | |
| 41 | + link 1,0,0xaaaaaaaa,"ToJClass" | |
| 42 | + link 1,0,0xaaaaaaaa,"ToJString" | |
| 43 | + | |
| 44 | +# cast thread data | |
| 45 | + link 1,0,0xaaaaaaaa,"JObjToJThd" | |
| 46 | + link 1,0,0xaaaaaaaa,"JThdToJObj" | |
| 47 | + | |
| 48 | +# misc cast | |
| 49 | + link 1,0,0xaaaaaaaa,"Class2Niladt" | |
| 50 | + link 1,0,0xaaaaaaaa,"Obj2Niladt" | |
| 51 | + link 1,0,0xaaaaaaaa,"JNI2Nilmod" | |
| 52 | + link 1,0,0xaaaaaaaa,"JArrayToHolder" | |
| 53 | + | |
| @@ -0,0 +1,53 @@ | ||
| 1 | +#0 | |
| 2 | + movp 32(fp),0(16(fp)) | |
| 3 | + ret | |
| 4 | + desc $0,0,"" | |
| 5 | + desc $1,40,"0080" | |
| 6 | + var @mp,0 | |
| 7 | + module Cast | |
| 8 | +# cast to JObject | |
| 9 | + link 1,0,0xb8ed9861,"FromJArray" | |
| 10 | + link 1,0,0xb8884c9a,"FromJClass" | |
| 11 | + link 1,0,0x76cd0754,"FromJString" | |
| 12 | +# cast JArray* to JArray | |
| 13 | + link 1,0,0x308d465a,"ByteToJArray" | |
| 14 | + link 1,0,0x54d1047d,"IntToJArray" | |
| 15 | + link 1,0,0x8943ab,"BigToJArray" | |
| 16 | + link 1,0,0xf7ce22ea,"RealToJArray" | |
| 17 | + link 1,0,0x7e0e257a,"ClassToJArray" | |
| 18 | + link 1,0,0xf0709f5f,"StringToJArray" | |
| 19 | + link 1,0,0x5e96bb51,"ObjectToJArray" | |
| 20 | +# cast JArray to JArray* | |
| 21 | + link 1,0,0xdab35b9b,"JArrayToByte" | |
| 22 | + link 1,0,0xdfce047b,"JArrayToInt" | |
| 23 | + link 1,0,0x8b84c7a8,"JArrayToBig" | |
| 24 | + link 1,0,0x7960d11,"JArrayToReal" | |
| 25 | + link 1,0,0xdaebabf,"JArrayToClass" | |
| 26 | + link 1,0,0x1102d2ef,"JArrayToString" | |
| 27 | + link 1,0,0x14d3cbb9,"JArrayToObject" | |
| 28 | + | |
| 29 | +# cast from JObject | |
| 30 | + link 1,0,0x6d675ef6,"ToJArray" | |
| 31 | + link 1,0,0xe0b15252,"ToJArrayB" | |
| 32 | + link 1,0,0x32346c9,"ToJArrayC" | |
| 33 | + link 1,0,0x32346c9,"ToJArrayS" | |
| 34 | + link 1,0,0x32346c9,"ToJArrayI" | |
| 35 | + link 1,0,0xdea604f9,"ToJArrayJ" | |
| 36 | + link 1,0,0x5cde7840,"ToJArrayF" | |
| 37 | + link 1,0,0x5cde7840,"ToJArrayD" | |
| 38 | + link 1,0,0xe0b15252,"ToJArrayZ" | |
| 39 | + link 1,0,0xe6e32a84,"ToJArrayJString" | |
| 40 | + link 1,0,0x4cbbe2c3,"ToJArrayJObject" | |
| 41 | + link 1,0,0x424af2d7,"ToJClass" | |
| 42 | + link 1,0,0x4fd3acd0,"ToJString" | |
| 43 | + | |
| 44 | +# cast thread data | |
| 45 | + link 1,0,0x52e73674,"JObjToJThd" | |
| 46 | + link 1,0,0x7e48ea3a,"JThdToJObj" | |
| 47 | + | |
| 48 | +# misc cast | |
| 49 | + link 1,0,0x2b7b0708,"Class2Niladt" | |
| 50 | + link 1,0,0x2e1c372c,"Obj2Niladt" | |
| 51 | + link 1,0,0x69964565,"JNI2Nilmod" | |
| 52 | + link 1,0,0xe04c9ec8,"JArrayToHolder" | |
| 53 | + | |
| @@ -0,0 +1,144 @@ | ||
| 1 | +# | |
| 2 | +# this file contains stubs for the fcts | |
| 3 | +# declared in cast.m. This file is | |
| 4 | +# run through the limbo compiler in order | |
| 5 | +# to obtain valid funtion signatures which | |
| 6 | +# are then combined with cast.base (the | |
| 7 | +# dis assmebly code) to produce a valid | |
| 8 | +# cast.s. The generated cast.s will contain | |
| 9 | +# the code from cast.base and the correct | |
| 10 | +# function signatures generated by limbo | |
| 11 | +# and this file. cast.s is then run through | |
| 12 | +# the assembler to produce cast.dis. | |
| 13 | +# weird, but it works. | |
| 14 | +# | |
| 15 | +implement Cast; | |
| 16 | + | |
| 17 | +include "jni.m"; | |
| 18 | + | |
| 19 | + | |
| 20 | +# | |
| 21 | +# to JObject | |
| 22 | +# | |
| 23 | +FromJArray( o : JNI->JArray ) : JNI->JObject | |
| 24 | +{ junk := o; return(nil); } | |
| 25 | + | |
| 26 | +FromJClass( o : JNI->JClass ) : JNI->JObject | |
| 27 | +{ junk := o; return(nil); } | |
| 28 | + | |
| 29 | +FromJString( o : JNI->JString ) : JNI->JObject | |
| 30 | +{ junk := o; return(nil); } | |
| 31 | + | |
| 32 | +# | |
| 33 | +# cast JArray* to JArray | |
| 34 | +# | |
| 35 | +ByteToJArray( o : ref JNI->ByteArray ) : JNI->JArray | |
| 36 | +{ junk := o; return(nil); } | |
| 37 | + | |
| 38 | +IntToJArray( o : ref JNI->IntArray ) : JNI->JArray | |
| 39 | +{ junk := o; return(nil); } | |
| 40 | + | |
| 41 | +BigToJArray( o : ref JNI->BigArray ) : JNI->JArray | |
| 42 | +{ junk := o; return(nil); } | |
| 43 | + | |
| 44 | +RealToJArray( o : ref JNI->RealArray ) : JNI->JArray | |
| 45 | +{ junk := o; return(nil); } | |
| 46 | + | |
| 47 | +ClassToJArray( o : ref JNI->ClassArray ) : JNI->JArray | |
| 48 | +{ junk := o; return(nil); } | |
| 49 | + | |
| 50 | +StringToJArray( o : ref JNI->StringArray ) : JNI->JArray | |
| 51 | +{ junk := o; return(nil); } | |
| 52 | + | |
| 53 | +ObjectToJArray( o : ref JNI->ObjectArray ) : JNI->JArray | |
| 54 | +{ junk := o; return(nil); } | |
| 55 | + | |
| 56 | +# | |
| 57 | +# cast JArray to JArray* | |
| 58 | +# | |
| 59 | +JArrayToByte( ptr : JNI->JArray ) : ref JNI->ByteArray | |
| 60 | +{ junk := ptr; return(nil); } | |
| 61 | + | |
| 62 | +JArrayToInt( ptr : JNI->JArray ) : ref JNI->IntArray | |
| 63 | +{ junk := ptr; return(nil); } | |
| 64 | + | |
| 65 | +JArrayToBig( ptr : JNI->JArray ) : ref JNI->BigArray | |
| 66 | +{ junk := ptr; return(nil); } | |
| 67 | + | |
| 68 | +JArrayToReal( ptr : JNI->JArray ) : ref JNI->RealArray | |
| 69 | +{ junk := ptr; return(nil); } | |
| 70 | + | |
| 71 | +JArrayToClass( ptr : JNI->JArray ) : ref JNI->ClassArray | |
| 72 | +{ junk := ptr; return(nil); } | |
| 73 | + | |
| 74 | +JArrayToString( ptr : JNI->JArray ) : ref JNI->StringArray | |
| 75 | +{ junk := ptr; return(nil); } | |
| 76 | + | |
| 77 | +JArrayToObject( ptr : JNI->JArray ) : ref JNI->ObjectArray | |
| 78 | +{ junk := ptr; return(nil); } | |
| 79 | + | |
| 80 | + | |
| 81 | +# | |
| 82 | +# cast from JObjects | |
| 83 | +# | |
| 84 | +ToJClass( o : JNI->JObject ) : JNI->JClass | |
| 85 | +{ junk := o; return(nil); } | |
| 86 | + | |
| 87 | +ToJString( o : JNI->JObject ) : JNI->JString | |
| 88 | +{ junk := o; return(nil); } | |
| 89 | + | |
| 90 | +ToJArray( o : JNI->JObject ) : JNI->JArray | |
| 91 | +{ junk := o; return(nil); } | |
| 92 | + | |
| 93 | +ToJArrayB( o : JNI->JObject ) : JNI->JArrayB | |
| 94 | +{ junk := o; return(nil); } | |
| 95 | + | |
| 96 | +ToJArrayC( o : JNI->JObject ) : JNI->JArrayC | |
| 97 | +{ junk := o; return(nil); } | |
| 98 | + | |
| 99 | +ToJArrayS( o : JNI->JObject ) : JNI->JArrayS | |
| 100 | +{ junk := o; return(nil); } | |
| 101 | + | |
| 102 | +ToJArrayI( o : JNI->JObject ) : JNI->JArrayI | |
| 103 | +{ junk := o; return(nil); } | |
| 104 | + | |
| 105 | +ToJArrayJ( o : JNI->JObject ) : JNI->JArrayJ | |
| 106 | +{ junk := o; return(nil); } | |
| 107 | + | |
| 108 | +ToJArrayF( o : JNI->JObject ) : JNI->JArrayF | |
| 109 | +{ junk := o; return(nil); } | |
| 110 | + | |
| 111 | +ToJArrayD( o : JNI->JObject ) : JNI->JArrayD | |
| 112 | +{ junk := o; return(nil); } | |
| 113 | + | |
| 114 | +ToJArrayZ( o : JNI->JObject ) : JNI->JArrayZ | |
| 115 | +{ junk := o; return(nil); } | |
| 116 | + | |
| 117 | +ToJArrayJString( o : JNI->JObject ) : JNI->JArrayJString | |
| 118 | +{ junk := o; return(nil); } | |
| 119 | + | |
| 120 | +ToJArrayJObject( o : JNI->JObject ) : JNI->JArrayJObject | |
| 121 | +{ junk := o; return(nil); } | |
| 122 | + | |
| 123 | +# | |
| 124 | +# cast for thread data | |
| 125 | +JObjToJThd( o : JNI->JObject ) : (JNI->JThread) | |
| 126 | +{ junk := o; return(nil); } | |
| 127 | + | |
| 128 | +JThdToJObj( o : JNI->JThread ) : (JNI->JObject) | |
| 129 | +{ junk := o; return(nil); } | |
| 130 | + | |
| 131 | +# | |
| 132 | +# misc casts | |
| 133 | +# | |
| 134 | +Class2Niladt( o : JNI->ClassData ) : ref Loader->Niladt | |
| 135 | +{ junk := o; return(nil); } | |
| 136 | + | |
| 137 | +Obj2Niladt( o : JNI->JObject ) : ref Loader->Niladt | |
| 138 | +{ junk := o; return(nil); } | |
| 139 | + | |
| 140 | +JNI2Nilmod( o : JNI ) : Nilmod | |
| 141 | +{ junk := o; return(nil); } | |
| 142 | + | |
| 143 | +JArrayToHolder( o : array of JNI->JArray ) : array of JNI->JString | |
| 144 | +{ junk := o; return(nil); } | |
| @@ -0,0 +1,3452 @@ | ||
| 1 | +implement JavaClassLoader; | |
| 2 | + | |
| 3 | +# | |
| 4 | +# Java Class Loader. | |
| 5 | +# | |
| 6 | + | |
| 7 | +include "sys.m"; | |
| 8 | + sys: Sys; | |
| 9 | + | |
| 10 | +stderr: ref Sys->FD; | |
| 11 | + | |
| 12 | +include "keyring.m"; | |
| 13 | + kr: Keyring; | |
| 14 | + | |
| 15 | +include "string.m"; | |
| 16 | + str: String; | |
| 17 | + | |
| 18 | +include "math.m"; | |
| 19 | + math: Math; | |
| 20 | + | |
| 21 | +include "hash.m"; | |
| 22 | + hash: Hash; | |
| 23 | + | |
| 24 | +include "loader.m"; | |
| 25 | +include "classloader.m"; | |
| 26 | + ld: Loader; | |
| 27 | + Niladt: import Loader; | |
| 28 | + jassist: JavaAssist; | |
| 29 | + jtrace: JavaTrace; | |
| 30 | + | |
| 31 | + JDEBUG, JVERBOSE: import JavaTrace; | |
| 32 | + | |
| 33 | + getint, getintarray, getptr: import jassist; | |
| 34 | + getreloc, getrtreloc, getstring: import jassist; | |
| 35 | + getclassadt, getabsint, getadtstring: import jassist; | |
| 36 | + getbytearray, getstrarray, arrayof: import jassist; | |
| 37 | + getmd, putclass, putint, putmod: import jassist; | |
| 38 | + putobj, putptr, putstring, makeadt: import jassist; | |
| 39 | + bytearraytoJS, intarraytoJS: import jassist; | |
| 40 | + bigarraytoJS, realarraytoJS: import jassist; | |
| 41 | + ArraytoJS, JStoObject: import jassist; | |
| 42 | + | |
| 43 | +this: JavaClassLoader; | |
| 44 | +thisnil: Nilmod; | |
| 45 | +sysnil: Nilmod; | |
| 46 | +loadlinks: array of Loader->Link; | |
| 47 | +syslinks: array of Loader->Link; | |
| 48 | +relocs: list of ref Class; | |
| 49 | +relocd: list of ref Class; | |
| 50 | +interf: list of ref Class; | |
| 51 | +interfx: list of ref Class; | |
| 52 | +initcl: list of ref Class; | |
| 53 | +main: ref Class; | |
| 54 | +arrayclass: ref Class; | |
| 55 | +arraymd: ref Loader->Niladt; | |
| 56 | +stringclass: ref Class; | |
| 57 | +fsindir: int; | |
| 58 | +cur: string; | |
| 59 | + | |
| 60 | +interfaces: array of ref Class; | |
| 61 | +ninterfaces: int = 0; | |
| 62 | +linterfaces: int = 0; | |
| 63 | + | |
| 64 | +INITINTER: con 32; | |
| 65 | + | |
| 66 | +acqchan: chan of int; | |
| 67 | +relchan: chan of int; | |
| 68 | +exitchan: chan of int; | |
| 69 | + | |
| 70 | +MSHUTDOWN, MENTER, MEXIT, MWAIT, MNOTIFY, MSLEEP, MINTERRUPT, MTIMER, MSYNC: | |
| 71 | + con iota; | |
| 72 | + | |
| 73 | +monitorctl: chan of (int, ref ThreadData, ref Object, int); | |
| 74 | +threadctl: chan of (ref ThreadData, int); | |
| 75 | + | |
| 76 | +threadcount: int = 0; | |
| 77 | +daemoncount: int = 0; | |
| 78 | +stopped: int = 0; | |
| 79 | + | |
| 80 | +ident: con "ClassLoader"; | |
| 81 | +warn: int = 1; | |
| 82 | +debug: int = 0; | |
| 83 | +verbose: int = 0; | |
| 84 | +errors: int = 0; | |
| 85 | + | |
| 86 | +# for generating ClassLoader exceptions use | |
| 87 | +# the following con's. They will be turned | |
| 88 | +# into a corresponding Java Exception by | |
| 89 | +# sysexcetion | |
| 90 | +# when thrown the format is: | |
| 91 | +# raise( ex +":"+detail ); | |
| 92 | +# see loaderror(); | |
| 93 | +# | |
| 94 | +# NOTE: the "raise" string has limited size | |
| 95 | +# hence the "e"+<int> | |
| 96 | +# | |
| 97 | +JCLDREX : con "JLD:"; #prefix | |
| 98 | +noclassdeffound, | |
| 99 | +classcircularity, | |
| 100 | +classformat, | |
| 101 | +nosuchmethod, | |
| 102 | +nosuchfield, | |
| 103 | +unsatisfiedlink, | |
| 104 | +linkageerr, | |
| 105 | +exceptionininitializer | |
| 106 | + : con "e" + (string iota); | |
| 107 | + | |
| 108 | +badcallindex : con "call index"; | |
| 109 | +nocloneindex : con "clone index"; | |
| 110 | + | |
| 111 | +encoding := array[] of | |
| 112 | +{ | |
| 113 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | |
| 114 | + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | |
| 115 | + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', | |
| 116 | + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', | |
| 117 | + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', | |
| 118 | + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', | |
| 119 | + 'w', 'x', 'y', 'z', '0', '1', '2', '3', | |
| 120 | + '4', '5', '6', '7', '8', '9', '+', '-', | |
| 121 | +}; | |
| 122 | + | |
| 123 | +bits := array[] of { 16r80, 16r40, 16r20, 16r10, 16r08, 16r04, 16r02, 16r01 }; | |
| 124 | +mbits := array[] of { 16r80, 16r20, 16r08, 16r02 }; | |
| 125 | + | |
| 126 | +# | |
| 127 | +# Diagnostics. | |
| 128 | +# | |
| 129 | + | |
| 130 | +mesg(s: string) | |
| 131 | +{ | |
| 132 | + sys->fprint(stderr, "%s: %s\n", ident, s); | |
| 133 | +} | |
| 134 | + | |
| 135 | +diag(s: string) | |
| 136 | +{ | |
| 137 | + if (cur != nil) | |
| 138 | + s = cur + ": " + s; | |
| 139 | + mesg(s); | |
| 140 | + errors++; | |
| 141 | +} | |
| 142 | + | |
| 143 | +loaderror( ex : string, msg : string ) | |
| 144 | +{ | |
| 145 | + s := msg; | |
| 146 | + | |
| 147 | + # if prefix exists then just rethrow msg | |
| 148 | + if ( str->prefix( JCLDREX+ex, msg ) == 0 ) | |
| 149 | + { | |
| 150 | + if ( cur != nil ) | |
| 151 | + s = cur +": " + s; | |
| 152 | + | |
| 153 | + s = sys->sprint( "%s%s:%s", JCLDREX, ex, s ); | |
| 154 | + } | |
| 155 | + | |
| 156 | + trace(JDEBUG,s); | |
| 157 | + | |
| 158 | + raise s; | |
| 159 | +} | |
| 160 | + | |
| 161 | +error(s: string) | |
| 162 | +{ | |
| 163 | + if ( s == nil ) | |
| 164 | + s = JCLDREX + "fatal error"; | |
| 165 | + else | |
| 166 | + { | |
| 167 | + # if prefix exists then just re-throw s | |
| 168 | + if ( str->prefix(JCLDREX,s) == 0 ) | |
| 169 | + { | |
| 170 | + # add prefix to tag as a Loader ex | |
| 171 | + s = sys->sprint( "%s%s:%s", JCLDREX, s, cur ); | |
| 172 | + } | |
| 173 | + } | |
| 174 | + | |
| 175 | + trace(JDEBUG,s); | |
| 176 | + | |
| 177 | + raise s; | |
| 178 | +} | |
| 179 | + | |
| 180 | +warning(s: string) | |
| 181 | +{ | |
| 182 | + if (!warn) | |
| 183 | + return; | |
| 184 | + if (cur != nil) | |
| 185 | + s = cur + ": " + s; | |
| 186 | + sys->fprint(stderr, "%s: warning: %s\n", ident, s); | |
| 187 | +} | |
| 188 | + | |
| 189 | +trace(c: int, s: string) | |
| 190 | +{ | |
| 191 | + if (jtrace != nil) | |
| 192 | + jtrace->trace(c, s); | |
| 193 | +} | |
| 194 | + | |
| 195 | +loadtrace() | |
| 196 | +{ | |
| 197 | + if (jtrace != nil) | |
| 198 | + return; | |
| 199 | + jtrace = load JavaTrace JavaTrace->PATH; | |
| 200 | + if (jtrace == nil) | |
| 201 | + error(sys->sprint("could not load %s: %r", JavaTrace->PATH)); | |
| 202 | + jtrace->init(jassist); | |
| 203 | +} | |
| 204 | + | |
| 205 | +# | |
| 206 | +# Load synchronization. Allow only one thread to be loading at a time. | |
| 207 | +# | |
| 208 | + | |
| 209 | +loadsync() | |
| 210 | +{ | |
| 211 | + for (;;) { | |
| 212 | + alt { | |
| 213 | + <- acqchan => | |
| 214 | + ; | |
| 215 | + <- exitchan => | |
| 216 | + return; | |
| 217 | + } | |
| 218 | + alt { | |
| 219 | + <- relchan => | |
| 220 | + ; | |
| 221 | + <- exitchan => | |
| 222 | + return; | |
| 223 | + } | |
| 224 | + } | |
| 225 | +} | |
| 226 | + | |
| 227 | +acquire() | |
| 228 | +{ | |
| 229 | + acqchan <-= 0; | |
| 230 | +} | |
| 231 | + | |
| 232 | +release() | |
| 233 | +{ | |
| 234 | + relchan <-= 0; | |
| 235 | +} | |
| 236 | + | |
| 237 | +context: ref Draw->Context; | |
| 238 | + | |
| 239 | +# | |
| 240 | +# Initialize loader. Entry. | |
| 241 | +# | |
| 242 | +init(j: JavaClassLoader, ctxt: ref Draw->Context) | |
| 243 | +{ | |
| 244 | + sys = load Sys Sys->PATH; | |
| 245 | + stderr = sys->fildes(2); | |
| 246 | + context = ctxt; | |
| 247 | + kr = load Keyring Keyring->PATH; | |
| 248 | + if (kr == nil) | |
| 249 | + error(sys->sprint("could not load %s: %r", Keyring->PATH)); | |
| 250 | + str = load String String->PATH; | |
| 251 | + if (str == nil) | |
| 252 | + error(sys->sprint("could not load %s: %r", String->PATH)); | |
| 253 | + math = load Math Math->PATH; | |
| 254 | + if (math == nil) | |
| 255 | + error(sys->sprint("could not load %s: %r", Math->PATH)); | |
| 256 | + math->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX); | |
| 257 | + hash = load Hash Hash->PATH; | |
| 258 | + if (hash == nil) | |
| 259 | + error(sys->sprint("could not load %s: %r", Hash->PATH)); | |
| 260 | + ld = load Loader Loader->PATH; | |
| 261 | + if (ld == nil) | |
| 262 | + error(sys->sprint("could not load %s: %r", Loader->PATH)); | |
| 263 | + jassist = load JavaAssist JavaAssist->PATH; | |
| 264 | + if (jassist == nil) | |
| 265 | + error(sys->sprint("could not load %s: %r", JavaAssist->PATH)); | |
| 266 | + if (verbose) { | |
| 267 | + loadtrace(); | |
| 268 | + if (debug) | |
| 269 | + jtrace->level = JDEBUG; | |
| 270 | + else | |
| 271 | + jtrace->level = JVERBOSE; | |
| 272 | + } | |
| 273 | + fsindir = jassist->little_endian(); | |
| 274 | + this = j; | |
| 275 | + thisnil = jassist->jclnilmod(j); | |
| 276 | + sysnil = jassist->sysnilmod(sys); | |
| 277 | + loadlinks = ld->link(thisnil); | |
| 278 | + syslinks = ld->link(sysnil); | |
| 279 | + if (loadlinks == nil || syslinks == nil) | |
| 280 | + error(sys->sprint("Loader->link failed: %r")); | |
| 281 | + initloadhash(); | |
| 282 | + acqchan = chan of int; | |
| 283 | + relchan = chan of int; | |
| 284 | + exitchan = chan of int; | |
| 285 | + spawn loadsync(); | |
| 286 | + monitorctl = chan of (int, ref ThreadData, ref Object, int); | |
| 287 | + spawn monitor(); | |
| 288 | + threadctl = chan of (ref ThreadData, int); | |
| 289 | + spawn threadmanager(); | |
| 290 | + jniinit(); | |
| 291 | +} | |
| 292 | + | |
| 293 | +loadarrayclass() | |
| 294 | +{ | |
| 295 | + arrayclass = loader(ARRAYCLASS); | |
| 296 | + arraymd = arrayclass.moddata; | |
| 297 | +} | |
| 298 | + | |
| 299 | +loadstringclass() | |
| 300 | +{ | |
| 301 | + stringclass = loader(STRINGCLASS); | |
| 302 | +} | |
| 303 | + | |
| 304 | +# | |
| 305 | +# Native interface initialization. | |
| 306 | +# | |
| 307 | +jniinit() | |
| 308 | +{ | |
| 309 | + j := load JavaNative JavaNative->PATH; | |
| 310 | + if (j == nil) | |
| 311 | + error(sys->sprint("could not load %s: %r", JavaNative->PATH)); | |
| 312 | + e := j->init(sys, ld, this, jassist); | |
| 313 | + if (e != nil) | |
| 314 | + error(sys->sprint("JavaNative->init failed: %s", e)); | |
| 315 | +} | |
| 316 | + | |
| 317 | +# | |
| 318 | +# Shutdown loader. Entry. | |
| 319 | +# | |
| 320 | +shutdown() | |
| 321 | +{ | |
| 322 | + if (exitchan != nil) { | |
| 323 | + exitchan <-= 0; | |
| 324 | + exitchan = nil; | |
| 325 | + } | |
| 326 | + if (monitorctl != nil) { | |
| 327 | + monitorctl <-= (MSHUTDOWN, nil, nil, 0); | |
| 328 | + monitorctl = nil; | |
| 329 | + } | |
| 330 | + if (threadctl != nil) { | |
| 331 | + threadctl <-= (nil, ThreadData.SHUTDOWN); | |
| 332 | + threadctl = nil; | |
| 333 | + } | |
| 334 | +} | |
| 335 | + | |
| 336 | +# | |
| 337 | +# Load a class and print information about it. | |
| 338 | +# Does not resolve the class and should not be | |
| 339 | +# called in the execution environment. Entry. | |
| 340 | +# | |
| 341 | +info(name: string) | |
| 342 | +{ | |
| 343 | + c := getclass(name); | |
| 344 | + if (c.state == NEW) | |
| 345 | + c.loadclass(); | |
| 346 | + loadtrace(); | |
| 347 | + jtrace->info(c); | |
| 348 | +} | |
| 349 | + | |
| 350 | +# | |
| 351 | +# Perform outstanding relocation on loaded classes. | |
| 352 | +# | |
| 353 | +doreloc() | |
| 354 | +{ | |
| 355 | + # | |
| 356 | + # Load classes we need for relocation. | |
| 357 | + # | |
| 358 | + while (relocs != nil) { | |
| 359 | + r: list of ref Class; | |
| 360 | + r = nil; | |
| 361 | + reloc := hd relocs; | |
| 362 | + relocs = tl relocs; | |
| 363 | + trace(JDEBUG, sys->sprint("reloc %s", reloc.name)); | |
| 364 | + i := CLASSREF; | |
| 365 | + while ((s := getstring(reloc.mod, i)) != nil) { | |
| 366 | + if (s != LOADER) | |
| 367 | + r = loadhierarchy(s) :: r; | |
| 368 | + else | |
| 369 | + r = nil :: r; | |
| 370 | + i += 2 * WORDZ; | |
| 371 | + } | |
| 372 | + reloc.refs = mkclarray(r); | |
| 373 | + reloc.relocate(); | |
| 374 | + relocd = reloc :: relocd; | |
| 375 | + } | |
| 376 | + # | |
| 377 | + # Patch the module data of the relocated classes. | |
| 378 | + # | |
| 379 | + while (relocd != nil) { | |
| 380 | + patch := hd relocd; | |
| 381 | + relocd = tl relocd; | |
| 382 | + trace(JDEBUG, sys->sprint("modpatch %s", patch.name)); | |
| 383 | + patch.modpatch(); | |
| 384 | + if (patch.native != nil || patch.classinit != nil) { | |
| 385 | + initcl = patch :: initcl; | |
| 386 | + patch.state = LOADED; | |
| 387 | + } else | |
| 388 | + patch.state = INITED; | |
| 389 | + } | |
| 390 | + # | |
| 391 | + # Extend interfaces. | |
| 392 | + # | |
| 393 | + while (interfx != nil) { | |
| 394 | + extend := hd interfx; | |
| 395 | + interfx = tl interfx; | |
| 396 | + extend.interdirect = extend.interextends; | |
| 397 | + extend.extinterfaces(); | |
| 398 | + } | |
| 399 | + # | |
| 400 | + # Make interface linkage tables for classes that implement interfaces. | |
| 401 | + # | |
| 402 | + while (interf != nil) { | |
| 403 | + inter := hd interf; | |
| 404 | + interf = tl interf; | |
| 405 | + inter.interdirect = inter.interextends; | |
| 406 | + inter.linkinterfaces(); | |
| 407 | + } | |
| 408 | + # | |
| 409 | + # Call class initializers. | |
| 410 | + # | |
| 411 | + initc : ref Class; | |
| 412 | + t : ref ThreadData; | |
| 413 | + | |
| 414 | + { | |
| 415 | + while (initcl != nil) { | |
| 416 | + initc = hd initcl; | |
| 417 | + initcl = tl initcl; | |
| 418 | + initc.state = INITED; | |
| 419 | + trace(JVERBOSE, sys->sprint("Switching class %s state to INITED", initc.name)); | |
| 420 | + t = getthreaddata(); | |
| 421 | + release(); | |
| 422 | + unblock(t); | |
| 423 | + if (initc.native != nil) | |
| 424 | + initc.initjni(); | |
| 425 | + if (initc.classinit != nil) { | |
| 426 | + trace(JVERBOSE, sys->sprint("%s-><clinit>()", initc.name)); | |
| 427 | + jassist->mcall0(initc.mod, initc.classinit.value); | |
| 428 | + trace(JDEBUG, sys->sprint("clinit done")); | |
| 429 | + } | |
| 430 | + block(t); | |
| 431 | + acquire(); | |
| 432 | + } | |
| 433 | + } | |
| 434 | + exception e | |
| 435 | + { | |
| 436 | + "*" => | |
| 437 | + #NOTE: a raise is only expected from the init calls therefore | |
| 438 | + # when we reach here we need to block and acquire | |
| 439 | + block(t); | |
| 440 | + acquire(); | |
| 441 | + trace(JVERBOSE, sys->sprint("Some exception: %s", e)); | |
| 442 | + if ( str->prefix(JCLDREX+exceptionininitializer, e ) == 1 ) | |
| 443 | + loaderror(exceptionininitializer, e ); #rethrow | |
| 444 | + else | |
| 445 | + { | |
| 446 | + # clear any java exception; we are replacing it | |
| 447 | + t.culprit = nil; | |
| 448 | + loaderror(exceptionininitializer, sys->sprint("%s[unk]", initc.name)); | |
| 449 | + } | |
| 450 | + } | |
| 451 | +} | |
| 452 | + | |
| 453 | +# | |
| 454 | +# Main "load class" routine. Load a class hierarchy and | |
| 455 | +# its dependencies and prepare it for use. Entry. | |
| 456 | +# No return on error. | |
| 457 | +# | |
| 458 | +loader(name: string): ref Class | |
| 459 | +{ | |
| 460 | + released := 0; | |
| 461 | + t := getthreaddata(); | |
| 462 | + { | |
| 463 | + trace(JDEBUG, sys->sprint("load class %s", name)); | |
| 464 | + block(t); | |
| 465 | + acquire(); | |
| 466 | + c := loadhierarchy(name); | |
| 467 | + if (relocs != nil) | |
| 468 | + doreloc(); | |
| 469 | + release(); | |
| 470 | + unblock(t); | |
| 471 | + released = 1; | |
| 472 | + trace(JDEBUG, sys->sprint("loader() exit")); | |
| 473 | +# if (errors) | |
| 474 | +# error(nil); | |
| 475 | + return c; | |
| 476 | + } | |
| 477 | + exception e | |
| 478 | + { | |
| 479 | + "*" => | |
| 480 | + if(released == 0) { | |
| 481 | + release(); | |
| 482 | + unblock(t); | |
| 483 | + } | |
| 484 | + if (e == nil) | |
| 485 | + e = "exit"; | |
| 486 | + | |
| 487 | + if ( str->prefix(JCLDREX, e) == 1 ) | |
| 488 | + error(e); | |
| 489 | + | |
| 490 | + error( sys->sprint( "%s", e) ); | |
| 491 | + | |
| 492 | + #else if (e.name == noclassdeffound) | |
| 493 | + #{ | |
| 494 | + # error(nil); | |
| 495 | + #} | |
| 496 | + #else | |
| 497 | + # error(sys->sprint("loader exception: %s: %s: %d", e.mod, e.name, e.pc)); | |
| 498 | + } | |
| 499 | + return nil; | |
| 500 | +} | |
| 501 | + | |
| 502 | +# | |
| 503 | +# Recursively load a hierarchy. | |
| 504 | +# | |
| 505 | +loadhierarchy(name: string): ref Class | |
| 506 | +{ | |
| 507 | + c := getclass(name); | |
| 508 | + case c.state { | |
| 509 | + NEW => | |
| 510 | + trace(JVERBOSE, sys->sprint("[%s]", name)); | |
| 511 | + c.loadclass(); | |
| 512 | + relocs = c :: relocs; | |
| 513 | + if ((s := getstring(c.mod, SUPER)) != nil) { | |
| 514 | + c.state = HIER; | |
| 515 | + trace(JVERBOSE, sys->sprint("Switching class %s state to HIER", name)); | |
| 516 | + c.super = loadhierarchy(s); | |
| 517 | + } else | |
| 518 | + c.super = nil; | |
| 519 | + c.state = RESOLVE; | |
| 520 | + trace(JVERBOSE, sys->sprint("Switching class %s state to RESOLVE", name)); | |
| 521 | + c.resolve(); | |
| 522 | + c.loadinterfaces(); | |
| 523 | + HIER => | |
| 524 | + loaderror( classcircularity, name ); | |
| 525 | + } | |
| 526 | + return c; | |
| 527 | +} | |
| 528 | + | |
| 529 | +# | |
| 530 | +# Check if a string matches exception, | |
| 531 | +# right aligned in string | |
| 532 | +# | |
| 533 | +matches(str, e: string): int | |
| 534 | +{ | |
| 535 | + if (len str >= len e && str[len str - len e:] == e) | |
| 536 | + return 1; | |
| 537 | + return 0; | |
| 538 | +} | |
| 539 | + | |
| 540 | +# | |
| 541 | +# Encode a class name path if its final component | |
| 542 | +# will be too long. Entry. | |
| 543 | +# | |
| 544 | +encodename(name: string): string | |
| 545 | +{ | |
| 546 | + (dir, base) := str->splitr(name, "/"); | |
| 547 | + b := array of byte base; | |
| 548 | + if (len b <= MAXUNENCODED) | |
| 549 | + return name; | |
| 550 | + d := array[kr->MD5dlen] of byte; | |
| 551 | + if (kr->md5(b, len b, d, nil) == nil) | |
| 552 | + error(sys->sprint("md5 failed: %r")); | |
| 553 | + e := array[ENCODEDLEN] of byte; | |
| 554 | + v := 0; | |
| 555 | + n := 0; | |
| 556 | + r := 0; | |
| 557 | + for (i := 0; i < ENCODEDLEN; i++) { | |
| 558 | + if (r < 6) { | |
| 559 | + v |= int d[n++] << r; | |
| 560 | + r += 8; | |
| 561 | + } | |
| 562 | + e[i] = byte encoding[v & 16r3F]; | |
| 563 | + v >>= 6; | |
| 564 | + r -= 6; | |
| 565 | + } | |
| 566 | + return dir + string e; | |
| 567 | +} | |
| 568 | + | |
| 569 | +## | |
| 570 | +## Runtime entries. | |
| 571 | +## | |
| 572 | + | |
| 573 | +# | |
| 574 | +# Runtime load. Passed a pointer into a module's data of a rtload table. | |
| 575 | +# | |
| 576 | +rtload(addr: int) | |
| 577 | +{ | |
| 578 | + o := getabsint(addr + RTTHISOFFSET); | |
| 579 | + r := getabsint(addr - (o + WORDZ)); | |
| 580 | + l := o + r; | |
| 581 | + d := makeadt(addr - l); | |
| 582 | + s := getadtstring(d, l + RTCLASSOFFSET); | |
| 583 | + a := getrtreloc(d, l + RTRELOCOFFSET); | |
| 584 | + t := getclassadt(d, CLASSADTOFFSET); | |
| 585 | + trace(JVERBOSE, sys->sprint("rtload %s [%d -> %d] for %s", s, o, r, t.name)); | |
| 586 | + if (t.state != INITED) | |
| 587 | + error("this not loaded"); | |
| 588 | + c := loader(s); | |
| 589 | + cur = c.name; | |
| 590 | + putmod(d, l, c.mod); | |
| 591 | + putmod(d, l + RTCLASSOFFSET, c.native); | |
| 592 | + putclass(d, l + RTRELOCOFFSET, c); | |
| 593 | + putint(d, l + RTTHISOFFSET, c.objtype); | |
| 594 | + o = l + RTFIRSTRELOC; | |
| 595 | + n := len a; | |
| 596 | + for (i := 0; i < n; i++) { | |
| 597 | + if ((a[i].flags & Rmask) == Rinvokespecial) { | |
| 598 | + (w, m, x) := t.special(a[i].field, a[i].signature, a[i].flags, c); | |
| 599 | + if (a[i].flags & Rspecialmp) { | |
| 600 | + if (w == CMP) | |
| 601 | + putmod(d, o, m.mod); | |
| 602 | + else if (w == CNP) | |
| 603 | + putmod(d, o, m.native); | |
| 604 | + else | |
| 605 | + error("bad special"); | |
| 606 | + } else | |
| 607 | + putint(d, o, x); | |
| 608 | + } else { | |
| 609 | + (w, v) := c.resolvereloc(a[i].field, a[i].signature, a[i].flags); | |
| 610 | + case w { | |
| 611 | + VVAL => | |
| 612 | + putint(d, o, v); | |
| 613 | + VMP => | |
| 614 | + putmod(d, o, c.mod); | |
| 615 | + VNP => | |
| 616 | + putmod(d, o, c.native); | |
| 617 | + VOBJ => | |
| 618 | + putobj(d, o, c.this); | |
| 619 | + * => | |
| 620 | + error("bad resolve"); | |
| 621 | + } | |
| 622 | + } | |
| 623 | + o += WORDZ; | |
| 624 | + } | |
| 625 | + cur = nil; | |
| 626 | +# if (errors) | |
| 627 | +# error("rtload failed"); | |
| 628 | +} | |
| 629 | + | |
| 630 | +# | |
| 631 | +# Get a Class adt by name. Used internally and made visible. | |
| 632 | +# It does no loading so should only be called if you know | |
| 633 | +# the class is loaded (or are loading it). | |
| 634 | +# | |
| 635 | + | |
| 636 | +CHSZ: con 31; | |
| 637 | +classhash := array[CHSZ] of list of ref Class; | |
| 638 | + | |
| 639 | +getclass(name: string): ref Class | |
| 640 | +{ | |
| 641 | + h := classhash[hash->fun1(name, CHSZ):]; | |
| 642 | + for (l := h[0]; l != nil; l = tl l) { | |
| 643 | + c := hd l; | |
| 644 | + if (c.name == name) | |
| 645 | + return c; | |
| 646 | + } | |
| 647 | + c := ref Class; | |
| 648 | + c.state = NEW; | |
| 649 | + trace(JVERBOSE, sys->sprint("Switching class %s state to NEW", name)); | |
| 650 | + c.name = name; | |
| 651 | + c.flags = 0; | |
| 652 | + c.info = ref Ldinfo; | |
| 653 | + h[0] = c :: h[0]; | |
| 654 | + return c; | |
| 655 | +} | |
| 656 | + | |
| 657 | +# | |
| 658 | +# Map a module to its class. This works for native modules too. | |
| 659 | +# | |
| 660 | + | |
| 661 | +MHSZ: con 31; | |
| 662 | +modhash := array[MHSZ] of list of (Nilmod, ref Class); | |
| 663 | + | |
| 664 | +addmodclass(m: Nilmod, c: ref Class) | |
| 665 | +{ | |
| 666 | + h := modhash[jassist->modhash(m) % MHSZ:]; | |
| 667 | + h[0] = (m, c) :: h[0]; | |
| 668 | +} | |
| 669 | + | |
| 670 | +getmodclass(m: Nilmod): ref Class | |
| 671 | +{ | |
| 672 | + for (l := modhash[jassist->modhash(m) % MHSZ]; l != nil; l = tl l) { | |
| 673 | + (t, c) := hd l; | |
| 674 | + if (t == m) | |
| 675 | + return c; | |
| 676 | + } | |
| 677 | + return nil; | |
| 678 | +} | |
| 679 | + | |
| 680 | +# | |
| 681 | +# Thread data. | |
| 682 | +# | |
| 683 | + | |
| 684 | +THSZ: con 31; | |
| 685 | +threadhash := array[THSZ] of list of ref ThreadData; | |
| 686 | + | |
| 687 | +getpid(): int | |
| 688 | +{ | |
| 689 | + return sys->pctl(0, nil); | |
| 690 | +} | |
| 691 | + | |
| 692 | +getcontext(): ref Draw->Context | |
| 693 | +{ | |
| 694 | + return context; | |
| 695 | +} | |
| 696 | + | |
| 697 | +getthreaddata(): ref ThreadData | |
| 698 | +{ | |
| 699 | + p := getpid(); | |
| 700 | + for (l := threadhash[p % THSZ]; l != nil; l = tl l) { | |
| 701 | + t := hd l; | |
| 702 | + if (t.pid == p) | |
| 703 | + return t; | |
| 704 | + } | |
| 705 | + acquire(); | |
| 706 | + h := threadhash[p % THSZ:]; | |
| 707 | + d := ref ThreadData; | |
| 708 | + d.pid = p; | |
| 709 | + d.wchan = chan of int; | |
| 710 | + d.flags = 0; | |
| 711 | + h[0] = d :: h[0]; | |
| 712 | + threadcount++; | |
| 713 | + trace(JVERBOSE, sys->sprint("count = %d + %d", threadcount, daemoncount)); | |
| 714 | + release(); | |
| 715 | + return d; | |
| 716 | +} | |
| 717 | + | |
| 718 | +delthreaddata() | |
| 719 | +{ | |
| 720 | + n: list of ref ThreadData; | |
| 721 | + acquire(); | |
| 722 | + p := getpid(); | |
| 723 | + h := threadhash[p % THSZ:]; | |
| 724 | + for (l := h[0]; l != nil; l = tl l) { | |
| 725 | + t := hd l; | |
| 726 | + if (t.pid == p) { | |
| 727 | + if (t.flags & ThreadData.DAEMON) | |
| 728 | + daemoncount--; | |
| 729 | + else | |
| 730 | + threadcount--; | |
| 731 | + } else | |
| 732 | + n = t :: n; | |
| 733 | + } | |
| 734 | + h[0] = n; | |
| 735 | + trace(JVERBOSE, sys->sprint("count = %d + %d", threadcount, daemoncount)); | |
| 736 | + if (threadcount == 0) | |
| 737 | + nothreads(nil); | |
| 738 | + else | |
| 739 | + release(); | |
| 740 | +} | |
| 741 | + | |
| 742 | +# | |
| 743 | +# Mark current thread a daemon. Entry. | |
| 744 | +# | |
| 745 | +daemonize() | |
| 746 | +{ | |
| 747 | + t := getthreaddata(); | |
| 748 | + acquire(); | |
| 749 | + if ((t.flags & ThreadData.DAEMON) == 0) { | |
| 750 | + t.flags |= ThreadData.DAEMON; | |
| 751 | + daemoncount++; | |
| 752 | + threadcount--; | |
| 753 | + } | |
| 754 | + trace(JVERBOSE, sys->sprint("count = %d + %d", threadcount, daemoncount)); | |
| 755 | + if (threadcount == 0) | |
| 756 | + nothreads(t); | |
| 757 | + else | |
| 758 | + release(); | |
| 759 | +} | |
| 760 | + | |
| 761 | +# | |
| 762 | +# Stop all threads. When all are dead we will shutdown. | |
| 763 | +# | |
| 764 | +stopthreads(t: ref ThreadData) | |
| 765 | +{ | |
| 766 | + for (i := 0; i < THSZ; i++) | |
| 767 | + for (l := threadhash[i]; l != nil; l = tl l) { | |
| 768 | + s := hd l; | |
| 769 | + if (s != t) | |
| 770 | + stop(s, nil); | |
| 771 | + } | |
| 772 | + stopped = 1; | |
| 773 | +} | |
| 774 | + | |
| 775 | +# | |
| 776 | +# No non-daemon threads. Maybe clean up, maybe shutdown. | |
| 777 | +# | |
| 778 | +nothreads(t: ref ThreadData) | |
| 779 | +{ | |
| 780 | + if (!stopped) | |
| 781 | + stopthreads(t); | |
| 782 | + if (daemoncount != 0) { | |
| 783 | + release(); | |
| 784 | + if (t != nil) { | |
| 785 | + t.culprit = threaddeath().new(); | |
| 786 | + raise JAVAEXCEPTION; | |
| 787 | + } | |
| 788 | + return; | |
| 789 | + } | |
| 790 | + release(); | |
| 791 | + shutdown(); | |
| 792 | +} | |
| 793 | + | |
| 794 | +# | |
| 795 | +# Entry for system.exit(). | |
| 796 | +# | |
| 797 | +system_exit() | |
| 798 | +{ | |
| 799 | + t := getthreaddata(); | |
| 800 | + acquire(); | |
| 801 | + stopthreads(t); | |
| 802 | + release(); | |
| 803 | + t.culprit = threaddeath().new(); | |
| 804 | + raise JAVAEXCEPTION; | |
| 805 | +} | |
| 806 | + | |
| 807 | +cmd_start: array of byte; | |
| 808 | +cmd_stop: array of byte; | |
| 809 | +cmd_kill: array of byte; | |
| 810 | +cmd_failed: int = 0; | |
| 811 | +tdclass: ref Class; | |
| 812 | + | |
| 813 | +ctlfile(t: ref ThreadData) | |
| 814 | +{ | |
| 815 | + if (t.ctlfile == nil) | |
| 816 | + t.ctlfile = PROG + "/" + string t.pid + "/dbgctl"; | |
| 817 | +} | |
| 818 | + | |
| 819 | +threaddeath(): ref Class | |
| 820 | +{ | |
| 821 | + if (tdclass == nil) | |
| 822 | + tdclass = loader(EXCEPTIONPATH + "ThreadDeath"); | |
| 823 | + return tdclass; | |
| 824 | +} | |
| 825 | + | |
| 826 | +dosuspend(t: ref ThreadData) | |
| 827 | +{ | |
| 828 | + ctlfile(t); | |
| 829 | + f := sys->open(t.ctlfile, Sys->ORDWR); | |
| 830 | + monsync(); | |
| 831 | + t.flags |= ThreadData.SUSPENDED; | |
| 832 | + if (f == nil) { | |
| 833 | + if (!cmd_failed) { | |
| 834 | + warning(sys->sprint("could not open %s: %r", t.ctlfile)); | |
| 835 | + cmd_failed = 1; | |
| 836 | + } | |
| 837 | + } else { | |
| 838 | + sys->write(f, cmd_stop, len cmd_stop); | |
| 839 | + t.control = f; | |
| 840 | + } | |
| 841 | +} | |
| 842 | + | |
| 843 | +doresume(t: ref ThreadData) | |
| 844 | +{ | |
| 845 | + if (t.control != nil) { | |
| 846 | + sys->write(t.control, cmd_start, len cmd_start); | |
| 847 | + t.control = nil; | |
| 848 | + } | |
| 849 | + monsync(); | |
| 850 | + t.flags &= ~ThreadData.SUSPENDED; | |
| 851 | + if (t.flags & ThreadData.ACKSUSP) { | |
| 852 | + t.wchan <-= MONOK; | |
| 853 | + t.flags &= ~ThreadData.ACKSUSP; | |
| 854 | + } | |
| 855 | +} | |
| 856 | + | |
| 857 | +dostop(t: ref ThreadData) | |
| 858 | +{ | |
| 859 | + ctlfile(t); | |
| 860 | + f := sys->open(t.ctlfile, Sys->ORDWR); | |
| 861 | + if (f == nil) { | |
| 862 | + if (!cmd_failed) { | |
| 863 | + warning(sys->sprint("could not open %s: %r", t.ctlfile)); | |
| 864 | + cmd_failed = 1; | |
| 865 | + } | |
| 866 | + } else | |
| 867 | + sys->write(f, cmd_kill, len cmd_kill); | |
| 868 | +} | |
| 869 | + | |
| 870 | +# | |
| 871 | +# The thread manager looks after suspend and resume. | |
| 872 | +# A thread that cannot be suspended enters a block()/unblock() | |
| 873 | +# pair for the duration of its critical region. | |
| 874 | +# | |
| 875 | + | |
| 876 | +threadmanager() | |
| 877 | +{ | |
| 878 | + cmd_start = array of byte "start"; | |
| 879 | + cmd_stop = array of byte "stop"; | |
| 880 | + cmd_kill = array of byte "maim"; | |
| 881 | + for (;;) { | |
| 882 | + (t, c) := <- threadctl; | |
| 883 | + if (t != nil && (t.flags & ThreadData.EXITED)) { | |
| 884 | + t = nil; | |
| 885 | + continue; | |
| 886 | + } | |
| 887 | + case c { | |
| 888 | + ThreadData.SHUTDOWN => | |
| 889 | + return; | |
| 890 | + ThreadData.BLOCK => | |
| 891 | + t.flags |= ThreadData.BLOCKED; | |
| 892 | + ThreadData.UNBLOCK => | |
| 893 | + if (t.flags & ThreadData.WAITSTOP) | |
| 894 | + dostop(t); | |
| 895 | + else if (t.flags & ThreadData.WAITSUSP) | |
| 896 | + dosuspend(t); | |
| 897 | + t.flags &= ~(ThreadData.BLOCKED | ThreadData.WAITSTOP | ThreadData.WAITSUSP); | |
| 898 | + ThreadData.SUSPEND => | |
| 899 | + if ((t.flags & ThreadData.SUSPENDED) == 0) { | |
| 900 | + if (t.flags & ThreadData.BLOCKED) | |
| 901 | + t.flags |= ThreadData.WAITSUSP; | |
| 902 | + else | |
| 903 | + dosuspend(t); | |
| 904 | + } | |
| 905 | + ThreadData.RESUME => | |
| 906 | + if (t.flags & ThreadData.SUSPENDED) | |
| 907 | + doresume(t); | |
| 908 | + else | |
| 909 | + t.flags &= ~ThreadData.WAITSUSP; | |
| 910 | + ThreadData.STOP => | |
| 911 | + if (t.flags & ThreadData.BLOCKED) | |
| 912 | + t.flags |= ThreadData.WAITSTOP; | |
| 913 | + else | |
| 914 | + dostop(t); | |
| 915 | + * => | |
| 916 | + threadctl = nil; | |
| 917 | + raise "bad threadctl command"; #error("bad threadctl command"); | |
| 918 | + } | |
| 919 | + t = nil; | |
| 920 | + } | |
| 921 | +} | |
| 922 | + | |
| 923 | +block(t: ref ThreadData) | |
| 924 | +{ | |
| 925 | + threadctl <-= (t, ThreadData.BLOCK); | |
| 926 | +} | |
| 927 | + | |
| 928 | +unblock(t: ref ThreadData) | |
| 929 | +{ | |
| 930 | + threadctl <-= (t, ThreadData.UNBLOCK); | |
| 931 | +} | |
| 932 | + | |
| 933 | +suspend(t: ref ThreadData) | |
| 934 | +{ | |
| 935 | + threadctl <-= (t, ThreadData.SUSPEND); | |
| 936 | +} | |
| 937 | + | |
| 938 | +resume(t: ref ThreadData) | |
| 939 | +{ | |
| 940 | + threadctl <-= (t, ThreadData.RESUME); | |
| 941 | +} | |
| 942 | + | |
| 943 | +stop(t: ref ThreadData, o: ref Object) | |
| 944 | +{ | |
| 945 | + if (o == nil) | |
| 946 | + o = threaddeath().new(); | |
| 947 | + t.culprit = o; | |
| 948 | + threadctl <-= (t, ThreadData.STOP); | |
| 949 | +} | |
| 950 | + | |
| 951 | +# | |
| 952 | +# Exceptions. | |
| 953 | +# | |
| 954 | + | |
| 955 | +mkexception( name : string ) : ref Object | |
| 956 | +{ | |
| 957 | + return(loader(EXCEPTIONPATH + name).new()); | |
| 958 | +} | |
| 959 | + | |
| 960 | +# convert an Inferno exception into a Java Exception | |
| 961 | +sysexception( e : string ) : ref Object | |
| 962 | +{ | |
| 963 | + s : string; | |
| 964 | + msg : string; | |
| 965 | + | |
| 966 | + | |
| 967 | + if ( e == nil ) | |
| 968 | + { | |
| 969 | + s = "InternalError"; | |
| 970 | + msg = "unknown"; | |
| 971 | + } | |
| 972 | + else if ( str->prefix(JCLDREX,e) == 1 ) | |
| 973 | + { | |
| 974 | + trace(JDEBUG, sys->sprint("sysexception: / %s /", e)); | |
| 975 | + # try to convert JavaClassLoader exceptions first | |
| 976 | + rest := e[len JCLDREX:]; #strip off prefix | |
| 977 | + | |
| 978 | + # pull the possible java ex name; save the rest as a message | |
| 979 | + ex : string; | |
| 980 | + (ex,msg) = str->splitl(rest, ":"); | |
| 981 | + | |
| 982 | + # convert to coresponding Java Exception, if any | |
| 983 | + case ex | |
| 984 | + { | |
| 985 | + noclassdeffound => s = "NoClassDefFoundError"; | |
| 986 | + nosuchmethod => s = "NoSuchMethodError"; | |
| 987 | + classcircularity => s = "ClassCircularityError"; | |
| 988 | + classformat => s = "ClassFormatError"; | |
| 989 | + unsatisfiedlink => s = "UnsatisfiedLinkError"; | |
| 990 | + exceptionininitializer => s = "ExceptionInInitializerError"; | |
| 991 | + linkageerr => s = "LinkageError"; #different then '*' | |
| 992 | + | |
| 993 | + # if none found then make into a generic LinkageError | |
| 994 | + * => s = "LinkageError"; | |
| 995 | + msg = rest; | |
| 996 | + } | |
| 997 | + } | |
| 998 | + else | |
| 999 | + { | |
| 1000 | + trace(JDEBUG, sys->sprint("sysexception: / %s /", e)); | |
| 1001 | + case e | |
| 1002 | + { | |
| 1003 | + # | |
| 1004 | + # inferno system exceptions | |
| 1005 | + # | |
| 1006 | + "zero divide" or | |
| 1007 | + "invalid math argument" or | |
| 1008 | + "Floating point exception" or | |
| 1009 | + "Integer Overflow" or | |
| 1010 | + "Divide by Zero" or | |
| 1011 | + "Floating Point Divide by Zero" or | |
| 1012 | + "Inexact Floating Point" or | |
| 1013 | + "Invalid Floating Operation" or | |
| 1014 | + "Floating Point Result Overflow" or | |
| 1015 | + "Floating Point Stack Check" or | |
| 1016 | + "Floating Point Result Underflow" => | |
| 1017 | + s = "ArithmeticException"; | |
| 1018 | + "heap full" or | |
| 1019 | + "no memory" => | |
| 1020 | + s = "OutOfMemoryError"; | |
| 1021 | + "array bounds error" or | |
| 1022 | + "Array Bounds Check" => | |
| 1023 | + s = "ArrayIndexOutOfBoundsException"; | |
| 1024 | + "negative array size" => | |
| 1025 | + s = "NegativeArraySizeException"; | |
| 1026 | + "dereference of nil" or | |
| 1027 | + "Segmentation violation" or | |
| 1028 | + "Bus error" => | |
| 1029 | + s = "NullPointerException"; | |
| 1030 | + "Stack Overflow" => | |
| 1031 | + s = "StackOverflowError"; | |
| 1032 | + * => | |
| 1033 | + s = "InternalError"; | |
| 1034 | + } | |
| 1035 | + | |
| 1036 | + # fill throwable object with information from inferno ex | |
| 1037 | + #msg = sys->sprint( "%s[%d]:%s", e.mod, e.pc, e.name ); | |
| 1038 | + } | |
| 1039 | + | |
| 1040 | + obj := mkexception(s); #create Java Ex object | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + # set the detailed message | |
| 1044 | + throwable := jassist->ObjecttoJT(obj); | |
| 1045 | + if (stringclass == nil) | |
| 1046 | + loadstringclass(); | |
| 1047 | + throwable.msg = ref JavaString(stringclass.moddata, msg); | |
| 1048 | + | |
| 1049 | + return( obj ); | |
| 1050 | +} | |
| 1051 | + | |
| 1052 | +culprit(e: string): ref Object | |
| 1053 | +{ | |
| 1054 | + thd := getthreaddata(); | |
| 1055 | + | |
| 1056 | + if ( thd.culprit == nil || e != JAVAEXCEPTION ) | |
| 1057 | + { | |
| 1058 | + # no java exception -- turn an inferno | |
| 1059 | + # exception into a Java Exception | |
| 1060 | + thd.culprit = sysexception(e); | |
| 1061 | + } | |
| 1062 | + | |
| 1063 | + return( thd.culprit ); | |
| 1064 | +} | |
| 1065 | + | |
| 1066 | +throw(c: ref Object) | |
| 1067 | +{ | |
| 1068 | + getthreaddata().culprit = c; | |
| 1069 | + raise JAVAEXCEPTION; | |
| 1070 | +} | |
| 1071 | + | |
| 1072 | +sthrow(s: string) | |
| 1073 | +{ | |
| 1074 | + throw(mkexception(s)); | |
| 1075 | +} | |
| 1076 | + | |
| 1077 | +# | |
| 1078 | +# Monitors. | |
| 1079 | +# | |
| 1080 | + | |
| 1081 | +MONOK, MONILL, MONINT: | |
| 1082 | + con iota; | |
| 1083 | + | |
| 1084 | +Synch: adt | |
| 1085 | +{ | |
| 1086 | + thread: ref ThreadData; | |
| 1087 | + count: int; | |
| 1088 | + status: int; | |
| 1089 | + next: cyclic ref Synch; | |
| 1090 | +}; | |
| 1091 | + | |
| 1092 | +Monitor: adt | |
| 1093 | +{ | |
| 1094 | + thread: ref ThreadData; | |
| 1095 | + object: ref Object; | |
| 1096 | + count: int; | |
| 1097 | + head: ref Synch; | |
| 1098 | + tail: ref Synch; | |
| 1099 | +}; | |
| 1100 | + | |
| 1101 | +Waiter: adt | |
| 1102 | +{ | |
| 1103 | + thread: ref ThreadData; | |
| 1104 | + object: ref Object; | |
| 1105 | + count: int; | |
| 1106 | + time: int; | |
| 1107 | + next: cyclic ref Waiter; | |
| 1108 | +}; | |
| 1109 | + | |
| 1110 | +sleepers: ref Waiter; | |
| 1111 | +waiters: ref Waiter; | |
| 1112 | +timeout: int; | |
| 1113 | + | |
| 1114 | +MAXSLEEP: con 1000; | |
| 1115 | +SLEEPTOL: con 50; | |
| 1116 | + | |
| 1117 | +MONHSZ: con 31; | |
| 1118 | +monhash := array[MONHSZ] of list of ref Monitor; | |
| 1119 | + | |
| 1120 | +getmonitor(o: ref Object): ref Monitor | |
| 1121 | +{ | |
| 1122 | + z: ref Monitor; | |
| 1123 | + h := monhash[jassist->objhash(o) % MONHSZ:]; | |
| 1124 | + for (l := h[0]; l != nil; l = tl l) { | |
| 1125 | + m := hd l; | |
| 1126 | + if (m.object == o) | |
| 1127 | + return m; | |
| 1128 | + if (m.count == 0) | |
| 1129 | + z = m; | |
| 1130 | + } | |
| 1131 | + if (z == nil) { | |
| 1132 | + z = ref Monitor; | |
| 1133 | + z.count = 0; | |
| 1134 | + h[0] = z :: h[0]; | |
| 1135 | + } | |
| 1136 | + z.object = o; | |
| 1137 | + return z; | |
| 1138 | +} | |
| 1139 | + | |
| 1140 | +# | |
| 1141 | +# Timer thread. | |
| 1142 | +# | |
| 1143 | +timer(t: int) | |
| 1144 | +{ | |
| 1145 | + s := t - sys->millisec(); | |
| 1146 | + if (s > 0) | |
| 1147 | + sys->sleep(s); | |
| 1148 | + if(monitorctl != nil) | |
| 1149 | + monitorctl <-= (MTIMER, nil, nil, t); | |
| 1150 | +} | |
| 1151 | + | |
| 1152 | +# | |
| 1153 | +# Wait to be interrupted, notified or for timeout to expire. | |
| 1154 | +# | |
| 1155 | +waiter(w: ref Waiter) | |
| 1156 | +{ | |
| 1157 | + w.thread.flags &= ~ThreadData.INTERRUPTED; | |
| 1158 | + s := w.time; | |
| 1159 | + if (s == 0) { | |
| 1160 | + w.next = waiters.next; | |
| 1161 | + waiters.next = w; | |
| 1162 | + } else { | |
| 1163 | + t := sys->millisec(); | |
| 1164 | + w.time += t; | |
| 1165 | + if (sleepers.next == nil) { | |
| 1166 | + sleepers.next = w; | |
| 1167 | + if (s > MAXSLEEP) | |
| 1168 | + s = MAXSLEEP; | |
| 1169 | + timeout = t + s; | |
| 1170 | + spawn timer(timeout); | |
| 1171 | + } else if (w.time >= sleepers.next.time) { | |
| 1172 | + h := sleepers.next; | |
| 1173 | + while (h.next != nil && w.time > h.next.time) | |
| 1174 | + h = h.next; | |
| 1175 | + w.next = h.next; | |
| 1176 | + h.next = w; | |
| 1177 | + } else { | |
| 1178 | + w.next = sleepers.next; | |
| 1179 | + sleepers.next = w; | |
| 1180 | + if (w.time < timeout - SLEEPTOL) { | |
| 1181 | + timeout = w.time; | |
| 1182 | + spawn timer(timeout); | |
| 1183 | + } | |
| 1184 | + } | |
| 1185 | + } | |
| 1186 | +} | |
| 1187 | + | |
| 1188 | +# | |
| 1189 | +# Respond to timer. | |
| 1190 | +# | |
| 1191 | +dotimer(t: int) | |
| 1192 | +{ | |
| 1193 | + c := sys->millisec(); | |
| 1194 | + n := t; | |
| 1195 | + if (t < c) | |
| 1196 | + n = c; | |
| 1197 | + n += SLEEPTOL; | |
| 1198 | + w := sleepers; | |
| 1199 | + while ((l := w.next) != nil && l.time <= n) { | |
| 1200 | + w.next = l.next; | |
| 1201 | + mondone(l, MONOK); | |
| 1202 | + } | |
| 1203 | + if (t == timeout && l != nil) { | |
| 1204 | + timeout = l.time; | |
| 1205 | + if (timeout - c > MAXSLEEP) | |
| 1206 | + timeout = c + MAXSLEEP; | |
| 1207 | + spawn timer(timeout); | |
| 1208 | + } | |
| 1209 | +} | |
| 1210 | + | |
| 1211 | +# | |
| 1212 | +# Notify. | |
| 1213 | +# | |
| 1214 | + | |
| 1215 | +donotifyl(w: ref Waiter, o: ref Object): ref Waiter | |
| 1216 | +{ | |
| 1217 | + while ((l := w.next) != nil) { | |
| 1218 | + if (l.object == o) { | |
| 1219 | + w.next = l.next; | |
| 1220 | + return l; | |
| 1221 | + } | |
| 1222 | + else | |
| 1223 | + w = l; | |
| 1224 | + } | |
| 1225 | + return nil; | |
| 1226 | +} | |
| 1227 | + | |
| 1228 | +donotify(o: ref Object) | |
| 1229 | +{ | |
| 1230 | + if ((l := donotifyl(waiters, o)) != nil || (l = donotifyl(sleepers, o)) != nil) | |
| 1231 | + mondone(l, MONOK); | |
| 1232 | +} | |
| 1233 | + | |
| 1234 | +# | |
| 1235 | +# Notify all. | |
| 1236 | +# | |
| 1237 | + | |
| 1238 | +donotifyalll(w: ref Waiter, o: ref Object) | |
| 1239 | +{ | |
| 1240 | + while ((t := w.next) != nil) { | |
| 1241 | + if (t.object == o) { | |
| 1242 | + w.next = t.next; | |
| 1243 | + mondone(t, MONOK); | |
| 1244 | + } else | |
| 1245 | + w = t; | |
| 1246 | + } | |
| 1247 | +} | |
| 1248 | + | |
| 1249 | +donotifyall(o: ref Object) | |
| 1250 | +{ | |
| 1251 | + donotifyalll(waiters, o); | |
| 1252 | + donotifyalll(sleepers, o); | |
| 1253 | +} | |
| 1254 | + | |
| 1255 | +# | |
| 1256 | +# Interrupt. | |
| 1257 | +# | |
| 1258 | + | |
| 1259 | +dointerruptl(w: ref Waiter, t: ref ThreadData): ref Waiter | |
| 1260 | +{ | |
| 1261 | + while ((l := w.next) != nil) { | |
| 1262 | + if (l.thread == t) { | |
| 1263 | + w.next = l.next; | |
| 1264 | + return l; | |
| 1265 | + } | |
| 1266 | + else | |
| 1267 | + w = l; | |
| 1268 | + } | |
| 1269 | + return nil; | |
| 1270 | +} | |
| 1271 | + | |
| 1272 | +dointerrupt(t: ref ThreadData) | |
| 1273 | +{ | |
| 1274 | + if ((l := dointerruptl(waiters, t)) != nil || (l = dointerruptl(sleepers, t)) != nil) { | |
| 1275 | + l.thread.flags |= ThreadData.INTERRUPTED; | |
| 1276 | + mondone(l, MONINT); | |
| 1277 | + } | |
| 1278 | +} | |
| 1279 | + | |
| 1280 | +# | |
| 1281 | +# Enter or reenter a monitor. | |
| 1282 | +# | |
| 1283 | +doenter(t: ref ThreadData, o: ref Object, n: int, s: int) | |
| 1284 | +{ | |
| 1285 | + m := getmonitor(o); | |
| 1286 | + if (m.count == 0) { | |
| 1287 | + m.thread = t; | |
| 1288 | + m.count = n; | |
| 1289 | + } else if (m.thread == t) | |
| 1290 | + m.count += n; | |
| 1291 | + else { | |
| 1292 | + w := ref Synch; | |
| 1293 | + w.thread = t; | |
| 1294 | + w.count = n; | |
| 1295 | + w.status = s; | |
| 1296 | + if (m.tail == nil) { | |
| 1297 | + m.head = w; | |
| 1298 | + m.tail = w; | |
| 1299 | + } else { | |
| 1300 | + m.tail.next = w; | |
| 1301 | + m.tail = w; | |
| 1302 | + } | |
| 1303 | + return ; | |
| 1304 | + } | |
| 1305 | + for (;;) { | |
| 1306 | + alt { | |
| 1307 | + t.wchan <-= s => | |
| 1308 | + return; | |
| 1309 | + * => | |
| 1310 | + if (t.flags & ThreadData.SUSPENDED) { | |
| 1311 | + t.flags |= ThreadData.ACKSUSP; | |
| 1312 | + return; | |
| 1313 | + } | |
| 1314 | + sys->sleep(0); | |
| 1315 | + } | |
| 1316 | + } | |
| 1317 | +} | |
| 1318 | + | |
| 1319 | +# | |
| 1320 | +# A sleeper or waiter is done. | |
| 1321 | +# | |
| 1322 | +mondone(w: ref Waiter, s: int) | |
| 1323 | +{ | |
| 1324 | + if (w.object != nil) | |
| 1325 | + doenter(w.thread, w.object, w.count, s); | |
| 1326 | + else | |
| 1327 | + w.thread.wchan <-= s; | |
| 1328 | +} | |
| 1329 | + | |
| 1330 | +# | |
| 1331 | +# Concede monitor to next synchronizer. | |
| 1332 | +# | |
| 1333 | +monitornext(m: ref Monitor) | |
| 1334 | +{ | |
| 1335 | + h := m.head; | |
| 1336 | + if (h != nil) { | |
| 1337 | + x := h.next; | |
| 1338 | + m.head = x; | |
| 1339 | + if (x == nil) | |
| 1340 | + m.tail = nil; | |
| 1341 | + m.thread = h.thread; | |
| 1342 | + m.count = h.count; | |
| 1343 | + m.thread.wchan <-= h.status; | |
| 1344 | + } else { | |
| 1345 | + m.thread = nil; | |
| 1346 | + m.object = nil; | |
| 1347 | + m.count = 0; | |
| 1348 | + } | |
| 1349 | +} | |
| 1350 | + | |
| 1351 | +# | |
| 1352 | +# Monitor thread. | |
| 1353 | +# | |
| 1354 | +monitor() | |
| 1355 | +{ | |
| 1356 | + m: ref Monitor; | |
| 1357 | + sleepers = ref Waiter; | |
| 1358 | + waiters = ref Waiter; | |
| 1359 | + for (;;) { | |
| 1360 | + (c, t, o, n) := <- monitorctl; | |
| 1361 | + case c { | |
| 1362 | + MSHUTDOWN => | |
| 1363 | + return; | |
| 1364 | + MSYNC => | |
| 1365 | + sys->sleep(0); | |
| 1366 | + MENTER => | |
| 1367 | + doenter(t, o, n, MONOK); | |
| 1368 | + MEXIT => | |
| 1369 | + m = getmonitor(o); | |
| 1370 | + if (m.count == 0) | |
| 1371 | + raise "mexit inbalance"; #error("mexit inbalance"); | |
| 1372 | + if (m.thread != t) | |
| 1373 | + raise "mexit mismatch"; #error("mexit mismatch"); | |
| 1374 | + m.count--; | |
| 1375 | + if (m.count == 0) | |
| 1376 | + monitornext(m); | |
| 1377 | + MWAIT => | |
| 1378 | + m = getmonitor(o); | |
| 1379 | + if (m.count == 0 || m.thread != t) { | |
| 1380 | + t.wchan <-= MONILL; | |
| 1381 | + break; | |
| 1382 | + } | |
| 1383 | + waiter(ref Waiter(t, o, m.count, n, nil)); | |
| 1384 | + monitornext(m); | |
| 1385 | + MNOTIFY => | |
| 1386 | + m = getmonitor(o); | |
| 1387 | + if (m.count == 0 || m.thread != t) { | |
| 1388 | + t.wchan <-= MONILL; | |
| 1389 | + break; | |
| 1390 | + } | |
| 1391 | + if (n) | |
| 1392 | + donotifyall(o); | |
| 1393 | + else | |
| 1394 | + donotify(o); | |
| 1395 | + t.wchan <-= MONOK; | |
| 1396 | + MSLEEP => | |
| 1397 | + waiter(ref Waiter(t, nil, 0, n, nil)); | |
| 1398 | + MINTERRUPT => | |
| 1399 | + dointerrupt(t); | |
| 1400 | + MTIMER => | |
| 1401 | + dotimer(n); | |
| 1402 | + * => | |
| 1403 | + monitorctl = nil; | |
| 1404 | + raise "bad monitorctl command"; #error("bad monitorctl command"); | |
| 1405 | + } | |
| 1406 | + t = nil; | |
| 1407 | + o = nil; | |
| 1408 | + m = nil; | |
| 1409 | + } | |
| 1410 | +} | |
| 1411 | + | |
| 1412 | +# | |
| 1413 | +# Common resume code. | |
| 1414 | +# | |
| 1415 | +monitorresume(d: ref ThreadData) | |
| 1416 | +{ | |
| 1417 | + case <- d.wchan { | |
| 1418 | + MONILL => | |
| 1419 | + unblock(d); | |
| 1420 | + sthrow("IllegalMonitorStateException"); | |
| 1421 | + MONINT => | |
| 1422 | + unblock(d); | |
| 1423 | + sthrow("InterruptedException"); | |
| 1424 | + } | |
| 1425 | + unblock(d); | |
| 1426 | +} | |
| 1427 | + | |
| 1428 | +# | |
| 1429 | +# Monitor / thread control entries. | |
| 1430 | +# | |
| 1431 | + | |
| 1432 | +monitorenter(o: ref Object) | |
| 1433 | +{ | |
| 1434 | + if ( o == nil ) | |
| 1435 | + sthrow("NullPointerException"); | |
| 1436 | + d := getthreaddata(); | |
| 1437 | + if (monitorctl != nil) { | |
| 1438 | + monitorctl <-= (MENTER, d, o, 1); | |
| 1439 | + <- d.wchan; | |
| 1440 | + } | |
| 1441 | +} | |
| 1442 | + | |
| 1443 | +monitorexit(o: ref Object) | |
| 1444 | +{ | |
| 1445 | + if ( o == nil ) | |
| 1446 | + sthrow("NullPointerException"); | |
| 1447 | + d := getthreaddata(); | |
| 1448 | + if (monitorctl != nil) | |
| 1449 | + monitorctl <-= (MEXIT, d, o, 0); | |
| 1450 | +} | |
| 1451 | + | |
| 1452 | +monitorwait(o: ref Object, l: int) | |
| 1453 | +{ | |
| 1454 | + if ( o == nil ) | |
| 1455 | + sthrow("NullPointerException"); | |
| 1456 | + d := getthreaddata(); | |
| 1457 | + if (monitorctl != nil) { | |
| 1458 | + block(d); | |
| 1459 | + monitorctl <-= (MWAIT, d, o, l); | |
| 1460 | + monitorresume(d); | |
| 1461 | + } | |
| 1462 | +} | |
| 1463 | + | |
| 1464 | +monitornotify(o: ref Object, f: int) | |
| 1465 | +{ | |
| 1466 | + if ( o == nil ) | |
| 1467 | + sthrow("NullPointerException"); | |
| 1468 | + d := getthreaddata(); | |
| 1469 | + if (monitorctl != nil) { | |
| 1470 | + block(d); | |
| 1471 | + monitorctl <-= (MNOTIFY, d, o, f); | |
| 1472 | + monitorresume(d); | |
| 1473 | + } | |
| 1474 | +} | |
| 1475 | + | |
| 1476 | +monsync() | |
| 1477 | +{ | |
| 1478 | + monitorctl <-= (MSYNC, nil, nil, 0); | |
| 1479 | +} | |
| 1480 | + | |
| 1481 | +sleep(l: int) | |
| 1482 | +{ | |
| 1483 | + if (l <= 100) { | |
| 1484 | + sys->sleep(l); | |
| 1485 | + return; | |
| 1486 | + } | |
| 1487 | + d := getthreaddata(); | |
| 1488 | + if (monitorctl != nil) { | |
| 1489 | + block(d); | |
| 1490 | + monitorctl <-= (MSLEEP, d, nil, l); | |
| 1491 | + monitorresume(d); | |
| 1492 | + } | |
| 1493 | +} | |
| 1494 | + | |
| 1495 | +interrupt(t: ref ThreadData) | |
| 1496 | +{ | |
| 1497 | + d := getthreaddata(); | |
| 1498 | + if (monitorctl != nil) { | |
| 1499 | + block(d); | |
| 1500 | + monitorctl <-= (MINTERRUPT, t, nil, 0); | |
| 1501 | + unblock(d); | |
| 1502 | + } | |
| 1503 | +} | |
| 1504 | + | |
| 1505 | +# | |
| 1506 | +# Runtime hierarchy/type check routines. | |
| 1507 | +# | |
| 1508 | + | |
| 1509 | +compatclass(who, what: ref Class): int | |
| 1510 | +{ | |
| 1511 | + if ((what.flags & ACC_INTERFACE) && (who.flags & ACC_INTERFACE) == 0) | |
| 1512 | + return who.getinterface(what) != nil; | |
| 1513 | + do { | |
| 1514 | + if (who == what) | |
| 1515 | + return 1; | |
| 1516 | + who = who.super; | |
| 1517 | + } while (who != nil); | |
| 1518 | + return 0; | |
| 1519 | +} | |
| 1520 | + | |
| 1521 | +checkcast(who: ref Object, what: ref Class) | |
| 1522 | +{ | |
| 1523 | + if (who != nil && !instanceof(who, what)) | |
| 1524 | + sthrow("ClassCastException"); | |
| 1525 | +} | |
| 1526 | + | |
| 1527 | +instanceof(who: ref Object, what: ref Class): int | |
| 1528 | +{ | |
| 1529 | + if (who == nil) | |
| 1530 | + return 0; | |
| 1531 | + return compatclass(who.class(), what); | |
| 1532 | +} | |
| 1533 | + | |
| 1534 | +acheckcast(who: ref Array, what: ref Class, dims: int) | |
| 1535 | +{ | |
| 1536 | + if (who != nil && !ainstanceof(who, what, dims)) | |
| 1537 | + sthrow("ClassCastException"); | |
| 1538 | +} | |
| 1539 | + | |
| 1540 | +ainstanceof(who: ref Array, what: ref Class, dims: int): int | |
| 1541 | +{ | |
| 1542 | + if (who == nil) | |
| 1543 | + return 0; | |
| 1544 | + if (arrayclass == nil) | |
| 1545 | + loadarrayclass(); | |
| 1546 | + if (who.mod != arraymd) | |
| 1547 | + return 0; | |
| 1548 | + # is 'what' Object[]... ? | |
| 1549 | + if (who.dims > dims && what.super == nil && (what.flags & ACC_INTERFACE) == 0) | |
| 1550 | + return 1; | |
| 1551 | + if (who.dims != dims || who.class == nil) | |
| 1552 | + return 0; | |
| 1553 | + return compatclass(who.class, what); | |
| 1554 | +} | |
| 1555 | + | |
| 1556 | +pcheckcast(who: ref Array, what, dims: int) | |
| 1557 | +{ | |
| 1558 | + if (who != nil && !pinstanceof(who, what, dims)) | |
| 1559 | + sthrow("ClassCastException"); | |
| 1560 | +} | |
| 1561 | + | |
| 1562 | +pinstanceof(who: ref Array, what, dims: int): int | |
| 1563 | +{ | |
| 1564 | + if (who == nil) | |
| 1565 | + return 0; | |
| 1566 | + if (arrayclass == nil) | |
| 1567 | + loadarrayclass(); | |
| 1568 | + if (who.mod != arraymd || who.dims != dims || who.class != nil) | |
| 1569 | + return 0; | |
| 1570 | + return who.primitive == what; | |
| 1571 | +} | |
| 1572 | + | |
| 1573 | +aastoreinstanceof(who: ref Object, what: ref Array): int | |
| 1574 | +{ | |
| 1575 | + if (arrayclass == nil) | |
| 1576 | + loadarrayclass(); | |
| 1577 | + if (what.mod != arraymd) | |
| 1578 | + return 0; | |
| 1579 | + if (what.dims == 1) { | |
| 1580 | + if (what.class == nil) | |
| 1581 | + return 0; | |
| 1582 | + if (who == nil) | |
| 1583 | + return 1; | |
| 1584 | + return compatclass(who.class(), what.class); | |
| 1585 | + } else { | |
| 1586 | + if (who == nil) | |
| 1587 | + return 1; | |
| 1588 | + if (who.class() != arrayclass) | |
| 1589 | + return 0; | |
| 1590 | + a := arrayof(who); | |
| 1591 | + if (a.dims != what.dims - 1) | |
| 1592 | + return 0; | |
| 1593 | + if (a.class == nil) | |
| 1594 | + return what.class == nil && a.primitive == what.primitive; | |
| 1595 | + if (what.class == nil) | |
| 1596 | + return 0; | |
| 1597 | + return compatclass(a.class, what.class); | |
| 1598 | + } | |
| 1599 | +} | |
| 1600 | + | |
| 1601 | +aastorecheck(who: ref Object, what: ref Array) | |
| 1602 | +{ | |
| 1603 | + if (what == nil) | |
| 1604 | + sthrow("NullPointerException"); | |
| 1605 | + if (!aastoreinstanceof(who, what)) | |
| 1606 | + sthrow("ArrayStoreException"); | |
| 1607 | +} | |
| 1608 | + | |
| 1609 | +multianewarray(ndim: int, c: ref Class, etype: int, bounds: array of int): ref Array | |
| 1610 | +{ | |
| 1611 | + n := bounds[0]; | |
| 1612 | + if (n < 0) | |
| 1613 | + sthrow("NegativeArraySizeException"); | |
| 1614 | + if (arrayclass == nil) | |
| 1615 | + loadarrayclass(); | |
| 1616 | + a := ref Array(arraymd, nil, ndim, c, etype); | |
| 1617 | + if (etype == 0 || ndim > 1) | |
| 1618 | + a.holder = array[n] of ref JavaString; | |
| 1619 | + else { | |
| 1620 | + case etype { | |
| 1621 | + T_BOOLEAN or T_BYTE => | |
| 1622 | + a.holder = bytearraytoJS(array[n] of byte); | |
| 1623 | + T_CHAR or T_SHORT or T_INT => | |
| 1624 | + a.holder = intarraytoJS(array[n] of int); | |
| 1625 | + T_LONG => | |
| 1626 | + a.holder = bigarraytoJS(array[n] of big); | |
| 1627 | + T_FLOAT or T_DOUBLE => | |
| 1628 | + a.holder = realarraytoJS(array[n] of real); | |
| 1629 | + } | |
| 1630 | + } | |
| 1631 | + if (len bounds > 1) { | |
| 1632 | + for (i := 0; i < n; i++) | |
| 1633 | + a.holder[i] = ArraytoJS(multianewarray(ndim - 1, c, etype, bounds[1:])); | |
| 1634 | + } | |
| 1635 | + return a; | |
| 1636 | +} | |
| 1637 | + | |
| 1638 | +arraycopy(src: ref Array, sx: int, dst: ref Array, dx: int, n: int) | |
| 1639 | +{ | |
| 1640 | + if (arrayclass == nil) | |
| 1641 | + loadarrayclass(); | |
| 1642 | + if (src == nil || dst == nil) | |
| 1643 | + sthrow("NullPointerException"); | |
| 1644 | + if (src.mod != arraymd || dst.mod != arraymd) | |
| 1645 | + sthrow("ArrayStoreException"); | |
| 1646 | + sa := src.holder; | |
| 1647 | + if (src.dims == dst.dims) { | |
| 1648 | + if (src.class == nil) { | |
| 1649 | + if (dst.class != nil || src.primitive != dst.primitive) | |
| 1650 | + sthrow("ArrayStoreException"); | |
| 1651 | + } else { | |
| 1652 | + if (dst.class == nil) | |
| 1653 | + sthrow("ArrayStoreException"); | |
| 1654 | + if (src.class != dst.class && !compatclass(src.class, dst.class)) | |
| 1655 | + for (i := 0; i < n; i++) | |
| 1656 | + if (!aastoreinstanceof(JStoObject(sa[sx + i]), dst)) | |
| 1657 | + sthrow("ArrayStoreException"); | |
| 1658 | + } | |
| 1659 | + } else if (dst.class == nil || dst.class.super != nil || dst.dims > src.dims) | |
| 1660 | + sthrow("ArrayStoreException"); | |
| 1661 | + if (sx < 0 || dx < 0 || n < 0 || sx + n > len src.holder || dx + n > len dst.holder || sx > 2147483647 - n || dx > 2147483647 - n) | |
| 1662 | + sthrow("ArrayIndexOutOfBoundsException"); | |
| 1663 | + dst.holder[dx:] = sa[sx:sx + n]; | |
| 1664 | +} | |
| 1665 | + | |
| 1666 | +# | |
| 1667 | +# Map a class and a interface cookie to a methodtable entry. | |
| 1668 | +# | |
| 1669 | +getinterface(c: ref Class, cookie: int) : int | |
| 1670 | +{ | |
| 1671 | + x := cookie >> 16; | |
| 1672 | + t := cookie & 16rFFFF; | |
| 1673 | + if (x >= ninterfaces) | |
| 1674 | + error("bad interface number"); | |
| 1675 | + k := interfaces[x]; | |
| 1676 | + m := c.getinterface(k); | |
| 1677 | + if (m == nil) | |
| 1678 | + error(sys->sprint("class %s does not implement interface %s", c.name, k.name)); | |
| 1679 | + if (t >= len m) | |
| 1680 | + error("bad interface index"); | |
| 1681 | + return m[t]; | |
| 1682 | +} | |
| 1683 | + | |
| 1684 | +# | |
| 1685 | +# Math. | |
| 1686 | +# | |
| 1687 | + | |
| 1688 | +lcmp(x, y: big): int | |
| 1689 | +{ | |
| 1690 | + if(x < y) | |
| 1691 | + return -1; | |
| 1692 | + if(x == y) | |
| 1693 | + return 0; | |
| 1694 | + return 1; | |
| 1695 | +} | |
| 1696 | + | |
| 1697 | +truncate(x: real): real | |
| 1698 | +{ | |
| 1699 | + if (x < 0.0) | |
| 1700 | + x = math->ceil(x); | |
| 1701 | + else | |
| 1702 | + x = math->floor(x); | |
| 1703 | + return x; | |
| 1704 | +} | |
| 1705 | + | |
| 1706 | +d2i(x: real): int | |
| 1707 | +{ | |
| 1708 | + return int truncate(x); | |
| 1709 | +} | |
| 1710 | + | |
| 1711 | +d2l(x: real): big | |
| 1712 | +{ | |
| 1713 | + return big truncate(x); | |
| 1714 | +} | |
| 1715 | + | |
| 1716 | +dcmpg(x, y: real): int | |
| 1717 | +{ | |
| 1718 | + if (math->isnan(x) || math->isnan(y) || x > y) | |
| 1719 | + return 1; | |
| 1720 | + if (x == y) | |
| 1721 | + return 0; | |
| 1722 | + return -1; | |
| 1723 | +} | |
| 1724 | + | |
| 1725 | +dcmpl(x, y: real): int | |
| 1726 | +{ | |
| 1727 | + if (math->isnan(x) || math->isnan(y) || x < y) | |
| 1728 | + return -1; | |
| 1729 | + if (x == y) | |
| 1730 | + return 0; | |
| 1731 | + return 1; | |
| 1732 | +} | |
| 1733 | + | |
| 1734 | +drem(x, y: real): real | |
| 1735 | +{ | |
| 1736 | + if (math->isnan(x) || math->isnan(y) || !math->finite(x) || y == 0.0) | |
| 1737 | + return math->NaN; | |
| 1738 | + if ((math->finite(x) && !math->finite(y)) || (x == 0.0 && math->finite(y))) | |
| 1739 | + return x; | |
| 1740 | + return math->fmod(x, y); | |
| 1741 | +} | |
| 1742 | + | |
| 1743 | +# | |
| 1744 | +# Class entries. | |
| 1745 | +# | |
| 1746 | + | |
| 1747 | +Class.run(c: self ref Class, args: list of string) | |
| 1748 | +{ | |
| 1749 | + m := c.findsmethod(MAINFIELD, MAINSIGNATURE); | |
| 1750 | + if (m == nil) | |
| 1751 | + loaderror( nosuchmethod, sys->sprint("%s: missing static method main", c.name)); | |
| 1752 | + main = c; | |
| 1753 | + if (arrayclass == nil) | |
| 1754 | + loadarrayclass(); | |
| 1755 | + if (stringclass == nil) | |
| 1756 | + loadstringclass(); | |
| 1757 | + n := len args; | |
| 1758 | + h := array[n] of ref JavaString; | |
| 1759 | + d := stringclass.moddata; | |
| 1760 | + for (i := 0; i < n; i++) { | |
| 1761 | + h[i] = ref JavaString(d, hd args); | |
| 1762 | + args = tl args; | |
| 1763 | + } | |
| 1764 | + #c.xeq(m.value, ref Array(arraymd, h, 1, stringclass, 0)); | |
| 1765 | + getthreaddata(); | |
| 1766 | + r := jassist->mcalla(c.mod, m.value, ref Array(arraymd, h, 1, stringclass, 0)); | |
| 1767 | + delthreaddata(); | |
| 1768 | +} | |
| 1769 | + | |
| 1770 | + | |
| 1771 | +Class.new(c: self ref Class): ref Object | |
| 1772 | +{ | |
| 1773 | + o := jassist->new(c.mod, c.objtype); | |
| 1774 | + o.mod = c.moddata; | |
| 1775 | + f := findasig(c.initmethods, VOIDSIGNATURE); | |
| 1776 | + if (f == nil) | |
| 1777 | + error(sys->sprint("%s: %s: missing constructor", nosuchmethod, c.name)); | |
| 1778 | + c.call(f.value, o); | |
| 1779 | + return o; | |
| 1780 | +} | |
| 1781 | + | |
| 1782 | +Class.call(c: self ref Class, x: int, a: ref Object): ref Object | |
| 1783 | +{ | |
| 1784 | + if (x < 0 || x >= c.mlinks) | |
| 1785 | + raise badcallindex; | |
| 1786 | + return jassist->mcall1(c.mod, x, a); | |
| 1787 | +} | |
| 1788 | + | |
| 1789 | +Class.clone(c: self ref Class, o: ref Object): ref Object | |
| 1790 | +{ | |
| 1791 | + if (c.cloneindex < 0) | |
| 1792 | + raise nocloneindex; | |
| 1793 | + return jassist->mcall1(c.mod, c.cloneindex, o); | |
| 1794 | +} | |
| 1795 | + | |
| 1796 | +# | |
| 1797 | +# Class private methods. | |
| 1798 | +# | |
| 1799 | + | |
| 1800 | +# | |
| 1801 | +# Load a class file. | |
| 1802 | +# | |
| 1803 | +Class.loadclass(c: self ref Class) | |
| 1804 | +{ | |
| 1805 | + c.encoding = encodename(c.name); | |
| 1806 | + f := c.encoding + ".dis"; | |
| 1807 | + m := load Nilmod f; | |
| 1808 | + if (m == nil) { | |
| 1809 | + e := sys->sprint("%r"); | |
| 1810 | + if (!matches(e, EXIST)) | |
| 1811 | + error(f + ": " + e); | |
| 1812 | + f = ROOT + f; | |
| 1813 | + m = load Nilmod f; | |
| 1814 | + if (m == nil) { | |
| 1815 | + e = sys->sprint("%r"); | |
| 1816 | + m : string; | |
| 1817 | + if (!matches(e, EXIST)) | |
| 1818 | + m = f + ": " + e; | |
| 1819 | + else | |
| 1820 | + m = c.name + ": class not found"; | |
| 1821 | + loaderror(noclassdeffound, m); | |
| 1822 | + } | |
| 1823 | + } | |
| 1824 | + trace(JDEBUG, sys->sprint("\"%s\"", f)); | |
| 1825 | + c.file = f; | |
| 1826 | + c.mod = m; | |
| 1827 | + if (getint(m, MAGIC) != JAVA) | |
| 1828 | + loaderror(classformat, f + ": bad magic number"); | |
| 1829 | + c.version = getint(m, VERSION) & 16rFF; | |
| 1830 | + if (c.version != SUXV) | |
| 1831 | + loaderror(classformat, f + ": incompatible version (rerun j2d)"); | |
| 1832 | + c.ownname = getstring(m, NAME); | |
| 1833 | + if (c.ownname != c.name && encodename(c.ownname) != c.name) | |
| 1834 | + warning("class file " + f + ": inconsistent classname: " + c.ownname); | |
| 1835 | +} | |
| 1836 | + | |
| 1837 | +# | |
| 1838 | +# The bulk of the work for loading a class is done here. | |
| 1839 | +# This is the essentially the first (resolution) pass. | |
| 1840 | +# | |
| 1841 | +Class.resolve(c: self ref Class) | |
| 1842 | +{ | |
| 1843 | + od, vm, pm, sd, sm, im: list of ref Field; | |
| 1844 | + oz, vz, sz: int; | |
| 1845 | + cur = c.name; | |
| 1846 | + c.info.links = ld->link(c.mod); | |
| 1847 | + if (c.info.links == nil) | |
| 1848 | + error(sys->sprint("link failed: %r")); | |
| 1849 | + c.mlinks = len c.info.links; | |
| 1850 | + c.info.types = ld->tdesc(c.mod); | |
| 1851 | + if (c.info.types == nil) | |
| 1852 | + error(sys->sprint("tdesc failed: %r")); | |
| 1853 | + c.objtype = len c.info.types; | |
| 1854 | + c.cloneindex = -1; | |
| 1855 | + if (c.super != nil) { | |
| 1856 | + od = c.super.objectdata; | |
| 1857 | + vz = len c.super.virtualmethods; | |
| 1858 | + oz = c.super.objectsize; | |
| 1859 | + } else { | |
| 1860 | + od = nil; | |
| 1861 | + vz = 0; | |
| 1862 | + oz = WORDZ; | |
| 1863 | + } | |
| 1864 | + vm = nil; | |
| 1865 | + pm = nil; | |
| 1866 | + sd = nil; | |
| 1867 | + sm = nil; | |
| 1868 | + im = nil; | |
| 1869 | + sz = 0; | |
| 1870 | + r := getreloc(c.mod, RELOC); | |
| 1871 | + n := len r; | |
| 1872 | + p := array[n] of Patch; | |
| 1873 | + e := 0; | |
| 1874 | + for (i := 0; i < n; i++) { | |
| 1875 | + s := r[i].field; | |
| 1876 | + if (s[0] != '@') | |
| 1877 | + break; | |
| 1878 | + case s { | |
| 1879 | + CLASS => | |
| 1880 | + p[i].what = PVALUE; | |
| 1881 | + p[i].value = c.objtype; | |
| 1882 | + c.flags = r[i].flags; | |
| 1883 | + MP or NP or ADT or OBJ => | |
| 1884 | + p[i].what = PEXTRA; | |
| 1885 | + p[i].value = e++; | |
| 1886 | + JEX => | |
| 1887 | + error("@jex not in @Loader"); | |
| 1888 | + SYS => | |
| 1889 | + error("@sys not in @Loader"); | |
| 1890 | + } | |
| 1891 | + } | |
| 1892 | + for (; i < n; i++) { | |
| 1893 | + t := r[i]; | |
| 1894 | + if (isdata(t.signature)) { | |
| 1895 | + if (isspecial(t.field)) | |
| 1896 | + error(sys->sprint("unknown special data: %s", t.field)); | |
| 1897 | + else if (isstatic(t.flags)) { | |
| 1898 | + trace(JDEBUG, sys->sprint("%s: static data", t.field)); | |
| 1899 | + sz = alignto(sz, t.signature); | |
| 1900 | + p[i].what = PSTATIC; | |
| 1901 | + p[i].value = sz; | |
| 1902 | + f := ref Field(t.field, t.signature, t.flags, sz); | |
| 1903 | + sz += sizeof(t.signature); | |
| 1904 | + sd = f :: sd; | |
| 1905 | + } else { | |
| 1906 | + trace(JDEBUG, sys->sprint("%s: new data", t.field)); | |
| 1907 | + oz = alignto(oz, t.signature); | |
| 1908 | + p[i].what = PVALUE; | |
| 1909 | + p[i].value = oz; | |
| 1910 | + f := ref Field(t.field, t.signature, t.flags, oz); | |
| 1911 | + od = f :: od; | |
| 1912 | + oz += sizeof(t.signature); | |
| 1913 | + } | |
| 1914 | + } else { | |
| 1915 | + if (isspecial(t.field)) { | |
| 1916 | + s := t.field; | |
| 1917 | + case s { | |
| 1918 | + SPECIALINIT => | |
| 1919 | + if (isstatic(t.flags)) | |
| 1920 | + error("<init> static"); | |
| 1921 | + x := c.getmethod(s, t.signature, t.flags); | |
| 1922 | + if (t.flags & Rspecialmp) { | |
| 1923 | + p[i].what = PEXTRA; | |
| 1924 | + p[i].value = e++; | |
| 1925 | + } else { | |
| 1926 | + p[i].what = PVALUE; | |
| 1927 | + p[i].value = x; | |
| 1928 | + } | |
| 1929 | + if (findsig(im, t.signature) == nil) | |
| 1930 | + im = ref Field(s, t.signature, t.flags, x) :: im; | |
| 1931 | + SPECIALCLINIT or SPECIALCLONE => | |
| 1932 | + if (!isstatic(t.flags)) | |
| 1933 | + error(s + " not static"); | |
| 1934 | + if (t.patch != nil) | |
| 1935 | + error(s + " patches"); | |
| 1936 | + if (t.signature != VOIDSIGNATURE) | |
| 1937 | + error(s + " bad signature"); | |
| 1938 | + if (isnative(t.flags)) | |
| 1939 | + error(s + " is native"); | |
| 1940 | + x := c.getmethod(s, t.signature, t.flags); | |
| 1941 | + if (s == SPECIALCLINIT) | |
| 1942 | + c.classinit = ref Field(s, t.signature, t.flags, x); | |
| 1943 | + else | |
| 1944 | + c.cloneindex = x; | |
| 1945 | + p[i].what = PVALUE; | |
| 1946 | + p[i].value = x; | |
| 1947 | + * => | |
| 1948 | + error(sys->sprint("unknown special: %s", s)); | |
| 1949 | + } | |
| 1950 | + } else if (isvirtual(t.flags)) { | |
| 1951 | + f := findfs(vm, t.field, t.signature); | |
| 1952 | + if (f == nil) { | |
| 1953 | + x := c.override(t.field, t.signature); | |
| 1954 | + if (x < 0) { | |
| 1955 | + trace(JDEBUG, sys->sprint("%s: new method", t.field)); | |
| 1956 | + x = vz++; | |
| 1957 | + } else { | |
| 1958 | + trace(JDEBUG, sys->sprint("%s: overriden method", t.field)); | |
| 1959 | + } | |
| 1960 | + f = ref Field(t.field, t.signature, t.flags, x); | |
| 1961 | + vm = f :: vm; | |
| 1962 | + } | |
| 1963 | + if (t.flags & Rspecialmp) { | |
| 1964 | + p[i].what = PVALUE; | |
| 1965 | + p[i].value = e++; | |
| 1966 | + } else { | |
| 1967 | + p[i].what = PMETHOD; | |
| 1968 | + p[i].value = f.value; | |
| 1969 | + } | |
| 1970 | + } else { | |
| 1971 | + trace(JDEBUG, sys->sprint("%s: static method", t.field)); | |
| 1972 | + x := c.getmethod(t.field, t.signature, t.flags); | |
| 1973 | + f := ref Field(t.field, t.signature, t.flags, x); | |
| 1974 | + p[i].what = PVALUE; | |
| 1975 | + p[i].value = x; | |
| 1976 | + if (isstatic(t.flags)) { | |
| 1977 | + trace(JDEBUG, sys->sprint("%s: static method", t.field)); | |
| 1978 | + sm = f :: sm; | |
| 1979 | + } else { | |
| 1980 | + trace(JDEBUG, sys->sprint("%s: private method", t.field)); | |
| 1981 | + pm = f :: pm; | |
| 1982 | + } | |
| 1983 | + } | |
| 1984 | + } | |
| 1985 | + } | |
| 1986 | + if (c.flags & ACC_INTERFACE) | |
| 1987 | + c.addinterface(); | |
| 1988 | + c.info.reloc = p; | |
| 1989 | + c.objectdata = od; | |
| 1990 | + c.virtualmethods = c.makevmtable(vm, vz); | |
| 1991 | + c.staticdata = mkfdarray(sd); | |
| 1992 | + c.staticmethods = mkfdarray(sm); | |
| 1993 | + c.privatemethods = mkfdarray(pm); | |
| 1994 | + c.initmethods = mkfdarray(im); | |
| 1995 | + c.objectsize = alignto(oz, nil); | |
| 1996 | + c.staticsize = alignto(sz, nil); | |
| 1997 | + c.info.extrabase = e; | |
| 1998 | + cur = nil; | |
| 1999 | +} | |
| 2000 | + | |
| 2001 | +# | |
| 2002 | +# Make a type for a class object. | |
| 2003 | +# | |
| 2004 | +Class.makeobjtype(c: self ref Class) | |
| 2005 | +{ | |
| 2006 | + z := ((c.objectsize / WORDZ) + 7) / 8; | |
| 2007 | + m := array[z] of byte; | |
| 2008 | + m[0] = byte 16r80; | |
| 2009 | + for (i := 1; i < z; i++) | |
| 2010 | + m[i] = byte 0; | |
| 2011 | + for (l := c.objectdata; l != nil; l = tl l) { | |
| 2012 | + f := hd l; | |
| 2013 | + if (ispointer(f.signature)) { | |
| 2014 | + v := f.value / WORDZ; | |
| 2015 | + x := v / 8; | |
| 2016 | + m[x] = byte ((int m[x]) | bits[v & 7]); | |
| 2017 | + } | |
| 2018 | + } | |
| 2019 | + c.objmap = m; | |
| 2020 | + if (ld->tnew(c.mod, c.objectsize, c.objmap) != c.objtype) | |
| 2021 | + error("objtype mismatch"); | |
| 2022 | +} | |
| 2023 | + | |
| 2024 | +# | |
| 2025 | +# Make a virtual method table from that of the superclass | |
| 2026 | +# and the overriden and new entries. | |
| 2027 | +# | |
| 2028 | +Class.makevmtable(c: self ref Class, m: list of ref Field, z: int): array of Method | |
| 2029 | +{ | |
| 2030 | + t := array[z] of Method; | |
| 2031 | + if (c.super != nil) { | |
| 2032 | + s := c.super.virtualmethods; | |
| 2033 | + n := len s; | |
| 2034 | + for (i := 0; i < n; i++) | |
| 2035 | + t[i] = s[i]; | |
| 2036 | + } | |
| 2037 | + while (m != nil) { | |
| 2038 | + f := hd m; | |
| 2039 | + n := f.value; | |
| 2040 | + # TODO: check if we don't have this method in links, so just use parent class's one | |
| 2041 | + trace(JDEBUG, sys->sprint("Makevmtable for %s, %d", c.name, z)); | |
| 2042 | + { | |
| 2043 | + f.value = c.getmethod(f.field, f.signature, f.flags); | |
| 2044 | + } | |
| 2045 | + exception e { | |
| 2046 | + JCLDREX + nosuchmethod + "*" => | |
| 2047 | + ; # silently ignore | |
| 2048 | + } | |
| 2049 | + t[n].field = f; | |
| 2050 | + t[n].class = c; | |
| 2051 | + m = tl m; | |
| 2052 | + } | |
| 2053 | + return t; | |
| 2054 | +} | |
| 2055 | + | |
| 2056 | +# | |
| 2057 | +# Load the interfaces implemented by a class. | |
| 2058 | +# | |
| 2059 | +Class.loadinterfaces(c: self ref Class) | |
| 2060 | +{ | |
| 2061 | + s := getstrarray(c.mod, INTERFACES); | |
| 2062 | + if (s == nil) | |
| 2063 | + return; | |
| 2064 | + n := len s; | |
| 2065 | + trace(JDEBUG, sys->sprint("inter %s %d", c.name, n)); | |
| 2066 | + l: list of ref Class; | |
| 2067 | + for (i := 0; i < n; i++) | |
| 2068 | + l = loadhierarchy(s[i]) :: l; | |
| 2069 | + c.interextends = l; | |
| 2070 | + if (c.flags & ACC_INTERFACE) { | |
| 2071 | + c.flags |= JCL_INTEREXT; | |
| 2072 | + interfx = c :: interfx; | |
| 2073 | + } else | |
| 2074 | + interf = c :: interf; | |
| 2075 | +} | |
| 2076 | + | |
| 2077 | +# | |
| 2078 | +# Add a class to a list. | |
| 2079 | +# | |
| 2080 | +addclass(c: ref Class, n: list of ref Class): list of ref Class | |
| 2081 | +{ | |
| 2082 | + for (l := n; l != nil; l = tl l) | |
| 2083 | + if (hd l == c) | |
| 2084 | + return n; | |
| 2085 | + return c :: n; | |
| 2086 | +} | |
| 2087 | + | |
| 2088 | +# | |
| 2089 | +# Extend list of interfaces. | |
| 2090 | +# | |
| 2091 | +interext(l: list of ref Class): list of ref Class | |
| 2092 | +{ | |
| 2093 | + n: list of ref Class; | |
| 2094 | + while (l != nil) { | |
| 2095 | + c := hd l; | |
| 2096 | + n = addclass(c, n); | |
| 2097 | + for (x := c.interextends; x != nil; x = tl x) | |
| 2098 | + n = addclass(hd x, n); | |
| 2099 | + l = tl l; | |
| 2100 | + } | |
| 2101 | + return n; | |
| 2102 | +} | |
| 2103 | + | |
| 2104 | +# | |
| 2105 | +# Extend (transitively) an interface. | |
| 2106 | +# | |
| 2107 | +intertrans(c: ref Class, n: list of ref Class): list of ref Class | |
| 2108 | +{ | |
| 2109 | + if (c.flags & JCL_INTERWORK) | |
| 2110 | + error("circular interface extension"); #ClassCircularityError ?? | |
| 2111 | + n = addclass(c, n); | |
| 2112 | + c.extinterfaces(); | |
| 2113 | + for (l := c.interextends; l != nil; l = tl l) | |
| 2114 | + n = addclass(hd l, n); | |
| 2115 | + return n; | |
| 2116 | +} | |
| 2117 | + | |
| 2118 | +# | |
| 2119 | +# Extend interfaces. | |
| 2120 | +# | |
| 2121 | +Class.extinterfaces(c: self ref Class) | |
| 2122 | +{ | |
| 2123 | + if ((c.flags & JCL_INTEREXT) == 0) | |
| 2124 | + return; | |
| 2125 | + c.flags |= JCL_INTERWORK; | |
| 2126 | + n: list of ref Class; | |
| 2127 | + for (l := c.interextends; l != nil; l = tl l) | |
| 2128 | + n = intertrans(hd l, n); | |
| 2129 | + c.interextends = n; | |
| 2130 | + c.flags &= ~(JCL_INTEREXT | JCL_INTERWORK); | |
| 2131 | +} | |
| 2132 | + | |
| 2133 | +# | |
| 2134 | +# Resolve the implementation of a class' interfaces. | |
| 2135 | +# | |
| 2136 | +Class.linkinterfaces(c: self ref Class) | |
| 2137 | +{ | |
| 2138 | + cur = c.name; | |
| 2139 | + l := interext(c.interextends); | |
| 2140 | + n := len l; | |
| 2141 | + a := array[n] of Interface; | |
| 2142 | + c.interfaces = a; | |
| 2143 | + for (i := 0; i < n; i++) { | |
| 2144 | + s := hd l; | |
| 2145 | + l = tl l; | |
| 2146 | + a[i].class = s; | |
| 2147 | + if ((s.flags & ACC_INTERFACE) == 0) | |
| 2148 | + loaderror(linkageerr, sys->sprint("%s not an interface", s.name)); | |
| 2149 | + v := s.virtualmethods; | |
| 2150 | + m := len v; | |
| 2151 | + o := array[m] of int; | |
| 2152 | + a[i].methods = o; | |
| 2153 | + for (j := 0; j < m; j++) { | |
| 2154 | + f := v[j].field; | |
| 2155 | + x := findmfsx(c.virtualmethods, f.field, f.signature); | |
| 2156 | + if (x < 0) | |
| 2157 | + loaderror( nosuchmethod, sys->sprint("method %s'%s' of interface %s not implemented", | |
| 2158 | + f.field, f.signature, s.name)); | |
| 2159 | + else | |
| 2160 | + o[j] = (METHODOFFSET + x * 2) * WORDZ; | |
| 2161 | + } | |
| 2162 | + } | |
| 2163 | + cur = nil; | |
| 2164 | +} | |
| 2165 | + | |
| 2166 | +# | |
| 2167 | +# This is the second pass of class loading. All classes needed for | |
| 2168 | +# relocation have been resolved. | |
| 2169 | +# | |
| 2170 | +Class.relocate(c: self ref Class) | |
| 2171 | +{ | |
| 2172 | + cur = c.name; | |
| 2173 | + trace(JDEBUG, sys->sprint("relocate(%s) enter", c.name)); | |
| 2174 | + # | |
| 2175 | + # Count extra entries (e.g. @mp and @adt). | |
| 2176 | + # | |
| 2177 | + n := nextra(getreloc(c.mod, RELOC)); | |
| 2178 | + i := CLASSREF; | |
| 2179 | + while ((s := getstring(c.mod, i)) != nil) { | |
| 2180 | + n += nextra(getreloc(c.mod, i + WORDZ)); | |
| 2181 | + i += 2 * WORDZ; | |
| 2182 | + } | |
| 2183 | + c.dataoffset = (i + 4 + 31) & ~31; | |
| 2184 | + c.nextra = n; | |
| 2185 | + # | |
| 2186 | + # Record extras. | |
| 2187 | + # | |
| 2188 | + c.info.extras = array[n] of Extra; | |
| 2189 | + n = c.extras(getreloc(c.mod, RELOC), 0, c); | |
| 2190 | + j := 0; | |
| 2191 | + i = CLASSREF; | |
| 2192 | + while ((s = getstring(c.mod, i)) != nil) { | |
| 2193 | + n = c.extras(getreloc(c.mod, i + WORDZ), n, c.refs[j]); | |
| 2194 | + i += 2 * WORDZ; | |
| 2195 | + j++; | |
| 2196 | + } | |
| 2197 | + # | |
| 2198 | + # Determine size of new module data. | |
| 2199 | + # | |
| 2200 | + v := len c.virtualmethods; | |
| 2201 | + z := METHODOFFSET * WORDZ + v * 2 * WORDZ + c.staticsize + c.nextra * WORDZ + WORDZ; | |
| 2202 | + c.datareloc = (z + 31) & ~31; | |
| 2203 | + c.datasize = getint(c.mod, DSIZE); | |
| 2204 | + c.modsize = c.datareloc + c.datasize; | |
| 2205 | + z = ((c.modsize / WORDZ) + 7) / 8; | |
| 2206 | + m := array[z] of byte; | |
| 2207 | + # | |
| 2208 | + # Create type map for module. | |
| 2209 | + # | |
| 2210 | + c.modmap = m; | |
| 2211 | + # | |
| 2212 | + # First two entries are nil and ref Class adt. | |
| 2213 | + # | |
| 2214 | + m[0] = byte 16rC0; | |
| 2215 | + for (i = 1; i < z; i++) | |
| 2216 | + m[i] = byte 0; | |
| 2217 | + # | |
| 2218 | + # Method table. | |
| 2219 | + # | |
| 2220 | + for (i = 1; i <= v; i++) { | |
| 2221 | + x := i / 4; | |
| 2222 | + m[x] = byte ((int m[x]) | mbits[i & 3]); | |
| 2223 | + } | |
| 2224 | + o := METHODOFFSET + v * 2; | |
| 2225 | + # | |
| 2226 | + # Static data. | |
| 2227 | + # | |
| 2228 | + c.staticoffset = o * WORDZ; | |
| 2229 | + d := c.staticdata; | |
| 2230 | + for (i = 0; i < len d; i++) { | |
| 2231 | + f := d[i]; | |
| 2232 | + if (ispointer(f.signature)) { | |
| 2233 | + w := o + (f.value / WORDZ); | |
| 2234 | + x := w / 8; | |
| 2235 | + m[x] = byte ((int m[x]) | bits[w & 7]); | |
| 2236 | + } | |
| 2237 | + } | |
| 2238 | + o += c.staticsize / WORDZ; | |
| 2239 | + # | |
| 2240 | + # Extra data. | |
| 2241 | + # | |
| 2242 | + c.info.extraoffset = o * WORDZ; | |
| 2243 | + for (i = 0; i < c.nextra; i++) { | |
| 2244 | + x := o / 8; | |
| 2245 | + m[x] = byte ((int m[x]) | bits[o & 7]); | |
| 2246 | + o++; | |
| 2247 | + } | |
| 2248 | + # | |
| 2249 | + # Copy class module data and its map. | |
| 2250 | + # | |
| 2251 | + if (c.datasize > 0) { | |
| 2252 | + if (c.datasize + c.dataoffset > c.info.types[0].size) { | |
| 2253 | + error("bad data size/offset"); | |
| 2254 | + c.datasize = 0; | |
| 2255 | + } else | |
| 2256 | + c.copymap(c.info.types[0].map, c.dataoffset); | |
| 2257 | + } | |
| 2258 | + trace(JDEBUG, sys->sprint("%s data %d reloc %d", c.name, c.modsize, c.datareloc)); | |
| 2259 | + trace(JDEBUG, sys->sprint("\t%d bytes at %d", c.datasize, c.dataoffset)); | |
| 2260 | + md := ld->dnew(c.modsize, c.modmap); | |
| 2261 | + if (md == nil) | |
| 2262 | + error(sys->sprint("dnew failed: %r")); | |
| 2263 | + c.moddata = md; | |
| 2264 | + c.this = ref ClassObject(nil, c, nil); | |
| 2265 | + # | |
| 2266 | + # Fetch the instruction stream and patch it. | |
| 2267 | + # | |
| 2268 | + instructions := ld->ifetch(c.mod); | |
| 2269 | + if (instructions == nil) | |
| 2270 | + error(sys->sprint("ifetch failed: %r")); | |
| 2271 | + c.instrpatch(instructions); | |
| 2272 | + trace(JDEBUG, sys->sprint("\t%d instrs", len instructions)); | |
| 2273 | + # | |
| 2274 | + # Make the new module. | |
| 2275 | + # | |
| 2276 | + links := c.info.links; | |
| 2277 | + oldmod := c.mod; | |
| 2278 | + c.mod = ld->newmod(c.name, STACKSIZE, len links, instructions, md); | |
| 2279 | + if (c.mod == nil) | |
| 2280 | + error(sys->sprint("newmod failed: %r")); | |
| 2281 | + addmodclass(c.mod, c); | |
| 2282 | + # | |
| 2283 | + # Install the new types. | |
| 2284 | + # | |
| 2285 | + types := c.info.types; | |
| 2286 | + for (i = 1; i < len types; i++) { | |
| 2287 | + if (ld->tnew(c.mod, types[i].size, types[i].map) != i) | |
| 2288 | + error(sys->sprint("tnew failed: %r")); | |
| 2289 | + } | |
| 2290 | + # | |
| 2291 | + # Install the links. | |
| 2292 | + # | |
| 2293 | + for (i = 0; i < len links; i++) { | |
| 2294 | + if (ld->ext(c.mod, i, links[i].pc, links[i].tdesc) < 0) | |
| 2295 | + error(sys->sprint("ext failed: %r")); | |
| 2296 | + } | |
| 2297 | + # | |
| 2298 | + # This word is used by rtload. | |
| 2299 | + # | |
| 2300 | + putint(md, c.datareloc - WORDZ, c.datareloc); | |
| 2301 | + if (c.datasize > 0) | |
| 2302 | + c.copymd(md, c.dataoffset, oldmod); | |
| 2303 | + c.makeobjtype(); | |
| 2304 | + trace(JDEBUG, sys->sprint("relocate(%s) exit", c.name)); | |
| 2305 | + cur = nil; | |
| 2306 | +} | |
| 2307 | + | |
| 2308 | +# | |
| 2309 | +# Instruction patching. | |
| 2310 | +# | |
| 2311 | +Class.instrpatch(c: self ref Class, inst: array of Loader->Inst) | |
| 2312 | +{ | |
| 2313 | + # | |
| 2314 | + # A class' own relocations were determined in resolve. | |
| 2315 | + # | |
| 2316 | + r := getreloc(c.mod, RELOC); | |
| 2317 | + p := c.info.reloc; | |
| 2318 | + x := c.info.extraoffset; | |
| 2319 | + n := len r; | |
| 2320 | + for (i := 0; i < n; i++) { | |
| 2321 | + v: int; | |
| 2322 | + case p[i].what { | |
| 2323 | + PVALUE => | |
| 2324 | + v = p[i].value; | |
| 2325 | + PEXTRA => | |
| 2326 | + v = x + p[i].value * WORDZ; | |
| 2327 | + PMETHOD => | |
| 2328 | + v = (METHODOFFSET + p[i].value * 2) * WORDZ; | |
| 2329 | + PSTATIC => | |
| 2330 | + v = c.staticoffset + p[i].value; | |
| 2331 | + * => | |
| 2332 | + error("bad Patch"); | |
| 2333 | + } | |
| 2334 | + ipatch(inst, r[i].patch, v); | |
| 2335 | + } | |
| 2336 | + x += c.info.extrabase * WORDZ; | |
| 2337 | + # | |
| 2338 | + # Data relocation. | |
| 2339 | + # | |
| 2340 | + ipatch(inst, getbytearray(c.mod, DRELOC), c.datareloc); | |
| 2341 | + # | |
| 2342 | + # Patching for referenced classes (and @Loader). | |
| 2343 | + # | |
| 2344 | + j := 0; | |
| 2345 | + i = CLASSREF; | |
| 2346 | + while ((s := getstring(c.mod, i)) != nil) { | |
| 2347 | + k := c.refs[j]; | |
| 2348 | + if (k != nil) | |
| 2349 | + x = k.relocref(c, inst, getreloc(c.mod, i + WORDZ), x); | |
| 2350 | + else | |
| 2351 | + x = relocloader(inst, getreloc(c.mod, i + WORDZ), x); | |
| 2352 | + i += 2 * WORDZ; | |
| 2353 | + j++; | |
| 2354 | + } | |
| 2355 | +} | |
| 2356 | + | |
| 2357 | +# | |
| 2358 | +# Third pass of class loader. All referenced classes | |
| 2359 | +# have had new modules allocated. | |
| 2360 | +# | |
| 2361 | +Class.modpatch(c: self ref Class) | |
| 2362 | +{ | |
| 2363 | + cur = c.name; | |
| 2364 | + d := c.moddata; | |
| 2365 | + putclass(d, CLASSADTOFFSET, c); | |
| 2366 | + v := c.virtualmethods; | |
| 2367 | + n := len v; | |
| 2368 | + o := METHODOFFSET * WORDZ; | |
| 2369 | + for (i := 0; i < n; i++) { | |
| 2370 | + m := v[i]; | |
| 2371 | + if (isnative(m.field.flags)) | |
| 2372 | + putmod(d, o, m.class.native); | |
| 2373 | + else | |
| 2374 | + putmod(d, o, m.class.mod); | |
| 2375 | + putint(d, o + WORDZ, m.field.value); | |
| 2376 | + o += 2 * WORDZ; | |
| 2377 | + } | |
| 2378 | + x := c.info.extras; | |
| 2379 | + n = len x; | |
| 2380 | + o = c.info.extraoffset; | |
| 2381 | + for (i = 0; i < n; i++) { | |
| 2382 | + e := x[i]; | |
| 2383 | + case e.what { | |
| 2384 | + CMP => | |
| 2385 | + if (e.class == nil) | |
| 2386 | + putmod(d, o, thisnil); | |
| 2387 | + else | |
| 2388 | + putmod(d, o, e.class.mod); | |
| 2389 | + CADT => | |
| 2390 | + putclass(d, o, e.class); | |
| 2391 | + CNP => | |
| 2392 | + putmod(d, o, e.class.native); | |
| 2393 | + COBJ => | |
| 2394 | + putobj(d, o, e.class.this); | |
| 2395 | + CJEX => | |
| 2396 | + putstring(d, o, JAVAEXCEPTION); | |
| 2397 | + CSYS => | |
| 2398 | + putmod(d, o, sysnil); | |
| 2399 | + * => | |
| 2400 | + error("bad extra what"); | |
| 2401 | + } | |
| 2402 | + o += WORDZ; | |
| 2403 | + } | |
| 2404 | + trace(JDEBUG, sys->sprint("compile %s", c.name)); | |
| 2405 | + if ((c.flags & DONTCOMPILE) == 0) { | |
| 2406 | + if (ld->compile(c.mod, c.flags & MUSTCOMPILE) < 0) | |
| 2407 | + error(sys->sprint("compile %s failed: %r", c.name)); | |
| 2408 | + if (c.native != nil) { | |
| 2409 | + trace(JDEBUG, sys->sprint("compile native %s", c.name)); | |
| 2410 | + if (ld->compile(c.native, c.flags & MUSTCOMPILE) < 0) | |
| 2411 | + error(sys->sprint("compile native %s failed: %r", c.name)); | |
| 2412 | + } | |
| 2413 | + } | |
| 2414 | + cur = nil; | |
| 2415 | +} | |
| 2416 | + | |
| 2417 | +# | |
| 2418 | +# Resolution routines. | |
| 2419 | +# | |
| 2420 | + | |
| 2421 | +# | |
| 2422 | +# Check for method override. | |
| 2423 | +# | |
| 2424 | +Class.override(c: self ref Class, f, s: string): int | |
| 2425 | +{ | |
| 2426 | + if (c.super == nil) | |
| 2427 | + return -1; | |
| 2428 | + m := c.super.virtualmethods; | |
| 2429 | + n := len m; | |
| 2430 | + for (i := 0; i < n; i++) { | |
| 2431 | + t := m[i].field; | |
| 2432 | + if (t.field == f && t.signature == s) | |
| 2433 | + return i; | |
| 2434 | + } | |
| 2435 | + return -1; | |
| 2436 | +} | |
| 2437 | + | |
| 2438 | +# | |
| 2439 | +# Find init method. | |
| 2440 | +# | |
| 2441 | +Class.findimethod(c: self ref Class, s: string): ref Field | |
| 2442 | +{ | |
| 2443 | + return findasig(c.initmethods, s); | |
| 2444 | +} | |
| 2445 | + | |
| 2446 | +# | |
| 2447 | +# Find private method. | |
| 2448 | +# | |
| 2449 | +Class.findpmethod(c: self ref Class, f, s: string): ref Field | |
| 2450 | +{ | |
| 2451 | + return findafs(c.privatemethods, f, s); | |
| 2452 | +} | |
| 2453 | + | |
| 2454 | +# | |
| 2455 | +# Find static field. | |
| 2456 | +# | |
| 2457 | +Class.findsfield(c: self ref Class, f: string): ref Field | |
| 2458 | +{ | |
| 2459 | + return findafield(c.staticdata, f); | |
| 2460 | +} | |
| 2461 | + | |
| 2462 | +# | |
| 2463 | +# Find static method. | |
| 2464 | +# | |
| 2465 | +Class.findsmethod(c: self ref Class, f, s: string): ref Field | |
| 2466 | +{ | |
| 2467 | + return findafs(c.staticmethods, f, s); | |
| 2468 | +} | |
| 2469 | + | |
| 2470 | +# | |
| 2471 | +# Find object field. | |
| 2472 | +# | |
| 2473 | +Class.findofield(c: self ref Class, f: string): ref Field | |
| 2474 | +{ | |
| 2475 | + return findfield(c.objectdata, f); | |
| 2476 | +} | |
| 2477 | + | |
| 2478 | +# | |
| 2479 | +# Find virtual method. | |
| 2480 | +# | |
| 2481 | +Class.findvmethod(c: self ref Class, f, s: string): int | |
| 2482 | +{ | |
| 2483 | + a := c.virtualmethods; | |
| 2484 | + n := len a; | |
| 2485 | + if (c.name == "java/lang/StringBuffer") { | |
| 2486 | + trace(JDEBUG, sys->sprint("Class: %s, virtual methods: %d", c.name, n)); | |
| 2487 | + trace(JDEBUG, sys->sprint("Started looking for method: %s, %s", f, s)); | |
| 2488 | + statenames := array [] of {"NEW", "HIER", "RESOLVE", "LOADED", "INITED"}; | |
| 2489 | + trace(JDEBUG, sys->sprint("Class state: %s", statenames[c.state])); | |
| 2490 | + } | |
| 2491 | + for (i := 0; i < n; i++) { | |
| 2492 | + t := a[i].field; | |
| 2493 | + if (t.field == f && t.signature == s) | |
| 2494 | + return i; | |
| 2495 | + } | |
| 2496 | + trace(JDEBUG, "returned fail"); | |
| 2497 | + return -1; | |
| 2498 | +} | |
| 2499 | + | |
| 2500 | +Class.loadnative(c: self ref Class) | |
| 2501 | +{ | |
| 2502 | + native := ROOT + c.encoding + "_L.dis"; | |
| 2503 | + mod := load Nilmod native; | |
| 2504 | + if (mod == nil) { | |
| 2505 | + trace(JVERBOSE, sys->sprint("Load native failed: %r")); | |
| 2506 | + return; | |
| 2507 | + } | |
| 2508 | + trace(JDEBUG, sys->sprint("\"%s\"", native)); | |
| 2509 | + links := ld->link(mod); | |
| 2510 | + if (links == nil) | |
| 2511 | + error(sys->sprint("%s: native Loader->link failed: %r", unsatisfiedlink)); | |
| 2512 | + c.info.nlinks = links; | |
| 2513 | + types := ld->tdesc(mod); | |
| 2514 | + if (types == nil) | |
| 2515 | + error(sys->sprint("%s: native tdesc failed: %r",unsatisfiedlink)); | |
| 2516 | + instrs := ld->ifetch(mod); | |
| 2517 | + if (instrs == nil) | |
| 2518 | + error(sys->sprint("%s: native ifetch failed: %r",unsatisfiedlink)); | |
| 2519 | + nm := ld->newmod("N-" + c.name, STACKSIZE, len links, instrs, getmd(mod)); | |
| 2520 | + if (nm == nil) | |
| 2521 | + error(sys->sprint("%s: native newmod failed: %r",unsatisfiedlink)); | |
| 2522 | + n := len types; | |
| 2523 | + for (i := 1; i < n; i++) { | |
| 2524 | + if (ld->tnew(nm, types[i].size, types[i].map) != i) | |
| 2525 | + error(sys->sprint("%s: native tnew failed: %r",unsatisfiedlink)); | |
| 2526 | + } | |
| 2527 | + n = len links; | |
| 2528 | + for (i = 0; i < n; i++) { | |
| 2529 | + if (ld->ext(nm, i, links[i].pc, links[i].tdesc) < 0) | |
| 2530 | + error(sys->sprint("%s: native ext failed: %r",unsatisfiedlink)); | |
| 2531 | + } | |
| 2532 | + addmodclass(nm, c); | |
| 2533 | + c.native = nm; | |
| 2534 | +} | |
| 2535 | + | |
| 2536 | +# | |
| 2537 | +# Search the links for a method. Maybe load the native module. | |
| 2538 | +# | |
| 2539 | +Class.getmethod(c: self ref Class, f, s: string, flags: int): int | |
| 2540 | +{ | |
| 2541 | + trace(JDEBUG, sys->sprint("Getmethod of %s: %s, %s, %d", c.name, f, s, flags)); | |
| 2542 | + l: array of Loader->Link; | |
| 2543 | + m: string; | |
| 2544 | + if (isnative(flags)) { | |
| 2545 | + if (c.native == nil) | |
| 2546 | + c.loadnative(); | |
| 2547 | + l = c.info.nlinks; | |
| 2548 | + m = mangle(f, s); | |
| 2549 | + } else { | |
| 2550 | + l = c.info.links; | |
| 2551 | + m = f + s; | |
| 2552 | + } | |
| 2553 | + n := len l; | |
| 2554 | + for (i := 0; i < n; i++) { | |
| 2555 | + if (l[i].name == m) | |
| 2556 | + return i; | |
| 2557 | + } | |
| 2558 | + if (!(flags & (ACC_ABSTRACT | ACC_NATIVE))) | |
| 2559 | + { | |
| 2560 | + loaderror( nosuchmethod, sys->sprint("method %x %s '%s' %s not found", flags, f, s, m) ); | |
| 2561 | + } | |
| 2562 | + return -1; | |
| 2563 | +} | |
| 2564 | + | |
| 2565 | +# | |
| 2566 | +# Find method called with invokespecial. | |
| 2567 | +# | |
| 2568 | +Class.special(c: self ref Class, f, s: string, flags: int, r: ref Class): (int, ref Class, int) | |
| 2569 | +{ | |
| 2570 | + if (f == SPECIALINIT) { | |
| 2571 | + i := findasig(r.initmethods, s); | |
| 2572 | + if (i == nil) | |
| 2573 | + error(sys->sprint("%s: <init> '%s' not found in class %s", nosuchmethod, s, r.name)); | |
| 2574 | + return (CMP, r, i.value); | |
| 2575 | + } else if (isprivate(flags)) { | |
| 2576 | + p := findafs(r.privatemethods, f, s); | |
| 2577 | + if (p == nil) | |
| 2578 | + error("invokespecial private botch"); | |
| 2579 | + if (isnative(p.flags)) | |
| 2580 | + return (CNP, r, p.value); | |
| 2581 | + else | |
| 2582 | + return (CMP, r, p.value); | |
| 2583 | + } else { | |
| 2584 | + r = c.super; | |
| 2585 | + if (r == nil) | |
| 2586 | + error("invokespecial super botch"); | |
| 2587 | + i := r.findvmethod(f, s); | |
| 2588 | + if (i < 0) | |
| 2589 | + error("invokespecial botch"); | |
| 2590 | + m := r.virtualmethods[i]; | |
| 2591 | + if (isnative(m.field.flags)) | |
| 2592 | + return (CNP, m.class, m.field.value); | |
| 2593 | + else | |
| 2594 | + return (CMP, m.class, m.field.value); | |
| 2595 | + } | |
| 2596 | +} | |
| 2597 | + | |
| 2598 | +# | |
| 2599 | +# Record info for an extra. | |
| 2600 | +# | |
| 2601 | +Class.extra(c: self ref Class, w, n: int, r: ref Class) | |
| 2602 | +{ | |
| 2603 | + c.info.extras[n].what = w; | |
| 2604 | + c.info.extras[n].class = r; | |
| 2605 | +} | |
| 2606 | + | |
| 2607 | +# | |
| 2608 | +# Record info for extras. | |
| 2609 | +# | |
| 2610 | +Class.extras(c: self ref Class, a: array of Reloc, n: int, r: ref Class): int | |
| 2611 | +{ | |
| 2612 | + l := len a; | |
| 2613 | + for (i := 0; i < l; i++) { | |
| 2614 | + f := a[i].field; | |
| 2615 | + if (f[0] != '@') | |
| 2616 | + break; | |
| 2617 | + case f { | |
| 2618 | + MP => | |
| 2619 | + c.extra(CMP, n, r); | |
| 2620 | + ADT => | |
| 2621 | + c.extra(CADT, n, r); | |
| 2622 | + NP => | |
| 2623 | + c.extra(CNP, n, r); | |
| 2624 | + OBJ => | |
| 2625 | + c.extra(COBJ, n, r); | |
| 2626 | + JEX => | |
| 2627 | + if (r != nil) | |
| 2628 | + error("@jex not in @Loader"); | |
| 2629 | + c.extra(CJEX, n, nil); | |
| 2630 | + SYS => | |
| 2631 | + if (r != nil) | |
| 2632 | + error("@sys not in @Loader"); | |
| 2633 | + c.extra(CSYS, n, nil); | |
| 2634 | + CLASS => | |
| 2635 | + n--; | |
| 2636 | + * => | |
| 2637 | + error(sys->sprint("unknown reloc: %s", f)); | |
| 2638 | + } | |
| 2639 | + n++; | |
| 2640 | + } | |
| 2641 | + for (; i < l; i++) { | |
| 2642 | + if (a[i].flags & Rspecialmp) { | |
| 2643 | + if ((a[i].flags & Rmask) != Rinvokespecial) | |
| 2644 | + error("bad Rspecialmp"); | |
| 2645 | + (v, s, nil) := c.special(a[i].field, a[i].signature, a[i].flags, r); | |
| 2646 | + c.extra(v, n, s); | |
| 2647 | + n++; | |
| 2648 | + } | |
| 2649 | + } | |
| 2650 | + return n; | |
| 2651 | +} | |
| 2652 | + | |
| 2653 | +# | |
| 2654 | +# Count the extra data fields need for a Reloc. | |
| 2655 | +# | |
| 2656 | +nextra(a: array of Reloc): int | |
| 2657 | +{ | |
| 2658 | + n := 0; | |
| 2659 | + l := len a; | |
| 2660 | + for (i := 0; i < l; i++) { | |
| 2661 | + f := a[i].field; | |
| 2662 | + if (f[0] != '@') | |
| 2663 | + break; | |
| 2664 | + case f { | |
| 2665 | + MP or NP or ADT or OBJ or JEX or SYS => | |
| 2666 | + n++; | |
| 2667 | + } | |
| 2668 | + } | |
| 2669 | + for (; i < l; i++) { | |
| 2670 | + if (a[i].flags & Rspecialmp) | |
| 2671 | + n++; | |
| 2672 | + } | |
| 2673 | + return n; | |
| 2674 | +} | |
| 2675 | + | |
| 2676 | +# | |
| 2677 | +# Copy old module map corresponding to module data to new map. | |
| 2678 | +# | |
| 2679 | +Class.copymap(c: self ref Class, om: array of byte, dr: int) | |
| 2680 | +{ | |
| 2681 | + nm := c.modmap; | |
| 2682 | + s := dr / MAPZ; | |
| 2683 | + d := c.datareloc / MAPZ; | |
| 2684 | + while (d < len nm) { | |
| 2685 | + if (s < len om) | |
| 2686 | + nm[d] = om[s]; | |
| 2687 | + else | |
| 2688 | + nm[d] = byte 0; | |
| 2689 | + s++; | |
| 2690 | + d++; | |
| 2691 | + } | |
| 2692 | +} | |
| 2693 | + | |
| 2694 | +# | |
| 2695 | +# Copy old module data to new module data. | |
| 2696 | +# | |
| 2697 | +Class.copymd(c: self ref Class, md: ref Niladt, dr: int, om: Nilmod) | |
| 2698 | +{ | |
| 2699 | + m := c.modmap; | |
| 2700 | + s := dr; | |
| 2701 | + d := c.datareloc; | |
| 2702 | + for (i := 0; i < c.datasize; i+= WORDZ) { | |
| 2703 | + w := d / WORDZ; | |
| 2704 | + if ((int m[w / 8] & bits[w & 7]) != 0) | |
| 2705 | + putptr(md, d, getptr(om, s)); | |
| 2706 | + else | |
| 2707 | + putint(md, d, getint(om, s)); | |
| 2708 | + d += WORDZ; | |
| 2709 | + s += WORDZ; | |
| 2710 | + } | |
| 2711 | +} | |
| 2712 | + | |
| 2713 | +# | |
| 2714 | +# Resolve a relocation for a referenced class. | |
| 2715 | +# | |
| 2716 | +Class.resolvereloc(c: self ref Class, r, s: string, flags: int): (int, int) | |
| 2717 | +{ | |
| 2718 | + v: int; | |
| 2719 | + f: ref Field; | |
| 2720 | + case flags & Rmask { | |
| 2721 | + Rgetputfield => | |
| 2722 | + f = findfield(c.objectdata, r); | |
| 2723 | + if (f == nil) | |
| 2724 | + loaderror(nosuchfield, sys->sprint("%s not resolved in class %s", r, c.name)); | |
| 2725 | + else { | |
| 2726 | + if (f.signature != s) { | |
| 2727 | + loaderror(nosuchfield, sys->sprint("%s type mismatch in class %s:%s vs %s", r, c.name, f.signature, s)); | |
| 2728 | + } | |
| 2729 | + v = f.value; | |
| 2730 | + } | |
| 2731 | + Rgetputstatic => | |
| 2732 | + f = c.findsfield(r); | |
| 2733 | + if (f == nil) | |
| 2734 | + loaderror( nosuchfield, sys->sprint("static %s not found in class %s", r, c.name)); | |
| 2735 | + else { | |
| 2736 | + if (f.signature != s) { | |
| 2737 | + loaderror(nosuchfield, sys->sprint("%s static type mismatch in class %s:%s vs %s", r, c.name, f.signature, s)); | |
| 2738 | + } | |
| 2739 | + v = c.staticoffset + f.value; | |
| 2740 | + } | |
| 2741 | + Rinvokeinterface => | |
| 2742 | + if ((c.flags & ACC_INTERFACE) == 0) { | |
| 2743 | + loaderror(linkageerr, sys->sprint("%s is not an interface", c.name)); | |
| 2744 | + break; | |
| 2745 | + } | |
| 2746 | + v = findmfsx(c.virtualmethods, r, s); | |
| 2747 | + if (v < 0) | |
| 2748 | + loaderror( nosuchmethod, sys->sprint("interface method %s '%s' not found in class %s", r, s, c.name)); | |
| 2749 | + v |= c.interindex << 16; | |
| 2750 | + Rinvokespecial => | |
| 2751 | + error("Rinvokespecial botch"); | |
| 2752 | + Rinvokestatic => | |
| 2753 | + f = c.findsmethod(r, s); | |
| 2754 | + if (f == nil) | |
| 2755 | + loaderror( nosuchmethod, sys->sprint("static method %s '%s' not found in class %s", r, s, c.name)); | |
| 2756 | + else if (flags & Rstaticmp) { | |
| 2757 | + if (f.flags & ACC_NATIVE) | |
| 2758 | + return (VNP, 0); | |
| 2759 | + else | |
| 2760 | + return (VMP, 0); | |
| 2761 | + } else | |
| 2762 | + v = f.value; | |
| 2763 | + Rinvokevirtual => | |
| 2764 | + v = c.findvmethod(r, s); | |
| 2765 | + if (v < 0) | |
| 2766 | + loaderror( nosuchmethod, sys->sprint("method %s '%s' not resolved in class %s", r, s, c.name)); | |
| 2767 | + v = (METHODOFFSET + v * 2) * WORDZ; | |
| 2768 | + * => | |
| 2769 | + if (r == OBJ) | |
| 2770 | + return (VOBJ, 0); | |
| 2771 | + error(sys->sprint("%s: bad Rmask", c.name)); | |
| 2772 | + } | |
| 2773 | + return (VVAL, v); | |
| 2774 | +} | |
| 2775 | + | |
| 2776 | +# | |
| 2777 | +# Perform relocation for a referenced class. | |
| 2778 | +# | |
| 2779 | +Class.relocref(c: self ref Class, t: ref Class, inst: array of Loader->Inst, a: array of Reloc, x: int): int | |
| 2780 | +{ | |
| 2781 | + v, w: int; | |
| 2782 | + mp := -1; | |
| 2783 | + np := -1; | |
| 2784 | + n := len a; | |
| 2785 | + for (i := 0; i < n; i++) { | |
| 2786 | + f := a[i].field; | |
| 2787 | + if (f[0] != '@') | |
| 2788 | + break; | |
| 2789 | + case f { | |
| 2790 | + MP => | |
| 2791 | + if (mp >= 0) | |
| 2792 | + error("repeat @mp"); | |
| 2793 | + mp = x; | |
| 2794 | + v = x; | |
| 2795 | + x += WORDZ; | |
| 2796 | + NP => | |
| 2797 | + if (np >= 0) | |
| 2798 | + error("repeat @np"); | |
| 2799 | + np = x; | |
| 2800 | + v = x; | |
| 2801 | + x += WORDZ; | |
| 2802 | + ADT => | |
| 2803 | + v = x; | |
| 2804 | + x += WORDZ; | |
| 2805 | + OBJ => | |
| 2806 | + v = x; | |
| 2807 | + x += WORDZ; | |
| 2808 | + JEX => | |
| 2809 | + error("@jex not in @Loader"); | |
| 2810 | + SYS => | |
| 2811 | + error("@sys not in @Loader"); | |
| 2812 | + CLASS => | |
| 2813 | + v = c.objtype; | |
| 2814 | + * => | |
| 2815 | + error("@botch"); | |
| 2816 | + } | |
| 2817 | + ipatch(inst, a[i].patch, v); | |
| 2818 | + } | |
| 2819 | + for (; i < n; i++) { | |
| 2820 | + if ((a[i].flags & Rmask) == Rinvokespecial) { | |
| 2821 | + if (a[i].flags & Rspecialmp) { | |
| 2822 | + v = x; | |
| 2823 | + x += WORDZ; | |
| 2824 | + } else | |
| 2825 | + (nil, nil, v) = t.special(a[i].field, a[i].signature, a[i].flags, c); | |
| 2826 | + } else { | |
| 2827 | + (w, v) = c.resolvereloc(a[i].field, a[i].signature, a[i].flags); | |
| 2828 | + if (w == VMP) { | |
| 2829 | + if (mp < 0) | |
| 2830 | + error("no @mp for Rstaticmp"); | |
| 2831 | + v = mp; | |
| 2832 | + } else if (w == VNP) { | |
| 2833 | + if (np < 0) | |
| 2834 | + error("no @np for Rstaticmp"); | |
| 2835 | + v = np; | |
| 2836 | + } | |
| 2837 | + } | |
| 2838 | + ipatch(inst, a[i].patch, v); | |
| 2839 | + } | |
| 2840 | + return x; | |
| 2841 | +} | |
| 2842 | + | |
| 2843 | +# | |
| 2844 | +# Record an interface and assign it an ordinal. | |
| 2845 | +# | |
| 2846 | +Class.addinterface(c: self ref Class) | |
| 2847 | +{ | |
| 2848 | + if (ninterfaces == linterfaces) { | |
| 2849 | + if (ninterfaces == 0) { | |
| 2850 | + linterfaces = INITINTER; | |
| 2851 | + interfaces = array[INITINTER] of ref Class; | |
| 2852 | + } else { | |
| 2853 | + n := linterfaces * 3 / 2; | |
| 2854 | + a := array[n] of ref Class; | |
| 2855 | + for (i := 0; i < linterfaces; i++) | |
| 2856 | + a[i] = interfaces[i]; | |
| 2857 | + linterfaces = n; | |
| 2858 | + interfaces = a; | |
| 2859 | + } | |
| 2860 | + } | |
| 2861 | + c.interindex = ninterfaces; | |
| 2862 | + interfaces[ninterfaces++] = c; | |
| 2863 | +} | |
| 2864 | + | |
| 2865 | +# | |
| 2866 | +# Search for an interface implementation. | |
| 2867 | +# | |
| 2868 | +Class.interlook(c: self ref Class, a: array of Interface): array of int | |
| 2869 | +{ | |
| 2870 | + if (a == nil) | |
| 2871 | + return nil; | |
| 2872 | + n := len a; | |
| 2873 | + for (i := 0; i < n; i++) { | |
| 2874 | + d := a[i].class; | |
| 2875 | + do { | |
| 2876 | + if (d == c) | |
| 2877 | + return a[i].methods; | |
| 2878 | + d = d.super; | |
| 2879 | + } while (d != nil); | |
| 2880 | + } | |
| 2881 | + return nil; | |
| 2882 | +} | |
| 2883 | + | |
| 2884 | +# | |
| 2885 | +# Fetch interface table, possibly cached. | |
| 2886 | +# | |
| 2887 | +Class.getinterface(c: self ref Class, k: ref Class): array of int | |
| 2888 | +{ | |
| 2889 | + for (l := c.intercache; l != nil; l = tl l) { | |
| 2890 | + (d, m) := hd l; | |
| 2891 | + if (d == k) | |
| 2892 | + return m; | |
| 2893 | + } | |
| 2894 | + m: array of int; | |
| 2895 | + d := c; | |
| 2896 | + do { | |
| 2897 | + m = k.interlook(d.interfaces); | |
| 2898 | + d = d.super; | |
| 2899 | + } while (m == nil && d != nil); | |
| 2900 | + if (m != nil) { | |
| 2901 | + c.intercache = (k, m) :: c.intercache; | |
| 2902 | + return m; | |
| 2903 | + } | |
| 2904 | + return nil; | |
| 2905 | +} | |
| 2906 | + | |
| 2907 | +# | |
| 2908 | +# Call native module init function. | |
| 2909 | +# | |
| 2910 | +Class.initjni(c: self ref Class) | |
| 2911 | +{ | |
| 2912 | + trace(JVERBOSE, sys->sprint("%s->init()", c.name)); | |
| 2913 | + l := c.info.nlinks; | |
| 2914 | + n := len l; | |
| 2915 | + for (i := 0; i < n; i++) { | |
| 2916 | + if (l[i].name == "init") { | |
| 2917 | + if (l[i].sig != jnisig) | |
| 2918 | + error(sys->sprint("init typecheck in class %s native", c.name)); | |
| 2919 | + jassist->mcallm(c.native, i, jninil); | |
| 2920 | + trace(JDEBUG, "done"); | |
| 2921 | + return; | |
| 2922 | + } | |
| 2923 | + } | |
| 2924 | + error(sys->sprint("no init function in class %s native", c.name)); | |
| 2925 | +} | |
| 2926 | + | |
| 2927 | +# | |
| 2928 | +# @Loader relocation. | |
| 2929 | +# | |
| 2930 | +relocloader(inst: array of Loader->Inst, a: array of Reloc, x: int): int | |
| 2931 | +{ | |
| 2932 | + v: int; | |
| 2933 | + n := len a; | |
| 2934 | + for (i := 0; i < n; i++) { | |
| 2935 | + r := a[i].field; | |
| 2936 | + case r { | |
| 2937 | + MP or JEX or SYS => | |
| 2938 | + v = x; | |
| 2939 | + x += WORDZ; | |
| 2940 | + CLASS => | |
| 2941 | + error("@Loader @Class"); | |
| 2942 | + ADT => | |
| 2943 | + error("@Loader @adt"); | |
| 2944 | + NP => | |
| 2945 | + error("@Loader @np"); | |
| 2946 | + OBJ => | |
| 2947 | + error("@Loader @obj"); | |
| 2948 | + * => | |
| 2949 | + v = getloader(r); | |
| 2950 | + if (v < 0) | |
| 2951 | + error(sys->sprint("no ClassLoader/Sys entry %s", r)); | |
| 2952 | + } | |
| 2953 | + ipatch(inst, a[i].patch, v); | |
| 2954 | + } | |
| 2955 | + return x; | |
| 2956 | +} | |
| 2957 | + | |
| 2958 | +# | |
| 2959 | +# @Loader and @Sys entries. | |
| 2960 | +# This uses a magic hash which maps each loadkey to a unique index. | |
| 2961 | +# If you add a loadkey you will need new magic. | |
| 2962 | +# | |
| 2963 | + | |
| 2964 | +LDHASH: con 38; | |
| 2965 | + | |
| 2966 | +LoadMap: adt | |
| 2967 | +{ | |
| 2968 | + name: string; | |
| 2969 | + value: int; | |
| 2970 | +}; | |
| 2971 | + | |
| 2972 | +loadtable := array[LDHASH] of LoadMap; | |
| 2973 | + | |
| 2974 | +loadkeys := array[] of | |
| 2975 | +{ | |
| 2976 | + "aastorecheck", | |
| 2977 | + "acheckcast", | |
| 2978 | + "ainstanceof", | |
| 2979 | + "checkcast", | |
| 2980 | + "culprit", | |
| 2981 | + "d2i", | |
| 2982 | + "d2l", | |
| 2983 | + "dcmpg", | |
| 2984 | + "dcmpl", | |
| 2985 | + "drem", | |
| 2986 | + "getinterface", | |
| 2987 | + "instanceof", | |
| 2988 | + "lcmp", | |
| 2989 | + "monitorenter", | |
| 2990 | + "monitorexit", | |
| 2991 | + "multianewarray", | |
| 2992 | + "pcheckcast", | |
| 2993 | + "pinstanceof", | |
| 2994 | + "raise", | |
| 2995 | + "rescue", | |
| 2996 | + "rtload", | |
| 2997 | + "throw", | |
| 2998 | + "unrescue", | |
| 2999 | +}; | |
| 3000 | + | |
| 3001 | +# | |
| 3002 | +# This function maps the above 23 strings to unique integers from 0 to 37. | |
| 3003 | +# | |
| 3004 | +loadhash(s: string): int | |
| 3005 | +{ | |
| 3006 | + return ((s[len s - 1] + 49) * len s + 19 * s[0]) % LDHASH; | |
| 3007 | +} | |
| 3008 | + | |
| 3009 | +loadenter(s: string, x: int) | |
| 3010 | +{ | |
| 3011 | + n := loadhash(s); | |
| 3012 | + if (loadtable[n].name == s) | |
| 3013 | + loadtable[n].value = x; | |
| 3014 | +} | |
| 3015 | + | |
| 3016 | +initloadhash() | |
| 3017 | +{ | |
| 3018 | + n := len loadkeys; | |
| 3019 | + for (i := 0; i < n; i++) { | |
| 3020 | + s := loadkeys[i]; | |
| 3021 | + loadtable[loadhash(s)].name = s; | |
| 3022 | + } | |
| 3023 | + a := loadlinks; | |
| 3024 | + n = len a; | |
| 3025 | + for (i = 0; i < n; i++) | |
| 3026 | + loadenter(a[i].name, i); | |
| 3027 | + a = syslinks; | |
| 3028 | + n = len a; | |
| 3029 | + for (i = 0; i < n; i++) | |
| 3030 | + loadenter(a[i].name, i); | |
| 3031 | +} | |
| 3032 | + | |
| 3033 | +# | |
| 3034 | +# Map a string to a @Loader or @Sys index. | |
| 3035 | +# | |
| 3036 | +getloader(s: string): int | |
| 3037 | +{ | |
| 3038 | + n := loadhash(s); | |
| 3039 | + if (loadtable[n].name != s) | |
| 3040 | + error("getloader botch"); | |
| 3041 | + return loadtable[n].value; | |
| 3042 | +} | |
| 3043 | + | |
| 3044 | +# | |
| 3045 | +# Get Class adt from an object. | |
| 3046 | +# | |
| 3047 | +Object.class(o: self ref Object): ref Class | |
| 3048 | +{ | |
| 3049 | + return getclassadt(o.mod, CLASSADTOFFSET); | |
| 3050 | +} | |
| 3051 | + | |
| 3052 | +# | |
| 3053 | +# Categorizers. | |
| 3054 | +# | |
| 3055 | +isdata(sig: string): int | |
| 3056 | +{ | |
| 3057 | + return sig[0] != '('; | |
| 3058 | +} | |
| 3059 | + | |
| 3060 | +isspecial(field: string): int | |
| 3061 | +{ | |
| 3062 | + return field[0] == '<'; | |
| 3063 | +} | |
| 3064 | + | |
| 3065 | +ispointer(sig: string): int | |
| 3066 | +{ | |
| 3067 | + case sig[0] { | |
| 3068 | + 'L' or '[' => | |
| 3069 | + return 1; | |
| 3070 | + } | |
| 3071 | + return 0; | |
| 3072 | +} | |
| 3073 | + | |
| 3074 | +isprivate(flags: int): int | |
| 3075 | +{ | |
| 3076 | + return flags & ACC_PRIVATE; | |
| 3077 | +} | |
| 3078 | + | |
| 3079 | +isstatic(flags: int): int | |
| 3080 | +{ | |
| 3081 | + return flags & ACC_STATIC; | |
| 3082 | +} | |
| 3083 | + | |
| 3084 | +isnative(flags: int): int | |
| 3085 | +{ | |
| 3086 | + return flags & ACC_NATIVE; | |
| 3087 | +} | |
| 3088 | + | |
| 3089 | +isvirtual(flags: int): int | |
| 3090 | +{ | |
| 3091 | + return (flags & (ACC_PRIVATE | ACC_STATIC)) == 0; | |
| 3092 | +} | |
| 3093 | + | |
| 3094 | +isabstract(flags: int): int | |
| 3095 | +{ | |
| 3096 | + return flags & ACC_ABSTRACT; | |
| 3097 | +} | |
| 3098 | + | |
| 3099 | +# | |
| 3100 | +# Type alignment. | |
| 3101 | +# | |
| 3102 | +alignto(sz: int, sig: string): int | |
| 3103 | +{ | |
| 3104 | + a: int; | |
| 3105 | + if (sig == nil) | |
| 3106 | + a = WORDZ; | |
| 3107 | + else { | |
| 3108 | + a = sizeof(sig); | |
| 3109 | + if (a == 1) | |
| 3110 | + return sz; | |
| 3111 | + } | |
| 3112 | + a--; | |
| 3113 | + return (sz + a) & ~a; | |
| 3114 | +} | |
| 3115 | + | |
| 3116 | +# | |
| 3117 | +# Type size. | |
| 3118 | +# | |
| 3119 | +sizeof(sig: string): int | |
| 3120 | +{ | |
| 3121 | + case sig[0] { | |
| 3122 | + 'Z' or 'B' => | |
| 3123 | + return 1; | |
| 3124 | + 'D' or 'J' or 'F' => | |
| 3125 | + return 2 * WORDZ; | |
| 3126 | + 'C' or 'S' or 'I' or 'L' or '[' => | |
| 3127 | + return WORDZ; | |
| 3128 | + } | |
| 3129 | + warning("unknown size: " + sig); | |
| 3130 | + return WORDZ; | |
| 3131 | +} | |
| 3132 | + | |
| 3133 | +# | |
| 3134 | +# Utilities. | |
| 3135 | +# | |
| 3136 | + | |
| 3137 | +mkclarray(l: list of ref Class): array of ref Class | |
| 3138 | +{ | |
| 3139 | + n := len l; | |
| 3140 | + a := array[n] of ref Class; | |
| 3141 | + while (--n >= 0) { | |
| 3142 | + a[n] = hd l; | |
| 3143 | + l = tl l; | |
| 3144 | + } | |
| 3145 | + return a; | |
| 3146 | +} | |
| 3147 | + | |
| 3148 | +mkfdarray(l: list of ref Field): array of ref Field | |
| 3149 | +{ | |
| 3150 | + n := len l; | |
| 3151 | + a := array[n] of ref Field; | |
| 3152 | + while (--n >= 0) { | |
| 3153 | + a[n] = hd l; | |
| 3154 | + l = tl l; | |
| 3155 | + } | |
| 3156 | + return a; | |
| 3157 | +} | |
| 3158 | + | |
| 3159 | +findfield(l: list of ref Field, f: string): ref Field | |
| 3160 | +{ | |
| 3161 | + while (l != nil) { | |
| 3162 | + h := hd l; | |
| 3163 | + if (h.field == f) | |
| 3164 | + return h; | |
| 3165 | + l = tl l; | |
| 3166 | + } | |
| 3167 | + return nil; | |
| 3168 | +} | |
| 3169 | + | |
| 3170 | +findsig(l: list of ref Field, s: string): ref Field | |
| 3171 | +{ | |
| 3172 | + while (l != nil) { | |
| 3173 | + h := hd l; | |
| 3174 | + if (h.signature == s) | |
| 3175 | + return h; | |
| 3176 | + l = tl l; | |
| 3177 | + } | |
| 3178 | + return nil; | |
| 3179 | +} | |
| 3180 | + | |
| 3181 | +findfs(l: list of ref Field, f, s: string): ref Field | |
| 3182 | +{ | |
| 3183 | + while (l != nil) { | |
| 3184 | + h := hd l; | |
| 3185 | + if (h.field == f && h.signature == s) | |
| 3186 | + return h; | |
| 3187 | + l = tl l; | |
| 3188 | + } | |
| 3189 | + return nil; | |
| 3190 | +} | |
| 3191 | + | |
| 3192 | +findafield(a: array of ref Field, f: string): ref Field | |
| 3193 | +{ | |
| 3194 | + n := len a; | |
| 3195 | + for (i := 0; i < n; i++) { | |
| 3196 | + if (a[i].field == f) | |
| 3197 | + return a[i]; | |
| 3198 | + } | |
| 3199 | + return nil; | |
| 3200 | +} | |
| 3201 | + | |
| 3202 | +findasig(a: array of ref Field, s: string): ref Field | |
| 3203 | +{ | |
| 3204 | + n := len a; | |
| 3205 | + for (i := 0; i < n; i++) { | |
| 3206 | + if (a[i].signature == s) | |
| 3207 | + return a[i]; | |
| 3208 | + } | |
| 3209 | + return nil; | |
| 3210 | +} | |
| 3211 | + | |
| 3212 | +findafs(a: array of ref Field, f, s: string): ref Field | |
| 3213 | +{ | |
| 3214 | + n := len a; | |
| 3215 | + for (i := 0; i < n; i++) { | |
| 3216 | + if (a[i].field == f && a[i].signature == s) | |
| 3217 | + return a[i]; | |
| 3218 | + } | |
| 3219 | + return nil; | |
| 3220 | +} | |
| 3221 | + | |
| 3222 | +findmfsx(a: array of Method, f, s: string): int | |
| 3223 | +{ | |
| 3224 | + n := len a; | |
| 3225 | + for (i := 0; i < n; i++) { | |
| 3226 | + t := a[i].field; | |
| 3227 | + if (t.field == f && t.signature == s) | |
| 3228 | + return i; | |
| 3229 | + } | |
| 3230 | + return -1; | |
| 3231 | +} | |
| 3232 | + | |
| 3233 | +# | |
| 3234 | +# Patch an instruction. | |
| 3235 | +# | |
| 3236 | +ipatch(inst: array of Loader->Inst, p: array of byte, d: int) | |
| 3237 | +{ | |
| 3238 | + v: int; | |
| 3239 | + l := len inst; | |
| 3240 | + n := len p; | |
| 3241 | + x := 0; | |
| 3242 | + if (fsindir) { | |
| 3243 | + for (i := 0; i < n; i++) { | |
| 3244 | + t := int p[i]; | |
| 3245 | + if (t & RDELTA) { | |
| 3246 | + x += (256 - t) << 3; | |
| 3247 | + continue; | |
| 3248 | + } | |
| 3249 | + x += t >> ISHIFT; | |
| 3250 | + if (x < 0 || x >= l) | |
| 3251 | + error("bad inst index"); | |
| 3252 | + if (inst[x].op == byte 57 && inst[x].mid == 0) { | |
| 3253 | + trace(JVERBOSE, sys->sprint("Skipping instruction %d", x)); | |
| 3254 | + continue; | |
| 3255 | + } | |
| 3256 | + case t & (POP | PTYPE) { | |
| 3257 | + PSRC | PIMM or PSRC | PSIND => | |
| 3258 | + inst[x].src += d; | |
| 3259 | + PSRC | PDIND1 => | |
| 3260 | + v = inst[x].src; | |
| 3261 | + inst[x].src = (v & int 16rFFFF0000) | ((v & 16rFFFF) + d); | |
| 3262 | + PSRC | PDIND2 => | |
| 3263 | + v = inst[x].src; | |
| 3264 | + inst[x].src = (v & 16rFFFF) | ((v & int 16rFFFF0000) + (d << 16)); | |
| 3265 | + PMID | PIMM or PMID | PSIND => | |
| 3266 | + inst[x].mid += d; | |
| 3267 | + PDST | PIMM or PDST | PSIND => | |
| 3268 | + inst[x].dst += d; | |
| 3269 | + PDST | PDIND1 => | |
| 3270 | + v = inst[x].dst; | |
| 3271 | + inst[x].dst = (v & int 16rFFFF0000) | ((v & 16rFFFF) + d); | |
| 3272 | + PDST | PDIND2 => | |
| 3273 | + v = inst[x].dst; | |
| 3274 | + inst[x].dst = (v & 16rFFFF) | ((v & int 16rFFFF0000) + (d << 16)); | |
| 3275 | + * => | |
| 3276 | + error("bad reloc"); | |
| 3277 | + } | |
| 3278 | + } | |
| 3279 | + } else { | |
| 3280 | + for (i := 0; i < n; i++) { | |
| 3281 | + t := int p[i]; | |
| 3282 | + if (t & RDELTA) { | |
| 3283 | + x += (256 - t) << 3; | |
| 3284 | + continue; | |
| 3285 | + } | |
| 3286 | + x += t >> ISHIFT; | |
| 3287 | + if (x < 0 || x >= l) | |
| 3288 | + error("bad inst index"); | |
| 3289 | + case t & (POP | PTYPE) { | |
| 3290 | + PSRC | PIMM or PSRC | PSIND => | |
| 3291 | + inst[x].src += d; | |
| 3292 | + PSRC | PDIND1 => | |
| 3293 | + v = inst[x].src; | |
| 3294 | + inst[x].src = (v & 16rFFFF) | ((v & int 16rFFFF0000) + (d << 16)); | |
| 3295 | + PSRC | PDIND2 => | |
| 3296 | + v = inst[x].src; | |
| 3297 | + inst[x].src = (v & int 16rFFFF0000) | ((v & 16rFFFF) + d); | |
| 3298 | + PMID | PIMM or PMID | PSIND => | |
| 3299 | + inst[x].mid += d; | |
| 3300 | + PDST | PIMM or PDST | PSIND => | |
| 3301 | + inst[x].dst += d; | |
| 3302 | + PDST | PDIND1 => | |
| 3303 | + v = inst[x].dst; | |
| 3304 | + inst[x].dst = (v & 16rFFFF) | ((v & int 16rFFFF0000) + (d << 16)); | |
| 3305 | + PDST | PDIND2 => | |
| 3306 | + v = inst[x].dst; | |
| 3307 | + inst[x].dst = (v & int 16rFFFF0000) | ((v & 16rFFFF) + d); | |
| 3308 | + * => | |
| 3309 | + error("bad POP"); | |
| 3310 | + } | |
| 3311 | + } | |
| 3312 | + } | |
| 3313 | +} | |
| 3314 | + | |
| 3315 | +# | |
| 3316 | +# String concatenation. | |
| 3317 | +# | |
| 3318 | +concat(l: list of string, r: int): string | |
| 3319 | +{ | |
| 3320 | + n := len l; | |
| 3321 | + do { | |
| 3322 | + t: list of string; | |
| 3323 | + t = nil; | |
| 3324 | + do { | |
| 3325 | + if (n > 1) { | |
| 3326 | + s0, s1: string; | |
| 3327 | + if (r) { | |
| 3328 | + s1 = hd l; | |
| 3329 | + l = tl l; | |
| 3330 | + s0 = hd l; | |
| 3331 | + l = tl l; | |
| 3332 | + } else { | |
| 3333 | + s0 = hd l; | |
| 3334 | + l = tl l; | |
| 3335 | + s1 = hd l; | |
| 3336 | + l = tl l; | |
| 3337 | + } | |
| 3338 | + t = (s0 + s1) :: t; | |
| 3339 | + n -= 2; | |
| 3340 | + } else { | |
| 3341 | + t = (hd l) :: t; | |
| 3342 | + break; | |
| 3343 | + } | |
| 3344 | + } while (l != nil); | |
| 3345 | + l = t; | |
| 3346 | + n = len l; | |
| 3347 | + r = 1 - r; | |
| 3348 | + } while (n > 1); | |
| 3349 | + return hd l; | |
| 3350 | +} | |
| 3351 | + | |
| 3352 | +# | |
| 3353 | +# Native name mangling. | |
| 3354 | +# | |
| 3355 | +mangle(f, s: string): string | |
| 3356 | +{ | |
| 3357 | + l := f :: nil; | |
| 3358 | + _ := 1; | |
| 3359 | + a := 0; | |
| 3360 | + while (s != nil) { | |
| 3361 | + n := len s; | |
| 3362 | + i := 0; | |
| 3363 | + scan: for (;;) { | |
| 3364 | + if (i == n) { | |
| 3365 | + s = nil; | |
| 3366 | + break; | |
| 3367 | + } | |
| 3368 | + if (_) | |
| 3369 | + l = "_" :: l; | |
| 3370 | + case s[i] { | |
| 3371 | + '(' or ')' => | |
| 3372 | + _ = 0; | |
| 3373 | + '[' => | |
| 3374 | + l = "a" :: l; | |
| 3375 | + _ = 0; | |
| 3376 | + a = 1; | |
| 3377 | + 'L' => | |
| 3378 | + (c, r) := str->splitl(s[i + 1:], ";)"); | |
| 3379 | + (nil, b) := str->splitr(c, "/"); | |
| 3380 | + if (a) | |
| 3381 | + l = b :: l; | |
| 3382 | + else | |
| 3383 | + l = b :: "r" :: l; | |
| 3384 | + if (r == nil) | |
| 3385 | + s = nil; | |
| 3386 | + else | |
| 3387 | + s = r[1:]; | |
| 3388 | + _ = 1; | |
| 3389 | + a = 0; | |
| 3390 | + break scan; | |
| 3391 | + * => | |
| 3392 | + l = s[i:i + 1] :: l; | |
| 3393 | + _ = 1; | |
| 3394 | + a = 0; | |
| 3395 | + } | |
| 3396 | + i++; | |
| 3397 | + } | |
| 3398 | + } | |
| 3399 | + return concat(l, 1); | |
| 3400 | +} | |
| 3401 | + | |
| 3402 | +handlejavaex(nil: string, obj: ref Object) | |
| 3403 | +{ | |
| 3404 | + class := obj.class(); | |
| 3405 | + if (class != tdclass) { | |
| 3406 | + throwable := jassist->ObjecttoJT(obj); | |
| 3407 | + msg : string = nil; | |
| 3408 | + if ( throwable.msg != nil ) | |
| 3409 | + msg = throwable.msg.str; | |
| 3410 | + sys->fprint(stderr, "%s: %s\n", class.name, msg); | |
| 3411 | + if (throwable.trace != nil) | |
| 3412 | + sys->fprint(stderr, "%s\n", string throwable.trace); | |
| 3413 | + } | |
| 3414 | + delthreaddata(); | |
| 3415 | + exit; | |
| 3416 | +} | |
| 3417 | + | |
| 3418 | +setflags( flags : list of (string,int) ) | |
| 3419 | +{ | |
| 3420 | + if ( flags == nil ) return; | |
| 3421 | + | |
| 3422 | + for((f,v):=hd flags; flags != nil; flags = tl flags ) | |
| 3423 | + { | |
| 3424 | + case (f) | |
| 3425 | + { | |
| 3426 | + "debug" => loadtrace(); | |
| 3427 | + jtrace->level = JDEBUG; | |
| 3428 | + "verbose" => loadtrace(); | |
| 3429 | + jtrace->level = JVERBOSE; | |
| 3430 | + "warn" => warn = v; | |
| 3431 | + } | |
| 3432 | + } | |
| 3433 | +} | |
| 3434 | + | |
| 3435 | +runmain( classloader : JavaClassLoader, classname : string, argv : list of string ) | |
| 3436 | +{ | |
| 3437 | + { | |
| 3438 | + classloader->loader(classname).run(tl tl argv); | |
| 3439 | + } | |
| 3440 | + exception e | |
| 3441 | + { | |
| 3442 | + "*" => | |
| 3443 | + m := sys->sprint("uncaught exception: %s", e); | |
| 3444 | + mesg(m); | |
| 3445 | + if ( (obj := culprit(e)) != nil) | |
| 3446 | + handlejavaex(e, obj); | |
| 3447 | + else { | |
| 3448 | + raise m; #just giveup | |
| 3449 | + } | |
| 3450 | + classloader->shutdown(); | |
| 3451 | + } | |
| 3452 | +} | |
| @@ -0,0 +1,216 @@ | ||
| 1 | +implement Dump; | |
| 2 | + | |
| 3 | +include "sys.m"; | |
| 4 | +include "draw.m"; | |
| 5 | +include "loader.m"; | |
| 6 | +include "classloader.m"; | |
| 7 | + | |
| 8 | +Context: import Draw; | |
| 9 | + | |
| 10 | +Dump: module | |
| 11 | +{ | |
| 12 | + MP: con "@mp"; | |
| 13 | + ADT: con "@adt"; | |
| 14 | + | |
| 15 | + JAVA: con ('J'<<24)|('a'<<16)|('v'<<8)|'a'; | |
| 16 | + | |
| 17 | + MAGIC, VERSION, NAME, SUPER, RELOC, DSIZE, DRELOC, CLASSREF: | |
| 18 | + con (iota * 4); | |
| 19 | + WORDZ: con 4; | |
| 20 | + | |
| 21 | + init: fn(nil: ref Context, argv: list of string); | |
| 22 | + | |
| 23 | + Reloc: adt | |
| 24 | + { | |
| 25 | + field: string; | |
| 26 | + signature: string; | |
| 27 | + flags: int; | |
| 28 | + patch: array of int; | |
| 29 | + }; | |
| 30 | + | |
| 31 | + Field: adt | |
| 32 | + { | |
| 33 | + field: string; | |
| 34 | + signature: string; | |
| 35 | + flags: int; | |
| 36 | + value: int; | |
| 37 | + class: cyclic ref Class; | |
| 38 | + }; | |
| 39 | + | |
| 40 | + Class: adt | |
| 41 | + { | |
| 42 | + state: int; | |
| 43 | + name: string; | |
| 44 | + ownname: string; | |
| 45 | + file: string; | |
| 46 | + version: int; | |
| 47 | + mod: Nilmod; | |
| 48 | + super: cyclic ref Class; | |
| 49 | + refs: cyclic array of ref Class; | |
| 50 | + objectdata: cyclic list of ref Field; | |
| 51 | + virtualmethod: cyclic list of ref Field; | |
| 52 | + staticdata: cyclic array of ref Field; | |
| 53 | + staticmethod: cyclic array of ref Field; | |
| 54 | + objectsize: int; | |
| 55 | + staticsize: int; | |
| 56 | + nextra: int; | |
| 57 | + datasize: int; | |
| 58 | + datareloc: int; | |
| 59 | + modsize: int; | |
| 60 | + modmap: array of byte; | |
| 61 | + objmap: array of byte; | |
| 62 | + objtype: int; | |
| 63 | + }; | |
| 64 | + | |
| 65 | +}; | |
| 66 | + | |
| 67 | +sys: Sys; | |
| 68 | +jassist: JavaAssist; | |
| 69 | + | |
| 70 | + getint, getptr, getreloc, getstring: import jassist; | |
| 71 | + putclass, putint, putmod, putptr: import jassist; | |
| 72 | + mnew: import jassist; | |
| 73 | + | |
| 74 | +stderr: ref Sys->FD; | |
| 75 | + | |
| 76 | +ident: con "Dump"; | |
| 77 | + | |
| 78 | +mesg(s: string) | |
| 79 | +{ | |
| 80 | + sys->fprint(stderr, "%s: %s\n", ident, s); | |
| 81 | +} | |
| 82 | + | |
| 83 | +error(s: string) | |
| 84 | +{ | |
| 85 | + mesg(s); | |
| 86 | + exit; | |
| 87 | +} | |
| 88 | + | |
| 89 | +init(nil: ref Context, argv: list of string) | |
| 90 | +{ | |
| 91 | + s := ""; | |
| 92 | + t: string; | |
| 93 | + a: array of byte; | |
| 94 | + | |
| 95 | + sys = load Sys Sys->PATH; | |
| 96 | + stderr = sys->fildes(2); | |
| 97 | + | |
| 98 | + jassist = load JavaAssist JavaAssist->PATH; | |
| 99 | + if (jassist == nil) | |
| 100 | + error(sys->sprint( | |
| 101 | + "could not load %s: %r", JavaAssist->PATH)); | |
| 102 | + | |
| 103 | + argv = tl argv; | |
| 104 | + | |
| 105 | + if(argv == nil) | |
| 106 | + exit; | |
| 107 | + | |
| 108 | + i := 0; | |
| 109 | + junk := array[10] of Nilmod; | |
| 110 | + while(argv != nil) { | |
| 111 | + s = hd argv; | |
| 112 | + t = "\n" + s + "\n"; | |
| 113 | + a = array of byte t; | |
| 114 | + if(sys->write(sys->fildes(1), a, len a) != len a) | |
| 115 | + sys->fprint(sys->fildes(2), "load: write error: %r\n"); | |
| 116 | + junk[i] = load Nilmod s; | |
| 117 | + dump(junk[i]); | |
| 118 | + if(junk == nil) | |
| 119 | + sys->fprint(sys->fildes(2), "load: error: %r\n"); | |
| 120 | + argv = tl argv; | |
| 121 | + } | |
| 122 | +} | |
| 123 | + | |
| 124 | +nextra(a: array of Reloc): int | |
| 125 | +{ | |
| 126 | + n := 0; | |
| 127 | + for (i := 0; i < len a; i++) { | |
| 128 | + case a[i].field { | |
| 129 | + MP or ADT => | |
| 130 | + n++; | |
| 131 | + } | |
| 132 | + } | |
| 133 | + return n; | |
| 134 | +} | |
| 135 | + | |
| 136 | +dump(m: Nilmod) | |
| 137 | +{ | |
| 138 | + ld := load Loader Loader->PATH; | |
| 139 | + if(ld == nil) | |
| 140 | + error(sys->sprint("could not load %s: %r", Loader->PATH)); | |
| 141 | + | |
| 142 | + if (getint(m, MAGIC) != JAVA){ | |
| 143 | + sys->fprint(sys->fildes(2), "\tbad magic number\n"); | |
| 144 | + return; | |
| 145 | + } | |
| 146 | + | |
| 147 | + version := getint(m, VERSION) & 16rFF; | |
| 148 | + sys->fprint(sys->fildes(1),"\tversion: %d\n",version); | |
| 149 | + ownname := getstring(m, NAME); | |
| 150 | + a := array of byte ownname; | |
| 151 | + sys->fprint(sys->fildes(1),"\townname: "); | |
| 152 | + if(sys->write(sys->fildes(1), a, len a) != len a) | |
| 153 | + sys->fprint(sys->fildes(2), "load: write error: %r\n"); | |
| 154 | + | |
| 155 | + super := getstring(m, SUPER); | |
| 156 | + sys->fprint(sys->fildes(1),"\tsuper: %s\n",super); | |
| 157 | + | |
| 158 | + r := getreloc(m, RELOC); | |
| 159 | + i := len r; | |
| 160 | + sys->fprint(sys->fildes(1),"\tlen r: %d\n",i); | |
| 161 | + for (j := 0; j < len r; j++) { | |
| 162 | + t := r[j]; | |
| 163 | + sys->fprint(sys->fildes(1),"\t\t%s\t%s\n",t.field,t.signature); | |
| 164 | + } | |
| 165 | + | |
| 166 | + datasize := getint(m, DSIZE); | |
| 167 | + sys->fprint(sys->fildes(1),"\tdatasize: %d\n",datasize); | |
| 168 | + dr := getint(m, DRELOC); | |
| 169 | + sys->fprint(sys->fildes(1), "\treloc: %d\n",dr); | |
| 170 | + i = CLASSREF; | |
| 171 | + n := 0; | |
| 172 | + | |
| 173 | + sys->fprint(sys->fildes(1),"\tclassrefs:\n"); | |
| 174 | + while ((s := getstring(m, i)) != nil) { | |
| 175 | + n += nextra(getreloc(m, i + WORDZ)); | |
| 176 | + sys->fprint(sys->fildes(1),"\t\t%s %d\n",s,n); | |
| 177 | + i += 2 * WORDZ; | |
| 178 | + } | |
| 179 | + | |
| 180 | +# td := ld->tdesc(m); | |
| 181 | +# z := 2 * WORDZ + n*WORDZ; | |
| 182 | +# mod := array[z] of byte; | |
| 183 | +# for (i = 1; i < z; i++) | |
| 184 | +# mod[i] = byte 0; | |
| 185 | +# # nil and ref Class | |
| 186 | +# mod[0] = byte 16rC0; | |
| 187 | +# md := ld->dnew(datasize,mod); | |
| 188 | +# instructions := ld->ifetch(m); | |
| 189 | + links := ld->link(m); | |
| 190 | + | |
| 191 | + R := ref Class; | |
| 192 | + S := ref Class; | |
| 193 | + classes: list of ref Class; | |
| 194 | + classes = S :: classes; | |
| 195 | + classes = R :: classes; | |
| 196 | + | |
| 197 | + refs := mkclarray(classes); | |
| 198 | + | |
| 199 | + sys->fprint(sys->fildes(1),"\n"); | |
| 200 | +} | |
| 201 | + | |
| 202 | +mkclarray(l: list of ref Class): array of ref Class | |
| 203 | +{ | |
| 204 | + n := len l; | |
| 205 | + sys->fprint(stderr, "mkclarray, len: %d\n",n); | |
| 206 | + a := array[n] of ref Class; | |
| 207 | + while (--n >= 0) { | |
| 208 | + sys->fprint(stderr, "mkclarray, len: %d\n",n); | |
| 209 | + a[n] = hd l; | |
| 210 | + l = tl l; | |
| 211 | + } | |
| 212 | + sys->fprint(stderr, "mkclarray, exitting\n"); | |
| 213 | + return a; | |
| 214 | +} | |
| 215 | + | |
| 216 | + | |
| @@ -0,0 +1,148 @@ | ||
| 1 | +# | |
| 2 | +# Java Class Loader dis assist. | |
| 3 | +# | |
| 4 | + | |
| 5 | +#0 | |
| 6 | +# getint: | |
| 7 | + addw 0(32(fp)),36(fp),40(fp) | |
| 8 | + movw 0(40(fp)),0(16(fp)) | |
| 9 | + ret | |
| 10 | +#3 | |
| 11 | +# getbytearray: | |
| 12 | +# getintarray: | |
| 13 | +# getreloc: | |
| 14 | +# getstrarray: | |
| 15 | +# getstring: | |
| 16 | + addw 0(32(fp)),36(fp),40(fp) | |
| 17 | + movp 0(40(fp)),0(16(fp)) | |
| 18 | + ret | |
| 19 | +#6 | |
| 20 | +# putint: | |
| 21 | + addw 32(fp),36(fp),44(fp) | |
| 22 | + movw 40(fp),0(44(fp)) | |
| 23 | + ret | |
| 24 | +#9 | |
| 25 | +# putclass: | |
| 26 | +# putmod: | |
| 27 | +# putobj: | |
| 28 | +# putptr: | |
| 29 | +# putstring: | |
| 30 | + addw 32(fp),36(fp),44(fp) | |
| 31 | + movp 40(fp),0(44(fp)) | |
| 32 | + ret | |
| 33 | +#12 | |
| 34 | +# little_endian: | |
| 35 | +# | |
| 36 | + movw $0,0(16(fp)) | |
| 37 | + movb 0(mp),0(16(fp)) | |
| 38 | + ret | |
| 39 | +#15 | |
| 40 | +# jclnilmod: | |
| 41 | +# sysnilmod: | |
| 42 | +# arrayof: | |
| 43 | +# bytearraytoJS: | |
| 44 | +# intarraytoJS: | |
| 45 | +# bigarraytoJS: | |
| 46 | +# realarraytoJS: | |
| 47 | +# ArraytoJS: | |
| 48 | +# JStoObject: | |
| 49 | +# ObjecttoJT: | |
| 50 | + movp 32(fp),0(16(fp)) | |
| 51 | + ret | |
| 52 | +#17 | |
| 53 | +# new: | |
| 54 | + mnewz 32(fp),36(fp),0(16(fp)) | |
| 55 | + ret | |
| 56 | +#19 | |
| 57 | +# getobjclass: | |
| 58 | + movp 0(32(fp)),36(fp) | |
| 59 | + movp 4(36(fp)),0(16(fp)) | |
| 60 | + ret | |
| 61 | +#22 | |
| 62 | +# modhash: | |
| 63 | +# objhash: | |
| 64 | + andw 32(fp),4(mp),0(16(fp)) | |
| 65 | + ret | |
| 66 | +#24 | |
| 67 | +# getrtreloc: | |
| 68 | +# getclassadt: | |
| 69 | +# getadtstring: | |
| 70 | + addw 32(fp),36(fp),40(fp) | |
| 71 | + movp 0(40(fp)),0(16(fp)) | |
| 72 | + ret | |
| 73 | +#27 | |
| 74 | +# getabsint | |
| 75 | + movw 0(32(fp)),0(16(fp)) | |
| 76 | + ret | |
| 77 | +#29 | |
| 78 | +# mcall0: | |
| 79 | + mframe 32(fp),36(fp),40(fp) | |
| 80 | + lea 0(16(fp)),16(40(fp)) | |
| 81 | + mcall 40(fp),36(fp),32(fp) | |
| 82 | + ret | |
| 83 | +#33 | |
| 84 | +# mcall1: | |
| 85 | +# mcalla: | |
| 86 | +# mcallm: | |
| 87 | + mframe 32(fp),36(fp),44(fp) | |
| 88 | + movp 40(fp),32(44(fp)) | |
| 89 | + lea 0(16(fp)),16(44(fp)) | |
| 90 | + mcall 44(fp),36(fp),32(fp) | |
| 91 | + ret | |
| 92 | +#38 | |
| 93 | +# getmd: | |
| 94 | + movp 0(32(fp)),0(16(fp)) | |
| 95 | + ret | |
| 96 | +#40 | |
| 97 | +# makeadt: | |
| 98 | + movp 32(fp),0(16(fp)) | |
| 99 | + ret | |
| 100 | + desc $0,8,"" | |
| 101 | + desc $1,48,"0080" | |
| 102 | + desc $2,48,"00a0" | |
| 103 | + desc $3,32,"" | |
| 104 | + desc $4,40,"0080" | |
| 105 | + desc $5,40,"00c0" | |
| 106 | + desc $6,40,"" | |
| 107 | + var @mp,8 | |
| 108 | + word @mp+0,1 | |
| 109 | + word @mp+4,2147483647 | |
| 110 | + module JavaAssist | |
| 111 | + link 1,0,0x9af56bb1,"getint" | |
| 112 | + link 1,3,0x480b7ac3,"getbytearray" | |
| 113 | + link 1,3,0x55e7e9b3,"getintarray" | |
| 114 | + link 1,3,0xd7e85087,"getptr" | |
| 115 | + link 1,3,0xbb4256c7,"getreloc" | |
| 116 | + link 1,3,0x67808576,"getstrarray" | |
| 117 | + link 1,3,0xe6647e4a,"getstring" | |
| 118 | + link 1,6,0x2de68727,"putint" | |
| 119 | + link 2,9,0xaa939019,"putclass" | |
| 120 | + link 2,9,0x66b5c780,"putmod" | |
| 121 | + link 2,9,0xa780c055,"putobj" | |
| 122 | + link 2,9,0x43ec4524,"putptr" | |
| 123 | + link 2,9,0x46bbe09a,"putstring" | |
| 124 | + link 3,12,0x616977e8,"little_endian" | |
| 125 | + link 4,15,0xfbfab1de,"jclnilmod" | |
| 126 | + link 4,15,0xa0d4011e,"sysnilmod" | |
| 127 | + link 4,15,0xafae2abc,"arrayof" | |
| 128 | + link 4,15,0x79238ebb,"bytearraytoJS" | |
| 129 | + link 4,15,0x9dfa2ee1,"intarraytoJS" | |
| 130 | + link 4,15,0x1ebcdfdd,"bigarraytoJS" | |
| 131 | + link 4,15,0xc8107991,"realarraytoJS" | |
| 132 | + link 4,15,0x464a7f42,"ArraytoJS" | |
| 133 | + link 4,15,0x76cd0754,"JStoObject" | |
| 134 | + link 4,15,0xaaaaaaaa,"ObjecttoJT" | |
| 135 | + link 1,17,0xbb2da06c,"new" | |
| 136 | + link 5,19,0x4e5bdbec,"getobjclass" | |
| 137 | + link 4,22,0x4e5d43e7,"modhash" | |
| 138 | + link 4,22,0x646cd7d0,"objhash" | |
| 139 | + link 1,24,0xa1fa7e52,"getrtreloc" | |
| 140 | + link 1,24,0x9d2938ae,"getclassadt" | |
| 141 | + link 1,24,0x3911b054,"getadtstring" | |
| 142 | + link 6,27,0xe67bf126,"getabsint" | |
| 143 | + link 1,29,0x9af56bb1,"mcall0" | |
| 144 | + link 2,33,0xcbd2cc54,"mcall1" | |
| 145 | + link 2,33,0x69095c2,"mcalla" | |
| 146 | + link 2,33,0x1fe62f91,"mcallm" | |
| 147 | + link 4,38,0x21126c42,"getmd" | |
| 148 | + link 6,40,0x2d805d,"makeadt" | |
| @@ -0,0 +1,148 @@ | ||
| 1 | +# | |
| 2 | +# Java Class Loader dis assist. | |
| 3 | +# | |
| 4 | + | |
| 5 | +#0 | |
| 6 | +# getint: | |
| 7 | + addw 0(32(fp)),36(fp),40(fp) | |
| 8 | + movw 0(40(fp)),0(16(fp)) | |
| 9 | + ret | |
| 10 | +#3 | |
| 11 | +# getbytearray: | |
| 12 | +# getintarray: | |
| 13 | +# getreloc: | |
| 14 | +# getstrarray: | |
| 15 | +# getstring: | |
| 16 | + addw 0(32(fp)),36(fp),40(fp) | |
| 17 | + movp 0(40(fp)),0(16(fp)) | |
| 18 | + ret | |
| 19 | +#6 | |
| 20 | +# putint: | |
| 21 | + addw 32(fp),36(fp),44(fp) | |
| 22 | + movw 40(fp),0(44(fp)) | |
| 23 | + ret | |
| 24 | +#9 | |
| 25 | +# putclass: | |
| 26 | +# putmod: | |
| 27 | +# putobj: | |
| 28 | +# putptr: | |
| 29 | +# putstring: | |
| 30 | + addw 32(fp),36(fp),44(fp) | |
| 31 | + movp 40(fp),0(44(fp)) | |
| 32 | + ret | |
| 33 | +#12 | |
| 34 | +# little_endian: | |
| 35 | +# | |
| 36 | + movw $0,0(16(fp)) | |
| 37 | + movb 0(mp),0(16(fp)) | |
| 38 | + ret | |
| 39 | +#15 | |
| 40 | +# jclnilmod: | |
| 41 | +# sysnilmod: | |
| 42 | +# arrayof: | |
| 43 | +# bytearraytoJS: | |
| 44 | +# intarraytoJS: | |
| 45 | +# bigarraytoJS: | |
| 46 | +# realarraytoJS: | |
| 47 | +# ArraytoJS: | |
| 48 | +# JStoObject: | |
| 49 | +# ObjecttoJT: | |
| 50 | + movp 32(fp),0(16(fp)) | |
| 51 | + ret | |
| 52 | +#17 | |
| 53 | +# new: | |
| 54 | + mnewz 32(fp),36(fp),0(16(fp)) | |
| 55 | + ret | |
| 56 | +#19 | |
| 57 | +# getobjclass: | |
| 58 | + movp 0(32(fp)),36(fp) | |
| 59 | + movp 4(36(fp)),0(16(fp)) | |
| 60 | + ret | |
| 61 | +#22 | |
| 62 | +# modhash: | |
| 63 | +# objhash: | |
| 64 | + andw 32(fp),4(mp),0(16(fp)) | |
| 65 | + ret | |
| 66 | +#24 | |
| 67 | +# getrtreloc: | |
| 68 | +# getclassadt: | |
| 69 | +# getadtstring: | |
| 70 | + addw 32(fp),36(fp),40(fp) | |
| 71 | + movp 0(40(fp)),0(16(fp)) | |
| 72 | + ret | |
| 73 | +#27 | |
| 74 | +# getabsint | |
| 75 | + movw 0(32(fp)),0(16(fp)) | |
| 76 | + ret | |
| 77 | +#29 | |
| 78 | +# mcall0: | |
| 79 | + mframe 32(fp),36(fp),40(fp) | |
| 80 | + lea 0(16(fp)),16(40(fp)) | |
| 81 | + mcall 40(fp),36(fp),32(fp) | |
| 82 | + ret | |
| 83 | +#33 | |
| 84 | +# mcall1: | |
| 85 | +# mcalla: | |
| 86 | +# mcallm: | |
| 87 | + mframe 32(fp),36(fp),44(fp) | |
| 88 | + movp 40(fp),32(44(fp)) | |
| 89 | + lea 0(16(fp)),16(44(fp)) | |
| 90 | + mcall 44(fp),36(fp),32(fp) | |
| 91 | + ret | |
| 92 | +#38 | |
| 93 | +# getmd: | |
| 94 | + movp 0(32(fp)),0(16(fp)) | |
| 95 | + ret | |
| 96 | +#40 | |
| 97 | +# makeadt: | |
| 98 | + movp 32(fp),0(16(fp)) | |
| 99 | + ret | |
| 100 | + desc $0,8,"" | |
| 101 | + desc $1,48,"0080" | |
| 102 | + desc $2,48,"00a0" | |
| 103 | + desc $3,32,"" | |
| 104 | + desc $4,40,"0080" | |
| 105 | + desc $5,40,"00c0" | |
| 106 | + desc $6,40,"" | |
| 107 | + var @mp,8 | |
| 108 | + word @mp+0,1 | |
| 109 | + word @mp+4,2147483647 | |
| 110 | + module JavaAssist | |
| 111 | + link 1,0,0x9af56bb1,"getint" | |
| 112 | + link 1,3,0x480b7ac3,"getbytearray" | |
| 113 | + link 1,3,0x55e7e9b3,"getintarray" | |
| 114 | + link 1,3,0xd7e85087,"getptr" | |
| 115 | + link 1,3,0xbb4256c7,"getreloc" | |
| 116 | + link 1,3,0x67808576,"getstrarray" | |
| 117 | + link 1,3,0xe6647e4a,"getstring" | |
| 118 | + link 1,6,0x2de68727,"putint" | |
| 119 | + link 2,9,0x8f05c931,"putclass" | |
| 120 | + link 2,9,0x66b5c780,"putmod" | |
| 121 | + link 2,9,0x4f9a2948,"putobj" | |
| 122 | + link 2,9,0x43ec4524,"putptr" | |
| 123 | + link 2,9,0x46bbe09a,"putstring" | |
| 124 | + link 3,12,0x616977e8,"little_endian" | |
| 125 | + link 4,15,0x18138a11,"jclnilmod" | |
| 126 | + link 4,15,0x8cdb1059,"sysnilmod" | |
| 127 | + link 4,15,0x6d675ef6,"arrayof" | |
| 128 | + link 4,15,0x79238ebb,"bytearraytoJS" | |
| 129 | + link 4,15,0x9dfa2ee1,"intarraytoJS" | |
| 130 | + link 4,15,0x1ebcdfdd,"bigarraytoJS" | |
| 131 | + link 4,15,0xc8107991,"realarraytoJS" | |
| 132 | + link 4,15,0xfb08d2ba,"ArraytoJS" | |
| 133 | + link 4,15,0x76cd0754,"JStoObject" | |
| 134 | + link 4,15,0xae823704,"ObjecttoJT" | |
| 135 | + link 1,17,0xbb2da06c,"new" | |
| 136 | + link 5,19,0x7e47f344,"getobjclass" | |
| 137 | + link 4,22,0x4e5d43e7,"modhash" | |
| 138 | + link 4,22,0x646cd7d0,"objhash" | |
| 139 | + link 1,24,0xa1fa7e52,"getrtreloc" | |
| 140 | + link 1,24,0x45af8037,"getclassadt" | |
| 141 | + link 1,24,0x3911b054,"getadtstring" | |
| 142 | + link 6,27,0xe67bf126,"getabsint" | |
| 143 | + link 1,29,0x9af56bb1,"mcall0" | |
| 144 | + link 2,33,0xcbd2cc54,"mcall1" | |
| 145 | + link 2,33,0x2c8f47,"mcalla" | |
| 146 | + link 2,33,0x1fe62f91,"mcallm" | |
| 147 | + link 4,38,0x21126c42,"getmd" | |
| 148 | + link 6,40,0x2d805d,"makeadt" | |
| @@ -0,0 +1,261 @@ | ||
| 1 | +implement JavaAssist; | |
| 2 | + | |
| 3 | +include "sys.m"; | |
| 4 | + | |
| 5 | +include "loader.m"; | |
| 6 | +include "classloader.m"; | |
| 7 | + | |
| 8 | +i: int = 23; | |
| 9 | +r: array of JavaClassLoader->Reloc; | |
| 10 | +s: string = "23"; | |
| 11 | +c: ref JavaClassLoader->Class; | |
| 12 | +p: ref Loader->Niladt; | |
| 13 | +x: int; | |
| 14 | +j: JavaAssist; | |
| 15 | + | |
| 16 | +plus(a, b: int): int | |
| 17 | +{ | |
| 18 | + return a + b; | |
| 19 | +} | |
| 20 | + | |
| 21 | +getint(mod: Nilmod, index: int): int | |
| 22 | +{ | |
| 23 | + modref(mod); | |
| 24 | + x = index; | |
| 25 | + return plus(1, 3); | |
| 26 | +} | |
| 27 | + | |
| 28 | +getbytearray(mod: Nilmod, index: int): array of byte | |
| 29 | +{ | |
| 30 | + modref(mod); | |
| 31 | + x = index; | |
| 32 | + return array[1] of byte; | |
| 33 | +} | |
| 34 | + | |
| 35 | +getintarray(mod: Nilmod, index: int): array of int | |
| 36 | +{ | |
| 37 | + modref(mod); | |
| 38 | + x = index; | |
| 39 | + return array[1] of int; | |
| 40 | +} | |
| 41 | + | |
| 42 | +getptr(mod: Nilmod, index: int): ref Loader->Niladt | |
| 43 | +{ | |
| 44 | + modref(mod); | |
| 45 | + x = index; | |
| 46 | + return p; | |
| 47 | +} | |
| 48 | + | |
| 49 | +getreloc(mod: Nilmod, index: int): array of JavaClassLoader->Reloc | |
| 50 | +{ | |
| 51 | + modref(mod); | |
| 52 | + x = index; | |
| 53 | + return r; | |
| 54 | +} | |
| 55 | + | |
| 56 | +getrtreloc(data: ref Loader->Niladt, index: int): array of JavaClassLoader->RTReloc | |
| 57 | +{ | |
| 58 | + p = data; | |
| 59 | + x = index; | |
| 60 | + return nil; | |
| 61 | +} | |
| 62 | + | |
| 63 | +getclassadt(data: ref Loader->Niladt, index: int): ref JavaClassLoader->Class | |
| 64 | +{ | |
| 65 | + p = data; | |
| 66 | + x = index; | |
| 67 | + return nil; | |
| 68 | +} | |
| 69 | + | |
| 70 | +getabsint(addr: int): int | |
| 71 | +{ | |
| 72 | + return 0; | |
| 73 | +} | |
| 74 | + | |
| 75 | +getadtstring(data: ref Loader->Niladt, index: int): string | |
| 76 | +{ | |
| 77 | + p = data; | |
| 78 | + x = index; | |
| 79 | + return nil; | |
| 80 | +} | |
| 81 | + | |
| 82 | +getstring(mod: Nilmod, index: int): string | |
| 83 | +{ | |
| 84 | + modref(mod); | |
| 85 | + x = index; | |
| 86 | + return s; | |
| 87 | +} | |
| 88 | + | |
| 89 | +mnew(mod: Nilmod, index: int): ref Loader->Niladt | |
| 90 | +{ | |
| 91 | + modref(mod); | |
| 92 | + x = index; | |
| 93 | + return p; | |
| 94 | +} | |
| 95 | + | |
| 96 | +putclass(data: ref Loader->Niladt, index: int, value: ref JavaClassLoader->Class) | |
| 97 | +{ | |
| 98 | + p = data; | |
| 99 | + x = index; | |
| 100 | + c = value; | |
| 101 | +} | |
| 102 | + | |
| 103 | +putint(data: ref Loader->Niladt, index: int, value: int) | |
| 104 | +{ | |
| 105 | + p = data; | |
| 106 | + x = index; | |
| 107 | + x = value; | |
| 108 | +} | |
| 109 | + | |
| 110 | +putmod(data: ref Loader->Niladt, index: int, value: Nilmod) | |
| 111 | +{ | |
| 112 | + p = data; | |
| 113 | + x = index; | |
| 114 | + modref(value); | |
| 115 | +} | |
| 116 | + | |
| 117 | +putobj(data: ref Loader->Niladt, index: int, value: ref JavaClassLoader->ClassObject) | |
| 118 | +{ | |
| 119 | + p = data; | |
| 120 | + x = index; | |
| 121 | + o := value; | |
| 122 | +} | |
| 123 | + | |
| 124 | +putptr(data: ref Loader->Niladt, index: int, value: ref Loader->Niladt) | |
| 125 | +{ | |
| 126 | + p = data; | |
| 127 | + x = index; | |
| 128 | + p = value; | |
| 129 | +} | |
| 130 | + | |
| 131 | +putstring(data: ref Loader->Niladt, index: int, value: string) | |
| 132 | +{ | |
| 133 | + p = data; | |
| 134 | + x = index; | |
| 135 | + s = value; | |
| 136 | +} | |
| 137 | + | |
| 138 | +modref(nil: Nilmod) | |
| 139 | +{ | |
| 140 | +} | |
| 141 | + | |
| 142 | +modref2(nil, nil: Nilmod) | |
| 143 | +{ | |
| 144 | +} | |
| 145 | + | |
| 146 | +little_endian(): int | |
| 147 | +{ | |
| 148 | + return 1; | |
| 149 | +} | |
| 150 | + | |
| 151 | +jclnilmod(nil: JavaClassLoader): Nilmod | |
| 152 | +{ | |
| 153 | + return nil; | |
| 154 | +} | |
| 155 | + | |
| 156 | +sysnilmod(nil: Sys): Nilmod | |
| 157 | +{ | |
| 158 | + return nil; | |
| 159 | +} | |
| 160 | + | |
| 161 | +new(mod: Nilmod, index: int): ref JavaClassLoader->Object | |
| 162 | +{ | |
| 163 | + modref(mod); | |
| 164 | + x = index; | |
| 165 | + return nil; | |
| 166 | +} | |
| 167 | + | |
| 168 | +getobjclass(j: ref JavaClassLoader->Object): ref JavaClassLoader->Class | |
| 169 | +{ | |
| 170 | + a := j.mod; | |
| 171 | + return nil; | |
| 172 | +} | |
| 173 | + | |
| 174 | +modhash(mod: Nilmod): int | |
| 175 | +{ | |
| 176 | + modref(mod); | |
| 177 | + return i & 16r7FFFFFFF; | |
| 178 | +} | |
| 179 | + | |
| 180 | +objhash(nil: ref JavaClassLoader->Object): int | |
| 181 | +{ | |
| 182 | + return 0; | |
| 183 | +} | |
| 184 | + | |
| 185 | +mcall0(nil: Nilmod, nil: int): int | |
| 186 | +{ | |
| 187 | + return j->little_endian(); | |
| 188 | +} | |
| 189 | + | |
| 190 | +mcall1(nil: Nilmod, nil: int, nil: ref JavaClassLoader->Object): ref JavaClassLoader->Object | |
| 191 | +{ | |
| 192 | + return j->JStoObject(nil); | |
| 193 | +} | |
| 194 | + | |
| 195 | +mcalla(nil: Nilmod, nil: int, nil: ref JavaClassLoader->Array): int | |
| 196 | +{ | |
| 197 | + return 0; | |
| 198 | +} | |
| 199 | + | |
| 200 | +mcallm(nil: Nilmod, nil: int, arg: Nilmod): int | |
| 201 | +{ | |
| 202 | + return j->modhash(arg); | |
| 203 | +} | |
| 204 | + | |
| 205 | +getstrarray(mod: Nilmod, index: int): array of string | |
| 206 | +{ | |
| 207 | + modref(mod); | |
| 208 | + x = index; | |
| 209 | + return array[1] of string; | |
| 210 | +} | |
| 211 | + | |
| 212 | +arrayof(nil: ref JavaClassLoader->Object): ref JavaClassLoader->Array | |
| 213 | +{ | |
| 214 | + return nil; | |
| 215 | +} | |
| 216 | + | |
| 217 | +bytearraytoJS(nil: array of byte): array of ref JavaClassLoader->JavaString | |
| 218 | +{ | |
| 219 | + return nil; | |
| 220 | +} | |
| 221 | + | |
| 222 | +intarraytoJS(nil: array of int): array of ref JavaClassLoader->JavaString | |
| 223 | +{ | |
| 224 | + return nil; | |
| 225 | +} | |
| 226 | + | |
| 227 | +bigarraytoJS(nil: array of big): array of ref JavaClassLoader->JavaString | |
| 228 | +{ | |
| 229 | + return nil; | |
| 230 | +} | |
| 231 | + | |
| 232 | +realarraytoJS(nil: array of real): array of ref JavaClassLoader->JavaString | |
| 233 | +{ | |
| 234 | + return nil; | |
| 235 | +} | |
| 236 | + | |
| 237 | +ArraytoJS(nil: ref JavaClassLoader->Array): ref JavaClassLoader->JavaString | |
| 238 | +{ | |
| 239 | + return nil; | |
| 240 | +} | |
| 241 | + | |
| 242 | +JStoObject(nil: ref JavaClassLoader->JavaString): ref JavaClassLoader->Object | |
| 243 | +{ | |
| 244 | + return nil; | |
| 245 | +} | |
| 246 | + | |
| 247 | +ObjecttoJT(nil: ref JavaClassLoader->Object): ref JavaClassLoader->JavaThrowable | |
| 248 | +{ | |
| 249 | + return nil; | |
| 250 | +} | |
| 251 | + | |
| 252 | +getmd(nil: Nilmod): ref Loader->Niladt | |
| 253 | +{ | |
| 254 | + return nil; | |
| 255 | +} | |
| 256 | + | |
| 257 | +makeadt(addr: int): ref Loader->Niladt | |
| 258 | +{ | |
| 259 | + x = addr; | |
| 260 | + return nil; | |
| 261 | +} | |
| @@ -0,0 +1,32 @@ | ||
| 1 | +implement JavaNative; | |
| 2 | + | |
| 3 | +include "jni.m"; | |
| 4 | + | |
| 5 | +# | |
| 6 | +# This is to isolate jni from the classloader. | |
| 7 | +# | |
| 8 | + | |
| 9 | +init(sys: Sys, ld: Loader, jldr: JavaClassLoader, jass: JavaAssist): string | |
| 10 | +{ | |
| 11 | + j := load JNI JNI->PATH; | |
| 12 | + if (j == nil) | |
| 13 | + return sys->sprint("could not load %s: %r", JNI->PATH); | |
| 14 | + (m, s) := j->Self(sys, j); | |
| 15 | + if (s != nil) | |
| 16 | + return s; | |
| 17 | + l := ld->link(m); | |
| 18 | + if (l == nil) | |
| 19 | + return sys->sprint("link failed: %r"); | |
| 20 | + n := len l; | |
| 21 | + t := -1; | |
| 22 | + for (i := 0; i < n; i++) { | |
| 23 | + if (l[i].name == "init") | |
| 24 | + t = i; | |
| 25 | + } | |
| 26 | + if (t == -1) | |
| 27 | + return sys->sprint("%s: not signed", JNI->PATH); | |
| 28 | + jldr->jninil = m; | |
| 29 | + jldr->jnisig = l[t].sig; | |
| 30 | + j->jinit(jldr, jass); | |
| 31 | + return nil; | |
| 32 | +} | |
| @@ -0,0 +1,66 @@ | ||
| 1 | +implement JavaTrace; | |
| 2 | + | |
| 3 | +include "sys.m"; | |
| 4 | + sys: Sys; | |
| 5 | + | |
| 6 | +include "loader.m"; | |
| 7 | +include "classloader.m"; | |
| 8 | + | |
| 9 | +Class, Reloc: import JavaClassLoader; | |
| 10 | +RELOC, CLASSREF, WORDZ: import JavaClassLoader; | |
| 11 | + | |
| 12 | +jassist: JavaAssist; | |
| 13 | + | |
| 14 | + getint, getintarray, getptr, getreloc, getstring: import jassist; | |
| 15 | + | |
| 16 | +init(a: JavaAssist) | |
| 17 | +{ | |
| 18 | + if (sys == nil) | |
| 19 | + sys = load Sys Sys->PATH; | |
| 20 | + jassist = a; | |
| 21 | + level = -1; | |
| 22 | + outfd = sys->fildes(2); | |
| 23 | +} | |
| 24 | + | |
| 25 | +trace(c: int, s: string) | |
| 26 | +{ | |
| 27 | + if (c <= level) | |
| 28 | + sys->fprint(outfd, "%s\n", s); | |
| 29 | +} | |
| 30 | + | |
| 31 | +info(c: ref Class) | |
| 32 | +{ | |
| 33 | + sys->fprint(outfd, "Class: %s [%s]\n", c.name, c.file); | |
| 34 | + sys->fprint(outfd, "--- Relocs ---\n"); | |
| 35 | + pr_relocs(getreloc(c.mod, RELOC)); | |
| 36 | + i := CLASSREF; | |
| 37 | + while ((s := getstring(c.mod, i)) != nil) { | |
| 38 | + sys->fprint(outfd, "--- %s ---\n", s); | |
| 39 | + pr_relocs(getreloc(c.mod, i + WORDZ)); | |
| 40 | + i += 2 * WORDZ; | |
| 41 | + } | |
| 42 | +} | |
| 43 | + | |
| 44 | +pr_reloc(r: Reloc) | |
| 45 | +{ | |
| 46 | + f := r.field; | |
| 47 | + if (f == nil) | |
| 48 | + f = "@"; | |
| 49 | + s := r.signature; | |
| 50 | + if (s == nil) | |
| 51 | + s = "@"; | |
| 52 | + n: int; | |
| 53 | + if (r.patch == nil) | |
| 54 | + n = -1; | |
| 55 | + else | |
| 56 | + n = len r.patch; | |
| 57 | + sys->fprint(outfd, "%s %s %d %d\n", f, s, r.flags, n); | |
| 58 | +} | |
| 59 | + | |
| 60 | +pr_relocs(r: array of JavaClassLoader->Reloc) | |
| 61 | +{ | |
| 62 | + n := len r; | |
| 63 | + for (i := 0; i < n; i++) | |
| 64 | + pr_reloc(r[i]); | |
| 65 | +} | |
| 66 | + | |
| @@ -0,0 +1,25 @@ | ||
| 1 | +implement JInfo; | |
| 2 | + | |
| 3 | +include "sys.m"; | |
| 4 | +include "loader.m"; | |
| 5 | +include "classloader.m"; | |
| 6 | + | |
| 7 | +JInfo: module | |
| 8 | +{ | |
| 9 | + init: fn(ctxt: ref Draw->Context, argv: list of string); | |
| 10 | +}; | |
| 11 | + | |
| 12 | +sys: Sys; | |
| 13 | + | |
| 14 | +init(ctxt: ref Draw->Context, args: list of string) | |
| 15 | +{ | |
| 16 | + sys = load Sys Sys->PATH; | |
| 17 | + cl := load JavaClassLoader JavaClassLoader->PATH; | |
| 18 | + if (cl == nil) { | |
| 19 | + sys->print("could not load %s: %r\n", JavaClassLoader->PATH); | |
| 20 | + exit; | |
| 21 | + } | |
| 22 | + cl->init(cl, ctxt); | |
| 23 | + for (l := tl args; l != nil; l = tl l) | |
| 24 | + cl->info(hd l); | |
| 25 | +} | |
| @@ -0,0 +1,1735 @@ | ||
| 1 | +implement JNI; | |
| 2 | + | |
| 3 | +include "jni.m"; | |
| 4 | +include "hash.m"; | |
| 5 | + | |
| 6 | +cast : Cast; | |
| 7 | +low : Low; | |
| 8 | +hash : Hash; | |
| 9 | + | |
| 10 | +JNI_VER := 16r00010001; | |
| 11 | + | |
| 12 | +# | |
| 13 | +# use the access functions at the bottom to | |
| 14 | +# retrive the values stored here. thease vars | |
| 15 | +# are initialized as late as possible. | |
| 16 | +# | |
| 17 | +string_class, # class data for java.lang.String | |
| 18 | +array_class, # for inferno.vm.Array | |
| 19 | +class_class, # for java.lang.Class | |
| 20 | +throwable_class, # for java.lang.Throwable | |
| 21 | +thread_class # for java.lang.Thread | |
| 22 | + : ClassData; | |
| 23 | + | |
| 24 | +# cache the main thread group | |
| 25 | +mainthreadgroup : JObject; | |
| 26 | + | |
| 27 | +GetVersion() : int | |
| 28 | +{ | |
| 29 | + return( JNI_VER ); | |
| 30 | +} | |
| 31 | + | |
| 32 | + | |
| 33 | +FindClass( name : string ) : ClassData | |
| 34 | +{ | |
| 35 | + # return class data adt used by the Java Loader | |
| 36 | + # which stores all the class information. | |
| 37 | + | |
| 38 | + # replace all ocurrences of "." with "/" in name | |
| 39 | + newname : string; | |
| 40 | + for(x:=0;x<len name; x++) | |
| 41 | + { | |
| 42 | + if (name[x]=='.') | |
| 43 | + newname[x] = '/'; | |
| 44 | + else | |
| 45 | + newname[x] = name[x]; | |
| 46 | + } | |
| 47 | + cl_data : ClassData; | |
| 48 | + if ( newname != nil && newname[0] == '[' ) { | |
| 49 | + class := LookupArrayClass(newname); | |
| 50 | + cl_data = class.class; | |
| 51 | + } else { | |
| 52 | + cl_data = jldr->loader(newname); | |
| 53 | + } | |
| 54 | + return cl_data; | |
| 55 | +} | |
| 56 | + | |
| 57 | +getContext(): ref Draw->Context | |
| 58 | +{ | |
| 59 | + return(jldr->getcontext()); | |
| 60 | +} | |
| 61 | + | |
| 62 | + | |
| 63 | +GetSuperclass( cl_data : ClassData ) : ClassData | |
| 64 | +{ | |
| 65 | + # we need the superclass of this | |
| 66 | + # class. | |
| 67 | + if ( cl_data == nil ) | |
| 68 | + return(nil); | |
| 69 | + return( cl_data.super ); | |
| 70 | +} | |
| 71 | + | |
| 72 | + | |
| 73 | +# | |
| 74 | +# Return the java.lang.Class instance associated | |
| 75 | +# with this instance. | |
| 76 | +# | |
| 77 | +GetObjectClass( obj : JObject ) : JClass | |
| 78 | +{ | |
| 79 | + if ( obj == nil ) | |
| 80 | + return( nil ); | |
| 81 | + # return the class of this obj | |
| 82 | + Object : import jldr; | |
| 83 | + cldata := obj.class(); | |
| 84 | + if ( cldata == nil ) | |
| 85 | + ThrowException( "java/lang/InternalError", "could not get objects class data" ); | |
| 86 | + if ( cldata.name == "inferno/vm/Array" ) | |
| 87 | + { | |
| 88 | + # handle arrays specially synthesize a unique class object | |
| 89 | + # for each type of array, and cache it for future use. | |
| 90 | + # this blows memory, but java requires a unique class object | |
| 91 | + # so two [[I's must result in the same class | |
| 92 | + return( ArrayClassObject( cast->ToJArray(obj) ) ); | |
| 93 | + } | |
| 94 | + return( GetClassObject( cldata ) ); | |
| 95 | +} | |
| 96 | + | |
| 97 | +# | |
| 98 | +# Return the internal Class Data information | |
| 99 | +# associated with this instance | |
| 100 | +# | |
| 101 | +GetObjectClassData( obj : JObject ) : ClassData | |
| 102 | +{ | |
| 103 | + if ( obj == nil ) | |
| 104 | + return( nil ); | |
| 105 | + # return the class of this obj | |
| 106 | + Object : import jldr; | |
| 107 | + return( obj.class() ); | |
| 108 | +} | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | +# | |
| 113 | +# return the associated java.lang.Class instance | |
| 114 | +# associated with the given internal Class | |
| 115 | +# Data. | |
| 116 | +# | |
| 117 | +GetClassObject( cl_data : ClassData ) : JClass | |
| 118 | +{ | |
| 119 | + if ( cl_data == nil ) | |
| 120 | + return( nil ); | |
| 121 | + # return the stored java.lang.Class instance | |
| 122 | + classobj := cl_data.this; | |
| 123 | + | |
| 124 | + if ( classobj.mod == nil ) | |
| 125 | + { | |
| 126 | + # first time, we used this object, we | |
| 127 | + # must patch the objects's 'mod' field. | |
| 128 | + classobj.mod = classclass().moddata; | |
| 129 | + } | |
| 130 | + | |
| 131 | + return( classobj ); | |
| 132 | +} | |
| 133 | + | |
| 134 | + | |
| 135 | +SetStaticField( class : ClassData, name : string, val : ref Value ) : int | |
| 136 | +{ | |
| 137 | + # get field info | |
| 138 | + Class : import jldr; | |
| 139 | + | |
| 140 | + if ( (class == nil) || (val == nil) ) | |
| 141 | + return( ERR ); | |
| 142 | + | |
| 143 | + field := class.findsfield( name ); | |
| 144 | + | |
| 145 | + if ( ! CheckField( field, val ) ) | |
| 146 | + return( ERR ); | |
| 147 | + | |
| 148 | + # static data is located in the "module data" | |
| 149 | + # of the module wich corresponds to the class. | |
| 150 | + # we can get this from the class.mod field and | |
| 151 | + # then we must convert it to a "generic" Niladt | |
| 152 | + ptr := jassist->getmd( class.mod ); | |
| 153 | + | |
| 154 | + # check offset and compute absolute offset | |
| 155 | + if ( field.value >= class.staticsize ) | |
| 156 | + return( ERR ); | |
| 157 | + | |
| 158 | + off := class.staticoffset + field.value; | |
| 159 | + | |
| 160 | + return( SetField( ptr, off, val ) ); | |
| 161 | +} | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | +GetStaticField( class : ClassData, name : string, typsig : string ) : ref Value | |
| 166 | +{ | |
| 167 | + # get field info | |
| 168 | + Class : import jldr; | |
| 169 | + | |
| 170 | + if ( class == nil ) | |
| 171 | + return( nil ); | |
| 172 | + | |
| 173 | + field := class.findsfield( name ); | |
| 174 | + | |
| 175 | + if ( (field == nil) || (field.signature != typsig) ) | |
| 176 | + return( nil ); | |
| 177 | + | |
| 178 | + # Static data is located in the "module data" | |
| 179 | + # of the module which corresponds to the class. | |
| 180 | + # We can get this from the class.mod field and | |
| 181 | + # then we must convert it to a "generic" Niladt | |
| 182 | + ptr := jassist->getmd( class.mod ); | |
| 183 | + | |
| 184 | + # check offset and compute absolute offset | |
| 185 | + if ( field.value >= class.staticsize ) | |
| 186 | + return( nil ); | |
| 187 | + | |
| 188 | + off := class.staticoffset + field.value; | |
| 189 | + | |
| 190 | + return( GetField( ptr, off, typsig[0] ) ); | |
| 191 | +} | |
| 192 | + | |
| 193 | + | |
| 194 | +SetObjField( object : JObject, name : string, val : ref Value ) : int | |
| 195 | +{ | |
| 196 | + # get field info | |
| 197 | + Object : import jldr; | |
| 198 | + Class : import jldr; | |
| 199 | + | |
| 200 | + if ( (object == nil) || (val == nil) ) | |
| 201 | + return( ERR ); | |
| 202 | + | |
| 203 | + class := object.class(); | |
| 204 | + field := class.findofield( name ); | |
| 205 | + | |
| 206 | + if ( ! CheckField( field, val ) ) | |
| 207 | + return( ERR ); | |
| 208 | + | |
| 209 | + # convert the object to a "generic" Niladt | |
| 210 | + ptr := cast->Obj2Niladt(object); | |
| 211 | + | |
| 212 | + # check offset and compute absolute offset | |
| 213 | + if ( field.value >= class.objectsize ) | |
| 214 | + return( ERR ); | |
| 215 | + | |
| 216 | + SetField( ptr, field.value, val ); | |
| 217 | + | |
| 218 | + return( OK ); | |
| 219 | +} | |
| 220 | + | |
| 221 | + | |
| 222 | +GetObjField( object : JObject, name : string, typsig : string ) : ref Value | |
| 223 | +{ | |
| 224 | + # get field info | |
| 225 | + Object : import jldr; | |
| 226 | + Class : import jldr; | |
| 227 | + | |
| 228 | + if ( object == nil ) | |
| 229 | + return( nil ); | |
| 230 | + | |
| 231 | + class := object.class(); | |
| 232 | + field := class.findofield( name ); | |
| 233 | + | |
| 234 | + if ( (field == nil) || (field.signature != typsig) ) | |
| 235 | + return( nil ); | |
| 236 | + | |
| 237 | + # convert the object to a "generic" Niladt | |
| 238 | + ptr := cast->Obj2Niladt(object); | |
| 239 | + | |
| 240 | + # check offset and compute absolute offset | |
| 241 | + if ( field.value >= class.objectsize ) | |
| 242 | + return( nil ); | |
| 243 | + | |
| 244 | + return( GetField( ptr, field.value, typsig[0] ) ); | |
| 245 | +} | |
| 246 | + | |
| 247 | + | |
| 248 | +CallStatic( cldata : ClassData, meth : string, sig : string, args : array of ref Value ) : (ref Value,int) | |
| 249 | +{ | |
| 250 | + # lookup method first | |
| 251 | + (mod,idx) := FindMethod( cldata, meth, sig, METH_STATIC ); | |
| 252 | + | |
| 253 | + if ( mod == nil ) | |
| 254 | + return( nil, CALLERR_NOMETHOD ); | |
| 255 | + | |
| 256 | + # check args against sig | |
| 257 | + (fctdesc, err) := CheckMethodArgs( sig, args ); | |
| 258 | + if ( err ) | |
| 259 | + return( nil, err ); | |
| 260 | + | |
| 261 | + retval : ref Value; | |
| 262 | + if ( fctdesc != nil ) | |
| 263 | + { | |
| 264 | + # create a Value to hold function result | |
| 265 | + if ( fctdesc.class != nil ) | |
| 266 | + retval = ref Value.TObject; | |
| 267 | + else | |
| 268 | + case fctdesc.prim | |
| 269 | + { | |
| 270 | + T_BOOLEAN => retval = ref Value.TBoolean; | |
| 271 | + T_CHAR => retval = ref Value.TChar; | |
| 272 | + T_FLOAT => retval = ref Value.TFloat; | |
| 273 | + T_DOUBLE => retval = ref Value.TDouble; | |
| 274 | + T_BYTE => retval = ref Value.TByte; | |
| 275 | + T_SHORT => retval = ref Value.TShort; | |
| 276 | + T_INT => retval = ref Value.TInt; | |
| 277 | + T_LONG => retval = ref Value.TLong; | |
| 278 | + * => return( nil, ERR ); | |
| 279 | + } | |
| 280 | + } | |
| 281 | + | |
| 282 | + low->CallMethod( mod, idx, nil, args, retval ); | |
| 283 | + return( retval, OK ); | |
| 284 | + | |
| 285 | +} | |
| 286 | + | |
| 287 | +CallMethod( obj : JObject, meth : string, sig : string, args : array of ref Value ) : (ref Value,int) | |
| 288 | +{ | |
| 289 | + # lookup method first | |
| 290 | + cldata := GetObjectClassData(obj); | |
| 291 | + (mod,idx) := FindMethod( cldata, meth, sig, (METH_VIRTUAL|METH_PRIVATE|METH_INIT) ); | |
| 292 | + | |
| 293 | + if ( mod == nil ) | |
| 294 | + return( nil, CALLERR_NOMETHOD ); | |
| 295 | + | |
| 296 | + # check args against sig -- sig can be assumed to be a | |
| 297 | + # valid meth sig, since a matching meth was found above | |
| 298 | + (fctdesc, err) := CheckMethodArgs( sig, args ); | |
| 299 | + if ( err ) | |
| 300 | + return( nil, err ); | |
| 301 | + | |
| 302 | + retval : ref Value; | |
| 303 | + if ( fctdesc != nil ) | |
| 304 | + { | |
| 305 | + # create a Value to hold function result | |
| 306 | + if ( fctdesc.class != nil ) | |
| 307 | + retval = ref Value.TObject; | |
| 308 | + else | |
| 309 | + case fctdesc.prim | |
| 310 | + { | |
| 311 | + T_BOOLEAN => retval = ref Value.TBoolean; | |
| 312 | + T_CHAR => retval = ref Value.TChar; | |
| 313 | + T_FLOAT => retval = ref Value.TFloat; | |
| 314 | + T_DOUBLE => retval = ref Value.TDouble; | |
| 315 | + T_BYTE => retval = ref Value.TByte; | |
| 316 | + T_SHORT => retval = ref Value.TShort; | |
| 317 | + T_INT => retval = ref Value.TInt; | |
| 318 | + T_LONG => retval = ref Value.TLong; | |
| 319 | + * => return( nil, ERR ); | |
| 320 | + } | |
| 321 | + } | |
| 322 | + | |
| 323 | + low->CallMethod( mod, idx, obj, args, retval ); | |
| 324 | + return( retval, OK ); | |
| 325 | +} | |
| 326 | + | |
| 327 | + | |
| 328 | +LowCall( mod : Nilmod, idx : int, this : JNI->JObject, args : array of ref JNI->Value, retval : ref JNI->Value ) | |
| 329 | +{ | |
| 330 | + low->CallMethod( mod, idx, this, args, retval ); | |
| 331 | +} | |
| 332 | + | |
| 333 | + | |
| 334 | +# return modifiers | |
| 335 | + | |
| 336 | +GetClassFlags(jcl : JClass) : int | |
| 337 | +{ | |
| 338 | + if ( jcl == nil ) | |
| 339 | + return 0; | |
| 340 | + return jcl.class.flags; | |
| 341 | +} | |
| 342 | + | |
| 343 | +GetFieldFlags(jcl : JClass, namesig : string) : int | |
| 344 | +{ | |
| 345 | + Class : import jldr; | |
| 346 | + | |
| 347 | + if ( jcl == nil || len namesig == 0 ) | |
| 348 | + return 0; | |
| 349 | + (name, sig) := str->splitl(namesig, " "); | |
| 350 | + if ( len sig == 0 ) | |
| 351 | + return 0; | |
| 352 | + sig = sig[1:]; | |
| 353 | + | |
| 354 | + field := jcl.class.findsfield(name); | |
| 355 | + if ( field != nil && field.signature == sig ) | |
| 356 | + return field.flags; | |
| 357 | + | |
| 358 | + object := jcl.class.objectdata; | |
| 359 | + super := GetSuperclass(jcl.class); | |
| 360 | + while ( object != nil && object != super.objectdata ) { | |
| 361 | + field = hd object; | |
| 362 | + if ( field.field == name && field.signature == sig ) | |
| 363 | + return field.flags; | |
| 364 | + object = tl object; | |
| 365 | + } | |
| 366 | + return 0; | |
| 367 | +} | |
| 368 | + | |
| 369 | +GetMethodFlags(jcl : JClass, namesig : string) : int | |
| 370 | +{ | |
| 371 | + Class : import jldr; | |
| 372 | + | |
| 373 | + if ( jcl == nil || len namesig == 0 ) | |
| 374 | + return 0; | |
| 375 | + (name, sig) := str->splitl(namesig, " "); | |
| 376 | + if ( len sig == 0 ) | |
| 377 | + return 0; | |
| 378 | + sig = sig[1:]; | |
| 379 | + | |
| 380 | + method := jcl.class.findsmethod(name, sig); | |
| 381 | + if ( method != nil ) | |
| 382 | + return method.flags; | |
| 383 | + | |
| 384 | + method = jcl.class.findpmethod(name, sig); | |
| 385 | + if ( method != nil ) | |
| 386 | + return method.flags; | |
| 387 | + | |
| 388 | + method = jcl.class.findimethod(sig); | |
| 389 | + if ( method != nil ) | |
| 390 | + return method.flags; | |
| 391 | + | |
| 392 | + vindex := jcl.class.findvmethod(name, sig); | |
| 393 | + if ( vindex > -1 ) { | |
| 394 | + vmethod := jcl.class.virtualmethods[vindex]; | |
| 395 | + if ( vmethod.class == jcl.class ) | |
| 396 | + return vmethod.field.flags; | |
| 397 | + } | |
| 398 | + return 0; | |
| 399 | +} | |
| 400 | + | |
| 401 | +# Return array of names combined with signatures. | |
| 402 | + | |
| 403 | +GetFieldSignatures(jcl : JClass, excl : int) : JArrayJString | |
| 404 | +{ | |
| 405 | + Class : import jldr; | |
| 406 | + | |
| 407 | + jary := array[0] of string; | |
| 408 | + if ( jcl == nil ) | |
| 409 | + return MkAString(jary); | |
| 410 | + class := jcl.class; | |
| 411 | + static := class.staticdata; | |
| 412 | + object := class.objectdata; | |
| 413 | + jary = array[len static + len object] of string; | |
| 414 | + l := len static; | |
| 415 | + i := 0; | |
| 416 | + for ( j := 0; j < l; j++ ) { | |
| 417 | + field := static[j]; | |
| 418 | + tmpf := field.flags & ACC_WRITTEN_FLAGS; | |
| 419 | + if ( (tmpf & excl) != 0 ) | |
| 420 | + continue; | |
| 421 | + jary[i++] = field.field + " " + field.signature; | |
| 422 | + } | |
| 423 | + for ( ; object != nil && object != class.super.objectdata; object = tl object ) { | |
| 424 | + field := hd object; | |
| 425 | + tmpf := field.flags & ACC_WRITTEN_FLAGS; | |
| 426 | + if ( (tmpf & excl) != 0 ) | |
| 427 | + continue; | |
| 428 | + jary[i++] = field.field + " " + field.signature; | |
| 429 | + } | |
| 430 | + if ( i < len jary ) { | |
| 431 | + newj := array[i] of string; | |
| 432 | + for ( j = 0; j < i; j++ ) | |
| 433 | + newj[j] = jary[j]; | |
| 434 | + jary = newj; | |
| 435 | + } | |
| 436 | + return MkAString(jary); | |
| 437 | +} | |
| 438 | + | |
| 439 | +GetMethodSignatures(jcl : JClass, excl : int) : JArrayJString | |
| 440 | +{ | |
| 441 | + Class : import jldr; | |
| 442 | + | |
| 443 | + jary := array[0] of string; | |
| 444 | + if ( jcl == nil ) | |
| 445 | + return MkAString(jary); | |
| 446 | + class := jcl.class; | |
| 447 | + static := class.staticmethods; | |
| 448 | + virtual := class.virtualmethods; | |
| 449 | + private := class.privatemethods; | |
| 450 | + construct := class.initmethods; | |
| 451 | + l := len static; | |
| 452 | + jary = array[l + len virtual + len private + len construct + 1] of string; | |
| 453 | + | |
| 454 | + i := 0; | |
| 455 | + if ( class.classinit != nil ) | |
| 456 | + jary[i++] = class.classinit.field + " " + class.classinit.signature; | |
| 457 | + | |
| 458 | + for ( j := 0; j < l; j++ ) { | |
| 459 | + method := static[j]; | |
| 460 | + tmpf := method.flags & ACC_WRITTEN_FLAGS; | |
| 461 | + if ( (tmpf & excl) != 0 ) | |
| 462 | + continue; | |
| 463 | + jary[i++] = method.field + " " + method.signature; | |
| 464 | + } | |
| 465 | + l = len virtual; | |
| 466 | + for ( j = 0; j < l; j++ ) { | |
| 467 | + vmethod := virtual[j]; | |
| 468 | + if ( vmethod.class != class ) | |
| 469 | + continue; | |
| 470 | + method := vmethod.field; | |
| 471 | + tmpf := method.flags & ACC_WRITTEN_FLAGS; | |
| 472 | + if ( (tmpf & excl) != 0 ) | |
| 473 | + continue; | |
| 474 | + jary[i++] = method.field + " " + method.signature; | |
| 475 | + } | |
| 476 | + l = len private; | |
| 477 | + for ( j = 0; j < l; j++ ) { | |
| 478 | + method := private[j]; | |
| 479 | + tmpf := method.flags & ACC_WRITTEN_FLAGS; | |
| 480 | + if ( (tmpf & excl) != 0 ) | |
| 481 | + continue; | |
| 482 | + jary[i++] = method.field + " " + method.signature; | |
| 483 | + } | |
| 484 | + l = len construct; | |
| 485 | + for ( j = 0; j < l; j++ ) { | |
| 486 | + method := construct[j]; | |
| 487 | + tmpf := method.flags & ACC_WRITTEN_FLAGS; | |
| 488 | + if ( (tmpf & excl) != 0 ) | |
| 489 | + continue; | |
| 490 | + jary[i++] = method.field + " " + method.signature; | |
| 491 | + } | |
| 492 | + if ( i < len jary ) { | |
| 493 | + newj := array[i] of string; | |
| 494 | + for ( j = 0; j < i; j++ ) | |
| 495 | + newj[j] = jary[j]; | |
| 496 | + jary = newj; | |
| 497 | + } | |
| 498 | + return MkAString(jary); | |
| 499 | +} | |
| 500 | + | |
| 501 | +# make a temporary JArray for IsAssignable() | |
| 502 | +tmpJArray( c : JClass ) : JArray | |
| 503 | +{ | |
| 504 | + desc := JSigToDescriptor( c.aryname ); | |
| 505 | + return JArray(arrayclass().moddata, nil, desc.dims, desc.class, desc.prim); | |
| 506 | +} | |
| 507 | + | |
| 508 | +# can src be assigned to dst? | |
| 509 | +IsAssignable( src, dst : JClass ) : JBoolean | |
| 510 | +{ | |
| 511 | + if ( (src==nil) || (dst==nil) ) | |
| 512 | + return( FALSE ); | |
| 513 | + | |
| 514 | + if ( dst.aryname != nil ) { | |
| 515 | + if ( src.aryname == nil ) | |
| 516 | + return( FALSE ); | |
| 517 | + jasrc := tmpJArray(src); | |
| 518 | + jadst := tmpJArray(dst); | |
| 519 | + if ( jadst.class == nil ) | |
| 520 | + return jldr->pinstanceof(jasrc, jadst.primitive, jadst.dims); | |
| 521 | + else | |
| 522 | + return jldr->ainstanceof(jasrc, jadst.class, jadst.dims); | |
| 523 | + } | |
| 524 | + | |
| 525 | + return( jldr->compatclass(src.class, dst.class) ); | |
| 526 | +} | |
| 527 | + | |
| 528 | +IsInstanceOf( obj : JObject, cl_data : ClassData ) : JBoolean | |
| 529 | +{ | |
| 530 | + if ( cl_data == nil ) | |
| 531 | + return( FALSE ); | |
| 532 | + return( jldr->instanceof( obj, cl_data ) ); | |
| 533 | +} | |
| 534 | + | |
| 535 | + | |
| 536 | +ArrayInstanceOf( ary : JArray, desc : ref Descriptor ) : JBoolean | |
| 537 | +{ | |
| 538 | + if ( (ary != nil) && (desc != nil) ) | |
| 539 | + { | |
| 540 | + # is it a array of ref or array of primitive | |
| 541 | + if ( ary.class != nil ) | |
| 542 | + return( jldr->ainstanceof(ary, desc.class, desc.dims) ); | |
| 543 | + else | |
| 544 | + return( jldr->pinstanceof(ary, desc.prim, desc.dims) ); | |
| 545 | + } | |
| 546 | + # not an array or not expected instance | |
| 547 | + return( FALSE ); | |
| 548 | +} | |
| 549 | + | |
| 550 | + | |
| 551 | +IsArray( obj : JObject ) : JBoolean | |
| 552 | +{ | |
| 553 | + if ( obj == nil ) | |
| 554 | + return( FALSE ); | |
| 555 | + | |
| 556 | + return( IsInstanceOf( obj, arrayclass() ) ); | |
| 557 | +} | |
| 558 | + | |
| 559 | + | |
| 560 | +# are obj1 and obj2 the same object | |
| 561 | +IsSameObject( obj1, obj2 : JObject ) : JBoolean | |
| 562 | +{ | |
| 563 | + return( obj1 == obj2 ); | |
| 564 | +} | |
| 565 | + | |
| 566 | +# Return T_BOOLEAN..T_LONG, T_VOID or 0 according to whether c represents | |
| 567 | +# a Java primitive type. If ignorevoid != 0, return 0 for 'void'; | |
| 568 | +# refection code generally wants to ignore void. | |
| 569 | + | |
| 570 | +PrimitiveIndex(c : JClass, ignorevoid : int) : int | |
| 571 | +{ | |
| 572 | + clname := c.class.name; # name of class | |
| 573 | + prefix : con "inferno/vm/"; # will begin with this if primitive | |
| 574 | + prefix_len : con len prefix; | |
| 575 | + ret := 0; | |
| 576 | + if ( len clname > prefix_len && prefix == clname[:prefix_len] ) | |
| 577 | + { | |
| 578 | + # check rest of name | |
| 579 | + suffix := clname[prefix_len:]; | |
| 580 | + case ( suffix ) | |
| 581 | + { | |
| 582 | + # primitive class names | |
| 583 | + "boolean_p" => | |
| 584 | + ret = T_BOOLEAN; | |
| 585 | + "byte_p" => | |
| 586 | + ret = T_BYTE; | |
| 587 | + "char_p" => | |
| 588 | + ret = T_CHAR; | |
| 589 | + "short_p" => | |
| 590 | + ret = T_SHORT; | |
| 591 | + "int_p" => | |
| 592 | + ret = T_INT; | |
| 593 | + "long_p" => | |
| 594 | + ret = T_LONG; | |
| 595 | + "float_p" => | |
| 596 | + ret = T_FLOAT; | |
| 597 | + "double_p" => | |
| 598 | + ret = T_DOUBLE; | |
| 599 | + "void_p" => | |
| 600 | + if ( ! ignorevoid ) | |
| 601 | + ret = T_VOID; | |
| 602 | + } | |
| 603 | + } | |
| 604 | + return ret; | |
| 605 | +} | |
| 606 | + | |
| 607 | +# | |
| 608 | +# throw the object | |
| 609 | +# | |
| 610 | +Throw( throwable : JObject ) | |
| 611 | +{ | |
| 612 | + if ( jldr->instanceof( throwable, throwableclass() ) ) | |
| 613 | + jldr->throw( throwable ); | |
| 614 | + | |
| 615 | + FatalError( "JNI Error: attempt to throw a non-throwable object" ); | |
| 616 | +} | |
| 617 | + | |
| 618 | + | |
| 619 | +# | |
| 620 | +# create an instance of the throwable class 'name' | |
| 621 | +# fill it with 'msg' and throw it | |
| 622 | +# | |
| 623 | +ThrowException( name : string, msg : string ) | |
| 624 | +{ | |
| 625 | + class := FindClass( name ); | |
| 626 | + if ( (class != nil) && (jldr->compatclass( class, throwableclass() )) ) | |
| 627 | + { | |
| 628 | + obj := AllocObject( class ); | |
| 629 | + | |
| 630 | + # put msg into the object and throw the object | |
| 631 | + args := array [1] of ref Value; | |
| 632 | + args[0] = ref Value.TObject(cast->FromJString(NewString(msg))); | |
| 633 | + #if ( SetObjField( obj, "detailMessage", val ) == OK ) | |
| 634 | + (val,err) := CallMethod( obj, "<init>", "(Ljava/lang/String;)V", args ); | |
| 635 | + | |
| 636 | + # throw regardless of constructor call | |
| 637 | + jldr->throw( obj ); | |
| 638 | + } | |
| 639 | + | |
| 640 | + FatalError( sys->sprint("JNI Error: while throwing an Exception[%s:%s]", | |
| 641 | + name, msg ) ); | |
| 642 | +} | |
| 643 | + | |
| 644 | +# | |
| 645 | +# return a Java Exception | |
| 646 | +# | |
| 647 | +JavaException( ex : string ) : JObject | |
| 648 | +{ | |
| 649 | + # grab any Java object currently being thrown. | |
| 650 | + jthrow := jldr->getthreaddata().culprit; | |
| 651 | + | |
| 652 | + # if ex is nil then the caller is just querying for | |
| 653 | + # the current java throwable so just return 'jthrow' | |
| 654 | + | |
| 655 | + # if jthrow is non-nil then return it and ignore ex | |
| 656 | + | |
| 657 | + if ( (jthrow != nil) || (ex == nil) ) | |
| 658 | + return( jthrow ); | |
| 659 | + | |
| 660 | + # if no java throwable but we have a non-nil ex then | |
| 661 | + # convert the Inferno exception to an appropriate Java ex. | |
| 662 | + # this will always produce a Java throwable object | |
| 663 | + return( jldr->sysexception(ex) ); | |
| 664 | + | |
| 665 | +} | |
| 666 | + | |
| 667 | +# | |
| 668 | +# clear the exception of the current thread. | |
| 669 | +# | |
| 670 | +ExceptionClear() | |
| 671 | +{ | |
| 672 | + thd := jldr->getthreaddata(); | |
| 673 | + thd.culprit = nil; | |
| 674 | +} | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | +# allocate a new instance of the class; no constructor called | |
| 679 | +AllocObject( cl_data : ClassData ) : JObject | |
| 680 | +{ | |
| 681 | + Class : import jldr; | |
| 682 | + | |
| 683 | + if ( cl_data == nil ) | |
| 684 | + return( nil ); | |
| 685 | + | |
| 686 | + obj := jassist->new(cl_data.mod, cl_data.objtype); | |
| 687 | + obj.mod = cl_data.moddata; | |
| 688 | + return( obj ); | |
| 689 | +} | |
| 690 | + | |
| 691 | + | |
| 692 | +# allocate a new instance of the class; call default constructor | |
| 693 | +NewObject( cl_data : ClassData ) : JObject | |
| 694 | +{ | |
| 695 | + Class : import jldr; | |
| 696 | + | |
| 697 | + if ( cl_data == nil ) | |
| 698 | + return( nil ); | |
| 699 | + | |
| 700 | + return( cl_data.new() ); | |
| 701 | +} | |
| 702 | + | |
| 703 | + | |
| 704 | +# | |
| 705 | +# Create an instance of java.lang.Class which | |
| 706 | +# represents a specific java class. This | |
| 707 | +# instance contains a ptr to its own class | |
| 708 | +# information, as well as a ptr to the class | |
| 709 | +# it represents. | |
| 710 | +# | |
| 711 | +NewClassObject( targ_class : ClassData ) : JClass | |
| 712 | +{ | |
| 713 | + # create an instance of java.lang.Class | |
| 714 | + cl_data := classclass(); | |
| 715 | + return( JClass(classclass().moddata, targ_class, nil) ); | |
| 716 | +} | |
| 717 | + | |
| 718 | + | |
| 719 | +NewString( val : string ) : JString | |
| 720 | +{ | |
| 721 | + return( JString( stringclass().moddata, val ) ); | |
| 722 | +} | |
| 723 | + | |
| 724 | +# | |
| 725 | +# just like above but return as a | |
| 726 | +# JObject type, rather then JString | |
| 727 | +# | |
| 728 | +NewStringObject( val : string ) : JObject | |
| 729 | +{ | |
| 730 | + # create a java string instance | |
| 731 | + jstr := JString( stringclass().moddata, val ); | |
| 732 | + | |
| 733 | + return( cast->FromJString(jstr) ); | |
| 734 | +} | |
| 735 | + | |
| 736 | +# duplicate the object | |
| 737 | +DupObject( src : JObject ) : JObject | |
| 738 | +{ | |
| 739 | + Object : import jldr; | |
| 740 | + Class : import jldr; | |
| 741 | + newobj : JObject; | |
| 742 | + | |
| 743 | + if ( src == nil ) | |
| 744 | + return( nil ); | |
| 745 | + | |
| 746 | + class := src.class(); | |
| 747 | + if ( class != arrayclass() ) | |
| 748 | + { | |
| 749 | + # safe-copy memory contents | |
| 750 | + # this calls a j2d generated <clone> method | |
| 751 | + newobj = class.clone( src ); | |
| 752 | + } | |
| 753 | + else | |
| 754 | + { | |
| 755 | + # handle arrays | |
| 756 | + | |
| 757 | + # create object wrapper fro the array | |
| 758 | + newobj = AllocObject( class ); | |
| 759 | + asrc := cast->ToJArray(src); | |
| 760 | + adst := cast->ToJArray(newobj); | |
| 761 | + # copy array description | |
| 762 | + adst.dims = asrc.dims; | |
| 763 | + adst.class = asrc.class; | |
| 764 | + adst.primitive = asrc.primitive; | |
| 765 | + | |
| 766 | + # copy array data | |
| 767 | + | |
| 768 | + # first create the appropriate "kind" of array | |
| 769 | + | |
| 770 | + length := len asrc.holder; | |
| 771 | + etype := asrc.primitive; | |
| 772 | + | |
| 773 | + if ( etype == 0 || asrc.dims > 1 ) | |
| 774 | + adst.holder = array[length] of JString; #any reference type | |
| 775 | + else | |
| 776 | + { | |
| 777 | + case asrc.primitive | |
| 778 | + { | |
| 779 | + T_BOOLEAN or T_BYTE => | |
| 780 | + adst.holder = jassist->bytearraytoJS(array[length] of byte); | |
| 781 | + T_CHAR or T_SHORT or T_INT => | |
| 782 | + adst.holder = jassist->intarraytoJS(array[length] of int); | |
| 783 | + T_LONG => | |
| 784 | + adst.holder = jassist->bigarraytoJS(array[length] of big); | |
| 785 | + T_FLOAT or T_DOUBLE => | |
| 786 | + adst.holder = jassist->realarraytoJS(array[length] of real); | |
| 787 | + } | |
| 788 | + } | |
| 789 | + | |
| 790 | + # copy the contents | |
| 791 | + adst.holder[:] = asrc.holder[:]; | |
| 792 | + | |
| 793 | + } | |
| 794 | + return( newobj ); | |
| 795 | +} | |
| 796 | + | |
| 797 | + | |
| 798 | +IdentityHash( obj : JObject ) : int | |
| 799 | +{ | |
| 800 | + return( jassist->objhash(obj) ); | |
| 801 | +} | |
| 802 | + | |
| 803 | + | |
| 804 | +GetArrayLength ( ary : JArray ) : int | |
| 805 | +{ | |
| 806 | + return( len ary.holder ); | |
| 807 | +} | |
| 808 | + | |
| 809 | +# | |
| 810 | +# grab the lock associated with the object | |
| 811 | +# | |
| 812 | +MonitorEnter( obj : JObject ) | |
| 813 | +{ | |
| 814 | + if ( obj == nil ) | |
| 815 | + ThrowException( "java.lang.NullPointerException", "JNI Error: nil passed to MonitorEnter()" ); | |
| 816 | + | |
| 817 | + jldr->monitorenter( obj ); | |
| 818 | +} | |
| 819 | + | |
| 820 | + | |
| 821 | +# | |
| 822 | +# release the lock associated with the object | |
| 823 | +# | |
| 824 | +MonitorExit( obj :JObject ) | |
| 825 | +{ | |
| 826 | + if ( obj == nil ) | |
| 827 | + ThrowException( "java.lang.NullPointerException", "JNI Error: nil passed to MonitorExit()" ); | |
| 828 | + jldr->monitorexit( obj ); | |
| 829 | +} | |
| 830 | + | |
| 831 | +# | |
| 832 | +# Notify any waiters | |
| 833 | +# all==1 => notify all | |
| 834 | +# | |
| 835 | +MonitorLockNotify( obj : JObject, all : int ) | |
| 836 | +{ | |
| 837 | + if ( obj == nil ) | |
| 838 | + ThrowException( "java.lang.NullPointerException", "JNI Error: nil passed to MonitorNotify()" ); | |
| 839 | + jldr->monitorenter(obj); | |
| 840 | + jldr->monitornotify(obj,(all==1)); | |
| 841 | + jldr->monitorexit(obj); | |
| 842 | +} | |
| 843 | + | |
| 844 | +# | |
| 845 | +# Same as above but don't do the monitor-enter/exit | |
| 846 | +# | |
| 847 | +MonitorNotify( obj : JObject, all : int ) | |
| 848 | +{ | |
| 849 | + if ( obj == nil ) | |
| 850 | + ThrowException( "java.lang.NullPointerException", "JNI Error: nil passed to MonitorNotify()" ); | |
| 851 | + jldr->monitornotify(obj,(all==1)); | |
| 852 | +} | |
| 853 | + | |
| 854 | +# | |
| 855 | +# attach/detach a Limbo thread | |
| 856 | +# | |
| 857 | + | |
| 858 | +thdcnt := 0; #use to number threads | |
| 859 | + | |
| 860 | +AttachCurrentThread( arg : ref ThreadAttachArgs ) : int | |
| 861 | +{ | |
| 862 | + # grab/create a thread struct for this thread | |
| 863 | + thd := jldr->getthreaddata(); | |
| 864 | + | |
| 865 | + # if no java obj then create and install one | |
| 866 | + if ( thd.this == nil ) | |
| 867 | + { | |
| 868 | + jobj := AllocObject( threadclass() ); | |
| 869 | + if (jobj == nil ) | |
| 870 | + return( -1 ); | |
| 871 | + jthd := cast->JObjToJThd(jobj); | |
| 872 | + jthd.PrivateInfo = thd; | |
| 873 | + jthd.daemon = arg.daemon; | |
| 874 | + if ( arg.daemon == byte 1) | |
| 875 | + jldr->daemonize(); | |
| 876 | + | |
| 877 | + if ( arg.group == nil ) | |
| 878 | + jthd.group = MainThreadGroup(); | |
| 879 | + else | |
| 880 | + jthd.group = arg.group; | |
| 881 | + | |
| 882 | + thdname : string; | |
| 883 | + if ( arg.name == nil ) | |
| 884 | + thdname = "nativethd-"+ string thdcnt++; | |
| 885 | + else | |
| 886 | + thdname = arg.name; | |
| 887 | + jthd.name = StringToAChar( thdname ); | |
| 888 | + | |
| 889 | + # set rest to defaults | |
| 890 | + jthd.priority = 5; #fake; not used | |
| 891 | + jthd.was_interrupted = byte 0; | |
| 892 | + jthd.stillborn = byte 0; | |
| 893 | + jthd.target = nil; | |
| 894 | + | |
| 895 | + # put thread object into thread data struct | |
| 896 | + thd.this = jobj; | |
| 897 | + } | |
| 898 | + | |
| 899 | + return( 0 ); #no error | |
| 900 | +} | |
| 901 | + | |
| 902 | + | |
| 903 | +DetachCurrentThread() : int | |
| 904 | +{ | |
| 905 | + # get the low-thread struct | |
| 906 | + thd := jldr->getthreaddata(); | |
| 907 | + | |
| 908 | + jobj := thd.this; # grab the java Thread obj | |
| 909 | + | |
| 910 | + if ( jobj != nil ) | |
| 911 | + { | |
| 912 | + #notify all waiters | |
| 913 | + MonitorLockNotify(jobj,1); | |
| 914 | + | |
| 915 | + # do some cleanup -- break circularity | |
| 916 | + jthd := cast->JObjToJThd(jobj); | |
| 917 | + jthd.PrivateInfo = nil; | |
| 918 | + thd.this = nil; | |
| 919 | + } | |
| 920 | + | |
| 921 | + # remove calling thd from the internal list | |
| 922 | + jldr->delthreaddata(); | |
| 923 | + | |
| 924 | + return( 0 ); | |
| 925 | +} | |
| 926 | + | |
| 927 | + | |
| 928 | +MainThreadGroup() : JObject | |
| 929 | +{ | |
| 930 | + if ( mainthreadgroup == nil ) | |
| 931 | + { | |
| 932 | + thd_grp_cl := FindClass( "java.lang.ThreadGroup" ); | |
| 933 | + if ( thd_grp_cl == nil ) | |
| 934 | + FatalError( "could not obtain ThreadGroup class" ); | |
| 935 | + | |
| 936 | + mainthreadgroup = NewObject( thd_grp_cl ); | |
| 937 | + if ( mainthreadgroup == nil ) | |
| 938 | + FatalError( "could not create root threadgroup" ); | |
| 939 | + } | |
| 940 | + | |
| 941 | + return( mainthreadgroup ); | |
| 942 | +} | |
| 943 | + | |
| 944 | + | |
| 945 | +FatalError( msg : string ) | |
| 946 | +{ | |
| 947 | + ThrowException( "java/lang/InternalError", msg ); | |
| 948 | +} | |
| 949 | + | |
| 950 | + | |
| 951 | +InitError( msg : string ) | |
| 952 | +{ | |
| 953 | + # prepend string to insure msg is not nil | |
| 954 | + # nil passed to error forces reporting which | |
| 955 | + # we will leave to the loader to determine | |
| 956 | + jldr->error( "JNI: "+ msg ); | |
| 957 | +} | |
| 958 | + | |
| 959 | + | |
| 960 | +# | |
| 961 | +# functions to make "java" arrays from limbo arrays | |
| 962 | +# | |
| 963 | +MkAByte( bary : array of byte ) : JArrayB | |
| 964 | +{ | |
| 965 | + # create Array object | |
| 966 | + cl_data := arrayclass(); | |
| 967 | + jbary := cast->ToJArrayB( AllocObject( cl_data ) ); | |
| 968 | + | |
| 969 | + jbary.ary = bary; | |
| 970 | + jbary.dims = 1; | |
| 971 | + jbary.class = nil; | |
| 972 | + jbary.primitive = T_BYTE; | |
| 973 | + | |
| 974 | + return( jbary ); | |
| 975 | +} | |
| 976 | + | |
| 977 | +MkAChar( ary : array of int ) : JArrayC | |
| 978 | +{ | |
| 979 | + # create Array object | |
| 980 | + jary := cast->ToJArrayC( AllocObject( arrayclass() ) ); | |
| 981 | + | |
| 982 | + jary.ary = ary; | |
| 983 | + jary.dims = 1; | |
| 984 | + jary.class = nil; | |
| 985 | + jary.primitive = T_CHAR; | |
| 986 | + | |
| 987 | + return( jary ); | |
| 988 | +} | |
| 989 | + | |
| 990 | +MkAShort( ary : array of int ) : JArrayS | |
| 991 | +{ | |
| 992 | + # create Array object | |
| 993 | + jary := cast->ToJArrayC( AllocObject( arrayclass() ) ); | |
| 994 | + | |
| 995 | + jary.ary = ary; | |
| 996 | + jary.dims = 1; | |
| 997 | + jary.class = nil; | |
| 998 | + jary.primitive = T_SHORT; | |
| 999 | + | |
| 1000 | + return( jary ); | |
| 1001 | +} | |
| 1002 | + | |
| 1003 | +MkAInt( iary : array of int ) : JArrayI | |
| 1004 | +{ | |
| 1005 | + # create Array object | |
| 1006 | + jiary := cast->ToJArrayI( AllocObject( arrayclass() ) ); | |
| 1007 | + | |
| 1008 | + jiary.ary = iary; | |
| 1009 | + jiary.dims = 1; | |
| 1010 | + jiary.class = nil; | |
| 1011 | + jiary.primitive = T_INT; | |
| 1012 | + | |
| 1013 | + return( jiary ); | |
| 1014 | +} | |
| 1015 | + | |
| 1016 | +MkALong( ary : array of big ) : JArrayJ | |
| 1017 | +{ | |
| 1018 | + # create Array object | |
| 1019 | + jary := cast->ToJArrayJ( AllocObject( arrayclass() ) ); | |
| 1020 | + | |
| 1021 | + jary.ary = ary; | |
| 1022 | + jary.dims = 1; | |
| 1023 | + jary.class = nil; | |
| 1024 | + jary.primitive = T_LONG; | |
| 1025 | + | |
| 1026 | + return( jary ); | |
| 1027 | +} | |
| 1028 | + | |
| 1029 | +MkAFloat( ary : array of real ) : JArrayF | |
| 1030 | +{ | |
| 1031 | + # create Array object | |
| 1032 | + jary := cast->ToJArrayF( AllocObject( arrayclass() ) ); | |
| 1033 | + | |
| 1034 | + jary.ary = ary; | |
| 1035 | + jary.dims = 1; | |
| 1036 | + jary.class = nil; | |
| 1037 | + jary.primitive = T_FLOAT; | |
| 1038 | + | |
| 1039 | + return( jary ); | |
| 1040 | +} | |
| 1041 | + | |
| 1042 | +MkADouble( ary : array of real ) : JArrayD | |
| 1043 | +{ | |
| 1044 | + # create Array object | |
| 1045 | + jary := cast->ToJArrayD( AllocObject( arrayclass() ) ); | |
| 1046 | + | |
| 1047 | + jary.ary = ary; | |
| 1048 | + jary.dims = 1; | |
| 1049 | + jary.class = nil; | |
| 1050 | + jary.primitive = T_DOUBLE; | |
| 1051 | + | |
| 1052 | + return( jary ); | |
| 1053 | +} | |
| 1054 | + | |
| 1055 | +MkABoolean( ary : array of byte ) : JArrayZ | |
| 1056 | +{ | |
| 1057 | + # create Array object | |
| 1058 | + jary := cast->ToJArrayZ( AllocObject( arrayclass() ) ); | |
| 1059 | + | |
| 1060 | + jary.ary = ary; | |
| 1061 | + jary.dims = 1; | |
| 1062 | + jary.class = nil; | |
| 1063 | + jary.primitive = T_BOOLEAN; | |
| 1064 | + | |
| 1065 | + return( jary ); | |
| 1066 | +} | |
| 1067 | + | |
| 1068 | + | |
| 1069 | +MkAString( sary : array of string ) : JArrayJString | |
| 1070 | +{ | |
| 1071 | + # create Array object | |
| 1072 | + jstrary := cast->ToJArrayJString( AllocObject( arrayclass() ) ); | |
| 1073 | + | |
| 1074 | + # fill it with the real dis array | |
| 1075 | + jstrary.ary = array[len sary] of JString; | |
| 1076 | + | |
| 1077 | + # now fill the dis array | |
| 1078 | + for( x:=0; x < len sary; x++ ) | |
| 1079 | + jstrary.ary[x] = NewString( sary[x] ); | |
| 1080 | + | |
| 1081 | + jstrary.dims = 1; | |
| 1082 | + jstrary.class = stringclass(); | |
| 1083 | + jstrary.primitive = 0; | |
| 1084 | + | |
| 1085 | + return( jstrary ); | |
| 1086 | +} | |
| 1087 | + | |
| 1088 | +MkAObject( ary : array of JObject ) : JArrayJObject | |
| 1089 | +{ | |
| 1090 | + # create Array object | |
| 1091 | + jary := cast->ToJArrayJObject( AllocObject( arrayclass() ) ); | |
| 1092 | + | |
| 1093 | + jary.ary = ary; | |
| 1094 | + jary.dims = 1; | |
| 1095 | + jary.class = stringclass(); | |
| 1096 | + if ( len ary > 0 ) | |
| 1097 | + jary.class = GetObjectClassData(ary[0]); | |
| 1098 | + jary.primitive = 0; | |
| 1099 | + | |
| 1100 | + return( jary ); | |
| 1101 | +} | |
| 1102 | + | |
| 1103 | + | |
| 1104 | +MkAJArray( jaary : array of JArray ) : JArray | |
| 1105 | +{ | |
| 1106 | + # create Array object | |
| 1107 | + jary := cast->ToJArray( AllocObject( arrayclass() ) ); | |
| 1108 | + | |
| 1109 | + # fill it with the real dis array | |
| 1110 | + jary.holder = cast->JArrayToHolder( jaary ); | |
| 1111 | + jary.dims = jaary[0].dims + 1; | |
| 1112 | + jary.class = arrayclass(); | |
| 1113 | + jary.primitive = 0; | |
| 1114 | + return( jary ); | |
| 1115 | +} | |
| 1116 | + | |
| 1117 | + | |
| 1118 | +MkAAByte( aabyte : array of array of byte ) : JArray | |
| 1119 | +{ | |
| 1120 | + # create array of JArray | |
| 1121 | + contents := array[len aabyte] of JArray; | |
| 1122 | + | |
| 1123 | + # fill contents with converted byte array | |
| 1124 | + for( x:=0; x<len aabyte; x++ ) | |
| 1125 | + { | |
| 1126 | + contents[x] = cast->ByteToJArray( MkAByte( aabyte[x] ) ); | |
| 1127 | + } | |
| 1128 | + | |
| 1129 | + # wrap up in an array of its own and return | |
| 1130 | + return( MkAJArray( contents ) ); | |
| 1131 | +} | |
| 1132 | + | |
| 1133 | +MkAAInt( aary : array of array of int ) : JArray | |
| 1134 | +{ | |
| 1135 | + # create array of JArray | |
| 1136 | + contents := array[len aary] of JArray; | |
| 1137 | + | |
| 1138 | + # fill contents with converted byte array | |
| 1139 | + for( x:=0; x<len aary; x++ ) | |
| 1140 | + { | |
| 1141 | + contents[x] = cast->IntToJArray( MkAInt( aary[x] ) ); | |
| 1142 | + } | |
| 1143 | + | |
| 1144 | + # wrap up in an array of its own and return | |
| 1145 | + return( MkAJArray( contents ) ); | |
| 1146 | +} | |
| 1147 | + | |
| 1148 | + | |
| 1149 | +# | |
| 1150 | +# Value adt | |
| 1151 | +# | |
| 1152 | + | |
| 1153 | +Value.Boolean( this : self ref Value ) : JBoolean | |
| 1154 | +{ | |
| 1155 | + pick sw := this | |
| 1156 | + { | |
| 1157 | + TBoolean => return( sw.jboolean ); | |
| 1158 | + * => FatalError( "Value: bad pick access" ); | |
| 1159 | + } | |
| 1160 | + return( 0); | |
| 1161 | +} | |
| 1162 | + | |
| 1163 | +Value.Byte( this : self ref Value ) : int | |
| 1164 | +{ | |
| 1165 | + pick sw := this | |
| 1166 | + { | |
| 1167 | + TByte => return( sw.jbyte ); | |
| 1168 | + * => FatalError( "Value: bad pick access" ); | |
| 1169 | + } | |
| 1170 | + return(0); | |
| 1171 | +} | |
| 1172 | + | |
| 1173 | +Value.Short( this : self ref Value ) : int | |
| 1174 | +{ | |
| 1175 | + pick sw := this | |
| 1176 | + { | |
| 1177 | + TShort => return( sw.jshort ); | |
| 1178 | + * => FatalError( "Value: bad pick access" ); | |
| 1179 | + } | |
| 1180 | + return(0); | |
| 1181 | +} | |
| 1182 | + | |
| 1183 | +Value.Int( this : self ref Value ) : int | |
| 1184 | +{ | |
| 1185 | + pick sw := this | |
| 1186 | + { | |
| 1187 | + TInt => return( sw.jint ); | |
| 1188 | + * => FatalError( "Value: bad pick access" ); | |
| 1189 | + } | |
| 1190 | + return(0); | |
| 1191 | +} | |
| 1192 | + | |
| 1193 | +Value.Long( this : self ref Value ) : big | |
| 1194 | +{ | |
| 1195 | + pick sw := this | |
| 1196 | + { | |
| 1197 | + TLong => return( sw.jlong ); | |
| 1198 | + * => FatalError( "Value: bad pick access" ); | |
| 1199 | + } | |
| 1200 | + return(big 0); | |
| 1201 | +} | |
| 1202 | + | |
| 1203 | +Value.Float( this : self ref Value ) : real | |
| 1204 | +{ | |
| 1205 | + pick sw := this | |
| 1206 | + { | |
| 1207 | + TFloat => return( sw.jfloat ); | |
| 1208 | + * => FatalError( "Value: bad pick access" ); | |
| 1209 | + } | |
| 1210 | + return(0.0); | |
| 1211 | +} | |
| 1212 | + | |
| 1213 | +Value.Double( this : self ref Value ) : real | |
| 1214 | +{ | |
| 1215 | + pick sw := this | |
| 1216 | + { | |
| 1217 | + TDouble => return( sw.jdouble ); | |
| 1218 | + * => FatalError( "Value: bad pick access" ); | |
| 1219 | + } | |
| 1220 | + return(0.0); | |
| 1221 | +} | |
| 1222 | + | |
| 1223 | +Value.Char( this : self ref Value ) : int | |
| 1224 | +{ | |
| 1225 | + pick sw := this | |
| 1226 | + { | |
| 1227 | + TChar => return( sw.jchar ); | |
| 1228 | + * => FatalError( "Value: bad pick access" ); | |
| 1229 | + } | |
| 1230 | + return(0); | |
| 1231 | +} | |
| 1232 | + | |
| 1233 | +Value.Object( this : self ref Value ) : JObject | |
| 1234 | +{ | |
| 1235 | + pick sw := this | |
| 1236 | + { | |
| 1237 | + TObject => return( sw.jobj); | |
| 1238 | + * => FatalError( "Value: bad pick access" ); | |
| 1239 | + } | |
| 1240 | + return(nil); | |
| 1241 | +} | |
| 1242 | + | |
| 1243 | + | |
| 1244 | +# | |
| 1245 | +# Take a "java vm" signagure string and | |
| 1246 | +# return a structure which describes the | |
| 1247 | +# type represented by the sig. | |
| 1248 | +# SEE: declaration of 'Descriptor' | |
| 1249 | +# | |
| 1250 | +JSigToDescriptor( sig : string ) : ref Descriptor | |
| 1251 | +{ | |
| 1252 | + desc := ref Descriptor(nil,0,0,nil,nil); | |
| 1253 | + siglen := len sig; | |
| 1254 | + if ( sig[0] == '(' ) # method | |
| 1255 | + { | |
| 1256 | + methsig := sig[1:]; | |
| 1257 | + sigsize := 2; #account for '(' and ')' in method sig | |
| 1258 | + while ( methsig[0] != ')' ) | |
| 1259 | + { | |
| 1260 | + # get descriptor for current param | |
| 1261 | + paramdesc := JSigToDescriptor(methsig); | |
| 1262 | + if ( paramdesc == nil ) | |
| 1263 | + return( nil ); #error | |
| 1264 | + | |
| 1265 | + # add the param to the list | |
| 1266 | + desc.params = paramdesc :: desc.params; | |
| 1267 | + | |
| 1268 | + # advance to next param | |
| 1269 | + tmp := len paramdesc.sig; | |
| 1270 | + if ( tmp >= len methsig ) | |
| 1271 | + return( nil ); #error in signature | |
| 1272 | + methsig = methsig[tmp:]; | |
| 1273 | + sigsize += tmp; | |
| 1274 | + } | |
| 1275 | + | |
| 1276 | + if ( len methsig <= 1 ) | |
| 1277 | + return( nil ); #error expected a return type | |
| 1278 | + | |
| 1279 | + rettyp := JSigToDescriptor( methsig[1:] ); | |
| 1280 | + if ( rettyp == nil ) | |
| 1281 | + return( nil ); #error | |
| 1282 | + # save the return type information in the current desc | |
| 1283 | + desc.class = rettyp.class; | |
| 1284 | + desc.prim = rettyp.prim; | |
| 1285 | + desc.dims = rettyp.dims; | |
| 1286 | + | |
| 1287 | + # set sig for method | |
| 1288 | + desc.sig = sig[0:sigsize+len rettyp.sig]; | |
| 1289 | + | |
| 1290 | + } | |
| 1291 | + else if ( sig[0] == 'L' ) # object (non-array) | |
| 1292 | + { | |
| 1293 | + # find ';' indicating end of class name or | |
| 1294 | + # the end of the str | |
| 1295 | + for( last := 1; last<siglen; last++ ) | |
| 1296 | + if ( sig[last] == ';' ) | |
| 1297 | + break; | |
| 1298 | + desc.class = FindClass( sig[1:last] ); | |
| 1299 | + desc.sig = sig[:last] + ";"; | |
| 1300 | + } | |
| 1301 | + else if ( sig[0] == '[' ) # array | |
| 1302 | + { | |
| 1303 | + # count dimensions | |
| 1304 | + last := siglen; | |
| 1305 | + for(x:=1; x<last; x++) | |
| 1306 | + { | |
| 1307 | + if ( sig[x] != '[' ) | |
| 1308 | + break; | |
| 1309 | + } | |
| 1310 | + if ( x >= last ) | |
| 1311 | + return nil; #error expect at least 1 char following ['s | |
| 1312 | + desc = JSigToDescriptor( sig[x:] ); | |
| 1313 | + if ( desc == nil ) | |
| 1314 | + return nil; | |
| 1315 | + | |
| 1316 | + # else just set dimensions and sig | |
| 1317 | + desc.dims = x; | |
| 1318 | + tmp := x + len desc.sig; | |
| 1319 | + desc.sig = sig[:tmp]; | |
| 1320 | + } | |
| 1321 | + else # primitive type | |
| 1322 | + { | |
| 1323 | + case sig[0] | |
| 1324 | + { | |
| 1325 | + 'B' => desc.prim = T_BYTE; | |
| 1326 | + 'Z' => desc.prim = T_BOOLEAN; | |
| 1327 | + 'S' => desc.prim = T_SHORT; | |
| 1328 | + 'C' => desc.prim = T_CHAR; | |
| 1329 | + 'I' => desc.prim = T_INT; | |
| 1330 | + 'J' => desc.prim = T_LONG; | |
| 1331 | + 'F' => desc.prim = T_FLOAT; | |
| 1332 | + 'D' => desc.prim = T_DOUBLE; | |
| 1333 | + 'V' => desc.prim = T_VOID; | |
| 1334 | + * => return( nil ); #unknown signature | |
| 1335 | + } | |
| 1336 | + desc.sig = sig[0:1]; | |
| 1337 | + } | |
| 1338 | + | |
| 1339 | + return desc; | |
| 1340 | +} | |
| 1341 | + | |
| 1342 | + | |
| 1343 | +IsNative( flags : int ) : int | |
| 1344 | +{ | |
| 1345 | + return( flags & ACC_NATIVE ); | |
| 1346 | +} | |
| 1347 | + | |
| 1348 | + | |
| 1349 | +# | |
| 1350 | +# Search for a method. Flags indicates which methods to | |
| 1351 | +# search for, and we may try to find in more than one | |
| 1352 | +# group, so cascade down. | |
| 1353 | +# | |
| 1354 | +FindMethod( class : ClassData, name : string, sig : string, flags : int ) : (Nilmod,int) | |
| 1355 | +{ | |
| 1356 | + Class : import jldr; | |
| 1357 | + | |
| 1358 | + if ( class == nil ) | |
| 1359 | + return( nil, 0 ); | |
| 1360 | + | |
| 1361 | + if ( flags & METH_PRIVATE ) | |
| 1362 | + { | |
| 1363 | + f := class.findpmethod( name, sig ); | |
| 1364 | + if ( f != nil ) | |
| 1365 | + { | |
| 1366 | + mod : Nilmod; | |
| 1367 | + if ( IsNative(f.flags) ) | |
| 1368 | + mod = class.native; | |
| 1369 | + else | |
| 1370 | + mod = class.mod; | |
| 1371 | + | |
| 1372 | + return ( mod, f.value ); | |
| 1373 | + } | |
| 1374 | + } | |
| 1375 | + | |
| 1376 | + if ( flags & METH_VIRTUAL ) | |
| 1377 | + { | |
| 1378 | + idx := class.findvmethod( name, sig ); | |
| 1379 | + if ( idx != -1 ) | |
| 1380 | + { | |
| 1381 | + m := class.virtualmethods[idx]; | |
| 1382 | + return( m.class.mod, m.field.value ); | |
| 1383 | + } | |
| 1384 | + } | |
| 1385 | + | |
| 1386 | + if ( flags & METH_STATIC ) | |
| 1387 | + { | |
| 1388 | + f := class.findsmethod( name, sig ); | |
| 1389 | + if ( f != nil ) | |
| 1390 | + { | |
| 1391 | + mod : Nilmod; | |
| 1392 | + if ( IsNative(f.flags) ) | |
| 1393 | + mod = class.native; | |
| 1394 | + else | |
| 1395 | + mod = class.mod; | |
| 1396 | + | |
| 1397 | + return ( mod, f.value ); | |
| 1398 | + } | |
| 1399 | + } | |
| 1400 | + | |
| 1401 | + if ( flags & METH_INIT ) | |
| 1402 | + { | |
| 1403 | + f := class.findimethod( sig ); | |
| 1404 | + if ( f != nil ) | |
| 1405 | + { | |
| 1406 | + mod := class.mod; #constructors can't be native | |
| 1407 | + return ( mod, f.value ); | |
| 1408 | + } | |
| 1409 | + } | |
| 1410 | + | |
| 1411 | + return (nil,0); | |
| 1412 | +} | |
| 1413 | + | |
| 1414 | +CastMod() : Cast | |
| 1415 | +{ | |
| 1416 | + return( cast ); | |
| 1417 | +} | |
| 1418 | + | |
| 1419 | +LowMod() : Low | |
| 1420 | +{ | |
| 1421 | + return( low ); | |
| 1422 | +} | |
| 1423 | + | |
| 1424 | +########## functions called by JavaClassLoader | |
| 1425 | + | |
| 1426 | +jinit( ldr : JavaClassLoader, jass : JavaAssist ) | |
| 1427 | +{ | |
| 1428 | + jldr = ldr; | |
| 1429 | + jassist = jass; | |
| 1430 | +} | |
| 1431 | + | |
| 1432 | +Self(s: Sys, j: JNI): (Nilmod, string) | |
| 1433 | +{ | |
| 1434 | + sys = s; | |
| 1435 | + math = load Math Math->PATH; | |
| 1436 | + if ( math == nil ) | |
| 1437 | + return (nil, sys->sprint("could not load %s: %r", Math->PATH)); | |
| 1438 | + | |
| 1439 | + str = load String String->PATH; | |
| 1440 | + if ( str == nil ) | |
| 1441 | + return (nil, sys->sprint("could not load %s: %r", String->PATH)); | |
| 1442 | + | |
| 1443 | + cast = load Cast Cast->PATH; | |
| 1444 | + if (cast == nil) | |
| 1445 | + return (nil, sys->sprint("could not load %s: %r", Cast->PATH)); | |
| 1446 | + low = load Low Low->PATH; | |
| 1447 | + if (low == nil) | |
| 1448 | + return (nil, sys->sprint("could not load %s: %r", Low->PATH)); | |
| 1449 | + return (cast->JNI2Nilmod(j), nil); | |
| 1450 | +} | |
| 1451 | + | |
| 1452 | +init(nil: JNI) | |
| 1453 | +{ | |
| 1454 | +} | |
| 1455 | + | |
| 1456 | +########## private functions | |
| 1457 | + | |
| 1458 | +# | |
| 1459 | +# private fct to create an instance of java.lang.Class | |
| 1460 | +# for a specific array type. each class instance is | |
| 1461 | +# cached in a hash table so future queries for the same | |
| 1462 | +# class will get the same object back. | |
| 1463 | +ArrayClassObject( ary : JArray ) : JClass | |
| 1464 | +{ | |
| 1465 | + arycodes := "[[[[[[[[[["; | |
| 1466 | + if ( ary.dims >= len arycodes ) | |
| 1467 | + while ( ary.dims >= len arycodes ) | |
| 1468 | + arycodes += arycodes; | |
| 1469 | + sig := arycodes[:ary.dims]; | |
| 1470 | + if ( ary.primitive == 0 ) | |
| 1471 | + { | |
| 1472 | + clname := ary.class.name; | |
| 1473 | + for(x:=0;x<len clname; x++ ) | |
| 1474 | + if ( clname[x] == '.' ) | |
| 1475 | + clname[x] = '/'; | |
| 1476 | + sig += "L"+ clname +";"; | |
| 1477 | + } | |
| 1478 | + else | |
| 1479 | + { | |
| 1480 | + typ := ary.primitive; | |
| 1481 | + if ( (typ >= T_BOOLEAN) || (typ <= T_LONG) ) | |
| 1482 | + { | |
| 1483 | + typcode := "ZCFDBSIJ"; | |
| 1484 | + sig[len sig] = typcode[typ-T_BOOLEAN]; | |
| 1485 | + } | |
| 1486 | + } | |
| 1487 | + clobj := LookupArrayClass( sig ); | |
| 1488 | + | |
| 1489 | + return( clobj ); | |
| 1490 | +} | |
| 1491 | + | |
| 1492 | +# | |
| 1493 | +# maintain a hash table of array class objects | |
| 1494 | +# order based on the array signature string. | |
| 1495 | +# | |
| 1496 | +ACSZ : con 31; | |
| 1497 | +actable := array[ACSZ] of list of JClass; | |
| 1498 | + | |
| 1499 | +LookupArrayClass( sig : string ) : JClass | |
| 1500 | +{ | |
| 1501 | + if ( hash == nil ) | |
| 1502 | + { | |
| 1503 | + hash = load Hash Hash->PATH; | |
| 1504 | + if ( hash == nil ) | |
| 1505 | + FatalError( sys->sprint( "could not load %s:%r", Hash->PATH ) ); | |
| 1506 | + } | |
| 1507 | + | |
| 1508 | + # search for an existing class object with same name | |
| 1509 | + for( l := actable[hash->fun1(sig,ACSZ)]; l != nil; l = tl l ) | |
| 1510 | + { | |
| 1511 | + class := hd l; | |
| 1512 | + if (class.aryname == sig) | |
| 1513 | + return( class ); | |
| 1514 | + } | |
| 1515 | + | |
| 1516 | + # could not find so add this class | |
| 1517 | + class := NewClassObject( arrayclass() ); | |
| 1518 | + class.aryname = sig; | |
| 1519 | + idx := hash->fun1(sig,ACSZ); | |
| 1520 | + actable[idx] = class :: actable[idx]; | |
| 1521 | + return( class ); | |
| 1522 | +} | |
| 1523 | + | |
| 1524 | + | |
| 1525 | +# | |
| 1526 | +# check argument array against method signature. It is assumed | |
| 1527 | +# that 'sig' is a well-formed method signature. This fct verifies | |
| 1528 | +# that the arguments match the signature (no widening of primtive | |
| 1529 | +# types is performed. It returns a tuple specifiying if the method | |
| 1530 | +# is a function and an error flag | |
| 1531 | +# RETURN: (isfct,err) | |
| 1532 | +# (desc,0) -- function; no error | |
| 1533 | +# (nil,0) -- procedure; no error | |
| 1534 | +# (nil,ERR) -- error; params did not match | |
| 1535 | +# | |
| 1536 | +CheckMethodArgs( sig : string, args : array of ref Value ) : (ref Descriptor,int) | |
| 1537 | +{ | |
| 1538 | + desc := JSigToDescriptor( sig ); # description of method | |
| 1539 | + if ( desc == nil ) | |
| 1540 | + return( nil,ERR ); # error | |
| 1541 | + | |
| 1542 | + # determine if the method returns a value | |
| 1543 | + isfct : ref Descriptor; | |
| 1544 | + if ((desc.class!=nil) || (desc.prim!=T_VOID)) | |
| 1545 | + isfct = desc; | |
| 1546 | + | |
| 1547 | + count := len args; | |
| 1548 | + if ( count != len desc.params ) | |
| 1549 | + return(nil,CALLERR_BADARGCNT); #argument count mismatch | |
| 1550 | + | |
| 1551 | + if ( count == 0 ) | |
| 1552 | + return(isfct,OK); # no params to compare | |
| 1553 | + | |
| 1554 | + for( params := desc.params; params!=nil; params = tl params ) | |
| 1555 | + { | |
| 1556 | + param := hd params; | |
| 1557 | + count--; | |
| 1558 | + valid := 0; #assume bad arg | |
| 1559 | + pick sw := args[count] | |
| 1560 | + { | |
| 1561 | + TObject => | |
| 1562 | + # check if actual ref arg compatible with formal | |
| 1563 | + if ( ( sw.jobj == nil ) | |
| 1564 | + || ( IsArray(sw.jobj) && (ArrayInstanceOf(cast->ToJArray(sw.jobj), param) ) ) | |
| 1565 | + || ( IsInstanceOf( sw.jobj, param.class ) ) ) | |
| 1566 | + valid = 1; | |
| 1567 | + TByte => valid = (param.prim == T_BYTE); | |
| 1568 | + TBoolean => valid = (param.prim == T_BOOLEAN); | |
| 1569 | + TChar => valid = (param.prim == T_CHAR); | |
| 1570 | + TShort => valid = (param.prim == T_SHORT); | |
| 1571 | + TInt => valid = (param.prim == T_INT); | |
| 1572 | + TLong => valid = (param.prim == T_LONG); | |
| 1573 | + TFloat => valid = (param.prim == T_FLOAT); | |
| 1574 | + TDouble => valid = (param.prim == T_DOUBLE); | |
| 1575 | + } | |
| 1576 | + | |
| 1577 | + if ( ! valid ) | |
| 1578 | + return(nil,CALLERR_BADARG+count); #class mismatch | |
| 1579 | + } | |
| 1580 | + | |
| 1581 | + # if we survived then all args matched | |
| 1582 | + return(isfct,OK); | |
| 1583 | +} | |
| 1584 | + | |
| 1585 | +# verify that 'val' matches 'field' | |
| 1586 | +# RETURN: 0 => no match | |
| 1587 | +# 1 => match | |
| 1588 | +# | |
| 1589 | +CheckField( field : ref jldr->Field, val : ref Value ) : int | |
| 1590 | +{ | |
| 1591 | + # check we have the right one | |
| 1592 | + if ( field == nil ) | |
| 1593 | + return( 0 ); | |
| 1594 | + | |
| 1595 | + valid := 0; | |
| 1596 | + | |
| 1597 | + pick sw := val | |
| 1598 | + { | |
| 1599 | + TObject => | |
| 1600 | + { | |
| 1601 | + # check reference type: object or array | |
| 1602 | + desc := JSigToDescriptor( field.signature ); | |
| 1603 | + | |
| 1604 | + if ( (field.signature[0] == 'L') && (desc.class != nil) ) | |
| 1605 | + { | |
| 1606 | + if ( sw.jobj != nil && IsInstanceOf( sw.jobj, desc.class ) == FALSE ) | |
| 1607 | + return( 0 ); | |
| 1608 | + } | |
| 1609 | + else if ( (field.signature[0] == '[') && (desc.dims>0) ) | |
| 1610 | + { | |
| 1611 | + # array ref type | |
| 1612 | + if ( sw.jobj != nil && ArrayInstanceOf( cast->ToJArray(sw.jobj), desc ) == FALSE ) | |
| 1613 | + return( 0 ); | |
| 1614 | + } | |
| 1615 | + else | |
| 1616 | + return( 0 ); | |
| 1617 | + valid = 1; # ref field is ok | |
| 1618 | + } | |
| 1619 | + TByte => valid = (field.signature[0] == 'B'); | |
| 1620 | + TBoolean => valid = (field.signature[0] == 'Z'); | |
| 1621 | + TChar => valid = (field.signature[0] == 'C'); | |
| 1622 | + TShort => valid = (field.signature[0] == 'S'); | |
| 1623 | + TInt => valid = (field.signature[0] == 'I'); | |
| 1624 | + TLong => valid = (field.signature[0] == 'J'); | |
| 1625 | + TFloat => valid = (field.signature[0] == 'F'); | |
| 1626 | + TDouble => valid = (field.signature[0] == 'D'); | |
| 1627 | + } | |
| 1628 | + | |
| 1629 | + return( valid ); | |
| 1630 | +} | |
| 1631 | + | |
| 1632 | +# | |
| 1633 | +# Set a field at the given refernce and offset. | |
| 1634 | +# | |
| 1635 | +SetField( ptr : ref Loader->Niladt, off : int, val : ref Value ) : int | |
| 1636 | +{ | |
| 1637 | + # must be good, set the field to the provided value | |
| 1638 | + pick sw := val | |
| 1639 | + { | |
| 1640 | + TByte => low->SetByte( ptr, off, byte sw.jbyte ); | |
| 1641 | + TBoolean => low->SetByte( ptr, off, byte sw.jboolean ); | |
| 1642 | + TShort => low->SetInt( ptr, off, sw.jshort ); | |
| 1643 | + TChar => low->SetInt( ptr, off, sw.jchar ); | |
| 1644 | + TInt => low->SetInt( ptr, off, sw.jint ); | |
| 1645 | + TLong => low->SetBig( ptr, off, sw.jlong ); | |
| 1646 | + TFloat => low->SetReal( ptr, off, sw.jfloat ); | |
| 1647 | + TDouble => low->SetReal( ptr, off, sw.jdouble ); | |
| 1648 | + TObject => low->SetObj( ptr, off, sw.jobj ); | |
| 1649 | + * => return( ERR ); | |
| 1650 | + } | |
| 1651 | + | |
| 1652 | + return( OK ); | |
| 1653 | +} | |
| 1654 | + | |
| 1655 | + | |
| 1656 | +# | |
| 1657 | +# grab a given field from the reference and offset given | |
| 1658 | +# | |
| 1659 | +GetField( ptr : ref Loader->Niladt, off : int, typ : int ) : ref Value | |
| 1660 | +{ | |
| 1661 | + val : ref Value; | |
| 1662 | + | |
| 1663 | + if ( (ptr==nil) || (off < 0) ) | |
| 1664 | + return( nil ); | |
| 1665 | + | |
| 1666 | + # use typ char to determine type we are after | |
| 1667 | + case typ | |
| 1668 | + { | |
| 1669 | + 'B' => val = ref Value.TByte(int low->GetByte( ptr, off )); | |
| 1670 | + 'C' => val = ref Value.TChar(low->GetInt( ptr, off )); | |
| 1671 | + 'S' => val = ref Value.TShort(low->GetInt( ptr, off )); | |
| 1672 | + 'I' => val = ref Value.TInt(low->GetInt( ptr, off )); | |
| 1673 | + 'Z' => val = ref Value.TBoolean(int low->GetByte( ptr, off )); | |
| 1674 | + 'J' => val = ref Value.TLong(low->GetBig( ptr, off )); | |
| 1675 | + 'F' => val = ref Value.TFloat(low->GetReal( ptr, off )); | |
| 1676 | + 'D' => val = ref Value.TDouble(low->GetReal( ptr, off )); | |
| 1677 | + 'L' or | |
| 1678 | + '[' => val = ref Value.TObject(low->GetObj( ptr, off )); | |
| 1679 | + * => return(nil); | |
| 1680 | + } | |
| 1681 | + | |
| 1682 | + return( val ); | |
| 1683 | +} | |
| 1684 | + | |
| 1685 | + | |
| 1686 | +# | |
| 1687 | +# The following functions will load specific java | |
| 1688 | +# classes on demand. The classes are loaded as late | |
| 1689 | +# as possible | |
| 1690 | +# | |
| 1691 | +stringclass() : ClassData | |
| 1692 | +{ | |
| 1693 | + if ( string_class == nil ) | |
| 1694 | + string_class = jldr->loader( "java/lang/String" ); | |
| 1695 | + return( string_class ); | |
| 1696 | +} | |
| 1697 | + | |
| 1698 | +arrayclass() : ClassData | |
| 1699 | +{ | |
| 1700 | + if ( array_class == nil ) | |
| 1701 | + array_class = jldr->loader( "inferno/vm/Array" ); | |
| 1702 | + return( array_class ); | |
| 1703 | +} | |
| 1704 | + | |
| 1705 | +classclass() : ClassData | |
| 1706 | +{ | |
| 1707 | + if ( class_class == nil ) | |
| 1708 | + class_class = jldr->loader( "java/lang/Class" ); | |
| 1709 | + return( class_class ); | |
| 1710 | +} | |
| 1711 | + | |
| 1712 | +throwableclass() : ClassData | |
| 1713 | +{ | |
| 1714 | + if (throwable_class == nil) | |
| 1715 | + throwable_class = jldr->loader("java/lang/Throwable"); | |
| 1716 | + return( throwable_class ); | |
| 1717 | +} | |
| 1718 | + | |
| 1719 | +threadclass() : ClassData | |
| 1720 | +{ | |
| 1721 | + if (thread_class == nil) | |
| 1722 | + thread_class = jldr->loader("java/lang/Thread"); | |
| 1723 | + return( thread_class ); | |
| 1724 | +} | |
| 1725 | + | |
| 1726 | +StringToAChar( s : string ) : JArrayC | |
| 1727 | +{ | |
| 1728 | + l := len s; | |
| 1729 | + ac := array[l] of int; | |
| 1730 | + | |
| 1731 | + for( x:=0; x<l; x++ ) | |
| 1732 | + ac[x] = s[x]; | |
| 1733 | + | |
| 1734 | + return( MkAChar(ac) ); | |
| 1735 | +} | |
| @@ -0,0 +1,142 @@ | ||
| 1 | +implement jvm; | |
| 2 | + | |
| 3 | +include "sys.m"; | |
| 4 | + FD: import Sys; | |
| 5 | + | |
| 6 | +include "loader.m"; | |
| 7 | +include "classloader.m"; | |
| 8 | +Context: import Draw; | |
| 9 | + | |
| 10 | +jvm: module | |
| 11 | +{ | |
| 12 | + init: fn(ctxt: ref Context, argv: list of string); | |
| 13 | +}; | |
| 14 | + | |
| 15 | +PJAVAVER : con "v1.0"; #javasoft pjava we are based on | |
| 16 | + | |
| 17 | +sys: Sys; | |
| 18 | +stderr: ref FD; | |
| 19 | +classloader: JavaClassLoader; | |
| 20 | +Class: import classloader; | |
| 21 | + | |
| 22 | +init(ctxt: ref Context, argv: list of string) | |
| 23 | +{ | |
| 24 | + sys = load Sys Sys->PATH; | |
| 25 | + stderr = sys->fildes(2); | |
| 26 | + | |
| 27 | + # split args into classloader options and java app args | |
| 28 | + (opts,args) := processargs(argv); | |
| 29 | + | |
| 30 | + classloader = load JavaClassLoader JavaClassLoader->PATH; | |
| 31 | + if (classloader == nil) { | |
| 32 | + sys->fprint(stderr, "could not load %s: %r\n", JavaClassLoader->PATH); | |
| 33 | + exit; | |
| 34 | + } | |
| 35 | + s := classname(hd tl args); | |
| 36 | + sys->pctl(sys->NEWPGRP, nil); | |
| 37 | + | |
| 38 | + classloader->init(classloader,ctxt); | |
| 39 | + | |
| 40 | + if ( opts != nil ) | |
| 41 | + classloader->setflags(opts); | |
| 42 | + | |
| 43 | + classloader->runmain(classloader, s, args); | |
| 44 | +} | |
| 45 | + | |
| 46 | +classname(s: string): string | |
| 47 | +{ | |
| 48 | + d: string; | |
| 49 | + n := len s; | |
| 50 | + for (i := 0; i < n; i++) { | |
| 51 | + c := s[i]; | |
| 52 | + if (c == '.') | |
| 53 | + d[i] = '/'; | |
| 54 | + else | |
| 55 | + d[i] = c; | |
| 56 | + } | |
| 57 | + return d; | |
| 58 | +} | |
| 59 | + | |
| 60 | +# | |
| 61 | +# process the argv of 'jvm' and handle any 'jvm' flags here | |
| 62 | +# and return: | |
| 63 | +# classloader options in the form of 'list of (string,val)' | |
| 64 | +# java class args in the form of 'list of string' | |
| 65 | +# valid classloader options are: | |
| 66 | +# ("debug",1|0) -- debug messages on==1 | |
| 67 | +# ("verbose",1|0) -- verbose messages on==1 | |
| 68 | +# ("warn",1|0) -- warning messages on==1 | |
| 69 | +# valid local jvm options are: | |
| 70 | +# i == version information | |
| 71 | +# h == jvm help | |
| 72 | +# | |
| 73 | +processargs( argv : list of string ) : (list of (string,int), list of string) | |
| 74 | +{ | |
| 75 | + if ( argv == nil ) | |
| 76 | + { | |
| 77 | + mesg("error: invalid parameters"); | |
| 78 | + showhelp("jvm"); #exits | |
| 79 | + } | |
| 80 | + | |
| 81 | + # cmd ::= 'jvm' [flags] javastuff | |
| 82 | + # flags ::= '-' CHAR+ | |
| 83 | + jvmcmd := hd argv; | |
| 84 | + stuff := tl argv; | |
| 85 | + flags : string; | |
| 86 | + if ( (stuff != nil) && (hd stuff)[0] == '-' ) | |
| 87 | + { | |
| 88 | + flags = hd stuff; | |
| 89 | + stuff = tl stuff; | |
| 90 | + } | |
| 91 | + | |
| 92 | + # process flags | |
| 93 | + opts : list of (string,int); | |
| 94 | + for(x:=1;x<len flags; x++) | |
| 95 | + { | |
| 96 | + case flags[x] | |
| 97 | + { | |
| 98 | + 'v' => opts = ("verbose",1)::opts; | |
| 99 | + 'd' => opts = ("debug",1)::opts; | |
| 100 | + 'w' => opts = ("warn",1)::opts; | |
| 101 | + 'i' => showinfo(); #exits | |
| 102 | + 'h' => showhelp(jvmcmd); #exits | |
| 103 | + * => mesg(sys->sprint( "error: %c is an invalid option\n", flags[x] )); | |
| 104 | + showhelp(jvmcmd); | |
| 105 | + | |
| 106 | + } | |
| 107 | + } | |
| 108 | + | |
| 109 | + if ( stuff == nil ) | |
| 110 | + { | |
| 111 | + mesg("error: missing classname"); | |
| 112 | + showhelp(jvmcmd); #exits | |
| 113 | + } | |
| 114 | + | |
| 115 | + return(opts,jvmcmd::stuff); | |
| 116 | +} | |
| 117 | + | |
| 118 | + | |
| 119 | +mesg(s:string) | |
| 120 | +{ | |
| 121 | + sys->fprint(stderr,"%s\n", s); | |
| 122 | +} | |
| 123 | + | |
| 124 | +showinfo() | |
| 125 | +{ | |
| 126 | + mesg(sys->sprint("Inferno PJava v%c [PJava %s]\n", JavaClassLoader->SUXV, PJAVAVER )); | |
| 127 | + exit; | |
| 128 | +} | |
| 129 | + | |
| 130 | +showhelp(cmd:string) | |
| 131 | +{ | |
| 132 | + mesg(sys->sprint( "usage:\t%s [-vdwih] classname classargs", cmd )); | |
| 133 | + mesg(sys->sprint( "\tv=verbose; d=debug; w=warnings; i=version; h=help" )); | |
| 134 | + exit; | |
| 135 | +} | |
| 136 | + | |
| 137 | +badopt(opt : int) | |
| 138 | +{ | |
| 139 | +} | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| @@ -0,0 +1,140 @@ | ||
| 1 | +#0 | |
| 2 | +# SetByte | |
| 3 | + addw 32(fp),36(fp),44(fp) | |
| 4 | + movb 40(fp),0(44(fp)) | |
| 5 | + ret | |
| 6 | +#3 | |
| 7 | +# SetInt | |
| 8 | + addw 32(fp),36(fp),44(fp) | |
| 9 | + movw 40(fp),0(44(fp)) | |
| 10 | + ret | |
| 11 | +#6 | |
| 12 | +# SetBig | |
| 13 | + addw 32(fp),36(fp),48(fp) | |
| 14 | + movl 40(fp),0(48(fp)) | |
| 15 | + ret | |
| 16 | +#9 | |
| 17 | +# SetReal | |
| 18 | + addw 32(fp),36(fp),48(fp) | |
| 19 | + movf 40(fp),0(48(fp)) | |
| 20 | + ret | |
| 21 | +#12 | |
| 22 | +# SetObj | |
| 23 | + addw 32(fp),36(fp),44(fp) | |
| 24 | + movp 40(fp),0(44(fp)) | |
| 25 | + ret | |
| 26 | +#15 | |
| 27 | +# GetByte | |
| 28 | + addw 32(fp),36(fp),40(fp) | |
| 29 | + movb 0(40(fp)),0(16(fp)) | |
| 30 | + ret | |
| 31 | +#18 | |
| 32 | +# GetInt | |
| 33 | + addw 32(fp),36(fp),40(fp) | |
| 34 | + movw 0(40(fp)),0(16(fp)) | |
| 35 | + ret | |
| 36 | +#21 | |
| 37 | +# GetBig | |
| 38 | + addw 32(fp),36(fp),40(fp) | |
| 39 | + movl 0(40(fp)),0(16(fp)) | |
| 40 | + ret | |
| 41 | +#24 | |
| 42 | +# GetReal | |
| 43 | + addw 32(fp),36(fp),40(fp) | |
| 44 | + movf 0(40(fp)),0(16(fp)) | |
| 45 | + ret | |
| 46 | +#27 | |
| 47 | +# GetObj | |
| 48 | + addw 32(fp),36(fp),40(fp) | |
| 49 | + movp 0(40(fp)),0(16(fp)) | |
| 50 | + ret | |
| 51 | +#30 | |
| 52 | +#CallMethod: frame size==80 map==0x00b840 | |
| 53 | +# params | |
| 54 | +# module ptr: 32(fp) ptr | |
| 55 | +# method idx: 36(fp) | |
| 56 | +# this ptr: 40(fp) ptr | |
| 57 | +# args: 44(fp) ptr | |
| 58 | +# ret-val: 48(fp) ptr | |
| 59 | +# local vars used: | |
| 60 | +# frame: 52(fp) not-marked | |
| 61 | +# frame-slot: 56(fp) | |
| 62 | +# loop index: 60(fp) | |
| 63 | +# tmp: 64(fp) -- used for array idexing & alignment ck | |
| 64 | +# pick-tmp: 68(fp) ptr | |
| 65 | +# array len: 72(fp) | |
| 66 | +# | |
| 67 | + mframe 32(fp),36(fp),52(fp) | |
| 68 | + addw 52(fp),$32,56(fp) #compute slot address for arg | |
| 69 | + beqw 0(mp),40(fp),$35 #if static then 'this' is nil | |
| 70 | + movp 40(fp),0(56(fp)) #move 'this' into frame | |
| 71 | + addw $4,56(fp) #next slot | |
| 72 | +#35 | |
| 73 | + # move args into frame | |
| 74 | + # for(idx:=0; idx <len args; idx++ ) | |
| 75 | + movw $0,60(fp) #initialize loop idx | |
| 76 | + lena 44(fp),72(fp) #length of array | |
| 77 | +#37 | |
| 78 | + blew 72(fp),60(fp),$60 #loop condition | |
| 79 | + indw 44(fp),64(fp),60(fp) #index the array | |
| 80 | + movp 0(64(fp)),68(fp) #grab the array element; its a ref pick-adt | |
| 81 | + case 0(68(fp)),4(mp) #switch off of the 'pick' id | |
| 82 | +#41 | |
| 83 | + movp 4(68(fp)),0(56(fp)) # object param | |
| 84 | + jmp $57 | |
| 85 | +#43 | |
| 86 | + movw 4(68(fp)),0(56(fp)) # word param (byte,short,char,boolean,int) | |
| 87 | + jmp $57 | |
| 88 | +#45 | |
| 89 | + andw 56(fp),$7,64(fp) # check for 8-byte alignment | |
| 90 | + beqw 64(fp),$0,$48 # branch if already aligned | |
| 91 | + addw $4,56(fp) # next slot is aligned | |
| 92 | + movl 8(68(fp)),0(56(fp)) # big param (long) | |
| 93 | + addw $8,56(fp) # next param slot | |
| 94 | + jmp $58 | |
| 95 | +#51 | |
| 96 | + andw 56(fp),$7,64(fp) # check for 8-byte alignment | |
| 97 | + beqw 64(fp),$0,$54 # branch if already aligned | |
| 98 | + addw $4,56(fp) # next slot is aligned | |
| 99 | + movf 8(68(fp)),0(56(fp)) # real param (float,double) | |
| 100 | + addw $8,56(fp) # next param slot | |
| 101 | + jmp $58 | |
| 102 | +#57 | |
| 103 | + addw $4,56(fp) # next slot | |
| 104 | +#58 | |
| 105 | + addw $1,60(fp) #inc loop index | |
| 106 | + jmp $37 #end-for | |
| 107 | +#60 | |
| 108 | + # setup return value if one exists | |
| 109 | + beqw 0(mp),48(fp),$65 #if nil then no functional return | |
| 110 | + case 0(48(fp)),60(mp) #switch off pick field of ret-value | |
| 111 | +#62 | |
| 112 | + lea 4(48(fp)),16(52(fp)) #4-byte aligned return addr | |
| 113 | + jmp $65 | |
| 114 | + lea 8(48(fp)),16(52(fp)) #8-byte aligned return addr | |
| 115 | +#65 | |
| 116 | + mcall 52(fp),36(fp),32(fp) | |
| 117 | + ret | |
| 118 | +# | |
| 119 | +# change the following with care | |
| 120 | +# | |
| 121 | + desc $0,92,"80" | |
| 122 | + desc $1,48,"00a0" | |
| 123 | + desc $2,40,"0080" | |
| 124 | + desc $3,48,"0080" | |
| 125 | + desc $4,80,"00b840" | |
| 126 | + var @mp,92 | |
| 127 | + word @mp+4,4,0,1,41,1,6,43,6,7,45,7,9,51,66 | |
| 128 | + word @mp+60,2,0,6,62,6,9,64,66 | |
| 129 | + module Low | |
| 130 | + link 3,0, 0xaaaaaaaa,"SetByte" | |
| 131 | + link 3,3, 0xaaaaaaaa,"SetInt" | |
| 132 | + link 3,6, 0xaaaaaaaa,"SetBig" | |
| 133 | + link 3,9 ,0xaaaaaaaa,"SetReal" | |
| 134 | + link 1,12,0xaaaaaaaa,"SetObj" | |
| 135 | + link 2,15,0xaaaaaaaa,"GetByte" | |
| 136 | + link 2,18,0xaaaaaaaa,"GetInt" | |
| 137 | + link 2,21,0xaaaaaaaa,"GetBig" | |
| 138 | + link 2,24,0xaaaaaaaa,"GetReal" | |
| 139 | + link 2,27,0xaaaaaaaa,"GetObj" | |
| 140 | + link 4,30,0xaaaaaaaa,"CallMethod" | |
| @@ -0,0 +1,140 @@ | ||
| 1 | +#0 | |
| 2 | +# SetByte | |
| 3 | + addw 32(fp),36(fp),44(fp) | |
| 4 | + movb 40(fp),0(44(fp)) | |
| 5 | + ret | |
| 6 | +#3 | |
| 7 | +# SetInt | |
| 8 | + addw 32(fp),36(fp),44(fp) | |
| 9 | + movw 40(fp),0(44(fp)) | |
| 10 | + ret | |
| 11 | +#6 | |
| 12 | +# SetBig | |
| 13 | + addw 32(fp),36(fp),48(fp) | |
| 14 | + movl 40(fp),0(48(fp)) | |
| 15 | + ret | |
| 16 | +#9 | |
| 17 | +# SetReal | |
| 18 | + addw 32(fp),36(fp),48(fp) | |
| 19 | + movf 40(fp),0(48(fp)) | |
| 20 | + ret | |
| 21 | +#12 | |
| 22 | +# SetObj | |
| 23 | + addw 32(fp),36(fp),44(fp) | |
| 24 | + movp 40(fp),0(44(fp)) | |
| 25 | + ret | |
| 26 | +#15 | |
| 27 | +# GetByte | |
| 28 | + addw 32(fp),36(fp),40(fp) | |
| 29 | + movb 0(40(fp)),0(16(fp)) | |
| 30 | + ret | |
| 31 | +#18 | |
| 32 | +# GetInt | |
| 33 | + addw 32(fp),36(fp),40(fp) | |
| 34 | + movw 0(40(fp)),0(16(fp)) | |
| 35 | + ret | |
| 36 | +#21 | |
| 37 | +# GetBig | |
| 38 | + addw 32(fp),36(fp),40(fp) | |
| 39 | + movl 0(40(fp)),0(16(fp)) | |
| 40 | + ret | |
| 41 | +#24 | |
| 42 | +# GetReal | |
| 43 | + addw 32(fp),36(fp),40(fp) | |
| 44 | + movf 0(40(fp)),0(16(fp)) | |
| 45 | + ret | |
| 46 | +#27 | |
| 47 | +# GetObj | |
| 48 | + addw 32(fp),36(fp),40(fp) | |
| 49 | + movp 0(40(fp)),0(16(fp)) | |
| 50 | + ret | |
| 51 | +#30 | |
| 52 | +#CallMethod: frame size==80 map==0x00b840 | |
| 53 | +# params | |
| 54 | +# module ptr: 32(fp) ptr | |
| 55 | +# method idx: 36(fp) | |
| 56 | +# this ptr: 40(fp) ptr | |
| 57 | +# args: 44(fp) ptr | |
| 58 | +# ret-val: 48(fp) ptr | |
| 59 | +# local vars used: | |
| 60 | +# frame: 52(fp) not-marked | |
| 61 | +# frame-slot: 56(fp) | |
| 62 | +# loop index: 60(fp) | |
| 63 | +# tmp: 64(fp) -- used for array idexing & alignment ck | |
| 64 | +# pick-tmp: 68(fp) ptr | |
| 65 | +# array len: 72(fp) | |
| 66 | +# | |
| 67 | + mframe 32(fp),36(fp),52(fp) | |
| 68 | + addw 52(fp),$32,56(fp) #compute slot address for arg | |
| 69 | + beqw 0(mp),40(fp),$35 #if static then 'this' is nil | |
| 70 | + movp 40(fp),0(56(fp)) #move 'this' into frame | |
| 71 | + addw $4,56(fp) #next slot | |
| 72 | +#35 | |
| 73 | + # move args into frame | |
| 74 | + # for(idx:=0; idx <len args; idx++ ) | |
| 75 | + movw $0,60(fp) #initialize loop idx | |
| 76 | + lena 44(fp),72(fp) #length of array | |
| 77 | +#37 | |
| 78 | + blew 72(fp),60(fp),$60 #loop condition | |
| 79 | + indw 44(fp),64(fp),60(fp) #index the array | |
| 80 | + movp 0(64(fp)),68(fp) #grab the array element; its a ref pick-adt | |
| 81 | + case 0(68(fp)),4(mp) #switch off of the 'pick' id | |
| 82 | +#41 | |
| 83 | + movp 4(68(fp)),0(56(fp)) # object param | |
| 84 | + jmp $57 | |
| 85 | +#43 | |
| 86 | + movw 4(68(fp)),0(56(fp)) # word param (byte,short,char,boolean,int) | |
| 87 | + jmp $57 | |
| 88 | +#45 | |
| 89 | + andw 56(fp),$7,64(fp) # check for 8-byte alignment | |
| 90 | + beqw 64(fp),$0,$48 # branch if already aligned | |
| 91 | + addw $4,56(fp) # next slot is aligned | |
| 92 | + movl 8(68(fp)),0(56(fp)) # big param (long) | |
| 93 | + addw $8,56(fp) # next param slot | |
| 94 | + jmp $58 | |
| 95 | +#51 | |
| 96 | + andw 56(fp),$7,64(fp) # check for 8-byte alignment | |
| 97 | + beqw 64(fp),$0,$54 # branch if already aligned | |
| 98 | + addw $4,56(fp) # next slot is aligned | |
| 99 | + movf 8(68(fp)),0(56(fp)) # real param (float,double) | |
| 100 | + addw $8,56(fp) # next param slot | |
| 101 | + jmp $58 | |
| 102 | +#57 | |
| 103 | + addw $4,56(fp) # next slot | |
| 104 | +#58 | |
| 105 | + addw $1,60(fp) #inc loop index | |
| 106 | + jmp $37 #end-for | |
| 107 | +#60 | |
| 108 | + # setup return value if one exists | |
| 109 | + beqw 0(mp),48(fp),$65 #if nil then no functional return | |
| 110 | + case 0(48(fp)),60(mp) #switch off pick field of ret-value | |
| 111 | +#62 | |
| 112 | + lea 4(48(fp)),16(52(fp)) #4-byte aligned return addr | |
| 113 | + jmp $65 | |
| 114 | + lea 8(48(fp)),16(52(fp)) #8-byte aligned return addr | |
| 115 | +#65 | |
| 116 | + mcall 52(fp),36(fp),32(fp) | |
| 117 | + ret | |
| 118 | +# | |
| 119 | +# change the following with care | |
| 120 | +# | |
| 121 | + desc $0,92,"80" | |
| 122 | + desc $1,48,"00a0" | |
| 123 | + desc $2,40,"0080" | |
| 124 | + desc $3,48,"0080" | |
| 125 | + desc $4,80,"00b840" | |
| 126 | + var @mp,92 | |
| 127 | + word @mp+4,4,0,1,41,1,6,43,6,7,45,7,9,51,66 | |
| 128 | + word @mp+60,2,0,6,62,6,9,64,66 | |
| 129 | + module Low | |
| 130 | + link 3,0, 0x349a7796,"SetByte" | |
| 131 | + link 3,3, 0x2de68727,"SetInt" | |
| 132 | + link 3,6, 0xd7e9f417,"SetBig" | |
| 133 | + link 3,9 ,0xa51f3c84,"SetReal" | |
| 134 | + link 1,12,0x2ada273,"SetObj" | |
| 135 | + link 2,15,0x65a049aa,"GetByte" | |
| 136 | + link 2,18,0x7060ebba,"GetInt" | |
| 137 | + link 2,21,0x9f04ed0,"GetBig" | |
| 138 | + link 2,24,0x553990fb,"GetReal" | |
| 139 | + link 2,27,0x30af57fd,"GetObj" | |
| 140 | + link 4,30,0x2943aeae,"CallMethod" | |
| @@ -0,0 +1,65 @@ | ||
| 1 | +# proto file will be replaced with low.s | |
| 2 | +implement Low; | |
| 3 | + | |
| 4 | +include "jni.m"; | |
| 5 | + | |
| 6 | +SetByte( ptr : ref Loader->Niladt, off : int, val : byte ) | |
| 7 | +{ | |
| 8 | + junk := (ptr,off,val); | |
| 9 | +} | |
| 10 | + | |
| 11 | +SetInt( ptr : ref Loader->Niladt, off : int, val : int ) | |
| 12 | +{ | |
| 13 | + junk := (ptr,off,val); | |
| 14 | +} | |
| 15 | + | |
| 16 | +SetBig( ptr : ref Loader->Niladt, off : int, val : big ) | |
| 17 | +{ | |
| 18 | + junk := (ptr,off,val); | |
| 19 | +} | |
| 20 | + | |
| 21 | +SetReal( ptr : ref Loader->Niladt, off : int, val : real ) | |
| 22 | +{ | |
| 23 | + junk := (ptr,off,val); | |
| 24 | +} | |
| 25 | + | |
| 26 | +SetObj( ptr : ref Loader->Niladt, off : int, val : JNI->JObject ) | |
| 27 | +{ | |
| 28 | + junk := (ptr,off,val); | |
| 29 | +} | |
| 30 | + | |
| 31 | +GetByte( ptr : ref Loader->Niladt, off : int ) : byte | |
| 32 | +{ | |
| 33 | + junk := (ptr,off); | |
| 34 | + return( byte 0 ); | |
| 35 | +} | |
| 36 | + | |
| 37 | +GetInt( ptr : ref Loader->Niladt, off : int ) : int | |
| 38 | +{ | |
| 39 | + junk := (ptr,off); | |
| 40 | + return( 0 ); | |
| 41 | +} | |
| 42 | + | |
| 43 | +GetBig( ptr : ref Loader->Niladt, off : int ) : big | |
| 44 | +{ | |
| 45 | + junk := (ptr,off); | |
| 46 | + return( big 0 ); | |
| 47 | +} | |
| 48 | + | |
| 49 | +GetReal( ptr : ref Loader->Niladt, off : int ) : real | |
| 50 | +{ | |
| 51 | + junk := (ptr,off); | |
| 52 | + return( 0.0 ); | |
| 53 | +} | |
| 54 | + | |
| 55 | +GetObj( ptr : ref Loader->Niladt, off : int ) : JNI->JObject | |
| 56 | +{ | |
| 57 | + junk := (ptr,off); | |
| 58 | + return( nil ); | |
| 59 | +} | |
| 60 | + | |
| 61 | +CallMethod( mod : Nilmod, idx : int, this : JNI->JObject, args : array of ref JNI->Value, retval : ref JNI->Value ) | |
| 62 | +{ | |
| 63 | + junk := (mod,idx,this,args,retval); | |
| 64 | +} | |
| 65 | + | |
| @@ -0,0 +1,45 @@ | ||
| 1 | +<../../../mkconfig | |
| 2 | + | |
| 3 | +TARG=\ | |
| 4 | + cast.dis\ | |
| 5 | + low.dis\ | |
| 6 | + jni.dis\ | |
| 7 | + classloader.dis\ | |
| 8 | + javaassist.dis\ | |
| 9 | + javatrace.dis\ | |
| 10 | + javanative.dis\ | |
| 11 | + jvm.dis\ | |
| 12 | + jinfo.dis\ | |
| 13 | + | |
| 14 | +MODULES=\ | |
| 15 | + $ROOT/java/module/classloader.m\ | |
| 16 | + $ROOT/java/module/jni.m\ | |
| 17 | + $ROOT/java/module/cast.m\ | |
| 18 | + | |
| 19 | +SYSMODULES=\ | |
| 20 | + draw.m\ | |
| 21 | + hash.m\ | |
| 22 | + keyring.m\ | |
| 23 | + loader.m\ | |
| 24 | + math.m\ | |
| 25 | + string.m\ | |
| 26 | + sys.m\ | |
| 27 | + | |
| 28 | +DISBIN=$ROOT/java/dis/java | |
| 29 | + | |
| 30 | +<$ROOT/mkfiles/mkdis | |
| 31 | + | |
| 32 | +LIMBOFLAGS=-I$MODDIR\ | |
| 33 | + -I$ROOT/java/module\ | |
| 34 | + | |
| 35 | +%.dis: sign.sh | |
| 36 | + | |
| 37 | +%.dis: %.base | |
| 38 | + chmod +x sign.sh | |
| 39 | + sh sign.sh ${stem}proto $stem | |
| 40 | + | |
| 41 | +classloader.dis: classloader.b | |
| 42 | + limbo -z $LIMBOFLAGS -gw classloader.b | |
| 43 | + | |
| 44 | +clean-std:V: | |
| 45 | + rm -f *.dis *.sbl *.s sign.sed | |
| @@ -0,0 +1,38 @@ | ||
| 1 | +/^ link.*"ArraytoJS"$/s/0x[^,]*/0xfb08d2ba/ | |
| 2 | +/^ link.*"JStoObject"$/s/0x[^,]*/0x76cd0754/ | |
| 3 | +/^ link.*"ObjecttoJT"$/s/0x[^,]*/0xae823704/ | |
| 4 | +/^ link.*"arrayof"$/s/0x[^,]*/0x6d675ef6/ | |
| 5 | +/^ link.*"bigarraytoJS"$/s/0x[^,]*/0x1ebcdfdd/ | |
| 6 | +/^ link.*"bytearraytoJS"$/s/0x[^,]*/0x79238ebb/ | |
| 7 | +/^ link.*"getabsint"$/s/0x[^,]*/0xe67bf126/ | |
| 8 | +/^ link.*"getadtstring"$/s/0x[^,]*/0x3911b054/ | |
| 9 | +/^ link.*"getbytearray"$/s/0x[^,]*/0x480b7ac3/ | |
| 10 | +/^ link.*"getclassadt"$/s/0x[^,]*/0x45af8037/ | |
| 11 | +/^ link.*"getint"$/s/0x[^,]*/0x9af56bb1/ | |
| 12 | +/^ link.*"getintarray"$/s/0x[^,]*/0x55e7e9b3/ | |
| 13 | +/^ link.*"getmd"$/s/0x[^,]*/0x21126c42/ | |
| 14 | +/^ link.*"getobjclass"$/s/0x[^,]*/0x7e47f344/ | |
| 15 | +/^ link.*"getptr"$/s/0x[^,]*/0xd7e85087/ | |
| 16 | +/^ link.*"getreloc"$/s/0x[^,]*/0xbb4256c7/ | |
| 17 | +/^ link.*"getrtreloc"$/s/0x[^,]*/0xa1fa7e52/ | |
| 18 | +/^ link.*"getstrarray"$/s/0x[^,]*/0x67808576/ | |
| 19 | +/^ link.*"getstring"$/s/0x[^,]*/0xe6647e4a/ | |
| 20 | +/^ link.*"intarraytoJS"$/s/0x[^,]*/0x9dfa2ee1/ | |
| 21 | +/^ link.*"jclnilmod"$/s/0x[^,]*/0x18138a11/ | |
| 22 | +/^ link.*"little_endian"$/s/0x[^,]*/0x616977e8/ | |
| 23 | +/^ link.*"makeadt"$/s/0x[^,]*/0x2d805d/ | |
| 24 | +/^ link.*"mcall0"$/s/0x[^,]*/0x9af56bb1/ | |
| 25 | +/^ link.*"mcall1"$/s/0x[^,]*/0xcbd2cc54/ | |
| 26 | +/^ link.*"mcalla"$/s/0x[^,]*/0x2c8f47/ | |
| 27 | +/^ link.*"mcallm"$/s/0x[^,]*/0x1fe62f91/ | |
| 28 | +/^ link.*"modhash"$/s/0x[^,]*/0x4e5d43e7/ | |
| 29 | +/^ link.*"new"$/s/0x[^,]*/0xbb2da06c/ | |
| 30 | +/^ link.*"objhash"$/s/0x[^,]*/0x646cd7d0/ | |
| 31 | +/^ link.*"putclass"$/s/0x[^,]*/0x8f05c931/ | |
| 32 | +/^ link.*"putint"$/s/0x[^,]*/0x2de68727/ | |
| 33 | +/^ link.*"putmod"$/s/0x[^,]*/0x66b5c780/ | |
| 34 | +/^ link.*"putobj"$/s/0x[^,]*/0x4f9a2948/ | |
| 35 | +/^ link.*"putptr"$/s/0x[^,]*/0x43ec4524/ | |
| 36 | +/^ link.*"putstring"$/s/0x[^,]*/0x46bbe09a/ | |
| 37 | +/^ link.*"realarraytoJS"$/s/0x[^,]*/0xc8107991/ | |
| 38 | +/^ link.*"sysnilmod"$/s/0x[^,]*/0x8cdb1059/ | |
| @@ -0,0 +1,6 @@ | ||
| 1 | +set -e | |
| 2 | +limbo -I../../module -GS $1.b | |
| 3 | +sed -n '/^ link/s;.*,\(0x[^,]*\),"\(.*\)"$;/^ link.*"\2"$/s/0x[^,]*/\1/;p' $1.s > sign.sed | |
| 4 | +sed -f sign.sed $2.base | tr -d '\15' > $2.s | |
| 5 | +asm $2.s | |
| 6 | +rm $1.s | |
| @@ -0,0 +1,7 @@ | ||
| 1 | +<../../mkconfig | |
| 2 | + | |
| 3 | +DIRS=\ | |
| 4 | + j2d\ | |
| 5 | + java\ | |
| 6 | + | |
| 7 | +<$ROOT/mkfiles/mksubdirs | |
| @@ -0,0 +1,8 @@ | ||
| 1 | +<../mkconfig | |
| 2 | + | |
| 3 | +DIRS=\ | |
| 4 | +# tools\ | |
| 5 | +# pkg\ | |
| 6 | + appl\ | |
| 7 | + | |
| 8 | +<$ROOT/mkfiles/mksubdirs | |
| @@ -0,0 +1,80 @@ | ||
| 1 | +# | |
| 2 | +# cast.m | |
| 3 | +# | |
| 4 | +# cast from JNI types to generic JNI types | |
| 5 | +# | |
| 6 | +Cast : module | |
| 7 | +{ | |
| 8 | + PATH : con "/dis/java/cast.dis"; | |
| 9 | + | |
| 10 | + # cast to JObject | |
| 11 | + FromJArray : fn( ary : JNI->JArray ) : (JNI->JObject); | |
| 12 | + FromJClass : fn( cl : JNI->JClass ) : (JNI->JObject); | |
| 13 | + FromJString : fn( str : JNI->JString ) : (JNI->JObject); | |
| 14 | + | |
| 15 | + # cast JArray* to JArray | |
| 16 | + ByteToJArray : fn( ptr : ref JNI->ByteArray ) : (JNI->JArray); | |
| 17 | + IntToJArray : fn( ptr : ref JNI->IntArray ) : (JNI->JArray); | |
| 18 | + BigToJArray : fn( ptr : ref JNI->BigArray ) : (JNI->JArray); | |
| 19 | + RealToJArray : fn( ptr : ref JNI->RealArray ) : (JNI->JArray); | |
| 20 | + ClassToJArray : fn( ptr : ref JNI->ClassArray ) : (JNI->JArray); | |
| 21 | + StringToJArray : fn( ptr : ref JNI->StringArray ) : (JNI->JArray); | |
| 22 | + ObjectToJArray : fn( ptr : ref JNI->ObjectArray ) : (JNI->JArray); | |
| 23 | + | |
| 24 | + # cast JArray to JArray* | |
| 25 | + JArrayToByte : fn( ptr : JNI->JArray ) : ref JNI->ByteArray; | |
| 26 | + JArrayToInt : fn( ptr : JNI->JArray ) : ref JNI->IntArray; | |
| 27 | + JArrayToBig : fn( ptr : JNI->JArray ) : ref JNI->BigArray; | |
| 28 | + JArrayToReal : fn( ptr : JNI->JArray ) : ref JNI->RealArray; | |
| 29 | + JArrayToClass : fn( ptr : JNI->JArray ) : ref JNI->ClassArray; | |
| 30 | + JArrayToString : fn( ptr : JNI->JArray ) : ref JNI->StringArray; | |
| 31 | + JArrayToObject : fn( ptr : JNI->JArray ) : ref JNI->ObjectArray; | |
| 32 | + | |
| 33 | + # cast from JObjects | |
| 34 | + ToJClass : fn( obj : JNI->JObject ) : (JNI->JClass); | |
| 35 | + ToJString : fn( obj : JNI->JObject ) : (JNI->JString); | |
| 36 | + ToJArray : fn( obj : JNI->JObject ) : (JNI->JArray); | |
| 37 | + ToJArrayB : fn( obj : JNI->JObject ) : (JNI->JArrayB); | |
| 38 | + ToJArrayC : fn( obj : JNI->JObject ) : (JNI->JArrayC); | |
| 39 | + ToJArrayS : fn( obj : JNI->JObject ) : (JNI->JArrayS); | |
| 40 | + ToJArrayI : fn( obj : JNI->JObject ) : (JNI->JArrayI); | |
| 41 | + ToJArrayJ : fn( obj : JNI->JObject ) : (JNI->JArrayJ); | |
| 42 | + ToJArrayF : fn( obj : JNI->JObject ) : (JNI->JArrayF); | |
| 43 | + ToJArrayD : fn( obj : JNI->JObject ) : (JNI->JArrayD); | |
| 44 | + ToJArrayZ : fn( obj : JNI->JObject ) : (JNI->JArrayZ); | |
| 45 | + ToJArrayJObject : fn( obj : JNI->JObject ) : (JNI->JArrayJObject); | |
| 46 | + ToJArrayJString : fn( obj : JNI->JObject ) : (JNI->JArrayJString); | |
| 47 | + | |
| 48 | + # cast for thread data | |
| 49 | + JObjToJThd : fn( obj : JNI->JObject ) : (JNI->JThread); | |
| 50 | + JThdToJObj : fn( jthd : JNI->JThread ) : (JNI->JObject); | |
| 51 | + | |
| 52 | + # cast to a niladt | |
| 53 | + Class2Niladt : fn( cl : JNI->ClassData ) : ref Loader->Niladt; | |
| 54 | + Obj2Niladt : fn( cl : JNI->JObject ) : ref Loader->Niladt; | |
| 55 | + | |
| 56 | + # utility | |
| 57 | + JNI2Nilmod : fn( j : JNI ) : Nilmod; | |
| 58 | + JArrayToHolder : fn( ary : array of JNI->JArray ) : array of JNI->JString; | |
| 59 | + | |
| 60 | +}; | |
| 61 | + | |
| 62 | +Low : module | |
| 63 | +{ | |
| 64 | + PATH : con "/dis/java/low.dis"; | |
| 65 | + | |
| 66 | + SetByte : fn( ptr : ref Loader->Niladt, off : int, val : byte ); | |
| 67 | + SetInt : fn( ptr : ref Loader->Niladt, off : int, val : int ); | |
| 68 | + SetBig : fn( ptr : ref Loader->Niladt, off : int, val : big ); | |
| 69 | + SetReal : fn( ptr : ref Loader->Niladt, off : int, val : real ); | |
| 70 | + SetObj : fn( ptr : ref Loader->Niladt, off : int, val : JNI->JObject ); | |
| 71 | + | |
| 72 | + GetByte : fn( ptr : ref Loader->Niladt, off : int ) : byte; | |
| 73 | + GetInt : fn( ptr : ref Loader->Niladt, off : int ) : int; | |
| 74 | + GetBig : fn( ptr : ref Loader->Niladt, off : int ) : big; | |
| 75 | + GetReal : fn( ptr : ref Loader->Niladt, off : int ) : real; | |
| 76 | + GetObj : fn( ptr : ref Loader->Niladt, off : int ) : (JNI->JObject); | |
| 77 | + | |
| 78 | + CallMethod : fn( mod : Nilmod, idx : int, this : JNI->JObject, args : array of ref JNI->Value, retval : ref JNI->Value ); | |
| 79 | + | |
| 80 | +}; | |
| @@ -0,0 +1,420 @@ | ||
| 1 | +include "draw.m"; | |
| 2 | +# | |
| 3 | +# Java Class Loader. | |
| 4 | +# | |
| 5 | + | |
| 6 | +JavaClassLoader: module | |
| 7 | +{ | |
| 8 | + PATH: con "/dis/java/classloader.dis"; | |
| 9 | + ROOT: con "/dis/java/java/"; | |
| 10 | + PROG: con "#p"; | |
| 11 | + LOADER: con "@Loader"; | |
| 12 | + CLASS: con "@Class"; | |
| 13 | + MP: con "@mp"; | |
| 14 | + ADT: con "@adt"; | |
| 15 | + NP: con "@np"; | |
| 16 | + OBJ: con "@obj"; | |
| 17 | + JEX: con "@jex"; | |
| 18 | + SYS: con "@sys"; | |
| 19 | + EXIST: con "does not exist"; | |
| 20 | + MAINFIELD: con "main"; | |
| 21 | + MAINSIGNATURE: con "([Ljava/lang/String;)V"; | |
| 22 | + VOIDSIGNATURE: con "()V"; | |
| 23 | + ARRAYCLASS: con "inferno/vm/Array"; | |
| 24 | + STRINGCLASS: con "java/lang/String"; | |
| 25 | + EXCEPTIONPATH: con "java/lang/"; | |
| 26 | + JAVAEXCEPTION: con "java ex"; | |
| 27 | + SPECIALINIT: con "<init>"; | |
| 28 | + SPECIALCLINIT: con "<clinit>"; | |
| 29 | + SPECIALCLONE: con "<clone>"; | |
| 30 | + SUXV: con '4'; | |
| 31 | + JAVA: con ('J'<<24)|('a'<<16)|('v'<<8)|'a'; | |
| 32 | + SUX: con ('S'<<24)|('u'<<16)|('x'<<8)|SUXV; | |
| 33 | + NEW, HIER, RESOLVE, LOADED, INITED: | |
| 34 | + con iota; | |
| 35 | + MAGIC, VERSION, NAME, SUPER, INTERFACES, RELOC, DSIZE, DRELOC, CLASSREF: | |
| 36 | + con (iota * 4); | |
| 37 | + CMP, CADT, CNP, COBJ, CJEX, CSYS: | |
| 38 | + con iota; | |
| 39 | + VVAL, VMP, VNP, VOBJ: con iota; | |
| 40 | + PVALUE, PEXTRA, PMETHOD, PSTATIC: | |
| 41 | + con iota; | |
| 42 | + WORDZ: con 4; | |
| 43 | + BIGZ: con 8; | |
| 44 | + MAPZ: con WORDZ * 8; | |
| 45 | + STACKSIZE: con 1024; | |
| 46 | + METHODOFFSET: con 2; | |
| 47 | + RTCLASSOFFSET: con 1 * WORDZ; | |
| 48 | + RTRELOCOFFSET: con 2 * WORDZ; | |
| 49 | + RTTHISOFFSET: con 3 * WORDZ; | |
| 50 | + RTFIRSTRELOC: con 4 * WORDZ; | |
| 51 | + CLASSADTOFFSET: con 1 * WORDZ; | |
| 52 | + MAXUNENCODED: con Sys->NAMEMAX - 7; | |
| 53 | + ENCODEDLEN: con 21; | |
| 54 | + RDELTA: con 16r80; | |
| 55 | + | |
| 56 | + T_BOOLEAN: con 4; | |
| 57 | + T_CHAR: con 5; | |
| 58 | + T_FLOAT: con 6; | |
| 59 | + T_DOUBLE: con 7; | |
| 60 | + T_BYTE: con 8; | |
| 61 | + T_SHORT: con 9; | |
| 62 | + T_INT: con 10; | |
| 63 | + T_LONG: con 11; | |
| 64 | + T_OBJECT: con 12; | |
| 65 | + T_ARRAY: con 13; | |
| 66 | + | |
| 67 | + ACC_PUBLIC: con 16r0001; | |
| 68 | + ACC_PRIVATE: con 16r0002; | |
| 69 | + ACC_PROTECTED: con 16r0004; | |
| 70 | + ACC_STATIC: con 16r0008; | |
| 71 | + ACC_FINAL: con 16r0010; | |
| 72 | + ACC_SUPER: con 16r0020; | |
| 73 | + ACC_SYNCHRONIZED: con 16r0020; | |
| 74 | + ACC_VOLATILE: con 16r0040; | |
| 75 | + ACC_TRANSIENT: con 16r0080; | |
| 76 | + ACC_NATIVE: con 16r0100; | |
| 77 | + ACC_INTERFACE: con 16r0200; | |
| 78 | + ACC_ABSTRACT: con 16r0400; | |
| 79 | + | |
| 80 | + JCL_INTEREXT: con 16r4000; | |
| 81 | + JCL_INTERWORK: con 16r8000; | |
| 82 | + | |
| 83 | + MUSTCOMPILE: con 16r10000; | |
| 84 | + DONTCOMPILE: con 16r20000; | |
| 85 | + | |
| 86 | + Rgetputfield: con 16r1 << 16; | |
| 87 | + Rgetputstatic: con 16r2 << 16; | |
| 88 | + Rinvokeinterface: con 16r3 << 16; | |
| 89 | + Rinvokespecial: con 16r4 << 16; | |
| 90 | + Rinvokestatic: con 16r5 << 16; | |
| 91 | + Rinvokevirtual: con 16r6 << 16; | |
| 92 | + Rmask: con 16r7 << 16; | |
| 93 | + | |
| 94 | + Rstaticmp: con 16r08 << 16; | |
| 95 | + Rspecialmp: con 16r10 << 16; | |
| 96 | + | |
| 97 | + POP: con 16r3 << 2; # operand | |
| 98 | + PSRC: con 16r1 << 2; # patch source operand | |
| 99 | + PDST: con 16r2 << 2; # destination | |
| 100 | + PMID: con 16r3 << 2; # middle | |
| 101 | + | |
| 102 | + PTYPE: con 16r3; # Operand type | |
| 103 | + PIMM: con 16r0; # patch immediate operand | |
| 104 | + PSIND: con 16r1; # single indirect offset | |
| 105 | + PDIND1: con 16r2; # first offset of double indirect | |
| 106 | + PDIND2: con 16r3; # second offset of double indirect | |
| 107 | + | |
| 108 | + ISHIFT: con 4; # instr index shift | |
| 109 | + | |
| 110 | + jninil: Nilmod; | |
| 111 | + jnisig: int; | |
| 112 | + | |
| 113 | + Extra: adt | |
| 114 | + { | |
| 115 | + what: int; | |
| 116 | + class: cyclic ref Class; | |
| 117 | + }; | |
| 118 | + | |
| 119 | + Field: adt | |
| 120 | + { | |
| 121 | + field: string; | |
| 122 | + signature: string; | |
| 123 | + flags: int; | |
| 124 | + value: int; | |
| 125 | + }; | |
| 126 | + | |
| 127 | + Method: adt | |
| 128 | + { | |
| 129 | + field: ref Field; | |
| 130 | + class: cyclic ref Class; | |
| 131 | + }; | |
| 132 | + | |
| 133 | + Patch: adt | |
| 134 | + { | |
| 135 | + what: int; | |
| 136 | + value: int; | |
| 137 | + }; | |
| 138 | + | |
| 139 | + Reloc: adt | |
| 140 | + { | |
| 141 | + field: string; | |
| 142 | + signature: string; | |
| 143 | + flags: int; | |
| 144 | + patch: array of byte; | |
| 145 | + }; | |
| 146 | + | |
| 147 | + RTReloc: adt | |
| 148 | + { | |
| 149 | + field: string; | |
| 150 | + signature: string; | |
| 151 | + flags: int; | |
| 152 | + }; | |
| 153 | + | |
| 154 | + Interface: adt | |
| 155 | + { | |
| 156 | + class: cyclic ref Class; | |
| 157 | + methods: array of int; | |
| 158 | + }; | |
| 159 | + | |
| 160 | + Ldinfo: adt | |
| 161 | + { | |
| 162 | + links: array of Loader->Link; | |
| 163 | + nlinks: array of Loader->Link; | |
| 164 | + types: array of Loader->Typedesc; | |
| 165 | + extraoffset: int; | |
| 166 | + extrabase: int; | |
| 167 | + extras: cyclic array of Extra; | |
| 168 | + reloc: array of Patch; | |
| 169 | + }; | |
| 170 | + | |
| 171 | + ClassObject: adt | |
| 172 | + { | |
| 173 | + mod: ref Loader->Niladt; | |
| 174 | + class: cyclic ref Class; | |
| 175 | + aryname: string; | |
| 176 | + }; | |
| 177 | + | |
| 178 | + Object: adt | |
| 179 | + { | |
| 180 | + mod: ref Loader->Niladt; | |
| 181 | + | |
| 182 | + class: fn(o: self ref Object): ref Class; | |
| 183 | + }; | |
| 184 | + | |
| 185 | + Array: adt | |
| 186 | + { | |
| 187 | + mod: ref Loader->Niladt; | |
| 188 | + holder: array of ref JavaString; | |
| 189 | + dims: int; | |
| 190 | + class: ref Class; | |
| 191 | + primitive: int; | |
| 192 | + }; | |
| 193 | + | |
| 194 | + JavaString: adt | |
| 195 | + { | |
| 196 | + mod: ref Loader->Niladt; | |
| 197 | + str: string; | |
| 198 | + }; | |
| 199 | + | |
| 200 | + JavaThrowable: adt | |
| 201 | + { | |
| 202 | + mod: ref Loader->Niladt; | |
| 203 | + trace: array of byte; | |
| 204 | + msg: ref JavaString; | |
| 205 | + }; | |
| 206 | + | |
| 207 | + ThreadData: adt | |
| 208 | + { | |
| 209 | + BLOCKED, SUSPENDED, ACKSUSP, WAITSUSP, WAITSTOP, INTERRUPTED, EXITED, DAEMON: | |
| 210 | + con (1 << iota); | |
| 211 | + SHUTDOWN, BLOCK, UNBLOCK, SUSPEND, RESUME, STOP: | |
| 212 | + con iota; | |
| 213 | + | |
| 214 | + pid: int; | |
| 215 | + wchan: chan of int; | |
| 216 | + flags: int; | |
| 217 | + ctlfile: string; | |
| 218 | + control: ref Sys->FD; | |
| 219 | + culprit: ref Object; | |
| 220 | + this: ref Object; | |
| 221 | + }; | |
| 222 | + | |
| 223 | + Class: adt | |
| 224 | + { | |
| 225 | + state: int; | |
| 226 | + name: string; | |
| 227 | + encoding: string; | |
| 228 | + ownname: string; | |
| 229 | + file: string; | |
| 230 | + version: int; | |
| 231 | + flags: int; | |
| 232 | + mod: Nilmod; | |
| 233 | + native: Nilmod; | |
| 234 | + super: cyclic ref Class; | |
| 235 | + this: cyclic ref ClassObject; | |
| 236 | + info: cyclic ref Ldinfo; | |
| 237 | + refs: cyclic array of ref Class; | |
| 238 | + staticdata: array of ref Field; | |
| 239 | + objectdata: list of ref Field; | |
| 240 | + privatemethods: array of ref Field; | |
| 241 | + staticmethods: array of ref Field; | |
| 242 | + virtualmethods: cyclic array of Method; | |
| 243 | + initmethods: array of ref Field; | |
| 244 | + classinit: ref Field; | |
| 245 | + cloneindex: int; | |
| 246 | + interfaces: cyclic array of Interface; | |
| 247 | + interindex: int; | |
| 248 | + intercache: cyclic list of (ref Class, array of int); | |
| 249 | + interextends: cyclic list of ref Class; | |
| 250 | + interdirect: cyclic list of ref Class; | |
| 251 | + objectsize: int; | |
| 252 | + staticoffset: int; | |
| 253 | + staticsize: int; | |
| 254 | + nextra: int; | |
| 255 | + dataoffset: int; | |
| 256 | + datasize: int; | |
| 257 | + datareloc: int; | |
| 258 | + moddata: ref Loader->Niladt; | |
| 259 | + modsize: int; | |
| 260 | + modmap: array of byte; | |
| 261 | + objmap: array of byte; | |
| 262 | + objtype: int; | |
| 263 | + mlinks: int; | |
| 264 | + | |
| 265 | + loadclass: fn(c: self ref Class); | |
| 266 | + resolve: fn(c: self ref Class); | |
| 267 | + loadinterfaces: fn(c: self ref Class); | |
| 268 | + extinterfaces: fn(c: self ref Class); | |
| 269 | + linkinterfaces: fn(c: self ref Class); | |
| 270 | + makeobjtype: fn(c: self ref Class); | |
| 271 | + makevmtable: fn(c: self ref Class, m: list of ref Field, z: int): array of Method; | |
| 272 | + relocate: fn(c: self ref Class); | |
| 273 | + instrpatch: fn(c: self ref Class, i: array of Loader->Inst); | |
| 274 | + modpatch: fn(c: self ref Class); | |
| 275 | + getmethod: fn(c: self ref Class, f, s: string, flag: int): int; | |
| 276 | + override: fn(c: self ref Class, f, s: string): int; | |
| 277 | + findimethod: fn(c: self ref Class, s: string): ref Field; | |
| 278 | + findpmethod: fn(c: self ref Class, f, s: string): ref Field; | |
| 279 | + findsfield: fn(c: self ref Class, f: string): ref Field; | |
| 280 | + findsmethod: fn(c: self ref Class, f, s: string): ref Field; | |
| 281 | + findofield: fn(c: self ref Class, f: string): ref Field; | |
| 282 | + findvmethod: fn(c: self ref Class, f, s: string): int; | |
| 283 | + extra: fn(c: self ref Class, w, n: int, r: ref Class); | |
| 284 | + extras: fn(c: self ref Class, a: array of Reloc, n: int, r: ref Class): int; | |
| 285 | + special: fn(c: self ref Class, f, s: string, flags: int, r: ref Class): (int, ref Class, int); | |
| 286 | + copymap: fn(c: self ref Class, m: array of byte, dr: int); | |
| 287 | + copymd: fn(c: self ref Class, md: ref Loader->Niladt, dr: int, om: Nilmod); | |
| 288 | + relocref: fn(c: self ref Class, t: ref Class, i: array of Loader->Inst, a: array of Reloc, x: int): int; | |
| 289 | + resolvereloc: fn(c: self ref Class, r, s: string, flags: int): (int, int); | |
| 290 | + addinterface: fn(c: self ref Class); | |
| 291 | + getinterface: fn(c: self ref Class, k: ref Class): array of int; | |
| 292 | + interlook: fn(c: self ref Class, a: array of Interface): array of int; | |
| 293 | + initjni: fn(c: self ref Class); | |
| 294 | + loadnative: fn(c: self ref Class); | |
| 295 | + | |
| 296 | + # runtime entry points | |
| 297 | + run: fn(c: self ref Class, args: list of string); | |
| 298 | + new: fn(c: self ref Class): ref Object; | |
| 299 | + call: fn(c: self ref Class, x: int, a: ref Object): ref Object; | |
| 300 | + clone: fn(c: self ref Class, o: ref Object): ref Object; | |
| 301 | + }; | |
| 302 | + | |
| 303 | + init: fn(j: JavaClassLoader, ctxt: ref Draw->Context); | |
| 304 | + shutdown: fn(); | |
| 305 | + info: fn(name: string); | |
| 306 | + loader: fn(name: string): ref Class; | |
| 307 | + encodename: fn(name: string): string; | |
| 308 | + getclass: fn(name: string): ref Class; | |
| 309 | + getmodclass: fn(mod: Nilmod): ref Class; | |
| 310 | + runmain: fn( j: JavaClassLoader, classname : string, argv : list of string ); | |
| 311 | + sysexception: fn( ex : string ) : ref Object; | |
| 312 | + setflags: fn( flags : list of (string,int) ); | |
| 313 | + | |
| 314 | + # runtime entry points | |
| 315 | + compatclass: fn(who, what: ref Class): int; | |
| 316 | + checkcast: fn(who: ref Object, what: ref Class); | |
| 317 | + instanceof: fn(who: ref Object, what: ref Class): int; | |
| 318 | + acheckcast: fn(who: ref Array, what: ref Class, dims: int); | |
| 319 | + ainstanceof: fn(who: ref Array, what: ref Class, dims: int): int; | |
| 320 | + pcheckcast: fn(who: ref Array, what, dims: int); | |
| 321 | + pinstanceof: fn(who: ref Array, what, dims: int): int; | |
| 322 | + aastorecheck: fn(who: ref Object, what: ref Array); | |
| 323 | + arraycopy: fn(src: ref Array, sx: int, dst: ref Array, dx: int, n: int); | |
| 324 | + multianewarray: fn(ndim: int, c: ref Class, etype: int, bounds: array of int): ref Array; | |
| 325 | + error: fn(s: string); | |
| 326 | + delthreaddata: fn(); | |
| 327 | + getthreaddata: fn(): ref ThreadData; | |
| 328 | + getcontext: fn(): ref Draw->Context; | |
| 329 | + daemonize: fn(); | |
| 330 | + culprit: fn(e: string): ref Object; | |
| 331 | + throw: fn(c: ref Object); | |
| 332 | + rtload: fn(addr: int); | |
| 333 | + getinterface: fn(c: ref Class, cookie: int): int; | |
| 334 | + monitorenter: fn(o: ref Object); | |
| 335 | + monitorexit: fn(o: ref Object); | |
| 336 | + monitorwait: fn(o: ref Object, l: int); | |
| 337 | + monitornotify: fn(o: ref Object, f: int); | |
| 338 | + sleep: fn(l: int); | |
| 339 | + interrupt: fn(t: ref ThreadData); | |
| 340 | + suspend: fn(t: ref ThreadData); | |
| 341 | + resume: fn(t: ref ThreadData); | |
| 342 | + stop: fn(t: ref ThreadData, o: ref Object); | |
| 343 | + | |
| 344 | + # math | |
| 345 | + lcmp: fn(x: big, y: big): int; | |
| 346 | + | |
| 347 | + d2i: fn(x: real): int; | |
| 348 | + d2l: fn(x: real): big; | |
| 349 | + dcmpg: fn(x, y: real): int; | |
| 350 | + dcmpl: fn(x, y: real): int; | |
| 351 | + drem: fn(x, y: real): real; | |
| 352 | +}; | |
| 353 | + | |
| 354 | +JavaNative: module | |
| 355 | +{ | |
| 356 | + PATH: con "/dis/java/javanative.dis"; | |
| 357 | + | |
| 358 | + init: fn(sys: Sys, ld: Loader, jldr: JavaClassLoader, jass: JavaAssist): string; | |
| 359 | +}; | |
| 360 | + | |
| 361 | +JavaAssist: module | |
| 362 | +{ | |
| 363 | + PATH: con "/dis/java/javaassist.dis"; | |
| 364 | + | |
| 365 | + getint: fn(mod: Nilmod, index: int): int; | |
| 366 | + getbytearray: fn(mod: Nilmod, index: int): array of byte; | |
| 367 | + getintarray: fn(mod: Nilmod, index: int): array of int; | |
| 368 | + getstrarray: fn(mod: Nilmod, index: int): array of string; | |
| 369 | + getptr: fn(mod: Nilmod, index: int): ref Loader->Niladt; | |
| 370 | + getreloc: fn(mod: Nilmod, index: int): array of JavaClassLoader->Reloc; | |
| 371 | + getrtreloc: fn(data: ref Loader->Niladt, index: int): array of JavaClassLoader->RTReloc; | |
| 372 | + getclassadt: fn(data: ref Loader->Niladt, index: int): ref JavaClassLoader->Class; | |
| 373 | + getabsint: fn(addr: int): int; | |
| 374 | + getadtstring: fn(data: ref Loader->Niladt, index: int): string; | |
| 375 | + getstring: fn(mod: Nilmod, index: int): string; | |
| 376 | + putclass: fn(data: ref Loader->Niladt, index: int, value: ref JavaClassLoader->Class); | |
| 377 | + putint: fn(data: ref Loader->Niladt, index: int, value: int); | |
| 378 | + putmod: fn(data: ref Loader->Niladt, index: int, value: Nilmod); | |
| 379 | + putobj: fn(data: ref Loader->Niladt, index: int, value: ref JavaClassLoader->ClassObject); | |
| 380 | + putptr: fn(data: ref Loader->Niladt, index: int, value: ref Loader->Niladt); | |
| 381 | + putstring: fn(data: ref Loader->Niladt, index: int, value: string); | |
| 382 | + little_endian: fn(): int; | |
| 383 | + jclnilmod: fn(j: JavaClassLoader): Nilmod; | |
| 384 | + sysnilmod: fn(s: Sys): Nilmod; | |
| 385 | + new: fn(mod: Nilmod, index: int): ref JavaClassLoader->Object; | |
| 386 | + getobjclass: fn(j: ref JavaClassLoader->Object): ref JavaClassLoader->Class; | |
| 387 | + modhash: fn(mod: Nilmod): int; | |
| 388 | + objhash: fn(j: ref JavaClassLoader->Object): int; | |
| 389 | + mcall0: fn(mod: Nilmod, index: int): int; | |
| 390 | + mcall1: fn(mod: Nilmod, index: int, arg: ref JavaClassLoader->Object): ref JavaClassLoader->Object; | |
| 391 | + mcalla: fn(mod: Nilmod, index: int, arg: ref JavaClassLoader->Array): int; | |
| 392 | + mcallm: fn(mod: Nilmod, index: int, arg: Nilmod): int; | |
| 393 | + getmd: fn(mod: Nilmod): ref Loader->Niladt; | |
| 394 | + arrayof: fn(o: ref JavaClassLoader->Object): ref JavaClassLoader->Array; | |
| 395 | + bytearraytoJS: fn(a: array of byte): array of ref JavaClassLoader->JavaString; | |
| 396 | + intarraytoJS: fn(a: array of int): array of ref JavaClassLoader->JavaString; | |
| 397 | + bigarraytoJS: fn(a: array of big): array of ref JavaClassLoader->JavaString; | |
| 398 | + realarraytoJS: fn(a: array of real): array of ref JavaClassLoader->JavaString; | |
| 399 | + ArraytoJS: fn(a: ref JavaClassLoader->Array): ref JavaClassLoader->JavaString; | |
| 400 | + JStoObject: fn(j: ref JavaClassLoader->JavaString): ref JavaClassLoader->Object; | |
| 401 | + ObjecttoJT: fn(o: ref JavaClassLoader->Object): ref JavaClassLoader->JavaThrowable; | |
| 402 | + makeadt: fn(addr: int): ref Loader->Niladt; | |
| 403 | +}; | |
| 404 | + | |
| 405 | +JavaTrace: module | |
| 406 | +{ | |
| 407 | + PATH: con "/dis/java/javatrace.dis"; | |
| 408 | + | |
| 409 | + JVERBOSE, | |
| 410 | + JDEBUG: con iota; | |
| 411 | + | |
| 412 | + init: fn(a: JavaAssist); | |
| 413 | + info: fn(c: ref JavaClassLoader->Class); | |
| 414 | + pr_reloc: fn(r: JavaClassLoader->Reloc); | |
| 415 | + pr_relocs: fn(r: array of JavaClassLoader->Reloc); | |
| 416 | + trace: fn(c: int, s: string); | |
| 417 | + | |
| 418 | + level: int; | |
| 419 | + outfd: ref Sys->FD; | |
| 420 | +}; | |
| @@ -0,0 +1,690 @@ | ||
| 1 | +# | |
| 2 | +# jni -- java native interface | |
| 3 | +# | |
| 4 | +# this module defines the limbo helper | |
| 5 | +# functions for java class library | |
| 6 | +# native methods (limbo). | |
| 7 | +# | |
| 8 | +# This module is based on the JNI | |
| 9 | +# specification from JavaSoft for | |
| 10 | +# VM implementations supporting a C/C++ | |
| 11 | +# interface. | |
| 12 | +# | |
| 13 | + | |
| 14 | +include "sys.m"; | |
| 15 | +include "math.m"; | |
| 16 | +include "string.m"; | |
| 17 | +include "loader.m"; | |
| 18 | +include "classloader.m"; | |
| 19 | +include "cast.m"; | |
| 20 | + | |
| 21 | +JNI : module | |
| 22 | +{ | |
| 23 | + # where to find jni.dis | |
| 24 | + PATH : con "/dis/java/jni.dis"; | |
| 25 | + | |
| 26 | + # | |
| 27 | + # exported read-only vars | |
| 28 | + # upon JNI initialization the following | |
| 29 | + # variables are assigned. Native method modules | |
| 30 | + # can use the following instances rather than | |
| 31 | + # loading their own copies. These variables | |
| 32 | + # should never be assigned. | |
| 33 | + sys : Sys; # std inferno sys module | |
| 34 | + math : Math; # std inferno math module | |
| 35 | + str : String; # std inferno string module | |
| 36 | + jldr : JavaClassLoader; # primary java class loader | |
| 37 | + jassist : JavaAssist; # java assist module | |
| 38 | + | |
| 39 | + # boolean constants | |
| 40 | + FALSE : con 0; | |
| 41 | + TRUE : con 1; | |
| 42 | + BFALSE : con byte 0; | |
| 43 | + BTRUE : con byte 1; | |
| 44 | + | |
| 45 | + # return error flags for JNI functions | |
| 46 | + OK : con 0; | |
| 47 | + ERR : con -1; | |
| 48 | + | |
| 49 | + # JVM Type Constants: used for identifying Java primitive types. | |
| 50 | + T_JVMSTART : con 4; | |
| 51 | + T_BOOLEAN, T_CHAR, T_FLOAT, T_DOUBLE, T_BYTE, T_SHORT, | |
| 52 | + T_INT, T_LONG, T_OBJECT, T_ARRAY, T_VOID, | |
| 53 | + T_JVMLAST | |
| 54 | + : con (iota + T_JVMSTART); | |
| 55 | + | |
| 56 | + # JVM class flags constants | |
| 57 | + ACC_PUBLIC: con 16r0001; | |
| 58 | + ACC_PRIVATE: con 16r0002; | |
| 59 | + ACC_PROTECTED: con 16r0004; | |
| 60 | + ACC_STATIC: con 16r0008; | |
| 61 | + ACC_FINAL: con 16r0010; | |
| 62 | + ACC_SUPER: con 16r0020; | |
| 63 | + ACC_SYNCHRONIZED: con 16r0020; | |
| 64 | + ACC_VOLATILE: con 16r0040; | |
| 65 | + ACC_TRANSIENT: con 16r0080; | |
| 66 | + ACC_NATIVE: con 16r0100; | |
| 67 | + ACC_INTERFACE: con 16r0200; | |
| 68 | + ACC_ABSTRACT: con 16r0400; | |
| 69 | + | |
| 70 | + ACC_WRITTEN_FLAGS: con 16r0fff; | |
| 71 | + | |
| 72 | + | |
| 73 | + # common java types | |
| 74 | + | |
| 75 | + # | |
| 76 | + # The following two types are used to represent | |
| 77 | + # Java classes. The 'ClassData' type contains all | |
| 78 | + # of the information pertaining to a class and is | |
| 79 | + # used to obtain class information and instantiate | |
| 80 | + # objects. Although there is information in the | |
| 81 | + # structure it should normally be treated as an | |
| 82 | + # opaque type by client native method modules. | |
| 83 | + # | |
| 84 | + ClassModule : type ref Loader->Niladt; | |
| 85 | + ClassData : type ref JavaClassLoader->Class; | |
| 86 | + | |
| 87 | + # | |
| 88 | + # This is the "generic" type of any Java instance. | |
| 89 | + # Operations on the object can be performed via this | |
| 90 | + # generic handle. | |
| 91 | + # | |
| 92 | + JObject : type ref JavaClassLoader->Object; | |
| 93 | + | |
| 94 | + # | |
| 95 | + # This represents an instance of java.lang.Class | |
| 96 | + # It is an object which contains a ptr to the | |
| 97 | + # actual class data it represents. | |
| 98 | + # | |
| 99 | + JClass : type ref JavaClassLoader->ClassObject; | |
| 100 | + | |
| 101 | + # | |
| 102 | + # This is an instance of java.lang.String. | |
| 103 | + # This class is a wrapper of a Dis string. | |
| 104 | + # | |
| 105 | + JString : type ref JavaClassLoader->JavaString; | |
| 106 | + | |
| 107 | + JBoolean : type int; | |
| 108 | + | |
| 109 | + # Java arrays are actually classes | |
| 110 | + # which wrap a Dis array. The array | |
| 111 | + # class matches the adt 'Array' defined | |
| 112 | + # in JavaClassLoader. The following arrays | |
| 113 | + # should mirror that adt and are used by | |
| 114 | + # limbo modules to access the array contents | |
| 115 | + # directly. Java Arrays should only be created | |
| 116 | + # in Java code or via the Array functions | |
| 117 | + # below. A simple limbo instance of the | |
| 118 | + # array adt's is not good enough. | |
| 119 | + | |
| 120 | + # JArray is used as a "generic" array and to represent | |
| 121 | + # multi-dimensional arrays. | |
| 122 | + JArray : type ref JavaClassLoader->Array; # x[][].. | |
| 123 | + | |
| 124 | + IntArray : adt | |
| 125 | + { | |
| 126 | + cl_mod: ref Loader->Niladt; # object's class data | |
| 127 | + ary: array of int; # actual dis array | |
| 128 | + dims: int; # number of dimensions | |
| 129 | + class: ClassData; # class data of base type | |
| 130 | + primitive: int; # set if base type is primitive | |
| 131 | + }; | |
| 132 | + | |
| 133 | + ByteArray : adt | |
| 134 | + { | |
| 135 | + cl_mod: ref Loader->Niladt; # object's class data | |
| 136 | + ary: array of byte; # actual dis array | |
| 137 | + dims: int; # number of dimensions | |
| 138 | + class: ClassData; # class data of base type | |
| 139 | + primitive: int; # set if base type is primitive | |
| 140 | + }; | |
| 141 | + | |
| 142 | + BigArray : adt | |
| 143 | + { | |
| 144 | + cl_mod: ref Loader->Niladt; # object's class data | |
| 145 | + ary: array of big; # actual dis array | |
| 146 | + dims: int; # number of dimensions | |
| 147 | + class: ClassData; # class data of base type | |
| 148 | + primitive: int; # set if base type is primitive | |
| 149 | + }; | |
| 150 | + | |
| 151 | + RealArray : adt | |
| 152 | + { | |
| 153 | + cl_mod: ref Loader->Niladt; # object's class data | |
| 154 | + ary: array of real; # actual dis array | |
| 155 | + dims: int; # number of dimensions | |
| 156 | + class: ClassData; # class data of base type | |
| 157 | + primitive: int; # set if base type is primitive | |
| 158 | + }; | |
| 159 | + | |
| 160 | + StringArray : adt | |
| 161 | + { | |
| 162 | + cl_mod: ref Loader->Niladt; # object's class data | |
| 163 | + ary: array of JString; # actual dis array | |
| 164 | + dims: int; # number of dimensions | |
| 165 | + class: ClassData; # class data of base type | |
| 166 | + primitive: int; # set if base type is primitive | |
| 167 | + }; | |
| 168 | + | |
| 169 | + ClassArray : adt | |
| 170 | + { | |
| 171 | + cl_mod: ref Loader->Niladt; # object's class data | |
| 172 | + ary: array of JClass; # actual dis array | |
| 173 | + dims: int; # number of dimensions | |
| 174 | + class: ClassData; # class data of base type | |
| 175 | + primitive: int; # set if base type is primitive | |
| 176 | + }; | |
| 177 | + | |
| 178 | + ObjectArray : adt | |
| 179 | + { | |
| 180 | + cl_mod: ref Loader->Niladt; # object's class data | |
| 181 | + ary: array of JObject; # actual dis array | |
| 182 | + dims: int; # number of dimensions | |
| 183 | + class: ClassData; # class data of base type | |
| 184 | + primitive: int; # set if base type is primitive | |
| 185 | + }; | |
| 186 | + | |
| 187 | + ArrayArray : adt | |
| 188 | + { | |
| 189 | + cl_mod: ref Loader->Niladt; # object's class data | |
| 190 | + ary: array of JArray; # actual dis array | |
| 191 | + dims: int; # number of dimensions | |
| 192 | + class: ClassData; # class data of base type | |
| 193 | + primitive: int; # set if base type is primitive | |
| 194 | + }; | |
| 195 | + | |
| 196 | + # | |
| 197 | + # Common type names emitted by 'javal'. | |
| 198 | + # | |
| 199 | + JArrayI : type ref IntArray; # int[] | |
| 200 | + JArrayC : type ref IntArray; # char[] | |
| 201 | + JArrayB : type ref ByteArray; # byte[] | |
| 202 | + JArrayS : type ref IntArray; # short[] | |
| 203 | + JArrayJ : type ref BigArray; # long[] | |
| 204 | + JArrayF : type ref RealArray; # float[] | |
| 205 | + JArrayD : type ref RealArray; # double[] | |
| 206 | + JArrayZ : type ref ByteArray; # boolean[] | |
| 207 | + | |
| 208 | + JArrayJClass : type ref ClassArray; # Class[] | |
| 209 | + JArrayJString : type ref StringArray; # String[] | |
| 210 | + JArrayJObject : type ref ObjectArray; # Object[] | |
| 211 | + | |
| 212 | + ThreadObject : adt | |
| 213 | + { | |
| 214 | + cl_mod : ClassModule; | |
| 215 | + name : JArrayC; | |
| 216 | + priority : int; | |
| 217 | + #threadQ : cyclic ref ThreadObject; | |
| 218 | + PrivateInfo : ref JavaClassLoader->ThreadData; | |
| 219 | + was_interrupted : byte; #boolean | |
| 220 | + #eetop : int; | |
| 221 | + #single_step : byte; #boolean | |
| 222 | + daemon : byte; #boolean | |
| 223 | + stillborn : byte; #boolean | |
| 224 | + target : JObject; | |
| 225 | + group : JObject; | |
| 226 | + #initial_stack_memory : int; | |
| 227 | + }; | |
| 228 | + JThread : type ref ThreadObject; | |
| 229 | + | |
| 230 | + | |
| 231 | + # | |
| 232 | + # This union type is used for setting/getting fields | |
| 233 | + # of an arbitrary Java object/class, and also for | |
| 234 | + # calling arbitrary object/class methods. | |
| 235 | + # To set Java reference types (i.e. objects, arrays) | |
| 236 | + # they must be converted to a JObject (i.e. use TObject). | |
| 237 | + # | |
| 238 | + # One way to create an instance of this type is: | |
| 239 | + # val := ref Value.TObject(obj); | |
| 240 | + # | |
| 241 | + # To retrieve a value use a 'pick' statement or one | |
| 242 | + # of the "getter" functions below. | |
| 243 | + # | |
| 244 | + # NOTE: the Low module is aware of the order of the "pick" tags | |
| 245 | + # | |
| 246 | + Value :adt | |
| 247 | + { | |
| 248 | + pick | |
| 249 | + { | |
| 250 | + TObject => jobj : JObject; | |
| 251 | + TByte => jbyte : int; | |
| 252 | + TBoolean => jboolean: int; | |
| 253 | + TChar => jchar : int; | |
| 254 | + TShort => jshort : int; | |
| 255 | + TInt => jint : int; | |
| 256 | + TLong => jlong : big; | |
| 257 | + TFloat => jfloat : real; | |
| 258 | + TDouble => jdouble : real; | |
| 259 | + } | |
| 260 | + | |
| 261 | + # | |
| 262 | + # Get a value of the expected type. If the | |
| 263 | + # actual type is not the expected type then | |
| 264 | + # a FatalError() is called. | |
| 265 | + # | |
| 266 | + Boolean : fn( this : self ref Value ) : JBoolean; | |
| 267 | + Byte : fn( this : self ref Value ) : int; | |
| 268 | + Short : fn( this : self ref Value ) : int; | |
| 269 | + Int : fn( this : self ref Value ) : int; | |
| 270 | + Long : fn( this : self ref Value ) : big; | |
| 271 | + Float : fn( this : self ref Value ) : real; | |
| 272 | + Double : fn( this : self ref Value ) : real; | |
| 273 | + Char : fn( this : self ref Value ) : int; | |
| 274 | + Object : fn( this : self ref Value ) : JObject; | |
| 275 | + | |
| 276 | + | |
| 277 | + }; | |
| 278 | + | |
| 279 | + # | |
| 280 | + # This structure is used to "describe" a Java type. A Java signature | |
| 281 | + # stored as a string is converted into this ADT for better comparisons. | |
| 282 | + # Depending on the actual type vairous parts of the ADT will be filled | |
| 283 | + # in. The 'sig' field will contain the appropriate java signagure string | |
| 284 | + # associated with the type. The following details how to distinguish the | |
| 285 | + # type: | |
| 286 | + # non-array ref: | |
| 287 | + # 'class' represents the class info; other fields are 0/nil | |
| 288 | + # array ref: | |
| 289 | + # "class" is nil for primitive array and 'prim' contains one of | |
| 290 | + # the "Java Type Constants" representing the array's base type. | |
| 291 | + # for non-primitive arrays 'class' is the ClassData for the base | |
| 292 | + # type; 'prim' is 0; 'dims' contains the number of dimensions | |
| 293 | + # primitive: | |
| 294 | + # 'class' is nil; 'dims' is 0; 'prim' is one of Java Type Consts | |
| 295 | + # method: | |
| 296 | + # 'params' is a list of Descriptor's for each param -- nil if the | |
| 297 | + # method has no parameters. The method return value is represented | |
| 298 | + # by the other fields as described above; a method w/ no return | |
| 299 | + # value will have (nil,T_VOID,0,"V",nil) descriptor. NOTE: the param | |
| 300 | + # list is in (Right-to-Left order -- i.e right most param is the | |
| 301 | + # list-head). | |
| 302 | + # | |
| 303 | + Descriptor : adt | |
| 304 | + { | |
| 305 | + class : ClassData; | |
| 306 | + prim : int; | |
| 307 | + dims : int; | |
| 308 | + sig : string; #type's java signature | |
| 309 | + params : cyclic list of ref Descriptor; | |
| 310 | + }; | |
| 311 | + | |
| 312 | + | |
| 313 | + # | |
| 314 | + # argument passed to AttachCurrentThread | |
| 315 | + # | |
| 316 | + ThreadAttachArgs : adt | |
| 317 | + { | |
| 318 | + name : string; #can be nil | |
| 319 | + daemon : byte; #1=true | |
| 320 | + group : JObject; #nil ==> main group | |
| 321 | + }; | |
| 322 | + | |
| 323 | + | |
| 324 | + # | |
| 325 | + # JNI Functions | |
| 326 | + # | |
| 327 | + | |
| 328 | + # | |
| 329 | + # Return JNI version number in the form | |
| 330 | + # of 0xVVVVIIII where VVVV=major version | |
| 331 | + # and IIII= minor version | |
| 332 | + # | |
| 333 | + GetVersion : fn() : int; | |
| 334 | + | |
| 335 | + | |
| 336 | + ## | |
| 337 | + ## Class/Object access | |
| 338 | + ## | |
| 339 | + | |
| 340 | + # | |
| 341 | + # Find the class data for a given class name. | |
| 342 | + # Will cause a load of the class if necessary. | |
| 343 | + # NOTE: this does not return a java.lang.Class | |
| 344 | + # object, but rather the internal structure. | |
| 345 | + # | |
| 346 | + FindClass : fn( name : string ) : ClassData; | |
| 347 | + | |
| 348 | + # | |
| 349 | + # Return the class's superclass data. | |
| 350 | + # | |
| 351 | + GetSuperclass : fn( cl_data : ClassData ) : ClassData; | |
| 352 | + | |
| 353 | + # | |
| 354 | + # Return the java.lang.Class instance associated | |
| 355 | + # with this instance. | |
| 356 | + # | |
| 357 | + GetObjectClass : fn( obj : JObject ) : JClass; | |
| 358 | + | |
| 359 | + # | |
| 360 | + # Return the internal Class Data information | |
| 361 | + # associated with this instance | |
| 362 | + # | |
| 363 | + GetObjectClassData : fn( obj : JObject ) : ClassData; | |
| 364 | + | |
| 365 | + # | |
| 366 | + # return the associated java.lang.Class instance | |
| 367 | + # associated with the given internal Class | |
| 368 | + # Data. | |
| 369 | + # | |
| 370 | + GetClassObject : fn( cl_data : ClassData ) : JClass; | |
| 371 | + | |
| 372 | + # | |
| 373 | + # return the java.lang.Class instance associated | |
| 374 | + # with the array class that has signature 'sig'. | |
| 375 | + # | |
| 376 | + LookupArrayClass : fn( sig : string ) : JClass; | |
| 377 | + | |
| 378 | + # | |
| 379 | + # Allocate an instance of java.lang.Class that | |
| 380 | + # represents the class indicated by 'cl_data'. | |
| 381 | + # The 'cl_data' can be obtained via the functions above. | |
| 382 | + # | |
| 383 | + NewClassObject : fn( cl_data : ClassData ) : JClass; | |
| 384 | + | |
| 385 | + # | |
| 386 | + # Allocate a new instance of the class; no constructor called. | |
| 387 | + # | |
| 388 | + AllocObject : fn( cl_data : ClassData ) : JObject; | |
| 389 | + | |
| 390 | + # | |
| 391 | + # Allocate a new instance of the class and | |
| 392 | + # attempt to call the "default" constructor. | |
| 393 | + # NOTE: this routine should be used with care, | |
| 394 | + # because not all classes have default constructors. | |
| 395 | + # | |
| 396 | + NewObject : fn( cl_data : ClassData ) : JObject; | |
| 397 | + | |
| 398 | + # | |
| 399 | + # Duplicate the object. This function will create | |
| 400 | + # a new instance of the object's class and perform | |
| 401 | + # a shallow copy of the the objects data contents | |
| 402 | + # into the new instance. | |
| 403 | + # NOTE: the constructor of the new object is not invoked | |
| 404 | + # | |
| 405 | + DupObject : fn( obj : JObject ) : JObject; | |
| 406 | + | |
| 407 | + # | |
| 408 | + # Return a hash code based on the object's reference, | |
| 409 | + # not its contents. This is called by | |
| 410 | + # java.lang.Object.hashCode() as well as | |
| 411 | + # System.identityHashCode(). | |
| 412 | + # | |
| 413 | + IdentityHash : fn( obj : JObject ) : int; | |
| 414 | + | |
| 415 | + # | |
| 416 | + # Allocate a java string object and place the | |
| 417 | + # dis string as its contents. | |
| 418 | + # | |
| 419 | + NewString : fn( val : string ) : JString; | |
| 420 | + | |
| 421 | + # | |
| 422 | + # Just like NewString but return as a | |
| 423 | + # JObject type, rather then JString | |
| 424 | + # | |
| 425 | + NewStringObject : fn( val : string ) : JObject; | |
| 426 | + | |
| 427 | + # | |
| 428 | + # Set object/class data fields. | |
| 429 | + # Must pass the "object instance"/"class data" along with the | |
| 430 | + # field name and the value it should be set to. The contents of | |
| 431 | + # the 'val' union type is used to determine the field type and if | |
| 432 | + # they are not compatable the function fails. | |
| 433 | + # | |
| 434 | + # RETURN: JNI->OK=> success; | |
| 435 | + # JNI->ERR=> failure | |
| 436 | + # | |
| 437 | + SetStaticField : fn( cl_data : ClassData, name : string, val : ref Value ) : int; | |
| 438 | + SetObjField : fn( obj : JObject, name : string, val : ref Value ) : int; | |
| 439 | + | |
| 440 | + # Get object/class data fields. | |
| 441 | + # Must pass the "object instance"/"class data" along with the field | |
| 442 | + # name and a "type signature" (see JVM reference). The type sig must | |
| 443 | + # match the actual field sig exactly. | |
| 444 | + # | |
| 445 | + # RETURN: nil=> failure; | |
| 446 | + # non-nil=> a 'Value' union type with the field contents | |
| 447 | + # | |
| 448 | + GetStaticField : fn( cl_data : ClassData, name : string, typ : string ) : ref Value; | |
| 449 | + GetObjField : fn( obj : JObject, name : string, typ : string ) : ref Value; | |
| 450 | + | |
| 451 | + | |
| 452 | + # | |
| 453 | + # Call a method: | |
| 454 | + # cl_data/obj : the class or object being called | |
| 455 | + # meth : name of method to call | |
| 456 | + # sig : signature of method being called | |
| 457 | + # args : array of args to pass (nil==void) 'this' is implicitly | |
| 458 | + # passed for dynamic (object) method calls | |
| 459 | + # return : tuple: value of method call (nil==void), error code | |
| 460 | + # | |
| 461 | + # example: | |
| 462 | + # v := Value.Int(99); | |
| 463 | + # args := array[] of {v}; | |
| 464 | + # (val,err) := CallMeth( o, "foo", "(I)I", args ); | |
| 465 | + # if ( err == JNI->OK ) | |
| 466 | + # sys->print( "return: %d\n", val.Int() ); | |
| 467 | + # | |
| 468 | + CallStatic : fn( cl_data : ClassData, meth : string, sig : string, args : array of ref Value ) : (ref Value,int); | |
| 469 | + CallMethod : fn( obj : JObject, meth : string, sig : string, args : array of ref Value ) : (ref Value,int); | |
| 470 | + | |
| 471 | + | |
| 472 | + # | |
| 473 | + # Method call error codes | |
| 474 | + # | |
| 475 | + CALLERR_NOMETHOD, # method not found | |
| 476 | + CALLERR_BADSIG, # bad signature | |
| 477 | + CALLERR_BADARGCNT, # arg count mismatch | |
| 478 | + CALLERR_BADARG # argument mismatch: errcode-CALLERR_BADARG==argument position | |
| 479 | + # 'badarg' must be last. | |
| 480 | + : con (iota+1); | |
| 481 | + | |
| 482 | + | |
| 483 | + ## | |
| 484 | + ## Object/Class comparison functions | |
| 485 | + ## | |
| 486 | + | |
| 487 | + IsInstanceOf : fn( obj : JObject, cl_data : ClassData ) : JBoolean; | |
| 488 | + IsAssignable : fn( assignee, assignTo : JClass ) : JBoolean; | |
| 489 | + IsSameObject : fn( obj1, obj2 : JObject ) : JBoolean; | |
| 490 | + | |
| 491 | + # Check if 'ary' can be assigned to an instance with matching 'desc'. | |
| 492 | + # If 'ary' or 'desc' are nil then return FALSE. | |
| 493 | + ArrayInstanceOf : fn( ary : JArray, desc : ref Descriptor ) : JBoolean; | |
| 494 | + | |
| 495 | + # Is the object an array? (nil==FALSE) | |
| 496 | + IsArray : fn( obj : JObject ) : JBoolean; | |
| 497 | + | |
| 498 | + ## | |
| 499 | + ## Support for Serializable | |
| 500 | + ## | |
| 501 | + | |
| 502 | + # Return the modifiers for the item. | |
| 503 | + # Return 0 if field or method not found in class. | |
| 504 | + # Do not search for fields/methods in superclass. | |
| 505 | + # string args are same format as strings returned | |
| 506 | + # by GetFieldSignatures and GetMethodSignatures. | |
| 507 | + # | |
| 508 | + GetClassFlags : fn(jcl : JClass) : int; | |
| 509 | + GetFieldFlags : fn(jcl : JClass, fieldsignature : string) : int; | |
| 510 | + GetMethodFlags : fn(jcl : JClass, methodsignature : string) : int; | |
| 511 | + | |
| 512 | + # Return array of Fields/Methods plus signatures as strings. | |
| 513 | + # Should be limited Fields/methods in this class, not superclass. | |
| 514 | + # Returned value strings are "fieldormethodname signature". | |
| 515 | + # | |
| 516 | + GetFieldSignatures : fn(jcl: JClass, excl : int) : JArrayJString; | |
| 517 | + GetMethodSignatures : fn(jcl: JClass, excl : int) : JArrayJString; | |
| 518 | + | |
| 519 | + ## | |
| 520 | + ## Throwing Exceptions | |
| 521 | + ## | |
| 522 | + | |
| 523 | + # | |
| 524 | + # Throw the pre-created 'throwable' object. The | |
| 525 | + # 'throwable' object must be an instance of | |
| 526 | + # "java.lang.Throwable", else failure. | |
| 527 | + # | |
| 528 | + Throw : fn( throwable : JObject ); | |
| 529 | + ThrowException : fn( name : string, msg : string ); | |
| 530 | + | |
| 531 | + # | |
| 532 | + # return the current Java Exception. The object | |
| 533 | + # returned can be used by "Throw" to re-throw it. | |
| 534 | + # | |
| 535 | + # ex is the current Inferno exception if in a rescue. | |
| 536 | + # if ex is nil then the current value of culprit() is | |
| 537 | + # returned (that may be nil). If ex is non nil and | |
| 538 | + # culprit() is nil then ex is converted to the appropriate | |
| 539 | + # Java throwable and returned. | |
| 540 | + # | |
| 541 | + JavaException: fn( ex : string ) : JObject; | |
| 542 | + | |
| 543 | + # | |
| 544 | + # Clear any current Exception for the calling thread. | |
| 545 | + # | |
| 546 | + ExceptionClear : fn(); | |
| 547 | + | |
| 548 | + ## | |
| 549 | + ## Array functions | |
| 550 | + ## | |
| 551 | + | |
| 552 | + GetArrayLength : fn( ary : JArray ) : int; | |
| 553 | + | |
| 554 | + # | |
| 555 | + # functions to make "java" arrays from limbo arrays | |
| 556 | + # | |
| 557 | + MkAByte : fn( ary : array of byte ) : JArrayB; | |
| 558 | + MkAChar : fn( ary : array of int ) : JArrayC; | |
| 559 | + MkAShort : fn( ary : array of int ) : JArrayS; | |
| 560 | + MkAInt : fn( ary : array of int ) : JArrayI; | |
| 561 | + MkALong : fn( ary : array of big ) : JArrayJ; | |
| 562 | + MkAFloat : fn( ary : array of real ) : JArrayF; | |
| 563 | + MkADouble : fn( ary : array of real ) : JArrayD; | |
| 564 | + MkABoolean : fn( ary : array of byte ) : JArrayZ; | |
| 565 | + MkAObject : fn( ary : array of JObject ) : JArrayJObject; | |
| 566 | + MkAString : fn( ary : array of string ) : JArrayJString; | |
| 567 | + | |
| 568 | + MkAAByte : fn( aary : array of array of byte ) : JArray; | |
| 569 | + MkAAInt : fn( aary : array of array of int ) : JArray; | |
| 570 | + | |
| 571 | + # This can be used to create arrays of arbitrary dimensions. | |
| 572 | + MkAJArray : fn( ary : array of JArray ) : JArray; | |
| 573 | + | |
| 574 | + # make a JArrayC from a Dis string | |
| 575 | + StringToAChar : fn( s : string ) : JArrayC; | |
| 576 | + | |
| 577 | + ## | |
| 578 | + ## Monitor, locking, and Thread functions | |
| 579 | + ## | |
| 580 | + | |
| 581 | + # | |
| 582 | + # Lock or unlock the object's associated | |
| 583 | + # lock. Block until the operation is complete. | |
| 584 | + # Upon an error: FatalError() is called | |
| 585 | + # | |
| 586 | + MonitorEnter : fn( obj : JObject ); | |
| 587 | + MonitorExit : fn( obj :JObject ); | |
| 588 | + | |
| 589 | + # | |
| 590 | + # Notify any waiters. | |
| 591 | + # all==1 => notify all | |
| 592 | + # *Lock* version will do a enter/exit. | |
| 593 | + # | |
| 594 | + MonitorLockNotify : fn( obj : JObject, all : int ); | |
| 595 | + MonitorNotify : fn( obj : JObject, all : int ); | |
| 596 | + | |
| 597 | + # | |
| 598 | + # Attach a "Limbo thread" to the "Java vm". | |
| 599 | + # This allows a Limbo "spawned" thread to | |
| 600 | + # look like a "Java thread" to the Java Classes. | |
| 601 | + # | |
| 602 | + # return 0=>success; <0=>fail | |
| 603 | + # | |
| 604 | + AttachCurrentThread : fn( arg : ref ThreadAttachArgs ) : int; | |
| 605 | + | |
| 606 | + # | |
| 607 | + # Detach a thread from the "java VM". | |
| 608 | + # | |
| 609 | + DetachCurrentThread : fn() : int; | |
| 610 | + | |
| 611 | + # | |
| 612 | + # returns the Main thread group. | |
| 613 | + # | |
| 614 | + MainThreadGroup : fn() : JObject; | |
| 615 | + | |
| 616 | + ## | |
| 617 | + ## Utility Functions | |
| 618 | + ## | |
| 619 | + | |
| 620 | + # flags indicating which methods to find | |
| 621 | + METH_PRIVATE, # private methods | |
| 622 | + METH_VIRTUAL, # virtual methods | |
| 623 | + METH_STATIC, # static methods | |
| 624 | + METH_INIT # constructors | |
| 625 | + : con ( 1 << iota ); | |
| 626 | + | |
| 627 | + # | |
| 628 | + # look up a method based on its name and signature. | |
| 629 | + # | |
| 630 | + # class : class descritpor to look in | |
| 631 | + # name : method name to look up | |
| 632 | + # sig : method signature | |
| 633 | + # flags : specifies what type of method to find and | |
| 634 | + # can be any of the above flags or'ed togeather. | |
| 635 | + # | |
| 636 | + # return: the (module,index) of the method | |
| 637 | + # | |
| 638 | + FindMethod : fn( class : ClassData, | |
| 639 | + name : string, | |
| 640 | + sig : string, | |
| 641 | + flags : int ) : (Nilmod,int); | |
| 642 | + | |
| 643 | + # | |
| 644 | + # If c represents a Java primitive type, return | |
| 645 | + # T_BOOLEAN..T_LONG or T_VOID; otherwise, return 0. | |
| 646 | + # Also return 0 if T_VOID applies, but ignorevoid != 0. | |
| 647 | + # | |
| 648 | + PrimitiveIndex: fn(c : JClass, ignorevoid : int) : int; | |
| 649 | + | |
| 650 | + # | |
| 651 | + # Convert a Java type signature string into | |
| 652 | + # a type descriptor structure. The signature | |
| 653 | + # passed in can represent any single type (including | |
| 654 | + # a method). Extra characters on the end are ignored. | |
| 655 | + # | |
| 656 | + JSigToDescriptor : fn( sig : string ) : ref Descriptor; | |
| 657 | + | |
| 658 | + # | |
| 659 | + # Throw a java.lang.InternalError | |
| 660 | + # | |
| 661 | + FatalError : fn( msg : string ); | |
| 662 | + | |
| 663 | + # | |
| 664 | + # Indicate to loader a native module init() | |
| 665 | + # function has failed. | |
| 666 | + # | |
| 667 | + InitError : fn( msg : string ); | |
| 668 | + | |
| 669 | + # | |
| 670 | + # Return an instance of the Cast module. | |
| 671 | + # | |
| 672 | + CastMod : fn() : Cast; | |
| 673 | + | |
| 674 | + # | |
| 675 | + # Return an instance of the Low module. | |
| 676 | + # | |
| 677 | + LowMod : fn() : Low; | |
| 678 | + | |
| 679 | + # return the current draw context | |
| 680 | + getContext:fn(): ref Draw->Context; | |
| 681 | + | |
| 682 | + # | |
| 683 | + # The following routines are called by the JavaClassLoader | |
| 684 | + # module to initialize JNI. Native method modules must not | |
| 685 | + # call thease routines. | |
| 686 | + # | |
| 687 | + jinit : fn( jldr : JavaClassLoader, jass : JavaAssist ); | |
| 688 | + Self: fn(s: Sys, j: JNI): (Nilmod, string); | |
| 689 | + init: fn(j: JNI); | |
| 690 | +}; | |
| @@ -0,0 +1 @@ | ||
| 1 | +All the *.java files here belong to OpenJDK version 1.7, see http://openjdk.java.net/ | |
| @@ -0,0 +1,338 @@ | ||
| 1 | +# | |
| 2 | +# %W% - %E% | |
| 3 | +# | |
| 4 | + | |
| 5 | +implement AwtColor; | |
| 6 | + | |
| 7 | +include "jni.m"; | |
| 8 | + jni : JNI; | |
| 9 | + ClassModule, | |
| 10 | + JString, | |
| 11 | + JArray, | |
| 12 | + JArrayI, | |
| 13 | + JArrayC, | |
| 14 | + JArrayB, | |
| 15 | + JArrayS, | |
| 16 | + JArrayJ, | |
| 17 | + JArrayF, | |
| 18 | + JArrayD, | |
| 19 | + JArrayZ, | |
| 20 | + JArrayJObject, | |
| 21 | + JArrayJClass, | |
| 22 | + JArrayJString, | |
| 23 | + JClass, | |
| 24 | + JThread, | |
| 25 | + Value, | |
| 26 | + sys, | |
| 27 | + FALSE, | |
| 28 | + JObject : import jni; | |
| 29 | + | |
| 30 | + draw: Draw; | |
| 31 | + Context, Display, Image: import draw; | |
| 32 | + | |
| 33 | +include "java/lang/ClassLoader_L.m"; | |
| 34 | +include "awt_Color.m"; | |
| 35 | + | |
| 36 | +ctxt : ref Context; | |
| 37 | +systemcolors_file := "/java/lib/systemcolor.properties"; | |
| 38 | + | |
| 39 | +rgbvmap := array[3*256] of { | |
| 40 | + byte 255,byte 255,byte 255, byte 255,byte 255,byte 170, | |
| 41 | + byte 255,byte 255,byte 85, byte 255,byte 255,byte 0, | |
| 42 | + byte 255,byte 170,byte 255, byte 255,byte 170,byte 170, | |
| 43 | + byte 255,byte 170,byte 85, byte 255,byte 170,byte 0, | |
| 44 | + byte 255,byte 85,byte 255, byte 255,byte 85,byte 170, | |
| 45 | + byte 255,byte 85,byte 85, byte 255,byte 85,byte 0, | |
| 46 | + byte 255,byte 0,byte 255, byte 255,byte 0,byte 170, | |
| 47 | + byte 255,byte 0,byte 85, byte 255,byte 0,byte 0, | |
| 48 | + byte 238,byte 0,byte 0, byte 238,byte 238,byte 238, | |
| 49 | + byte 238,byte 238,byte 158, byte 238,byte 238,byte 79, | |
| 50 | + byte 238,byte 238,byte 0, byte 238,byte 158,byte 238, | |
| 51 | + byte 238,byte 158,byte 158, byte 238,byte 158,byte 79, | |
| 52 | + byte 238,byte 158,byte 0, byte 238,byte 79,byte 238, | |
| 53 | + byte 238,byte 79,byte 158, byte 238,byte 79,byte 79, | |
| 54 | + byte 238,byte 79,byte 0, byte 238,byte 0,byte 238, | |
| 55 | + byte 238,byte 0,byte 158, byte 238,byte 0,byte 79, | |
| 56 | + byte 221,byte 0,byte 73, byte 221,byte 0,byte 0, | |
| 57 | + byte 221,byte 221,byte 221, byte 221,byte 221,byte 147, | |
| 58 | + byte 221,byte 221,byte 73, byte 221,byte 221,byte 0, | |
| 59 | + byte 221,byte 147,byte 221, byte 221,byte 147,byte 147, | |
| 60 | + byte 221,byte 147,byte 73, byte 221,byte 147,byte 0, | |
| 61 | + byte 221,byte 73,byte 221, byte 221,byte 73,byte 147, | |
| 62 | + byte 221,byte 73,byte 73, byte 221,byte 73,byte 0, | |
| 63 | + byte 221,byte 0,byte 221, byte 221,byte 0,byte 147, | |
| 64 | + byte 204,byte 0,byte 136, byte 204,byte 0,byte 68, | |
| 65 | + byte 204,byte 0,byte 0, byte 204,byte 204,byte 204, | |
| 66 | + byte 204,byte 204,byte 136, byte 204,byte 204,byte 68, | |
| 67 | + byte 204,byte 204,byte 0, byte 204,byte 136,byte 204, | |
| 68 | + byte 204,byte 136,byte 136, byte 204,byte 136,byte 68, | |
| 69 | + byte 204,byte 136,byte 0, byte 204,byte 68,byte 204, | |
| 70 | + byte 204,byte 68,byte 136, byte 204,byte 68,byte 68, | |
| 71 | + byte 204,byte 68,byte 0, byte 204,byte 0,byte 204, | |
| 72 | + byte 170,byte 255,byte 170, byte 170,byte 255,byte 85, | |
| 73 | + byte 170,byte 255,byte 0, byte 170,byte 170,byte 255, | |
| 74 | + byte 187,byte 187,byte 187, byte 187,byte 187,byte 93, | |
| 75 | + byte 187,byte 187,byte 0, byte 170,byte 85,byte 255, | |
| 76 | + byte 187,byte 93,byte 187, byte 187,byte 93,byte 93, | |
| 77 | + byte 187,byte 93,byte 0, byte 170,byte 0,byte 255, | |
| 78 | + byte 187,byte 0,byte 187, byte 187,byte 0,byte 93, | |
| 79 | + byte 187,byte 0,byte 0, byte 170,byte 255,byte 255, | |
| 80 | + byte 158,byte 238,byte 238, byte 158,byte 238,byte 158, | |
| 81 | + byte 158,byte 238,byte 79, byte 158,byte 238,byte 0, | |
| 82 | + byte 158,byte 158,byte 238, byte 170,byte 170,byte 170, | |
| 83 | + byte 170,byte 170,byte 85, byte 170,byte 170,byte 0, | |
| 84 | + byte 158,byte 79,byte 238, byte 170,byte 85,byte 170, | |
| 85 | + byte 170,byte 85,byte 85, byte 170,byte 85,byte 0, | |
| 86 | + byte 158,byte 0,byte 238, byte 170,byte 0,byte 170, | |
| 87 | + byte 170,byte 0,byte 85, byte 170,byte 0,byte 0, | |
| 88 | + byte 153,byte 0,byte 0, byte 147,byte 221,byte 221, | |
| 89 | + byte 147,byte 221,byte 147, byte 147,byte 221,byte 73, | |
| 90 | + byte 147,byte 221,byte 0, byte 147,byte 147,byte 221, | |
| 91 | + byte 153,byte 153,byte 153, byte 153,byte 153,byte 76, | |
| 92 | + byte 153,byte 153,byte 0, byte 147,byte 73,byte 221, | |
| 93 | + byte 153,byte 76,byte 153, byte 153,byte 76,byte 76, | |
| 94 | + byte 153,byte 76,byte 0, byte 147,byte 0,byte 221, | |
| 95 | + byte 153,byte 0,byte 153, byte 153,byte 0,byte 76, | |
| 96 | + byte 136,byte 0,byte 68, byte 136,byte 0,byte 0, | |
| 97 | + byte 136,byte 204,byte 204, byte 136,byte 204,byte 136, | |
| 98 | + byte 136,byte 204,byte 68, byte 136,byte 204,byte 0, | |
| 99 | + byte 136,byte 136,byte 204, byte 136,byte 136,byte 136, | |
| 100 | + byte 136,byte 136,byte 68, byte 136,byte 136,byte 0, | |
| 101 | + byte 136,byte 68,byte 204, byte 136,byte 68,byte 136, | |
| 102 | + byte 136,byte 68,byte 68, byte 136,byte 68,byte 0, | |
| 103 | + byte 136,byte 0,byte 204, byte 136,byte 0,byte 136, | |
| 104 | + byte 85,byte 255,byte 85, byte 85,byte 255,byte 0, | |
| 105 | + byte 85,byte 170,byte 255, byte 93,byte 187,byte 187, | |
| 106 | + byte 93,byte 187,byte 93, byte 93,byte 187,byte 0, | |
| 107 | + byte 85,byte 85,byte 255, byte 93,byte 93,byte 187, | |
| 108 | + byte 119,byte 119,byte 119, byte 119,byte 119,byte 0, | |
| 109 | + byte 85,byte 0,byte 255, byte 93,byte 0,byte 187, | |
| 110 | + byte 119,byte 0,byte 119, byte 119,byte 0,byte 0, | |
| 111 | + byte 85,byte 255,byte 255, byte 85,byte 255,byte 170, | |
| 112 | + byte 79,byte 238,byte 158, byte 79,byte 238,byte 79, | |
| 113 | + byte 79,byte 238,byte 0, byte 79,byte 158,byte 238, | |
| 114 | + byte 85,byte 170,byte 170, byte 85,byte 170,byte 85, | |
| 115 | + byte 85,byte 170,byte 0, byte 79,byte 79,byte 238, | |
| 116 | + byte 85,byte 85,byte 170, byte 102,byte 102,byte 102, | |
| 117 | + byte 102,byte 102,byte 0, byte 79,byte 0,byte 238, | |
| 118 | + byte 85,byte 0,byte 170, byte 102,byte 0,byte 102, | |
| 119 | + byte 102,byte 0,byte 0, byte 79,byte 238,byte 238, | |
| 120 | + byte 73,byte 221,byte 221, byte 73,byte 221,byte 147, | |
| 121 | + byte 73,byte 221,byte 73, byte 73,byte 221,byte 0, | |
| 122 | + byte 73,byte 147,byte 221, byte 76,byte 153,byte 153, | |
| 123 | + byte 76,byte 153,byte 76, byte 76,byte 153,byte 0, | |
| 124 | + byte 73,byte 73,byte 221, byte 76,byte 76,byte 153, | |
| 125 | + byte 85,byte 85,byte 85, byte 85,byte 85,byte 0, | |
| 126 | + byte 73,byte 0,byte 221, byte 76,byte 0,byte 153, | |
| 127 | + byte 85,byte 0,byte 85, byte 85,byte 0,byte 0, | |
| 128 | + byte 68,byte 0,byte 0, byte 68,byte 204,byte 204, | |
| 129 | + byte 68,byte 204,byte 136, byte 68,byte 204,byte 68, | |
| 130 | + byte 68,byte 204,byte 0, byte 68,byte 136,byte 204, | |
| 131 | + byte 68,byte 136,byte 136, byte 68,byte 136,byte 68, | |
| 132 | + byte 68,byte 136,byte 0, byte 68,byte 68,byte 204, | |
| 133 | + byte 68,byte 68,byte 136, byte 68,byte 68,byte 68, | |
| 134 | + byte 68,byte 68,byte 0, byte 68,byte 0,byte 204, | |
| 135 | + byte 68,byte 0,byte 136, byte 68,byte 0,byte 68, | |
| 136 | + byte 0,byte 255,byte 0, byte 0,byte 170,byte 255, | |
| 137 | + byte 0,byte 187,byte 187, byte 0,byte 187,byte 93, | |
| 138 | + byte 0,byte 187,byte 0, byte 0,byte 85,byte 255, | |
| 139 | + byte 0,byte 93,byte 187, byte 0,byte 119,byte 119, | |
| 140 | + byte 0,byte 119,byte 0, byte 0,byte 0,byte 255, | |
| 141 | + byte 0,byte 0,byte 187, byte 0,byte 0,byte 119, | |
| 142 | + byte 51,byte 51,byte 51, byte 0,byte 255,byte 255, | |
| 143 | + byte 0,byte 255,byte 170, byte 0,byte 255,byte 85, | |
| 144 | + byte 0,byte 238,byte 79, byte 0,byte 238,byte 0, | |
| 145 | + byte 0,byte 158,byte 238, byte 0,byte 170,byte 170, | |
| 146 | + byte 0,byte 170,byte 85, byte 0,byte 170,byte 0, | |
| 147 | + byte 0,byte 79,byte 238, byte 0,byte 85,byte 170, | |
| 148 | + byte 0,byte 102,byte 102, byte 0,byte 102,byte 0, | |
| 149 | + byte 0,byte 0,byte 238, byte 0,byte 0,byte 170, | |
| 150 | + byte 0,byte 0,byte 102, byte 34,byte 34,byte 34, | |
| 151 | + byte 0,byte 238,byte 238, byte 0,byte 238,byte 158, | |
| 152 | + byte 0,byte 221,byte 147, byte 0,byte 221,byte 73, | |
| 153 | + byte 0,byte 221,byte 0, byte 0,byte 147,byte 221, | |
| 154 | + byte 0,byte 153,byte 153, byte 0,byte 153,byte 76, | |
| 155 | + byte 0,byte 153,byte 0, byte 0,byte 73,byte 221, | |
| 156 | + byte 0,byte 76,byte 153, byte 0,byte 85,byte 85, | |
| 157 | + byte 0,byte 85,byte 0, byte 0,byte 0,byte 221, | |
| 158 | + byte 0,byte 0,byte 153, byte 0,byte 0,byte 85, | |
| 159 | + byte 17,byte 17,byte 17, byte 0,byte 221,byte 221, | |
| 160 | + byte 0,byte 204,byte 204, byte 0,byte 204,byte 136, | |
| 161 | + byte 0,byte 204,byte 68, byte 0,byte 204,byte 0, | |
| 162 | + byte 0,byte 136,byte 204, byte 0,byte 136,byte 136, | |
| 163 | + byte 0,byte 136,byte 68, byte 0,byte 136,byte 0, | |
| 164 | + byte 0,byte 68,byte 204, byte 0,byte 68,byte 136, | |
| 165 | + byte 0,byte 68,byte 68, byte 0,byte 68,byte 0, | |
| 166 | + byte 0,byte 0,byte 204, byte 0,byte 0,byte 136, | |
| 167 | + byte 0,byte 0,byte 68, byte 0,byte 0,byte 0, | |
| 168 | +}; | |
| 169 | + | |
| 170 | +modinit(jni_p : JNI) | |
| 171 | +{ | |
| 172 | + if (ctxt != nil) | |
| 173 | + return; | |
| 174 | + | |
| 175 | + jni = jni_p; | |
| 176 | + sys = jni->sys; | |
| 177 | + ctxt = jni->getContext(); | |
| 178 | + if (ctxt == nil) | |
| 179 | + jni->ThrowException("java.awt.AWTError", "can't get Draw Context"); | |
| 180 | + draw = load Draw Draw->PATH; | |
| 181 | + | |
| 182 | +} | |
| 183 | + | |
| 184 | +getColor(jni_p: JNI, c: JObject) : ref Image | |
| 185 | +{ | |
| 186 | + modinit(jni_p); | |
| 187 | + | |
| 188 | + cm_index := getColorIndex(jni_p, c); | |
| 189 | + # (red, green, blue) := ctxt.display.cmap2rgb(cm_index); | |
| 190 | + # sys->print("Inferno color: red=%d, green=%d, blue=%d\n", red, green, blue); | |
| 191 | + col := ctxt.display.color(cm_index); | |
| 192 | + return col; | |
| 193 | +} | |
| 194 | + | |
| 195 | +getColorIndex(jni_p: JNI, c: JObject) : int | |
| 196 | +{ | |
| 197 | + modinit(jni_p); | |
| 198 | + | |
| 199 | + if (c == nil) { | |
| 200 | + sys->print("getColorIndex: null Color object\n"); | |
| 201 | + return 0; | |
| 202 | + } | |
| 203 | + | |
| 204 | + val := jni->GetObjField( c, "pData", "I" ); | |
| 205 | + if ( val == nil ) | |
| 206 | + sys->print( "getColorIndex: Couldn't get pData field from color object.\n" ); | |
| 207 | + else { | |
| 208 | + pdata := val.Int(); | |
| 209 | + if (pdata != 0) { | |
| 210 | + # sys->print("Using pData. pData = %d\n", pdata); | |
| 211 | + return pdata - 1; | |
| 212 | + } | |
| 213 | + } | |
| 214 | + | |
| 215 | + (ret, err) := jni->CallMethod(c, "getRGB", "()I", nil); | |
| 216 | + if (err != jni->OK) | |
| 217 | + jni->FatalError("awt_Color couldn't get RGB values of color"); | |
| 218 | + | |
| 219 | + rgb := ret.Int(); | |
| 220 | + r := (rgb >> 16) & 255; | |
| 221 | + g := (rgb >> 8) & 255; | |
| 222 | + b := (rgb >> 0) & 255; | |
| 223 | + cm_index := ctxt.display.rgb2cmap(r,g,b); | |
| 224 | + # sys->print( "rgb: %d\n", rgb); | |
| 225 | + # sys->print( "red: %d; green: %d; blue %d\n", r, g, b); | |
| 226 | + # sys->print("Color map index is %d.\n", cm_index); | |
| 227 | + | |
| 228 | + # sys->print("Setting pData to %d\n", cm_index+1); | |
| 229 | + val = ref Value.TInt(cm_index+1); | |
| 230 | + err = jni->SetObjField( c, "pData", val ); | |
| 231 | + if (err != jni->OK) | |
| 232 | + sys->print("getColorIndex: Couldn't set Color pData field\n"); | |
| 233 | + | |
| 234 | + return cm_index; | |
| 235 | +} | |
| 236 | + | |
| 237 | +makeColorModel(jni_p: JNI, bits: int) : JObject | |
| 238 | +{ | |
| 239 | + modinit(jni_p); | |
| 240 | + | |
| 241 | + cast := jni->CastMod(); | |
| 242 | + jbary := jni->MkAByte(rgbvmap); | |
| 243 | + arraylen := len jbary.ary; | |
| 244 | + # sys->print("makeColorModel: Array length is %d.\n", arraylen); | |
| 245 | + | |
| 246 | + args := array[5] of ref Value; | |
| 247 | + args[0] = ref Value.TInt(bits); | |
| 248 | + args[1] = ref Value.TInt(256); | |
| 249 | + args[2] = ref Value.TObject(cast->FromJArray(cast->ByteToJArray(jbary))); | |
| 250 | + args[3] = ref Value.TInt(0); | |
| 251 | + args[4] = ref Value.TBoolean(jni->FALSE); | |
| 252 | + | |
| 253 | + cl_data := jni->FindClass("java/awt/image/IndexColorModel"); | |
| 254 | + if (cl_data == nil) | |
| 255 | + jni->FatalError("awt_Color couldn't load java/awt/image/IndexColorModel"); | |
| 256 | + jobj := jni->AllocObject(cl_data); | |
| 257 | + (ret, err) := jni->CallMethod(jobj, "<init>", "(II[BIZ)V", args); | |
| 258 | + | |
| 259 | + if (err != jni->OK) | |
| 260 | + jni->FatalError("awt_Color couldn't create IndexColorModel"); | |
| 261 | + | |
| 262 | + system_flag := ref Value.TInt(1); | |
| 263 | + err = jni->SetObjField( jobj, "pData", system_flag ); | |
| 264 | + if (err != jni->OK) | |
| 265 | + sys->print("makeColorModel: Couldn't set ColorModel pData field to 1\n"); | |
| 266 | + | |
| 267 | + return jobj; | |
| 268 | +} | |
| 269 | + | |
| 270 | + | |
| 271 | +loadSystemColors(jni_p: JNI, systemColors: JArrayI) | |
| 272 | +{ | |
| 273 | + val : ref Value; | |
| 274 | + | |
| 275 | + modinit(jni_p); | |
| 276 | + | |
| 277 | + cl := jni->GetClassObject(jni->FindClass("java/awt/SystemColor")); | |
| 278 | + if (cl == nil) | |
| 279 | + jni->FatalError("iToolkit_L couldn't load java/awt/SystemColor"); | |
| 280 | + val = jni->GetStaticField( cl.class, "NUM_COLORS", "I" ); | |
| 281 | + if ( val == nil ) { | |
| 282 | + sys->print( "loadSystemColors: Couldn't get NUM_COLORS field from SystemColor class.\n" ); | |
| 283 | + return; | |
| 284 | + } | |
| 285 | + | |
| 286 | + num_colors := val.Int(); | |
| 287 | + # sys->print("Using GetStaticField: NUM_COLORS = %d\n", num_colors); | |
| 288 | + | |
| 289 | + lines := readfile(systemcolors_file); | |
| 290 | + if (lines == nil) { | |
| 291 | + sys->print( "loadSystemColors: Couldn't read %s\n", systemcolors_file); | |
| 292 | + return; | |
| 293 | + } | |
| 294 | + for(; lines != nil; lines = tl lines) { | |
| 295 | + line := hd lines; | |
| 296 | + (n, l) := sys->tokenize(line, " \t="); | |
| 297 | + if (n < 2 || line[0] == '#') | |
| 298 | + continue; | |
| 299 | + key := hd l; | |
| 300 | + line = hd tl l; | |
| 301 | + (n, l) = sys->tokenize(line, ";"); | |
| 302 | + if (n != 3) | |
| 303 | + continue; | |
| 304 | + r := int hd l; | |
| 305 | + g := int hd tl l; | |
| 306 | + b := int hd tl tl l; | |
| 307 | + # sys->print(" key = %s: r = %d; g = %d; b = %d\n", key, r, g, b); | |
| 308 | + val = jni->GetStaticField( cl.class, key, "I" ); | |
| 309 | + if ( val == nil ) | |
| 310 | + continue; | |
| 311 | + index := val.Int(); | |
| 312 | + color := (255 << 24) | ((r & 255) << 16) | ((g & 255) << 8) | ((b & 255) << 0); | |
| 313 | + systemColors.ary[index] = color; | |
| 314 | + } | |
| 315 | + | |
| 316 | + return; | |
| 317 | +} | |
| 318 | + | |
| 319 | + | |
| 320 | +# read a file and return its lines as a list of strings | |
| 321 | +readfile(filename: string) : list of string | |
| 322 | +{ | |
| 323 | + fd := sys->open(filename, sys->OREAD); | |
| 324 | + if(fd != nil) { | |
| 325 | + (n, dir) := sys->fstat(fd); | |
| 326 | + if(n < 0) | |
| 327 | + return nil; # shouldn't happen | |
| 328 | + buf := array[dir.length] of byte; | |
| 329 | + n = sys->read(fd, buf, dir.length); | |
| 330 | + if(n == dir.length) { | |
| 331 | + (nil, linelist) := sys->tokenize(string buf[0:n], "\r\n"); | |
| 332 | + return linelist; | |
| 333 | + } | |
| 334 | + } | |
| 335 | + return nil; | |
| 336 | +} | |
| 337 | + | |
| 338 | + | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +# | |
| 2 | +# %W% - %E% | |
| 3 | +# | |
| 4 | + | |
| 5 | +AwtColor : module | |
| 6 | +{ | |
| 7 | + PATH : con "/dis/java/inferno/awt/awt_Color.dis"; | |
| 8 | + | |
| 9 | + getColor : fn(jni: JNI, c: JObject) : ref Image; | |
| 10 | + getColorIndex : fn(jni: JNI, c: JObject) : int; | |
| 11 | + makeColorModel : fn(jni: JNI, bits: int) : JObject; | |
| 12 | + loadSystemColors : fn(jni: JNI, systemColors: JArrayI); | |
| 13 | +}; | |
| @@ -0,0 +1,250 @@ | ||
| 1 | +# | |
| 2 | +# %W% - %E% | |
| 3 | +# | |
| 4 | + | |
| 5 | +implement FrameManager; | |
| 6 | + | |
| 7 | +include "sys.m"; | |
| 8 | + sys: Sys; | |
| 9 | + | |
| 10 | +include "string.m"; | |
| 11 | + str: String; | |
| 12 | + | |
| 13 | +include "draw.m"; | |
| 14 | + draw: Draw; | |
| 15 | + Context, Display, Point, Rect, Image, Screen: import draw; | |
| 16 | + | |
| 17 | +include "tk.m"; | |
| 18 | + tk: Tk; | |
| 19 | + Toplevel: import tk; | |
| 20 | + | |
| 21 | +include "wmlib.m"; | |
| 22 | + wmlib: Wmlib; | |
| 23 | + | |
| 24 | +include "awt_Frame.m"; | |
| 25 | + | |
| 26 | +screen: ref Screen; | |
| 27 | +display: ref Display; | |
| 28 | +ones: ref Image; | |
| 29 | +white: ref Image; | |
| 30 | +nochan: chan of string; | |
| 31 | +tHeight : int; | |
| 32 | +bWidth: int; | |
| 33 | + | |
| 34 | +win_cfg := array[] of { | |
| 35 | + "canvas .c -height 306 -width 406", | |
| 36 | + "pack .c -side bottom -fill both -expand 1", | |
| 37 | +# ".c configure -side bottom -fill both -expand 1", | |
| 38 | + "pack propagate . 0", | |
| 39 | +}; | |
| 40 | + | |
| 41 | +win_bind := array[] of { | |
| 42 | + "bind # <Motion> {send butt m %b %X %Y}", | |
| 43 | + "bind # <Leave> {send butt Leave}", | |
| 44 | +# "bind # <ButtonPress> {focus #; send foc focus; send butt p %b %X %Y}", | |
| 45 | + "bind # <ButtonPress> {focus #; send butt p %b %X %Y}", | |
| 46 | + "bind # <ButtonRelease> {send butt r %b %X %Y}", | |
| 47 | + "bind # <Double-Button> {send butt d %b %X %Y}", | |
| 48 | + "bind # <Enter> {send butt Enter}", | |
| 49 | + "bind # <KeyPress> {send key %K}", | |
| 50 | +# "bind . <FocusIn> {send foc focus}", | |
| 51 | +# "bind .Wm_t <Button-1> +{focus #; send foc focus}", | |
| 52 | + "bind .Wm_t <Button-1> +{focus #}", | |
| 53 | +# "bind .Wm_t.title <Button-1> +{focus #; send foc focus}", | |
| 54 | + "bind .Wm_t.title <Button-1> +{focus #}", | |
| 55 | +}; | |
| 56 | + | |
| 57 | +modinit(ctxt: ref Context) | |
| 58 | +{ | |
| 59 | + if (sys != nil) | |
| 60 | + return; | |
| 61 | + | |
| 62 | + sys = load Sys Sys->PATH; | |
| 63 | + str = load String String->PATH; | |
| 64 | + draw = load Draw Draw->PATH; | |
| 65 | + tk = load Tk Tk->PATH; | |
| 66 | + wmlib = load Wmlib Wmlib->PATH; | |
| 67 | + nochan = chan of string; | |
| 68 | + | |
| 69 | + display = ctxt.display; | |
| 70 | + screen = ctxt.screen; | |
| 71 | + ones = display.ones; | |
| 72 | + white = display.color(Draw->White); | |
| 73 | + | |
| 74 | + wmlib->init(); | |
| 75 | +} | |
| 76 | +showwin(cv : ref Canvas) | |
| 77 | +{ | |
| 78 | + tk->cmd(cv.top, "pack " + cv.canvas); | |
| 79 | +} | |
| 80 | +makewin(ctxt: ref Context, title: string, x, y, width, height: int): ref Canvas | |
| 81 | +{ | |
| 82 | + modinit(ctxt); | |
| 83 | + where := "-x " + string x + " -y " + string y; | |
| 84 | + (t, menu) := wmlib->titlebar(screen, where, title, Wmlib->Appl); | |
| 85 | + | |
| 86 | +# calculate topInset and boardwidth | |
| 87 | + bWidth = int tk->cmd(t, ". cget -bd"); | |
| 88 | + tHeight = int tk->cmd(t, ". cget -height"); | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + if (width > 0 && height > 0) | |
| 93 | + win_cfg[0] = "canvas .c -height " + string (height - tHeight - bWidth) + | |
| 94 | + " -width " + string (width - 2*bWidth); | |
| 95 | + | |
| 96 | +# win_cfg[0] = "canvas .c -height " + string height + " -width " + string width; | |
| 97 | + | |
| 98 | + wmlib->tkcmds(t, win_cfg); | |
| 99 | + return alloccanvas(t, ctxt, ".c", menu); | |
| 100 | +} | |
| 101 | + | |
| 102 | +resizewin(cv: ref Canvas, x, y, width, height : int) | |
| 103 | +{ | |
| 104 | +} | |
| 105 | + | |
| 106 | +alloccanvas(t: ref Toplevel, ctxt: ref Draw->Context, canvas: string, menu: chan of string): ref Canvas | |
| 107 | +{ | |
| 108 | + cmd := chan of string; | |
| 109 | + tk->namechan(t, cmd, "cmd"); | |
| 110 | + butt := chan of string; | |
| 111 | + tk->namechan(t, butt, "butt"); | |
| 112 | +# mouse := chan of string; | |
| 113 | +# tk->namechan(t, mouse, "mouse"); | |
| 114 | + | |
| 115 | + key := chan of string; | |
| 116 | + tk->namechan(t, key, "key"); | |
| 117 | + | |
| 118 | + foc := chan of string; | |
| 119 | + tk->namechan(t, foc, "foc"); | |
| 120 | + | |
| 121 | + tk->cmd(t, "bind . <Configure> {send cmd resize}"); | |
| 122 | + tk->cmd(t, "bind . <Map> {send cmd map}"); | |
| 123 | + | |
| 124 | + for (i := 0; i < len win_bind; i++) | |
| 125 | + tk->cmd(t, expand(win_bind[i], canvas)); | |
| 126 | + | |
| 127 | + tk->cmd(t, "update"); | |
| 128 | + | |
| 129 | + c := ref Canvas; | |
| 130 | + display = ctxt.display; | |
| 131 | + c.image = display.image; | |
| 132 | + c.rect = canvposn(t, canvas); | |
| 133 | + c.buf = display.newimage(c.image.r, c.image.ldepth , 0, Draw->White); | |
| 134 | + c.events = chan of ref Event; | |
| 135 | + c.top = t; | |
| 136 | + c.ctxt = ctxt; | |
| 137 | + c.canvas = canvas; | |
| 138 | + c.pid = sys->pctl(0, nil); | |
| 139 | + | |
| 140 | +# calculate topInset and boardwidth | |
| 141 | + y1 := int tk->cmd(t, ". cget -acty") + int tk->cmd(t, ".dy get"); | |
| 142 | + y2 := int tk->cmd(t, ".c cget -acty") + int tk->cmd(t, ".dy get"); | |
| 143 | + | |
| 144 | +# tHeight = int tk->cmd(t, ".Wm_t cget -actheight"); | |
| 145 | + tHeight = y2 - y1; | |
| 146 | + bWidth = int tk->cmd(t, ". cget -bd"); | |
| 147 | + | |
| 148 | + paint(c, c_canvposn(t, canvas)); | |
| 149 | + spawn handler(c, menu, cmd, butt, key, foc); | |
| 150 | + return c; | |
| 151 | +} | |
| 152 | + | |
| 153 | +hidewin(c: ref Canvas) | |
| 154 | +{ | |
| 155 | + tk->cmd(c.top, "pack forget " + c.canvas); | |
| 156 | +} | |
| 157 | + | |
| 158 | +handler(c: ref Canvas, menu, cmd, butt, key, foc: chan of string) | |
| 159 | +{ | |
| 160 | + detail: string; | |
| 161 | + t := c.top; | |
| 162 | + if (menu == nil) | |
| 163 | + menu = nochan; | |
| 164 | + for (;;) alt { | |
| 165 | + detail = <- menu => | |
| 166 | + case detail { | |
| 167 | + "exit" => | |
| 168 | + c.events <- = ref Event(Event.Shutdown, nil); | |
| 169 | + "task" => | |
| 170 | + c.events <- = ref Event(Event.Icon, nil); | |
| 171 | +# "move" => | |
| 172 | +# sys->print("===== moving \n"); | |
| 173 | + * => | |
| 174 | + ; | |
| 175 | + } | |
| 176 | + wmlib->titlectl(c.top, detail); | |
| 177 | + | |
| 178 | + detail = <- cmd => | |
| 179 | + (n, word) := sys->tokenize(detail, " "); | |
| 180 | + case hd word { | |
| 181 | + "resize" or "map" => | |
| 182 | + c.rect = canvposn(t, c.canvas); | |
| 183 | + paint(c, c_canvposn(t, c.canvas)); | |
| 184 | + e := Event.Resize; | |
| 185 | + if (hd word == "map") { | |
| 186 | + e = Event.DeIcon; | |
| 187 | + tk->cmd(t, "focus " + c.canvas); | |
| 188 | + } | |
| 189 | + c.events <- = ref Event(e, nil); | |
| 190 | + * => | |
| 191 | + ; | |
| 192 | + } | |
| 193 | + detail = <- butt => | |
| 194 | + | |
| 195 | + c.events <- = ref Event(Event.Button, detail); | |
| 196 | + detail = <- key => | |
| 197 | + c.events <- = ref Event(Event.Key, detail); | |
| 198 | +# detail = <- foc => | |
| 199 | +# c.events <- = ref Event(Event.Focus, detail); | |
| 200 | + | |
| 201 | + } | |
| 202 | +} | |
| 203 | + | |
| 204 | +expand(cmd, canvas: string): string | |
| 205 | +{ | |
| 206 | + s: string; | |
| 207 | + for (;;) { | |
| 208 | + (l, r) := str->splitl(cmd, "#"); | |
| 209 | + s = s + l; | |
| 210 | + if (r == nil) | |
| 211 | + return s; | |
| 212 | + s = s + canvas; | |
| 213 | + cmd = r[1:]; | |
| 214 | + } | |
| 215 | +} | |
| 216 | + | |
| 217 | +paint(c: ref Canvas, r: Rect) | |
| 218 | +{ | |
| 219 | + c.image.draw(r, white, ones, (0, 0)); | |
| 220 | +} | |
| 221 | + | |
| 222 | +c_canvposn(t: ref Toplevel, c: string): Rect | |
| 223 | +{ | |
| 224 | + r: Rect; | |
| 225 | + | |
| 226 | + r.min.x = int tk->cmd(t, c + " cget -actx") + int tk->cmd(t, ".dx get"); | |
| 227 | + r.min.y = int tk->cmd(t, c + " cget -acty") + int tk->cmd(t, ".dy get"); | |
| 228 | + r.max.x = r.min.x + int tk->cmd(t, c + " cget -actwidth") + int tk->cmd(t, ".dw get"); | |
| 229 | + r.max.y = r.min.y + int tk->cmd(t, c + " cget -actheight") + int tk->cmd(t, ".dh get"); | |
| 230 | + return r; | |
| 231 | +} | |
| 232 | +canvposn(t: ref Toplevel, c: string): Rect | |
| 233 | +{ | |
| 234 | + r: Rect; | |
| 235 | + | |
| 236 | + r.min.x = int tk->cmd(t, ". cget -actx") + int tk->cmd(t, ".dx get"); | |
| 237 | + r.min.y = int tk->cmd(t, ". cget -acty") + int tk->cmd(t, ".dy get"); | |
| 238 | + r.max.x = r.min.x + int tk->cmd(t, ". cget -actwidth") + int tk->cmd(t, ".dw get"); | |
| 239 | + r.max.y = r.min.y + int tk->cmd(t, ". cget -actheight") + int tk->cmd(t, ".dh get"); | |
| 240 | + return r; | |
| 241 | +} | |
| 242 | +getInsets(): (int, int) | |
| 243 | +{ | |
| 244 | + return (bWidth, tHeight); | |
| 245 | +} | |
| 246 | + | |
| 247 | +mapCanvas(dimg : ref Image, wimg : ref Image) | |
| 248 | +{ | |
| 249 | + dimg.draw(dimg.r, wimg, ones, dimg.r.min); | |
| 250 | +} | |
| @@ -0,0 +1,46 @@ | ||
| 1 | +# | |
| 2 | +# %W% - %E% | |
| 3 | +# | |
| 4 | + | |
| 5 | +FrameManager: module | |
| 6 | +{ | |
| 7 | + PATH: con "/dis/java/inferno/awt/awt_Frame.dis"; | |
| 8 | + | |
| 9 | + Event: adt | |
| 10 | + { | |
| 11 | + event: int; | |
| 12 | + detail: string; | |
| 13 | + | |
| 14 | + Button, Key, | |
| 15 | + Icon, DeIcon, | |
| 16 | + Resize, Shutdown, Focus | |
| 17 | + : con iota; | |
| 18 | + }; | |
| 19 | + | |
| 20 | + Attr: adt | |
| 21 | + { | |
| 22 | + origin: Draw->Point; | |
| 23 | + dims: Draw->Point; | |
| 24 | + }; | |
| 25 | + | |
| 26 | + Canvas: adt | |
| 27 | + { | |
| 28 | + # interface | |
| 29 | + image: ref Draw->Image; | |
| 30 | + buf: ref Draw->Image; | |
| 31 | + rect: Draw->Rect; | |
| 32 | + events: chan of ref Event; | |
| 33 | + attr: ref Attr; | |
| 34 | + # implementation | |
| 35 | + ctxt : ref Draw->Context; | |
| 36 | + top: ref Tk->Toplevel; | |
| 37 | + canvas: string; | |
| 38 | + pid: int; | |
| 39 | + }; | |
| 40 | + | |
| 41 | + makewin: fn(ctxt: ref Draw->Context, title: string, x, y, width, height: int): ref Canvas; | |
| 42 | + resizewin: fn(cv: ref Canvas, x, y, width, height : int); | |
| 43 | + hidewin: fn(c: ref Canvas); | |
3 more lines aren’t shown here.
This diff is large: its 210 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 267 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 277 lines aren’t shown here.
This diff is large: its 116 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 528 lines aren’t shown here.
This diff is large: its 589 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 607 lines aren’t shown here.
This diff is large: its 246 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
Empty file added.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 181 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 907 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 653 lines aren’t shown here.
This diff is large: its 304 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 412 lines aren’t shown here.
This diff is large: its 378 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 202 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 463 lines aren’t shown here.
This diff is large: its 170 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
Binary file not shown.
This diff is large: its 411 lines aren’t shown here.
Binary file not shown.
This diff is large: its 92 lines aren’t shown here.
Binary file not shown.
This diff is large: its 162 lines aren’t shown here.
Binary file not shown.
This diff is large: its 106 lines aren’t shown here.
Binary file not shown.
This diff is large: its 134 lines aren’t shown here.
Binary file not shown.
This diff is large: its 70 lines aren’t shown here.
Binary file not shown.
This diff is large: its 64 lines aren’t shown here.
Binary file not shown.
This diff is large: its 93 lines aren’t shown here.
Binary file not shown.
This diff is large: its 63 lines aren’t shown here.
Binary file not shown.
This diff is large: its 390 lines aren’t shown here.
Binary file not shown.
This diff is large: its 64 lines aren’t shown here.
Binary file not shown.
This diff is large: its 225 lines aren’t shown here.
Binary file not shown.
This diff is large: its 57 lines aren’t shown here.
Binary file not shown.
This diff is large: its 190 lines aren’t shown here.
Binary file not shown.
This diff is large: its 64 lines aren’t shown here.
Binary file not shown.
This diff is large: its 64 lines aren’t shown here.
Binary file not shown.
This diff is large: its 152 lines aren’t shown here.
Binary file not shown.
This diff is large: its 64 lines aren’t shown here.
Binary file not shown.
This diff is large: its 110 lines aren’t shown here.
Binary file not shown.
This diff is large: its 206 lines aren’t shown here.
Binary file not shown.
This diff is large: its 77 lines aren’t shown here.
Binary file not shown.
This diff is large: its 169 lines aren’t shown here.
Binary file not shown.
This diff is large: its 288 lines aren’t shown here.
Binary file not shown.
This diff is large: its 64 lines aren’t shown here.
Binary file not shown.
This diff is large: its 117 lines aren’t shown here.
Binary file not shown.
This diff is large: its 57 lines aren’t shown here.
Binary file not shown.
This diff is large: its 51 lines aren’t shown here.
Binary file not shown.
This diff is large: its 89 lines aren’t shown here.
Binary file not shown.
This diff is large: its 83 lines aren’t shown here.
Binary file not shown.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
Binary file not shown.
This diff is large: its 214 lines aren’t shown here.
Binary file not shown.
This diff is large: its 99 lines aren’t shown here.
Binary file not shown.
This diff is large: its 177 lines aren’t shown here.
Binary file not shown.
This diff is large: its 128 lines aren’t shown here.
Binary file not shown.
This diff is large: its 107 lines aren’t shown here.
Binary file not shown.
This diff is large: its 110 lines aren’t shown here.
Binary file not shown.
This diff is large: its 232 lines aren’t shown here.
Binary file not shown.
This diff is large: its 69 lines aren’t shown here.
Binary file not shown.
This diff is large: its 71 lines aren’t shown here.
Binary file not shown.
This diff is large: its 87 lines aren’t shown here.
Binary file not shown.
This diff is large: its 88 lines aren’t shown here.
Binary file not shown.
This diff is large: its 170 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 428 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 660 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 484 lines aren’t shown here.
This diff is large: its 264 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 429 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 559 lines aren’t shown here.
This diff is large: its 116 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 213 lines aren’t shown here.
This diff is large: its 944 lines aren’t shown here.
This diff is large: its 273 lines aren’t shown here.
This diff is large: its 216 lines aren’t shown here.
This diff is large: its 262 lines aren’t shown here.
This diff is large: its 192 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 429 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 1146 lines aren’t shown here.
This diff is large: its 162 lines aren’t shown here.
This diff is large: its 165 lines aren’t shown here.
This diff is large: its 148 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 427 lines aren’t shown here.
This diff is large: its 169 lines aren’t shown here.
This diff is large: its 163 lines aren’t shown here.
This diff is large: its 162 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 568 lines aren’t shown here.
This diff is large: its 413 lines aren’t shown here.
This diff is large: its 237 lines aren’t shown here.
This diff is large: its 187 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 353 lines aren’t shown here.
This diff is large: its 332 lines aren’t shown here.
This diff is large: its 161 lines aren’t shown here.
This diff is large: its 131 lines aren’t shown here.
This diff is large: its 200 lines aren’t shown here.
This diff is large: its 349 lines aren’t shown here.
This diff is large: its 134 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 204 lines aren’t shown here.
This diff is large: its 134 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 904 lines aren’t shown here.
This diff is large: its 222 lines aren’t shown here.
This diff is large: its 411 lines aren’t shown here.
This diff is large: its 260 lines aren’t shown here.
This diff is large: its 230 lines aren’t shown here.
This diff is large: its 542 lines aren’t shown here.
This diff is large: its 155 lines aren’t shown here.
This diff is large: its 204 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 430 lines aren’t shown here.
This diff is large: its 436 lines aren’t shown here.
This diff is large: its 155 lines aren’t shown here.
This diff is large: its 283 lines aren’t shown here.
This diff is large: its 199 lines aren’t shown here.
This diff is large: its 522 lines aren’t shown here.
This diff is large: its 129 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 321 lines aren’t shown here.
This diff is large: its 230 lines aren’t shown here.
This diff is large: its 445 lines aren’t shown here.
This diff is large: its 265 lines aren’t shown here.
This diff is large: its 457 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 278 lines aren’t shown here.
This diff is large: its 176 lines aren’t shown here.
This diff is large: its 369 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
Binary file not shown.
This diff is large: its 54 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1822 lines aren’t shown here.
Binary file not shown.
This diff is large: its 95 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1533 lines aren’t shown here.
Binary file not shown.
This diff is large: its 107 lines aren’t shown here.
Binary file not shown.
This diff is large: its 308 lines aren’t shown here.
This diff is large: its 209 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
Binary file not shown.
This diff is large: its 124 lines aren’t shown here.
Binary file not shown.
This diff is large: its 137 lines aren’t shown here.
Binary file not shown.
This diff is large: its 34 lines aren’t shown here.
Binary file not shown.
This diff is large: its 63 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1168 lines aren’t shown here.
Binary file not shown.
This diff is large: its 50 lines aren’t shown here.
Binary file not shown.
This diff is large: its 147 lines aren’t shown here.
Binary file not shown.
This diff is large: its 219 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 487 lines aren’t shown here.
Binary file not shown.
This diff is large: its 217 lines aren’t shown here.
Binary file not shown.
This diff is large: its 500 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
Binary file not shown.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
Binary file not shown.
This diff is large: its 447 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1029 lines aren’t shown here.
Binary file not shown.
This diff is large: its 100 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 1318 lines aren’t shown here.
Binary file not shown.
This diff is large: its 105 lines aren’t shown here.
Binary file not shown.
This diff is large: its 318 lines aren’t shown here.
Binary file not shown.
This diff is large: its 321 lines aren’t shown here.
This diff is large: its 107 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
Binary file not shown.
This diff is large: its 403 lines aren’t shown here.
Binary file not shown.
This diff is large: its 268 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
Binary file not shown.
This diff is large: its 137 lines aren’t shown here.
Binary file not shown.
This diff is large: its 134 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 261 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 310 lines aren’t shown here.
Binary file not shown.
This diff is large: its 84 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1565 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 372 lines aren’t shown here.
Binary file not shown.
This diff is large: its 255 lines aren’t shown here.
This diff is large: its 367 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1676 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
Binary file not shown.
This diff is large: its 89 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 1810 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
Binary file not shown.
This diff is large: its 99 lines aren’t shown here.
Binary file not shown.
This diff is large: its 2417 lines aren’t shown here.
This diff is large: its 158 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
Binary file not shown.
This diff is large: its 225 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 285 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 242 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1593 lines aren’t shown here.
Binary file not shown.
This diff is large: its 104 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 1172 lines aren’t shown here.
Binary file not shown.
This diff is large: its 127 lines aren’t shown here.
Binary file not shown.
This diff is large: its 2047 lines aren’t shown here.
This diff is large: its 501 lines aren’t shown here.
This diff is large: its 220 lines aren’t shown here.
Binary file not shown.
This diff is large: its 193 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
Binary file not shown.
This diff is large: its 323 lines aren’t shown here.
Binary file not shown.
This diff is large: its 131 lines aren’t shown here.
Binary file not shown.
This diff is large: its 316 lines aren’t shown here.
Binary file not shown.
This diff is large: its 94 lines aren’t shown here.
Binary file not shown.
This diff is large: its 135 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
Binary file not shown.
This diff is large: its 64 lines aren’t shown here.
Binary file not shown.
This diff is large: its 65 lines aren’t shown here.
Binary file not shown.
This diff is large: its 78 lines aren’t shown here.
Binary file not shown.
This diff is large: its 77 lines aren’t shown here.
Binary file not shown.
This diff is large: its 66 lines aren’t shown here.
Binary file not shown.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
Binary file not shown.
This diff is large: its 55 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 135 lines aren’t shown here.
Binary file not shown.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 221 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 1304 lines aren’t shown here.
This diff is large: its 168 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 636 lines aren’t shown here.
This diff is large: its 1399 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 352 lines aren’t shown here.
This diff is large: its 1740 lines aren’t shown here.
This diff is large: its 1498 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 1142 lines aren’t shown here.
This diff is large: its 183 lines aren’t shown here.
This diff is large: its 2156 lines aren’t shown here.
This diff is large: its 234 lines aren’t shown here.
This diff is large: its 832 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 179 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 735 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 151 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 362 lines aren’t shown here.
This diff is large: its 366 lines aren’t shown here.
This diff is large: its 268 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 847 lines aren’t shown here.
This diff is large: its 477 lines aren’t shown here.
This diff is large: its 461 lines aren’t shown here.
This diff is large: its 375 lines aren’t shown here.
This diff is large: its 224 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 1284 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 114 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 212 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 160 lines aren’t shown here.
This diff is large: its 296 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 307 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 176 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 114 lines aren’t shown here.
This diff is large: its 167 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 429 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 286 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 566 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 337 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 321 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
Binary file not shown.
This diff is large: its 45 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 566 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 1310 lines aren’t shown here.
Binary file not shown.
This diff is large: its 212 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 904 lines aren’t shown here.
This diff is large: its 560 lines aren’t shown here.
This diff is large: its 135 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 2621 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 187 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 178 lines aren’t shown here.
Binary file not shown.
This diff is large: its 47 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 296 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 225 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 401 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 131 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 185 lines aren’t shown here.
This diff is large: its 480 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 235 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 228 lines aren’t shown here.
This diff is large: its 246 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 176 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 237 lines aren’t shown here.
This diff is large: its 182 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 235 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 752 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
Binary file not shown.
This diff is large: its 299 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1623 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 2683 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 495 lines aren’t shown here.
Binary file not shown.
This diff is large: its 258 lines aren’t shown here.
Binary file not shown.
This diff is large: its 400 lines aren’t shown here.
Binary file not shown.
This diff is large: its 908 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1490 lines aren’t shown here.
Binary file not shown.
This diff is large: its 44 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1219 lines aren’t shown here.
Binary file not shown.
This diff is large: its 437 lines aren’t shown here.
This diff is large: its 726 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
Binary file not shown.
This diff is large: its 175 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 547 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 819 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 665 lines aren’t shown here.
Binary file not shown.
This diff is large: its 323 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1323 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 2205 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1620 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 643 lines aren’t shown here.
Binary file not shown.
This diff is large: its 501 lines aren’t shown here.
Binary file not shown.
This diff is large: its 339 lines aren’t shown here.
Binary file not shown.
This diff is large: its 98 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 282 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 345 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 210 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 373 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 114 lines aren’t shown here.
This diff is large: its 154 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 262 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 430 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 445 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 831 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 240 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 474 lines aren’t shown here.
This diff is large: its 150 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 182 lines aren’t shown here.
This diff is large: its 864 lines aren’t shown here.
This diff is large: its 431 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 286 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 201 lines aren’t shown here.
This diff is large: its 378 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 545 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 116 lines aren’t shown here.
This diff is large: its 116 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
Binary file not shown.
This diff is large: its 233 lines aren’t shown here.
Binary file not shown.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 2065 lines aren’t shown here.
Binary file not shown.
This diff is large: its 131 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 305 lines aren’t shown here.
Binary file not shown.
This diff is large: its 229 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1493 lines aren’t shown here.
Binary file not shown.
This diff is large: its 68 lines aren’t shown here.
Binary file not shown.
This diff is large: its 78 lines aren’t shown here.
Binary file not shown.
This diff is large: its 47 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 779 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 1498 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 271 lines aren’t shown here.
Binary file not shown.
This diff is large: its 719 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 470 lines aren’t shown here.
Binary file not shown.
This diff is large: its 322 lines aren’t shown here.
Binary file not shown.
This diff is large: its 275 lines aren’t shown here.
Binary file not shown.
This diff is large: its 366 lines aren’t shown here.
Binary file not shown.
This diff is large: its 189 lines aren’t shown here.
Binary file not shown.
This diff is large: its 211 lines aren’t shown here.
Binary file not shown.
This diff is large: its 125 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 176 lines aren’t shown here.
Binary file not shown.
This diff is large: its 179 lines aren’t shown here.
Binary file not shown.
This diff is large: its 71 lines aren’t shown here.
Binary file not shown.
This diff is large: its 123 lines aren’t shown here.
Binary file not shown.
This diff is large: its 69 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 281 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 679 lines aren’t shown here.
Binary file not shown.
This diff is large: its 65 lines aren’t shown here.
Binary file not shown.
This diff is large: its 193 lines aren’t shown here.
Binary file not shown.
This diff is large: its 96 lines aren’t shown here.
Binary file not shown.
This diff is large: its 91 lines aren’t shown here.
Binary file not shown.
This diff is large: its 242 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 138 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 839 lines aren’t shown here.
Binary file not shown.
This diff is large: its 103 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 253 lines aren’t shown here.
Binary file not shown.
This diff is large: its 107 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 911 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 189 lines aren’t shown here.
Binary file not shown.
This diff is large: its 111 lines aren’t shown here.
Binary file not shown.
This diff is large: its 73 lines aren’t shown here.
Binary file not shown.
This diff is large: its 41 lines aren’t shown here.
Binary file not shown.
This diff is large: its 104 lines aren’t shown here.
Binary file not shown.
This diff is large: its 60 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 233 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 495 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 242 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
Binary file not shown.
This diff is large: its 571 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 347 lines aren’t shown here.
Binary file not shown.
This diff is large: its 107 lines aren’t shown here.
Binary file not shown.
This diff is large: its 666 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 545 lines aren’t shown here.
Binary file not shown.
This diff is large: its 111 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 149 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
Binary file not shown.
This diff is large: its 122 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
Binary file not shown.
This diff is large: its 247 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 809 lines aren’t shown here.
Binary file not shown.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 758 lines aren’t shown here.
This diff is large: its 478 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 309 lines aren’t shown here.
This diff is large: its 220 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 403 lines aren’t shown here.
This diff is large: its 264 lines aren’t shown here.
This diff is large: its 288 lines aren’t shown here.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 182 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 150 lines aren’t shown here.
This diff is large: its 267 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 138 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 218 lines aren’t shown here.
This diff is large: its 1286 lines aren’t shown here.
This diff is large: its 949 lines aren’t shown here.
This diff is large: its 381 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 1515 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 149 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 487 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 161 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 129 lines aren’t shown here.
This diff is large: its 171 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 215 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 490 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 283 lines aren’t shown here.
This diff is large: its 218 lines aren’t shown here.
This diff is large: its 363 lines aren’t shown here.
This diff is large: its 477 lines aren’t shown here.
This diff is large: its 184 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 279 lines aren’t shown here.
This diff is large: its 194 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 512 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 327 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 207 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 574 lines aren’t shown here.
This diff is large: its 191 lines aren’t shown here.
This diff is large: its 1027 lines aren’t shown here.
This diff is large: its 758 lines aren’t shown here.
This diff is large: its 317 lines aren’t shown here.
This diff is large: its 195 lines aren’t shown here.
This diff is large: its 520 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 415 lines aren’t shown here.
This diff is large: its 562 lines aren’t shown here.
This diff is large: its 176 lines aren’t shown here.
This diff is large: its 243 lines aren’t shown here.
This diff is large: its 210 lines aren’t shown here.
This diff is large: its 2571 lines aren’t shown here.
This diff is large: its 1072 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 265 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 142 lines aren’t shown here.
This diff is large: its 572 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 134 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 1376 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 2660 lines aren’t shown here.
This diff is large: its 701 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 270 lines aren’t shown here.
This diff is large: its 1153 lines aren’t shown here.
This diff is large: its 346 lines aren’t shown here.
This diff is large: its 273 lines aren’t shown here.
This diff is large: its 631 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is larger than a page shows: the files after these aren’t listed. Clone the repository to see all of it.