--- /dev/null
+
+ Copyright (c) 2005-2008, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
dumps has been removed from the VM.
</p>
-<h3>Android x.y ("Honeycomb")</h3>
+<h3>Android 3.0 ("Honeycomb")</h3>
<p>
A new command-line tool has been added:
</p>
<p>
The native code in the core libraries (chiefly <code>libcore</code>,
but also <code>dalvik/vm/native</code>) is written in C/C++ and is expected
-to work without modification in a Linux environment. Much of the code
-comes directly from the Apache Harmony project.
+to work without modification in a Linux environment.
</p><p>
The core libraries pull in code from many other projects, including
OpenSSL, zlib, and ICU. These will also need to be ported before the VM
<li>Make sure <code>dalvik/vm/Android.mk</code> will find the files for
your architecture. If <code>$(TARGET_ARCH)</code> is configured this
will happen automatically.
+<li>Disable the Dalvik JIT. You can do this in the general device
+configuration, or by editing the initialization of WITH_JIT in
+<code>dalvik/vm/Dvm.mk</code> to always be <code>false</code>.
</ol>
</p><p>
You now have the basic framework in place. Whenever you make a change, you
in assembly.
<li>In the <code>dalvik</code> directory, regenerate the
<code>libdvm.so</code> library with <code>mm</code>. You can also use
-<code>make libdvm</code> from the top of the tree.
+<code>mmm dalvik/vm</code> from the top of the tree.
</ol>
</p><p>
This will leave you with an updated libdvm.so, which can be pushed out to
<h3>Replacing Stubs</h3>
<p>
-There are roughly 230 Dalvik opcodes, including some that are inserted by
+There are roughly 250 Dalvik opcodes, including some that are inserted by
<a href="dexopt.html">dexopt</a> and aren't described in the
<a href="dalvik-bytecode.html">Dalvik bytecode</a> documentation. Each
one must perform the appropriate actions, fetch the next opcode, and
tests for this.)
</p>
+
+<h2>Other Performance Issues</h2>
+
+<p>
+The <code>System.arraycopy()</code> function is heavily used. The
+implementation relies on the bionic C library to provide a fast,
+platform-optimized data copy function for arrays with elements wider
+than one byte. If you're not using bionic, or your platform does not
+have an implementation of this method, Dalvik will use correct but
+sub-optimal algorithms instead. For best performance you will want
+to provide your own version.
+</p><p>
+See the comments in <code>dalvik/vm/native/java_lang_System.c</code>
+for details.
+</p>
+
<p>
<address>Copyright © 2009 The Android Open Source Project</address>
--- /dev/null
+
+ Copyright (c) 2005-2008, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
#include <fcntl.h>
#include <errno.h>
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
/*
* Extract "classes.dex" from archive file.
/*
* Pop open the (presumed) DEX file.
*/
- fd = open(fileName, O_RDONLY);
+ fd = open(fileName, O_RDONLY | O_BINARY);
if (fd < 0) {
if (!quiet) {
fprintf(stderr, "ERROR: unable to open '%s': %s\n",
* Make sure that the given cache can hold a string of the given length,
* including the final '\0' byte.
*/
-static void dexStringCacheAlloc(DexStringCache* pCache, size_t length) {
+void dexStringCacheAlloc(DexStringCache* pCache, size_t length) {
if (pCache->allocatedSize != 0) {
if (pCache->allocatedSize >= length) {
return;
return dexGetProtoId(pProto->dexFile, pProto->protoIdx);
}
-/*
- * Get the short-form method descriptor for the given prototype. The
- * prototype must be protoIdx-based.
- */
+/* (documented in header file) */
const char* dexProtoGetShorty(const DexProto* pProto) {
const DexProtoId* protoId = getProtoId(pProto);
return dexStringById(pProto->dexFile, protoId->shortyIdx);
}
-/*
- * Get the full method descriptor for the given prototype.
- */
+/* (documented in header file) */
const char* dexProtoGetMethodDescriptor(const DexProto* pProto,
DexStringCache* pCache) {
const DexFile* dexFile = pProto->dexFile;
return pCache->value;
}
-/*
- * Get a copy of the descriptor string associated with the given prototype.
- * The returned pointer must be free()ed by the caller.
- */
+/* (documented in header file) */
char* dexProtoCopyMethodDescriptor(const DexProto* pProto) {
DexStringCache cache;
dexProtoGetMethodDescriptor(pProto, &cache));
}
-/*
- * Get the parameter descriptors for the given prototype. This is the
- * concatenation of all the descriptors for all the parameters, in
- * order, with no other adornment.
- */
+/* (documented in header file) */
const char* dexProtoGetParameterDescriptors(const DexProto* pProto,
DexStringCache* pCache) {
DexParameterIterator iterator;
return pCache->value;
}
-/*
- * Get the type descriptor for the return type of the given prototype.
- */
+/* (documented in header file) */
const char* dexProtoGetReturnType(const DexProto* pProto) {
const DexProtoId* protoId = getProtoId(pProto);
return dexStringByTypeIdx(pProto->dexFile, protoId->returnTypeIdx);
}
-/*
- * Get the parameter count of the given prototype.
- */
+/* (documented in header file) */
size_t dexProtoGetParameterCount(const DexProto* pProto) {
const DexProtoId* protoId = getProtoId(pProto);
const DexTypeList* typeList =
return (typeList == NULL) ? 0 : typeList->size;
}
-/*
- * Compute the number of parameter words (u4 units) required by the
- * given prototype. For example, if the method takes (int, long) and
- * returns double, this would return 3 (one for the int, two for the
- * long, and the return type isn't relevant).
- */
+/* (documented in header file) */
int dexProtoComputeArgsSize(const DexProto* pProto) {
const char* shorty = dexProtoGetShorty(pProto);
int count = 0;
}
}
-/*
- * Compare the two prototypes. The two prototypes are compared
- * with the return type as the major order, then the first arguments,
- * then second, etc. If two prototypes are identical except that one
- * has extra arguments, then the shorter argument is considered the
- * earlier one in sort order (similar to strcmp()).
- */
+/* (documented in header file) */
int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2) {
return protoCompare(pProto1, pProto2, true);
}
-/*
- * Compare the two prototypes. The two prototypes are compared
- * with the first argument as the major order, then second, etc. If two
- * prototypes are identical except that one has extra arguments, then the
- * shorter argument is considered the earlier one in sort order (similar
- * to strcmp()).
- */
+/* (documented in header file) */
int dexProtoCompareParameters(const DexProto* pProto1, const DexProto* pProto2){
return protoCompare(pProto1, pProto2, false);
}
}
/*
- * Compare a prototype and a string method descriptor. The comparison
- * is done as if the descriptor were converted to a prototype and compared
- * with dexProtoCompare().
+ * Common implementation for dexProtoCompareToDescriptor() and
+ * dexProtoCompareToParameterDescriptors(). The descriptor argument
+ * can be either a full method descriptor (with parens and a return
+ * type) or an unadorned concatenation of types (e.g. a list of
+ * argument types).
*/
-int dexProtoCompareToDescriptor(const DexProto* proto,
- const char* descriptor) {
- // First compare the return types.
-
- int result = strcmp(dexProtoGetReturnType(proto),
- methodDescriptorReturnType(descriptor));
-
- if (result != 0) {
- return result;
- }
-
- // The return types match, so we have to check arguments.
-
+static int protoCompareToParameterDescriptors(const DexProto* proto,
+ const char* descriptor, bool expectParens) {
+ char expectedEndChar = expectParens ? ')' : '\0';
DexParameterIterator iterator;
dexParameterIteratorInit(&iterator, proto);
- // Skip the '('.
- assert (*descriptor == '(');
- descriptor++;
+ if (expectParens) {
+ // Skip the '('.
+ assert (*descriptor == '(');
+ descriptor++;
+ }
for (;;) {
const char* protoDesc = dexParameterIteratorNextDescriptor(&iterator);
- if (*descriptor == ')') {
+ if (*descriptor == expectedEndChar) {
// It's the end of the descriptor string.
if (protoDesc == NULL) {
// It's also the end of the prototype's arguments.
// Both prototype and descriptor have arguments. Compare them.
const char* nextDesc = methodDescriptorNextType(descriptor);
+ assert(nextDesc != NULL);
for (;;) {
char c1 = *(protoDesc++);
}
}
+/* (documented in header file) */
+int dexProtoCompareToDescriptor(const DexProto* proto,
+ const char* descriptor) {
+ // First compare the return types.
+
+ const char *returnType = methodDescriptorReturnType(descriptor);
+ assert(returnType != NULL);
+
+ int result = strcmp(dexProtoGetReturnType(proto), returnType);
+
+ if (result != 0) {
+ return result;
+ }
+
+ // The return types match, so we have to check arguments.
+ return protoCompareToParameterDescriptors(proto, descriptor, true);
+}
+
+/* (documented in header file) */
+int dexProtoCompareToParameterDescriptors(const DexProto* proto,
+ const char* descriptors) {
+ return protoCompareToParameterDescriptors(proto, descriptors, false);
+}
+
+
+
+
+
/*
* ===========================================================================
} DexStringCache;
/*
+ * Make sure that the given cache can hold a string of the given length,
+ * including the final '\0' byte.
+ */
+void dexStringCacheAlloc(DexStringCache* pCache, size_t length);
+
+/*
* Initialize the given DexStringCache. Use this function before passing
* one into any other function.
*/
int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2);
/*
- * Compare the two prototypes. The two prototypes are compared
- * with the first argument as the major order, then second, etc. If two
- * prototypes are identical except that one has extra arguments, then the
- * shorter argument is considered the earlier one in sort order (similar
- * to strcmp()).
+ * Compare the two prototypes, ignoring return type. The two
+ * prototypes are compared with the first argument as the major order,
+ * then second, etc. If two prototypes are identical except that one
+ * has extra arguments, then the shorter argument is considered the
+ * earlier one in sort order (similar to strcmp()).
*/
-int dexProtoCompareParameters(const DexProto* pProto1, const DexProto* pProto2);
+int dexProtoCompareParameters(const DexProto* pProto1,
+ const DexProto* pProto2);
/*
* Compare a prototype and a string method descriptor. The comparison
int dexProtoCompareToDescriptor(const DexProto* proto, const char* descriptor);
/*
+ * Compare a prototype and a concatenation of type descriptors. The
+ * comparison is done as if the descriptors were converted to a
+ * prototype and compared with dexProtoCompareParameters().
+ */
+int dexProtoCompareToParameterDescriptors(const DexProto* proto,
+ const char* descriptors);
+
+/*
* Single-thread prototype parameter iterator. This structure holds a
* pointer to a prototype and its parts, along with a cursor.
*/
#include <JNIHelp.h> // TEMP_FAILURE_RETRY may or may not be in unistd
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
/*
* Zip file constants.
memset(pArchive, 0, sizeof(ZipArchive));
- fd = open(fileName, O_RDONLY, 0);
+ fd = open(fileName, O_RDONLY | O_BINARY, 0);
if (fd < 0) {
err = errno ? errno : -1;
LOGV("Unable to open '%s': %s\n", fileName, strerror(err));
#include "JNIHelp.h"
#include "utils/Log.h"
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value) {
(*env)->SetIntField(env, fileDescriptor, gCachedFields.descriptorField, value);
}
+
+/*
+ * DO NOT USE THIS FUNCTION
+ *
+ * Get a pointer to the elements of a non-movable array.
+ *
+ * The semantics are similar to GetDirectBufferAddress. Specifically, the VM
+ * guarantees that the array will not move, and the caller must ensure that
+ * it does not continue to use the pointer after the object is collected.
+ *
+ * We currently use an illegal sequence that trips up CheckJNI when
+ * the "forcecopy" mode is enabled. We pass in a magic value to work
+ * around the problem.
+ *
+ * Returns NULL if the array is movable.
+ */
+jbyte* jniGetNonMovableArrayElements(JNIEnv* env, jarray arrayObj)
+{
+#define kNoCopyMagic 0xd5aab57f /* also in CheckJni.c */
+
+ /*
+ * Normally the "isCopy" parameter is for a return value only, so the
+ * non-CheckJNI VM will ignore whatever we pass in.
+ */
+ uint32_t noCopy = kNoCopyMagic;
+ jbyte *addr = (*env)->GetByteArrayElements(env, arrayObj,
+ (jboolean*)&noCopy);
+
+ /*
+ * The non-CheckJNI implementation only cares about the array object,
+ * so we can replace the element pointer with the magic value.
+ */
+ (*env)->ReleaseByteArrayElements(env, arrayObj, (jbyte*) kNoCopyMagic, 0);
+ return addr;
+}
* For C++ code, we provide inlines that map to the C functions. g++ always
* inlines these, even on non-optimized builds.
*/
-#if defined(__cplusplus) && !defined(JNI_FORCE_C)
+#if defined(__cplusplus)
inline int jniRegisterNativeMethods(JNIEnv* env, const char* className,
const JNINativeMethod* gMethods, int numMethods)
{
object -> string
object -> string (modified)
caught ArrayStoreException (expected)
+copy: 0,0,0: [0, 1, 2, 3, 4, 5, 6, 7]
+copy: 0,0,8: [0, 1, 2, 3, 4, 5, 6, 7]
+copy: 0,2,4: [0, 1, 0, 1, 2, 3, 6, 7]
+copy: 2,0,4: [2, 3, 4, 5, 4, 5, 6, 7]
+copy: 1,3,4: [0, 1, 2, 1, 2, 3, 4, 7]
+copy: 3,1,4: [0, 3, 4, 5, 6, 5, 6, 7]
+copy: 3,1,5: [0, 3, 4, 5, 6, 7, 6, 7]
+copy: 1,3,5: [0, 1, 2, 1, 2, 3, 4, 5]
+copy: 0,3,5: [0, 1, 2, 0, 1, 2, 3, 4]
+copy: 3,0,5: [3, 4, 5, 6, 7, 5, 6, 7]
+copy: 0,5,1: [0, 1, 2, 3, 4, 0, 6, 7]
* limitations under the License.
*/
+import java.util.Arrays;
+
/**
* System.arraycopy cases
*/
public class Main {
public static void main(String args[]) {
+ testObjectCopy();
+ testOverlappingMoves();
+ }
+
+ public static void testObjectCopy() {
String[] stringArray = new String[8];
Object[] objectArray = new Object[8];
System.out.println("caught ArrayStoreException (expected)");
}
}
+
+ static final int ARRAY_SIZE = 8;
+
+ static void initByteArray(byte[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = (byte) i;
+ }
+ }
+ static void initShortArray(short[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = (short) i;
+ }
+ }
+ static void initIntArray(int[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = (int) i;
+ }
+ }
+ static void initLongArray(long[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = (long) i;
+ }
+ }
+
+ /*
+ * Perform an array copy operation on primitive arrays with different
+ * element widths.
+ */
+ static void makeCopies(int srcPos, int dstPos, int length) {
+ byte[] byteArray = new byte[ARRAY_SIZE];
+ short[] shortArray = new short[ARRAY_SIZE];
+ int[] intArray = new int[ARRAY_SIZE];
+ long[] longArray = new long[ARRAY_SIZE];
+
+ initByteArray(byteArray);
+ initShortArray(shortArray);
+ initIntArray(intArray);
+ initLongArray(longArray);
+
+ System.arraycopy(byteArray, srcPos, byteArray, dstPos, length);
+ System.arraycopy(shortArray, srcPos, shortArray, dstPos, length);
+ System.arraycopy(intArray, srcPos, intArray, dstPos, length);
+ System.arraycopy(longArray, srcPos, longArray, dstPos, length);
+
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ if (intArray[i] != byteArray[i]) {
+ System.out.println("mismatch int vs byte at " + i + " : " +
+ Arrays.toString(byteArray));
+ break;
+ } else if (intArray[i] != shortArray[i]) {
+ System.out.println("mismatch int vs short at " + i + " : " +
+ Arrays.toString(shortArray));
+ break;
+ } else if (intArray[i] != longArray[i]) {
+ System.out.println("mismatch int vs long at " + i + " : " +
+ Arrays.toString(longArray));
+ break;
+ }
+ }
+
+ System.out.println("copy: " + srcPos + "," + dstPos + "," + length +
+ ": " + Arrays.toString(intArray));
+ }
+
+ public static void testOverlappingMoves() {
+ /* do nothing */
+ makeCopies(0, 0, 0);
+
+ /* do more nothing */
+ makeCopies(0, 0, ARRAY_SIZE);
+
+ /* copy forward, even alignment */
+ makeCopies(0, 2, 4);
+
+ /* copy backward, even alignment */
+ makeCopies(2, 0, 4);
+
+ /* copy forward, odd alignment */
+ makeCopies(1, 3, 4);
+
+ /* copy backward, odd alignment */
+ makeCopies(3, 1, 4);
+
+ /* copy backward, odd length */
+ makeCopies(3, 1, 5);
+
+ /* copy forward, odd length */
+ makeCopies(1, 3, 5);
+
+ /* copy forward, mixed alignment */
+ makeCopies(0, 3, 5);
+
+ /* copy backward, mixed alignment */
+ makeCopies(3, 0, 5);
+
+ /* copy forward, mixed alignment, trivial length */
+ makeCopies(0, 5, 1);
+ }
}
# Overwrite default settings
ifneq ($(TARGET_ARCH),x86)
-ifeq ($(TARGET_SIMULATOR),false)
+ifneq ($(TARGET_SIMULATOR),true)
LOCAL_PRELINK_MODULE := true
endif
endif
NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
+/*
+ * Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
+ * The code deliberately uses an invalid sequence of operations, so we
+ * need to pass it through unmodified. Review that code before making
+ * any changes here.
+ */
+#define kNoCopyMagic 0xd5aab57f
+
#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
_ctype##Array array, jboolean* isCopy) \
CHECK_ENTER(env, kFlag_Default); \
CHECK_ARRAY(env, array); \
_ctype* result; \
+ u4 noCopy = 0; \
+ if (((JNIEnvExt*)env)->forceDataCopy && isCopy != NULL) { \
+ /* capture this before the base call tramples on it */ \
+ noCopy = *(u4*) isCopy; \
+ } \
result = BASE_ENV(env)->Get##_jname##ArrayElements(env, \
array, isCopy); \
if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) { \
- result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
+ if (noCopy == kNoCopyMagic) { \
+ LOGV("FC: not copying %p %x\n", array, noCopy); \
+ } else { \
+ result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
+ } \
} \
CHECK_EXIT(env); \
return result; \
CHECK_NON_NULL(env, elems); \
CHECK_RELEASE_MODE(env, mode); \
if (((JNIEnvExt*)env)->forceDataCopy) { \
- elems = (_ctype*) releaseGuardedPACopy(env, array, elems, mode);\
+ if ((uintptr_t)elems == kNoCopyMagic) { \
+ LOGV("FC: not freeing %p\n", array); \
+ elems = NULL; /* base JNI call doesn't currently need */ \
+ } else { \
+ elems = (_ctype*) releaseGuardedPACopy(env, array, elems, \
+ mode); \
+ } \
} \
BASE_ENV(env)->Release##_jname##ArrayElements(env, \
array, elems, mode); \
*/
#define DALVIK_MAJOR_VERSION 1
#define DALVIK_MINOR_VERSION 5
-#define DALVIK_BUG_VERSION 0
+#define DALVIK_BUG_VERSION 1
/*
* VM build number. This must change whenever something that affects the
if (!dvmCheckOptHeaderAndDependencies(fd, false, 0, 0, true, true)) {
LOGE("%s odex has stale dependencies\n", fileName);
free(cachedName);
+ cachedName = NULL;
close(fd);
fd = -1;
goto tryArchive;
_ctype##Array jarr, _ctype* elems, jint mode) \
{ \
UNUSED_PARAMETER(elems); \
- JNI_ENTER(); \
if (mode != JNI_COMMIT) { \
+ JNI_ENTER(); \
ArrayObject* arrayObj = \
(ArrayObject*) dvmDecodeIndirectRef(env, jarr); \
unpinPrimitiveArray(arrayObj); \
+ JNI_EXIT(); \
} \
- JNI_EXIT(); \
}
static void throwArrayRegionOutOfBounds(ArrayObject* arrayObj, jsize start,
static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray jarr,
void* carray, jint mode)
{
- JNI_ENTER();
if (mode != JNI_COMMIT) {
+ JNI_ENTER();
ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
unpinPrimitiveArray(arrayObj);
+ JNI_EXIT();
}
- JNI_EXIT();
}
/*
*/
changeInterp = setjmp(jmpBuf) -1;
if (changeInterp >= 0) {
- Thread* threadSelf = dvmThreadSelf();
LOGVV("mterp threadid=%d returning %d\n",
- threadSelf->threadId, changeInterp);
+ dvmThreadSelf()->threadId, changeInterp);
return changeInterp;
}
u2 inst = /*glue->*/pc[0];
Handler handler = (Handler) gDvmMterpHandlers[inst & 0xff];
+ (void) gDvmMterpHandlerNames; /* avoid gcc "defined but not used" */
LOGVV("handler %p %s\n",
handler, (const char*) gDvmMterpHandlerNames[inst & 0xff]);
(*handler)(glue);
.LintMax:
.long 0x7FFFFFFF
+
.global dvmAsmInstructionStart
.type dvmAsmInstructionStart, %function
dvmAsmInstructionStart = .L_OP_NOP
*/
changeInterp = setjmp(jmpBuf) -1;
if (changeInterp >= 0) {
- Thread* threadSelf = dvmThreadSelf();
LOGVV("mterp threadid=%d returning %d\n",
- threadSelf->threadId, changeInterp);
+ dvmThreadSelf()->threadId, changeInterp);
return changeInterp;
}
u2 inst = /*glue->*/pc[0];
Handler handler = (Handler) gDvmMterpHandlers[inst & 0xff];
+ (void) gDvmMterpHandlerNames; /* avoid gcc "defined but not used" */
LOGVV("handler %p %s\n",
handler, (const char*) gDvmMterpHandlerNames[inst & 0xff]);
(*handler)(glue);
}
}
+
/*
* C mterp exit point. Call here to bail out of the interpreter.
*/
dvmThrowException("Ljava/io/IOException;",
"Re-opening BOOTCLASSPATH DEX files is not allowed");
free(sourceName);
+ free(outputName);
RETURN_VOID();
}
int fd = -1;
if (fileDescriptor != NULL) {
fd = getFileDescriptor(fileDescriptor);
- if (fd < 0)
+ if (fd < 0) {
+ free(fileName);
RETURN_VOID();
+ }
}
result = hprofDumpHeap(fileName, fd, false);
#endif
}
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
if ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0) {
/* To let a non-privileged gdbserver attach to this
* process, we must set its dumpable bit flag. However
}
/*
+ * static native Member getDeclaredConstructorOrMethod(
+ * Class clazz, String name, Class[] args);
+ */
+static void Dalvik_java_lang_Class_getDeclaredConstructorOrMethod(
+ const u4* args, JValue* pResult)
+{
+ ClassObject* clazz = (ClassObject*) args[0];
+ StringObject* nameObj = (StringObject*) args[1];
+ ArrayObject* methodArgs = (ArrayObject*) args[2];
+
+ Object* methodObj;
+
+ methodObj = dvmGetDeclaredConstructorOrMethod(clazz, nameObj, methodArgs);
+ dvmReleaseTrackedAlloc(methodObj, NULL);
+
+ RETURN_PTR(methodObj);
+}
+
+/*
* Class[] getInterfaces()
*/
static void Dalvik_java_lang_Class_getInterfaces(const u4* args,
Dalvik_java_lang_Class_getDeclaredFields },
{ "getDeclaredMethods", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;",
Dalvik_java_lang_Class_getDeclaredMethods },
+ { "getDeclaredConstructorOrMethod", "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;",
+ Dalvik_java_lang_Class_getDeclaredConstructorOrMethod },
{ "getInterfaces", "()[Ljava/lang/Class;",
Dalvik_java_lang_Class_getInterfaces },
{ "getModifiers", "(Ljava/lang/Class;Z)I",
*/
/*
- * java.lang.Class
+ * java.lang.Class native methods
*/
#include "Dalvik.h"
#include "native/InternalNativePriv.h"
/*
- * Call the appropriate copy function given the circumstances.
+ * The VM makes guarantees about the atomicity of accesses to primitive
+ * variables. These guarantees also apply to elements of arrays.
+ * In particular, 8-bit, 16-bit, and 32-bit accesses must be atomic and
+ * must not cause "word tearing". Accesses to 64-bit array elements must
+ * either be atomic or treated as two 32-bit operations. References are
+ * always read and written atomically, regardless of the number of bits
+ * used to represent them.
+ *
+ * We can't rely on standard libc functions like memcpy() and memmove()
+ * in our implementation of System.arraycopy(), because they may copy
+ * byte-by-byte (either for the full run or for "unaligned" parts at the
+ * start or end). We need to use functions that guarantee 16-bit or 32-bit
+ * atomicity as appropriate.
+ *
+ * System.arraycopy() is heavily used, so having an efficient implementation
+ * is important. The bionic libc provides a platform-optimized memory move
+ * function that should be used when possible. If it's not available,
+ * the trivial "reference implementation" versions below can be used until
+ * a proper version can be written.
+ *
+ * For these functions, The caller must guarantee that dest/src are aligned
+ * appropriately for the element type, and that n is a multiple of the
+ * element size.
*/
-static void copy(void *dest, const void *src, size_t n, bool sameArray,
- size_t elemSize)
+#ifdef __BIONIC__
+/* always present in bionic libc */
+#define HAVE_MEMMOVE_WORDS
+#endif
+
+#ifdef HAVE_MEMMOVE_WORDS
+extern void _memmove_words(void* dest, const void* src, size_t n);
+#define move16 _memmove_words
+#define move32 _memmove_words
+#else
+static void move16(void* dest, const void* src, size_t n)
{
- if (sameArray) {
- /* Might overlap. */
- if (elemSize == sizeof(Object*)) {
- /*
- * In addition to handling overlap properly, bcopy()
- * guarantees atomic treatment of words. This is needed so
- * that concurrent threads never see half-formed pointers
- * or ints. The former is required for proper gc behavior,
- * and the latter is also required for proper high-level
- * language support.
- *
- * Note: bcopy()'s argument order is different than memcpy().
- */
- bcopy(src, dest, n);
- } else {
- memmove(dest, src, n);
+ assert((((uintptr_t) dest | (uintptr_t) src | n) & 0x01) == 0);
+
+ uint16_t* d = (uint16_t*) dest;
+ const uint16_t* s = (uint16_t*) src;
+
+ n /= sizeof(uint16_t);
+
+ if (d < s) {
+ /* copy forward */
+ while (n--) {
+ *d++ = *s++;
}
} else {
- memcpy(dest, src, n); /* Can't overlap; use faster function. */
+ /* copy backward */
+ d += n;
+ s += n;
+ while (n--) {
+ *--d = *--s;
+ }
}
}
+static void move32(void* dest, const void* src, size_t n)
+{
+ assert((((uintptr_t) dest | (uintptr_t) src | n) & 0x03) == 0);
+
+ uint32_t* d = (uint32_t*) dest;
+ const uint32_t* s = (uint32_t*) src;
+
+ n /= sizeof(uint32_t);
+
+ if (d < s) {
+ /* copy forward */
+ while (n--) {
+ *d++ = *s++;
+ }
+ } else {
+ /* copy backward */
+ d += n;
+ s += n;
+ while (n--) {
+ *--d = *--s;
+ }
+ }
+}
+#endif /*HAVE_MEMMOVE_WORDS*/
+
/*
* public static void arraycopy(Object src, int srcPos, Object dest,
* int destPos, int length)
int srcPos, dstPos, length;
char srcType, dstType;
bool srcPrim, dstPrim;
- bool sameArray;
srcArray = (ArrayObject*) args[0];
srcPos = args[1];
dstPos = args[3];
length = args[4];
- sameArray = (srcArray == dstArray);
-
/* check for null or bad pointer */
if (!dvmValidateObject((Object*)srcArray) ||
!dvmValidateObject((Object*)dstArray))
assert(dvmCheckException(dvmThreadSelf()));
RETURN_VOID();
}
+
/* make sure it's an array */
if (!dvmIsArray(srcArray) || !dvmIsArray(dstArray)) {
dvmThrowExceptionFmt("Ljava/lang/ArrayStoreException;",
RETURN_VOID();
}
- // avoid int overflow
+ /* avoid int overflow */
if (srcPos < 0 || dstPos < 0 || length < 0 ||
srcPos > (int) srcArray->length - length ||
dstPos > (int) dstArray->length - length)
srcPrim = (srcType != '[' && srcType != 'L');
dstPrim = (dstType != '[' && dstType != 'L');
if (srcPrim || dstPrim) {
- int width;
-
if (srcPrim != dstPrim || srcType != dstType) {
dvmThrowExceptionFmt("Ljava/lang/ArrayStoreException;",
"source and destination arrays are incompatible: %s and %s",
RETURN_VOID();
}
- switch (srcClass->descriptor[1]) {
+ if (false) LOGD("arraycopy prim[%c] dst=%p %d src=%p %d len=%d\n",
+ srcType, dstArray->contents, dstPos,
+ srcArray->contents, srcPos, length);
+
+ switch (srcType) {
case 'B':
case 'Z':
- width = 1;
+ /* 1 byte per element */
+ memmove((u1*) dstArray->contents + dstPos,
+ (const u1*) srcArray->contents + srcPos,
+ length);
break;
case 'C':
case 'S':
- width = 2;
+ /* 2 bytes per element */
+ move16((u1*) dstArray->contents + dstPos * 2,
+ (const u1*) srcArray->contents + srcPos * 2,
+ length * 2);
break;
case 'F':
case 'I':
- width = 4;
+ /* 4 bytes per element */
+ move32((u1*) dstArray->contents + dstPos * 4,
+ (const u1*) srcArray->contents + srcPos * 4,
+ length * 4);
break;
case 'D':
case 'J':
- width = 8;
+ /*
+ * 8 bytes per element. We don't need to guarantee atomicity
+ * of the entire 64-bit word, so we can use the 32-bit copier.
+ */
+ move32((u1*) dstArray->contents + dstPos * 8,
+ (const u1*) srcArray->contents + srcPos * 8,
+ length * 8);
break;
- default: /* 'V' or something weird */
+ default: /* illegal array type */
LOGE("Weird array type '%s'\n", srcClass->descriptor);
- assert(false);
- width = 0;
- break;
+ dvmAbort();
}
-
- if (false) LOGVV("arraycopy prim dst=%p %d src=%p %d len=%d\n",
- dstArray->contents, dstPos * width,
- srcArray->contents, srcPos * width,
- length * width);
- copy((u1*)dstArray->contents + dstPos * width,
- (const u1*)srcArray->contents + srcPos * width,
- length * width,
- sameArray, width);
} else {
/*
* Neither class is primitive. See if elements in "src" are instances
* of elements in "dst" (e.g. copy String to String or String to
* Object).
*/
- int width = sizeof(Object*);
+ const int width = sizeof(Object*);
if (srcClass->arrayDim == dstClass->arrayDim &&
dvmInstanceof(srcClass, dstClass))
/*
* "dst" can hold "src"; copy the whole thing.
*/
- if (false) LOGVV("arraycopy ref dst=%p %d src=%p %d len=%d\n",
+ if (false) LOGD("arraycopy ref dst=%p %d src=%p %d len=%d\n",
dstArray->contents, dstPos * width,
srcArray->contents, srcPos * width,
length * width);
- copy((u1*)dstArray->contents + dstPos * width,
- (const u1*)srcArray->contents + srcPos * width,
- length * width,
- sameArray, width);
+ move32((u1*)dstArray->contents + dstPos * width,
+ (const u1*)srcArray->contents + srcPos * width,
+ length * width);
dvmWriteBarrierArray(dstArray, dstPos, dstPos+length);
} else {
/*
- * The arrays are not fundamentally compatible. However, we may
- * still be able to do this if the destination object is compatible
- * (e.g. copy Object to String, but the Object being copied is
- * actually a String). We need to copy elements one by one until
- * something goes wrong.
+ * The arrays are not fundamentally compatible. However, we
+ * may still be able to do this if the destination object is
+ * compatible (e.g. copy Object[] to String[], but the Object
+ * being copied is actually a String). We need to copy elements
+ * one by one until something goes wrong.
*
- * Because of overlapping moves, what we really want to do is
- * compare the types and count up how many we can move, then call
- * memmove() to shift the actual data. If we just start from the
- * front we could do a smear rather than a move.
+ * Because of overlapping moves, what we really want to do
+ * is compare the types and count up how many we can move,
+ * then call move32() to shift the actual data. If we just
+ * start from the front we could do a smear rather than a move.
*/
Object** srcObj;
Object** dstObj;
}
}
- if (false) LOGVV("arraycopy iref dst=%p %d src=%p %d count=%d of %d\n",
+ if (false) LOGD("arraycopy iref dst=%p %d src=%p %d count=%d of %d\n",
dstArray->contents, dstPos * width,
srcArray->contents, srcPos * width,
copyCount, length);
- copy((u1*)dstArray->contents + dstPos * width,
- (const u1*)srcArray->contents + srcPos * width,
- copyCount * width,
- sameArray, width);
+ move32((u1*)dstArray->contents + dstPos * width,
+ (const u1*)srcArray->contents + srcPos * width,
+ copyCount * width);
dvmWriteBarrierArray(dstArray, 0, copyCount);
if (copyCount != length) {
dvmThrowExceptionFmt("Ljava/lang/ArrayStoreException;",
INLINE bool dvmIsAbstractMethod(const Method* method) {
return (method->accessFlags & ACC_ABSTRACT) != 0;
}
+INLINE bool dvmIsSyntheticMethod(const Method* method) {
+ return (method->accessFlags & ACC_SYNTHETIC) != 0;
+}
INLINE bool dvmIsMirandaMethod(const Method* method) {
return (method->accessFlags & ACC_MIRANDA) != 0;
}
}
/*
+ * Fills targetDescriptorCache with the descriptors of the classes in args.
+ * This is the concatenation of the descriptors with no other adornment,
+ * consistent with dexProtoGetParameterDescriptors.
+ */
+static void createTargetDescriptor(ArrayObject* args,
+ DexStringCache* targetDescriptorCache)
+{
+ size_t i;
+ ClassObject** argsArray = NULL;
+ size_t length;
+ char* at;
+ const char* descriptor;
+
+ argsArray = (ClassObject**) args->contents;
+
+ length = 1; /* +1 for the terminating '\0' */
+ for (i = 0; i < args->length; ++i) {
+ length += strlen(argsArray[i]->descriptor);
+ }
+
+ dexStringCacheAlloc(targetDescriptorCache, length);
+
+ at = (char*) targetDescriptorCache->value;
+ for (i = 0; i < args->length; ++i) {
+ descriptor = argsArray[i]->descriptor;
+ strcpy(at, descriptor);
+ at += strlen(descriptor);
+ }
+}
+
+static Object* findConstructorOrMethodInArray(int methodsCount, Method* methods,
+ const char* name, const char* parameterDescriptors)
+{
+ Method* method = NULL;
+ Method* result = NULL;
+ int i;
+
+ for (i = 0; i < methodsCount; ++i) {
+ method = &methods[i];
+ if (strcmp(name, method->name) != 0
+ || dvmIsMirandaMethod(method)
+ || dexProtoCompareToParameterDescriptors(&method->prototype,
+ parameterDescriptors) != 0) {
+ continue;
+ }
+
+ result = method;
+
+ /*
+ * Covariant return types permit the class to define multiple
+ * methods with the same name and parameter types. Prefer to return
+ * a non-synthetic method in such situations. We may still return
+ * a synthetic method to handle situations like escalated visibility.
+ */
+ if (!dvmIsSyntheticMethod(method)) {
+ break;
+ }
+ }
+
+ if (result != NULL) {
+ return dvmCreateReflectObjForMethod(result->clazz, result);
+ }
+
+ return NULL;
+}
+
+/*
+ * Get the named method.
+ */
+Object* dvmGetDeclaredConstructorOrMethod(ClassObject* clazz,
+ StringObject* nameObj, ArrayObject* args)
+{
+ Object* result = NULL;
+ DexStringCache targetDescriptorCache;
+ char* name;
+ const char* targetDescriptor;
+
+ dexStringCacheInit(&targetDescriptorCache);
+
+ name = dvmCreateCstrFromString(nameObj);
+ createTargetDescriptor(args, &targetDescriptorCache);
+ targetDescriptor = targetDescriptorCache.value;
+
+ result = findConstructorOrMethodInArray(clazz->directMethodCount,
+ clazz->directMethods, name, targetDescriptor);
+ if (result == NULL) {
+ result = findConstructorOrMethodInArray(clazz->virtualMethodCount,
+ clazz->virtualMethods, name, targetDescriptor);
+ }
+
+ free(name);
+ dexStringCacheRelease(&targetDescriptorCache);
+ return result;
+}
+
+/*
* Get all interfaces a class implements. If this is unable to allocate
* the result array, this raises an OutOfMemoryError and returns NULL.
*/
ArrayObject* dvmGetDeclaredMethods(ClassObject* clazz, bool publicOnly);
/*
+ * Get the named method.
+ */
+Object* dvmGetDeclaredConstructorOrMethod(ClassObject* clazz,
+ StringObject* nameObj, ArrayObject* args);
+
+/*
* Get all interfaces a class implements. If this is unable to allocate
* the result array, this raises an OutOfMemoryError and returns NULL.
*/