OSDN Git Service

Merge "Compile libdex as C++." into dalvik-dev
authorDan Bornstein <danfuzz@android.com>
Thu, 14 Apr 2011 21:01:32 +0000 (14:01 -0700)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Thu, 14 Apr 2011 21:01:32 +0000 (14:01 -0700)
17 files changed:
docs/embedded-vm-control.html
docs/jni-tips.html [deleted file]
vm/AtomicCache.h
vm/Dvm.mk
vm/analysis/DexPrepare.c
vm/analysis/DexVerify.h
vm/analysis/Optimize.h
vm/interp/Interp.h
vm/interp/InterpState.h
vm/interp/Jit.c
vm/oo/AccessCheck.cpp [moved from vm/oo/AccessCheck.c with 100% similarity]
vm/oo/Array.cpp [moved from vm/oo/Array.c with 99% similarity]
vm/oo/Class.cpp [moved from vm/oo/Class.c with 98% similarity]
vm/oo/Class.h
vm/oo/Object.cpp [moved from vm/oo/Object.c with 100% similarity]
vm/oo/Resolve.cpp [moved from vm/oo/Resolve.c with 100% similarity]
vm/oo/TypeCheck.cpp [moved from vm/oo/TypeCheck.c with 100% similarity]

index a0bdd29..5c444de 100644 (file)
@@ -87,9 +87,6 @@ property.  The value set for <code>dalvik.vm.jniopts</code> will
 be passed in as the <code>-Xjniopts</code> argument.  For example:
 <pre>adb shell setprop dalvik.vm.jniopts forcecopy</pre>
 
-<p>For more information about JNI checks, see
-<a href="jni-tips.html">JNI Tips</a>.
-
 
 <h2><a name="assertions">Assertions</a></h2>
 
