Adding oat_process
- Added oat_process, a version of app_process use to launch frameworks apps
- Added liboat_runtime, a version of libandroid_runtime that uses art instead of dvm
This is just a special makefile, frameworks/base/core/jni code is used for source
- Added support for build a boot.oat with the full BOOTCLASSPATH
The older smaller boat.oat is now core.oat
- Added mem_map code for making sure a requested memory region is available
Moved mem_map code to cc file to make easier to debug with smaller rebuild
- Moved oat base address to 0x6000000 as a work around to host addres conflict
- Added -Xms and -Xmx options to dex2oat to allow build specific memory options
- Fixed miranda method initialization problem found compiling full bootclasspath
- Made compiler.cc tolerant of verification errors found compiling full bootclasspath
- Bumped arena block alloc warning to avoid noise when compiling full bootclasspath
- Marked implicit GC unimplemented to fail fast
- Added --output argument to oatdump
- Made many object asserts tolerate access in IsErroneous state
now that verifier is failing validation of some classes during compilation
- Made runtime tolerate unknown access as short term solution for oat_process
- Workaround SSA issue to restore full bootclasspath compilation
- Added test-art-target-processs to excercise oat_process with "am"
"am" found bug where class_linker was using Method::GetClass and not ::GetDeclaringClass
Change-Id: I1a645a142b163e06bab9e72eb094ae1f1dbfbd97
diff --git a/Android.mk b/Android.mk
index a7d41d7..49e0706 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,7 +15,6 @@
#
LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
# These can be overridden via the environment or by editing to
# enable/disable certain build configuration.
@@ -95,11 +94,34 @@
.PHONY: test-art-target-oat
test-art-target-oat: $(ART_TEST_OAT_TARGETS)
+# $(1): name
+define build-art-framework-oat
+ $(call build-art-oat,$(1),$(TARGET_BOOT_OAT),$(TARGET_BOOT_DEX))
+endef
+
+$(eval $(call build-art-framework-oat,am))
+
+.PHONY: test-art-target-oat-process
+test-art-target-oat-process: $(TARGET_OUT_JAVA_LIBRARIES)/am.oat
+ adb remount
+ adb sync
+ adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_process -Xbootimage:/system/framework/boot.oat -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am && touch /sdcard/test-art-target-process"
+ $(hide) (adb pull /sdcard/test-art-target-process /tmp/ && echo test-art-target-process PASSED) || echo test-art-target-process FAILED
+ $(hide) rm /tmp/test-art-target-process
+
+.PHONY: dump-core-oat
+dump-core-oat: $(TARGET_CORE_OAT) $(OATDUMP)
+ $(OATDUMP) $(addprefix --dex-file=,$(TARGET_CORE_DEX)) --image=$(TARGET_CORE_OAT) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/core.oatdump.txt
+ @echo Output in /tmp/core.oatdump.txt
+
.PHONY: dump-boot-oat
dump-boot-oat: $(TARGET_BOOT_OAT) $(OATDUMP)
- $(OATDUMP) $(addprefix --dex-file=,$(TARGET_BOOT_DEX)) --image=$(TARGET_BOOT_OAT) --strip-prefix=$(PRODUCT_OUT)
+ $(OATDUMP) $(addprefix --dex-file=,$(TARGET_BOOT_DEX)) --image=$(TARGET_BOOT_OAT) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt
+ @echo Output in /tmp/boot.oatdump.txt
# "mm cpplint-art" to style check art source files
.PHONY: cpplint-art
cpplint-art:
$(LOCAL_PATH)/tools/cpplint.py $(LOCAL_PATH)/src/*.h $(LOCAL_PATH)/src/*.cc
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 6cdd203..a77d5a8 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -122,6 +122,7 @@
src/mark_sweep.cc \
src/managed_register_arm.cc \
src/managed_register_x86.cc \
+ src/mem_map.cc \
src/memory_region.cc \
src/monitor.cc \
src/mspace.c \
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index e027911..2ea132d 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -25,26 +25,37 @@
OATDUMP := $(OATDUMPD)
# start of oat reserved address space
-OAT_HOST_BASE_ADDRESS := 0x50000000
-OAT_TARGET_BASE_ADDRESS := 0x50000000
+OAT_HOST_BASE_ADDRESS := 0x60000000
+OAT_TARGET_BASE_ADDRESS := 0x60000000
-HOST_BOOT_OAT := $(HOST_OUT_JAVA_LIBRARIES)/boot.oat
-TARGET_BOOT_OAT := $(TARGET_OUT_JAVA_LIBRARIES)/boot.oat
+########################################################################
+# A smaller libcore only oat file
+HOST_CORE_JARS := core-hostdex
+TARGET_CORE_JARS := core
-# TODO: just use libcore for now, not full bootclasspath.
-# eventually need to replace with full list based on DEXPREOPT_BOOT_JARS.
-HOST_BOOT_JARS := core-hostdex
-TARGET_BOOT_JARS := core
+HOST_CORE_DEX := $(foreach jar,$(HOST_CORE_JARS), $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
+TARGET_CORE_DEX := $(foreach jar,$(TARGET_CORE_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
-HOST_BOOT_DEX := $(foreach jar,$(HOST_BOOT_JARS), $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
-TARGET_BOOT_DEX := $(foreach jar,$(TARGET_BOOT_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
+HOST_CORE_OAT := $(HOST_OUT_JAVA_LIBRARIES)/core.oat
+TARGET_CORE_OAT := $(TARGET_OUT_JAVA_LIBRARIES)/core.oat
# TODO: change DEX2OATD to order-only prerequisite when output is stable
-$(HOST_BOOT_OAT): $(HOST_BOOT_DEX) $(DEX2OAT)
+$(HOST_CORE_OAT): $(HOST_CORE_DEX) $(DEX2OAT)
@echo "host dex2oat: $@ ($<)"
- $(hide) $(DEX2OAT) $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --image=$@ --base=$(OAT_HOST_BASE_ADDRESS)
+ $(hide) $(DEX2OAT) -Xms16m -Xmx16m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --image=$@ --base=$(OAT_HOST_BASE_ADDRESS)
+
+# TODO: change DEX2OATD to order-only prerequisite when output is stable
+$(TARGET_CORE_OAT): $(TARGET_CORE_DEX) $(DEX2OAT)
+ @echo "target dex2oat: $@ ($<)"
+ $(hide) $(DEX2OAT) -Xms32m -Xmx32m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --image=$@ --base=$(OAT_TARGET_BASE_ADDRESS) --strip-prefix=$(PRODUCT_OUT)
+
+########################################################################
+# The full system boot classpath
+TARGET_BOOT_JARS := $(subst :, ,$(DEXPREOPT_BOOT_JARS))
+TARGET_BOOT_DEX := $(foreach jar,$(TARGET_BOOT_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
+TARGET_BOOT_OAT := $(TARGET_OUT_JAVA_LIBRARIES)/boot.oat
# TODO: change DEX2OATD to order-only prerequisite when output is stable
$(TARGET_BOOT_OAT): $(TARGET_BOOT_DEX) $(DEX2OAT)
@echo "target dex2oat: $@ ($<)"
- $(hide) $(DEX2OAT) $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --image=$@ --base=$(OAT_TARGET_BASE_ADDRESS) --strip-prefix=$(PRODUCT_OUT)
+ $(hide) $(DEX2OAT) -Xms256m -Xmx256m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --image=$@ --base=$(OAT_TARGET_BASE_ADDRESS) --strip-prefix=$(PRODUCT_OUT)
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index 0b8cfa9..4605583 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -33,16 +33,23 @@
########################################################################
+# $(1): module
+# $(2): boot oat
+# $(3): boot dex files
+define build-art-oat
+# TODO: change DEX2OATD to order-only prerequisite when output is stable
+$(TARGET_OUT_JAVA_LIBRARIES)/$(1).oat: $(TARGET_OUT_JAVA_LIBRARIES)/$(1).jar $(2) $(DEX2OAT)
+ @echo "target dex2oat: $$@ ($$<)"
+ $(hide) $(DEX2OAT) -Xms16m -Xmx16m $(addprefix --boot-dex-file=,$(3)) --boot=$(2) $(addprefix --dex-file=,$$<) --image=$$@ --strip-prefix=$(PRODUCT_OUT)
+endef
+
+########################################################################
ART_TEST_OAT_FILES :=
# $(1): directory
define build-art-test-oat
-# TODO: change DEX2OATD to order-only prerequisite when output is stable
-$(TARGET_OUT_JAVA_LIBRARIES)/art-test-dex-$(1).oat: $(TARGET_OUT_JAVA_LIBRARIES)/art-test-dex-$(1).jar $(TARGET_BOOT_OAT) $(DEX2OAT)
- @echo "target dex2oat: $$@ ($$<)"
- $(hide) $(DEX2OAT) $(addprefix --boot-dex-file=,$(TARGET_BOOT_DEX)) --boot=$(TARGET_BOOT_OAT) $(addprefix --dex-file=,$$<) --image=$$@ --strip-prefix=$(PRODUCT_OUT)
-
-ART_TEST_OAT_FILES += $(TARGET_OUT_JAVA_LIBRARIES)/art-test-dex-$(1).oat
+ $(call build-art-oat,art-test-dex-$(1),$(TARGET_CORE_OAT),$(TARGET_CORE_DEX))
+ ART_TEST_OAT_FILES += $(TARGET_OUT_JAVA_LIBRARIES)/art-test-dex-$(1).oat
endef
$(foreach dir,$(TEST_DEX_DIRECTORIES), $(eval $(call build-art-test-oat,$(dir))))
@@ -57,7 +64,7 @@
test-art-target-oat-$(1): test-art-target-sync
adb shell touch /sdcard/test-art-target-oat-$(1)
adb shell rm /sdcard/test-art-target-oat-$(1)
- adb shell sh -c "oatexecd -Xbootclasspath:/system/framework/core.jar -Xbootimage:/system/framework/boot.oat -classpath /system/framework/art-test-dex-$(1).jar -Ximage:/system/framework/art-test-dex-$(1).oat $(1) $(2) && touch /sdcard/test-art-target-oat-$(1)"
+ adb shell sh -c "oatexecd -Xbootclasspath:/system/framework/core.jar -Xbootimage:/system/framework/core.oat -classpath /system/framework/art-test-dex-$(1).jar -Ximage:/system/framework/art-test-dex-$(1).oat $(1) $(2) && touch /sdcard/test-art-target-oat-$(1)"
$(hide) (adb pull /sdcard/test-art-target-oat-$(1) /tmp/ && echo test-art-target-oat-$(1) PASSED) || (echo test-art-target-oat-$(1) FAILED && exit 1)
$(hide) rm /tmp/test-art-target-oat-$(1)
diff --git a/oat_process/Android.mk b/oat_process/Android.mk
new file mode 100644
index 0000000..9fb9401
--- /dev/null
+++ b/oat_process/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+
+local_src_files:= \
+ app_main.cpp
+
+local_shared_libraries := \
+ libcutils \
+ libutils \
+ libbinder
+
+include $(CLEAR_VARS)
+LOCAL_MODULE:= oat_process
+LOCAL_MODULE_TAGS:= optional
+LOCAL_SRC_FILES:= $(local_src_files)
+LOCAL_SHARED_LIBRARIES := liboat_runtimed $(local_shared_libraries)
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS:= optional
+LOCAL_MODULE:= oat_processd
+LOCAL_SRC_FILES:= $(local_src_files)
+LOCAL_SHARED_LIBRARIES := liboat_runtimed $(local_shared_libraries)
+include $(BUILD_EXECUTABLE)
diff --git a/oat_process/MODULE_LICENSE_APACHE2 b/oat_process/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/oat_process/MODULE_LICENSE_APACHE2
diff --git a/oat_process/NOTICE b/oat_process/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/oat_process/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/oat_process/app_main.cpp b/oat_process/app_main.cpp
new file mode 100644
index 0000000..bf827a8
--- /dev/null
+++ b/oat_process/app_main.cpp
@@ -0,0 +1,204 @@
+/*
+ * Main entry of app process.
+ *
+ * Starts the interpreted runtime, then starts up the application.
+ *
+ */
+
+#define LOG_TAG "appproc"
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <utils/Log.h>
+#include <cutils/process_name.h>
+#include <cutils/memory.h>
+#include <android_runtime/AndroidRuntime.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+namespace android {
+
+void app_usage()
+{
+ fprintf(stderr,
+ "Usage: oat_process [java-options] cmd-dir start-class-name [options]\n");
+}
+
+class AppRuntime : public AndroidRuntime
+{
+public:
+ AppRuntime()
+ : mParentDir(NULL)
+ , mClassName(NULL)
+ , mClass(NULL)
+ , mArgC(0)
+ , mArgV(NULL)
+ {
+ }
+
+#if 0
+ // this appears to be unused
+ const char* getParentDir() const
+ {
+ return mParentDir;
+ }
+#endif
+
+ const char* getClassName() const
+ {
+ return mClassName;
+ }
+
+ virtual void onVmCreated(JNIEnv* env)
+ {
+ if (mClassName == NULL) {
+ return; // Zygote. Nothing to do here.
+ }
+
+ /*
+ * This is a little awkward because the JNI FindClass call uses the
+ * class loader associated with the native method we're executing in.
+ * If called in onStarted (from RuntimeInit.finishInit because we're
+ * launching "am", for example), FindClass would see that we're calling
+ * from a boot class' native method, and so wouldn't look for the class
+ * we're trying to look up in CLASSPATH. Unfortunately it needs to,
+ * because the "am" classes are not boot classes.
+ *
+ * The easiest fix is to call FindClass here, early on before we start
+ * executing boot class Java code and thereby deny ourselves access to
+ * non-boot classes.
+ */
+ char* slashClassName = toSlashClassName(mClassName);
+ mClass = env->FindClass(slashClassName);
+ if (mClass == NULL) {
+ LOGE("ERROR: could not find class '%s'\n", mClassName);
+ }
+ free(slashClassName);
+
+ mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
+ }
+
+ virtual void onStarted()
+ {
+ sp<ProcessState> proc = ProcessState::self();
+ LOGV("App process: starting thread pool.\n");
+ proc->startThreadPool();
+
+ AndroidRuntime* ar = AndroidRuntime::getRuntime();
+ ar->callMain(mClassName, mClass, mArgC, mArgV);
+
+ IPCThreadState::self()->stopProcess();
+ }
+
+ virtual void onZygoteInit()
+ {
+ sp<ProcessState> proc = ProcessState::self();
+ LOGV("App process: starting thread pool.\n");
+ proc->startThreadPool();
+ }
+
+ virtual void onExit(int code)
+ {
+ if (mClassName == NULL) {
+ // if zygote
+ IPCThreadState::self()->stopProcess();
+ }
+
+ AndroidRuntime::onExit(code);
+ }
+
+
+ const char* mParentDir;
+ const char* mClassName;
+ jclass mClass;
+ int mArgC;
+ const char* const* mArgV;
+};
+
+}
+
+using namespace android;
+
+/*
+ * sets argv0 to as much of newArgv0 as will fit
+ */
+static void setArgv0(const char *argv0, const char *newArgv0)
+{
+ strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
+}
+
+int main(int argc, const char* const argv[])
+{
+ // These are global variables in ProcessState.cpp
+ mArgC = argc;
+ mArgV = argv;
+
+ mArgLen = 0;
+ for (int i=0; i<argc; i++) {
+ mArgLen += strlen(argv[i]) + 1;
+ }
+ mArgLen--;
+
+ AppRuntime runtime;
+ const char* argv0 = argv[0];
+
+ // Process command line arguments
+ // ignore argv[0]
+ argc--;
+ argv++;
+
+ // Everything up to '--' or first non '-' arg goes to the vm
+
+ int i = runtime.addVmArguments(argc, argv);
+
+ // Parse runtime arguments. Stop at first unrecognized option.
+ bool zygote = false;
+ bool startSystemServer = false;
+ bool application = false;
+ const char* parentDir = NULL;
+ const char* niceName = NULL;
+ const char* className = NULL;
+ while (i < argc) {
+ const char* arg = argv[i++];
+ if (!parentDir) {
+ parentDir = arg;
+ } else if (strcmp(arg, "--zygote") == 0) {
+ zygote = true;
+ niceName = "zygote";
+ } else if (strcmp(arg, "--start-system-server") == 0) {
+ startSystemServer = true;
+ } else if (strcmp(arg, "--application") == 0) {
+ application = true;
+ } else if (strncmp(arg, "--nice-name=", 12) == 0) {
+ niceName = arg + 12;
+ } else {
+ className = arg;
+ break;
+ }
+ }
+
+ if (niceName && *niceName) {
+ setArgv0(argv0, niceName);
+ set_process_name(niceName);
+ }
+
+ runtime.mParentDir = parentDir;
+
+ if (zygote) {
+ runtime.start("com.android.internal.os.ZygoteInit",
+ startSystemServer ? "start-system-server" : "");
+ } else if (className) {
+ // Remainder of args get passed to startup class main()
+ runtime.mClassName = className;
+ runtime.mArgC = argc - i;
+ runtime.mArgV = argv + i;
+ runtime.start("com.android.internal.os.RuntimeInit",
+ application ? "application" : "tool");
+ } else {
+ fprintf(stderr, "Error: no class name or --zygote supplied.\n");
+ app_usage();
+ LOG_ALWAYS_FATAL("oat_process: no class name or --zygote supplied.");
+ return 10;
+ }
+}
diff --git a/oat_runtime/Android.mk b/oat_runtime/Android.mk
new file mode 100644
index 0000000..4d5416a
--- /dev/null
+++ b/oat_runtime/Android.mk
@@ -0,0 +1,256 @@
+LOCAL_PATH:= $(call my-dir)/../../frameworks/base/core/jni
+
+local_cflags += -DHAVE_CONFIG_H -DKHTML_NO_EXCEPTIONS -DGKWQ_NO_JAVA
+local_cflags += -DNO_SUPPORT_JS_BINDING -DQT_NO_WHEELEVENT -DKHTML_NO_XBL
+local_cflags += -U__APPLE__
+
+ifeq ($(TARGET_ARCH), arm)
+ local_cflags += -DPACKED="__attribute__ ((packed))"
+else
+ local_cflags += -DPACKED=""
+endif
+
+ifeq ($(WITH_JIT),true)
+ local_cflags += -DWITH_JIT
+endif
+
+ifneq ($(USE_CUSTOM_RUNTIME_HEAP_MAX),)
+ local_cflags += -DCUSTOM_RUNTIME_HEAP_MAX=$(USE_CUSTOM_RUNTIME_HEAP_MAX)
+endif
+
+ifeq ($(USE_OPENGL_RENDERER),true)
+ local_cflags += -DUSE_OPENGL_RENDERER
+endif
+
+local_cflags += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+local_src_files:= \
+ ActivityManager.cpp \
+ AndroidRuntime.cpp \
+ Time.cpp \
+ com_android_internal_content_NativeLibraryHelper.cpp \
+ com_google_android_gles_jni_EGLImpl.cpp \
+ com_google_android_gles_jni_GLImpl.cpp.arm \
+ android_app_NativeActivity.cpp \
+ android_opengl_GLES10.cpp \
+ android_opengl_GLES10Ext.cpp \
+ android_opengl_GLES11.cpp \
+ android_opengl_GLES11Ext.cpp \
+ android_opengl_GLES20.cpp \
+ android_database_CursorWindow.cpp \
+ android_database_SQLiteCompiledSql.cpp \
+ android_database_SQLiteDebug.cpp \
+ android_database_SQLiteDatabase.cpp \
+ android_database_SQLiteProgram.cpp \
+ android_database_SQLiteQuery.cpp \
+ android_database_SQLiteStatement.cpp \
+ android_emoji_EmojiFactory.cpp \
+ android_view_Display.cpp \
+ android_view_Surface.cpp \
+ android_view_TextureView.cpp \
+ android_view_InputChannel.cpp \
+ android_view_InputQueue.cpp \
+ android_view_KeyEvent.cpp \
+ android_view_KeyCharacterMap.cpp \
+ android_view_GLES20Canvas.cpp \
+ android_view_MotionEvent.cpp \
+ android_view_PointerIcon.cpp \
+ android_view_VelocityTracker.cpp \
+ android_text_AndroidCharacter.cpp \
+ android_text_AndroidBidi.cpp \
+ android_os_Debug.cpp \
+ android_os_FileUtils.cpp \
+ android_os_MemoryFile.cpp \
+ android_os_MessageQueue.cpp \
+ android_os_ParcelFileDescriptor.cpp \
+ android_os_Power.cpp \
+ android_os_StatFs.cpp \
+ android_os_SystemClock.cpp \
+ android_os_SystemProperties.cpp \
+ android_os_UEventObserver.cpp \
+ android_net_LocalSocketImpl.cpp \
+ android_net_NetUtils.cpp \
+ android_net_TrafficStats.cpp \
+ android_net_wifi_Wifi.cpp \
+ android_nio_utils.cpp \
+ android_nfc_NdefMessage.cpp \
+ android_nfc_NdefRecord.cpp \
+ android_text_format_Time.cpp \
+ android_util_AssetManager.cpp \
+ android_util_Binder.cpp \
+ android_util_EventLog.cpp \
+ android_util_Log.cpp \
+ android_util_FloatMath.cpp \
+ android_util_Process.cpp \
+ android_util_StringBlock.cpp \
+ android_util_XmlBlock.cpp \
+ android/graphics/AutoDecodeCancel.cpp \
+ android/graphics/Bitmap.cpp \
+ android/graphics/BitmapFactory.cpp \
+ android/graphics/Camera.cpp \
+ android/graphics/Canvas.cpp \
+ android/graphics/ColorFilter.cpp \
+ android/graphics/DrawFilter.cpp \
+ android/graphics/CreateJavaOutputStreamAdaptor.cpp \
+ android/graphics/Graphics.cpp \
+ android/graphics/HarfbuzzSkia.cpp \
+ android/graphics/Interpolator.cpp \
+ android/graphics/LayerRasterizer.cpp \
+ android/graphics/MaskFilter.cpp \
+ android/graphics/Matrix.cpp \
+ android/graphics/Movie.cpp \
+ android/graphics/NinePatch.cpp \
+ android/graphics/NinePatchImpl.cpp \
+ android/graphics/NinePatchPeeker.cpp \
+ android/graphics/Paint.cpp \
+ android/graphics/Path.cpp \
+ android/graphics/PathMeasure.cpp \
+ android/graphics/PathEffect.cpp \
+ android_graphics_PixelFormat.cpp \
+ android/graphics/Picture.cpp \
+ android/graphics/PorterDuff.cpp \
+ android/graphics/BitmapRegionDecoder.cpp \
+ android/graphics/Rasterizer.cpp \
+ android/graphics/Region.cpp \
+ android/graphics/Shader.cpp \
+ android/graphics/SurfaceTexture.cpp \
+ android/graphics/TextLayout.cpp \
+ android/graphics/TextLayoutCache.cpp \
+ android/graphics/Typeface.cpp \
+ android/graphics/Utils.cpp \
+ android/graphics/Xfermode.cpp \
+ android/graphics/YuvToJpegEncoder.cpp \
+ android_media_AudioRecord.cpp \
+ android_media_AudioSystem.cpp \
+ android_media_AudioTrack.cpp \
+ android_media_JetPlayer.cpp \
+ android_media_ToneGenerator.cpp \
+ android_hardware_Camera.cpp \
+ android_hardware_SensorManager.cpp \
+ android_hardware_UsbDevice.cpp \
+ android_hardware_UsbDeviceConnection.cpp \
+ android_hardware_UsbRequest.cpp \
+ android_debug_JNITest.cpp \
+ android_util_FileObserver.cpp \
+ android/opengl/poly_clip.cpp.arm \
+ android/opengl/util.cpp.arm \
+ android_bluetooth_HeadsetBase.cpp \
+ android_bluetooth_common.cpp \
+ android_bluetooth_BluetoothAudioGateway.cpp \
+ android_bluetooth_BluetoothSocket.cpp \
+ android_bluetooth_c.c \
+ android_server_BluetoothService.cpp \
+ android_server_BluetoothEventLoop.cpp \
+ android_server_BluetoothA2dpService.cpp \
+ android_server_Watchdog.cpp \
+ android_ddm_DdmHandleNativeHeap.cpp \
+ com_android_internal_os_ZygoteInit.cpp \
+ android_backup_BackupDataInput.cpp \
+ android_backup_BackupDataOutput.cpp \
+ android_backup_FileBackupHelperBase.cpp \
+ android_backup_BackupHelperDispatcher.cpp \
+ android_app_backup_FullBackup.cpp \
+ android_content_res_ObbScanner.cpp \
+ android_content_res_Configuration.cpp \
+ android_animation_PropertyValuesHolder.cpp
+
+local_c_includes += \
+ $(LOCAL_PATH)/android/graphics \
+ $(LOCAL_PATH)/../../libs/hwui \
+ $(call include-path-for, bluedroid) \
+ $(call include-path-for, libhardware)/hardware \
+ $(call include-path-for, libhardware_legacy)/hardware_legacy \
+ $(LOCAL_PATH)/../../include/ui \
+ $(LOCAL_PATH)/../../include/utils \
+ external/skia/include/core \
+ external/skia/include/effects \
+ external/skia/include/images \
+ external/skia/src/ports \
+ external/skia/include/utils \
+ external/sqlite/dist \
+ external/sqlite/android \
+ external/expat/lib \
+ external/openssl/include \
+ external/tremor/Tremor \
+ external/icu4c/i18n \
+ external/icu4c/common \
+ external/jpeg \
+ external/harfbuzz/contrib \
+ external/harfbuzz/src \
+ external/zlib \
+ frameworks/opt/emoji
+
+local_shared_libraries := \
+ libexpat \
+ libnativehelper \
+ libcutils \
+ libutils \
+ libbinder \
+ libnetutils \
+ libui \
+ libgui \
+ libcamera_client \
+ libskia \
+ libsqlite \
+ libEGL \
+ libGLESv1_CM \
+ libGLESv2 \
+ libETC1 \
+ libhardware \
+ libhardware_legacy \
+ libsonivox \
+ libcrypto \
+ libssl \
+ libicuuc \
+ libicui18n \
+ libmedia \
+ libwpa_client \
+ libjpeg \
+ libnfc_ndef \
+ libusbhost \
+ libharfbuzz \
+ libz \
+
+ifeq ($(USE_OPENGL_RENDERER),true)
+ local_shared_libraries += libhwui
+endif
+
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+local_c_includes += \
+ external/dbus \
+ system/bluetooth/bluez-clean-headers
+local_cflags += -DHAVE_BLUETOOTH
+local_shared_libraries += libbluedroid libdbus
+endif
+
+local_shared_libraries += \
+ libdl
+# we need to access the private Bionic header
+# <bionic_tls.h> in com_google_android_gles_jni_GLImpl.cpp
+local_cflags += -I$(LOCAL_PATH)/../../../../bionic/libc/private
+
+local_ldlibs += -lpthread -ldl
+
+ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
+ local_cflags += -DMALLOC_LEAK_CHECK
+endif
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS := $(local_cflags)
+LOCAL_SRC_FILES := $(local_src_files)
+LOCAL_C_INCLUDES := $(local_c_includes)
+LOCAL_SHARED_LIBRARIES := libart $(local_shared_libraries)
+LOCAL_LDLIBS := $(local_ldlibs)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE:= liboat_runtime
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS := $(local_cflags)
+LOCAL_SRC_FILES := $(local_src_files)
+LOCAL_C_INCLUDES := $(local_c_includes)
+LOCAL_SHARED_LIBRARIES := libartd $(local_shared_libraries)
+LOCAL_LDLIBS := $(local_ldlibs)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE:= liboat_runtimed
+include $(BUILD_SHARED_LIBRARY)
diff --git a/src/class_linker.cc b/src/class_linker.cc
index de70fa5..a9c2005 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -657,7 +657,7 @@
Thread* self = Thread::Current();
DCHECK(self != NULL);
- CHECK(!self->IsExceptionPending());
+ CHECK(!self->IsExceptionPending()) << PrettyTypeOf(self->GetException());
// Find the class in the loaded classes table.
Class* klass = LookupClass(descriptor, class_loader);
if (klass == NULL) {
@@ -701,7 +701,6 @@
LoadClass(dex_file, dex_class_def, klass, class_loader);
// Check for a pending exception during load
if (self->IsExceptionPending()) {
- // TODO: free native allocations in klass
return NULL;
}
ObjectLock lock(klass);
@@ -711,7 +710,6 @@
if (!success) {
// We may fail to insert if we raced with another thread.
klass->SetClinitThreadId(0);
- // TODO: free native allocations in klass
klass = LookupClass(descriptor, class_loader);
CHECK(klass != NULL);
return klass;
@@ -1230,7 +1228,12 @@
LOG(ERROR) << "Verification failed on class "
<< klass->GetDescriptor()->ToModifiedUtf8();
Object* exception = Thread::Current()->GetException();
- klass->SetVerifyErrorClass(exception->GetClass());
+ // CHECK(exception != NULL) << PrettyClass(klass);
+ if (exception == NULL) {
+ UNIMPLEMENTED(ERROR) << "null verification exception for " << PrettyClass(klass);
+ } else {
+ klass->SetVerifyErrorClass(exception->GetClass());
+ }
klass->SetStatus(Class::kStatusError);
return;
}
@@ -1381,7 +1384,7 @@
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
const Method* method = interface_entry->GetMethodArray()->Get(j);
if (!HasSameMethodDescriptorClasses(method, interface,
- method->GetClass())) {
+ method->GetDeclaringClass())) {
ThrowLinkageError("Classes resolve differently in interface");
return false;
}
@@ -1394,7 +1397,7 @@
bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
const Class* klass1,
const Class* klass2) {
- const DexFile& dex_file = FindDexFile(method->GetClass()->GetDexCache());
+ const DexFile& dex_file = FindDexFile(method->GetDeclaringClass()->GetDexCache());
const DexFile::ProtoId& proto_id = dex_file.GetProtoId(method->GetProtoIdx());
DexFile::ParameterIterator *it;
for (it = dex_file.GetParameterIterator(proto_id); it->HasNext(); it->Next()) {
@@ -1865,8 +1868,9 @@
if (miranda_count != 0) {
int old_method_count = klass->NumVirtualMethods();
int new_method_count = old_method_count + miranda_count;
- klass->SetVirtualMethods(
- klass->GetVirtualMethods()->CopyOf(new_method_count));
+ klass->SetVirtualMethods((old_method_count == 0)
+ ? AllocObjectArray<Method>(new_method_count)
+ : klass->GetVirtualMethods()->CopyOf(new_method_count));
ObjectArray<Method>* vtable = klass->GetVTableDuringLinking();
CHECK(vtable != NULL);
diff --git a/src/common_test.h b/src/common_test.h
index a291976..127cad6 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -2,6 +2,7 @@
#include <dirent.h>
#include <dlfcn.h>
+#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -104,6 +105,8 @@
Runtime::Options options;
options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL)));
+ options.push_back(std::make_pair("-Xms16m", reinterpret_cast<void*>(NULL)));
+ options.push_back(std::make_pair("-Xmx16m", reinterpret_cast<void*>(NULL)));
runtime_.reset(Runtime::Create(options, false));
ASSERT_TRUE(runtime_.get() != NULL);
class_linker_ = runtime_->GetClassLinker();
diff --git a/src/compiler.cc b/src/compiler.cc
index 71727fd..54793ba 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -2,6 +2,8 @@
#include "compiler.h"
+#include <sys/mman.h>
+
#include "assembler.h"
#include "class_linker.h"
#include "class_loader.h"
@@ -72,7 +74,9 @@
// Class derived values are more complicated, they require the linker and loader.
for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
- CHECK(klass->IsResolved());
+ if (klass == NULL) {
+ Thread::Current()->ClearException();
+ }
}
// Method and Field are the worst. We can't resolve without either
@@ -172,13 +176,19 @@
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
const char* descriptor = dex_file.GetClassDescriptor(class_def);
Class* klass = class_linker->FindClass(descriptor, class_loader);
- class_linker->EnsureInitialized(klass, false);
+ if (klass != NULL) {
+ class_linker->EnsureInitialized(klass, false);
+ }
+ // clear any class not found or verification exceptions
+ Thread::Current()->ClearException();
}
DexCache* dex_cache = class_linker->FindDexCache(dex_file);
for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
- if (klass->IsInitialized()) {
+ if (klass == NULL) {
+ Thread::Current()->ClearException();
+ } else if (klass->IsInitialized()) {
dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
}
}
@@ -199,8 +209,15 @@
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
const char* descriptor = dex_file.GetClassDescriptor(class_def);
Class* klass = class_linker->FindClass(descriptor, class_loader);
- CHECK(klass != NULL);
- CompileClass(klass);
+ if (klass == NULL) {
+ // previous verification error will cause FindClass to throw
+ Thread* self = Thread::Current();
+ // CHECK(self->IsExceptionPending());
+ UNIMPLEMENTED(WARNING) << "CHECK for verification error after FindClass " << descriptor;
+ self->ClearException();
+ } else {
+ CompileClass(klass);
+ }
}
}
diff --git a/src/compiler/Utility.cc b/src/compiler/Utility.cc
index fbdf62c..7d3a887 100644
--- a/src/compiler/Utility.cc
+++ b/src/compiler/Utility.cc
@@ -78,7 +78,7 @@
currentArena->next = newArena;
currentArena = newArena;
numArenaBlocks++;
- if (numArenaBlocks > 1000) {
+ if (numArenaBlocks > 20000) {
LOG(INFO) << "Total arena pages: " << numArenaBlocks;
}
goto retry;
@@ -373,7 +373,8 @@
bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
const ArenaBitVector* src2)
{
- if (dest->storageSize != src1->storageSize ||
+ if (src2 == NULL ||
+ dest->storageSize != src1->storageSize ||
dest->storageSize != src2->storageSize ||
dest->expandable != src1->expandable ||
dest->expandable != src2->expandable)
@@ -392,7 +393,8 @@
bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
const ArenaBitVector* src2)
{
- if (dest->storageSize != src1->storageSize ||
+ if (src2 == NULL ||
+ dest->storageSize != src1->storageSize ||
dest->storageSize != src2->storageSize ||
dest->expandable != src1->expandable ||
dest->expandable != src2->expandable)
diff --git a/src/compiler/codegen/arm/CodegenCommon.cc b/src/compiler/codegen/arm/CodegenCommon.cc
index 40494f3..08da8d8 100644
--- a/src/compiler/codegen/arm/CodegenCommon.cc
+++ b/src/compiler/codegen/arm/CodegenCommon.cc
@@ -280,8 +280,11 @@
int dest, int src1, int src2)
{
ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true);
- assert(isPseudoOpcode(opcode) ||
- (EncodingMap[opcode].flags & IS_TERTIARY_OP));
+ DCHECK(isPseudoOpcode(opcode) ||
+ (EncodingMap[opcode].flags & IS_TERTIARY_OP))
+ << (int)opcode << " "
+ << PrettyMethod(cUnit->method) << " "
+ << cUnit->currentDalvikOffset;
insn->opcode = opcode;
insn->operands[0] = dest;
insn->operands[1] = src1;
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index f60699c..053575a 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -39,7 +39,7 @@
// TODO: remove this by making boot image contain boot DexFile information?
fprintf(stderr,
" --boot-dex-file=<dex-file>: specifies a .dex file that is part of the boot\n"
- " image specified with --boot. \n"
+ " image specified with --boot. \n"
" Example: --boot-dex-file=/system/framework/core.jar\n"
"\n");
fprintf(stderr,
@@ -48,9 +48,19 @@
"\n");
fprintf(stderr,
" --strip-prefix may be used to strip a path prefix from dex file names in the\n"
- " the generated image to match the target file system layout.\n"
+ " the generated image to match the target file system layout.\n"
" Example: --strip-prefix=out/target/product/crespo\n"
"\n");
+ fprintf(stderr,
+ " -Xms<n> may be used to specify an initial heap size for the runtime used to\n"
+ " run dex2oat\n"
+ " Example: -Xms256m\n"
+ "\n");
+ fprintf(stderr,
+ " -Xmx<n> may be used to specify a maximum heap size for the runtime used to\n"
+ " run dex2oat\n"
+ " Example: -Xmx256m\n"
+ "\n");
exit(EXIT_FAILURE);
}
@@ -71,6 +81,8 @@
std::vector<const char*> boot_dex_filenames;
uintptr_t image_base = 0;
std::string strip_location_prefix;
+ const char* Xms = NULL;
+ const char* Xmx = NULL;
for (int i = 0; i < argc; i++) {
const StringPiece option(argv[i]);
@@ -85,7 +97,7 @@
char* end;
image_base = strtoul(image_base_str, &end, 16);
if (end == image_base_str || *end != '\0') {
- fprintf(stderr, "could not parse hexadecimal value for option %s\n", option.data());
+ fprintf(stderr, "Failed to parse hexadecimal value for option %s\n", option.data());
usage();
}
} else if (option.starts_with("--boot=")) {
@@ -97,6 +109,10 @@
boot_dex_filenames.push_back(option.substr(strlen("--boot-dex-file=")).data());
} else if (option.starts_with("--strip-prefix=")) {
strip_location_prefix = option.substr(strlen("--strip-prefix=")).data();
+ } else if (option.starts_with("-Xms")) {
+ Xms = option.data();
+ } else if (option.starts_with("-Xmx")) {
+ Xmx = option.data();
} else {
fprintf(stderr, "unknown argument %s\n", option.data());
usage();
@@ -138,6 +154,12 @@
options.push_back(std::make_pair("bootclasspath", &boot_dex_files));
options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
}
+ if (Xms != NULL) {
+ options.push_back(std::make_pair(Xms, reinterpret_cast<void*>(NULL)));
+ }
+ if (Xmx != NULL) {
+ options.push_back(std::make_pair(Xmx, reinterpret_cast<void*>(NULL)));
+ }
UniquePtr<Runtime> runtime(Runtime::Create(options, false));
if (runtime.get() == NULL) {
fprintf(stderr, "could not create runtime\n");
diff --git a/src/heap.cc b/src/heap.cc
index 4d8d176..8311944 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -330,6 +330,7 @@
++Runtime::Current()->GetStats()->gc_for_alloc_count;
++Thread::Current()->GetStats()->gc_for_alloc_count;
}
+ UNIMPLEMENTED(FATAL) << "No implicit GC, use larger -Xms -Xmx";
CollectGarbageInternal();
ptr = space->AllocWithoutGrowth(size);
if (ptr != NULL) {
diff --git a/src/heap.h b/src/heap.h
index f39454a..ea05a73 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -35,9 +35,9 @@
class Heap {
public:
- static const size_t kInitialSize = 64 * MB; // TODO: lower to 4
+ static const size_t kInitialSize = 4 * MB;
- static const size_t kMaximumSize = 64 * MB; // TODO: lower to 16
+ static const size_t kMaximumSize = 16 * MB;
typedef void (RootVisitor)(const Object* root, void* arg);
diff --git a/src/mem_map.cc b/src/mem_map.cc
new file mode 100644
index 0000000..e44a894
--- /dev/null
+++ b/src/mem_map.cc
@@ -0,0 +1,163 @@
+#include "mem_map.h"
+
+#include <sys/mman.h>
+
+#include "utils.h"
+
+/*
+ * Copyright (C) 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#include "mem_map.h"
+
+#include <sys/mman.h>
+
+namespace art {
+
+size_t ParseHex(const std::string& string) {
+ CHECK_EQ(8U, string.size());
+ const char* str = string.c_str();
+ char* end;
+ size_t value = strtoul(str, &end, 16);
+ CHECK(end != str) << "Failed to parse hexadecimal value from " << string;
+ CHECK(*end == '\0') << "Failed to parse hexadecimal value from " << string;
+ return value;
+}
+
+void CheckMapRequest(byte* addr, size_t length) {
+#ifndef NDEBUG
+ if (addr == NULL) {
+ return;
+ }
+ size_t base = reinterpret_cast<size_t>(addr);
+ size_t limit = base + length;
+
+ std::string maps;
+ bool read = ReadFileToString("/proc/self/maps", &maps);
+ if (!read) {
+ PLOG(FATAL) << "Failed to read /proc/self/maps";
+ }
+ // Quick and dirty parse of output like shown below. We only focus
+ // on grabbing the two 32-bit hex values at the start of each line
+ // and will fail on wider addresses found on 64-bit systems.
+
+ // 00008000-0001f000 r-xp 00000000 b3:01 273 /system/bin/toolbox
+ // 0001f000-00021000 rw-p 00017000 b3:01 273 /system/bin/toolbox
+ // 00021000-00029000 rw-p 00000000 00:00 0 [heap]
+ // 40011000-40053000 r-xp 00000000 b3:01 1050 /system/lib/libc.so
+ // 40053000-40056000 rw-p 00042000 b3:01 1050 /system/lib/libc.so
+ // 40056000-40061000 rw-p 00000000 00:00 0
+ // 40061000-40063000 r-xp 00000000 b3:01 1107 /system/lib/libusbhost.so
+ // 40063000-40064000 rw-p 00002000 b3:01 1107 /system/lib/libusbhost.so
+ // 4009d000-400a0000 r-xp 00000000 b3:01 1022 /system/lib/liblog.so
+ // 400a0000-400a1000 rw-p 00003000 b3:01 1022 /system/lib/liblog.so
+ // 400b7000-400cc000 r-xp 00000000 b3:01 932 /system/lib/libm.so
+ // 400cc000-400cd000 rw-p 00015000 b3:01 932 /system/lib/libm.so
+ // 400cf000-400d0000 r--p 00000000 00:00 0
+ // 400e4000-400ec000 r--s 00000000 00:0b 388 /dev/__properties__ (deleted)
+ // 400ec000-400fa000 r-xp 00000000 b3:01 1101 /system/lib/libcutils.so
+ // 400fa000-400fb000 rw-p 0000e000 b3:01 1101 /system/lib/libcutils.so
+ // 400fb000-4010a000 rw-p 00000000 00:00 0
+ // 4010d000-4010e000 r-xp 00000000 b3:01 929 /system/lib/libstdc++.so
+ // 4010e000-4010f000 rw-p 00001000 b3:01 929 /system/lib/libstdc++.so
+ // b0001000-b0009000 r-xp 00001000 b3:01 1098 /system/bin/linker
+ // b0009000-b000a000 rw-p 00009000 b3:01 1098 /system/bin/linker
+ // b000a000-b0015000 rw-p 00000000 00:00 0
+ // bee35000-bee56000 rw-p 00000000 00:00 0 [stack]
+ // ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
+
+ for (size_t i = 0; i < maps.size(); i++) {
+ size_t remaining = maps.size() - i;
+ if (remaining < 8+1+8) { // 00008000-0001f000
+ LOG(FATAL) << "Failed to parse at pos " << i << "\n" << maps;
+ }
+ std::string start_str = maps.substr(i, 8);
+ std::string end_str = maps.substr(i+1+8, 8);
+ uint32_t start = ParseHex(start_str);
+ uint32_t end = ParseHex(end_str);
+ CHECK(!(base >= start && base < end)
+ && !(limit >= start && limit < end)
+ && !(base <= start && limit > end))
+ << StringPrintf("Requested region %08x-%08x overlaps with existing map %08x-%08x\n",
+ base, limit, start, end)
+ << maps;
+ i += 8+1+8;
+ i = maps.find('\n', i);
+ CHECK(i != std::string::npos) << "Failed to find newline from pos " << i << "\n" << maps;
+ }
+#endif
+}
+
+MemMap* MemMap::Map(byte* addr, size_t length, int prot) {
+ CHECK_NE(0U, length);
+ CHECK_NE(0, prot);
+ size_t page_aligned_size = RoundUp(length, kPageSize);
+ CheckMapRequest(addr, page_aligned_size);
+ byte* actual = reinterpret_cast<byte*>(mmap(addr,
+ page_aligned_size,
+ prot,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1,
+ 0));
+ if (actual == MAP_FAILED) {
+ PLOG(ERROR) << "mmap failed";
+ return NULL;
+ }
+ return new MemMap(actual, length, actual, page_aligned_size);
+}
+
+MemMap* MemMap::Map(byte* addr, size_t length, int prot, int flags, int fd, off_t start) {
+ CHECK_NE(0U, length);
+ CHECK_NE(0, prot);
+ CHECK_NE(0, flags & (MAP_SHARED | MAP_PRIVATE));
+ // adjust to be page-aligned
+ int page_offset = start % kPageSize;
+ off_t page_aligned_offset = start - page_offset;
+ size_t page_aligned_size = RoundUp(length + page_offset, kPageSize);
+ CheckMapRequest(addr, page_aligned_size);
+ byte* actual = reinterpret_cast<byte*>(mmap(addr,
+ page_aligned_size,
+ prot,
+ flags,
+ fd,
+ page_aligned_offset));
+ if (actual == MAP_FAILED) {
+ PLOG(ERROR) << "mmap failed";
+ return NULL;
+ }
+ return new MemMap(actual + page_offset, length, actual, page_aligned_size);
+}
+
+MemMap::~MemMap() {
+ if (base_addr_ == NULL && base_length_ == 0) {
+ return;
+ }
+ int result = munmap(base_addr_, base_length_);
+ base_addr_ = NULL;
+ base_length_ = 0;
+ if (result == -1) {
+ PLOG(FATAL) << "munmap failed";
+ }
+}
+
+MemMap::MemMap(byte* addr, size_t length, void* base_addr, size_t base_length)
+ : addr_(addr), length_(length), base_addr_(base_addr), base_length_(base_length) {
+ CHECK(addr_ != NULL);
+ CHECK(length_ != 0);
+ CHECK(base_addr_ != NULL);
+ CHECK(base_length_ != 0);
+};
+
+} // namespace art
diff --git a/src/mem_map.h b/src/mem_map.h
index f44939c..3c73613 100644
--- a/src/mem_map.h
+++ b/src/mem_map.h
@@ -17,9 +17,10 @@
#ifndef ART_SRC_MEM_MAP_H_
#define ART_SRC_MEM_MAP_H_
-#include <sys/mman.h>
+#include <stddef.h>
+#include <sys/types.h>
-#include "utils.h"
+#include "globals.h"
namespace art {
@@ -37,22 +38,7 @@
// Request an anonymous region of a specified length and a requested base address.
//
// On success, returns returns a MemMap instance. On failure, returns a NULL;
- static MemMap* Map(byte* addr, size_t length, int prot) {
- CHECK_NE(0U, length);
- CHECK_NE(0, prot);
- size_t page_aligned_size = RoundUp(length, kPageSize);
- byte* actual = reinterpret_cast<byte*>(mmap(addr,
- page_aligned_size,
- prot,
- MAP_PRIVATE | MAP_ANONYMOUS,
- -1,
- 0));
- if (actual == MAP_FAILED) {
- PLOG(ERROR) << "mmap failed";
- return NULL;
- }
- return new MemMap(actual, length, actual, page_aligned_size);
- }
+ static MemMap* Map(byte* addr, size_t length, int prot);
// Map part of a file, taking care of non-page aligned offsets. The
// "start" offset is absolute, not relative.
@@ -67,44 +53,10 @@
// requesting a specific address for the base of the mapping.
//
// On success, returns returns a MemMap instance. On failure, returns a NULL;
- static MemMap* Map(byte* addr, size_t length, int prot, int flags, int fd, off_t start) {
- CHECK_NE(0U, length);
- CHECK_NE(0, prot);
- CHECK(flags & MAP_SHARED || flags & MAP_PRIVATE);
- // adjust to be page-aligned
- int page_offset = start % kPageSize;
- off_t page_aligned_offset = start - page_offset;
- size_t page_aligned_size = RoundUp(length + page_offset, kPageSize);
- byte* actual = reinterpret_cast<byte*>(mmap(addr,
- page_aligned_size,
- prot,
- flags,
- fd,
- page_aligned_offset));
- if (actual == MAP_FAILED) {
- PLOG(ERROR) << "mmap failed";
- return NULL;
- }
- return new MemMap(actual + page_offset, length, actual, page_aligned_size);
- }
+ static MemMap* Map(byte* addr, size_t length, int prot, int flags, int fd, off_t start);
- ~MemMap() {
- Unmap();
- }
-
- // Release a memory mapping, returning true on success or it was previously unmapped.
- bool Unmap() {
- if (base_addr_ == NULL && base_length_ == 0) {
- return true;
- }
- int result = munmap(base_addr_, base_length_);
- base_addr_ = NULL;
- base_length_ = 0;
- if (result == -1) {
- return false;
- }
- return true;
- }
+ // Releases the memory mapping
+ ~MemMap();
byte* GetAddress() const {
return addr_;
@@ -119,13 +71,7 @@
}
private:
- MemMap(byte* addr, size_t length, void* base_addr, size_t base_length)
- : addr_(addr), length_(length), base_addr_(base_addr), base_length_(base_length) {
- CHECK(addr_ != NULL);
- CHECK(length_ != 0);
- CHECK(base_addr_ != NULL);
- CHECK(base_length_ != 0);
- };
+ MemMap(byte* addr, size_t length, void* base_addr, size_t base_length);
byte* addr_; // start of data
size_t length_; // length of data
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 7578fb1..52cddb5 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -3,6 +3,8 @@
#include <stdio.h>
#include <stdlib.h>
+#include <fstream>
+#include <iostream>
#include <string>
#include <vector>
@@ -45,6 +47,10 @@
" the generated image to match the target file system layout.\n"
" Example: --strip-prefix=out/target/product/crespo\n"
"\n");
+ fprintf(stderr,
+ " --output=<file> may be used to send the output to a file.\n"
+ " Example: --output=/tmp/oatdump.txt\n"
+ "\n");
exit(EXIT_FAILURE);
}
@@ -52,15 +58,32 @@
"kJniStubArray",
};
-struct OatDump {
- const Space* dump_space;
+class OatDump {
- bool InDumpSpace(const Object* object) {
- DCHECK(dump_space != NULL);
- const byte* o = reinterpret_cast<const byte*>(object);
- return (o >= dump_space->GetBase() && o < dump_space->GetLimit());
+ public:
+ static void Dump(std::ostream& os, Space& image_space, const ImageHeader& image_header) {
+ os << "MAGIC:\n";
+ os << image_header.GetMagic() << "\n\n";
+
+ os << "ROOTS:\n";
+ for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
+ ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
+ os << StringPrintf("%s: %p\n",
+ image_roots_descriptions_[i], image_header.GetImageRoot(image_root));
+ }
+ os << "\n";
+
+ os << "OBJECTS:\n" << std::flush;
+ OatDump state(image_space, os);
+ HeapBitmap* heap_bitmap = Heap::GetLiveBits();
+ DCHECK(heap_bitmap != NULL);
+ heap_bitmap->Walk(OatDump::Callback, &state);
}
+ private:
+
+ OatDump(const Space& dump_space, std::ostream& os) : dump_space_(dump_space_), os_(os) {}
+
static void Callback(Object* obj, void* arg) {
DCHECK(obj != NULL);
DCHECK(arg != NULL);
@@ -106,8 +129,15 @@
}
}
}
- std::cout << summary;
+ state->os_ << summary << std::flush;
}
+
+ bool InDumpSpace(const Object* object) {
+ const byte* o = reinterpret_cast<const byte*>(object);
+ return (o >= dump_space_.GetBase() && o < dump_space_.GetLimit());
+ }
+ const Space& dump_space_;
+ std::ostream& os_;
};
int oatdump(int argc, char** argv) {
@@ -125,6 +155,8 @@
const char* boot_image_filename = NULL;
std::vector<const char*> boot_dex_filenames;
std::string strip_location_prefix;
+ std::ostream* os = &std::cout;
+ UniquePtr<std::ofstream> out;
for (int i = 0; i < argc; i++) {
const StringPiece option(argv[i]);
@@ -138,6 +170,14 @@
boot_dex_filenames.push_back(option.substr(strlen("--boot-dex-file=")).data());
} else if (option.starts_with("--strip-prefix=")) {
strip_location_prefix = option.substr(strlen("--strip-prefix=")).data();
+ } else if (option.starts_with("--output=")) {
+ const char* filename = option.substr(strlen("--output=")).data();
+ out.reset(new std::ofstream(filename));
+ if (!out->good()) {
+ fprintf(stderr, "failed to open output filename %s\n", filename);
+ usage();
+ }
+ os = out.get();
} else {
fprintf(stderr, "unknown argument %s\n", option.data());
usage();
@@ -202,24 +242,7 @@
fprintf(stderr, "invalid image header %s\n", image_filename);
return EXIT_FAILURE;
}
-
- printf("MAGIC:\n");
- printf("%s\n\n", image_header.GetMagic());
-
- printf("ROOTS:\n");
- for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
- ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
- printf("%s: %p\n", image_roots_descriptions_[i], image_header.GetImageRoot(image_root));
- }
- printf("\n");
-
- printf("OBJECTS:\n");
- OatDump state;
- state.dump_space = image_space;
- HeapBitmap* heap_bitmap = Heap::GetLiveBits();
- DCHECK(heap_bitmap != NULL);
- heap_bitmap->Walk(OatDump::Callback, &state);
-
+ OatDump::Dump(*os, *image_space, image_header);
return EXIT_SUCCESS;
}
diff --git a/src/object.cc b/src/object.cc
index 756b8a7..40bc2e2 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -332,7 +332,7 @@
}
Class* Method::GetReturnType() const {
- DCHECK(GetDeclaringClass()->IsResolved());
+ DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
// Short-cut
Class* result = GetDexCacheResolvedTypes()->Get(GetReturnTypeIdx());
if (result == NULL) {
diff --git a/src/object.h b/src/object.h
index 2e3a791..eb11be7 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1536,7 +1536,7 @@
}
uint32_t GetSuperClassTypeIdx() const {
- DCHECK(IsIdxLoaded());
+ DCHECK(IsIdxLoaded() || IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, super_class_type_idx_),
false);
}
@@ -1567,7 +1567,7 @@
void SetDexCache(DexCache* new_dex_cache);
ObjectArray<Method>* GetDirectMethods() const {
- DCHECK(IsLoaded());
+ DCHECK(IsLoaded() || IsErroneous());
return GetFieldObject<ObjectArray<Method>*>(
OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
}
@@ -1597,7 +1597,7 @@
}
ObjectArray<Method>* GetVirtualMethods() const {
- DCHECK(IsLoaded());
+ DCHECK(IsLoaded() || IsErroneous());
return GetFieldObject<ObjectArray<Method>*>(
OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
}
@@ -1616,12 +1616,12 @@
}
Method* GetVirtualMethod(uint32_t i) const {
- DCHECK(IsResolved());
+ DCHECK(IsResolved() || IsErroneous());
return GetVirtualMethods()->Get(i);
}
Method* GetVirtualMethodDuringLinking(uint32_t i) const {
- DCHECK(IsLoaded());
+ DCHECK(IsLoaded() || IsErroneous());
return GetVirtualMethods()->Get(i);
}
@@ -1633,13 +1633,13 @@
}
ObjectArray<Method>* GetVTable() const {
- DCHECK(IsResolved());
+ DCHECK(IsResolved() || IsErroneous());
return GetFieldObject<ObjectArray<Method>*>(
OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
}
ObjectArray<Method>* GetVTableDuringLinking() const {
- DCHECK(IsLoaded());
+ DCHECK(IsLoaded() || IsErroneous());
return GetFieldObject<ObjectArray<Method>*>(
OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
}
@@ -1690,14 +1690,14 @@
const StringPiece& signature);
size_t NumInterfaces() const {
- CHECK(IsIdxLoaded()); // used during loading
+ CHECK(IsIdxLoaded() || IsErroneous()); // used during loading
ObjectArray<Class>* interfaces = GetFieldObject<ObjectArray<Class>*>(
OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false);
return (interfaces != NULL) ? interfaces->GetLength() : 0;
}
IntArray* GetInterfacesTypeIdx() const {
- CHECK(IsIdxLoaded());
+ CHECK(IsIdxLoaded() || IsErroneous());
return GetFieldObject<IntArray*>(
OFFSET_OF_OBJECT_MEMBER(Class, interfaces_type_idx_), false);
}
@@ -1705,7 +1705,7 @@
void SetInterfacesTypeIdx(IntArray* new_interfaces_idx);
ObjectArray<Class>* GetInterfaces() const {
- CHECK(IsLoaded());
+ CHECK(IsLoaded() || IsErroneous());
return GetFieldObject<ObjectArray<Class>*>(
OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false);
}
@@ -1739,7 +1739,7 @@
}
ObjectArray<InterfaceEntry>* GetIfTable() const {
- DCHECK(IsResolved());
+ DCHECK(IsResolved() || IsErroneous());
return GetFieldObject<ObjectArray<InterfaceEntry>*>(
OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
}
@@ -1750,7 +1750,7 @@
// Get instance fields
ObjectArray<Field>* GetIFields() const {
- DCHECK(IsLoaded());
+ DCHECK(IsLoaded() || IsErroneous());
return GetFieldObject<ObjectArray<Field>*>(
OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
}
@@ -1779,14 +1779,14 @@
// Returns the number of instance fields containing reference types.
size_t NumReferenceInstanceFields() const {
- DCHECK(IsResolved());
+ DCHECK(IsResolved() || IsErroneous());
DCHECK(sizeof(size_t) == sizeof(int32_t));
return GetField32(
OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
}
size_t NumReferenceInstanceFieldsDuringLinking() const {
- DCHECK(IsLoaded());
+ DCHECK(IsLoaded() || IsErroneous());
DCHECK(sizeof(size_t) == sizeof(int32_t));
return GetField32(
OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
@@ -1799,7 +1799,7 @@
}
uint32_t GetReferenceInstanceOffsets() const {
- DCHECK(IsResolved());
+ DCHECK(IsResolved() || IsErroneous());
return GetField32(
OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false);
}
@@ -1813,14 +1813,14 @@
// Returns the number of static fields containing reference types.
size_t NumReferenceStaticFields() const {
- DCHECK(IsResolved());
+ DCHECK(IsResolved() || IsErroneous());
DCHECK(sizeof(size_t) == sizeof(int32_t));
return GetField32(
OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
}
size_t NumReferenceStaticFieldsDuringLinking() const {
- DCHECK(IsLoaded());
+ DCHECK(IsLoaded() || IsErroneous());
DCHECK(sizeof(size_t) == sizeof(int32_t));
return GetField32(
OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
@@ -1833,7 +1833,7 @@
}
ObjectArray<Field>* GetSFields() const {
- DCHECK(IsLoaded());
+ DCHECK(IsLoaded() || IsErroneous());
return GetFieldObject<ObjectArray<Field>*>(
OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
}
@@ -1877,7 +1877,7 @@
Field* FindDeclaredStaticField(const StringPiece& name, Class* type);
pid_t GetClinitThreadId() const {
- DCHECK(IsIdxLoaded());
+ DCHECK(IsIdxLoaded() || IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), false);
}
@@ -2113,7 +2113,7 @@
}
inline void Field::SetOffset(MemberOffset num_bytes) {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
Class* type = GetTypeDuringLinking();
if (type != NULL && (type->IsPrimitiveDouble() || type->IsPrimitiveLong())) {
DCHECK(IsAligned(num_bytes.Uint32Value(), 8));
@@ -2126,7 +2126,7 @@
Class* result = GetFieldObject<Class*>(
OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), false);
DCHECK(result != NULL);
- DCHECK(result->IsLoaded());
+ DCHECK(result->IsLoaded() || result->IsErroneous());
return result;
}
@@ -2140,7 +2140,7 @@
GetFieldObject<Class*>(
OFFSET_OF_OBJECT_MEMBER(Method, declaring_class_), false);
DCHECK(result != NULL);
- DCHECK(result->IsLoaded());
+ DCHECK(result->IsLoaded() || result->IsErroneous());
return result;
}
@@ -2150,7 +2150,7 @@
}
inline uint32_t Method::GetReturnTypeIdx() const {
- DCHECK(GetDeclaringClass()->IsResolved());
+ DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_),
false);
}
@@ -2442,7 +2442,7 @@
};
inline const String* Field::GetName() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
String* result =
GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Field, name_), false);
DCHECK(result != NULL);
@@ -2455,29 +2455,29 @@
}
inline uint32_t Field::GetAccessFlags() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), false);
}
inline uint32_t Field::GetTypeIdx() const {
- DCHECK(GetDeclaringClass()->IsIdxLoaded());
+ DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, type_idx_), false);
}
inline MemberOffset Field::GetOffset() const {
- DCHECK(GetDeclaringClass()->IsResolved());
+ DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
return MemberOffset(
GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false));
}
inline MemberOffset Field::GetOffsetDuringLinking() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return MemberOffset(
GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false));
}
inline const String* Method::GetName() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
const String* result =
GetFieldObject<const String*>(
OFFSET_OF_OBJECT_MEMBER(Method, name_), false);
@@ -2512,7 +2512,7 @@
}
inline String* Method::GetShorty() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetFieldObject<String*>(
OFFSET_OF_OBJECT_MEMBER(Method, shorty_), false);
}
@@ -2525,7 +2525,7 @@
}
inline const String* Method::GetSignature() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
const String* result =
GetFieldObject<const String*>(
OFFSET_OF_OBJECT_MEMBER(Method, signature_), false);
@@ -2541,7 +2541,8 @@
inline uint32_t Class::GetAccessFlags() const {
// Check class is loaded or this is java.lang.String that has a
// circularity issue during loading the names of its members
- DCHECK(IsLoaded() || this == String::GetJavaLangString() ||
+ DCHECK(IsLoaded() || IsErroneous() ||
+ this == String::GetJavaLangString() ||
this == Field::GetJavaLangReflectField() ||
this == Method::GetJavaLangReflectMethod()) << PrettyClass(this);
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
@@ -2556,7 +2557,7 @@
}
inline String* Class::GetSourceFile() const {
- DCHECK(IsLoaded());
+ DCHECK(IsLoaded() || IsErroneous());
return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, source_file_), false);
}
@@ -2565,32 +2566,32 @@
}
inline uint32_t Method::GetAccessFlags() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, access_flags_), false);
}
inline uint16_t Method::GetMethodIndex() const {
- DCHECK(GetDeclaringClass()->IsResolved());
+ DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_index_), false);
}
inline uint16_t Method::NumRegisters() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_registers_), false);
}
inline uint16_t Method::NumIns() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_ins_), false);
}
inline uint16_t Method::NumOuts() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_outs_), false);
}
inline uint32_t Method::GetProtoIdx() const {
- DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, proto_idx_), false);
}
diff --git a/src/object_bitmap.cc b/src/object_bitmap.cc
index 4b4c5ee..06d86d6 100644
--- a/src/object_bitmap.cc
+++ b/src/object_bitmap.cc
@@ -18,6 +18,7 @@
#include "UniquePtr.h"
#include "logging.h"
+#include "utils.h"
namespace art {
diff --git a/src/runtime.cc b/src/runtime.cc
index 0990851..e6bd6e2 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -300,8 +300,9 @@
} else {
if (!ignore_unrecognized) {
// TODO: print usage via vfprintf
- LOG(FATAL) << "Unrecognized option " << option;
- return NULL;
+ LOG(ERROR) << "Unrecognized option " << option;
+ // TODO: this should exit, but for now tolerate unknown options
+ //return NULL;
}
}
}
@@ -321,7 +322,9 @@
if (parsed->boot_class_path_.empty()) {
if (parsed->boot_class_path_string_ == NULL) {
const char* BOOTCLASSPATH = getenv("BOOTCLASSPATH");
- parsed->boot_class_path_string_ = BOOTCLASSPATH;
+ if (BOOTCLASSPATH != NULL) {
+ parsed->boot_class_path_string_ = BOOTCLASSPATH;
+ }
}
CreateClassPath(parsed->boot_class_path_string_, parsed->boot_class_path_);
}