diff options
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 = ®_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 = ®_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_ = ®_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)." |