diff --git a/docs/jni-tips.html b/docs/jni-tips.html
deleted file mode 100644 (file)
index c01c107..0000000
+++ /dev/null
@@ -1,770 +0,0 @@
-<html>
-  <head>
-    <title>Android JNI Tips</title>
-    <link rel=stylesheet href="android.css">
-  </head>
-
-  <body>
-    <h1><a name="JNI_Tips"></a>Android JNI Tips</h1>
-<p>
-</p><p>
-</p><ul>
-<li> <a href="#What_s_JNI_">What's JNI?</a>
-</li>
-<li> <a href="#JavaVM_and_JNIEnv">JavaVM and JNIEnv</a>
-</li>
-<li> <a href="#Threads">Threads</a>
-</li>
-<li> <a href="#jclass_jmethodID_and_jfieldID">jclass, jmethodID, and jfieldID</a>
-</li>
-<li> <a href="#local_vs_global_references">Local vs. Global References</a>
-</li>
-<li> <a href="#UTF_8_and_UTF_16_strings">UTF-8 and UTF-16 Strings</a>
-</li>
-<li> <a href="#Arrays">Primitive Arrays</a>
-</li>
-<li> <a href="#RegionCalls">Region Calls</a>
-</li>
-<li> <a href="#Exceptions">Exceptions</a>
-</li>
-
-<li> <a href="#Extended_checking">Extended Checking</a>
-</li>
-<li> <a href="#Native_Libraries">Native Libraries</a>
-</li>
-<li> <a href="#64bit">64-bit Considerations</a>
-</li>
-
-<li> <a href="#Unsupported">Unsupported Features</a>
-</li>
-
-<li> <a href="#FAQUnsatisfied">FAQ: UnsatisfiedLinkError</a>
-</li>
-<li> <a href="#FAQFindClass">FAQ: FindClass didn't find my class</a>
-</li>
-<li> <a href="#FAQSharing">FAQ: Sharing raw data with native code</a>
-</li>
-
-</ul>
-<p>
-<noautolink>
-</noautolink></p><p>
-</p><h2><a name="What_s_JNI_"> </a> What's JNI? </h2>
-<p>
-
-JNI is the Java Native Interface.  It defines a way for code written in the
-Java programming language to interact with native
-code, e.g. functions written in C/C++.  It's VM-neutral, has support for loading code from
-dynamic shared libraries, and while cumbersome at times is reasonably efficient.
-</p><p>
-You really should read through the
-<a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html">JNI spec for J2SE 1.6</a>
-to get a sense for how JNI works and what features are available.  Some
-aspects of the interface aren't immediately obvious on
-first reading, so you may find the next few sections handy.
-The more detailed <i>JNI Programmer's Guide and Specification</i> can be found
-<a href="http://java.sun.com/docs/books/jni/html/jniTOC.html">here</a>.
-</p><p>
-</p><p>
-</p><h2><a name="JavaVM_and_JNIEnv"> </a> JavaVM and JNIEnv </h2>
-<p>
-JNI defines two key data structures, "JavaVM" and "JNIEnv".  Both of these are essentially
-pointers to pointers to function tables.  (In the C++ version, it's a class whose sole member
-is a pointer to a function table.)  The JavaVM provides the "invocation interface" functions,
-which allow you to create and destroy the VM.  In theory you can have multiple VMs per process,
-but Android's VM only allows one.
-</p><p>
-The JNIEnv provides most of the JNI functions.  Your native functions all receive a JNIEnv as
-the first argument.
-</p><p>
-
-On some VMs, the JNIEnv is used for thread-local storage.  For this reason, <strong>you cannot share a JNIEnv between threads</strong>.
-If a piece of code has no other way to get its JNIEnv, you should share
-the JavaVM, and use JavaVM-&gt;GetEnv to discover the thread's JNIEnv.
-</p><p>
-The C declarations of JNIEnv and JavaVM are different from the C++
-declarations.  "jni.h" provides different typedefs
-depending on whether it's included into ".c" or ".cpp".  For this reason it's a bad idea to
-include JNIEnv arguments in header files included by both languages.  (Put another way: if your
-header file requires "#ifdef __cplusplus", you may have to do some extra work if anything in
-that header refers to JNIEnv.)
-
-</p><p>
-</p><h2><a name="Threads"> Threads </a></h2>
-<p>
-All VM threads are Linux threads, scheduled by the kernel.  They're usually
-started using Java language features (notably <code>Thread.start()</code>),
-but they can also be created elsewhere and then attached to the VM.  For
-example, a thread started with <code>pthread_create</code> can be attached
-with the JNI <code>AttachCurrentThread</code> or
-<code>AttachCurrentThreadAsDaemon</code> functions.  Until a thread is
-attached to the VM, it has no JNIEnv, and
-<strong>cannot make JNI calls</strong>.
-</p><p>
-Attaching a natively-created thread causes the VM to allocate and initialize
-a <code>Thread</code> object, add it to the "main" <code>ThreadGroup</code>,
-and add the thread to the set that is visible to the debugger.  Calling
-<code>AttachCurrentThread</code> on an already-attached thread is a no-op.
-</p><p>
-The Dalvik VM does not suspend threads executing native code.  If
-garbage collection is in progress, or the debugger has issued a suspend
-request, the VM will pause the thread the next time it makes a JNI call.
-</p><p>
-Threads attached through JNI <strong>must call
-<code>DetachCurrentThread</code> before they exit</strong>.
-If coding this directly is awkward, in Android &gt;= 2.0 you
-can use <code>pthread_key_create</code> to define a destructor
-function that will be called before the thread exits, and
-call <code>DetachCurrentThread</code> from there.  (Use that
-key with <code>pthread_setspecific</code> to store the JNIEnv in
-thread-local-storage; that way it'll be passed into your destructor as
-the argument.)
-
-
-</p><h2><a name="jclass_jmethodID_and_jfieldID"> jclass, jmethodID, and jfieldID </a></h2>
-<p>
-If you want to access an object's field from native code, you would do the following:
-</p><p>
-</p><ul>
-<li> Get the class object reference for the class with <code>FindClass</code>
-</li>
-<li> Get the field ID for the field with <code>GetFieldID</code>
-</li>
-<li> Get the contents of the field with something appropriate, e.g.
-<code>GetIntField</code>
-</li>
-</ul>
-<p>
-Similarly, to call a method, you'd first get a class object reference and then a method ID.  The IDs are often just
-pointers to internal VM data structures.  Looking them up may require several string
-comparisons, but once you have them the actual call to get the field or invoke the method
-is very quick.
-</p><p>
-If performance is important, it's useful to look the values up once and cache the results
-in your native code.  Because we are limiting ourselves to one VM per process, it's reasonable
-to store this data in a static local structure.
-</p><p>
-The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded.  Classes
-are only unloaded if all classes associated with a ClassLoader can be garbage collected,
-which is rare but will not be impossible in our system.  Note however that
-the <code>jclass</code>
-is a class reference and <strong>must be protected</strong> with a call
-to <code>NewGlobalRef</code> (see the next section).
-</p><p>
-If you would like to cache the IDs when a class is loaded, and automatically re-cache them
-if the class is ever unloaded and reloaded, the correct way to initialize
-the IDs is to add a piece of code that looks like this to the appropriate class:
-</p><p>
-
-</p><pre>    /*
-     * We use a class initializer to allow the native code to cache some
-     * field offsets.
-     */
-
-    /*
-     * A native function that looks up and caches interesting
-     * class/field/method IDs for this class.  Returns false on failure.
-     */
-    native private static boolean nativeClassInit();
-
-    /*
-     * Invoke the native initializer when the class is loaded.
-     */
-    static {
-        if (!nativeClassInit())
-            throw new RuntimeException("native init failed");
-    }
-</pre>
-<p>
-Create a nativeClassInit method in your C/C++ code that performs the ID lookups.  The code
-will be executed once, when the class is initialized.  If the class is ever unloaded and
-then reloaded, it will be executed again.  (See the implementation of java.io.FileDescriptor
-for an example in our source tree.)
-</p><p>
-</p><p>
-</p><p>
-</p><h2><a name="local_vs_global_references"> Local vs. Global References </a></h2>
-<p>
-Every object that JNI returns is a "local reference".  This means that it's valid for the
-duration of the current native method in the current thread.
-<strong>Even if the object itself continues to live on after the native method returns, the reference is not valid.</strong>
-This applies to all sub-classes of <code>jobject</code>, including
-<code>jclass</code>, <code>jstring</code>, and <code>jarray</code>.
-(Dalvik VM will warn you about most reference mis-uses when extended JNI
-checks are enabled.)
-</p><p>
-
-If you want to hold on to a reference for a longer period, you must use
-a "global" reference.  The <code>NewGlobalRef</code> function takes the
-local reference as an argument and returns a global one.
-The global reference is guaranteed to be valid until you call
-<code>DeleteGlobalRef</code>.
-
-</p><p>
-This pattern is commonly used when caching copies of class objects obtained
-from <code>FindClass</code>, e.g.:
-<p><pre>jclass* localClass = env-&gt;FindClass("MyClass");
-jclass* globalClass = (jclass*) env-&gt;NewGlobalRef(localClass);
-</pre>
-
-</p><p>
-All JNI methods accept both local and global references as arguments.
-It's possible for references to the same object to have different values;
-for example, the return values from consecutive calls to
-<code>NewGlobalRef</code> on the same object may be different.
-<strong>To see if two references refer to the same object,
-you must use the <code>IsSameObject</code> function.</strong>  Never compare
-references with "==" in native code.
-</p><p>
-One consequence of this is that you
-<strong>must not assume object references are constant or unique</strong>
-in native code.  The 32-bit value representing an object may be different
-from one invocation of a method to the next, and it's possible that two
-different objects could have the same 32-bit value on consecutive calls.  Do
-not use <code>jobject</code> values as keys.
-</p><p>
-Programmers are required to "not excessively allocate" local references.  In practical terms this means
-that if you're creating large numbers of local references, perhaps while running through an array of
-Objects, you should free them manually with
-<code>DeleteLocalRef</code> instead of letting JNI do it for you.  The
-VM is only required to reserve slots for
-16 local references, so if you need more than that you should either delete as you go or use
-<code>EnsureLocalCapacity</code> to reserve more.
-</p><p>
-Note: method and field IDs are just 32-bit identifiers, not object
-references, and should not be passed to <code>NewGlobalRef</code>.  The raw data
-pointers returned by functions like <code>GetStringUTFChars</code>
-and <code>GetByteArrayElements</code> are also not objects.
-</p><p>
-One unusual case deserves separate mention.  If you attach a native
-thread to the VM with AttachCurrentThread, the code you are running will
-never "return" to the VM until the thread detaches from the VM.  Any local
-references you create will have to be deleted manually unless you're going
-to detach the thread soon.
-</p><p>
-</p><p>
-</p><p>
-</p><h2><a name="UTF_8_and_UTF_16_strings"> </a> UTF-8 and UTF-16 Strings </h2>
-<p>
-The Java programming language uses UTF-16.  For convenience, JNI provides methods that work with "modified UTF-8" encoding
-as well.  (Some VMs use the modified UTF-8 internally to store strings; ours do not.)  The
-modified encoding only supports the 8- and 16-bit forms, and stores ASCII NUL values in a 16-bit encoding.
-The nice thing about it is that you can count on having C-style zero-terminated strings,
-suitable for use with standard libc string functions.  The down side is that you cannot pass
-arbitrary UTF-8 data into the VM and expect it to work correctly.
-</p><p>
-It's usually best to operate with UTF-16 strings.  With our current VMs, the
-<code>GetStringChars</code> method
-does not require a copy, whereas <code>GetStringUTFChars</code> requires a malloc and a UTF conversion.  Note that
-<strong>UTF-16 strings are not zero-terminated</strong>, and \u0000 is allowed,
-so you need to hang on to the string length as well as
-the string pointer.
-
-</p><p>
-<strong>Don't forget to Release the strings you Get</strong>.  The
-string functions return <code>jchar*</code> or <code>jbyte*</code>, which
-are C-style pointers to primitive data rather than local references.  They
-are guaranteed valid until Release is called, which means they are not
-released when the native method returns.
-</p><p>
-<strong>Data passed to NewStringUTF must be in "modified" UTF-8 format</strong>.  A
-common mistake is reading character data from a file or network stream
-and handing it to <code>NewStringUTF</code> without filtering it.
-Unless you know the data is 7-bit ASCII, you need to strip out high-ASCII
-characters or convert them to proper "modified" UTF-8 form.  If you don't,
-the UTF-16 conversion will likely not be what you expect.  The extended
-JNI checks will scan strings and warn you about invalid data, but they
-won't catch everything.
-</p><p>
-</p><p>
-
-
-</p><h2><a name="Arrays"> </a> Primitive Arrays </h2>
-<p>
-JNI provides functions for accessing the contents of array objects.
-While arrays of objects must be accessed one entry at a time, arrays of
-primitives can be read and written directly as if they were declared in C.
-</p><p>
-To make the interface as efficient as possible without constraining
-the VM implementation,
-the <code>Get&lt;PrimitiveType&gt;ArrayElements</code> family of calls
-allows the VM to either return a pointer to the actual elements, or
-allocate some memory and make a copy.  Either way, the raw pointer returned
-is guaranteed to be valid until the corresponding <code>Release</code> call
-is issued (which implies that, if the data wasn't copied, the array object
-will be pinned down and can't be relocated as part of compacting the heap).
-<strong>You must Release every array you Get.</strong>  Also, if the Get
-call fails, you must ensure that your code doesn't try to Release a NULL
-pointer later.
-</p><p>
-You can determine whether or not the data was copied by passing in a
-non-NULL pointer for the <code>isCopy</code> argument.  This is rarely
-useful.
-</p><p>
-The <code>Release</code> call takes a <code>mode</code> argument that can
-have one of three values.  The actions performed by the VM depend upon
-whether it returned a pointer to the actual data or a copy of it:
-<ul>
-    <li><code>0</code>
-    <ul>
-        <li>Actual: the array object is un-pinned.
-        <li>Copy: data is copied back.  The buffer with the copy is freed.
-    </ul>
-    <li><code>JNI_COMMIT</code>
-    <ul>
-        <li>Actual: does nothing.
-        <li>Copy: data is copied back.  The buffer with the copy
-        <strong>is not freed</strong>.
-    </ul>
-    <li><code>JNI_ABORT</code>
-    <ul>
-        <li>Actual: the array object is un-pinned.  Earlier
-        writes are <strong>not</strong> aborted.
-        <li>Copy: the buffer with the copy is freed; any changes to it are lost.
-    </ul>
-</ul>
-</p><p>
-One reason for checking the <code>isCopy</code> flag is to know if
-you need to call <code>Release</code> with <code>JNI_COMMIT</code>
-after making changes to an array &mdash; if you're alternating between making
-changes and executing code that uses the contents of the array, you may be
-able to
-skip the no-op commit.  Another possible reason for checking the flag is for
-efficient handling of <code>JNI_ABORT</code>.  For example, you might want
-to get an array, modify it in place, pass pieces to other functions, and
-then discard the changes.  If you know that JNI is making a new copy for
-you, there's no need to create another "editable" copy.  If JNI is passing
-you the original, then you do need to make your own copy.
-</p><p>
-Some have asserted that you can skip the <code>Release</code> call if
-<code>*isCopy</code> is false.  This is not the case.  If no copy buffer was
-allocated, then the original memory must be pinned down and can't be moved by
-the garbage collector.
-</p><p>
-Also note that the <code>JNI_COMMIT</code> flag does NOT release the array,
-and you will need to call <code>Release</code> again with a different flag
-eventually.
-</p><p>
-</p><p>
-
-
-</p><h2><a name="RegionCalls"> Region Calls </a></h2>
-
-<p>
-There is an alternative to calls like <code>Get&lt;Type&gt;ArrayElements</code>
-and <code>GetStringChars</code> that may be very helpful when all you want
-to do is copy data in or out.  Consider the following:
-<pre>
-    jbyte* data = env->GetByteArrayElements(array, NULL);
-    if (data != NULL) {
-        memcpy(buffer, data, len);
-        env->ReleaseByteArrayElements(array, data, JNI_ABORT);
-    }
-</pre>
-<p>
-This grabs the array, copies the first <code>len</code> byte
-elements out of it, and then releases the array.  Depending upon the VM
-policies the <code>Get</code> call will either pin or copy the array contents.
-We copy the data (for perhaps a second time), then call Release; in this case
-we use <code>JNI_ABORT</code> so there's no chance of a third copy.
-</p><p>
-We can accomplish the same thing with this:
-<pre>
-    env->GetByteArrayRegion(array, 0, len, buffer);
-</pre>
-</p><p>
-This has several advantages:
-<ul>
-    <li>Requires one JNI call instead of 2, reducing overhead.
-    <li>Doesn't require pinning or extra data copies.
-    <li>Reduces the risk of programmer error &mdash; no risk of forgetting
-    to call <code>Release</code> after something fails.
-</ul>
-</p><p>
-Similarly, you can use the <code>Set&lt;Type&gt;ArrayRegion</code> call
-to copy data into an array, and <code>GetStringRegion</code> or
-<code>GetStringUTFRegion</code> to copy characters out of a
-<code>String</code>.
-
-
-</p><h2><a name="Exceptions"> Exceptions </a></h2>
-<p>
-<strong>You may not call most JNI functions while an exception is pending.</strong>
-Your code is expected to notice the exception (via the function's return value,
-<code>ExceptionCheck()</code>, or <code>ExceptionOccurred()</code>) and return,
-or clear the exception and handle it.
-</p><p>
-The only JNI functions that you are allowed to call while an exception is
-pending are:
-<font size="-1"><ul>
-    <li>DeleteGlobalRef
-    <li>DeleteLocalRef
-    <li>DeleteWeakGlobalRef
-    <li>ExceptionCheck
-    <li>ExceptionClear
-    <li>ExceptionDescribe
-    <li>ExceptionOccurred
-    <li>MonitorExit
-    <li>PopLocalFrame
-    <li>PushLocalFrame
-    <li>Release&lt;PrimitiveType&gt;ArrayElements
-    <li>ReleasePrimitiveArrayCritical
-    <li>ReleaseStringChars
-    <li>ReleaseStringCritical
-    <li>ReleaseStringUTFChars
-</ul></font>
-</p><p>
-Many JNI calls can throw an exception, but often provide a simpler way
-of checking for failure.  For example, if <code>NewString</code> returns
-a non-NULL value, you don't need to check for an exception.  However, if
-you call a method (using a function like <code>CallObjectMethod</code>),
-you must always check for an exception, because the return value is not
-going to be valid if an exception was thrown.
-</p><p>
-Note that exceptions thrown by interpreted code do not "leap over" native code,
-and C++ exceptions thrown by native code are not handled by Dalvik.
-The JNI <code>Throw</code> and <code>ThrowNew</code> instructions just
-set an exception pointer in the current thread.  Upon returning to the VM from
-native code, the exception will be noted and handled appropriately.
-</p><p>
-Native code can "catch" an exception by calling <code>ExceptionCheck</code> or
-<code>ExceptionOccurred</code>, and clear it with
-<code>ExceptionClear</code>.  As usual,
-discarding exceptions without handling them can lead to problems.
-</p><p>
-There are no built-in functions for manipulating the Throwable object
-itself, so if you want to (say) get the exception string you will need to
-find the Throwable class, look up the method ID for
-<code>getMessage "()Ljava/lang/String;"</code>, invoke it, and if the result
-is non-NULL use <code>GetStringUTFChars</code> to get something you can
-hand to printf or a LOG macro.
-
-</p><p>
-</p><p>
-</p><h2><a name="Extended_checking"> Extended Checking </a></h2>
-<p>
-JNI does very little error checking.  Calling <code>SetIntField</code>
-on an Object field will succeed, even if the field is marked
-<code>private</code> and <code>final</code>.  The
-goal is to minimize the overhead on the assumption that, if you've written it in native code,
-you probably did it for performance reasons.
-</p><p>
-In Dalvik, you can enable additional checks by setting the
-"<code>-Xcheck:jni</code>" flag.  If the flag is set, the VM directs
-the JavaVM and JNIEnv pointers to a different table of functions.
-These functions perform an extended series of checks before calling the
-standard implementation.
-
-</p><p>
-The additional tests include:
-</p><p>
-</p>
-<ul>
-<li> Check for null pointers where not allowed.
-</li>
-<li> Verify argument type correctness (jclass is a class object,
-jfieldID points to field data, jstring is a java.lang.String).
-</li>
-<li> Field type correctness, e.g. don't store a HashMap in a String field.
-</li>
-<li> Ensure jmethodID is appropriate when making a static or virtual
-method call.
-</li>
-<li> Check to see if an exception is pending on calls where pending exceptions are not legal.
-</li>
-<li> Check for calls to inappropriate functions between Critical get/release calls.
-</li>
-<li> Check that JNIEnv structs aren't being shared between threads.
-
-</li>
-<li> Make sure local references aren't used outside their allowed lifespan.
-</li>
-<li> UTF-8 strings contain only valid "modified UTF-8" data.
-</li>
-</ul>
-<p>Accessibility of methods and fields (i.e. public vs. private) is not
-checked.
-<p>
-For a description of how to enable CheckJNI for Android apps, see
-<a href="embedded-vm-control.html">Controlling the Embedded VM</a>.
-It's currently enabled by default in the Android emulator and on
-"engineering" device builds.
-
-</p><p>
-JNI checks can be modified with the <code>-Xjniopts</code> command-line
-flag.  Currently supported values include:
-</p>
-<blockquote><dl>
-<dt>forcecopy
-<dd>When set, any function that can return a copy of the original data
-(array of primitive values, UTF-16 chars) will always do so.  The buffers
-are over-allocated and surrounded with a guard pattern to help identify
-code writing outside the buffer, and the contents are erased before the
-storage is freed to trip up code that uses the data after calling Release.
-This will have a noticeable performance impact on some applications.
-<dt>warnonly
-<dd>By default, JNI "warnings" cause the VM to abort.  With this flag
-it continues on.
-</dl></blockquote>
-
-
-</p><p>
-</p><h2><a name="Native_Libraries"> Native Libraries </a></h2>
-<p>
-You can load native code from shared libraries with the standard
-<code>System.loadLibrary()</code> call.  The
-preferred way to get at your native code is:
-</p><p>
-</p><ul>
-<li> Call <code>System.loadLibrary()</code> from a static class
-initializer.  (See the earlier example, where one is used to call
-<code>nativeClassInit()</code>.)  The argument is the "undecorated"
-library name, e.g. to load "libfubar.so" you would pass in "fubar".
-
-</li>
-<li> Provide a native function: <code><strong>jint JNI_OnLoad(JavaVM* vm, void* reserved)</strong></code>
-</li>
-<li>In <code>JNI_OnLoad</code>, register all of your native methods.  You
-should declare
-the methods "static" so the names don't take up space in the symbol table
-on the device.
-</li>
-</ul>
-<p>
-The <code>JNI_OnLoad</code> function should look something like this if
-written in C:
-</p><blockquote><pre>jint JNI_OnLoad(JavaVM* vm, void* reserved)
-{
-    JNIEnv* env;
-    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
-        return -1;
-
-    /* get class with (*env)->FindClass */
-    /* register methods with (*env)->RegisterNatives */
-
-    return JNI_VERSION_1_6;
-}
-</pre></blockquote>
-</p><p>
-You can also call <code>System.load()</code> with the full path name of the
-shared library.  For Android apps, you may find it useful to get the full
-path to the application's private data storage area from the context object.
-</p><p>
-This is the recommended approach, but not the only approach.  The VM does
-not require explicit registration, nor that you provide a
-<code>JNI_OnLoad</code> function.
-You can instead use "discovery" of native methods that are named in a
-specific way (see <a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615">
-    the JNI spec</a> for details), though this is less desirable.
-It requires more space in the shared object symbol table,
-loading is slower because it requires string searches through all of the
-loaded shared libraries, and if a method signature is wrong you won't know
-about it until the first time the method is actually used.
-</p><p>
-One other note about <code>JNI_OnLoad</code>: any <code>FindClass</code>
-calls you make from there will happen in the context of the class loader
-that was used to load the shared library.  Normally <code>FindClass</code>
-uses the loader associated with the method at the top of the interpreted
-stack, or if there isn't one (because the thread was just attached to
-the VM) it uses the "system" class loader.  This makes
-<code>JNI_OnLoad</code> a convenient place to look up and cache class
-object references.
-</p><p>
-
-
-</p><h2><a name="64bit"> 64-bit Considerations </a></h2>
-
-<p>
-Android is currently expected to run on 32-bit platforms.  In theory it
-could be built for a 64-bit system, but that is not a goal at this time.
-For the most part this isn't something that you will need to worry about
-when interacting with native code,
-but it becomes significant if you plan to store pointers to native
-structures in integer fields in an object.  To support architectures
-that use 64-bit pointers, <strong>you need to stash your native pointers in a
-<code>long</code> field rather than an <code>int</code></strong>.
-
-
-</p><h2><a name="Unsupported"> Unsupported Features </a></h2>
-<p>All JNI 1.6 features are supported, with the following exceptions:
-<ul>
-    <li><code>DefineClass</code> is not implemented.  Dalvik does not use
-    Java bytecodes or class files, so passing in binary class data
-    doesn't work.  Translation facilities may be added in a future
-    version of the VM.</li>
-    <li>"Weak global" references are implemented, but may only be passed
-    to <code>NewLocalRef</code>, <code>NewGlobalRef</code>, and
-    <code>DeleteWeakGlobalRef</code>.  (The spec strongly encourages
-    programmers to create hard references to weak globals before doing
-    anything with them, so this should not be at all limiting.)</li>
-    <li><code>GetObjectRefType</code> (new in 1.6) is implemented but not fully
-    functional &mdash; it can't always tell the difference between "local" and
-    "global" references.</li>
-</ul>
-
-<p>For backward compatibility, you may need to be aware of:
-<ul>
-    <li>Until 2.0 ("Eclair"), the '$' character was not properly
-    converted to "_00024" during searches for method names.  Working
-    around this requires using explicit registration or moving the
-    native methods out of inner classes.
-    <li>Until 2.0, it was not possible to use a <code>pthread_key_create</code>
-    destructor function to avoid the VM's "thread must be detached before
-    exit" check.  (The VM also uses a pthread key destructor function,
-    so it'd be a race to see which gets called first.)
-    <li>"Weak global" references were not implemented until 2.2 ("Froyo").
-    Older VMs will vigorously reject attempts to use them.  You can use
-    the Android platform version constants to test for support.
-</ul>
-
-
-</p><h2><a name="FAQUnsatisfied"> FAQ: UnsatisfiedLinkError </a></h2>
-<p>
-When working on native code it's not uncommon to see a failure like this:
-<pre>java.lang.UnsatisfiedLinkError: Library foo not found</pre>
-<p>
-In some cases it means what it says &mdash; the library wasn't found.  In
-other cases the library exists but couldn't be opened by dlopen(), and
-the details of the failure can be found in the exception's detail message.
-<p>
-Common reasons why you might encounter "library not found" exceptions:
-<ul>
-    <li>The library doesn't exist or isn't accessible to the app.  Use
-    <code>adb shell ls -l &lt;path&gt;</code> to check its presence
-    and permissions.
-    <li>The library wasn't built with the NDK.  This can result in
-    dependencies on functions or libraries that don't exist on the device.
-</ul>
-</p><p>
-Another class of <code>UnsatisfiedLinkError</code> failures looks like:
-<pre>java.lang.UnsatisfiedLinkError: myfunc
-        at Foo.myfunc(Native Method)
-        at Foo.main(Foo.java:10)</pre>
-<p>
-In logcat, you'll see:
-<pre>W/dalvikvm(  880): No implementation found for native LFoo;.myfunc ()V</pre>
-<p>
-This means that the VM tried to find a matching method but was unsuccessful.
-Some common reasons for this are:
-<ul>
-    <li>The library isn't getting loaded.  Check the logcat output for
-    messages about library loading.
-    <li>The method isn't being found due to a name or signature mismatch.  This
-    is commonly caused by:
-    <ul>
-        <li>For lazy method lookup, failing to declare C++ functions
-        with <code>extern C</code>.  You can use <code>arm-eabi-nm</code>
-        to see the symbols as they appear in the library; if they look
-        mangled (e.g. <code>_Z15Java_Foo_myfuncP7_JNIEnvP7_jclass</code>
-        rather than <code>Java_Foo_myfunc</code>) then you need to
-        adjust the declaration.
-        <li>For explicit registration, minor errors when entering the
-        method signature.  Make sure that what you're passing to the
-        registration call matches the signature in the log file.
-        Remember that 'B' is <code>byte</code> and 'Z' is <code>boolean</code>.
-        Class name components in signatures start with 'L', end with ';',
-        use '/' to separate package/class names, and use '$' to separate
-        inner-class names
-        (e.g. <code>Ljava/util/Map$Entry;</code>).
-    </ul>
-</ul>
-<p>
-Using <code>javah</code> to automatically generate JNI headers may help
-avoid some problems.
-
-
-</p><h2><a name="FAQFindClass"> FAQ: FindClass didn't find my class </a></h2>
-<p>
-Make sure that the class name string has the correct format.  JNI class
-names start with the package name and are separated with slashes,
-e.g. <code>java/lang/String</code>.  If you're looking up an array class,
-you need to start with the appropriate number of square brackets and
-must also wrap the class with 'L' and ';', so a one-dimensional array of
-<code>String</code> would be <code>[Ljava/lang/String;</code>.
-</p><p>
-If the class name looks right, you could be running into a class loader
-issue.  <code>FindClass</code> wants to start the class search in the
-class loader associated with your code.  It examines the VM call stack,
-which will look something like:
-<pre>    Foo.myfunc(Native Method)
-    Foo.main(Foo.java:10)
-    dalvik.system.NativeStart.main(Native Method)</pre>
-<p>
-The topmost method is <code>Foo.myfunc</code>.  <code>FindClass</code>
-finds the <code>ClassLoader</code> object associated with the <code>Foo</code>
-class and uses that.
-</p><p>
-This usually does what you want.  You can get into trouble if you
-create a thread outside the VM (perhaps by calling <code>pthread_create</code>
-and then attaching it to the VM with <code>AttachCurrentThread</code>).
-Now the stack trace looks like this:
-<pre>    dalvik.system.NativeStart.run(Native Method)</pre>
-<p>
-The topmost method is <code>NativeStart.run</code>, which isn't part of
-your application.  If you call <code>FindClass</code> from this thread, the
-VM will start in the "system" class loader instead of the one associated
-with your application, so attempts to find app-specific classes will fail.
-</p><p>
-There are a few ways to work around this:
-<ul>
-    <li>Do your <code>FindClass</code> lookups once, in
-    <code>JNI_OnLoad</code>, and cache the class references for later
-    use.  Any <code>FindClass</code> calls made as part of executing
-    <code>JNI_OnLoad</code> will use the class loader associated with
-    the function that called <code>System.loadLibrary</code> (this is a
-    special rule, provided to make library initialization more convenient).
-    If your app code is loading the library, <code>FindClass</code>
-    will use the correct class loader.
-    <li>Pass an instance of the class into the functions that need
-    it, e.g. declare your native method to take a Class argument and
-    then pass <code>Foo.class</code> in.
-    <li>Cache a reference to the <code>ClassLoader</code> object somewhere
-    handy, and issue <code>loadClass</code> calls directly.  This requires
-    some effort.
-</ul>
-
-</p><p>
-
-
-</p><h2><a name="FAQSharing"> FAQ: Sharing raw data with native code </a></h2>
-<p>
-You may find yourself in a situation where you need to access a large
-buffer of raw data from code written in Java and C/C++.  Common examples
-include manipulation of bitmaps or sound samples.  There are two
-basic approaches.
-</p><p>
-You can store the data in a <code>byte[]</code>.  This allows very fast
-access from code written in Java.  On the native side, however, you're
-not guaranteed to be able to access the data without having to copy it.  In
-some implementations, <code>GetByteArrayElements</code> and
-<code>GetPrimitiveArrayCritical</code> will return actual pointers to the
-raw data in the managed heap, but in others it will allocate a buffer
-on the native heap and copy the data over.
-</p><p>
-The alternative is to store the data in a direct byte buffer.  These
-can be created with <code>java.nio.ByteBuffer.allocateDirect</code>, or
-the JNI <code>NewDirectByteBuffer</code> function.  Unlike regular
-byte buffers, the storage is not allocated on the managed heap, and can
-always be accessed directly from native code (get the address
-with <code>GetDirectBufferAddress</code>).  Depending on how direct
-byte buffer access is implemented in the VM, accessing the data from code
-written in Java can be very slow.
-</p><p>
-The choice of which to use depends on two factors:
-<ol>
-    <li>Will most of the data accesses happen from code written in Java
-    or in C/C++?
-    <li>If the data is eventually being passed to a system API, what form
-    must it be in?  (For example, if the data is eventually passed to a
-    function that takes a byte[], doing processing in a direct
-    <code>ByteBuffer</code> might be unwise.)
-</ol>
-If there's no clear winner, use a direct byte buffer.  Support for them
-is built directly into JNI, and access to them from code written in
-Java can be made faster with VM improvements.
-</p>
-
-<address>Copyright &copy; 2008 The Android Open Source Project</address>
-
-  </body>
-</html>
index 686eac5..2342162 100644 (file)
 #ifndef _DALVIK_ATOMICCACHE
 #define _DALVIK_ATOMICCACHE
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * If set to "1", gather some stats on our caching success rate.
  */
@@ -170,4 +174,8 @@ void dvmUpdateAtomicCache(u4 key1, u4 key2, u4 value, AtomicCacheEntry* pEntry,
  */
 void dvmDumpAtomicCacheStats(const AtomicCache* pCache);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /*_DALVIK_ATOMICCACHE*/
index a9624e3..cc84dc1 100644 (file)
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -177,12 +177,12 @@ LOCAL_SRC_FILES := \
        native/org_apache_harmony_dalvik_ddmc_DdmServer.cpp \
        native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cpp \
        native/sun_misc_Unsafe.cpp \
-       oo/AccessCheck.c \
-       oo/Array.c \
-       oo/Class.c \
-       oo/Object.c \
-       oo/Resolve.c \
-       oo/TypeCheck.c \
+       oo/AccessCheck.cpp \
+       oo/Array.cpp \
+       oo/Class.cpp \
+       oo/Object.cpp \
+       oo/Resolve.cpp \
+       oo/TypeCheck.cpp \
        reflect/Annotation.cpp \
        reflect/Proxy.cpp \
        reflect/Reflect.cpp \
index 0f82cbf..fce09e2 100644 (file)
@@ -104,6 +104,8 @@ retry:
             return fd;
         }
         readOnly = true;
+    } else {
+        fchmod(fd, 0644);
     }
 
     /*
index 90a724f..a990502 100644 (file)
 #ifndef _DALVIK_DEXVERIFY
 #define _DALVIK_DEXVERIFY
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Global verification mode.  These must be in order from least verification
  * to most.  If we're using "exact GC", we may need to perform some of
@@ -63,4 +67,8 @@ typedef struct {
     size_t  biggestAlloc;       /* largest RegisterLine table alloc */
 } VerifierStats;
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /*_DALVIK_DEXVERIFY*/
index 75b6eab..9383881 100644 (file)
 #ifndef _DALVIK_OPTIMIZE
 #define _DALVIK_OPTIMIZE
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Entry point from DEX preparation.
  */
