summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.gtest.mk2
-rw-r--r--compiler/Android.bp1
-rw-r--r--compiler/common_compiler_test.cc2
-rw-r--r--compiler/debug/elf_debug_info_writer.h1
-rw-r--r--compiler/dex/dex_to_dex_compiler.cc1
-rw-r--r--compiler/dex/inline_method_analyser.cc (renamed from runtime/quick/inline_method_analyser.cc)26
-rw-r--r--compiler/dex/inline_method_analyser.h (renamed from runtime/quick/inline_method_analyser.h)127
-rw-r--r--compiler/dex/verified_method.cc11
-rw-r--r--compiler/driver/compiler_driver.cc1
-rw-r--r--compiler/elf_writer.cc9
-rw-r--r--compiler/exception_test.cc2
-rw-r--r--compiler/image_test.cc1
-rw-r--r--compiler/image_writer.cc1
-rw-r--r--compiler/jni/jni_compiler_test.cc1
-rw-r--r--compiler/optimizing/code_generator.cc5
-rw-r--r--compiler/optimizing/code_generator_arm64.h4
-rw-r--r--compiler/optimizing/code_generator_vector_arm64.cc58
-rw-r--r--compiler/optimizing/inliner.cc2
-rw-r--r--compiler/optimizing/instruction_simplifier.cc2
-rw-r--r--compiler/optimizing/instruction_simplifier_arm.cc1
-rw-r--r--compiler/optimizing/intrinsics.cc3
-rw-r--r--compiler/optimizing/intrinsics_arm.cc6
-rw-r--r--compiler/optimizing/intrinsics_arm64.cc6
-rw-r--r--compiler/optimizing/intrinsics_arm_vixl.cc6
-rw-r--r--compiler/optimizing/intrinsics_x86.cc6
-rw-r--r--compiler/optimizing/intrinsics_x86_64.cc8
-rw-r--r--compiler/optimizing/nodes.cc2
-rw-r--r--compiler/optimizing/nodes.h2
-rw-r--r--compiler/optimizing/nodes_vector.h154
-rw-r--r--compiler/optimizing/reference_type_propagation.cc2
-rw-r--r--compiler/verifier_deps_test.cc1
-rw-r--r--imgdiag/imgdiag.cc1
-rw-r--r--patchoat/patchoat.cc1
-rw-r--r--runtime/Android.bp5
-rw-r--r--runtime/arch/arm/fault_handler_arm.cc8
-rw-r--r--runtime/arch/arm64/fault_handler_arm64.cc7
-rw-r--r--runtime/arch/mips/fault_handler_mips.cc10
-rw-r--r--runtime/arch/mips64/fault_handler_mips64.cc11
-rw-r--r--runtime/arch/x86/fault_handler_x86.cc9
-rw-r--r--runtime/art_field-inl.h11
-rw-r--r--runtime/art_field.cc7
-rw-r--r--runtime/art_field.h17
-rw-r--r--runtime/art_method-inl.h40
-rw-r--r--runtime/art_method.cc36
-rw-r--r--runtime/art_method.h22
-rw-r--r--runtime/base/allocator.cc1
-rw-r--r--runtime/class_linker-inl.h49
-rw-r--r--runtime/class_linker.cc8
-rw-r--r--runtime/class_linker.h29
-rw-r--r--runtime/class_table.cc1
-rw-r--r--runtime/common_runtime_test.cc1
-rw-r--r--runtime/debugger.cc17
-rw-r--r--runtime/debugger.h3
-rw-r--r--runtime/dex_file_annotations.cc34
-rw-r--r--runtime/dex_file_annotations.h2
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h29
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc1
-rw-r--r--runtime/entrypoints/jni/jni_entrypoints.cc1
-rw-r--r--runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc10
-rw-r--r--runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc2
-rw-r--r--runtime/gc/accounting/mod_union_table.cc1
-rw-r--r--runtime/gc/accounting/remembered_set.cc3
-rw-r--r--runtime/gc/collector/concurrent_copying-inl.h8
-rw-r--r--runtime/gc/collector/concurrent_copying.cc29
-rw-r--r--runtime/gc/collector/concurrent_copying.h14
-rw-r--r--runtime/gc/collector/mark_compact.cc1
-rw-r--r--runtime/gc/collector/mark_sweep-inl.h1
-rw-r--r--runtime/gc/collector/semi_space.cc1
-rw-r--r--runtime/gc/heap.cc8
-rw-r--r--runtime/gc/heap.h5
-rw-r--r--runtime/gc/heap_verification_test.cc125
-rw-r--r--runtime/gc/reference_processor.cc1
-rw-r--r--runtime/gc/space/image_space.cc4
-rw-r--r--runtime/gc/system_weak_test.cc1
-rw-r--r--runtime/gc/verification.cc142
-rw-r--r--runtime/gc/verification.h67
-rw-r--r--runtime/hprof/hprof.cc3
-rw-r--r--runtime/image.cc1
-rw-r--r--runtime/indirect_reference_table-inl.h1
-rw-r--r--runtime/indirect_reference_table.cc1
-rw-r--r--runtime/intern_table_test.cc1
-rw-r--r--runtime/interpreter/interpreter_common.cc2
-rw-r--r--runtime/interpreter/unstarted_runtime_test.cc3
-rw-r--r--runtime/java_vm_ext.cc2
-rw-r--r--runtime/jdwp/jdwp_handler.cc15
-rw-r--r--runtime/jit/jit.cc1
-rw-r--r--runtime/jit/profile_compilation_info.cc2
-rw-r--r--runtime/jni_env_ext-inl.h4
-rw-r--r--runtime/jni_env_ext.h5
-rw-r--r--runtime/method_handles.cc2
-rw-r--r--runtime/mirror/array-inl.h3
-rw-r--r--runtime/mirror/class-inl.h80
-rw-r--r--runtime/mirror/class-refvisitor-inl.h82
-rw-r--r--runtime/mirror/class.cc1
-rw-r--r--runtime/mirror/class.h18
-rw-r--r--runtime/mirror/dex_cache-inl.h6
-rw-r--r--runtime/mirror/dex_cache_test.cc1
-rw-r--r--runtime/mirror/method_handle_impl-inl.h45
-rw-r--r--runtime/mirror/method_handle_impl.cc6
-rw-r--r--runtime/mirror/method_handle_impl.h20
-rw-r--r--runtime/mirror/method_handles_lookup.cc2
-rw-r--r--runtime/mirror/method_type_test.cc2
-rw-r--r--runtime/mirror/object-inl.h271
-rw-r--r--runtime/mirror/object-readbarrier-inl.h227
-rw-r--r--runtime/mirror/object-refvisitor-inl.h92
-rw-r--r--runtime/mirror/object.cc1
-rw-r--r--runtime/mirror/object.h11
-rw-r--r--runtime/mirror/object_array-inl.h3
-rw-r--r--runtime/mirror/object_test.cc13
-rw-r--r--runtime/monitor.cc1
-rw-r--r--runtime/native/dalvik_system_DexFile.cc9
-rw-r--r--runtime/native/dalvik_system_VMDebug.cc3
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc1
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.cc1
-rw-r--r--runtime/native/java_lang_Class.cc3
-rw-r--r--runtime/native/java_lang_VMClassLoader.cc1
-rw-r--r--runtime/native/java_lang_Void.cc2
-rw-r--r--runtime/native/java_lang_reflect_Field.cc2
-rw-r--r--runtime/native/scoped_fast_native_object_access-inl.h2
-rw-r--r--runtime/oat_file.cc2
-rw-r--r--runtime/oat_file_assistant.cc1
-rw-r--r--runtime/oat_file_assistant_test.cc1
-rw-r--r--runtime/oat_file_manager.cc4
-rw-r--r--runtime/oat_file_manager.h1
-rw-r--r--runtime/openjdkjvm/OpenjdkJvm.cc29
-rw-r--r--runtime/openjdkjvmti/events.cc3
-rw-r--r--runtime/openjdkjvmti/ti_class.cc2
-rw-r--r--runtime/openjdkjvmti/ti_class_definition.cc2
-rw-r--r--runtime/openjdkjvmti/ti_class_loader.cc1
-rw-r--r--runtime/openjdkjvmti/ti_redefine.cc3
-rw-r--r--runtime/openjdkjvmti/ti_search.cc2
-rw-r--r--runtime/openjdkjvmti/ti_stack.cc4
-rw-r--r--runtime/openjdkjvmti/ti_thread.cc2
-rw-r--r--runtime/openjdkjvmti/ti_threadgroup.cc2
-rw-r--r--runtime/proxy_test.cc1
-rw-r--r--runtime/read_barrier-inl.h1
-rw-r--r--runtime/reference_table_test.cc1
-rw-r--r--runtime/reflection.cc1
-rw-r--r--runtime/reflection_test.cc1
-rw-r--r--runtime/runtime-inl.h1
-rw-r--r--runtime/runtime.cc1
-rw-r--r--runtime/scoped_thread_state_change-inl.h7
-rw-r--r--runtime/scoped_thread_state_change.cc41
-rw-r--r--runtime/scoped_thread_state_change.h25
-rw-r--r--runtime/thread.cc1
-rw-r--r--runtime/verifier/method_verifier.cc12
-rw-r--r--runtime/verifier/method_verifier_test.cc2
-rw-r--r--runtime/verifier/verifier_deps.cc3
-rw-r--r--test/161-final-abstract-class/expected.txt1
-rw-r--r--test/161-final-abstract-class/info.txt1
-rw-r--r--test/161-final-abstract-class/smali/AbstractFinal.smali16
-rw-r--r--test/161-final-abstract-class/smali/TestClass.smali22
-rw-r--r--test/161-final-abstract-class/src/Main.java48
-rw-r--r--test/497-inlining-and-class-loader/clear_dex_cache.cc5
-rw-r--r--test/900-hello-plugin/load_unload.cc2
-rw-r--r--test/911-get-stack-trace/expected.txt70
-rw-r--r--test/911-get-stack-trace/src/art/PrintThread.java22
-rw-r--r--test/911-get-stack-trace/src/art/Test911.java33
-rw-r--r--test/common/runtime_state.cc2
-rwxr-xr-xtest/testrunner/run_build_test_target.py6
-rw-r--r--test/valgrind-suppressions.txt6
-rw-r--r--test/valgrind-target-suppressions.txt7
-rwxr-xr-xtools/run-jdwp-tests.sh13
163 files changed, 1648 insertions, 953 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index ed34a8df5f..11af1c0ca8 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -125,6 +125,7 @@ ART_GTEST_stub_test_DEX_DEPS := AllFields
ART_GTEST_transaction_test_DEX_DEPS := Transaction
ART_GTEST_type_lookup_table_test_DEX_DEPS := Lookup
ART_GTEST_unstarted_runtime_test_DEX_DEPS := Nested
+ART_GTEST_heap_verification_test_DEX_DEPS := ProtoCompare ProtoCompare2 StaticsFromCode XandY
ART_GTEST_verifier_deps_test_DEX_DEPS := VerifierDeps VerifierDepsMulti MultiDex
ART_GTEST_dex_to_dex_decompiler_test_DEX_DEPS := VerifierDeps DexToDexDecompiler
@@ -655,6 +656,7 @@ ART_GTEST_reflection_test_DEX_DEPS :=
ART_GTEST_stub_test_DEX_DEPS :=
ART_GTEST_transaction_test_DEX_DEPS :=
ART_GTEST_dex2oat_environment_tests_DEX_DEPS :=
+ART_GTEST_heap_verification_test_DEX_DEPS :=
ART_GTEST_verifier_deps_test_DEX_DEPS :=
ART_VALGRIND_DEPENDENCIES :=
ART_VALGRIND_TARGET_DEPENDENCIES :=
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 312fc7b35a..dec8b577d8 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -29,6 +29,7 @@ art_cc_defaults {
"debug/elf_debug_writer.cc",
"dex/dex_to_dex_compiler.cc",
"dex/dex_to_dex_decompiler.cc",
+ "dex/inline_method_analyser.cc",
"dex/verified_method.cc",
"dex/verification_results.cc",
"dex/quick_compiler_callbacks.cc",
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 8b3029261f..39edd1eb02 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -18,7 +18,7 @@
#include "arch/instruction_set_features.h"
#include "art_field-inl.h"
-#include "art_method.h"
+#include "art_method-inl.h"
#include "base/enums.h"
#include "class_linker.h"
#include "compiled_method.h"
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index 30d4b47c6a..558c7d5754 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -21,6 +21,7 @@
#include <unordered_set>
#include <vector>
+#include "art_field-inl.h"
#include "debug/dwarf/debug_abbrev_writer.h"
#include "debug/dwarf/debug_info_entry_writer.h"
#include "debug/elf_compilation_unit.h"
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 538fe93793..1573062033 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -27,7 +27,6 @@
#include "dex_instruction-inl.h"
#include "driver/compiler_driver.h"
#include "driver/dex_compilation_unit.h"
-#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
#include "thread-inl.h"
diff --git a/runtime/quick/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index 3347070468..e691a67dc0 100644
--- a/runtime/quick/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -26,7 +26,6 @@
#include "dex_instruction_utils.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
-#include "verifier/method_verifier-inl.h"
/*
* NOTE: This code is part of the quick compiler. It lives in the runtime
@@ -391,7 +390,6 @@ bool AnalyseConstructor(const DexFile::CodeItem* code_item,
#undef STORE_IPUT
result->opcode = kInlineOpConstructor;
- result->flags = kInlineSpecial;
result->d.constructor_data.reserved = 0u;
return true;
}
@@ -429,25 +427,6 @@ static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_CHAR) ==
static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_SHORT) ==
InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT), "iget/iput_short variant");
-// This is used by compiler and debugger. We look into the dex cache for resolved methods and
-// fields. However, in the context of the debugger, not all methods and fields are resolved. Since
-// we need to be able to detect possibly inlined method, we pass a null inline method to indicate
-// we don't want to take unresolved methods and fields into account during analysis.
-bool InlineMethodAnalyser::AnalyseMethodCode(verifier::MethodVerifier* verifier,
- InlineMethod* result) {
- DCHECK(verifier != nullptr);
- if (!Runtime::Current()->UseJitCompilation()) {
- DCHECK_EQ(verifier->CanLoadClasses(), result != nullptr);
- }
-
- // Note: verifier->GetMethod() may be null.
- return AnalyseMethodCode(verifier->CodeItem(),
- verifier->GetMethodReference(),
- (verifier->GetAccessFlags() & kAccStatic) != 0u,
- verifier->GetMethod(),
- result);
-}
-
bool InlineMethodAnalyser::AnalyseMethodCode(ArtMethod* method, InlineMethod* result) {
const DexFile::CodeItem* code_item = method->GetCodeItem();
if (code_item == nullptr) {
@@ -473,7 +452,6 @@ bool InlineMethodAnalyser::AnalyseMethodCode(const DexFile::CodeItem* code_item,
case Instruction::RETURN_VOID:
if (result != nullptr) {
result->opcode = kInlineOpNop;
- result->flags = kInlineSpecial;
result->d.data = 0u;
}
return true;
@@ -549,7 +527,6 @@ bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_ite
if (result != nullptr) {
result->opcode = kInlineOpReturnArg;
- result->flags = kInlineSpecial;
InlineReturnArgData* data = &result->d.return_data;
data->arg = reg - arg_start;
data->is_wide = (return_opcode == Instruction::RETURN_WIDE) ? 1u : 0u;
@@ -586,7 +563,6 @@ bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item
}
if (result != nullptr) {
result->opcode = kInlineOpNonWideConst;
- result->flags = kInlineSpecial;
result->d.data = static_cast<uint64_t>(const_value);
}
return true;
@@ -647,7 +623,6 @@ bool InlineMethodAnalyser::AnalyseIGetMethod(const DexFile::CodeItem* code_item,
return false;
}
result->opcode = kInlineOpIGet;
- result->flags = kInlineSpecial;
data->op_variant = IGetVariant(opcode);
data->method_is_static = is_static ? 1u : 0u;
data->object_arg = object_arg; // Allow IGET on any register, not just "this".
@@ -716,7 +691,6 @@ bool InlineMethodAnalyser::AnalyseIPutMethod(const DexFile::CodeItem* code_item,
return false;
}
result->opcode = kInlineOpIPut;
- result->flags = kInlineSpecial;
data->op_variant = IPutVariant(opcode);
data->method_is_static = is_static ? 1u : 0u;
data->object_arg = object_arg; // Allow IPUT on any register, not just "this".
diff --git a/runtime/quick/inline_method_analyser.h b/compiler/dex/inline_method_analyser.h
index 2df2ced7f4..a35e97fa11 100644
--- a/runtime/quick/inline_method_analyser.h
+++ b/compiler/dex/inline_method_analyser.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_QUICK_INLINE_METHOD_ANALYSER_H_
-#define ART_RUNTIME_QUICK_INLINE_METHOD_ANALYSER_H_
+#ifndef ART_COMPILER_DEX_INLINE_METHOD_ANALYSER_H_
+#define ART_COMPILER_DEX_INLINE_METHOD_ANALYSER_H_
#include "base/macros.h"
#include "base/mutex.h"
@@ -36,128 +36,12 @@ class MethodVerifier;
class ArtMethod;
enum InlineMethodOpcode : uint16_t {
- kIntrinsicDoubleCvt,
- kIntrinsicFloatCvt,
- kIntrinsicFloat2Int,
- kIntrinsicDouble2Long,
- kIntrinsicFloatIsInfinite,
- kIntrinsicDoubleIsInfinite,
- kIntrinsicFloatIsNaN,
- kIntrinsicDoubleIsNaN,
- kIntrinsicReverseBits,
- kIntrinsicReverseBytes,
- kIntrinsicBitCount,
- kIntrinsicCompare,
- kIntrinsicHighestOneBit,
- kIntrinsicLowestOneBit,
- kIntrinsicNumberOfLeadingZeros,
- kIntrinsicNumberOfTrailingZeros,
- kIntrinsicRotateRight,
- kIntrinsicRotateLeft,
- kIntrinsicSignum,
- kIntrinsicAbsInt,
- kIntrinsicAbsLong,
- kIntrinsicAbsFloat,
- kIntrinsicAbsDouble,
- kIntrinsicMinMaxInt,
- kIntrinsicMinMaxLong,
- kIntrinsicMinMaxFloat,
- kIntrinsicMinMaxDouble,
- kIntrinsicCos,
- kIntrinsicSin,
- kIntrinsicAcos,
- kIntrinsicAsin,
- kIntrinsicAtan,
- kIntrinsicAtan2,
- kIntrinsicCbrt,
- kIntrinsicCosh,
- kIntrinsicExp,
- kIntrinsicExpm1,
- kIntrinsicHypot,
- kIntrinsicLog,
- kIntrinsicLog10,
- kIntrinsicNextAfter,
- kIntrinsicSinh,
- kIntrinsicTan,
- kIntrinsicTanh,
- kIntrinsicSqrt,
- kIntrinsicCeil,
- kIntrinsicFloor,
- kIntrinsicRint,
- kIntrinsicRoundFloat,
- kIntrinsicRoundDouble,
- kIntrinsicReferenceGetReferent,
- kIntrinsicCharAt,
- kIntrinsicCompareTo,
- kIntrinsicEquals,
- kIntrinsicGetCharsNoCheck,
- kIntrinsicIsEmptyOrLength,
- kIntrinsicIndexOf,
- kIntrinsicNewStringFromBytes,
- kIntrinsicNewStringFromChars,
- kIntrinsicNewStringFromString,
- kIntrinsicCurrentThread,
- kIntrinsicPeek,
- kIntrinsicPoke,
- kIntrinsicCas,
- kIntrinsicUnsafeGet,
- kIntrinsicUnsafePut,
-
- // 1.8.
- kIntrinsicUnsafeGetAndAddInt,
- kIntrinsicUnsafeGetAndAddLong,
- kIntrinsicUnsafeGetAndSetInt,
- kIntrinsicUnsafeGetAndSetLong,
- kIntrinsicUnsafeGetAndSetObject,
- kIntrinsicUnsafeLoadFence,
- kIntrinsicUnsafeStoreFence,
- kIntrinsicUnsafeFullFence,
-
- kIntrinsicSystemArrayCopyCharArray,
- kIntrinsicSystemArrayCopy,
-
kInlineOpNop,
kInlineOpReturnArg,
kInlineOpNonWideConst,
kInlineOpIGet,
kInlineOpIPut,
kInlineOpConstructor,
- kInlineStringInit,
-};
-std::ostream& operator<<(std::ostream& os, const InlineMethodOpcode& rhs);
-
-enum InlineMethodFlags : uint16_t {
- kNoInlineMethodFlags = 0x0000,
- kInlineIntrinsic = 0x0001,
- kInlineSpecial = 0x0002,
-};
-
-// IntrinsicFlags are stored in InlineMethod::d::raw_data
-enum IntrinsicFlags {
- kIntrinsicFlagNone = 0,
-
- // kIntrinsicMinMaxInt
- kIntrinsicFlagMax = kIntrinsicFlagNone,
- kIntrinsicFlagMin = 1,
-
- // kIntrinsicIsEmptyOrLength
- kIntrinsicFlagLength = kIntrinsicFlagNone,
- kIntrinsicFlagIsEmpty = kIntrinsicFlagMin,
-
- // kIntrinsicIndexOf
- kIntrinsicFlagBase0 = kIntrinsicFlagMin,
-
- // kIntrinsicUnsafeGet, kIntrinsicUnsafePut, kIntrinsicUnsafeCas
- kIntrinsicFlagIsLong = kIntrinsicFlagMin,
- // kIntrinsicUnsafeGet, kIntrinsicUnsafePut
- kIntrinsicFlagIsVolatile = 2,
- // kIntrinsicUnsafePut, kIntrinsicUnsafeCas
- kIntrinsicFlagIsObject = 4,
- // kIntrinsicUnsafePut
- kIntrinsicFlagIsOrdered = 8,
-
- // kIntrinsicDoubleCvt, kIntrinsicFloatCvt.
- kIntrinsicFlagToFloatingPoint = kIntrinsicFlagMin,
};
struct InlineIGetIPutData {
@@ -198,7 +82,6 @@ static_assert(sizeof(InlineConstructorData) == sizeof(uint64_t),
struct InlineMethod {
InlineMethodOpcode opcode;
- InlineMethodFlags flags;
union {
uint64_t data;
InlineIGetIPutData ifield_data;
@@ -213,12 +96,8 @@ class InlineMethodAnalyser {
* Analyse method code to determine if the method is a candidate for inlining.
* If it is, record the inlining data.
*
- * @param verifier the method verifier holding data about the method to analyse.
- * @param method placeholder for the inline method data.
* @return true if the method is a candidate for inlining, false otherwise.
*/
- static bool AnalyseMethodCode(verifier::MethodVerifier* verifier, InlineMethod* result)
- REQUIRES_SHARED(Locks::mutator_lock_);
static bool AnalyseMethodCode(ArtMethod* method, InlineMethod* result)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -274,4 +153,4 @@ class InlineMethodAnalyser {
} // namespace art
-#endif // ART_RUNTIME_QUICK_INLINE_METHOD_ANALYSER_H_
+#endif // ART_COMPILER_DEX_INLINE_METHOD_ANALYSER_H_
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index cbca33320d..608a18aa66 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -18,22 +18,15 @@
#include <algorithm>
#include <memory>
-#include <vector>
-#include "art_method-inl.h"
-#include "base/enums.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "dex_file.h"
#include "dex_instruction-inl.h"
-#include "dex_instruction_utils.h"
-#include "mirror/class-inl.h"
-#include "mirror/dex_cache-inl.h"
-#include "mirror/object-inl.h"
-#include "utils.h"
+#include "runtime.h"
#include "verifier/method_verifier-inl.h"
#include "verifier/reg_type-inl.h"
#include "verifier/register_line-inl.h"
+#include "verifier/verifier_deps.h"
namespace art {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 1a4452429e..805c5dadc1 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -61,6 +61,7 @@
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/throwable.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
index 0c0609009d..37e4f113fa 100644
--- a/compiler/elf_writer.cc
+++ b/compiler/elf_writer.cc
@@ -16,17 +16,8 @@
#include "elf_writer.h"
-#include "art_method-inl.h"
#include "base/unix_file/fd_file.h"
-#include "class_linker.h"
-#include "dex_file-inl.h"
-#include "dex_method_iterator.h"
-#include "driver/compiler_driver.h"
#include "elf_file.h"
-#include "invoke_type.h"
-#include "mirror/object-inl.h"
-#include "oat.h"
-#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index c975944a04..dc880b089e 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -30,7 +30,7 @@
#include "mirror/stack_trace_element.h"
#include "oat_quick_method_header.h"
#include "optimizing/stack_map_stream.h"
-#include "runtime.h"
+#include "runtime-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "handle_scope-inl.h"
#include "thread.h"
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index 897d81993d..7e53d8d2ab 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -22,6 +22,7 @@
#include "android-base/stringprintf.h"
+#include "art_method-inl.h"
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
#include "compiler_callbacks.h"
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index d129249d63..952a7c637a 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -59,6 +59,7 @@
#include "mirror/executable.h"
#include "mirror/method.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
#include "oat.h"
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index 21042a337d..b34d9385c8 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -27,6 +27,7 @@
#include "dex_file.h"
#include "gtest/gtest.h"
#include "indirect_reference_table.h"
+#include "java_vm_ext.h"
#include "jni_internal.h"
#include "mem_map.h"
#include "mirror/class-inl.h"
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index b7c80756b0..5136d7d2b8 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -42,18 +42,23 @@
#endif
#include "bytecode_utils.h"
+#include "class_linker.h"
#include "compiled_method.h"
#include "dex/verified_method.h"
#include "driver/compiler_driver.h"
#include "graph_visualizer.h"
+#include "intern_table.h"
#include "intrinsics.h"
#include "leb128.h"
#include "mirror/array-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object_reference.h"
+#include "mirror/reference.h"
#include "mirror/string.h"
#include "parallel_move_resolver.h"
#include "ssa_liveness_analysis.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-inl.h"
#include "utils/assembler.h"
namespace art {
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 58feea2423..332ab49153 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -321,7 +321,9 @@ class InstructionCodeGeneratorARM64 : public InstructionCodeGenerator {
vixl::aarch64::MemOperand CreateVecMemRegisters(
HVecMemoryOperation* instruction,
Location* reg_loc,
- bool is_load);
+ bool is_load,
+ // This function may acquire a scratch register.
+ vixl::aarch64::UseScratchRegisterScope* temps_scope);
Arm64Assembler* const assembler_;
CodeGeneratorARM64* const codegen_;
diff --git a/compiler/optimizing/code_generator_vector_arm64.cc b/compiler/optimizing/code_generator_vector_arm64.cc
index b3eb639142..93befa439c 100644
--- a/compiler/optimizing/code_generator_vector_arm64.cc
+++ b/compiler/optimizing/code_generator_vector_arm64.cc
@@ -27,6 +27,7 @@ using helpers::HeapOperand;
using helpers::InputRegisterAt;
using helpers::Int64ConstantFrom;
using helpers::XRegisterFrom;
+using helpers::WRegisterFrom;
#define __ GetVIXLAssembler()->
@@ -774,7 +775,8 @@ static void CreateVecMemLocations(ArenaAllocator* arena,
MemOperand InstructionCodeGeneratorARM64::CreateVecMemRegisters(
HVecMemoryOperation* instruction,
Location* reg_loc,
- bool is_load) {
+ bool is_load,
+ UseScratchRegisterScope* temps_scope) {
LocationSummary* locations = instruction->GetLocations();
Register base = InputRegisterAt(instruction, 0);
Location index = locations->InAt(1);
@@ -784,20 +786,18 @@ MemOperand InstructionCodeGeneratorARM64::CreateVecMemRegisters(
uint32_t offset = mirror::Array::DataOffset(Primitive::ComponentSize(packed_type)).Uint32Value();
size_t shift = Primitive::ComponentSizeShift(packed_type);
- UseScratchRegisterScope temps(GetVIXLAssembler());
- Register temp = temps.AcquireSameSizeAs(base);
+ // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
+ DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
+
if (index.IsConstant()) {
offset += Int64ConstantFrom(index) << shift;
- __ Add(temp, base, offset);
+ return HeapOperand(base, offset);
} else {
- if (instruction->InputAt(0)->IsIntermediateAddress()) {
- temp = base;
- } else {
- __ Add(temp, base, offset);
- }
- __ Add(temp.X(), temp.X(), Operand(XRegisterFrom(index), LSL, shift));
+ Register temp = temps_scope->AcquireSameSizeAs(base);
+ __ Add(temp, base, Operand(WRegisterFrom(index), LSL, shift));
+
+ return HeapOperand(temp, offset);
}
- return HeapOperand(temp);
}
void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
@@ -806,28 +806,22 @@ void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Location reg_loc = Location::NoLocation();
- MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ true);
+ UseScratchRegisterScope temps(GetVIXLAssembler());
+ MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ true, &temps);
VRegister reg = VRegisterFrom(reg_loc);
+
switch (instruction->GetPackedType()) {
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
- DCHECK_EQ(16u, instruction->GetVectorLength());
- __ Ld1(reg.V16B(), mem);
- break;
case Primitive::kPrimChar:
case Primitive::kPrimShort:
- DCHECK_EQ(8u, instruction->GetVectorLength());
- __ Ld1(reg.V8H(), mem);
- break;
case Primitive::kPrimInt:
case Primitive::kPrimFloat:
- DCHECK_EQ(4u, instruction->GetVectorLength());
- __ Ld1(reg.V4S(), mem);
- break;
case Primitive::kPrimLong:
case Primitive::kPrimDouble:
- DCHECK_EQ(2u, instruction->GetVectorLength());
- __ Ld1(reg.V2D(), mem);
+ DCHECK_LE(2u, instruction->GetVectorLength());
+ DCHECK_LE(instruction->GetVectorLength(), 16u);
+ __ Ldr(reg, mem);
break;
default:
LOG(FATAL) << "Unsupported SIMD type";
@@ -841,28 +835,22 @@ void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Location reg_loc = Location::NoLocation();
- MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ false);
+ UseScratchRegisterScope temps(GetVIXLAssembler());
+ MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ false, &temps);
VRegister reg = VRegisterFrom(reg_loc);
+
switch (instruction->GetPackedType()) {
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
- DCHECK_EQ(16u, instruction->GetVectorLength());
- __ St1(reg.V16B(), mem);
- break;
case Primitive::kPrimChar:
case Primitive::kPrimShort:
- DCHECK_EQ(8u, instruction->GetVectorLength());
- __ St1(reg.V8H(), mem);
- break;
case Primitive::kPrimInt:
case Primitive::kPrimFloat:
- DCHECK_EQ(4u, instruction->GetVectorLength());
- __ St1(reg.V4S(), mem);
- break;
case Primitive::kPrimLong:
case Primitive::kPrimDouble:
- DCHECK_EQ(2u, instruction->GetVectorLength());
- __ St1(reg.V2D(), mem);
+ DCHECK_LE(2u, instruction->GetVectorLength());
+ DCHECK_LE(instruction->GetVectorLength(), 16u);
+ __ Str(reg, mem);
break;
default:
LOG(FATAL) << "Unsupported SIMD type";
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 4af2539812..1f8a58cdaa 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -22,6 +22,7 @@
#include "class_linker.h"
#include "constant_folding.h"
#include "dead_code_elimination.h"
+#include "dex/inline_method_analyser.h"
#include "dex/verified_method.h"
#include "dex/verification_results.h"
#include "driver/compiler_driver-inl.h"
@@ -37,7 +38,6 @@
#include "optimizing_compiler.h"
#include "reference_type_propagation.h"
#include "register_allocator_linear_scan.h"
-#include "quick/inline_method_analyser.h"
#include "sharpening.h"
#include "ssa_builder.h"
#include "ssa_phi_elimination.h"
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 60790e5b84..2dcc12e294 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -16,6 +16,8 @@
#include "instruction_simplifier.h"
+#include "art_method-inl.h"
+#include "class_linker-inl.h"
#include "escape.h"
#include "intrinsics.h"
#include "mirror/class-inl.h"
diff --git a/compiler/optimizing/instruction_simplifier_arm.cc b/compiler/optimizing/instruction_simplifier_arm.cc
index 5f5e29b024..3fc7c50bb1 100644
--- a/compiler/optimizing/instruction_simplifier_arm.cc
+++ b/compiler/optimizing/instruction_simplifier_arm.cc
@@ -19,6 +19,7 @@
#include "instruction_simplifier_arm.h"
#include "instruction_simplifier_shared.h"
#include "mirror/array-inl.h"
+#include "mirror/string.h"
#include "nodes.h"
namespace art {
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 8df80adc9f..6236bd87ab 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -16,7 +16,8 @@
#include "intrinsics.h"
-#include "art_method.h"
+#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "class_linker.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index 1006a776f0..750f9cc213 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -22,9 +22,13 @@
#include "entrypoints/quick/quick_entrypoints.h"
#include "intrinsics.h"
#include "intrinsics_utils.h"
+#include "lock_word.h"
#include "mirror/array-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/reference.h"
#include "mirror/string.h"
-#include "thread.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-inl.h"
#include "utils/arm/assembler_arm.h"
namespace art {
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 47bcb5d000..4d360158a2 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -22,9 +22,13 @@
#include "common_arm64.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "intrinsics.h"
+#include "lock_word.h"
#include "mirror/array-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/reference.h"
#include "mirror/string-inl.h"
-#include "thread.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-inl.h"
#include "utils/arm64/assembler_arm64.h"
using namespace vixl::aarch64; // NOLINT(build/namespaces)
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 0d933eaf82..fd8a37ae05 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -17,10 +17,16 @@
#include "intrinsics_arm_vixl.h"
#include "arch/arm/instruction_set_features_arm.h"
+#include "art_method.h"
#include "code_generator_arm_vixl.h"
#include "common_arm.h"
#include "lock_word.h"
#include "mirror/array-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/reference.h"
+#include "mirror/string.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-inl.h"
#include "aarch32/constants-aarch32.h"
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index ecf919bceb..8e4574774f 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -25,9 +25,13 @@
#include "entrypoints/quick/quick_entrypoints.h"
#include "intrinsics.h"
#include "intrinsics_utils.h"
+#include "lock_word.h"
#include "mirror/array-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/reference.h"
#include "mirror/string.h"
-#include "thread.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-inl.h"
#include "utils/x86/assembler_x86.h"
#include "utils/x86/constants_x86.h"
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 13956dfb8e..8ed2ad86bf 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -19,15 +19,19 @@
#include <limits>
#include "arch/x86_64/instruction_set_features_x86_64.h"
-#include "art_method-inl.h"
+#include "art_method.h"
#include "base/bit_utils.h"
#include "code_generator_x86_64.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "intrinsics.h"
#include "intrinsics_utils.h"
+#include "lock_word.h"
#include "mirror/array-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/reference.h"
#include "mirror/string.h"
-#include "thread.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-inl.h"
#include "utils/x86_64/assembler_x86_64.h"
#include "utils/x86_64/constants_x86_64.h"
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index e71fea92a9..ca953a1a7e 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -17,6 +17,8 @@
#include <cfloat>
+#include "art_method-inl.h"
+#include "class_linker-inl.h"
#include "code_generator.h"
#include "common_dominator.h"
#include "ssa_builder.h"
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index af953c8f99..8368026e92 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1362,7 +1362,6 @@ class HLoopInformationOutwardIterator : public ValueObject {
M(UShr, BinaryOperation) \
M(Xor, BinaryOperation) \
M(VecReplicateScalar, VecUnaryOperation) \
- M(VecSetScalars, VecUnaryOperation) \
M(VecSumReduce, VecUnaryOperation) \
M(VecCnv, VecUnaryOperation) \
M(VecNeg, VecUnaryOperation) \
@@ -1382,6 +1381,7 @@ class HLoopInformationOutwardIterator : public ValueObject {
M(VecShl, VecBinaryOperation) \
M(VecShr, VecBinaryOperation) \
M(VecUShr, VecBinaryOperation) \
+ M(VecSetScalars, VecOperation) \
M(VecMultiplyAccumulate, VecOperation) \
M(VecLoad, VecMemoryOperation) \
M(VecStore, VecMemoryOperation) \
diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h
index 450691c1ea..fb9dfb7afa 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -116,16 +116,23 @@ class HVecOperation : public HVariableInputSizeInstruction {
class HVecUnaryOperation : public HVecOperation {
public:
HVecUnaryOperation(ArenaAllocator* arena,
+ HInstruction* input,
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc)
: HVecOperation(arena,
packed_type,
SideEffects::None(),
- /*number_of_inputs*/ 1,
+ /* number_of_inputs */ 1,
vector_length,
- dex_pc) { }
+ dex_pc) {
+ SetRawInputAt(0, input);
+ }
+
+ HInstruction* GetInput() const { return InputAt(0); }
+
DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation);
+
private:
DISALLOW_COPY_AND_ASSIGN(HVecUnaryOperation);
};
@@ -134,20 +141,26 @@ class HVecUnaryOperation : public HVecOperation {
class HVecBinaryOperation : public HVecOperation {
public:
HVecBinaryOperation(ArenaAllocator* arena,
+ HInstruction* left,
+ HInstruction* right,
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc)
: HVecOperation(arena,
packed_type,
SideEffects::None(),
- /*number_of_inputs*/ 2,
+ /* number_of_inputs */ 2,
vector_length,
- dex_pc) { }
+ dex_pc) {
+ SetRawInputAt(0, left);
+ SetRawInputAt(1, right);
+ }
HInstruction* GetLeft() const { return InputAt(0); }
HInstruction* GetRight() const { return InputAt(1); }
DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
+
private:
DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation);
};
@@ -179,7 +192,7 @@ class HVecMemoryOperation : public HVecOperation {
};
//
-// Definitions of concrete vector operations in HIR.
+// Definitions of concrete unary vector operations in HIR.
//
// Replicates the given scalar into a vector,
@@ -191,32 +204,14 @@ class HVecReplicateScalar FINAL : public HVecUnaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
- SetRawInputAt(0, scalar);
+ : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) {
+ DCHECK(!scalar->IsVecOperation());
}
DECLARE_INSTRUCTION(VecReplicateScalar);
private:
DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
};
-// Assigns the given scalar elements to a vector,
-// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
-class HVecSetScalars FINAL : public HVecUnaryOperation {
- HVecSetScalars(ArenaAllocator* arena,
- HInstruction** scalars, // array
- Primitive::Type packed_type,
- size_t vector_length,
- uint32_t dex_pc = kNoDexPc)
- : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
- for (size_t i = 0; i < vector_length; i++) {
- SetRawInputAt(0, scalars[i]);
- }
- }
- DECLARE_INSTRUCTION(VecSetScalars);
- private:
- DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
-};
-
// Sum-reduces the given vector into a shorter vector (m < n) or scalar (m = 1),
// viz. sum-reduce[ x1, .. , xn ] = [ y1, .., ym ], where yi = sum_j x_j.
class HVecSumReduce FINAL : public HVecUnaryOperation {
@@ -225,10 +220,9 @@ class HVecSumReduce FINAL : public HVecUnaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
DCHECK(input->IsVecOperation());
DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, input);
}
// TODO: probably integral promotion
@@ -248,10 +242,9 @@ class HVecCnv FINAL : public HVecUnaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
DCHECK(input->IsVecOperation());
DCHECK_NE(input->AsVecOperation()->GetPackedType(), packed_type); // actual convert
- SetRawInputAt(0, input);
}
Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
@@ -272,10 +265,9 @@ class HVecNeg FINAL : public HVecUnaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
DCHECK(input->IsVecOperation());
DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, input);
}
DECLARE_INSTRUCTION(VecNeg);
private:
@@ -291,10 +283,9 @@ class HVecAbs FINAL : public HVecUnaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
DCHECK(input->IsVecOperation());
DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, input);
}
DECLARE_INSTRUCTION(VecAbs);
private:
@@ -311,15 +302,18 @@ class HVecNot FINAL : public HVecUnaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
DCHECK(input->IsVecOperation());
- SetRawInputAt(0, input);
}
DECLARE_INSTRUCTION(VecNot);
private:
DISALLOW_COPY_AND_ASSIGN(HVecNot);
};
+//
+// Definitions of concrete binary vector operations in HIR.
+//
+
// Adds every component in the two vectors,
// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
class HVecAdd FINAL : public HVecBinaryOperation {
@@ -330,12 +324,10 @@ class HVecAdd FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecAdd);
private:
@@ -356,14 +348,12 @@ class HVecHalvingAdd FINAL : public HVecBinaryOperation {
bool is_unsigned,
bool is_rounded,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc),
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc),
is_unsigned_(is_unsigned),
is_rounded_(is_rounded) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
bool IsUnsigned() const { return is_unsigned_; }
@@ -388,12 +378,10 @@ class HVecSub FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecSub);
private:
@@ -410,12 +398,10 @@ class HVecMul FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecMul);
private:
@@ -432,12 +418,10 @@ class HVecDiv FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecDiv);
private:
@@ -454,12 +438,10 @@ class HVecMin FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecMin);
private:
@@ -476,12 +458,10 @@ class HVecMax FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecMax);
private:
@@ -498,10 +478,8 @@ class HVecAnd FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecAnd);
private:
@@ -518,10 +496,8 @@ class HVecAndNot FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecAndNot);
private:
@@ -538,10 +514,8 @@ class HVecOr FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecOr);
private:
@@ -558,10 +532,8 @@ class HVecXor FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation() && right->IsVecOperation());
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecXor);
private:
@@ -578,11 +550,9 @@ class HVecShl FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecShl);
private:
@@ -599,11 +569,9 @@ class HVecShr FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecShr);
private:
@@ -620,17 +588,43 @@ class HVecUShr FINAL : public HVecBinaryOperation {
Primitive::Type packed_type,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
DCHECK(left->IsVecOperation());
DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
- SetRawInputAt(0, left);
- SetRawInputAt(1, right);
}
DECLARE_INSTRUCTION(VecUShr);
private:
DISALLOW_COPY_AND_ASSIGN(HVecUShr);
};
+//
+// Definitions of concrete miscellaneous vector operations in HIR.
+//
+
+// Assigns the given scalar elements to a vector,
+// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
+class HVecSetScalars FINAL : public HVecOperation {
+ HVecSetScalars(ArenaAllocator* arena,
+ HInstruction** scalars, // array
+ Primitive::Type packed_type,
+ size_t vector_length,
+ uint32_t dex_pc = kNoDexPc)
+ : HVecOperation(arena,
+ packed_type,
+ SideEffects::None(),
+ /* number_of_inputs */ vector_length,
+ vector_length,
+ dex_pc) {
+ for (size_t i = 0; i < vector_length; i++) {
+ DCHECK(!scalars[i]->IsVecOperation());
+ SetRawInputAt(0, scalars[i]);
+ }
+ }
+ DECLARE_INSTRUCTION(VecSetScalars);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
+};
+
// Multiplies every component in the two vectors, adds the result vector to the accumulator vector.
// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] =
// [ acc1 + x1 * y1, .. , accn + xn * yn ].
@@ -647,7 +641,7 @@ class HVecMultiplyAccumulate FINAL : public HVecOperation {
: HVecOperation(arena,
packed_type,
SideEffects::None(),
- /*number_of_inputs*/ 3,
+ /* number_of_inputs */ 3,
vector_length,
dex_pc),
op_kind_(op) {
@@ -697,7 +691,7 @@ class HVecLoad FINAL : public HVecMemoryOperation {
: HVecMemoryOperation(arena,
packed_type,
SideEffects::ArrayReadOfType(packed_type),
- /*number_of_inputs*/ 2,
+ /* number_of_inputs */ 2,
vector_length,
dex_pc) {
SetRawInputAt(0, base);
@@ -722,7 +716,7 @@ class HVecStore FINAL : public HVecMemoryOperation {
: HVecMemoryOperation(arena,
packed_type,
SideEffects::ArrayWriteOfType(packed_type),
- /*number_of_inputs*/ 3,
+ /* number_of_inputs */ 3,
vector_length,
dex_pc) {
DCHECK(value->IsVecOperation());
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index d5637b9b75..98332d35fb 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -16,6 +16,8 @@
#include "reference_type_propagation.h"
+#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "base/enums.h"
#include "class_linker-inl.h"
#include "mirror/class-inl.h"
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index 3b6b9cc7f0..0b1ab758b2 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -17,6 +17,7 @@
// Test is in compiler, as it uses compiler related code.
#include "verifier/verifier_deps.h"
+#include "art_method-inl.h"
#include "class_linker.h"
#include "common_compiler_test.h"
#include "compiler_callbacks.h"
diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc
index f307cbc4f5..06a0f231ba 100644
--- a/imgdiag/imgdiag.cc
+++ b/imgdiag/imgdiag.cc
@@ -28,6 +28,7 @@
#include "android-base/stringprintf.h"
+#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/unix_file/fd_file.h"
#include "gc/space/image_space.h"
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 0c2717f207..fbb0978d53 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -42,6 +42,7 @@
#include "mirror/dex_cache.h"
#include "mirror/executable.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "mirror/method.h"
#include "mirror/reference.h"
#include "noop_compiler_callbacks.h"
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 8972e91321..0860b2e899 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -93,6 +93,7 @@ cc_defaults {
"gc/space/space.cc",
"gc/space/zygote_space.cc",
"gc/task_processor.cc",
+ "gc/verification.cc",
"hprof/hprof.cc",
"image.cc",
"indirect_reference_table.cc",
@@ -186,13 +187,13 @@ cc_defaults {
"plugin.cc",
"primitive.cc",
"quick_exception_handler.cc",
- "quick/inline_method_analyser.cc",
"reference_table.cc",
"reflection.cc",
"runtime.cc",
"runtime_callbacks.cc",
"runtime_common.cc",
"runtime_options.cc",
+ "scoped_thread_state_change.cc",
"signal_catcher.cc",
"stack.cc",
"stack_map.cc",
@@ -451,7 +452,6 @@ gensrcs {
"oat.h",
"object_callbacks.h",
"process_state.h",
- "quick/inline_method_analyser.h",
"runtime.h",
"stack.h",
"thread.h",
@@ -548,6 +548,7 @@ art_cc_test {
"gc/accounting/space_bitmap_test.cc",
"gc/collector/immune_spaces_test.cc",
"gc/heap_test.cc",
+ "gc/heap_verification_test.cc",
"gc/reference_queue_test.cc",
"gc/space/dlmalloc_space_static_test.cc",
"gc/space/dlmalloc_space_random_test.cc",
diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc
index 923ff4ff29..4c15450ff7 100644
--- a/runtime/arch/arm/fault_handler_arm.cc
+++ b/runtime/arch/arm/fault_handler_arm.cc
@@ -19,14 +19,12 @@
#include <sys/ucontext.h>
-#include "art_method-inl.h"
+#include "art_method.h"
#include "base/enums.h"
-#include "base/macros.h"
#include "base/hex_dump.h"
-#include "globals.h"
#include "base/logging.h"
-#include "base/hex_dump.h"
-#include "thread.h"
+#include "base/macros.h"
+#include "globals.h"
#include "thread-inl.h"
//
diff --git a/runtime/arch/arm64/fault_handler_arm64.cc b/runtime/arch/arm64/fault_handler_arm64.cc
index 193af58f11..dc4e8f389e 100644
--- a/runtime/arch/arm64/fault_handler_arm64.cc
+++ b/runtime/arch/arm64/fault_handler_arm64.cc
@@ -19,14 +19,13 @@
#include <sys/ucontext.h>
-#include "art_method-inl.h"
+#include "art_method.h"
#include "base/enums.h"
+#include "base/hex_dump.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "globals.h"
-#include "base/logging.h"
-#include "base/hex_dump.h"
#include "registers_arm64.h"
-#include "thread.h"
#include "thread-inl.h"
extern "C" void art_quick_throw_stack_overflow();
diff --git a/runtime/arch/mips/fault_handler_mips.cc b/runtime/arch/mips/fault_handler_mips.cc
index f9c19e87e6..7072a8a613 100644
--- a/runtime/arch/mips/fault_handler_mips.cc
+++ b/runtime/arch/mips/fault_handler_mips.cc
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-#include "arch/mips/quick_method_frame_info_mips.h"
#include "fault_handler.h"
#include <sys/ucontext.h>
-#include "art_method-inl.h"
+
+#include "art_method.h"
+#include "base/hex_dump.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "globals.h"
-#include "base/logging.h"
-#include "base/hex_dump.h"
+#include "quick_method_frame_info_mips.h"
#include "registers_mips.h"
-#include "thread.h"
#include "thread-inl.h"
extern "C" void art_quick_throw_stack_overflow();
diff --git a/runtime/arch/mips64/fault_handler_mips64.cc b/runtime/arch/mips64/fault_handler_mips64.cc
index d668d3ab62..f9a92c834e 100644
--- a/runtime/arch/mips64/fault_handler_mips64.cc
+++ b/runtime/arch/mips64/fault_handler_mips64.cc
@@ -14,16 +14,17 @@
* limitations under the License.
*/
-#include "arch/mips64/quick_method_frame_info_mips64.h"
#include "fault_handler.h"
+
#include <sys/ucontext.h>
-#include "art_method-inl.h"
+
+#include "art_method.h"
+#include "base/hex_dump.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "globals.h"
-#include "base/logging.h"
-#include "base/hex_dump.h"
+#include "quick_method_frame_info_mips64.h"
#include "registers_mips64.h"
-#include "thread.h"
#include "thread-inl.h"
extern "C" void art_quick_throw_stack_overflow();
diff --git a/runtime/arch/x86/fault_handler_x86.cc b/runtime/arch/x86/fault_handler_x86.cc
index 014cc15a40..7d8abb8cc5 100644
--- a/runtime/arch/x86/fault_handler_x86.cc
+++ b/runtime/arch/x86/fault_handler_x86.cc
@@ -19,14 +19,13 @@
#include <sys/ucontext.h>
-#include "art_method-inl.h"
+#include "art_method.h"
#include "base/enums.h"
-#include "base/macros.h"
-#include "globals.h"
-#include "base/logging.h"
#include "base/hex_dump.h"
+#include "base/logging.h"
+#include "base/macros.h"
#include "base/safe_copy.h"
-#include "thread.h"
+#include "globals.h"
#include "thread-inl.h"
#if defined(__APPLE__)
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index 16b73c681f..0de0f02f9b 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "class_linker.h"
+#include "dex_file-inl.h"
#include "gc_root-inl.h"
#include "gc/accounting/card_table-inl.h"
#include "jvalue.h"
@@ -46,16 +47,6 @@ inline void ArtField::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_clas
declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
}
-inline uint32_t ArtField::GetAccessFlags() {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return access_flags_;
-}
-
-inline MemberOffset ArtField::GetOffset() {
- DCHECK(GetDeclaringClass()->IsResolved());
- return MemberOffset(offset_);
-}
-
inline MemberOffset ArtField::GetOffsetDuringLinking() {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return MemberOffset(offset_);
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index 7e131040be..bc728f4476 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -78,5 +78,12 @@ std::string ArtField::PrettyField(bool with_type) {
return result;
}
+void ArtField::GetAccessFlagsDCheck() {
+ CHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
+}
+
+void ArtField::GetOffsetDCheck() {
+ CHECK(GetDeclaringClass()->IsResolved());
+}
} // namespace art
diff --git a/runtime/art_field.h b/runtime/art_field.h
index 666ed8a868..3789b0ce2f 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -51,7 +51,12 @@ class ArtField FINAL {
return declaring_class_.AddressWithoutBarrier();
}
- uint32_t GetAccessFlags() REQUIRES_SHARED(Locks::mutator_lock_);
+ uint32_t GetAccessFlags() REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kIsDebugBuild) {
+ GetAccessFlagsDCheck();
+ }
+ return access_flags_;
+ }
void SetAccessFlags(uint32_t new_access_flags) REQUIRES_SHARED(Locks::mutator_lock_) {
// Not called within a transaction.
@@ -80,7 +85,12 @@ class ArtField FINAL {
}
// Offset to field within an Object.
- MemberOffset GetOffset() REQUIRES_SHARED(Locks::mutator_lock_);
+ MemberOffset GetOffset() REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kIsDebugBuild) {
+ GetOffsetDCheck();
+ }
+ return MemberOffset(offset_);
+ }
static MemberOffset OffsetOffset() {
return MemberOffset(OFFSETOF_MEMBER(ArtField, offset_));
@@ -227,6 +237,9 @@ class ArtField FINAL {
ObjPtr<mirror::DexCache> dex_cache)
REQUIRES_SHARED(Locks::mutator_lock_);
+ void GetAccessFlagsDCheck() REQUIRES_SHARED(Locks::mutator_lock_);
+ void GetOffsetDCheck() REQUIRES_SHARED(Locks::mutator_lock_);
+
GcRoot<mirror::Class> declaring_class_;
uint32_t access_flags_ = 0;
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 5cf0e0f90c..59cd978a66 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -82,37 +82,6 @@ inline bool ArtMethod::CASDeclaringClass(mirror::Class* expected_class,
expected_root, desired_root);
}
-// AssertSharedHeld doesn't work in GetAccessFlags, so use a NO_THREAD_SAFETY_ANALYSIS helper.
-// TODO: Figure out why ASSERT_SHARED_CAPABILITY doesn't work.
-template <ReadBarrierOption kReadBarrierOption>
-ALWAYS_INLINE static inline void DoGetAccessFlagsHelper(ArtMethod* method)
- NO_THREAD_SAFETY_ANALYSIS {
- CHECK(method->IsRuntimeMethod() ||
- method->GetDeclaringClass<kReadBarrierOption>()->IsIdxLoaded() ||
- method->GetDeclaringClass<kReadBarrierOption>()->IsErroneous());
-}
-
-template <ReadBarrierOption kReadBarrierOption>
-inline uint32_t ArtMethod::GetAccessFlags() {
- if (kCheckDeclaringClassState) {
- Thread* self = Thread::Current();
- if (!Locks::mutator_lock_->IsSharedHeld(self)) {
- if (self->IsThreadSuspensionAllowable()) {
- ScopedObjectAccess soa(self);
- CHECK(IsRuntimeMethod() ||
- GetDeclaringClass<kReadBarrierOption>()->IsIdxLoaded() ||
- GetDeclaringClass<kReadBarrierOption>()->IsErroneous());
- }
- } else {
- // We cannot use SOA in this case. We might be holding the lock, but may not be in the
- // runnable state (e.g., during GC).
- Locks::mutator_lock_->AssertSharedHeld(self);
- DoGetAccessFlagsHelper<kReadBarrierOption>(this);
- }
- }
- return access_flags_.load(std::memory_order_relaxed);
-}
-
inline uint16_t ArtMethod::GetMethodIndex() {
DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved());
return method_index_;
@@ -224,10 +193,6 @@ inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
}
}
-inline bool ArtMethod::IsRuntimeMethod() {
- return dex_method_index_ == DexFile::kDexNoIndex;
-}
-
inline bool ArtMethod::IsCalleeSaveMethod() {
if (!IsRuntimeMethod()) {
return false;
@@ -273,6 +238,11 @@ inline const char* ArtMethod::GetDeclaringClassDescriptor() {
return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx));
}
+inline const char* ArtMethod::GetShorty() {
+ uint32_t unused_length;
+ return GetShorty(&unused_length);
+}
+
inline const char* ArtMethod::GetShorty(uint32_t* out_length) {
DCHECK(!IsProxyMethod());
const DexFile* dex_file = GetDexFile();
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 76fdd43992..7de8916ad5 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -21,7 +21,6 @@
#include "android-base/stringprintf.h"
#include "arch/context.h"
-#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/stringpiece.h"
#include "class_linker-inl.h"
@@ -56,6 +55,10 @@ extern "C" void art_quick_invoke_stub(ArtMethod*, uint32_t*, uint32_t, Thread*,
extern "C" void art_quick_invoke_static_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
const char*);
+// Enforce that we he have the right index for runtime methods.
+static_assert(ArtMethod::kRuntimeMethodDexMethodIndex == DexFile::kDexNoIndex,
+ "Wrong runtime-method dex method index");
+
ArtMethod* ArtMethod::GetNonObsoleteMethod() {
DCHECK_EQ(kRuntimePointerSize, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
if (LIKELY(!IsObsolete())) {
@@ -807,4 +810,35 @@ std::string ArtMethod::JniLongName() {
return long_name;
}
+// AssertSharedHeld doesn't work in GetAccessFlags, so use a NO_THREAD_SAFETY_ANALYSIS helper.
+// TODO: Figure out why ASSERT_SHARED_CAPABILITY doesn't work.
+template <ReadBarrierOption kReadBarrierOption>
+ALWAYS_INLINE static inline void DoGetAccessFlagsHelper(ArtMethod* method)
+ NO_THREAD_SAFETY_ANALYSIS {
+ CHECK(method->IsRuntimeMethod() ||
+ method->GetDeclaringClass<kReadBarrierOption>()->IsIdxLoaded() ||
+ method->GetDeclaringClass<kReadBarrierOption>()->IsErroneous());
+}
+
+template <ReadBarrierOption kReadBarrierOption> void ArtMethod::GetAccessFlagsDCheck() {
+ if (kCheckDeclaringClassState) {
+ Thread* self = Thread::Current();
+ if (!Locks::mutator_lock_->IsSharedHeld(self)) {
+ if (self->IsThreadSuspensionAllowable()) {
+ ScopedObjectAccess soa(self);
+ CHECK(IsRuntimeMethod() ||
+ GetDeclaringClass<kReadBarrierOption>()->IsIdxLoaded() ||
+ GetDeclaringClass<kReadBarrierOption>()->IsErroneous());
+ }
+ } else {
+ // We cannot use SOA in this case. We might be holding the lock, but may not be in the
+ // runnable state (e.g., during GC).
+ Locks::mutator_lock_->AssertSharedHeld(self);
+ DoGetAccessFlagsHelper<kReadBarrierOption>(this);
+ }
+ }
+}
+template void ArtMethod::GetAccessFlagsDCheck<ReadBarrierOption::kWithReadBarrier>();
+template void ArtMethod::GetAccessFlagsDCheck<ReadBarrierOption::kWithoutReadBarrier>();
+
} // namespace art
diff --git a/runtime/art_method.h b/runtime/art_method.h
index b01b344bda..856bfd23e5 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -55,6 +55,10 @@ class ArtMethod FINAL {
public:
static constexpr bool kCheckDeclaringClassState = kIsDebugBuild;
+ // The runtime dex_method_index is kDexNoIndex. To lower dependencies, we use this
+ // constexpr, and ensure that the value is correct in art_method.cc.
+ static constexpr uint32_t kRuntimeMethodDexMethodIndex = 0xFFFFFFFF;
+
ArtMethod() : access_flags_(0), dex_code_item_offset_(0), dex_method_index_(0),
method_index_(0), hotness_count_(0) { }
@@ -90,7 +94,12 @@ class ArtMethod FINAL {
// Note: GetAccessFlags acquires the mutator lock in debug mode to check that it is not called for
// a proxy method.
template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- ALWAYS_INLINE uint32_t GetAccessFlags();
+ uint32_t GetAccessFlags() {
+ if (kCheckDeclaringClassState) {
+ GetAccessFlagsDCheck<kReadBarrierOption>();
+ }
+ return access_flags_.load(std::memory_order_relaxed);
+ }
// This version should only be called when it's certain there is no
// concurrency so there is no need to guarantee atomicity. For example,
@@ -504,7 +513,9 @@ class ArtMethod FINAL {
// Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
// conventions for a method of managed code. Returns false for Proxy methods.
- ALWAYS_INLINE bool IsRuntimeMethod();
+ ALWAYS_INLINE bool IsRuntimeMethod() {
+ return dex_method_index_ == kRuntimeMethodDexMethodIndex;;
+ }
// Is this a hand crafted method used for something like describing callee saves?
bool IsCalleeSaveMethod() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -532,10 +543,7 @@ class ArtMethod FINAL {
const char* GetDeclaringClassDescriptor() REQUIRES_SHARED(Locks::mutator_lock_);
- const char* GetShorty() REQUIRES_SHARED(Locks::mutator_lock_) {
- uint32_t unused_length;
- return GetShorty(&unused_length);
- }
+ ALWAYS_INLINE const char* GetShorty() REQUIRES_SHARED(Locks::mutator_lock_);
const char* GetShorty(uint32_t* out_length) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -743,6 +751,8 @@ class ArtMethod FINAL {
}
}
+ template <ReadBarrierOption kReadBarrierOption> void GetAccessFlagsDCheck();
+
DISALLOW_COPY_AND_ASSIGN(ArtMethod); // Need to use CopyFrom to deal with 32 vs 64 bits.
};
diff --git a/runtime/base/allocator.cc b/runtime/base/allocator.cc
index f1d0a5fbff..2a2790c7d9 100644
--- a/runtime/base/allocator.cc
+++ b/runtime/base/allocator.cc
@@ -21,7 +21,6 @@
#include "atomic.h"
#include "base/logging.h"
-#include "thread-inl.h"
namespace art {
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 9ddc6cf0ae..3c51f52616 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -25,7 +25,7 @@
#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/iftable.h"
-#include "mirror/object_array.h"
+#include "mirror/object_array-inl.h"
#include "handle_scope-inl.h"
#include "scoped_thread_state_change-inl.h"
@@ -33,10 +33,6 @@
namespace art {
-inline mirror::Class* ClassLinker::FindSystemClass(Thread* self, const char* descriptor) {
- return FindClass(self, descriptor, ScopedNullHandle<mirror::ClassLoader>());
-}
-
inline mirror::Class* ClassLinker::FindArrayClass(Thread* self,
ObjPtr<mirror::Class>* element_class) {
for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
@@ -65,19 +61,6 @@ inline mirror::Class* ClassLinker::FindArrayClass(Thread* self,
return array_class.Ptr();
}
-inline mirror::String* ClassLinker::ResolveString(dex::StringIndex string_idx,
- ArtMethod* referrer) {
- Thread::PoisonObjectPointersIfDebug();
- ObjPtr<mirror::String> string = referrer->GetDexCache()->GetResolvedString(string_idx);
- if (UNLIKELY(string == nullptr)) {
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
- const DexFile& dex_file = *dex_cache->GetDexFile();
- string = ResolveString(dex_file, string_idx, dex_cache);
- }
- return string.Ptr();
-}
-
inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(
dex::TypeIndex type_idx,
ObjPtr<mirror::DexCache> dex_cache,
@@ -191,36 +174,6 @@ inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
return resolved_field;
}
-inline mirror::Object* ClassLinker::AllocObject(Thread* self) {
- return GetClassRoot(kJavaLangObject)->Alloc<true, false>(
- self,
- Runtime::Current()->GetHeap()->GetCurrentAllocator()).Ptr();
-}
-
-template <class T>
-inline mirror::ObjectArray<T>* ClassLinker::AllocObjectArray(Thread* self, size_t length) {
- return mirror::ObjectArray<T>::Alloc(self, GetClassRoot(kObjectArrayClass), length);
-}
-
-inline mirror::ObjectArray<mirror::Class>* ClassLinker::AllocClassArray(Thread* self,
- size_t length) {
- return mirror::ObjectArray<mirror::Class>::Alloc(self, GetClassRoot(kClassArrayClass), length);
-}
-
-inline mirror::ObjectArray<mirror::String>* ClassLinker::AllocStringArray(Thread* self,
- size_t length) {
- return mirror::ObjectArray<mirror::String>::Alloc(self,
- GetClassRoot(kJavaLangStringArrayClass),
- length);
-}
-
-inline mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) {
- return down_cast<mirror::IfTable*>(
- mirror::IfTable::Alloc(self,
- GetClassRoot(kObjectArrayClass),
- ifcount * mirror::IfTable::kMax));
-}
-
inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) {
DCHECK(!class_roots_.IsNull());
mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read();
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 1d0684202c..ee33fc4c91 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -65,6 +65,7 @@
#include "imtable-inl.h"
#include "intern_table.h"
#include "interpreter/interpreter.h"
+#include "java_vm_ext.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "jit/profile_compilation_info.h"
@@ -8983,6 +8984,13 @@ mirror::Class* ClassLinker::GetHoldingClassOfCopiedMethod(ArtMethod* method) {
return visitor.holder_.Ptr();
}
+mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) {
+ return down_cast<mirror::IfTable*>(
+ mirror::IfTable::Alloc(self,
+ GetClassRoot(kObjectArrayClass),
+ ifcount * mirror::IfTable::kMax));
+}
+
// Instantiate ResolveMethod.
template ArtMethod* ClassLinker::ResolveMethod<ClassLinker::kForceICCECheck>(
const DexFile& dex_file,
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index a26e63b49e..1c280a4662 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -185,7 +185,9 @@ class ClassLinker {
// boot_class_path_.
mirror::Class* FindSystemClass(Thread* self, const char* descriptor)
REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Locks::dex_lock_);
+ REQUIRES(!Locks::dex_lock_) {
+ return FindClass(self, descriptor, ScopedNullHandle<mirror::ClassLoader>());
+ }
// Finds the array class given for the element class.
mirror::Class* FindArrayClass(Thread* self, ObjPtr<mirror::Class>* element_class)
@@ -231,12 +233,6 @@ class ClassLinker {
REQUIRES_SHARED(Locks::mutator_lock_);
// Resolve a String with the given index from the DexFile, storing the
- // result in the DexCache. The referrer is used to identify the
- // target DexCache and ClassLoader to use for resolution.
- mirror::String* ResolveString(dex::StringIndex string_idx, ArtMethod* referrer)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- // Resolve a String with the given index from the DexFile, storing the
// result in the DexCache.
mirror::String* ResolveString(const DexFile& dex_file,
dex::StringIndex string_idx,
@@ -436,25 +432,6 @@ class ClassLinker {
REQUIRES(!Locks::dex_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Allocate an instance of a java.lang.Object.
- mirror::Object* AllocObject(Thread* self)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Roles::uninterruptible_);
-
- // TODO: replace this with multiple methods that allocate the correct managed type.
- template <class T>
- mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Roles::uninterruptible_);
-
- mirror::ObjectArray<mirror::Class>* AllocClassArray(Thread* self, size_t length)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Roles::uninterruptible_);
-
- mirror::ObjectArray<mirror::String>* AllocStringArray(Thread* self, size_t length)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Roles::uninterruptible_);
-
LengthPrefixedArray<ArtField>* AllocArtFieldArray(Thread* self,
LinearAlloc* allocator,
size_t length);
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index 374b711aa8..0891d3f9f5 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -17,6 +17,7 @@
#include "class_table.h"
#include "mirror/class-inl.h"
+#include "oat_file.h"
namespace art {
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 15724a1027..01c6641ae9 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -39,6 +39,7 @@
#include "gtest/gtest.h"
#include "handle_scope-inl.h"
#include "interpreter/unstarted_runtime.h"
+#include "java_vm_ext.h"
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 63794bff6f..d0b50fe820 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -1092,6 +1092,23 @@ JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signatu
return JDWP::ERR_NONE;
}
+JDWP::JdwpError Dbg::GetSourceDebugExtension(JDWP::RefTypeId class_id,
+ std::string* extension_data) {
+ JDWP::JdwpError error;
+ mirror::Class* c = DecodeClass(class_id, &error);
+ if (c == nullptr) {
+ return error;
+ }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> klass(hs.NewHandle(c));
+ const char* data = annotations::GetSourceDebugExtension(klass);
+ if (data == nullptr) {
+ return JDWP::ERR_ABSENT_INFORMATION;
+ }
+ *extension_data = data;
+ return JDWP::ERR_NONE;
+}
+
JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string* result) {
JDWP::JdwpError error;
mirror::Class* c = DecodeClass(class_id, &error);
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 27124e19fb..4f3ff40e86 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -288,6 +288,9 @@ class Dbg {
REQUIRES_SHARED(Locks::mutator_lock_);
static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string* signature)
REQUIRES_SHARED(Locks::mutator_lock_);
+ static JDWP::JdwpError GetSourceDebugExtension(JDWP::RefTypeId ref_type_id,
+ std::string* extension_data)
+ REQUIRES_SHARED(Locks::mutator_lock_);
static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string* source_file)
REQUIRES_SHARED(Locks::mutator_lock_);
static JDWP::JdwpError GetObjectTag(JDWP::ObjectId object_id, uint8_t* tag)
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
index 6b9654dc49..7d56bca6ce 100644
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -1420,6 +1420,40 @@ mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirro
return GetSignatureValue(data, annotation_set);
}
+const char* GetSourceDebugExtension(Handle<mirror::Class> klass) {
+ ClassData data(klass);
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet(
+ data.GetDexFile(),
+ annotation_set,
+ "Ldalvik/annotation/SourceDebugExtension;",
+ DexFile::kDexVisibilitySystem);
+ if (annotation_item == nullptr) {
+ return nullptr;
+ }
+ const uint8_t* annotation =
+ SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "value");
+ if (annotation == nullptr) {
+ return nullptr;
+ }
+ DexFile::AnnotationValue annotation_value;
+ if (!ProcessAnnotationValue<false>(data,
+ &annotation,
+ &annotation_value,
+ ScopedNullHandle<mirror::Class>(),
+ DexFile::kAllRaw)) {
+ return nullptr;
+ }
+ if (annotation_value.type_ != DexFile::kDexAnnotationString) {
+ return nullptr;
+ }
+ dex::StringIndex index(static_cast<uint32_t>(annotation_value.value_.GetI()));
+ return data.GetDexFile().StringDataByIdx(index);
+}
+
bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) {
ClassData data(klass);
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
diff --git a/runtime/dex_file_annotations.h b/runtime/dex_file_annotations.h
index c66c5bdb8b..651c9844eb 100644
--- a/runtime/dex_file_annotations.h
+++ b/runtime/dex_file_annotations.h
@@ -89,6 +89,8 @@ bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags)
REQUIRES_SHARED(Locks::mutator_lock_);
mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
+const char* GetSourceDebugExtension(Handle<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_);
bool IsClassAnnotationPresent(Handle<mirror::Class> klass,
Handle<mirror::Class> annotation_class)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index ba8cec3a52..37734e8afb 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -19,6 +19,7 @@
#include "entrypoint_utils.h"
+#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/enums.h"
#include "class_linker-inl.h"
@@ -39,6 +40,7 @@
#include "runtime.h"
#include "stack_map.h"
#include "thread.h"
+#include "well_known_classes.h"
namespace art {
@@ -779,9 +781,32 @@ inline mirror::Class* ResolveVerifyAndClinit(dex::TypeIndex type_idx,
return h_class.Get();
}
+static inline mirror::String* ResolveString(ClassLinker* class_linker,
+ dex::StringIndex string_idx,
+ ArtMethod* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ Thread::PoisonObjectPointersIfDebug();
+ ObjPtr<mirror::String> string = referrer->GetDexCache()->GetResolvedString(string_idx);
+ if (UNLIKELY(string == nullptr)) {
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
+ const DexFile& dex_file = *dex_cache->GetDexFile();
+ string = class_linker->ResolveString(dex_file, string_idx, dex_cache);
+ }
+ return string.Ptr();
+}
+
inline mirror::String* ResolveStringFromCode(ArtMethod* referrer, dex::StringIndex string_idx) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- return class_linker->ResolveString(string_idx, referrer);
+ Thread::PoisonObjectPointersIfDebug();
+ ObjPtr<mirror::String> string = referrer->GetDexCache()->GetResolvedString(string_idx);
+ if (UNLIKELY(string == nullptr)) {
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
+ const DexFile& dex_file = *dex_cache->GetDexFile();
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ string = class_linker->ResolveString(dex_file, string_idx, dex_cache);
+ }
+ return string.Ptr();
}
inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) {
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index b5130d7999..c340a885c3 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -26,6 +26,7 @@
#include "entrypoints/quick/callee_save_frame.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "gc/accounting/card_table-inl.h"
+#include "java_vm_ext.h"
#include "mirror/class-inl.h"
#include "mirror/method.h"
#include "mirror/object-inl.h"
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
index 546e59d223..eeb138b295 100644
--- a/runtime/entrypoints/jni/jni_entrypoints.cc
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -17,6 +17,7 @@
#include "art_method-inl.h"
#include "base/logging.h"
#include "entrypoints/entrypoint_utils.h"
+#include "java_vm_ext.h"
#include "mirror/object-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 343343fc3f..3820d854f9 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -14,22 +14,18 @@
* limitations under the License.
*/
-#include "art_method-inl.h"
#include "base/logging.h"
+#include "base/mutex.h"
#include "callee_save_frame.h"
-#include "dex_file-inl.h"
#include "interpreter/interpreter.h"
-#include "mirror/class-inl.h"
-#include "mirror/object_array-inl.h"
-#include "mirror/object-inl.h"
+#include "obj_ptr-inl.h" // TODO: Find the other include that isn't complete, and clean this up.
#include "quick_exception_handler.h"
#include "thread.h"
-#include "verifier/method_verifier.h"
namespace art {
NO_RETURN static void artDeoptimizeImpl(Thread* self, bool single_frame)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ REQUIRES_SHARED(Locks::mutator_lock_) {
if (VLOG_IS_ON(deopt)) {
if (single_frame) {
// Deopt logging will be in DeoptimizeSingleFrame. It is there to take advantage of the
diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
index aa547bf04e..81560ccbaf 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "art_method-inl.h"
+#include "art_method.h"
#include "base/enums.h"
#include "callee_save_frame.h"
#include "entrypoints/runtime_asm_entrypoints.h"
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index a5bb91a71e..34e30c177f 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -26,6 +26,7 @@
#include "gc/space/image_space.h"
#include "gc/space/space.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "space_bitmap-inl.h"
#include "thread-inl.h"
diff --git a/runtime/gc/accounting/remembered_set.cc b/runtime/gc/accounting/remembered_set.cc
index 7b1e2b83c3..f2fe58aa83 100644
--- a/runtime/gc/accounting/remembered_set.cc
+++ b/runtime/gc/accounting/remembered_set.cc
@@ -26,8 +26,9 @@
#include "gc/collector/semi_space.h"
#include "gc/heap.h"
#include "gc/space/space.h"
-#include "mirror/object-inl.h"
#include "mirror/class-inl.h"
+#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "mirror/object_array-inl.h"
#include "space_bitmap-inl.h"
#include "thread.h"
diff --git a/runtime/gc/collector/concurrent_copying-inl.h b/runtime/gc/collector/concurrent_copying-inl.h
index 854d0a58ff..dd449f991b 100644
--- a/runtime/gc/collector/concurrent_copying-inl.h
+++ b/runtime/gc/collector/concurrent_copying-inl.h
@@ -22,7 +22,7 @@
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
#include "gc/space/region_space.h"
-#include "mirror/object-inl.h"
+#include "mirror/object-readbarrier-inl.h"
#include "lock_word.h"
namespace art {
@@ -96,7 +96,9 @@ inline mirror::Object* ConcurrentCopying::MarkImmuneSpace(mirror::Object* ref) {
}
template<bool kGrayImmuneObject, bool kFromGCThread>
-inline mirror::Object* ConcurrentCopying::Mark(mirror::Object* from_ref) {
+inline mirror::Object* ConcurrentCopying::Mark(mirror::Object* from_ref,
+ mirror::Object* holder,
+ MemberOffset offset) {
if (from_ref == nullptr) {
return nullptr;
}
@@ -141,7 +143,7 @@ inline mirror::Object* ConcurrentCopying::Mark(mirror::Object* from_ref) {
if (immune_spaces_.ContainsObject(from_ref)) {
return MarkImmuneSpace<kGrayImmuneObject>(from_ref);
} else {
- return MarkNonMoving(from_ref);
+ return MarkNonMoving(from_ref, holder, offset);
}
default:
UNREACHABLE();
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 792c191017..d5af29e4c6 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -29,10 +29,12 @@
#include "gc/reference_processor.h"
#include "gc/space/image_space.h"
#include "gc/space/space-inl.h"
+#include "gc/verification.h"
#include "image-inl.h"
#include "intern_table.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "thread_list.h"
@@ -374,6 +376,15 @@ class ConcurrentCopying::FlipCallback : public Closure {
cc->VerifyGrayImmuneObjects();
}
}
+ // May be null during runtime creation, in this case leave java_lang_Object null.
+ // This is safe since single threaded behavior should mean FillDummyObject does not
+ // happen when java_lang_Object_ is null.
+ if (WellKnownClasses::java_lang_Object != nullptr) {
+ cc->java_lang_Object_ = down_cast<mirror::Class*>(cc->Mark(
+ WellKnownClasses::ToClass(WellKnownClasses::java_lang_Object).Ptr()));
+ } else {
+ cc->java_lang_Object_ = nullptr;
+ }
}
private:
@@ -2067,11 +2078,10 @@ void ConcurrentCopying::FillWithDummyObject(mirror::Object* dummy_obj, size_t by
size_t data_offset = mirror::Array::DataOffset(component_size).SizeValue();
if (data_offset > byte_size) {
// An int array is too big. Use java.lang.Object.
- ObjPtr<mirror::Class> java_lang_Object =
- WellKnownClasses::ToClass(WellKnownClasses::java_lang_Object);
- AssertToSpaceInvariant(nullptr, MemberOffset(0), java_lang_Object.Ptr());
- CHECK_EQ(byte_size, (java_lang_Object->GetObjectSize<kVerifyNone, kWithoutReadBarrier>()));
- dummy_obj->SetClass(java_lang_Object.Ptr());
+ CHECK(java_lang_Object_ != nullptr);
+ AssertToSpaceInvariant(nullptr, MemberOffset(0), java_lang_Object_);
+ CHECK_EQ(byte_size, (java_lang_Object_->GetObjectSize<kVerifyNone, kWithoutReadBarrier>()));
+ dummy_obj->SetClass(java_lang_Object_);
CHECK_EQ(byte_size, (dummy_obj->SizeOf<kVerifyNone>()));
} else {
// Use an int array.
@@ -2361,7 +2371,9 @@ bool ConcurrentCopying::IsOnAllocStack(mirror::Object* ref) {
return alloc_stack->Contains(ref);
}
-mirror::Object* ConcurrentCopying::MarkNonMoving(mirror::Object* ref) {
+mirror::Object* ConcurrentCopying::MarkNonMoving(mirror::Object* ref,
+ mirror::Object* holder,
+ MemberOffset offset) {
// ref is in a non-moving space (from_ref == to_ref).
DCHECK(!region_space_->HasAddress(ref)) << ref;
DCHECK(!immune_spaces_.ContainsObject(ref));
@@ -2407,6 +2419,11 @@ mirror::Object* ConcurrentCopying::MarkNonMoving(mirror::Object* ref) {
return ref;
}
}
+ if (is_los && !IsAligned<kPageSize>(ref)) {
+ // Ref is a large object that is not aligned, it must be heap corruption. Dump data before
+ // AtomicSetReadBarrierState since it will fault if the address is not valid.
+ heap_->GetVerification()->LogHeapCorruption(ref, offset, holder, /* fatal */ true);
+ }
// Not marked or on the allocation stack. Try to mark it.
// This may or may not succeed, which is ok.
bool cas_success = false;
diff --git a/runtime/gc/collector/concurrent_copying.h b/runtime/gc/collector/concurrent_copying.h
index a0da9fc58f..c21520d2fa 100644
--- a/runtime/gc/collector/concurrent_copying.h
+++ b/runtime/gc/collector/concurrent_copying.h
@@ -106,7 +106,9 @@ class ConcurrentCopying : public GarbageCollector {
return IsMarked(ref) == ref;
}
template<bool kGrayImmuneObject = true, bool kFromGCThread = false>
- ALWAYS_INLINE mirror::Object* Mark(mirror::Object* from_ref)
+ ALWAYS_INLINE mirror::Object* Mark(mirror::Object* from_ref,
+ mirror::Object* holder = nullptr,
+ MemberOffset offset = MemberOffset(0))
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
ALWAYS_INLINE mirror::Object* MarkFromReadBarrier(mirror::Object* from_ref)
@@ -224,7 +226,10 @@ class ConcurrentCopying : public GarbageCollector {
void DisableMarking() REQUIRES_SHARED(Locks::mutator_lock_);
void IssueDisableMarkingCheckpoint() REQUIRES_SHARED(Locks::mutator_lock_);
void ExpandGcMarkStack() REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* MarkNonMoving(mirror::Object* from_ref) REQUIRES_SHARED(Locks::mutator_lock_)
+ mirror::Object* MarkNonMoving(mirror::Object* from_ref,
+ mirror::Object* holder = nullptr,
+ MemberOffset offset = MemberOffset(0))
+ REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_);
ALWAYS_INLINE mirror::Object* MarkUnevacFromSpaceRegion(mirror::Object* from_ref,
accounting::SpaceBitmap<kObjectAlignment>* bitmap)
@@ -316,6 +321,11 @@ class ConcurrentCopying : public GarbageCollector {
Mutex immune_gray_stack_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
std::vector<mirror::Object*> immune_gray_stack_ GUARDED_BY(immune_gray_stack_lock_);
+ // Class of java.lang.Object. Filled in from WellKnownClasses in FlipCallback. Must
+ // be filled in before flipping thread roots so that FillDummyObject can run. Not
+ // ObjPtr since the GC may transition to suspended and runnable between phases.
+ mirror::Class* java_lang_Object_;
+
class AssertToSpaceInvariantFieldVisitor;
class AssertToSpaceInvariantObjectVisitor;
class AssertToSpaceInvariantRefsVisitor;
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index c61f69dad3..cab293f23c 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -29,6 +29,7 @@
#include "gc/space/space-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "runtime.h"
#include "stack.h"
#include "thread-inl.h"
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index e72277ffb2..e4993ce718 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -21,6 +21,7 @@
#include "gc/heap.h"
#include "mirror/class-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/reference.h"
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 67e7383a4f..41e605104c 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -44,6 +44,7 @@
#include "monitor.h"
#include "mirror/reference-inl.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "runtime.h"
#include "thread-inl.h"
#include "thread_list.h"
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 28dd62717a..64dce5f4e7 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -60,16 +60,19 @@
#include "gc/space/space-inl.h"
#include "gc/space/zygote_space.h"
#include "gc/task_processor.h"
+#include "gc/verification.h"
#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "gc_pause_listener.h"
#include "heap-inl.h"
#include "image.h"
#include "intern_table.h"
+#include "java_vm_ext.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "obj_ptr-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/reference-inl.h"
#include "os.h"
@@ -285,6 +288,7 @@ Heap::Heap(size_t initial_size,
CHECK_EQ(foreground_collector_type_, kCollectorTypeCC);
CHECK_EQ(background_collector_type_, kCollectorTypeCCBackground);
}
+ verification_.reset(new Verification(this));
CHECK_GE(large_object_threshold, kMinLargeObjectThreshold);
ScopedTrace trace(__FUNCTION__);
Runtime* const runtime = Runtime::Current();
@@ -4266,5 +4270,9 @@ mirror::Object* Heap::AllocWithNewTLAB(Thread* self,
return ret;
}
+const Verification* Heap::GetVerification() const {
+ return verification_.get();
+}
+
} // namespace gc
} // namespace art
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 241d84ce22..aa123d8736 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -64,6 +64,7 @@ class AllocRecordObjectMap;
class GcPauseListener;
class ReferenceProcessor;
class TaskProcessor;
+class Verification;
namespace accounting {
class HeapBitmap;
@@ -821,6 +822,8 @@ class Heap {
// reasons, we assume it stays valid when we read it (so that we don't require a lock).
void RemoveGcPauseListener();
+ const Verification* GetVerification() const;
+
private:
class ConcurrentGCTask;
class CollectorTransitionTask;
@@ -1433,6 +1436,8 @@ class Heap {
// An installed GC Pause listener.
Atomic<GcPauseListener*> gc_pause_listener_;
+ std::unique_ptr<Verification> verification_;
+
friend class CollectorTransitionTask;
friend class collector::GarbageCollector;
friend class collector::MarkCompact;
diff --git a/runtime/gc/heap_verification_test.cc b/runtime/gc/heap_verification_test.cc
new file mode 100644
index 0000000000..c8233e37ab
--- /dev/null
+++ b/runtime/gc/heap_verification_test.cc
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_runtime_test.h"
+
+#include "class_linker.h"
+#include "handle_scope-inl.h"
+#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/string.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+#include "verification.h"
+
+namespace art {
+namespace gc {
+
+class VerificationTest : public CommonRuntimeTest {
+ protected:
+ VerificationTest() {}
+
+ template <class T>
+ mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+ return mirror::ObjectArray<T>::Alloc(
+ self,
+ class_linker->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass),
+ length);
+ }
+};
+
+TEST_F(VerificationTest, IsValidHeapObjectAddress) {
+ ScopedObjectAccess soa(Thread::Current());
+ const Verification* const v = Runtime::Current()->GetHeap()->GetVerification();
+ EXPECT_FALSE(v->IsValidHeapObjectAddress(reinterpret_cast<const void*>(1)));
+ EXPECT_FALSE(v->IsValidHeapObjectAddress(reinterpret_cast<const void*>(4)));
+ EXPECT_FALSE(v->IsValidHeapObjectAddress(nullptr));
+ VariableSizedHandleScope hs(soa.Self());
+ Handle<mirror::String> string(
+ hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "test")));
+ EXPECT_TRUE(v->IsValidHeapObjectAddress(string.Get()));
+ EXPECT_TRUE(v->IsValidHeapObjectAddress(string->GetClass()));
+ const uintptr_t uint_klass = reinterpret_cast<uintptr_t>(string->GetClass());
+ // Not actually a valid object but the verification can't know that. Guaranteed to be inside a
+ // heap space.
+ EXPECT_TRUE(v->IsValidHeapObjectAddress(
+ reinterpret_cast<const void*>(uint_klass + kObjectAlignment)));
+ EXPECT_FALSE(v->IsValidHeapObjectAddress(
+ reinterpret_cast<const void*>(&uint_klass)));
+}
+
+TEST_F(VerificationTest, IsValidClass) {
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope hs(soa.Self());
+ Handle<mirror::String> string(
+ hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "test")));
+ const Verification* const v = Runtime::Current()->GetHeap()->GetVerification();
+ EXPECT_FALSE(v->IsValidClass(reinterpret_cast<const void*>(1)));
+ EXPECT_FALSE(v->IsValidClass(reinterpret_cast<const void*>(4)));
+ EXPECT_FALSE(v->IsValidClass(nullptr));
+ EXPECT_FALSE(v->IsValidClass(string.Get()));
+ EXPECT_TRUE(v->IsValidClass(string->GetClass()));
+ const uintptr_t uint_klass = reinterpret_cast<uintptr_t>(string->GetClass());
+ EXPECT_FALSE(v->IsValidClass(reinterpret_cast<const void*>(uint_klass - kObjectAlignment)));
+ EXPECT_FALSE(v->IsValidClass(reinterpret_cast<const void*>(&uint_klass)));
+}
+
+TEST_F(VerificationTest, DumpObjectInfo) {
+ ScopedLogSeverity sls(LogSeverity::INFO);
+ ScopedObjectAccess soa(Thread::Current());
+ Runtime* const runtime = Runtime::Current();
+ VariableSizedHandleScope hs(soa.Self());
+ Handle<mirror::String> string(
+ hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "obj")));
+ Handle<mirror::ObjectArray<mirror::Object>> arr(
+ hs.NewHandle(AllocObjectArray<mirror::Object>(soa.Self(), 256)));
+ const Verification* const v = runtime->GetHeap()->GetVerification();
+ LOG(INFO) << v->DumpObjectInfo(reinterpret_cast<const void*>(1), "obj");
+ LOG(INFO) << v->DumpObjectInfo(reinterpret_cast<const void*>(4), "obj");
+ LOG(INFO) << v->DumpObjectInfo(nullptr, "obj");
+ LOG(INFO) << v->DumpObjectInfo(string.Get(), "test");
+ LOG(INFO) << v->DumpObjectInfo(string->GetClass(), "obj");
+ const uintptr_t uint_klass = reinterpret_cast<uintptr_t>(string->GetClass());
+ LOG(INFO) << v->DumpObjectInfo(reinterpret_cast<const void*>(uint_klass - kObjectAlignment),
+ "obj");
+ LOG(INFO) << v->DumpObjectInfo(reinterpret_cast<const void*>(&uint_klass), "obj");
+ LOG(INFO) << v->DumpObjectInfo(arr.Get(), "arr");
+}
+
+TEST_F(VerificationTest, LogHeapCorruption) {
+ ScopedLogSeverity sls(LogSeverity::INFO);
+ ScopedObjectAccess soa(Thread::Current());
+ Runtime* const runtime = Runtime::Current();
+ VariableSizedHandleScope hs(soa.Self());
+ Handle<mirror::String> string(
+ hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "obj")));
+ using ObjArray = mirror::ObjectArray<mirror::Object>;
+ Handle<ObjArray> arr(
+ hs.NewHandle(AllocObjectArray<mirror::Object>(soa.Self(), 256)));
+ const Verification* const v = runtime->GetHeap()->GetVerification();
+ arr->Set(0, string.Get());
+ // Test normal cases.
+ v->LogHeapCorruption(arr.Get(), ObjArray::DataOffset(kHeapReferenceSize), string.Get(), false);
+ v->LogHeapCorruption(string.Get(), mirror::Object::ClassOffset(), string->GetClass(), false);
+ // Test null holder cases.
+ v->LogHeapCorruption(nullptr, MemberOffset(0), string.Get(), false);
+ v->LogHeapCorruption(nullptr, MemberOffset(0), arr.Get(), false);
+}
+
+} // namespace gc
+} // namespace art
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 65a550ee5c..886c950710 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -18,6 +18,7 @@
#include "base/time_utils.h"
#include "collector/garbage_collector.h"
+#include "java_vm_ext.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/reference-inl.h"
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 662efe2c8d..e9f0758b85 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -25,7 +25,8 @@
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
-#include "art_method.h"
+#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "base/enums.h"
#include "base/macros.h"
#include "base/stl_util.h"
@@ -38,6 +39,7 @@
#include "image_space_fs.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "oat_file.h"
#include "os.h"
#include "space-inl.h"
diff --git a/runtime/gc/system_weak_test.cc b/runtime/gc/system_weak_test.cc
index 9b601c0753..dfbbd2a0c1 100644
--- a/runtime/gc/system_weak_test.cc
+++ b/runtime/gc/system_weak_test.cc
@@ -23,6 +23,7 @@
#include "base/mutex.h"
#include "collector_type.h"
#include "common_runtime_test.h"
+#include "gc_root-inl.h"
#include "handle_scope-inl.h"
#include "heap.h"
#include "mirror/string.h"
diff --git a/runtime/gc/verification.cc b/runtime/gc/verification.cc
new file mode 100644
index 0000000000..7b31c8a259
--- /dev/null
+++ b/runtime/gc/verification.cc
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "verification.h"
+
+#include <iomanip>
+#include <sstream>
+
+#include "art_field-inl.h"
+#include "mirror/class-inl.h"
+
+namespace art {
+namespace gc {
+
+std::string Verification::DumpObjectInfo(const void* addr, const char* tag) const {
+ std::ostringstream oss;
+ oss << tag << "=" << addr;
+ if (IsValidHeapObjectAddress(addr)) {
+ mirror::Object* obj = reinterpret_cast<mirror::Object*>(const_cast<void*>(addr));
+ mirror::Class* klass = obj->GetClass<kVerifyNone, kWithoutReadBarrier>();
+ oss << " klass=" << klass;
+ if (IsValidClass(klass)) {
+ oss << "(" << klass->PrettyClass() << ")";
+ if (klass->IsArrayClass<kVerifyNone, kWithoutReadBarrier>()) {
+ oss << " length=" << obj->AsArray<kVerifyNone, kWithoutReadBarrier>()->GetLength();
+ }
+ } else {
+ oss << " <invalid address>";
+ }
+ space::Space* const space = heap_->FindSpaceFromAddress(addr);
+ if (space != nullptr) {
+ oss << " space=" << *space;
+ }
+ accounting::CardTable* card_table = heap_->GetCardTable();
+ if (card_table->AddrIsInCardTable(addr)) {
+ oss << " card=" << static_cast<size_t>(
+ card_table->GetCard(reinterpret_cast<const mirror::Object*>(addr)));
+ }
+ // Dump adjacent RAM.
+ const uintptr_t uint_addr = reinterpret_cast<uintptr_t>(addr);
+ static constexpr size_t kBytesBeforeAfter = 2 * kObjectAlignment;
+ const uintptr_t dump_start = uint_addr - kBytesBeforeAfter;
+ const uintptr_t dump_end = uint_addr + kBytesBeforeAfter;
+ if (dump_start < dump_end &&
+ IsValidHeapObjectAddress(reinterpret_cast<const void*>(dump_start)) &&
+ IsValidHeapObjectAddress(reinterpret_cast<const void*>(dump_end - kObjectAlignment))) {
+ oss << " adjacent_ram=";
+ for (uintptr_t p = dump_start; p < dump_end; ++p) {
+ if (p == uint_addr) {
+ // Marker of where the object is.
+ oss << "|";
+ }
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(p);
+ oss << std::hex << std::setfill('0') << std::setw(2) << static_cast<uintptr_t>(*ptr);
+ }
+ }
+ } else {
+ oss << " <invalid address>";
+ }
+ return oss.str();
+}
+
+void Verification::LogHeapCorruption(ObjPtr<mirror::Object> holder,
+ MemberOffset offset,
+ mirror::Object* ref,
+ bool fatal) const {
+ // Lowest priority logging first:
+ PrintFileToLog("/proc/self/maps", LogSeverity::FATAL_WITHOUT_ABORT);
+ MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), true);
+ // Buffer the output in the string stream since it is more important than the stack traces
+ // and we want it to have log priority. The stack traces are printed from Runtime::Abort
+ // which is called from LOG(FATAL) but before the abort message.
+ std::ostringstream oss;
+ oss << "GC tried to mark invalid reference " << ref << std::endl;
+ oss << DumpObjectInfo(ref, "ref") << "\n";
+ if (holder != nullptr) {
+ oss << DumpObjectInfo(holder.Ptr(), "holder");
+ mirror::Class* holder_klass = holder->GetClass<kVerifyNone, kWithoutReadBarrier>();
+ if (IsValidClass(holder_klass)) {
+ oss << "field_offset=" << offset.Uint32Value();
+ ArtField* field = holder->FindFieldByOffset(offset);
+ if (field != nullptr) {
+ oss << " name=" << field->GetName();
+ }
+ }
+ }
+
+ if (fatal) {
+ LOG(FATAL) << oss.str();
+ } else {
+ LOG(FATAL_WITHOUT_ABORT) << oss.str();
+ }
+}
+
+bool Verification::IsValidHeapObjectAddress(const void* addr, space::Space** out_space) const {
+ if (!IsAligned<kObjectAlignment>(addr)) {
+ return false;
+ }
+ space::Space* const space = heap_->FindSpaceFromAddress(addr);
+ if (space != nullptr) {
+ if (out_space != nullptr) {
+ *out_space = space;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Verification::IsValidClass(const void* addr) const {
+ if (!IsValidHeapObjectAddress(addr)) {
+ return false;
+ }
+ mirror::Class* klass = reinterpret_cast<mirror::Class*>(const_cast<void*>(addr));
+ mirror::Class* k1 = klass->GetClass<kVerifyNone, kWithoutReadBarrier>();
+ if (!IsValidHeapObjectAddress(k1)) {
+ return false;
+ }
+ // k should be class class, take the class again to verify.
+ // Note that this check may not be valid for the no image space since the class class might move
+ // around from moving GC.
+ mirror::Class* k2 = k1->GetClass<kVerifyNone, kWithoutReadBarrier>();
+ if (!IsValidHeapObjectAddress(k2)) {
+ return false;
+ }
+ return k1 == k2;
+}
+
+} // namespace gc
+} // namespace art
diff --git a/runtime/gc/verification.h b/runtime/gc/verification.h
new file mode 100644
index 0000000000..3d95d93015
--- /dev/null
+++ b/runtime/gc/verification.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ART_RUNTIME_GC_VERIFICATION_H_
+#define ART_RUNTIME_GC_VERIFICATION_H_
+
+#include "obj_ptr.h"
+#include "offsets.h"
+
+namespace art {
+
+namespace mirror {
+class Class;
+class Object;
+} // namespace mirror
+
+namespace gc {
+
+namespace space {
+class Space;
+} // namespace space
+
+class Heap;
+
+class Verification {
+ public:
+ explicit Verification(gc::Heap* heap) : heap_(heap) {}
+
+ // Dump some reveant to debugging info about an object.
+ std::string DumpObjectInfo(const void* obj, const char* tag) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // Don't use ObjPtr for things that might not be aligned like the invalid reference.
+ void LogHeapCorruption(ObjPtr<mirror::Object> holder,
+ MemberOffset offset,
+ mirror::Object* ref,
+ bool fatal) const REQUIRES_SHARED(Locks::mutator_lock_);
+
+
+ // Return true if the klass is likely to be a valid mirror::Class.
+ bool IsValidClass(const void* klass) const REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // Does not allow null.
+ bool IsValidHeapObjectAddress(const void* addr, space::Space** out_space = nullptr) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ private:
+ gc::Heap* const heap_;
+};
+
+} // namespace gc
+} // namespace art
+
+#endif // ART_RUNTIME_GC_VERIFICATION_H_
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 495fec7a48..4f390fd30a 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -40,6 +40,7 @@
#include "android-base/stringprintf.h"
#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "base/logging.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
@@ -58,7 +59,7 @@
#include "jdwp/jdwp_priv.h"
#include "mirror/class.h"
#include "mirror/class-inl.h"
-#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "os.h"
#include "safe_map.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/runtime/image.cc b/runtime/image.cc
index b153ea0e02..b2486a1209 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -17,6 +17,7 @@
#include "image.h"
#include "base/bit_utils.h"
+#include "base/length_prefixed_array.h"
#include "mirror/object_array.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h
index 24ee22759c..2128f8cde8 100644
--- a/runtime/indirect_reference_table-inl.h
+++ b/runtime/indirect_reference_table-inl.h
@@ -24,7 +24,6 @@
#include "base/dumpable.h"
#include "gc_root-inl.h"
#include "obj_ptr-inl.h"
-#include "runtime-inl.h"
#include "verify_object.h"
namespace art {
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index 9fbb2e9930..c852d5af3a 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -18,6 +18,7 @@
#include "base/dumpable-inl.h"
#include "base/systrace.h"
+#include "java_vm_ext.h"
#include "jni_internal.h"
#include "nth_caller_visitor.h"
#include "reference_table.h"
diff --git a/runtime/intern_table_test.cc b/runtime/intern_table_test.cc
index f0d0260482..311515c7ed 100644
--- a/runtime/intern_table_test.cc
+++ b/runtime/intern_table_test.cc
@@ -18,6 +18,7 @@
#include "base/hash_set.h"
#include "common_runtime_test.h"
+#include "gc_root-inl.h"
#include "mirror/object.h"
#include "handle_scope-inl.h"
#include "mirror/string.h"
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 8978bfd5af..326f5c96c0 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -28,7 +28,7 @@
#include "mirror/array-inl.h"
#include "mirror/class.h"
#include "mirror/emulated_stack_frame.h"
-#include "mirror/method_handle_impl.h"
+#include "mirror/method_handle_impl-inl.h"
#include "reflection.h"
#include "reflection-inl.h"
#include "stack.h"
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 56e261cfc8..c314f3c35e 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -1341,7 +1341,8 @@ TEST_F(UnstartedRuntimeTest, ConstructorNewInstance0) {
ASSERT_TRUE(cons != nullptr);
Handle<mirror::ObjectArray<mirror::Object>> args = hs.NewHandle(
- class_linker->AllocObjectArray<mirror::Object>(self, 1));
+ mirror::ObjectArray<mirror::Object>::Alloc(
+ self, class_linker_->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass), 1));
ASSERT_TRUE(args != nullptr);
args->Set(0, input.Get());
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index c8dc2f2d20..6d3118e4aa 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -20,7 +20,7 @@
#include "android-base/stringprintf.h"
-#include "art_method.h"
+#include "art_method-inl.h"
#include "base/dumpable.h"
#include "base/mutex.h"
#include "base/stl_util.h"
diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc
index 971d03958c..e8a9904dc6 100644
--- a/runtime/jdwp/jdwp_handler.cc
+++ b/runtime/jdwp/jdwp_handler.cc
@@ -335,7 +335,7 @@ static JdwpError VM_CapabilitiesNew(JdwpState*, Request* request, ExpandBuf* rep
expandBufAdd1(reply, false); // canUnrestrictedlyRedefineClasses
expandBufAdd1(reply, false); // canPopFrames
expandBufAdd1(reply, true); // canUseInstanceFilters
- expandBufAdd1(reply, false); // canGetSourceDebugExtension
+ expandBufAdd1(reply, true); // canGetSourceDebugExtension
expandBufAdd1(reply, false); // canRequestVMDeathEvent
expandBufAdd1(reply, false); // canSetDefaultStratum
expandBufAdd1(reply, true); // 1.6: canGetInstanceInfo
@@ -499,13 +499,18 @@ static JdwpError RT_ClassObject(JdwpState*, Request* request, ExpandBuf* pReply)
/*
* Returns the value of the SourceDebugExtension attribute.
- *
- * JDB seems interested, but DEX files don't currently support this.
*/
-static JdwpError RT_SourceDebugExtension(JdwpState*, Request*, ExpandBuf*)
+static JdwpError RT_SourceDebugExtension(JdwpState*, Request* request, ExpandBuf* pReply)
REQUIRES_SHARED(Locks::mutator_lock_) {
/* referenceTypeId in, string out */
- return ERR_ABSENT_INFORMATION;
+ RefTypeId refTypeId = request->ReadRefTypeId();
+ std::string extension_data;
+ JdwpError status = Dbg::GetSourceDebugExtension(refTypeId, &extension_data);
+ if (status != ERR_NONE) {
+ return status;
+ }
+ expandBufAddUtf8String(pReply, extension_data);
+ return ERR_NONE;
}
static JdwpError RT_Signature(JdwpState*, Request* request, ExpandBuf* pReply, bool with_generic)
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 3631a9d467..b32b272a31 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -23,6 +23,7 @@
#include "debugger.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "interpreter/interpreter.h"
+#include "java_vm_ext.h"
#include "jit_code_cache.h"
#include "oat_file_manager.h"
#include "oat_quick_method_header.h"
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index 2d1601e883..52649c7075 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -24,7 +24,6 @@
#include <sys/stat.h>
#include <sys/uio.h>
-#include "art_method-inl.h"
#include "base/mutex.h"
#include "base/scoped_flock.h"
#include "base/stl_util.h"
@@ -33,6 +32,7 @@
#include "jit/profiling_info.h"
#include "os.h"
#include "safe_map.h"
+#include "utils.h"
namespace art {
diff --git a/runtime/jni_env_ext-inl.h b/runtime/jni_env_ext-inl.h
index 004f824b9d..25893b7eda 100644
--- a/runtime/jni_env_ext-inl.h
+++ b/runtime/jni_env_ext-inl.h
@@ -19,9 +19,7 @@
#include "jni_env_ext.h"
-#include "indirect_reference_table-inl.h"
-#include "obj_ptr-inl.h"
-#include "utils.h"
+#include "mirror/object.h"
namespace art {
diff --git a/runtime/jni_env_ext.h b/runtime/jni_env_ext.h
index 4004c457b5..60e4295e40 100644
--- a/runtime/jni_env_ext.h
+++ b/runtime/jni_env_ext.h
@@ -23,12 +23,17 @@
#include "base/mutex.h"
#include "indirect_reference_table.h"
#include "object_callbacks.h"
+#include "obj_ptr.h"
#include "reference_table.h"
namespace art {
class JavaVMExt;
+namespace mirror {
+class Object;
+} // namespace mirror
+
// Number of local references in the indirect reference table. The value is arbitrary but
// low enough that it forces sanity checks.
static constexpr size_t kLocalsInitial = 512;
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index b6f8a173c0..54d45b1e79 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -22,7 +22,7 @@
#include "jvalue.h"
#include "jvalue-inl.h"
#include "mirror/emulated_stack_frame.h"
-#include "mirror/method_handle_impl.h"
+#include "mirror/method_handle_impl-inl.h"
#include "mirror/method_type.h"
#include "reflection.h"
#include "reflection-inl.h"
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 04c80c5cc0..bfbd4df537 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -24,8 +24,9 @@
#include "base/bit_utils.h"
#include "base/casts.h"
#include "base/logging.h"
-#include "class-inl.h"
+#include "class.h"
#include "gc/heap-inl.h"
+#include "object-inl.h"
#include "obj_ptr-inl.h"
#include "thread.h"
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 9124a3ad84..6c723efde2 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -19,18 +19,18 @@
#include "class.h"
-#include "art_field-inl.h"
+#include "art_field.h"
#include "art_method.h"
-#include "art_method-inl.h"
#include "base/array_slice.h"
#include "base/length_prefixed_array.h"
+#include "class_linker-inl.h"
#include "class_loader.h"
#include "common_throws.h"
-#include "dex_file.h"
+#include "dex_file-inl.h"
#include "gc/heap-inl.h"
#include "iftable.h"
-#include "class_ext-inl.h"
#include "object_array-inl.h"
+#include "object-inl.h"
#include "read_barrier-inl.h"
#include "reference-inl.h"
#include "runtime.h"
@@ -343,6 +343,21 @@ inline bool Class::Implements(ObjPtr<Class> klass) {
return false;
}
+template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
+inline bool Class::IsVariableSize() {
+ // Classes, arrays, and strings vary in size, and so the object_size_ field cannot
+ // be used to Get their instance size
+ return IsClassClass<kVerifyFlags, kReadBarrierOption>() ||
+ IsArrayClass<kVerifyFlags, kReadBarrierOption>() ||
+ IsStringClass();
+}
+
+inline void Class::SetObjectSize(uint32_t new_object_size) {
+ DCHECK(!IsVariableSize());
+ // Not called within a transaction.
+ return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size);
+}
+
// Determine whether "this" is assignable from "src", where both of these
// are array classes.
//
@@ -784,32 +799,6 @@ inline uint32_t Class::ComputeClassSize(bool has_embedded_vtable,
return size;
}
-template <bool kVisitNativeRoots,
- VerifyObjectFlags kVerifyFlags,
- ReadBarrierOption kReadBarrierOption,
- typename Visitor>
-inline void Class::VisitReferences(ObjPtr<Class> klass, const Visitor& visitor) {
- VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass.Ptr(), visitor);
- // Right after a class is allocated, but not yet loaded
- // (kStatusNotReady, see ClassLinker::LoadClass()), GC may find it
- // and scan it. IsTemp() may call Class::GetAccessFlags() but may
- // fail in the DCHECK in Class::GetAccessFlags() because the class
- // status is kStatusNotReady. To avoid it, rely on IsResolved()
- // only. This is fine because a temp class never goes into the
- // kStatusResolved state.
- if (IsResolved<kVerifyFlags>()) {
- // Temp classes don't ever populate imt/vtable or static fields and they are not even
- // allocated with the right size for those. Also, unresolved classes don't have fields
- // linked yet.
- VisitStaticFieldsReferences<kVerifyFlags, kReadBarrierOption>(this, visitor);
- }
- if (kVisitNativeRoots) {
- // Since this class is reachable, we must also visit the associated roots when we scan it.
- VisitNativeRoots<kReadBarrierOption>(
- visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
- }
-}
-
template<ReadBarrierOption kReadBarrierOption>
inline bool Class::IsReferenceClass() const {
return this == Reference::GetJavaLangRefReference<kReadBarrierOption>();
@@ -942,31 +931,6 @@ inline uint32_t Class::NumDirectInterfaces() {
}
}
-template<ReadBarrierOption kReadBarrierOption, class Visitor>
-void Class::VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) {
- for (ArtField& field : GetSFieldsUnchecked()) {
- // Visit roots first in case the declaring class gets moved.
- field.VisitRoots(visitor);
- if (kIsDebugBuild && IsResolved()) {
- CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
- }
- }
- for (ArtField& field : GetIFieldsUnchecked()) {
- // Visit roots first in case the declaring class gets moved.
- field.VisitRoots(visitor);
- if (kIsDebugBuild && IsResolved()) {
- CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
- }
- }
- for (ArtMethod& method : GetMethods(pointer_size)) {
- method.VisitRoots<kReadBarrierOption>(visitor, pointer_size);
- }
- ObjPtr<ClassExt> ext(GetExtData<kDefaultVerifyFlags, kReadBarrierOption>());
- if (!ext.IsNull()) {
- ext->VisitNativeRoots<kReadBarrierOption, Visitor>(visitor, pointer_size);
- }
-}
-
inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(PointerSize pointer_size) {
CheckPointerSize(pointer_size);
return GetDirectMethodsSliceUnchecked(pointer_size).AsRange();
@@ -1036,6 +1000,12 @@ inline bool Class::IsArrayClass() {
return GetComponentType<kVerifyFlags, kReadBarrierOption>() != nullptr;
}
+template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
+inline bool Class::IsObjectArrayClass() {
+ ObjPtr<Class> const component_type = GetComponentType<kVerifyFlags, kReadBarrierOption>();
+ return component_type != nullptr && !component_type->IsPrimitive();
+}
+
inline bool Class::IsAssignableFrom(ObjPtr<Class> src) {
DCHECK(src != nullptr);
if (this == src) {
diff --git a/runtime/mirror/class-refvisitor-inl.h b/runtime/mirror/class-refvisitor-inl.h
new file mode 100644
index 0000000000..3d52ead0f4
--- /dev/null
+++ b/runtime/mirror/class-refvisitor-inl.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_CLASS_REFVISITOR_INL_H_
+#define ART_RUNTIME_MIRROR_CLASS_REFVISITOR_INL_H_
+
+#include "class-inl.h"
+
+#include "art_field-inl.h"
+#include "class_ext-inl.h"
+
+namespace art {
+namespace mirror {
+
+template <bool kVisitNativeRoots,
+ VerifyObjectFlags kVerifyFlags,
+ ReadBarrierOption kReadBarrierOption,
+ typename Visitor>
+inline void Class::VisitReferences(ObjPtr<Class> klass, const Visitor& visitor) {
+ VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass.Ptr(), visitor);
+ // Right after a class is allocated, but not yet loaded
+ // (kStatusNotReady, see ClassLinker::LoadClass()), GC may find it
+ // and scan it. IsTemp() may call Class::GetAccessFlags() but may
+ // fail in the DCHECK in Class::GetAccessFlags() because the class
+ // status is kStatusNotReady. To avoid it, rely on IsResolved()
+ // only. This is fine because a temp class never goes into the
+ // kStatusResolved state.
+ if (IsResolved<kVerifyFlags>()) {
+ // Temp classes don't ever populate imt/vtable or static fields and they are not even
+ // allocated with the right size for those. Also, unresolved classes don't have fields
+ // linked yet.
+ VisitStaticFieldsReferences<kVerifyFlags, kReadBarrierOption>(this, visitor);
+ }
+ if (kVisitNativeRoots) {
+ // Since this class is reachable, we must also visit the associated roots when we scan it.
+ VisitNativeRoots<kReadBarrierOption>(
+ visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
+ }
+}
+
+template<ReadBarrierOption kReadBarrierOption, class Visitor>
+void Class::VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) {
+ for (ArtField& field : GetSFieldsUnchecked()) {
+ // Visit roots first in case the declaring class gets moved.
+ field.VisitRoots(visitor);
+ if (kIsDebugBuild && IsResolved()) {
+ CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
+ }
+ }
+ for (ArtField& field : GetIFieldsUnchecked()) {
+ // Visit roots first in case the declaring class gets moved.
+ field.VisitRoots(visitor);
+ if (kIsDebugBuild && IsResolved()) {
+ CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
+ }
+ }
+ for (ArtMethod& method : GetMethods(pointer_size)) {
+ method.VisitRoots<kReadBarrierOption>(visitor, pointer_size);
+ }
+ ObjPtr<ClassExt> ext(GetExtData<kDefaultVerifyFlags, kReadBarrierOption>());
+ if (!ext.IsNull()) {
+ ext->VisitNativeRoots<kReadBarrierOption, Visitor>(visitor, pointer_size);
+ }
+}
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_CLASS_REFVISITOR_INL_H_
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 26af488bd2..06ee3d36fe 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -32,6 +32,7 @@
#include "method.h"
#include "object_array-inl.h"
#include "object-inl.h"
+#include "object-refvisitor-inl.h"
#include "object_lock.h"
#include "runtime.h"
#include "thread.h"
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 27aecd5150..dfb2788c51 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -530,10 +530,7 @@ class MANAGED Class FINAL : public Object {
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- bool IsObjectArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<Class> const component_type = GetComponentType<kVerifyFlags, kReadBarrierOption>();
- return component_type != nullptr && !component_type->IsPrimitive();
- }
+ ALWAYS_INLINE bool IsObjectArrayClass() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsIntArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -561,12 +558,7 @@ class MANAGED Class FINAL : public Object {
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- bool IsVariableSize() REQUIRES_SHARED(Locks::mutator_lock_) {
- // Classes, arrays, and strings vary in size, and so the object_size_ field cannot
- // be used to Get their instance size
- return IsClassClass<kVerifyFlags, kReadBarrierOption>() ||
- IsArrayClass<kVerifyFlags, kReadBarrierOption>() || IsStringClass();
- }
+ ALWAYS_INLINE bool IsVariableSize() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
@@ -614,11 +606,7 @@ class MANAGED Class FINAL : public Object {
return OFFSET_OF_OBJECT_MEMBER(Class, object_size_alloc_fast_path_);
}
- void SetObjectSize(uint32_t new_object_size) REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(!IsVariableSize());
- // Not called within a transaction.
- return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size);
- }
+ ALWAYS_INLINE void SetObjectSize(uint32_t new_object_size) REQUIRES_SHARED(Locks::mutator_lock_);
void SetObjectSizeAllocFastPath(uint32_t new_object_size) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 5d3af5071a..18e22ef8f8 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -19,13 +19,15 @@
#include "dex_cache.h"
-#include "art_field-inl.h"
-#include "art_method-inl.h"
+#include "art_field.h"
+#include "art_method.h"
#include "base/casts.h"
#include "base/enums.h"
#include "base/logging.h"
+#include "class_linker.h"
#include "dex_file.h"
#include "gc_root.h"
+#include "gc/heap-inl.h"
#include "mirror/class.h"
#include "mirror/call_site.h"
#include "mirror/method_type.h"
diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc
index 71a47f66a0..a110ed7f6b 100644
--- a/runtime/mirror/dex_cache_test.cc
+++ b/runtime/mirror/dex_cache_test.cc
@@ -18,6 +18,7 @@
#include <stdio.h>
+#include "art_method-inl.h"
#include "class_linker.h"
#include "common_runtime_test.h"
#include "linear_alloc.h"
diff --git a/runtime/mirror/method_handle_impl-inl.h b/runtime/mirror/method_handle_impl-inl.h
new file mode 100644
index 0000000000..0840d16c38
--- /dev/null
+++ b/runtime/mirror/method_handle_impl-inl.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_INL_H_
+#define ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_INL_H_
+
+#include "method_handle_impl.h"
+
+#include "art_method-inl.h"
+#include "object-inl.h"
+
+namespace art {
+namespace mirror {
+
+inline mirror::MethodType* MethodHandle::GetMethodType() {
+ return GetFieldObject<mirror::MethodType>(OFFSET_OF_OBJECT_MEMBER(MethodHandle, method_type_));
+}
+
+inline mirror::MethodType* MethodHandle::GetNominalType() {
+ return GetFieldObject<mirror::MethodType>(OFFSET_OF_OBJECT_MEMBER(MethodHandle, nominal_type_));
+}
+
+inline ObjPtr<mirror::Class> MethodHandle::GetTargetClass() {
+ Kind kind = GetHandleKind();
+ return (kind <= kLastValidKind) ?
+ GetTargetMethod()->GetDeclaringClass() : GetTargetField()->GetDeclaringClass();
+}
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_INL_H_
diff --git a/runtime/mirror/method_handle_impl.cc b/runtime/mirror/method_handle_impl.cc
index fa4d25a031..42b8473ef0 100644
--- a/runtime/mirror/method_handle_impl.cc
+++ b/runtime/mirror/method_handle_impl.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "method_handle_impl.h"
+#include "method_handle_impl-inl.h"
#include "class-inl.h"
#include "gc_root-inl.h"
@@ -42,6 +42,10 @@ void MethodHandle::Initialize(uintptr_t art_field_or_method,
GcRoot<mirror::Class> MethodHandleImpl::static_class_;
+mirror::Class* MethodHandleImpl::StaticClass() {
+ return static_class_.Read();
+}
+
void MethodHandleImpl::SetClass(Class* klass) {
CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
CHECK(klass != nullptr);
diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h
index 9938af8abf..c598fa3876 100644
--- a/runtime/mirror/method_handle_impl.h
+++ b/runtime/mirror/method_handle_impl.h
@@ -21,7 +21,7 @@
#include "art_method.h"
#include "class.h"
#include "gc_root.h"
-#include "object-inl.h"
+#include "object.h"
#include "method_type.h"
namespace art {
@@ -65,13 +65,9 @@ class MANAGED MethodHandle : public Object {
return static_cast<Kind>(handle_kind);
}
- mirror::MethodType* GetMethodType() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetFieldObject<mirror::MethodType>(OFFSET_OF_OBJECT_MEMBER(MethodHandle, method_type_));
- }
+ ALWAYS_INLINE mirror::MethodType* GetMethodType() REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::MethodType* GetNominalType() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetFieldObject<mirror::MethodType>(OFFSET_OF_OBJECT_MEMBER(MethodHandle, nominal_type_));
- }
+ ALWAYS_INLINE mirror::MethodType* GetNominalType() REQUIRES_SHARED(Locks::mutator_lock_);
ArtField* GetTargetField() REQUIRES_SHARED(Locks::mutator_lock_) {
return reinterpret_cast<ArtField*>(
@@ -83,11 +79,7 @@ class MANAGED MethodHandle : public Object {
GetField64(OFFSET_OF_OBJECT_MEMBER(MethodHandle, art_field_or_method_)));
}
- ObjPtr<mirror::Class> GetTargetClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- Kind kind = GetHandleKind();
- return (kind <= kLastValidKind) ?
- GetTargetMethod()->GetDeclaringClass() : GetTargetField()->GetDeclaringClass();
- }
+ ALWAYS_INLINE ObjPtr<mirror::Class> GetTargetClass() REQUIRES_SHARED(Locks::mutator_lock_);
static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -132,9 +124,7 @@ class MANAGED MethodHandleImpl : public MethodHandle {
Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
+ static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/method_handles_lookup.cc b/runtime/mirror/method_handles_lookup.cc
index c758e54dd4..0c25fa8ba0 100644
--- a/runtime/mirror/method_handles_lookup.cc
+++ b/runtime/mirror/method_handles_lookup.cc
@@ -16,7 +16,7 @@
#include "method_handles_lookup.h"
-#include "class.h"
+#include "class-inl.h"
#include "gc_root-inl.h"
#include "object-inl.h"
#include "handle_scope.h"
diff --git a/runtime/mirror/method_type_test.cc b/runtime/mirror/method_type_test.cc
index 41231ef617..a361772c58 100644
--- a/runtime/mirror/method_type_test.cc
+++ b/runtime/mirror/method_type_test.cc
@@ -20,7 +20,7 @@
#include <vector>
#include "class-inl.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "class_loader.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index f83645e6e8..baed5f167c 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -23,7 +23,7 @@
#include "art_method.h"
#include "atomic.h"
#include "array-inl.h"
-#include "class.h"
+#include "class-inl.h"
#include "class_flags.h"
#include "class_linker.h"
#include "class_loader-inl.h"
@@ -32,6 +32,7 @@
#include "monitor.h"
#include "object_array-inl.h"
#include "object_reference-inl.h"
+#include "object-readbarrier-inl.h"
#include "obj_ptr-inl.h"
#include "read_barrier-inl.h"
#include "reference.h"
@@ -66,14 +67,6 @@ inline void Object::SetClass(ObjPtr<Class> new_klass) {
}
template<VerifyObjectFlags kVerifyFlags>
-inline LockWord Object::GetLockWord(bool as_volatile) {
- if (as_volatile) {
- return LockWord(GetField32Volatile<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
- }
- return LockWord(GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
-}
-
-template<VerifyObjectFlags kVerifyFlags>
inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
// Force use of non-transactional mode and do not check.
if (as_volatile) {
@@ -91,24 +84,12 @@ inline bool Object::CasLockWordWeakSequentiallyConsistent(LockWord old_val, Lock
OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
}
-inline bool Object::CasLockWordWeakRelaxed(LockWord old_val, LockWord new_val) {
- // Force use of non-transactional mode and do not check.
- return CasFieldWeakRelaxed32<false, false>(
- OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
-}
-
inline bool Object::CasLockWordWeakAcquire(LockWord old_val, LockWord new_val) {
// Force use of non-transactional mode and do not check.
return CasFieldWeakAcquire32<false, false>(
OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
}
-inline bool Object::CasLockWordWeakRelease(LockWord old_val, LockWord new_val) {
- // Force use of non-transactional mode and do not check.
- return CasFieldWeakRelease32<false, false>(
- OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
-}
-
inline uint32_t Object::GetLockOwnerThreadId() {
return Monitor::GetLockOwnerThreadId(this);
}
@@ -141,84 +122,6 @@ inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
}
-inline uint32_t Object::GetReadBarrierState(uintptr_t* fake_address_dependency) {
- if (!kUseBakerReadBarrier) {
- LOG(FATAL) << "Unreachable";
- UNREACHABLE();
- }
-#if defined(__arm__)
- uintptr_t obj = reinterpret_cast<uintptr_t>(this);
- uintptr_t result;
- DCHECK_EQ(OFFSETOF_MEMBER(Object, monitor_), 4U);
- // Use inline assembly to prevent the compiler from optimizing away the false dependency.
- __asm__ __volatile__(
- "ldr %[result], [%[obj], #4]\n\t"
- // This instruction is enough to "fool the compiler and the CPU" by having `fad` always be
- // null, without them being able to assume that fact.
- "eor %[fad], %[result], %[result]\n\t"
- : [result] "+r" (result), [fad] "=r" (*fake_address_dependency)
- : [obj] "r" (obj));
- DCHECK_EQ(*fake_address_dependency, 0U);
- LockWord lw(static_cast<uint32_t>(result));
- uint32_t rb_state = lw.ReadBarrierState();
- return rb_state;
-#elif defined(__aarch64__)
- uintptr_t obj = reinterpret_cast<uintptr_t>(this);
- uintptr_t result;
- DCHECK_EQ(OFFSETOF_MEMBER(Object, monitor_), 4U);
- // Use inline assembly to prevent the compiler from optimizing away the false dependency.
- __asm__ __volatile__(
- "ldr %w[result], [%[obj], #4]\n\t"
- // This instruction is enough to "fool the compiler and the CPU" by having `fad` always be
- // null, without them being able to assume that fact.
- "eor %[fad], %[result], %[result]\n\t"
- : [result] "+r" (result), [fad] "=r" (*fake_address_dependency)
- : [obj] "r" (obj));
- DCHECK_EQ(*fake_address_dependency, 0U);
- LockWord lw(static_cast<uint32_t>(result));
- uint32_t rb_state = lw.ReadBarrierState();
- return rb_state;
-#elif defined(__i386__) || defined(__x86_64__)
- LockWord lw = GetLockWord(false);
- // i386/x86_64 don't need fake address dependency. Use a compiler fence to avoid compiler
- // reordering.
- *fake_address_dependency = 0;
- std::atomic_signal_fence(std::memory_order_acquire);
- uint32_t rb_state = lw.ReadBarrierState();
- return rb_state;
-#else
- // MIPS32/MIPS64: use a memory barrier to prevent load-load reordering.
- LockWord lw = GetLockWord(false);
- *fake_address_dependency = 0;
- std::atomic_thread_fence(std::memory_order_acquire);
- uint32_t rb_state = lw.ReadBarrierState();
- return rb_state;
-#endif
-}
-
-inline uint32_t Object::GetReadBarrierState() {
- if (!kUseBakerReadBarrier) {
- LOG(FATAL) << "Unreachable";
- UNREACHABLE();
- }
- DCHECK(kUseBakerReadBarrier);
- LockWord lw(GetField<uint32_t, /*kIsVolatile*/false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
- uint32_t rb_state = lw.ReadBarrierState();
- DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
- return rb_state;
-}
-
-inline uint32_t Object::GetReadBarrierStateAcquire() {
- if (!kUseBakerReadBarrier) {
- LOG(FATAL) << "Unreachable";
- UNREACHABLE();
- }
- LockWord lw(GetFieldAcquire<uint32_t>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
- uint32_t rb_state = lw.ReadBarrierState();
- DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
- return rb_state;
-}
-
inline uint32_t Object::GetMarkBit() {
#ifdef USE_READ_BARRIER
return GetLockWord(false).MarkBitState();
@@ -239,54 +142,6 @@ inline void Object::SetReadBarrierState(uint32_t rb_state) {
SetLockWord(lw, false);
}
-template<bool kCasRelease>
-inline bool Object::AtomicSetReadBarrierState(uint32_t expected_rb_state, uint32_t rb_state) {
- if (!kUseBakerReadBarrier) {
- LOG(FATAL) << "Unreachable";
- UNREACHABLE();
- }
- DCHECK(ReadBarrier::IsValidReadBarrierState(expected_rb_state)) << expected_rb_state;
- DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
- LockWord expected_lw;
- LockWord new_lw;
- do {
- LockWord lw = GetLockWord(false);
- if (UNLIKELY(lw.ReadBarrierState() != expected_rb_state)) {
- // Lost the race.
- return false;
- }
- expected_lw = lw;
- expected_lw.SetReadBarrierState(expected_rb_state);
- new_lw = lw;
- new_lw.SetReadBarrierState(rb_state);
- // ConcurrentCopying::ProcessMarkStackRef uses this with kCasRelease == true.
- // If kCasRelease == true, use a CAS release so that when GC updates all the fields of
- // an object and then changes the object from gray to black, the field updates (stores) will be
- // visible (won't be reordered after this CAS.)
- } while (!(kCasRelease ?
- CasLockWordWeakRelease(expected_lw, new_lw) :
- CasLockWordWeakRelaxed(expected_lw, new_lw)));
- return true;
-}
-
-inline bool Object::AtomicSetMarkBit(uint32_t expected_mark_bit, uint32_t mark_bit) {
- LockWord expected_lw;
- LockWord new_lw;
- do {
- LockWord lw = GetLockWord(false);
- if (UNLIKELY(lw.MarkBitState() != expected_mark_bit)) {
- // Lost the race.
- return false;
- }
- expected_lw = lw;
- new_lw = lw;
- new_lw.SetMarkBitState(mark_bit);
- // Since this is only set from the mutator, we can use the non release Cas.
- } while (!CasLockWordWeakRelaxed(expected_lw, new_lw));
- return true;
-}
-
-
inline void Object::AssertReadBarrierState() const {
CHECK(kUseBakerReadBarrier);
Object* obj = const_cast<Object*>(this);
@@ -727,24 +582,6 @@ inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offs
}
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
-inline bool Object::CasFieldWeakRelaxed32(MemberOffset field_offset,
- int32_t old_value, int32_t new_value) {
- if (kCheckTransaction) {
- DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
- }
- if (kTransactionActive) {
- Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
- }
- if (kVerifyFlags & kVerifyThis) {
- VerifyObject(this);
- }
- uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
- AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
-
- return atomic_addr->CompareExchangeWeakRelaxed(old_value, new_value);
-}
-
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasFieldWeakAcquire32(MemberOffset field_offset,
int32_t old_value, int32_t new_value) {
if (kCheckTransaction) {
@@ -798,19 +635,6 @@ inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_of
return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
}
-template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
-inline int64_t Object::GetField64(MemberOffset field_offset) {
- if (kVerifyFlags & kVerifyThis) {
- VerifyObject(this);
- }
- return GetField<int64_t, kIsVolatile>(field_offset);
-}
-
-template<VerifyObjectFlags kVerifyFlags>
-inline int64_t Object::GetField64Volatile(MemberOffset field_offset) {
- return GetField64<kVerifyFlags, true>(field_offset);
-}
-
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
bool kIsVolatile>
inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
@@ -1075,36 +899,6 @@ inline bool Object::CasFieldWeakRelaxedObjectWithoutWriteBarrier(
return success;
}
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
-inline bool Object::CasFieldStrongRelaxedObjectWithoutWriteBarrier(
- MemberOffset field_offset,
- ObjPtr<Object> old_value,
- ObjPtr<Object> new_value) {
- if (kCheckTransaction) {
- DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
- }
- if (kVerifyFlags & kVerifyThis) {
- VerifyObject(this);
- }
- if (kVerifyFlags & kVerifyWrites) {
- VerifyObject(new_value);
- }
- if (kVerifyFlags & kVerifyReads) {
- VerifyObject(old_value);
- }
- if (kTransactionActive) {
- Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
- }
- HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
- HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
- uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
- Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
-
- bool success = atomic_addr->CompareExchangeStrongRelaxed(old_ref.reference_,
- new_ref.reference_);
- return success;
-}
-
template<bool kIsStatic,
VerifyObjectFlags kVerifyFlags,
ReadBarrierOption kReadBarrierOption,
@@ -1186,67 +980,6 @@ inline mirror::DexCache* Object::AsDexCache() {
return down_cast<mirror::DexCache*>(this);
}
-template <bool kVisitNativeRoots,
- VerifyObjectFlags kVerifyFlags,
- ReadBarrierOption kReadBarrierOption,
- typename Visitor,
- typename JavaLangRefVisitor>
-inline void Object::VisitReferences(const Visitor& visitor,
- const JavaLangRefVisitor& ref_visitor) {
- ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
- visitor(this, ClassOffset(), false);
- const uint32_t class_flags = klass->GetClassFlags<kVerifyNone>();
- if (LIKELY(class_flags == kClassFlagNormal)) {
- DCHECK((!klass->IsVariableSize<kVerifyFlags, kReadBarrierOption>()));
- VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
- DCHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
- DCHECK(!klass->IsStringClass());
- DCHECK(!klass->IsClassLoaderClass());
- DCHECK((!klass->IsArrayClass<kVerifyFlags, kReadBarrierOption>()));
- } else {
- if ((class_flags & kClassFlagNoReferenceFields) == 0) {
- DCHECK(!klass->IsStringClass());
- if (class_flags == kClassFlagClass) {
- DCHECK((klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
- ObjPtr<Class> as_klass = AsClass<kVerifyNone, kReadBarrierOption>();
- as_klass->VisitReferences<kVisitNativeRoots, kVerifyFlags, kReadBarrierOption>(klass,
- visitor);
- } else if (class_flags == kClassFlagObjectArray) {
- DCHECK((klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
- AsObjectArray<mirror::Object, kVerifyNone, kReadBarrierOption>()->VisitReferences(visitor);
- } else if ((class_flags & kClassFlagReference) != 0) {
- VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
- ref_visitor(klass, AsReference<kVerifyFlags, kReadBarrierOption>());
- } else if (class_flags == kClassFlagDexCache) {
- mirror::DexCache* const dex_cache = AsDexCache<kVerifyFlags, kReadBarrierOption>();
- dex_cache->VisitReferences<kVisitNativeRoots,
- kVerifyFlags,
- kReadBarrierOption>(klass, visitor);
- } else {
- mirror::ClassLoader* const class_loader = AsClassLoader<kVerifyFlags, kReadBarrierOption>();
- class_loader->VisitReferences<kVisitNativeRoots,
- kVerifyFlags,
- kReadBarrierOption>(klass, visitor);
- }
- } else if (kIsDebugBuild) {
- CHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
- CHECK((!klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
- // String still has instance fields for reflection purposes but these don't exist in
- // actual string instances.
- if (!klass->IsStringClass()) {
- size_t total_reference_instance_fields = 0;
- ObjPtr<Class> super_class = klass;
- do {
- total_reference_instance_fields += super_class->NumReferenceInstanceFields();
- super_class = super_class->GetSuperClass<kVerifyFlags, kReadBarrierOption>();
- } while (super_class != nullptr);
- // The only reference field should be the object's class. This field is handled at the
- // beginning of the function.
- CHECK_EQ(total_reference_instance_fields, 1u);
- }
- }
- }
-}
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/object-readbarrier-inl.h b/runtime/mirror/object-readbarrier-inl.h
new file mode 100644
index 0000000000..58e7c20667
--- /dev/null
+++ b/runtime/mirror/object-readbarrier-inl.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_OBJECT_READBARRIER_INL_H_
+#define ART_RUNTIME_MIRROR_OBJECT_READBARRIER_INL_H_
+
+#include "object.h"
+
+#include "atomic.h"
+#include "lock_word-inl.h"
+#include "object_reference-inl.h"
+#include "read_barrier.h"
+#include "runtime.h"
+
+namespace art {
+namespace mirror {
+
+template<VerifyObjectFlags kVerifyFlags>
+inline LockWord Object::GetLockWord(bool as_volatile) {
+ if (as_volatile) {
+ return LockWord(GetField32Volatile<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+ }
+ return LockWord(GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline bool Object::CasFieldWeakRelaxed32(MemberOffset field_offset,
+ int32_t old_value, int32_t new_value) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kTransactionActive) {
+ Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
+
+ return atomic_addr->CompareExchangeWeakRelaxed(old_value, new_value);
+}
+
+inline bool Object::CasLockWordWeakRelaxed(LockWord old_val, LockWord new_val) {
+ // Force use of non-transactional mode and do not check.
+ return CasFieldWeakRelaxed32<false, false>(
+ OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
+}
+
+inline bool Object::CasLockWordWeakRelease(LockWord old_val, LockWord new_val) {
+ // Force use of non-transactional mode and do not check.
+ return CasFieldWeakRelease32<false, false>(
+ OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
+}
+
+inline uint32_t Object::GetReadBarrierState(uintptr_t* fake_address_dependency) {
+ if (!kUseBakerReadBarrier) {
+ LOG(FATAL) << "Unreachable";
+ UNREACHABLE();
+ }
+#if defined(__arm__)
+ uintptr_t obj = reinterpret_cast<uintptr_t>(this);
+ uintptr_t result;
+ DCHECK_EQ(OFFSETOF_MEMBER(Object, monitor_), 4U);
+ // Use inline assembly to prevent the compiler from optimizing away the false dependency.
+ __asm__ __volatile__(
+ "ldr %[result], [%[obj], #4]\n\t"
+ // This instruction is enough to "fool the compiler and the CPU" by having `fad` always be
+ // null, without them being able to assume that fact.
+ "eor %[fad], %[result], %[result]\n\t"
+ : [result] "+r" (result), [fad] "=r" (*fake_address_dependency)
+ : [obj] "r" (obj));
+ DCHECK_EQ(*fake_address_dependency, 0U);
+ LockWord lw(static_cast<uint32_t>(result));
+ uint32_t rb_state = lw.ReadBarrierState();
+ return rb_state;
+#elif defined(__aarch64__)
+ uintptr_t obj = reinterpret_cast<uintptr_t>(this);
+ uintptr_t result;
+ DCHECK_EQ(OFFSETOF_MEMBER(Object, monitor_), 4U);
+ // Use inline assembly to prevent the compiler from optimizing away the false dependency.
+ __asm__ __volatile__(
+ "ldr %w[result], [%[obj], #4]\n\t"
+ // This instruction is enough to "fool the compiler and the CPU" by having `fad` always be
+ // null, without them being able to assume that fact.
+ "eor %[fad], %[result], %[result]\n\t"
+ : [result] "+r" (result), [fad] "=r" (*fake_address_dependency)
+ : [obj] "r" (obj));
+ DCHECK_EQ(*fake_address_dependency, 0U);
+ LockWord lw(static_cast<uint32_t>(result));
+ uint32_t rb_state = lw.ReadBarrierState();
+ return rb_state;
+#elif defined(__i386__) || defined(__x86_64__)
+ LockWord lw = GetLockWord(false);
+ // i386/x86_64 don't need fake address dependency. Use a compiler fence to avoid compiler
+ // reordering.
+ *fake_address_dependency = 0;
+ std::atomic_signal_fence(std::memory_order_acquire);
+ uint32_t rb_state = lw.ReadBarrierState();
+ return rb_state;
+#else
+ // MIPS32/MIPS64: use a memory barrier to prevent load-load reordering.
+ LockWord lw = GetLockWord(false);
+ *fake_address_dependency = 0;
+ std::atomic_thread_fence(std::memory_order_acquire);
+ uint32_t rb_state = lw.ReadBarrierState();
+ return rb_state;
+#endif
+}
+
+inline uint32_t Object::GetReadBarrierState() {
+ if (!kUseBakerReadBarrier) {
+ LOG(FATAL) << "Unreachable";
+ UNREACHABLE();
+ }
+ DCHECK(kUseBakerReadBarrier);
+ LockWord lw(GetField<uint32_t, /*kIsVolatile*/false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+ uint32_t rb_state = lw.ReadBarrierState();
+ DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
+ return rb_state;
+}
+
+inline uint32_t Object::GetReadBarrierStateAcquire() {
+ if (!kUseBakerReadBarrier) {
+ LOG(FATAL) << "Unreachable";
+ UNREACHABLE();
+ }
+ LockWord lw(GetFieldAcquire<uint32_t>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+ uint32_t rb_state = lw.ReadBarrierState();
+ DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
+ return rb_state;
+}
+
+template<bool kCasRelease>
+inline bool Object::AtomicSetReadBarrierState(uint32_t expected_rb_state, uint32_t rb_state) {
+ if (!kUseBakerReadBarrier) {
+ LOG(FATAL) << "Unreachable";
+ UNREACHABLE();
+ }
+ DCHECK(ReadBarrier::IsValidReadBarrierState(expected_rb_state)) << expected_rb_state;
+ DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
+ LockWord expected_lw;
+ LockWord new_lw;
+ do {
+ LockWord lw = GetLockWord(false);
+ if (UNLIKELY(lw.ReadBarrierState() != expected_rb_state)) {
+ // Lost the race.
+ return false;
+ }
+ expected_lw = lw;
+ expected_lw.SetReadBarrierState(expected_rb_state);
+ new_lw = lw;
+ new_lw.SetReadBarrierState(rb_state);
+ // ConcurrentCopying::ProcessMarkStackRef uses this with kCasRelease == true.
+ // If kCasRelease == true, use a CAS release so that when GC updates all the fields of
+ // an object and then changes the object from gray to black, the field updates (stores) will be
+ // visible (won't be reordered after this CAS.)
+ } while (!(kCasRelease ?
+ CasLockWordWeakRelease(expected_lw, new_lw) :
+ CasLockWordWeakRelaxed(expected_lw, new_lw)));
+ return true;
+}
+
+inline bool Object::AtomicSetMarkBit(uint32_t expected_mark_bit, uint32_t mark_bit) {
+ LockWord expected_lw;
+ LockWord new_lw;
+ do {
+ LockWord lw = GetLockWord(false);
+ if (UNLIKELY(lw.MarkBitState() != expected_mark_bit)) {
+ // Lost the race.
+ return false;
+ }
+ expected_lw = lw;
+ new_lw = lw;
+ new_lw.SetMarkBitState(mark_bit);
+ // Since this is only set from the mutator, we can use the non release Cas.
+ } while (!CasLockWordWeakRelaxed(expected_lw, new_lw));
+ return true;
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline bool Object::CasFieldStrongRelaxedObjectWithoutWriteBarrier(
+ MemberOffset field_offset,
+ ObjPtr<Object> old_value,
+ ObjPtr<Object> new_value) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ if (kVerifyFlags & kVerifyWrites) {
+ VerifyObject(new_value);
+ }
+ if (kVerifyFlags & kVerifyReads) {
+ VerifyObject(old_value);
+ }
+ if (kTransactionActive) {
+ Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
+ }
+ HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
+ HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
+
+ bool success = atomic_addr->CompareExchangeStrongRelaxed(old_ref.reference_,
+ new_ref.reference_);
+ return success;
+}
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_OBJECT_READBARRIER_INL_H_
diff --git a/runtime/mirror/object-refvisitor-inl.h b/runtime/mirror/object-refvisitor-inl.h
new file mode 100644
index 0000000000..49ab7c2a53
--- /dev/null
+++ b/runtime/mirror/object-refvisitor-inl.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_OBJECT_REFVISITOR_INL_H_
+#define ART_RUNTIME_MIRROR_OBJECT_REFVISITOR_INL_H_
+
+#include "object-inl.h"
+
+#include "class-refvisitor-inl.h"
+
+namespace art {
+namespace mirror {
+
+template <bool kVisitNativeRoots,
+ VerifyObjectFlags kVerifyFlags,
+ ReadBarrierOption kReadBarrierOption,
+ typename Visitor,
+ typename JavaLangRefVisitor>
+inline void Object::VisitReferences(const Visitor& visitor,
+ const JavaLangRefVisitor& ref_visitor) {
+ ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
+ visitor(this, ClassOffset(), false);
+ const uint32_t class_flags = klass->GetClassFlags<kVerifyNone>();
+ if (LIKELY(class_flags == kClassFlagNormal)) {
+ DCHECK((!klass->IsVariableSize<kVerifyFlags, kReadBarrierOption>()));
+ VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
+ DCHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
+ DCHECK(!klass->IsStringClass());
+ DCHECK(!klass->IsClassLoaderClass());
+ DCHECK((!klass->IsArrayClass<kVerifyFlags, kReadBarrierOption>()));
+ } else {
+ if ((class_flags & kClassFlagNoReferenceFields) == 0) {
+ DCHECK(!klass->IsStringClass());
+ if (class_flags == kClassFlagClass) {
+ DCHECK((klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
+ ObjPtr<Class> as_klass = AsClass<kVerifyNone, kReadBarrierOption>();
+ as_klass->VisitReferences<kVisitNativeRoots, kVerifyFlags, kReadBarrierOption>(klass,
+ visitor);
+ } else if (class_flags == kClassFlagObjectArray) {
+ DCHECK((klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
+ AsObjectArray<mirror::Object, kVerifyNone, kReadBarrierOption>()->VisitReferences(visitor);
+ } else if ((class_flags & kClassFlagReference) != 0) {
+ VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
+ ref_visitor(klass, AsReference<kVerifyFlags, kReadBarrierOption>());
+ } else if (class_flags == kClassFlagDexCache) {
+ mirror::DexCache* const dex_cache = AsDexCache<kVerifyFlags, kReadBarrierOption>();
+ dex_cache->VisitReferences<kVisitNativeRoots,
+ kVerifyFlags,
+ kReadBarrierOption>(klass, visitor);
+ } else {
+ mirror::ClassLoader* const class_loader = AsClassLoader<kVerifyFlags, kReadBarrierOption>();
+ class_loader->VisitReferences<kVisitNativeRoots,
+ kVerifyFlags,
+ kReadBarrierOption>(klass, visitor);
+ }
+ } else if (kIsDebugBuild) {
+ CHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>()));
+ CHECK((!klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
+ // String still has instance fields for reflection purposes but these don't exist in
+ // actual string instances.
+ if (!klass->IsStringClass()) {
+ size_t total_reference_instance_fields = 0;
+ ObjPtr<Class> super_class = klass;
+ do {
+ total_reference_instance_fields += super_class->NumReferenceInstanceFields();
+ super_class = super_class->GetSuperClass<kVerifyFlags, kReadBarrierOption>();
+ } while (super_class != nullptr);
+ // The only reference field should be the object's class. This field is handled at the
+ // beginning of the function.
+ CHECK_EQ(total_reference_instance_fields, 1u);
+ }
+ }
+ }
+}
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_OBJECT_REFVISITOR_INL_H_
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index eabc29adad..6e5fdb773f 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -30,6 +30,7 @@
#include "iftable-inl.h"
#include "monitor.h"
#include "object-inl.h"
+#include "object-refvisitor-inl.h"
#include "object_array-inl.h"
#include "runtime.h"
#include "handle_scope-inl.h"
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 417a22dfe3..35a1b733e1 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -487,11 +487,18 @@ class MANAGED LOCKABLE Object {
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
ALWAYS_INLINE int64_t GetField64(MemberOffset field_offset)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ return GetField<int64_t, kIsVolatile>(field_offset);
+ }
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE int64_t GetField64Volatile(MemberOffset field_offset)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetField64<kVerifyFlags, true>(field_offset);
+ }
template<bool kTransactionActive, bool kCheckTransaction = true,
VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 3e04bf6474..dbec40c6d0 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -24,8 +24,9 @@
#include "android-base/stringprintf.h"
#include "array-inl.h"
+#include "class.h"
#include "gc/heap.h"
-#include "mirror/class.h"
+#include "object-inl.h"
#include "obj_ptr-inl.h"
#include "runtime.h"
#include "handle_scope-inl.h"
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index d306f9c391..d7527d59b4 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -73,6 +73,13 @@ class ObjectTest : public CommonRuntimeTest {
}
EXPECT_EQ(expected_hash, string->GetHashCode());
}
+
+ template <class T>
+ mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return mirror::ObjectArray<T>::Alloc(
+ self, class_linker_->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass), length);
+ }
};
// Keep constants in sync.
@@ -100,8 +107,7 @@ TEST_F(ObjectTest, IsInSamePackage) {
TEST_F(ObjectTest, Clone) {
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
- Handle<ObjectArray<Object>> a1(
- hs.NewHandle(class_linker_->AllocObjectArray<Object>(soa.Self(), 256)));
+ Handle<ObjectArray<Object>> a1(hs.NewHandle(AllocObjectArray<Object>(soa.Self(), 256)));
size_t s1 = a1->SizeOf();
Object* clone = a1->Clone(soa.Self());
EXPECT_EQ(s1, clone->SizeOf());
@@ -111,8 +117,7 @@ TEST_F(ObjectTest, Clone) {
TEST_F(ObjectTest, AllocObjectArray) {
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
- Handle<ObjectArray<Object>> oa(
- hs.NewHandle(class_linker_->AllocObjectArray<Object>(soa.Self(), 2)));
+ Handle<ObjectArray<Object>> oa(hs.NewHandle(AllocObjectArray<Object>(soa.Self(), 2)));
EXPECT_EQ(2, oa->GetLength());
EXPECT_TRUE(oa->Get(0) == nullptr);
EXPECT_TRUE(oa->Get(1) == nullptr);
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index f3cb0df80e..e365b42670 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -31,7 +31,6 @@
#include "lock_word-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "mirror/object_array-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "thread_list.h"
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 0e61cf64f9..0617dae1ae 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -254,10 +254,11 @@ static jobject DexFile_createCookieWithArray(JNIEnv* env,
return CreateSingleDexFileCookie(env, std::move(dex_mem_map));
}
+// TODO(calin): clean up the unused parameters (here and in libcore).
static jobject DexFile_openDexFileNative(JNIEnv* env,
jclass,
jstring javaSourceName,
- jstring javaOutputName,
+ jstring javaOutputName ATTRIBUTE_UNUSED,
jint flags ATTRIBUTE_UNUSED,
jobject class_loader,
jobjectArray dex_elements) {
@@ -265,10 +266,7 @@ static jobject DexFile_openDexFileNative(JNIEnv* env,
if (sourceName.c_str() == nullptr) {
return 0;
}
- NullableScopedUtfChars outputName(env, javaOutputName);
- if (env->ExceptionCheck()) {
- return 0;
- }
+
Runtime* const runtime = Runtime::Current();
ClassLinker* linker = runtime->GetClassLinker();
std::vector<std::unique_ptr<const DexFile>> dex_files;
@@ -276,7 +274,6 @@ static jobject DexFile_openDexFileNative(JNIEnv* env,
const OatFile* oat_file = nullptr;
dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(),
- outputName.c_str(),
class_loader,
dex_elements,
/*out*/ &oat_file,
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index f6a73a8660..5c4e242e4d 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -31,9 +31,12 @@
#include "gc/space/large_object_space.h"
#include "gc/space/space-inl.h"
#include "gc/space/zygote_space.h"
+#include "handle_scope-inl.h"
#include "hprof/hprof.h"
+#include "java_vm_ext.h"
#include "jni_internal.h"
#include "mirror/class.h"
+#include "mirror/object_array-inl.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
#include "scoped_fast_native_object_access-inl.h"
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 34bbf32a9a..ff4d93109e 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -46,6 +46,7 @@ extern "C" void android_set_application_target_sdk_version(uint32_t version);
#include "gc/space/image_space.h"
#include "gc/task_processor.h"
#include "intern_table.h"
+#include "java_vm_ext.h"
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 836ba81d8e..2eaa8c71b1 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -21,6 +21,7 @@
#include "android-base/stringprintf.h"
#include "arch/instruction_set.h"
+#include "art_method-inl.h"
#include "debugger.h"
#include "java_vm_ext.h"
#include "jit/jit.h"
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 381dc7beb0..4f999471c6 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -19,8 +19,9 @@
#include <iostream>
#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "base/enums.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "common_throws.h"
#include "dex_file-inl.h"
#include "dex_file_annotations.h"
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 54ab8615c0..a9ba33ecc1 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -23,6 +23,7 @@
#include "obj_ptr.h"
#include "scoped_fast_native_object_access-inl.h"
#include "ScopedUtfChars.h"
+#include "well_known_classes.h"
#include "zip_archive.h"
namespace art {
diff --git a/runtime/native/java_lang_Void.cc b/runtime/native/java_lang_Void.cc
index 96bfd1b4fb..e2b4b82cfb 100644
--- a/runtime/native/java_lang_Void.cc
+++ b/runtime/native/java_lang_Void.cc
@@ -16,7 +16,7 @@
#include "java_lang_Void.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "jni_internal.h"
#include "runtime.h"
#include "scoped_fast_native_object_access-inl.h"
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 9198964f87..0fb3903641 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -18,6 +18,7 @@
#include "android-base/stringprintf.h"
+#include "art_field-inl.h"
#include "class_linker.h"
#include "class_linker-inl.h"
#include "common_throws.h"
@@ -29,6 +30,7 @@
#include "reflection-inl.h"
#include "scoped_fast_native_object_access-inl.h"
#include "utils.h"
+#include "well_known_classes.h"
namespace art {
diff --git a/runtime/native/scoped_fast_native_object_access-inl.h b/runtime/native/scoped_fast_native_object_access-inl.h
index 50a554c930..b2abc4691a 100644
--- a/runtime/native/scoped_fast_native_object_access-inl.h
+++ b/runtime/native/scoped_fast_native_object_access-inl.h
@@ -19,7 +19,7 @@
#include "scoped_fast_native_object_access.h"
-#include "art_method-inl.h"
+#include "art_method.h"
#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index a00674a9fe..4a85d4795e 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -34,7 +34,7 @@
#include "android-base/stringprintf.h"
-#include "art_method-inl.h"
+#include "art_method.h"
#include "base/bit_vector.h"
#include "base/enums.h"
#include "base/stl_util.h"
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index db6f8ee488..a7be73a849 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -20,6 +20,7 @@
#include <sys/stat.h>
+#include "android-base/stringprintf.h"
#include "android-base/strings.h"
#include "base/logging.h"
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 9b35489330..4a738ab0a3 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -897,7 +897,6 @@ class RaceGenerateTask : public Task {
const OatFile* oat_file = nullptr;
dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
dex_location_.c_str(),
- oat_location_.c_str(),
/*class_loader*/nullptr,
/*dex_elements*/nullptr,
&oat_file,
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 139022210c..6799918534 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -615,7 +615,6 @@ bool OatFileManager::HasCollisions(const OatFile* oat_file,
std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
const char* dex_location,
- const char* oat_location,
jobject class_loader,
jobjectArray dex_elements,
const OatFile** out_oat_file,
@@ -630,8 +629,9 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
Locks::mutator_lock_->AssertNotHeld(self);
Runtime* const runtime = Runtime::Current();
+ // TODO(calin): remove the explicit oat_location for OatFileAssistant
OatFileAssistant oat_file_assistant(dex_location,
- oat_location,
+ /*oat_location*/ nullptr,
kRuntimeISA,
!runtime->IsAotCompiler());
diff --git a/runtime/oat_file_manager.h b/runtime/oat_file_manager.h
index 45ac4b79e7..05a5f5b7b9 100644
--- a/runtime/oat_file_manager.h
+++ b/runtime/oat_file_manager.h
@@ -96,7 +96,6 @@ class OatFileManager {
// files.
std::vector<std::unique_ptr<const DexFile>> OpenDexFilesFromOat(
const char* dex_location,
- const char* oat_location,
jobject class_loader,
jobjectArray dex_elements,
/*out*/ const OatFile** out_oat_file,
diff --git a/runtime/openjdkjvm/OpenjdkJvm.cc b/runtime/openjdkjvm/OpenjdkJvm.cc
index bdaad20d7e..0b93b079d5 100644
--- a/runtime/openjdkjvm/OpenjdkJvm.cc
+++ b/runtime/openjdkjvm/OpenjdkJvm.cc
@@ -35,28 +35,31 @@
#include<stdio.h>
#include <dlfcn.h>
#include <limits.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
#include <unistd.h>
+#include "../../libcore/ojluni/src/main/native/jvm.h" // TODO(narayan): fix it
+
+#include "base/logging.h"
+#include "base/macros.h"
#include "common_throws.h"
#include "gc/heap.h"
-#include "thread.h"
-#include "thread_list.h"
-#include "runtime.h"
#include "handle_scope-inl.h"
-#include "scoped_thread_state_change-inl.h"
-#include "ScopedUtfChars.h"
-#include "mirror/class_loader.h"
-#include "verify_object.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "../../libcore/ojluni/src/main/native/jvm.h" // TODO(narayan): fix it
+#include "java_vm_ext.h"
#include "jni_internal.h"
+#include "mirror/class_loader.h"
#include "mirror/string-inl.h"
+#include "monitor.h"
#include "native/scoped_fast_native_object_access-inl.h"
+#include "runtime.h"
+#include "thread.h"
+#include "thread_list.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
+#include "ScopedUtfChars.h"
+#include "verify_object.h"
#undef LOG_TAG
#define LOG_TAG "artopenjdk"
diff --git a/runtime/openjdkjvmti/events.cc b/runtime/openjdkjvmti/events.cc
index 521494a856..0ec92b7c60 100644
--- a/runtime/openjdkjvmti/events.cc
+++ b/runtime/openjdkjvmti/events.cc
@@ -36,10 +36,11 @@
#include "gc/allocation_listener.h"
#include "gc/gc_pause_listener.h"
#include "gc/heap.h"
+#include "handle_scope-inl.h"
#include "instrumentation.h"
#include "jni_env_ext-inl.h"
#include "mirror/class.h"
-#include "mirror/object.h"
+#include "mirror/object-inl.h"
#include "runtime.h"
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/runtime/openjdkjvmti/ti_class.cc b/runtime/openjdkjvmti/ti_class.cc
index e94c4e6112..e0af6e8dee 100644
--- a/runtime/openjdkjvmti/ti_class.cc
+++ b/runtime/openjdkjvmti/ti_class.cc
@@ -55,6 +55,7 @@
#include "mirror/object_array-inl.h"
#include "mirror/object_reference.h"
#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
#include "mirror/reference.h"
#include "primitive.h"
#include "reflection.h"
@@ -68,6 +69,7 @@
#include "ti_phase.h"
#include "ti_redefine.h"
#include "utils.h"
+#include "well_known_classes.h"
namespace openjdkjvmti {
diff --git a/runtime/openjdkjvmti/ti_class_definition.cc b/runtime/openjdkjvmti/ti_class_definition.cc
index 0671105532..180895b597 100644
--- a/runtime/openjdkjvmti/ti_class_definition.cc
+++ b/runtime/openjdkjvmti/ti_class_definition.cc
@@ -32,10 +32,12 @@
#include "ti_class_definition.h"
#include "base/array_slice.h"
+#include "class_linker-inl.h"
#include "dex_file.h"
#include "fixed_up_dex_file.h"
#include "handle_scope-inl.h"
#include "handle.h"
+#include "mirror/class_ext.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "reflection.h"
diff --git a/runtime/openjdkjvmti/ti_class_loader.cc b/runtime/openjdkjvmti/ti_class_loader.cc
index 66357eb32f..5544dde219 100644
--- a/runtime/openjdkjvmti/ti_class_loader.cc
+++ b/runtime/openjdkjvmti/ti_class_loader.cc
@@ -35,6 +35,7 @@
#include "android-base/stringprintf.h"
+#include "art_field-inl.h"
#include "art_jvmti.h"
#include "base/array_slice.h"
#include "base/logging.h"
diff --git a/runtime/openjdkjvmti/ti_redefine.cc b/runtime/openjdkjvmti/ti_redefine.cc
index 358bb0f70e..41ed86237f 100644
--- a/runtime/openjdkjvmti/ti_redefine.cc
+++ b/runtime/openjdkjvmti/ti_redefine.cc
@@ -35,9 +35,12 @@
#include "android-base/stringprintf.h"
+#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "art_jvmti.h"
#include "base/array_slice.h"
#include "base/logging.h"
+#include "class_linker-inl.h"
#include "debugger.h"
#include "dex_file.h"
#include "dex_file_types.h"
diff --git a/runtime/openjdkjvmti/ti_search.cc b/runtime/openjdkjvmti/ti_search.cc
index f51a98f976..ec139f2004 100644
--- a/runtime/openjdkjvmti/ti_search.cc
+++ b/runtime/openjdkjvmti/ti_search.cc
@@ -33,6 +33,7 @@
#include "jni.h"
+#include "art_field-inl.h"
#include "art_jvmti.h"
#include "base/enums.h"
#include "base/macros.h"
@@ -50,6 +51,7 @@
#include "ti_phase.h"
#include "thread-inl.h"
#include "thread_list.h"
+#include "well_known_classes.h"
namespace openjdkjvmti {
diff --git a/runtime/openjdkjvmti/ti_stack.cc b/runtime/openjdkjvmti/ti_stack.cc
index 067c7c153d..1ddf04feb4 100644
--- a/runtime/openjdkjvmti/ti_stack.cc
+++ b/runtime/openjdkjvmti/ti_stack.cc
@@ -36,8 +36,9 @@
#include <unordered_map>
#include <vector>
-#include "art_jvmti.h"
+#include "art_field-inl.h"
#include "art_method-inl.h"
+#include "art_jvmti.h"
#include "base/bit_utils.h"
#include "base/enums.h"
#include "base/mutex.h"
@@ -54,6 +55,7 @@
#include "thread-inl.h"
#include "thread_list.h"
#include "thread_pool.h"
+#include "well_known_classes.h"
namespace openjdkjvmti {
diff --git a/runtime/openjdkjvmti/ti_thread.cc b/runtime/openjdkjvmti/ti_thread.cc
index e5ff090ddf..3dfa63313d 100644
--- a/runtime/openjdkjvmti/ti_thread.cc
+++ b/runtime/openjdkjvmti/ti_thread.cc
@@ -32,7 +32,7 @@
#include "ti_thread.h"
#include "android-base/strings.h"
-#include "art_field.h"
+#include "art_field-inl.h"
#include "art_jvmti.h"
#include "base/logging.h"
#include "base/mutex.h"
diff --git a/runtime/openjdkjvmti/ti_threadgroup.cc b/runtime/openjdkjvmti/ti_threadgroup.cc
index df14333314..dd7be113d6 100644
--- a/runtime/openjdkjvmti/ti_threadgroup.cc
+++ b/runtime/openjdkjvmti/ti_threadgroup.cc
@@ -31,7 +31,7 @@
#include "ti_threadgroup.h"
-#include "art_field.h"
+#include "art_field-inl.h"
#include "art_jvmti.h"
#include "base/logging.h"
#include "base/macros.h"
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 5748475163..4e95b019b9 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -21,6 +21,7 @@
#include "base/enums.h"
#include "class_linker-inl.h"
#include "common_compiler_test.h"
+#include "mirror/class-inl.h"
#include "mirror/field-inl.h"
#include "mirror/method.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/runtime/read_barrier-inl.h b/runtime/read_barrier-inl.h
index c102fb0aa4..d3859b0dfa 100644
--- a/runtime/read_barrier-inl.h
+++ b/runtime/read_barrier-inl.h
@@ -22,6 +22,7 @@
#include "gc/collector/concurrent_copying-inl.h"
#include "gc/heap.h"
#include "mirror/object_reference.h"
+#include "mirror/object-readbarrier-inl.h"
#include "mirror/reference.h"
#include "runtime.h"
#include "utils.h"
diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc
index 4ccfb6d83b..e809ecf1f6 100644
--- a/runtime/reference_table_test.cc
+++ b/runtime/reference_table_test.cc
@@ -18,6 +18,7 @@
#include "android-base/stringprintf.h"
+#include "art_method-inl.h"
#include "class_linker.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 87bc7df214..e16ef1d77c 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -23,6 +23,7 @@
#include "common_throws.h"
#include "dex_file-inl.h"
#include "indirect_reference_table-inl.h"
+#include "java_vm_ext.h"
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/executable.h"
diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc
index 2f70ded8eb..1ba4b7b9d1 100644
--- a/runtime/reflection_test.cc
+++ b/runtime/reflection_test.cc
@@ -23,6 +23,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
#include "common_compiler_test.h"
+#include "java_vm_ext.h"
#include "jni_internal.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h
index 8346550c93..75c25dd21d 100644
--- a/runtime/runtime-inl.h
+++ b/runtime/runtime-inl.h
@@ -21,6 +21,7 @@
#include "art_method.h"
#include "class_linker.h"
+#include "gc_root-inl.h"
#include "obj_ptr-inl.h"
#include "read_barrier-inl.h"
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index a48a58d235..93b416ce72 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -83,6 +83,7 @@
#include "instrumentation.h"
#include "intern_table.h"
#include "interpreter/interpreter.h"
+#include "java_vm_ext.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "jni_internal.h"
diff --git a/runtime/scoped_thread_state_change-inl.h b/runtime/scoped_thread_state_change-inl.h
index c817a9ee8d..ed6e349de4 100644
--- a/runtime/scoped_thread_state_change-inl.h
+++ b/runtime/scoped_thread_state_change-inl.h
@@ -19,6 +19,7 @@
#include "scoped_thread_state_change.h"
+#include "base/casts.h"
#include "jni_env_ext-inl.h"
#include "obj_ptr-inl.h"
#include "thread-inl.h"
@@ -74,8 +75,10 @@ inline ScopedThreadStateChange::~ScopedThreadStateChange() {
template<typename T>
inline T ScopedObjectAccessAlreadyRunnable::AddLocalReference(ObjPtr<mirror::Object> obj) const {
Locks::mutator_lock_->AssertSharedHeld(Self());
- DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
- DCHECK_NE(obj, Runtime::Current()->GetClearedJniWeakGlobal());
+ if (kIsDebugBuild) {
+ CHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
+ DCheckObjIsNotClearedJniWeakGlobal(obj);
+ }
return obj == nullptr ? nullptr : Env()->AddLocalReference<T>(obj);
}
diff --git a/runtime/scoped_thread_state_change.cc b/runtime/scoped_thread_state_change.cc
new file mode 100644
index 0000000000..94354fc586
--- /dev/null
+++ b/runtime/scoped_thread_state_change.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "scoped_thread_state_change.h"
+
+#include <type_traits>
+
+#include "base/casts.h"
+#include "base/logging.h"
+#include "java_vm_ext.h"
+#include "obj_ptr-inl.h"
+#include "runtime-inl.h"
+
+namespace art {
+
+// See ScopedObjectAccessAlreadyRunnable::ScopedObjectAccessAlreadyRunnable(JavaVM*).
+static_assert(std::is_base_of<JavaVM, JavaVMExt>::value, "JavaVMExt does not extend JavaVM");
+
+void ScopedObjectAccessAlreadyRunnable::DCheckObjIsNotClearedJniWeakGlobal(
+ ObjPtr<mirror::Object> obj) {
+ DCHECK_NE(obj, Runtime::Current()->GetClearedJniWeakGlobal());
+}
+
+bool ScopedObjectAccessAlreadyRunnable::ForceCopy() const {
+ return vm_->ForceCopy();
+}
+
+} // namespace art
diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h
index 5f03741d1f..02b6124118 100644
--- a/runtime/scoped_thread_state_change.h
+++ b/runtime/scoped_thread_state_change.h
@@ -17,17 +17,23 @@
#ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
#define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
-#include "art_field.h"
-#include "base/casts.h"
+#include "jni.h"
+
+#include "base/macros.h"
+#include "base/mutex.h"
#include "base/value_object.h"
-#include "java_vm_ext.h"
#include "thread_state.h"
-#include "verify_object.h"
namespace art {
+class JavaVMExt;
struct JNIEnvExt;
template<class MirrorType> class ObjPtr;
+class Thread;
+
+namespace mirror {
+class Object;
+} // namespace mirror
// Scoped change into and out of a particular state. Handles Runnable transitions that require
// more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and
@@ -74,9 +80,7 @@ class ScopedObjectAccessAlreadyRunnable : public ValueObject {
return vm_;
}
- bool ForceCopy() const {
- return vm_->ForceCopy();
- }
+ bool ForceCopy() const;
/*
* Add a local reference for an object to the indirect reference table associated with the
@@ -105,12 +109,17 @@ class ScopedObjectAccessAlreadyRunnable : public ValueObject {
// Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
// change into Runnable or acquire a share on the mutator_lock_.
+ // Note: The reinterpret_cast is backed by a static_assert in the cc file. Avoid a down_cast,
+ // as it prevents forward declaration of JavaVMExt.
explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
- : self_(nullptr), env_(nullptr), vm_(down_cast<JavaVMExt*>(vm)) {}
+ : self_(nullptr), env_(nullptr), vm_(reinterpret_cast<JavaVMExt*>(vm)) {}
// Here purely to force inlining.
ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}
+ static void DCheckObjIsNotClearedJniWeakGlobal(ObjPtr<mirror::Object> obj)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Self thread, can be null.
Thread* const self_;
// The full JNIEnv.
diff --git a/runtime/thread.cc b/runtime/thread.cc
index f887aaa256..201701a510 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -56,6 +56,7 @@
#include "gc/space/space-inl.h"
#include "handle_scope-inl.h"
#include "indirect_reference_table-inl.h"
+#include "java_vm_ext.h"
#include "jni_internal.h"
#include "mirror/class_loader.h"
#include "mirror/class-inl.h"
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 38d151bc67..e1c6af4f71 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3732,7 +3732,7 @@ const RegType& MethodVerifier::ResolveClassAndCheckAccess(dex::TypeIndex class_i
self_->ClearException();
}
const RegType* result = nullptr;
- if (klass != nullptr && !klass->IsErroneous()) {
+ if (klass != nullptr) {
bool precise = klass->CannotBeAssignedFromOtherTypes();
if (precise && !IsInstantiableOrPrimitive(klass)) {
const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
@@ -4137,6 +4137,12 @@ void MethodVerifier::VerifyInvocationArgsUnresolvedMethod(const Instruction* ins
}
bool MethodVerifier::CheckCallSite(uint32_t call_site_idx) {
+ if (call_site_idx >= dex_file_->NumCallSiteIds()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Bad call site id #" << call_site_idx
+ << " >= " << dex_file_->NumCallSiteIds();
+ return false;
+ }
+
CallSiteArrayValueIterator it(*dex_file_, dex_file_->GetCallSiteId(call_site_idx));
// Check essential arguments are provided. The dex file verifier has verified indicies of the
// main values (method handle, name, method_type).
@@ -4147,9 +4153,11 @@ bool MethodVerifier::CheckCallSite(uint32_t call_site_idx) {
return false;
}
- // Get and check the first argument: the method handle.
+ // Get and check the first argument: the method handle (index range
+ // checked by the dex file verifier).
uint32_t method_handle_idx = static_cast<uint32_t>(it.GetJavaValue().i);
it.Next();
+
const DexFile::MethodHandleItem& mh = dex_file_->GetMethodHandle(method_handle_idx);
if (mh.method_handle_type_ != static_cast<uint16_t>(DexFile::MethodHandleType::kInvokeStatic)) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Call site #" << call_site_idx
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index be5c18b9eb..bdb6b6879d 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -23,7 +23,7 @@
#include "class_linker-inl.h"
#include "common_runtime_test.h"
-#include "dex_file.h"
+#include "dex_file-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "utils.h"
#include "verifier_log_mode.h"
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index 55e793527e..0497a6d6d1 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -18,8 +18,11 @@
#include <cstring>
+#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "base/stl_util.h"
#include "compiler_callbacks.h"
+#include "dex_file-inl.h"
#include "leb128.h"
#include "mirror/class-inl.h"
#include "obj_ptr-inl.h"
diff --git a/test/161-final-abstract-class/expected.txt b/test/161-final-abstract-class/expected.txt
new file mode 100644
index 0000000000..1e635844cc
--- /dev/null
+++ b/test/161-final-abstract-class/expected.txt
@@ -0,0 +1 @@
+java.lang.InstantiationError: AbstractFinal
diff --git a/test/161-final-abstract-class/info.txt b/test/161-final-abstract-class/info.txt
new file mode 100644
index 0000000000..2b7bee7a51
--- /dev/null
+++ b/test/161-final-abstract-class/info.txt
@@ -0,0 +1 @@
+Regression test for verifier crash when processing a final abstract (erroneous) class.
diff --git a/test/161-final-abstract-class/smali/AbstractFinal.smali b/test/161-final-abstract-class/smali/AbstractFinal.smali
new file mode 100644
index 0000000000..796fc40760
--- /dev/null
+++ b/test/161-final-abstract-class/smali/AbstractFinal.smali
@@ -0,0 +1,16 @@
+# Copyright (C) 2017 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.
+
+.class abstract final LAbstractFinal;
+.super Ljava/lang/Object;
diff --git a/test/161-final-abstract-class/smali/TestClass.smali b/test/161-final-abstract-class/smali/TestClass.smali
new file mode 100644
index 0000000000..fa38f59854
--- /dev/null
+++ b/test/161-final-abstract-class/smali/TestClass.smali
@@ -0,0 +1,22 @@
+# Copyright (C) 2017 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.
+
+.class LTestClass;
+.super Ljava/lang/Object;
+
+.method public static test()V
+ .registers 1
+ new-instance v0, LAbstractFinal;
+ return-void
+.end method
diff --git a/test/161-final-abstract-class/src/Main.java b/test/161-final-abstract-class/src/Main.java
new file mode 100644
index 0000000000..2452490226
--- /dev/null
+++ b/test/161-final-abstract-class/src/Main.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class Main {
+ public static void main(String[] args) {
+ try {
+ // Make sure that the abstract final class is marked as erroneous.
+ Class.forName("AbstractFinal");
+ System.out.println("UNREACHABLE!");
+ } catch (VerifyError expected) {
+ } catch (Throwable t) {
+ t.printStackTrace(System.out);
+ }
+ try {
+ // Verification of TestClass.test() used to crash when processing
+ // the final abstract (erroneous) class.
+ Class<?> tc = Class.forName("TestClass");
+ Method test = tc.getDeclaredMethod("test");
+ test.invoke(null);
+ System.out.println("UNREACHABLE!");
+ } catch (InvocationTargetException ite) {
+ if (ite.getCause() instanceof InstantiationError) {
+ System.out.println(
+ ite.getCause().getClass().getName() + ": " + ite.getCause().getMessage());
+ } else {
+ ite.printStackTrace(System.out);
+ }
+ } catch (Throwable t) {
+ t.printStackTrace(System.out);
+ }
+ }
+}
diff --git a/test/497-inlining-and-class-loader/clear_dex_cache.cc b/test/497-inlining-and-class-loader/clear_dex_cache.cc
index 6c73d7d9b6..9ba05bc706 100644
--- a/test/497-inlining-and-class-loader/clear_dex_cache.cc
+++ b/test/497-inlining-and-class-loader/clear_dex_cache.cc
@@ -14,9 +14,12 @@
* limitations under the License.
*/
-#include "art_method-inl.h"
+#include "art_method.h"
#include "base/enums.h"
#include "jni.h"
+#include "mirror/array-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/dex_cache-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread.h"
diff --git a/test/900-hello-plugin/load_unload.cc b/test/900-hello-plugin/load_unload.cc
index 290997aa08..19312b4d71 100644
--- a/test/900-hello-plugin/load_unload.cc
+++ b/test/900-hello-plugin/load_unload.cc
@@ -20,6 +20,8 @@
#include "art_method-inl.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "java_vm_ext.h"
+#include "runtime.h"
namespace art {
diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt
index 2318414010..fb5f71bda2 100644
--- a/test/911-get-stack-trace/expected.txt
+++ b/test/911-get-stack-trace/expected.txt
@@ -4,7 +4,7 @@
From top
---------
getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
- print (Ljava/lang/Thread;II)V 0 36
+ print (Ljava/lang/Thread;II)V 0 38
printOrWait (IILart/ControlData;)V 6 41
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -22,10 +22,9 @@ From top
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
doTest ()V 38 25
- run ()V 20 26
- main ([Ljava/lang/String;)V 0 19
+ run ()V 0 30
---------
- print (Ljava/lang/Thread;II)V 0 36
+ print (Ljava/lang/Thread;II)V 0 38
printOrWait (IILart/ControlData;)V 6 41
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -43,11 +42,10 @@ From top
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
doTest ()V 42 26
- run ()V 20 26
- main ([Ljava/lang/String;)V 0 19
+ run ()V 0 30
---------
getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
- print (Ljava/lang/Thread;II)V 0 36
+ print (Ljava/lang/Thread;II)V 0 38
printOrWait (IILart/ControlData;)V 6 41
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -59,19 +57,19 @@ From top
baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
From bottom
---------
- main ([Ljava/lang/String;)V 0 19
+ run ()V 0 30
---------
+ baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
doTest ()V 65 32
- run ()V 20 26
- main ([Ljava/lang/String;)V 0 19
+ run ()V 0 30
---------
+ bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- doTest ()V 69 33
################################
### Other thread (suspended) ###
@@ -258,9 +256,12 @@ ReferenceQueueDaemon
Signal Catcher
---------
-main
+Test911
---------
+main
+<not printed>
+---------
AllTraces Thread 0
wait ()V -1 -2
printOrWait (IILart/ControlData;)V 24 47
@@ -356,14 +357,16 @@ ReferenceQueueDaemon
Signal Catcher
---------
-main
+Test911
getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
printAll (I)V 0 75
doTest ()V 128 59
- run ()V 44 38
- main ([Ljava/lang/String;)V 0 19
+ run ()V 24 42
---------
+main
+<not printed>
+---------
AllTraces Thread 0
wait ()V -1 -2
printOrWait (IILart/ControlData;)V 24 47
@@ -589,18 +592,23 @@ ReferenceQueueDaemon
Signal Catcher
---------
-main
+Test911
getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
printAll (I)V 0 75
doTest ()V 133 61
- run ()V 44 38
- main ([Ljava/lang/String;)V 0 19
+ run ()V 24 42
+---------
+main
+<not printed>
########################################
### Other select threads (suspended) ###
########################################
---------
+Test911
+
+---------
ThreadListTraces Thread 0
---------
@@ -616,7 +624,11 @@ ThreadListTraces Thread 6
ThreadListTraces Thread 8
---------
-main
+Test911
+ getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
+ printList ([Ljava/lang/Thread;I)V 0 68
+ doTest ()V 116 54
+ run ()V 32 46
---------
ThreadListTraces Thread 0
@@ -659,12 +671,11 @@ ThreadListTraces Thread 8
foo (IIILart/ControlData;)I 0 21
---------
-main
+Test911
getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
printList ([Ljava/lang/Thread;I)V 0 68
- doTest ()V 116 54
- run ()V 52 42
- main ([Ljava/lang/String;)V 0 19
+ doTest ()V 121 56
+ run ()V 32 46
---------
ThreadListTraces Thread 0
@@ -771,25 +782,16 @@ ThreadListTraces Thread 8
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
----------
-main
- getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
- printList ([Ljava/lang/Thread;I)V 0 68
- doTest ()V 121 56
- run ()V 52 42
- main ([Ljava/lang/String;)V 0 19
-
###################
### Same thread ###
###################
-5
+4
JVMTI_ERROR_ILLEGAL_ARGUMENT
[public static native java.lang.Object[] art.Frames.getFrameLocation(java.lang.Thread,int), ffffffff]
[public static void art.Frames.doTestSameThread(), 38]
[public static void art.Frames.doTest() throws java.lang.Exception, 0]
-[public static void art.Test911.run() throws java.lang.Exception, 3c]
-[public static void Main.main(java.lang.String[]) throws java.lang.Exception, 0]
+[public void art.Test911$1.run(), 28]
JVMTI_ERROR_NO_MORE_FRAMES
################################
diff --git a/test/911-get-stack-trace/src/art/PrintThread.java b/test/911-get-stack-trace/src/art/PrintThread.java
index de1da9c8a6..f50a66b963 100644
--- a/test/911-get-stack-trace/src/art/PrintThread.java
+++ b/test/911-get-stack-trace/src/art/PrintThread.java
@@ -19,6 +19,8 @@ package art;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class PrintThread {
public static void print(String[][] stack) {
@@ -36,6 +38,20 @@ public class PrintThread {
print(getStackTrace(t, start, max));
}
+ // We have to ignore some threads when printing all stack traces. These are threads that may or
+ // may not exist depending on the environment.
+ public final static String IGNORE_THREAD_NAME_REGEX =
+ "Binder:|RenderThread|hwuiTask|Jit thread pool worker|Instr:|JDWP|Profile Saver|main";
+ public final static Matcher IGNORE_THREADS =
+ Pattern.compile(IGNORE_THREAD_NAME_REGEX).matcher("");
+
+ // We have to skip the stack of some threads when printing all stack traces. These are threads
+ // that may have a different call stack (e.g., when run as an app), or may be in a
+ // non-deterministic state.
+ public final static String CUT_STACK_THREAD_NAME_REGEX = "Daemon|main";
+ public final static Matcher CUT_STACK_THREADS =
+ Pattern.compile(CUT_STACK_THREAD_NAME_REGEX).matcher("");
+
public static void printAll(Object[][] stacks) {
List<String> stringified = new ArrayList<String>(stacks.length);
@@ -43,11 +59,11 @@ public class PrintThread {
Thread t = (Thread)stackInfo[0];
String name = (t != null) ? t.getName() : "null";
String stackSerialization;
- if (name.contains("Daemon")) {
+ if (CUT_STACK_THREADS.reset(name).find()) {
// Do not print daemon stacks, as they're non-deterministic.
stackSerialization = "<not printed>";
- } else if (name.startsWith("Jit thread pool worker")) {
- // Skip JIT thread pool. It may or may not be there depending on configuration.
+ } else if (IGNORE_THREADS.reset(name).find()) {
+ // Skip IGNORE_THREADS.
continue;
} else {
StringBuilder sb = new StringBuilder();
diff --git a/test/911-get-stack-trace/src/art/Test911.java b/test/911-get-stack-trace/src/art/Test911.java
index 71a5196c22..ee5936823b 100644
--- a/test/911-get-stack-trace/src/art/Test911.java
+++ b/test/911-get-stack-trace/src/art/Test911.java
@@ -23,27 +23,38 @@ public class Test911 {
Main.bindAgentJNIForClass(PrintThread.class);
Main.bindAgentJNIForClass(ThreadListTraces.class);
- SameThread.doTest();
+ Thread t = new Thread("Test911") {
+ @Override
+ public void run() {
+ try {
+ SameThread.doTest();
- System.out.println();
+ System.out.println();
- OtherThread.doTestOtherThreadWait();
+ OtherThread.doTestOtherThreadWait();
- System.out.println();
+ System.out.println();
- OtherThread.doTestOtherThreadBusyLoop();
+ OtherThread.doTestOtherThreadBusyLoop();
- System.out.println();
+ System.out.println();
- AllTraces.doTest();
+ AllTraces.doTest();
- System.out.println();
+ System.out.println();
- ThreadListTraces.doTest();
+ ThreadListTraces.doTest();
- System.out.println();
+ System.out.println();
- Frames.doTest();
+ Frames.doTest();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ t.start();
+ t.join();
System.out.println("Done");
}
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index c7a57cefb6..b683a27728 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -16,12 +16,14 @@
#include "jni.h"
+#include "art_method-inl.h"
#include "base/enums.h"
#include "base/logging.h"
#include "dex_file-inl.h"
#include "instrumentation.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
+#include "jit/profiling_info.h"
#include "mirror/class-inl.h"
#include "oat_quick_method_header.h"
#include "runtime.h"
diff --git a/test/testrunner/run_build_test_target.py b/test/testrunner/run_build_test_target.py
index 0ab50afa40..b1274c901a 100755
--- a/test/testrunner/run_build_test_target.py
+++ b/test/testrunner/run_build_test_target.py
@@ -62,7 +62,7 @@ custom_env['SOONG_ALLOW_MISSING_DEPENDENCIES'] = 'true'
print custom_env
os.environ.update(custom_env)
-if target.get('make'):
+if target.has_key('make'):
build_command = 'make'
build_command += ' -j' + str(n_threads)
build_command += ' -C ' + env.ANDROID_BUILD_TOP
@@ -74,7 +74,7 @@ if target.get('make'):
if subprocess.call(build_command.split()):
sys.exit(1)
-if target.get('golem'):
+if target.has_key('golem'):
machine_type = target.get('golem')
# use art-opt-cc by default since it mimics the default preopt config.
default_golem_config = 'art-opt-cc'
@@ -92,7 +92,7 @@ if target.get('golem'):
if subprocess.call(cmd):
sys.exit(1)
-if target.get('run-test'):
+if target.has_key('run-test'):
run_test_command = [os.path.join(env.ANDROID_BUILD_TOP,
'art/test/testrunner/testrunner.py')]
run_test_command += target.get('run-test', [])
diff --git a/test/valgrind-suppressions.txt b/test/valgrind-suppressions.txt
index c775f98b70..086a856f51 100644
--- a/test/valgrind-suppressions.txt
+++ b/test/valgrind-suppressions.txt
@@ -69,3 +69,9 @@
fun:_ZN12BacktraceMap6CreateEib
}
+{
+ process_vm_readv
+ Memcheck:Param
+ process_vm_readv(lvec[...])
+ fun:process_vm_readv
+}
diff --git a/test/valgrind-target-suppressions.txt b/test/valgrind-target-suppressions.txt
index 452a17412a..0d63a1c7aa 100644
--- a/test/valgrind-target-suppressions.txt
+++ b/test/valgrind-target-suppressions.txt
@@ -67,3 +67,10 @@
fun:msync
fun:_ZN3art6MemMap11MapInternalEPvmiiilb
}
+
+{
+ process_vm_readv
+ Memcheck:Param
+ process_vm_readv(lvec[...])
+ fun:process_vm_readv
+}
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index 07c300e7a7..720b1d2f5d 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -108,6 +108,17 @@ while true; do
fi
done
+# The JDWP tests include a class with a SourceDebugExtension attribute. Convert this class into
+# a DEX so the JDWP SourceDebugExtension can be tested. There is no corresponding java file as by
+# definition the class file is generated from a different language.
+jsr45_dex=$ANDROID_HOST_OUT/jsr45-test.dex
+(cd $ANDROID_BUILD_TOP/external/apache-harmony/jdwp/src/test/resources &&
+ dx --dex --output=$jsr45_dex org/apache/harmony/jpda/tests/jdwp/Events/SourceDebugExtensionMockClass.class )
+if [ $? -ne 0 ]; then
+ echo Failed to convert class file to DEX. >&2
+ exit 1
+fi
+
# For the host:
#
# If, on the other hand, there is a variant set, use it to modify the art_debugee parameter to
@@ -160,7 +171,7 @@ vogar $vm_command \
--vm-arg -Djpda.settings.waitingTime=$jdwp_test_timeout \
--vm-arg -Djpda.settings.transportAddress=127.0.0.1:55107 \
--vm-arg -Djpda.settings.debuggeeJavaPath="$art_debugee $image $debuggee_args" \
- --classpath $test_jack \
+ --classpath $test_jack --resource-classpath $jsr45_dex \
--toolchain jack --language JN \
--vm-arg -Xcompiler-option --vm-arg --debuggable \
--jack-arg -g \