summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk20
-rw-r--r--build/Android.common_build.mk7
-rw-r--r--build/Android.common_path.mk24
-rw-r--r--build/Android.common_test.mk6
-rw-r--r--build/Android.gtest.mk6
-rw-r--r--build/Android.oat.mk215
-rw-r--r--compiler/optimizing/builder.cc20
-rw-r--r--compiler/optimizing/code_generator_arm.cc58
-rw-r--r--compiler/optimizing/code_generator_arm64.cc1
-rw-r--r--compiler/optimizing/code_generator_x86.cc50
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc50
-rw-r--r--compiler/optimizing/nodes.h57
-rw-r--r--runtime/class_linker.cc97
-rw-r--r--runtime/dex_file.h3
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc20
-rw-r--r--runtime/gc/space/image_space.cc40
-rw-r--r--runtime/interpreter/interpreter_common.cc5
-rw-r--r--runtime/interpreter/interpreter_common.h12
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc8
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc8
-rw-r--r--runtime/method_helper-inl.h40
-rw-r--r--runtime/method_helper.cc34
-rw-r--r--runtime/method_helper.h23
-rw-r--r--runtime/mirror/art_method-inl.h22
-rw-r--r--runtime/mirror/art_method.cc15
-rw-r--r--runtime/mirror/art_method.h8
-rw-r--r--runtime/mirror/class.h6
-rw-r--r--runtime/oat_file.cc8
-rw-r--r--runtime/reflection.cc4
-rw-r--r--runtime/verifier/method_verifier.cc10
-rw-r--r--test/417-optimizing-arith-div/expected.txt0
-rw-r--r--test/417-optimizing-arith-div/info.txt1
-rw-r--r--test/417-optimizing-arith-div/src/Main.java137
-rw-r--r--test/Android.run-test.mk108
-rwxr-xr-xtest/etc/run-test-jar4
-rwxr-xr-xtest/run-test18
36 files changed, 827 insertions, 318 deletions
diff --git a/Android.mk b/Android.mk
index 282b17918a..22bf305d3c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -23,6 +23,7 @@ art_path := $(LOCAL_PATH)
#
include $(art_path)/build/Android.common_path.mk
+include $(art_path)/build/Android.oat.mk
# Following the example of build's dont_bother for clean targets.
art_dont_bother := false
@@ -41,20 +42,14 @@ clean-oat: clean-oat-host clean-oat-target
.PHONY: clean-oat-host
clean-oat-host:
- rm -f $(HOST_CORE_IMG_OUT)
- rm -f $(HOST_CORE_OAT_OUT)
+ rm -f $(HOST_CORE_IMG_OUTS)
+ rm -f $(HOST_CORE_OAT_OUTS)
rm -f $(HOST_OUT_JAVA_LIBRARIES)/$(ART_HOST_ARCH)/*.odex
ifneq ($(HOST_PREFER_32_BIT),true)
- rm -f $(2ND_HOST_CORE_IMG_OUT)
- rm -f $(2ND_HOST_CORE_OAT_OUT)
rm -f $(HOST_OUT_JAVA_LIBRARIES)/$(2ND_ART_HOST_ARCH)/*.odex
endif
- rm -f $(TARGET_CORE_IMG_OUT)
- rm -f $(TARGET_CORE_OAT_OUT)
-ifdef TARGET_2ND_ARCH
- rm -f $(2ND_TARGET_CORE_IMG_OUT)
- rm -f $(2ND_TARGET_CORE_OAT_OUT)
-endif
+ rm -f $(TARGET_CORE_IMG_OUTS)
+ rm -f $(TARGET_CORE_OAT_OUTS)
rm -rf $(DEXPREOPT_PRODUCT_DIR_FULL_PATH)
rm -f $(TARGET_OUT_UNSTRIPPED)/system/framework/*.odex
rm -f $(TARGET_OUT_UNSTRIPPED)/system/framework/*/*.oat
@@ -109,7 +104,6 @@ include $(art_path)/oatdump/Android.mk
include $(art_path)/patchoat/Android.mk
include $(art_path)/dalvikvm/Android.mk
include $(art_path)/tools/Android.mk
-include $(art_path)/build/Android.oat.mk
include $(art_path)/sigchainlib/Android.mk
@@ -365,10 +359,10 @@ oat-target-sync: oat-target
build-art: build-art-host build-art-target
.PHONY: build-art-host
-build-art-host: $(HOST_OUT_EXECUTABLES)/art $(ART_HOST_DEPENDENCIES) $(HOST_CORE_IMG_OUT) $(2ND_HOST_CORE_IMG_OUT)
+build-art-host: $(HOST_OUT_EXECUTABLES)/art $(ART_HOST_DEPENDENCIES) $(HOST_CORE_IMG_OUTS)
.PHONY: build-art-target
-build-art-target: $(TARGET_OUT_EXECUTABLES)/art $(ART_TARGET_DEPENDENCIES) $(TARGET_CORE_IMG_OUT) $(2ND_TARGET_CORE_IMG_OUT)
+build-art-target: $(TARGET_OUT_EXECUTABLES)/art $(ART_TARGET_DEPENDENCIES) $(TARGET_CORE_IMG_OUTS)
########################################################################
# targets to switch back and forth from libdvm to libart
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk
index 478c63c9a5..d90a31e832 100644
--- a/build/Android.common_build.mk
+++ b/build/Android.common_build.mk
@@ -84,13 +84,6 @@ ART_USE_PORTABLE_COMPILER := true
endif
#
-# Used to enable optimizing compiler
-#
-ifeq ($(ART_USE_OPTIMIZING_COMPILER),true)
-DEX2OAT_FLAGS := --compiler-backend=Optimizing
-endif
-
-#
# Used to change the default GC. Valid values are CMS, SS, GSS. The default is CMS.
#
art_default_gc_type ?= CMS
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk
index 10695b6be7..281d189626 100644
--- a/build/Android.common_path.mk
+++ b/build/Android.common_path.mk
@@ -47,25 +47,33 @@ ifdef TARGET_2ND_ARCH
2ND_TARGET_CORE_OAT := $(ART_TARGET_TEST_DIR)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)/core.oat
endif
+CORE_OAT_SUFFIX := .oat
+
# Core.oat locations under the out directory.
-HOST_CORE_OAT_OUT := $(HOST_OUT_JAVA_LIBRARIES)/$(ART_HOST_ARCH)/core.oat
+HOST_CORE_OAT_OUT_BASE := $(HOST_OUT_JAVA_LIBRARIES)/$(ART_HOST_ARCH)/core
ifneq ($(HOST_PREFER_32_BIT),true)
-2ND_HOST_CORE_OAT_OUT := $(HOST_OUT_JAVA_LIBRARIES)/$(2ND_ART_HOST_ARCH)/core.oat
+2ND_HOST_CORE_OAT_OUT_BASE := $(HOST_OUT_JAVA_LIBRARIES)/$(2ND_ART_HOST_ARCH)/core
endif
-TARGET_CORE_OAT_OUT := $(ART_TARGET_TEST_OUT)/$(DEX2OAT_TARGET_ARCH)/core.oat
+HOST_CORE_OAT_OUTS :=
+TARGET_CORE_OAT_OUT_BASE := $(ART_TARGET_TEST_OUT)/$(DEX2OAT_TARGET_ARCH)/core
ifdef TARGET_2ND_ARCH
-2ND_TARGET_CORE_OAT_OUT := $(ART_TARGET_TEST_OUT)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)/core.oat
+2ND_TARGET_CORE_OAT_OUT_BASE := $(ART_TARGET_TEST_OUT)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)/core
endif
+TARGET_CORE_OAT_OUTS :=
+
+CORE_IMG_SUFFIX := .art
# Core.art locations under the out directory.
-HOST_CORE_IMG_OUT := $(HOST_OUT_JAVA_LIBRARIES)/$(ART_HOST_ARCH)/core.art
+HOST_CORE_IMG_OUT_BASE := $(HOST_OUT_JAVA_LIBRARIES)/$(ART_HOST_ARCH)/core
ifneq ($(HOST_PREFER_32_BIT),true)
-2ND_HOST_CORE_IMG_OUT := $(HOST_OUT_JAVA_LIBRARIES)/$(2ND_ART_HOST_ARCH)/core.art
+2ND_HOST_CORE_IMG_OUT_BASE := $(HOST_OUT_JAVA_LIBRARIES)/$(2ND_ART_HOST_ARCH)/core
endif
-TARGET_CORE_IMG_OUT := $(ART_TARGET_TEST_OUT)/$(DEX2OAT_TARGET_ARCH)/core.art
+HOST_CORE_IMG_OUTS :=
+TARGET_CORE_IMG_OUT_BASE := $(ART_TARGET_TEST_OUT)/$(DEX2OAT_TARGET_ARCH)/core
ifdef TARGET_2ND_ARCH
-2ND_TARGET_CORE_IMG_OUT := $(ART_TARGET_TEST_OUT)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)/core.art
+2ND_TARGET_CORE_IMG_OUT_BASE := $(ART_TARGET_TEST_OUT)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)/core
endif
+TARGET_CORE_IMG_OUTS :=
# Oat location of core.art.
HOST_CORE_IMG_LOCATION := $(HOST_OUT_JAVA_LIBRARIES)/core.art
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk
index ca718f1ed0..2493565120 100644
--- a/build/Android.common_test.mk
+++ b/build/Android.common_test.mk
@@ -63,6 +63,12 @@ ART_TEST_INTERPRETER ?= $(ART_TEST_FULL)
# Do you want optimizing compiler tests run?
ART_TEST_OPTIMIZING ?= $(ART_TEST_FULL)
+# Do we want to test a PIC-compiled core image?
+ART_TEST_PIC_IMAGE ?= $(ART_TEST_FULL)
+
+# Do we want to test PIC-compiled tests ("apps")?
+ART_TEST_PIC_TEST ?= $(ART_TEST_FULL)
+
# Do you want tracing tests run?
ART_TEST_TRACE ?= $(ART_TEST_FULL)
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index db7257a94d..9e640c68aa 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -59,11 +59,11 @@ ART_GTEST_stub_test_DEX_DEPS := AllFields
ART_GTEST_transaction_test_DEX_DEPS := Transaction
# The elf writer test has dependencies on core.oat.
-ART_GTEST_elf_writer_test_HOST_DEPS := $(HOST_CORE_OAT_OUT) $(2ND_HOST_CORE_OAT_OUT)
-ART_GTEST_elf_writer_test_TARGET_DEPS := $(TARGET_CORE_OAT_OUT) $(2ND_TARGET_CORE_OAT_OUT)
+ART_GTEST_elf_writer_test_HOST_DEPS := $(HOST_CORE_IMAGE_default_no-pic_64) $(HOST_CORE_IMAGE_default_no-pic_32)
+ART_GTEST_elf_writer_test_TARGET_DEPS := $(TARGET_CORE_IMAGE_default_no-pic_64) $(TARGET_CORE_IMAGE_default_no-pic_32)
ART_GTEST_jni_internal_test_TARGET_DEPS := $(TARGET_CORE_DEX_FILES)
ART_GTEST_proxy_test_TARGET_DEPS := $(TARGET_CORE_DEX_FILES)
-ART_GTEST_proxy_test_HOST_DEPS := $(HOST_CORE_OAT_OUT) $(2ND_HOST_CORE_OAT_OUT)
+ART_GTEST_proxy_test_HOST_DEPS := $(HOST_CORE_IMAGE_default_no-pic_64) $(HOST_CORE_IMAGE_default_no-pic_32)
# The path for which all the source files are relative, not actually the current directory.
LOCAL_PATH := art
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index 2becbb800f..80a000bf15 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -24,73 +24,186 @@
include art/build/Android.common_build.mk
# Use dex2oat debug version for better error reporting
-# $(1): 2ND_ or undefined, 2ND_ for 32-bit host builds.
+# $(1): compiler - default, optimizing or interpreter.
+# $(2): pic/no-pic
+# $(3): 2ND_ or undefined, 2ND_ for 32-bit host builds.
# NB depending on HOST_CORE_DEX_LOCATIONS so we are sure to have the dex files in frameworks for
# run-test --no-image
define create-core-oat-host-rules
-$$($(1)HOST_CORE_IMG_OUT): $$(HOST_CORE_DEX_LOCATIONS) $$(DEX2OAT_DEPENDENCY)
+ core_compile_options :=
+ core_image_name :=
+ core_oat_name :=
+ core_infix :=
+ core_pic_infix :=
+
+ ifeq ($(1),optimizing)
+ core_compile_options += --compiler-backend=optimizing
+ core_infix := -optimizing
+ endif
+ ifeq ($(1),interpreter)
+ core_compile_options += --compiler-filter=interpret-only
+ core_infix := -interpreter
+ endif
+ ifeq ($(1),default)
+ # Default has no infix, no compile options.
+ endif
+ ifneq ($(filter-out default interpreter optimizing,$(1)),)
+ #Technically this test is not precise, but hopefully good enough.
+ $$(error found $(1) expected default, interpreter or optimizing)
+ endif
+
+ ifeq ($(2),pic)
+ core_compile_options += --compile-pic
+ core_pic_infix := -pic
+ endif
+ ifeq ($(2),no-pic)
+ # No change for non-pic
+ endif
+ ifneq ($(filter-out pic no-pic,$(2)),)
+ # Technically this test is not precise, but hopefully good enough.
+ $$(error found $(2) expected pic or no-pic)
+ endif
+
+ core_image_name := $($(3)HOST_CORE_IMG_OUT_BASE)$$(core_infix)$$(core_pic_infix)$(CORE_IMG_SUFFIX)
+ core_oat_name := $($(3)HOST_CORE_OAT_OUT_BASE)$$(core_infix)$$(core_pic_infix)$(CORE_OAT_SUFFIX)
+
+ # Using the bitness suffix makes it easier to add as a dependency for the run-test mk.
+ ifeq ($(3),)
+ HOST_CORE_IMAGE_$(1)_$(2)_64 := $$(core_image_name)
+ else
+ HOST_CORE_IMAGE_$(1)_$(2)_32 := $$(core_image_name)
+ endif
+ HOST_CORE_IMG_OUTS += $$(core_image_name)
+ HOST_CORE_OAT_OUTS += $$(core_oat_name)
+
+$$(core_image_name): PRIVATE_CORE_COMPILE_OPTIONS := $$(core_compile_options)
+$$(core_image_name): PRIVATE_CORE_IMG_NAME := $$(core_image_name)
+$$(core_image_name): PRIVATE_CORE_OAT_NAME := $$(core_oat_name)
+$$(core_image_name): $$(HOST_CORE_DEX_LOCATIONS) $$(DEX2OAT_DEPENDENCY)
@echo "host dex2oat: $$@ ($$?)"
@mkdir -p $$(dir $$@)
- $$(hide) $$(DEX2OAT) $$(DEX2OAT_FLAGS) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) --runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
+ $$(hide) $$(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) --runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
--image-classes=$$(PRELOADED_CLASSES) $$(addprefix --dex-file=,$$(HOST_CORE_DEX_FILES)) \
- $$(addprefix --dex-location=,$$(HOST_CORE_DEX_LOCATIONS)) --oat-file=$$($(1)HOST_CORE_OAT_OUT) \
- --oat-location=$$($(1)HOST_CORE_OAT) --image=$$($(1)HOST_CORE_IMG_OUT) \
- --base=$$(LIBART_IMG_HOST_BASE_ADDRESS) --instruction-set=$$($(1)ART_HOST_ARCH) \
- --instruction-set-features=$$($(1)HOST_INSTRUCTION_SET_FEATURES) \
- --host --android-root=$$(HOST_OUT) --include-patch-information
+ $$(addprefix --dex-location=,$$(HOST_CORE_DEX_LOCATIONS)) --oat-file=$$(PRIVATE_CORE_OAT_NAME) \
+ --oat-location=$$(PRIVATE_CORE_OAT_NAME) --image=$$(PRIVATE_CORE_IMG_NAME) \
+ --base=$$(LIBART_IMG_HOST_BASE_ADDRESS) --instruction-set=$$($(3)ART_HOST_ARCH) \
+ --instruction-set-features=$$($(3)HOST_INSTRUCTION_SET_FEATURES) \
+ --host --android-root=$$(HOST_OUT) --include-patch-information \
+ $$(PRIVATE_CORE_COMPILE_OPTIONS)
-# This "renaming" eases declaration in art/Android.mk
-HOST_CORE_IMG_OUT$($(1)ART_PHONY_TEST_HOST_SUFFIX) := $($(1)HOST_CORE_IMG_OUT)
+$$(core_oat_name): $$(core_image_name)
-$$($(1)HOST_CORE_OAT_OUT): $$($(1)HOST_CORE_IMG_OUT)
+ # Clean up locally used variables.
+ core_compile_options :=
+ core_image_name :=
+ core_oat_name :=
+ core_infix :=
+ core_pic_infix :=
endef # create-core-oat-host-rules
-$(eval $(call create-core-oat-host-rules,))
-ifneq ($(HOST_PREFER_32_BIT),true)
-$(eval $(call create-core-oat-host-rules,2ND_))
-endif
+# $(1): compiler - default, optimizing or interpreter.
+define create-core-oat-host-rule-combination
+ $(call create-core-oat-host-rules,$(1),no-pic,)
+ $(call create-core-oat-host-rules,$(1),pic,)
+
+ ifneq ($(HOST_PREFER_32_BIT),true)
+ $(call create-core-oat-host-rules,$(1),no-pic,2ND_)
+ $(call create-core-oat-host-rules,$(1),pic,2ND_)
+ endif
+endef
+
+$(eval $(call create-core-oat-host-rule-combination,default))
+$(eval $(call create-core-oat-host-rule-combination,optimizing))
+$(eval $(call create-core-oat-host-rule-combination,interpreter))
+
define create-core-oat-target-rules
-$$($(1)TARGET_CORE_IMG_OUT): $$(TARGET_CORE_DEX_FILES) $$(DEX2OAT_DEPENDENCY)
+ core_compile_options :=
+ core_image_name :=
+ core_oat_name :=
+ core_infix :=
+ core_pic_infix :=
+
+ ifeq ($(1),optimizing)
+ core_compile_options += --compiler-backend=optimizing
+ core_infix := -optimizing
+ endif
+ ifeq ($(1),interpreter)
+ core_compile_options += --compiler-filter=interpret-only
+ core_infix := -interpreter
+ endif
+ ifeq ($(1),default)
+ # Default has no infix, no compile options.
+ endif
+ ifneq ($(filter-out default interpreter optimizing,$(1)),)
+ # Technically this test is not precise, but hopefully good enough.
+ $$(error found $(1) expected default, interpreter or optimizing)
+ endif
+
+ ifeq ($(2),pic)
+ core_compile_options += --compile-pic
+ core_pic_infix := -pic
+ endif
+ ifeq ($(2),no-pic)
+ # No change for non-pic
+ endif
+ ifneq ($(filter-out pic no-pic,$(2)),)
+ #Technically this test is not precise, but hopefully good enough.
+ $$(error found $(2) expected pic or no-pic)
+ endif
+
+ core_image_name := $($(3)TARGET_CORE_IMG_OUT_BASE)$$(core_infix)$$(core_pic_infix)$(CORE_IMG_SUFFIX)
+ core_oat_name := $($(3)TARGET_CORE_OAT_OUT_BASE)$$(core_infix)$$(core_pic_infix)$(CORE_OAT_SUFFIX)
+
+ # Using the bitness suffix makes it easier to add as a dependency for the run-test mk.
+ ifeq ($(3),)
+ ifdef TARGET_2ND_ARCH
+ TARGET_CORE_IMAGE_$(1)_$(2)_64 := $$(core_image_name)
+ else
+ TARGET_CORE_IMAGE_$(1)_$(2)_32 := $$(core_image_name)
+ endif
+ else
+ TARGET_CORE_IMAGE_$(1)_$(2)_32 := $$(core_image_name)
+ endif
+ TARGET_CORE_IMG_OUTS += $$(core_image_name)
+ TARGET_CORE_OAT_OUTS += $$(core_oat_name)
+
+$$(core_image_name): PRIVATE_CORE_COMPILE_OPTIONS := $$(core_compile_options)
+$$(core_image_name): PRIVATE_CORE_IMG_NAME := $$(core_image_name)
+$$(core_image_name): PRIVATE_CORE_OAT_NAME := $$(core_oat_name)
+$$(core_image_name): $$(TARGET_CORE_DEX_FILES) $$(DEX2OAT_DEPENDENCY)
@echo "target dex2oat: $$@ ($$?)"
@mkdir -p $$(dir $$@)
- $$(hide) $$(DEX2OAT) $$(DEX2OAT_FLAGS) --runtime-arg -Xms$(DEX2OAT_XMS) --runtime-arg -Xmx$(DEX2OAT_XMX) \
+ $$(hide) $$(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_XMS) --runtime-arg -Xmx$(DEX2OAT_XMX) \
--image-classes=$$(PRELOADED_CLASSES) $$(addprefix --dex-file=,$$(TARGET_CORE_DEX_FILES)) \
- $$(addprefix --dex-location=,$$(TARGET_CORE_DEX_LOCATIONS)) --oat-file=$$($(1)TARGET_CORE_OAT_OUT) \
- --oat-location=$$($(1)TARGET_CORE_OAT) --image=$$($(1)TARGET_CORE_IMG_OUT) \
- --base=$$(LIBART_IMG_TARGET_BASE_ADDRESS) --instruction-set=$$($(1)TARGET_ARCH) \
- --instruction-set-features=$$($(1)TARGET_INSTRUCTION_SET_FEATURES) \
- --android-root=$$(PRODUCT_OUT)/system --include-patch-information
+ $$(addprefix --dex-location=,$$(TARGET_CORE_DEX_LOCATIONS)) --oat-file=$$(PRIVATE_CORE_OAT_NAME) \
+ --oat-location=$$(PRIVATE_CORE_OAT_NAME) --image=$$(PRIVATE_CORE_IMG_NAME) \
+ --base=$$(LIBART_IMG_TARGET_BASE_ADDRESS) --instruction-set=$$($(3)TARGET_ARCH) \
+ --instruction-set-features=$$($(3)TARGET_INSTRUCTION_SET_FEATURES) \
+ --android-root=$$(PRODUCT_OUT)/system --include-patch-information \
+ $$(PRIVATE_CORE_COMPILE_OPTIONS)
-# This "renaming" eases declaration in art/Android.mk
-TARGET_CORE_IMG_OUT$($(1)ART_PHONY_TEST_TARGET_SUFFIX) := $($(1)TARGET_CORE_IMG_OUT)
+$$(core_oat_name): $$(core_image_name)
-$$($(1)TARGET_CORE_OAT_OUT): $$($(1)TARGET_CORE_IMG_OUT)
+ # Clean up locally used variables.
+ core_compile_options :=
+ core_image_name :=
+ core_oat_name :=
+ core_infix :=
+ core_pic_infix :=
endef # create-core-oat-target-rules
-ifdef TARGET_2ND_ARCH
-$(eval $(call create-core-oat-target-rules,2ND_))
-endif
-$(eval $(call create-core-oat-target-rules,))
-
-
-ifeq ($(ART_BUILD_HOST),true)
-include $(CLEAR_VARS)
-LOCAL_MODULE := core.art-host
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common.mk
-LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.oat.mk
-LOCAL_ADDITIONAL_DEPENDENCIES += $(HOST_CORE_IMG_OUT)
-include $(BUILD_PHONY_PACKAGE)
-endif # ART_BUILD_HOST
-
-# If we aren't building the host toolchain, skip building the target core.art.
-ifeq ($(ART_BUILD_TARGET),true)
-include $(CLEAR_VARS)
-LOCAL_MODULE := core.art
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common.mk
-LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.oat.mk
-LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_CORE_IMG_OUT)
-include $(BUILD_PHONY_PACKAGE)
-endif # ART_BUILD_TARGET
+# $(1): compiler - default, optimizing or interpreter.
+define create-core-oat-target-rule-combination
+ $(call create-core-oat-target-rules,$(1),no-pic,)
+ $(call create-core-oat-target-rules,$(1),pic,)
+
+ ifdef TARGET_2ND_ARCH
+ $(call create-core-oat-target-rules,$(1),no-pic,2ND_)
+ $(call create-core-oat-target-rules,$(1),pic,2ND_)
+ endif
+endef
+
+$(eval $(call create-core-oat-target-rule-combination,default))
+$(eval $(call create-core-oat-target-rule-combination,optimizing))
+$(eval $(call create-core-oat-target-rule-combination,interpreter))
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index cc9c6c15b2..f80ebdb5ec 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -828,6 +828,16 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32
break;
}
+ case Instruction::DIV_FLOAT: {
+ Binop_23x<HDiv>(instruction, Primitive::kPrimFloat);
+ break;
+ }
+
+ case Instruction::DIV_DOUBLE: {
+ Binop_23x<HDiv>(instruction, Primitive::kPrimDouble);
+ break;
+ }
+
case Instruction::ADD_LONG_2ADDR: {
Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
break;
@@ -883,6 +893,16 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32
break;
}
+ case Instruction::DIV_FLOAT_2ADDR: {
+ Binop_12x<HDiv>(instruction, Primitive::kPrimFloat);
+ break;
+ }
+
+ case Instruction::DIV_DOUBLE_2ADDR: {
+ Binop_12x<HDiv>(instruction, Primitive::kPrimDouble);
+ break;
+ }
+
case Instruction::ADD_INT_LIT16: {
Binop_22s<HAdd>(instruction, false);
break;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 7adf2ccc84..a5d4c43c28 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1128,7 +1128,7 @@ void LocationsBuilderARM::VisitAdd(HAdd* add) {
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetInAt(1, Location::RequiresFpuRegister());
- locations->SetOut(Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
}
@@ -1193,7 +1193,7 @@ void LocationsBuilderARM::VisitSub(HSub* sub) {
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetInAt(1, Location::RequiresFpuRegister());
- locations->SetOut(Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
}
default:
@@ -1262,7 +1262,7 @@ void LocationsBuilderARM::VisitMul(HMul* mul) {
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetInAt(1, Location::RequiresFpuRegister());
- locations->SetOut(Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
}
@@ -1329,6 +1329,58 @@ void InstructionCodeGeneratorARM::VisitMul(HMul* mul) {
}
}
+void LocationsBuilderARM::VisitDiv(HDiv* div) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
+void InstructionCodeGeneratorARM::VisitDiv(HDiv* div) {
+ LocationSummary* locations = div->GetLocations();
+ Location out = locations->Out();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+
+ case Primitive::kPrimFloat: {
+ __ vdivs(out.As<SRegister>(), first.As<SRegister>(), second.As<SRegister>());
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ __ vdivd(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
+ FromLowSToD(first.AsFpuRegisterPairLow<SRegister>()),
+ FromLowSToD(second.AsFpuRegisterPairLow<SRegister>()));
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 79528ac128..f9aa44b5b7 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -535,6 +535,7 @@ InstructionCodeGeneratorARM64::InstructionCodeGeneratorARM64(HGraph* graph,
M(ArrayGet) \
M(ArraySet) \
M(DoubleConstant) \
+ M(Div) \
M(FloatConstant) \
M(Mul) \
M(Neg) \
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 99fa11d5a5..495ff8b4a4 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1293,6 +1293,56 @@ void InstructionCodeGeneratorX86::VisitMul(HMul* mul) {
}
}
+void LocationsBuilderX86::VisitDiv(HDiv* div) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::SameAsFirstInput());
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
+void InstructionCodeGeneratorX86::VisitDiv(HDiv* div) {
+ LocationSummary* locations = div->GetLocations();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+ DCHECK(first.Equals(locations->Out()));
+
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+
+ case Primitive::kPrimFloat: {
+ __ divss(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ __ divsd(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 163156a955..4d11a2409d 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1218,6 +1218,56 @@ void InstructionCodeGeneratorX86_64::VisitMul(HMul* mul) {
}
}
+void LocationsBuilderX86_64::VisitDiv(HDiv* div) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::SameAsFirstInput());
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
+void InstructionCodeGeneratorX86_64::VisitDiv(HDiv* div) {
+ LocationSummary* locations = div->GetLocations();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+ DCHECK(first.Equals(locations->Out()));
+
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+
+ case Primitive::kPrimFloat: {
+ __ divss(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ __ divsd(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
void LocationsBuilderX86_64::VisitNewInstance(HNewInstance* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 7adb84008a..f530708aeb 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -468,46 +468,47 @@ class HBasicBlock : public ArenaObject {
#define FOR_EACH_CONCRETE_INSTRUCTION(M) \
M(Add, BinaryOperation) \
+ M(ArrayGet, Instruction) \
+ M(ArrayLength, Instruction) \
+ M(ArraySet, Instruction) \
+ M(BoundsCheck, Instruction) \
+ M(Compare, BinaryOperation) \
M(Condition, BinaryOperation) \
+ M(Div, BinaryOperation) \
+ M(DoubleConstant, Constant) \
M(Equal, Condition) \
- M(NotEqual, Condition) \
- M(LessThan, Condition) \
- M(LessThanOrEqual, Condition) \
- M(GreaterThan, Condition) \
- M(GreaterThanOrEqual, Condition) \
M(Exit, Instruction) \
+ M(FloatConstant, Constant) \
M(Goto, Instruction) \
+ M(GreaterThan, Condition) \
+ M(GreaterThanOrEqual, Condition) \
M(If, Instruction) \
+ M(InstanceFieldGet, Instruction) \
+ M(InstanceFieldSet, Instruction) \
M(IntConstant, Constant) \
M(InvokeStatic, Invoke) \
M(InvokeVirtual, Invoke) \
+ M(LessThan, Condition) \
+ M(LessThanOrEqual, Condition) \
M(LoadLocal, Instruction) \
M(Local, Instruction) \
M(LongConstant, Constant) \
+ M(Mul, BinaryOperation) \
+ M(Neg, UnaryOperation) \
+ M(NewArray, Instruction) \
M(NewInstance, Instruction) \
M(Not, UnaryOperation) \
- M(ParameterValue, Instruction) \
+ M(NotEqual, Condition) \
+ M(NullCheck, Instruction) \
M(ParallelMove, Instruction) \
+ M(ParameterValue, Instruction) \
M(Phi, Instruction) \
M(Return, Instruction) \
M(ReturnVoid, Instruction) \
M(StoreLocal, Instruction) \
M(Sub, BinaryOperation) \
- M(Compare, BinaryOperation) \
- M(InstanceFieldGet, Instruction) \
- M(InstanceFieldSet, Instruction) \
- M(ArrayGet, Instruction) \
- M(ArraySet, Instruction) \
- M(ArrayLength, Instruction) \
- M(BoundsCheck, Instruction) \
- M(NullCheck, Instruction) \
- M(Temporary, Instruction) \
M(SuspendCheck, Instruction) \
- M(Mul, BinaryOperation) \
- M(Neg, UnaryOperation) \
- M(FloatConstant, Constant) \
- M(DoubleConstant, Constant) \
- M(NewArray, Instruction) \
+ M(Temporary, Instruction) \
#define FOR_EACH_INSTRUCTION(M) \
FOR_EACH_CONCRETE_INSTRUCTION(M) \
@@ -1658,8 +1659,6 @@ class HSub : public HBinaryOperation {
HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
: HBinaryOperation(result_type, left, right) {}
- virtual bool IsCommutative() { return false; }
-
virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
return x - y;
}
@@ -1689,6 +1688,20 @@ class HMul : public HBinaryOperation {
DISALLOW_COPY_AND_ASSIGN(HMul);
};
+class HDiv : public HBinaryOperation {
+ public:
+ HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right)
+ : HBinaryOperation(result_type, left, right) {}
+
+ virtual int32_t Evaluate(int32_t x, int32_t y) const { return x / y; }
+ virtual int64_t Evaluate(int64_t x, int64_t y) const { return x / y; }
+
+ DECLARE_INSTRUCTION(Div);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HDiv);
+};
+
// The value of a parameter in this method. Its location depends on
// the calling convention.
class HParameterValue : public HExpression<0> {
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f01f2c64b6..e2514ec9b0 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4051,13 +4051,10 @@ static void CheckProxyMethod(Handle<mirror::ArtMethod> method,
CHECK(prototype->HasSameDexCacheResolvedTypes(method.Get()));
CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex());
- StackHandleScope<2> hs(Thread::Current());
- MethodHelper mh(hs.NewHandle(method.Get()));
- MethodHelper mh2(hs.NewHandle(prototype.Get()));
CHECK_STREQ(method->GetName(), prototype->GetName());
CHECK_STREQ(method->GetShorty(), prototype->GetShorty());
// More complex sanity - via dex cache
- CHECK_EQ(mh.GetReturnType(), mh2.GetReturnType());
+ CHECK_EQ(method->GetInterfaceMethodIfProxy()->GetReturnType(), prototype->GetReturnType());
}
static bool CanWeInitializeClass(mirror::Class* klass, bool can_init_statics,
@@ -4209,13 +4206,28 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
}
}
- if (klass->NumStaticFields() > 0) {
+ const size_t num_static_fields = klass->NumStaticFields();
+ if (num_static_fields > 0) {
const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
const DexFile& dex_file = klass->GetDexFile();
StackHandleScope<3> hs(self);
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
+
+ // Eagerly fill in static fields so that the we don't have to do as many expensive
+ // Class::FindStaticField in ResolveField.
+ for (size_t i = 0; i < num_static_fields; ++i) {
+ mirror::ArtField* field = klass->GetStaticField(i);
+ const uint32_t field_idx = field->GetDexFieldIndex();
+ mirror::ArtField* resolved_field = dex_cache->GetResolvedField(field_idx);
+ if (resolved_field == nullptr) {
+ dex_cache->SetResolvedField(field_idx, field);
+ } else if (kIsDebugBuild) {
+ CHECK_EQ(field, resolved_field);
+ }
+ }
+
EncodedStaticFieldValueIterator value_it(dex_file, &dex_cache, &class_loader,
this, *dex_class_def);
const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
@@ -4322,7 +4334,8 @@ bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) {
return true;
}
// Begin with the methods local to the superclass.
- StackHandleScope<2> hs(Thread::Current());
+ Thread* self = Thread::Current();
+ StackHandleScope<2> hs(self);
MutableMethodHelper mh(hs.NewHandle<mirror::ArtMethod>(nullptr));
MutableMethodHelper super_mh(hs.NewHandle<mirror::ArtMethod>(nullptr));
if (klass->HasSuperClass() &&
@@ -4331,7 +4344,7 @@ bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) {
mh.ChangeMethod(klass->GetVTableEntry(i));
super_mh.ChangeMethod(klass->GetSuperClass()->GetVTableEntry(i));
if (mh.GetMethod() != super_mh.GetMethod() &&
- !mh.HasSameSignatureWithDifferentClassLoaders(&super_mh)) {
+ !mh.HasSameSignatureWithDifferentClassLoaders(self, &super_mh)) {
ThrowLinkageError(klass.Get(),
"Class %s method %s resolves differently in superclass %s",
PrettyDescriptor(klass.Get()).c_str(),
@@ -4348,7 +4361,7 @@ bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) {
mh.ChangeMethod(klass->GetIfTable()->GetMethodArray(i)->GetWithoutChecks(j));
super_mh.ChangeMethod(klass->GetIfTable()->GetInterface(i)->GetVirtualMethod(j));
if (mh.GetMethod() != super_mh.GetMethod() &&
- !mh.HasSameSignatureWithDifferentClassLoaders(&super_mh)) {
+ !mh.HasSameSignatureWithDifferentClassLoaders(self, &super_mh)) {
ThrowLinkageError(klass.Get(),
"Class %s method %s resolves differently in interface %s",
PrettyDescriptor(klass.Get()).c_str(),
@@ -4610,6 +4623,49 @@ bool ClassLinker::LinkMethods(Thread* self, Handle<mirror::Class> klass,
return LinkInterfaceMethods(self, klass, interfaces, out_imt); // Link interface method last.
}
+// Comparator for name and signature of a method, used in finding overriding methods. Implementation
+// avoids the use of handles, if it didn't then rather than compare dex files we could compare dex
+// caches in the implementation below.
+class MethodNameAndSignatureComparator FINAL : public ValueObject {
+ public:
+ explicit MethodNameAndSignatureComparator(mirror::ArtMethod* method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
+ dex_file_(method->GetDexFile()), mid_(&dex_file_->GetMethodId(method->GetDexMethodIndex())),
+ name_(nullptr), name_len_(0) {
+ DCHECK(!method->IsProxyMethod()) << PrettyMethod(method);
+ }
+
+ bool HasSameNameAndSignature(mirror::ArtMethod* other)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(!other->IsProxyMethod()) << PrettyMethod(other);
+ const DexFile* other_dex_file = other->GetDexFile();
+ const DexFile::MethodId& other_mid = other_dex_file->GetMethodId(other->GetDexMethodIndex());
+ if (dex_file_ == other_dex_file) {
+ return mid_->name_idx_ == other_mid.name_idx_ && mid_->proto_idx_ == other_mid.proto_idx_;
+ }
+ if (name_ == nullptr) {
+ name_ = dex_file_->StringDataAndUtf16LengthByIdx(mid_->name_idx_, &name_len_);
+ }
+ uint32_t other_name_len;
+ const char* other_name = other_dex_file->StringDataAndUtf16LengthByIdx(other_mid.name_idx_,
+ &other_name_len);
+ if (name_len_ != other_name_len || strcmp(name_, other_name) != 0) {
+ return false;
+ }
+ return dex_file_->GetMethodSignature(*mid_) == other_dex_file->GetMethodSignature(other_mid);
+ }
+
+ private:
+ // Dex file for the method to compare against.
+ const DexFile* const dex_file_;
+ // MethodId for the method to compare against.
+ const DexFile::MethodId* const mid_;
+ // Lazily computed name from the dex file's strings.
+ const char* name_;
+ // Lazily computed name length.
+ uint32_t name_len_;
+};
+
bool ClassLinker::LinkVirtualMethods(Thread* self, Handle<mirror::Class> klass) {
const size_t num_virtual_methods = klass->NumVirtualMethods();
if (klass->HasSuperClass()) {
@@ -4640,12 +4696,15 @@ bool ClassLinker::LinkVirtualMethods(Thread* self, Handle<mirror::Class> klass)
// See if any of our virtual methods override the superclass.
for (size_t i = 0; i < num_virtual_methods; ++i) {
mirror::ArtMethod* local_method = klass->GetVirtualMethodDuringLinking(i);
- MethodProtoHelper local_helper(local_method);
+ MethodNameAndSignatureComparator
+ virtual_method_name_comparator(local_method->GetInterfaceMethodIfProxy());
size_t j = 0;
for (; j < actual_count; ++j) {
mirror::ArtMethod* super_method = vtable->GetWithoutChecks(j);
- MethodProtoHelper super_helper(super_method);
- if (local_helper.HasSameNameAndSignature(super_helper)) {
+ if (super_method->GetDeclaringClass() == klass.Get()) {
+ continue; // A previously overridden method.
+ }
+ if (virtual_method_name_comparator.HasSameNameAndSignature(super_method)) {
if (klass->CanAccessMember(super_method->GetDeclaringClass(),
super_method->GetAccessFlags())) {
if (super_method->IsFinal()) {
@@ -4903,7 +4962,7 @@ bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass
}
for (size_t j = 0; j < num_methods; ++j) {
mirror::ArtMethod* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j);
- MethodProtoHelper interface_helper(interface_method);
+ MethodNameAndSignatureComparator interface_name_comparator(interface_method);
int32_t k;
// For each method listed in the interface's method list, find the
// matching method in our class's method list. We want to favor the
@@ -4915,8 +4974,10 @@ bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass
// matter which direction we go. We walk it backward anyway.)
for (k = input_array->GetLength() - 1; k >= 0; --k) {
mirror::ArtMethod* vtable_method = input_array->GetWithoutChecks(k);
- MethodProtoHelper vtable_helper(vtable_method);
- if (interface_helper.HasSameNameAndSignature(vtable_helper)) {
+ mirror::ArtMethod* vtable_method_for_name_comparison =
+ vtable_method->GetInterfaceMethodIfProxy();
+ if (interface_name_comparator.HasSameNameAndSignature(
+ vtable_method_for_name_comparison)) {
if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) {
ThrowIllegalAccessError(
klass.Get(),
@@ -4935,7 +4996,10 @@ bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass
} else if (imt_ref != conflict_method) {
// If we are not a conflict and we have the same signature and name as the imt entry,
// it must be that we overwrote a superclass vtable entry.
- if (MethodProtoHelper(imt_ref).HasSameNameAndSignature(vtable_helper)) {
+ MethodNameAndSignatureComparator
+ imt_ref_name_comparator(imt_ref->GetInterfaceMethodIfProxy());
+ if (imt_ref_name_comparator.HasSameNameAndSignature(
+ vtable_method_for_name_comparison)) {
out_imt->SetReference(imt_index, vtable_method);
} else {
out_imt->SetReference(imt_index, conflict_method);
@@ -4948,8 +5012,7 @@ bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass
mirror::ArtMethod* miranda_method = nullptr;
for (size_t l = 0; l < miranda_list_size; ++l) {
mirror::ArtMethod* mir_method = miranda_list->Get(l);
- MethodProtoHelper vtable_helper(mir_method);
- if (interface_helper.HasSameNameAndSignature(vtable_helper)) {
+ if (interface_name_comparator.HasSameNameAndSignature(mir_method)) {
miranda_method = mir_method;
break;
}
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 620bd6eeab..10fe6bf9af 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -24,6 +24,7 @@
#include "base/logging.h"
#include "base/mutex.h" // For Locks::mutator_lock_.
+#include "base/value_object.h"
#include "globals.h"
#include "invoke_type.h"
#include "jni.h"
@@ -1027,7 +1028,7 @@ class DexFileParameterIterator {
};
// Abstract the signature of a method.
-class Signature {
+class Signature : public ValueObject {
public:
std::string ToString() const;
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 7b90339b68..da2dfe11d0 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -218,17 +218,14 @@ void CheckReferenceResult(mirror::Object* o, Thread* self) {
if (o == nullptr) {
return;
}
- mirror::ArtMethod* m = self->GetCurrentMethod(nullptr);
// Make sure that the result is an instance of the type this method was expected to return.
- StackHandleScope<1> hs(self);
- Handle<mirror::ArtMethod> h_m(hs.NewHandle(m));
- mirror::Class* return_type = MethodHelper(h_m).GetReturnType();
+ mirror::Class* return_type = self->GetCurrentMethod(nullptr)->GetReturnType();
if (!o->InstanceOf(return_type)) {
Runtime::Current()->GetJavaVM()->JniAbortF(nullptr,
"attempt to return an instance of %s from %s",
PrettyTypeOf(o).c_str(),
- PrettyMethod(h_m.Get()).c_str());
+ PrettyMethod(self->GetCurrentMethod(nullptr)).c_str());
}
}
@@ -283,20 +280,19 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, cons
return zero;
} else {
StackHandleScope<1> hs(soa.Self());
- MethodHelper mh_interface_method(
+ Handle<mirror::ArtMethod> h_interface_method(
hs.NewHandle(soa.Decode<mirror::ArtMethod*>(interface_method_jobj)));
// This can cause thread suspension.
- mirror::Class* result_type = mh_interface_method.GetReturnType();
+ mirror::Class* result_type = h_interface_method->GetReturnType();
mirror::Object* result_ref = soa.Decode<mirror::Object*>(result);
mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
mirror::ArtMethod* proxy_method;
- if (mh_interface_method.GetMethod()->GetDeclaringClass()->IsInterface()) {
- proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(
- mh_interface_method.GetMethod());
+ if (h_interface_method->GetDeclaringClass()->IsInterface()) {
+ proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(h_interface_method.Get());
} else {
// Proxy dispatch to a method defined in Object.
- DCHECK(mh_interface_method.GetMethod()->GetDeclaringClass()->IsObjectClass());
- proxy_method = mh_interface_method.GetMethod();
+ DCHECK(h_interface_method->GetDeclaringClass()->IsObjectClass());
+ proxy_method = h_interface_method.Get();
}
ThrowLocation throw_location(rcvr, proxy_method, -1);
JValue result_unboxed;
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 5b77540dcd..6e1639c8e4 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -115,18 +115,6 @@ static void RealPruneDexCache(const std::string& cache_dir_path) {
CHECK_EQ(0, TEMP_FAILURE_RETRY(closedir(cache_dir))) << "Unable to close directory.";
}
-static void RemoveImageFiles(const std::string& image_filename, std::string* error_msg) {
- if (TEMP_FAILURE_RETRY(unlink(image_filename.c_str())) != 0) {
- *error_msg = StringPrintf("Failed to remove image file after previous error: %s",
- error_msg->c_str());
- }
- std::string oat_filename(ImageHeader::GetOatLocationFromImageLocation(image_filename));
- if (TEMP_FAILURE_RETRY(unlink(oat_filename.c_str())) != 0) {
- *error_msg = StringPrintf("Failed to remove oat file after previous error: %s",
- error_msg->c_str());
- }
-}
-
static bool GenerateImage(const std::string& image_filename, InstructionSet image_isa,
std::string* error_msg) {
const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());
@@ -445,7 +433,11 @@ ImageSpace* ImageSpace::Create(const char* image_location,
*error_msg = StringPrintf("Unable to relocate image '%s' from '%s' to '%s': %s",
image_location, system_filename.c_str(),
cache_filename.c_str(), reason.c_str());
- RemoveImageFiles(cache_filename, error_msg);
+ // We failed to create files, remove any possibly garbage output.
+ // Since ImageCreationAllowed was true above, we are the zygote
+ // and therefore the only process expected to generate these for
+ // the device.
+ PruneDexCache(image_isa);
return nullptr;
}
}
@@ -492,19 +484,23 @@ ImageSpace* ImageSpace::Create(const char* image_location,
return space;
}
- // If the /system file exists, it should be up-to-date, don't try to generate it. Same if it is
- // a relocated copy from something in /system (i.e. checksum's match).
- // Otherwise, log a warning and fall through to GenerateImage.
if (relocated_version_used) {
- LOG(FATAL) << "Attempted to use relocated version of " << image_location << " "
- << "at " << cache_filename << " generated from " << system_filename << " "
- << "but image failed to load: " << *error_msg;
+ // Something is wrong with the relocated copy (even though checksums match). Cleanup.
+ // This can happen if the .oat is corrupt, since the above only checks the .art checksums.
+ // TODO: Check the oat file validity earlier.
+ *error_msg = StringPrintf("Attempted to use relocated version of %s at %s generated from %s "
+ "but image failed to load: %s",
+ image_location, cache_filename.c_str(), system_filename.c_str(),
+ error_msg->c_str());
+ PruneDexCache(image_isa);
return nullptr;
} else if (is_system) {
+ // If the /system file exists, it should be up-to-date, don't try to generate it.
*error_msg = StringPrintf("Failed to load /system image '%s': %s",
image_filename->c_str(), error_msg->c_str());
return nullptr;
} else {
+ // Otherwise, log a warning and fall through to GenerateImage.
LOG(WARNING) << *error_msg;
}
}
@@ -520,7 +516,11 @@ ImageSpace* ImageSpace::Create(const char* image_location,
} else if (!GenerateImage(cache_filename, image_isa, error_msg)) {
*error_msg = StringPrintf("Failed to generate image '%s': %s",
cache_filename.c_str(), error_msg->c_str());
- RemoveImageFiles(cache_filename, error_msg);
+ // We failed to create files, remove any possibly garbage output.
+ // Since ImageCreationAllowed was true above, we are the zygote
+ // and therefore the only process expected to generate these for
+ // the device.
+ PruneDexCache(image_isa);
return nullptr;
} else {
// Note that we must not use the file descriptor associated with
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index c887a8877f..5c77b96a5f 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -891,9 +891,8 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper* mh,
Object* obj = shadow_frame->GetVRegReference(arg_offset);
result->SetI(obj->IdentityHashCode());
} else if (name == "java.lang.String java.lang.reflect.ArtMethod.getMethodName(java.lang.reflect.ArtMethod)") {
- StackHandleScope<1> hs(self);
- MethodHelper mh(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsArtMethod()));
- result->SetL(mh.GetNameAsString(self));
+ mirror::ArtMethod* method = shadow_frame->GetVRegReference(arg_offset)->AsArtMethod();
+ result->SetL(method->GetNameAsString(self));
} else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)" ||
name == "void java.lang.System.arraycopy(char[], int, char[], int, int)") {
// Special case array copying without initializing System.
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index fa03fc7fa9..6a0aaf252f 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -187,7 +187,7 @@ bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint1
// Handles string resolution for const-string and const-string-jumbo instructions. Also ensures the
// java.lang.String class is initialized.
-static inline String* ResolveString(Thread* self, MethodHelper& mh, uint32_t string_idx)
+static inline String* ResolveString(Thread* self, ShadowFrame& shadow_frame, uint32_t string_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK(!kMovingMethods);
Class* java_lang_string_class = String::GetJavaLangString();
@@ -200,7 +200,15 @@ static inline String* ResolveString(Thread* self, MethodHelper& mh, uint32_t str
return nullptr;
}
}
- return mh.ResolveString(string_idx);
+ mirror::ArtMethod* method = shadow_frame.GetMethod();
+ mirror::String* s = method->GetDexCacheStrings()->Get(string_idx);
+ if (UNLIKELY(s == nullptr)) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
+ s = Runtime::Current()->GetClassLinker()->ResolveString(*method->GetDexFile(), string_idx,
+ dex_cache);
+ }
+ return s;
}
// Handles div-int, div-int/2addr, div-int/li16 and div-int/lit8 instructions.
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 88d6544e80..3a177ebde4 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -321,9 +321,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
const uint8_t vreg_index = inst->VRegA_11x(inst_data);
Object* obj_result = shadow_frame.GetVRegReference(vreg_index);
if (do_assignability_check && obj_result != NULL) {
- StackHandleScope<1> hs(self);
- MethodHelper mh(hs.NewHandle(shadow_frame.GetMethod()));
- Class* return_type = mh.GetReturnType();
+ Class* return_type = shadow_frame.GetMethod()->GetReturnType();
obj_result = shadow_frame.GetVRegReference(vreg_index);
if (return_type == NULL) {
// Return the pending exception.
@@ -420,7 +418,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(CONST_STRING) {
- String* s = ResolveString(self, mh, inst->VRegB_21c());
+ String* s = ResolveString(self, shadow_frame, inst->VRegB_21c());
if (UNLIKELY(s == NULL)) {
HANDLE_PENDING_EXCEPTION();
} else {
@@ -431,7 +429,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(CONST_STRING_JUMBO) {
- String* s = ResolveString(self, mh, inst->VRegB_31c());
+ String* s = ResolveString(self, shadow_frame, inst->VRegB_31c());
if (UNLIKELY(s == NULL)) {
HANDLE_PENDING_EXCEPTION();
} else {
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 14e8a522eb..9fb90f187e 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -233,9 +233,7 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem
const size_t ref_idx = inst->VRegA_11x(inst_data);
Object* obj_result = shadow_frame.GetVRegReference(ref_idx);
if (do_assignability_check && obj_result != NULL) {
- StackHandleScope<1> hs(self);
- MethodHelper mhs(hs.NewHandle(shadow_frame.GetMethod()));
- Class* return_type = mhs.GetReturnType();
+ Class* return_type = shadow_frame.GetMethod()->GetReturnType();
// Re-load since it might have moved.
obj_result = shadow_frame.GetVRegReference(ref_idx);
if (return_type == NULL) {
@@ -331,7 +329,7 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem
break;
case Instruction::CONST_STRING: {
PREAMBLE();
- String* s = ResolveString(self, mh, inst->VRegB_21c());
+ String* s = ResolveString(self, shadow_frame, inst->VRegB_21c());
if (UNLIKELY(s == NULL)) {
HANDLE_PENDING_EXCEPTION();
} else {
@@ -342,7 +340,7 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem
}
case Instruction::CONST_STRING_JUMBO: {
PREAMBLE();
- String* s = ResolveString(self, mh, inst->VRegB_31c());
+ String* s = ResolveString(self, shadow_frame, inst->VRegB_31c());
if (UNLIKELY(s == NULL)) {
HANDLE_PENDING_EXCEPTION();
} else {
diff --git a/runtime/method_helper-inl.h b/runtime/method_helper-inl.h
index 21cc67c362..7a7949e0fa 100644
--- a/runtime/method_helper-inl.h
+++ b/runtime/method_helper-inl.h
@@ -57,46 +57,6 @@ inline mirror::Class* MethodHelperT<HandleKind>::GetClassFromTypeIdx(uint16_t ty
return type;
}
-template <template <class T> class HandleKind>
-inline mirror::Class* MethodHelperT<HandleKind>::GetReturnType(bool resolve) {
- mirror::ArtMethod* method = GetMethod();
- const DexFile* dex_file = method->GetDexFile();
- const DexFile::MethodId& method_id = dex_file->GetMethodId(method->GetDexMethodIndex());
- const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
- uint16_t return_type_idx = proto_id.return_type_idx_;
- return GetClassFromTypeIdx(return_type_idx, resolve);
-}
-
-template <template <class T> class HandleKind>
-inline mirror::String* MethodHelperT<HandleKind>::ResolveString(uint32_t string_idx) {
- mirror::ArtMethod* method = GetMethod();
- mirror::String* s = method->GetDexCacheStrings()->Get(string_idx);
- if (UNLIKELY(s == nullptr)) {
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
- s = Runtime::Current()->GetClassLinker()->ResolveString(*method->GetDexFile(), string_idx,
- dex_cache);
- }
- return s;
-}
-
-inline MethodProtoHelper::MethodProtoHelper(mirror::ArtMethod* method) {
- method = method->GetInterfaceMethodIfProxy();
- dex_file_ = method->GetDexFile();
- mid_ = &dex_file_->GetMethodId(method->GetDexMethodIndex());
- name_ = dex_file_->StringDataAndUtf16LengthByIdx(mid_->name_idx_, &name_len_);
-}
-
-inline bool MethodProtoHelper::HasSameNameAndSignature(const MethodProtoHelper& other) const {
- if (name_len_ != other.name_len_ || strcmp(name_, other.name_) != 0) {
- return false;
- }
- if (dex_file_ == other.dex_file_) {
- return mid_->name_idx_ == other.mid_->name_idx_ && mid_->proto_idx_ == other.mid_->proto_idx_;
- }
- return dex_file_->GetMethodSignature(*mid_) == other.dex_file_->GetMethodSignature(*other.mid_);
-}
-
} // namespace art
#endif // ART_RUNTIME_METHOD_HELPER_INL_H_
diff --git a/runtime/method_helper.cc b/runtime/method_helper.cc
index 79c2b91a55..81e17943ec 100644
--- a/runtime/method_helper.cc
+++ b/runtime/method_helper.cc
@@ -26,23 +26,15 @@
namespace art {
template <template <class T> class HandleKind>
-mirror::String* MethodHelperT<HandleKind>::GetNameAsString(Thread* self) {
- const DexFile* dex_file = method_->GetDexFile();
- mirror::ArtMethod* method = method_->GetInterfaceMethodIfProxy();
- uint32_t dex_method_idx = method->GetDexMethodIndex();
- const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
- StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
- return Runtime::Current()->GetClassLinker()->ResolveString(*dex_file, method_id.name_idx_,
- dex_cache);
-}
-
-template <template <class T> class HandleKind>
template <template <class T2> class HandleKind2>
-bool MethodHelperT<HandleKind>::HasSameSignatureWithDifferentClassLoaders(
+bool MethodHelperT<HandleKind>::HasSameSignatureWithDifferentClassLoaders(Thread* self,
MethodHelperT<HandleKind2>* other) {
- if (UNLIKELY(GetReturnType() != other->GetReturnType())) {
- return false;
+ {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> return_type(hs.NewHandle(GetMethod()->GetReturnType()));
+ if (UNLIKELY(other->GetMethod()->GetReturnType() != return_type.Get())) {
+ return false;
+ }
}
const DexFile::TypeList* types = method_->GetParameterTypeList();
const DexFile::TypeList* other_types = other->method_->GetParameterTypeList();
@@ -140,10 +132,6 @@ uint32_t MethodHelperT<HandleKind>::FindDexMethodIndexInOtherDexFile(
}
// Instantiate methods.
-template mirror::String* MethodHelperT<Handle>::GetNameAsString(Thread* self);
-
-template mirror::String* MethodHelperT<MutableHandle>::GetNameAsString(Thread* self);
-
template
uint32_t MethodHelperT<Handle>::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile);
template
@@ -158,19 +146,19 @@ uint32_t MethodHelperT<MutableHandle>::FindDexMethodIndexInOtherDexFile(
const DexFile& other_dexfile, uint32_t name_and_signature_idx);
template
-bool MethodHelperT<Handle>::HasSameSignatureWithDifferentClassLoaders<Handle>(
+bool MethodHelperT<Handle>::HasSameSignatureWithDifferentClassLoaders<Handle>(Thread* self,
MethodHelperT<Handle>* other);
template
-bool MethodHelperT<Handle>::HasSameSignatureWithDifferentClassLoaders<MutableHandle>(
+bool MethodHelperT<Handle>::HasSameSignatureWithDifferentClassLoaders<MutableHandle>(Thread* self,
MethodHelperT<MutableHandle>* other);
template
-bool MethodHelperT<MutableHandle>::HasSameSignatureWithDifferentClassLoaders<Handle>(
+bool MethodHelperT<MutableHandle>::HasSameSignatureWithDifferentClassLoaders<Handle>(Thread* self,
MethodHelperT<Handle>* other);
template
bool MethodHelperT<MutableHandle>::HasSameSignatureWithDifferentClassLoaders<MutableHandle>(
- MethodHelperT<MutableHandle>* other);
+ Thread* self, MethodHelperT<MutableHandle>* other);
} // namespace art
diff --git a/runtime/method_helper.h b/runtime/method_helper.h
index 913b41b931..dc305d57b7 100644
--- a/runtime/method_helper.h
+++ b/runtime/method_helper.h
@@ -24,19 +24,6 @@
namespace art {
-class MethodProtoHelper {
- public:
- ALWAYS_INLINE MethodProtoHelper(mirror::ArtMethod* method)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ALWAYS_INLINE bool HasSameNameAndSignature(const MethodProtoHelper& other) const;
-
- private:
- const DexFile* dex_file_;
- const DexFile::MethodId* mid_;
- const char* name_;
- uint32_t name_len_;
-};
-
template <template <class T> class HandleKind>
class MethodHelperT {
public:
@@ -53,8 +40,6 @@ class MethodHelperT {
return method_.Get();
}
- mirror::String* GetNameAsString(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const char* result = shorty_;
if (result == nullptr) {
@@ -85,10 +70,6 @@ class MethodHelperT {
return refs;
}
- // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large
- // number of bugs at call sites.
- mirror::Class* GetReturnType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// "1 +" because the first in Args is the receiver.
// "- 1" because we don't count the return type.
@@ -122,14 +103,12 @@ class MethodHelperT {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template <template <class T> class HandleKind2>
- bool HasSameSignatureWithDifferentClassLoaders(MethodHelperT<HandleKind2>* other)
+ bool HasSameSignatureWithDifferentClassLoaders(Thread* self, MethodHelperT<HandleKind2>* other)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Class* GetClassFromTypeIdx(uint16_t type_idx, bool resolve = true)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index cb6ac4f370..ca361f83c9 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -436,11 +436,15 @@ inline mirror::DexCache* ArtMethod::GetDexCache() {
return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache();
}
+inline bool ArtMethod::IsProxyMethod() {
+ return GetDeclaringClass()->IsProxyClass();
+}
+
inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy() {
- mirror::Class* klass = GetDeclaringClass();
- if (LIKELY(!klass->IsProxyClass())) {
+ if (LIKELY(!IsProxyMethod())) {
return this;
}
+ mirror::Class* klass = GetDeclaringClass();
mirror::ArtMethod* interface_method = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex());
DCHECK(interface_method != nullptr);
DCHECK_EQ(interface_method,
@@ -463,6 +467,20 @@ inline void ArtMethod::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cach
new_dex_cache_classes);
}
+inline mirror::Class* ArtMethod::GetReturnType(bool resolve) {
+ DCHECK(!IsProxyMethod());
+ const DexFile* dex_file = GetDexFile();
+ const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
+ const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
+ uint16_t return_type_idx = proto_id.return_type_idx_;
+ mirror::Class* type = GetDexCacheResolvedType(return_type_idx);
+ if (type == nullptr && resolve) {
+ type = Runtime::Current()->GetClassLinker()->ResolveType(return_type_idx, this);
+ CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
+ }
+ return type;
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 014d1a9d77..acd104383c 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -67,6 +67,17 @@ void ArtMethod::VisitRoots(RootCallback* callback, void* arg) {
}
}
+mirror::String* ArtMethod::GetNameAsString(Thread* self) {
+ mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+ const DexFile* dex_file = method->GetDexFile();
+ uint32_t dex_method_idx = method->GetDexMethodIndex();
+ const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
+ StackHandleScope<1> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
+ return Runtime::Current()->GetClassLinker()->ResolveString(*dex_file, method_id.name_idx_,
+ dex_cache);
+}
+
InvokeType ArtMethod::GetInvokeType() {
// TODO: kSuper?
if (GetDeclaringClass()->IsInterface()) {
@@ -105,10 +116,6 @@ size_t ArtMethod::NumArgRegisters(const StringPiece& shorty) {
return num_registers;
}
-bool ArtMethod::IsProxyMethod() {
- return GetDeclaringClass()->IsProxyClass();
-}
-
ArtMethod* ArtMethod::FindOverriddenMethod() {
if (IsStatic()) {
return NULL;
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 92b2c306c6..6927f1d251 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -484,6 +484,8 @@ class MANAGED ArtMethod FINAL : public Object {
ALWAYS_INLINE const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ mirror::String* GetNameAsString(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
const DexFile::CodeItem* GetCodeItem() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsResolvedTypeIdx(uint16_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -505,13 +507,17 @@ class MANAGED ArtMethod FINAL : public Object {
const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large
+ // number of bugs at call sites.
+ mirror::Class* GetReturnType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
mirror::ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- protected:
+ private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
// The class we are a part of.
HeapReference<Class> declaring_class_;
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 6a7faaaf34..d9094fc393 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1147,11 +1147,11 @@ class MANAGED Class FINAL : public Object {
// The following data exist in real class objects.
// Embedded Imtable, for class object that's not an interface, fixed size.
- ImTableEntry embedded_imtable_[0];
+ // ImTableEntry embedded_imtable_[0];
// Embedded Vtable, for class object that's not an interface, variable size.
- VTableEntry embedded_vtable_[0];
+ // VTableEntry embedded_vtable_[0];
// Static fields, variable size.
- uint32_t fields_[0];
+ // uint32_t fields_[0];
// java.lang.Class
static GcRoot<Class> java_lang_Class_;
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 4214bdf4a3..54f5eab018 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -302,7 +302,7 @@ bool OatFile::Setup(std::string* error_msg) {
oat += sizeof(dex_file_offset);
if (UNLIKELY(oat > End())) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
- " after dex file offsets", GetLocation().c_str(), i,
+ "after dex file offsets", GetLocation().c_str(), i,
dex_file_location.c_str());
return false;
}
@@ -310,13 +310,13 @@ bool OatFile::Setup(std::string* error_msg) {
const uint8_t* dex_file_pointer = Begin() + dex_file_offset;
if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
- " dex file magic '%s'", GetLocation().c_str(), i,
+ "dex file magic '%s'", GetLocation().c_str(), i,
dex_file_location.c_str(), dex_file_pointer);
return false;
}
if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
- " dex file version '%s'", GetLocation().c_str(), i,
+ "dex file version '%s'", GetLocation().c_str(), i,
dex_file_location.c_str(), dex_file_pointer);
return false;
}
@@ -326,7 +326,7 @@ bool OatFile::Setup(std::string* error_msg) {
oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_);
if (UNLIKELY(oat > End())) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated "
- " method offsets", GetLocation().c_str(), i,
+ "method offsets", GetLocation().c_str(), i,
dex_file_location.c_str());
return false;
}
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index b57e48fdd5..228d2007d4 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -632,8 +632,8 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM
}
// Box if necessary and return.
- return soa.AddLocalReference<jobject>(BoxPrimitive(mh.GetReturnType()->GetPrimitiveType(),
- result));
+ return soa.AddLocalReference<jobject>(
+ BoxPrimitive(Primitive::GetType(mh.GetMethod()->GetReturnTypeDescriptor()[0]), result));
}
bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) {
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index fb07ba0c2d..80124517d7 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2256,8 +2256,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
if (called_method != nullptr) {
StackHandleScope<1> hs(self_);
Handle<mirror::ArtMethod> h_called_method(hs.NewHandle(called_method));
- MethodHelper mh(h_called_method);
- mirror::Class* return_type_class = mh.GetReturnType(can_load_classes_);
+ mirror::Class* return_type_class = h_called_method->GetReturnType(can_load_classes_);
if (return_type_class != nullptr) {
return_type = &reg_types_.FromClass(h_called_method->GetReturnTypeDescriptor(),
return_type_class,
@@ -2301,8 +2300,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
return_type_descriptor = called_method->GetReturnTypeDescriptor();
StackHandleScope<1> hs(self_);
Handle<mirror::ArtMethod> h_called_method(hs.NewHandle(called_method));
- MethodHelper mh(h_called_method);
- mirror::Class* return_type_class = mh.GetReturnType(can_load_classes_);
+ mirror::Class* return_type_class = h_called_method->GetReturnType(can_load_classes_);
if (return_type_class != nullptr) {
return_type = &reg_types_.FromClass(return_type_descriptor,
return_type_class,
@@ -4112,9 +4110,7 @@ InstructionFlags* MethodVerifier::CurrentInsnFlags() {
const RegType& MethodVerifier::GetMethodReturnType() {
if (return_type_ == nullptr) {
if (mirror_method_.Get() != nullptr) {
- StackHandleScope<1> hs(self_);
- mirror::Class* return_type_class =
- MethodHelper(hs.NewHandle(mirror_method_.Get())).GetReturnType(can_load_classes_);
+ mirror::Class* return_type_class = mirror_method_->GetReturnType(can_load_classes_);
if (return_type_class != nullptr) {
return_type_ = &reg_types_.FromClass(mirror_method_->GetReturnTypeDescriptor(),
return_type_class,
diff --git a/test/417-optimizing-arith-div/expected.txt b/test/417-optimizing-arith-div/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/417-optimizing-arith-div/expected.txt
diff --git a/test/417-optimizing-arith-div/info.txt b/test/417-optimizing-arith-div/info.txt
new file mode 100644
index 0000000000..1374b0ffb3
--- /dev/null
+++ b/test/417-optimizing-arith-div/info.txt
@@ -0,0 +1 @@
+Tests for division operation.
diff --git a/test/417-optimizing-arith-div/src/Main.java b/test/417-optimizing-arith-div/src/Main.java
new file mode 100644
index 0000000000..535cafb113
--- /dev/null
+++ b/test/417-optimizing-arith-div/src/Main.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+// Note that $opt$ is a marker for the optimizing compiler to ensure
+// it does compile the method.
+public class Main {
+
+ public static void expectEquals(float expected, float result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ public static void expectEquals(double expected, double result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ public static void expectApproxEquals(float a, float b) {
+ float maxDelta = 0.00001F;
+ boolean aproxEquals = (a > b) ? ((a - b) < maxDelta) : ((b - a) < maxDelta);
+ if (!aproxEquals) {
+ throw new Error("Expected: " + a + ", found: " + b
+ + ", with delta: " + maxDelta + " " + (a - b));
+ }
+ }
+
+ public static void expectApproxEquals(double a, double b) {
+ double maxDelta = 0.00001D;
+ boolean aproxEquals = (a > b) ? ((a - b) < maxDelta) : ((b - a) < maxDelta);
+ if (!aproxEquals) {
+ throw new Error("Expected: " + a + ", found: "
+ + b + ", with delta: " + maxDelta + " " + (a - b));
+ }
+ }
+
+ public static void expectNaN(float a) {
+ if (a == a) {
+ throw new Error("Expected NaN: " + a);
+ }
+ }
+
+ public static void expectNaN(double a) {
+ if (a == a) {
+ throw new Error("Expected NaN: " + a);
+ }
+ }
+
+ public static void main(String[] args) {
+ div();
+ }
+
+ public static void div() {
+ divFloat();
+ divDouble();
+ }
+
+ private static void divFloat() {
+ expectApproxEquals(1.6666666F, $opt$Div(5F, 3F));
+ expectApproxEquals(0F, $opt$Div(0F, 3F));
+ expectApproxEquals(-0.3333333F, $opt$Div(1F, -3F));
+ expectApproxEquals(4F, $opt$Div(-12F, -3F));
+ expectApproxEquals(0.5, $opt$Div(0.1F, 0.2F));
+ expectApproxEquals(-2.5F, $opt$Div(-0.5F, 0.2F));
+
+ expectEquals(0F, $opt$Div(0F, Float.POSITIVE_INFINITY));
+ expectEquals(0F, $opt$Div(11F, Float.POSITIVE_INFINITY));
+ expectEquals(0F, $opt$Div(0F, Float.NEGATIVE_INFINITY));
+ expectEquals(0F, $opt$Div(11F, Float.NEGATIVE_INFINITY));
+
+ expectNaN($opt$Div(0F, 0F));
+ expectNaN($opt$Div(Float.NaN, 11F));
+ expectNaN($opt$Div(-11F, Float.NaN));
+ expectNaN($opt$Div(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY));
+ expectNaN($opt$Div(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY));
+ expectNaN($opt$Div(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY));
+ expectNaN($opt$Div(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY));
+ expectNaN($opt$Div(Float.NaN, Float.NEGATIVE_INFINITY));
+ expectNaN($opt$Div(Float.POSITIVE_INFINITY, Float.NaN));
+
+ expectEquals(Float.POSITIVE_INFINITY, $opt$Div(3F, 0F));
+ expectEquals(Float.NEGATIVE_INFINITY, $opt$Div(-3F, 0F));
+ expectEquals(Float.POSITIVE_INFINITY, $opt$Div(Float.MAX_VALUE, Float.MIN_VALUE));
+ expectEquals(Float.NEGATIVE_INFINITY, $opt$Div(-Float.MAX_VALUE, Float.MIN_VALUE));
+ }
+
+ private static void divDouble() {
+ expectApproxEquals(1.6666666D, $opt$Div(5D, 3D));
+ expectApproxEquals(0D, $opt$Div(0D, 3D));
+ expectApproxEquals(-0.3333333D, $opt$Div(1D, -3D));
+ expectApproxEquals(4D, $opt$Div(-12D, -3D));
+ expectApproxEquals(0.5, $opt$Div(0.1D, 0.2D));
+ expectApproxEquals(-2.5D, $opt$Div(-0.5D, 0.2D));
+
+ expectEquals(0D, $opt$Div(0D, Float.POSITIVE_INFINITY));
+ expectEquals(0D, $opt$Div(11D, Float.POSITIVE_INFINITY));
+ expectEquals(0D, $opt$Div(0D, Float.NEGATIVE_INFINITY));
+ expectEquals(0D, $opt$Div(11D, Float.NEGATIVE_INFINITY));
+
+ expectNaN($opt$Div(0D, 0D));
+ expectNaN($opt$Div(Float.NaN, 11D));
+ expectNaN($opt$Div(-11D, Float.NaN));
+ expectNaN($opt$Div(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY));
+ expectNaN($opt$Div(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY));
+ expectNaN($opt$Div(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY));
+ expectNaN($opt$Div(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY));
+ expectNaN($opt$Div(Float.NaN, Float.NEGATIVE_INFINITY));
+ expectNaN($opt$Div(Float.POSITIVE_INFINITY, Float.NaN));
+
+ expectEquals(Float.POSITIVE_INFINITY, $opt$Div(3D, 0D));
+ expectEquals(Float.NEGATIVE_INFINITY, $opt$Div(-3D, 0D));
+ expectEquals(Float.POSITIVE_INFINITY, $opt$Div(Float.MAX_VALUE, Float.MIN_VALUE));
+ expectEquals(Float.NEGATIVE_INFINITY, $opt$Div(-Float.MAX_VALUE, Float.MIN_VALUE));
+ }
+
+ static float $opt$Div(float a, float b) {
+ return a / b;
+ }
+
+ static double $opt$Div(double a, double b) {
+ return a / b;
+ }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 2de4d5ca73..2bff720375 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -113,6 +113,13 @@ IMAGE_TYPES := image
ifeq ($(ART_TEST_RUN_TEST_NO_IMAGE),true)
IMAGE_TYPES += no-image
endif
+ifeq ($(ART_TEST_PIC_IMAGE),true)
+ IMAGE_TYPES += picimage
+endif
+PICTEST_TYPES := nopictest
+ifeq ($(ART_TEST_PIC_TEST),true)
+ PICTEST_TYPES += pictest
+endif
RUN_TYPES :=
ifeq ($(ART_TEST_RUN_TEST_DEBUG),true)
RUN_TYPES += debug
@@ -139,10 +146,11 @@ define all-run-test-names
$(foreach gc, $(7), \
$(foreach jni, $(8), \
$(foreach image, $(9), \
- $(foreach test, $(10), \
- $(foreach address_size, $(11), \
- test-art-$(target)-run-test-$(run-type)-$(prebuild)-$(compiler)-$(relocate)-$(trace)-$(gc)-$(jni)-$(image)-$(test)$(address_size) \
- )))))))))))
+ $(foreach pictest, $(10), \
+ $(foreach test, $(11), \
+ $(foreach address_size, $(12), \
+ test-art-$(target)-run-test-$(run-type)-$(prebuild)-$(compiler)-$(relocate)-$(trace)-$(gc)-$(jni)-$(image)-$(pictest)-$(test)$(address_size) \
+ ))))))))))))
endef # all-run-test-names
# To generate a full list or tests:
@@ -164,7 +172,7 @@ TEST_ART_TIMING_SENSITIVE_RUN_TESTS := \
ifdef dist_goal
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
- $(IMAGE_TYPES), $(TEST_ART_TIMING_SENSITIVE_RUN_TESTS), $(ALL_ADDRESS_SIZES))
+ $(IMAGE_TYPES), $(PICTEST_TYPES), $(TEST_ART_TIMING_SENSITIVE_RUN_TESTS), $(ALL_ADDRESS_SIZES))
endif
TEST_ART_TIMING_SENSITIVE_RUN_TESTS :=
@@ -174,7 +182,7 @@ TEST_ART_BROKEN_RUN_TESTS := \
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
- $(IMAGE_TYPES), $(TEST_ART_BROKEN_RUN_TESTS), $(ALL_ADDRESS_SIZES))
+ $(IMAGE_TYPES), $(PICTEST_TYPES), $(TEST_ART_BROKEN_RUN_TESTS), $(ALL_ADDRESS_SIZES))
TEST_ART_BROKEN_RUN_TESTS :=
@@ -185,7 +193,7 @@ TEST_ART_BROKEN_PREBUILD_RUN_TESTS := \
ifneq (,$(filter prebuild,$(PREBUILD_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),prebuild, \
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
- $(IMAGE_TYPES), $(TEST_ART_BROKEN_PREBUILD_RUN_TESTS), $(ALL_ADDRESS_SIZES))
+ $(IMAGE_TYPES), $(PICTEST_TYPES), $(TEST_ART_BROKEN_PREBUILD_RUN_TESTS), $(ALL_ADDRESS_SIZES))
endif
TEST_ART_BROKEN_PREBUILD_RUN_TESTS :=
@@ -196,7 +204,7 @@ TEST_ART_BROKEN_NO_PREBUILD_TESTS := \
ifneq (,$(filter no-prebuild,$(PREBUILD_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),no-prebuild, \
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
- $(IMAGE_TYPES), $(TEST_ART_BROKEN_NO_PREBUILD_TESTS), $(ALL_ADDRESS_SIZES))
+ $(IMAGE_TYPES), $(PICTEST_TYPES), $(TEST_ART_BROKEN_NO_PREBUILD_TESTS), $(ALL_ADDRESS_SIZES))
endif
TEST_ART_BROKEN_NO_PREBUILD_TESTS :=
@@ -209,7 +217,7 @@ TEST_ART_BROKEN_NO_RELOCATE_TESTS := \
ifneq (,$(filter no-relocate,$(RELOCATE_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
$(COMPILER_TYPES), no-relocate,$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
- $(IMAGE_TYPES), $(TEST_ART_BROKEN_NO_RELOCATE_TESTS), $(ALL_ADDRESS_SIZES))
+ $(IMAGE_TYPES), $(PICTEST_TYPES), $(TEST_ART_BROKEN_NO_RELOCATE_TESTS), $(ALL_ADDRESS_SIZES))
endif
TEST_ART_BROKEN_NO_RELOCATE_TESTS :=
@@ -222,14 +230,14 @@ TEST_ART_BROKEN_GCSTRESS_RUN_TESTS := \
ifneq (,$(filter gcstress,$(GC_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),gcstress,$(JNI_TYPES), \
- $(IMAGE_TYPES), $(TEST_ART_BROKEN_GCSTRESS_RUN_TESTS), $(ALL_ADDRESS_SIZES))
+ $(IMAGE_TYPES), $(PICTEST_TYPES), $(TEST_ART_BROKEN_GCSTRESS_RUN_TESTS), $(ALL_ADDRESS_SIZES))
endif
TEST_ART_BROKEN_GCSTRESS_RUN_TESTS :=
# 115-native-bridge setup is complicated. Need to implement it correctly for the target.
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,target,$(RUN_TYPES),$(PREBUILD_TYPES),$(COMPILER_TYPES), \
- $(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES),115-native-bridge, \
+ $(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES),$(PICTEST_TYPES),115-native-bridge, \
$(ALL_ADDRESS_SIZES))
# All these tests check that we have sane behavior if we don't have a patchoat or dex2oat.
@@ -244,20 +252,20 @@ TEST_ART_BROKEN_FALLBACK_RUN_TESTS := \
ifneq (,$(filter no-dex2oat,$(PREBUILD_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),no-dex2oat, \
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES), \
- $(TEST_ART_BROKEN_FALLBACK_RUN_TESTS),$(ALL_ADDRESS_SIZES))
+ $(PICTEST_TYPES),$(TEST_ART_BROKEN_FALLBACK_RUN_TESTS),$(ALL_ADDRESS_SIZES))
endif
ifneq (,$(filter no-image,$(IMAGE_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
$(COMPILER_TYPES), $(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),no-image, \
- $(TEST_ART_BROKEN_FALLBACK_RUN_TESTS),$(ALL_ADDRESS_SIZES))
+ $(PICTEST_TYPES), $(TEST_ART_BROKEN_FALLBACK_RUN_TESTS),$(ALL_ADDRESS_SIZES))
endif
ifneq (,$(filter relocate-no-patchoat,$(RELOCATE_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
$(COMPILER_TYPES), relocate-no-patchoat,$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
- $(IMAGE_TYPES),$(TEST_ART_BROKEN_FALLBACK_RUN_TESTS),$(ALL_ADDRESS_SIZES))
+ $(IMAGE_TYPES),$(PICTEST_TYPES),$(TEST_ART_BROKEN_FALLBACK_RUN_TESTS),$(ALL_ADDRESS_SIZES))
endif
TEST_ART_BROKEN_FALLBACK_RUN_TESTS :=
@@ -280,7 +288,7 @@ TEST_ART_BROKEN_NDEBUG_TESTS := \
ifneq (,$(filter ndebug,$(RUN_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),ndebug,$(PREBUILD_TYPES), \
$(COMPILER_TYPES), $(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES), \
- $(TEST_ART_BROKEN_NDEBUG_TESTS),$(ALL_ADDRESS_SIZES))
+ $(PICTEST_TYPES),$(TEST_ART_BROKEN_NDEBUG_TESTS),$(ALL_ADDRESS_SIZES))
endif
TEST_ART_BROKEN_NDEBUG_TESTS :=
@@ -292,7 +300,7 @@ TEST_ART_BROKEN_DEFAULT_RUN_TESTS := \
ifneq (,$(filter default,$(COMPILER_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
default,$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
- $(IMAGE_TYPES),$(TEST_ART_BROKEN_DEFAULT_RUN_TESTS),$(ALL_ADDRESS_SIZES))
+ $(IMAGE_TYPES),$(PICTEST_TYPES),$(TEST_ART_BROKEN_DEFAULT_RUN_TESTS),$(ALL_ADDRESS_SIZES))
endif
TEST_ART_BROKEN_DEFAULT_RUN_TESTS :=
@@ -325,13 +333,14 @@ TEST_ART_BROKEN_OPTIMIZING_ARM64_RUN_TESTS := \
413-regalloc-regression \
414-optimizing-arith-sub \
415-optimizing-arith-neg \
+ 417-optimizing-arith-div \
700-LoadArgRegs \
800-smali
ifneq (,$(filter optimizing,$(COMPILER_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,target,$(RUN_TYPES),$(PREBUILD_TYPES), \
optimizing,$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
- $(IMAGE_TYPES),$(TEST_ART_BROKEN_OPTIMIZING_ARM64_RUN_TESTS),64)
+ $(IMAGE_TYPES),$(PICTEST_TYPES),$(TEST_ART_BROKEN_OPTIMIZING_ARM64_RUN_TESTS),64)
endif
TEST_ART_BROKEN_OPTIMIZING_ARM64_RUN_TESTS :=
@@ -370,8 +379,9 @@ $(foreach target, $(TARGET_TYPES), \
$(foreach run_type, $(RUN_TYPES), \
$(eval ART_RUN_TEST_$(call name-to-var,$(target))_$(call name-to-var,$(run_type))_RULES :=)))
-# We need dex2oat and dalvikvm on the target as well as the core image.
-TEST_ART_TARGET_SYNC_DEPS += $(ART_TARGET_EXECUTABLES) $(TARGET_CORE_IMG_OUT) $(2ND_TARGET_CORE_IMG_OUT)
+# We need dex2oat and dalvikvm on the target as well as the core images (all images as we sync
+# only once).
+TEST_ART_TARGET_SYNC_DEPS += $(ART_TARGET_EXECUTABLES) $(TARGET_CORE_IMG_OUTS)
# Also need libarttest.
TEST_ART_TARGET_SYNC_DEPS += $(ART_TARGET_TEST_OUT)/$(TARGET_ARCH)/libarttest.so
@@ -385,27 +395,26 @@ ifdef TARGET_2ND_ARCH
TEST_ART_TARGET_SYNC_DEPS += $(ART_TARGET_TEST_OUT)/$(TARGET_2ND_ARCH)/libnativebridgetest.so
endif
-# All tests require the host executables and the core images.
+# All tests require the host executables. The tests also depend on the core images, but on
+# specific version depending on the compiler.
ART_TEST_HOST_RUN_TEST_DEPENDENCIES := \
$(ART_HOST_EXECUTABLES) \
$(ART_HOST_OUT_SHARED_LIBRARIES)/libarttest$(ART_HOST_SHLIB_EXTENSION) \
$(ART_HOST_OUT_SHARED_LIBRARIES)/libnativebridgetest$(ART_HOST_SHLIB_EXTENSION) \
- $(ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$(ART_HOST_SHLIB_EXTENSION) \
- $(HOST_CORE_IMG_OUT)
+ $(ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$(ART_HOST_SHLIB_EXTENSION)
ifneq ($(HOST_PREFER_32_BIT),true)
ART_TEST_HOST_RUN_TEST_DEPENDENCIES += \
$(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libarttest$(ART_HOST_SHLIB_EXTENSION) \
$(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libnativebridgetest$(ART_HOST_SHLIB_EXTENSION) \
- $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$(ART_HOST_SHLIB_EXTENSION) \
- $(2ND_HOST_CORE_IMG_OUT)
+ $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$(ART_HOST_SHLIB_EXTENSION)
endif
# Create a rule to build and run a tests following the form:
# test-art-{1: host or target}-run-test-{2: debug ndebug}-{3: prebuild no-prebuild no-dex2oat}-
# {4: interpreter default optimizing}-{5: relocate no-relocate relocate-no-patchoat}-
# {6: trace or no-trace}-{7: gcstress gcverify cms}-{8: forcecopy checkjni jni}-
-# {9: no-image image}-{10: test name}{11: 32 or 64}
+# {9: no-image image picimage}-{10: pictest nopictest}-{11: test name}{12: 32 or 64}
define define-test-art-run-test
run_test_options :=
prereq_rule :=
@@ -456,7 +465,7 @@ define define-test-art-run-test
endif
ifeq ($(4),optimizing)
test_groups += ART_RUN_TEST_$$(uc_host_or_target)_OPTIMIZING_RULES
- run_test_options += -Xcompiler-option --compiler-backend=Optimizing
+ run_test_options += --optimizing
else
ifeq ($(4),interpreter)
test_groups += ART_RUN_TEST_$$(uc_host_or_target)_INTERPRETER_RULES
@@ -469,6 +478,7 @@ define define-test-art-run-test
endif
endif
endif
+
ifeq ($(5),relocate)
test_groups += ART_RUN_TEST_$$(uc_host_or_target)_RELOCATE_RULES
run_test_options += --relocate
@@ -534,23 +544,48 @@ define define-test-art-run-test
else
ifeq ($(9),image)
test_groups += ART_RUN_TEST_$$(uc_host_or_target)_IMAGE_RULES
+ # Add the core dependency.
+ ifeq ($(1),host)
+ prereq_rule += $(HOST_CORE_IMAGE_$(4)_no-pic_$(12))
+ else
+ prereq_rule += $(TARGET_CORE_IMAGE_$(4)_no-pic_$(12))
+ endif
+ else
+ ifeq ($(9),picimage)
+ test_groups += ART_RUN_TEST_$$(uc_host_or_target)_PICIMAGE_RULES
+ run_test_options += --pic-image
+ ifeq ($(1),host)
+ prereq_rule += $(HOST_CORE_IMAGE_$(4)_pic_$(12))
+ else
+ prereq_rule += $(TARGET_CORE_IMAGE_$(4)_pic_$(12))
+ endif
+ else
+ $$(error found $(9) expected $(IMAGE_TYPES))
+ endif
+ endif
+ endif
+ ifeq ($(10),pictest)
+ run_test_options += --pic-test
+ else
+ ifeq ($(10),nopictest)
+ # Nothing to be done.
else
- $$(error found $(9) expected $(IMAGE_TYPES))
+ $$(error found $(10) expected $(PICTEST_TYPES))
endif
endif
- # $(10) is the test name
- test_groups += ART_RUN_TEST_$$(uc_host_or_target)_$(call name-to-var,$(10))_RULES
- ifeq ($(11),64)
+ # $(11) is the test name
+ test_groups += ART_RUN_TEST_$$(uc_host_or_target)_$(call name-to-var,$(11))_RULES
+ ifeq ($(12),64)
test_groups += ART_RUN_TEST_$$(uc_host_or_target)_64_RULES
run_test_options += --64
else
- ifeq ($(11),32)
+ ifeq ($(12),32)
test_groups += ART_RUN_TEST_$$(uc_host_or_target)_32_RULES
else
- $$(error found $(11) expected $(ALL_ADDRESS_SIZES))
+ $$(error found $(12) expected $(ALL_ADDRESS_SIZES))
endif
endif
- run_test_rule_name := test-art-$(1)-run-test-$(2)-$(3)-$(4)-$(5)-$(6)-$(7)-$(8)-$(9)-$(10)$(11)
+ run_test_rule_name := test-art-$(1)-run-test-$(2)-$(3)-$(4)-$(5)-$(6)-$(7)-$(8)-$(9)-$(10)-$(11)$(12)
run_test_options := --output-path $(ART_HOST_TEST_DIR)/run-test-output/$$(run_test_rule_name) \
$$(run_test_options)
$$(run_test_rule_name): PRIVATE_RUN_TEST_OPTIONS := $$(run_test_options)
@@ -560,7 +595,7 @@ $$(run_test_rule_name): $(DX) $(HOST_OUT_EXECUTABLES)/jasmin $(HOST_OUT_EXECUTAB
DX=$(abspath $(DX)) JASMIN=$(abspath $(HOST_OUT_EXECUTABLES)/jasmin) \
SMALI=$(abspath $(HOST_OUT_EXECUTABLES)/smali) \
DXMERGER=$(abspath $(HOST_OUT_EXECUTABLES)/dexmerger) \
- art/test/run-test $$(PRIVATE_RUN_TEST_OPTIONS) $(10) \
+ art/test/run-test $$(PRIVATE_RUN_TEST_OPTIONS) $(11) \
&& $$(call ART_TEST_PASSED,$$@) || $$(call ART_TEST_FAILED,$$@)
$$(hide) (echo $(MAKECMDGOALS) | grep -q $$@ && \
echo "run-test run as top-level target, removing test directory $(ART_HOST_TEST_DIR)" && \
@@ -587,8 +622,9 @@ $(foreach target, $(TARGET_TYPES), \
$(foreach gc, $(GC_TYPES), \
$(foreach jni, $(JNI_TYPES), \
$(foreach image, $(IMAGE_TYPES), \
- $(eval $(call define-test-art-run-test,$(target),$(run_type),$(prebuild),$(compiler),$(relocate),$(trace),$(gc),$(jni),$(image),$(test),$(address_size))) \
- )))))))))))
+ $(foreach pictest, $(PICTEST_TYPES), \
+ $(eval $(call define-test-art-run-test,$(target),$(run_type),$(prebuild),$(compiler),$(relocate),$(trace),$(gc),$(jni),$(image),$(pictest),$(test),$(address_size))) \
+ ))))))))))))
define-test-art-run-test :=
# Define a phony rule whose purpose is to test its prerequisites.
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 82d47d7451..eec8930fb9 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -136,6 +136,10 @@ while true; do
DALVIKVM="dalvikvm64"
ARCHITECTURES_PATTERN="${ARCHITECTURES_64}"
shift
+ elif [ "x$1" = "x--pic-test" ]; then
+ FLAGS="${FLAGS} -Xcompiler-option --compile-pic"
+ COMPILE_FLAGS="${COMPILE_FLAGS} --compile-pic"
+ shift
elif expr "x$1" : "x--" >/dev/null 2>&1; then
echo "unknown $0 option: $1" 1>&2
exit 1
diff --git a/test/run-test b/test/run-test
index 9c97de0c45..b0a4bb169e 100755
--- a/test/run-test
+++ b/test/run-test
@@ -95,6 +95,8 @@ always_clean="no"
have_dex2oat="yes"
have_patchoat="yes"
have_image="yes"
+image_suffix=""
+pic_image_suffix=""
while true; do
if [ "x$1" = "x--host" ]; then
@@ -125,6 +127,12 @@ while true; do
elif [ "x$1" = "x--no-image" ]; then
have_image="no"
shift
+ elif [ "x$1" = "x--pic-image" ]; then
+ pic_image_suffix="-pic"
+ shift
+ elif [ "x$1" = "x--pic-test" ]; then
+ run_args="${run_args} --pic-test"
+ shift
elif [ "x$1" = "x--relocate" ]; then
relocate="yes"
shift
@@ -174,6 +182,11 @@ while true; do
shift
elif [ "x$1" = "x--interpreter" ]; then
run_args="${run_args} --interpreter"
+ image_suffix="-interpreter"
+ shift
+ elif [ "x$1" = "x--optimizing" ]; then
+ run_args="${run_args} -Xcompiler-option --compiler-backend=Optimizing"
+ image_suffix="-optimizing"
shift
elif [ "x$1" = "x--no-verify" ]; then
run_args="${run_args} --no-verify"
@@ -308,12 +321,12 @@ elif [ "$runtime" = "art" ]; then
if [ -z "$ANDROID_HOST_OUT" ]; then
export ANDROID_HOST_OUT=$ANDROID_BUILD_TOP/out/host/linux-x86
fi
- run_args="${run_args} --boot -Ximage:${ANDROID_HOST_OUT}/framework/core.art"
+ run_args="${run_args} --boot -Ximage:${ANDROID_HOST_OUT}/framework/core${image_suffix}${pic_image_suffix}.art"
run_args="${run_args} --runtime-option -Djava.library.path=${ANDROID_HOST_OUT}/lib${suffix64}"
else
guess_arch_name
run_args="${run_args} --runtime-option -Djava.library.path=/data/art-test/${target_arch_name}"
- run_args="${run_args} --boot -Ximage:/data/art-test/core.art"
+ run_args="${run_args} --boot -Ximage:/data/art-test/core${image_suffix}${pic_image_suffix}.art"
fi
if [ "$relocate" = "yes" ]; then
run_args="${run_args} --relocate"
@@ -391,6 +404,7 @@ if [ "$usage" = "yes" ]; then
echo " --gdb Run under gdb; incompatible with some tests."
echo " --build-only Build test files only (off by default)."
echo " --interpreter Enable interpreter only mode (off by default)."
+ echo " --optimizing Enable optimizing compiler (off by default)."
echo " --no-verify Turn off verification (on by default)."
echo " --no-optimize Turn off optimization (on by default)."
echo " --no-precise Turn off precise GC (on by default)."