diff --git a/classpath/allsources.lst b/classpath/allsources.lst index 73a45b1f..cd5a38d4 100644 --- a/classpath/allsources.lst +++ b/classpath/allsources.lst @@ -10,6 +10,7 @@ java/lang/VMThread.java java/lang/VMClass.java java/lang/VMDouble.java java/lang/VMFloat.java +java/lang/VMSystem.java java/lang/ExceptionHelper.java java/lang/ObjectHelper.java java/lang/StringHelper.java @@ -294,6 +295,8 @@ sun/misc/Ref.java ../../classpath/gnu/java/security/Engine.java ../../classpath/gnu/java/security/OID.java ../../classpath/gnu/java/security/PolicyFile.java +../../classpath/gnu/java/security/action/GetPropertyAction.java +../../classpath/gnu/java/security/action/SetAccessibleAction.java ../../classpath/gnu/java/security/der/BitString.java ../../classpath/gnu/java/security/der/DER.java ../../classpath/gnu/java/security/der/DEREncodingException.java @@ -602,6 +605,7 @@ sun/misc/Ref.java ../../classpath/java/awt/image/BufferedImage.java ../../classpath/java/awt/image/BufferedImageOp.java ../../classpath/java/awt/image/BufferStrategy.java +../../classpath/java/awt/image/ByteLookupTable.java ../../classpath/java/awt/image/ColorModel.java ../../classpath/java/awt/image/ComponentColorModel.java ../../classpath/java/awt/image/ComponentSampleModel.java @@ -621,6 +625,8 @@ sun/misc/Ref.java ../../classpath/java/awt/image/ImageProducer.java ../../classpath/java/awt/image/ImagingOpException.java ../../classpath/java/awt/image/IndexColorModel.java +../../classpath/java/awt/image/Kernel.java +../../classpath/java/awt/image/LookupTable.java ../../classpath/java/awt/image/MemoryImageSource.java ../../classpath/java/awt/image/PackedColorModel.java ../../classpath/java/awt/image/PixelGrabber.java @@ -632,6 +638,7 @@ sun/misc/Ref.java ../../classpath/java/awt/image/ReplicateScaleFilter.java ../../classpath/java/awt/image/RGBImageFilter.java ../../classpath/java/awt/image/SampleModel.java +../../classpath/java/awt/image/ShortLookupTable.java ../../classpath/java/awt/image/SinglePixelPackedSampleModel.java ../../classpath/java/awt/image/TileObserver.java ../../classpath/java/awt/image/VolatileImage.java @@ -687,8 +694,10 @@ sun/misc/Ref.java ../../classpath/java/beans/Beans.java ../../classpath/java/beans/Customizer.java ../../classpath/java/beans/DesignMode.java +../../classpath/java/beans/EventHandler.java ../../classpath/java/beans/EventSetDescriptor.java ../../classpath/java/beans/ExceptionListener.java +../../classpath/java/beans/Expression.java ../../classpath/java/beans/FeatureDescriptor.java ../../classpath/java/beans/IndexedPropertyDescriptor.java ../../classpath/java/beans/IntrospectionException.java @@ -705,6 +714,7 @@ sun/misc/Ref.java ../../classpath/java/beans/PropertyEditorSupport.java ../../classpath/java/beans/PropertyVetoException.java ../../classpath/java/beans/SimpleBeanInfo.java +../../classpath/java/beans/Statement.java ../../classpath/java/beans/VetoableChangeListener.java ../../classpath/java/beans/VetoableChangeListenerProxy.java ../../classpath/java/beans/VetoableChangeSupport.java @@ -1202,8 +1212,10 @@ sun/misc/Ref.java ../../classpath/java/security/cert/PolicyQualifierInfo.java ../../classpath/java/security/cert/TrustAnchor.java ../../classpath/java/security/cert/X509Certificate.java +../../classpath/java/security/cert/X509CertSelector.java ../../classpath/java/security/cert/X509CRL.java ../../classpath/java/security/cert/X509CRLEntry.java +../../classpath/java/security/cert/X509CRLSelector.java ../../classpath/java/security/cert/X509Extension.java ../../classpath/java/security/interfaces/DSAKey.java ../../classpath/java/security/interfaces/DSAKeyPairGenerator.java @@ -1429,6 +1441,46 @@ sun/misc/Ref.java ../../classpath/javax/accessibility/AccessibleTableModelChange.java ../../classpath/javax/accessibility/AccessibleText.java ../../classpath/javax/accessibility/AccessibleValue.java +../../classpath/javax/crypto/BadPaddingException.java +../../classpath/javax/crypto/Cipher.java +../../classpath/javax/crypto/CipherInputStream.java +../../classpath/javax/crypto/CipherOutputStream.java +../../classpath/javax/crypto/CipherSpi.java +../../classpath/javax/crypto/EncryptedPrivateKeyInfo.java +../../classpath/javax/crypto/ExemptionMechanism.java +../../classpath/javax/crypto/ExemptionMechanismException.java +../../classpath/javax/crypto/ExemptionMechanismSpi.java +../../classpath/javax/crypto/IllegalBlockSizeException.java +../../classpath/javax/crypto/KeyAgreement.java +../../classpath/javax/crypto/KeyAgreementSpi.java +../../classpath/javax/crypto/KeyGenerator.java +../../classpath/javax/crypto/KeyGeneratorSpi.java +../../classpath/javax/crypto/Mac.java +../../classpath/javax/crypto/MacSpi.java +../../classpath/javax/crypto/NoSuchPaddingException.java +../../classpath/javax/crypto/NullCipher.java +../../classpath/javax/crypto/NullCipherImpl.java +../../classpath/javax/crypto/SealedObject.java +../../classpath/javax/crypto/SecretKey.java +../../classpath/javax/crypto/SecretKeyFactory.java +../../classpath/javax/crypto/SecretKeyFactorySpi.java +../../classpath/javax/crypto/ShortBufferException.java +../../classpath/javax/crypto/interfaces/DHKey.java +../../classpath/javax/crypto/interfaces/DHPrivateKey.java +../../classpath/javax/crypto/interfaces/DHPublicKey.java +../../classpath/javax/crypto/interfaces/PBEKey.java +../../classpath/javax/crypto/spec/DESedeKeySpec.java +../../classpath/javax/crypto/spec/DESKeySpec.java +../../classpath/javax/crypto/spec/DHGenParameterSpec.java +../../classpath/javax/crypto/spec/DHParameterSpec.java +../../classpath/javax/crypto/spec/DHPrivateKeySpec.java +../../classpath/javax/crypto/spec/DHPublicKeySpec.java +../../classpath/javax/crypto/spec/IvParameterSpec.java +../../classpath/javax/crypto/spec/PBEKeySpec.java +../../classpath/javax/crypto/spec/PBEParameterSpec.java +../../classpath/javax/crypto/spec/RC2ParameterSpec.java +../../classpath/javax/crypto/spec/RC5ParameterSpec.java +../../classpath/javax/crypto/spec/SecretKeySpec.java ../../classpath/javax/imageio/IIOException.java ../../classpath/javax/imageio/ImageReader.java ../../classpath/javax/imageio/ImageTranscoder.java @@ -1536,6 +1588,40 @@ sun/misc/Ref.java ../../classpath/javax/naming/spi/Resolver.java ../../classpath/javax/naming/spi/ResolveResult.java ../../classpath/javax/naming/spi/StateFactory.java +../../classpath/javax/net/ServerSocketFactory.java +../../classpath/javax/net/SocketFactory.java +../../classpath/javax/net/VanillaServerSocketFactory.java +../../classpath/javax/net/VanillaSocketFactory.java +../../classpath/javax/net/ssl/HandshakeCompletedEvent.java +../../classpath/javax/net/ssl/HandshakeCompletedListener.java +../../classpath/javax/net/ssl/HostnameVerifier.java +../../classpath/javax/net/ssl/HttpsURLConnection.java +../../classpath/javax/net/ssl/KeyManager.java +../../classpath/javax/net/ssl/KeyManagerFactory.java +../../classpath/javax/net/ssl/KeyManagerFactorySpi.java +../../classpath/javax/net/ssl/ManagerFactoryParameters.java +../../classpath/javax/net/ssl/SSLContext.java +../../classpath/javax/net/ssl/SSLContextSpi.java +../../classpath/javax/net/ssl/SSLException.java +../../classpath/javax/net/ssl/SSLHandshakeException.java +../../classpath/javax/net/ssl/SSLKeyException.java +../../classpath/javax/net/ssl/SSLPeerUnverifiedException.java +../../classpath/javax/net/ssl/SSLPermission.java +../../classpath/javax/net/ssl/SSLProtocolException.java +../../classpath/javax/net/ssl/SSLServerSocket.java +../../classpath/javax/net/ssl/SSLServerSocketFactory.java +../../classpath/javax/net/ssl/SSLSession.java +../../classpath/javax/net/ssl/SSLSessionBindingEvent.java +../../classpath/javax/net/ssl/SSLSessionBindingListener.java +../../classpath/javax/net/ssl/SSLSessionContext.java +../../classpath/javax/net/ssl/SSLSocket.java +../../classpath/javax/net/ssl/SSLSocketFactory.java +../../classpath/javax/net/ssl/TrivialHostnameVerifier.java +../../classpath/javax/net/ssl/TrustManager.java +../../classpath/javax/net/ssl/TrustManagerFactory.java +../../classpath/javax/net/ssl/TrustManagerFactorySpi.java +../../classpath/javax/net/ssl/X509KeyManager.java +../../classpath/javax/net/ssl/X509TrustManager.java ../../classpath/javax/print/AttributeException.java ../../classpath/javax/print/CancelablePrintJob.java ../../classpath/javax/print/Doc.java @@ -1661,7 +1747,53 @@ sun/misc/Ref.java ../../classpath/javax/rmi/CORBA/Util.java ../../classpath/javax/rmi/CORBA/UtilDelegate.java ../../classpath/javax/rmi/CORBA/ValueHandler.java +../../classpath/javax/security/auth/AuthPermission.java +../../classpath/javax/security/auth/Destroyable.java +../../classpath/javax/security/auth/DestroyFailedException.java +../../classpath/javax/security/auth/Policy.java +../../classpath/javax/security/auth/PrivateCredentialPermission.java +../../classpath/javax/security/auth/Refreshable.java +../../classpath/javax/security/auth/RefreshFailedException.java +../../classpath/javax/security/auth/Subject.java +../../classpath/javax/security/auth/SubjectDomainCombiner.java +../../classpath/javax/security/auth/callback/Callback.java +../../classpath/javax/security/auth/callback/CallbackHandler.java +../../classpath/javax/security/auth/callback/ChoiceCallback.java +../../classpath/javax/security/auth/callback/ConfirmationCallback.java +../../classpath/javax/security/auth/callback/LanguageCallback.java +../../classpath/javax/security/auth/callback/NameCallback.java +../../classpath/javax/security/auth/callback/PasswordCallback.java +../../classpath/javax/security/auth/callback/TextInputCallback.java +../../classpath/javax/security/auth/callback/TextOutputCallback.java +../../classpath/javax/security/auth/callback/UnsupportedCallbackException.java +../../classpath/javax/security/auth/login/AccountExpiredException.java +../../classpath/javax/security/auth/login/AppConfigurationEntry.java +../../classpath/javax/security/auth/login/Configuration.java +../../classpath/javax/security/auth/login/CredentialExpiredException.java +../../classpath/javax/security/auth/login/FailedLoginException.java +../../classpath/javax/security/auth/login/LoginContext.java +../../classpath/javax/security/auth/login/LoginException.java +../../classpath/javax/security/auth/login/NullConfiguration.java ../../classpath/javax/security/auth/x500/X500Principal.java +../../classpath/javax/security/auth/x500/X500PrivateCredential.java +../../classpath/javax/security/cert/Certificate.java +../../classpath/javax/security/cert/CertificateEncodingException.java +../../classpath/javax/security/cert/CertificateException.java +../../classpath/javax/security/cert/CertificateExpiredException.java +../../classpath/javax/security/cert/CertificateNotYetValidException.java +../../classpath/javax/security/cert/CertificateParsingException.java +../../classpath/javax/security/cert/X509CertBridge.java +../../classpath/javax/security/cert/X509Certificate.java +../../classpath/javax/security/sasl/AuthenticationException.java +../../classpath/javax/security/sasl/AuthorizeCallback.java +../../classpath/javax/security/sasl/RealmCallback.java +../../classpath/javax/security/sasl/RealmChoiceCallback.java +../../classpath/javax/security/sasl/Sasl.java +../../classpath/javax/security/sasl/SaslClient.java +../../classpath/javax/security/sasl/SaslClientFactory.java +../../classpath/javax/security/sasl/SaslException.java +../../classpath/javax/security/sasl/SaslServer.java +../../classpath/javax/security/sasl/SaslServerFactory.java ../../classpath/javax/sql/ConnectionEvent.java ../../classpath/javax/sql/ConnectionEventListener.java ../../classpath/javax/sql/ConnectionPoolDataSource.java @@ -1681,6 +1813,7 @@ sun/misc/Ref.java ../../classpath/javax/swing/AbstractCellEditor.java ../../classpath/javax/swing/AbstractListModel.java ../../classpath/javax/swing/AbstractSet.java +../../classpath/javax/swing/AbstractSpinnerModel.java ../../classpath/javax/swing/Action.java ../../classpath/javax/swing/ActionMap.java ../../classpath/javax/swing/BorderFactory.java @@ -1745,6 +1878,7 @@ sun/misc/Ref.java ../../classpath/javax/swing/JScrollPane.java ../../classpath/javax/swing/JSeparator.java ../../classpath/javax/swing/JSlider.java +../../classpath/javax/swing/JSpinner.java ../../classpath/javax/swing/JSplitPane.java ../../classpath/javax/swing/JTabbedPane.java ../../classpath/javax/swing/JTable.java @@ -1779,7 +1913,11 @@ sun/misc/Ref.java ../../classpath/javax/swing/SingleSelectionModel.java ../../classpath/javax/swing/SizeRequirements.java ../../classpath/javax/swing/SizeSequence.java +../../classpath/javax/swing/SpinnerListModel.java ../../classpath/javax/swing/SpinnerModel.java +../../classpath/javax/swing/SpinnerNumberModel.java +../../classpath/javax/swing/Spring.java +../../classpath/javax/swing/SpringLayout.java ../../classpath/javax/swing/SwingConstants.java ../../classpath/javax/swing/SwingUtilities.java ../../classpath/javax/swing/Timer.java @@ -1920,12 +2058,16 @@ sun/misc/Ref.java ../../classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java ../../classpath/javax/swing/plaf/basic/BasicSeparatorUI.java ../../classpath/javax/swing/plaf/basic/BasicSliderUI.java +../../classpath/javax/swing/plaf/basic/BasicSpinnerUI.java ../../classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java ../../classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java ../../classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java +../../classpath/javax/swing/plaf/basic/BasicTextFieldUI.java ../../classpath/javax/swing/plaf/basic/BasicTextUI.java ../../classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java +../../classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java ../../classpath/javax/swing/plaf/basic/BasicToolBarUI.java +../../classpath/javax/swing/plaf/basic/BasicToolTipUI.java ../../classpath/javax/swing/plaf/basic/BasicTreeUI.java ../../classpath/javax/swing/plaf/basic/BasicViewportUI.java ../../classpath/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -1943,26 +2085,31 @@ sun/misc/Ref.java ../../classpath/javax/swing/text/AttributeSet.java ../../classpath/javax/swing/text/BadLocationException.java ../../classpath/javax/swing/text/Caret.java -../../classpath/javax/swing/text/CharacterIterator.java ../../classpath/javax/swing/text/ComponentView.java ../../classpath/javax/swing/text/DefaultCaret.java ../../classpath/javax/swing/text/DefaultEditorKit.java +../../classpath/javax/swing/text/DefaultHighlighter.java ../../classpath/javax/swing/text/Document.java ../../classpath/javax/swing/text/DocumentFilter.java ../../classpath/javax/swing/text/EditorKit.java ../../classpath/javax/swing/text/Element.java +../../classpath/javax/swing/text/FieldView.java ../../classpath/javax/swing/text/GapContent.java +../../classpath/javax/swing/text/Highlighter.java ../../classpath/javax/swing/text/JTextComponent.java ../../classpath/javax/swing/text/Keymap.java +../../classpath/javax/swing/text/LayeredHighlighter.java ../../classpath/javax/swing/text/MutableAttributeSet.java ../../classpath/javax/swing/text/NavigationFilter.java ../../classpath/javax/swing/text/PlainDocument.java -../../classpath/javax/swing/text/PlainEditorKit.java +../../classpath/javax/swing/text/PlainView.java ../../classpath/javax/swing/text/Position.java ../../classpath/javax/swing/text/Segment.java ../../classpath/javax/swing/text/Style.java ../../classpath/javax/swing/text/StyledDocument.java ../../classpath/javax/swing/text/StyledEditorKit.java +../../classpath/javax/swing/text/TabableView.java +../../classpath/javax/swing/text/TabExpander.java ../../classpath/javax/swing/text/TextAction.java ../../classpath/javax/swing/text/View.java ../../classpath/javax/swing/text/ViewFactory.java @@ -2011,11 +2158,19 @@ sun/misc/Ref.java ../../classpath/javax/transaction/xa/XAException.java ../../classpath/javax/transaction/xa/XAResource.java ../../classpath/javax/transaction/xa/Xid.java +../../classpath/org/ietf/jgss/ChannelBinding.java +../../classpath/org/ietf/jgss/GSSContext.java +../../classpath/org/ietf/jgss/GSSCredential.java +../../classpath/org/ietf/jgss/GSSException.java +../../classpath/org/ietf/jgss/GSSManager.java +../../classpath/org/ietf/jgss/GSSName.java +../../classpath/org/ietf/jgss/MessageProp.java +../../classpath/org/ietf/jgss/Oid.java +../../classpath/vm/reference/gnu/java/nio/VMSelector.java ../../classpath/vm/reference/java/io/VMObjectStreamClass.java ../../classpath/vm/reference/java/lang/VMObject.java ../../classpath/vm/reference/java/lang/VMSecurityManager.java ../../classpath/vm/reference/java/lang/VMString.java -../../classpath/vm/reference/java/lang/VMSystem.java ../../classpath/vm/reference/java/lang/VMThrowable.java ../../classpath/vm/reference/java/security/VMAccessController.java ../../classpath/vm/reference/gnu/java/nio/VMPipe.java diff --git a/classpath/java/lang/VMRuntime.java b/classpath/java/lang/VMRuntime.java index 55258bfa..d671b568 100644 --- a/classpath/java/lang/VMRuntime.java +++ b/classpath/java/lang/VMRuntime.java @@ -93,7 +93,7 @@ final class VMRuntime static long totalMemory() { // NOTE this really is a bogus number, but we have to return something - return cli.System.GC.GetTotalMemory(false); + return cli.System.GC.GetTotalMemory(false) + freeMemory(); } /** diff --git a/classpath/map.xml b/classpath/map.xml index be2ee7fb..c71f6776 100644 --- a/classpath/map.xml +++ b/classpath/map.xml @@ -867,6 +867,8 @@ + diff --git a/ikvm.build b/ikvm.build index 2c18dd7b..b7dd8c8e 100644 --- a/ikvm.build +++ b/ikvm.build @@ -2,10 +2,7 @@ - - - - + @@ -20,8 +17,8 @@ - - + + diff --git a/ikvm.sln b/ikvm.sln index bf67f703..d535bffa 100644 --- a/ikvm.sln +++ b/ikvm.sln @@ -3,10 +3,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKVM.Runtime", "runtime\IKV ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IKVM.JNI.CLR-Win32", "jni\clr-win32\IKVM.JNI.CLR-Win32.vcproj", "{4D400F9D-68A1-4066-95F6-85AF0E58B710}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ikvm", "ikvm\ikvm.csproj", "{4FBAFF23-1E48-4977-8C50-30F87E70A8B5}" ProjectSection(ProjectDependencies) = postProject EndProjectSection @@ -23,6 +19,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKVM.AWT.WinForms", "awt\IK ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ikvm-native", "native\native.vcproj", "{14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -33,10 +33,6 @@ Global {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Debug.Build.0 = Debug|.NET {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Release.ActiveCfg = Release|.NET {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Release.Build.0 = Release|.NET - {4D400F9D-68A1-4066-95F6-85AF0E58B710}.Debug.ActiveCfg = Debug|Win32 - {4D400F9D-68A1-4066-95F6-85AF0E58B710}.Debug.Build.0 = Debug|Win32 - {4D400F9D-68A1-4066-95F6-85AF0E58B710}.Release.ActiveCfg = Release|Win32 - {4D400F9D-68A1-4066-95F6-85AF0E58B710}.Release.Build.0 = Release|Win32 {4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Debug.ActiveCfg = Debug|.NET {4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Debug.Build.0 = Debug|.NET {4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Release.ActiveCfg = Release|.NET @@ -53,6 +49,10 @@ Global {E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Debug.Build.0 = Debug|.NET {E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Release.ActiveCfg = Release|.NET {E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Release.Build.0 = Release|.NET + {14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}.Debug.ActiveCfg = Debug|Win32 + {14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}.Debug.Build.0 = Debug|Win32 + {14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}.Release.ActiveCfg = Release|Win32 + {14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/jni/clr-win32/AssemblyInfo.cpp b/jni/clr-win32/AssemblyInfo.cpp deleted file mode 100644 index e93ef2a9..00000000 --- a/jni/clr-win32/AssemblyInfo.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright (C) 2002 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ -#include "stdafx.h" - -using namespace System::Reflection; -using namespace System::Runtime::CompilerServices; - -// -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -// -[assembly:AssemblyTitleAttribute("")]; -[assembly:AssemblyDescriptionAttribute("")]; -[assembly:AssemblyConfigurationAttribute("")]; -[assembly:AssemblyCompanyAttribute("")]; -[assembly:AssemblyProductAttribute("")]; -[assembly:AssemblyCopyrightAttribute("")]; -[assembly:AssemblyTrademarkAttribute("")]; -[assembly:AssemblyCultureAttribute("")]; - -// -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the value or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly:AssemblyVersionAttribute("0.9.*")]; - -// -// In order to sign your assembly you must specify a key to use. Refer to the -// Microsoft .NET Framework documentation for more information on assembly signing. -// -// Use the attributes below to control which key is used for signing. -// -// Notes: -// (*) If no key is specified, the assembly is not signed. -// (*) KeyName refers to a key that has been installed in the Crypto Service -// Provider (CSP) on your machine. KeyFile refers to a file which contains -// a key. -// (*) If the KeyFile and the KeyName values are both specified, the -// following processing occurs: -// (1) If the KeyName can be found in the CSP, that key is used. -// (2) If the KeyName does not exist and the KeyFile does exist, the key -// in the KeyFile is installed into the CSP and used. -// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. -// When specifying the KeyFile, the location of the KeyFile should be -// relative to the project directory. -// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework -// documentation for more information on this. -// -[assembly:AssemblyDelaySignAttribute(false)]; -//[assembly: AssemblyKeyFile("c:\\ikvm-key\\ikvm.snk")]; -[assembly:AssemblyKeyNameAttribute("")]; - diff --git a/jni/clr-win32/Stdafx.cpp b/jni/clr-win32/Stdafx.cpp deleted file mode 100644 index 42f1745b..00000000 --- a/jni/clr-win32/Stdafx.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// jni.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" diff --git a/jni/clr-win32/Stdafx.h b/jni/clr-win32/Stdafx.h deleted file mode 100644 index 91e9cc50..00000000 --- a/jni/clr-win32/Stdafx.h +++ /dev/null @@ -1,9 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, -// but are changed infrequently - -#pragma once - -#using - -#include diff --git a/jni/clr-win32/clr-win32.build b/jni/clr-win32/clr-win32.build deleted file mode 100644 index f2d84e84..00000000 --- a/jni/clr-win32/clr-win32.build +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/jni/clr-win32/jni.cpp b/jni/clr-win32/jni.cpp deleted file mode 100644 index d94bc539..00000000 --- a/jni/clr-win32/jni.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - Copyright (C) 2002, 2004 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -#include "stdafx.h" -#include -#include "jnienv.h" -#include "jni.h" - -#pragma managed - -#include - -using namespace System; -using namespace System::Collections; -using namespace System::Runtime::InteropServices; -using namespace System::Reflection; - -typedef JNIEXPORT jint (JNICALL *PJNI_ONLOAD)(JavaVM* vm, void* reserved); - -int JNI::LoadNativeLibrary(String* name) -{ - HMODULE hMod = LoadLibrary(name); - if(!hMod) - { - return 0; - } - //void* pOnLoad = GetProcAddress(hMod, S"_JNI_OnLoad@8"); - //if(pOnLoad) - //{ - // JavaVM* pVM; - // ((JNIEnv*)0)->JNIEnv::GetJavaVM(&pVM); - // LocalRefStruct loc; - // loc.Enter(); - // jint version = ((PJNI_ONLOAD)pOnLoad)(pVM, 0); - // try - // { - // loc.Leave(); - // } - // catch(...) - // { - // // If the JNI_OnLoad procedure threw an exception, we have to unload the library - // FreeLibrary(hMod); - // throw; - // } - // if(version != JNI_VERSION_1_1 && version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4) - // { - // // NOTE we don't call JNI_OnUnload when the version doesn't match! - // FreeLibrary(hMod); - // throw VM::UnsatisfiedLinkError(String::Format(S"Unsupported JNI version 0x{0:X} required by {1}", __box(version), name)); - // } - //} - libs->Add(__box((int)hMod)); - return 1; -} - -Type* JNI::GetLocalRefStructType() -{ - return 0; - //return __typeof(LocalRefStruct); -} - -MethodInfo* JNI::GetJniFuncPtrMethod() -{ - return __typeof(JNI)->GetMethod("GetJniFuncPtr"); -} - -IntPtr JNI::GetJniFuncPtr(String* method, String* sig, String* clazz) -{ - System::Text::StringBuilder* mangledSig = new System::Text::StringBuilder(); - int sp = 0; - for(int i = 1; sig->Chars[i] != ')'; i++) - { - switch(sig->Chars[i]) - { - case '[': - mangledSig->Append(S"_3"); - sp += 4; - while(sig->Chars[++i] == '[') - { - mangledSig->Append(S"_3"); - } - mangledSig->Append(sig->Chars[i]); - if(sig->Chars[i] == 'L') - { - while(sig->Chars[++i] != ';') - { - if(sig->Chars[i] == '/') - { - mangledSig->Append(S"_"); - } - else if(sig->Chars[i] == '_') - { - mangledSig->Append(S"_1"); - } - else - { - mangledSig->Append(sig->Chars[i]); - } - } - mangledSig->Append(S"_2"); - } - break; - case 'L': - sp += 4; - mangledSig->Append(S"L"); - while(sig->Chars[++i] != ';') - { - if(sig->Chars[i] == '/') - { - mangledSig->Append(S"_"); - } - else if(sig->Chars[i] == '_') - { - mangledSig->Append(S"_1"); - } - else - { - mangledSig->Append(sig->Chars[i]); - } - } - mangledSig->Append(S"_2"); - break; - case 'J': - case 'D': - mangledSig->Append(sig->Chars[i]); - sp += 8; - break; - case 'F': - case 'I': - case 'C': - case 'Z': - case 'S': - case 'B': - mangledSig->Append(sig->Chars[i]); - sp += 4; - break; - default: - DebugBreak(); - throw new NotImplementedException(); - } - } - void* func = 0; - // TODO implement this correctly - String* methodName = String::Format(S"_Java_{0}_{1}@{2}", clazz->Replace(S"_", S"_1")->Replace('/', '_'), method->Replace(S"_", S"_1"), __box(sp + 8)); - for(int i = 0; i < libs->Count; i++) - { - HMODULE hMod = (HMODULE)__unbox(libs->Item[i]); - func = GetProcAddress(hMod, methodName); - if(func) - { - return (IntPtr)func; - } - } - methodName = String::Concat(String::Format(S"_Java_{0}_{1}__{2}@", clazz->Replace(S"_", S"_1")->Replace('/', '_'), method->Replace(S"_", S"_1"), mangledSig), __box(sp + 8)); - for(int i = 0; i < libs->Count; i++) - { - HMODULE hMod = (HMODULE)__unbox(libs->Item[i]); - func = GetProcAddress(hMod, methodName); - if(func) - { - return (IntPtr)func; - } - } - throw VM::UnsatisfiedLinkError(methodName); -} - -//// If we put the ThreadStatic in LocalRefStruct we get an ExecutionEngineException (?!) -//__gc class TlsHack -//{ -//public: -// [ThreadStatic] -// static JNIEnv* pJNIEnv; -//}; -// -//JNIEnv* LocalRefStruct::GetEnv() -//{ -// return TlsHack::pJNIEnv; -//} -// -//IntPtr LocalRefStruct::Enter() -//{ -// pJNIEnv = TlsHack::pJNIEnv; -// if(!pJNIEnv) -// { -// // TODO we should create a managed helper object that deletes JNIEnv when the thread dies -// pJNIEnv = TlsHack::pJNIEnv = new JNIEnv(); -// pJNIEnv->pendingException = 0; -// pJNIEnv->localRefSlot = 0; -// localRefs = pJNIEnv->localRefs = new LocalRefListEntry __gc[32]; -// } -// else -// { -// pPrevLocalRefCache = pJNIEnv->pActiveLocalRefCache; -// localRefs = pJNIEnv->localRefs; -// } -// -// pJNIEnv->localRefSlot++; -// if(pJNIEnv->localRefSlot >= 32) -// { -// // TODO instead of bailing out, we should grow the array -// VM::FatalError("JNI nesting too deep"); -// } -// -// // NOTE since this __value type can (should) only be allocated on the stack, -// // it is "safe" to store the this pointer in a __nogc*, but the compiler -// // doesn't know this, so we have to use a __pin* to bypass its checks. -// LocalRefStruct __pin* pPinHack = this; -// pJNIEnv->pActiveLocalRefCache = pPinHack; -// localRefs[pJNIEnv->localRefSlot].static_list = &pPinHack->fastlocalrefs.loc1; -// return (IntPtr)pJNIEnv; -//} -// -//void LocalRefStruct::Leave() -//{ -// Object* x = pJNIEnv->UnwrapRef(pJNIEnv->pendingException); -// pJNIEnv->pendingException = 0; -// pJNIEnv->pActiveLocalRefCache = pPrevLocalRefCache; -// localRefs[pJNIEnv->localRefSlot].dynamic_list = 0; -// // TODO figure out if it is legal to Leave a JNI method while PushLocalFrame is active (i.e. without the corresponding PopLocalFrame) -// pJNIEnv->localRefSlot--; -// if(x) -// { -// throw x; -// } -//} -// -//IntPtr LocalRefStruct::MakeLocalRef(Object* obj) -//{ -// if(obj == 0) -// { -// return 0; -// } -// int i = localRefs[pJNIEnv->localRefSlot].MakeLocalRef(obj); -// if(i >= 0) -// { -// return (pJNIEnv->localRefSlot << LOCAL_REF_SHIFT) + i; -// } -// // TODO consider allocating a new slot (if we do this, the code in -// // PushLocalFrame/PopLocalFrame (and Leave) must be fixed to take this into account) -// VM::FatalError("Too many JNI local references"); -// return 0; -//} -// -//Object* LocalRefStruct::UnwrapLocalRef(IntPtr localref) -//{ -// int i = (int)localref; -// return localRefs[i >> LOCAL_REF_SHIFT].UnwrapLocalRef(i & LOCAL_REF_MASK); -//} diff --git a/jni/clr-win32/jni.h b/jni/clr-win32/jni.h deleted file mode 100644 index 400cee9a..00000000 --- a/jni/clr-win32/jni.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - Copyright (C) 2002, 2004 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -#pragma once - -using namespace System; -using namespace System::Collections; -using namespace System::Runtime::InteropServices; -using namespace System::Reflection; - -class JNIEnv; - -#pragma managed - -template T __unbox(Object* o) -{ - // HACK the MC++ compiler has a bug when unboxing, the static_cast<> is to work around that bug - return *(static_cast(__try_cast<__box T*>(o))); -} - -public __gc class JNI : public IJniProvider -{ - static ArrayList* libs = new ArrayList(); - [DllImport("kernel32")] - [System::Security::SuppressUnmanagedCodeSecurityAttribute] - static HMODULE LoadLibrary(String* lpLibFileName); - [DllImport("kernel32")] - [System::Security::SuppressUnmanagedCodeSecurityAttribute] - static void* GetProcAddress(HMODULE hMod, String* lpProcName); -public: - int LoadNativeLibrary(String* name); - Type* GetLocalRefStructType(); - MethodInfo* GetJniFuncPtrMethod(); - - void** GetVtable() - { - JNIEnv p; - return *(void***)&p; - } - - IntPtr LoadLibraryFoo(String* name) - { - return (IntPtr)(void*)LoadLibrary(name); - } - - void FreeLibraryFoo(IntPtr p) - { - FreeLibrary((HMODULE)(void*)p); - } - - IntPtr GetProcAddress(IntPtr library, String* name, int argcount) - { - String* n = String::Format(S"_{0}@{1}", name, __box(argcount)); - return (IntPtr)GetProcAddress((HMODULE)(void*)library, n); - } - - IntPtr GetJavaVM() - { - JavaVM* pvm; - ((JNIEnv*)0)->JNIEnv::GetJavaVM(&pvm); - return pvm; - } - - typedef JNIEXPORT jint (JNICALL *PJNI_ONLOAD)(JavaVM* vm, void* reserved); - - int CallOnLoad(IntPtr pFunc, IntPtr javavm, IntPtr reserved) - { - return ((PJNI_ONLOAD)(void*)pFunc)((JavaVM*)(void*)javavm, (void*)reserved); - } - - static IntPtr GetJniFuncPtr(String* name, String* sig, String* clazz); -}; - -public __gc class VM -{ -public: - static IntPtr GetMethodCookie(Object* clazz, String* name, String* sig, bool isStatic) - { - return JniHelper::GetMethodCookie(clazz, name, sig, isStatic); - } - static String* GetMethodArgList(IntPtr cookie) - { - return JniHelper::GetMethodArgList(cookie); - } - static Object* InvokeMethod(IntPtr cookie, Object* obj, Object* args[], bool nonVirtual) - { - return JniHelper::InvokeMethod(cookie, obj, args, nonVirtual); - } - static IntPtr GetFieldCookie(Object* clazz, String* name, String* sig, bool isStatic) - { - return JniHelper::GetFieldCookie(clazz, name, sig, isStatic); - } - static Object* GetFieldValue(IntPtr cookie, Object* obj) - { - return JniHelper::GetFieldValue(cookie, obj); - } - static void SetFieldValue(IntPtr cookie, Object* obj, Object* value) - { - JniHelper::SetFieldValue(cookie, obj, value); - } - static Object* FindClass(String* javaName) - { - return JniHelper::FindClass(javaName); - } - static Exception* UnsatisfiedLinkError(String* msg) - { - return JniHelper::UnsatisfiedLinkError(msg); - } - static Object* GetObjectClass(Object* o) - { - return JniHelper::GetObjectClass(o); - } - static bool IsInstanceOf(Object* o, Object* clazz) - { - return JniHelper::IsInstanceOf(o, clazz); - } - static bool IsAssignableFrom(Object* sub, Object* sup) - { - return JniHelper::IsAssignableFrom(sub, sup); - } - static Object* GetSuperclass(Object* sub) - { - return JniHelper::GetSuperclass(sub); - } - static Object* AllocObject(Object* clazz) - { - return JniHelper::AllocObject(clazz); - } - static IntPtr MethodToCookie(Object* method) - { - return JniHelper::MethodToCookie(method); - } - static IntPtr FieldToCookie(Object* field) - { - return JniHelper::FieldToCookie(field); - } - static Object* CookieToMethod(IntPtr method) - { - return JniHelper::CookieToMethod(method); - } - static Object* CookieToField(IntPtr field) - { - return JniHelper::CookieToField(field); - } - static void FatalError(String* msg) - { - Console::Error->WriteLine(S"Fatal Error in JNI: {0}", msg); - JniHelper::FatalError(msg); - } - static Object* DefineClass(String* name, Object* loader, System::Byte array __gc[]) - { - return JniHelper::DefineClass(name, loader, array); - } - static bool SetNativeMethodPointer(Object* clazz, String* name, String* signature, IntPtr methodPtr) - { - return JniHelper::SetNativeMethodPointer(clazz, name, signature, methodPtr); - } - static void ResetNativeMethodPointers(Object* clazz) - { - return JniHelper::ResetNativeMethodPointers(clazz); - } - - static JNIEnv* GetEnv() - { - return (JNIEnv*)(void*)JniHelper::GetEnv(); - } - static jobject MakeLocalRef(JNIEnv* pEnv, Object* obj) - { - return (jobject)(void*)JniHelper::MakeLocalRef(pEnv, obj); - } - static Object* UnwrapRef(JNIEnv* pEnv, jobject obj) - { - return JniHelper::UnwrapRef(pEnv, obj); - } -}; diff --git a/jni/clr-win32/jnienv.cpp b/jni/clr-win32/jnienv.cpp deleted file mode 100644 index 147df814..00000000 --- a/jni/clr-win32/jnienv.cpp +++ /dev/null @@ -1,1506 +0,0 @@ -/* - Copyright (C) 2002, 2003, 2004 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -#include "stdafx.h" -#include "jnienv.h" -#include "jni.h" -#include -#include -#include - -#define DEBUG -#undef NDEBUG - -#include - -using namespace System; -using namespace System::Runtime::InteropServices; -using namespace System::Reflection; - -// this struct exists to ensure the right compile switch is used, if it fails -// to compile, you must compile with /Zc:wchar_t -struct wchar_t_must_be_builtin -{ - void foo(wchar_t t) {} - void foo(unsigned short t) {} -}; - -#pragma managed - -String* StringFromUTF8(const char* psz) -{ - // Sun's modified UTF8 encoding is not compatible with System::Text::Encoding::UTF8, so - // we need to roll our own - int len = 0; - while(psz[len]) len++; - System::Text::StringBuilder* sb = new System::Text::StringBuilder(len); - for(int i = 0; i < len; i++) - { - int c = (unsigned char)*psz++; - int char2, char3; - switch (c >> 4) - { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - // 0xxxxxxx - break; - case 12: case 13: - // 110x xxxx 10xx xxxx - char2 = *psz++; - i++; - c = (((c & 0x1F) << 6) | (char2 & 0x3F)); - break; - case 14: - // 1110 xxxx 10xx xxxx 10xx xxxx - char2 = *psz++; - char3 = *psz++; - i++; - i++; - c = (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); - break; - } - sb->Append((wchar_t)c); - } - return sb->ToString(); -} - -jobject JNIEnv::MakeLocalRef(System::Object* obj) -{ - return VM::MakeLocalRef(this, obj); -} - -Object* JNIEnv::UnwrapRef(jobject o) -{ - return VM::UnwrapRef(this, o); -} - - -JNIEnv::JNIEnv() -{ -} - -JNIEnv::~JNIEnv() -{ -} - -void JNIEnv::reserved0() -{ - VM::FatalError("JNIEnv::reserved0"); -} - -void JNIEnv::reserved1() -{ - VM::FatalError("JNIEnv::reserved1"); -} - -void JNIEnv::reserved2() -{ - VM::FatalError("JNIEnv::reserved2"); -} - -void JNIEnv::reserved3() -{ - VM::FatalError("JNIEnv::reserved3"); -} - -jstring JNIEnv::NewStringUTF(const char *psz) -{ - return (jstring)MakeLocalRef(StringFromUTF8(psz)); -} - -jstring JNIEnv::NewString(const jchar *unicode, jsize len) -{ - return (jstring)MakeLocalRef(new String((__wchar_t*)unicode, 0, len)); -} - -static jsize StringUTFLength(String* s) -{ - jsize len = 0; - for(int i = 0; i < s->Length; i++) - { - jchar ch = s->Chars[i]; - if ((ch != 0) && (ch <=0x7f)) - { - len++; - } - else if (ch <= 0x7FF) - { - len += 2; - } - else - { - len += 3; - } - } - return len; -} - -jsize JNICALL JNIEnv::GetStringUTFLength(jstring str) -{ - String* s = __try_cast(UnwrapRef(str)); - if(s) - { - return StringUTFLength(s); - } - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - return 0; -} - -const char* JNIEnv::GetStringUTFChars(jstring str, jboolean *isCopy) -{ - String* s = __try_cast(UnwrapRef(str)); - if(s) - { - // TODO handle out of memory (what does the unmanaged new do?) - char *buf = new char[StringUTFLength(s) + 1]; - int j = 0; - for(int i = 0; i < s->Length; i++) - { - jchar ch = s->Chars[i]; - if ((ch != 0) && (ch <=0x7f)) - { - buf[j++] = (char)ch; - } - else if (ch <= 0x7FF) - { - /* 11 bits or less. */ - unsigned char high_five = ch >> 6; - unsigned char low_six = ch & 0x3F; - buf[j++] = high_five | 0xC0; /* 110xxxxx */ - buf[j++] = low_six | 0x80; /* 10xxxxxx */ - } - else - { - /* possibly full 16 bits. */ - char high_four = ch >> 12; - char mid_six = (ch >> 6) & 0x3F; - char low_six = ch & 0x3f; - buf[j++] = high_four | 0xE0; /* 1110xxxx */ - buf[j++] = mid_six | 0x80; /* 10xxxxxx */ - buf[j++] = low_six | 0x80; /* 10xxxxxx*/ - } - } - buf[j] = 0; - if(isCopy) - { - *isCopy = JNI_TRUE; - } - return buf; - } - else - { - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - return 0; - } -} - -void JNICALL JNIEnv::GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) -{ - String* s = __try_cast(UnwrapRef(str)); - if(s) - { - if(start > s->Length || s->Length - start < len) - { - ThrowNew(FindClass("java/lang/StringIndexOutOfBoundsException"), ""); - return; - } - else - { - const wchar_t __pin* p = PtrToStringChars(s); - memcpy(buf, p, len); - return; - } - } - else - { - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - } -} - -void JNICALL JNIEnv::GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) -{ - String* s = __try_cast(UnwrapRef(str)); - if(s) - { - if(start > s->Length || s->Length - start < len) - { - ThrowNew(FindClass("java/lang/StringIndexOutOfBoundsException"), ""); - return; - } - else - { - int j = 0; - for(jsize i = 0; i < len; i++) - { - jchar ch = s->Chars[start + i]; - if ((ch != 0) && (ch <=0x7f)) - { - buf[j++] = (char)ch; - } - else if (ch <= 0x7FF) - { - /* 11 bits or less. */ - unsigned char high_five = ch >> 6; - unsigned char low_six = ch & 0x3F; - buf[j++] = high_five | 0xC0; /* 110xxxxx */ - buf[j++] = low_six | 0x80; /* 10xxxxxx */ - } - else - { - /* possibly full 16 bits. */ - char high_four = ch >> 12; - char mid_six = (ch >> 6) & 0x3F; - char low_six = ch & 0x3f; - buf[j++] = high_four | 0xE0; /* 1110xxxx */ - buf[j++] = mid_six | 0x80; /* 10xxxxxx */ - buf[j++] = low_six | 0x80; /* 10xxxxxx*/ - } - } - } - } - else - { - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - } -} - -const jchar* JNICALL JNIEnv::GetStringCritical(jstring str, jboolean *isCopy) -{ - String* s = __try_cast(UnwrapRef(str)); - if(s) - { - // TODO handle out of memory (what does the unmanaged new do?) - jchar* cstring = new jchar[s->Length]; - const wchar_t __pin* p = PtrToStringChars(s); - memcpy(cstring, p, s->Length * 2); - if(isCopy) - { - *isCopy = JNI_TRUE; - } - return cstring; - } - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - return 0; -} - -#pragma unmanaged -void JNIEnv::ReleaseStringUTFChars(jstring str, const char* chars) -{ - delete[] chars; -} - -void JNICALL JNIEnv::ReleaseStringCritical(jstring string, const jchar* cstring) -{ - delete[] cstring; -} - -#pragma managed -jint JNIEnv::ThrowNew(jclass clazz, const char *msg) -{ - jstring str = NewStringUTF(msg); - jmethodID constructor = GetMethodID(clazz, "", "(Ljava/lang/String;)V"); - assert(constructor); - jobject exc = NewObject(clazz, constructor, str); - DeleteLocalRef(str); - Throw((jthrowable)exc); - DeleteLocalRef(exc); - return JNI_OK; -} - -jint JNICALL JNIEnv::Throw(jthrowable obj) -{ - //// TODO once we implement PopLocalFrame, we need to make sure that pendingException isn't in the popped local frame - //pendingException = (jthrowable)NewLocalRef(obj); - //return JNI_OK; - throw new InvalidOperationException(); -} - -jthrowable JNICALL JNIEnv::ExceptionOccurred() -{ - //return (jthrowable)NewLocalRef(pendingException); - throw new InvalidOperationException(); -} - -void JNICALL JNIEnv::ExceptionDescribe() -{ - //if(pendingException) - //{ - // // when calling JNI methods there cannot be an exception pending, so we clear the exception - // // temporarily, while we print it - // jthrowable exception = pendingException; - // pendingException = 0; - // jclass cls = FindClass("java/lang/Throwable"); - // if(cls) - // { - // jmethodID mid = GetMethodID(cls, "printStackTrace", "()V"); - // DeleteLocalRef(cls); - // if(mid) - // { - // CallVoidMethod(exception, mid); - // } - // else - // { - // Console::Error->WriteLine(S"JNI internal error: printStackTrace method not found in java.lang.Throwable"); - // } - // } - // else - // { - // Console::Error->WriteLine(S"JNI internal error: java.lang.Throwable not found"); - // } - // pendingException = exception; - //} - throw new InvalidOperationException(); -} - -void JNICALL JNIEnv::ExceptionClear() -{ - //DeleteLocalRef(pendingException); - //pendingException = 0; - throw new InvalidOperationException(); -} - -jclass JNIEnv::FindClass(const char *utf) -{ - try - { - return (jclass)MakeLocalRef(VM::FindClass(StringFromUTF8(utf))); - } - catch(Exception* x) - { - jobject o = MakeLocalRef(x); - Throw((jthrowable)o); - DeleteLocalRef(o); - return 0; - } -} - -jobject JNIEnv::AllocObject(jclass cls) -{ - return MakeLocalRef(VM::AllocObject(UnwrapRef(cls))); -} - -jmethodID JNIEnv::FindMethodID(jclass cls, const char* name, const char* sig, bool isstatic) -{ - jmethodID mid = (jmethodID)(void*)VM::GetMethodCookie(UnwrapRef(cls), StringFromUTF8(name), StringFromUTF8(sig), isstatic); - if(!mid) - { - // TODO set the exception message - ThrowNew(FindClass("java/lang/NoSuchMethodError"), ""); - return 0; - } - return mid; -} - -jfieldID JNIEnv::FindFieldID(jclass cls, const char* name, const char* sig, bool isstatic) -{ - jfieldID fid = (jfieldID)(void*)VM::GetFieldCookie(UnwrapRef(cls), StringFromUTF8(name), StringFromUTF8(sig), isstatic); - if(!fid) - { - // TODO set the exception message - ThrowNew(FindClass("java/lang/NoSuchFieldError"), ""); - return 0; - } - return fid; -} - -jmethodID JNIEnv::GetStaticMethodID(jclass cls, const char *name, const char *sig) -{ - return FindMethodID(cls, name, sig, true); -} - -static int GetMethodArgs(jmethodID methodID, char* sig) -{ - int count = 0; - String* s = VM::GetMethodArgList(methodID); - for(int i = 0; i < s->Length; i++) - { - *sig++ = (char)s->get_Chars(i); - count++; - } - *sig = 0; - return count; -} - -Object* JNIEnv::InvokeHelper(jobject object, jmethodID methodID, jvalue* args, bool nonVirtual) -{ - DebugBreak(); - return 0; - ////assert(!pendingException); - //assert(methodID); - - //char sig[257]; - //int argc = GetMethodArgs(methodID, sig); - //Object* argarray __gc[] = new Object*[argc]; - //for(int i = 0; i < argc; i++) - //{ - // switch(sig[i]) - // { - // case 'Z': - // argarray[i] = __box(args[i].z != JNI_FALSE); - // break; - // case 'B': - // argarray[i] = __box((char)args[i].b); - // break; - // case 'C': - // argarray[i] = __box((__wchar_t)args[i].c); - // break; - // case 'S': - // argarray[i] = __box((short)args[i].s); - // break; - // case 'I': - // argarray[i] = __box((int)args[i].i); - // break; - // case 'J': - // argarray[i] = __box((__int64)args[i].j); - // break; - // case 'F': - // argarray[i] = __box((float)args[i].f); - // break; - // case 'D': - // argarray[i] = __box((double)args[i].d); - // break; - // case 'L': - // argarray[i] = UnwrapRef(args[i].l); - // break; - // } - //} - //try - //{ - // return VM::InvokeMethod(methodID, UnwrapRef(object), argarray, nonVirtual); - //} - //catch(Exception* x) - //{ - // jobject o = MakeLocalRef(x); - // Throw((jthrowable)o); - // DeleteLocalRef(o); - // return 0; - //} -} - -void JNICALL JNIEnv::CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue* args) -{ - InvokeHelper(0, methodID, args, false); -} -#pragma unmanaged - -void JNICALL JNIEnv::CallStaticVoidMethodV(jclass clazz, jmethodID methodID, va_list args) -{ - char arglist[257]; - int argc = GetMethodArgs(methodID, arglist); - jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue)); - for(int i = 0; i < argc; i++) - { - switch(arglist[i]) - { - case 'Z': - case 'B': - case 'S': - case 'C': - case 'I': - argarray[i].i = va_arg(args, int); - break; - case 'J': - argarray[i].j = va_arg(args, __int64); - break; - case 'L': - argarray[i].l = va_arg(args, jobject); - break; - case 'D': - argarray[i].d = va_arg(args, double); - break; - case 'F': - argarray[i].f = (float)va_arg(args, double); - break; - } - } - CallStaticVoidMethodA(clazz, methodID, argarray); -} - -void JNIEnv::CallStaticVoidMethod(jclass clazz, jmethodID methodID, ...) -{ - va_list args; - va_start(args, methodID); - CallStaticVoidMethodV(clazz, methodID, args); - va_end(args); -} - -#define STATIC_METHOD_IMPL(Type,type) \ -type JNICALL JNIEnv::CallStatic##Type##MethodV(jclass clazz, jmethodID methodID, va_list args)\ -{\ - char sig[257];\ - int argc = GetMethodArgs(methodID, sig);\ - jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue));\ - for(int i = 0; i < argc; i++)\ - {\ - switch(sig[i])\ - {\ - case 'Z':\ - case 'B':\ - case 'S':\ - case 'C':\ - case 'I':\ - argarray[i].i = va_arg(args, int);\ - break;\ - case 'J':\ - argarray[i].j = va_arg(args, __int64);\ - break;\ - case 'L':\ - argarray[i].l = va_arg(args, jobject);\ - break;\ - case 'D':\ - argarray[i].d = va_arg(args, double);\ - break;\ - case 'F':\ - argarray[i].f = (float)va_arg(args, double);\ - break;\ - }\ - }\ - return CallStatic##Type##MethodA(clazz, methodID, argarray);\ -}\ -type JNIEnv::CallStatic##Type##Method(jclass clazz, jmethodID methodID, ...)\ -{\ - va_list args;\ - va_start(args, methodID);\ - type ret = CallStatic##Type##MethodV(clazz, methodID, args);\ - va_end(args);\ - return ret;\ -} -#define STATIC_METHOD_IMPL_MANAGED(Type,type,cpptype) \ -type JNICALL JNIEnv::CallStatic##Type##MethodA(jclass cls, jmethodID methodID, jvalue* args)\ -{\ - Object* ret = InvokeHelper(0, methodID, args, false);\ - if(ret) return __unbox(ret);\ - return 0;\ -} - -STATIC_METHOD_IMPL(Object,jobject) -STATIC_METHOD_IMPL(Boolean,jboolean) -STATIC_METHOD_IMPL(Byte,jbyte) -STATIC_METHOD_IMPL(Char,jchar) -STATIC_METHOD_IMPL(Short,jshort) -STATIC_METHOD_IMPL(Int,jint) -STATIC_METHOD_IMPL(Long,jlong) -STATIC_METHOD_IMPL(Float,jfloat) -STATIC_METHOD_IMPL(Double,jdouble) -#pragma managed -STATIC_METHOD_IMPL_MANAGED(Boolean,jboolean,bool) -STATIC_METHOD_IMPL_MANAGED(Byte,jbyte,System::SByte) -STATIC_METHOD_IMPL_MANAGED(Char,jchar,wchar_t) -STATIC_METHOD_IMPL_MANAGED(Short,jshort,short) -STATIC_METHOD_IMPL_MANAGED(Int,jint,int) -STATIC_METHOD_IMPL_MANAGED(Long,jlong,__int64) -STATIC_METHOD_IMPL_MANAGED(Float,jfloat,float) -STATIC_METHOD_IMPL_MANAGED(Double,jdouble,double) - -// special case for Object -jobject JNICALL JNIEnv::CallStaticObjectMethodA(jclass cls, jmethodID methodID, jvalue* args) -{ - return MakeLocalRef(InvokeHelper(0, methodID, args, false)); -} - -#pragma unmanaged -jmethodID JNIEnv::GetMethodID(jclass cls, const char *name, const char *sig) -{ - return FindMethodID(cls, name, sig, false); -} - -jfieldID JNICALL JNIEnv::GetFieldID(jclass cls, const char *name, const char *sig) -{ - return FindFieldID(cls, name, sig, false); -} - -jfieldID JNICALL JNIEnv::GetStaticFieldID(jclass cls, const char *name, const char *sig) -{ - return FindFieldID(cls, name, sig, true); -} - -#pragma managed -#define GET_SET_FIELD(Type,type,cpptype) \ -void JNICALL JNIEnv::Set##Type##Field(jobject obj, jfieldID fieldID, type val)\ -{\ - VM::SetFieldValue((IntPtr)fieldID, UnwrapRef(obj), __box((cpptype)val));\ -}\ -type JNICALL JNIEnv::Get##Type##Field(jobject obj, jfieldID fieldID)\ -{\ - return __unbox(VM::GetFieldValue((IntPtr)fieldID, UnwrapRef(obj)));\ -}\ -void JNICALL JNIEnv::SetStatic##Type##Field(jclass clazz, jfieldID fieldID, type val)\ -{\ - /* // TODO consider checking that clazz is the right object */ \ - VM::SetFieldValue((IntPtr)fieldID, 0, __box((cpptype)val));\ -}\ -type JNICALL JNIEnv::GetStatic##Type##Field(jclass clazz, jfieldID fieldID)\ -{\ - /* // TODO consider checking that clazz is the right object */ \ - return __unbox(VM::GetFieldValue((IntPtr)fieldID, 0));\ -} - -#pragma warning (push) -// stop the compiler from wanking about "forcing value to bool 'true' or 'false' (performance warning)" -#pragma warning (disable : 4800) -GET_SET_FIELD(Boolean,jboolean,bool) -#pragma warning (pop) -GET_SET_FIELD(Byte,jbyte,System::SByte) -GET_SET_FIELD(Char,jchar,wchar_t) -GET_SET_FIELD(Short,jshort,short) -GET_SET_FIELD(Int,jint,int) -GET_SET_FIELD(Long,jlong,__int64) -GET_SET_FIELD(Float,jfloat,float) -GET_SET_FIELD(Double,jdouble,double) - -void JNICALL JNIEnv::SetObjectField(jobject obj, jfieldID fieldID, jobject val) -{ - VM::SetFieldValue((IntPtr)fieldID, UnwrapRef(obj), UnwrapRef(val)); -} - -jobject JNICALL JNIEnv::GetObjectField(jobject obj, jfieldID fieldID) -{ - return MakeLocalRef(VM::GetFieldValue((IntPtr)fieldID, UnwrapRef(obj))); -} - -void JNICALL JNIEnv::SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject val) -{ - VM::SetFieldValue((IntPtr)fieldID, 0, UnwrapRef(val)); -} - -jobject JNICALL JNIEnv::GetStaticObjectField(jclass clazz, jfieldID fieldID) -{ - return MakeLocalRef(VM::GetFieldValue((IntPtr)fieldID, 0)); -} - -#pragma unmanaged - -#define METHOD_IMPL(Type,type) \ -type JNIEnv::Call##Type##Method(jobject obj, jmethodID methodID, ...) \ -{\ - va_list args;\ - va_start(args, methodID);\ - type ret = Call##Type##MethodV(obj, methodID, args);\ - va_end(args);\ - return ret;\ -}\ -type JNIEnv::CallNonvirtual##Type##Method(jobject obj, jclass clazz, jmethodID methodID, ...) \ -{\ - va_list args;\ - va_start(args, methodID);\ - type ret = CallNonvirtual##Type##MethodV(obj, clazz, methodID, args);\ - va_end(args);\ - return ret;\ -}\ -type JNICALL JNIEnv::Call##Type##MethodV(jobject obj, jmethodID methodID, va_list args)\ -{\ - char sig[257];\ - int argc = GetMethodArgs(methodID, sig);\ - jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue));\ - for(int i = 0; i < argc; i++)\ - {\ - switch(sig[i])\ - {\ - case 'Z':\ - case 'B':\ - case 'S':\ - case 'C':\ - case 'I':\ - argarray[i].i = va_arg(args, int);\ - break;\ - case 'J':\ - argarray[i].j = va_arg(args, __int64);\ - break;\ - case 'L':\ - argarray[i].l = va_arg(args, jobject);\ - break;\ - case 'D':\ - argarray[i].d = va_arg(args, double);\ - break;\ - case 'F':\ - argarray[i].f = (float)va_arg(args, double);\ - break;\ - }\ - }\ - return Call##Type##MethodA(obj, methodID, argarray);\ -}\ -type JNICALL JNIEnv::CallNonvirtual##Type##MethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args)\ -{\ - char sig[257];\ - int argc = GetMethodArgs(methodID, sig);\ - jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue));\ - for(int i = 0; i < argc; i++)\ - {\ - switch(sig[i])\ - {\ - case 'Z':\ - case 'B':\ - case 'S':\ - case 'C':\ - case 'I':\ - argarray[i].i = va_arg(args, int);\ - break;\ - case 'J':\ - argarray[i].j = va_arg(args, __int64);\ - break;\ - case 'L':\ - argarray[i].l = va_arg(args, jobject);\ - break;\ - case 'D':\ - argarray[i].d = va_arg(args, double);\ - break;\ - case 'F':\ - argarray[i].f = (float)va_arg(args, double);\ - break;\ - }\ - }\ - return CallNonvirtual##Type##MethodA(obj, clazz, methodID, argarray);\ -} - -#define METHOD_IMPL_MANAGED(Type,type,cpptype) \ -type JNICALL JNIEnv::Call##Type##MethodA(jobject obj, jmethodID methodID, jvalue* args)\ -{\ - Object* ret = InvokeHelper(obj, methodID, args, false);\ - if(ret) return __unbox(ret);\ - return 0;\ -}\ -type JNICALL JNIEnv::CallNonvirtual##Type##MethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue* args)\ -{\ - Object* ret = InvokeHelper(obj, methodID, args, true);\ - if(ret) return __unbox(ret);\ - return 0;\ -} - -#pragma unmanaged -METHOD_IMPL(Object,jobject) -METHOD_IMPL(Boolean,jboolean) -METHOD_IMPL(Byte,jbyte) -METHOD_IMPL(Char,jchar) -METHOD_IMPL(Short,jshort) -METHOD_IMPL(Int,jint) -METHOD_IMPL(Long,jlong) -METHOD_IMPL(Float,jfloat) -METHOD_IMPL(Double,jdouble) -#pragma managed -METHOD_IMPL_MANAGED(Boolean,jboolean,bool) -METHOD_IMPL_MANAGED(Byte,jbyte,System::SByte) -METHOD_IMPL_MANAGED(Char,jchar,wchar_t) -METHOD_IMPL_MANAGED(Short,jshort,short) -METHOD_IMPL_MANAGED(Int,jint,int) -METHOD_IMPL_MANAGED(Long,jlong,__int64) -METHOD_IMPL_MANAGED(Float,jfloat,float) -METHOD_IMPL_MANAGED(Double,jdouble,double) - -// special case for Object, because we need to convert the reference to a localref -jobject JNICALL JNIEnv::CallObjectMethodA(jobject obj, jmethodID methodID, jvalue* args) -{ - return MakeLocalRef(InvokeHelper(obj, methodID, args, false)); -} -jobject JNICALL JNIEnv::CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue* args) -{ - return MakeLocalRef(InvokeHelper(obj, methodID, args, true)); -} -#pragma unmanaged - -void JNIEnv::CallVoidMethod(jobject obj, jmethodID methodID, ...) -{ - va_list args; - va_start(args, methodID); - CallVoidMethodV(obj, methodID, args); - va_end(args); -} - -void JNIEnv::CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...) -{ - va_list args; - va_start(args, methodID); - CallNonvirtualVoidMethodV(obj, clazz, methodID, args); - va_end(args); -} - -void JNICALL JNIEnv::CallVoidMethodV(jobject obj, jmethodID methodID, va_list args) -{ - char sig[257]; - int argc = GetMethodArgs(methodID, sig); - jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue)); - for(int i = 0; i < argc; i++) - { - switch(sig[i]) - { - case 'Z': - case 'B': - case 'S': - case 'C': - case 'I': - argarray[i].i = va_arg(args, int); - break; - case 'J': - argarray[i].j = va_arg(args, __int64); - break; - case 'L': - argarray[i].l = va_arg(args, jobject); - break; - case 'D': - argarray[i].d = va_arg(args, double); - break; - case 'F': - argarray[i].f = (float)va_arg(args, double); - break; - } - } - CallVoidMethodA(obj, methodID, argarray); -} - -void JNICALL JNIEnv::CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args) -{ - char sig[257]; - int argc = GetMethodArgs(methodID, sig); - jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue)); - for(int i = 0; i < argc; i++) - { - switch(sig[i]) - { - case 'Z': - case 'B': - case 'S': - case 'C': - case 'I': - argarray[i].i = va_arg(args, int); - break; - case 'J': - argarray[i].j = va_arg(args, __int64); - break; - case 'L': - argarray[i].l = va_arg(args, jobject); - break; - case 'D': - argarray[i].d = va_arg(args, double); - break; - case 'F': - argarray[i].f = (float)va_arg(args, double); - break; - } - } - CallNonvirtualVoidMethodA(obj, clazz, methodID, argarray); -} - -#pragma managed -void JNICALL JNIEnv::CallVoidMethodA(jobject obj, jmethodID methodID, jvalue* args) -{ - InvokeHelper(obj, methodID, args, false); -} - -void JNICALL JNIEnv::CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue* args) -{ - InvokeHelper(obj, methodID, args, true); -} - -jsize JNIEnv::GetStringLength(jstring str) -{ - String* s = __try_cast(UnwrapRef(str)); - return s->Length; -} - -const jchar* JNIEnv::GetStringChars(jstring str, jboolean *isCopy) -{ - String* s = __try_cast(UnwrapRef(str)); - jchar* p = new jchar[s->Length]; - for(int i = 0; i < s->Length; i++) - { - p[i] = s->Chars[i]; - } - if(isCopy) - { - *isCopy = JNI_TRUE; - } - return p; -} - -void JNIEnv::ReleaseStringChars(jstring str, const jchar *chars) -{ - delete[] chars; -} - -jsize JNIEnv::GetArrayLength(jarray array) -{ - Array* ar = __try_cast(UnwrapRef(array)); - return ar->Length; -} - -#define NEW_ARRAY(Type,type,cpptype) \ -type##Array JNIEnv::New##Type##Array(jsize len)\ -{\ - try\ - {\ - return (type##Array)MakeLocalRef(new cpptype __gc[len]);\ - }\ - catch(OutOfMemoryException*)\ - {\ - ThrowNew(FindClass("java/lang/OutOfMemoryError"), "");\ - return 0;\ - }\ -} - -#pragma warning (push) -// stop the compiler from wanking about "forcing value to bool 'true' or 'false' (performance warning)" -#pragma warning (disable : 4800) -NEW_ARRAY(Boolean, jboolean, bool) -#pragma warning (pop) -NEW_ARRAY(Byte, jbyte, System::SByte) -NEW_ARRAY(Char, jchar, wchar_t) -NEW_ARRAY(Short, jshort, short) -NEW_ARRAY(Int, jint, int) -NEW_ARRAY(Long, jlong, __int64) -NEW_ARRAY(Float, jfloat, float) -NEW_ARRAY(Double, jdouble, double) - -jobjectArray JNIEnv::NewObjectArray(jsize len, jclass clazz, jobject init) -{ - try - { - Object* ar __gc[] = new Object* __gc[len]; - Object* o = UnwrapRef(init); - if(o) - { - for(jsize i = 0; i < len; i++) - { - ar[i] = o; - } - } - return (jobjectArray)MakeLocalRef(ar); - } - catch(OutOfMemoryException*) - { - ThrowNew(FindClass("java/lang/OutOfMemoryError"), ""); - return 0; - } -} - -void JNIEnv::SetObjectArrayElement(jobjectArray array, jsize index, jobject val) -{ - Object* ar __gc[] = __try_cast(UnwrapRef(array)); - if(index >= ar->Length) - { - // TODO handle error - assert(false); - } - ar[index] = UnwrapRef(val); -} - -jobject JNIEnv::GetObjectArrayElement(jobjectArray array, jsize index) -{ - Object* ar __gc[] = __try_cast(UnwrapRef(array)); - if(index >= ar->Length) - { - // TODO handle error - assert(false); - } - return MakeLocalRef(ar[index]); -} - -#define GET_SET_ARRAY_REGION(Name, JavaType, ClrType) \ -void JNICALL JNIEnv::Get##Name##ArrayRegion(JavaType##Array array, jsize start, jsize l, JavaType *buf) \ -{ \ - ClrType ar __gc[] = __try_cast(UnwrapRef(array)); \ - for(; l != 0; l--) \ - { \ - *buf++ = ar[start++]; \ - } \ -} \ -void JNICALL JNIEnv::Set##Name##ArrayRegion(JavaType##Array array, jsize start, jsize l, JavaType *buf) \ -{ \ - ClrType ar __gc[] = __try_cast(UnwrapRef(array)); \ - for(; l != 0; l--) \ - { \ - ar[start++] = *buf++; \ - } \ -} - -#pragma warning (push) -// stop the compiler from wanking about "forcing value to bool 'true' or 'false' (performance warning)" -#pragma warning (disable : 4800) -GET_SET_ARRAY_REGION(Boolean, jboolean, bool) -#pragma warning (pop) -GET_SET_ARRAY_REGION(Byte, jbyte, System::SByte) -GET_SET_ARRAY_REGION(Char, jchar, wchar_t) -GET_SET_ARRAY_REGION(Short, jshort, short) -GET_SET_ARRAY_REGION(Int, jint, int) -GET_SET_ARRAY_REGION(Long, jlong, __int64) -GET_SET_ARRAY_REGION(Float, jfloat, float) -GET_SET_ARRAY_REGION(Double, jdouble, double) - -#define GET_SET_ARRAY_ELEMENTS(Type,type,cpptype) \ -type* JNIEnv::Get##Type##ArrayElements(type##Array array, jboolean *isCopy)\ -{\ - cpptype ar __gc[] = __try_cast(UnwrapRef(array));\ - type* p = new type[ar->Length];\ - if(ar->Length)\ - {\ - cpptype __pin* par = &ar[0];\ - memcpy(p, par, ar->Length * sizeof(cpptype));\ - }\ - if(isCopy)\ - {\ - *isCopy = JNI_TRUE;\ - }\ - return p;\ -}\ -void JNIEnv::Release##Type##ArrayElements(type##Array array, type *elems, jint mode)\ -{\ - if(mode == 0 || mode == JNI_COMMIT)\ - {\ - cpptype ar __gc[] = __try_cast(UnwrapRef(array));\ - if(ar->Length)\ - {\ - cpptype __pin* p = &ar[0];\ - memcpy(p, elems, ar->Length * sizeof(cpptype));\ - }\ - }\ - if(mode == 0 || mode == JNI_ABORT)\ - {\ - delete[] elems;\ - }\ -} - -#pragma warning (push) -// stop the compiler from wanking about "forcing value to bool 'true' or 'false' (performance warning)" -#pragma warning (disable : 4800) -GET_SET_ARRAY_ELEMENTS(Boolean,jboolean,bool) -#pragma warning (pop) -GET_SET_ARRAY_ELEMENTS(Byte,jbyte,System::SByte) -GET_SET_ARRAY_ELEMENTS(Char,jchar,wchar_t) -GET_SET_ARRAY_ELEMENTS(Short,jshort,short) -GET_SET_ARRAY_ELEMENTS(Int,jint,int) -GET_SET_ARRAY_ELEMENTS(Long,jlong,__int64) -GET_SET_ARRAY_ELEMENTS(Float,jfloat,float) -GET_SET_ARRAY_ELEMENTS(Double,jdouble,double) - -#pragma unmanaged -jobject JNICALL JNIEnv::NewObject(jclass clazz, jmethodID methodID, ...) -{ - va_list args; - va_start(args, methodID); - jobject o = NewObjectV(clazz, methodID, args); - va_end(args); - return o; -} - -jobject JNICALL JNIEnv::NewObjectV(jclass clazz, jmethodID methodID, va_list args) -{ - char sig[257]; - int argc = GetMethodArgs(methodID, sig); - jvalue* argarray = (jvalue*)_alloca(argc * sizeof(jvalue)); - for(int i = 0; i < argc; i++) - { - switch(sig[i]) - { - case 'Z': - case 'B': - case 'S': - case 'C': - case 'I': - argarray[i].i = va_arg(args, int); - break; - case 'J': - argarray[i].j = va_arg(args, __int64); - break; - case 'L': - argarray[i].l = va_arg(args, jobject); - break; - case 'D': - argarray[i].d = va_arg(args, double); - break; - case 'F': - argarray[i].f = (float)va_arg(args, double); - break; - } - } - return NewObjectA(clazz, methodID, argarray); -} - -#pragma managed -jobject JNICALL JNIEnv::NewObjectA(jclass clazz, jmethodID methodID, jvalue *args) -{ - return MakeLocalRef(InvokeHelper(0, methodID, args, false)); -} - -jclass JNICALL JNIEnv::GetObjectClass(jobject obj) -{ - if(obj) - { - return (jclass)MakeLocalRef(VM::GetObjectClass(UnwrapRef(obj))); - } - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - return 0; -} - -jboolean JNICALL JNIEnv::IsInstanceOf(jobject obj, jclass clazz) -{ - if(clazz) - { - return obj && VM::IsInstanceOf(UnwrapRef(obj), UnwrapRef(clazz)); - } - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - return JNI_FALSE; -} - -jboolean JNICALL JNIEnv::IsAssignableFrom(jclass sub, jclass sup) -{ - if(sub && sup) - { - return VM::IsAssignableFrom(UnwrapRef(sub), UnwrapRef(sup)); - } - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - return JNI_FALSE; -} - -jclass JNICALL JNIEnv::GetSuperclass(jclass sub) -{ - if(sub) - { - return (jclass)MakeLocalRef(VM::GetSuperclass(UnwrapRef(sub))); - } - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - return 0; -} - -jobject JNICALL JNIEnv::NewLocalRef(jobject ref) -{ - return MakeLocalRef(UnwrapRef(ref)); -} - -jobject JNICALL JNIEnv::NewGlobalRef(jobject obj) -{ - //if(!obj) - //{ - // return 0; - //} - //// TODO search for an empty slot before adding it to the end... - //return (jobject)-(GlobalRefs::globalRefs->Add(UnwrapRef(obj)) + 1); - throw new InvalidOperationException(); -} - -void JNICALL JNIEnv::DeleteGlobalRef(jobject gref) -{ - //int i = int(gref); - //if(i < 0) - //{ - // GlobalRefs::globalRefs->Item[(-i) - 1] = 0; - // return; - //} - //if(i > 0) - //{ - // DebugBreak(); - //} - throw new InvalidOperationException(); -} - -void JNICALL JNIEnv::DeleteLocalRef(jobject obj) -{ - //int i = (int)obj; - //if(i > 0) - //{ - // localRefs[i >> LOCAL_REF_SHIFT].DeleteLocalRef(i & LOCAL_REF_MASK); - // return; - //} - //if(i < 0) - //{ - // Console::WriteLine("bogus localref in DeleteLocalRef"); - // DebugBreak(); - //} - throw new InvalidOperationException(); -} - -jboolean JNICALL JNIEnv::IsSameObject(jobject obj1, jobject obj2) -{ - return UnwrapRef(obj1) == UnwrapRef(obj2); -} - -jint JNICALL JNIEnv::MonitorEnter(jobject obj) -{ - Object* o = UnwrapRef(obj); - if(o) - { - try - { - System::Threading::Monitor::Enter(o); - return JNI_OK; - } - catch(System::Threading::ThreadInterruptedException*) - { - ThrowNew(FindClass("java/lang/InterruptedException"), ""); - return JNI_ERR; - } - } - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - return JNI_ERR; -} - -jint JNICALL JNIEnv::MonitorExit(jobject obj) -{ - Object* o = UnwrapRef(obj); - if(o) - { - try - { - System::Threading::Monitor::Exit(o); - return JNI_OK; - } - catch(System::Threading::SynchronizationLockException*) - { - ThrowNew(FindClass("java/lang/IllegalMonitorStateException"), ""); - return JNI_ERR; - } - } - ThrowNew(FindClass("java/lang/NullPointerException"), ""); - return JNI_ERR; -} - -#pragma unmanaged -jint JNICALL JNIEnv::GetJavaVM(JavaVM **vm) -{ - static JavaVM theVM; - *vm = &theVM; - return 0; -} - -#pragma managed -static jsize GetPrimitiveArrayElementSize(Array* ar) -{ - Type* type = ar->GetType()->GetElementType(); - if(type == __typeof(System::SByte) || type == __typeof(System::Boolean)) - { - return 1; - } - else if(type == __typeof(System::Int16) || type == __typeof(System::Char)) - { - return 2; - } - else if(type == __typeof(System::Int32) || type == __typeof(System::Single)) - { - return 4; - } - else if(type == __typeof(System::Int64) || type == __typeof(System::Double)) - { - return 8; - } - else - { - assert(false); - return 1; - } -} - -void* JNICALL JNIEnv::GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) -{ - Array* ar = __try_cast(UnwrapRef(array)); - int len = ar->Length * GetPrimitiveArrayElementSize(ar); - GCHandle h = GCHandle::Alloc(ar, GCHandleType::Pinned); - try - { - char* buf = new char[len]; - if(!buf) - { - // TODO throw OutOfMemoryError - assert(false); - return 0; - } - memcpy(buf, (void*)h.AddrOfPinnedObject(), len); - if(isCopy) - { - *isCopy = JNI_TRUE; - } - return buf; - } - __finally - { - h.Free(); - } -} - -void JNICALL JNIEnv::ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) -{ - if(mode == 0 || mode == JNI_COMMIT) - { - Array* ar = __try_cast(UnwrapRef(array)); - int len = ar->Length * GetPrimitiveArrayElementSize(ar); - GCHandle h = GCHandle::Alloc(ar, GCHandleType::Pinned); - try - { - memcpy((void*)h.AddrOfPinnedObject(), carray, len); - } - __finally - { - h.Free(); - } - } - if(mode == 0 || mode == JNI_ABORT) - { - delete[] (char*)carray; - } -} - -jint JNICALL JNIEnv::GetVersion() -{ - // We implement (part of) JNI version 1.4 - return JNI_VERSION_1_4; -} - -jboolean JNICALL JNIEnv::ExceptionCheck() -{ - //return pendingException != 0; - throw new InvalidOperationException(); -} - -jmethodID JNICALL JNIEnv::FromReflectedMethod(jobject method) -{ - return (jmethodID)(void*)VM::MethodToCookie(UnwrapRef(method)); -} - -jfieldID JNICALL JNIEnv::FromReflectedField(jobject field) -{ - return (jfieldID)(void*)VM::FieldToCookie(UnwrapRef(field)); -} - -jobject JNICALL JNIEnv::ToReflectedMethod(jclass clazz, jmethodID methodID) -{ - return MakeLocalRef(VM::CookieToMethod(methodID)); -} - -jobject JNICALL JNIEnv::ToReflectedField(jclass clazz, jfieldID fieldID) -{ - return MakeLocalRef(VM::CookieToField(fieldID)); -} - -void JNICALL JNIEnv::FatalError(const char *msg) -{ - VM::FatalError(StringFromUTF8(msg)); -} - -jclass JNICALL JNIEnv::DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len) -{ - System::Byte array __gc[] = new System::Byte __gc[len]; - Marshal::Copy((void*)buf, array, 0, len); - return (jclass)MakeLocalRef(VM::DefineClass(StringFromUTF8(name), UnwrapRef(loader), array)); -} - -void JavaVM::reserved0() -{ - VM::FatalError("JavaVM::reserved0"); -} - -void JavaVM::reserved1() -{ - VM::FatalError("JavaVM::reserved1"); -} - -void JavaVM::reserved2() -{ - VM::FatalError("JavaVM::reserved2"); -} - -jint JavaVM::DestroyJavaVM() -{ - return JNI_ERR; -} - -#pragma unmanaged -static void AttachCurrentThread_NotImplemented() -{ - assert(false); - _asm int 3 -} - -#pragma managed -jint JavaVM::AttachCurrentThread(void **penv, void *args) -{ - // TODO do we need a new local ref frame? - // TODO for now we only support attaching to an existing thread - // TODO support args (JavaVMAttachArgs) - JNIEnv* p = VM::GetEnv(); - if(p) - { - *penv = p; - return JNI_OK; - } - AttachCurrentThread_NotImplemented(); - return JNI_ERR; -} -#pragma unmanaged - -jint JavaVM::DetachCurrentThread() -{ - assert(false); - _asm int 3 -} - -#pragma managed -jint JavaVM::GetEnv(void **penv, jint version) -{ - // TODO we should check the version - JNIEnv* p = VM::GetEnv(); - if(p) - { - *penv = p; - return JNI_OK; - } - return JNI_EDETACHED; -} - -jint JNICALL JNIEnv::RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods) -{ - Object* pclass = UnwrapRef(clazz); - for(int i = 0; i < nMethods; i++) - { - if(!VM::SetNativeMethodPointer(pclass, StringFromUTF8(methods[i].name), StringFromUTF8(methods[i].signature), methods[i].fnPtr)) - { - // TODO set the exception message - ThrowNew(FindClass("java/lang/NoSuchMethodError"), ""); - return JNI_ERR; - } - } - return JNI_OK; -} - -jint JNICALL JNIEnv::UnregisterNatives(jclass clazz) -{ - VM::ResetNativeMethodPointers(UnwrapRef(clazz)); - return JNI_OK; -} - -#pragma unmanaged - -jint JavaVM::AttachCurrentThreadAsDaemon(void **penv, void *args) -{ - assert(false); - _asm int 3 -} - -//////////////////////////////////////////////////////////////////////////// -#pragma warning (disable : 4035) - -jint JNICALL JNIEnv::PushLocalFrame(jint capacity) { assert(false); _asm int 3} -jobject JNICALL JNIEnv::PopLocalFrame(jobject result) { assert(false); _asm int 3} -jint JNICALL JNIEnv::EnsureLocalCapacity(jint capacity) { assert(false); _asm int 3} - -jweak JNICALL JNIEnv::NewWeakGlobalRef(jobject obj) { assert(false); _asm int 3} -void JNICALL JNIEnv::DeleteWeakGlobalRef(jweak ref) { assert(false); _asm int 3} - -jobject JNICALL JNIEnv::NewDirectByteBuffer(void* address, jlong capacity) { assert(false); _asm int 3} -void* JNICALL JNIEnv::GetDirectBufferAddress(jobject buf) { assert(false); _asm int 3} -jlong JNICALL JNIEnv::GetDirectBufferCapacity(jobject buf) { assert(false); _asm int 3} diff --git a/jni/clr-win32/jnienv.h b/jni/clr-win32/jnienv.h deleted file mode 100644 index 7978f47e..00000000 --- a/jni/clr-win32/jnienv.h +++ /dev/null @@ -1,595 +0,0 @@ -/* - Copyright (C) 2002, 2003, 2004 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -#include - -using namespace System; -using namespace System::Runtime::InteropServices; - -#pragma unmanaged - -#define JNI_TRUE 1 -#define JNI_FALSE 0 - -typedef struct { - char *name; - char *signature; - void *fnPtr; -} JNINativeMethod; - -#define JNI_VERSION_1_1 0x00010001 -#define JNI_VERSION_1_2 0x00010002 -#define JNI_VERSION_1_4 0x00010004 - -/* - * possible return values for JNI functions. - */ - -#define JNI_OK 0 -#define JNI_ERR (-1) -#define JNI_EDETACHED (-2) -#define JNI_EVERSION (-3) -/* - * used in ReleaseScalarArrayElements - */ - -#define JNI_COMMIT 1 -#define JNI_ABORT 2 - -class JavaVM; - -#define JNIEXPORT -#define JNICALL __stdcall - -#ifndef _HELPERTYPES_ -#define _HELPERTYPES_ -class _jobject {}; -class _jclass : public _jobject {}; -class _jstring : public _jobject {}; -class _jthrowable : public _jobject {}; -class Array$ : public _jobject {}; -class ObjectArray$ : public Array$ {}; -class BooleanArray$ : public Array$ {}; -class ByteArray$ : public Array$ {}; -class CharArray$ : public Array$ {}; -class ShortArray$ : public Array$ {}; -class IntArray$ : public Array$ {}; -class LongArray$ : public Array$ {}; -class FloatArray$ : public Array$ {}; -class DoubleArray$ : public Array$ {}; -#endif //_HELPERTYPES_ - -typedef class _jclass* jclass; -typedef class _jobject* jobject; -typedef jobject jweak; -typedef class _jstring* jstring; -typedef class _jthrowable* jthrowable; -typedef class Array$* jarray; -typedef class ObjectArray$* jobjectArray; -typedef class BooleanArray$* jbooleanArray; -typedef class ByteArray$* jbyteArray; -typedef class CharArray$* jcharArray; -typedef class ShortArray$* jshortArray; -typedef class IntArray$* jintArray; -typedef class LongArray$* jlongArray; -typedef class FloatArray$* jfloatArray; -typedef class DoubleArray$* jdoubleArray; -typedef struct _jmethodID* jmethodID; -typedef struct _jfieldID* jfieldID; - -struct _jmethodID -{ -}; - -struct _jfieldID -{ -}; - -/* - * JNI Types - */ - -typedef unsigned char jboolean; -typedef unsigned short jchar; -typedef short jshort; -typedef float jfloat; -typedef double jdouble; - -typedef long jint; -typedef __int64 jlong; -typedef signed char jbyte; - -typedef jint jsize; - -typedef union jvalue { - jboolean z; - jbyte b; - jchar c; - jshort s; - jint i; - jlong j; - jfloat f; - jdouble d; - jobject l; -} jvalue; - -//public __value class LocalRefStruct; - -#pragma managed - -//[StructLayout(LayoutKind::Sequential)] -//__value struct LocalRefCache -//{ -// Object* loc1; -// Object* loc2; -// Object* loc3; -// Object* loc4; -// Object* loc5; -// Object* loc6; -// Object* loc7; -// Object* loc8; -// Object* loc9; -// Object* loc10; -//}; -// -//#define STATIC_LIST_SIZE 10 -//#define BUCKET_SIZE (1 << LOCAL_REF_SHIFT) -//#define LOCAL_REF_SHIFT 10 -//#define LOCAL_REF_MASK (BUCKET_SIZE - 1) -// -//__value struct LocalRefListEntry -//{ -// Object* __nogc* static_list; -// Object* dynamic_list __gc[]; -// -// int MakeLocalRef(Object* o) -// { -// Object** p = static_list; -// for(int i = 0; i < STATIC_LIST_SIZE; i++) -// { -// if(p[i] == 0) -// { -// p[i] = o; -// return i; -// } -// } -// if(!dynamic_list) -// { -// dynamic_list = new Object* __gc[32 - STATIC_LIST_SIZE]; -// } -// for(int i = 0; i < dynamic_list->Length; i++) -// { -// if(dynamic_list[i] == 0) -// { -// dynamic_list[i] = o; -// return i + STATIC_LIST_SIZE; -// } -// } -// int newsize = (dynamic_list->Length + STATIC_LIST_SIZE) * 2 - STATIC_LIST_SIZE; -// if(newsize > BUCKET_SIZE) -// { -// return -1; -// } -// Object* tmp __gc[] = dynamic_list; -// dynamic_list = new Object* __gc[newsize]; -// Array::Copy(tmp, 0, dynamic_list, 0, tmp->Length); -// dynamic_list[tmp->Length] = o; -// return tmp->Length + STATIC_LIST_SIZE; -// } -// -// void DeleteLocalRef(unsigned int i) -// { -// if(i < STATIC_LIST_SIZE) -// { -// static_list[i] = 0; -// } -// else -// { -// dynamic_list[i - STATIC_LIST_SIZE] = 0; -// } -// } -// -// Object* UnwrapLocalRef(unsigned int i) -// { -// if(i < STATIC_LIST_SIZE) -// { -// return static_list[i]; -// } -// else -// { -// return dynamic_list[i - STATIC_LIST_SIZE]; -// } -// } -//}; -// -//__gc struct GlobalRefs -//{ -// static System::Collections::ArrayList* globalRefs = new System::Collections::ArrayList(); -//}; -// -//class JNIEnv; -// -//public __value class LocalRefStruct -//{ -// JNIEnv* pJNIEnv; -// LocalRefStruct __nogc* pPrevLocalRefCache; -// LocalRefCache fastlocalrefs; -// LocalRefListEntry localRefs __gc[]; -// -//public: -// static JNIEnv* GetEnv(); -// -// IntPtr Enter(); -// void Leave(); -// -// IntPtr MakeLocalRef(Object* o); -// Object* UnwrapLocalRef(IntPtr p); -//}; - -class JNIEnv -{ -public: - jobject MakeLocalRef(System::Object* obj); - //{ - // return (jobject)(void*)pActiveLocalRefCache->MakeLocalRef(obj); - //} - - Object* UnwrapRef(jobject o); - //{ - // int i = (int)o; - // if(i > 0) - // { - // return pActiveLocalRefCache->UnwrapLocalRef((void*)o); - // } - // if(i < 0) - // { - // return GlobalRefs::globalRefs->Item[(-i) - 1]; - // } - // return 0; - //} - - jmethodID FindMethodID(jclass cls, const char* name, const char* sig, bool isstatic); - Object* InvokeHelper(jobject object, jmethodID methodID, jvalue* args, bool nonVirtual); - jfieldID FindFieldID(jclass cls, const char* name, const char* sig, bool isstatic); - - //int localRefSlot; - //LocalRefStruct __nogc* pActiveLocalRefCache; - //gcroot localRefs; - //jthrowable pendingException; - - JNIEnv(); - ~JNIEnv(); - - virtual void JNICALL reserved0(); - virtual void JNICALL reserved1(); - virtual void JNICALL reserved2(); - virtual void JNICALL reserved3(); - - virtual jint JNICALL GetVersion(); - - virtual jclass JNICALL DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len); - virtual jclass JNICALL FindClass(const char *name); - - virtual jmethodID JNICALL FromReflectedMethod(jobject method); - virtual jfieldID JNICALL FromReflectedField(jobject field); - virtual jobject JNICALL ToReflectedMethod(jclass clazz, jmethodID methodID); - - virtual jclass JNICALL GetSuperclass(jclass sub); - virtual jboolean JNICALL IsAssignableFrom(jclass sub, jclass sup); - - virtual jobject JNICALL ToReflectedField(jclass clazz, jfieldID fieldID); - - virtual jint JNICALL Throw(jthrowable obj); - virtual jint JNICALL ThrowNew(jclass clazz, const char *msg); - virtual jthrowable JNICALL ExceptionOccurred(); - virtual void JNICALL ExceptionDescribe(); - virtual void JNICALL ExceptionClear(); - virtual void JNICALL FatalError(const char *msg); - - virtual jint JNICALL PushLocalFrame(jint capacity); - virtual jobject JNICALL PopLocalFrame(jobject result); - - virtual jobject JNICALL NewGlobalRef(jobject lobj); - virtual void JNICALL DeleteGlobalRef(jobject gref); - virtual void JNICALL DeleteLocalRef(jobject obj); - virtual jboolean JNICALL IsSameObject(jobject obj1, jobject obj2); - - virtual jobject JNICALL NewLocalRef(jobject ref); - virtual jint JNICALL EnsureLocalCapacity(jint capacity); - - virtual jobject JNICALL AllocObject(jclass clazz); - virtual jobject JNICALL NewObject(jclass clazz, jmethodID methodID, ...); - virtual jobject JNICALL NewObjectV(jclass clazz, jmethodID methodID, va_list args); - virtual jobject JNICALL NewObjectA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual jclass JNICALL GetObjectClass(jobject obj); - virtual jboolean JNICALL IsInstanceOf(jobject obj, jclass clazz); - - virtual jmethodID JNICALL GetMethodID(jclass clazz, const char *name, const char *sig); - - virtual jobject JNICALL CallObjectMethod(jobject obj, jmethodID methodID, ...); - virtual jobject JNICALL CallObjectMethodV(jobject obj, jmethodID methodID, va_list args); - virtual jobject JNICALL CallObjectMethodA(jobject obj, jmethodID methodID, jvalue * args); - - virtual jboolean JNICALL CallBooleanMethod(jobject obj, jmethodID methodID, ...); - virtual jboolean JNICALL CallBooleanMethodV(jobject obj, jmethodID methodID, va_list args); - virtual jboolean JNICALL CallBooleanMethodA(jobject obj, jmethodID methodID, jvalue * args); - - virtual jbyte JNICALL CallByteMethod(jobject obj, jmethodID methodID, ...); - virtual jbyte JNICALL CallByteMethodV(jobject obj, jmethodID methodID, va_list args); - virtual jbyte JNICALL CallByteMethodA(jobject obj, jmethodID methodID, jvalue *args); - - virtual jchar JNICALL CallCharMethod(jobject obj, jmethodID methodID, ...); - virtual jchar JNICALL CallCharMethodV(jobject obj, jmethodID methodID, va_list args); - virtual jchar JNICALL CallCharMethodA(jobject obj, jmethodID methodID, jvalue *args); - - virtual jshort JNICALL CallShortMethod(jobject obj, jmethodID methodID, ...); - virtual jshort JNICALL CallShortMethodV(jobject obj, jmethodID methodID, va_list args); - virtual jshort JNICALL CallShortMethodA(jobject obj, jmethodID methodID, jvalue *args); - - virtual jint JNICALL CallIntMethod(jobject obj, jmethodID methodID, ...); - virtual jint JNICALL CallIntMethodV(jobject obj, jmethodID methodID, va_list args); - virtual jint JNICALL CallIntMethodA(jobject obj, jmethodID methodID, jvalue *args); - - virtual jlong JNICALL CallLongMethod(jobject obj, jmethodID methodID, ...); - virtual jlong JNICALL CallLongMethodV(jobject obj, jmethodID methodID, va_list args); - virtual jlong JNICALL CallLongMethodA(jobject obj, jmethodID methodID, jvalue *args); - - virtual jfloat JNICALL CallFloatMethod(jobject obj, jmethodID methodID, ...); - virtual jfloat JNICALL CallFloatMethodV(jobject obj, jmethodID methodID, va_list args); - virtual jfloat JNICALL CallFloatMethodA(jobject obj, jmethodID methodID, jvalue *args); - - virtual jdouble JNICALL CallDoubleMethod(jobject obj, jmethodID methodID, ...); - virtual jdouble JNICALL CallDoubleMethodV(jobject obj, jmethodID methodID, va_list args); - virtual jdouble JNICALL CallDoubleMethodA(jobject obj, jmethodID methodID, jvalue *args); - - virtual void JNICALL CallVoidMethod(jobject obj, jmethodID methodID, ...); - virtual void JNICALL CallVoidMethodV(jobject obj, jmethodID methodID, va_list args); - virtual void JNICALL CallVoidMethodA(jobject obj, jmethodID methodID, jvalue * args); - - virtual jobject JNICALL CallNonvirtualObjectMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual jobject JNICALL CallNonvirtualObjectMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual jobject JNICALL CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); - - virtual jboolean JNICALL CallNonvirtualBooleanMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual jboolean JNICALL CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual jboolean JNICALL CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); - - virtual jbyte JNICALL CallNonvirtualByteMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual jbyte JNICALL CallNonvirtualByteMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual jbyte JNICALL CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); - - virtual jchar JNICALL CallNonvirtualCharMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual jchar JNICALL CallNonvirtualCharMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual jchar JNICALL CallNonvirtualCharMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); - - virtual jshort JNICALL CallNonvirtualShortMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual jshort JNICALL CallNonvirtualShortMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual jshort JNICALL CallNonvirtualShortMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); - - virtual jint JNICALL CallNonvirtualIntMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual jint JNICALL CallNonvirtualIntMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual jint JNICALL CallNonvirtualIntMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); - - virtual jlong JNICALL CallNonvirtualLongMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual jlong JNICALL CallNonvirtualLongMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual jlong JNICALL CallNonvirtualLongMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); - - virtual jfloat JNICALL CallNonvirtualFloatMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual jfloat JNICALL CallNonvirtualFloatMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual jfloat JNICALL CallNonvirtualFloatMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); - - virtual jdouble JNICALL CallNonvirtualDoubleMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual jdouble JNICALL CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual jdouble JNICALL CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); - - virtual void JNICALL CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...); - virtual void JNICALL CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); - virtual void JNICALL CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); - - virtual jfieldID JNICALL GetFieldID(jclass clazz, const char *name, const char *sig); - - virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID); - virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID); - virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID); - virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID); - virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID); - virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID); - virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID); - virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID); - virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID); - - virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val); - virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val); - virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val); - virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val); - virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val); - virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val); - virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val); - virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val); - virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val); - - virtual jmethodID JNICALL GetStaticMethodID(jclass clazz, const char *name, const char *sig); - - virtual jobject JNICALL CallStaticObjectMethod(jclass clazz, jmethodID methodID, ...); - virtual jobject JNICALL CallStaticObjectMethodV(jclass clazz, jmethodID methodID, va_list args); - virtual jobject JNICALL CallStaticObjectMethodA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual jboolean JNICALL CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...); - virtual jboolean JNICALL CallStaticBooleanMethodV(jclass clazz, jmethodID methodID, va_list args); - virtual jboolean JNICALL CallStaticBooleanMethodA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual jbyte JNICALL CallStaticByteMethod(jclass clazz, jmethodID methodID, ...); - virtual jbyte JNICALL CallStaticByteMethodV(jclass clazz, jmethodID methodID, va_list args); - virtual jbyte JNICALL CallStaticByteMethodA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual jchar JNICALL CallStaticCharMethod(jclass clazz, jmethodID methodID, ...); - virtual jchar JNICALL CallStaticCharMethodV(jclass clazz, jmethodID methodID, va_list args); - virtual jchar JNICALL CallStaticCharMethodA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual jshort JNICALL CallStaticShortMethod(jclass clazz, jmethodID methodID, ...); - virtual jshort JNICALL CallStaticShortMethodV(jclass clazz, jmethodID methodID, va_list args); - virtual jshort JNICALL CallStaticShortMethodA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual jint JNICALL CallStaticIntMethod(jclass clazz, jmethodID methodID, ...); - virtual jint JNICALL CallStaticIntMethodV(jclass clazz, jmethodID methodID, va_list args); - virtual jint JNICALL CallStaticIntMethodA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual jlong JNICALL CallStaticLongMethod(jclass clazz, jmethodID methodID, ...); - virtual jlong JNICALL CallStaticLongMethodV(jclass clazz, jmethodID methodID, va_list args); - virtual jlong JNICALL CallStaticLongMethodA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual jfloat JNICALL CallStaticFloatMethod(jclass clazz, jmethodID methodID, ...); - virtual jfloat JNICALL CallStaticFloatMethodV(jclass clazz, jmethodID methodID, va_list args); - virtual jfloat JNICALL CallStaticFloatMethodA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual jdouble JNICALL CallStaticDoubleMethod(jclass clazz, jmethodID methodID, ...); - virtual jdouble JNICALL CallStaticDoubleMethodV(jclass clazz, jmethodID methodID, va_list args); - virtual jdouble JNICALL CallStaticDoubleMethodA(jclass clazz, jmethodID methodID, jvalue *args); - - virtual void JNICALL CallStaticVoidMethod(jclass cls, jmethodID methodID, ...); - virtual void JNICALL CallStaticVoidMethodV(jclass cls, jmethodID methodID, va_list args); - virtual void JNICALL CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue * args); - - virtual jfieldID JNICALL GetStaticFieldID(jclass clazz, const char *name, const char *sig); - virtual jobject JNICALL GetStaticObjectField(jclass clazz, jfieldID fieldID); - virtual jboolean JNICALL GetStaticBooleanField(jclass clazz, jfieldID fieldID); - virtual jbyte JNICALL GetStaticByteField(jclass clazz, jfieldID fieldID); - virtual jchar JNICALL GetStaticCharField(jclass clazz, jfieldID fieldID); - virtual jshort JNICALL GetStaticShortField(jclass clazz, jfieldID fieldID); - virtual jint JNICALL GetStaticIntField(jclass clazz, jfieldID fieldID); - virtual jlong JNICALL GetStaticLongField(jclass clazz, jfieldID fieldID); - virtual jfloat JNICALL GetStaticFloatField(jclass clazz, jfieldID fieldID); - virtual jdouble JNICALL GetStaticDoubleField(jclass clazz, jfieldID fieldID); - - virtual void JNICALL SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject value); - virtual void JNICALL SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean value); - virtual void JNICALL SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte value); - virtual void JNICALL SetStaticCharField(jclass clazz, jfieldID fieldID, jchar value); - virtual void JNICALL SetStaticShortField(jclass clazz, jfieldID fieldID, jshort value); - virtual void JNICALL SetStaticIntField(jclass clazz, jfieldID fieldID, jint value); - virtual void JNICALL SetStaticLongField(jclass clazz, jfieldID fieldID, jlong value); - virtual void JNICALL SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat value); - virtual void JNICALL SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble value); - - virtual jstring JNICALL NewString(const jchar *unicode, jsize len); - virtual jsize JNICALL GetStringLength(jstring str); - virtual const jchar *JNICALL GetStringChars(jstring str, jboolean *isCopy); - virtual void JNICALL ReleaseStringChars(jstring str, const jchar *chars); - - virtual jstring JNICALL NewStringUTF(const char *utf); - virtual jsize JNICALL GetStringUTFLength(jstring str); - virtual const char* JNICALL GetStringUTFChars(jstring str, jboolean *isCopy); - virtual void JNICALL ReleaseStringUTFChars(jstring str, const char* chars); - - virtual jsize JNICALL GetArrayLength(jarray array); - - virtual jobjectArray JNICALL NewObjectArray(jsize len, jclass clazz, jobject init); - virtual jobject JNICALL GetObjectArrayElement(jobjectArray array, jsize index); - virtual void JNICALL SetObjectArrayElement(jobjectArray array, jsize index, jobject val); - - virtual jbooleanArray JNICALL NewBooleanArray(jsize len); - virtual jbyteArray JNICALL NewByteArray(jsize len); - virtual jcharArray JNICALL NewCharArray(jsize len); - virtual jshortArray JNICALL NewShortArray(jsize len); - virtual jintArray JNICALL NewIntArray(jsize len); - virtual jlongArray JNICALL NewLongArray(jsize len); - virtual jfloatArray JNICALL NewFloatArray(jsize len); - virtual jdoubleArray JNICALL NewDoubleArray(jsize len); - - virtual jboolean * JNICALL GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy); - virtual jbyte * JNICALL GetByteArrayElements(jbyteArray array, jboolean *isCopy); - virtual jchar * JNICALL GetCharArrayElements(jcharArray array, jboolean *isCopy); - virtual jshort * JNICALL GetShortArrayElements(jshortArray array, jboolean *isCopy); - virtual jint * JNICALL GetIntArrayElements(jintArray array, jboolean *isCopy); - virtual jlong * JNICALL GetLongArrayElements(jlongArray array, jboolean *isCopy); - virtual jfloat * JNICALL GetFloatArrayElements(jfloatArray array, jboolean *isCopy); - virtual jdouble * JNICALL GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy); - - virtual void JNICALL ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems, jint mode); - virtual void JNICALL ReleaseByteArrayElements(jbyteArray array, jbyte *elems, jint mode); - virtual void JNICALL ReleaseCharArrayElements(jcharArray array, jchar *elems, jint mode); - virtual void JNICALL ReleaseShortArrayElements(jshortArray array, jshort *elems, jint mode); - virtual void JNICALL ReleaseIntArrayElements(jintArray array, jint *elems, jint mode); - virtual void JNICALL ReleaseLongArrayElements(jlongArray array, jlong *elems, jint mode); - virtual void JNICALL ReleaseFloatArrayElements(jfloatArray array, jfloat *elems, jint mode); - virtual void JNICALL ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems, jint mode); - - virtual void JNICALL GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); - virtual void JNICALL GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); - virtual void JNICALL GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); - virtual void JNICALL GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); - virtual void JNICALL GetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); - virtual void JNICALL GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); - virtual void JNICALL GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); - virtual void JNICALL GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); - - virtual void JNICALL SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); - virtual void JNICALL SetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); - virtual void JNICALL SetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); - virtual void JNICALL SetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); - virtual void JNICALL SetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); - virtual void JNICALL SetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); - virtual void JNICALL SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); - virtual void JNICALL SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); - - virtual jint JNICALL RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods); - virtual jint JNICALL UnregisterNatives(jclass clazz); - - virtual jint JNICALL MonitorEnter(jobject obj); - virtual jint JNICALL MonitorExit(jobject obj); - - virtual jint JNICALL GetJavaVM(JavaVM **vm); - - virtual void JNICALL GetStringRegion(jstring str, jsize start, jsize len, jchar *buf); - virtual void JNICALL GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf); - - virtual void* JNICALL GetPrimitiveArrayCritical(jarray array, jboolean *isCopy); - virtual void JNICALL ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode); - - virtual const jchar* JNICALL GetStringCritical(jstring string, jboolean *isCopy); - virtual void JNICALL ReleaseStringCritical(jstring string, const jchar *cstring); - - virtual jweak JNICALL NewWeakGlobalRef(jobject obj); - virtual void JNICALL DeleteWeakGlobalRef(jweak ref); - - virtual jboolean JNICALL ExceptionCheck(); - - virtual jobject JNICALL NewDirectByteBuffer(void* address, jlong capacity); - virtual void* JNICALL GetDirectBufferAddress(jobject buf); - virtual jlong JNICALL GetDirectBufferCapacity(jobject buf); -}; - -class JavaVM -{ -public: - virtual void JNICALL reserved0(); - virtual void JNICALL reserved1(); - virtual void JNICALL reserved2(); - virtual jint JNICALL DestroyJavaVM(); - virtual jint JNICALL AttachCurrentThread(void **penv, void *args); - virtual jint JNICALL DetachCurrentThread(); - virtual jint JNICALL GetEnv(void **penv, jint version); - virtual jint JNICALL AttachCurrentThreadAsDaemon(void **penv, void *args); -}; diff --git a/jni/mono/JNI.cs b/jni/mono/JNI.cs deleted file mode 100644 index 4e68c9fb..00000000 --- a/jni/mono/JNI.cs +++ /dev/null @@ -1,567 +0,0 @@ -// -// JNI: a class used by IKVM.NET to access JNI related functionality. -// - -// -// This is the mono version of the JNI provider. As much code is written in C# -// as possible. The code depends on having a non-copying garbage collector. -// - -using System; -using System.Collections; -using System.Text; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; - -[assembly:AssemblyVersionAttribute("0.9.*")] -//[assembly:AssemblyKeyFile("c:\\ikvm-key\\ikvm.snk")] - -public class VM -{ - public static Exception UnsatisfiedLinkError (string msg) { - return JniHelper.UnsatisfiedLinkError (msg); - } -} - -public class JNI : IJniProvider -{ - static Hashtable modules = new Hashtable (); - - [DllImport("mono-ikvm-jni")] - private static extern IntPtr native_load_native_library (string filename); - - [DllImport("mono-ikvm-jni")] - private static extern bool native_lookup_symbol (IntPtr module, string symbol_name, ref int symbol); - - [DllImport("gmodule-2.0")] - private static extern IntPtr g_module_open (string file_name, int flags); - - [DllImport("gmodule-2.0")] - private static extern bool g_module_symbol (IntPtr module, string symbol_name, ref int symbol); - - public int LoadNativeLibrary (string filename) { - Console.WriteLine ("LoadNativeLibrary : " + filename); - - IntPtr module = g_module_open (filename, 0); - if (module == (IntPtr)0) - return 0; - - modules [module] = filename; - return 1; - } - - public Type GetLocalRefStructType () { - return typeof (IkvmJNIEnv); - } - - public MethodInfo GetJniFuncPtrMethod () { - return typeof (JNI).GetMethod ("GetJniFuncPtr"); - } - - // - // Return a pointer to the C function implementing the given native - // method. - public static IntPtr GetJniFuncPtr (string method, string sig, string klass) { - // Console.WriteLine ("JNI_FUNC: " + method + " " + sig + " " + klass); - - StringBuilder mangledSig = new StringBuilder (); - int sp = 0; - for (int i = 1; sig[i] != ')'; ++i) { - switch (sig[i]) { - case '[': - mangledSig.Append("_3"); - sp += 4; - while(sig[++i] == '[') - mangledSig.Append("_3"); - mangledSig.Append(sig[i]); - if(sig[i] == 'L') { - while(sig[++i] != ';') { - if(sig[i] == '/') - mangledSig.Append("_"); - else if(sig[i] == '_') - mangledSig.Append("_1"); - else - mangledSig.Append(sig[i]); - } - mangledSig.Append("_2"); - } - break; - case 'L': - sp += 4; - mangledSig.Append("L"); - while(sig[++i] != ';') { - if(sig[i] == '/') - mangledSig.Append("_"); - else if(sig[i] == '_') - mangledSig.Append("_1"); - else - mangledSig.Append(sig[i]); - } - mangledSig.Append("_2"); - break; - case 'J': - case 'D': - mangledSig.Append(sig[i]); - sp += 8; - break; - case 'F': - case 'I': - case 'C': - case 'Z': - case 'S': - case 'B': - mangledSig.Append(sig[i]); - sp += 4; - break; - default: - throw new NotImplementedException(); - } - } - - string methodName = ""; - for (int pass = 0; pass < 2; ++pass) { - methodName = String.Format ("Java_{0}_{1}", klass.Replace("_", "_1").Replace('/', '_'), method.Replace("_", "_1")); - if (pass == 1) - methodName = methodName + "__" + mangledSig; - Console.WriteLine ("METHOD_NAME1: " + methodName); - - foreach (IntPtr module in modules.Keys) { - int function = 0; - bool found = g_module_symbol (module, methodName, ref function); - if (found) { - // Console.WriteLine ("FOUND IN " + modules[module] + " -> " + function); - return new IntPtr (function); - } - } - } - - throw VM.UnsatisfiedLinkError(methodName); - } -} - -// -// When running on a runtime with a non-copying collector, we can use object -// references instead of handles. -// - -// Hackish struct used for ptr<->reference conversion - -[StructLayout (LayoutKind.Sequential)] -struct PtrStruct { - public IntPtr ptr; - public object localref; -} - -[StructLayout (LayoutKind.Sequential)] -class JNIEnv { - IntPtr func_table; - - JNIEnv self; - - object[] localrefs; - - int localref_ptr; - - public object pendingException; - - GCHandle gc_handle; - - public JNIEnv (IntPtr the_func_table) { - func_table = the_func_table; - localrefs = new object[32]; - self = this; - - /* Pin ourselves */ - gc_handle = GCHandle.Alloc (this, GCHandleType.Pinned); - } - - public IntPtr Enter () { - pendingException = null; - localref_ptr = 0; - return GetEnvPtr (); - } - - public void Leave () { - if (localref_ptr > 0) { - for (int i = 0; i < localref_ptr; ++i) - localrefs [i] = null; - localref_ptr = 0; - } - } - - public unsafe IntPtr GetEnvPtr () { - void *current; - fixed (void *p = &func_table) { - current = p; - } - - return (IntPtr)current; - } - - public unsafe static JNIEnv GetJniEnvFromEnvPtr (IntPtr ptr) { - /* FIXME: */ - return (JNIEnv)ConvertToObject (*(IntPtr*)((long)ptr + 4)); - } - - public IntPtr MakeLocalRef (object o) { -#if COPYING_COLLECTOR - // Console.WriteLine ("MakeLocalRef."); - - if (o == null) - return (IntPtr)0; - - localrefs [localref_ptr] = o; - localref_ptr ++; - if (localref_ptr == localrefs.Length) { - object[] localrefs2 = new object [localrefs.Length * 2]; - System.Array.Copy (localrefs, localrefs2, localrefs.Length); - localrefs = localrefs2; - } - return (IntPtr)(localref_ptr); -#else - return ConvertToPtr (o); -#endif - } - - public unsafe void DeleteLocalRef (IntPtr localRef) { -#if COPYING_COLLECTOR - // Console.WriteLine ("DeleteLocalRef."); - - int index = (int)localRef; - localrefs [index - 1] = null; -#endif - } - - public unsafe object UnwrapLocalRef (IntPtr localRef) { -#if COPYING_COLLECTOR - // Console.WriteLine ("UnwrapLocalRef."); - - int index = (int)localRef; - if (index == 0) - return null; - else - return localrefs [index - 1]; -#else - return ConvertToObject (localRef); -#endif - } - - private unsafe static object ConvertToObject (IntPtr ptr) { - PtrStruct s; - s.ptr = ptr; - s.localref = null; - IntPtr *p = &s.ptr; - p [1] = ptr; - return s.localref; - } - - private unsafe static IntPtr ConvertToPtr (object o) { - PtrStruct s; - s.localref = o; - IntPtr *p = &s.ptr; - return p [1]; - } -} - -[StructLayout (LayoutKind.Sequential)] -public unsafe struct IkvmJNIEnv { - JNIEnv env; - - // This should be the first field in the structure - IntPtr func_table; - -#if COPYING_COLLECTOR - // Allocate most of the array in-line - IntPtr localref0; - object localref1; - object localref2; - object localref3; - object localref4; - object localref5; - object localref6; - object localref7; - object localref8; - object localref9; - object localref10; - object localref11; - object localref12; - object localref13; - object localref14; - object localref15; - object localref16; - - object[] localrefs; - - int localref_ptr; -#endif - - [ThreadStatic] - static JNIEnv current; - - void* previous; - - public static IntPtr the_func_table; - - static ArrayList globalRefs; - - static int t_count = 0; - - // - // Called before entering a native method - // - public IntPtr Enter () { - env = current; - if (env == null) { - env = new JNIEnv (the_func_table); - current = env; - } - - return env.Enter (); - } - - // - // Called after leaving a native method - // - public void Leave () { - env.Leave (); - } - - public IntPtr MakeLocalRef (object o) { - return env.MakeLocalRef (o); - } - - public unsafe object UnwrapLocalRef (IntPtr localRef) { - return env.UnwrapLocalRef (localRef); - } - - [DllImport("mono-ikvm-jni")] - private static extern IntPtr mono_jni_get_func_table (); - - [DllImport("mono-ikvm-jni")] - private static extern int mono_jni_jnienv_init ( - Delegate makelocalref_func, - Delegate unwind_func, - Delegate makeglobalref_func, - Delegate deleteglobalref_func, - Delegate getfieldcookie_func, - Delegate getmethodcookie_func, - Delegate setfieldvalue_func, - Delegate getfieldvalue_func, - Delegate getclassfromobject_func, - Delegate exceptioncheck_func, - Delegate getpendingexception_func, - Delegate setpendingexception_func, - Delegate invokemethod_func, - Delegate getmethodarglist_func, - Delegate findclass_func, - Delegate getjnienv_func, - Delegate allocobject_func); - - [DllImport("mono-ikvm-jni")] - public extern static void mono_jni_set_jnifunc (int index, Delegate func); - - static IkvmJNIEnv () { - Console.WriteLine ("INIT"); - - globalRefs = new ArrayList (); - - mono_jni_jnienv_init ( - new MakeLocalRefDelegate (HelperMakeLocalRef), - new UnwrapRefDelegate (HelperUnwrapRef), - new MakeGlobalRefDelegate (MakeGlobalRef), - new DeleteRefDelegate (DeleteRef), - new GetFieldCookieDelegate (GetFieldCookie), - new GetMethodCookieDelegate (GetMethodCookie), - new SetFieldValueDelegate (SetFieldValue), - new GetFieldValueDelegate (GetFieldValue), - new GetClassFromObjectDelegate (GetClassFromObject), - new ExceptionCheckDelegate (ExceptionCheck), - new GetPendingExceptionDelegate (GetPendingException), - new SetPendingExceptionDelegate (SetPendingException), - new InvokeMethodDelegate (InvokeMethod), - new GetMethodArgListDelegate (GetMethodArgList), - new FindClassDelegate (FindClass), - new GetJniEnvDelegate (GetJniEnv), - new AllocObjectDelegate (JniHelper.AllocObject)); - - the_func_table = mono_jni_get_func_table (); - } - - private static object ConvertToObject (IntPtr ptr) { - PtrStruct s; - s.ptr = ptr; - s.localref = null; - IntPtr *p = &s.ptr; - p [1] = ptr; - return s.localref; - } - - private static IntPtr ConvertToPtr (object o) { - PtrStruct s; - s.localref = o; - IntPtr *p = &s.ptr; - return p [1]; - } - - /* - // Return the address of the 'func_table' member from a boxed JNIEnv object - // Implemented in IL - private static IntPtr GetJniEnvPtr (object o) { - return null; - } - */ - - // - // Methods called by the native code - // - - public delegate IntPtr MakeLocalRefDelegate (IntPtr jniEnv, object obj); - - public static unsafe IntPtr HelperMakeLocalRef (IntPtr jniEnv, object obj) { -#if COPYING_COLLECTOR - return JNIEnv.GetJniEnvFromEnvPtr (jniEnv).MakeLocalRef (obj); -#else - return ConvertToPtr (obj); -#endif - } - - public delegate object UnwrapRefDelegate (IntPtr jniEnv, IntPtr reference); - - public static unsafe object HelperUnwrapRef (IntPtr jniEnv, IntPtr reference) { -#if COPYING_COLLECTOR - if ((int)reference >= 0) - return JNIEnv.GetJniEnvFromEnvPtr (jniEnv).UnwrapLocalRef (reference); - else - return globalRefs [(- (int)reference) - 1]; -#else - return ConvertToObject (reference); -#endif - } - - public delegate IntPtr MakeGlobalRefDelegate (object obj); - - public static IntPtr MakeGlobalRef (object obj) { -#if COPYING_COLLECTOR - if (obj == null) - return (IntPtr)0; - else - return (IntPtr)(- (globalRefs.Add (obj) + 1)); -#else - return ConvertToPtr (obj); -#endif - } - - public delegate void DeleteRefDelegate (IntPtr jniEnv, IntPtr reference); - - public static unsafe void DeleteRef (IntPtr jniEnv, IntPtr reference) { -#if COPYING_COLLECTOR - if ((int)reference == 0) - return; - else - if ((int)reference > 0) - JNIEnv.GetJniEnvFromEnvPtr (jniEnv).DeleteLocalRef (reference); - else { - int index = (- (int)reference) - 1; - globalRefs [index] = null; - } -#endif - } - - public delegate IntPtr GetFieldCookieDelegate(object clazz, object name, object sig, bool isStatic); - - public static IntPtr GetFieldCookie(object clazz, object name, object sig, bool isStatic) { - IntPtr res = JniHelper.GetFieldCookie (clazz, (string)name, (string)sig, isStatic); - return res; - /* - if ((int)res == 0) - throw new NotImplementedException (); - else - return res; - */ - } - - public delegate IntPtr GetMethodCookieDelegate (object clazz, object name, object sig, bool isStatic); - - public static IntPtr GetMethodCookie(object clazz, object name, object sig, bool isStatic) { - IntPtr res = JniHelper.GetMethodCookie (clazz, (string)name, (string)sig, isStatic); - return res; - /* - if ((int)res == 0) - throw new NotImplementedException (); - else - return res; - */ - } - - public delegate void SetFieldValueDelegate(IntPtr cookie, object obj, object val); - - public static void SetFieldValue (IntPtr cookie, object obj, object val) { - JniHelper.SetFieldValue (cookie, obj, val); - } - - public delegate object GetFieldValueDelegate (IntPtr cookie, object obj); - - public static object GetFieldValue (IntPtr cookie, object obj) { - return JniHelper.GetFieldValue (cookie, obj); - } - - public delegate object GetClassFromObjectDelegate (object obj); - - public static object GetClassFromObject (object obj) { - return JniHelper.GetClassFromType (obj.GetType ()); - } - - public delegate bool ExceptionCheckDelegate (IntPtr jniEnv); - - public static unsafe bool ExceptionCheck (IntPtr jniEnv) { - if (JNIEnv.GetJniEnvFromEnvPtr (jniEnv).pendingException == null) - return false; - else - return true; - } - - public delegate object GetPendingExceptionDelegate (IntPtr jniEnv); - - public static unsafe object GetPendingException (IntPtr jniEnv) { - return JNIEnv.GetJniEnvFromEnvPtr (jniEnv).pendingException; - } - - public delegate void SetPendingExceptionDelegate (IntPtr jniEnv, object obj); - - public static unsafe void SetPendingException (IntPtr jniEnv, object obj) { - JNIEnv.GetJniEnvFromEnvPtr (jniEnv).pendingException = obj; - } - - public delegate object InvokeMethodDelegate (IntPtr jniEnv, IntPtr cookie, object obj, object args, bool nonVirtual); - - public static object InvokeMethod (IntPtr jniEnv, IntPtr cookie, object obj, object args, bool nonVirtual) { - try { - return JniHelper.InvokeMethod (cookie, obj, (object[])args, nonVirtual); - } - catch (Exception ex) { - SetPendingException (jniEnv, ex); - return null; - } - } - - public delegate string GetMethodArgListDelegate (IntPtr cookie); - - public static string GetMethodArgList (IntPtr cookie) { - return JniHelper.GetMethodArgList (cookie); - } - - public delegate object FindClassDelegate (object javaName); - - public static object FindClass (object javaName) { - return JniHelper.FindClass ((string)javaName); - } - - public unsafe delegate IntPtr GetJniEnvDelegate (); - - public static unsafe IntPtr GetJniEnv () { - return current.GetEnvPtr (); - } - - public delegate object AllocObjectDelegate (object clazz); -} diff --git a/jni/mono/mono.build b/jni/mono/mono.build deleted file mode 100644 index 3bdc182b..00000000 --- a/jni/mono/mono.build +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/native/jni.c b/native/jni.c new file mode 100644 index 00000000..33c78bec --- /dev/null +++ b/native/jni.c @@ -0,0 +1,500 @@ +/* + Copyright (C) 2004 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +#include +#include +#include "jni.h" + +#ifdef _WIN32 +#define ALLOCA _alloca +#else +#include +#define ALLOCA alloca +#endif + +static jobject JNICALL NewObject(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...) +{ + jobject o; + va_list args; + va_start(args, methodID); + o = (*pEnv)->NewObjectV(pEnv, clazz, methodID, args); + va_end(args); + return o; +} + +#define MAKE_ARG_ARRAY(pEnv, args, argarray) \ +do { \ + jbyte sig[257];\ + int argc = (*pEnv)->GetMethodArgs(pEnv, methodID, sig);\ + int i;\ + argarray = (jvalue*)ALLOCA(argc * sizeof(jvalue));\ + for(i = 0; i < argc; i++)\ + {\ + switch(sig[i])\ + {\ + case 'Z':\ + case 'B':\ + case 'S':\ + case 'C':\ + case 'I':\ + argarray[i].i = va_arg(args, jint);\ + break;\ + case 'J':\ + argarray[i].j = va_arg(args, jlong);\ + break;\ + case 'L':\ + argarray[i].l = va_arg(args, jobject);\ + break;\ + case 'D':\ + argarray[i].d = va_arg(args, double);\ + break;\ + case 'F':\ + argarray[i].f = (float)va_arg(args, double);\ + break;\ + }\ + }\ +} while(0); + +static jobject JNICALL NewObjectV(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args) +{ + jvalue* argarray; + MAKE_ARG_ARRAY(pEnv, args, argarray); + return (*pEnv)->NewObjectA(pEnv, clazz, methodID, argarray); +} + +#define MAKE_METHOD(Type, type) \ +static type JNICALL Call##Type##Method(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...)\ +{\ + type ret;\ + va_list args;\ + va_start(args, methodID);\ + ret = (*pEnv)->Call##Type##MethodV(pEnv, obj, methodID, args);\ + va_end(args);\ + return ret;\ +}\ +static type JNICALL Call##Type##MethodV(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args)\ +{\ + jvalue* argarray;\ + MAKE_ARG_ARRAY(pEnv, args, argarray);\ + return (*pEnv)->Call##Type##MethodA(pEnv, obj, methodID, argarray);\ +}\ +static type JNICALL CallNonvirtual##Type##Method(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...)\ +{\ + type ret;\ + va_list args;\ + va_start(args, methodID);\ + ret = (*pEnv)->CallNonvirtual##Type##MethodV(pEnv, obj, clazz, methodID, args);\ + va_end(args);\ + return ret;\ +}\ +static type JNICALL CallNonvirtual##Type##MethodV(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args)\ +{\ + jvalue* argarray;\ + MAKE_ARG_ARRAY(pEnv, args, argarray);\ + return (*pEnv)->CallNonvirtual##Type##MethodA(pEnv, obj, clazz, methodID, argarray);\ +}\ +static type JNICALL CallStatic##Type##Method(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...)\ +{\ + type ret;\ + va_list args;\ + va_start(args, methodID);\ + ret = (*pEnv)->CallStatic##Type##MethodV(pEnv, clazz, methodID, args);\ + va_end(args);\ + return ret;\ +}\ +static type JNICALL CallStatic##Type##MethodV(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args)\ +{\ + jvalue* argarray;\ + MAKE_ARG_ARRAY(pEnv, args, argarray);\ + return (*pEnv)->CallStatic##Type##MethodA(pEnv, clazz, methodID, argarray);\ +} + +MAKE_METHOD(Object, jobject) +MAKE_METHOD(Boolean, jboolean) +MAKE_METHOD(Byte, jbyte) +MAKE_METHOD(Char, jchar) +MAKE_METHOD(Short, jshort) +MAKE_METHOD(Int, jint) +MAKE_METHOD(Long, jlong) +MAKE_METHOD(Float, jfloat) +MAKE_METHOD(Double, jdouble) + +static void JNICALL CallVoidMethod(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...) +{ + va_list args; + va_start(args, methodID); + (*pEnv)->CallVoidMethodV(pEnv, obj, methodID, args); + va_end(args); +} +static void JNICALL CallVoidMethodV(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args) +{ + jvalue* argarray; + MAKE_ARG_ARRAY(pEnv, args, argarray); + (*pEnv)->CallVoidMethodA(pEnv, obj, methodID, argarray); +} +static void JNICALL CallNonvirtualVoidMethod(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + va_list args; + va_start(args, methodID); + (*pEnv)->CallNonvirtualVoidMethodV(pEnv, obj, clazz, methodID, args); + va_end(args); +} +static void JNICALL CallNonvirtualVoidMethodV(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + jvalue* argarray; + MAKE_ARG_ARRAY(pEnv, args, argarray); + (*pEnv)->CallNonvirtualVoidMethodA(pEnv, obj, clazz, methodID, argarray); +} +static void JNICALL CallStaticVoidMethod(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...) +{ + va_list args; + va_start(args, methodID); + (*pEnv)->CallStaticVoidMethodV(pEnv, clazz, methodID, args); + va_end(args); +} +static void JNICALL CallStaticVoidMethodV(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args) +{ + jvalue* argarray; + MAKE_ARG_ARRAY(pEnv, args, argarray); + (*pEnv)->CallStaticVoidMethodA(pEnv, clazz, methodID, argarray); +} + +static void* JNIEnv_vtable[] = +{ + 0, // void JNICALL reserved0(); + 0, // void JNICALL reserved1(); + 0, // void JNICALL reserved2(); + 0, // void JNICALL reserved3(); + + 0, // jint JNICALL GetVersion(); + + 0, // jclass JNICALL DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len); + 0, // jclass JNICALL FindClass(const char *name); + + 0, // jmethodID JNICALL FromReflectedMethod(jobject method); + 0, // jfieldID JNICALL FromReflectedField(jobject field); + 0, // jobject JNICALL ToReflectedMethod(jclass clazz, jmethodID methodID); + + 0, // jclass JNICALL GetSuperclass(jclass sub); + 0, // jboolean JNICALL IsAssignableFrom(jclass sub, jclass sup); + + 0, // jobject JNICALL ToReflectedField(jclass clazz, jfieldID fieldID); + + 0, // jint JNICALL Throw(jthrowable obj); + 0, // jint JNICALL ThrowNew(jclass clazz, const char *msg); + 0, // jthrowable JNICALL ExceptionOccurred(); + 0, // void JNICALL ExceptionDescribe(); + 0, // void JNICALL ExceptionClear(); + 0, // void JNICALL FatalError(const char *msg); + + 0, // jint JNICALL PushLocalFrame(jint capacity); + 0, // jobject JNICALL PopLocalFrame(jobject result); + + 0, // jobject JNICALL NewGlobalRef(jobject lobj); + 0, // void JNICALL DeleteGlobalRef(jobject gref); + 0, // void JNICALL DeleteLocalRef(jobject obj); + 0, // jboolean JNICALL IsSameObject(jobject obj1, jobject obj2); + + 0, // jobject JNICALL NewLocalRef(jobject ref); + 0, // jint JNICALL EnsureLocalCapacity(jint capacity); + + 0, // jobject JNICALL AllocObject(jclass clazz); + NewObject, // jobject JNICALL NewObject(jclass clazz, jmethodID methodID, ...); + NewObjectV, // jobject JNICALL NewObjectV(jclass clazz, jmethodID methodID, va_list args); + 0, // jobject JNICALL NewObjectA(jclass clazz, jmethodID methodID, jvalue *args); + + 0, // jclass JNICALL GetObjectClass(jobject obj); + 0, // jboolean JNICALL IsInstanceOf(jobject obj, jclass clazz); + + 0, // jmethodID JNICALL GetMethodID(jclass clazz, const char *name, const char *sig); + + CallObjectMethod, // jobject JNICALL CallObjectMethod(jobject obj, jmethodID methodID, ...); + CallObjectMethodV, // jobject JNICALL CallObjectMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jobject JNICALL CallObjectMethodA(jobject obj, jmethodID methodID, jvalue * args); + + CallBooleanMethod, // jboolean JNICALL CallBooleanMethod(jobject obj, jmethodID methodID, ...); + CallBooleanMethodV, // jboolean JNICALL CallBooleanMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jboolean JNICALL CallBooleanMethodA(jobject obj, jmethodID methodID, jvalue * args); + + CallByteMethod, // jbyte JNICALL CallByteMethod(jobject obj, jmethodID methodID, ...); + CallByteMethodV, // jbyte JNICALL CallByteMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jbyte JNICALL CallByteMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallCharMethod, // jchar JNICALL CallCharMethod(jobject obj, jmethodID methodID, ...); + CallCharMethodV, // jchar JNICALL CallCharMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jchar JNICALL CallCharMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallShortMethod, // jshort JNICALL CallShortMethod(jobject obj, jmethodID methodID, ...); + CallShortMethodV, // jshort JNICALL CallShortMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jshort JNICALL CallShortMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallIntMethod, // jint JNICALL CallIntMethod(jobject obj, jmethodID methodID, ...); + CallIntMethodV, // jint JNICALL CallIntMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jint JNICALL CallIntMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallLongMethod, // jlong JNICALL CallLongMethod(jobject obj, jmethodID methodID, ...); + CallLongMethodV, // jlong JNICALL CallLongMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jlong JNICALL CallLongMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallFloatMethod, // jfloat JNICALL CallFloatMethod(jobject obj, jmethodID methodID, ...); + CallFloatMethodV, // jfloat JNICALL CallFloatMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jfloat JNICALL CallFloatMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallDoubleMethod, // jdouble JNICALL CallDoubleMethod(jobject obj, jmethodID methodID, ...); + CallDoubleMethodV, // jdouble JNICALL CallDoubleMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jdouble JNICALL CallDoubleMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallVoidMethod, // void JNICALL CallVoidMethod(jobject obj, jmethodID methodID, ...); + CallVoidMethodV, // void JNICALL CallVoidMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // void JNICALL CallVoidMethodA(jobject obj, jmethodID methodID, jvalue * args); + + CallNonvirtualObjectMethod, // jobject JNICALL CallNonvirtualObjectMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualObjectMethodV, // jobject JNICALL CallNonvirtualObjectMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jobject JNICALL CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + CallNonvirtualBooleanMethod, // jboolean JNICALL CallNonvirtualBooleanMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualBooleanMethodV, // jboolean JNICALL CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jboolean JNICALL CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + CallNonvirtualByteMethod, // jbyte JNICALL CallNonvirtualByteMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualByteMethodV, // jbyte JNICALL CallNonvirtualByteMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jbyte JNICALL CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualCharMethod, // jchar JNICALL CallNonvirtualCharMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualCharMethodV, // jchar JNICALL CallNonvirtualCharMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jchar JNICALL CallNonvirtualCharMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualShortMethod, // jshort JNICALL CallNonvirtualShortMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualShortMethodV, // jshort JNICALL CallNonvirtualShortMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jshort JNICALL CallNonvirtualShortMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualIntMethod, // jint JNICALL CallNonvirtualIntMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualIntMethodV, // jint JNICALL CallNonvirtualIntMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jint JNICALL CallNonvirtualIntMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualLongMethod, // jlong JNICALL CallNonvirtualLongMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualLongMethodV, // jlong JNICALL CallNonvirtualLongMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jlong JNICALL CallNonvirtualLongMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualFloatMethod, // jfloat JNICALL CallNonvirtualFloatMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualFloatMethodV, // jfloat JNICALL CallNonvirtualFloatMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jfloat JNICALL CallNonvirtualFloatMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualDoubleMethod, // jdouble JNICALL CallNonvirtualDoubleMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualDoubleMethodV, // jdouble JNICALL CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jdouble JNICALL CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualVoidMethod, // void JNICALL CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualVoidMethodV, // void JNICALL CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // void JNICALL CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + 0, // jfieldID JNICALL GetFieldID(jclass clazz, const char *name, const char *sig); + + 0, // jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID); + 0, // jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID); + 0, // jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID); + 0, // jchar JNICALL GetCharField(jobject obj, jfieldID fieldID); + 0, // jshort JNICALL GetShortField(jobject obj, jfieldID fieldID); + 0, // jint JNICALL GetIntField(jobject obj, jfieldID fieldID); + 0, // jlong JNICALL GetLongField(jobject obj, jfieldID fieldID); + 0, // jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID); + 0, // jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID); + + 0, // void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val); + 0, // void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val); + 0, // void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val); + 0, // void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val); + 0, // void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val); + 0, // void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val); + 0, // void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val); + 0, // void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val); + 0, // void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val); + + 0, // jmethodID JNICALL GetStaticMethodID(jclass clazz, const char *name, const char *sig); + + CallStaticObjectMethod, // jobject JNICALL CallStaticObjectMethod(jclass clazz, jmethodID methodID, ...); + CallStaticObjectMethodV, // jobject JNICALL CallStaticObjectMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jobject JNICALL CallStaticObjectMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticBooleanMethod, // jboolean JNICALL CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...); + CallStaticBooleanMethodV, // jboolean JNICALL CallStaticBooleanMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jboolean JNICALL CallStaticBooleanMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticByteMethod, // jbyte JNICALL CallStaticByteMethod(jclass clazz, jmethodID methodID, ...); + CallStaticByteMethodV, // jbyte JNICALL CallStaticByteMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jbyte JNICALL CallStaticByteMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticCharMethod, // jchar JNICALL CallStaticCharMethod(jclass clazz, jmethodID methodID, ...); + CallStaticCharMethodV, // jchar JNICALL CallStaticCharMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jchar JNICALL CallStaticCharMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticShortMethod, // jshort JNICALL CallStaticShortMethod(jclass clazz, jmethodID methodID, ...); + CallStaticShortMethodV, // jshort JNICALL CallStaticShortMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jshort JNICALL CallStaticShortMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticIntMethod, // jint JNICALL CallStaticIntMethod(jclass clazz, jmethodID methodID, ...); + CallStaticIntMethodV, // jint JNICALL CallStaticIntMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jint JNICALL CallStaticIntMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticLongMethod, // jlong JNICALL CallStaticLongMethod(jclass clazz, jmethodID methodID, ...); + CallStaticLongMethodV, // jlong JNICALL CallStaticLongMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jlong JNICALL CallStaticLongMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticFloatMethod, // jfloat JNICALL CallStaticFloatMethod(jclass clazz, jmethodID methodID, ...); + CallStaticFloatMethodV, // jfloat JNICALL CallStaticFloatMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jfloat JNICALL CallStaticFloatMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticDoubleMethod, // jdouble JNICALL CallStaticDoubleMethod(jclass clazz, jmethodID methodID, ...); + CallStaticDoubleMethodV, // jdouble JNICALL CallStaticDoubleMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jdouble JNICALL CallStaticDoubleMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticVoidMethod, // void JNICALL CallStaticVoidMethod(jclass cls, jmethodID methodID, ...); + CallStaticVoidMethodV, // void JNICALL CallStaticVoidMethodV(jclass cls, jmethodID methodID, va_list args); + 0, // void JNICALL CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue * args); + + 0, // jfieldID JNICALL GetStaticFieldID(jclass clazz, const char *name, const char *sig); + + 0, // jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID); + 0, // jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID); + 0, // jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID); + 0, // jchar JNICALL GetCharField(jobject obj, jfieldID fieldID); + 0, // jshort JNICALL GetShortField(jobject obj, jfieldID fieldID); + 0, // jint JNICALL GetIntField(jobject obj, jfieldID fieldID); + 0, // jlong JNICALL GetLongField(jobject obj, jfieldID fieldID); + 0, // jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID); + 0, // jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID); + + 0, // void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val); + 0, // void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val); + 0, // void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val); + 0, // void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val); + 0, // void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val); + 0, // void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val); + 0, // void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val); + 0, // void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val); + 0, // void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val); + + 0, // jstring JNICALL NewString(const jchar *unicode, jsize len); + 0, // jsize JNICALL GetStringLength(jstring str); + 0, // const jchar *JNICALL GetStringChars(jstring str, jboolean *isCopy); + 0, // void JNICALL ReleaseStringChars(jstring str, const jchar *chars); + + 0, // jstring JNICALL NewStringUTF(const char *utf); + 0, // jsize JNICALL GetStringUTFLength(jstring str); + 0, // const char* JNICALL GetStringUTFChars(jstring str, jboolean *isCopy); + 0, // void JNICALL ReleaseStringUTFChars(jstring str, const char* chars); + + 0, // jsize JNICALL GetArrayLength(jarray array); + + 0, // jobjectArray JNICALL NewObjectArray(jsize len, jclass clazz, jobject init); + 0, // jobject JNICALL GetObjectArrayElement(jobjectArray array, jsize index); + 0, // void JNICALL SetObjectArrayElement(jobjectArray array, jsize index, jobject val); + + 0, // jbooleanArray JNICALL NewBooleanArray(jsize len); + 0, // jbyteArray JNICALL NewByteArray(jsize len); + 0, // jcharArray JNICALL NewCharArray(jsize len); + 0, // jshortArray JNICALL NewShortArray(jsize len); + 0, // jintArray JNICALL NewIntArray(jsize len); + 0, // jlongArray JNICALL NewLongArray(jsize len); + 0, // jfloatArray JNICALL NewFloatArray(jsize len); + 0, // jdoubleArray JNICALL NewDoubleArray(jsize len); + + 0, // jboolean * JNICALL GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy); + 0, // jbyte * JNICALL GetByteArrayElements(jbyteArray array, jboolean *isCopy); + 0, // jchar * JNICALL GetCharArrayElements(jcharArray array, jboolean *isCopy); + 0, // jshort * JNICALL GetShortArrayElements(jshortArray array, jboolean *isCopy); + 0, // jint * JNICALL GetIntArrayElements(jintArray array, jboolean *isCopy); + 0, // jlong * JNICALL GetLongArrayElements(jlongArray array, jboolean *isCopy); + 0, // jfloat * JNICALL GetFloatArrayElements(jfloatArray array, jboolean *isCopy); + 0, // jdouble * JNICALL GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy); + + 0, // void JNICALL ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems, jint mode); + 0, // void JNICALL ReleaseByteArrayElements(jbyteArray array, jbyte *elems, jint mode); + 0, // void JNICALL ReleaseCharArrayElements(jcharArray array, jchar *elems, jint mode); + 0, // void JNICALL ReleaseShortArrayElements(jshortArray array, jshort *elems, jint mode); + 0, // void JNICALL ReleaseIntArrayElements(jintArray array, jint *elems, jint mode); + 0, // void JNICALL ReleaseLongArrayElements(jlongArray array, jlong *elems, jint mode); + 0, // void JNICALL ReleaseFloatArrayElements(jfloatArray array, jfloat *elems, jint mode); + 0, // void JNICALL ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems, jint mode); + + 0, // void JNICALL GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); + 0, // void JNICALL GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); + 0, // void JNICALL GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); + 0, // void JNICALL GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); + 0, // void JNICALL GetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); + 0, // void JNICALL GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); + 0, // void JNICALL GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); + 0, // void JNICALL GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); + + 0, // void JNICALL SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); + 0, // void JNICALL SetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); + 0, // void JNICALL SetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); + 0, // void JNICALL SetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); + 0, // void JNICALL SetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); + 0, // void JNICALL SetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); + 0, // void JNICALL SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); + 0, // void JNICALL SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); + + 0, // jint JNICALL RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods); + 0, // jint JNICALL UnregisterNatives(jclass clazz); + + 0, // jint JNICALL MonitorEnter(jobject obj); + 0, // jint JNICALL MonitorExit(jobject obj); + + 0, // jint JNICALL GetJavaVM(JavaVM **vm); + + 0, // void JNICALL GetStringRegion(jstring str, jsize start, jsize len, jchar *buf); + 0, // void JNICALL GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf); + + 0, // void* JNICALL GetPrimitiveArrayCritical(jarray array, jboolean *isCopy); + 0, // void JNICALL ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode); + + 0, // const jchar* JNICALL GetStringCritical(jstring string, jboolean *isCopy); + 0, // void JNICALL ReleaseStringCritical(jstring string, const jchar *cstring); + + 0, // jweak JNICALL NewWeakGlobalRef(jobject obj); + 0, // void JNICALL DeleteWeakGlobalRef(jweak ref); + + 0, // jboolean JNICALL ExceptionCheck(); + + 0, // jobject JNICALL NewDirectByteBuffer(void* address, jlong capacity); + 0, // void* JNICALL GetDirectBufferAddress(jobject buf); + 0 // jlong JNICALL GetDirectBufferCapacity(jobject buf); +}; + +JNIEXPORT void** JNICALL ikvm_GetJNIEnvVTable() +{ + return JNIEnv_vtable; +} + +JNIEXPORT void* JNICALL ikvm_MarshalDelegate(void* p) +{ + return p; +} + +typedef jint (JNICALL *PJNI_ONLOAD)(JavaVM* vm, void* reserved); + +JNIEXPORT jint JNICALL ikvm_CallOnLoad(PJNI_ONLOAD method, JavaVM* vm, void* reserved) +{ + return method(vm, reserved); +} diff --git a/native/jni.h b/native/jni.h new file mode 100644 index 00000000..4fac309c --- /dev/null +++ b/native/jni.h @@ -0,0 +1,401 @@ +/* + Copyright (C) 2004 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +#ifndef __JNI_H__ +#define __JNI_H__ + +#ifdef _WIN32 + #define JNICALL __stdcall + #ifdef __cplusplus + #define JNIEXPORT extern "C" __declspec(dllexport) + #else + #define JNIEXPORT __declspec(dllexport) + #endif +#else + #define JNICALL + #ifdef __cplusplus + #define JNIEXPORT extern "C" + #else + #define JNIEXPORT + #endif + #include +#endif + +typedef void* jobject; +typedef void* jstring; +typedef void* jweak; +typedef void* jthrowable; +typedef void* jclass; +typedef void* jmethodID; +typedef void* jfieldID; +typedef void* jarray; +typedef void* jobjectArray; +typedef void* jbooleanArray; +typedef void* jbyteArray; +typedef void* jcharArray; +typedef void* jshortArray; +typedef void* jintArray; +typedef void* jlongArray; +typedef void* jfloatArray; +typedef void* jdoubleArray; + +typedef unsigned char jboolean; +typedef signed char jbyte; +typedef unsigned short jchar; +typedef short jshort; +typedef int jint; +#ifdef __GNUC__ + typedef long long int jlong; +#else + typedef __int64 jlong; +#endif +typedef float jfloat; +typedef double jdouble; +typedef jint jsize; + +typedef struct +{ + char *name; + char *signature; + void *fnPtr; +} JNINativeMethod; + +typedef union jvalue +{ + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +} jvalue; + +typedef void* JavaVM; +typedef struct JNIEnv_methods *JNIEnv; + +struct JNIEnv_methods +{ + jint (JNICALL *GetMethodArgs)(JNIEnv* pEnv, jmethodID method, jbyte* sig); + void (JNICALL *reserved1)(JNIEnv* pEnv); + void (JNICALL *reserved2)(JNIEnv* pEnv); + void (JNICALL *reserved3)(JNIEnv* pEnv); + + jint (JNICALL *GetVersion)(JNIEnv* pEnv); + + jclass (JNICALL *DefineClass)(JNIEnv* pEnv, const char *name, jobject loader, const jbyte *buf, jsize len); + jclass (JNICALL *FindClass)(JNIEnv* pEnv, const char *name); + + jmethodID (JNICALL *FromReflectedMethod)(JNIEnv* pEnv, jobject method); + jfieldID (JNICALL *FromReflectedField)(JNIEnv* pEnv, jobject field); + jobject (JNICALL *ToReflectedMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID); + + jclass (JNICALL *GetSuperclass)(JNIEnv* pEnv, jclass sub); + jboolean (JNICALL *IsAssignableFrom)(JNIEnv* pEnv, jclass sub, jclass sup); + + jobject (JNICALL *ToReflectedField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + + jint (JNICALL *Throw)(JNIEnv* pEnv, jthrowable obj); + jint (JNICALL *ThrowNew)(JNIEnv* pEnv, jclass clazz, const char *msg); + jthrowable (JNICALL *ExceptionOccurred)(JNIEnv* pEnv); + void (JNICALL *ExceptionDescribe)(JNIEnv* pEnv); + void (JNICALL *ExceptionClear)(JNIEnv* pEnv); + void (JNICALL *FatalError)(JNIEnv* pEnv, const char *msg); + + jint (JNICALL *PushLocalFrame)(JNIEnv* pEnv, jint capacity); + jobject (JNICALL *PopLocalFrame)(JNIEnv* pEnv, jobject result); + + jobject (JNICALL *NewGlobalRef)(JNIEnv* pEnv, jobject lobj); + void (JNICALL *DeleteGlobalRef)(JNIEnv* pEnv, jobject gref); + void (JNICALL *DeleteLocalRef)(JNIEnv* pEnv, jobject obj); + jboolean (JNICALL *IsSameObject)(JNIEnv* pEnv, jobject obj1, jobject obj2); + + jobject (JNICALL *NewLocalRef)(JNIEnv* pEnv, jobject ref); + jint (JNICALL *EnsureLocalCapacity)(JNIEnv* pEnv, jint capacity); + + jobject (JNICALL *AllocObject)(JNIEnv* pEnv, jclass clazz); + jobject (JNICALL *NewObject)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *NewObjectV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *NewObjectA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jclass (JNICALL *GetObjectClass)(JNIEnv* pEnv, jobject obj); + jboolean (JNICALL *IsInstanceOf)(JNIEnv* pEnv, jobject obj, jclass clazz); + + jmethodID (JNICALL *GetMethodID)(JNIEnv* pEnv, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallObjectMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jobject (JNICALL *CallObjectMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jobject (JNICALL *CallObjectMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue * args); + + jboolean (JNICALL *CallBooleanMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jboolean (JNICALL *CallBooleanMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jboolean (JNICALL *CallBooleanMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue * args); + + jbyte (JNICALL *CallByteMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jbyte (JNICALL *CallByteMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jbyte (JNICALL *CallByteMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jchar (JNICALL *CallCharMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jchar (JNICALL *CallCharMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jchar (JNICALL *CallCharMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jshort (JNICALL *CallShortMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jshort (JNICALL *CallShortMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jshort (JNICALL *CallShortMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jint (JNICALL *CallIntMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jint (JNICALL *CallIntMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jint (JNICALL *CallIntMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jlong (JNICALL *CallLongMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jlong (JNICALL *CallLongMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jlong (JNICALL *CallLongMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jfloat (JNICALL *CallFloatMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jfloat (JNICALL *CallFloatMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jfloat (JNICALL *CallFloatMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jdouble (JNICALL *CallDoubleMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jdouble (JNICALL *CallDoubleMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jdouble (JNICALL *CallDoubleMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + void (JNICALL *CallVoidMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + void (JNICALL *CallVoidMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + void (JNICALL *CallVoidMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue * args); + + jobject (JNICALL *CallNonvirtualObjectMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallNonvirtualObjectMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *CallNonvirtualObjectMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + jboolean (JNICALL *CallNonvirtualBooleanMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallNonvirtualBooleanMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jboolean (JNICALL *CallNonvirtualBooleanMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + jbyte (JNICALL *CallNonvirtualByteMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallNonvirtualByteMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jbyte (JNICALL *CallNonvirtualByteMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jchar (JNICALL *CallNonvirtualCharMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallNonvirtualCharMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jchar (JNICALL *CallNonvirtualCharMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jshort (JNICALL *CallNonvirtualShortMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallNonvirtualShortMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jshort (JNICALL *CallNonvirtualShortMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jint (JNICALL *CallNonvirtualIntMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallNonvirtualIntMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jint (JNICALL *CallNonvirtualIntMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jlong (JNICALL *CallNonvirtualLongMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallNonvirtualLongMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jlong (JNICALL *CallNonvirtualLongMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jfloat (JNICALL *CallNonvirtualFloatMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallNonvirtualFloatMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jfloat (JNICALL *CallNonvirtualFloatMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jdouble (JNICALL *CallNonvirtualDoubleMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallNonvirtualDoubleMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jdouble (JNICALL *CallNonvirtualDoubleMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + void (JNICALL *CallNonvirtualVoidMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + void (JNICALL *CallNonvirtualVoidMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + void (JNICALL *CallNonvirtualVoidMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + jfieldID (JNICALL *GetFieldID)(JNIEnv* pEnv, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *GetObjectField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jboolean (JNICALL *GetBooleanField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jbyte (JNICALL *GetByteField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jchar (JNICALL *GetCharField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jshort (JNICALL *GetShortField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jint (JNICALL *GetIntField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jlong (JNICALL *GetLongField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jfloat (JNICALL *GetFloatField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jdouble (JNICALL *GetDoubleField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + + void (JNICALL *SetObjectField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jobject val); + void (JNICALL *SetBooleanField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jboolean val); + void (JNICALL *SetByteField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val); + void (JNICALL *SetCharField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val); + void (JNICALL *SetShortField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jshort val); + void (JNICALL *SetIntField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jint val); + void (JNICALL *SetLongField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jlong val); + void (JNICALL *SetFloatField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jfloat val); + void (JNICALL *SetDoubleField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jdouble val); + + jmethodID (JNICALL *GetStaticMethodID)(JNIEnv* pEnv, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallStaticObjectMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallStaticObjectMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *CallStaticObjectMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jboolean (JNICALL *CallStaticBooleanMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallStaticBooleanMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jboolean (JNICALL *CallStaticBooleanMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jbyte (JNICALL *CallStaticByteMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallStaticByteMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jbyte (JNICALL *CallStaticByteMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jchar (JNICALL *CallStaticCharMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallStaticCharMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jchar (JNICALL *CallStaticCharMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jshort (JNICALL *CallStaticShortMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallStaticShortMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jshort (JNICALL *CallStaticShortMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jint (JNICALL *CallStaticIntMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallStaticIntMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jint (JNICALL *CallStaticIntMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jlong (JNICALL *CallStaticLongMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallStaticLongMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jlong (JNICALL *CallStaticLongMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jfloat (JNICALL *CallStaticFloatMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallStaticFloatMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jfloat (JNICALL *CallStaticFloatMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jdouble (JNICALL *CallStaticDoubleMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallStaticDoubleMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jdouble (JNICALL *CallStaticDoubleMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + void (JNICALL *CallStaticVoidMethod)(JNIEnv* pEnv, jclass cls, jmethodID methodID, ...); + void (JNICALL *CallStaticVoidMethodV)(JNIEnv* pEnv, jclass cls, jmethodID methodID, va_list args); + void (JNICALL *CallStaticVoidMethodA)(JNIEnv* pEnv, jclass cls, jmethodID methodID, jvalue * args); + + jfieldID (JNICALL *GetStaticFieldID)(JNIEnv* pEnv, jclass clazz, const char *name, const char *sig); + jobject (JNICALL *GetStaticObjectField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jboolean (JNICALL *GetStaticBooleanField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jbyte (JNICALL *GetStaticByteField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jchar (JNICALL *GetStaticCharField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jshort (JNICALL *GetStaticShortField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jint (JNICALL *GetStaticIntField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jlong (JNICALL *GetStaticLongField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jfloat (JNICALL *GetStaticFloatField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jdouble (JNICALL *GetStaticDoubleField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + + void (JNICALL *SetStaticObjectField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jobject value); + void (JNICALL *SetStaticBooleanField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jboolean value); + void (JNICALL *SetStaticByteField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte value); + void (JNICALL *SetStaticCharField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar value); + void (JNICALL *SetStaticShortField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jshort value); + void (JNICALL *SetStaticIntField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jint value); + void (JNICALL *SetStaticLongField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jlong value); + void (JNICALL *SetStaticFloatField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jfloat value); + void (JNICALL *SetStaticDoubleField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jdouble value); + + jstring (JNICALL *NewString)(JNIEnv* pEnv, const jchar *unicode, jsize len); + jsize (JNICALL *GetStringLength)(JNIEnv* pEnv, jstring str); + const jchar *(JNICALL *GetStringChars)(JNIEnv* pEnv, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringChars)(JNIEnv* pEnv, jstring str, const jchar *chars); + + jstring (JNICALL *NewStringUTF)(JNIEnv* pEnv, const char *utf); + jsize (JNICALL *GetStringUTFLength)(JNIEnv* pEnv, jstring str); + const char* (JNICALL *GetStringUTFChars)(JNIEnv* pEnv, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringUTFChars)(JNIEnv* pEnv, jstring str, const char* chars); + + jsize (JNICALL *GetArrayLength)(JNIEnv* pEnv, jarray array); + + jobjectArray (JNICALL *NewObjectArray)(JNIEnv* pEnv, jsize len, jclass clazz, jobject init); + jobject (JNICALL *GetObjectArrayElement)(JNIEnv* pEnv, jobjectArray array, jsize index); + void (JNICALL *SetObjectArrayElement)(JNIEnv* pEnv, jobjectArray array, jsize index, jobject val); + + jbooleanArray (JNICALL *NewBooleanArray)(JNIEnv* pEnv, jsize len); + jbyteArray (JNICALL *NewByteArray)(JNIEnv* pEnv, jsize len); + jcharArray (JNICALL *NewCharArray)(JNIEnv* pEnv, jsize len); + jshortArray (JNICALL *NewShortArray)(JNIEnv* pEnv, jsize len); + jintArray (JNICALL *NewIntArray)(JNIEnv* pEnv, jsize len); + jlongArray (JNICALL *NewLongArray)(JNIEnv* pEnv, jsize len); + jfloatArray (JNICALL *NewFloatArray)(JNIEnv* pEnv, jsize len); + jdoubleArray (JNICALL *NewDoubleArray)(JNIEnv* pEnv, jsize len); + + jboolean * (JNICALL *GetBooleanArrayElements)(JNIEnv* pEnv, jbooleanArray array, jboolean *isCopy); + jbyte * (JNICALL *GetByteArrayElements)(JNIEnv* pEnv, jbyteArray array, jboolean *isCopy); + jchar * (JNICALL *GetCharArrayElements)(JNIEnv* pEnv, jcharArray array, jboolean *isCopy); + jshort * (JNICALL *GetShortArrayElements)(JNIEnv* pEnv, jshortArray array, jboolean *isCopy); + jint * (JNICALL *GetIntArrayElements)(JNIEnv* pEnv, jintArray array, jboolean *isCopy); + jlong * (JNICALL *GetLongArrayElements)(JNIEnv* pEnv, jlongArray array, jboolean *isCopy); + jfloat * (JNICALL *GetFloatArrayElements)(JNIEnv* pEnv, jfloatArray array, jboolean *isCopy); + jdouble * (JNICALL *GetDoubleArrayElements)(JNIEnv* pEnv, jdoubleArray array, jboolean *isCopy); + + void (JNICALL *ReleaseBooleanArrayElements)(JNIEnv* pEnv, jbooleanArray array, jboolean *elems, jint mode); + void (JNICALL *ReleaseByteArrayElements)(JNIEnv* pEnv, jbyteArray array, jbyte *elems, jint mode); + void (JNICALL *ReleaseCharArrayElements)(JNIEnv* pEnv, jcharArray array, jchar *elems, jint mode); + void (JNICALL *ReleaseShortArrayElements)(JNIEnv* pEnv, jshortArray array, jshort *elems, jint mode); + void (JNICALL *ReleaseIntArrayElements)(JNIEnv* pEnv, jintArray array, jint *elems, jint mode); + void (JNICALL *ReleaseLongArrayElements)(JNIEnv* pEnv, jlongArray array, jlong *elems, jint mode); + void (JNICALL *ReleaseFloatArrayElements)(JNIEnv* pEnv, jfloatArray array, jfloat *elems, jint mode); + void (JNICALL *ReleaseDoubleArrayElements)(JNIEnv* pEnv, jdoubleArray array, jdouble *elems, jint mode); + + void (JNICALL *GetBooleanArrayRegion)(JNIEnv* pEnv, jbooleanArray array, jsize start, jsize l, jboolean *buf); + void (JNICALL *GetByteArrayRegion)(JNIEnv* pEnv, jbyteArray array, jsize start, jsize len, jbyte *buf); + void (JNICALL *GetCharArrayRegion)(JNIEnv* pEnv, jcharArray array, jsize start, jsize len, jchar *buf); + void (JNICALL *GetShortArrayRegion)(JNIEnv* pEnv, jshortArray array, jsize start, jsize len, jshort *buf); + void (JNICALL *GetIntArrayRegion)(JNIEnv* pEnv, jintArray array, jsize start, jsize len, jint *buf); + void (JNICALL *GetLongArrayRegion)(JNIEnv* pEnv, jlongArray array, jsize start, jsize len, jlong *buf); + void (JNICALL *GetFloatArrayRegion)(JNIEnv* pEnv, jfloatArray array, jsize start, jsize len, jfloat *buf); + void (JNICALL *GetDoubleArrayRegion)(JNIEnv* pEnv, jdoubleArray array, jsize start, jsize len, jdouble *buf); + + void (JNICALL *SetBooleanArrayRegion)(JNIEnv* pEnv, jbooleanArray array, jsize start, jsize l, jboolean *buf); + void (JNICALL *SetByteArrayRegion)(JNIEnv* pEnv, jbyteArray array, jsize start, jsize len, jbyte *buf); + void (JNICALL *SetCharArrayRegion)(JNIEnv* pEnv, jcharArray array, jsize start, jsize len, jchar *buf); + void (JNICALL *SetShortArrayRegion)(JNIEnv* pEnv, jshortArray array, jsize start, jsize len, jshort *buf); + void (JNICALL *SetIntArrayRegion)(JNIEnv* pEnv, jintArray array, jsize start, jsize len, jint *buf); + void (JNICALL *SetLongArrayRegion)(JNIEnv* pEnv, jlongArray array, jsize start, jsize len, jlong *buf); + void (JNICALL *SetFloatArrayRegion)(JNIEnv* pEnv, jfloatArray array, jsize start, jsize len, jfloat *buf); + void (JNICALL *SetDoubleArrayRegion)(JNIEnv* pEnv, jdoubleArray array, jsize start, jsize len, jdouble *buf); + + jint (JNICALL *RegisterNatives)(JNIEnv* pEnv, jclass clazz, const JNINativeMethod *methods, jint nMethods); + jint (JNICALL *UnregisterNatives)(JNIEnv* pEnv, jclass clazz); + + jint (JNICALL *MonitorEnter)(JNIEnv* pEnv, jobject obj); + jint (JNICALL *MonitorExit)(JNIEnv* pEnv, jobject obj); + + jint (JNICALL *GetJavaVM)(JNIEnv* pEnv, JavaVM **vm); + + void (JNICALL *GetStringRegion)(JNIEnv* pEnv, jstring str, jsize start, jsize len, jchar *buf); + void (JNICALL *GetStringUTFRegion)(JNIEnv* pEnv, jstring str, jsize start, jsize len, char *buf); + + void* (JNICALL *GetPrimitiveArrayCritical)(JNIEnv* pEnv, jarray array, jboolean *isCopy); + void (JNICALL *ReleasePrimitiveArrayCritical)(JNIEnv* pEnv, jarray array, void *carray, jint mode); + + const jchar* (JNICALL *GetStringCritical)(JNIEnv* pEnv, jstring string, jboolean *isCopy); + void (JNICALL *ReleaseStringCritical)(JNIEnv* pEnv, jstring string, const jchar *cstring); + + jweak (JNICALL *NewWeakGlobalRef)(JNIEnv* pEnv, jobject obj); + void (JNICALL *DeleteWeakGlobalRef)(JNIEnv* pEnv, jweak ref); + + jboolean (JNICALL *ExceptionCheck)(JNIEnv* pEnv); + + jobject (JNICALL *NewDirectByteBuffer)(JNIEnv* pEnv, void* address, jlong capacity); + void* (JNICALL *GetDirectBufferAddress)(JNIEnv* pEnv, jobject buf); + jlong (JNICALL *GetDirectBufferCapacity)(JNIEnv* pEnv, jobject buf); +}; + +#endif //__JNI_H__ diff --git a/native/native.build b/native/native.build new file mode 100644 index 00000000..c35fc9af --- /dev/null +++ b/native/native.build @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jni/clr-win32/IKVM.JNI.CLR-Win32.vcproj b/native/native.vcproj similarity index 56% rename from jni/clr-win32/IKVM.JNI.CLR-Win32.vcproj rename to native/native.vcproj index e8997250..82f553c8 100644 --- a/jni/clr-win32/IKVM.JNI.CLR-Win32.vcproj +++ b/native/native.vcproj @@ -2,9 +2,9 @@ + Name="ikvm-native" + ProjectGUID="{14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}" + Keyword="Win32Proj"> @@ -15,27 +15,29 @@ OutputDirectory="Debug" IntermediateDirectory="Debug" ConfigurationType="2" - CharacterSet="2" - ManagedExtensions="TRUE"> + CharacterSet="2"> + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="4"/> + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(OutDir)/native.pdb" + SubSystem="2" + ImportLibrary="$(OutDir)/native.lib" + TargetMachine="1"/> + CharacterSet="2"> + GenerateDebugInformation="TRUE" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + ImportLibrary="$(OutDir)/native.lib" + TargetMachine="1"/> - + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + RelativePath=".\jni.c"> - - - - - - - - - - + RelativePath=".\os.c"> + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> - - - - + RelativePath=".\jni.h"> + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> diff --git a/native/os.c b/native/os.c new file mode 100644 index 00000000..55ecd378 --- /dev/null +++ b/native/os.c @@ -0,0 +1,73 @@ +/* + Copyright (C) 2004 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +#ifdef _WIN32 + #include + #include "jni.h" + + JNIEXPORT void* JNICALL ikvm_LoadLibrary(char* psz) + { + return LoadLibrary(psz); + } + + JNIEXPORT void JNICALL ikvm_FreeLibrary(HMODULE handle) + { + FreeLibrary(handle); + } + + JNIEXPORT void* JNICALL ikvm_GetProcAddress(HMODULE handle, char* name, jint argc) + { + char buf[512]; + if(strlen(name) > sizeof(buf) - 11) + { + return 0; + } + wsprintf(buf, "_%s@%d", name, argc); + return GetProcAddress(handle, buf); + } +#else + #include + #include "jni.h" + + JNIEXPORT void* JNICALL ikvm_LoadLibrary(char* psz) + { + return g_module_open(psz, 0); + } + + JNIEXPORT void JNICALL ikvm_FreeLibrary(GModule* handle) + { + g_module_close(handle); + } + + JNIEXPORT void* JNICALL ikvm_GetProcAddress(GModule* handle, char* name, jint argc) + { + void *symbol; + + gboolean res = g_module_symbol(handle, name, &symbol); + + if (res) + return symbol; + else + return NULL; + } +#endif diff --git a/runtime/BigEndianBinaryReader.cs b/runtime/BigEndianBinaryReader.cs index 71d3a17c..07a99eff 100644 --- a/runtime/BigEndianBinaryReader.cs +++ b/runtime/BigEndianBinaryReader.cs @@ -28,30 +28,26 @@ sealed class BigEndianBinaryReader { private byte[] buf; private int pos; + private int end; - internal BigEndianBinaryReader(byte[] buf) - : this(buf, 0) - { - } - - internal BigEndianBinaryReader(byte[] buf, int offset) + internal BigEndianBinaryReader(byte[] buf, int offset, int length) { this.buf = buf; this.pos = offset; + this.end = checked(offset + length); + if(offset < 0 || length < 0 || buf.Length - offset < length) + { + throw new ClassFormatError("Truncated class file"); + } } - internal BigEndianBinaryReader Section(int length) + internal BigEndianBinaryReader Section(uint length) { - BigEndianBinaryReader br = new BigEndianBinaryReader(buf, pos); - pos += length; + BigEndianBinaryReader br = new BigEndianBinaryReader(buf, pos, checked((int)length)); + Skip(length); return br; } - internal BigEndianBinaryReader Duplicate() - { - return new BigEndianBinaryReader(buf, pos); - } - internal int Position { get @@ -60,18 +56,33 @@ sealed class BigEndianBinaryReader } } - internal void Skip(int count) + internal void Skip(uint count) { - pos += count; + if(end - pos < count) + { + throw new ClassFormatError("Truncated class file"); + } + checked + { + pos += (int)count; + } } internal byte ReadByte() { + if(pos == end) + { + throw new ClassFormatError("Truncated class file"); + } return buf[pos++]; } internal sbyte ReadSByte() { + if(pos == end) + { + throw new ClassFormatError("Truncated class file"); + } return (sbyte)buf[pos++]; } @@ -82,6 +93,10 @@ sealed class BigEndianBinaryReader internal short ReadInt16() { + if(end - pos < 2) + { + throw new ClassFormatError("Truncated class file"); + } short s = (short)((buf[pos] << 8) + buf[pos + 1]); pos += 2; return s; @@ -89,6 +104,10 @@ sealed class BigEndianBinaryReader internal int ReadInt32() { + if(end - pos < 4) + { + throw new ClassFormatError("Truncated class file"); + } int i = (int)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]); pos += 4; return i; @@ -96,6 +115,10 @@ sealed class BigEndianBinaryReader internal long ReadInt64() { + if(end - pos < 8) + { + throw new ClassFormatError("Truncated class file"); + } uint i1 = (uint)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]); uint i2 = (uint)((buf[pos + 4] << 24) + (buf[pos + 5] << 16) + (buf[pos + 6] << 8) + buf[pos + 7]); long l = (((long)i1) << 32) + i2; @@ -111,6 +134,10 @@ sealed class BigEndianBinaryReader internal string ReadString() { int len = ReadUInt16(); + if(end - pos < len) + { + throw new ClassFormatError("Truncated class file"); + } // special code path for ASCII strings (which occur *very* frequently) for(int j = 0; j < len; j++) { @@ -129,7 +156,7 @@ sealed class BigEndianBinaryReader case 0: if(c == 0) { - throw new FormatException(); + throw new ClassFormatError("Illegal UTF8 string in constant pool"); } break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: @@ -140,7 +167,7 @@ sealed class BigEndianBinaryReader char2 = buf[pos + ++i]; if((char2 & 0xc0) != 0x80) { - throw new FormatException(); + throw new ClassFormatError("Illegal UTF8 string in constant pool"); } c = (((c & 0x1F) << 6) | (char2 & 0x3F)); break; @@ -150,12 +177,12 @@ sealed class BigEndianBinaryReader char3 = buf[pos + ++i]; if((char2 & 0xc0) != 0x80 || (char3 & 0xc0) != 0x80) { - throw new FormatException(); + throw new ClassFormatError("Illegal UTF8 string in constant pool"); } c = (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; default: - throw new FormatException(); + throw new ClassFormatError("Illegal UTF8 string in constant pool"); } ch[l++] = (char)c; } @@ -170,6 +197,10 @@ sealed class BigEndianBinaryReader internal ushort ReadUInt16() { + if(end - pos < 2) + { + throw new ClassFormatError("Truncated class file"); + } ushort s = (ushort)((buf[pos] << 8) + buf[pos + 1]); pos += 2; return s; @@ -177,6 +208,10 @@ sealed class BigEndianBinaryReader internal uint ReadUInt32() { + if(end - pos < 4) + { + throw new ClassFormatError("Truncated class file"); + } uint i = (uint)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]); pos += 4; return i; diff --git a/runtime/ByteCode.cs b/runtime/ByteCode.cs index 8862a94b..da3bd1f0 100644 --- a/runtime/ByteCode.cs +++ b/runtime/ByteCode.cs @@ -23,7 +23,7 @@ */ using System; -enum ByteCode +enum ByteCode : byte { __nop = 0, __aconst_null = 1, @@ -229,11 +229,11 @@ enum ByteCode __jsr_w = 201 } -enum NormalizedByteCode +enum NormalizedByteCode : byte { __nop = 0, __aconst_null = 1, - __iconst = -1, + __iconst = 255, __lconst_0 = 9, __lconst_1 = 10, __fconst_0 = 11, @@ -380,7 +380,7 @@ enum NormalizedByteCode __ifnonnull = 199, } -enum ByteCodeMode +enum ByteCodeMode : byte { Unused, Simple, @@ -388,58 +388,80 @@ enum ByteCodeMode Constant_2, Branch_2, Local_1, - Local_2, Constant_2_1_1, Immediate_1, Immediate_2, Local_1_Immediate_1, - Local_2_Immediate_2, Tableswitch, Lookupswitch, Constant_2_Immediate_1, - Branch_4 + Branch_4, + WidePrefix +} + +enum ByteCodeModeWide : byte +{ + Unused, + Local_2, + Local_2_Immediate_2 +} + +[Flags] +enum ByteCodeFlags : byte +{ + None = 0, + FixedArg = 1, + CannotThrow = 2 } struct ByteCodeMetaData { private static ByteCodeMetaData[] data = new ByteCodeMetaData[202]; private ByteCodeMode reg; - private ByteCodeMode wide; + private ByteCodeModeWide wide; private NormalizedByteCode normbc; + private ByteCodeFlags flags; private int arg; - private bool hasFixedArg; - private bool cannotThrow; - private ByteCodeMetaData(ByteCode bc, ByteCodeMode reg, ByteCodeMode wide, bool cannotThrow) + private ByteCodeMetaData(ByteCode bc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) { this.reg = reg; this.wide = wide; - this.normbc = (NormalizedByteCode)Enum.Parse(typeof(NormalizedByteCode), bc.ToString()); + this.normbc = (NormalizedByteCode)bc; this.arg = 0; - this.hasFixedArg = false; - this.cannotThrow = cannotThrow; + this.flags = ByteCodeFlags.None; + if(cannotThrow) + { + this.flags |= ByteCodeFlags.CannotThrow; + } data[(int)bc] = this; } - private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, ByteCodeMode reg, ByteCodeMode wide, bool cannotThrow) + private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) { this.reg = reg; this.wide = wide; this.normbc = normbc; this.arg = 0; - this.hasFixedArg = false; - this.cannotThrow = cannotThrow; + this.flags = ByteCodeFlags.None; + if(cannotThrow) + { + this.flags |= ByteCodeFlags.CannotThrow; + } data[(int)bc] = this; } - private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, int arg, ByteCodeMode reg, ByteCodeMode wide, bool cannotThrow) + private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, int arg, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) { this.reg = reg; this.wide = wide; this.normbc = normbc; this.arg = arg; - this.hasFixedArg = true; - this.cannotThrow = cannotThrow; + this.flags = ByteCodeFlags.FixedArg; + if(cannotThrow) + { + this.flags |= ByteCodeFlags.CannotThrow; + } data[(int)bc] = this; } @@ -450,7 +472,7 @@ struct ByteCodeMetaData internal static int GetArg(ByteCode bc, int arg) { - if(data[(int)bc].hasFixedArg) + if((data[(int)bc].flags & ByteCodeFlags.FixedArg) != 0) { return data[(int)bc].arg; } @@ -462,224 +484,219 @@ struct ByteCodeMetaData return data[(int)bc].reg; } - internal static ByteCodeMode GetWideMode(ByteCode bc) + internal static ByteCodeModeWide GetWideMode(ByteCode bc) { - ByteCodeMode m = data[(int)bc].wide; - if(m == ByteCodeMode.Unused) - { - throw new ArgumentException("Wide version of " + bc + " is not a valid instruction", "bc"); - } - return m; + return data[(int)bc].wide; } internal static bool CanThrowException(ByteCode bc) { - return !data[(int)bc].cannotThrow; + return (data[(int)bc].flags & ByteCodeFlags.CannotThrow) == 0; } static ByteCodeMetaData() { - new ByteCodeMetaData(ByteCode.__nop, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__aconst_null, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_m1, NormalizedByteCode.__iconst, -1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_0, NormalizedByteCode.__iconst, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_1, NormalizedByteCode.__iconst, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_2, NormalizedByteCode.__iconst, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_3, NormalizedByteCode.__iconst, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_4, NormalizedByteCode.__iconst, 4, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_5, NormalizedByteCode.__iconst, 5, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lconst_0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lconst_1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fconst_0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fconst_1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fconst_2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dconst_0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dconst_1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__bipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__sipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ldc, ByteCodeMode.Constant_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ldc_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ldc2_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iload, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lload, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fload, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dload, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__aload, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iload_0, NormalizedByteCode.__iload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iload_1, NormalizedByteCode.__iload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iload_2, NormalizedByteCode.__iload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iload_3, NormalizedByteCode.__iload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lload_0, NormalizedByteCode.__lload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lload_1, NormalizedByteCode.__lload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lload_2, NormalizedByteCode.__lload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lload_3, NormalizedByteCode.__lload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fload_0, NormalizedByteCode.__fload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fload_1, NormalizedByteCode.__fload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fload_2, NormalizedByteCode.__fload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fload_3, NormalizedByteCode.__fload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dload_0, NormalizedByteCode.__dload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dload_1, NormalizedByteCode.__dload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dload_2, NormalizedByteCode.__dload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dload_3, NormalizedByteCode.__dload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__aload_0, NormalizedByteCode.__aload, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__aload_1, NormalizedByteCode.__aload, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__aload_2, NormalizedByteCode.__aload, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__aload_3, NormalizedByteCode.__aload, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iaload, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__laload, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__faload, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__daload, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__aaload, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__baload, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__caload, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__saload, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__istore, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lstore, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fstore, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dstore, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__astore, ByteCodeMode.Local_1, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__istore_0, NormalizedByteCode.__istore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__istore_1, NormalizedByteCode.__istore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__istore_2, NormalizedByteCode.__istore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__istore_3, NormalizedByteCode.__istore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lstore_0, NormalizedByteCode.__lstore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lstore_1, NormalizedByteCode.__lstore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lstore_2, NormalizedByteCode.__lstore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lstore_3, NormalizedByteCode.__lstore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fstore_0, NormalizedByteCode.__fstore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fstore_1, NormalizedByteCode.__fstore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fstore_2, NormalizedByteCode.__fstore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fstore_3, NormalizedByteCode.__fstore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dstore_0, NormalizedByteCode.__dstore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dstore_1, NormalizedByteCode.__dstore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dstore_2, NormalizedByteCode.__dstore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dstore_3, NormalizedByteCode.__dstore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__astore_0, NormalizedByteCode.__astore, 0, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__astore_1, NormalizedByteCode.__astore, 1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__astore_2, NormalizedByteCode.__astore, 2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__astore_3, NormalizedByteCode.__astore, 3, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iastore, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__lastore, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__fastore, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__dastore, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__aastore, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__bastore, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__castore, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__sastore, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__pop, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__pop2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dup, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dup_x1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dup_x2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dup2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dup2_x1, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dup2_x2, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__swap, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iadd, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ladd, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fadd, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dadd, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__isub, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lsub, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fsub, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dsub, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__imul, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lmul, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fmul, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dmul, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__idiv, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ldiv, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fdiv, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ddiv, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__irem, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lrem, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__frem, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__drem, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ineg, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lneg, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fneg, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dneg, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ishl, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lshl, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ishr, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lshr, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iushr, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lushr, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iand, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__land, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ior, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lor, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ixor, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lxor, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iinc, ByteCodeMode.Local_1_Immediate_1, ByteCodeMode.Local_2_Immediate_2, true); - new ByteCodeMetaData(ByteCode.__i2l, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__i2f, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__i2d, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__l2i, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__l2f, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__l2d, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__f2i, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__f2l, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__f2d, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__d2i, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__d2l, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__d2f, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__i2b, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__i2c, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__i2s, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lcmp, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fcmpl, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__fcmpg, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dcmpl, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dcmpg, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ifeq, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ifne, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__iflt, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ifge, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ifgt, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ifle, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmpeq, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmpne, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmplt, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmpge, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmpgt, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmple, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__if_acmpeq, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__if_acmpne, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__goto, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__jsr, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ret, ByteCodeMode.Local_1, ByteCodeMode.Local_2, true); - new ByteCodeMetaData(ByteCode.__tableswitch, NormalizedByteCode.__lookupswitch, ByteCodeMode.Tableswitch, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lookupswitch, ByteCodeMode.Lookupswitch, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ireturn, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__lreturn, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__freturn, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__dreturn, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__areturn, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__return, ByteCodeMode.Simple, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__getstatic, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__putstatic, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__getfield, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__putfield, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__invokevirtual, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__invokespecial, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__invokestatic, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__invokeinterface, ByteCodeMode.Constant_2_1_1, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__xxxunusedxxx, NormalizedByteCode.__nop, ByteCodeMode.Unused, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__new, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__newarray, ByteCodeMode.Immediate_1, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__anewarray, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__arraylength, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__athrow, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__checkcast, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__instanceof, ByteCodeMode.Constant_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__monitorenter, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__monitorexit, ByteCodeMode.Simple, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__wide, NormalizedByteCode.__nop, ByteCodeMode.Unused, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__multianewarray, ByteCodeMode.Constant_2_Immediate_1, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__ifnull, ByteCodeMode.Branch_2, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__ifnonnull, ByteCodeMode.Branch_2, ByteCodeMode.Unused, false); - new ByteCodeMetaData(ByteCode.__goto_w, NormalizedByteCode.__goto, ByteCodeMode.Branch_4, ByteCodeMode.Unused, true); - new ByteCodeMetaData(ByteCode.__jsr_w, NormalizedByteCode.__jsr, ByteCodeMode.Branch_4, ByteCodeMode.Unused, true); + new ByteCodeMetaData(ByteCode.__nop, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aconst_null, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_m1, NormalizedByteCode.__iconst, -1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_0, NormalizedByteCode.__iconst, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_1, NormalizedByteCode.__iconst, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_2, NormalizedByteCode.__iconst, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_3, NormalizedByteCode.__iconst, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_4, NormalizedByteCode.__iconst, 4, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_5, NormalizedByteCode.__iconst, 5, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fconst_2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__bipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_1, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__sipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ldc, ByteCodeMode.Constant_1, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ldc_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ldc2_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__lload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__fload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__dload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__aload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__iload_0, NormalizedByteCode.__iload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload_1, NormalizedByteCode.__iload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload_2, NormalizedByteCode.__iload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload_3, NormalizedByteCode.__iload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_0, NormalizedByteCode.__lload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_1, NormalizedByteCode.__lload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_2, NormalizedByteCode.__lload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_3, NormalizedByteCode.__lload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_0, NormalizedByteCode.__fload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_1, NormalizedByteCode.__fload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_2, NormalizedByteCode.__fload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_3, NormalizedByteCode.__fload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_0, NormalizedByteCode.__dload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_1, NormalizedByteCode.__dload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_2, NormalizedByteCode.__dload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_3, NormalizedByteCode.__dload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_0, NormalizedByteCode.__aload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_1, NormalizedByteCode.__aload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_2, NormalizedByteCode.__aload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_3, NormalizedByteCode.__aload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iaload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__laload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__faload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__daload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__aaload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__baload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__caload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__saload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__istore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__lstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__fstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__dstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__astore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__istore_0, NormalizedByteCode.__istore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__istore_1, NormalizedByteCode.__istore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__istore_2, NormalizedByteCode.__istore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__istore_3, NormalizedByteCode.__istore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_0, NormalizedByteCode.__lstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_1, NormalizedByteCode.__lstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_2, NormalizedByteCode.__lstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_3, NormalizedByteCode.__lstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_0, NormalizedByteCode.__fstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_1, NormalizedByteCode.__fstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_2, NormalizedByteCode.__fstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_3, NormalizedByteCode.__fstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_0, NormalizedByteCode.__dstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_1, NormalizedByteCode.__dstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_2, NormalizedByteCode.__dstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_3, NormalizedByteCode.__dstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_0, NormalizedByteCode.__astore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_1, NormalizedByteCode.__astore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_2, NormalizedByteCode.__astore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_3, NormalizedByteCode.__astore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__lastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__fastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__dastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__aastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__bastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__castore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__sastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__pop, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__pop2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup_x1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup_x2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup2_x1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup2_x2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__swap, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ladd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__isub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__imul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__idiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ldiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fdiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ddiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__irem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lrem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__frem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__drem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ineg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ishl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lshl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ishr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lshr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iushr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lushr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iand, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__land, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ior, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ixor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lxor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iinc, ByteCodeMode.Local_1_Immediate_1, ByteCodeModeWide.Local_2_Immediate_2, true); + new ByteCodeMetaData(ByteCode.__i2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__l2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__l2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__l2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__f2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__f2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__f2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__d2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__d2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__d2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2b, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2c, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2s, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lcmp, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fcmpl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fcmpg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dcmpl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dcmpg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iflt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifge, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifgt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifle, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmplt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpge, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpgt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmple, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_acmpeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_acmpne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__goto, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__jsr, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ret, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__tableswitch, NormalizedByteCode.__lookupswitch, ByteCodeMode.Tableswitch, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lookupswitch, ByteCodeMode.Lookupswitch, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ireturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lreturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__freturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dreturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__areturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__return, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__getstatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__putstatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__getfield, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__putfield, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokevirtual, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokespecial, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokestatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokeinterface, ByteCodeMode.Constant_2_1_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__xxxunusedxxx, NormalizedByteCode.__nop, ByteCodeMode.Unused, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__new, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__newarray, ByteCodeMode.Immediate_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__anewarray, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__arraylength, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__athrow, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__checkcast, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__instanceof, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__monitorenter, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__monitorexit, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__wide, NormalizedByteCode.__nop, ByteCodeMode.WidePrefix, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__multianewarray, ByteCodeMode.Constant_2_Immediate_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__ifnull, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifnonnull, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__goto_w, NormalizedByteCode.__goto, ByteCodeMode.Branch_4, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__jsr_w, NormalizedByteCode.__jsr, ByteCodeMode.Branch_4, ByteCodeModeWide.Unused, true); } } diff --git a/runtime/ClassFile.cs b/runtime/ClassFile.cs index 890379c7..15a8a7f0 100644 --- a/runtime/ClassFile.cs +++ b/runtime/ClassFile.cs @@ -24,28 +24,32 @@ using System; using System.IO; using System.Collections; +// MONOBUG mcs 1.0 still has problems resolving properties vs. type names +using __Modifiers = Modifiers; class ClassFile { private ConstantPoolItem[] constantpool; + private string[] utf8_cp; private Modifiers access_flags; private ConstantPoolItemClass this_cpi; private ConstantPoolItemClass super_cpi; private ConstantPoolItemClass[] interfaces; private Field[] fields; private Method[] methods; - private Attribute[] attributes; private string sourceFile; - private bool sourceFileCached; private ClassFile outerClass; - private int majorVersion; + private ushort majorVersion; + private bool deprecated; + private string ikvmAssembly; + private InnerClass[] innerClasses; private static readonly char[] illegalcharacters = { '<', '>' }; - internal ClassFile(byte[] buf, int offset, int length, string inputClassName) + internal ClassFile(byte[] buf, int offset, int length, string inputClassName, bool allowJavaLangObject) { try { - BigEndianBinaryReader br = new BigEndianBinaryReader(buf, offset); + BigEndianBinaryReader br = new BigEndianBinaryReader(buf, offset, length); if(br.ReadUInt32() != 0xCAFEBABE) { throw new ClassFormatError("Bad magic number"); @@ -56,16 +60,51 @@ class ClassFile { throw new UnsupportedClassVersionError(majorVersion + "." + minorVersion); } - Hashtable classCache = new Hashtable(); int constantpoolcount = br.ReadUInt16(); constantpool = new ConstantPoolItem[constantpoolcount]; + utf8_cp = new string[constantpoolcount]; for(int i = 1; i < constantpoolcount; i++) { - constantpool[i] = ConstantPoolItem.Read(inputClassName, classCache, br); - // LONG and DOUBLE items take up two slots... - if(constantpool[i].IsWide) + Constant tag = (Constant)br.ReadByte(); + switch(tag) { - i++; + case Constant.Class: + constantpool[i] = new ConstantPoolItemClass(br); + break; + case Constant.Double: + constantpool[i] = new ConstantPoolItemDouble(br); + i++; + break; + case Constant.Fieldref: + constantpool[i] = new ConstantPoolItemFieldref(br); + break; + case Constant.Float: + constantpool[i] = new ConstantPoolItemFloat(br); + break; + case Constant.Integer: + constantpool[i] = new ConstantPoolItemInteger(br); + break; + case Constant.InterfaceMethodref: + constantpool[i] = new ConstantPoolItemInterfaceMethodref(br); + break; + case Constant.Long: + constantpool[i] = new ConstantPoolItemLong(br); + i++; + break; + case Constant.Methodref: + constantpool[i] = new ConstantPoolItemMethodref(br); + break; + case Constant.NameAndType: + constantpool[i] = new ConstantPoolItemNameAndType(br); + break; + case Constant.String: + constantpool[i] = new ConstantPoolItemString(br); + break; + case Constant.Utf8: + utf8_cp[i] = br.ReadString(); + break; + default: + throw new ClassFormatError("{0} (Illegal constant pool type 0x{1:X})", inputClassName, tag); } } for(int i = 1; i < constantpoolcount; i++) @@ -119,7 +158,7 @@ class ClassFile } else { - if(this.Name != "java.lang.Object") + if(this.Name != "java.lang.Object" || !allowJavaLangObject) { throw new ClassFormatError("{0} (Bad superclass index)", Name); } @@ -135,8 +174,7 @@ class ClassFile } int interfaces_count = br.ReadUInt16(); interfaces = new ConstantPoolItemClass[interfaces_count]; - Hashtable interfaceNames = new Hashtable(); - for(int i = 0; i < interfaces_count; i++) + for(int i = 0; i < interfaces.Length; i++) { int index = br.ReadUInt16(); if(index == 0 || index >= constantpool.Length) @@ -148,39 +186,43 @@ class ClassFile { throw new ClassFormatError("{0} (Interface name has bad constant type)", Name); } - interfaces[i] = (ConstantPoolItemClass)GetConstantPoolItem(index); - if(interfaceNames.ContainsKey(interfaces[i])) + interfaces[i] = cpi; + for(int j = 0; j < i; j++) { - throw new ClassFormatError("{0} (Repetitive interface name)", Name); + if(interfaces[j].Name == cpi.Name) + { + throw new ClassFormatError("{0} (Repetitive interface name)", Name); + } } - interfaceNames.Add(interfaces[i], interfaces[i]); } int fields_count = br.ReadUInt16(); fields = new Field[fields_count]; Hashtable fieldNameSigs = new Hashtable(); for(int i = 0; i < fields_count; i++) { - fields[i] = new Field(this, classCache, br); + fields[i] = new Field(this, br); string name = fields[i].Name; - // NOTE It's not in the vmspec (as far as I can tell), but Sun's VM doens't allow names that + // NOTE It's not in the vmspec (as far as I can tell), but Sun's VM doesn't allow names that // contain '<' or '>' if(name.Length == 0 || name.IndexOfAny(illegalcharacters) != -1) { throw new ClassFormatError("{0} (Illegal field name \"{1}\")", Name, name); } - string nameSig = name + fields[i].Signature; - if(fieldNameSigs.ContainsKey(nameSig)) + try + { + fieldNameSigs.Add(name + fields[i].Signature, null); + } + catch(ArgumentException) { throw new ClassFormatError("{0} (Repetitive field name/signature)", Name); } - fieldNameSigs.Add(nameSig, nameSig); } int methods_count = br.ReadUInt16(); methods = new Method[methods_count]; Hashtable methodNameSigs = new Hashtable(); for(int i = 0; i < methods_count; i++) { - methods[i] = new Method(this, classCache, br); + methods[i] = new Method(this, br); string name = methods[i].Name; string sig = methods[i].Signature; if(name.Length == 0 || (name.IndexOfAny(illegalcharacters) != -1 && name != "" && name != "")) @@ -191,29 +233,61 @@ class ClassFile { throw new ClassFormatError("{0} (Method \"{1}\" has illegal signature \"{2}\")", Name, name, sig); } - string nameSig = name + sig; - if(methodNameSigs.ContainsKey(nameSig)) + try + { + methodNameSigs.Add(name + sig, null); + } + catch(ArgumentException) { throw new ClassFormatError("{0} (Repetitive method name/signature)", Name); } - methodNameSigs.Add(nameSig, nameSig); } int attributes_count = br.ReadUInt16(); - attributes = new Attribute[attributes_count]; for(int i = 0; i < attributes_count; i++) { - attributes[i] = Attribute.Read(this, br); + switch(GetConstantPoolUtf8String(br.ReadUInt16())) + { + case "Deprecated": + deprecated = true; + if(br.ReadUInt32() != 0) + { + throw new ClassFormatError("Deprecated attribute has non-zero length"); + } + break; + case "SourceFile": + if(br.ReadUInt32() != 2) + { + throw new ClassFormatError("SourceFile attribute has incorrect length"); + } + sourceFile = GetConstantPoolUtf8String(br.ReadUInt16()); + break; + case "InnerClasses": + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + ushort count = rdr.ReadUInt16(); + innerClasses = new InnerClass[count]; + for(int j = 0; j < innerClasses.Length; j++) + { + innerClasses[j].innerClass = rdr.ReadUInt16(); + innerClasses[j].outerClass = rdr.ReadUInt16(); + innerClasses[j].name = rdr.ReadUInt16(); + innerClasses[j].accessFlags = (Modifiers)rdr.ReadUInt16(); + } + break; + case "IKVM.NET.Assembly": + if(br.ReadUInt32() != 2) + { + throw new ClassFormatError("IKVM.NET.Assembly attribute has incorrect length"); + } + ikvmAssembly = GetConstantPoolUtf8String(br.ReadUInt16()); + break; + default: + br.Skip(br.ReadUInt32()); + break; + } } if(br.Position != offset + length) { - if(br.Position > offset + length) - { - throw new ClassFormatError("Truncated class file"); - } - else - { - throw new ClassFormatError("Extra bytes at the end of the class file"); - } + throw new ClassFormatError("Extra bytes at the end of the class file"); } } catch(IndexOutOfRangeException) @@ -251,13 +325,13 @@ class ClassFile } } - internal void Link(TypeWrapper thisType) + internal void Link(TypeWrapper thisType, Hashtable classCache) { for(int i = 1; i < constantpool.Length; i++) { if(constantpool[i] != null) { - constantpool[i].Link(thisType); + constantpool[i].Link(thisType, classCache); } } } @@ -331,9 +405,9 @@ class ClassFile return ((ConstantPoolItemClass)constantpool[index]).Name; } - internal TypeWrapper GetConstantPoolClassType(int index, ClassLoaderWrapper classLoader) + internal TypeWrapper GetConstantPoolClassType(int index) { - return ((ConstantPoolItemClass)constantpool[index]).GetClassType(classLoader); + return ((ConstantPoolItemClass)constantpool[index]).GetClassType(); } private string GetConstantPoolString(int index) @@ -341,14 +415,9 @@ class ClassFile return ((ConstantPoolItemString)constantpool[index]).Value; } - private ConstantPoolItemUtf8 GetConstantPoolUtf8(int index) - { - return ((ConstantPoolItemUtf8)constantpool[index]); - } - internal string GetConstantPoolUtf8String(int index) { - return GetConstantPoolUtf8(index).Value; + return utf8_cp[index]; } internal ConstantType GetConstantPoolConstantType(int index) @@ -389,20 +458,6 @@ class ClassFile } } - internal string PackageName - { - get - { - string name = Name; - int index = name.LastIndexOf('.'); - if(index == -1) - { - return ""; - } - return name.Substring(0, index); - } - } - internal string SuperClass { get @@ -435,31 +490,10 @@ class ClassFile } } - private Attribute GetAttribute(string name) - { - for(int i = 0; i < attributes.Length; i++) - { - if(attributes[i].Name == name) - { - return attributes[i]; - } - } - return null; - } - internal string SourceFileAttribute { get { - if(!sourceFileCached) - { - sourceFileCached = true; - Attribute attr = GetAttribute("SourceFile"); - if(attr != null) - { - sourceFile = ((ConstantPoolItemUtf8)GetConstantPoolItem(attr.Data.ReadUInt16())).Value; - } - } return sourceFile; } } @@ -468,12 +502,7 @@ class ClassFile { get { - Attribute attr = GetAttribute("IKVM.NET.Assembly"); - if(attr != null) - { - return ((ConstantPoolItemUtf8)GetConstantPoolItem(attr.Data.ReadUInt16())).Value; - } - return null; + return ikvmAssembly; } } @@ -481,15 +510,15 @@ class ClassFile { get { - return GetAttribute("Deprecated") != null; + return deprecated; } } internal struct InnerClass { - internal int innerClass; // ConstantPoolItemClass - internal int outerClass; // ConstantPoolItemClass - internal int name; // ConstantPoolItemUtf8 + internal ushort innerClass; // ConstantPoolItemClass + internal ushort outerClass; // ConstantPoolItemClass + internal ushort name; // ConstantPoolItemUtf8 internal Modifiers accessFlags; } @@ -497,22 +526,7 @@ class ClassFile { get { - Attribute attr = GetAttribute("InnerClasses"); - if(attr != null) - { - BigEndianBinaryReader rdr = attr.Data; - ushort count = rdr.ReadUInt16(); - InnerClass[] list = new InnerClass[count]; - for(int i = 0; i < list.Length; i++) - { - list[i].innerClass = rdr.ReadUInt16(); - list[i].outerClass = rdr.ReadUInt16(); - list[i].name = rdr.ReadUInt16(); - list[i].accessFlags = (Modifiers)rdr.ReadUInt16(); - } - return list; - } - return null; + return innerClasses; } } @@ -528,19 +542,11 @@ class ClassFile internal abstract class ConstantPoolItem { - internal virtual bool IsWide - { - get - { - return false; - } - } - internal virtual void Resolve(ClassFile classFile) { } - internal virtual void Link(TypeWrapper thisType) + internal virtual void Link(TypeWrapper thisType, Hashtable classCache) { } @@ -548,38 +554,6 @@ class ClassFile { throw new InvalidOperationException(); } - - internal static ConstantPoolItem Read(string inputClassName, Hashtable classCache, BigEndianBinaryReader br) - { - byte tag = br.ReadByte(); - switch((Constant)tag) - { - case Constant.Class: - return new ConstantPoolItemClass(classCache, br); - case Constant.Double: - return new ConstantPoolItemDouble(br); - case Constant.Fieldref: - return new ConstantPoolItemFieldref(br); - case Constant.Float: - return new ConstantPoolItemFloat(br); - case Constant.Integer: - return new ConstantPoolItemInteger(br); - case Constant.InterfaceMethodref: - return new ConstantPoolItemInterfaceMethodref(br); - case Constant.Long: - return new ConstantPoolItemLong(br); - case Constant.Methodref: - return new ConstantPoolItemMethodref(br); - case Constant.NameAndType: - return new ConstantPoolItemNameAndType(classCache, br); - case Constant.String: - return new ConstantPoolItemString(br); - case Constant.Utf8: - return new ConstantPoolItemUtf8(inputClassName, br); - default: - throw new ClassFormatError("{0} (Illegal constant pool type 0x{1:X})", inputClassName, tag); - } - } } internal class ConstantPoolItemClass : ConstantPoolItem @@ -587,17 +561,23 @@ class ClassFile private ushort name_index; private string name; private TypeWrapper typeWrapper; - private Hashtable classCache; - internal ConstantPoolItemClass(Hashtable classCache, BigEndianBinaryReader br) + internal ConstantPoolItemClass(BigEndianBinaryReader br) { - this.classCache = classCache; name_index = br.ReadUInt16(); } internal override void Resolve(ClassFile classFile) { - name = ((ConstantPoolItemUtf8)classFile.GetConstantPoolItem(name_index)).DottifiedValue;; + name = classFile.GetConstantPoolUtf8String(name_index).Replace('/', '.'); + } + + internal override void Link(TypeWrapper thisType, Hashtable classCache) + { + if(typeWrapper == null) + { + typeWrapper = LoadClassHelper(thisType.GetClassLoader(), classCache, name); + } } internal string Name @@ -608,12 +588,8 @@ class ClassFile } } - internal TypeWrapper GetClassType(ClassLoaderWrapper classLoader) + internal TypeWrapper GetClassType() { - if(typeWrapper == null) - { - typeWrapper = LoadClassHelper(classLoader, classCache, name); - } return typeWrapper; } @@ -784,14 +760,6 @@ class ClassFile return d; } } - - internal override bool IsWide - { - get - { - return true; - } - } } internal class ConstantPoolItemFMI : ConstantPoolItem @@ -813,6 +781,12 @@ class ClassFile clazz = (ConstantPoolItemClass)classFile.GetConstantPoolItem(class_index); } + internal override void Link(TypeWrapper thisType, Hashtable classCache) + { + name_and_type.Link(thisType, classCache); + clazz.Link(thisType, classCache); + } + internal string Name { get @@ -837,9 +811,9 @@ class ClassFile } } - internal TypeWrapper GetClassType(ClassLoaderWrapper classLoader) + internal TypeWrapper GetClassType() { - return clazz.GetClassType(classLoader); + return clazz.GetClassType(); } } @@ -851,19 +825,18 @@ class ClassFile { } - internal TypeWrapper GetFieldType(ClassLoaderWrapper classLoader) + internal TypeWrapper GetFieldType() { - return name_and_type.GetFieldType(classLoader); + return name_and_type.GetFieldType(); } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, Hashtable classCache) { - ClassLoaderWrapper classLoader = thisType.GetClassLoader(); - GetFieldType(classLoader); - TypeWrapper wrapper = GetClassType(classLoader); + base.Link(thisType, classCache); + TypeWrapper wrapper = GetClassType(); if(!wrapper.IsUnloadable) { - field = wrapper.GetFieldWrapper(Name, GetFieldType(classLoader)); + field = wrapper.GetFieldWrapper(Name, GetFieldType()); if(field != null) { field.Link(); @@ -886,14 +859,14 @@ class ClassFile { } - internal TypeWrapper[] GetArgTypes(ClassLoaderWrapper classLoader) + internal TypeWrapper[] GetArgTypes() { - return name_and_type.GetArgTypes(classLoader); + return name_and_type.GetArgTypes(); } - internal TypeWrapper GetRetType(ClassLoaderWrapper classLoader) + internal TypeWrapper GetRetType() { - return name_and_type.GetRetType(classLoader); + return name_and_type.GetRetType(); } internal MethodWrapper GetMethod() @@ -913,12 +886,10 @@ class ClassFile { } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, Hashtable classCache) { - ClassLoaderWrapper classLoader = thisType.GetClassLoader(); - TypeWrapper wrapper = GetClassType(classLoader); - GetArgTypes(classLoader); - GetRetType(classLoader); + base.Link(thisType, classCache); + TypeWrapper wrapper = GetClassType(); if(!wrapper.IsUnloadable) { MethodDescriptor md = new MethodDescriptor(Name, Signature); @@ -928,7 +899,7 @@ class ClassFile method.Link(); } if(Name != "" && - (thisType.Modifiers & (Modifiers.Interface | Modifiers.Super)) == Modifiers.Super && + (thisType.Modifiers & (__Modifiers.Interface | __Modifiers.Super)) == __Modifiers.Super && thisType != wrapper && thisType.IsSubTypeOf(wrapper)) { invokespecialMethod = thisType.BaseTypeWrapper.GetMethodWrapper(md, true); @@ -966,12 +937,10 @@ class ClassFile return null; } - internal override void Link(TypeWrapper thisType) + internal override void Link(TypeWrapper thisType, Hashtable classCache) { - ClassLoaderWrapper classLoader = thisType.GetClassLoader(); - TypeWrapper wrapper = GetClassType(classLoader); - GetArgTypes(classLoader); - GetRetType(classLoader); + base.Link(thisType, classCache); + TypeWrapper wrapper = GetClassType(); if(!wrapper.IsUnloadable) { MethodDescriptor md = new MethodDescriptor(Name, Signature); @@ -1056,14 +1025,6 @@ class ClassFile return l; } } - - internal override bool IsWide - { - get - { - return true; - } - } } internal class ConstantPoolItemNameAndType : ConstantPoolItem @@ -1075,23 +1036,38 @@ class ClassFile private TypeWrapper[] argTypeWrappers; private TypeWrapper retTypeWrapper; private TypeWrapper fieldTypeWrapper; - private Hashtable classCache; - internal ConstantPoolItemNameAndType(Hashtable classCache, BigEndianBinaryReader br) + internal ConstantPoolItemNameAndType(BigEndianBinaryReader br) { - this.classCache = classCache; name_index = br.ReadUInt16(); descriptor_index = br.ReadUInt16(); } internal override void Resolve(ClassFile classFile) { - ConstantPoolItemUtf8 nameUtf8 = (ConstantPoolItemUtf8)classFile.GetConstantPoolItem(name_index); - nameUtf8.Resolve(classFile); - name = nameUtf8.Value; - ConstantPoolItemUtf8 descriptorUtf8 = (ConstantPoolItemUtf8)classFile.GetConstantPoolItem(descriptor_index); - descriptorUtf8.Resolve(classFile); - descriptor = descriptorUtf8.DottifiedValue; + name = classFile.GetConstantPoolUtf8String(name_index).Replace('/', '.'); + descriptor = classFile.GetConstantPoolUtf8String(descriptor_index).Replace('/', '.'); + } + + internal override void Link(TypeWrapper thisType, Hashtable classCache) + { + if(descriptor[0] == '(') + { + if(argTypeWrappers == null) + { + ClassLoaderWrapper classLoader = thisType.GetClassLoader(); + argTypeWrappers = ArgTypeWrapperListFromSig(classLoader, classCache, descriptor); + retTypeWrapper = RetTypeWrapperFromSig(classLoader, classCache, descriptor); + } + } + else + { + if(fieldTypeWrapper == null) + { + ClassLoaderWrapper classLoader = thisType.GetClassLoader(); + fieldTypeWrapper = FieldTypeWrapperFromSig(classLoader, classCache, descriptor); + } + } } internal string Name @@ -1110,30 +1086,18 @@ class ClassFile } } - internal TypeWrapper[] GetArgTypes(ClassLoaderWrapper classLoader) + internal TypeWrapper[] GetArgTypes() { - if(argTypeWrappers == null) - { - argTypeWrappers = ArgTypeWrapperListFromSig(classLoader, classCache, descriptor); - } return argTypeWrappers; } - internal TypeWrapper GetRetType(ClassLoaderWrapper classLoader) + internal TypeWrapper GetRetType() { - if(retTypeWrapper == null) - { - retTypeWrapper = RetTypeWrapperFromSig(classLoader, classCache, descriptor); - } return retTypeWrapper; } - internal TypeWrapper GetFieldType(ClassLoaderWrapper classLoader) + internal TypeWrapper GetFieldType() { - if(fieldTypeWrapper == null) - { - fieldTypeWrapper = FieldTypeWrapperFromSig(classLoader, classCache, descriptor); - } return fieldTypeWrapper; } } @@ -1150,9 +1114,7 @@ class ClassFile internal override void Resolve(ClassFile classFile) { - ConstantPoolItemUtf8 utf8 = (ConstantPoolItemUtf8)classFile.GetConstantPoolItem(string_index); - utf8.Resolve(classFile); - s = utf8.Value; + s = classFile.GetConstantPoolUtf8String(string_index); } internal override ConstantType GetConstantType() @@ -1169,40 +1131,7 @@ class ClassFile } } - private class ConstantPoolItemUtf8 : ConstantPoolItem - { - private string s; - - internal ConstantPoolItemUtf8(string inputClassName, BigEndianBinaryReader br) - { - try - { - s = br.ReadString(); - } - catch(FormatException) - { - throw new ClassFormatError("{0} (Illegal UTF8 string in constant pool)", inputClassName); - } - } - - internal string Value - { - get - { - return s; - } - } - - internal string DottifiedValue - { - get - { - return s.Replace('/', '.'); - } - } - } - - private enum Constant + internal enum Constant { Utf8 = 1, Integer = 3, @@ -1217,37 +1146,19 @@ class ClassFile NameAndType = 12 } - internal class Attribute + internal class FieldOrMethod { + protected Modifiers access_flags; private string name; - private BigEndianBinaryReader data; + private string descriptor; + protected bool deprecated; - private Attribute() + internal FieldOrMethod(ClassFile classFile, BigEndianBinaryReader br) { - } - - internal static Attribute Read(ClassFile classFile, BigEndianBinaryReader br) - { - try - { - int name_index = br.ReadUInt16(); - string name = classFile.GetConstantPoolUtf8(name_index).Value; - int attribute_length = br.ReadInt32(); - Attribute a = new Attribute(); - a.name = name; - a.data = br.Section(attribute_length); - return a; - } - catch(InvalidCastException) - { - } - catch(NullReferenceException) - { - } - catch(IndexOutOfRangeException) - { - } - throw new ClassFormatError("{0} (Attribute name invalid type)", classFile.Name); + access_flags = (Modifiers)br.ReadUInt16(); + name = classFile.GetConstantPoolUtf8String(br.ReadUInt16()); + // TODO validate the descriptor + descriptor = classFile.GetConstantPoolUtf8String(br.ReadUInt16()).Replace('/', '.'); } internal string Name @@ -1258,87 +1169,14 @@ class ClassFile } } - internal BigEndianBinaryReader Data - { - get - { - return data.Duplicate(); - } - } - } - - internal class FieldOrMethod - { - private ClassFile classFile; - protected Modifiers access_flags; - private ushort name_index; - private ushort descriptor_index; - private Attribute[] attributes; - private TypeWrapper[] argTypeWrappers; - private TypeWrapper retTypeWrapper; - private TypeWrapper fieldTypeWrapper; - private Hashtable classCache; - - internal FieldOrMethod(ClassFile classFile, Hashtable classCache, BigEndianBinaryReader br) - { - this.classFile = classFile; - this.classCache = classCache; - access_flags = (Modifiers)br.ReadUInt16(); - // TODO check that name is ConstantPoolItemUtf8 - name_index = br.ReadUInt16(); - // TODO check that descriptor is ConstantPoolItemUtf8 and validate the descriptor - descriptor_index = br.ReadUInt16(); - int attributes_count = br.ReadUInt16(); - attributes = new Attribute[attributes_count]; - for(int i = 0; i < attributes_count; i++) - { - attributes[i] = Attribute.Read(classFile, br); - } - } - - internal string Name - { - get - { - return classFile.GetConstantPoolUtf8(name_index).Value; - } - } - internal string Signature { get { - return classFile.GetConstantPoolUtf8(descriptor_index).DottifiedValue; + return descriptor; } } - internal TypeWrapper[] GetArgTypes(ClassLoaderWrapper classLoader) - { - if(argTypeWrappers == null) - { - argTypeWrappers = ArgTypeWrapperListFromSig(classLoader, classCache, Signature); - } - return argTypeWrappers; - } - - internal TypeWrapper GetRetType(ClassLoaderWrapper classLoader) - { - if(retTypeWrapper == null) - { - retTypeWrapper = RetTypeWrapperFromSig(classLoader, classCache, Signature); - } - return retTypeWrapper; - } - - internal TypeWrapper GetFieldType(ClassLoaderWrapper classLoader) - { - if(fieldTypeWrapper == null) - { - fieldTypeWrapper = FieldTypeWrapperFromSig(classLoader, classCache, Signature); - } - return fieldTypeWrapper; - } - internal Modifiers Modifiers { get @@ -1427,31 +1265,11 @@ class ClassFile } } - protected Attribute GetAttribute(string name) - { - foreach(Attribute attr in attributes) - { - if(attr.Name == name) - { - return attr; - } - } - return null; - } - - internal ClassFile ClassFile - { - get - { - return classFile; - } - } - internal bool DeprecatedAttribute { get { - return GetAttribute("Deprecated") != null; + return deprecated; } } } @@ -1460,7 +1278,7 @@ class ClassFile { private object constantValue; - internal Field(ClassFile classFile, Hashtable classCache, BigEndianBinaryReader br) : base(classFile, classCache, br) + internal Field(ClassFile classFile, BigEndianBinaryReader br) : base(classFile, br) { if((IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected) || (IsFinal && IsVolatile) @@ -1468,66 +1286,89 @@ class ClassFile { throw new ClassFormatError("{0} (Illegal field modifiers: 0x{1:X})", classFile.Name, access_flags); } + int attributes_count = br.ReadUInt16(); + for(int i = 0; i < attributes_count; i++) + { + switch(classFile.GetConstantPoolUtf8String(br.ReadUInt16())) + { + case "Deprecated": + deprecated = true; + if(br.ReadUInt32() != 0) + { + throw new ClassFormatError("Deprecated attribute has non-zero length"); + } + break; + case "ConstantValue": + { + if(br.ReadUInt32() != 2) + { + throw new ClassFormatError("Invalid ConstantValue attribute length"); + } + ushort index = br.ReadUInt16(); + try + { + switch(Signature) + { + case "I": + constantValue = classFile.GetConstantPoolConstantInteger(index); + break; + case "S": + constantValue = (short)classFile.GetConstantPoolConstantInteger(index); + break; + case "B": + constantValue = (sbyte)classFile.GetConstantPoolConstantInteger(index); + break; + case "C": + constantValue = (char)classFile.GetConstantPoolConstantInteger(index); + break; + case "Z": + constantValue = classFile.GetConstantPoolConstantInteger(index) != 0; + break; + case "J": + constantValue = classFile.GetConstantPoolConstantLong(index); + break; + case "F": + constantValue = classFile.GetConstantPoolConstantFloat(index); + break; + case "D": + constantValue = classFile.GetConstantPoolConstantDouble(index); + break; + case "Ljava.lang.String;": + constantValue = classFile.GetConstantPoolConstantString(index); + break; + default: + throw new ClassFormatError("{0} (Invalid signature for constant)", classFile.Name); + } + } + catch(InvalidCastException) + { + throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); + } + catch(IndexOutOfRangeException) + { + throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); + } + catch(InvalidOperationException) + { + throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); + } + catch(NullReferenceException) + { + throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); + } + break; + } + default: + br.Skip(br.ReadUInt32()); + break; + } + } // spec (4.7.2) says we should silently ignore ConstantValue attribute on non-static fields // NOTE a field doesn't have to be final to have a constant value! - if(IsStatic) + if(!IsStatic) { - Attribute attr = GetAttribute("ConstantValue"); - if(attr != null) - { - ushort index = attr.Data.ReadUInt16(); - try - { - switch(Signature) - { - case "I": - constantValue = classFile.GetConstantPoolConstantInteger(index); - break; - case "S": - constantValue = (short)classFile.GetConstantPoolConstantInteger(index); - break; - case "B": - constantValue = (sbyte)classFile.GetConstantPoolConstantInteger(index); - break; - case "C": - constantValue = (char)classFile.GetConstantPoolConstantInteger(index); - break; - case "Z": - constantValue = classFile.GetConstantPoolConstantInteger(index) != 0; - break; - case "J": - constantValue = classFile.GetConstantPoolConstantLong(index); - break; - case "F": - constantValue = classFile.GetConstantPoolConstantFloat(index); - break; - case "D": - constantValue = classFile.GetConstantPoolConstantDouble(index); - break; - case "Ljava.lang.String;": - constantValue = classFile.GetConstantPoolConstantString(index); - break; - default: - throw new ClassFormatError("{0} (Invalid signature for constant)", classFile.Name); - } - } - catch(InvalidCastException) - { - throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); - } - catch(IndexOutOfRangeException) - { - throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); - } - catch(InvalidOperationException) - { - throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); - } - catch(NullReferenceException) - { - throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); - } - } + // TODO is this needed? + constantValue = null; } } @@ -1543,8 +1384,9 @@ class ClassFile internal class Method : FieldOrMethod { private Code code; + private string[] exceptions; - internal Method(ClassFile classFile, Hashtable classCache, BigEndianBinaryReader br) : base(classFile, classCache, br) + internal Method(ClassFile classFile, BigEndianBinaryReader br) : base(classFile, br) { // vmspec 4.6 says that all flags, except ACC_STRICT are ignored on if(Name == "" && Signature == "()V") @@ -1564,8 +1406,57 @@ class ClassFile throw new ClassFormatError("{0} (Illegal method modifiers: 0x{1:X})", classFile.Name, access_flags); } } - // TODO if the method is abstract or native it may not have a Code attribute (right?) - // and if it is not abstract or native, it must have a Code attribute + int attributes_count = br.ReadUInt16(); + for(int i = 0; i < attributes_count; i++) + { + switch(classFile.GetConstantPoolUtf8String(br.ReadUInt16())) + { + case "Deprecated": + deprecated = true; + if(br.ReadUInt32() != 0) + { + throw new ClassFormatError("Deprecated attribute has non-zero length"); + } + break; + case "Code": + if(!code.IsEmpty) + { + throw new ClassFormatError("Duplicate Code attribute"); + } + code.Read(classFile, this, br.Section(br.ReadUInt32())); + break; + case "Exceptions": + if(exceptions != null) + { + throw new ClassFormatError("Duplicate Exceptions attribute"); + } + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + ushort count = rdr.ReadUInt16(); + exceptions = new string[count]; + for(int j = 0; j < count; j++) + { + exceptions[j] = classFile.GetConstantPoolClass(rdr.ReadUInt16()); + } + break; + default: + br.Skip(br.ReadUInt32()); + break; + } + } + if(IsAbstract || IsNative) + { + if(!code.IsEmpty) + { + throw new ClassFormatError("Abstract or native method cannot have a Code attribute"); + } + } + else + { + if(code.IsEmpty) + { + throw new ClassFormatError("Method has no Code attribute"); + } + } } internal bool IsStrictfp @@ -1585,73 +1476,106 @@ class ClassFile } } - internal Code CodeAttribute - { - get - { - if(code == null) - { - Attribute attr = GetAttribute("Code"); - if(attr != null) - { - code = new Code(this, attr); - } - } - return code; - } - } - internal string[] ExceptionsAttribute { get { - Attribute attr = GetAttribute("Exceptions"); - if(attr != null) - { - BigEndianBinaryReader rdr = attr.Data; - ushort count = rdr.ReadUInt16(); - string[] exceptions = new string[count]; - for(int i = 0; i < count; i++) - { - exceptions[i] = ClassFile.GetConstantPoolClass(rdr.ReadUInt16()); - } - return exceptions; - } - return null; + return exceptions; } } - internal class Code + // maps argument 'slot' (as encoded in the xload/xstore instructions) into the ordinal + internal int[] ArgMap { - private Method method; - private ushort max_stack; - private ushort max_locals; - private Instruction[] instructions; - private int[] pcIndexMap; - private ExceptionTableEntry[] exception_table; - private Attribute[] codeAttributes; - private int[] argmap; - private LineNumberTableEntry[] lineNumberTable; - private bool lineNumberTableCached; - private LocalVariableTableEntry[] localVariableTable; - private bool localVariableTableCached; - - internal Code(Method method, Attribute attr) + get + { + return code.argmap; + } + } + + internal int MaxStack + { + get + { + return code.max_stack; + } + } + + internal int MaxLocals + { + get + { + return code.max_locals; + } + } + + internal Instruction[] Instructions + { + get + { + return code.instructions; + } + } + + // maps a PC to an index in the Instruction[], invalid PCs return -1 + internal int[] PcIndexMap + { + get + { + return code.pcIndexMap; + } + } + + internal ExceptionTableEntry[] ExceptionTable + { + get + { + return code.exception_table; + } + } + + internal LineNumberTableEntry[] LineNumberTableAttribute + { + get + { + return code.lineNumberTable; + } + } + + internal LocalVariableTableEntry[] LocalVariableTableAttribute + { + get + { + return code.localVariableTable; + } + } + + private struct Code + { + internal ushort max_stack; + internal ushort max_locals; + internal Instruction[] instructions; + internal int[] pcIndexMap; + internal ExceptionTableEntry[] exception_table; + internal int[] argmap; + internal LineNumberTableEntry[] lineNumberTable; + internal LocalVariableTableEntry[] localVariableTable; + + internal void Read(ClassFile classFile, Method method, BigEndianBinaryReader br) { - this.method = method; - BigEndianBinaryReader br = attr.Data; max_stack = br.ReadUInt16(); max_locals = br.ReadUInt16(); uint code_length = br.ReadUInt32(); - ArrayList instructions = new ArrayList(); + Instruction[] instructions = new Instruction[code_length + 1]; int basePosition = br.Position; + int instructionIndex = 0; while(br.Position - basePosition < code_length) { - instructions.Add(Instruction.Read(this, br.Position - basePosition, br)); + instructions[instructionIndex++].Read((ushort)(br.Position - basePosition), br); } // we add an additional nop instruction to make it easier for consumers of the code array - instructions.Add(new Instruction(this, br.Position - basePosition, ByteCode.__nop)); - this.instructions = (Instruction[])instructions.ToArray(typeof(Instruction)); + instructions[instructionIndex++].SetTermNop((ushort)(br.Position - basePosition)); + this.instructions = instructions; ushort exception_table_length = br.ReadUInt16(); exception_table = new ExceptionTableEntry[exception_table_length]; for(int i = 0; i < exception_table_length; i++) @@ -1664,179 +1588,105 @@ class ClassFile exception_table[i].ordinal = i; } ushort attributes_count = br.ReadUInt16(); - codeAttributes = new Attribute[attributes_count]; for(int i = 0; i < attributes_count; i++) { - codeAttributes[i] = Attribute.Read(method.ClassFile, br); + switch(classFile.GetConstantPoolUtf8String(br.ReadUInt16())) + { + case "LineNumberTable": + if(JVM.Debug) + { + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + int count = rdr.ReadUInt16(); + lineNumberTable = new LineNumberTableEntry[count]; + for(int j = 0; j < count; j++) + { + lineNumberTable[j].start_pc = rdr.ReadUInt16(); + lineNumberTable[j].line_number = rdr.ReadUInt16(); + } + } + else + { + br.Skip(br.ReadUInt32()); + } + break; + case "LocalVariableTable": + if(JVM.Debug) + { + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + int count = rdr.ReadUInt16(); + localVariableTable = new LocalVariableTableEntry[count]; + for(int j = 0; j < count; j++) + { + localVariableTable[j].start_pc = rdr.ReadUInt16(); + localVariableTable[j].length = rdr.ReadUInt16(); + localVariableTable[j].name = classFile.GetConstantPoolUtf8String(rdr.ReadUInt16()); + localVariableTable[j].descriptor = classFile.GetConstantPoolUtf8String(rdr.ReadUInt16()).Replace('/', '.'); + localVariableTable[j].index = rdr.ReadUInt16(); + } + } + else + { + br.Skip(br.ReadUInt32()); + } + break; + default: + br.Skip(br.ReadUInt32()); + break; + } } // build the pcIndexMap - pcIndexMap = new int[this.instructions[this.instructions.Length - 1].PC + 1]; + pcIndexMap = new int[this.instructions[instructionIndex - 1].PC + 1]; for(int i = 0; i < pcIndexMap.Length; i++) { pcIndexMap[i] = -1; } - for(int i = 0; i < this.instructions.Length - 1; i++) + for(int i = 0; i < instructionIndex - 1; i++) { pcIndexMap[this.instructions[i].PC] = i; } - } - - // maps argument 'slot' (as encoded in the xload/xstore instructions) into the ordinal - internal int[] ArgMap - { - get + // build the argmap + string sig = method.Signature; + ArrayList args = new ArrayList(); + int pos = 0; + if(!method.IsStatic) { - if(argmap == null) + args.Add(pos++); + } + for(int i = 1; sig[i] != ')'; i++) + { + args.Add(pos++); + switch(sig[i]) { - string sig = method.Signature; - ArrayList args = new ArrayList(); - int pos = 0; - if(!method.IsStatic) + case 'L': + i = sig.IndexOf(';', i); + break; + case 'D': + case 'J': + args.Add(-1); + break; + case '[': { - args.Add(pos++); - } - for(int i = 1; sig[i] != ')'; i++) - { - args.Add(pos++); - switch(sig[i]) + while(sig[i] == '[') { - case 'L': - i = sig.IndexOf(';', i); - break; - case 'D': - case 'J': - args.Add(-1); - break; - case '[': - { - while(sig[i] == '[') - { - i++; - } - if(sig[i] == 'L') - { - i = sig.IndexOf(';', i); - } - break; - } + i++; } - } - argmap = new int[args.Count]; - args.CopyTo(argmap); - } - return argmap; - } - } - - internal Method Method - { - get - { - return method; - } - } - - internal int MaxStack - { - get - { - return max_stack; - } - } - - internal int MaxLocals - { - get - { - return max_locals; - } - } - - internal Instruction[] Instructions - { - get - { - return instructions; - } - } - - // maps a PC to an index in the Instruction[], invalid PCs return -1 - internal int[] PcIndexMap - { - get - { - return pcIndexMap; - } - } - - internal ExceptionTableEntry[] ExceptionTable - { - get - { - return exception_table; - } - } - - private Attribute GetAttribute(string name) - { - foreach(Attribute attr in codeAttributes) - { - if(attr.Name == name) - { - return attr; - } - } - return null; - } - - internal LineNumberTableEntry[] LineNumberTableAttribute - { - get - { - if(!lineNumberTableCached) - { - lineNumberTableCached = true; - Attribute attr = GetAttribute("LineNumberTable"); - if(attr != null) - { - BigEndianBinaryReader rdr = attr.Data; - int count = rdr.ReadUInt16(); - lineNumberTable = new LineNumberTableEntry[count]; - for(int i = 0; i < count; i++) + if(sig[i] == 'L') { - lineNumberTable[i].start_pc = rdr.ReadUInt16(); - lineNumberTable[i].line_number = rdr.ReadUInt16(); + i = sig.IndexOf(';', i); } + break; } } - return lineNumberTable; } + argmap = new int[args.Count]; + args.CopyTo(argmap); } - internal LocalVariableTableEntry[] LocalVariableTableAttribute + internal bool IsEmpty { get { - if(!localVariableTableCached) - { - localVariableTableCached = true; - Attribute attr = GetAttribute("LocalVariableTable"); - if(attr != null) - { - BigEndianBinaryReader rdr = attr.Data; - int count = rdr.ReadUInt16(); - localVariableTable = new LocalVariableTableEntry[count]; - for(int i = 0; i < count; i++) - { - localVariableTable[i].start_pc = rdr.ReadUInt16(); - localVariableTable[i].length = rdr.ReadUInt16(); - localVariableTable[i].name = method.ClassFile.GetConstantPoolUtf8(rdr.ReadUInt16()).Value; - localVariableTable[i].descriptor = method.ClassFile.GetConstantPoolUtf8(rdr.ReadUInt16()).DottifiedValue; - localVariableTable[i].index = rdr.ReadUInt16(); - } - } - } - return localVariableTable; + return instructions == null; } } } @@ -1850,131 +1700,139 @@ class ClassFile internal int ordinal; } - internal class Instruction + internal struct Instruction { - private Method.Code method; - private int pc; + private ushort pc; private ByteCode opcode; + private NormalizedByteCode normopcode; private int arg1; - private int arg2; - private int default_offset; - private int[] values; - private int[] target_offsets; + private short arg2; + private SwitchEntry[] switch_entries; - internal Instruction(Method.Code method, int pc, ByteCode opcode) - : this(method, pc, opcode, 0) + struct SwitchEntry { + internal int value; + internal int target_offset; } - private Instruction(Method.Code method, int pc, ByteCode opcode, int arg1) - : this(method, pc, opcode, arg1, 0) + internal void SetTermNop(ushort pc) { - } - - private Instruction(Method.Code method, int pc, ByteCode opcode, int arg1, int arg2) - { - this.method = method; + // TODO what happens if we already have exactly the maximum number of instructions? this.pc = pc; - this.opcode = opcode; - this.arg1 = arg1; - this.arg2 = arg2; + this.opcode = ByteCode.__nop; } - private Instruction(Method.Code method, int pc, ByteCode opcode, int default_offset, int[] values, int[] target_offsets) - : this(method, pc, opcode) - { - this.default_offset = default_offset; - this.values = values; - this.target_offsets = target_offsets; - } - - internal static Instruction Read(Method.Code method, int pc, BigEndianBinaryReader br) + internal void Read(ushort pc, BigEndianBinaryReader br) { + this.pc = pc; ByteCode bc = (ByteCode)br.ReadByte(); - ByteCodeMode mode = ByteCodeMetaData.GetMode(bc); - if(bc == ByteCode.__wide) - { - bc = (ByteCode)br.ReadByte(); - // NOTE the PC of a wide instruction is actually the PC of the - // wide prefix, not the following instruction (vmspec 4.9.2) - mode = ByteCodeMetaData.GetWideMode(bc); - } - switch(mode) + switch(ByteCodeMetaData.GetMode(bc)) { case ByteCodeMode.Simple: - return new Instruction(method, pc, bc); + break; case ByteCodeMode.Constant_1: case ByteCodeMode.Local_1: - return new Instruction(method, pc, bc, br.ReadByte()); + arg1 = br.ReadByte(); + break; case ByteCodeMode.Constant_2: - case ByteCodeMode.Local_2: - return new Instruction(method, pc, bc, br.ReadUInt16()); + arg1 = br.ReadUInt16(); + break; case ByteCodeMode.Branch_2: - return new Instruction(method, pc, bc, br.ReadInt16()); + arg1 = br.ReadInt16(); + break; case ByteCodeMode.Branch_4: - return new Instruction(method, pc, bc, br.ReadInt32()); + arg1 = br.ReadInt32(); + break; case ByteCodeMode.Constant_2_1_1: - { - Instruction instr = new Instruction(method, pc, bc, br.ReadUInt16()); + arg1 = br.ReadUInt16(); // TODO validate these br.ReadByte(); // count br.ReadByte(); // unused - return instr; - } + break; case ByteCodeMode.Immediate_1: - return new Instruction(method, pc, bc, br.ReadSByte()); + arg1 = br.ReadSByte(); + break; case ByteCodeMode.Immediate_2: - return new Instruction(method, pc, bc, br.ReadInt16()); + arg1 = br.ReadInt16(); + break; case ByteCodeMode.Local_1_Immediate_1: - return new Instruction(method, pc, bc, br.ReadByte(), br.ReadSByte()); - case ByteCodeMode.Local_2_Immediate_2: - return new Instruction(method, pc, bc, br.ReadUInt16(), br.ReadInt16()); + arg1 = br.ReadByte(); + arg2 = br.ReadSByte(); + break; case ByteCodeMode.Constant_2_Immediate_1: - return new Instruction(method, pc, bc, br.ReadUInt16(), br.ReadSByte()); + arg1 = br.ReadUInt16(); + arg2 = br.ReadSByte(); + break; case ByteCodeMode.Tableswitch: { // skip the padding - int p = pc + 1; - int align = ((p + 3) & 0x7ffffffc) - p; - for(int i = 0; i < align; i++) - { - br.ReadByte(); - } + uint p = pc + 1u; + uint align = ((p + 3) & 0x7ffffffc) - p; + br.Skip(align); int default_offset = br.ReadInt32(); + this.arg1 = default_offset; int low = br.ReadInt32(); int high = br.ReadInt32(); - int[] values = new int[high - low + 1]; - int[] target_offset = new int[high - low + 1]; + if(low > high) + { + // TODO is this the right exception? + throw new ClassFormatError("Incorrect tableswitch (low > high)"); + } + SwitchEntry[] entries = new SwitchEntry[high - low + 1]; for(int i = low; i <= high; i++) { - values[i - low] = i; - target_offset[i - low] = br.ReadInt32(); + entries[i - low].value = i; + entries[i - low].target_offset = br.ReadInt32(); } - return new Instruction(method, pc, bc, default_offset, values, target_offset); + this.switch_entries = entries; + break; } case ByteCodeMode.Lookupswitch: { // skip the padding - int p = pc + 1; - int align = ((p + 3) & 0x7ffffffc) - p; - for(int i = 0; i < align; i++) - { - br.ReadByte(); - } + uint p = pc + 1u; + uint align = ((p + 3) & 0x7ffffffc) - p; + br.Skip(align); int default_offset = br.ReadInt32(); + this.arg1 = default_offset; int count = br.ReadInt32(); - int[] values = new int[count]; - int[] target_offset = new int[count]; + if(count < 0) + { + // TODO is this the right exception? + throw new ClassFormatError("Incorrect lookupswitch (npairs < 0)"); + } + SwitchEntry[] entries = new SwitchEntry[count]; for(int i = 0; i < count; i++) { - values[i] = br.ReadInt32(); - target_offset[i] = br.ReadInt32(); + entries[i].value = br.ReadInt32(); + entries[i].target_offset = br.ReadInt32(); } - return new Instruction(method, pc, bc, default_offset, values, target_offset); + this.switch_entries = entries; + break; } + case ByteCodeMode.WidePrefix: + bc = (ByteCode)br.ReadByte(); + // NOTE the PC of a wide instruction is actually the PC of the + // wide prefix, not the following instruction (vmspec 4.9.2) + switch(ByteCodeMetaData.GetWideMode(bc)) + { + case ByteCodeModeWide.Local_2: + arg1 = br.ReadUInt16(); + break; + case ByteCodeModeWide.Local_2_Immediate_2: + arg1 = br.ReadUInt16(); + arg2 = br.ReadInt16(); + break; + default: + throw new ClassFormatError("Invalid wide prefix on opcode: {0}", bc); + } + break; default: throw new ClassFormatError("Invalid opcode: {0}", bc); } + this.opcode = bc; + this.normopcode = ByteCodeMetaData.GetNormalizedByteCode(bc); + arg1 = ByteCodeMetaData.GetArg(opcode, arg1); } internal int PC @@ -1997,7 +1855,7 @@ class ClassFile { get { - return ByteCodeMetaData.GetNormalizedByteCode(opcode); + return normopcode; } } @@ -2021,7 +1879,7 @@ class ClassFile { get { - return ByteCodeMetaData.GetArg(opcode, arg1); + return arg1; } } @@ -2029,48 +1887,42 @@ class ClassFile { get { - return default_offset; + return arg1; } } - internal int[] Values + internal int SwitchEntryCount { get { - return values; + return switch_entries.Length; } } - internal int[] TargetOffsets + internal int GetSwitchValue(int i) { - get - { - return target_offsets; - } + return switch_entries[i].value; } - internal Method.Code MethodCode + internal int GetSwitchTargetOffset(int i) { - get - { - return method; - } + return switch_entries[i].target_offset; } } internal struct LineNumberTableEntry { - internal int start_pc; - internal int line_number; + internal ushort start_pc; + internal ushort line_number; } internal struct LocalVariableTableEntry { - internal int start_pc; - internal int length; + internal ushort start_pc; + internal ushort length; internal string name; internal string descriptor; - internal int index; + internal ushort index; } } } diff --git a/runtime/ClassLoaderWrapper.cs b/runtime/ClassLoaderWrapper.cs index e4357fea..1945fc88 100644 --- a/runtime/ClassLoaderWrapper.cs +++ b/runtime/ClassLoaderWrapper.cs @@ -42,6 +42,7 @@ class ClassLoaderWrapper private static ClassLoaderWrapper bootstrapClassLoader; private object javaClassLoader; private Hashtable types = new Hashtable(); + private ArrayList nativeLibraries; // FXBUG moduleBuilder is static, because multiple dynamic assemblies is broken (TypeResolve doesn't fire) // so for the time being, we share one dynamic assembly among all classloaders private static ModuleBuilder moduleBuilder; @@ -193,7 +194,7 @@ class ClassLoaderWrapper { Tracer.Warning(Tracer.Compiler, "Class name clash: {0}", name); } - return name + "\\\\" + instanceId; + return name + "/" + instanceId; } else { @@ -902,4 +903,28 @@ class ClassLoaderWrapper return null; } } + + internal void RegisterNativeLibrary(IntPtr p) + { + lock(this) + { + if(nativeLibraries == null) + { + nativeLibraries = new ArrayList(); + } + nativeLibraries.Add(p); + } + } + + internal IntPtr[] GetNativeLibraries() + { + lock(this) + { + if(nativeLibraries == null) + { + return new IntPtr[0]; + } + return (IntPtr[])nativeLibraries.ToArray(typeof(IntPtr)); + } + } } diff --git a/runtime/IKVM.Runtime.csproj b/runtime/IKVM.Runtime.csproj index 79320c0f..54f9d0cd 100644 --- a/runtime/IKVM.Runtime.csproj +++ b/runtime/IKVM.Runtime.csproj @@ -24,7 +24,7 @@ > BUCKET_SIZE) + { + return -1; + } + object[] tmp = dynamic_list; + dynamic_list = new object[newsize]; + Array.Copy(tmp, 0, dynamic_list, 0, tmp.Length); + dynamic_list[tmp.Length] = o; + return tmp.Length + STATIC_LIST_SIZE; + } + + internal void DeleteLocalRef(int i) + { + if(i < STATIC_LIST_SIZE) + { + u.static_list[i] = null; + } + else + { + dynamic_list[i - STATIC_LIST_SIZE] = null; + } + } + + internal object UnwrapLocalRef(int i) + { + if(i < STATIC_LIST_SIZE) + { + return u.static_list[i]; + } + else + { + return dynamic_list[i - STATIC_LIST_SIZE]; + } + } +} + +class GlobalRefs +{ + internal static System.Collections.ArrayList globalRefs = new System.Collections.ArrayList(); +} + +unsafe class VtableBuilder +{ + delegate int pf_int_IntPtr(JNIEnv* pEnv, IntPtr p); + delegate IntPtr pf_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p); + delegate void pf_void_IntPtr(JNIEnv* pEnv, IntPtr p); + delegate IntPtr pf_IntPtr(JNIEnv* pEnv); + delegate void pf_void(JNIEnv* pEnv); + delegate sbyte pf_sbyte(JNIEnv* pEnv); + delegate IntPtr pf_IntPtr_pbyte(JNIEnv* pEnv, byte* p); + delegate int pf_int(JNIEnv* pEnv); + delegate IntPtr pf_IntPtr_pbyte_IntPtr_pbyte_IntPtr(JNIEnv* pEnv, byte* p1, IntPtr p2, byte* p3, int p4); + delegate IntPtr pf_IntPtr_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate int pf_int_IntPtr_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2); + delegate void pf_void_pbyte(JNIEnv* pEnv, byte* p1); + delegate IntPtr pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2, byte* p3); + delegate int pf_int_IntPtr_pJNINativeMethod_int(JNIEnv* pEnv, IntPtr p1, JNIEnv.JNINativeMethod* p2, int p3); + delegate int pf_int_ppJavaVM(JNIEnv* pEnv, JavaVM** ppJavaVM); + delegate sbyte pf_sbyte_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate short pf_short_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate int pf_int_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate long pf_long_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate float pf_float_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate double pf_double_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate void pf_void_IntPtr_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3); + delegate void pf_void_IntPtr_IntPtr_sbyte(JNIEnv* pEnv, IntPtr p1, IntPtr p2, sbyte p3); + delegate void pf_void_IntPtr_IntPtr_short(JNIEnv* pEnv, IntPtr p1, IntPtr p2, short p3); + delegate void pf_void_IntPtr_IntPtr_int(JNIEnv* pEnv, IntPtr p1, IntPtr p2, int p3); + delegate void pf_void_IntPtr_IntPtr_long(JNIEnv* pEnv, IntPtr p1, IntPtr p2, long p3); + delegate void pf_void_IntPtr_IntPtr_float(JNIEnv* pEnv, IntPtr p1, IntPtr p2, float p3); + delegate void pf_void_IntPtr_IntPtr_double(JNIEnv* pEnv, IntPtr p1, IntPtr p2, double p3); + delegate IntPtr pf_IntPtr_pchar_int(JNIEnv* pEnv, char* p1, int p2); + delegate void pf_void_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate IntPtr pf_IntPtr_int_IntPtr_IntPtr(JNIEnv* pEnv, int p1, IntPtr p2, IntPtr p3); + delegate IntPtr pf_IntPtr_IntPtr_int(JNIEnv* pEnv, IntPtr p1, int p2); + delegate void pf_void_IntPtr_int_IntPtr(JNIEnv* pEnv, IntPtr p1, int p2, IntPtr p3); + delegate IntPtr pf_IntPtr_int(JNIEnv* pEnv, int p1); + delegate void pf_void_IntPtr_int_int_IntPtr(JNIEnv* pEnv, IntPtr p1, int p2, int p3, IntPtr p4); + delegate IntPtr pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate sbyte pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate short pf_short_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate int pf_int_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate long pf_long_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate float pf_float_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate double pf_double_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate void pf_void_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate IntPtr pf_IntPtr_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate sbyte pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate short pf_short_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate int pf_int_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate long pf_long_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate float pf_float_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate double pf_double_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate void pf_void_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + + internal static void* vtable; + + static VtableBuilder() + { + // JNIEnv + void** pmcpp = JniHelper.ikvm_GetJNIEnvVTable(); + void** p = (void**)Marshal.AllocHGlobal(IntPtr.Size * vtableDelegates.Length); + for(int i = 0; i < vtableDelegates.Length; i++) + { + if(vtableDelegates[i] != null) + { + p[i] = JniHelper.ikvm_MarshalDelegate(vtableDelegates[i]); + } + else + { + p[i] = pmcpp[i]; + } + } + vtable = p; + } + + static Delegate[] vtableDelegates = + { + new pf_int_IntPtr_pbyte(JNIEnv.GetMethodArgs), //virtual void JNICALL reserved0(); + null, //virtual void JNICALL reserved1(); + null, //virtual void JNICALL reserved2(); + null, //virtual void JNICALL reserved3(); + + new pf_int(JNIEnv.GetVersion), //virtual jint JNICALL GetVersion(); + + new pf_IntPtr_pbyte_IntPtr_pbyte_IntPtr(JNIEnv.DefineClass), //virtual jclass JNICALL DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len); + new pf_IntPtr_pbyte(JNIEnv.FindClass), //virtual jclass JNICALL FindClass(const char *name); + + new pf_IntPtr_IntPtr(JNIEnv.FromReflectedMethod), //virtual jmethodID JNICALL FromReflectedMethod(jobject method); + new pf_IntPtr_IntPtr(JNIEnv.FromReflectedField), //virtual jfieldID JNICALL FromReflectedField(jobject field); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.ToReflectedMethod), //virtual jobject JNICALL ToReflectedMethod(jclass clazz, jmethodID methodID); + + new pf_IntPtr_IntPtr(JNIEnv.GetSuperclass), //virtual jclass JNICALL GetSuperclass(jclass sub); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsAssignableFrom), //virtual jboolean JNICALL IsAssignableFrom(jclass sub, jclass sup); + + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.ToReflectedField), //virtual jobject JNICALL ToReflectedField(jclass clazz, jfieldID fieldID); + + new pf_int_IntPtr(JNIEnv.Throw), //virtual jint JNICALL Throw(jthrowable obj); + new pf_int_IntPtr_pbyte(JNIEnv.ThrowNew), //virtual jint JNICALL ThrowNew(jclass clazz, const char *msg); + new pf_IntPtr(JNIEnv.ExceptionOccurred), //virtual jthrowable JNICALL ExceptionOccurred(); + new pf_void(JNIEnv.ExceptionDescribe), //virtual void JNICALL ExceptionDescribe(); + new pf_void(JNIEnv.ExceptionClear), //virtual void JNICALL ExceptionClear(); + new pf_void_pbyte(JNIEnv.FatalError), //virtual void JNICALL FatalError(const char *msg); + + new pf_void(JNIEnv.NotImplemented), //virtual jint JNICALL PushLocalFrame(jint capacity); + new pf_void(JNIEnv.NotImplemented), //virtual jobject JNICALL PopLocalFrame(jobject result); + + new pf_IntPtr_IntPtr(JNIEnv.NewGlobalRef), //virtual jobject JNICALL NewGlobalRef(jobject lobj); + new pf_void_IntPtr(JNIEnv.DeleteGlobalRef), //virtual void JNICALL DeleteGlobalRef(jobject gref); + new pf_void_IntPtr(JNIEnv.DeleteLocalRef), //virtual void JNICALL DeleteLocalRef(jobject obj); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsSameObject), //virtual jboolean JNICALL IsSameObject(jobject obj1, jobject obj2); + + new pf_IntPtr_IntPtr(JNIEnv.NewLocalRef), //virtual jobject JNICALL NewLocalRef(jobject ref); + new pf_void(JNIEnv.NotImplemented), //virtual jint JNICALL EnsureLocalCapacity(jint capacity); + + new pf_IntPtr_IntPtr(JNIEnv.AllocObject), //virtual jobject JNICALL AllocObject(jclass clazz); + null, //virtual jobject JNICALL NewObject(jclass clazz, jmethodID methodID, ...); + null, //virtual jobject JNICALL NewObjectV(jclass clazz, jmethodID methodID, va_list args); + new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.NewObjectA), //virtual jobject JNICALL NewObjectA(jclass clazz, jmethodID methodID, jvalue *args); + + new pf_IntPtr_IntPtr(JNIEnv.GetObjectClass), //virtual jclass JNICALL GetObjectClass(jobject obj); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsInstanceOf), //virtual jboolean JNICALL IsInstanceOf(jobject obj, jclass clazz); + + new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetMethodID), //virtual jmethodID JNICALL GetMethodID(jclass clazz, const char *name, const char *sig); + + null, //virtual jobject JNICALL CallObjectMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jobject JNICALL CallObjectMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallObjectMethodA), //virtual jobject JNICALL CallObjectMethodA(jobject obj, jmethodID methodID, jvalue * args); + + null, //virtual jboolean JNICALL CallBooleanMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jboolean JNICALL CallBooleanMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallBooleanMethodA), //virtual jboolean JNICALL CallBooleanMethodA(jobject obj, jmethodID methodID, jvalue * args); + + null, //virtual jbyte JNICALL CallByteMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jbyte JNICALL CallByteMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallByteMethodA), //virtual jbyte JNICALL CallByteMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jchar JNICALL CallCharMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jchar JNICALL CallCharMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallCharMethodA), //virtual jchar JNICALL CallCharMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jshort JNICALL CallShortMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jshort JNICALL CallShortMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallShortMethodA), //virtual jshort JNICALL CallShortMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jint JNICALL CallIntMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jint JNICALL CallIntMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_int_IntPtr_IntPtr_pjvalue(JNIEnv.CallIntMethodA), //virtual jint JNICALL CallIntMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jlong JNICALL CallLongMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jlong JNICALL CallLongMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_long_IntPtr_IntPtr_pjvalue(JNIEnv.CallLongMethodA), //virtual jlong JNICALL CallLongMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jfloat JNICALL CallFloatMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jfloat JNICALL CallFloatMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_float_IntPtr_IntPtr_pjvalue(JNIEnv.CallFloatMethodA), //virtual jfloat JNICALL CallFloatMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jdouble JNICALL CallDoubleMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jdouble JNICALL CallDoubleMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_double_IntPtr_IntPtr_pjvalue(JNIEnv.CallDoubleMethodA), //virtual jdouble JNICALL CallDoubleMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual void JNICALL CallVoidMethod(jobject obj, jmethodID methodID, ...); + null, //virtual void JNICALL CallVoidMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_void_IntPtr_IntPtr_pjvalue(JNIEnv.CallVoidMethodA), //virtual void JNICALL CallVoidMethodA(jobject obj, jmethodID methodID, jvalue * args); + + null, //virtual jobject JNICALL CallNonvirtualObjectMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jobject JNICALL CallNonvirtualObjectMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_IntPtr_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualObjectMethodA), //virtual jobject JNICALL CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + null, //virtual jboolean JNICALL CallNonvirtualBooleanMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jboolean JNICALL CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualBooleanMethodA), //virtual jboolean JNICALL CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + null, //virtual jbyte JNICALL CallNonvirtualByteMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jbyte JNICALL CallNonvirtualByteMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualByteMethodA), //virtual jbyte JNICALL CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jchar JNICALL CallNonvirtualCharMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jchar JNICALL CallNonvirtualCharMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_short_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualCharMethodA), //virtual jchar JNICALL CallNonvirtualCharMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jshort JNICALL CallNonvirtualShortMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jshort JNICALL CallNonvirtualShortMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_short_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualShortMethodA), //virtual jshort JNICALL CallNonvirtualShortMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jint JNICALL CallNonvirtualIntMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jint JNICALL CallNonvirtualIntMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_int_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualIntMethodA), //virtual jint JNICALL CallNonvirtualIntMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jlong JNICALL CallNonvirtualLongMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jlong JNICALL CallNonvirtualLongMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_long_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualLongMethodA), //virtual jlong JNICALL CallNonvirtualLongMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jfloat JNICALL CallNonvirtualFloatMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jfloat JNICALL CallNonvirtualFloatMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_float_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualFloatMethodA), //virtual jfloat JNICALL CallNonvirtualFloatMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jdouble JNICALL CallNonvirtualDoubleMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jdouble JNICALL CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_double_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualDoubleMethodA), //virtual jdouble JNICALL CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual void JNICALL CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual void JNICALL CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_void_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualVoidMethodA), //virtual void JNICALL CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetFieldID), //virtual jfieldID JNICALL GetFieldID(jclass clazz, const char *name, const char *sig); + + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetObjectField), //virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetBooleanField), //virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetByteField), //virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID); + new pf_short_IntPtr_IntPtr(JNIEnv.GetCharField), //virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID); + new pf_short_IntPtr_IntPtr(JNIEnv.GetShortField), //virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID); + new pf_int_IntPtr_IntPtr(JNIEnv.GetIntField), //virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID); + new pf_long_IntPtr_IntPtr(JNIEnv.GetLongField), //virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID); + new pf_float_IntPtr_IntPtr(JNIEnv.GetFloatField), //virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID); + new pf_double_IntPtr_IntPtr(JNIEnv.GetDoubleField), //virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID); + + new pf_void_IntPtr_IntPtr_IntPtr(JNIEnv.SetObjectField), //virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val); + new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetBooleanField), //virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val); + new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetByteField), //virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val); + new pf_void_IntPtr_IntPtr_short(JNIEnv.SetCharField), //virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val); + new pf_void_IntPtr_IntPtr_short(JNIEnv.SetShortField), //virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val); + new pf_void_IntPtr_IntPtr_int(JNIEnv.SetIntField), //virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val); + new pf_void_IntPtr_IntPtr_long(JNIEnv.SetLongField), //virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val); + new pf_void_IntPtr_IntPtr_float(JNIEnv.SetFloatField), //virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val); + new pf_void_IntPtr_IntPtr_double(JNIEnv.SetDoubleField), //virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val); + + new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticMethodID), //virtual jmethodID JNICALL GetStaticMethodID(jclass clazz, const char *name, const char *sig); + + null, //virtual jobject JNICALL CallStaticObjectMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jobject JNICALL CallStaticObjectMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticObjectMethodA), //virtual jobject JNICALL CallStaticObjectMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jboolean JNICALL CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jboolean JNICALL CallStaticBooleanMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticBooleanMethodA), //virtual jboolean JNICALL CallStaticBooleanMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jbyte JNICALL CallStaticByteMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jbyte JNICALL CallStaticByteMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticByteMethodA), //virtual jbyte JNICALL CallStaticByteMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jchar JNICALL CallStaticCharMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jchar JNICALL CallStaticCharMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticCharMethodA), //virtual jchar JNICALL CallStaticCharMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jshort JNICALL CallStaticShortMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jshort JNICALL CallStaticShortMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticShortMethodA), //virtual jshort JNICALL CallStaticShortMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jint JNICALL CallStaticIntMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jint JNICALL CallStaticIntMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_int_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticIntMethodA), //virtual jint JNICALL CallStaticIntMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jlong JNICALL CallStaticLongMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jlong JNICALL CallStaticLongMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_long_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticLongMethodA), //virtual jlong JNICALL CallStaticLongMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jfloat JNICALL CallStaticFloatMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jfloat JNICALL CallStaticFloatMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_float_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticFloatMethodA), //virtual jfloat JNICALL CallStaticFloatMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jdouble JNICALL CallStaticDoubleMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jdouble JNICALL CallStaticDoubleMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_double_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticDoubleMethodA), //virtual jdouble JNICALL CallStaticDoubleMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual void JNICALL CallStaticVoidMethod(jclass cls, jmethodID methodID, ...); + null, //virtual void JNICALL CallStaticVoidMethodV(jclass cls, jmethodID methodID, va_list args); + new pf_void_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticVoidMethodA), //virtual void JNICALL CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue * args); + + new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticFieldID), //virtual jfieldID JNICALL GetStaticFieldID(jclass clazz, const char *name, const char *sig); + + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetStaticObjectField), //virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetStaticBooleanField), //virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetStaticByteField), //virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID); + new pf_short_IntPtr_IntPtr(JNIEnv.GetStaticCharField), //virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID); + new pf_short_IntPtr_IntPtr(JNIEnv.GetStaticShortField), //virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID); + new pf_int_IntPtr_IntPtr(JNIEnv.GetStaticIntField), //virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID); + new pf_long_IntPtr_IntPtr(JNIEnv.GetStaticLongField), //virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID); + new pf_float_IntPtr_IntPtr(JNIEnv.GetStaticFloatField), //virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID); + new pf_double_IntPtr_IntPtr(JNIEnv.GetStaticDoubleField), //virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID); + + new pf_void_IntPtr_IntPtr_IntPtr(JNIEnv.SetStaticObjectField), //virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val); + new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetStaticBooleanField), //virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val); + new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetStaticByteField), //virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val); + new pf_void_IntPtr_IntPtr_short(JNIEnv.SetStaticCharField), //virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val); + new pf_void_IntPtr_IntPtr_short(JNIEnv.SetStaticShortField), //virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val); + new pf_void_IntPtr_IntPtr_int(JNIEnv.SetStaticIntField), //virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val); + new pf_void_IntPtr_IntPtr_long(JNIEnv.SetStaticLongField), //virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val); + new pf_void_IntPtr_IntPtr_float(JNIEnv.SetStaticFloatField), //virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val); + new pf_void_IntPtr_IntPtr_double(JNIEnv.SetStaticDoubleField), //virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val); + + new pf_IntPtr_pchar_int(JNIEnv.NewString), //virtual jstring JNICALL NewString(const jchar *unicode, jsize len); + new pf_int_IntPtr(JNIEnv.GetStringLength), //virtual jsize JNICALL GetStringLength(jstring str); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetStringChars), //virtual const jchar *JNICALL GetStringChars(jstring str, jboolean *isCopy); + new pf_void_IntPtr_IntPtr(JNIEnv.ReleaseStringChars), //virtual void JNICALL ReleaseStringChars(jstring str, const jchar *chars); + + new pf_IntPtr_IntPtr(JNIEnv.NewStringUTF), //virtual jstring JNICALL NewStringUTF(const char *utf); + new pf_int_IntPtr(JNIEnv.GetStringUTFLength), //virtual jsize JNICALL GetStringUTFLength(jstring str); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetStringUTFChars), //virtual const char* JNICALL GetStringUTFChars(jstring str, jboolean *isCopy); + new pf_void_IntPtr_IntPtr(JNIEnv.ReleaseStringUTFChars), //virtual void JNICALL ReleaseStringUTFChars(jstring str, const char* chars); + + new pf_int_IntPtr(JNIEnv.GetArrayLength), //virtual jsize JNICALL GetArrayLength(jarray array); + + new pf_IntPtr_int_IntPtr_IntPtr(JNIEnv.NewObjectArray), //virtual jobjectArray JNICALL NewObjectArray(jsize len, jclass clazz, jobject init); + new pf_IntPtr_IntPtr_int(JNIEnv.GetObjectArrayElement), //virtual jobject JNICALL GetObjectArrayElement(jobjectArray array, jsize index); + new pf_void_IntPtr_int_IntPtr(JNIEnv.SetObjectArrayElement), //virtual void JNICALL SetObjectArrayElement(jobjectArray array, jsize index, jobject val); + + new pf_IntPtr_int(JNIEnv.NewBooleanArray), //virtual jbooleanArray JNICALL NewBooleanArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewByteArray), //virtual jbyteArray JNICALL NewByteArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewCharArray), //virtual jcharArray JNICALL NewCharArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewShortArray), //virtual jshortArray JNICALL NewShortArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewIntArray), //virtual jintArray JNICALL NewIntArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewLongArray), //virtual jlongArray JNICALL NewLongArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewFloatArray), //virtual jfloatArray JNICALL NewFloatArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewDoubleArray), //virtual jdoubleArray JNICALL NewDoubleArray(jsize len); + + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetBooleanArrayElements), //virtual jboolean * JNICALL GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetByteArrayElements), //virtual jbyte * JNICALL GetByteArrayElements(jbyteArray array, jboolean *isCopy); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetCharArrayElements), //virtual jchar * JNICALL GetCharArrayElements(jcharArray array, jboolean *isCopy); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetShortArrayElements), //virtual jshort * JNICALL GetShortArrayElements(jshortArray array, jboolean *isCopy); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetIntArrayElements), //virtual jint * JNICALL GetIntArrayElements(jintArray array, jboolean *isCopy); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetLongArrayElements), //virtual jlong * JNICALL GetLongArrayElements(jlongArray array, jboolean *isCopy); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetFloatArrayElements), //virtual jfloat * JNICALL GetFloatArrayElements(jfloatArray array, jboolean *isCopy); + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetDoubleArrayElements), //virtual jdouble * JNICALL GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy); + + new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleaseBooleanArrayElements), //virtual void JNICALL ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems, jint mode); + new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleaseByteArrayElements), //virtual void JNICALL ReleaseByteArrayElements(jbyteArray array, jbyte *elems, jint mode); + new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleaseCharArrayElements), //virtual void JNICALL ReleaseCharArrayElements(jcharArray array, jchar *elems, jint mode); + new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleaseShortArrayElements), //virtual void JNICALL ReleaseShortArrayElements(jshortArray array, jshort *elems, jint mode); + new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleaseIntArrayElements), //virtual void JNICALL ReleaseIntArrayElements(jintArray array, jint *elems, jint mode); + new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleaseLongArrayElements), //virtual void JNICALL ReleaseLongArrayElements(jlongArray array, jlong *elems, jint mode); + new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleaseFloatArrayElements), //virtual void JNICALL ReleaseFloatArrayElements(jfloatArray array, jfloat *elems, jint mode); + new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleaseDoubleArrayElements), //virtual void JNICALL ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems, jint mode); + + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetBooleanArrayRegion), //virtual void JNICALL GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetByteArrayRegion), //virtual void JNICALL GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetCharArrayRegion), //virtual void JNICALL GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetShortArrayRegion), //virtual void JNICALL GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetIntArrayRegion), //virtual void JNICALL GetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetLongArrayRegion), //virtual void JNICALL GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetFloatArrayRegion), //virtual void JNICALL GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetDoubleArrayRegion), //virtual void JNICALL GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); + + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetBooleanArrayRegion), //virtual void JNICALL SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetByteArrayRegion), //virtual void JNICALL SetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetCharArrayRegion), //virtual void JNICALL SetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetShortArrayRegion), //virtual void JNICALL SetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetIntArrayRegion), //virtual void JNICALL SetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetLongArrayRegion), //virtual void JNICALL SetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetFloatArrayRegion), //virtual void JNICALL SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetDoubleArrayRegion), //virtual void JNICALL SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); + + new pf_int_IntPtr_pJNINativeMethod_int(JNIEnv.RegisterNatives), //virtual jint JNICALL RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods); + new pf_int_IntPtr(JNIEnv.UnregisterNatives), //virtual jint JNICALL UnregisterNatives(jclass clazz); + + new pf_int_IntPtr(JNIEnv.MonitorEnter), //virtual jint JNICALL MonitorEnter(jobject obj); + new pf_int_IntPtr(JNIEnv.MonitorExit), //virtual jint JNICALL MonitorExit(jobject obj); + + new pf_int_ppJavaVM(JNIEnv.GetJavaVM), //virtual jint JNICALL GetJavaVM(JavaVM **vm); + + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetStringRegion), //virtual void JNICALL GetStringRegion(jstring str, jsize start, jsize len, jchar *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetStringUTFRegion), //virtual void JNICALL GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf); + + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetPrimitiveArrayCritical), //virtual void* JNICALL GetPrimitiveArrayCritical(jarray array, jboolean *isCopy); + new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleasePrimitiveArrayCritical), //virtual void JNICALL ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode); + + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetStringCritical), //virtual const jchar* JNICALL GetStringCritical(jstring string, jboolean *isCopy); + new pf_void_IntPtr_IntPtr(JNIEnv.ReleaseStringCritical), //virtual void JNICALL ReleaseStringCritical(jstring string, const jchar *cstring); + + new pf_void(JNIEnv.NotImplemented), //virtual jweak JNICALL NewWeakGlobalRef(jobject obj); + new pf_void(JNIEnv.NotImplemented), //virtual void JNICALL DeleteWeakGlobalRef(jweak ref); + + new pf_sbyte(JNIEnv.ExceptionCheck), //virtual jboolean JNICALL ExceptionCheck(); + + new pf_void(JNIEnv.NotImplemented), //virtual jobject JNICALL NewDirectByteBuffer(void* address, jlong capacity); + new pf_void(JNIEnv.NotImplemented), //virtual void* JNICALL GetDirectBufferAddress(jobject buf); + new pf_void(JNIEnv.NotImplemented) //virtual jlong JNICALL GetDirectBufferCapacity(jobject buf); + }; +} + +[StructLayout(LayoutKind.Sequential)] +unsafe struct JavaVM +{ + internal static JavaVM* pJavaVM; + void** vtable; + void* firstVtableEntry; + delegate int pf_int(JavaVM* pJVM); + delegate int pf_int_ppvoid_pvoid(JavaVM* pJVM, void** p1, void* p2); + delegate int pf_int_ppvoid_int(JavaVM* pJVM, void** p1, int p2); + + static Delegate[] vtableDelegates = + { + null, + null, + null, + new pf_int(DestroyJavaVM), + new pf_int_ppvoid_pvoid(AttachCurrentThread), + new pf_int(DetachCurrentThread), + new pf_int_ppvoid_int(GetEnv), + new pf_int_ppvoid_pvoid(AttachCurrentThreadAsDaemon) + }; + + static JavaVM() + { + pJavaVM = (JavaVM*)(void*)Marshal.AllocHGlobal(IntPtr.Size * (1 + vtableDelegates.Length)); +#if __MonoCS__ + // MONOBUG mcs requires this bogus fixed construct (and Microsoft doesn't allow it) + fixed(void** p = &pJavaVM->firstVtableEntry) { pJavaVM->vtable = p; } +#else + pJavaVM->vtable = &pJavaVM->firstVtableEntry; +#endif + for(int i = 0; i < vtableDelegates.Length; i++) + { + pJavaVM->vtable[i] = JniHelper.ikvm_MarshalDelegate(vtableDelegates[i]); + } + } + + internal static int DestroyJavaVM(JavaVM* pJVM) + { + return JNIEnv.JNI_ERR; + } + + internal static int AttachCurrentThread(JavaVM* pJVM, void **penv, void *args) + { + // TODO do we need a new local ref frame? + // TODO for now we only support attaching to an existing thread + // TODO support args (JavaVMAttachArgs) + JNIEnv* p = TlsHack.pJNIEnv; + if(p != null) + { + *penv = p; + return JNIEnv.JNI_OK; + } + JVM.CriticalFailure("AttachCurrentThread for non-Java threads not implemented", null); + return JNIEnv.JNI_ERR; + } + + internal static int DetachCurrentThread(JavaVM* pJVM) + { + JVM.CriticalFailure("DetachCurrentThread not implemented", null); + return JNIEnv.JNI_ERR; + } + + internal static int GetEnv(JavaVM* pJVM, void **penv, int version) + { + // TODO we should check the version + JNIEnv* p = TlsHack.pJNIEnv; + if(p != null) + { + *penv = p; + return JNIEnv.JNI_OK; + } + return JNIEnv.JNI_EDETACHED; + } + + internal static int AttachCurrentThreadAsDaemon(JavaVM* pJVM, void **penv, void *args) + { + // TODO do we need a new local ref frame? + // TODO for now we only support attaching to an existing thread + // TODO support args (JavaVMAttachArgs) + JNIEnv* p = TlsHack.pJNIEnv; + if(p != null) + { + *penv = p; + return JNIEnv.JNI_OK; + } + JVM.CriticalFailure("AttachCurrentThreadAsDaemon not implemented", null); + return JNIEnv.JNI_ERR; + } +} + +[StructLayout(LayoutKind.Sequential)] +unsafe struct JNIEnv +{ + internal const int JNI_OK = 0; + internal const int JNI_ERR = -1; + internal const int JNI_EDETACHED = -2; + internal const int JNI_EVERSION = -3; + internal const int JNI_COMMIT = 1; + internal const int JNI_ABORT = 2; + internal const int JNI_VERSION_1_1 = 0x00010001; + internal const int JNI_VERSION_1_2 = 0x00010002; + internal const int JNI_VERSION_1_4 = 0x00010004; + internal const sbyte JNI_TRUE = 1; + internal const sbyte JNI_FALSE = 0; + internal void* vtable; + [StructLayout(LayoutKind.Explicit)] + internal unsafe struct Union + { + [FieldOffset(0)] + internal JniFrame* activeFrame; + [FieldOffset(0)] + internal void* pFrame; + } + internal Union u; + internal GCHandle localRefs; + internal int localRefSlot; + internal IntPtr pendingException; + + private static string StringFromUTF8(byte* psz) + { + // Sun's modified UTF8 encoding is not compatible with System.Text.Encoding.UTF8, + // so we need to roll our own + int len = 0; + bool hasNonAscii = false; + while(psz[len] != 0) + { + hasNonAscii |= psz[len] >= 128; + len++; + } + if(!hasNonAscii) + { + // optimize the common case of 7-bit ASCII + return new String((sbyte*)psz); + } + StringBuilder sb = new StringBuilder(len); + for(int i = 0; i < len; i++) + { + int c = *psz++; + int char2, char3; + switch(c >> 4) + { + case 12: + case 13: + char2 = *psz++; + i++; + c = (((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + char2 = *psz++; + char3 = *psz++; + i++; + i++; + c = ((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | (char3 & 0x3F); + break; + } + sb.Append((char)c); + } + return sb.ToString(); + } + + private static int StringUTF8Length(string s) + { + int len = 0; + for(int i = 0; i < s.Length; i++) + { + char ch = s[i]; + if((ch != 0) && (ch <= 0x7F)) + { + len++; + } + else if(ch <= 0x7FF) + { + len += 2; + } + else + { + len += 3; + } + } + return len; } // this method returns a simplified method argument descriptor. @@ -58,7 +791,7 @@ public sealed class JniHelper // "()V" -> "" // "(ILjava.lang.String;)I" -> "IL" // "([Ljava.lang.String;)V" -> "L" - public static string GetMethodArgList(IntPtr cookie) + private static string GetMethodArgList(IntPtr cookie) { try { @@ -95,44 +828,583 @@ public sealed class JniHelper } } - public static object InvokeMethod(IntPtr cookie, object obj, object[] args, bool nonVirtual) + internal static int GetMethodArgs(JNIEnv* pEnv, IntPtr method, byte* sig) + { + string s = GetMethodArgList(method); + for(int i = 0; i < s.Length; i++) + { + sig[i] = (byte)s[i]; + } + return s.Length; + } + + internal static int GetVersion(JNIEnv* pEnv) + { + return JNI_VERSION_1_4; + } + + internal static IntPtr DefineClass(JNIEnv* pEnv, byte* name, IntPtr loader, byte* pbuf, int length) + { + byte[] buf = new byte[length]; + Marshal.Copy((IntPtr)(void*)pbuf, buf, 0, length); + // TODO what should the protection domain be? + return pEnv->MakeLocalRef(NativeCode.java.lang.VMClassLoader.defineClass(pEnv->UnwrapRef(loader), StringFromUTF8(name), buf, 0, buf.Length, null)); + } + + private static ClassLoaderWrapper FindNativeMethodClassLoader() + { + StackTrace st = new StackTrace(); + for(int i = 0; i < st.FrameCount; i++) + { + StackFrame frame = st.GetFrame(i); + Type type = frame.GetMethod().DeclaringType; + if(type != null) + { + // TODO we need a more robust algorithm to find the "caller" (note that in addition to native methods, + // System.loadLibrary can also trigger executing native code) + ClassLoaderWrapper loader = ClassLoaderWrapper.GetWrapperFromType(type).GetClassLoader(); + if(loader.GetJavaClassLoader() != null) + { + return loader; + } + } + } + // TODO instead of using the bootstrap class loader, we need to use the system (aka application) class loader + return ClassLoaderWrapper.GetBootstrapClassLoader(); + } + + internal static IntPtr FindClass(JNIEnv* pEnv, byte* name) { try { - return MethodWrapper.FromCookie(cookie).Invoke(obj, args, nonVirtual); + TypeWrapper wrapper = FindNativeMethodClassLoader().LoadClassByDottedName(StringFromUTF8(name).Replace('/', '.')); + // TODO is this needed? + wrapper.Finish(); + return pEnv->MakeLocalRef(NativeCode.java.lang.VMClass.getClassFromWrapper(wrapper)); } catch(Exception x) { - throw ExceptionHelper.MapExceptionFast(x); + SetPendingException(pEnv, x); + return IntPtr.Zero; } } - // NOTE sig contains slashed class names - public static IntPtr GetFieldCookie(object clazz, string name, string sig, bool isStatic) + internal static IntPtr FromReflectedMethod(JNIEnv* pEnv, IntPtr method) + { + object methodObj = pEnv->UnwrapRef(method); + MethodWrapper mw = (MethodWrapper)methodObj.GetType().GetField("methodCookie", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(methodObj); + return mw.Cookie; + } + + internal static IntPtr FromReflectedField(JNIEnv* pEnv, IntPtr field) + { + object fieldObj = pEnv->UnwrapRef(field); + FieldWrapper fw = (FieldWrapper)fieldObj.GetType().GetField("fieldCookie", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(fieldObj); + return fw.Cookie; + } + + internal static IntPtr ToReflectedMethod(JNIEnv* pEnv, IntPtr clazz_ignored, IntPtr method) + { + MethodWrapper mw = MethodWrapper.FromCookie(method); + TypeWrapper tw; + if(mw.Name == "") + { + tw = ClassLoaderWrapper.LoadClassCritical("java.lang.reflect.Constructor"); + } + else + { + tw = ClassLoaderWrapper.LoadClassCritical("java.lang.reflect.Method"); + } + object clazz = NativeCode.java.lang.VMClass.getClassFromWrapper(mw.DeclaringType); + return pEnv->MakeLocalRef(Activator.CreateInstance(tw.TypeAsTBD, new object[] { clazz, mw })); + } + + internal static IntPtr GetSuperclass(JNIEnv* pEnv, IntPtr sub) + { + TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(sub)).BaseTypeWrapper; + return pEnv->MakeLocalRef(wrapper == null ? null : NativeCode.java.lang.VMClass.getClassFromWrapper(wrapper)); + } + + internal static sbyte IsAssignableFrom(JNIEnv* pEnv, IntPtr sub, IntPtr super) + { + TypeWrapper w1 = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(sub)); + TypeWrapper w2 = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(super)); + return w2.IsAssignableTo(w1) ? JNI_TRUE : JNI_FALSE; + } + + internal static IntPtr ToReflectedField(JNIEnv* pEnv, IntPtr clazz_ignored, IntPtr field) + { + FieldWrapper fw = FieldWrapper.FromCookie(field); + TypeWrapper tw = ClassLoaderWrapper.LoadClassCritical("java.lang.reflect.Field"); + object clazz = NativeCode.java.lang.VMClass.getClassFromWrapper(fw.DeclaringType); + return pEnv->MakeLocalRef(Activator.CreateInstance(tw.TypeAsTBD, new object[] { clazz, fw })); + } + + private static void SetPendingException(JNIEnv* pEnv, Exception x) + { + DeleteLocalRef(pEnv, pEnv->pendingException); + pEnv->pendingException = pEnv->MakeLocalRef(x); + } + + internal static int Throw(JNIEnv* pEnv, IntPtr throwable) + { + DeleteLocalRef(pEnv, pEnv->pendingException); + pEnv->pendingException = NewLocalRef(pEnv, throwable); + return JNI_OK; + } + + internal static int ThrowNew(JNIEnv* pEnv, IntPtr clazz, byte* msg) + { + TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)); + MethodWrapper mw = wrapper.GetMethodWrapper(new MethodDescriptor("", "(Ljava.lang.String;)V"), false); + if(mw != null) + { + int rc; + Exception exception; + try + { + wrapper.Finish(); + exception = (Exception)mw.Invoke(null, new object[] { StringFromUTF8(msg) }, false); + rc = JNI_OK; + } + catch(Exception x) + { + exception = x; + rc = JNI_ERR; + } + SetPendingException(pEnv, exception); + return rc; + } + else + { + SetPendingException(pEnv, JavaException.NoSuchMethodError("(Ljava.lang.String;)V")); + return JNI_ERR; + } + } + + internal static IntPtr ExceptionOccurred(JNIEnv* pEnv) + { + return NewLocalRef(pEnv, pEnv->pendingException); + } + + internal static void ExceptionDescribe(JNIEnv* pEnv) + { + Exception x = (Exception)pEnv->UnwrapRef(pEnv->pendingException); + if(x != null) + { + try + { + MethodWrapper mw = ClassLoaderWrapper.LoadClassCritical("java.lang.Throwable").GetMethodWrapper(new MethodDescriptor("printStackTrace", "()V"), false); + mw.Invoke(x, null, false); + } + catch(Exception ex) + { + Debug.Assert(false, ex.ToString()); + } + } + } + + internal static void ExceptionClear(JNIEnv* pEnv) + { + DeleteLocalRef(pEnv, pEnv->pendingException); + pEnv->pendingException = IntPtr.Zero; + } + + internal static void FatalError(JNIEnv* pEnv, byte* msg) + { + JVM.CriticalFailure(StringFromUTF8(msg), null); + } + + internal static IntPtr NewGlobalRef(JNIEnv* pEnv, IntPtr obj) + { + if(obj == IntPtr.Zero) + { + return IntPtr.Zero; + } + // TODO search for an empty slot before adding it to the end... + return (IntPtr)(-(GlobalRefs.globalRefs.Add(pEnv->UnwrapRef(obj)) + 1)); + } + + internal static void DeleteGlobalRef(JNIEnv* pEnv, IntPtr obj) + { + int i = obj.ToInt32(); + if(i < 0) + { + GlobalRefs.globalRefs[(-i) - 1] = null; + return; + } + if(i > 0) + { + Debug.Assert(false, "Local ref passed to DeleteGlobalRef"); + } + } + + internal static void DeleteLocalRef(JNIEnv* pEnv, IntPtr obj) + { + int i = obj.ToInt32(); + if(i > 0) + { + pEnv->u.activeFrame->localRefs[i >> LocalRefListEntry.LOCAL_REF_SHIFT].DeleteLocalRef(i & LocalRefListEntry.LOCAL_REF_MASK); + return; + } + if(i < 0) + { + Debug.Assert(false, "bogus localref in DeleteLocalRef"); + } + } + + internal static sbyte IsSameObject(JNIEnv* pEnv, IntPtr obj1, IntPtr obj2) + { + return pEnv->UnwrapRef(obj1) == pEnv->UnwrapRef(obj2) ? JNI_TRUE : JNI_FALSE; + } + + internal static IntPtr NewLocalRef(JNIEnv* pEnv, IntPtr obj) + { + return pEnv->MakeLocalRef(pEnv->UnwrapRef(obj)); + } + + internal static IntPtr AllocObject(JNIEnv* pEnv, IntPtr clazz) { try { - TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(clazz); + TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)); wrapper.Finish(); - // TODO what about searching the base classes? - FieldWrapper fw = wrapper.GetFieldWrapper(name, wrapper.GetClassLoader().ExpressionTypeWrapper(sig.Replace('/', '.'))); - if(fw != null) - { - if(fw.IsStatic == isStatic) - { - return fw.Cookie; - } - } - return (IntPtr)0; + // TODO add error handling (e.g. when trying to instantiate an interface or abstract class) + return pEnv->MakeLocalRef(System.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType)); } - catch + catch(Exception x) { - Debug.Assert(false); - throw; + SetPendingException(pEnv, x); + return IntPtr.Zero; } } - public static void SetFieldValue(IntPtr cookie, object obj, object val) + [StructLayout(LayoutKind.Explicit)] + internal struct jvalue + { + [FieldOffset(0)] + public sbyte b; + [FieldOffset(0)] + public short s; + [FieldOffset(0)] + public int i; + [FieldOffset(0)] + public long j; + [FieldOffset(0)] + public float f; + [FieldOffset(0)] + public double d; + [FieldOffset(0)] + public IntPtr l; + } + + private static object InvokeHelper(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue *args, bool nonVirtual) + { + string sig = GetMethodArgList(methodID); + object[] argarray = new object[sig.Length]; + for(int i = 0; i < sig.Length; i++) + { + switch(sig[i]) + { + case 'Z': + argarray[i] = args[i].b != 0; + break; + case 'B': + argarray[i] = args[i].b; + break; + case 'C': + argarray[i] = (char)args[i].s; + break; + case 'S': + argarray[i] = args[i].s; + break; + case 'I': + argarray[i] = args[i].i; + break; + case 'J': + argarray[i] = args[i].j; + break; + case 'F': + argarray[i] = args[i].f; + break; + case 'D': + argarray[i] = args[i].d; + break; + case 'L': + argarray[i] = pEnv->UnwrapRef(args[i].l); + break; + } + } + try + { + return MethodWrapper.FromCookie(methodID).Invoke(pEnv->UnwrapRef(obj), argarray, nonVirtual); + } + catch(Exception x) + { + SetPendingException(pEnv, ExceptionHelper.MapExceptionFast(x)); + return null; + } + } + + internal static IntPtr NewObjectA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false)); + } + + internal static IntPtr GetObjectClass(JNIEnv* pEnv, IntPtr obj) + { + return pEnv->MakeLocalRef(NativeCode.java.lang.VMClass.getClassFromType(pEnv->UnwrapRef(obj).GetType())); + } + + internal static sbyte IsInstanceOf(JNIEnv* pEnv, IntPtr obj, IntPtr clazz) + { + object objClass = NativeCode.java.lang.VMClass.getClassFromType(pEnv->UnwrapRef(obj).GetType()); + TypeWrapper w1 = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)); + TypeWrapper w2 = NativeCode.java.lang.VMClass.getWrapperFromClass(objClass); + return w2.IsAssignableTo(w1) ? JNI_TRUE : JNI_FALSE; + } + + private static IntPtr FindMethodID(JNIEnv* pEnv, IntPtr clazz, byte* name, byte* sig, bool isstatic) + { + try + { + TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)); + wrapper.Finish(); + MethodDescriptor md = new MethodDescriptor(StringFromUTF8(name), StringFromUTF8(sig).Replace('/', '.')); + MethodWrapper mw = wrapper.GetMethodWrapper(md, true); + if(mw != null) + { + if(mw.IsStatic == isstatic) + { + mw.Link(); + return mw.Cookie; + } + } + SetPendingException(pEnv, JavaException.NoSuchMethodError("{0}{1}", md.Name, md.Signature)); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + } + return IntPtr.Zero; + } + + internal static IntPtr GetMethodID(JNIEnv* pEnv, IntPtr clazz, byte* name, byte* sig) + { + return FindMethodID(pEnv, clazz, name, sig, false); + } + + internal static IntPtr CallObjectMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, false)); + } + + internal static sbyte CallBooleanMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return ((bool)o) ? JNI_TRUE : JNI_FALSE; + } + return JNI_FALSE; + } + + internal static sbyte CallByteMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (sbyte)o; + } + return 0; + } + + internal static short CallCharMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (short)(char)o; + } + return 0; + } + + internal static short CallShortMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (short)o; + } + return 0; + } + + internal static int CallIntMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (int)o; + } + return 0; + } + + internal static long CallLongMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (long)o; + } + return 0; + } + + internal static float CallFloatMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (float)o; + } + return 0; + } + + internal static double CallDoubleMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (double)o; + } + return 0; + } + + internal static void CallVoidMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr methodID, jvalue* args) + { + InvokeHelper(pEnv, obj, methodID, args, false); + } + + internal static IntPtr CallNonvirtualObjectMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, true)); + } + + internal static sbyte CallNonvirtualBooleanMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return ((bool)o) ? JNI_TRUE : JNI_FALSE; + } + return JNI_FALSE; + } + + internal static sbyte CallNonvirtualByteMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (sbyte)o; + } + return 0; + } + + internal static short CallNonvirtualCharMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (short)(char)o; + } + return 0; + } + + internal static short CallNonvirtualShortMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (short)o; + } + return 0; + } + + internal static int CallNonvirtualIntMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (int)o; + } + return 0; + } + + internal static long CallNonvirtualLongMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (long)o; + } + return 0; + } + + internal static float CallNonvirtualFloatMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (float)o; + } + return 0; + } + + internal static double CallNonvirtualDoubleMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (double)o; + } + return 0; + } + + internal static void CallNonvirtualVoidMethodA(JNIEnv* pEnv, IntPtr obj, IntPtr clazz, IntPtr methodID, jvalue* args) + { + InvokeHelper(pEnv, obj, methodID, args, true); + } + + private static IntPtr FindFieldID(JNIEnv* pEnv, IntPtr clazz, byte* name, byte* sig, bool isstatic) + { + try + { + TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)); + wrapper.Finish(); + // TODO what about searching the base classes? + FieldWrapper fw = wrapper.GetFieldWrapper(StringFromUTF8(name), wrapper.GetClassLoader().ExpressionTypeWrapper(StringFromUTF8(sig).Replace('/', '.'))); + if(fw != null) + { + if(fw.IsStatic == isstatic) + { + // TODO fw.Link() + return fw.Cookie; + } + } + SetPendingException(pEnv, JavaException.NoSuchFieldError(StringFromUTF8(name))); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + } + return IntPtr.Zero; + } + + internal static IntPtr GetFieldID(JNIEnv* pEnv, IntPtr clazz, byte* name, byte* sig) + { + return FindFieldID(pEnv, clazz, name, sig, false); + } + + private static void SetFieldValue(IntPtr cookie, object obj, object val) { try { @@ -145,7 +1417,7 @@ public sealed class JniHelper } } - public static object GetFieldValue(IntPtr cookie, object obj) + private static object GetFieldValue(IntPtr cookie, object obj) { try { @@ -158,206 +1430,1264 @@ public sealed class JniHelper } } - public static object FindClass(string javaName) + internal static IntPtr GetObjectField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID) { - try - { - // TODO instead of using the bootstrap class loader, we need to use the system (aka application) class loader - TypeWrapper wrapper = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(javaName.Replace('/', '.')); - wrapper.Finish(); - return NativeCode.java.lang.VMClass.getClassFromWrapper(wrapper); - } - catch - { - Debug.Assert(false); - throw; - } + return pEnv->MakeLocalRef(GetFieldValue(fieldID, pEnv->UnwrapRef(obj))); } - public static Exception UnsatisfiedLinkError(string msg) + internal static sbyte GetBooleanField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID) { - try - { - return JavaException.UnsatisfiedLinkError(msg); - } - catch - { - Debug.Assert(false); - throw; - } + return ((bool)GetFieldValue(fieldID, pEnv->UnwrapRef(obj))) ? JNI_TRUE : JNI_FALSE; } - [Obsolete] - public static object GetClassFromType(Type type) + internal static sbyte GetByteField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID) { - try - { - return NativeCode.java.lang.VMClass.getClassFromType(type); - } - catch - { - Debug.Assert(false); - throw; - } + return (sbyte)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); } - public static object GetObjectClass(object o) + internal static short GetCharField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID) { - try - { - return NativeCode.java.lang.VMClass.getClassFromType(o.GetType()); - } - catch - { - Debug.Assert(false); - throw; - } + return (short)(char)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); } - public static bool IsInstanceOf(object o, object clazz) + internal static short GetShortField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID) { - try - { - return IsAssignableFrom(clazz, GetObjectClass(o)); - } - catch - { - Debug.Assert(false); - throw; - } + return (short)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); } - public static bool IsAssignableFrom(object sub, object sup) + internal static int GetIntField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID) { - try - { - TypeWrapper w1 = NativeCode.java.lang.VMClass.getWrapperFromClass(sub); - TypeWrapper w2 = NativeCode.java.lang.VMClass.getWrapperFromClass(sup); - return w2.IsAssignableTo(w1); - } - catch - { - Debug.Assert(false); - throw; - } - } - - public static object GetSuperclass(object clazz) - { - try - { - TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(clazz).BaseTypeWrapper; - return wrapper == null ? null : NativeCode.java.lang.VMClass.getClassFromWrapper(wrapper); - } - catch - { - Debug.Assert(false); - throw; - } + return (int)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); } - public static object AllocObject(object clazz) + internal static long GetLongField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID) { - try - { - TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(clazz); - wrapper.Finish(); - // TODO add error handling (e.g. when trying to instantiate an interface or abstract class) - return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType); - } - catch - { - Debug.Assert(false); - throw; - } + return (long)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); } - public static IntPtr MethodToCookie(object method) + internal static float GetFloatField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID) { - try - { - MethodWrapper mw = (MethodWrapper)method.GetType().GetField("methodCookie", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(method); - return mw.Cookie; - } - catch - { - Debug.Assert(false); - throw; - } + return (float)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); } - public static IntPtr FieldToCookie(object field) + internal static double GetDoubleField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID) { - try - { - FieldWrapper fw = (FieldWrapper)field.GetType().GetField("fieldCookie", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(field); - return fw.Cookie; - } - catch - { - Debug.Assert(false); - throw; - } + return (double)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); } - public static object CookieToMethod(IntPtr method) + internal static void SetObjectField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID, IntPtr val) { - try + SetFieldValue(fieldID, pEnv->UnwrapRef(obj), pEnv->UnwrapRef(val)); + } + + internal static void SetBooleanField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID, sbyte val) + { + SetFieldValue(fieldID, pEnv->UnwrapRef(obj), val != JNI_FALSE); + } + + internal static void SetByteField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID, sbyte val) + { + SetFieldValue(fieldID, pEnv->UnwrapRef(obj), val); + } + + internal static void SetCharField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID, short val) + { + SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (char)val); + } + + internal static void SetShortField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID, short val) + { + SetFieldValue(fieldID, pEnv->UnwrapRef(obj), val); + } + + internal static void SetIntField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID, int val) + { + SetFieldValue(fieldID, pEnv->UnwrapRef(obj), val); + } + + internal static void SetLongField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID, long val) + { + SetFieldValue(fieldID, pEnv->UnwrapRef(obj), val); + } + + internal static void SetFloatField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID, float val) + { + SetFieldValue(fieldID, pEnv->UnwrapRef(obj), val); + } + + internal static void SetDoubleField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID, double val) + { + SetFieldValue(fieldID, pEnv->UnwrapRef(obj), val); + } + + internal static IntPtr GetStaticMethodID(JNIEnv* pEnv, IntPtr clazz, byte* name, byte* sig) + { + return FindMethodID(pEnv, clazz, name, sig, true); + } + + internal static IntPtr CallStaticObjectMethodA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false)); + } + + internal static sbyte CallStaticBooleanMethodA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) { - MethodWrapper mw = MethodWrapper.FromCookie(method); - TypeWrapper tw; - if(mw.Name == "") + return ((bool)o) ? JNI_TRUE : JNI_FALSE; + } + return JNI_FALSE; + } + + internal static sbyte CallStaticByteMethodA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (sbyte)o; + } + return 0; + } + + internal static short CallStaticCharMethodA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (short)(char)o; + } + return 0; + } + + internal static short CallStaticShortMethodA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (short)o; + } + return 0; + } + + internal static int CallStaticIntMethodA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (int)o; + } + return 0; + } + + internal static long CallStaticLongMethodA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (long)o; + } + return 0; + } + + internal static float CallStaticFloatMethodA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (float)o; + } + return 0; + } + + internal static double CallStaticDoubleMethodA(JNIEnv* pEnv, IntPtr clazz, IntPtr methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (double)o; + } + return 0; + } + + internal static void CallStaticVoidMethodA(JNIEnv* pEnv, IntPtr cls, IntPtr methodID, jvalue * args) + { + InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + } + + internal static IntPtr GetStaticFieldID(JNIEnv* pEnv, IntPtr clazz, byte* name, byte* sig) + { + return FindFieldID(pEnv, clazz, name, sig, true); + } + + internal static IntPtr GetStaticObjectField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID) + { + return pEnv->MakeLocalRef(GetFieldValue(fieldID, null)); + } + + internal static sbyte GetStaticBooleanField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID) + { + return ((bool)GetFieldValue(fieldID, null)) ? JNI_TRUE : JNI_FALSE; + } + + internal static sbyte GetStaticByteField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID) + { + return (sbyte)GetFieldValue(fieldID, null); + } + + internal static short GetStaticCharField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID) + { + return (short)(char)GetFieldValue(fieldID, null); + } + + internal static short GetStaticShortField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID) + { + return (short)GetFieldValue(fieldID, null); + } + + internal static int GetStaticIntField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID) + { + return (int)GetFieldValue(fieldID, null); + } + + internal static long GetStaticLongField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID) + { + return (long)GetFieldValue(fieldID, null); + } + + internal static float GetStaticFloatField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID) + { + return (float)GetFieldValue(fieldID, null); + } + + internal static double GetStaticDoubleField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID) + { + return (double)GetFieldValue(fieldID, null); + } + + internal static void SetStaticObjectField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID, IntPtr val) + { + SetFieldValue(fieldID, null, pEnv->UnwrapRef(val)); + } + + internal static void SetStaticBooleanField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID, sbyte val) + { + SetFieldValue(fieldID, null, val != JNI_FALSE); + } + + internal static void SetStaticByteField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID, sbyte val) + { + SetFieldValue(fieldID, null, val); + } + + internal static void SetStaticCharField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID, short val) + { + SetFieldValue(fieldID, null, (char)val); + } + + internal static void SetStaticShortField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID, short val) + { + SetFieldValue(fieldID, null, val); + } + + internal static void SetStaticIntField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID, int val) + { + SetFieldValue(fieldID, null, val); + } + + internal static void SetStaticLongField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID, long val) + { + SetFieldValue(fieldID, null, val); + } + + internal static void SetStaticFloatField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID, float val) + { + SetFieldValue(fieldID, null, val); + } + + internal static void SetStaticDoubleField(JNIEnv* pEnv, IntPtr clazz, IntPtr fieldID, double val) + { + SetFieldValue(fieldID, null, val); + } + + internal static IntPtr NewString(JNIEnv* pEnv, char* unicode, int len) + { + return pEnv->MakeLocalRef(new String(unicode, 0, len)); + } + + internal static int GetStringLength(JNIEnv* pEnv, IntPtr str) + { + return ((string)pEnv->UnwrapRef(str)).Length; + } + + internal static IntPtr GetStringChars(JNIEnv* pEnv, IntPtr str, IntPtr isCopy) + { + string s = (string)pEnv->UnwrapRef(str); + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return Marshal.StringToHGlobalUni(s); + } + + internal static void ReleaseStringChars(JNIEnv* pEnv, IntPtr str, IntPtr chars) + { + Marshal.FreeHGlobal(chars); + } + + internal static IntPtr NewStringUTF(JNIEnv* pEnv, IntPtr psz) + { + return pEnv->MakeLocalRef(StringFromUTF8((byte*)(void*)psz)); + } + + internal static int GetStringUTFLength(JNIEnv* pEnv, IntPtr str) + { + return StringUTF8Length((string)pEnv->UnwrapRef(str)); + } + + internal static IntPtr GetStringUTFChars(JNIEnv* pEnv, IntPtr str, IntPtr isCopy) + { + string s = (string)pEnv->UnwrapRef(str); + byte* buf = (byte*)Marshal.AllocHGlobal(StringUTF8Length(s) + 1); + int j = 0; + for(int i = 0; i < s.Length; i++) + { + char ch = s[i]; + if((ch != 0) && (ch <= 0x7F)) { - tw = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName("java.lang.reflect.Constructor"); + buf[j++] = (byte)ch; + } + else if(ch <= 0x7FF) + { + buf[j++] = (byte)((ch >> 6) | 0xC0); + buf[j++] = (byte)((ch & 0x3F) | 0x80); } else { - tw = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName("java.lang.reflect.Method"); + buf[j++] = (byte)((ch >> 12) | 0xE0); + buf[j++] = (byte)(((ch >> 6) & 0x3F) | 0x80); + buf[j++] = (byte)((ch & 0x3F) | 0x80); } - object clazz = NativeCode.java.lang.VMClass.getClassFromWrapper(mw.DeclaringType); - return Activator.CreateInstance(tw.TypeAsTBD, new object[] { clazz, mw }); } - catch + buf[j] = 0; + if(isCopy != IntPtr.Zero) { - Debug.Assert(false); - throw; + *((sbyte*)(void*)isCopy) = JNI_TRUE; } + return (IntPtr)(void*)buf; } - public static object CookieToField(IntPtr field) + internal static void ReleaseStringUTFChars(JNIEnv* pEnv, IntPtr str, IntPtr chars) + { + Marshal.FreeHGlobal(chars); + } + + internal static int GetArrayLength(JNIEnv* pEnv, IntPtr array) + { + return ((Array)pEnv->UnwrapRef(array)).Length; + } + + internal static IntPtr NewObjectArray(JNIEnv* pEnv, int len, IntPtr clazz, IntPtr init) + { + // TODO if we want to support (non-primitive) value types we can't use the object[] cast + object[] array = (object[])Array.CreateInstance(NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)).TypeAsArrayType, len); + object o = pEnv->UnwrapRef(init); + if(o != null) + { + for(int i = 0; i < array.Length; i++) + { + array[i] = o; + } + } + return pEnv->MakeLocalRef(array); + } + + internal static IntPtr GetObjectArrayElement(JNIEnv* pEnv, IntPtr array, int index) { try { - FieldWrapper fw = FieldWrapper.FromCookie(field); - TypeWrapper tw = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName("java.lang.reflect.Field"); - object clazz = NativeCode.java.lang.VMClass.getClassFromWrapper(fw.DeclaringType); - return Activator.CreateInstance(tw.TypeAsTBD, new object[] { clazz, fw }); + // TODO if we want to support (non-primitive) value types we can't use the object[] cast + return pEnv->MakeLocalRef(((object[])pEnv->UnwrapRef(array))[index]); } - catch + catch(IndexOutOfRangeException) { - Debug.Assert(false); - throw; + SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException()); + return IntPtr.Zero; } } - public static void FatalError(string msg) + internal static void SetObjectArrayElement(JNIEnv* pEnv, IntPtr array, int index, IntPtr val) { - JVM.CriticalFailure(msg, null); + try + { + // TODO if we want to support (non-primitive) value types we can't use the object[] cast + ((object[])pEnv->UnwrapRef(array))[index] = pEnv->UnwrapRef(val); + } + catch(IndexOutOfRangeException) + { + SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException()); + } } - public static object DefineClass(string name, object classLoader, byte[] buf) + internal static IntPtr NewBooleanArray(JNIEnv* pEnv, int len) { - // TODO what should the protection domain be? - return NativeCode.java.lang.VMClassLoader.defineClass(classLoader, name, buf, 0, buf.Length, null); + return pEnv->MakeLocalRef(new bool[len]); + } + + internal static IntPtr NewByteArray(JNIEnv* pEnv, int len) + { + return pEnv->MakeLocalRef(new sbyte[len]); + } + + internal static IntPtr NewCharArray(JNIEnv* pEnv, int len) + { + return pEnv->MakeLocalRef(new char[len]); + } + + internal static IntPtr NewShortArray(JNIEnv* pEnv, int len) + { + return pEnv->MakeLocalRef(new short[len]); + } + + internal static IntPtr NewIntArray(JNIEnv* pEnv, int len) + { + return pEnv->MakeLocalRef(new int[len]); + } + + internal static IntPtr NewLongArray(JNIEnv* pEnv, int len) + { + return pEnv->MakeLocalRef(new long[len]); + } + + internal static IntPtr NewFloatArray(JNIEnv* pEnv, int len) + { + return pEnv->MakeLocalRef(new float[len]); + } + + internal static IntPtr NewDoubleArray(JNIEnv* pEnv, int len) + { + return pEnv->MakeLocalRef(new double[len]); + } + + internal static IntPtr GetBooleanArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) + { + bool[] b = (bool[])pEnv->UnwrapRef(array); + IntPtr buf = Marshal.AllocHGlobal(b.Length * 1); + sbyte* p = (sbyte*)(void*)buf; + for(int i = 0; i < b.Length; i++) + { + *p++ = b[i] ? JNI_TRUE : JNI_FALSE; + } + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return buf; + } + + internal static IntPtr GetByteArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) + { + sbyte[] b = (sbyte[])pEnv->UnwrapRef(array); + IntPtr buf = Marshal.AllocHGlobal(b.Length * 1); + sbyte* p = (sbyte*)(void*)buf; + for(int i = 0; i < b.Length; i++) + { + *p++ = b[i]; + } + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return buf; + } + + internal static IntPtr GetCharArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) + { + char[] b = (char[])pEnv->UnwrapRef(array); + IntPtr buf = Marshal.AllocHGlobal(b.Length * 2); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return buf; + } + + internal static IntPtr GetShortArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) + { + short[] b = (short[])pEnv->UnwrapRef(array); + IntPtr buf = Marshal.AllocHGlobal(b.Length * 2); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return buf; + } + + internal static IntPtr GetIntArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) + { + int[] b = (int[])pEnv->UnwrapRef(array); + IntPtr buf = Marshal.AllocHGlobal(b.Length * 4); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return buf; + } + + internal static IntPtr GetLongArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) + { + long[] b = (long[])pEnv->UnwrapRef(array); + IntPtr buf = Marshal.AllocHGlobal(b.Length * 8); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return buf; + } + + internal static IntPtr GetFloatArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) + { + float[] b = (float[])pEnv->UnwrapRef(array); + IntPtr buf = Marshal.AllocHGlobal(b.Length * 4); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return buf; + } + + internal static IntPtr GetDoubleArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) + { + double[] b = (double[])pEnv->UnwrapRef(array); + IntPtr buf = Marshal.AllocHGlobal(b.Length * 8); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return buf; + } + + internal static void ReleaseBooleanArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr elems, int mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + bool[] b = (bool[])pEnv->UnwrapRef(array); + sbyte* p = (sbyte*)(void*)elems; + for(int i = 0; i < b.Length; i++) + { + b[i] = *p++ != JNI_FALSE; + } + } + if(mode == 0 || mode == JNI_ABORT) + { + Marshal.FreeHGlobal(elems); + } + } + + internal static void ReleaseByteArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr elems, int mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + sbyte[] b = (sbyte[])pEnv->UnwrapRef(array); + sbyte* p = (sbyte*)(void*)elems; + for(int i = 0; i < b.Length; i++) + { + b[i] = *p++; + } + } + if(mode == 0 || mode == JNI_ABORT) + { + Marshal.FreeHGlobal(elems); + } + } + + internal static void ReleaseCharArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr elems, int mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + char[] b = (char[])pEnv->UnwrapRef(array); + Marshal.Copy(elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + Marshal.FreeHGlobal(elems); + } + } + + internal static void ReleaseShortArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr elems, int mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + short[] b = (short[])pEnv->UnwrapRef(array); + Marshal.Copy(elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + Marshal.FreeHGlobal(elems); + } + } + + internal static void ReleaseIntArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr elems, int mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + int[] b = (int[])pEnv->UnwrapRef(array); + Marshal.Copy(elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + Marshal.FreeHGlobal(elems); + } + } + + internal static void ReleaseLongArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr elems, int mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + long[] b = (long[])pEnv->UnwrapRef(array); + Marshal.Copy(elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + Marshal.FreeHGlobal(elems); + } + } + + internal static void ReleaseFloatArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr elems, int mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + float[] b = (float[])pEnv->UnwrapRef(array); + Marshal.Copy(elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + Marshal.FreeHGlobal(elems); + } + } + + internal static void ReleaseDoubleArrayElements(JNIEnv* pEnv, IntPtr array, IntPtr elems, int mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + double[] b = (double[])pEnv->UnwrapRef(array); + Marshal.Copy(elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + Marshal.FreeHGlobal(elems); + } + } + + internal static void GetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + bool[] b = (bool[])pEnv->UnwrapRef(array); + sbyte* p = (sbyte*)(void*)buf; + for(int i = 0; i < len; i++) + { + *p++ = b[start + i] ? JNI_TRUE : JNI_FALSE; + } + } + + internal static void GetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + sbyte[] b = (sbyte[])pEnv->UnwrapRef(array); + sbyte* p = (sbyte*)(void*)buf; + for(int i = 0; i < len; i++) + { + *p++ = b[start + i]; + } + } + + internal static void GetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + char[] b = (char[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + + internal static void GetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + short[] b = (short[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + + internal static void GetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + int[] b = (int[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + + internal static void GetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + long[] b = (long[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + + internal static void GetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + float[] b = (float[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + + internal static void GetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + double[] b = (double[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + + internal static void SetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + bool[] b = (bool[])pEnv->UnwrapRef(array); + sbyte* p = (sbyte*)(void*)buf; + for(int i = 0; i < len; i++) + { + b[start + i] = *p++ != JNI_FALSE; + } + } + + internal static void SetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + sbyte[] b = (sbyte[])pEnv->UnwrapRef(array); + sbyte* p = (sbyte*)(void*)buf; + for(int i = 0; i < len; i++) + { + b[start + i] = *p++; + } + } + + internal static void SetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + char[] b = (char[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + + internal static void SetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + short[] b = (short[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + + internal static void SetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + int[] b = (int[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + + internal static void SetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + long[] b = (long[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + + internal static void SetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + float[] b = (float[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + + internal static void SetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + double[] b = (double[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + + [StructLayout(LayoutKind.Sequential)] + internal struct JNINativeMethod + { + public byte* name; + public byte* signature; + public void* fnPtr; + } + + internal static int RegisterNatives(JNIEnv* pEnv, IntPtr clazz, JNINativeMethod* methods, int nMethods) + { + try + { + TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)); + wrapper.Finish(); + for(int i = 0; i < nMethods; i++) + { + FieldInfo fi = wrapper.TypeAsTBD.GetField("jniptr/" + StringFromUTF8(methods[i].name) + StringFromUTF8(methods[i].signature).Replace('/', '.'), BindingFlags.Static | BindingFlags.NonPublic); + if(fi == null) + { + SetPendingException(pEnv, JavaException.NoSuchMethodError(StringFromUTF8(methods[i].name))); + return JNI_ERR; + } + fi.SetValue(null, (IntPtr)methods[i].fnPtr); + } + return JNI_OK; + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return JNI_ERR; + } + } + + internal static int UnregisterNatives(JNIEnv* pEnv, IntPtr clazz) + { + try + { + TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)); + wrapper.Finish(); + foreach(FieldInfo fi in wrapper.TypeAsTBD.GetFields(BindingFlags.Static | BindingFlags.NonPublic)) + { + if(fi.Name.StartsWith("jniptr/")) + { + fi.SetValue(null, IntPtr.Zero); + } + } + return JNI_OK; + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return JNI_ERR; + } + } + + internal static int MonitorEnter(JNIEnv* pEnv, IntPtr obj) + { + try + { + System.Threading.Monitor.Enter(pEnv->UnwrapRef(obj)); + return JNI_OK; + } + catch(System.Threading.ThreadInterruptedException) + { + SetPendingException(pEnv, JavaException.InterruptedException()); + return JNI_ERR; + } + } + + internal static int MonitorExit(JNIEnv* pEnv, IntPtr obj) + { + try + { + System.Threading.Monitor.Exit(pEnv->UnwrapRef(obj)); + return JNI_OK; + } + catch(System.Threading.SynchronizationLockException) + { + SetPendingException(pEnv, JavaException.IllegalMonitorStateException()); + return JNI_ERR; + } + } + + internal static int GetJavaVM(JNIEnv* pEnv, JavaVM **ppJavaVM) + { + *ppJavaVM = JavaVM.pJavaVM; + return JNI_OK; + } + + internal static void GetStringRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf) + { + string s = (string)pEnv->UnwrapRef(str); + if(s != null) + { + if(start < 0 || start > s.Length || s.Length - start < len) + { + SetPendingException(pEnv, JavaException.StringIndexOutOfBoundsException("")); + return; + } + else + { + char* p = (char*)(void*)buf; + // TODO isn't there a managed memcpy? + for(int i = 0; i < len; i++) + { + *p++ = s[start + i]; + } + return; + } + } + else + { + SetPendingException(pEnv, JavaException.NullPointerException()); + } + } + + internal static void GetStringUTFRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf) + { + string s = (string)pEnv->UnwrapRef(str); + if(s != null) + { + if(start < 0 || start > s.Length || s.Length - start < len) + { + SetPendingException(pEnv, JavaException.StringIndexOutOfBoundsException("")); + return; + } + else + { + byte* p = (byte*)(void*)buf; + for(int i = 0; i < len; i++) + { + char ch = s[start + i]; + if((ch != 0) && (ch <= 0x7F)) + { + *p++ = (byte)ch; + } + else if(ch <= 0x7FF) + { + *p++ = (byte)((ch >> 6) | 0xC0); + *p++ = (byte)((ch & 0x3F) | 0x80); + } + else + { + *p++ = (byte)((ch >> 12) | 0xE0); + *p++ = (byte)(((ch >> 6) & 0x3F) | 0x80); + *p++ = (byte)((ch & 0x3F) | 0x80); + } + } + return; + } + } + else + { + SetPendingException(pEnv, JavaException.NullPointerException()); + } + } + + private static int GetPrimitiveArrayElementSize(Array ar) + { + Type type = ar.GetType().GetElementType(); + if(type == typeof(sbyte) || type == typeof(bool)) + { + return 1; + } + else if(type == typeof(short) || type == typeof(char)) + { + return 2; + } + else if(type == typeof(int) || type == typeof(float)) + { + return 4; + } + else if(type == typeof(long) || type == typeof(double)) + { + return 8; + } + else + { + JVM.CriticalFailure("invalid array type", null); + return 0; + } + } + + internal static IntPtr GetPrimitiveArrayCritical(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) + { + Array ar = (Array)pEnv->UnwrapRef(array); + int len = ar.Length * GetPrimitiveArrayElementSize(ar); + GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned); + try + { + IntPtr hglobal = Marshal.AllocHGlobal(len); + byte* pdst = (byte*)(void*)hglobal; + byte* psrc = (byte*)(void*)h.AddrOfPinnedObject(); + // TODO isn't there a managed memcpy? + for(int i = 0; i < len; i++) + { + *pdst++ = *psrc++; + } + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return hglobal; + } + finally + { + h.Free(); + } + } + + internal static void ReleasePrimitiveArrayCritical(JNIEnv* pEnv, IntPtr array, IntPtr carray, int mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + Array ar = (Array)pEnv->UnwrapRef(array); + int len = ar.Length * GetPrimitiveArrayElementSize(ar); + GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned); + try + { + byte* pdst = (byte*)(void*)h.AddrOfPinnedObject(); + byte* psrc = (byte*)(void*)carray; + // TODO isn't there a managed memcpy? + for(int i = 0; i < len; i++) + { + *pdst++ = *psrc++; + } + } + finally + { + h.Free(); + } + } + if(mode == 0 || mode == JNI_ABORT) + { + Marshal.FreeHGlobal(carray); + } + } + + internal static IntPtr GetStringCritical(JNIEnv* pEnv, IntPtr str, IntPtr isCopy) + { + string s = (string)pEnv->UnwrapRef(str); + if(s != null) + { + if(isCopy != IntPtr.Zero) + { + *((sbyte*)(void*)isCopy) = JNI_TRUE; + } + return Marshal.StringToHGlobalUni(s); + } + SetPendingException(pEnv, JavaException.NullPointerException()); + return IntPtr.Zero; + } + + internal static void ReleaseStringCritical(JNIEnv* pEnv, IntPtr str, IntPtr cstring) + { + Marshal.FreeHGlobal(cstring); + } + + internal static sbyte ExceptionCheck(JNIEnv* pEnv) + { + return pEnv->UnwrapRef(pEnv->pendingException) != null ? JNI_TRUE : JNI_FALSE; + } + + internal static void NotImplemented(JNIEnv* pEnv) + { + JVM.CriticalFailure("Unimplemented JNIEnv function called", null); + } + + internal IntPtr MakeLocalRef(object obj) + { + return u.activeFrame->MakeLocalRef(obj); + } + + internal object UnwrapRef(IntPtr o) + { + int i = o.ToInt32(); + if(i > 0) + { + return u.activeFrame->UnwrapLocalRef(o); + } + if(i < 0) + { + return GlobalRefs.globalRefs[(-i) - 1]; + } + return null; } } -public interface IJniProvider +unsafe class TlsHack { - int LoadNativeLibrary(string filename); - Type GetLocalRefStructType(); - // NOTE the signature of the GetJniFuncPtr method is: - // IntPtr GetJniFuncPtr(String method, String sig, String clazz) - // sig & clazz are contain slashed class names - MethodInfo GetJniFuncPtrMethod(); + [ThreadStatic] + internal static JNIEnv* pJNIEnv; +} + +[StructLayout(LayoutKind.Sequential)] +public unsafe struct JniFrame +{ + private JNIEnv* pJNIEnv; + private JniFrame* pPrevFrame; + private LocalRefCache fastlocalrefs; + internal LocalRefListEntry[] localRefs; + private RuntimeMethodHandle method; + // HACK since this isn't a blittable type and C# doesn't allow us to turn the this pointer into a JniFrame*, we need + // this hack to turn the address of a field into a pointer to the struct (it turns out that on the 1.1 CLR the address + // of the first field is not equal to the this pointer [for this particular struct]) + private static readonly int jniFramePointerAdjustment = (int)new JNIEnv.Union().activeFrame->GetAddress(); + + private byte* GetAddress() + { + fixed(void* p = &pJNIEnv) + { + return (byte*)p; + } + } + + public IntPtr Enter(RuntimeMethodHandle method) + { + this.method = method; + pJNIEnv = TlsHack.pJNIEnv; + if(pJNIEnv == null) + { + // TODO when the thread dies, we're leaking the JNIEnv and the GCHandle + pJNIEnv = TlsHack.pJNIEnv = (JNIEnv*)Marshal.AllocHGlobal(sizeof(JNIEnv)); + pJNIEnv->vtable = VtableBuilder.vtable; + pJNIEnv->u.activeFrame = null; + localRefs = new LocalRefListEntry[32]; + pJNIEnv->localRefs = GCHandle.Alloc(localRefs); + pJNIEnv->localRefSlot = 0; + pJNIEnv->pendingException = IntPtr.Zero; + } + else + { + localRefs = (LocalRefListEntry[])pJNIEnv->localRefs.Target; + } + pPrevFrame = pJNIEnv->u.activeFrame; + pJNIEnv->u.pFrame = GetAddress() - jniFramePointerAdjustment; + pJNIEnv->localRefSlot++; + if(pJNIEnv->localRefSlot >= localRefs.Length) + { + // TODO instead of bailing out, we should grow the array + JVM.CriticalFailure("JNI nesting too deep", null); + } + fixed(void* p = &pPrevFrame) + { + // HACK we assume that the fastlocalrefs struct starts at &pPrevFrame + IntPtr.Size + localRefs[pJNIEnv->localRefSlot].u.pv = ((byte*)p) + IntPtr.Size; + } + return (IntPtr)(void*)pJNIEnv; + } + + public void Leave() + { + Exception x = (Exception)pJNIEnv->UnwrapRef(pJNIEnv->pendingException); + pJNIEnv->pendingException = IntPtr.Zero; + pJNIEnv->u.activeFrame = pPrevFrame; + localRefs[pJNIEnv->localRefSlot].dynamic_list = null; + // TODO figure out if it is legal to Leave a JNI method while PushLocalFrame is active + // (i.e. without the corresponding PopLocalFrame) + pJNIEnv->localRefSlot--; + if(x != null) + { + throw x; + } + } + + public static IntPtr GetFuncPtr(RuntimeMethodHandle method, string clazz, string name, string sig) + { + MethodBase mb = MethodBase.GetMethodFromHandle(method); + // MONOBUG Mono 1.0 doesn't implement MethodBase.GetMethodFromHandle + if(mb == null) + { + mb = new StackFrame(1).GetMethod(); + } + ClassLoaderWrapper loader = ClassLoaderWrapper.GetWrapperFromType(mb.DeclaringType).GetClassLoader(); + StringBuilder mangledSig = new StringBuilder(); + int sp = 0; + for(int i = 1; sig[i] != ')'; i++) + { + switch(sig[i]) + { + case '[': + mangledSig.Append("_3"); + sp += IntPtr.Size; + while(sig[++i] == '[') + { + mangledSig.Append("_3"); + } + mangledSig.Append(sig[i]); + if(sig[i] == 'L') + { + while(sig[++i] != ';') + { + if(sig[i] == '/') + { + mangledSig.Append("_"); + } + else if(sig[i] == '_') + { + mangledSig.Append("_1"); + } + else + { + mangledSig.Append(sig[i]); + } + } + mangledSig.Append("_2"); + } + break; + case 'L': + sp += IntPtr.Size; + mangledSig.Append("L"); + while(sig[++i] != ';') + { + if(sig[i] == '/') + { + mangledSig.Append("_"); + } + else if(sig[i] == '_') + { + mangledSig.Append("_1"); + } + else + { + mangledSig.Append(sig[i]); + } + } + mangledSig.Append("_2"); + break; + case 'J': + case 'D': + mangledSig.Append(sig[i]); + sp += 8; + break; + case 'F': + case 'I': + case 'C': + case 'Z': + case 'S': + case 'B': + mangledSig.Append(sig[i]); + sp += 4; + break; + default: + Debug.Assert(false); + break; + } + } + lock(JniHelper.JniLock) + { + string methodName = String.Format("Java_{0}_{1}", clazz.Replace("_", "_1").Replace('/', '_'), name.Replace("_", "_1")); + foreach(IntPtr p in loader.GetNativeLibraries()) + { + IntPtr pfunc = JniHelper.ikvm_GetProcAddress(p, methodName, sp + 2 * IntPtr.Size); + if(pfunc != IntPtr.Zero) + { + return pfunc; + } + } + methodName = String.Format("Java_{0}_{1}__{2}", clazz.Replace("_", "_1").Replace('/', '_'), name.Replace("_", "_1"), mangledSig); + foreach(IntPtr p in loader.GetNativeLibraries()) + { + IntPtr pfunc = JniHelper.ikvm_GetProcAddress(p, methodName, sp + 2 * IntPtr.Size); + if(pfunc != IntPtr.Zero) + { + return pfunc; + } + } + } + throw JavaException.UnsatisfiedLinkError("{0}.{1}{2}", clazz, name, sig); + } + + public IntPtr MakeLocalRef(object obj) + { + if(obj == null) + { + return IntPtr.Zero; + } + int i = localRefs[pJNIEnv->localRefSlot].MakeLocalRef(obj); + if(i >= 0) + { + return (IntPtr)((pJNIEnv->localRefSlot << LocalRefListEntry.LOCAL_REF_SHIFT) + i); + } + // TODO consider allocating a new slot (if we do this, the code in + // PushLocalFrame/PopLocalFrame (and Leave) must be fixed to take this into account) + JVM.CriticalFailure("Too many JNI local references", null); + return IntPtr.Zero; + } + + public object UnwrapLocalRef(IntPtr p) + { + int i = p.ToInt32(); + return localRefs[i >> LocalRefListEntry.LOCAL_REF_SHIFT].UnwrapLocalRef(i & LocalRefListEntry.LOCAL_REF_MASK); + } } diff --git a/runtime/MemberWrapper.cs b/runtime/MemberWrapper.cs index 5959a768..6356b220 100644 --- a/runtime/MemberWrapper.cs +++ b/runtime/MemberWrapper.cs @@ -1135,6 +1135,7 @@ class FieldWrapper : MemberWrapper // HACK if linking fails, we unlink to make sure // that the next link attempt will fail again fieldType = null; + throw; } } } diff --git a/runtime/TypeWrapper.cs b/runtime/TypeWrapper.cs index 696cbed2..1de8d192 100644 --- a/runtime/TypeWrapper.cs +++ b/runtime/TypeWrapper.cs @@ -102,7 +102,7 @@ class EmitHelper // have a now, a newer version that does have a will not have it's called by us. // A possible solution would be to use RuntimeHelpers.RunClassConstructor when "type" is a Java type and // lives in another assembly as the caller (which we don't know at the moment). - FieldInfo field = type.GetField("__"); + FieldInfo field = type.GetField("__", BindingFlags.Static | BindingFlags.NonPublic); if(field != null) { ilgen.Emit(OpCodes.Ldsfld, field); @@ -676,10 +676,6 @@ abstract class TypeWrapper protected abstract FieldWrapper GetFieldImpl(string fieldName, TypeWrapper fieldType); -// internal FieldWrapper GetFieldWrapper(string fieldName, string fieldSig) -// { -// } - internal virtual FieldWrapper GetFieldWrapper(string fieldName, TypeWrapper fieldType) { lock(fields.SyncRoot) @@ -1385,9 +1381,7 @@ abstract class TypeWrapper { ilgen.Emit(OpCodes.Isinst, TypeAsTBD); ilgen.Emit(OpCodes.Ldnull); - ilgen.Emit(OpCodes.Ceq); - ilgen.Emit(OpCodes.Ldc_I4_0); - ilgen.Emit(OpCodes.Ceq); + ilgen.Emit(OpCodes.Cgt_Un); } } @@ -2013,6 +2007,7 @@ sealed class DynamicTypeWrapper : TypeWrapper private readonly TypeWrapper outerClassWrapper; private readonly TypeBuilder typeBuilderGhostInterface; private Hashtable memberclashtable; + private Hashtable classCache = new Hashtable(); internal JavaTypeImpl(ClassFile f, DynamicTypeWrapper wrapper) { @@ -2376,7 +2371,7 @@ sealed class DynamicTypeWrapper : TypeWrapper // make sure all classes are loaded, before we start finishing the type. During finishing, we // may not run any Java code, because that might result in a request to finish the type that we // are in the process of finishing, and this would be a problem. - classFile.Link(wrapper); + classFile.Link(wrapper, classCache); // for(int i = 0; i < fields.Length; i++) // { // fields[i].Link(); @@ -2408,13 +2403,13 @@ sealed class DynamicTypeWrapper : TypeWrapper { if(innerclasses[i].innerClass != 0 && innerclasses[i].outerClass != 0) { - if(classFile.GetConstantPoolClassType(innerclasses[i].outerClass, wrapper.GetClassLoader()) == wrapper) + if(classFile.GetConstantPoolClassType(innerclasses[i].outerClass) == wrapper) { - wrappers.Add(classFile.GetConstantPoolClassType(innerclasses[i].innerClass, wrapper.GetClassLoader())); + wrappers.Add(classFile.GetConstantPoolClassType(innerclasses[i].innerClass)); } - if(classFile.GetConstantPoolClassType(innerclasses[i].innerClass, wrapper.GetClassLoader()) == wrapper) + if(classFile.GetConstantPoolClassType(innerclasses[i].innerClass) == wrapper) { - declaringTypeWrapper = classFile.GetConstantPoolClassType(innerclasses[i].outerClass, wrapper.GetClassLoader()); + declaringTypeWrapper = classFile.GetConstantPoolClassType(innerclasses[i].outerClass); AttributeHelper.SetInnerClass(typeBuilder, classFile.GetConstantPoolClass(innerclasses[i].innerClass), classFile.GetConstantPoolClass(innerclasses[i].outerClass), @@ -2532,9 +2527,7 @@ sealed class DynamicTypeWrapper : TypeWrapper ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Isinst, wrapper.TypeAsBaseType); ilgen.Emit(OpCodes.Ldnull); - ilgen.Emit(OpCodes.Ceq); - ilgen.Emit(OpCodes.Ldc_I4_0); - ilgen.Emit(OpCodes.Ceq); + ilgen.Emit(OpCodes.Cgt_Un); ilgen.MarkLabel(end); ilgen.Emit(OpCodes.Ret); // Implement the "IsInstanceArray" method @@ -2673,7 +2666,7 @@ sealed class DynamicTypeWrapper : TypeWrapper if(mb is ConstructorBuilder) { ILGenerator ilGenerator = ((ConstructorBuilder)mb).GetILGenerator(); - Tracer.EmitMethodTrace(ilGenerator, m.ClassFile.Name + "." + m.Name + m.Signature); + Tracer.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature); if(basehasclinit && m.IsClassInitializer && !classFile.IsInterface) { hasclinit = true; @@ -2681,7 +2674,7 @@ sealed class DynamicTypeWrapper : TypeWrapper EmitConstantValueInitialization(ilGenerator); EmitHelper.RunClassConstructor(ilGenerator, Type.BaseType); } - Compiler.Compile(wrapper, m, ilGenerator); + Compiler.Compile(wrapper, methods[i], classFile, m, ilGenerator); } else { @@ -2689,11 +2682,11 @@ sealed class DynamicTypeWrapper : TypeWrapper { // NOTE in the JVM it is apparently legal for a non-abstract class to have abstract methods, but // the CLR doens't allow this, so we have to emit a method that throws an AbstractMethodError - if(!m.ClassFile.IsAbstract && !m.ClassFile.IsInterface) + if(!classFile.IsAbstract && !classFile.IsInterface) { ILGenerator ilGenerator = ((MethodBuilder)mb).GetILGenerator(); - Tracer.EmitMethodTrace(ilGenerator, m.ClassFile.Name + "." + m.Name + m.Signature); - EmitHelper.Throw(ilGenerator, "java.lang.AbstractMethodError", m.ClassFile.Name + "." + m.Name + m.Signature); + Tracer.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature); + EmitHelper.Throw(ilGenerator, "java.lang.AbstractMethodError", classFile.Name + "." + m.Name + m.Signature); } } else if(m.IsNative) @@ -2702,7 +2695,7 @@ sealed class DynamicTypeWrapper : TypeWrapper try { ILGenerator ilGenerator = ((MethodBuilder)mb).GetILGenerator(); - Tracer.EmitMethodTrace(ilGenerator, m.ClassFile.Name + "." + m.Name + m.Signature); + Tracer.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature); // do we have a native implementation in map.xml? if(nativeMethods != null) { @@ -2716,7 +2709,7 @@ sealed class DynamicTypeWrapper : TypeWrapper // see if there exists a NativeCode class for this type Type nativeCodeType = Type.GetType("NativeCode." + classFile.Name.Replace('$', '+')); MethodInfo nativeMethod = null; - TypeWrapper[] args = m.GetArgTypes(wrapper.GetClassLoader()); + TypeWrapper[] args = methods[i].GetParameters(); if(nativeCodeType != null) { TypeWrapper[] nargs = args; @@ -2775,11 +2768,11 @@ sealed class DynamicTypeWrapper : TypeWrapper { if(ClassLoaderWrapper.IsSaveDebugImage) { - JniProxyBuilder.Generate(ilGenerator, wrapper, typeBuilder, m, args); + JniProxyBuilder.Generate(ilGenerator, wrapper, methods[i], typeBuilder, classFile, m, args); } else { - JniBuilder.Generate(ilGenerator, wrapper, typeBuilder, m, args); + JniBuilder.Generate(ilGenerator, wrapper, methods[i], typeBuilder, classFile, m, args); } } } @@ -2792,8 +2785,8 @@ sealed class DynamicTypeWrapper : TypeWrapper else { ILGenerator ilGenerator = ((MethodBuilder)mb).GetILGenerator(); - Tracer.EmitMethodTrace(ilGenerator, m.ClassFile.Name + "." + m.Name + m.Signature); - Compiler.Compile(wrapper, m, ilGenerator); + Tracer.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature); + Compiler.Compile(wrapper, methods[i], classFile, m, ilGenerator); } } } @@ -2935,7 +2928,7 @@ sealed class DynamicTypeWrapper : TypeWrapper return n; } - internal static void Generate(ILGenerator ilGenerator, TypeWrapper wrapper, TypeBuilder typeBuilder, ClassFile.Method m, TypeWrapper[] args) + internal static void Generate(ILGenerator ilGenerator, TypeWrapper wrapper, MethodWrapper mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, TypeWrapper[] args) { if(mod == null) { @@ -2952,8 +2945,8 @@ sealed class DynamicTypeWrapper : TypeWrapper { argTypes[i] = args[i].TypeAsParameterType; } - MethodBuilder mb = tb.DefineMethod("method", MethodAttributes.Public | MethodAttributes.Static, m.GetRetType(wrapper.GetClassLoader()).TypeAsParameterType, argTypes); - JniBuilder.Generate(mb.GetILGenerator(), wrapper, tb, m, args); + MethodBuilder mb = tb.DefineMethod("method", MethodAttributes.Public | MethodAttributes.Static, mw.ReturnType.TypeAsParameterType, argTypes); + JniBuilder.Generate(mb.GetILGenerator(), wrapper, mw, tb, classFile, m, args); for(int i = 0; i < argTypes.Length; i++) { ilGenerator.Emit(OpCodes.Ldarg, (short)i); @@ -2971,8 +2964,8 @@ sealed class DynamicTypeWrapper : TypeWrapper private class JniBuilder { - private static readonly Type localRefStructType = JVM.JniProvider.GetLocalRefStructType(); - private static readonly MethodInfo jniFuncPtrMethod = JVM.JniProvider.GetJniFuncPtrMethod(); + private static readonly Type localRefStructType = typeof(JniFrame); + private static readonly MethodInfo jniFuncPtrMethod = localRefStructType.GetMethod("GetFuncPtr"); private static readonly MethodInfo enterLocalRefStruct = localRefStructType.GetMethod("Enter"); private static readonly MethodInfo leaveLocalRefStruct = localRefStructType.GetMethod("Leave"); private static readonly MethodInfo makeLocalRef = localRefStructType.GetMethod("MakeLocalRef"); @@ -2981,27 +2974,29 @@ sealed class DynamicTypeWrapper : TypeWrapper private static readonly MethodInfo getClassFromType = typeof(NativeCode.java.lang.VMClass).GetMethod("getClassFromType"); private static readonly MethodInfo writeLine = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }, null); - internal static void Generate(ILGenerator ilGenerator, TypeWrapper wrapper, TypeBuilder typeBuilder, ClassFile.Method m, TypeWrapper[] args) + internal static void Generate(ILGenerator ilGenerator, TypeWrapper wrapper, MethodWrapper mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, TypeWrapper[] args) { - FieldBuilder methodPtr = typeBuilder.DefineField(m.Name + "$Ptr", typeof(IntPtr), FieldAttributes.Static | FieldAttributes.PrivateScope); + FieldBuilder methodPtr = typeBuilder.DefineField("jniptr/" + m.Name + m.Signature, typeof(IntPtr), FieldAttributes.Static | FieldAttributes.PrivateScope); LocalBuilder localRefStruct = ilGenerator.DeclareLocal(localRefStructType); ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); ilGenerator.Emit(OpCodes.Initobj, localRefStructType); ilGenerator.Emit(OpCodes.Ldsfld, methodPtr); Label oklabel = ilGenerator.DefineLabel(); ilGenerator.Emit(OpCodes.Brtrue, oklabel); + ilGenerator.Emit(OpCodes.Ldtoken, (MethodInfo)mw.GetMethod()); + ilGenerator.Emit(OpCodes.Ldstr, classFile.Name.Replace('.', '/')); ilGenerator.Emit(OpCodes.Ldstr, m.Name); ilGenerator.Emit(OpCodes.Ldstr, m.Signature.Replace('.', '/')); - ilGenerator.Emit(OpCodes.Ldstr, m.ClassFile.Name.Replace('.', '/')); ilGenerator.Emit(OpCodes.Call, jniFuncPtrMethod); ilGenerator.Emit(OpCodes.Stsfld, methodPtr); ilGenerator.MarkLabel(oklabel); ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); + ilGenerator.Emit(OpCodes.Ldtoken, (MethodInfo)mw.GetMethod()); ilGenerator.Emit(OpCodes.Call, enterLocalRefStruct); LocalBuilder jnienv = ilGenerator.DeclareLocal(typeof(IntPtr)); ilGenerator.Emit(OpCodes.Stloc, jnienv); Label tryBlock = ilGenerator.BeginExceptionBlock(); - TypeWrapper retTypeWrapper = m.GetRetType(wrapper.GetClassLoader()); + TypeWrapper retTypeWrapper = mw.ReturnType; if(!retTypeWrapper.IsPrimitive) { // this one is for use after we return from "calli" @@ -3188,7 +3183,8 @@ sealed class DynamicTypeWrapper : TypeWrapper FieldBuilder field; ClassFile.Field fld = classFile.Fields[i]; string fieldName = fld.Name; - TypeWrapper typeWrapper = fld.GetFieldType(wrapper.GetClassLoader()); + // TODO we're not allowed to load types here (potentially), it needs to be done in the Link step + TypeWrapper typeWrapper = ClassFile.FieldTypeWrapperFromSig(wrapper.GetClassLoader(), classCache, fld.Signature); Type type = typeWrapper.TypeAsFieldType; bool setNameSig = typeWrapper.IsUnloadable || typeWrapper.IsGhostArray; if(setNameSig) @@ -3236,7 +3232,7 @@ sealed class DynamicTypeWrapper : TypeWrapper attribs |= FieldAttributes.Literal; field = typeBuilder.DefineField(fieldName, type, attribs); field.SetConstant(constantValue); - fields[i] = new FieldWrapper.ConstantFieldWrapper(wrapper, fld.GetFieldType(wrapper.GetClassLoader()), fld.Name, fld.Signature, fld.Modifiers, field, constantValue); + fields[i] = new FieldWrapper.ConstantFieldWrapper(wrapper, typeWrapper, fld.Name, fld.Signature, fld.Modifiers, field, constantValue); } else { @@ -3244,7 +3240,8 @@ sealed class DynamicTypeWrapper : TypeWrapper if(isWrappedFinal) { // NOTE public/protected blank final fields get converted into a read-only property with a private field - // backing store we used to make the field privatescope, but that really serves no purpose (and it hinders + // backing store + // we used to make the field privatescope, but that really serves no purpose (and it hinders // serialization, which uses .NET reflection to get at the field) attribs &= ~FieldAttributes.FieldAccessMask; attribs |= FieldAttributes.Private; @@ -3302,11 +3299,11 @@ sealed class DynamicTypeWrapper : TypeWrapper { emitSet += CodeEmitter.Create(OpCodes.Stfld, field); } - fields[i] = FieldWrapper.Create1(wrapper, fld.GetFieldType(wrapper.GetClassLoader()), fld.Name, fld.Signature, fld.Modifiers, field, emitGet, emitSet); + fields[i] = FieldWrapper.Create1(wrapper, typeWrapper, fld.Name, fld.Signature, fld.Modifiers, field, emitGet, emitSet); } else { - fields[i] = FieldWrapper.Create3(wrapper, fld.GetFieldType(wrapper.GetClassLoader()), field, fld.Signature, fld.Modifiers); + fields[i] = FieldWrapper.Create3(wrapper, typeWrapper, field, fld.Signature, fld.Modifiers); } } // if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store @@ -3337,7 +3334,7 @@ sealed class DynamicTypeWrapper : TypeWrapper { // We create a field that the derived classes can access in their .cctor to trigger our .cctor // (previously we used RuntimeHelpers.RunClassConstructor, but that is slow and requires additional privileges) - FieldBuilder field = typeBuilder.DefineField("__", typeof(int), FieldAttributes.SpecialName | FieldAttributes.Public | FieldAttributes.Static); + FieldBuilder field = typeBuilder.DefineField("__", typeof(int), FieldAttributes.SpecialName | FieldAttributes.Family | FieldAttributes.Static); AttributeHelper.HideFromJava(field); } if(typeBuilder.IsInterface) @@ -3500,7 +3497,7 @@ sealed class DynamicTypeWrapper : TypeWrapper // only if the classfile is abstract, we make the CLR method abstract, otherwise, // we have to generate a method that throws an AbstractMethodError (because the JVM // allows abstract methods in non-abstract classes) - if(m.ClassFile.IsAbstract || m.ClassFile.IsInterface) + if(classFile.IsAbstract || classFile.IsInterface) { attribs |= MethodAttributes.Abstract; } @@ -3685,40 +3682,37 @@ sealed class DynamicTypeWrapper : TypeWrapper private static ParameterBuilder[] AddParameterNames(MethodBase mb, ClassFile.Method m) { - if(m.CodeAttribute != null) + ClassFile.Method.LocalVariableTableEntry[] localVars = m.LocalVariableTableAttribute; + if(localVars != null) { - ClassFile.Method.LocalVariableTableEntry[] localVars = m.CodeAttribute.LocalVariableTableAttribute; - if(localVars != null) + int bias = 1; + if(m.IsStatic) { - int bias = 1; - if(m.IsStatic) + bias = 0; + } + ParameterBuilder[] parameterBuilders = new ParameterBuilder[m.ArgMap.Length - bias]; + for(int i = bias; i < m.ArgMap.Length; i++) + { + if(m.ArgMap[i] != -1) { - bias = 0; - } - ParameterBuilder[] parameterBuilders = new ParameterBuilder[m.CodeAttribute.ArgMap.Length - bias]; - for(int i = bias; i < m.CodeAttribute.ArgMap.Length; i++) - { - if(m.CodeAttribute.ArgMap[i] != -1) + for(int j = 0; j < localVars.Length; j++) { - for(int j = 0; j < localVars.Length; j++) + if(localVars[j].index == i && parameterBuilders[i - bias] == null) { - if(localVars[j].index == i && parameterBuilders[i - bias] == null) + if(mb is MethodBuilder) { - if(mb is MethodBuilder) - { - parameterBuilders[i - bias] = ((MethodBuilder)mb).DefineParameter(m.CodeAttribute.ArgMap[i] + 1 - bias, ParameterAttributes.None, localVars[j].name); - } - else if(mb is ConstructorBuilder) - { - parameterBuilders[i - bias] = ((ConstructorBuilder)mb).DefineParameter(m.CodeAttribute.ArgMap[i], ParameterAttributes.None, localVars[j].name); - } - break; + parameterBuilders[i - bias] = ((MethodBuilder)mb).DefineParameter(m.ArgMap[i] + 1 - bias, ParameterAttributes.None, localVars[j].name); } + else if(mb is ConstructorBuilder) + { + parameterBuilders[i - bias] = ((ConstructorBuilder)mb).DefineParameter(m.ArgMap[i], ParameterAttributes.None, localVars[j].name); + } + break; } } } - return parameterBuilders; } + return parameterBuilders; } return null; } diff --git a/runtime/classpath.cs b/runtime/classpath.cs index 389b2464..500f23fe 100644 --- a/runtime/classpath.cs +++ b/runtime/classpath.cs @@ -409,8 +409,7 @@ namespace NativeCode.java public static int nativeLoad(string filename) { - // TODO native libraries somehow need to be scoped by class loader - return JVM.JniProvider.LoadNativeLibrary(filename); + return JniHelper.LoadLibrary(filename); } } @@ -532,7 +531,7 @@ namespace NativeCode.java try { // TODO I doubt that this is correct - return double.Parse(s); + return double.Parse(s, System.Globalization.CultureInfo.InvariantCulture); } catch(FormatException x) { @@ -788,21 +787,11 @@ namespace NativeCode.java } } - public static bool isWordsBigEndian() - { - return !BitConverter.IsLittleEndian; - } - - public static long currentTimeMillis() - { - const long january_1st_1970 = 62135596800000L; - return DateTime.UtcNow.Ticks / 10000L - january_1st_1970; - } - public static void setErr(object printStream) { TypeWrapper tw = ClassLoaderWrapper.LoadClassCritical("java.lang.System"); FieldWrapper fw = tw.GetFieldWrapper("err", ClassLoaderWrapper.LoadClassCritical("java.io.PrintStream")); + fw.SetValue(null, printStream); } public static void setIn(object inputStream) @@ -818,11 +807,6 @@ namespace NativeCode.java FieldWrapper fw = tw.GetFieldWrapper("out", ClassLoaderWrapper.LoadClassCritical("java.io.PrintStream")); fw.SetValue(null, printStream); } - - public static int identityHashCode(object o) - { - return RuntimeHelpers.GetHashCode(o); - } } public class VMClassLoader @@ -914,7 +898,7 @@ namespace NativeCode.java { try { - ClassFile classFile = new ClassFile(data, offset, length, name); + ClassFile classFile = new ClassFile(data, offset, length, name, false); if(name != null && classFile.Name != name) { throw new NoClassDefFoundError(name + " (wrong name: " + classFile.Name + ")"); @@ -1511,7 +1495,28 @@ namespace NativeCode.java int hours = timeSpan.Hours; int mins = timeSpan.Minutes; - return "GMT" + hours + ":" + mins; + if(mins != 0) + { + if(hours < 0) + { + return "GMT+" + ((-hours) * 60 + mins); + } + else + { + return "GMT-" + (hours * 60 + mins); + } + } + else + { + if(hours < 0) + { + return "GMT+" + (-hours); + } + else + { + return "GMT-" + (hours + mins); + } + } } } } diff --git a/runtime/compiler.cs b/runtime/compiler.cs index 103fc196..7ce2565f 100644 --- a/runtime/compiler.cs +++ b/runtime/compiler.cs @@ -56,7 +56,9 @@ class Compiler private static TypeWrapper java_lang_Throwable; private static TypeWrapper java_lang_ThreadDeath; private TypeWrapper clazz; - private ClassFile.Method.Code m; + private MethodWrapper mw; + private ClassFile classFile; + private ClassFile.Method m; private ILGenerator ilGenerator; private ClassLoaderWrapper classLoader; private MethodAnalyzer ma; @@ -122,9 +124,11 @@ class Compiler } } - private Compiler(TypeWrapper clazz, ClassFile.Method.Code m, ILGenerator ilGenerator, ClassLoaderWrapper classLoader, ISymbolDocumentWriter symboldocument) + private Compiler(TypeWrapper clazz, MethodWrapper mw, ClassFile classFile, ClassFile.Method m, ILGenerator ilGenerator, ClassLoaderWrapper classLoader, ISymbolDocumentWriter symboldocument) { this.clazz = clazz; + this.mw = mw; + this.classFile = classFile; this.m = m; this.ilGenerator = ilGenerator; this.classLoader = classLoader; @@ -133,14 +137,14 @@ class Compiler Profiler.Enter("MethodAnalyzer"); try { - ma = new MethodAnalyzer(clazz, m, classLoader); + ma = new MethodAnalyzer(clazz, mw, classFile, m, classLoader); } finally { Profiler.Leave("MethodAnalyzer"); } - TypeWrapper[] args = m.Method.GetArgTypes(classLoader); + TypeWrapper[] args = mw.GetParameters(); LocalVar[] locals = ma.GetAllLocalVars(); foreach(LocalVar v in locals) { @@ -148,7 +152,7 @@ class Compiler { int arg = m.ArgMap[v.local]; TypeWrapper tw; - if(m.Method.IsStatic) + if(m.IsStatic) { tw = args[arg]; } @@ -287,9 +291,9 @@ class Compiler { case NormalizedByteCode.__lookupswitch: // start at -1 to have an opportunity to handle the default offset - for(int k = -1; k < m.Instructions[j].Values.Length; k++) + for(int k = -1; k < m.Instructions[j].SwitchEntryCount; k++) { - int targetPC = m.Instructions[j].PC + (k == -1 ? m.Instructions[j].DefaultOffset : m.Instructions[j].TargetOffsets[k]); + int targetPC = m.Instructions[j].PC + (k == -1 ? m.Instructions[j].DefaultOffset : m.Instructions[j].GetSwitchTargetOffset(k)); if(ei.start_pc < targetPC && targetPC < ei.end_pc) { ExceptionTableEntry en = new ExceptionTableEntry(); @@ -378,7 +382,7 @@ class Compiler // we run finally blocks when a thread is killed. if(ei.catch_type != 0) { - TypeWrapper exceptionType = m.Method.ClassFile.GetConstantPoolClassType(ei.catch_type, classLoader); + TypeWrapper exceptionType = classFile.GetConstantPoolClassType(ei.catch_type); if(!exceptionType.IsUnloadable && !java_lang_ThreadDeath.IsAssignableTo(exceptionType)) { int start = FindPcIndex(ei.start_pc); @@ -457,9 +461,9 @@ class Compiler this.type = type; } - internal void Emit(ILGenerator ilgen, ClassFile.Method m) + internal void Emit(ILGenerator ilgen, ClassFile classFile, ClassFile.Method m) { - Tracer.Warning(Tracer.Compiler, "{0}: {1}\n\tat {2}.{3}{4}", type.Name, Message, m.ClassFile.Name, m.Name, m.Signature); + Tracer.Warning(Tracer.Compiler, "{0}: {1}\n\tat {2}.{3}{4}", type.Name, Message, classFile.Name, m.Name, m.Signature); ilgen.Emit(OpCodes.Ldstr, Message); MethodWrapper method = type.GetMethodWrapper(new MethodDescriptor("", "(Ljava.lang.String;)V"), false); method.Link(); @@ -661,13 +665,13 @@ class Compiler } } - internal static void Compile(TypeWrapper clazz, ClassFile.Method m, ILGenerator ilGenerator) + internal static void Compile(TypeWrapper clazz, MethodWrapper mw, ClassFile classFile, ClassFile.Method m, ILGenerator ilGenerator) { ClassLoaderWrapper classLoader = clazz.GetClassLoader(); ISymbolDocumentWriter symboldocument = null; if(JVM.Debug) { - string sourcefile = m.ClassFile.SourceFileAttribute; + string sourcefile = classFile.SourceFileAttribute; if(sourcefile != null) { if(JVM.SourcePath != null) @@ -677,7 +681,7 @@ class Compiler symboldocument = classLoader.ModuleBuilder.DefineDocument(sourcefile, SymLanguageType.Java, Guid.Empty, SymDocumentType.Text); // the very first instruction in the method must have an associated line number, to be able // to step into the method in Visual Studio .NET - ClassFile.Method.LineNumberTableEntry[] table = m.CodeAttribute.LineNumberTableAttribute; + ClassFile.Method.LineNumberTableEntry[] table = m.LineNumberTableAttribute; if(table != null) { int firstPC = int.MaxValue; @@ -697,7 +701,7 @@ class Compiler } } } - TypeWrapper[] args= m.GetArgTypes(classLoader); + TypeWrapper[] args = mw.GetParameters(); for(int i = 0; i < args.Length; i++) { if(args[i].IsUnloadable) @@ -716,7 +720,7 @@ class Compiler Profiler.Enter("new Compiler"); try { - c = new Compiler(clazz, m.CodeAttribute, ilGenerator, classLoader, symboldocument); + c = new Compiler(clazz, mw, classFile, m, ilGenerator, classLoader, symboldocument); } finally { @@ -986,7 +990,7 @@ class Compiler private void CheckLoaderConstraints(ClassFile.ConstantPoolItemFieldref cpi, FieldWrapper fw) { - if(cpi.GetFieldType(classLoader) != fw.FieldTypeWrapper && !fw.FieldTypeWrapper.IsUnloadable) + if(cpi.GetFieldType() != fw.FieldTypeWrapper && !fw.FieldTypeWrapper.IsUnloadable) { throw new LinkageError("Loader constraints violated: " + fw.Name); } @@ -994,11 +998,11 @@ class Compiler private void CheckLoaderConstraints(ClassFile.ConstantPoolItemMI cpi, MethodWrapper mw) { - if(cpi.GetRetType(classLoader) != mw.ReturnType && !mw.ReturnType.IsUnloadable) + if(cpi.GetRetType() != mw.ReturnType && !mw.ReturnType.IsUnloadable) { throw new LinkageError("Loader constraints violated: " + mw.Name + mw.Signature); } - TypeWrapper[] here = cpi.GetArgTypes(classLoader); + TypeWrapper[] here = cpi.GetArgTypes(); TypeWrapper[] there = mw.GetParameters(); for(int i = 0; i < here.Length; i++) { @@ -1091,7 +1095,7 @@ class Compiler } else { - exceptionTypeWrapper = m.Method.ClassFile.GetConstantPoolClassType(exc.catch_type, classLoader); + exceptionTypeWrapper = classFile.GetConstantPoolClassType(exc.catch_type); } Type excType = exceptionTypeWrapper.TypeAsExceptionType; bool mapSafe = !exceptionTypeWrapper.IsUnloadable && !exceptionTypeWrapper.IsMapUnsafeException; @@ -1299,28 +1303,27 @@ class Compiler break; case NormalizedByteCode.__ldc: { - ClassFile cf = instr.MethodCode.Method.ClassFile; int constant = instr.Arg1; - switch(cf.GetConstantPoolConstantType(constant)) + switch(classFile.GetConstantPoolConstantType(constant)) { case ClassFile.ConstantType.Double: - ilGenerator.Emit(OpCodes.Ldc_R8, cf.GetConstantPoolConstantDouble(constant)); + ilGenerator.Emit(OpCodes.Ldc_R8, classFile.GetConstantPoolConstantDouble(constant)); break; case ClassFile.ConstantType.Float: - ilGenerator.Emit(OpCodes.Ldc_R4, cf.GetConstantPoolConstantFloat(constant)); + ilGenerator.Emit(OpCodes.Ldc_R4, classFile.GetConstantPoolConstantFloat(constant)); break; case ClassFile.ConstantType.Integer: - EmitLdc_I4(cf.GetConstantPoolConstantInteger(constant)); + EmitLdc_I4(classFile.GetConstantPoolConstantInteger(constant)); break; case ClassFile.ConstantType.Long: - ilGenerator.Emit(OpCodes.Ldc_I8, cf.GetConstantPoolConstantLong(constant)); + ilGenerator.Emit(OpCodes.Ldc_I8, classFile.GetConstantPoolConstantLong(constant)); break; case ClassFile.ConstantType.String: - ilGenerator.Emit(OpCodes.Ldstr, cf.GetConstantPoolConstantString(constant)); + ilGenerator.Emit(OpCodes.Ldstr, classFile.GetConstantPoolConstantString(constant)); break; case ClassFile.ConstantType.Class: { - TypeWrapper tw = cf.GetConstantPoolClassType(constant, classLoader); + TypeWrapper tw = classFile.GetConstantPoolClassType(constant); if(tw.IsUnloadable) { Profiler.Count("EmitDynamicClassLiteral"); @@ -1344,13 +1347,13 @@ class Compiler } case NormalizedByteCode.__invokestatic: { - ClassFile.ConstantPoolItemMI cpi = m.Method.ClassFile.GetMethodref(instr.Arg1); + ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(instr.Arg1); // HACK special case for calls to System.arraycopy, if the array arguments on the stack // are of a known array type, we can redirect to an optimized version of arraycopy. if(cpi.Class == "java.lang.System" && cpi.Name == "arraycopy" && cpi.Signature == "(Ljava.lang.Object;ILjava.lang.Object;II)V" && - cpi.GetClassType(classLoader).GetClassLoader() == ClassLoaderWrapper.GetBootstrapClassLoader()) + cpi.GetClassType().GetClassLoader() == ClassLoaderWrapper.GetBootstrapClassLoader()) { TypeWrapper t1 = ma.GetRawStackTypeWrapper(i, 2); TypeWrapper t2 = ma.GetRawStackTypeWrapper(i, 4); @@ -1384,7 +1387,7 @@ class Compiler MethodWrapper method = GetMethodCallEmitter(cpi, null, NormalizedByteCode.__invokestatic); // if the stack values don't match the argument types (for interface argument types) // we must emit code to cast the stack value to the interface type - CastInterfaceArgs(method, cpi.GetArgTypes(classLoader), i, false, false); + CastInterfaceArgs(method, cpi.GetArgTypes(), i, false, false); method.EmitCall(ilGenerator); break; } @@ -1392,10 +1395,10 @@ class Compiler case NormalizedByteCode.__invokeinterface: case NormalizedByteCode.__invokespecial: { - ClassFile.ConstantPoolItemMI cpi = m.Method.ClassFile.GetMethodref(instr.Arg1); - int argcount = cpi.GetArgTypes(classLoader).Length; + ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(instr.Arg1); + int argcount = cpi.GetArgTypes().Length; TypeWrapper type = ma.GetRawStackTypeWrapper(i, argcount); - TypeWrapper thisType = SigTypeToClassName(type, cpi.GetClassType(classLoader)); + TypeWrapper thisType = SigTypeToClassName(type, cpi.GetClassType()); MethodWrapper method = GetMethodCallEmitter(cpi, thisType, instr.NormalizedOpCode); @@ -1403,18 +1406,18 @@ class Compiler // we must emit code to cast the stack value to the interface type if(instr.NormalizedOpCode == NormalizedByteCode.__invokespecial && cpi.Name == "" && VerifierTypeWrapper.IsNew(type)) { - TypeWrapper[] args = cpi.GetArgTypes(classLoader); + TypeWrapper[] args = cpi.GetArgTypes(); CastInterfaceArgs(method, args, i, false, false); } else { // the this reference is included in the argument list because it may also need to be cast - TypeWrapper[] methodArgs = cpi.GetArgTypes(classLoader); + TypeWrapper[] methodArgs = cpi.GetArgTypes(); TypeWrapper[] args = new TypeWrapper[methodArgs.Length + 1]; methodArgs.CopyTo(args, 1); if(instr.NormalizedOpCode == NormalizedByteCode.__invokeinterface) { - args[0] = cpi.GetClassType(classLoader); + args[0] = cpi.GetClassType(); } else { @@ -1586,7 +1589,7 @@ class Compiler LocalBuilder local = null; if(instr.NormalizedOpCode != NormalizedByteCode.__return) { - TypeWrapper retTypeWrapper = m.Method.GetRetType(classLoader); + TypeWrapper retTypeWrapper = mw.ReturnType; retTypeWrapper.EmitConvStackToParameterType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0)); if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable) { @@ -1615,7 +1618,7 @@ class Compiler } else { - TypeWrapper retTypeWrapper = m.Method.GetRetType(classLoader); + TypeWrapper retTypeWrapper = mw.ReturnType; retTypeWrapper.EmitConvStackToParameterType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0)); if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable) { @@ -1706,7 +1709,7 @@ class Compiler break; case NormalizedByteCode.__new: { - TypeWrapper wrapper = instr.MethodCode.Method.ClassFile.GetConstantPoolClassType(instr.Arg1, classLoader); + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); if(wrapper.IsUnloadable) { Profiler.Count("EmitDynamicNewCheckOnly"); @@ -1742,7 +1745,7 @@ class Compiler ilGenerator.Emit(OpCodes.Ldloc, localInt); ilGenerator.Emit(OpCodes.Stelem_I4); } - TypeWrapper wrapper = instr.MethodCode.Method.ClassFile.GetConstantPoolClassType(instr.Arg1, classLoader); + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); if(wrapper.IsUnloadable) { Profiler.Count("EmitDynamicMultianewarray"); @@ -1767,7 +1770,7 @@ class Compiler } case NormalizedByteCode.__anewarray: { - TypeWrapper wrapper = instr.MethodCode.Method.ClassFile.GetConstantPoolClassType(instr.Arg1, classLoader); + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); if(wrapper.IsUnloadable) { Profiler.Count("EmitDynamicNewarray"); @@ -1829,7 +1832,7 @@ class Compiler break; case NormalizedByteCode.__checkcast: { - TypeWrapper wrapper = instr.MethodCode.Method.ClassFile.GetConstantPoolClassType(instr.Arg1, classLoader); + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); if(!wrapper.IsUnloadable && !wrapper.IsAccessibleFrom(clazz)) { throw new IllegalAccessError("Try to access class " + wrapper.Name + " from class " + clazz.Name); @@ -1839,7 +1842,7 @@ class Compiler } case NormalizedByteCode.__instanceof: { - TypeWrapper wrapper = instr.MethodCode.Method.ClassFile.GetConstantPoolClassType(instr.Arg1, classLoader); + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); if(!wrapper.IsUnloadable && !wrapper.IsAccessibleFrom(clazz)) { throw new IllegalAccessError("Try to access class " + wrapper.Name + " from class " + clazz.Name); @@ -2476,14 +2479,14 @@ class Compiler break; case NormalizedByteCode.__lookupswitch: // TODO use OpCodes.Switch - for(int j = 0; j < instr.Values.Length; j++) + for(int j = 0; j < instr.SwitchEntryCount; j++) { ilGenerator.Emit(OpCodes.Dup); - EmitLdc_I4(instr.Values[j]); + EmitLdc_I4(instr.GetSwitchValue(j)); Label label = ilGenerator.DefineLabel(); ilGenerator.Emit(OpCodes.Bne_Un_S, label); ilGenerator.Emit(OpCodes.Pop); - ilGenerator.Emit(OpCodes.Br, block.GetLabel(instr.PC + instr.TargetOffsets[j])); + ilGenerator.Emit(OpCodes.Br, block.GetLabel(instr.PC + instr.GetSwitchTargetOffset(j))); ilGenerator.MarkLabel(label); } ilGenerator.Emit(OpCodes.Pop); @@ -2598,7 +2601,7 @@ class Compiler } catch(EmitException x) { - x.Emit(ilGenerator, m.Method); + x.Emit(ilGenerator, classFile, m); // mark the next instruction as not forward reachable, // this will cause the stack to be loaded from locals // (which is needed for the code to be verifiable) @@ -2781,12 +2784,12 @@ class Compiler private void GetPutField(Instruction instr, int i) { NormalizedByteCode bytecode = instr.NormalizedOpCode; - ClassFile.ConstantPoolItemFieldref cpi = m.Method.ClassFile.GetFieldref(instr.Arg1); + ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); bool write = (bytecode == NormalizedByteCode.__putfield || bytecode == NormalizedByteCode.__putstatic); - TypeWrapper wrapper = cpi.GetClassType(classLoader); + TypeWrapper wrapper = cpi.GetClassType(); if(wrapper.IsUnloadable) { - TypeWrapper fieldTypeWrapper = cpi.GetFieldType(classLoader); + TypeWrapper fieldTypeWrapper = cpi.GetFieldType(); if(write && !fieldTypeWrapper.IsUnloadable && fieldTypeWrapper.IsPrimitive) { ilGenerator.Emit(OpCodes.Box, fieldTypeWrapper.TypeAsTBD); @@ -2827,11 +2830,11 @@ class Compiler TypeWrapper thisType = null; if(bytecode == NormalizedByteCode.__getfield) { - thisType = SigTypeToClassName(ma.GetRawStackTypeWrapper(i, 0), cpi.GetClassType(classLoader)); + thisType = SigTypeToClassName(ma.GetRawStackTypeWrapper(i, 0), cpi.GetClassType()); } else if(bytecode == NormalizedByteCode.__putfield) { - thisType = SigTypeToClassName(ma.GetRawStackTypeWrapper(i, 1), cpi.GetClassType(classLoader)); + thisType = SigTypeToClassName(ma.GetRawStackTypeWrapper(i, 1), cpi.GetClassType()); } bool isStatic = (bytecode == NormalizedByteCode.__putstatic || bytecode == NormalizedByteCode.__getstatic); FieldWrapper field = cpi.GetField(); //wrapper.GetFieldWrapper(cpi.Name, cpi.GetFieldType(classLoader)); @@ -2925,23 +2928,23 @@ class Compiler internal override void EmitCall(ILGenerator ilgen) { - Emit(dynamicInvokestatic, ilgen, cpi.GetRetType(classLoader)); + Emit(dynamicInvokestatic, ilgen, cpi.GetRetType()); } internal override void EmitCallvirt(ILGenerator ilgen) { - Emit(dynamicInvokevirtual, ilgen, cpi.GetRetType(classLoader)); + Emit(dynamicInvokevirtual, ilgen, cpi.GetRetType()); } internal override void EmitNewobj(ILGenerator ilgen) { - Emit(dynamicInvokeSpecialNew, ilgen, cpi.GetClassType(classLoader)); + Emit(dynamicInvokeSpecialNew, ilgen, cpi.GetClassType()); } private void Emit(MethodInfo helperMethod, ILGenerator ilGenerator, TypeWrapper retTypeWrapper) { Profiler.Count("EmitDynamicInvokeEmitter"); - TypeWrapper[] args = cpi.GetArgTypes(classLoader); + TypeWrapper[] args = cpi.GetArgTypes(); LocalBuilder argarray = ilGenerator.DeclareLocal(typeof(object[])); LocalBuilder val = ilGenerator.DeclareLocal(typeof(object)); ilGenerator.Emit(OpCodes.Ldc_I4, args.Length); @@ -2971,7 +2974,7 @@ class Compiler private MethodWrapper GetMethodCallEmitter(ClassFile.ConstantPoolItemMI cpi, TypeWrapper thisType, NormalizedByteCode invoke) { - TypeWrapper wrapper = cpi.GetClassType(classLoader); + TypeWrapper wrapper = cpi.GetClassType(); if(wrapper.IsUnloadable || (thisType != null && thisType.IsUnloadable)) { return new DynamicMethodWrapper(classLoader, clazz, cpi); @@ -3149,11 +3152,11 @@ class Compiler private bool IsUnloadable(ClassFile.ConstantPoolItemMI cpi) { - if(cpi.GetClassType(classLoader).IsUnloadable || cpi.GetRetType(classLoader).IsUnloadable) + if(cpi.GetClassType().IsUnloadable || cpi.GetRetType().IsUnloadable) { return true; } - TypeWrapper[] args = cpi.GetArgTypes(classLoader); + TypeWrapper[] args = cpi.GetArgTypes(); for(int i = 0; i < args.Length; i++) { if(args[i].IsUnloadable) diff --git a/runtime/runtime.build b/runtime/runtime.build index ee1536d5..f839a04f 100644 --- a/runtime/runtime.build +++ b/runtime/runtime.build @@ -1,7 +1,7 @@ - + diff --git a/runtime/verifier.cs b/runtime/verifier.cs index 5105a743..10ecb9fe 100644 --- a/runtime/verifier.cs +++ b/runtime/verifier.cs @@ -1051,7 +1051,7 @@ class LocalVar internal int start_pc; internal int end_pc; - internal void FindLvtEntry(ClassFile.Method.Code method, int instructionIndex) + internal void FindLvtEntry(ClassFile.Method method, int instructionIndex) { ClassFile.Method.LocalVariableTableEntry[] lvt = method.LocalVariableTableAttribute; if(lvt != null) @@ -1087,7 +1087,8 @@ class MethodAnalyzer private static TypeWrapper DoubleArrayType; private static TypeWrapper LongArrayType; private ClassLoaderWrapper classLoader; - private ClassFile.Method.Code method; + private ClassFile classFile; + private ClassFile.Method method; private InstructionState[] state; private ArrayList[] callsites; private LocalVar[/*instructionIndex*/] localVars; @@ -1106,9 +1107,10 @@ class MethodAnalyzer LongArrayType = PrimitiveTypeWrapper.LONG.MakeArrayType(1); } - internal MethodAnalyzer(TypeWrapper wrapper, ClassFile.Method.Code method, ClassLoaderWrapper classLoader) + internal MethodAnalyzer(TypeWrapper wrapper, MethodWrapper mw, ClassFile classFile, ClassFile.Method method, ClassLoaderWrapper classLoader) { this.classLoader = classLoader; + this.classFile = classFile; this.method = method; state = new InstructionState[method.Instructions.Length]; callsites = new ArrayList[method.Instructions.Length]; @@ -1124,10 +1126,10 @@ class MethodAnalyzer // start by computing the initial state, the stack is empty and the locals contain the arguments state[0] = new InstructionState(method.MaxLocals, method.MaxStack); int firstNonArgLocalIndex = 0; - if(!method.Method.IsStatic) + if(!method.IsStatic) { // this reference. If we're a constructor, the this reference is uninitialized. - if(method.Method.Name == "") + if(method.Name == "") { state[0].SetLocalType(firstNonArgLocalIndex++, VerifierTypeWrapper.UninitializedThis, -1); } @@ -1136,7 +1138,7 @@ class MethodAnalyzer state[0].SetLocalType(firstNonArgLocalIndex++, wrapper, -1); } } - TypeWrapper[] argTypeWrappers = method.Method.GetArgTypes(classLoader); + TypeWrapper[] argTypeWrappers = mw.GetParameters(); for(int i = 0; i < argTypeWrappers.Length; i++) { TypeWrapper type = argTypeWrappers[i]; @@ -1157,10 +1159,11 @@ class MethodAnalyzer } InstructionState s = state[0].Copy(); bool done = false; + ClassFile.Method.Instruction[] instructions = method.Instructions; while(!done) { done = true; - for(int i = 0; i < method.Instructions.Length; i++) + for(int i = 0; i < instructions.Length; i++) { if(state[i] != null && state[i].changed) { @@ -1172,7 +1175,7 @@ class MethodAnalyzer // mark the exception handlers reachable from this instruction for(int j = 0; j < method.ExceptionTable.Length; j++) { - if(method.ExceptionTable[j].start_pc <= method.Instructions[i].PC && method.ExceptionTable[j].end_pc > method.Instructions[i].PC) + if(method.ExceptionTable[j].start_pc <= instructions[i].PC && method.ExceptionTable[j].end_pc > instructions[i].PC) { // NOTE this used to be CopyLocalsAndSubroutines, but it doesn't (always) make // sense to copy the subroutine state @@ -1198,7 +1201,7 @@ class MethodAnalyzer } } state[i].CopyTo(s); - ClassFile.Method.Instruction instr = method.Instructions[i]; + ClassFile.Method.Instruction instr = instructions[i]; switch(instr.NormalizedOpCode) { case NormalizedByteCode.__aload: @@ -1378,17 +1381,17 @@ class MethodAnalyzer s.PopObjectType(); break; case NormalizedByteCode.__getstatic: - s.PushType((GetFieldref(instr.Arg1)).GetFieldType(classLoader)); + s.PushType((GetFieldref(instr.Arg1)).GetFieldType()); break; case NormalizedByteCode.__putstatic: - s.PopType(GetFieldref(instr.Arg1).GetFieldType(classLoader)); + s.PopType(GetFieldref(instr.Arg1).GetFieldType()); break; case NormalizedByteCode.__getfield: - s.PopObjectType(GetFieldref(instr.Arg1).GetClassType(classLoader)); - s.PushType(GetFieldref(instr.Arg1).GetFieldType(classLoader)); + s.PopObjectType(GetFieldref(instr.Arg1).GetClassType()); + s.PushType(GetFieldref(instr.Arg1).GetFieldType()); break; case NormalizedByteCode.__putfield: - s.PopType(GetFieldref(instr.Arg1).GetFieldType(classLoader)); + s.PopType(GetFieldref(instr.Arg1).GetFieldType()); // putfield is allowed to access the unintialized this if(s.PeekType() == VerifierTypeWrapper.UninitializedThis) { @@ -1396,7 +1399,7 @@ class MethodAnalyzer } else { - s.PopObjectType(GetFieldref(instr.Arg1).GetClassType(classLoader)); + s.PopObjectType(GetFieldref(instr.Arg1).GetClassType()); } break; case NormalizedByteCode.__ldc: @@ -1419,7 +1422,7 @@ class MethodAnalyzer s.PushType(CoreClasses.java.lang.String.Wrapper); break; case ClassFile.ConstantType.Class: - if(method.Method.ClassFile.MajorVersion < 49) + if(classFile.MajorVersion < 49) { throw new VerifyError("Illegal type in constant pool"); } @@ -1450,7 +1453,7 @@ class MethodAnalyzer { throw new VerifyError("Illegal call to internal method"); } - TypeWrapper[] args = cpi.GetArgTypes(classLoader); + TypeWrapper[] args = cpi.GetArgTypes(); for(int j = args.Length - 1; j >= 0; j--) { s.PopType(args[j]); @@ -1466,8 +1469,8 @@ class MethodAnalyzer if(cpi.Name == "") { TypeWrapper type = s.PopType(); - if((VerifierTypeWrapper.IsNew(type) && ((VerifierTypeWrapper)type).UnderlyingType != cpi.GetClassType(classLoader)) || - (type == VerifierTypeWrapper.UninitializedThis && cpi.GetClassType(classLoader) != wrapper.BaseTypeWrapper && cpi.GetClassType(classLoader) != wrapper) || + if((VerifierTypeWrapper.IsNew(type) && ((VerifierTypeWrapper)type).UnderlyingType != cpi.GetClassType()) || + (type == VerifierTypeWrapper.UninitializedThis && cpi.GetClassType() != wrapper.BaseTypeWrapper && cpi.GetClassType() != wrapper) || (!VerifierTypeWrapper.IsNew(type) && type != VerifierTypeWrapper.UninitializedThis)) { // TODO oddly enough, Java fails verification for the class without @@ -1493,7 +1496,7 @@ class MethodAnalyzer if(instr.NormalizedOpCode != NormalizedByteCode.__invokeinterface) { TypeWrapper refType = s.PopObjectType(); - TypeWrapper targetType = cpi.GetClassType(classLoader); + TypeWrapper targetType = cpi.GetClassType(); if(!VerifierTypeWrapper.IsNullOrUnloadable(refType) && !targetType.IsUnloadable && !refType.IsAssignableTo(targetType)) @@ -1522,7 +1525,7 @@ class MethodAnalyzer } } } - TypeWrapper retType = cpi.GetRetType(classLoader); + TypeWrapper retType = cpi.GetRetType(); if(retType != PrimitiveTypeWrapper.VOID) { s.PushType(retType); @@ -1832,19 +1835,18 @@ class MethodAnalyzer s.PopObjectType(); break; case NormalizedByteCode.__return: - if(method.Method.GetRetType(classLoader) != PrimitiveTypeWrapper.VOID) + if(mw.ReturnType != PrimitiveTypeWrapper.VOID) { throw new VerifyError("Wrong return type in function"); } break; case NormalizedByteCode.__areturn: - s.PopObjectType(method.Method.GetRetType(classLoader)); + s.PopObjectType(mw.ReturnType); break; case NormalizedByteCode.__ireturn: { s.PopInt(); - TypeWrapper retType = method.Method.GetRetType(classLoader); - if(!retType.IsIntOnStackPrimitive) + if(!mw.ReturnType.IsIntOnStackPrimitive) { throw new VerifyError("Wrong return type in function"); } @@ -1852,21 +1854,21 @@ class MethodAnalyzer } case NormalizedByteCode.__lreturn: s.PopLong(); - if(method.Method.GetRetType(classLoader) != PrimitiveTypeWrapper.LONG) + if(mw.ReturnType != PrimitiveTypeWrapper.LONG) { throw new VerifyError("Wrong return type in function"); } break; case NormalizedByteCode.__freturn: s.PopFloat(); - if(method.Method.GetRetType(classLoader) != PrimitiveTypeWrapper.FLOAT) + if(mw.ReturnType != PrimitiveTypeWrapper.FLOAT) { throw new VerifyError("Wrong return type in function"); } break; case NormalizedByteCode.__dreturn: s.PopDouble(); - if(method.Method.GetRetType(classLoader) != PrimitiveTypeWrapper.DOUBLE) + if(mw.ReturnType != PrimitiveTypeWrapper.DOUBLE) { throw new VerifyError("Wrong return type in function"); } @@ -2014,7 +2016,7 @@ class MethodAnalyzer break; } case NormalizedByteCode.__nop: - if(i + 1 == method.Method.CodeAttribute.Instructions.Length) + if(i + 1 == instructions.Length) { throw new VerifyError("Falling off the end of the code"); } @@ -2032,9 +2034,9 @@ class MethodAnalyzer switch(instr.NormalizedOpCode) { case NormalizedByteCode.__lookupswitch: - for(int j = 0; j < instr.Values.Length; j++) + for(int j = 0; j < instr.SwitchEntryCount; j++) { - state[method.PcIndexMap[instr.PC + instr.TargetOffsets[j]]] += s; + state[method.PcIndexMap[instr.PC + instr.GetSwitchTargetOffset(j)]] += s; } state[method.PcIndexMap[instr.PC + instr.DefaultOffset]] += s; break; @@ -2125,12 +2127,12 @@ class MethodAnalyzer } catch(VerifyError x) { - string opcode = method.Instructions[i].OpCode.ToString(); + string opcode = instructions[i].OpCode.ToString(); if(opcode.StartsWith("__")) { opcode = opcode.Substring(2); } - x.SetInfo(method.Instructions[i].PC, method.Method.ClassFile.Name, method.Method.Name, method.Method.Signature, opcode); + x.SetInfo(instructions[i].PC, classFile.Name, method.Name, method.Signature, opcode); Tracer.Info(Tracer.Verifier, x.ToString()); throw; } @@ -2152,14 +2154,14 @@ class MethodAnalyzer if(JVM.Debug) { // if we're emitting debug info, we need to keep dead stores as well... - for(int i = 0; i < method.Instructions.Length; i++) + for(int i = 0; i < instructions.Length; i++) { - if(IsStoreLocal(method.Instructions[i].NormalizedOpCode)) + if(IsStoreLocal(instructions[i].NormalizedOpCode)) { - if(!localByStoreSite.ContainsKey(i + ":" + method.Instructions[i].NormalizedArg1)) + if(!localByStoreSite.ContainsKey(i + ":" + instructions[i].NormalizedArg1)) { LocalVar v = new LocalVar(); - v.local = method.Instructions[i].NormalizedArg1; + v.local = instructions[i].NormalizedArg1; v.type = GetRawStackTypeWrapper(i, 0); v.FindLvtEntry(method, i); locals.Add(v); @@ -2214,25 +2216,25 @@ class MethodAnalyzer } } } - invokespecialLocalVars = new LocalVar[method.Instructions.Length][]; - localVars = new LocalVar[method.Instructions.Length]; + invokespecialLocalVars = new LocalVar[instructions.Length][]; + localVars = new LocalVar[instructions.Length]; for(int i = 0; i < localVars.Length; i++) { LocalVar v = null; if(localStoreReaders[i] != null) { - Debug.Assert(IsLoadLocal(method.Instructions[i].NormalizedOpCode)); + Debug.Assert(IsLoadLocal(instructions[i].NormalizedOpCode)); // lame way to look up the local variable for a load // (by indirecting through a corresponding store) foreach(int store in localStoreReaders[i].Keys) { - v = (LocalVar)localByStoreSite[store + ":" + method.Instructions[i].NormalizedArg1]; + v = (LocalVar)localByStoreSite[store + ":" + instructions[i].NormalizedArg1]; break; } } else { - if(method.Instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial) + if(instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial) { invokespecialLocalVars[i] = new LocalVar[method.MaxLocals]; for(int j = 0; j < invokespecialLocalVars[i].Length; j++) @@ -2242,7 +2244,7 @@ class MethodAnalyzer } else { - v = (LocalVar)localByStoreSite[i + ":" + method.Instructions[i].NormalizedArg1]; + v = (LocalVar)localByStoreSite[i + ":" + instructions[i].NormalizedArg1]; } } if(v != null) @@ -2392,7 +2394,7 @@ class MethodAnalyzer { try { - ClassFile.ConstantPoolItemMI item = method.Method.ClassFile.GetMethodref(index); + ClassFile.ConstantPoolItemMI item = classFile.GetMethodref(index); if(item != null) { return item; @@ -2411,7 +2413,7 @@ class MethodAnalyzer { try { - ClassFile.ConstantPoolItemFieldref item = method.Method.ClassFile.GetFieldref(index); + ClassFile.ConstantPoolItemFieldref item = classFile.GetFieldref(index); if(item != null) { return item; @@ -2430,7 +2432,7 @@ class MethodAnalyzer { try { - return method.Method.ClassFile.GetConstantPoolConstantType(index); + return classFile.GetConstantPoolConstantType(index); } catch(IndexOutOfRangeException) { @@ -2451,7 +2453,7 @@ class MethodAnalyzer { try { - return method.Method.ClassFile.GetConstantPoolClass(index); + return classFile.GetConstantPoolClass(index); } catch(InvalidCastException) { @@ -2466,7 +2468,7 @@ class MethodAnalyzer { try { - return method.Method.ClassFile.GetConstantPoolClassType(index, classLoader); + return classFile.GetConstantPoolClassType(index); } catch(InvalidCastException) { diff --git a/runtime/vm.cs b/runtime/vm.cs index 6042510a..52cb64f1 100644 --- a/runtime/vm.cs +++ b/runtime/vm.cs @@ -36,7 +36,6 @@ public class JVM private static bool debug = false; private static bool noJniStubs = false; private static bool isStaticCompiler = false; - private static IJniProvider jniProvider; private static bool compilationPhase1; private static string sourcePath; @@ -108,38 +107,6 @@ public class JVM } } - public static IJniProvider JniProvider - { - get - { - if(jniProvider == null) - { - Type provider; - string providerAssembly = Environment.GetEnvironmentVariable("IKVM_JNI_PROVIDER"); - if(providerAssembly != null) - { - Tracer.Info(Tracer.Runtime, "Loading environment specified JNI provider: {0}", providerAssembly); - provider = Assembly.LoadFrom(providerAssembly).GetType("JNI", true); - } - else - { - if(IsUnix) - { - Tracer.Info(Tracer.Runtime, "Loading JNI provider: IKVM.JNI.Mono"); - provider = Assembly.LoadWithPartialName("IKVM.JNI.Mono").GetType("JNI", true); - } - else - { - Tracer.Info(Tracer.Runtime, "Loading JNI provider: IKVM.JNI.CLR-Win32"); - provider = Assembly.LoadWithPartialName("IKVM.JNI.CLR-Win32").GetType("JNI", true); - } - } - jniProvider = (IJniProvider)Activator.CreateInstance(provider); - } - return jniProvider; - } - } - private class CompilerClassLoader : ClassLoaderWrapper { private Hashtable classes; @@ -1355,7 +1322,7 @@ public class JVM ClassFile f; try { - f = new ClassFile(classes[i], 0, classes[i].Length, null); + f = new ClassFile(classes[i], 0, classes[i].Length, null, true); } catch(UnsupportedClassVersionError x) {