@@ -44,4 +48,8 @@ InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx,
 StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx,
     VerifyError* pFailure);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /*_DALVIK_OPTIMIZE*/
index 91e2262..5626160 100644 (file)
 #ifndef _DALVIK_INTERP_INTERP
 #define _DALVIK_INTERP_INTERP
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Stash the dalvik PC in the frame.  Called  during interpretation.
  */
@@ -117,4 +121,8 @@ extern void* dvmAsmInstructionStart[];
 extern void* dvmAsmAltInstructionStart[];
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /*_DALVIK_INTERP_INTERP*/
index 6f86476..fb21f0d 100644 (file)
 #ifndef _DALVIK_INTERP_STATE
 #define _DALVIK_INTERP_STATE
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Execution mode, e.g. interpreter vs. JIT.
  */
@@ -243,4 +247,8 @@ typedef struct {
 
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /*_DALVIK_INTERP_STATE*/
index c32e922..faf5880 100644 (file)
@@ -111,6 +111,7 @@ void* dvmSelfVerificationSaveState(const u2* pc, u4* fp,
 
     self->interpSave.fp = (u4*)shadowSpace->shadowFP;
     self->interpStackEnd = (u1*)shadowSpace->registerSpace;
+    self->curFrame = self->interpSave.fp;
 
     // Create a copy of the stack
     memcpy(((char*)shadowSpace->shadowFP)-preBytes, ((char*)fp)-preBytes,
@@ -156,29 +157,6 @@ void* dvmSelfVerificationRestoreState(const u2* pc, u4* fp,
     // Special case when punting after a single instruction
     if (exitState == kSVSPunt && pc == shadowSpace->startPC) {
         shadowSpace->selfVerificationState = kSVSIdle;
-    } else if (exitState == kSVSBackwardBranch && pc < shadowSpace->startPC) {
-        /*
-         * Consider a trace with a backward branch:
-         *   1: ..
-         *   2: ..
-         *   3: ..
-         *   4: ..
-         *   5: Goto {1 or 2 or 3 or 4}
-         *
-         * If there instruction 5 goes to 1 and there is no single-step
-         * instruction in the loop, pc is equal to shadowSpace->startPC and
-         * we will honor the backward branch condition.
-         *
-         * If the single-step instruction is outside the loop, then after
-         * resuming in the trace the startPC will be less than pc so we will
-         * also honor the backward branch condition.
-         *
-         * If the single-step is inside the loop, we won't hit the same endPC
-         * twice when the interpreter is re-executing the trace so we want to
-         * cancel the backward branch condition. In this case it can be
-         * detected as the endPC (ie pc) will be less than startPC.
-         */
-        shadowSpace->selfVerificationState = kSVSNormal;
     } else {
         shadowSpace->selfVerificationState = exitState;
     }
@@ -186,6 +164,7 @@ void* dvmSelfVerificationRestoreState(const u2* pc, u4* fp,
     /* Restore state before returning */
     self->interpSave.pc = shadowSpace->startPC;
     self->interpSave.fp = shadowSpace->fp;
+    self->curFrame = self->interpSave.fp;
     self->interpSave.method = shadowSpace->method;
     self->interpSave.methodClassDex = shadowSpace->methodClassDex;
     self->retval = shadowSpace->retval;
@@ -303,16 +282,20 @@ void dvmCheckSelfVerification(const u2* pc, Thread* self)
     }
 
     /*
-     * Skip endPC once when trace has a backward branch. If the SV state is
-     * single step, keep it that way.
+     * Generalize the self verification state to kSVSDebugInterp unless the
+     * entry reason is kSVSBackwardBranch or kSVSSingleStep.
      */
-    if ((state == kSVSBackwardBranch && pc == shadowSpace->endPC) ||
-        (state != kSVSBackwardBranch && state != kSVSSingleStep)) {
+    if (state != kSVSBackwardBranch && state != kSVSSingleStep) {
         shadowSpace->selfVerificationState = kSVSDebugInterp;
     }
 
-    /* Check that the current pc is the end of the trace */
-    if ((state == kSVSDebugInterp || state == kSVSSingleStep) &&
+    /*
+     * Check that the current pc is the end of the trace when at least one
+     * instruction is interpreted.
+     */
+    if ((state == kSVSDebugInterp || state == kSVSSingleStep ||
+         state == kSVSBackwardBranch) &&
+        shadowSpace->traceLength != 0 &&
         pc == shadowSpace->endPC) {
 
         shadowSpace->selfVerificationState = kSVSIdle;
@@ -322,6 +305,11 @@ void dvmCheckSelfVerification(const u2* pc, Thread* self)
                          shadowSpace->registerSpaceSize*4 -
                          (int) shadowSpace->shadowFP;
         if (memcmp(shadowSpace->fp, shadowSpace->shadowFP, frameBytes)) {
+            if (state == kSVSBackwardBranch) {
+                /* State mismatch on backward branch - try one more iteration */
+                shadowSpace->selfVerificationState = kSVSDebugInterp;
+                goto log_and_continue;
+            }
             LOGD("~~~ DbgIntp(%d): REGISTERS DIVERGENCE!", self->threadId);
             selfVerificationDumpState(pc, self);
             selfVerificationDumpTrace(pc, self);
@@ -346,6 +334,14 @@ void dvmCheckSelfVerification(const u2* pc, Thread* self)
                               (int) self->curFrame - localRegs;
             if (memcmp(((char*)self->curFrame)+localRegs,
                 ((char*)shadowSpace->endShadowFP)+localRegs, frameBytes2)) {
+                if (state == kSVSBackwardBranch) {
+                    /*
+                     * State mismatch on backward branch - try one more
+                     * iteration.
+                     */
+                    shadowSpace->selfVerificationState = kSVSDebugInterp;
+                    goto log_and_continue;
+                }
                 LOGD("~~~ DbgIntp(%d): REGISTERS (FRAME2) DIVERGENCE!",
                     self->threadId);
                 selfVerificationDumpState(pc, self);
@@ -371,6 +367,14 @@ void dvmCheckSelfVerification(const u2* pc, Thread* self)
              heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
             int memData = *((unsigned int*) heapSpacePtr->addr);
             if (heapSpacePtr->data != memData) {
+                if (state == kSVSBackwardBranch) {
+                    /*
+                     * State mismatch on backward branch - try one more
+                     * iteration.
+                     */
+                    shadowSpace->selfVerificationState = kSVSDebugInterp;
+                    goto log_and_continue;
+                }
                 LOGD("~~~ DbgIntp(%d): MEMORY DIVERGENCE!", self->threadId);
                 LOGD("Addr: 0x%x Intrp Data: 0x%x Jit Data: 0x%x",
                     heapSpacePtr->addr, memData, heapSpacePtr->data);
@@ -403,16 +407,16 @@ void dvmCheckSelfVerification(const u2* pc, Thread* self)
                              false /* disable */);
         self->jitState = kJitDone;
         return;
-
+    }
+log_and_continue:
     /* If end not been reached, make sure max length not exceeded */
-    } else if (shadowSpace->traceLength >= JIT_MAX_TRACE_LEN) {
+    if (shadowSpace->traceLength >= JIT_MAX_TRACE_LEN) {
         LOGD("~~~ DbgIntp(%d): CONTROL DIVERGENCE!", self->threadId);
         LOGD("startPC: 0x%x endPC: 0x%x currPC: 0x%x",
             (int)shadowSpace->startPC, (int)shadowSpace->endPC, (int)pc);
         selfVerificationDumpState(pc, self);
         selfVerificationDumpTrace(pc, self);
         selfVerificationSpinLoop(shadowSpace);
-
         return;
     }
     /* Log the instruction address and decoded instruction for debug */
similarity index 100%
rename from vm/oo/AccessCheck.c
rename to vm/oo/AccessCheck.cpp
similarity index 99%
rename from vm/oo/Array.c
rename to vm/oo/Array.cpp
index 48602d1..cdf899c 100644 (file)
@@ -520,7 +520,7 @@ static ClassObject* createArrayClass(const char* descriptor, Object* loader)
 bool dvmCopyObjectArray(ArrayObject* dstArray, const ArrayObject* srcArray,
     ClassObject* dstElemClass)
 {
-    Object** src = (Object**)srcArray->contents;
+    Object** src = (Object**)(void*)srcArray->contents;
     u4 length, count;
 
     assert(srcArray->length == dstArray->length);
@@ -549,7 +549,7 @@ bool dvmCopyObjectArray(ArrayObject* dstArray, const ArrayObject* srcArray,
 bool dvmUnboxObjectArray(ArrayObject* dstArray, const ArrayObject* srcArray,
     ClassObject* dstElemClass)
 {
-    Object** src = (Object**)srcArray->contents;
+    Object** src = (Object**)(void*)srcArray->contents;
     void* dst = (void*)dstArray->contents;
     u4 count = dstArray->length;
     PrimitiveType typeIndex = dstElemClass->primitiveType;
similarity index 98%
rename from vm/oo/Class.c
rename to vm/oo/Class.cpp
index 7f8f190..811e103 100644 (file)
@@ -1325,7 +1325,6 @@ static ClassObject* findClassFromLoaderNoInit(const char* descriptor,
     //        descriptor, loader);
 
     Thread* self = dvmThreadSelf();
-    ClassObject* clazz;
 
     assert(loader != NULL);
 
@@ -1339,7 +1338,7 @@ static ClassObject* findClassFromLoaderNoInit(const char* descriptor,
      * lookup-by-descriptor twice.  It appears this is still a win, so
      * I'm keeping it in.
      */
-    clazz = dvmLookupClass(descriptor, loader, false);
+    ClassObject* clazz = dvmLookupClass(descriptor, loader, false);
     if (clazz != NULL) {
         LOGVV("Already loaded: %s %p\n", descriptor, loader);
         return clazz;
@@ -1354,7 +1353,7 @@ static ClassObject* findClassFromLoaderNoInit(const char* descriptor,
     dotName = dvmDescriptorToDot(descriptor);
     if (dotName == NULL) {
         dvmThrowOutOfMemoryError(NULL);
-        goto bail;
+        return NULL;
     }
     nameObj = dvmCreateStringFromCstr(dotName);
     if (nameObj == NULL) {
@@ -1371,30 +1370,31 @@ static ClassObject* findClassFromLoaderNoInit(const char* descriptor,
      * the bootstrap class loader can find it before doing its own load.
      */
     LOGVV("--- Invoking loadClass(%s, %p)\n", dotName, loader);
-    const Method* loadClass =
-        loader->clazz->vtable[gDvm.voffJavaLangClassLoader_loadClass];
-    JValue result;
-    dvmCallMethod(self, loadClass, loader, &result, nameObj);
-    clazz = (ClassObject*) result.l;
-
-    dvmMethodTraceClassPrepEnd();
+    {
+        const Method* loadClass =
+            loader->clazz->vtable[gDvm.voffJavaLangClassLoader_loadClass];
+        JValue result;
+        dvmCallMethod(self, loadClass, loader, &result, nameObj);
+        clazz = (ClassObject*) result.l;
 
-    Object* excep = dvmGetException(self);
-    if (excep != NULL) {
+        dvmMethodTraceClassPrepEnd();
+        Object* excep = dvmGetException(self);
+        if (excep != NULL) {
 #if DVM_SHOW_EXCEPTION >= 2
-        LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
-            dotName, loader, excep->clazz->descriptor);
+            LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
+                 dotName, loader, excep->clazz->descriptor);
 #endif
-        dvmAddTrackedAlloc(excep, self);
-        dvmClearException(self);
-        dvmThrowChainedNoClassDefFoundError(descriptor, excep);
-        dvmReleaseTrackedAlloc(excep, self);
-        clazz = NULL;
-        goto bail;
-    } else if (clazz == NULL) {
-        LOGW("ClassLoader returned NULL w/o exception pending\n");
-        dvmThrowNullPointerException("ClassLoader returned null");
-        goto bail;
+            dvmAddTrackedAlloc(excep, self);
+            dvmClearException(self);
+            dvmThrowChainedNoClassDefFoundError(descriptor, excep);
+            dvmReleaseTrackedAlloc(excep, self);
+            clazz = NULL;
+            goto bail;
+        } else if (clazz == NULL) {
+            LOGW("ClassLoader returned NULL w/o exception pending\n");
+            dvmThrowNullPointerException("ClassLoader returned null");
+            goto bail;
+        }
     }
 
     /* not adding clazz to tracked-alloc list, because it's a ClassObject */
@@ -3023,17 +3023,19 @@ static bool createIftable(ClassObject* clazz)
     bool zapIftable = false;
     bool zapVtable = false;
     bool zapIfvipool = false;
-    int ifCount, superIfCount, idx;
-    int i;
+    int poolOffset = 0, poolSize = 0;
+    Method** mirandaList = NULL;
+    int mirandaCount = 0, mirandaAlloc = 0;
 
+    int superIfCount;
     if (clazz->super != NULL)
         superIfCount = clazz->super->iftableCount;
     else
         superIfCount = 0;
 
-    ifCount = superIfCount;
+    int ifCount = superIfCount;
     ifCount += clazz->interfaceCount;
-    for (i = 0; i < clazz->interfaceCount; i++)
+    for (int i = 0; i < clazz->interfaceCount; i++)
         ifCount += clazz->interfaces[i]->iftableCount;
 
     LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n",
@@ -3042,8 +3044,7 @@ static bool createIftable(ClassObject* clazz)
     if (ifCount == 0) {
         assert(clazz->iftableCount == 0);
         assert(clazz->iftable == NULL);
-        result = true;
-        goto bail;
+        return true;
     }
 
     /*
@@ -3062,13 +3063,10 @@ static bool createIftable(ClassObject* clazz)
     /*
      * Create a flattened interface hierarchy of our immediate interfaces.
      */
-    idx = superIfCount;
+    int idx = superIfCount;
 
-    for (i = 0; i < clazz->interfaceCount; i++) {
-        ClassObject* interf;
-        int j;
-
-        interf = clazz->interfaces[i];
+    for (int i = 0; i < clazz->interfaceCount; i++) {
+        ClassObject* interf = clazz->interfaces[i];
         assert(interf != NULL);
 
         /* make sure this is still an interface class */
@@ -3084,7 +3082,7 @@ static bool createIftable(ClassObject* clazz)
         clazz->iftable[idx++].clazz = interf;
 
         /* add entries for the interface's superinterfaces */
-        for (j = 0; j < interf->iftableCount; j++) {
+        for (int j = 0; j < interf->iftableCount; j++) {
             clazz->iftable[idx++].clazz = interf->iftable[j].clazz;
         }
     }
@@ -3111,10 +3109,8 @@ static bool createIftable(ClassObject* clazz)
          * because it wants to return just the interfaces declared to be
          * implemented directly by the class.  I'm excluding this code for now.
          */
-        for (i = superIfCount; i < ifCount; i++) {
-            int j;
-
-            for (j = 0; j < ifCount; j++) {
+        for (int i = superIfCount; i < ifCount; i++) {
+            for (int j = 0; j < ifCount; j++) {
                 if (i == j)
                     continue;
                 if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) {
@@ -3164,8 +3160,7 @@ static bool createIftable(ClassObject* clazz)
      * is flat for fast access in a class and all of its subclasses, but
      * "ifviPool" is only created for the topmost implementor.
      */
-    int poolSize = 0;
-    for (i = superIfCount; i < ifCount; i++) {
+    for (int i = superIfCount; i < ifCount; i++) {
         /*
          * Note it's valid for an interface to have no methods (e.g.
          * java/io/Serializable).
@@ -3191,11 +3186,7 @@ static bool createIftable(ClassObject* clazz)
      * Fill in the vtable offsets for the interfaces that weren't part of
      * our superclass.
      */
-    int poolOffset = 0;
-    Method** mirandaList = NULL;
-    int mirandaCount = 0, mirandaAlloc = 0;
-
-    for (i = superIfCount; i < ifCount; i++) {
+    for (int i = superIfCount; i < ifCount; i++) {
         ClassObject* interface;
         int methIdx;
 
@@ -3331,7 +3322,7 @@ static bool createIftable(ClassObject* clazz)
         Method* meth;
         int oldMethodCount, oldVtableCount;
 
-        for (i = 0; i < mirandaCount; i++) {
+        for (int i = 0; i < mirandaCount; i++) {
             LOGVV("MIRANDA %d: %s.%s\n", i,
                 mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
         }
@@ -3381,7 +3372,7 @@ static bool createIftable(ClassObject* clazz)
             LOGVV("MIRANDA fixing vtable pointers\n");
             dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
             Method* meth = newVirtualMethods;
-            for (i = 0; i < clazz->virtualMethodCount; i++, meth++)
+            for (int i = 0; i < clazz->virtualMethodCount; i++, meth++)
                 clazz->vtable[meth->methodIndex] = meth;
             dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
         }
@@ -3417,7 +3408,7 @@ static bool createIftable(ClassObject* clazz)
          * dvmAbstractMethodStub().
          */
         meth = clazz->virtualMethods + oldMethodCount;
-        for (i = 0; i < mirandaCount; i++, meth++) {
+        for (int i = 0; i < mirandaCount; i++, meth++) {
             dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
             cloneMethod(meth, mirandaList[i]);
             meth->clazz = clazz;
@@ -4174,9 +4165,9 @@ static bool validateSuperDescriptors(const ClassObject* clazz)
  */
 bool dvmIsClassInitializing(const ClassObject* clazz)
 {
-    ClassStatus status;
-
-    status = android_atomic_acquire_load((ClassStatus*) &clazz->status);
+    const int32_t* addr = (const int32_t*)(const void*)&clazz->status;
+    int32_t value = android_atomic_acquire_load(addr);
+    ClassStatus status = static_cast<ClassStatus>(value);
     return (status == CLASS_INITIALIZING &&
             clazz->initThreadId == dvmThreadSelf()->threadId);
 }
@@ -4247,6 +4238,8 @@ bool dvmIsClassInitializing(const ClassObject* clazz)
  */
 bool dvmInitClass(ClassObject* clazz)
 {
+    u8 startWhen = 0;
+
 #if LOG_CLASS_LOADING
     bool initializedByUs = false;
 #endif
@@ -4412,7 +4405,6 @@ noverify:
         return false;
     }
 
-    u8 startWhen = 0;
     if (gDvm.allocProf.enabled) {
         startWhen = dvmGetRelativeTimeNsec();
     }
@@ -4455,7 +4447,8 @@ noverify:
 
     /* order matters here, esp. interaction with dvmIsClassInitializing */
     clazz->initThreadId = self->threadId;
-    android_atomic_release_store(CLASS_INITIALIZING, &clazz->status);
+    android_atomic_release_store(CLASS_INITIALIZING,
+                                 (int32_t*)(void*)&clazz->status);
     dvmUnlockObject(self, (Object*) clazz);
 
     /* init our superclass */
index 43a3954..f0c853c 100644 (file)
@@ -39,14 +39,16 @@ extern "C" {
  * Ordering is significant.  (Currently only ".dex" is supported directly
  * by the VM.)
  */
+typedef enum {
+    kCpeUnknown = 0,
+    kCpeDir,
+    kCpeJar,
+    kCpeDex,
+    kCpeLastEntry       /* used as sentinel at end of array */
+} ClassPathEntryKind;
+
 typedef struct ClassPathEntry {
-    enum {
-        kCpeUnknown = 0,
-        kCpeDir,
-        kCpeJar,
-        kCpeDex,
-        kCpeLastEntry       /* used as sentinel at end of array */
-    }       kind;
+    ClassPathEntryKind kind;
     char*   fileName;
     void*   ptr;            /* JarFile* or DexFile* */
 } ClassPathEntry;
similarity index 100%
rename from vm/oo/Object.c
rename to vm/oo/Object.cpp
similarity index 100%
rename from vm/oo/Resolve.c
rename to vm/oo/Resolve.cpp
similarity index 100%
rename from vm/oo/TypeCheck.c
rename to vm/oo/TypeCheck.cpp