Merge "ART: Support per PID stack trace files."
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index ed34a8d..11af1c0 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -125,6 +125,7 @@
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_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/build/art.go b/build/art.go
index 053968d..61a9759 100644
--- a/build/art.go
+++ b/build/art.go
@@ -59,8 +59,8 @@
}
if !envFalse(ctx, "ART_USE_READ_BARRIER") && ctx.AConfig().ArtUseReadBarrier() {
- // Used to change the read barrier type. Valid values are BAKER, BROOKS, TABLELOOKUP.
- // The default is BAKER.
+ // Used to change the read barrier type. Valid values are BAKER, BROOKS,
+ // TABLELOOKUP. The default is BAKER.
barrierType := envDefault(ctx, "ART_READ_BARRIER_TYPE", "BAKER")
cflags = append(cflags,
"-DART_USE_READ_BARRIER=1",
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 312fc7b..dec8b57 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -29,6 +29,7 @@
"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 8b30292..39edd1e 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 30d4b47..558c7d5 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 538fe93..1573062 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
similarity index 95%
rename from runtime/quick/inline_method_analyser.cc
rename to compiler/dex/inline_method_analyser.cc
index 3347070..e691a67 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 @@
#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_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 @@
case Instruction::RETURN_VOID:
if (result != nullptr) {
result->opcode = kInlineOpNop;
- result->flags = kInlineSpecial;
result->d.data = 0u;
}
return true;
@@ -549,7 +527,6 @@
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 @@
}
if (result != nullptr) {
result->opcode = kInlineOpNonWideConst;
- result->flags = kInlineSpecial;
result->d.data = static_cast<uint64_t>(const_value);
}
return true;
@@ -647,7 +623,6 @@
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 @@
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
similarity index 61%
rename from runtime/quick/inline_method_analyser.h
rename to compiler/dex/inline_method_analyser.h
index 2df2ced..a35e97f 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 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 @@
struct InlineMethod {
InlineMethodOpcode opcode;
- InlineMethodFlags flags;
union {
uint64_t data;
InlineIGetIPutData ifield_data;
@@ -213,12 +96,8 @@
* 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 @@
} // 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 cbca333..608a18a 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 1a44524..f77b3dd 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"
@@ -77,8 +78,8 @@
#include "vdex_file.h"
#include "verifier/method_verifier.h"
#include "verifier/method_verifier-inl.h"
-#include "verifier/verifier_log_mode.h"
#include "verifier/verifier_deps.h"
+#include "verifier/verifier_enums.h"
namespace art {
@@ -2131,7 +2132,7 @@
hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> klass(
hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader)));
- verifier::MethodVerifier::FailureKind failure_kind;
+ verifier::FailureKind failure_kind;
if (klass == nullptr) {
CHECK(soa.Self()->IsExceptionPending());
soa.Self()->ClearException();
@@ -2154,7 +2155,7 @@
true /* allow soft failures */,
log_level_,
&error_msg);
- if (failure_kind == verifier::MethodVerifier::kHardFailure) {
+ if (failure_kind == verifier::FailureKind::kHardFailure) {
LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
<< " because: " << error_msg;
manager_->GetCompiler()->SetHadHardVerifierFailure();
@@ -2162,10 +2163,10 @@
// Force a soft failure for the VerifierDeps. This is a sanity measure, as
// the vdex file already records that the class hasn't been resolved. It avoids
// trying to do future verification optimizations when processing the vdex file.
- DCHECK(failure_kind == verifier::MethodVerifier::kSoftFailure ||
- failure_kind == verifier::MethodVerifier::kNoFailure)
+ DCHECK(failure_kind == verifier::FailureKind::kSoftFailure ||
+ failure_kind == verifier::FailureKind::kNoFailure)
<< failure_kind;
- failure_kind = verifier::MethodVerifier::kSoftFailure;
+ failure_kind = verifier::FailureKind::kSoftFailure;
}
} else if (!SkipClass(jclass_loader, dex_file, klass.Get())) {
CHECK(klass->IsResolved()) << klass->PrettyClass();
@@ -2197,16 +2198,16 @@
<< " failed to fully verify: state= " << klass->GetStatus();
}
if (klass->IsVerified()) {
- DCHECK_EQ(failure_kind, verifier::MethodVerifier::kNoFailure);
+ DCHECK_EQ(failure_kind, verifier::FailureKind::kNoFailure);
} else if (klass->ShouldVerifyAtRuntime()) {
- DCHECK_EQ(failure_kind, verifier::MethodVerifier::kSoftFailure);
+ DCHECK_EQ(failure_kind, verifier::FailureKind::kSoftFailure);
} else {
- DCHECK_EQ(failure_kind, verifier::MethodVerifier::kHardFailure);
+ DCHECK_EQ(failure_kind, verifier::FailureKind::kHardFailure);
}
}
} else {
// Make the skip a soft failure, essentially being considered as verify at runtime.
- failure_kind = verifier::MethodVerifier::kSoftFailure;
+ failure_kind = verifier::FailureKind::kSoftFailure;
}
verifier::VerifierDeps::MaybeRecordVerificationStatus(
dex_file, class_def.class_idx_, failure_kind);
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
index 0c06090..37e4f11 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 c975944..dc880b0 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 897d819..7e53d8d 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 d129249..952a7c6 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 21042a3..b34d938 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/oat_writer.cc b/compiler/oat_writer.cc
index 1781643..af60def 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -55,7 +55,6 @@
#include "type_lookup_table.h"
#include "utils/dex_cache_arrays_layout-inl.h"
#include "vdex_file.h"
-#include "verifier/method_verifier.h"
#include "verifier/verifier_deps.h"
#include "zip_archive.h"
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index b7c8075..5136d7d 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 58feea2..332ab49 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -321,7 +321,9 @@
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_arm.cc b/compiler/optimizing/code_generator_vector_arm.cc
index 6e82123..f8552dc 100644
--- a/compiler/optimizing/code_generator_vector_arm.cc
+++ b/compiler/optimizing/code_generator_vector_arm.cc
@@ -245,6 +245,14 @@
LOG(FATAL) << "No SIMD for " << instruction->GetId();
}
+void LocationsBuilderARM::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
+void InstructionCodeGeneratorARM::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
void LocationsBuilderARM::VisitVecLoad(HVecLoad* instruction) {
LOG(FATAL) << "No SIMD for " << instruction->GetId();
}
diff --git a/compiler/optimizing/code_generator_vector_arm64.cc b/compiler/optimizing/code_generator_vector_arm64.cc
index 2dfccff..93befa4 100644
--- a/compiler/optimizing/code_generator_vector_arm64.cc
+++ b/compiler/optimizing/code_generator_vector_arm64.cc
@@ -27,6 +27,7 @@
using helpers::InputRegisterAt;
using helpers::Int64ConstantFrom;
using helpers::XRegisterFrom;
+using helpers::WRegisterFrom;
#define __ GetVIXLAssembler()->
@@ -681,6 +682,67 @@
}
}
+void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
+ switch (instr->GetPackedType()) {
+ case Primitive::kPrimByte:
+ case Primitive::kPrimChar:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimInt:
+ locations->SetInAt(
+ HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister());
+ locations->SetInAt(
+ HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister());
+ locations->SetInAt(
+ HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister());
+ DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0);
+ locations->SetOut(Location::SameAsFirstInput());
+ break;
+ default:
+ LOG(FATAL) << "Unsupported SIMD type";
+ UNREACHABLE();
+ }
+}
+
+// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
+// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
+// However vector MultiplyAccumulate instruction is not affected.
+void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LocationSummary* locations = instr->GetLocations();
+ VRegister acc = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex));
+ VRegister left = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex));
+ VRegister right = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex));
+ switch (instr->GetPackedType()) {
+ case Primitive::kPrimByte:
+ DCHECK_EQ(16u, instr->GetVectorLength());
+ if (instr->GetOpKind() == HInstruction::kAdd) {
+ __ Mla(acc.V16B(), left.V16B(), right.V16B());
+ } else {
+ __ Mls(acc.V16B(), left.V16B(), right.V16B());
+ }
+ break;
+ case Primitive::kPrimChar:
+ case Primitive::kPrimShort:
+ DCHECK_EQ(8u, instr->GetVectorLength());
+ if (instr->GetOpKind() == HInstruction::kAdd) {
+ __ Mla(acc.V8H(), left.V8H(), right.V8H());
+ } else {
+ __ Mls(acc.V8H(), left.V8H(), right.V8H());
+ }
+ break;
+ case Primitive::kPrimInt:
+ DCHECK_EQ(4u, instr->GetVectorLength());
+ if (instr->GetOpKind() == HInstruction::kAdd) {
+ __ Mla(acc.V4S(), left.V4S(), right.V4S());
+ } else {
+ __ Mls(acc.V4S(), left.V4S(), right.V4S());
+ }
+ break;
+ default:
+ LOG(FATAL) << "Unsupported SIMD type";
+ }
+}
+
// Helper to set up locations for vector memory operations.
static void CreateVecMemLocations(ArenaAllocator* arena,
HVecMemoryOperation* instruction,
@@ -713,7 +775,8 @@
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);
@@ -723,20 +786,18 @@
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) {
@@ -745,28 +806,22 @@
void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Location reg_loc = Location::NoLocation();
- MemOperand mem = CreateVecMemRegisters(instruction, ®_loc, /*is_load*/ true);
+ UseScratchRegisterScope temps(GetVIXLAssembler());
+ MemOperand mem = CreateVecMemRegisters(instruction, ®_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";
@@ -780,28 +835,22 @@
void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Location reg_loc = Location::NoLocation();
- MemOperand mem = CreateVecMemRegisters(instruction, ®_loc, /*is_load*/ false);
+ UseScratchRegisterScope temps(GetVIXLAssembler());
+ MemOperand mem = CreateVecMemRegisters(instruction, ®_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/code_generator_vector_arm_vixl.cc b/compiler/optimizing/code_generator_vector_arm_vixl.cc
index 990178b..53f314e 100644
--- a/compiler/optimizing/code_generator_vector_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_vector_arm_vixl.cc
@@ -245,6 +245,14 @@
LOG(FATAL) << "No SIMD for " << instruction->GetId();
}
+void LocationsBuilderARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
+void InstructionCodeGeneratorARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
void LocationsBuilderARMVIXL::VisitVecLoad(HVecLoad* instruction) {
LOG(FATAL) << "No SIMD for " << instruction->GetId();
}
diff --git a/compiler/optimizing/code_generator_vector_mips.cc b/compiler/optimizing/code_generator_vector_mips.cc
index 8ea1ca7..c4a3225 100644
--- a/compiler/optimizing/code_generator_vector_mips.cc
+++ b/compiler/optimizing/code_generator_vector_mips.cc
@@ -245,6 +245,14 @@
LOG(FATAL) << "No SIMD for " << instruction->GetId();
}
+void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
+void InstructionCodeGeneratorMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
void LocationsBuilderMIPS::VisitVecLoad(HVecLoad* instruction) {
LOG(FATAL) << "No SIMD for " << instruction->GetId();
}
diff --git a/compiler/optimizing/code_generator_vector_mips64.cc b/compiler/optimizing/code_generator_vector_mips64.cc
index a484bb4..50b95c1 100644
--- a/compiler/optimizing/code_generator_vector_mips64.cc
+++ b/compiler/optimizing/code_generator_vector_mips64.cc
@@ -245,6 +245,14 @@
LOG(FATAL) << "No SIMD for " << instruction->GetId();
}
+void LocationsBuilderMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
+void InstructionCodeGeneratorMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
void LocationsBuilderMIPS64::VisitVecLoad(HVecLoad* instruction) {
LOG(FATAL) << "No SIMD for " << instruction->GetId();
}
diff --git a/compiler/optimizing/code_generator_vector_x86.cc b/compiler/optimizing/code_generator_vector_x86.cc
index a86d060..013b092 100644
--- a/compiler/optimizing/code_generator_vector_x86.cc
+++ b/compiler/optimizing/code_generator_vector_x86.cc
@@ -730,6 +730,14 @@
}
}
+void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
+void InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
// Helper to set up locations for vector memory operations.
static void CreateVecMemLocations(ArenaAllocator* arena,
HVecMemoryOperation* instruction,
diff --git a/compiler/optimizing/code_generator_vector_x86_64.cc b/compiler/optimizing/code_generator_vector_x86_64.cc
index 6967353..66f19a4 100644
--- a/compiler/optimizing/code_generator_vector_x86_64.cc
+++ b/compiler/optimizing/code_generator_vector_x86_64.cc
@@ -719,6 +719,14 @@
}
}
+void LocationsBuilderX86_64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
+void InstructionCodeGeneratorX86_64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
+ LOG(FATAL) << "No SIMD for " << instr->GetId();
+}
+
// Helper to set up locations for vector memory operations.
static void CreateVecMemLocations(ArenaAllocator* arena,
HVecMemoryOperation* instruction,
diff --git a/compiler/optimizing/code_sinking.cc b/compiler/optimizing/code_sinking.cc
index dc3d378..0b4dcd3 100644
--- a/compiler/optimizing/code_sinking.cc
+++ b/compiler/optimizing/code_sinking.cc
@@ -161,9 +161,15 @@
for (const HUseListNode<HInstruction*>& use : instruction->GetUses()) {
HInstruction* user = use.GetUser();
if (!(filter && ShouldFilterUse(instruction, user, post_dominated))) {
- finder.Update(user->IsPhi()
- ? user->GetBlock()->GetPredecessors()[use.GetIndex()]
- : user->GetBlock());
+ HBasicBlock* block = user->GetBlock();
+ if (user->IsPhi()) {
+ // Special case phis by taking the incoming block for regular ones,
+ // or the dominator for catch phis.
+ block = user->AsPhi()->IsCatchPhi()
+ ? block->GetDominator()
+ : block->GetPredecessors()[use.GetIndex()];
+ }
+ finder.Update(block);
}
}
for (const HUseListNode<HEnvironment*>& use : instruction->GetEnvUses()) {
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 1b2b9f8..e5d94c3 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -514,6 +514,10 @@
StartAttributeStream("rounded") << std::boolalpha << hadd->IsRounded() << std::noboolalpha;
}
+ void VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) OVERRIDE {
+ StartAttributeStream("kind") << instruction->GetOpKind();
+ }
+
#if defined(ART_ENABLE_CODEGEN_arm) || defined(ART_ENABLE_CODEGEN_arm64)
void VisitMultiplyAccumulate(HMultiplyAccumulate* instruction) OVERRIDE {
StartAttributeStream("kind") << instruction->GetOpKind();
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 66948eb..1f8a58c 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"
@@ -1539,6 +1539,14 @@
return iput;
}
+template <typename T>
+static inline Handle<T> NewHandleIfDifferent(T* object,
+ Handle<T> hint,
+ VariableSizedHandleScope* handles)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return (object != hint.Get()) ? handles->NewHandle(object) : hint;
+}
+
bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction,
ArtMethod* resolved_method,
ReferenceTypeInfo receiver_type,
@@ -1550,9 +1558,13 @@
const DexFile& callee_dex_file = *resolved_method->GetDexFile();
uint32_t method_index = resolved_method->GetDexMethodIndex();
ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
- Handle<mirror::DexCache> dex_cache(handles_->NewHandle(resolved_method->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(handles_->NewHandle(
- resolved_method->GetDeclaringClass()->GetClassLoader()));
+ Handle<mirror::DexCache> dex_cache = NewHandleIfDifferent(resolved_method->GetDexCache(),
+ caller_compilation_unit_.GetDexCache(),
+ handles_);
+ Handle<mirror::ClassLoader> class_loader =
+ NewHandleIfDifferent(resolved_method->GetDeclaringClass()->GetClassLoader(),
+ caller_compilation_unit_.GetClassLoader(),
+ handles_);
DexCompilationUnit dex_compilation_unit(
class_loader,
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 60790e5..2dcc12e 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 5f5e29b..3fc7c50 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/instruction_simplifier_arm64.cc b/compiler/optimizing/instruction_simplifier_arm64.cc
index 73b7b2b..f16e372 100644
--- a/compiler/optimizing/instruction_simplifier_arm64.cc
+++ b/compiler/optimizing/instruction_simplifier_arm64.cc
@@ -210,5 +210,11 @@
}
}
+void InstructionSimplifierArm64Visitor::VisitVecMul(HVecMul* instruction) {
+ if (TryCombineVecMultiplyAccumulate(instruction, kArm64)) {
+ RecordSimplification();
+ }
+}
+
} // namespace arm64
} // namespace art
diff --git a/compiler/optimizing/instruction_simplifier_arm64.h b/compiler/optimizing/instruction_simplifier_arm64.h
index 65654f5..eec4e49 100644
--- a/compiler/optimizing/instruction_simplifier_arm64.h
+++ b/compiler/optimizing/instruction_simplifier_arm64.h
@@ -74,6 +74,7 @@
void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
void VisitUShr(HUShr* instruction) OVERRIDE;
void VisitXor(HXor* instruction) OVERRIDE;
+ void VisitVecMul(HVecMul* instruction) OVERRIDE;
OptimizingCompilerStats* stats_;
};
diff --git a/compiler/optimizing/instruction_simplifier_shared.cc b/compiler/optimizing/instruction_simplifier_shared.cc
index c2b1374..7d1f146 100644
--- a/compiler/optimizing/instruction_simplifier_shared.cc
+++ b/compiler/optimizing/instruction_simplifier_shared.cc
@@ -278,5 +278,71 @@
return true;
}
+bool TryCombineVecMultiplyAccumulate(HVecMul* mul, InstructionSet isa) {
+ Primitive::Type type = mul->GetPackedType();
+ switch (isa) {
+ case kArm64:
+ if (!(type == Primitive::kPrimByte ||
+ type == Primitive::kPrimChar ||
+ type == Primitive::kPrimShort ||
+ type == Primitive::kPrimInt)) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+
+ ArenaAllocator* arena = mul->GetBlock()->GetGraph()->GetArena();
+
+ if (mul->HasOnlyOneNonEnvironmentUse()) {
+ HInstruction* use = mul->GetUses().front().GetUser();
+ if (use->IsVecAdd() || use->IsVecSub()) {
+ // Replace code looking like
+ // VECMUL tmp, x, y
+ // VECADD/SUB dst, acc, tmp
+ // with
+ // VECMULACC dst, acc, x, y
+ // Note that we do not want to (unconditionally) perform the merge when the
+ // multiplication has multiple uses and it can be merged in all of them.
+ // Multiple uses could happen on the same control-flow path, and we would
+ // then increase the amount of work. In the future we could try to evaluate
+ // whether all uses are on different control-flow paths (using dominance and
+ // reverse-dominance information) and only perform the merge when they are.
+ HInstruction* accumulator = nullptr;
+ HVecBinaryOperation* binop = use->AsVecBinaryOperation();
+ HInstruction* binop_left = binop->GetLeft();
+ HInstruction* binop_right = binop->GetRight();
+ // This is always true since the `HVecMul` has only one use (which is checked above).
+ DCHECK_NE(binop_left, binop_right);
+ if (binop_right == mul) {
+ accumulator = binop_left;
+ } else if (use->IsVecAdd()) {
+ DCHECK_EQ(binop_left, mul);
+ accumulator = binop_right;
+ }
+
+ HInstruction::InstructionKind kind =
+ use->IsVecAdd() ? HInstruction::kAdd : HInstruction::kSub;
+ if (accumulator != nullptr) {
+ HVecMultiplyAccumulate* mulacc =
+ new (arena) HVecMultiplyAccumulate(arena,
+ kind,
+ accumulator,
+ mul->GetLeft(),
+ mul->GetRight(),
+ binop->GetPackedType(),
+ binop->GetVectorLength());
+
+ binop->GetBlock()->ReplaceAndRemoveInstructionWith(binop, mulacc);
+ DCHECK(!mul->HasUses());
+ mul->GetBlock()->RemoveInstruction(mul);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
} // namespace art
diff --git a/compiler/optimizing/instruction_simplifier_shared.h b/compiler/optimizing/instruction_simplifier_shared.h
index 83e3ffc..2ea103a 100644
--- a/compiler/optimizing/instruction_simplifier_shared.h
+++ b/compiler/optimizing/instruction_simplifier_shared.h
@@ -58,6 +58,8 @@
HInstruction* index,
size_t data_offset);
+bool TryCombineVecMultiplyAccumulate(HVecMul* mul, InstructionSet isa);
+
} // namespace art
#endif // ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_SHARED_H_
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 8df80ad..6236bd8 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 1006a77..750f9cc 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 47bcb5d..4d36015 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 0d933ea..fd8a37a 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 ecf919b..8e45747 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 13956df..8ed2ad8 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 e71fea9..ca953a1 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 6be237e..8368026 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1362,7 +1362,6 @@
M(UShr, BinaryOperation) \
M(Xor, BinaryOperation) \
M(VecReplicateScalar, VecUnaryOperation) \
- M(VecSetScalars, VecUnaryOperation) \
M(VecSumReduce, VecUnaryOperation) \
M(VecCnv, VecUnaryOperation) \
M(VecNeg, VecUnaryOperation) \
@@ -1382,6 +1381,8 @@
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 bff58d0..fb9dfb7 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -116,16 +116,23 @@
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,16 +141,26 @@
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);
};
@@ -175,7 +192,7 @@
};
//
-// Definitions of concrete vector operations in HIR.
+// Definitions of concrete unary vector operations in HIR.
//
// Replicates the given scalar into a vector,
@@ -187,32 +204,14 @@
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 {
@@ -221,10 +220,9 @@
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
@@ -244,10 +242,9 @@
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(); }
@@ -268,10 +265,9 @@
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:
@@ -287,10 +283,9 @@
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:
@@ -307,15 +302,18 @@
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 {
@@ -326,12 +324,10 @@
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:
@@ -352,14 +348,12 @@
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_; }
@@ -384,12 +378,10 @@
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:
@@ -406,12 +398,10 @@
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:
@@ -428,12 +418,10 @@
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:
@@ -450,12 +438,10 @@
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:
@@ -472,12 +458,10 @@
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:
@@ -494,10 +478,8 @@
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:
@@ -514,10 +496,8 @@
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:
@@ -534,10 +514,8 @@
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:
@@ -554,10 +532,8 @@
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:
@@ -574,11 +550,9 @@
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:
@@ -595,11 +569,9 @@
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:
@@ -616,17 +588,96 @@
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 ].
+class HVecMultiplyAccumulate FINAL : public HVecOperation {
+ public:
+ HVecMultiplyAccumulate(ArenaAllocator* arena,
+ InstructionKind op,
+ HInstruction* accumulator,
+ HInstruction* mul_left,
+ HInstruction* mul_right,
+ Primitive::Type packed_type,
+ size_t vector_length,
+ uint32_t dex_pc = kNoDexPc)
+ : HVecOperation(arena,
+ packed_type,
+ SideEffects::None(),
+ /* number_of_inputs */ 3,
+ vector_length,
+ dex_pc),
+ op_kind_(op) {
+ DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
+ DCHECK(accumulator->IsVecOperation());
+ DCHECK(mul_left->IsVecOperation() && mul_right->IsVecOperation());
+ DCHECK_EQ(accumulator->AsVecOperation()->GetPackedType(), packed_type);
+ DCHECK_EQ(mul_left->AsVecOperation()->GetPackedType(), packed_type);
+ DCHECK_EQ(mul_right->AsVecOperation()->GetPackedType(), packed_type);
+
+ SetRawInputAt(kInputAccumulatorIndex, accumulator);
+ SetRawInputAt(kInputMulLeftIndex, mul_left);
+ SetRawInputAt(kInputMulRightIndex, mul_right);
+ }
+
+ static constexpr int kInputAccumulatorIndex = 0;
+ static constexpr int kInputMulLeftIndex = 1;
+ static constexpr int kInputMulRightIndex = 2;
+
+ bool CanBeMoved() const OVERRIDE { return true; }
+
+ bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
+ return op_kind_ == other->AsVecMultiplyAccumulate()->op_kind_;
+ }
+
+ InstructionKind GetOpKind() const { return op_kind_; }
+
+ DECLARE_INSTRUCTION(VecMultiplyAccumulate);
+
+ private:
+ // Indicates if this is a MADD or MSUB.
+ const InstructionKind op_kind_;
+
+ DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate);
+};
+
// Loads a vector from memory, viz. load(mem, 1)
// yield the vector [ mem(1), .. , mem(n) ].
class HVecLoad FINAL : public HVecMemoryOperation {
@@ -640,7 +691,7 @@
: HVecMemoryOperation(arena,
packed_type,
SideEffects::ArrayReadOfType(packed_type),
- /*number_of_inputs*/ 2,
+ /* number_of_inputs */ 2,
vector_length,
dex_pc) {
SetRawInputAt(0, base);
@@ -665,7 +716,7 @@
: 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/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 8aad539..065c11e 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -98,7 +98,7 @@
#include "ssa_liveness_analysis.h"
#include "ssa_phi_elimination.h"
#include "utils/assembler.h"
-#include "verifier/method_verifier.h"
+#include "verifier/verifier_compiler_binding.h"
namespace art {
@@ -1041,7 +1041,7 @@
const VerifiedMethod* verified_method = compiler_driver->GetVerifiedMethod(&dex_file, method_idx);
DCHECK(!verified_method->HasRuntimeThrow());
if (compiler_driver->IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file)
- || verifier::MethodVerifier::CanCompilerHandleVerificationFailure(
+ || verifier::CanCompilerHandleVerificationFailure(
verified_method->GetEncounteredVerificationFailures())) {
ArenaAllocator arena(Runtime::Current()->GetArenaPool());
CodeVectorAllocator code_allocator(&arena);
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index d5637b9..98332d3 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/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index 071cd57..f8c4008 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -5610,7 +5610,7 @@
" 214: ecbd 8a10 vpop {s16-s31}\n",
" 218: e8bd 8de0 ldmia.w sp!, {r5, r6, r7, r8, sl, fp, pc}\n",
" 21c: 4660 mov r0, ip\n",
- " 21e: f8d9 c2b4 ldr.w ip, [r9, #692] ; 0x2b4\n",
+ " 21e: f8d9 c2b8 ldr.w ip, [r9, #696] ; 0x2b8\n",
" 222: 47e0 blx ip\n",
nullptr
};
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index 3b6b9cc..4d55eb0 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"
@@ -27,12 +28,13 @@
#include "driver/compiler_options.h"
#include "driver/compiler_driver.h"
#include "handle_scope-inl.h"
-#include "verifier/method_verifier-inl.h"
+#include "indenter.h"
#include "mirror/class_loader.h"
#include "runtime.h"
-#include "thread.h"
#include "scoped_thread_state_change-inl.h"
+#include "thread.h"
#include "utils/atomic_method_ref_map-inl.h"
+#include "verifier/method_verifier-inl.h"
namespace art {
namespace verifier {
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index a9108e0e..5090c11 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -382,8 +382,6 @@
"input dex file.");
UsageError("");
UsageError(" --force-determinism: force the compiler to emit a deterministic output.");
- UsageError(" This option is incompatible with read barriers (e.g., if dex2oat has been");
- UsageError(" built with the environment variable `ART_USE_READ_BARRIER` set to `true`).");
UsageError("");
UsageError(" --classpath-dir=<directory-path>: directory used to resolve relative class paths.");
UsageError("");
@@ -915,9 +913,10 @@
// Fill some values into the key-value store for the oat header.
key_value_store_.reset(new SafeMap<std::string, std::string>());
- // Automatically force determinism for the boot image in a host build if the default GC is CMS
- // or MS and read barriers are not enabled, as the former switches the GC to a non-concurrent
- // one by passing the option `-Xgc:nonconcurrent` (see below).
+ // Automatically force determinism for the boot image in a host build if read barriers
+ // are enabled, or if the default GC is CMS or MS. When the default GC is CMS
+ // (Concurrent Mark-Sweep), the GC is switched to a non-concurrent one by passing the
+ // option `-Xgc:nonconcurrent` (see below).
if (!kIsTargetBuild && IsBootImage()) {
if (SupportsDeterministicCompilation()) {
force_determinism_ = true;
@@ -939,9 +938,9 @@
}
static bool SupportsDeterministicCompilation() {
- return (gc::kCollectorTypeDefault == gc::kCollectorTypeCMS ||
- gc::kCollectorTypeDefault == gc::kCollectorTypeMS) &&
- !kEmitCompilerReadBarrier;
+ return (kUseReadBarrier ||
+ gc::kCollectorTypeDefault == gc::kCollectorTypeCMS ||
+ gc::kCollectorTypeDefault == gc::kCollectorTypeMS);
}
void ExpandOatAndImageFilenames() {
@@ -1233,7 +1232,7 @@
no_inline_from_string_ = option.substr(strlen("--no-inline-from=")).data();
} else if (option == "--force-determinism") {
if (!SupportsDeterministicCompilation()) {
- Usage("Cannot use --force-determinism with read barriers or non-CMS garbage collector");
+ Usage("Option --force-determinism requires read barriers or a CMS/MS garbage collector");
}
force_determinism_ = true;
} else if (option.starts_with("--classpath-dir=")) {
@@ -2421,15 +2420,25 @@
// foreground collector by default for dex2oat.
raw_options.push_back(std::make_pair("-XX:DisableHSpaceCompactForOOM", nullptr));
- // If we're asked to be deterministic, ensure non-concurrent GC for determinism. Also
- // force the free-list implementation for large objects.
if (compiler_options_->IsForceDeterminism()) {
+ // If we're asked to be deterministic, ensure non-concurrent GC for determinism.
+ //
+ // Note that with read barriers, this option is ignored, because Runtime::Init
+ // overrides the foreground GC to be gc::kCollectorTypeCC when instantiating
+ // gc::Heap. This is fine, as concurrent GC requests are not honored in dex2oat,
+ // which uses an unstarted runtime.
raw_options.push_back(std::make_pair("-Xgc:nonconcurrent", nullptr));
+
+ // Also force the free-list implementation for large objects.
raw_options.push_back(std::make_pair("-XX:LargeObjectSpace=freelist", nullptr));
// We also need to turn off the nonmoving space. For that, we need to disable HSpace
// compaction (done above) and ensure that neither foreground nor background collectors
// are concurrent.
+ //
+ // Likewise, this option is ignored with read barriers because Runtime::Init
+ // overrides the background GC to be gc::kCollectorTypeCCBackground, but that's
+ // fine too, for the same reason (see above).
raw_options.push_back(std::make_pair("-XX:BackgroundGC=nonconcurrent", nullptr));
// To make identity hashcode deterministic, set a known seed.
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 344d735..204af22 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -24,6 +24,7 @@
#include <inttypes.h>
#include <stdio.h>
+#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <iostream>
#include <memory>
diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc
index f307cbc..06a0f23 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 0c2717f..fbb0978 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 8972e91..cff2cbc 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -93,6 +93,7 @@
"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 @@
"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,13 +452,12 @@
"oat.h",
"object_callbacks.h",
"process_state.h",
- "quick/inline_method_analyser.h",
"runtime.h",
"stack.h",
"thread.h",
"thread_state.h",
"ti/agent.h",
- "verifier/method_verifier.h",
+ "verifier/verifier_enums.h",
],
output_extension: "operator_out.cc",
}
@@ -548,6 +548,7 @@
"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 923ff4f..4c15450 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 193af58..dc4e8f3 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 f9c19e8..7072a8a 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 d668d3a..f9a92c8 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 014cc15..7d8abb8 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 16b73c6..0de0f02 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 @@
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 7e13104..bc728f4 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -78,5 +78,12 @@
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 666ed8a..3789b0c 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -51,7 +51,12 @@
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 @@
}
// 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 @@
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 5cf0e0f..59cd978 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -82,37 +82,6 @@
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::IsRuntimeMethod() {
- return dex_method_index_ == DexFile::kDexNoIndex;
-}
-
inline bool ArtMethod::IsCalleeSaveMethod() {
if (!IsRuntimeMethod()) {
return false;
@@ -273,6 +238,11 @@
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 76fdd43..7de8916 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_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 @@
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 b01b344..856bfd2 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -55,6 +55,10 @@
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 @@
// 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 @@
// 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 @@
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 @@
}
}
+ 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/asm_support.h b/runtime/asm_support.h
index 4a2e34f..6d271ed 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -98,7 +98,7 @@
ADD_TEST_EQ(THREAD_LOCAL_END_OFFSET,
art::Thread::ThreadLocalEndOffset<POINTER_SIZE>().Int32Value())
// Offset of field Thread::tlsPtr_.thread_local_objects.
-#define THREAD_LOCAL_OBJECTS_OFFSET (THREAD_LOCAL_END_OFFSET + __SIZEOF_POINTER__)
+#define THREAD_LOCAL_OBJECTS_OFFSET (THREAD_LOCAL_END_OFFSET + 2 * __SIZEOF_POINTER__)
ADD_TEST_EQ(THREAD_LOCAL_OBJECTS_OFFSET,
art::Thread::ThreadLocalObjectsOffset<POINTER_SIZE>().Int32Value())
diff --git a/runtime/base/allocator.cc b/runtime/base/allocator.cc
index f1d0a5f..2a2790c 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 9ddc6cf..3c51f52 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 @@
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 @@
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 4bc8e8e..3ecf595 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"
@@ -2592,9 +2593,25 @@
return nullptr;
}
+ // Inlined DescriptorToDot(descriptor) with extra validation.
+ //
+ // Throw NoClassDefFoundError early rather than potentially load a class only to fail
+ // the DescriptorEquals() check below and give a confusing error message. For example,
+ // when native code erroneously calls JNI GetFieldId() with signature "java/lang/String"
+ // instead of "Ljava/lang/String;", the message below using the "dot" names would be
+ // "class loader [...] returned class java.lang.String instead of java.lang.String".
+ size_t descriptor_length = strlen(descriptor);
+ if (UNLIKELY(descriptor[0] != 'L') ||
+ UNLIKELY(descriptor[descriptor_length - 1] != ';') ||
+ UNLIKELY(memchr(descriptor + 1, '.', descriptor_length - 2) != nullptr)) {
+ ThrowNoClassDefFoundError("Invalid descriptor: %s.", descriptor);
+ return nullptr;
+ }
+ std::string class_name_string(descriptor + 1, descriptor_length - 2);
+ std::replace(class_name_string.begin(), class_name_string.end(), '/', '.');
+
ScopedLocalRef<jobject> class_loader_object(
soa.Env(), soa.AddLocalReference<jobject>(class_loader.Get()));
- std::string class_name_string(DescriptorToDot(descriptor));
ScopedLocalRef<jobject> result(soa.Env(), nullptr);
{
ScopedThreadStateChange tsc(self, kNative);
@@ -3964,7 +3981,7 @@
}
}
-verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass(
+verifier::FailureKind ClassLinker::VerifyClass(
Thread* self, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level) {
{
// TODO: assert that the monitor on the Class is held
@@ -3986,19 +4003,19 @@
// this class as a parent to another.
if (klass->IsErroneous()) {
ThrowEarlierClassFailure(klass.Get());
- return verifier::MethodVerifier::kHardFailure;
+ return verifier::FailureKind::kHardFailure;
}
// Don't attempt to re-verify if already verified.
if (klass->IsVerified()) {
EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
- return verifier::MethodVerifier::kNoFailure;
+ return verifier::FailureKind::kNoFailure;
}
// For AOT, don't attempt to re-verify if we have already found we should
// verify at runtime.
if (Runtime::Current()->IsAotCompiler() && klass->ShouldVerifyAtRuntime()) {
- return verifier::MethodVerifier::kSoftFailure;
+ return verifier::FailureKind::kSoftFailure;
}
if (klass->GetStatus() == mirror::Class::kStatusResolved) {
@@ -4014,7 +4031,7 @@
if (!Runtime::Current()->IsVerificationEnabled()) {
mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self);
EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
- return verifier::MethodVerifier::kNoFailure;
+ return verifier::FailureKind::kNoFailure;
}
}
@@ -4024,7 +4041,7 @@
// If we have a superclass and we get a hard verification failure we can return immediately.
if (supertype != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) {
CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
- return verifier::MethodVerifier::kHardFailure;
+ return verifier::FailureKind::kHardFailure;
}
// Verify all default super-interfaces.
@@ -4051,7 +4068,7 @@
} else if (UNLIKELY(!AttemptSupertypeVerification(self, klass, iface))) {
// We had a hard failure while verifying this interface. Just return immediately.
CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
- return verifier::MethodVerifier::kHardFailure;
+ return verifier::FailureKind::kHardFailure;
} else if (UNLIKELY(!iface->IsVerified())) {
// We softly failed to verify the iface. Stop checking and clean up.
// Put the iface into the supertype handle so we know what caused us to fail.
@@ -4078,7 +4095,7 @@
DCHECK(!mirror::Class::IsErroneous(oat_file_class_status) || !preverified);
std::string error_msg;
- verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
+ verifier::FailureKind verifier_failure = verifier::FailureKind::kNoFailure;
if (!preverified) {
Runtime* runtime = Runtime::Current();
verifier_failure = verifier::MethodVerifier::VerifyClass(self,
@@ -4092,8 +4109,8 @@
// Verification is done, grab the lock again.
ObjectLock<mirror::Class> lock(self, klass);
- if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
- if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) {
+ if (preverified || verifier_failure != verifier::FailureKind::kHardFailure) {
+ if (!preverified && verifier_failure != verifier::FailureKind::kNoFailure) {
VLOG(class_linker) << "Soft verification failure in class "
<< klass->PrettyDescriptor()
<< " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
@@ -4102,7 +4119,7 @@
self->AssertNoPendingException();
// Make sure all classes referenced by catch blocks are resolved.
ResolveClassExceptionHandlerTypes(klass);
- if (verifier_failure == verifier::MethodVerifier::kNoFailure) {
+ if (verifier_failure == verifier::FailureKind::kNoFailure) {
// Even though there were no verifier failures we need to respect whether the super-class and
// super-default-interfaces were verified or requiring runtime reverification.
if (supertype == nullptr || supertype->IsVerified()) {
@@ -4111,10 +4128,10 @@
CHECK_EQ(supertype->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime);
mirror::Class::SetStatus(klass, mirror::Class::kStatusRetryVerificationAtRuntime, self);
// Pretend a soft failure occurred so that we don't consider the class verified below.
- verifier_failure = verifier::MethodVerifier::kSoftFailure;
+ verifier_failure = verifier::FailureKind::kSoftFailure;
}
} else {
- CHECK_EQ(verifier_failure, verifier::MethodVerifier::kSoftFailure);
+ CHECK_EQ(verifier_failure, verifier::FailureKind::kSoftFailure);
// Soft failures at compile time should be retried at runtime. Soft
// failures at runtime will be handled by slow paths in the generated
// code. Set status accordingly.
@@ -4135,7 +4152,7 @@
ThrowVerifyError(klass.Get(), "%s", error_msg.c_str());
mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
}
- if (preverified || verifier_failure == verifier::MethodVerifier::kNoFailure) {
+ if (preverified || verifier_failure == verifier::FailureKind::kNoFailure) {
// Class is verified so we don't need to do any access check on its methods.
// Let the interpreter know it by setting the kAccSkipAccessChecks flag onto each
// method.
@@ -8967,6 +8984,13 @@
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 a26e63b..7f652ec 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -24,9 +24,7 @@
#include <utility>
#include <vector>
-#include "base/allocator.h"
#include "base/enums.h"
-#include "base/hash_set.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "class_table.h"
@@ -38,8 +36,7 @@
#include "jni.h"
#include "mirror/class.h"
#include "object_callbacks.h"
-#include "verifier/method_verifier.h"
-#include "verifier/verifier_log_mode.h"
+#include "verifier/verifier_enums.h"
namespace art {
@@ -185,7 +182,9 @@
// 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 +230,6 @@
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 +429,6 @@
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);
@@ -476,7 +450,7 @@
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- verifier::MethodVerifier::FailureKind VerifyClass(
+ verifier::FailureKind VerifyClass(
Thread* self,
Handle<mirror::Class> klass,
verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone)
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index 374b711..0891d3f 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 15724a1..01c6641 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/common_runtime_test.h b/runtime/common_runtime_test.h
index bfa273d..56e8aa3 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -243,6 +243,12 @@
return; \
}
+#define TEST_DISABLED_FOR_MEMORY_TOOL() \
+ if (RUNNING_ON_MEMORY_TOOL > 0) { \
+ printf("WARNING: TEST DISABLED FOR MEMORY TOOL\n"); \
+ return; \
+ }
+
} // namespace art
namespace std {
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 688f95b..625794e 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
+#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <sys/stat.h>
#include <zlib.h>
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 59b734f..5fbdc46 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -17,6 +17,7 @@
#include "elf_file.h"
#include <inttypes.h>
+#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <sys/types.h>
#include <unistd.h>
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index ba8cec3..37734e8 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 @@
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 b5130d7..c340a88 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 546e59d..eeb138b 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 343343f..3820d85 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 aa547bf..81560cc 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/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index 55a4625..a3c3981 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -121,7 +121,8 @@
sizeof(Thread::tls_ptr_sized_values::active_suspend_barriers));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_start, thread_local_pos, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_pos, thread_local_end, sizeof(void*));
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_end, thread_local_objects, sizeof(void*));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_end, thread_local_limit, sizeof(void*));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_limit, thread_local_objects, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_objects, jni_entrypoints, sizeof(size_t));
// Skip across the entrypoints structures.
diff --git a/runtime/gc/accounting/atomic_stack.h b/runtime/gc/accounting/atomic_stack.h
index db9568a..351798e 100644
--- a/runtime/gc/accounting/atomic_stack.h
+++ b/runtime/gc/accounting/atomic_stack.h
@@ -17,6 +17,8 @@
#ifndef ART_RUNTIME_GC_ACCOUNTING_ATOMIC_STACK_H_
#define ART_RUNTIME_GC_ACCOUNTING_ATOMIC_STACK_H_
+#include <sys/mman.h> // For the PROT_* and MAP_* constants.
+
#include <algorithm>
#include <memory>
#include <string>
@@ -25,7 +27,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "mem_map.h"
-#include "stack.h"
+#include "stack_reference.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/accounting/bitmap.cc b/runtime/gc/accounting/bitmap.cc
index 380cb8e..e535380 100644
--- a/runtime/gc/accounting/bitmap.cc
+++ b/runtime/gc/accounting/bitmap.cc
@@ -16,6 +16,8 @@
#include "bitmap-inl.h"
+#include <sys/mman.h> // For the PROT_* and MAP_* constants.
+
#include "base/bit_utils.h"
#include "card_table.h"
#include "jit/jit_code_cache.h"
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index a5bb91a..34e30c1 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/read_barrier_table.h b/runtime/gc/accounting/read_barrier_table.h
index e77a5b8..775746f 100644
--- a/runtime/gc/accounting/read_barrier_table.h
+++ b/runtime/gc/accounting/read_barrier_table.h
@@ -17,6 +17,8 @@
#ifndef ART_RUNTIME_GC_ACCOUNTING_READ_BARRIER_TABLE_H_
#define ART_RUNTIME_GC_ACCOUNTING_READ_BARRIER_TABLE_H_
+#include <sys/mman.h> // For the PROT_* and MAP_* constants.
+
#include "base/bit_utils.h"
#include "base/mutex.h"
#include "gc/space/space.h"
diff --git a/runtime/gc/accounting/remembered_set.cc b/runtime/gc/accounting/remembered_set.cc
index 7b1e2b8..f2fe58a 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/allocator_type.h b/runtime/gc/allocator_type.h
index 185a9b7..2f1f577 100644
--- a/runtime/gc/allocator_type.h
+++ b/runtime/gc/allocator_type.h
@@ -35,6 +35,10 @@
};
std::ostream& operator<<(std::ostream& os, const AllocatorType& rhs);
+inline constexpr bool IsTLABAllocator(AllocatorType allocator) {
+ return allocator == kAllocatorTypeTLAB || allocator == kAllocatorTypeRegionTLAB;
+}
+
} // namespace gc
} // namespace art
diff --git a/runtime/gc/collector/concurrent_copying-inl.h b/runtime/gc/collector/concurrent_copying-inl.h
index 854d0a5..dd449f9 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 @@
}
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 @@
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 bcf5008..4192f34 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -22,17 +22,21 @@
#include "base/stl_util.h"
#include "base/systrace.h"
#include "debugger.h"
+#include "gc/accounting/atomic_stack.h"
#include "gc/accounting/heap_bitmap-inl.h"
#include "gc/accounting/mod_union_table-inl.h"
+#include "gc/accounting/read_barrier_table.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/gc_pause_listener.h"
#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 +378,15 @@
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:
@@ -1031,13 +1044,15 @@
explicit VerifyNoFromSpaceRefsVisitor(ConcurrentCopying* collector)
: collector_(collector) {}
- void operator()(mirror::Object* ref) const
+ void operator()(mirror::Object* ref,
+ MemberOffset offset = MemberOffset(0),
+ mirror::Object* holder = nullptr) const
REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE {
if (ref == nullptr) {
// OK.
return;
}
- collector_->AssertToSpaceInvariant(nullptr, MemberOffset(0), ref);
+ collector_->AssertToSpaceInvariant(holder, offset, ref);
if (kUseBakerReadBarrier) {
CHECK_EQ(ref->GetReadBarrierState(), ReadBarrier::WhiteState())
<< "Ref " << ref << " " << ref->PrettyTypeOf()
@@ -1067,7 +1082,7 @@
mirror::Object* ref =
obj->GetFieldObject<mirror::Object, kDefaultVerifyFlags, kWithoutReadBarrier>(offset);
VerifyNoFromSpaceRefsVisitor visitor(collector_);
- visitor(ref);
+ visitor(ref, offset, obj.Ptr());
}
void operator()(ObjPtr<mirror::Class> klass,
ObjPtr<mirror::Reference> ref) const
@@ -2065,11 +2080,10 @@
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.
@@ -2359,7 +2373,9 @@
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));
@@ -2405,6 +2421,11 @@
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 a0da9fc..f877314 100644
--- a/runtime/gc/collector/concurrent_copying.h
+++ b/runtime/gc/collector/concurrent_copying.h
@@ -23,8 +23,6 @@
#include "jni.h"
#include "object_callbacks.h"
#include "offsets.h"
-#include "gc/accounting/atomic_stack.h"
-#include "gc/accounting/read_barrier_table.h"
#include "gc/accounting/space_bitmap.h"
#include "mirror/object.h"
#include "mirror/object_reference.h"
@@ -40,8 +38,11 @@
namespace gc {
namespace accounting {
+ template<typename T> class AtomicStack;
+ typedef AtomicStack<mirror::Object> ObjectStack;
typedef SpaceBitmap<kObjectAlignment> ContinuousSpaceBitmap;
class HeapBitmap;
+ class ReadBarrierTable;
} // namespace accounting
namespace space {
@@ -106,7 +107,9 @@
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 +227,10 @@
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 +322,11 @@
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 c61f69d..cab293f 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 e72277f..e4993ce 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 67e7383..41e6051 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-inl.h b/runtime/gc/heap-inl.h
index 394e541..79086da 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -57,8 +57,8 @@
HandleWrapperObjPtr<mirror::Class> h = hs.NewHandleWrapper(&klass);
self->PoisonObjectPointers();
}
- // Need to check that we arent the large object allocator since the large object allocation code
- // path this function. If we didn't check we would have an infinite loop.
+ // Need to check that we aren't the large object allocator since the large object allocation code
+ // path includes this function. If we didn't check we would have an infinite loop.
ObjPtr<mirror::Object> obj;
if (kCheckLargeObject && UNLIKELY(ShouldAllocLargeObject(klass, byte_count))) {
obj = AllocLargeObject<kInstrumented, PreFenceVisitor>(self, &klass, byte_count,
@@ -77,12 +77,11 @@
size_t bytes_allocated;
size_t usable_size;
size_t new_num_bytes_allocated = 0;
- if (allocator == kAllocatorTypeTLAB || allocator == kAllocatorTypeRegionTLAB) {
+ if (IsTLABAllocator(allocator)) {
byte_count = RoundUp(byte_count, space::BumpPointerSpace::kAlignment);
}
// If we have a thread local allocation we don't need to update bytes allocated.
- if ((allocator == kAllocatorTypeTLAB || allocator == kAllocatorTypeRegionTLAB) &&
- byte_count <= self->TlabSize()) {
+ if (IsTLABAllocator(allocator) && byte_count <= self->TlabSize()) {
obj = self->AllocTlab(byte_count);
DCHECK(obj != nullptr) << "AllocTlab can't fail";
obj->SetClass(klass);
@@ -199,7 +198,7 @@
} else {
DCHECK(!gc_stress_mode_);
}
- // IsConcurrentGc() isn't known at compile time so we can optimize by not checking it for
+ // IsGcConcurrent() isn't known at compile time so we can optimize by not checking it for
// the BumpPointer or TLAB allocators. This is nice since it allows the entire if statement to be
// optimized out. And for the other allocators, AllocatorMayHaveConcurrentGC is a constant since
// the allocator_type should be constant propagated.
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 4a25610..7da7221 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"
@@ -135,6 +138,13 @@
static const char* kRegionSpaceName = "main space (region space)";
+// If true, we log all GCs in the both the foreground and background. Used for debugging.
+static constexpr bool kLogAllGCs = false;
+
+// How much we grow the TLAB if we can do it.
+static constexpr size_t kPartialTlabSize = 16 * KB;
+static constexpr bool kUsePartialTlabs = true;
+
#if defined(__LP64__) || !defined(ADDRESS_SANITIZER)
// 300 MB (0x12c00000) - (default non-moving space capacity).
static uint8_t* const kPreferredAllocSpaceBegin =
@@ -278,6 +288,7 @@
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();
@@ -2762,7 +2773,7 @@
const std::vector<uint64_t>& pause_times = GetCurrentGcIteration()->GetPauseTimes();
// Print the GC if it is an explicit GC (e.g. Runtime.gc()) or a slow GC
// (mutator time blocked >= long_pause_log_threshold_).
- bool log_gc = gc_cause == kGcCauseExplicit;
+ bool log_gc = kLogAllGCs || gc_cause == kGcCauseExplicit;
if (!log_gc && CareAboutPauseTimes()) {
// GC for alloc pauses the allocating thread, so consider it as a pause.
log_gc = duration > long_gc_log_threshold_ ||
@@ -3727,8 +3738,8 @@
if (!Runtime::Current()->IsShuttingDown(self)) {
// Wait for any GCs currently running to finish.
if (WaitForGcToComplete(cause, self) == collector::kGcTypeNone) {
- // If the we can't run the GC type we wanted to run, find the next appropriate one and try that
- // instead. E.g. can't do partial, so do full instead.
+ // If the we can't run the GC type we wanted to run, find the next appropriate one and try
+ // that instead. E.g. can't do partial, so do full instead.
collector::GcType next_gc_type = next_gc_type_;
// If forcing full and next gc type is sticky, override with a non-sticky type.
if (force_full && next_gc_type == collector::kGcTypeSticky) {
@@ -4182,7 +4193,21 @@
size_t* usable_size,
size_t* bytes_tl_bulk_allocated) {
const AllocatorType allocator_type = GetCurrentAllocator();
- if (allocator_type == kAllocatorTypeTLAB) {
+ if (kUsePartialTlabs && alloc_size <= self->TlabRemainingCapacity()) {
+ DCHECK_GT(alloc_size, self->TlabSize());
+ // There is enough space if we grow the TLAB. Lets do that. This increases the
+ // TLAB bytes.
+ const size_t min_expand_size = alloc_size - self->TlabSize();
+ const size_t expand_bytes = std::max(
+ min_expand_size,
+ std::min(self->TlabRemainingCapacity() - self->TlabSize(), kPartialTlabSize));
+ if (UNLIKELY(IsOutOfMemoryOnAllocation(allocator_type, expand_bytes, grow))) {
+ return nullptr;
+ }
+ *bytes_tl_bulk_allocated = expand_bytes;
+ self->ExpandTlab(expand_bytes);
+ DCHECK_LE(alloc_size, self->TlabSize());
+ } else if (allocator_type == kAllocatorTypeTLAB) {
DCHECK(bump_pointer_space_ != nullptr);
const size_t new_tlab_size = alloc_size + kDefaultTLABSize;
if (UNLIKELY(IsOutOfMemoryOnAllocation(allocator_type, new_tlab_size, grow))) {
@@ -4202,15 +4227,18 @@
if (LIKELY(!IsOutOfMemoryOnAllocation(allocator_type,
space::RegionSpace::kRegionSize,
grow))) {
+ const size_t new_tlab_size = kUsePartialTlabs
+ ? std::max(alloc_size, kPartialTlabSize)
+ : gc::space::RegionSpace::kRegionSize;
// Try to allocate a tlab.
- if (!region_space_->AllocNewTlab(self)) {
+ if (!region_space_->AllocNewTlab(self, new_tlab_size)) {
// Failed to allocate a tlab. Try non-tlab.
return region_space_->AllocNonvirtual<false>(alloc_size,
bytes_allocated,
usable_size,
bytes_tl_bulk_allocated);
}
- *bytes_tl_bulk_allocated = space::RegionSpace::kRegionSize;
+ *bytes_tl_bulk_allocated = new_tlab_size;
// Fall-through to using the TLAB below.
} else {
// Check OOME for a non-tlab allocation.
@@ -4242,5 +4270,9 @@
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 241d84c..aa123d8 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -64,6 +64,7 @@
class GcPauseListener;
class ReferenceProcessor;
class TaskProcessor;
+class Verification;
namespace accounting {
class HeapBitmap;
@@ -821,6 +822,8 @@
// 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 @@
// 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 0000000..2cdfc16
--- /dev/null
+++ b/runtime/gc/heap_verification_test.cc
@@ -0,0 +1,145 @@
+/*
+ * 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 "base/memory_tool.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, IsValidClassOrNotInHeap) {
+ 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_TRUE(v->IsValidClass(string->GetClass()));
+ EXPECT_FALSE(v->IsValidClass(string.Get()));
+}
+
+TEST_F(VerificationTest, IsValidClassInHeap) {
+ TEST_DISABLED_FOR_MEMORY_TOOL();
+ 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();
+ 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, DumpInvalidObjectInfo) {
+ ScopedLogSeverity sls(LogSeverity::INFO);
+ ScopedObjectAccess soa(Thread::Current());
+ Runtime* const runtime = Runtime::Current();
+ VariableSizedHandleScope hs(soa.Self());
+ 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");
+}
+
+TEST_F(VerificationTest, DumpValidObjectInfo) {
+ TEST_DISABLED_FOR_MEMORY_TOOL();
+ 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(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) {
+ TEST_DISABLED_FOR_MEMORY_TOOL();
+ 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 65a550e..886c950 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/bump_pointer_space.cc b/runtime/gc/space/bump_pointer_space.cc
index 1303d77..426b332 100644
--- a/runtime/gc/space/bump_pointer_space.cc
+++ b/runtime/gc/space/bump_pointer_space.cc
@@ -249,7 +249,7 @@
void BumpPointerSpace::RevokeThreadLocalBuffersLocked(Thread* thread) {
objects_allocated_.FetchAndAddSequentiallyConsistent(thread->GetThreadLocalObjectsAllocated());
bytes_allocated_.FetchAndAddSequentiallyConsistent(thread->GetThreadLocalBytesAllocated());
- thread->SetTlab(nullptr, nullptr);
+ thread->SetTlab(nullptr, nullptr, nullptr);
}
bool BumpPointerSpace::AllocNewTlab(Thread* self, size_t bytes) {
@@ -259,7 +259,7 @@
if (start == nullptr) {
return false;
}
- self->SetTlab(start, start + bytes);
+ self->SetTlab(start, start + bytes, start + bytes);
return true;
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 662efe2..e9f0758 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/space/region_space-inl.h b/runtime/gc/space/region_space-inl.h
index 5809027..3910a03 100644
--- a/runtime/gc/space/region_space-inl.h
+++ b/runtime/gc/space/region_space-inl.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_GC_SPACE_REGION_SPACE_INL_H_
#include "region_space.h"
+#include "thread-inl.h"
namespace art {
namespace gc {
@@ -335,6 +336,28 @@
return nullptr;
}
+inline size_t RegionSpace::Region::BytesAllocated() const {
+ if (IsLarge()) {
+ DCHECK_LT(begin_ + kRegionSize, Top());
+ return static_cast<size_t>(Top() - begin_);
+ } else if (IsLargeTail()) {
+ DCHECK_EQ(begin_, Top());
+ return 0;
+ } else {
+ DCHECK(IsAllocated()) << static_cast<uint>(state_);
+ DCHECK_LE(begin_, Top());
+ size_t bytes;
+ if (is_a_tlab_) {
+ bytes = thread_->GetThreadLocalBytesAllocated();
+ } else {
+ bytes = static_cast<size_t>(Top() - begin_);
+ }
+ DCHECK_LE(bytes, kRegionSize);
+ return bytes;
+ }
+}
+
+
} // namespace space
} // namespace gc
} // namespace art
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index 1ad4843..09b4a3a 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -427,7 +427,7 @@
r->objects_allocated_.FetchAndAddSequentiallyConsistent(1);
}
-bool RegionSpace::AllocNewTlab(Thread* self) {
+bool RegionSpace::AllocNewTlab(Thread* self, size_t min_bytes) {
MutexLock mu(self, region_lock_);
RevokeThreadLocalBuffersLocked(self);
// Retain sufficient free regions for full evacuation.
@@ -443,7 +443,7 @@
r->SetTop(r->End());
r->is_a_tlab_ = true;
r->thread_ = self;
- self->SetTlab(r->Begin(), r->End());
+ self->SetTlab(r->Begin(), r->Begin() + min_bytes, r->End());
return true;
}
}
@@ -463,13 +463,13 @@
DCHECK_ALIGNED(tlab_start, kRegionSize);
Region* r = RefToRegionLocked(reinterpret_cast<mirror::Object*>(tlab_start));
DCHECK(r->IsAllocated());
- DCHECK_EQ(thread->GetThreadLocalBytesAllocated(), kRegionSize);
+ DCHECK_LE(thread->GetThreadLocalBytesAllocated(), kRegionSize);
r->RecordThreadLocalAllocations(thread->GetThreadLocalObjectsAllocated(),
thread->GetThreadLocalBytesAllocated());
r->is_a_tlab_ = false;
r->thread_ = nullptr;
}
- thread->SetTlab(nullptr, nullptr);
+ thread->SetTlab(nullptr, nullptr, nullptr);
}
size_t RegionSpace::RevokeAllThreadLocalBuffers() {
diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h
index 2537929..80eecca 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -234,7 +234,7 @@
}
void RecordAlloc(mirror::Object* ref) REQUIRES(!region_lock_);
- bool AllocNewTlab(Thread* self) REQUIRES(!region_lock_);
+ bool AllocNewTlab(Thread* self, size_t min_bytes) REQUIRES(!region_lock_);
uint32_t Time() {
return time_;
@@ -417,21 +417,7 @@
return live_bytes_;
}
- size_t BytesAllocated() const {
- if (IsLarge()) {
- DCHECK_LT(begin_ + kRegionSize, Top());
- return static_cast<size_t>(Top() - begin_);
- } else if (IsLargeTail()) {
- DCHECK_EQ(begin_, Top());
- return 0;
- } else {
- DCHECK(IsAllocated()) << static_cast<uint>(state_);
- DCHECK_LE(begin_, Top());
- size_t bytes = static_cast<size_t>(Top() - begin_);
- DCHECK_LE(bytes, kRegionSize);
- return bytes;
- }
- }
+ size_t BytesAllocated() const;
size_t ObjectsAllocated() const {
if (IsLarge()) {
@@ -476,7 +462,7 @@
DCHECK_EQ(Top(), end_);
objects_allocated_.StoreRelaxed(num_objects);
top_.StoreRelaxed(begin_ + num_bytes);
- DCHECK_EQ(Top(), end_);
+ DCHECK_LE(Top(), end_);
}
private:
diff --git a/runtime/gc/system_weak_test.cc b/runtime/gc/system_weak_test.cc
index 9b601c0..dfbbd2a 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 0000000..7b31c8a
--- /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 0000000..3d95d93
--- /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 495fec7..4f390fd 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 b153ea0..b2486a1 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 24ee227..2128f8c 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 9fbb2e9..c852d5a 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 f0d0260..311515c7 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 8978bfd..ef0ddb3 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -28,11 +28,10 @@
#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"
-#include "verifier/method_verifier.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 56e261c..c314f3c 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -1341,7 +1341,8 @@
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 b93b8f2..6d3118e 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"
@@ -40,6 +40,7 @@
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change-inl.h"
#include "sigchain.h"
+#include "ti/agent.h"
#include "thread-inl.h"
#include "thread_list.h"
@@ -268,7 +269,6 @@
detail += "No implementation found for ";
detail += m->PrettyMethod();
detail += " (tried " + jni_short_name + " and " + jni_long_name + ")";
- LOG(ERROR) << detail;
return nullptr;
}
@@ -929,6 +929,26 @@
return was_successful;
}
+static void* FindCodeForNativeMethodInAgents(ArtMethod* m) REQUIRES_SHARED(Locks::mutator_lock_) {
+ std::string jni_short_name(m->JniShortName());
+ std::string jni_long_name(m->JniLongName());
+ for (const ti::Agent& agent : Runtime::Current()->GetAgents()) {
+ void* fn = agent.FindSymbol(jni_short_name);
+ if (fn != nullptr) {
+ VLOG(jni) << "Found implementation for " << m->PrettyMethod()
+ << " (symbol: " << jni_short_name << ") in " << agent;
+ return fn;
+ }
+ fn = agent.FindSymbol(jni_long_name);
+ if (fn != nullptr) {
+ VLOG(jni) << "Found implementation for " << m->PrettyMethod()
+ << " (symbol: " << jni_long_name << ") in " << agent;
+ return fn;
+ }
+ }
+ return nullptr;
+}
+
void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m) {
CHECK(m->IsNative());
mirror::Class* c = m->GetDeclaringClass();
@@ -941,8 +961,14 @@
MutexLock mu(self, *Locks::jni_libraries_lock_);
native_method = libraries_->FindNativeMethod(m, detail);
}
+ if (native_method == nullptr) {
+ // Lookup JNI native methods from native TI Agent libraries. See runtime/ti/agent.h for more
+ // information. Agent libraries are searched for native methods after all jni libraries.
+ native_method = FindCodeForNativeMethodInAgents(m);
+ }
// Throwing can cause libraries_lock to be reacquired.
if (native_method == nullptr) {
+ LOG(ERROR) << detail;
self->ThrowNewException("Ljava/lang/UnsatisfiedLinkError;", detail.c_str());
}
return native_method;
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 3631a9d..b32b272 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 2d1601e..52649c7 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/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index 9d6cd95..d190bdf 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -16,6 +16,7 @@
#include "profile_saver.h"
+#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -431,6 +432,16 @@
pthread_create,
(&profiler_pthread_, nullptr, &RunProfileSaverThread, reinterpret_cast<void*>(instance_)),
"Profile saver thread");
+
+#if defined(ART_TARGET_ANDROID)
+ // At what priority to schedule the saver threads. 9 is the lowest foreground priority on device.
+ static constexpr int kProfileSaverPthreadPriority = 9;
+ int result = setpriority(
+ PRIO_PROCESS, pthread_gettid_np(profiler_pthread_), kProfileSaverPthreadPriority);
+ if (result != 0) {
+ PLOG(ERROR) << "Failed to setpriority to :" << kProfileSaverPthreadPriority;
+ }
+#endif
}
void ProfileSaver::Stop(bool dump_info) {
diff --git a/runtime/jni_env_ext-inl.h b/runtime/jni_env_ext-inl.h
index 004f824..25893b7 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 4004c45..60e4295 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/jni_internal.cc b/runtime/jni_internal.cc
index b146b51..2626eef 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -2159,10 +2159,11 @@
}
CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class, JNI_ERR);
ScopedObjectAccess soa(env);
- ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::Class> c = hs.NewHandle(soa.Decode<mirror::Class>(java_class));
if (UNLIKELY(method_count == 0)) {
LOG(WARNING) << "JNI RegisterNativeMethods: attempt to register 0 native methods for "
- << mirror::Class::PrettyDescriptor(c);
+ << c->PrettyDescriptor();
return JNI_OK;
}
CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", methods, JNI_ERR);
@@ -2171,13 +2172,13 @@
const char* sig = methods[i].signature;
const void* fnPtr = methods[i].fnPtr;
if (UNLIKELY(name == nullptr)) {
- ReportInvalidJNINativeMethod(soa, c, "method name", i, return_errors);
+ ReportInvalidJNINativeMethod(soa, c.Get(), "method name", i, return_errors);
return JNI_ERR;
} else if (UNLIKELY(sig == nullptr)) {
- ReportInvalidJNINativeMethod(soa, c, "method signature", i, return_errors);
+ ReportInvalidJNINativeMethod(soa, c.Get(), "method signature", i, return_errors);
return JNI_ERR;
} else if (UNLIKELY(fnPtr == nullptr)) {
- ReportInvalidJNINativeMethod(soa, c, "native function", i, return_errors);
+ ReportInvalidJNINativeMethod(soa, c.Get(), "native function", i, return_errors);
return JNI_ERR;
}
bool is_fast = false;
@@ -2220,7 +2221,7 @@
// the parent.
ArtMethod* m = nullptr;
bool warn_on_going_to_parent = down_cast<JNIEnvExt*>(env)->vm->IsCheckJniEnabled();
- for (ObjPtr<mirror::Class> current_class = c;
+ for (ObjPtr<mirror::Class> current_class = c.Get();
current_class != nullptr;
current_class = current_class->GetSuperClass()) {
// Search first only comparing methods which are native.
@@ -2252,14 +2253,14 @@
<< "Failed to register native method "
<< c->PrettyDescriptor() << "." << name << sig << " in "
<< c->GetDexCache()->GetLocation()->ToModifiedUtf8();
- ThrowNoSuchMethodError(soa, c, name, sig, "static or non-static");
+ ThrowNoSuchMethodError(soa, c.Get(), name, sig, "static or non-static");
return JNI_ERR;
} else if (!m->IsNative()) {
LOG(return_errors ? ::android::base::ERROR : ::android::base::FATAL)
<< "Failed to register non-native method "
<< c->PrettyDescriptor() << "." << name << sig
<< " as native";
- ThrowNoSuchMethodError(soa, c, name, sig, "native");
+ ThrowNoSuchMethodError(soa, c.Get(), name, sig, "native");
return JNI_ERR;
}
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 40309b9..6c39361 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -16,26 +16,26 @@
#include "mem_map.h"
-#include "base/memory_tool.h"
-#include <backtrace/BacktraceMap.h>
#include <inttypes.h>
#include <stdlib.h>
+#include <sys/mman.h> // For the PROT_* and MAP_* constants.
+#ifndef ANDROID_OS
+#include <sys/resource.h>
+#endif
#include <memory>
#include <sstream>
#include "android-base/stringprintf.h"
+#include "android-base/unique_fd.h"
+#include "backtrace/BacktraceMap.h"
+#include "cutils/ashmem.h"
-#include "base/unix_file/fd_file.h"
-#include "os.h"
-#include "thread-inl.h"
+#include "base/allocator.h"
+#include "base/memory_tool.h"
+#include "globals.h"
#include "utils.h"
-#include <cutils/ashmem.h>
-
-#ifndef ANDROID_OS
-#include <sys/resource.h>
-#endif
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
@@ -44,6 +44,12 @@
namespace art {
using android::base::StringPrintf;
+using android::base::unique_fd;
+
+using Maps = AllocationTrackingMultiMap<void*, MemMap*, kAllocatorTagMaps>;
+
+// All the non-empty MemMaps. Use a multimap as we do a reserve-and-divide (eg ElfMap::Load()).
+static Maps* gMaps GUARDED_BY(MemMap::GetMemMapsLock()) = nullptr;
static std::ostream& operator<<(
std::ostream& os,
@@ -59,7 +65,7 @@
return os;
}
-std::ostream& operator<<(std::ostream& os, const MemMap::Maps& mem_maps) {
+std::ostream& operator<<(std::ostream& os, const Maps& mem_maps) {
os << "MemMap:" << std::endl;
for (auto it = mem_maps.begin(); it != mem_maps.end(); ++it) {
void* base = it->first;
@@ -71,7 +77,6 @@
}
std::mutex* MemMap::mem_maps_lock_ = nullptr;
-MemMap::Maps* MemMap::maps_ = nullptr;
#if USE_ART_LOW_4G_ALLOCATOR
// Handling mem_map in 32b address range for 64b architectures that do not support MAP_32BIT.
@@ -132,7 +137,7 @@
#endif
// Return true if the address range is contained in a single memory map by either reading
-// the maps_ variable or the /proc/self/map entry.
+// the gMaps variable or the /proc/self/map entry.
bool MemMap::ContainedWithinExistingMap(uint8_t* ptr, size_t size, std::string* error_msg) {
uintptr_t begin = reinterpret_cast<uintptr_t>(ptr);
uintptr_t end = begin + size;
@@ -141,7 +146,7 @@
// further.
{
std::lock_guard<std::mutex> mu(*mem_maps_lock_);
- for (auto& pair : *maps_) {
+ for (auto& pair : *gMaps) {
MemMap* const map = pair.second;
if (begin >= reinterpret_cast<uintptr_t>(map->Begin()) &&
end <= reinterpret_cast<uintptr_t>(map->End())) {
@@ -302,8 +307,6 @@
flags |= MAP_FIXED;
}
- File fd;
-
if (use_ashmem) {
if (!kIsTargetBuild) {
// When not on Android (either host or assuming a linux target) ashmem is faked using
@@ -316,15 +319,17 @@
}
}
+ unique_fd fd;
+
+
if (use_ashmem) {
// android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are
// prefixed "dalvik-".
std::string debug_friendly_name("dalvik-");
debug_friendly_name += name;
- fd.Reset(ashmem_create_region(debug_friendly_name.c_str(), page_aligned_byte_count),
- /* check_usage */ false);
+ fd.reset(ashmem_create_region(debug_friendly_name.c_str(), page_aligned_byte_count));
- if (fd.Fd() == -1) {
+ if (fd.get() == -1) {
// We failed to create the ashmem region. Print a warning, but continue
// anyway by creating a true anonymous mmap with an fd of -1. It is
// better to use an unlabelled anonymous map than to fail to create a
@@ -344,7 +349,7 @@
page_aligned_byte_count,
prot,
flags,
- fd.Fd(),
+ fd.get(),
0,
low_4gb);
saved_errno = errno;
@@ -361,7 +366,7 @@
page_aligned_byte_count,
prot,
flags,
- fd.Fd(),
+ fd.get(),
strerror(saved_errno));
}
return nullptr;
@@ -490,15 +495,15 @@
}
}
- // Remove it from maps_.
+ // Remove it from gMaps.
std::lock_guard<std::mutex> mu(*mem_maps_lock_);
bool found = false;
- DCHECK(maps_ != nullptr);
- for (auto it = maps_->lower_bound(base_begin_), end = maps_->end();
+ DCHECK(gMaps != nullptr);
+ for (auto it = gMaps->lower_bound(base_begin_), end = gMaps->end();
it != end && it->first == base_begin_; ++it) {
if (it->second == this) {
found = true;
- maps_->erase(it);
+ gMaps->erase(it);
break;
}
}
@@ -518,10 +523,10 @@
CHECK(base_begin_ != nullptr);
CHECK_NE(base_size_, 0U);
- // Add it to maps_.
+ // Add it to gMaps.
std::lock_guard<std::mutex> mu(*mem_maps_lock_);
- DCHECK(maps_ != nullptr);
- maps_->insert(std::make_pair(base_begin_, this));
+ DCHECK(gMaps != nullptr);
+ gMaps->insert(std::make_pair(base_begin_, this));
}
}
@@ -551,22 +556,21 @@
DCHECK_EQ(tail_base_begin + tail_base_size, old_base_end);
DCHECK_ALIGNED(tail_base_size, kPageSize);
- int int_fd = -1;
+ unique_fd fd;
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
if (use_ashmem) {
// android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are
// prefixed "dalvik-".
std::string debug_friendly_name("dalvik-");
debug_friendly_name += tail_name;
- int_fd = ashmem_create_region(debug_friendly_name.c_str(), tail_base_size);
+ fd.reset(ashmem_create_region(debug_friendly_name.c_str(), tail_base_size));
flags = MAP_PRIVATE | MAP_FIXED;
- if (int_fd == -1) {
+ if (fd.get() == -1) {
*error_msg = StringPrintf("ashmem_create_region failed for '%s': %s",
tail_name, strerror(errno));
return nullptr;
}
}
- File fd(int_fd, /* check_usage */ false);
MEMORY_TOOL_MAKE_UNDEFINED(tail_base_begin, tail_base_size);
// Unmap/map the tail region.
@@ -581,13 +585,17 @@
// calls. Otherwise, libc (or something else) might take this memory
// region. Note this isn't perfect as there's no way to prevent
// other threads to try to take this memory region here.
- uint8_t* actual = reinterpret_cast<uint8_t*>(mmap(tail_base_begin, tail_base_size, tail_prot,
- flags, fd.Fd(), 0));
+ uint8_t* actual = reinterpret_cast<uint8_t*>(mmap(tail_base_begin,
+ tail_base_size,
+ tail_prot,
+ flags,
+ fd.get(),
+ 0));
if (actual == MAP_FAILED) {
PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
*error_msg = StringPrintf("anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0) failed. See process "
"maps in the log.", tail_base_begin, tail_base_size, tail_prot, flags,
- fd.Fd());
+ fd.get());
return nullptr;
}
return new MemMap(tail_name, actual, tail_size, actual, tail_base_size, tail_prot, false);
@@ -662,7 +670,7 @@
}
void MemMap::DumpMapsLocked(std::ostream& os, bool terse) {
- const auto& mem_maps = *maps_;
+ const auto& mem_maps = *gMaps;
if (!terse) {
os << mem_maps;
return;
@@ -722,7 +730,7 @@
bool MemMap::HasMemMap(MemMap* map) {
void* base_begin = map->BaseBegin();
- for (auto it = maps_->lower_bound(base_begin), end = maps_->end();
+ for (auto it = gMaps->lower_bound(base_begin), end = gMaps->end();
it != end && it->first == base_begin; ++it) {
if (it->second == map) {
return true;
@@ -734,8 +742,8 @@
MemMap* MemMap::GetLargestMemMapAt(void* address) {
size_t largest_size = 0;
MemMap* largest_map = nullptr;
- DCHECK(maps_ != nullptr);
- for (auto it = maps_->lower_bound(address), end = maps_->end();
+ DCHECK(gMaps != nullptr);
+ for (auto it = gMaps->lower_bound(address), end = gMaps->end();
it != end && it->first == address; ++it) {
MemMap* map = it->second;
CHECK(map != nullptr);
@@ -753,10 +761,10 @@
return;
}
mem_maps_lock_ = new std::mutex();
- // Not for thread safety, but for the annotation that maps_ is GUARDED_BY(mem_maps_lock_).
+ // Not for thread safety, but for the annotation that gMaps is GUARDED_BY(mem_maps_lock_).
std::lock_guard<std::mutex> mu(*mem_maps_lock_);
- DCHECK(maps_ == nullptr);
- maps_ = new Maps;
+ DCHECK(gMaps == nullptr);
+ gMaps = new Maps;
}
void MemMap::Shutdown() {
@@ -765,11 +773,11 @@
return;
}
{
- // Not for thread safety, but for the annotation that maps_ is GUARDED_BY(mem_maps_lock_).
+ // Not for thread safety, but for the annotation that gMaps is GUARDED_BY(mem_maps_lock_).
std::lock_guard<std::mutex> mu(*mem_maps_lock_);
- DCHECK(maps_ != nullptr);
- delete maps_;
- maps_ = nullptr;
+ DCHECK(gMaps != nullptr);
+ delete gMaps;
+ gMaps = nullptr;
}
delete mem_maps_lock_;
mem_maps_lock_ = nullptr;
@@ -830,17 +838,17 @@
std::lock_guard<std::mutex> mu(*mem_maps_lock_);
for (uintptr_t ptr = next_mem_pos_; ptr < 4 * GB; ptr += kPageSize) {
- // Use maps_ as an optimization to skip over large maps.
+ // Use gMaps as an optimization to skip over large maps.
// Find the first map which is address > ptr.
- auto it = maps_->upper_bound(reinterpret_cast<void*>(ptr));
- if (it != maps_->begin()) {
+ auto it = gMaps->upper_bound(reinterpret_cast<void*>(ptr));
+ if (it != gMaps->begin()) {
auto before_it = it;
--before_it;
// Start at the end of the map before the upper bound.
ptr = std::max(ptr, reinterpret_cast<uintptr_t>(before_it->second->BaseEnd()));
CHECK_ALIGNED(ptr, kPageSize);
}
- while (it != maps_->end()) {
+ while (it != gMaps->end()) {
// How much space do we have until the next map?
size_t delta = reinterpret_cast<uintptr_t>(it->first) - ptr;
// If the space may be sufficient, break out of the loop.
@@ -1001,12 +1009,12 @@
base_size_ = aligned_base_size;
begin_ = aligned_base_begin;
size_ = aligned_base_size;
- DCHECK(maps_ != nullptr);
+ DCHECK(gMaps != nullptr);
if (base_begin < aligned_base_begin) {
- auto it = maps_->find(base_begin);
- CHECK(it != maps_->end()) << "MemMap not found";
- maps_->erase(it);
- maps_->insert(std::make_pair(base_begin_, this));
+ auto it = gMaps->find(base_begin);
+ CHECK(it != gMaps->end()) << "MemMap not found";
+ gMaps->erase(it);
+ gMaps->insert(std::make_pair(base_begin_, this));
}
}
diff --git a/runtime/mem_map.h b/runtime/mem_map.h
index ceb4c33..140877e 100644
--- a/runtime/mem_map.h
+++ b/runtime/mem_map.h
@@ -17,18 +17,14 @@
#ifndef ART_RUNTIME_MEM_MAP_H_
#define ART_RUNTIME_MEM_MAP_H_
-#include "base/mutex.h"
-
-#include <string>
-#include <map>
-#include <mutex>
-
#include <stddef.h>
-#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <sys/types.h>
-#include "base/allocator.h"
-#include "globals.h"
+#include <map>
+#include <mutex>
+#include <string>
+
+#include "android-base/thread_annotations.h"
namespace art {
@@ -180,8 +176,6 @@
static void DumpMaps(std::ostream& os, bool terse = false)
REQUIRES(!MemMap::mem_maps_lock_);
- typedef AllocationTrackingMultiMap<void*, MemMap*, kAllocatorTagMaps> Maps;
-
// Init and Shutdown are NOT thread safe.
// Both may be called multiple times and MemMap objects may be created any
// time after the first call to Init and before the first call to Shutodwn.
@@ -196,6 +190,11 @@
// Align the map by unmapping the unaligned parts at the lower and the higher ends.
void AlignBy(size_t size);
+ // For annotation reasons.
+ static std::mutex* GetMemMapsLock() RETURN_CAPABILITY(mem_maps_lock_) {
+ return nullptr;
+ }
+
private:
MemMap(const std::string& name,
uint8_t* begin,
@@ -245,14 +244,10 @@
static std::mutex* mem_maps_lock_;
- // All the non-empty MemMaps. Use a multimap as we do a reserve-and-divide (eg ElfMap::Load()).
- static Maps* maps_ GUARDED_BY(MemMap::mem_maps_lock_);
-
friend class MemMapTest; // To allow access to base_begin_ and base_size_.
};
std::ostream& operator<<(std::ostream& os, const MemMap& mem_map);
-std::ostream& operator<<(std::ostream& os, const MemMap::Maps& mem_maps);
// Zero and release pages if possible, no requirements on alignments.
void ZeroAndReleasePages(void* address, size_t length);
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index b6f8a17..54d45b1 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 04c80c5..bfbd4df 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 be3b937..5122b37 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"
@@ -96,7 +96,13 @@
}
inline uint32_t Class::GetCopiedMethodsStartOffset() {
- return GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_));
+ // Object::GetFieldShort returns an int16_t value, but
+ // Class::copied_methods_offset_ is an uint16_t value; cast the
+ // latter to int16_t before returning it as an uint32_t value, so
+ // that uint16_t values between 2^15 and 2^16-1 are correctly
+ // handled.
+ return static_cast<uint16_t>(
+ GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_)));
}
inline uint32_t Class::GetDirectMethodsStartOffset() {
@@ -104,7 +110,13 @@
}
inline uint32_t Class::GetVirtualMethodsStartOffset() {
- return GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_));
+ // Object::GetFieldShort returns an int16_t value, but
+ // Class::virtual_method_offset_ is an uint16_t value; cast the
+ // latter to int16_t before returning it as an uint32_t value, so
+ // that uint16_t values between 2^15 and 2^16-1 are correctly
+ // handled.
+ return static_cast<uint16_t>(
+ GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_)));
}
template<VerifyObjectFlags kVerifyFlags>
@@ -343,6 +355,21 @@
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 +811,6 @@
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>();
@@ -823,7 +824,10 @@
}
inline const DexFile& Class::GetDexFile() {
- return *GetDexCache()->GetDexFile();
+ // From-space version is the same as the to-space version since the dex file never changes.
+ // Avoiding the read barrier here is important to prevent recursive AssertToSpaceInvariant issues
+ // from PrettyTypeOf.
+ return *GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetDexFile();
}
inline bool Class::DescriptorEquals(const char* match) {
@@ -939,31 +943,6 @@
}
}
-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();
@@ -1033,6 +1012,12 @@
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 0000000..3d52ead
--- /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 26af488..06ee3d3 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 27aecd5..dfb2788 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -530,10 +530,7 @@
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 @@
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 @@
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 5d3af50..18e22ef 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 71a47f6..a110ed7 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 0000000..0840d16
--- /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 fa4d25a..42b8473 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 @@
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 9938af8..c598fa3 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 @@
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 @@
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 @@
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 c758e54..0c25fa8 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 41231ef..a361772 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 f83645e..baed5f1 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 @@
}
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 0000000..58e7c20
--- /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 0000000..49ab7c2
--- /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 f5b9ab3..6e5fdb7 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"
@@ -281,12 +282,16 @@
}
std::string Object::PrettyTypeOf() {
- if (GetClass() == nullptr) {
+ // From-space version is the same as the to-space version since the dex file never changes.
+ // Avoiding the read barrier here is important to prevent recursive AssertToSpaceInvariant
+ // issues.
+ ObjPtr<mirror::Class> klass = GetClass<kDefaultVerifyFlags, kWithoutReadBarrier>();
+ if (klass == nullptr) {
return "(raw)";
}
std::string temp;
- std::string result(PrettyDescriptor(GetClass()->GetDescriptor(&temp)));
- if (IsClass()) {
+ std::string result(PrettyDescriptor(klass->GetDescriptor(&temp)));
+ if (klass->IsClassClass()) {
result += "<" + PrettyDescriptor(AsClass()->GetDescriptor(&temp)) + ">";
}
return result;
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 417a22d..35a1b73 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -487,11 +487,18 @@
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 3e04bf6..dbec40c 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 d306f9c..d7527d5 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -73,6 +73,13 @@
}
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, 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, 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 f3cb0df..e365b42 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 0e61cf6..0617dae 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -254,10 +254,11 @@
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 @@
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 @@
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 f6a73a8..5c4e242 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 34bbf32..ff4d931 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -46,6 +46,7 @@
#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 836ba81..2eaa8c7 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 381dc7b..4f99947 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 54ab861..a9ba33e 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 96bfd1b..e2b4b82 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 9198964..0fb3903 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 50a554c..b2abc46 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.h b/runtime/oat.h
index 58ea91b..05706252 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,7 +32,7 @@
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- static constexpr uint8_t kOatVersion[] = { '1', '1', '8', '\0' }; // ARM64 Read barriers thunks.
+ static constexpr uint8_t kOatVersion[] = { '1', '1', '9', '\0' }; // Add thread_local_limit.
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index a00674a..4a85d479 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 db6f8ee..a7be73a 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 9b35489..4a738ab 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -897,7 +897,6 @@
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 1390222..6799918 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -615,7 +615,6 @@
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 @@
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 45ac4b7..05a5f5b 100644
--- a/runtime/oat_file_manager.h
+++ b/runtime/oat_file_manager.h
@@ -96,7 +96,6 @@
// 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 bdaad20..0b93b07 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 <unistd.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 "jni_internal.h"
-#include "mirror/string-inl.h"
-#include "native/scoped_fast_native_object_access-inl.h"
-#include "ScopedLocalRef.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 "handle_scope-inl.h"
+#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 "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 521494a..0ec92b7 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 e94c4e6..e0af6e8 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 0671105..180895b 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 66357eb..5544dde 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_method.cc b/runtime/openjdkjvmti/ti_method.cc
index 2adabba..f7e5347 100644
--- a/runtime/openjdkjvmti/ti_method.cc
+++ b/runtime/openjdkjvmti/ti_method.cc
@@ -44,6 +44,7 @@
#include "ScopedLocalRef.h"
#include "thread-inl.h"
#include "thread_list.h"
+#include "ti_phase.h"
namespace openjdkjvmti {
@@ -54,12 +55,14 @@
OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kNativeMethodBind)) {
art::Thread* thread = art::Thread::Current();
+ art::JNIEnvExt* jnienv = thread->GetJniEnv();
ScopedLocalRef<jthread> thread_jni(
- thread->GetJniEnv(), thread->GetJniEnv()->AddLocalReference<jthread>(thread->GetPeer()));
+ jnienv, PhaseUtil::IsLivePhase() ? jnienv->AddLocalReference<jthread>(thread->GetPeer())
+ : nullptr);
art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative);
event_handler->DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>(
thread,
- static_cast<JNIEnv*>(thread->GetJniEnv()),
+ static_cast<JNIEnv*>(jnienv),
thread_jni.get(),
art::jni::EncodeArtMethod(method),
const_cast<void*>(cur_method),
diff --git a/runtime/openjdkjvmti/ti_redefine.cc b/runtime/openjdkjvmti/ti_redefine.cc
index 358bb0f..cca1486 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"
@@ -63,7 +66,7 @@
#include "ti_class_loader.h"
#include "transform.h"
#include "verifier/method_verifier.h"
-#include "verifier/verifier_log_mode.h"
+#include "verifier/verifier_enums.h"
namespace openjdkjvmti {
@@ -1060,7 +1063,7 @@
art::StackHandleScope<2> hs(driver_->self_);
std::string error;
// TODO Make verification log level lower
- art::verifier::MethodVerifier::FailureKind failure =
+ art::verifier::FailureKind failure =
art::verifier::MethodVerifier::VerifyClass(driver_->self_,
dex_file_.get(),
hs.NewHandle(iter.GetNewDexCache()),
@@ -1071,7 +1074,7 @@
/*log_level*/
art::verifier::HardFailLogMode::kLogWarning,
&error);
- bool passes = failure == art::verifier::MethodVerifier::kNoFailure;
+ bool passes = failure == art::verifier::FailureKind::kNoFailure;
if (!passes) {
RecordFailure(ERR(FAILS_VERIFICATION), "Failed to verify class. Error was: " + error);
}
diff --git a/runtime/openjdkjvmti/ti_search.cc b/runtime/openjdkjvmti/ti_search.cc
index f51a98f..ec139f2 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 067c7c1..1ddf04f 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 e5ff090..3dfa633 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 df14333..dd7be11 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 5748475..4e95b01 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/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 72e0500..b866941 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -32,7 +32,6 @@
#include "oat_quick_method_header.h"
#include "stack.h"
#include "stack_map.h"
-#include "verifier/method_verifier.h"
namespace art {
diff --git a/runtime/read_barrier-inl.h b/runtime/read_barrier-inl.h
index c102fb0..d3859b0 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 4ccfb6d..e809ecf 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 87bc7df..e16ef1d 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 2f70ded..1ba4b7b 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 8346550..75c25dd 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 bfe9f9c..0125539 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/runtime.h b/runtime/runtime.h
index 86d8e4f..df13b70 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -657,6 +657,10 @@
void AttachAgent(const std::string& agent_arg);
+ const std::list<ti::Agent>& GetAgents() const {
+ return agents_;
+ }
+
RuntimeCallbacks* GetRuntimeCallbacks();
void InitThreadGroups(Thread* self);
diff --git a/runtime/runtime_options.h b/runtime/runtime_options.h
index 5fcb86e..c509992 100644
--- a/runtime/runtime_options.h
+++ b/runtime/runtime_options.h
@@ -17,13 +17,15 @@
#ifndef ART_RUNTIME_RUNTIME_OPTIONS_H_
#define ART_RUNTIME_RUNTIME_OPTIONS_H_
-#include "base/variant_map.h"
-#include "cmdline_types.h" // TODO: don't need to include this file here
-
-// Map keys
#include <vector>
#include <string>
+
+#include <stdio.h>
+#include <stdarg.h>
+
#include "base/logging.h"
+#include "base/variant_map.h"
+#include "cmdline_types.h" // TODO: don't need to include this file here
#include "jdwp/jdwp.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
@@ -31,9 +33,7 @@
#include "gc/space/large_object_space.h"
#include "arch/instruction_set.h"
#include "jit/profile_saver_options.h"
-#include "verifier/verify_mode.h"
-#include <stdio.h>
-#include <stdarg.h>
+#include "verifier/verifier_enums.h"
namespace art {
diff --git a/runtime/scoped_thread_state_change-inl.h b/runtime/scoped_thread_state_change-inl.h
index c817a9e..ed6e349 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 @@
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 0000000..94354fc
--- /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 5f03741..02b6124 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 @@
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 @@
// 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-inl.h b/runtime/thread-inl.h
index 02a1e4d..aa769fa 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -303,10 +303,6 @@
}
}
-inline size_t Thread::TlabSize() const {
- return tlsPtr_.thread_local_end - tlsPtr_.thread_local_pos;
-}
-
inline mirror::Object* Thread::AllocTlab(size_t bytes) {
DCHECK_GE(TlabSize(), bytes);
++tlsPtr_.thread_local_objects;
diff --git a/runtime/thread.cc b/runtime/thread.cc
index a8a03c7..201701a 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"
@@ -3468,11 +3469,13 @@
}
}
-void Thread::SetTlab(uint8_t* start, uint8_t* end) {
+void Thread::SetTlab(uint8_t* start, uint8_t* end, uint8_t* limit) {
DCHECK_LE(start, end);
+ DCHECK_LE(end, limit);
tlsPtr_.thread_local_start = start;
tlsPtr_.thread_local_pos = tlsPtr_.thread_local_start;
tlsPtr_.thread_local_end = end;
+ tlsPtr_.thread_local_limit = limit;
tlsPtr_.thread_local_objects = 0;
}
diff --git a/runtime/thread.h b/runtime/thread.h
index 4d5d644..5251012 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -1035,10 +1035,24 @@
void ResetQuickAllocEntryPointsForThread(bool is_marking);
// Returns the remaining space in the TLAB.
- size_t TlabSize() const;
+ size_t TlabSize() const {
+ return tlsPtr_.thread_local_end - tlsPtr_.thread_local_pos;
+ }
+
+ // Returns the remaining space in the TLAB if we were to expand it to maximum capacity.
+ size_t TlabRemainingCapacity() const {
+ return tlsPtr_.thread_local_limit - tlsPtr_.thread_local_pos;
+ }
+
+ // Expand the TLAB by a fixed number of bytes. There must be enough capacity to do so.
+ void ExpandTlab(size_t bytes) {
+ tlsPtr_.thread_local_end += bytes;
+ DCHECK_LE(tlsPtr_.thread_local_end, tlsPtr_.thread_local_limit);
+ }
+
// Doesn't check that there is room.
mirror::Object* AllocTlab(size_t bytes);
- void SetTlab(uint8_t* start, uint8_t* end);
+ void SetTlab(uint8_t* start, uint8_t* end, uint8_t* limit);
bool HasTlab() const;
uint8_t* GetTlabStart() {
return tlsPtr_.thread_local_start;
@@ -1451,6 +1465,7 @@
frame_id_to_shadow_frame(nullptr), name(nullptr), pthread_self(0),
last_no_thread_suspension_cause(nullptr), checkpoint_function(nullptr),
thread_local_start(nullptr), thread_local_pos(nullptr), thread_local_end(nullptr),
+ thread_local_limit(nullptr),
thread_local_objects(0), mterp_current_ibase(nullptr), mterp_default_ibase(nullptr),
mterp_alt_ibase(nullptr), thread_local_alloc_stack_top(nullptr),
thread_local_alloc_stack_end(nullptr),
@@ -1577,6 +1592,10 @@
uint8_t* thread_local_pos;
uint8_t* thread_local_end;
+ // Thread local limit is how much we can expand the thread local buffer to, it is greater or
+ // equal to thread_local_end.
+ uint8_t* thread_local_limit;
+
size_t thread_local_objects;
// Entrypoint function pointers.
diff --git a/runtime/ti/agent.cc b/runtime/ti/agent.cc
index 0bba44c..86f5282 100644
--- a/runtime/ti/agent.cc
+++ b/runtime/ti/agent.cc
@@ -72,6 +72,11 @@
}
}
+void* Agent::FindSymbol(const std::string& name) const {
+ CHECK(IsStarted()) << "Cannot find symbols in an unloaded agent library " << this;
+ return dlsym(dlopen_handle_, name.c_str());
+}
+
Agent::LoadError Agent::DoDlOpen(/*out*/std::string* error_msg) {
DCHECK(error_msg != nullptr);
@@ -86,18 +91,15 @@
return kLoadingError;
}
- onload_ = reinterpret_cast<AgentOnLoadFunction>(dlsym(dlopen_handle_,
- AGENT_ON_LOAD_FUNCTION_NAME));
+ onload_ = reinterpret_cast<AgentOnLoadFunction>(FindSymbol(AGENT_ON_LOAD_FUNCTION_NAME));
if (onload_ == nullptr) {
VLOG(agents) << "Unable to find 'Agent_OnLoad' symbol in " << this;
}
- onattach_ = reinterpret_cast<AgentOnLoadFunction>(dlsym(dlopen_handle_,
- AGENT_ON_ATTACH_FUNCTION_NAME));
+ onattach_ = reinterpret_cast<AgentOnLoadFunction>(FindSymbol(AGENT_ON_ATTACH_FUNCTION_NAME));
if (onattach_ == nullptr) {
VLOG(agents) << "Unable to find 'Agent_OnAttach' symbol in " << this;
}
- onunload_= reinterpret_cast<AgentOnUnloadFunction>(dlsym(dlopen_handle_,
- AGENT_ON_UNLOAD_FUNCTION_NAME));
+ onunload_= reinterpret_cast<AgentOnUnloadFunction>(FindSymbol(AGENT_ON_UNLOAD_FUNCTION_NAME));
if (onunload_ == nullptr) {
VLOG(agents) << "Unable to find 'Agent_OnUnload' symbol in " << this;
}
diff --git a/runtime/ti/agent.h b/runtime/ti/agent.h
index 7408aee..b5ecba1 100644
--- a/runtime/ti/agent.h
+++ b/runtime/ti/agent.h
@@ -29,8 +29,14 @@
using AgentOnLoadFunction = jint (*)(JavaVM*, const char*, void*);
using AgentOnUnloadFunction = void (*)(JavaVM*);
+// Agents are native libraries that will be loaded by the runtime for the purpose of
+// instrumentation. They will be entered by Agent_OnLoad or Agent_OnAttach depending on whether the
+// agent is being attached during runtime startup or later.
+//
+// The agent's Agent_OnUnload function will be called during runtime shutdown.
+//
// TODO: consider splitting ti::Agent into command line, agent and shared library handler classes
-
+// TODO Support native-bridge. Currently agents can only be the actual runtime ISA of the device.
class Agent {
public:
enum LoadError {
@@ -56,6 +62,8 @@
return !GetArgs().empty();
}
+ void* FindSymbol(const std::string& name) const;
+
LoadError Load(/*out*/jint* call_res, /*out*/std::string* error_msg) {
VLOG(agents) << "Loading agent: " << name_ << " " << args_;
return DoLoadHelper(false, call_res, error_msg);
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 9ff104b..945f08b 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -16,6 +16,8 @@
#include "vdex_file.h"
+#include <sys/mman.h> // For the PROT_* and MAP_* constants.
+
#include <memory>
#include "base/logging.h"
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 38d151b..2b0c612 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -36,6 +36,7 @@
#include "dex_instruction_visitor.h"
#include "experimental_flags.h"
#include "gc/accounting/card_table-inl.h"
+#include "handle_scope-inl.h"
#include "indenter.h"
#include "intern_table.h"
#include "leb128.h"
@@ -52,7 +53,7 @@
#include "scoped_thread_state_change-inl.h"
#include "utils.h"
#include "verifier_deps.h"
-#include "handle_scope-inl.h"
+#include "verifier_compiler_binding.h"
namespace art {
namespace verifier {
@@ -136,14 +137,14 @@
reg_line->MarkAllRegistersAsConflicts(verifier);
}
-MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self,
- mirror::Class* klass,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- std::string* error) {
+FailureKind MethodVerifier::VerifyClass(Thread* self,
+ mirror::Class* klass,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ std::string* error) {
if (klass->IsVerified()) {
- return kNoFailure;
+ return FailureKind::kNoFailure;
}
bool early_failure = false;
std::string failure_message;
@@ -167,7 +168,7 @@
ClassReference ref(&dex_file, klass->GetDexClassDefIndex());
callbacks->ClassRejected(ref);
}
- return kHardFailure;
+ return FailureKind::kHardFailure;
}
StackHandleScope<2> hs(self);
Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
@@ -188,12 +189,9 @@
return kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod();
}
-static MethodVerifier::FailureKind FailureKindMax(MethodVerifier::FailureKind fk1,
- MethodVerifier::FailureKind fk2) {
- static_assert(MethodVerifier::FailureKind::kNoFailure <
- MethodVerifier::FailureKind::kSoftFailure
- && MethodVerifier::FailureKind::kSoftFailure <
- MethodVerifier::FailureKind::kHardFailure,
+static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) {
+ static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure
+ && FailureKind::kSoftFailure < FailureKind::kHardFailure,
"Unexpected FailureKind order");
return std::max(fk1, fk2);
}
@@ -257,8 +255,8 @@
log_level,
need_precise_constants,
&hard_failure_msg);
- if (result.kind == kHardFailure) {
- if (failure_data.kind == kHardFailure) {
+ if (result.kind == FailureKind::kHardFailure) {
+ if (failure_data.kind == FailureKind::kHardFailure) {
// If we logged an error before, we need a newline.
*error_string += "\n";
} else {
@@ -277,15 +275,15 @@
return failure_data;
}
-MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const DexFile::ClassDef& class_def,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- std::string* error) {
+FailureKind MethodVerifier::VerifyClass(Thread* self,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const DexFile::ClassDef& class_def,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ std::string* error) {
ScopedTrace trace(__FUNCTION__);
// A class must not be abstract and final.
@@ -293,13 +291,13 @@
*error = "Verifier rejected class ";
*error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
*error += ": class is abstract and final.";
- return kHardFailure;
+ return FailureKind::kHardFailure;
}
const uint8_t* class_data = dex_file->GetClassData(class_def);
if (class_data == nullptr) {
// empty class, probably a marker interface
- return kNoFailure;
+ return FailureKind::kNoFailure;
}
ClassDataItemIterator it(*dex_file, class_data);
while (it.HasNextStaticField() || it.HasNextInstanceField()) {
@@ -335,8 +333,8 @@
data1.Merge(data2);
- if (data1.kind == kNoFailure) {
- return kNoFailure;
+ if (data1.kind == FailureKind::kNoFailure) {
+ return FailureKind::kNoFailure;
} else {
if ((data1.types & VERIFY_ERROR_LOCKING) != 0) {
// Print a warning about expected slow-down. Use a string temporary to print one contiguous
@@ -412,7 +410,7 @@
verifier.DumpFailures(VLOG_STREAM(verifier) << "Soft verification failures in "
<< dex_file->PrettyMethod(method_idx) << "\n");
}
- result.kind = kSoftFailure;
+ result.kind = FailureKind::kSoftFailure;
if (method != nullptr &&
!CanCompilerHandleVerificationFailure(verifier.encountered_failure_types_)) {
method->SetDontCompile();
@@ -432,7 +430,7 @@
// code is valid (even the dead and unverified one). As such this is done only for apps.
// (CompilerDriver DCHECKs in VerifyClassVisitor that methods from boot image are
// fully verified).
- result.kind = kSoftFailure;
+ result.kind = FailureKind::kSoftFailure;
}
}
if ((verifier.encountered_failure_types_ & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
@@ -446,7 +444,7 @@
if (UNLIKELY(verifier.have_pending_experimental_failure_)) {
// Failed due to being forced into interpreter. This is ok because
// we just want to skip verification.
- result.kind = kSoftFailure;
+ result.kind = FailureKind::kSoftFailure;
} else {
CHECK(verifier.have_pending_hard_failure_);
if (VLOG_IS_ON(verifier)) {
@@ -477,7 +475,7 @@
*hard_failure_msg =
verifier.failure_messages_[verifier.failure_messages_.size() - 1]->str();
}
- result.kind = kHardFailure;
+ result.kind = FailureKind::kHardFailure;
if (callbacks != nullptr) {
// Let the interested party know that we failed the class.
@@ -3732,7 +3730,7 @@
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 +4135,12 @@
}
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 +4151,11 @@
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.h b/runtime/verifier/method_verifier.h
index 7b67967..26dc15e 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -33,7 +33,7 @@
#include "method_reference.h"
#include "register_line.h"
#include "reg_type_cache.h"
-#include "verifier_log_mode.h"
+#include "verifier_enums.h"
namespace art {
@@ -50,57 +50,6 @@
using RegisterLineArenaUniquePtr = std::unique_ptr<RegisterLine, RegisterLineArenaDelete>;
class RegType;
-/*
- * "Direct" and "virtual" methods are stored independently. The type of call used to invoke the
- * method determines which list we search, and whether we travel up into superclasses.
- *
- * (<clinit>, <init>, and methods declared "private" or "static" are stored in the "direct" list.
- * All others are stored in the "virtual" list.)
- */
-enum MethodType {
- METHOD_UNKNOWN = 0,
- METHOD_DIRECT, // <init>, private
- METHOD_STATIC, // static
- METHOD_VIRTUAL, // virtual
- METHOD_SUPER, // super
- METHOD_INTERFACE, // interface
- METHOD_POLYMORPHIC // polymorphic
-};
-std::ostream& operator<<(std::ostream& os, const MethodType& rhs);
-
-/*
- * An enumeration of problems that can turn up during verification.
- * Both VERIFY_ERROR_BAD_CLASS_SOFT and VERIFY_ERROR_BAD_CLASS_HARD denote failures that cause
- * the entire class to be rejected. However, VERIFY_ERROR_BAD_CLASS_SOFT denotes a soft failure
- * that can potentially be corrected, and the verifier will try again at runtime.
- * VERIFY_ERROR_BAD_CLASS_HARD denotes a hard failure that can't be corrected, and will cause
- * the class to remain uncompiled. Other errors denote verification errors that cause bytecode
- * to be rewritten to fail at runtime.
- */
-enum VerifyError {
- VERIFY_ERROR_BAD_CLASS_HARD = 1, // VerifyError; hard error that skips compilation.
- VERIFY_ERROR_BAD_CLASS_SOFT = 2, // VerifyError; soft error that verifies again at runtime.
-
- VERIFY_ERROR_NO_CLASS = 4, // NoClassDefFoundError.
- VERIFY_ERROR_NO_FIELD = 8, // NoSuchFieldError.
- VERIFY_ERROR_NO_METHOD = 16, // NoSuchMethodError.
- VERIFY_ERROR_ACCESS_CLASS = 32, // IllegalAccessError.
- VERIFY_ERROR_ACCESS_FIELD = 64, // IllegalAccessError.
- VERIFY_ERROR_ACCESS_METHOD = 128, // IllegalAccessError.
- VERIFY_ERROR_CLASS_CHANGE = 256, // IncompatibleClassChangeError.
- VERIFY_ERROR_INSTANTIATION = 512, // InstantiationError.
- // For opcodes that don't have complete verifier support, we need a way to continue
- // execution at runtime without attempting to re-verify (since we know it will fail no
- // matter what). Instead, run as the interpreter in a special "do access checks" mode
- // which will perform verifier-like checking on the fly.
- VERIFY_ERROR_FORCE_INTERPRETER = 1024, // Skip the verification phase at runtime;
- // force the interpreter to do access checks.
- // (sets a soft fail at compile time).
- VERIFY_ERROR_LOCKING = 2048, // Could not guarantee balanced locking. This should be
- // punted to the interpreter with access checks.
-};
-std::ostream& operator<<(std::ostream& os, const VerifyError& rhs);
-
// We don't need to store the register data for many instructions, because we either only need
// it at branch points (for verification) or GC points and branches (for verification +
// type-precise register analysis).
@@ -136,20 +85,6 @@
// The verifier
class MethodVerifier {
public:
- enum FailureKind {
- kNoFailure,
- kSoftFailure,
- kHardFailure,
- };
-
- static bool CanCompilerHandleVerificationFailure(uint32_t encountered_failure_types) {
- constexpr uint32_t unresolved_mask = verifier::VerifyError::VERIFY_ERROR_NO_CLASS
- | verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS
- | verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD
- | verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD;
- return (encountered_failure_types & (~unresolved_mask)) == 0;
- }
-
// Verify a class. Returns "kNoFailure" on success.
static FailureKind VerifyClass(Thread* self,
mirror::Class* klass,
@@ -325,7 +260,7 @@
// Verification result for method(s). Includes a (maximum) failure kind, and (the union of)
// all failure types.
struct FailureData : ValueObject {
- FailureKind kind = kNoFailure;
+ FailureKind kind = FailureKind::kNoFailure;
uint32_t types = 0U;
// Merge src into this. Uses the most severe failure kind, and the union of types.
@@ -869,7 +804,6 @@
DISALLOW_COPY_AND_ASSIGN(MethodVerifier);
};
-std::ostream& operator<<(std::ostream& os, const MethodVerifier::FailureKind& rhs);
} // namespace verifier
} // namespace art
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index be5c18b..d987467 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -23,10 +23,10 @@
#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"
+#include "verifier_enums.h"
namespace art {
namespace verifier {
@@ -41,15 +41,15 @@
// Verify the class
std::string error_msg;
- MethodVerifier::FailureKind failure = MethodVerifier::VerifyClass(
+ FailureKind failure = MethodVerifier::VerifyClass(
self, klass, nullptr, true, HardFailLogMode::kLogWarning, &error_msg);
if (android::base::StartsWith(descriptor, "Ljava/lang/invoke")) {
- ASSERT_TRUE(failure == MethodVerifier::kSoftFailure ||
- failure == MethodVerifier::kNoFailure) << error_msg;
+ ASSERT_TRUE(failure == FailureKind::kSoftFailure ||
+ failure == FailureKind::kNoFailure) << error_msg;
} else {
- ASSERT_TRUE(failure == MethodVerifier::kNoFailure) << error_msg;
+ ASSERT_TRUE(failure == FailureKind::kNoFailure) << error_msg;
}
}
diff --git a/runtime/verifier/verifier_compiler_binding.h b/runtime/verifier/verifier_compiler_binding.h
new file mode 100644
index 0000000..4f9a13f
--- /dev/null
+++ b/runtime/verifier/verifier_compiler_binding.h
@@ -0,0 +1,40 @@
+/*
+ * 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_VERIFIER_VERIFIER_COMPILER_BINDING_H_
+#define ART_RUNTIME_VERIFIER_VERIFIER_COMPILER_BINDING_H_
+
+#include <inttypes.h>
+
+#include "base/macros.h"
+#include "verifier_enums.h"
+
+namespace art {
+namespace verifier {
+
+ALWAYS_INLINE
+static inline bool CanCompilerHandleVerificationFailure(uint32_t encountered_failure_types) {
+ constexpr uint32_t unresolved_mask = verifier::VerifyError::VERIFY_ERROR_NO_CLASS
+ | verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS
+ | verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD
+ | verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD;
+ return (encountered_failure_types & (~unresolved_mask)) == 0;
+}
+
+} // namespace verifier
+} // namespace art
+
+#endif // ART_RUNTIME_VERIFIER_VERIFIER_COMPILER_BINDING_H_
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index 55e7935..122e05f 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -18,10 +18,15 @@
#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 "indenter.h"
#include "leb128.h"
#include "mirror/class-inl.h"
+#include "mirror/class_loader.h"
#include "obj_ptr-inl.h"
#include "runtime.h"
@@ -499,8 +504,8 @@
void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file,
dex::TypeIndex type_idx,
- MethodVerifier::FailureKind failure_kind) {
- if (failure_kind == MethodVerifier::kNoFailure) {
+ FailureKind failure_kind) {
+ if (failure_kind == FailureKind::kNoFailure) {
// We only record classes that did not fully verify at compile time.
return;
}
diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h
index 11750fd..d69e4dc 100644
--- a/runtime/verifier/verifier_deps.h
+++ b/runtime/verifier/verifier_deps.h
@@ -21,17 +21,26 @@
#include <set>
#include <vector>
-#include "art_field.h"
-#include "art_method.h"
#include "base/array_ref.h"
#include "base/mutex.h"
-#include "indenter.h"
+#include "handle.h"
#include "method_resolution_kind.h"
-#include "method_verifier.h" // For MethodVerifier::FailureKind.
#include "obj_ptr.h"
-#include "os.h"
+#include "thread.h"
+#include "verifier_enums.h" // For MethodVerifier::FailureKind.
namespace art {
+
+class ArtField;
+class ArtMethod;
+class DexFile;
+class VariableIndentationOutputStream;
+
+namespace mirror {
+class Class;
+class ClassLoader;
+}
+
namespace verifier {
// Verification dependencies collector class used by the MethodVerifier to record
@@ -59,7 +68,7 @@
// Record the verification status of the class at `type_idx`.
static void MaybeRecordVerificationStatus(const DexFile& dex_file,
dex::TypeIndex type_idx,
- MethodVerifier::FailureKind failure_kind)
+ FailureKind failure_kind)
REQUIRES(!Locks::verifier_deps_lock_);
// Record the outcome `klass` of resolving type `type_idx` from `dex_file`.
diff --git a/runtime/verifier/verifier_enums.h b/runtime/verifier/verifier_enums.h
new file mode 100644
index 0000000..bbdd45d
--- /dev/null
+++ b/runtime/verifier/verifier_enums.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 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_VERIFIER_VERIFIER_ENUMS_H_
+#define ART_RUNTIME_VERIFIER_VERIFIER_ENUMS_H_
+
+#include <stdint.h>
+
+namespace art {
+namespace verifier {
+
+// The mode that the verifier should run as.
+enum class VerifyMode : int8_t {
+ kNone, // Everything is assumed verified.
+ kEnable, // Standard verification, try pre-verifying at compile-time.
+ kSoftFail, // Force a soft fail, punting to the interpreter with access checks.
+};
+
+// The outcome of verification.
+enum class FailureKind {
+ kNoFailure,
+ kSoftFailure,
+ kHardFailure,
+};
+std::ostream& operator<<(std::ostream& os, const FailureKind& rhs);
+
+// How to log hard failures during verification.
+enum class HardFailLogMode {
+ kLogNone, // Don't log hard failures at all.
+ kLogVerbose, // Log with severity VERBOSE.
+ kLogWarning, // Log with severity WARNING.
+ kLogInternalFatal, // Log with severity FATAL_WITHOUT_ABORT
+};
+
+/*
+ * "Direct" and "virtual" methods are stored independently. The type of call used to invoke the
+ * method determines which list we search, and whether we travel up into superclasses.
+ *
+ * (<clinit>, <init>, and methods declared "private" or "static" are stored in the "direct" list.
+ * All others are stored in the "virtual" list.)
+ */
+enum MethodType {
+ METHOD_UNKNOWN = 0,
+ METHOD_DIRECT, // <init>, private
+ METHOD_STATIC, // static
+ METHOD_VIRTUAL, // virtual
+ METHOD_SUPER, // super
+ METHOD_INTERFACE, // interface
+ METHOD_POLYMORPHIC // polymorphic
+};
+std::ostream& operator<<(std::ostream& os, const MethodType& rhs);
+
+/*
+ * An enumeration of problems that can turn up during verification.
+ * Both VERIFY_ERROR_BAD_CLASS_SOFT and VERIFY_ERROR_BAD_CLASS_HARD denote failures that cause
+ * the entire class to be rejected. However, VERIFY_ERROR_BAD_CLASS_SOFT denotes a soft failure
+ * that can potentially be corrected, and the verifier will try again at runtime.
+ * VERIFY_ERROR_BAD_CLASS_HARD denotes a hard failure that can't be corrected, and will cause
+ * the class to remain uncompiled. Other errors denote verification errors that cause bytecode
+ * to be rewritten to fail at runtime.
+ */
+enum VerifyError {
+ VERIFY_ERROR_BAD_CLASS_HARD = 1, // VerifyError; hard error that skips compilation.
+ VERIFY_ERROR_BAD_CLASS_SOFT = 2, // VerifyError; soft error that verifies again at runtime.
+
+ VERIFY_ERROR_NO_CLASS = 4, // NoClassDefFoundError.
+ VERIFY_ERROR_NO_FIELD = 8, // NoSuchFieldError.
+ VERIFY_ERROR_NO_METHOD = 16, // NoSuchMethodError.
+ VERIFY_ERROR_ACCESS_CLASS = 32, // IllegalAccessError.
+ VERIFY_ERROR_ACCESS_FIELD = 64, // IllegalAccessError.
+ VERIFY_ERROR_ACCESS_METHOD = 128, // IllegalAccessError.
+ VERIFY_ERROR_CLASS_CHANGE = 256, // IncompatibleClassChangeError.
+ VERIFY_ERROR_INSTANTIATION = 512, // InstantiationError.
+ // For opcodes that don't have complete verifier support, we need a way to continue
+ // execution at runtime without attempting to re-verify (since we know it will fail no
+ // matter what). Instead, run as the interpreter in a special "do access checks" mode
+ // which will perform verifier-like checking on the fly.
+ VERIFY_ERROR_FORCE_INTERPRETER = 1024, // Skip the verification phase at runtime;
+ // force the interpreter to do access checks.
+ // (sets a soft fail at compile time).
+ VERIFY_ERROR_LOCKING = 2048, // Could not guarantee balanced locking. This should be
+ // punted to the interpreter with access checks.
+};
+std::ostream& operator<<(std::ostream& os, const VerifyError& rhs);
+
+} // namespace verifier
+} // namespace art
+
+#endif // ART_RUNTIME_VERIFIER_VERIFIER_ENUMS_H_
diff --git a/runtime/verifier/verifier_log_mode.h b/runtime/verifier/verifier_log_mode.h
deleted file mode 100644
index e83d174..0000000
--- a/runtime/verifier/verifier_log_mode.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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_VERIFIER_VERIFIER_LOG_MODE_H_
-#define ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
-
-namespace art {
-namespace verifier {
-
-enum class HardFailLogMode {
- kLogNone, // Don't log hard failures at all.
- kLogVerbose, // Log with severity VERBOSE.
- kLogWarning, // Log with severity WARNING.
- kLogInternalFatal, // Log with severity FATAL_WITHOUT_ABORT
-};
-
-} // namespace verifier
-} // namespace art
-
-#endif // ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
diff --git a/runtime/verifier/verify_mode.h b/runtime/verifier/verify_mode.h
deleted file mode 100644
index bea4378..0000000
--- a/runtime/verifier/verify_mode.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2015 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_VERIFIER_VERIFY_MODE_H_
-#define ART_RUNTIME_VERIFIER_VERIFY_MODE_H_
-
-#include <stdint.h>
-
-namespace art {
-namespace verifier {
-
-// The mode that the verifier should run as.
-enum class VerifyMode : int8_t {
- kNone, // Everything is assumed verified.
- kEnable, // Standard verification, try pre-verifying at compile-time.
- kSoftFail, // Force a soft fail, punting to the interpreter with access checks.
-};
-
-} // namespace verifier
-} // namespace art
-
-#endif // ART_RUNTIME_VERIFIER_VERIFY_MODE_H_
diff --git a/runtime/zip_archive.cc b/runtime/zip_archive.cc
index 416873f..0d0d5c7 100644
--- a/runtime/zip_archive.cc
+++ b/runtime/zip_archive.cc
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <stdio.h>
+#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/test/161-final-abstract-class/expected.txt b/test/161-final-abstract-class/expected.txt
new file mode 100644
index 0000000..1e63584
--- /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 0000000..2b7bee7
--- /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 0000000..796fc40
--- /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 0000000..fa38f59
--- /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 0000000..2452490
--- /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 6c73d7d..9ba05bc 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/550-checker-multiply-accumulate/src/Main.java b/test/550-checker-multiply-accumulate/src/Main.java
index 09376a2..810f0fa 100644
--- a/test/550-checker-multiply-accumulate/src/Main.java
+++ b/test/550-checker-multiply-accumulate/src/Main.java
@@ -424,6 +424,88 @@
return - (left * right);
}
+ /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier_arm64 (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: VecAdd loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier_arm64 (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: VecMultiplyAccumulate kind:Add loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START-ARM64: void Main.SimdMulAdd(int[], int[]) instruction_simplifier_arm64 (after)
+ /// CHECK-NOT: VecMull
+ /// CHECK-NOT: VecAdd
+ public static void SimdMulAdd(int[] array1, int[] array2) {
+ for (int j = 0; j < 100; j++) {
+ array2[j] += 12345 * array1[j];
+ }
+ }
+
+ /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier_arm64 (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: VecSub loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier_arm64 (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: VecMultiplyAccumulate kind:Sub loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START-ARM64: void Main.SimdMulSub(int[], int[]) instruction_simplifier_arm64 (after)
+ /// CHECK-NOT: VecMull
+ /// CHECK-NOT: VecSub
+ public static void SimdMulSub(int[] array1, int[] array2) {
+ for (int j = 0; j < 100; j++) {
+ array2[j] -= 12345 * array1[j];
+ }
+ }
+
+ /// CHECK-START-ARM64: void Main.SimdMulMultipleUses(int[], int[]) instruction_simplifier_arm64 (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: VecMul loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: VecSub loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START-ARM64: void Main.SimdMulMultipleUses(int[], int[]) instruction_simplifier_arm64 (after)
+ /// CHECK-NOT: VecMultiplyAccumulate
+ public static void SimdMulMultipleUses(int[] array1, int[] array2) {
+ for (int j = 0; j < 100; j++) {
+ int temp = 12345 * array1[j];
+ array2[j] -= temp;
+ array1[j] = temp;
+ }
+ }
+
+ public static final int ARRAY_SIZE = 1000;
+
+ public static void initArray(int[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = i;
+ }
+ }
+
+ public static int calcArraySum(int[] array) {
+ int sum = 0;
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ sum += array[i];
+ }
+ return sum;
+ }
+
+ public static void testSimdMultiplyAccumulate() {
+ int[] array1 = new int[ARRAY_SIZE];
+ int[] array2 = new int[ARRAY_SIZE];
+
+ initArray(array1);
+ initArray(array2);
+ SimdMulSub(array1, array2);
+ assertIntEquals(-60608250, calcArraySum(array2));
+
+ initArray(array1);
+ initArray(array2);
+ SimdMulAdd(array1, array2);
+ assertIntEquals(61607250, calcArraySum(array2));
+ }
+
public static void main(String[] args) {
assertIntEquals(7, $opt$noinline$mulAdd(1, 2, 3));
assertLongEquals(-26, $opt$noinline$mulSub(4, 5, 6));
@@ -433,5 +515,7 @@
assertLongEquals(-225, $opt$noinline$mulMinusOne(15, 16));
assertIntEquals(-306, $opt$noinline$mulNeg(17, 18));
assertLongEquals(-380, $opt$noinline$mulNeg(19, 20));
+
+ testSimdMultiplyAccumulate();
}
}
diff --git a/test/647-jni-get-field-id/expected.txt b/test/647-jni-get-field-id/expected.txt
new file mode 100644
index 0000000..9506dd7
--- /dev/null
+++ b/test/647-jni-get-field-id/expected.txt
@@ -0,0 +1,26 @@
+JNI_OnLoad called
+getFieldId(class TestClass, "intField", "I")
+Result: true
+getFieldId(class TestClass, "intField", "int")
+Caught java.lang.NoSuchFieldError
+ caused by java.lang.NoClassDefFoundError
+getFieldId(class TestClass, "intField", "Lint;")
+Caught java.lang.NoSuchFieldError
+ caused by java.lang.ClassNotFoundException
+getFieldId(class TestClass, "stringField", "I")
+Caught java.lang.NoSuchFieldError
+getFieldId(class TestClass, "stringField", "Ljava/lang/String;")
+Result: true
+getFieldId(class TestClass, "stringField", "java/lang/String")
+Caught java.lang.NoSuchFieldError
+ caused by java.lang.NoClassDefFoundError
+getFieldId(class TestClass, "stringField", "Ljava.lang.String;")
+Caught java.lang.NoSuchFieldError
+ caused by java.lang.NoClassDefFoundError
+getFieldId(class TestClass, "stringField", "java.lang.String")
+Caught java.lang.NoSuchFieldError
+ caused by java.lang.NoClassDefFoundError
+Test that MyClassLoader.loadClass("Bad.Class") shall not be called.
+ Error message for Bad/Class: Invalid descriptor: Bad/Class.
+ Error message for Bad.Class: Invalid descriptor: Bad.Class.
+ Error message for LBad.Class;: Invalid descriptor: LBad.Class;.
diff --git a/test/647-jni-get-field-id/get_field_id.cc b/test/647-jni-get-field-id/get_field_id.cc
new file mode 100644
index 0000000..2056cfb
--- /dev/null
+++ b/test/647-jni-get-field-id/get_field_id.cc
@@ -0,0 +1,43 @@
+/*
+ * 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 "jni.h"
+
+#include "ScopedUtfChars.h"
+
+namespace art {
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_getFieldId(JNIEnv* env,
+ jclass,
+ jclass cls,
+ jstring name,
+ jstring signature) {
+ ScopedUtfChars name_chars(env, name);
+ if (name_chars.c_str() == nullptr) {
+ return false;
+ }
+ ScopedUtfChars signature_chars(env, signature);
+ if (signature_chars.c_str() == nullptr) {
+ return false;
+ }
+ jfieldID field_id = env->GetFieldID(cls, name_chars.c_str(), signature_chars.c_str());
+ if (field_id == nullptr) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace art
diff --git a/test/647-jni-get-field-id/info.txt b/test/647-jni-get-field-id/info.txt
new file mode 100644
index 0000000..00a2b20
--- /dev/null
+++ b/test/647-jni-get-field-id/info.txt
@@ -0,0 +1 @@
+Test for native calls to JNI GetFieldID() with odd signatures.
diff --git a/test/647-jni-get-field-id/src/DefiningLoader.java b/test/647-jni-get-field-id/src/DefiningLoader.java
new file mode 100644
index 0000000..8597c11a
--- /dev/null
+++ b/test/647-jni-get-field-id/src/DefiningLoader.java
@@ -0,0 +1,239 @@
+/*
+ * 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.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * A class loader with atypical behavior: we try to load a private
+ * class implementation before asking the system or boot loader. This
+ * is used to create multiple classes with identical names in a single VM.
+ *
+ * If DexFile is available, we use that; if not, we assume we're not in
+ * Dalvik and instantiate the class with defineClass().
+ *
+ * The location of the DEX files and class data is dependent upon the
+ * test framework.
+ */
+public class DefiningLoader extends ClassLoader {
+ static {
+ // For JVM, register as parallel capable.
+ // Android treats all class loaders as parallel capable and makes this a no-op.
+ registerAsParallelCapable();
+ }
+
+ /* this is where the .class files live */
+ static final String CLASS_PATH1 = "classes/";
+ static final String CLASS_PATH2 = "classes2/";
+
+ /* this is the DEX/Jar file */
+ static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/647-jni-get-field-id.jar";
+
+ /* on Dalvik, this is a DexFile; otherwise, it's null */
+ private Class<?> mDexClass;
+
+ private Object mDexFile;
+
+ /**
+ * Construct DefiningLoader, grabbing a reference to the DexFile class
+ * if we're running under Dalvik.
+ */
+ public DefiningLoader(ClassLoader parent) {
+ super(parent);
+
+ try {
+ mDexClass = parent.loadClass("dalvik.system.DexFile");
+ } catch (ClassNotFoundException cnfe) {
+ // ignore -- not running Dalvik
+ }
+ }
+
+ /**
+ * Finds the class with the specified binary name.
+ *
+ * We search for a file in CLASS_PATH or pull an entry from DEX_FILE.
+ * If we don't find a match, we throw an exception.
+ */
+ protected Class<?> findClass(String name) throws ClassNotFoundException
+ {
+ if (mDexClass != null) {
+ return findClassDalvik(name);
+ } else {
+ return findClassNonDalvik(name);
+ }
+ }
+
+ /**
+ * Finds the class with the specified binary name, from a DEX file.
+ */
+ private Class<?> findClassDalvik(String name)
+ throws ClassNotFoundException {
+
+ if (mDexFile == null) {
+ synchronized (DefiningLoader.class) {
+ Constructor<?> ctor;
+ /*
+ * Construct a DexFile object through reflection.
+ */
+ try {
+ ctor = mDexClass.getConstructor(String.class);
+ } catch (NoSuchMethodException nsme) {
+ throw new ClassNotFoundException("getConstructor failed",
+ nsme);
+ }
+
+ try {
+ mDexFile = ctor.newInstance(DEX_FILE);
+ } catch (InstantiationException ie) {
+ throw new ClassNotFoundException("newInstance failed", ie);
+ } catch (IllegalAccessException iae) {
+ throw new ClassNotFoundException("newInstance failed", iae);
+ } catch (InvocationTargetException ite) {
+ throw new ClassNotFoundException("newInstance failed", ite);
+ }
+ }
+ }
+
+ /*
+ * Call DexFile.loadClass(String, ClassLoader).
+ */
+ Method meth;
+
+ try {
+ meth = mDexClass.getMethod("loadClass", String.class, ClassLoader.class);
+ } catch (NoSuchMethodException nsme) {
+ throw new ClassNotFoundException("getMethod failed", nsme);
+ }
+
+ try {
+ meth.invoke(mDexFile, name, this);
+ } catch (IllegalAccessException iae) {
+ throw new ClassNotFoundException("loadClass failed", iae);
+ } catch (InvocationTargetException ite) {
+ throw new ClassNotFoundException("loadClass failed",
+ ite.getCause());
+ }
+
+ return null;
+ }
+
+ /**
+ * Finds the class with the specified binary name, from .class files.
+ */
+ private Class<?> findClassNonDalvik(String name)
+ throws ClassNotFoundException {
+
+ String[] pathNames = { CLASS_PATH1 + name + ".class", CLASS_PATH2 + name + ".class" };
+
+ String pathName = null;
+ RandomAccessFile raf = null;
+
+ for (String pn : pathNames) {
+ pathName = pn;
+ try {
+ //System.out.println("--- Defining: looking for " + pathName);
+ raf = new RandomAccessFile(new File(pathName), "r");
+ break;
+ } catch (FileNotFoundException fnfe) {
+ }
+ }
+ if (raf == null) {
+ throw new ClassNotFoundException("Not found: " + pathNames[0] + ":" + pathNames[1]);
+ }
+
+ /* read the entire file in */
+ byte[] fileData;
+ try {
+ fileData = new byte[(int) raf.length()];
+ raf.readFully(fileData);
+ } catch (IOException ioe) {
+ throw new ClassNotFoundException("Read error: " + pathName);
+ } finally {
+ try {
+ raf.close();
+ } catch (IOException ioe) {
+ // drop
+ }
+ }
+
+ /* create the class */
+ //System.out.println("--- Defining: defining " + name);
+ try {
+ return defineClass(name, fileData, 0, fileData.length);
+ } catch (Throwable th) {
+ throw new ClassNotFoundException("defineClass failed", th);
+ }
+ }
+
+ /**
+ * Load a class.
+ *
+ * Normally a class loader wouldn't override this, but we want our
+ * version of the class to take precedence over an already-loaded
+ * version.
+ *
+ * We still want the system classes (e.g. java.lang.Object) from the
+ * bootstrap class loader.
+ */
+ synchronized protected Class<?> loadClass(String name, boolean resolve)
+ throws ClassNotFoundException
+ {
+ Class<?> res;
+
+ /*
+ * 1. Invoke findLoadedClass(String) to check if the class has
+ * already been loaded.
+ *
+ * This doesn't change.
+ */
+ res = findLoadedClass(name);
+ if (res != null) {
+ // System.out.println("FancyLoader.loadClass: " + name + " already loaded");
+ if (resolve)
+ resolveClass(res);
+ return res;
+ }
+
+ /*
+ * 3. Invoke the findClass(String) method to find the class.
+ */
+ try {
+ res = findClass(name);
+ if (resolve)
+ resolveClass(res);
+ }
+ catch (ClassNotFoundException e) {
+ // we couldn't find it, so eat the exception and keep going
+ }
+
+ /*
+ * 2. Invoke the loadClass method on the parent class loader. If
+ * the parent loader is null the class loader built-in to the
+ * virtual machine is used, instead.
+ *
+ * (Since we're not in java.lang, we can't actually invoke the
+ * parent's loadClass() method, but we passed our parent to the
+ * super-class which can take care of it for us.)
+ */
+ res = super.loadClass(name, resolve); // returns class or throws
+ return res;
+ }
+}
diff --git a/test/647-jni-get-field-id/src/Main.java b/test/647-jni-get-field-id/src/Main.java
new file mode 100644
index 0000000..590ee8a
--- /dev/null
+++ b/test/647-jni-get-field-id/src/Main.java
@@ -0,0 +1,106 @@
+/*
+ * 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) {
+ System.loadLibrary(args[0]);
+
+ testGetFieldId(TestClass.class, "intField", "I");
+ testGetFieldId(TestClass.class, "intField", "int");
+ testGetFieldId(TestClass.class, "intField", "Lint;");
+ testGetFieldId(TestClass.class, "stringField", "I");
+ testGetFieldId(TestClass.class, "stringField", "Ljava/lang/String;");
+ testGetFieldId(TestClass.class, "stringField", "java/lang/String");
+ testGetFieldId(TestClass.class, "stringField", "Ljava.lang.String;");
+ testGetFieldId(TestClass.class, "stringField", "java.lang.String");
+
+ try {
+ Method get = Main.class.getDeclaredMethod("getFieldId",
+ Class.class,
+ String.class,
+ String.class);
+ MyClassLoader loader = new MyClassLoader(Main.class.getClassLoader());
+ Class<?> otherMain = Class.forName("Main", true, loader);
+ Method m = otherMain.getDeclaredMethod("testClassLoading", Method.class);
+ m.invoke(null, get);
+ } catch (Throwable t) {
+ t.printStackTrace(System.out);
+ }
+ }
+
+ public static void testClassLoading(Method get) throws Exception {
+ System.out.println("Test that MyClassLoader.loadClass(\"Bad.Class\") shall not be called.");
+ String[] bad_class_names = { "Bad/Class", "Bad.Class", "LBad.Class;" };
+ for (String signature : bad_class_names) {
+ try {
+ get.invoke(null, TestClass.class, "bogus", signature);
+ System.out.println("FAIL!");
+ } catch (InvocationTargetException ite) {
+ if (!(ite.getCause() instanceof NoSuchFieldError) ||
+ !(ite.getCause().getCause() instanceof NoClassDefFoundError)) {
+ throw ite;
+ }
+ NoClassDefFoundError ncdfe = (NoClassDefFoundError) ite.getCause().getCause();
+ System.out.println(" Error message for " + signature + ": " + ncdfe.getMessage());
+ }
+ }
+ }
+
+ public static void testGetFieldId(Class<?> cls, String name, String signature) {
+ System.out.println("getFieldId(" + cls + ", \"" + name + "\", \"" + signature + "\")");
+ try {
+ boolean result = getFieldId(cls, name, signature);
+ System.out.println("Result: " + result);
+ } catch (Throwable t) {
+ System.out.println("Caught " + DescribeThrowable(t));
+ for (Throwable cause = t.getCause(); cause != null; cause = cause.getCause()) {
+ System.out.println(" caused by " + DescribeThrowable(cause));
+ }
+ }
+ }
+
+ public static String DescribeThrowable(Throwable t) {
+ return PRINT_MESSAGE ? t.getClass().getName() + ": " + t.getMessage()
+ : t.getClass().getName();
+ }
+
+ public static native boolean getFieldId(Class<?> cls, String name, String signature);
+
+ // Set to true to see actual messages.
+ public static final boolean PRINT_MESSAGE = false;
+}
+
+class TestClass {
+ public int intField;
+ public String stringField;
+}
+
+class MyClassLoader extends DefiningLoader {
+ public MyClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ public Class<?> loadClass(String name) throws ClassNotFoundException
+ {
+ if (name.equals("Bad.Class")) {
+ throw new Error("findClass(\"Bad.Class\")");
+ }
+ return super.loadClass(name);
+ }
+}
diff --git a/test/647-sinking-catch/expected.txt b/test/647-sinking-catch/expected.txt
new file mode 100644
index 0000000..b2cde18
--- /dev/null
+++ b/test/647-sinking-catch/expected.txt
@@ -0,0 +1 @@
+Three
diff --git a/test/647-sinking-catch/info.txt b/test/647-sinking-catch/info.txt
new file mode 100644
index 0000000..7a8c6a9
--- /dev/null
+++ b/test/647-sinking-catch/info.txt
@@ -0,0 +1,2 @@
+Regression test for the code sinking optimization, which used
+to incorrectly use catch phis.
diff --git a/test/647-sinking-catch/smali/TestCase.smali b/test/647-sinking-catch/smali/TestCase.smali
new file mode 100644
index 0000000..49a3060
--- /dev/null
+++ b/test/647-sinking-catch/smali/TestCase.smali
@@ -0,0 +1,35 @@
+# 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 public LTestCase;
+.super Ljava/lang/Object;
+
+.method public static foo()V
+ .registers 6
+ new-instance v0, Ljava/lang/Exception;
+ invoke-direct {v0}, Ljava/lang/Exception;-><init>()V
+ const-string v1, "Zero"
+ :try_start
+ const-string v1, "One"
+ const-string v1, "Two"
+ const-string v1, "Three"
+ throw v0
+ :try_end
+ .catchall {:try_start .. :try_end} :catch_all
+
+ :catch_all
+ sget-object v5, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ invoke-virtual {v5, v1}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+ throw v0
+.end method
diff --git a/test/647-sinking-catch/src/Main.java b/test/647-sinking-catch/src/Main.java
new file mode 100644
index 0000000..0e59056
--- /dev/null
+++ b/test/647-sinking-catch/src/Main.java
@@ -0,0 +1,38 @@
+/*
+ * 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 testMethod(String method) throws Exception {
+ Class<?> c = Class.forName("TestCase");
+ Method m = c.getMethod(method);
+
+ Object[] arguments = new Object[] { };
+ try {
+ m.invoke(null, arguments);
+ throw new Error();
+ } catch (InvocationTargetException e) {
+ // expected
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ testMethod("foo");
+ }
+}
diff --git a/test/648-many-direct-methods/build b/test/648-many-direct-methods/build
new file mode 100755
index 0000000..7e888e5
--- /dev/null
+++ b/test/648-many-direct-methods/build
@@ -0,0 +1,25 @@
+#! /bin/bash
+#
+# Copyright 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.
+
+# Exit on a failure.
+set -e
+
+mkdir -p ./src
+
+# Generate the Java file or fail.
+./util-src/generate_java.py ./src
+
+./default-build "$@"
diff --git a/test/648-many-direct-methods/expected.txt b/test/648-many-direct-methods/expected.txt
new file mode 100644
index 0000000..b0aad4d
--- /dev/null
+++ b/test/648-many-direct-methods/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/648-many-direct-methods/info.txt b/test/648-many-direct-methods/info.txt
new file mode 100644
index 0000000..a65ab80
--- /dev/null
+++ b/test/648-many-direct-methods/info.txt
@@ -0,0 +1,2 @@
+Regression test checking that the runtime can handle a huge number of
+direct methods (b/33650497).
diff --git a/test/648-many-direct-methods/util-src/generate_java.py b/test/648-many-direct-methods/util-src/generate_java.py
new file mode 100755
index 0000000..6cae868
--- /dev/null
+++ b/test/648-many-direct-methods/util-src/generate_java.py
@@ -0,0 +1,137 @@
+#! /usr/bin/python3
+#
+# 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.
+
+"""
+Generate Java test files for test 648-many-direct-methods.
+"""
+
+import os
+import sys
+from pathlib import Path
+
+BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+if BUILD_TOP is None:
+ print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
+ sys.exit(1)
+
+# Allow us to import utils and mixins.
+sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
+
+from testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks
+import testgen.mixins as mixins
+
+class MainClass(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin):
+ """
+ A Main.java file containing the Main class and the main function. It will run
+ all the test functions we have.
+ """
+
+ MAIN_CLASS_TEMPLATE = """{copyright}
+public class Main {{
+{main_func}
+{test_groups}
+
+}}"""
+
+ MAIN_FUNCTION_TEMPLATE = """
+ public static void main(String[] args) {
+ System.out.println("passed");
+ }"""
+
+ def __init__(self):
+ """
+ Initialize this MainClass. We start out with no tests.
+ """
+ self.tests = set()
+
+ def add_test_method(self, num):
+ """
+ Add test method number 'num'
+ """
+ self.tests.add(TestMethod(num))
+
+ def get_name(self):
+ """
+ Get the name of this class
+ """
+ return "Main"
+
+ def __str__(self):
+ """
+ Print the MainClass Java code.
+ """
+ all_tests = sorted(self.tests)
+ test_groups = ""
+ for t in all_tests:
+ test_groups += str(t)
+ main_func = self.MAIN_FUNCTION_TEMPLATE
+
+ return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright("java"),
+ main_func = main_func,
+ test_groups = test_groups)
+
+class TestMethod(mixins.Named, mixins.NameComparableMixin):
+ """
+ A function that represents a test method. Should only be
+ constructed by MainClass.add_test_method.
+ """
+
+ TEST_FUNCTION_TEMPLATE = """
+ public static void {fname}() {{}}"""
+
+ def __init__(self, farg):
+ """
+ Initialize a test method for the given argument.
+ """
+ self.farg = farg
+
+ def get_name(self):
+ """
+ Get the name of this test method.
+ """
+ return "method{:05d}".format(self.farg)
+
+ def __str__(self):
+ """
+ Print the Java code of this test method.
+ """
+ return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name())
+
+# Number of generated test methods. This number has been chosen to
+# make sure the number of direct methods in class Main is greater or
+# equal to 2^16, and thus requires an *unsigned* 16-bit (short)
+# integer to be represented (b/33650497).
+NUM_TEST_METHODS = 32768
+
+def create_test_file():
+ """
+ Creates the object representing the test file. It just needs to be dumped.
+ """
+ mc = MainClass()
+ for i in range(1, NUM_TEST_METHODS + 1):
+ mc.add_test_method(i)
+ return mc
+
+def main(argv):
+ java_dir = Path(argv[1])
+ if not java_dir.exists() or not java_dir.is_dir():
+ print("{} is not a valid Java dir".format(java_dir), file=sys.stderr)
+ sys.exit(1)
+ mainclass = create_test_file()
+ mainclass.dump(java_dir)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/test/900-hello-plugin/load_unload.cc b/test/900-hello-plugin/load_unload.cc
index 290997a..19312b4 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/901-hello-ti-agent/src/art/Test901.java b/test/901-hello-ti-agent/src/art/Test901.java
index 26f7399..eef2188 100644
--- a/test/901-hello-ti-agent/src/art/Test901.java
+++ b/test/901-hello-ti-agent/src/art/Test901.java
@@ -18,8 +18,6 @@
public class Test901 {
public static void run() {
- Main.bindAgentJNIForClass(Test901.class);
-
System.out.println("Hello, world!");
if (checkLivePhase()) {
diff --git a/test/902-hello-transformation/src/art/Main.java b/test/902-hello-transformation/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/902-hello-transformation/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/902-hello-transformation/src/art/Redefinition.java b/test/902-hello-transformation/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/902-hello-transformation/src/art/Redefinition.java
+++ b/test/902-hello-transformation/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/903-hello-tagging/src/art/Test903.java b/test/903-hello-tagging/src/art/Test903.java
index 1691a94..49645dd 100644
--- a/test/903-hello-tagging/src/art/Test903.java
+++ b/test/903-hello-tagging/src/art/Test903.java
@@ -22,8 +22,6 @@
public class Test903 {
public static void run() {
- Main.bindAgentJNIForClass(Test903.class);
-
doTest();
testGetTaggedObjects();
testTags();
diff --git a/test/904-object-allocation/src/art/Main.java b/test/904-object-allocation/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/904-object-allocation/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/904-object-allocation/src/art/Test904.java b/test/904-object-allocation/src/art/Test904.java
index 70a4b98..fda8985 100644
--- a/test/904-object-allocation/src/art/Test904.java
+++ b/test/904-object-allocation/src/art/Test904.java
@@ -21,8 +21,6 @@
public class Test904 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test904.class);
-
// Use a list to ensure objects must be allocated.
ArrayList<Object> l = new ArrayList<>(100);
diff --git a/test/905-object-free/src/art/Test905.java b/test/905-object-free/src/art/Test905.java
index 1ed7a0e..62b6e62 100644
--- a/test/905-object-free/src/art/Test905.java
+++ b/test/905-object-free/src/art/Test905.java
@@ -21,7 +21,6 @@
public class Test905 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test905.class);
doTest();
}
diff --git a/test/906-iterate-heap/src/art/Test906.java b/test/906-iterate-heap/src/art/Test906.java
index feebf9c..fe18e38 100644
--- a/test/906-iterate-heap/src/art/Test906.java
+++ b/test/906-iterate-heap/src/art/Test906.java
@@ -21,7 +21,6 @@
public class Test906 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test906.class);
doTest();
}
diff --git a/test/907-get-loaded-classes/src/art/Main.java b/test/907-get-loaded-classes/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/907-get-loaded-classes/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/907-get-loaded-classes/src/art/Test907.java b/test/907-get-loaded-classes/src/art/Test907.java
index d654428..df9ce7a 100644
--- a/test/907-get-loaded-classes/src/art/Test907.java
+++ b/test/907-get-loaded-classes/src/art/Test907.java
@@ -22,7 +22,6 @@
public class Test907 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test907.class);
doTest();
}
diff --git a/test/908-gc-start-finish/src/art/Main.java b/test/908-gc-start-finish/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/908-gc-start-finish/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/908-gc-start-finish/src/art/Test908.java b/test/908-gc-start-finish/src/art/Test908.java
index ceaa98c..db84a6c 100644
--- a/test/908-gc-start-finish/src/art/Test908.java
+++ b/test/908-gc-start-finish/src/art/Test908.java
@@ -20,7 +20,6 @@
public class Test908 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test908.class);
doTest();
}
diff --git a/test/909-attach-agent/src/art/Main.java b/test/909-attach-agent/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/909-attach-agent/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/910-methods/src/art/Main.java b/test/910-methods/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/910-methods/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/910-methods/src/art/Test910.java b/test/910-methods/src/art/Test910.java
index aa6d13a..e1da277 100644
--- a/test/910-methods/src/art/Test910.java
+++ b/test/910-methods/src/art/Test910.java
@@ -22,7 +22,6 @@
public class Test910 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test910.class);
doTest();
}
diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt
index 2318414..8510ff9 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 @@
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 25
---------
- 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 @@
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 25
---------
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 @@
baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
From bottom
---------
- main ([Ljava/lang/String;)V 0 19
+ run ()V 0 25
---------
+ 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 25
---------
+ 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 @@
Signal Catcher
---------
-main
+Test911
---------
+main
+<not printed>
+---------
AllTraces Thread 0
wait ()V -1 -2
printOrWait (IILart/ControlData;)V 24 47
@@ -356,14 +357,16 @@
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 37
---------
+main
+<not printed>
+---------
AllTraces Thread 0
wait ()V -1 -2
printOrWait (IILart/ControlData;)V 24 47
@@ -589,18 +592,23 @@
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 37
+---------
+main
+<not printed>
########################################
### Other select threads (suspended) ###
########################################
---------
+Test911
+
+---------
ThreadListTraces Thread 0
---------
@@ -616,55 +624,58 @@
ThreadListTraces Thread 8
---------
-main
-
----------
-ThreadListTraces Thread 0
- wait ()V -1 -2
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-ThreadListTraces Thread 2
- wait ()V -1 -2
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-ThreadListTraces Thread 4
- wait ()V -1 -2
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-ThreadListTraces Thread 6
- wait ()V -1 -2
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-ThreadListTraces Thread 8
- wait ()V -1 -2
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- 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
+ run ()V 32 41
+
+---------
+ThreadListTraces Thread 0
+ wait ()V -1 -2
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+ThreadListTraces Thread 2
+ wait ()V -1 -2
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+ThreadListTraces Thread 4
+ wait ()V -1 -2
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+ThreadListTraces Thread 6
+ wait ()V -1 -2
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+ThreadListTraces Thread 8
+ wait ()V -1 -2
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+Test911
+ getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
+ printList ([Ljava/lang/Thread;I)V 0 68
+ doTest ()V 121 56
+ run ()V 32 41
---------
ThreadListTraces Thread 0
@@ -771,25 +782,16 @@
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/Main.java b/test/911-get-stack-trace/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/911-get-stack-trace/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/911-get-stack-trace/src/art/PrintThread.java b/test/911-get-stack-trace/src/art/PrintThread.java
index de1da9c..f50a66b 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 @@
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 @@
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 @@
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 71a5196..5774546 100644
--- a/test/911-get-stack-trace/src/art/Test911.java
+++ b/test/911-get-stack-trace/src/art/Test911.java
@@ -18,32 +18,38 @@
public class Test911 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(AllTraces.class);
- Main.bindAgentJNIForClass(Frames.class);
- Main.bindAgentJNIForClass(PrintThread.class);
- Main.bindAgentJNIForClass(ThreadListTraces.class);
+ Thread t = new Thread("Test911") {
+ @Override
+ public void run() {
+ try {
+ SameThread.doTest();
- 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/912-classes/src/art/Test912.java b/test/912-classes/src/art/Test912.java
index f3ff2b0..9896eac 100644
--- a/test/912-classes/src/art/Test912.java
+++ b/test/912-classes/src/art/Test912.java
@@ -25,7 +25,6 @@
public class Test912 {
public static void run() throws Exception {
- art.Main.bindAgentJNIForClass(Test912.class);
doTest();
}
diff --git a/test/912-classes/src/art/Test912Art.java b/test/912-classes/src/art/Test912Art.java
index e438473..6da3cad 100644
--- a/test/912-classes/src/art/Test912Art.java
+++ b/test/912-classes/src/art/Test912Art.java
@@ -25,7 +25,6 @@
public class Test912Art {
public static void run() throws Exception {
- art.Main.bindAgentJNIForClass(Test912Art.class);
doTest();
}
diff --git a/test/913-heaps/src/art/Test913.java b/test/913-heaps/src/art/Test913.java
index d3b29cf..8800b1a 100644
--- a/test/913-heaps/src/art/Test913.java
+++ b/test/913-heaps/src/art/Test913.java
@@ -25,8 +25,6 @@
public class Test913 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test913.class);
-
doTest();
// Use a countdown latch for synchronization, as join() will introduce more roots.
diff --git a/test/914-hello-obsolescence/src/art/Main.java b/test/914-hello-obsolescence/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/914-hello-obsolescence/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/914-hello-obsolescence/src/art/Redefinition.java b/test/914-hello-obsolescence/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/914-hello-obsolescence/src/art/Redefinition.java
+++ b/test/914-hello-obsolescence/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/915-obsolete-2/src/art/Main.java b/test/915-obsolete-2/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/915-obsolete-2/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/915-obsolete-2/src/art/Redefinition.java b/test/915-obsolete-2/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/915-obsolete-2/src/art/Redefinition.java
+++ b/test/915-obsolete-2/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/916-obsolete-jit/src/Main.java b/test/916-obsolete-jit/src/Main.java
index cb202e4..17a7a86 100644
--- a/test/916-obsolete-jit/src/Main.java
+++ b/test/916-obsolete-jit/src/Main.java
@@ -116,7 +116,6 @@
}
public static void main(String[] args) {
- art.Main.bindAgentJNIForClass(Main.class);
doTest(new Transform(), new TestWatcher());
}
diff --git a/test/916-obsolete-jit/src/art/Main.java b/test/916-obsolete-jit/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/916-obsolete-jit/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/916-obsolete-jit/src/art/Redefinition.java b/test/916-obsolete-jit/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/916-obsolete-jit/src/art/Redefinition.java
+++ b/test/916-obsolete-jit/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/917-fields-transformation/src/art/Main.java b/test/917-fields-transformation/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/917-fields-transformation/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/917-fields-transformation/src/art/Redefinition.java b/test/917-fields-transformation/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/917-fields-transformation/src/art/Redefinition.java
+++ b/test/917-fields-transformation/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/918-fields/src/art/Main.java b/test/918-fields/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/918-fields/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/918-fields/src/art/Test918.java b/test/918-fields/src/art/Test918.java
index 89d518c..ca23c03 100644
--- a/test/918-fields/src/art/Test918.java
+++ b/test/918-fields/src/art/Test918.java
@@ -21,7 +21,6 @@
public class Test918 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test918.class);
doTest();
}
diff --git a/test/919-obsolete-fields/src/art/Main.java b/test/919-obsolete-fields/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/919-obsolete-fields/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/919-obsolete-fields/src/art/Redefinition.java b/test/919-obsolete-fields/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/919-obsolete-fields/src/art/Redefinition.java
+++ b/test/919-obsolete-fields/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/920-objects/src/art/Main.java b/test/920-objects/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/920-objects/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/920-objects/src/art/Test920.java b/test/920-objects/src/art/Test920.java
index 708e417..03038a6 100644
--- a/test/920-objects/src/art/Test920.java
+++ b/test/920-objects/src/art/Test920.java
@@ -21,7 +21,6 @@
public class Test920 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test920.class);
doTest();
}
diff --git a/test/921-hello-failure/src/art/Main.java b/test/921-hello-failure/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/921-hello-failure/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/921-hello-failure/src/art/Redefinition.java b/test/921-hello-failure/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/921-hello-failure/src/art/Redefinition.java
+++ b/test/921-hello-failure/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/922-properties/src/art/Main.java b/test/922-properties/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/922-properties/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/922-properties/src/art/Test922.java b/test/922-properties/src/art/Test922.java
index 4b2204a..d105a21 100644
--- a/test/922-properties/src/art/Test922.java
+++ b/test/922-properties/src/art/Test922.java
@@ -21,7 +21,6 @@
public class Test922 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test922.class);
doTest();
}
diff --git a/test/923-monitors/src/art/Main.java b/test/923-monitors/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/923-monitors/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/923-monitors/src/art/Test923.java b/test/923-monitors/src/art/Test923.java
index 02e86a6..0995cf0 100644
--- a/test/923-monitors/src/art/Test923.java
+++ b/test/923-monitors/src/art/Test923.java
@@ -23,7 +23,6 @@
public class Test923 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test923.class);
doTest();
}
diff --git a/test/924-threads/src/art/Main.java b/test/924-threads/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/924-threads/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/924-threads/src/art/Test924.java b/test/924-threads/src/art/Test924.java
index 5445939..84b7c62 100644
--- a/test/924-threads/src/art/Test924.java
+++ b/test/924-threads/src/art/Test924.java
@@ -29,8 +29,6 @@
public class Test924 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test924.class);
-
// Run the test on its own thread, so we have a known state for the "current" thread.
Thread t = new Thread("TestThread") {
@Override
diff --git a/test/925-threadgroups/src/art/Main.java b/test/925-threadgroups/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/925-threadgroups/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/925-threadgroups/src/art/Test925.java b/test/925-threadgroups/src/art/Test925.java
index 14ca7a7..8d1e665 100644
--- a/test/925-threadgroups/src/art/Test925.java
+++ b/test/925-threadgroups/src/art/Test925.java
@@ -25,7 +25,6 @@
public class Test925 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test925.class);
doTest();
}
diff --git a/test/926-multi-obsolescence/src/art/Main.java b/test/926-multi-obsolescence/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/926-multi-obsolescence/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/926-multi-obsolescence/src/art/Redefinition.java b/test/926-multi-obsolescence/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/926-multi-obsolescence/src/art/Redefinition.java
+++ b/test/926-multi-obsolescence/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/927-timers/src/art/Main.java b/test/927-timers/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/927-timers/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/927-timers/src/art/Test927.java b/test/927-timers/src/art/Test927.java
index 1ed0160..e5bd8f1 100644
--- a/test/927-timers/src/art/Test927.java
+++ b/test/927-timers/src/art/Test927.java
@@ -20,7 +20,6 @@
public class Test927 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test927.class);
doTest();
}
diff --git a/test/928-jni-table/src/art/Main.java b/test/928-jni-table/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/928-jni-table/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/928-jni-table/src/art/Test928.java b/test/928-jni-table/src/art/Test928.java
index 3f3935d..0fbfb7e 100644
--- a/test/928-jni-table/src/art/Test928.java
+++ b/test/928-jni-table/src/art/Test928.java
@@ -18,7 +18,6 @@
public class Test928 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test928.class);
doJNITableTest();
System.out.println("Done");
diff --git a/test/929-search/src/Main.java b/test/929-search/src/Main.java
index 4073c3f..bbeb081 100644
--- a/test/929-search/src/Main.java
+++ b/test/929-search/src/Main.java
@@ -18,7 +18,6 @@
public class Main {
public static void main(String[] args) throws Exception {
- art.Main.bindAgentJNIForClass(Main.class);
doTest();
}
diff --git a/test/929-search/src/art/Main.java b/test/929-search/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/929-search/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/930-hello-retransform/src/art/Main.java b/test/930-hello-retransform/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/930-hello-retransform/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/930-hello-retransform/src/art/Redefinition.java b/test/930-hello-retransform/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/930-hello-retransform/src/art/Redefinition.java
+++ b/test/930-hello-retransform/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/931-agent-thread/src/art/Main.java b/test/931-agent-thread/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/931-agent-thread/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/931-agent-thread/src/art/Test931.java b/test/931-agent-thread/src/art/Test931.java
index bc096a7..be69466 100644
--- a/test/931-agent-thread/src/art/Test931.java
+++ b/test/931-agent-thread/src/art/Test931.java
@@ -20,7 +20,6 @@
public class Test931 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test931.class);
testAgentThread();
System.out.println("Done");
diff --git a/test/932-transform-saves/src/art/Main.java b/test/932-transform-saves/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/932-transform-saves/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/932-transform-saves/src/art/Redefinition.java b/test/932-transform-saves/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/932-transform-saves/src/art/Redefinition.java
+++ b/test/932-transform-saves/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/933-misc-events/src/art/Main.java b/test/933-misc-events/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/933-misc-events/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/933-misc-events/src/art/Test933.java b/test/933-misc-events/src/art/Test933.java
index afebbf8..04f96e1 100644
--- a/test/933-misc-events/src/art/Test933.java
+++ b/test/933-misc-events/src/art/Test933.java
@@ -18,7 +18,6 @@
public class Test933 {
public static void run() throws Exception {
- Main.bindAgentJNIForClass(Test933.class);
testSigQuit();
System.out.println("Done");
diff --git a/test/934-load-transform/src/Main.java b/test/934-load-transform/src/Main.java
index 69c839f..1401b7d 100644
--- a/test/934-load-transform/src/Main.java
+++ b/test/934-load-transform/src/Main.java
@@ -70,7 +70,6 @@
}
public static void main(String[] args) {
- art.Main.bindAgentJNIForClass(Main.class);
// Don't pop transformations. Make sure that even if 2 threads race to define the class both
// will get the same result.
setPopRetransformations(false);
diff --git a/test/934-load-transform/src/art/Main.java b/test/934-load-transform/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/934-load-transform/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/934-load-transform/src/art/Redefinition.java b/test/934-load-transform/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/934-load-transform/src/art/Redefinition.java
+++ b/test/934-load-transform/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/935-non-retransformable/src/art/Main.java b/test/935-non-retransformable/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/935-non-retransformable/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/935-non-retransformable/src/art/Redefinition.java b/test/935-non-retransformable/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/935-non-retransformable/src/art/Redefinition.java
+++ b/test/935-non-retransformable/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/936-search-onload/src/Main.java b/test/936-search-onload/src/Main.java
index 8d40753..2e7a871 100644
--- a/test/936-search-onload/src/Main.java
+++ b/test/936-search-onload/src/Main.java
@@ -18,7 +18,6 @@
public class Main {
public static void main(String[] args) throws Exception {
- art.Main.bindAgentJNIForClass(Main.class);
doTest();
}
diff --git a/test/936-search-onload/src/art/Main.java b/test/936-search-onload/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/936-search-onload/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/937-hello-retransform-package/src/art/Main.java b/test/937-hello-retransform-package/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/937-hello-retransform-package/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/937-hello-retransform-package/src/art/Redefinition.java b/test/937-hello-retransform-package/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/937-hello-retransform-package/src/art/Redefinition.java
+++ b/test/937-hello-retransform-package/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/938-load-transform-bcp/src/Main.java b/test/938-load-transform-bcp/src/Main.java
index e560942..69658c0 100644
--- a/test/938-load-transform-bcp/src/Main.java
+++ b/test/938-load-transform-bcp/src/Main.java
@@ -97,7 +97,6 @@
}
public static void main(String[] args) {
- art.Main.bindAgentJNIForClass(Main.class);
setPopRetransformations(false);
addCommonTransformationResult("java/util/OptionalLong", CLASS_BYTES, DEX_BYTES);
enableCommonRetransformation(true);
diff --git a/test/938-load-transform-bcp/src/art/Main.java b/test/938-load-transform-bcp/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/938-load-transform-bcp/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/938-load-transform-bcp/src/art/Redefinition.java b/test/938-load-transform-bcp/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/938-load-transform-bcp/src/art/Redefinition.java
+++ b/test/938-load-transform-bcp/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/939-hello-transformation-bcp/src/art/Main.java b/test/939-hello-transformation-bcp/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/939-hello-transformation-bcp/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/939-hello-transformation-bcp/src/art/Redefinition.java b/test/939-hello-transformation-bcp/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/939-hello-transformation-bcp/src/art/Redefinition.java
+++ b/test/939-hello-transformation-bcp/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/940-recursive-obsolete/src/art/Main.java b/test/940-recursive-obsolete/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/940-recursive-obsolete/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/940-recursive-obsolete/src/art/Redefinition.java b/test/940-recursive-obsolete/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/940-recursive-obsolete/src/art/Redefinition.java
+++ b/test/940-recursive-obsolete/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/941-recurive-obsolete-jit/src/Main.java b/test/941-recurive-obsolete-jit/src/Main.java
index 1c391a4..89d593b 100644
--- a/test/941-recurive-obsolete-jit/src/Main.java
+++ b/test/941-recurive-obsolete-jit/src/Main.java
@@ -101,7 +101,6 @@
}
public static void main(String[] args) {
- art.Main.bindAgentJNIForClass(Main.class);
doTest(new Transform());
}
diff --git a/test/941-recurive-obsolete-jit/src/art/Main.java b/test/941-recurive-obsolete-jit/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/941-recurive-obsolete-jit/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/941-recurive-obsolete-jit/src/art/Redefinition.java b/test/941-recurive-obsolete-jit/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/941-recurive-obsolete-jit/src/art/Redefinition.java
+++ b/test/941-recurive-obsolete-jit/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/942-private-recursive/src/art/Main.java b/test/942-private-recursive/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/942-private-recursive/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/942-private-recursive/src/art/Redefinition.java b/test/942-private-recursive/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/942-private-recursive/src/art/Redefinition.java
+++ b/test/942-private-recursive/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/943-private-recursive-jit/src/Main.java b/test/943-private-recursive-jit/src/Main.java
index 01760ad..871c636 100644
--- a/test/943-private-recursive-jit/src/Main.java
+++ b/test/943-private-recursive-jit/src/Main.java
@@ -111,7 +111,6 @@
}
public static void main(String[] args) {
- art.Main.bindAgentJNIForClass(Main.class);
doTest(new Transform());
}
diff --git a/test/943-private-recursive-jit/src/art/Main.java b/test/943-private-recursive-jit/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/943-private-recursive-jit/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/943-private-recursive-jit/src/art/Redefinition.java b/test/943-private-recursive-jit/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/943-private-recursive-jit/src/art/Redefinition.java
+++ b/test/943-private-recursive-jit/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/944-transform-classloaders/src/art/Main.java b/test/944-transform-classloaders/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/944-transform-classloaders/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/944-transform-classloaders/src/art/Redefinition.java b/test/944-transform-classloaders/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/944-transform-classloaders/src/art/Redefinition.java
+++ b/test/944-transform-classloaders/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/945-obsolete-native/src/art/Main.java b/test/945-obsolete-native/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/945-obsolete-native/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/945-obsolete-native/src/art/Redefinition.java b/test/945-obsolete-native/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/945-obsolete-native/src/art/Redefinition.java
+++ b/test/945-obsolete-native/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/945-obsolete-native/src/art/Test945.java b/test/945-obsolete-native/src/art/Test945.java
index 6cf31f6..97fd0bb 100644
--- a/test/945-obsolete-native/src/art/Test945.java
+++ b/test/945-obsolete-native/src/art/Test945.java
@@ -21,9 +21,9 @@
public class Test945 {
static class Transform {
- static {
- art.Main.bindAgentJNIForClass(Transform.class);
- }
+ // static block to ensure that there is a <clinit> method. This used to be needed due to a bug.
+ // Since it's annoying to recompute the transformed bytes we will just leave this here.
+ static { }
public void sayHi(Runnable r) {
System.out.println("hello");
diff --git a/test/946-obsolete-throw/src/art/Main.java b/test/946-obsolete-throw/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/946-obsolete-throw/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/946-obsolete-throw/src/art/Redefinition.java b/test/946-obsolete-throw/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/946-obsolete-throw/src/art/Redefinition.java
+++ b/test/946-obsolete-throw/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/947-reflect-method/src/art/Main.java b/test/947-reflect-method/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/947-reflect-method/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/947-reflect-method/src/art/Redefinition.java b/test/947-reflect-method/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/947-reflect-method/src/art/Redefinition.java
+++ b/test/947-reflect-method/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/948-change-annotations/src/Main.java b/test/948-change-annotations/src/Main.java
index 5d3406d..4fd2bfd 100644
--- a/test/948-change-annotations/src/Main.java
+++ b/test/948-change-annotations/src/Main.java
@@ -56,7 +56,6 @@
"AAQgAAACAAAAmwIAAAAgAAABAAAApwIAAAAQAAABAAAAuAIAAA==");
public static void main(String[] args) {
- art.Main.bindAgentJNIForClass(Main.class);
doTest(new RemoveAnnotationsTest());
doTest(new AddAnnotationsTest());
doTest(new ChangeAnnotationValues());
diff --git a/test/948-change-annotations/src/art/Main.java b/test/948-change-annotations/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/948-change-annotations/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/948-change-annotations/src/art/Redefinition.java b/test/948-change-annotations/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/948-change-annotations/src/art/Redefinition.java
+++ b/test/948-change-annotations/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/949-in-memory-transform/src/art/Main.java b/test/949-in-memory-transform/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/949-in-memory-transform/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/949-in-memory-transform/src/art/Redefinition.java b/test/949-in-memory-transform/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/949-in-memory-transform/src/art/Redefinition.java
+++ b/test/949-in-memory-transform/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/950-redefine-intrinsic/src/Main.java b/test/950-redefine-intrinsic/src/Main.java
index 369a8f4..d4f4e8f 100644
--- a/test/950-redefine-intrinsic/src/Main.java
+++ b/test/950-redefine-intrinsic/src/Main.java
@@ -426,7 +426,6 @@
}
public static void main(String[] args) {
- art.Main.bindAgentJNIForClass(Main.class);
doTest(10000);
}
diff --git a/test/950-redefine-intrinsic/src/art/Main.java b/test/950-redefine-intrinsic/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/950-redefine-intrinsic/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/950-redefine-intrinsic/src/art/Redefinition.java b/test/950-redefine-intrinsic/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/950-redefine-intrinsic/src/art/Redefinition.java
+++ b/test/950-redefine-intrinsic/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/951-threaded-obsolete/src/art/Main.java b/test/951-threaded-obsolete/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/951-threaded-obsolete/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/951-threaded-obsolete/src/art/Redefinition.java b/test/951-threaded-obsolete/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/951-threaded-obsolete/src/art/Redefinition.java
+++ b/test/951-threaded-obsolete/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/980-redefine-object/src/Main.java b/test/980-redefine-object/src/Main.java
index 63c0cab..2428b55 100644
--- a/test/980-redefine-object/src/Main.java
+++ b/test/980-redefine-object/src/Main.java
@@ -316,7 +316,6 @@
}
public static void main(String[] args) {
- art.Main.bindAgentJNIForClass(Main.class);
doTest();
}
diff --git a/test/980-redefine-object/src/art/Main.java b/test/980-redefine-object/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/980-redefine-object/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/980-redefine-object/src/art/Redefinition.java b/test/980-redefine-object/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/980-redefine-object/src/art/Redefinition.java
+++ b/test/980-redefine-object/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/981-dedup-original-dex/src/art/Main.java b/test/981-dedup-original-dex/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/981-dedup-original-dex/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/981-dedup-original-dex/src/art/Redefinition.java b/test/981-dedup-original-dex/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/981-dedup-original-dex/src/art/Redefinition.java
+++ b/test/981-dedup-original-dex/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/982-ok-no-retransform/src/art/Main.java b/test/982-ok-no-retransform/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/982-ok-no-retransform/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/982-ok-no-retransform/src/art/Redefinition.java b/test/982-ok-no-retransform/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/982-ok-no-retransform/src/art/Redefinition.java
+++ b/test/982-ok-no-retransform/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/983-source-transform-verify/src/art/Main.java b/test/983-source-transform-verify/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/983-source-transform-verify/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/983-source-transform-verify/src/art/Redefinition.java b/test/983-source-transform-verify/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/983-source-transform-verify/src/art/Redefinition.java
+++ b/test/983-source-transform-verify/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/984-obsolete-invoke/src/art/Main.java b/test/984-obsolete-invoke/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/984-obsolete-invoke/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/984-obsolete-invoke/src/art/Redefinition.java b/test/984-obsolete-invoke/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/984-obsolete-invoke/src/art/Redefinition.java
+++ b/test/984-obsolete-invoke/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/984-obsolete-invoke/src/art/Test984.java b/test/984-obsolete-invoke/src/art/Test984.java
index 3fe66f6..0b0767c 100644
--- a/test/984-obsolete-invoke/src/art/Test984.java
+++ b/test/984-obsolete-invoke/src/art/Test984.java
@@ -72,7 +72,6 @@
"AA==");
public static void run() {
- art.Main.bindAgentJNIForClass(Test984.class);
doTest();
}
diff --git a/test/985-re-obsolete/src/art/Main.java b/test/985-re-obsolete/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/985-re-obsolete/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/985-re-obsolete/src/art/Redefinition.java b/test/985-re-obsolete/src/art/Redefinition.java
index 0350ab4..56d2938 100644
--- a/test/985-re-obsolete/src/art/Redefinition.java
+++ b/test/985-re-obsolete/src/art/Redefinition.java
@@ -19,11 +19,6 @@
import java.util.ArrayList;
// Common Redefinition functions. Placed here for use by CTS
public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
public static final class CommonClassDefinition {
public final Class<?> target;
public final byte[] class_file_bytes;
diff --git a/test/986-native-method-bind/expected.txt b/test/986-native-method-bind/expected.txt
index 189217d..a470285 100644
--- a/test/986-native-method-bind/expected.txt
+++ b/test/986-native-method-bind/expected.txt
@@ -1,8 +1,11 @@
-private static native void art.Test986$Transform.sayHi() = Java_art_Test986_00024Transform_sayHi -> Java_art_Test986_00024Transform_sayHi
-Hello
-private static native void art.Test986$Transform.sayHi() = Java_art_Test986_00024Transform_sayHi -> NoReallySayGoodbye
+private static native void art.Test986$Transform.sayHi2() = Java_art_Test986_00024Transform_sayHi2 -> Java_art_Test986_00024Transform_sayHi2
+Hello - 2
+private static native void art.Test986$Transform.sayHi() = Java_art_Test986_00024Transform_sayHi__ -> NoReallySayGoodbye
Bye
-public static native void art.Main.bindAgentJNI(java.lang.String,java.lang.ClassLoader) = Java_art_Main_bindAgentJNI -> Java_art_Main_bindAgentJNI
-public static native void art.Main.bindAgentJNIForClass(java.lang.Class) = Java_art_Main_bindAgentJNIForClass -> Java_art_Main_bindAgentJNIForClass
-private static native void art.Test986.setNativeBindNotify(boolean) = Java_art_Test986_setNativeBindNotify -> Java_art_Test986_setNativeBindNotify
-private static native void art.Test986.setupNativeBindNotify() = Java_art_Test986_setupNativeBindNotify -> Java_art_Test986_setupNativeBindNotify
+private static native void art.Test986.rebindTransformClass(java.lang.Class) = Java_art_Test986_rebindTransformClass -> Java_art_Test986_rebindTransformClass
+private static native void art.Test986$Transform.sayHi() = Java_art_Test986_00024Transform_sayHi__ -> Java_art_Test986_00024Transform_sayHi2
+private static native void art.Test986$Transform.sayHi2() = Java_art_Test986_00024Transform_sayHi2 -> Java_art_Test986_00024Transform_sayHi2
+Hello - 2
+private static native void art.Test986$Transform.sayHi() = Java_art_Test986_00024Transform_sayHi__ -> Java_art_Test986_00024Transform_sayHi__
+private static native void art.Test986$Transform.sayHi2() = Java_art_Test986_00024Transform_sayHi2 -> Java_art_Test986_00024Transform_sayHi2
+Hello
diff --git a/test/986-native-method-bind/native_bind.cc b/test/986-native-method-bind/native_bind.cc
index 4f93f87..eec635b 100644
--- a/test/986-native-method-bind/native_bind.cc
+++ b/test/986-native-method-bind/native_bind.cc
@@ -38,11 +38,16 @@
env->CallStaticVoidMethod(klass.get(), targetMethod);
}
-extern "C" JNIEXPORT void JNICALL Java_art_Test986_00024Transform_sayHi(
+extern "C" JNIEXPORT void JNICALL Java_art_Test986_00024Transform_sayHi__(
JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) {
doUpPrintCall(env, "doSayHi");
}
+extern "C" JNIEXPORT void JNICALL Java_art_Test986_00024Transform_sayHi2(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) {
+ doUpPrintCall(env, "doSayHi2");
+}
+
extern "C" JNIEXPORT void JNICALL NoReallySayGoodbye(JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) {
doUpPrintCall(env, "doSayBye");
}
@@ -106,5 +111,17 @@
}
}
+extern "C" JNIEXPORT void JNICALL Java_art_Test986_rebindTransformClass(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jclass k) {
+ JNINativeMethod m[2];
+ m[0].name= "sayHi";
+ m[0].signature = "()V";
+ m[0].fnPtr = reinterpret_cast<void*>(Java_art_Test986_00024Transform_sayHi__);
+ m[1].name= "sayHi2";
+ m[1].signature = "()V";
+ m[1].fnPtr = reinterpret_cast<void*>(Java_art_Test986_00024Transform_sayHi2);
+ env->RegisterNatives(k, m, 2);
+}
+
} // namespace Test986NativeBind
} // namespace art
diff --git a/test/986-native-method-bind/src/art/Main.java b/test/986-native-method-bind/src/art/Main.java
deleted file mode 100644
index 8b01920..0000000
--- a/test/986-native-method-bind/src/art/Main.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-// Binder class so the agent's C code has something that can be bound and exposed to tests.
-// In a package to separate cleanly and work around CTS reference issues (though this class
-// should be replaced in the CTS version).
-public class Main {
- // Load the given class with the given classloader, and bind all native methods to corresponding
- // C methods in the agent. Will abort if any of the steps fail.
- public static native void bindAgentJNI(String className, ClassLoader classLoader);
- // Same as above, giving the class directly.
- public static native void bindAgentJNIForClass(Class<?> klass);
-}
diff --git a/test/986-native-method-bind/src/art/Redefinition.java b/test/986-native-method-bind/src/art/Redefinition.java
deleted file mode 100644
index 0350ab4..0000000
--- a/test/986-native-method-bind/src/art/Redefinition.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-package art;
-
-import java.util.ArrayList;
-// Common Redefinition functions. Placed here for use by CTS
-public class Redefinition {
- // Bind native functions.
- static {
- Main.bindAgentJNIForClass(Redefinition.class);
- }
-
- public static final class CommonClassDefinition {
- public final Class<?> target;
- public final byte[] class_file_bytes;
- public final byte[] dex_file_bytes;
-
- public CommonClassDefinition(Class<?> target, byte[] class_file_bytes, byte[] dex_file_bytes) {
- this.target = target;
- this.class_file_bytes = class_file_bytes;
- this.dex_file_bytes = dex_file_bytes;
- }
- }
-
- // A set of possible test configurations. Test should set this if they need to.
- // This must be kept in sync with the defines in ti-agent/common_helper.cc
- public static enum Config {
- COMMON_REDEFINE(0),
- COMMON_RETRANSFORM(1),
- COMMON_TRANSFORM(2);
-
- private final int val;
- private Config(int val) {
- this.val = val;
- }
- }
-
- public static void setTestConfiguration(Config type) {
- nativeSetTestConfiguration(type.val);
- }
-
- private static native void nativeSetTestConfiguration(int type);
-
- // Transforms the class
- public static native void doCommonClassRedefinition(Class<?> target,
- byte[] classfile,
- byte[] dexfile);
-
- public static void doMultiClassRedefinition(CommonClassDefinition... defs) {
- ArrayList<Class<?>> classes = new ArrayList<>();
- ArrayList<byte[]> class_files = new ArrayList<>();
- ArrayList<byte[]> dex_files = new ArrayList<>();
-
- for (CommonClassDefinition d : defs) {
- classes.add(d.target);
- class_files.add(d.class_file_bytes);
- dex_files.add(d.dex_file_bytes);
- }
- doCommonMultiClassRedefinition(classes.toArray(new Class<?>[0]),
- class_files.toArray(new byte[0][]),
- dex_files.toArray(new byte[0][]));
- }
-
- public static void addMultiTransformationResults(CommonClassDefinition... defs) {
- for (CommonClassDefinition d : defs) {
- addCommonTransformationResult(d.target.getCanonicalName(),
- d.class_file_bytes,
- d.dex_file_bytes);
- }
- }
-
- public static native void doCommonMultiClassRedefinition(Class<?>[] targets,
- byte[][] classfiles,
- byte[][] dexfiles);
- public static native void doCommonClassRetransformation(Class<?>... target);
- public static native void setPopRetransformations(boolean pop);
- public static native void popTransformationFor(String name);
- public static native void enableCommonRetransformation(boolean enable);
- public static native void addCommonTransformationResult(String target_name,
- byte[] class_bytes,
- byte[] dex_bytes);
-}
diff --git a/test/986-native-method-bind/src/art/Test986.java b/test/986-native-method-bind/src/art/Test986.java
index edd2e9d..f621c9f 100644
--- a/test/986-native-method-bind/src/art/Test986.java
+++ b/test/986-native-method-bind/src/art/Test986.java
@@ -20,18 +20,12 @@
import java.util.HashMap;
public class Test986 {
- static {
- // NB This is called before any setup is done so we don't need to worry about getting bind
- // events.
- Main.bindAgentJNIForClass(Test986.class);
- }
-
-
private static final HashMap<Method, String> SymbolMap = new HashMap<>();
// A class with a native method we can play with.
static class Transform {
private static native void sayHi();
+ private static native void sayHi2();
}
public static void run() throws Exception {
@@ -44,6 +38,10 @@
SymbolMap.put(method, dest);
}
+ private static void removeNativeTransform(Method method) {
+ SymbolMap.remove(method);
+ }
+
/**
* Notifies java that a native method bind has occurred and requests the new symbol to bind to.
*/
@@ -58,14 +56,23 @@
public static void doTest() throws Exception {
Method say_hi_method = Transform.class.getDeclaredMethod("sayHi");
- // TODO We should test auto-binding but due to the way this is run that will be annoying.
- Main.bindAgentJNIForClass(Transform.class);
- Transform.sayHi();
+
+ // Test we will bind fine if we make no changes.
+ Transform.sayHi2();
+
+ // Test we can get in the middle of autobind
setNativeTransform(say_hi_method, "NoReallySayGoodbye");
- Main.bindAgentJNIForClass(Transform.class);
Transform.sayHi();
- Main.bindAgentJNIForClass(Main.class);
- Main.bindAgentJNIForClass(Test986.class);
+
+ // Test we can get in between manual bind.
+ setNativeTransform(say_hi_method, "Java_art_Test986_00024Transform_sayHi2");
+ rebindTransformClass();
+ Transform.sayHi();
+
+ // Test we can get rid of transform
+ removeNativeTransform(say_hi_method);
+ rebindTransformClass();
+ Transform.sayHi();
}
// Functions called from native code.
@@ -73,10 +80,18 @@
System.out.println("Hello");
}
+ public static void doSayHi2() {
+ System.out.println("Hello - 2");
+ }
+
public static void doSayBye() {
System.out.println("Bye");
}
private static native void setNativeBindNotify(boolean enable);
private static native void setupNativeBindNotify();
+ private static void rebindTransformClass() {
+ rebindTransformClass(Transform.class);
+ }
+ private static native void rebindTransformClass(Class<?> trans);
}
diff --git a/test/987-agent-bind/agent_bind.cc b/test/987-agent-bind/agent_bind.cc
new file mode 100644
index 0000000..44366c1
--- /dev/null
+++ b/test/987-agent-bind/agent_bind.cc
@@ -0,0 +1,52 @@
+/*
+ * 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 <inttypes.h>
+#include <memory>
+#include <stdio.h>
+#include <dlfcn.h>
+
+#include "android-base/stringprintf.h"
+#include "jni.h"
+#include "jvmti.h"
+
+// Test infrastructure
+#include "jni_binder.h"
+#include "jvmti_helper.h"
+#include "test_env.h"
+#include "scoped_local_ref.h"
+
+namespace art {
+namespace Test987AgentBind {
+
+static void doUpPrintCall(JNIEnv* env, const char* function) {
+ ScopedLocalRef<jclass> klass(env, env->FindClass("art/Test987"));
+ jmethodID targetMethod = env->GetStaticMethodID(klass.get(), function, "()V");
+ env->CallStaticVoidMethod(klass.get(), targetMethod);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test987_00024Transform_sayHi__(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) {
+ doUpPrintCall(env, "doSayHi");
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test987_00024Transform_sayHi2(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) {
+ doUpPrintCall(env, "doSayHi2");
+}
+
+} // namespace Test987AgentBind
+} // namespace art
diff --git a/test/987-agent-bind/expected.txt b/test/987-agent-bind/expected.txt
new file mode 100644
index 0000000..ee4a424
--- /dev/null
+++ b/test/987-agent-bind/expected.txt
@@ -0,0 +1,2 @@
+Hello
+Hello - 2
diff --git a/test/987-agent-bind/info.txt b/test/987-agent-bind/info.txt
new file mode 100644
index 0000000..ae4a651
--- /dev/null
+++ b/test/987-agent-bind/info.txt
@@ -0,0 +1 @@
+Tests that native methods are bound from agent libs.
diff --git a/test/987-agent-bind/run b/test/987-agent-bind/run
new file mode 100755
index 0000000..e92b873
--- /dev/null
+++ b/test/987-agent-bind/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+./default-run "$@" --jvmti
diff --git a/test/987-agent-bind/src/Main.java b/test/987-agent-bind/src/Main.java
new file mode 100644
index 0000000..9ce6242
--- /dev/null
+++ b/test/987-agent-bind/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ art.Test987.run();
+ }
+}
diff --git a/test/987-agent-bind/src/art/Test987.java b/test/987-agent-bind/src/art/Test987.java
new file mode 100644
index 0000000..ae97ff2
--- /dev/null
+++ b/test/987-agent-bind/src/art/Test987.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+package art;
+
+public class Test987 {
+ // A class with a native method we can play with.
+ static class Transform {
+ private static native void sayHi();
+ private static native void sayHi2();
+ }
+
+ public static void run() throws Exception {
+ doTest();
+ }
+
+ public static void doTest() throws Exception {
+ Transform.sayHi();
+ Transform.sayHi2();
+ }
+ // Functions called from native code.
+ public static void doSayHi() {
+ System.out.println("Hello");
+ }
+
+ public static void doSayHi2() {
+ System.out.println("Hello - 2");
+ }
+}
diff --git a/test/Android.bp b/test/Android.bp
index d8a3f0e..1679669 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -277,6 +277,7 @@
"945-obsolete-native/obsolete_native.cc",
"984-obsolete-invoke/obsolete_invoke.cc",
"986-native-method-bind/native_bind.cc",
+ "987-agent-bind/agent_bind.cc",
],
shared_libs: [
"libbase",
@@ -391,6 +392,7 @@
"597-deopt-new-string/deopt.cc",
"626-const-class-linking/clear_dex_cache_types.cc",
"642-fp-callees/fp_callees.cc",
+ "647-jni-get-field-id/get_field_id.cc",
],
shared_libs: [
"libbacktrace",
diff --git a/test/Android.run-test-jvmti-java-library.mk b/test/Android.run-test-jvmti-java-library.mk
index 70ee693..c480be5 100644
--- a/test/Android.run-test-jvmti-java-library.mk
+++ b/test/Android.run-test-jvmti-java-library.mk
@@ -74,6 +74,8 @@
981-dedup-original-dex/src/art/Test981.java \
982-ok-no-retransform/src/art/Test982.java \
984-obsolete-invoke/src/art/Test984.java \
+ 985-re-obsolete/src/art/Test985.java \
+ 986-native-method-bind/src/art/Test986.java \
JVMTI_RUN_TEST_GENERATED_NUMBERS := \
901 \
@@ -114,6 +116,8 @@
981 \
982 \
984 \
+ 985 \
+ 986 \
# Try to enforce that the directories correspond to the Java files we pull in.
JVMTI_RUN_TEST_DIR_CHECK := $(sort $(foreach DIR,$(JVMTI_RUN_TEST_GENERATED_NUMBERS), \
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index c7a57ce..b683a27 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/etc/run-test-jar b/test/etc/run-test-jar
index c243af5..b34da08 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -390,16 +390,18 @@
fi
if [[ "$JVMTI_STRESS" = "y" ]]; then
- if [[ "$USE_JVM" = "n" ]]; then
- plugin=libopenjdkjvmtid.so
- agent=libtistressd.so
- if [[ "$TEST_IS_NDEBUG" = "y" ]]; then
- agent=libtistress.so
- plugin=libopenjdkjvmti.so
- fi
+ plugin=libopenjdkjvmtid.so
+ agent=libtistressd.so
+ if [[ "$TEST_IS_NDEBUG" = "y" ]]; then
+ agent=libtistress.so
+ plugin=libopenjdkjvmti.so
+ fi
- file_1=$(mktemp --tmpdir=${DEX_LOCATION})
- file_2=$(mktemp --tmpdir=${DEX_LOCATION})
+ file_1=$(mktemp --tmpdir=${DEX_LOCATION})
+ file_2=$(mktemp --tmpdir=${DEX_LOCATION})
+ if [[ "$USE_JVM" = "y" ]]; then
+ FLAGS="${FLAGS} -agentpath:${ANDROID_HOST_OUT}/nativetest64/${agent}=/bin/false,${file_1},${file_2}"
+ else
# TODO Remove need for DEXTER_BINARY!
FLAGS="${FLAGS} -agentpath:${agent}=${DEXTER_BINARY},${file_1},${file_2}"
if [ "$IS_JVMTI_TEST" = "n" ]; then
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 0e42a29..3ca67bf 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -602,5 +602,67 @@
],
"bug": "b/37239009",
"variant": "jvmti-stress"
+ },
+ {
+ "tests": [
+ "004-JniTest",
+ "004-NativeAllocations",
+ "004-ReferenceMap",
+ "004-StackWalk",
+ "048-reflect-v8",
+ "089-many-methods",
+ "138-duplicate-classes-check",
+ "146-bad-interface",
+ "157-void-class",
+ "563-checker-invoke-super",
+ "580-checker-string-fact-intrinsics",
+ "596-monitor-inflation",
+ "604-hot-static-interface",
+ "612-jit-dex-cache",
+ "613-inlining-dex-cache",
+ "616-cha-interface-default",
+ "636-wrong-static-access",
+ "909-attach-agent",
+ "910-methods",
+ "911-get-stack-trace",
+ "912-classes",
+ "913-heaps",
+ "914-hello-obsolescence",
+ "915-obsolete-2",
+ "916-obsolete-jit",
+ "919-obsolete-fields",
+ "921-hello-failure",
+ "926-multi-obsolescence",
+ "940-recursive-obsolete",
+ "941-recurive-obsolete-jit",
+ "942-private-recursive",
+ "943-private-recursive-jit",
+ "945-obsolete-native",
+ "946-obsolete-throw",
+ "948-change-annotations",
+ "950-redefine-intrinsic",
+ "951-threaded-obsolete",
+ "952-invoke-custom",
+ "953-invoke-polymorphic-compiler",
+ "956-methodhandles",
+ "957-methodhandle-transforms",
+ "958-methodhandle-stackframe",
+ "959-invoke-polymorphic-accessors",
+ "960-default-smali",
+ "961-default-iface-resolution-gen",
+ "962-iface-static",
+ "963-default-range-smali",
+ "964-default-iface-init-gen",
+ "965-default-verify",
+ "966-default-conflict",
+ "967-default-ame",
+ "969-iface-super",
+ "981-dedup-original-dex",
+ "984-obsolete-invoke",
+ "985-re-obsolete"
+ ],
+ "description": "Tests that use javac/dx to build (not jack).",
+ "env_vars": {"ANDROID_COMPILE_WITH_JACK": "false"},
+ "bug": "b/37636792"
}
]
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index 7d9297f..a0c4ea8 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -95,6 +95,9 @@
ANDROID_BUILD_TOP = _get_android_build_top()
+# Compiling with jack? Possible values in (True, False, 'default')
+ANDROID_COMPILE_WITH_JACK = _getEnvBoolean('ANDROID_COMPILE_WITH_JACK', 'default')
+
# Directory used for temporary test files on the host.
ART_HOST_TEST_DIR = tempfile.mkdtemp(prefix = 'test-art-')
diff --git a/test/testrunner/run_build_test_target.py b/test/testrunner/run_build_test_target.py
index 0ab50af..b1274c9 100755
--- a/test/testrunner/run_build_test_target.py
+++ b/test/testrunner/run_build_test_target.py
@@ -62,7 +62,7 @@
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 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 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/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 8072631..a809246 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -450,6 +450,12 @@
options_test += ' --instruction-set-features ' + \
env.HOST_2ND_ARCH_PREFIX_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES
+ # Use the default run-test behavior unless ANDROID_COMPILE_WITH_JACK is explicitly set.
+ if env.ANDROID_COMPILE_WITH_JACK == True:
+ options_test += ' --build-with-jack'
+ elif env.ANDROID_COMPILE_WITH_JACK == False:
+ options_test += ' --build-with-javac-dx'
+
# TODO(http://36039166): This is a temporary solution to
# fix build breakages.
options_test = (' --output-path %s') % (
diff --git a/test/ti-agent/agent_startup.cc b/test/ti-agent/agent_startup.cc
index be73de5..d6fd266 100644
--- a/test/ti-agent/agent_startup.cc
+++ b/test/ti-agent/agent_startup.cc
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include "agent_startup.h"
-
#include "android-base/logging.h"
#include "android-base/macros.h"
@@ -26,75 +24,7 @@
namespace art {
-static constexpr const char* kMainClass = "art/Main";
-
-static StartCallback gCallback = nullptr;
-
-// TODO: Check this. This may not work on device. The classloader containing the app's classes
-// may not have been created at this point (i.e., if it's not the system classloader).
-static void JNICALL VMInitCallback(jvmtiEnv* callback_jvmti_env,
- JNIEnv* jni_env,
- jthread thread ATTRIBUTE_UNUSED) {
- // Bind kMainClass native methods.
- BindFunctions(callback_jvmti_env, jni_env, kMainClass);
-
- if (gCallback != nullptr) {
- gCallback(callback_jvmti_env, jni_env);
- gCallback = nullptr;
- }
-
- // And delete the jvmtiEnv.
- callback_jvmti_env->DisposeEnvironment();
-}
-
-// Install a phase callback that will bind JNI functions on VMInit.
-void BindOnLoad(JavaVM* vm, StartCallback callback) {
- // Use a new jvmtiEnv. Otherwise we might collide with table changes.
- jvmtiEnv* install_env;
- if (vm->GetEnv(reinterpret_cast<void**>(&install_env), JVMTI_VERSION_1_0) != 0) {
- LOG(FATAL) << "Could not get jvmtiEnv";
- }
- SetAllCapabilities(install_env);
-
- {
- jvmtiEventCallbacks callbacks;
- memset(&callbacks, 0, sizeof(jvmtiEventCallbacks));
- callbacks.VMInit = VMInitCallback;
-
- CheckJvmtiError(install_env, install_env->SetEventCallbacks(&callbacks, sizeof(callbacks)));
- }
-
- CheckJvmtiError(install_env, install_env->SetEventNotificationMode(JVMTI_ENABLE,
- JVMTI_EVENT_VM_INIT,
- nullptr));
-
- gCallback = callback;
-}
-
-// Ensure binding of the Main class when the agent is started through OnAttach.
-void BindOnAttach(JavaVM* vm, StartCallback callback) {
- // Get a JNIEnv. As the thread is attached, we must not destroy it.
- JNIEnv* env;
- CHECK_EQ(0, vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6))
- << "Could not get JNIEnv";
-
- jvmtiEnv* bind_jvmti_env;
- CHECK_EQ(0, vm->GetEnv(reinterpret_cast<void**>(&bind_jvmti_env), JVMTI_VERSION_1_0))
- << "Could not get jvmtiEnv";
- SetAllCapabilities(bind_jvmti_env);
-
- BindFunctions(bind_jvmti_env, env, kMainClass);
-
- if (callback != nullptr) {
- callback(bind_jvmti_env, env);
- }
-
- if (bind_jvmti_env->DisposeEnvironment() != JVMTI_ERROR_NONE) {
- LOG(FATAL) << "Could not dispose temporary jvmtiEnv";
- }
-}
-
-// Utility functions for art.Main shim.
+// Utility functions for binding jni methods.
extern "C" JNIEXPORT void JNICALL Java_art_Main_bindAgentJNI(
JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jstring className, jobject classLoader) {
ScopedUtfChars name(env, className);
diff --git a/test/ti-agent/agent_startup.h b/test/ti-agent/agent_startup.h
deleted file mode 100644
index 4963320..0000000
--- a/test/ti-agent/agent_startup.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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_TEST_TI_AGENT_AGENT_STARTUP_H_
-#define ART_TEST_TI_AGENT_AGENT_STARTUP_H_
-
-#include <functional>
-
-#include "jni.h"
-#include "jvmti.h"
-
-namespace art {
-
-using StartCallback = void(*)(jvmtiEnv*, JNIEnv*);
-
-// Ensure binding of the Main class when the agent is started through OnLoad.
-void BindOnLoad(JavaVM* vm, StartCallback callback);
-
-// Ensure binding of the Main class when the agent is started through OnAttach.
-void BindOnAttach(JavaVM* vm, StartCallback callback);
-
-} // namespace art
-
-#endif // ART_TEST_TI_AGENT_AGENT_STARTUP_H_
diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc
index 3455409..fd47f59 100644
--- a/test/ti-agent/common_load.cc
+++ b/test/ti-agent/common_load.cc
@@ -20,7 +20,6 @@
#include "base/logging.h"
#include "base/macros.h"
-#include "agent_startup.h"
#include "common_helper.h"
#include "jni_binder.h"
#include "jvmti_helper.h"
@@ -117,8 +116,6 @@
SetIsJVM(remaining_options);
- BindOnLoad(vm, nullptr);
-
AgentLib* lib = FindAgent(name_option);
OnLoad fn = nullptr;
if (lib == nullptr) {
@@ -141,8 +138,6 @@
return -1;
}
- BindOnAttach(vm, nullptr);
-
AgentLib* lib = FindAgent(name_option);
if (lib == nullptr) {
printf("Unable to find agent named: %s, add it to the list in test/ti-agent/common_load.cc\n",
diff --git a/test/ti-stress/stress.cc b/test/ti-stress/stress.cc
index fa49a35..e8e3cc7 100644
--- a/test/ti-stress/stress.cc
+++ b/test/ti-stress/stress.cc
@@ -84,6 +84,48 @@
return ReadIntoBuffer(data->out_temp_dex, dex);
}
+static void doJvmtiMethodBind(jvmtiEnv* jvmtienv,
+ JNIEnv* env,
+ jthread thread,
+ jmethodID m,
+ void* address,
+ /*out*/void** out_address) {
+ *out_address = address;
+ jvmtiThreadInfo info;
+ if (thread == nullptr) {
+ info.name = const_cast<char*>("<NULLPTR>");
+ } else if (jvmtienv->GetThreadInfo(thread, &info) != JVMTI_ERROR_NONE) {
+ LOG(WARNING) << "Unable to get thread info!";
+ info.name = const_cast<char*>("<UNKNOWN THREAD>");
+ }
+ char *fname, *fsig, *fgen;
+ char *cname, *cgen;
+ jclass klass = nullptr;
+ if (jvmtienv->GetMethodDeclaringClass(m, &klass) != JVMTI_ERROR_NONE) {
+ LOG(ERROR) << "Unable to get method declaring class!";
+ return;
+ }
+ if (jvmtienv->GetMethodName(m, &fname, &fsig, &fgen) != JVMTI_ERROR_NONE) {
+ LOG(ERROR) << "Unable to get method name!";
+ env->DeleteLocalRef(klass);
+ return;
+ }
+ if (jvmtienv->GetClassSignature(klass, &cname, &cgen) != JVMTI_ERROR_NONE) {
+ LOG(ERROR) << "Unable to get class name!";
+ env->DeleteLocalRef(klass);
+ return;
+ }
+ LOG(INFO) << "Loading native method \"" << cname << "->" << fname << fsig << "\". Thread is "
+ << info.name;
+ jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(cname));
+ jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(cgen));
+ jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fname));
+ jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fsig));
+ jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fgen));
+ env->DeleteLocalRef(klass);
+ return;
+}
+
// The hook we are using.
void JNICALL ClassFileLoadHookSecretNoOp(jvmtiEnv* jvmti,
JNIEnv* jni_env ATTRIBUTE_UNUSED,
@@ -143,7 +185,10 @@
LOG(INFO) << "manual load & initialization of class java/lang/VMClassLoader!";
jclass klass = jni_env->FindClass("java/lang/VMClassLoader");
if (klass == nullptr) {
- LOG(ERROR) << "Unable to find VMClassLoader class!";
+ // Probably on RI. Clear the exception so we can continue but don't mark vmclassloader as
+ // initialized.
+ LOG(WARNING) << "Unable to find VMClassLoader class!";
+ jni_env->ExceptionClear();
} else {
// GetMethodID is spec'd to cause the class to be initialized.
jni_env->GetMethodID(klass, "hashCode", "()I");
@@ -187,12 +232,19 @@
jvmtiEventCallbacks cb;
memset(&cb, 0, sizeof(cb));
cb.ClassFileLoadHook = ClassFileLoadHookSecretNoOp;
+ cb.NativeMethodBind = doJvmtiMethodBind;
cb.VMInit = EnsureVMClassloaderInitializedCB;
if (jvmti->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) {
LOG(ERROR) << "Unable to set class file load hook cb!";
return 1;
}
if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
+ JVMTI_EVENT_NATIVE_METHOD_BIND,
+ nullptr) != JVMTI_ERROR_NONE) {
+ LOG(ERROR) << "Unable to enable JVMTI_EVENT_NATIVE_METHOD_BIND event!";
+ return 1;
+ }
+ if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_VM_INIT,
nullptr) != JVMTI_ERROR_NONE) {
LOG(ERROR) << "Unable to enable JVMTI_EVENT_VM_INIT event!";
diff --git a/test/valgrind-suppressions.txt b/test/valgrind-suppressions.txt
index c775f98..086a856 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 452a174..0d63a1c 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
+}