Merge "Add ClassLoader to app-image roots."
diff --git a/build/art.go b/build/art.go
index ccaa11d..0af1767 100644
--- a/build/art.go
+++ b/build/art.go
@@ -259,7 +259,7 @@
}
func artLibrary() (blueprint.Module, []interface{}) {
- library, _ := cc.NewLibrary(android.HostAndDeviceSupported, true, true)
+ library, _ := cc.NewLibrary(android.HostAndDeviceSupported)
module, props := library.Init()
props = installCodegenCustomizer(module, props, true)
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 2c6df38..55f3c3c 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -57,6 +57,9 @@
using helpers::RegisterFrom;
using helpers::SRegisterFrom;
+using vixl::ExactAssemblyScope;
+using vixl::CodeBufferCheckScope;
+
using RegisterList = vixl32::RegisterList;
static bool ExpectedPairLayout(Location location) {
@@ -843,9 +846,9 @@
__ Subs(tmp, tmp, expected);
{
- AssemblerAccurateScope aas(arm_codegen->GetVIXLAssembler(),
- 2 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(arm_codegen->GetVIXLAssembler(),
+ 2 * kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ it(ne);
__ clrex(ne);
@@ -1261,9 +1264,9 @@
// We are about to use the assembler to place literals directly. Make sure we have enough
// underlying code buffer and we have generated a jump table of the right size, using
// codegen->GetVIXLAssembler()->GetBuffer().Align();
- AssemblerAccurateScope aas(codegen->GetVIXLAssembler(),
- num_entries * sizeof(int32_t),
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(codegen->GetVIXLAssembler(),
+ num_entries * sizeof(int32_t),
+ CodeBufferCheckScope::kMaximumSize);
// TODO(VIXL): Check that using lower case bind is fine here.
codegen->GetVIXLAssembler()->bind(&table_start_);
for (uint32_t i = 0; i < num_entries; i++) {
@@ -1377,9 +1380,9 @@
vixl32::Register temp = temps.Acquire();
__ Sub(temp, sp, static_cast<int32_t>(GetStackOverflowReservedBytes(kArm)));
// The load must immediately precede RecordPcInfo.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ ldr(temp, MemOperand(temp));
RecordPcInfo(nullptr, 0);
}
@@ -1637,9 +1640,9 @@
__ Ldr(lr, MemOperand(tr, GetThreadOffset<kArmPointerSize>(entrypoint).Int32Value()));
// Ensure the pc position is recorded immediately after the `blx` instruction.
// blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::k16BitT32InstructionSizeInBytes,
- CodeBufferCheckScope::kExactSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::k16BitT32InstructionSizeInBytes,
+ CodeBufferCheckScope::kExactSize);
__ blx(lr);
if (EntrypointRequiresStackMap(entrypoint)) {
RecordPcInfo(instruction, dex_pc, slow_path);
@@ -2082,9 +2085,9 @@
__ Cmp(InputRegisterAt(cond, 0),
CodeGenerator::GetInt32ValueOf(right.GetConstant()));
}
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- 3 * vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ 3 * vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ ite(ARMCondition(cond->GetCondition()));
__ mov(ARMCondition(cond->GetCondition()), OutputRegister(cond), 1);
__ mov(ARMCondition(cond->GetOppositeCondition()), OutputRegister(cond), 0);
@@ -2370,9 +2373,9 @@
// Ensure the pc position is recorded immediately after the `ldr` instruction.
{
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
// /* HeapReference<Class> */ temp = receiver->klass_
__ ldr(temp, MemOperand(RegisterFrom(receiver), class_offset));
codegen_->MaybeRecordImplicitNullCheck(invoke);
@@ -2418,7 +2421,7 @@
{
// Ensure the pc position is recorded immediately after the `blx` instruction.
// blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
+ ExactAssemblyScope aas(GetVIXLAssembler(),
vixl32::k16BitT32InstructionSizeInBytes,
CodeBufferCheckScope::kExactSize);
// LR();
@@ -3793,9 +3796,9 @@
// If the shift is > 32 bits, override the high part
__ Subs(temp, o_l, Operand::From(kArmBitsPerWord));
{
- AssemblerAccurateScope guard(GetVIXLAssembler(),
- 2 * vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope guard(GetVIXLAssembler(),
+ 2 * vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ it(pl);
__ lsl(pl, o_h, low, temp);
}
@@ -3812,9 +3815,9 @@
// If the shift is > 32 bits, override the low part
__ Subs(temp, o_h, Operand::From(kArmBitsPerWord));
{
- AssemblerAccurateScope guard(GetVIXLAssembler(),
- 2 * vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope guard(GetVIXLAssembler(),
+ 2 * vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ it(pl);
__ asr(pl, o_l, high, temp);
}
@@ -3829,9 +3832,9 @@
__ Orr(o_l, o_l, temp);
__ Subs(temp, o_h, Operand::From(kArmBitsPerWord));
{
- AssemblerAccurateScope guard(GetVIXLAssembler(),
- 2 * vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope guard(GetVIXLAssembler(),
+ 2 * vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ it(pl);
__ lsr(pl, o_l, high, temp);
}
@@ -3948,9 +3951,9 @@
GetAssembler()->LoadFromOffset(kLoadWord, temp, tr, QUICK_ENTRY_POINT(pNewEmptyString));
GetAssembler()->LoadFromOffset(kLoadWord, lr, temp, code_offset.Int32Value());
// blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::k16BitT32InstructionSizeInBytes,
- CodeBufferCheckScope::kExactSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::k16BitT32InstructionSizeInBytes,
+ CodeBufferCheckScope::kExactSize);
__ blx(lr);
codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
} else {
@@ -4192,9 +4195,9 @@
__ Bind(&fail);
{
// Ensure the pc position is recorded immediately after the `ldrexd` instruction.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
// We need a load followed by store. (The address used in a STREX instruction must
// be the same as the address in the most recently executed LDREX instruction.)
__ ldrexd(temp1, temp2, MemOperand(addr));
@@ -4715,9 +4718,9 @@
UseScratchRegisterScope temps(GetVIXLAssembler());
// Ensure the pc position is recorded immediately after the `ldr` instruction.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ ldr(temps.Acquire(), MemOperand(InputRegisterAt(instruction, 0)));
RecordPcInfo(instruction, instruction->GetDexPc());
}
@@ -5233,9 +5236,9 @@
{
// Ensure we record the pc position immediately after the `ldr` instruction.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
// /* HeapReference<Class> */ temp1 = array->klass_
__ ldr(temp1, MemOperand(array, class_offset));
codegen_->MaybeRecordImplicitNullCheck(instruction);
@@ -5384,9 +5387,9 @@
vixl32::Register obj = InputRegisterAt(instruction, 0);
vixl32::Register out = OutputRegister(instruction);
{
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ ldr(out, MemOperand(obj, offset));
codegen_->MaybeRecordImplicitNullCheck(instruction);
}
@@ -7351,9 +7354,9 @@
relative_call_patches_.emplace_back(*invoke->GetTargetMethod().dex_file,
invoke->GetTargetMethod().dex_method_index);
{
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ bind(&relative_call_patches_.back().label);
// Arbitrarily branch to the BL itself, override at link time.
__ bl(&relative_call_patches_.back().label);
@@ -7365,9 +7368,9 @@
// LR()
{
// blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::k16BitT32InstructionSizeInBytes,
- CodeBufferCheckScope::kExactSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::k16BitT32InstructionSizeInBytes,
+ CodeBufferCheckScope::kExactSize);
__ blx(lr);
}
break;
@@ -7380,9 +7383,9 @@
ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArmPointerSize).Int32Value());
{
// blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::k16BitT32InstructionSizeInBytes,
- CodeBufferCheckScope::kExactSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::k16BitT32InstructionSizeInBytes,
+ CodeBufferCheckScope::kExactSize);
// LR()
__ blx(lr);
}
@@ -7406,9 +7409,9 @@
uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
{
// Make sure the pc is recorded immediately after the `ldr` instruction.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
// /* HeapReference<Class> */ temp = receiver->klass_
__ ldr(temp, MemOperand(receiver, class_offset));
MaybeRecordImplicitNullCheck(invoke);
@@ -7433,9 +7436,9 @@
// `RecordPcInfo()` immediately following record the correct pc. Use a scope to help guarantee
// that.
// blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- vixl32::k16BitT32InstructionSizeInBytes,
- CodeBufferCheckScope::kExactSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::k16BitT32InstructionSizeInBytes,
+ CodeBufferCheckScope::kExactSize);
__ blx(lr);
}
@@ -7702,9 +7705,9 @@
void CodeGeneratorARMVIXL::EmitMovwMovtPlaceholder(
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels,
vixl32::Register out) {
- AssemblerAccurateScope aas(GetVIXLAssembler(),
- 3 * vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ 3 * vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
// TODO(VIXL): Think about using mov instead of movw.
__ bind(&labels->movw_label);
__ movw(out, /* placeholder */ 0u);
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 5ec3da4..93ea601 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -120,7 +120,7 @@
bb_addresses_(switch_instr->GetArena()->Adapter(kArenaAllocCodeGenerator)) {
uint32_t num_entries = switch_instr_->GetNumEntries();
for (uint32_t i = 0; i < num_entries; i++) {
- IntLiteral *lit = new IntLiteral(0);
+ IntLiteral *lit = new IntLiteral(0, vixl32::RawLiteral::kManuallyPlaced);
bb_addresses_.emplace_back(lit);
}
}
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 433dced..95551c8 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -47,6 +47,9 @@
using namespace vixl::aarch32; // NOLINT(build/namespaces)
+using vixl::ExactAssemblyScope;
+using vixl::CodeBufferCheckScope;
+
ArmVIXLAssembler* IntrinsicCodeGeneratorARMVIXL::GetAssembler() {
return codegen_->GetAssembler();
}
@@ -467,9 +470,9 @@
__ Cmp(op1, op2);
{
- AssemblerAccurateScope aas(assembler->GetVIXLAssembler(),
- 3 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(assembler->GetVIXLAssembler(),
+ 3 * kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ ite(is_min ? lt : gt);
__ mov(is_min ? lt : gt, out, op1);
@@ -1050,9 +1053,9 @@
__ Subs(tmp, tmp, expected);
{
- AssemblerAccurateScope aas(assembler->GetVIXLAssembler(),
- 3 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(assembler->GetVIXLAssembler(),
+ 3 * kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ itt(eq);
__ strex(eq, tmp, value, MemOperand(tmp_ptr));
@@ -1066,9 +1069,9 @@
__ Rsbs(out, tmp, 1);
{
- AssemblerAccurateScope aas(assembler->GetVIXLAssembler(),
- 2 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(assembler->GetVIXLAssembler(),
+ 2 * kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ it(cc);
__ mov(cc, out, 0);
@@ -1185,9 +1188,9 @@
// temp0 = min(len(str), len(arg)).
{
- AssemblerAccurateScope aas(assembler->GetVIXLAssembler(),
- 2 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(assembler->GetVIXLAssembler(),
+ 2 * kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ it(gt);
__ mov(gt, temp0, temp1);
@@ -1207,9 +1210,9 @@
// This could in theory exceed INT32_MAX, so treat temp0 as unsigned.
__ Lsls(temp3, temp3, 31u); // Extract purely the compression flag.
- AssemblerAccurateScope aas(assembler->GetVIXLAssembler(),
- 2 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(assembler->GetVIXLAssembler(),
+ 2 * kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ it(ne);
__ add(ne, temp0, temp0, temp0);
@@ -1324,9 +1327,9 @@
__ Mov(temp2, arg);
__ Lsrs(temp3, temp3, 1u); // Continue the move of the compression flag.
{
- AssemblerAccurateScope aas(assembler->GetVIXLAssembler(),
- 3 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(assembler->GetVIXLAssembler(),
+ 3 * kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ itt(cs); // Interleave with selection of temp1 and temp2.
__ mov(cs, temp1, arg); // Preserves flags.
__ mov(cs, temp2, str); // Preserves flags.
@@ -1361,9 +1364,9 @@
static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
"Expecting 0=compressed, 1=uncompressed");
- AssemblerAccurateScope aas(assembler->GetVIXLAssembler(),
- 2 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(assembler->GetVIXLAssembler(),
+ 2 * kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ it(cc);
__ rsb(cc, out, out, 0);
}
@@ -1457,9 +1460,9 @@
// For string compression, calculate the number of bytes to compare (not chars).
// This could in theory exceed INT32_MAX, so treat temp as unsigned.
__ Lsrs(temp, temp, 1u); // Extract length and check compression flag.
- AssemblerAccurateScope aas(assembler->GetVIXLAssembler(),
- 2 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope aas(assembler->GetVIXLAssembler(),
+ 2 * kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
__ it(cs); // If uncompressed,
__ add(cs, temp, temp, temp); // double the byte count.
}
diff --git a/compiler/utils/arm/assembler_arm_vixl.cc b/compiler/utils/arm/assembler_arm_vixl.cc
index 1614d04..76a94e8 100644
--- a/compiler/utils/arm/assembler_arm_vixl.cc
+++ b/compiler/utils/arm/assembler_arm_vixl.cc
@@ -23,6 +23,9 @@
using namespace vixl::aarch32; // NOLINT(build/namespaces)
+using vixl::ExactAssemblyScope;
+using vixl::CodeBufferCheckScope;
+
namespace art {
namespace arm {
@@ -459,9 +462,9 @@
if (!label->IsBound()) {
// Try to use 16-bit T2 encoding of B instruction.
DCHECK(OutsideITBlock());
- AssemblerAccurateScope ass(this,
- kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope ass(this,
+ kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
b(al, Narrow, label);
AddBranchLabel(label);
return;
diff --git a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
index 2d026b8..4e64f13 100644
--- a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
+++ b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
@@ -24,6 +24,9 @@
using namespace vixl::aarch32; // NOLINT(build/namespaces)
namespace vixl32 = vixl::aarch32;
+using vixl::ExactAssemblyScope;
+using vixl::CodeBufferCheckScope;
+
namespace art {
namespace arm {
@@ -455,16 +458,16 @@
if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value(), kCcDontCare)) {
if (!out_reg.Equals(in_reg)) {
- AssemblerAccurateScope guard(asm_.GetVIXLAssembler(),
- 3 * vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
+ 3 * vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
___ it(eq, 0xc);
___ mov(eq, out_reg.AsVIXLRegister(), 0);
asm_.AddConstantInIt(out_reg.AsVIXLRegister(), sp, handle_scope_offset.Int32Value(), ne);
} else {
- AssemblerAccurateScope guard(asm_.GetVIXLAssembler(),
- 2 * vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
+ 2 * vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
___ it(ne, 0x8);
asm_.AddConstantInIt(out_reg.AsVIXLRegister(), sp, handle_scope_offset.Int32Value(), ne);
}
@@ -493,9 +496,9 @@
___ Cmp(scratch.AsVIXLRegister(), 0);
if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value(), kCcDontCare)) {
- AssemblerAccurateScope guard(asm_.GetVIXLAssembler(),
- 2 * vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
+ 2 * vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
___ it(ne, 0x8);
asm_.AddConstantInIt(scratch.AsVIXLRegister(), sp, handle_scope_offset.Int32Value(), ne);
} else {
@@ -586,9 +589,9 @@
___ Cmp(scratch.AsVIXLRegister(), 0);
{
- AssemblerAccurateScope guard(asm_.GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
+ ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
+ vixl32::kMaxInstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
___ b(ne, Narrow, exception_blocks_.back()->Entry());
}
// TODO: think about using CBNZ here.
diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc
index 31d3e4c..f62822d 100644
--- a/compiler/utils/mips64/assembler_mips64_test.cc
+++ b/compiler/utils/mips64/assembler_mips64_test.cc
@@ -605,15 +605,18 @@
}
TEST_F(AssemblerMIPS64Test, LongBalc) {
+ constexpr uint32_t kNopCount1 = (1u << 25) + 1;
+ constexpr uint32_t kNopCount2 = (1u << 25) + 1;
+ constexpr uint32_t kRequiredCapacity = (kNopCount1 + kNopCount2 + 6u) * 4u;
+ ASSERT_LT(__ GetBuffer()->Capacity(), kRequiredCapacity);
+ __ GetBuffer()->ExtendCapacity(kRequiredCapacity);
mips64::Mips64Label label1, label2;
__ Balc(&label1);
- constexpr uint32_t kNopCount1 = (1u << 25) + 1;
for (uint32_t i = 0; i != kNopCount1; ++i) {
__ Nop();
}
__ Bind(&label1);
__ Balc(&label2);
- constexpr uint32_t kNopCount2 = (1u << 25) + 1;
for (uint32_t i = 0; i != kNopCount2; ++i) {
__ Nop();
}
diff --git a/runtime/cha.cc b/runtime/cha.cc
index be675a8..d94b091 100644
--- a/runtime/cha.cc
+++ b/runtime/cha.cc
@@ -100,7 +100,11 @@
bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
ArtMethod* method = GetMethod();
- if (method == nullptr || method->IsRuntimeMethod() || method->IsNative()) {
+ // Avoid types of methods that do not have an oat quick method header.
+ if (method == nullptr ||
+ method->IsRuntimeMethod() ||
+ method->IsNative() ||
+ method->IsProxyMethod()) {
return true;
}
if (GetCurrentQuickFrame() == nullptr) {
@@ -110,6 +114,7 @@
// Method may have multiple versions of compiled code. Check
// the method header to see if it has should_deoptimize flag.
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
+ DCHECK(method_header != nullptr);
if (!method_header->HasShouldDeoptimizeFlag()) {
// This compiled version doesn't have should_deoptimize flag. Skip.
return true;
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 0a65cd1..213986a 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -25,6 +25,7 @@
#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/iftable.h"
+#include "mirror/throwable.h"
#include "mirror/object_array.h"
#include "handle_scope-inl.h"
#include "scoped_thread_state_change-inl.h"
@@ -89,17 +90,28 @@
inline mirror::Class* ClassLinker::ResolveType(dex::TypeIndex type_idx, ArtMethod* referrer) {
Thread::PoisonObjectPointersIfDebug();
+ if (kIsDebugBuild) {
+ Thread::Current()->AssertNoPendingException();
+ }
ObjPtr<mirror::Class> resolved_type =
referrer->GetDexCacheResolvedType(type_idx, image_pointer_size_);
if (UNLIKELY(resolved_type == nullptr)) {
- ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
- const DexFile& dex_file = *dex_cache->GetDexFile();
- resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
- // Note: We cannot check here to see whether we added the type to the cache. The type
- // might be an erroneous class, which results in it being hidden from us.
+ // There could be an out of bounds exception from GetDexCacheResolvedType, don't call
+ // ResolveType for this case.
+ if (LIKELY(!hs.Self()->IsExceptionPending())) {
+ ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
+ const DexFile& dex_file = *dex_cache->GetDexFile();
+ resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
+ // Note: We cannot check here to see whether we added the type to the cache. The type
+ // might be an erroneous class, which results in it being hidden from us.
+ } else {
+ // Make sure its an array out of bounds exception.
+ DCHECK(hs.Self()->GetException()->GetClass()->DescriptorEquals(
+ "Ljava/lang/ArrayIndexOutOfBoundsException;"));
+ }
}
return resolved_type.Ptr();
}
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 2cde7d5..081be96 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -75,11 +75,10 @@
MutexLock mu(self, *Locks::reference_processor_lock_);
while ((!kUseReadBarrier && SlowPathEnabled()) ||
(kUseReadBarrier && !self->GetWeakRefAccessEnabled())) {
- mirror::HeapReference<mirror::Object>* const referent_addr =
- reference->GetReferentReferenceAddr();
+ ObjPtr<mirror::Object> referent = reference->GetReferent<kWithoutReadBarrier>();
// If the referent became cleared, return it. Don't need barrier since thread roots can't get
// updated until after we leave the function due to holding the mutator lock.
- if (referent_addr->AsMirrorPtr() == nullptr) {
+ if (referent == nullptr) {
return nullptr;
}
// Try to see if the referent is already marked by using the is_marked_callback. We can return
@@ -91,10 +90,15 @@
// case only black nodes can be safely returned. If the GC is preserving references, the
// mutator could take a white field from a grey or white node and move it somewhere else
// in the heap causing corruption since this field would get swept.
- if (collector_->IsMarkedHeapReference(referent_addr)) {
+ // Use the cached referent instead of calling GetReferent since other threads could call
+ // Reference.clear() after we did the null check resulting in a null pointer being
+ // incorrectly passed to IsMarked. b/33569625
+ ObjPtr<mirror::Object> forwarded_ref = collector_->IsMarked(referent.Ptr());
+ if (forwarded_ref != nullptr) {
+ // Non null means that it is marked.
if (!preserving_references_ ||
(LIKELY(!reference->IsFinalizerReferenceInstance()) && reference->IsUnprocessed())) {
- return referent_addr->AsMirrorPtr();
+ return forwarded_ref;
}
}
}
@@ -265,11 +269,23 @@
}
}
-bool ReferenceProcessor::MakeCircularListIfUnenqueued(
- ObjPtr<mirror::FinalizerReference> reference) {
+void ReferenceProcessor::ClearReferent(ObjPtr<mirror::Reference> ref) {
Thread* self = Thread::Current();
MutexLock mu(self, *Locks::reference_processor_lock_);
- // Wait untul we are done processing reference.
+ // Need to wait until reference processing is done since IsMarkedHeapReference does not have a
+ // CAS. If we do not wait, it can result in the GC un-clearing references due to race conditions.
+ // This also handles the race where the referent gets cleared after a null check but before
+ // IsMarkedHeapReference is called.
+ WaitUntilDoneProcessingReferences(self);
+ if (Runtime::Current()->IsActiveTransaction()) {
+ ref->ClearReferent<true>();
+ } else {
+ ref->ClearReferent<false>();
+ }
+}
+
+void ReferenceProcessor::WaitUntilDoneProcessingReferences(Thread* self) {
+ // Wait until we are done processing reference.
while ((!kUseReadBarrier && SlowPathEnabled()) ||
(kUseReadBarrier && !self->GetWeakRefAccessEnabled())) {
// Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
@@ -277,6 +293,13 @@
self->CheckEmptyCheckpoint();
condition_.WaitHoldingLocks(self);
}
+}
+
+bool ReferenceProcessor::MakeCircularListIfUnenqueued(
+ ObjPtr<mirror::FinalizerReference> reference) {
+ Thread* self = Thread::Current();
+ MutexLock mu(self, *Locks::reference_processor_lock_);
+ WaitUntilDoneProcessingReferences(self);
// At this point, since the sentinel of the reference is live, it is guaranteed to not be
// enqueued if we just finished processing references. Otherwise, we may be doing the main GC
// phase. Since we are holding the reference processor lock, it guarantees that reference
diff --git a/runtime/gc/reference_processor.h b/runtime/gc/reference_processor.h
index 759b7e1..b15544d 100644
--- a/runtime/gc/reference_processor.h
+++ b/runtime/gc/reference_processor.h
@@ -73,6 +73,9 @@
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::reference_processor_lock_,
!Locks::reference_queue_finalizer_references_lock_);
+ void ClearReferent(ObjPtr<mirror::Reference> ref)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(!Locks::reference_processor_lock_);
private:
bool SlowPathEnabled() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -84,6 +87,10 @@
// referents.
void StartPreservingReferences(Thread* self) REQUIRES(!Locks::reference_processor_lock_);
void StopPreservingReferences(Thread* self) REQUIRES(!Locks::reference_processor_lock_);
+ // Wait until reference processing is done.
+ void WaitUntilDoneProcessingReferences(Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(Locks::reference_processor_lock_);
// Collector which is clearing references, used by the GetReferent to return referents which are
// already marked.
collector::GarbageCollector* collector_ GUARDED_BY(Locks::reference_processor_lock_);
diff --git a/runtime/native/java_lang_ref_Reference.cc b/runtime/native/java_lang_ref_Reference.cc
index bedca10..c778068 100644
--- a/runtime/native/java_lang_ref_Reference.cc
+++ b/runtime/native/java_lang_ref_Reference.cc
@@ -33,8 +33,15 @@
return soa.AddLocalReference<jobject>(referent);
}
+static void Reference_clearReferent(JNIEnv* env, jobject javaThis) {
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Reference> ref = soa.Decode<mirror::Reference>(javaThis);
+ Runtime::Current()->GetHeap()->GetReferenceProcessor()->ClearReferent(ref);
+}
+
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(Reference, getReferent, "!()Ljava/lang/Object;"),
+ NATIVE_METHOD(Reference, clearReferent, "!()V"),
};
void register_java_lang_ref_Reference(JNIEnv* env) {
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index 1ad3f08..5f97b60 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -700,7 +700,7 @@
jmethodID method,
jint* entry_count_ptr,
jvmtiLineNumberEntry** table_ptr) {
- return ERR(NOT_IMPLEMENTED);
+ return MethodUtil::GetLineNumberTable(env, method, entry_count_ptr, table_ptr);
}
static jvmtiError GetMethodLocation(jvmtiEnv* env,
diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc
index ffa5ac7..a0a0923 100644
--- a/runtime/openjdkjvmti/ti_method.cc
+++ b/runtime/openjdkjvmti/ti_method.cc
@@ -130,4 +130,63 @@
return ERR(NONE);
}
+using LineNumberContext = std::vector<jvmtiLineNumberEntry>;
+
+static bool CollectLineNumbers(void* void_context, const art::DexFile::PositionInfo& entry) {
+ LineNumberContext* context = reinterpret_cast<LineNumberContext*>(void_context);
+ jvmtiLineNumberEntry jvmti_entry = { static_cast<jlocation>(entry.address_),
+ static_cast<jint>(entry.line_) };
+ context->push_back(jvmti_entry);
+ return false; // Collect all, no early exit.
+}
+
+jvmtiError MethodUtil::GetLineNumberTable(jvmtiEnv* env,
+ jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLineNumberEntry** table_ptr) {
+ if (method == nullptr) {
+ return ERR(NULL_POINTER);
+ }
+ art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+ DCHECK(!art_method->IsRuntimeMethod());
+
+ const art::DexFile::CodeItem* code_item;
+ const art::DexFile* dex_file;
+ {
+ art::ScopedObjectAccess soa(art::Thread::Current());
+
+ if (art_method->IsProxyMethod()) {
+ return ERR(ABSENT_INFORMATION);
+ }
+ if (art_method->IsNative()) {
+ return ERR(NATIVE_METHOD);
+ }
+ if (entry_count_ptr == nullptr || table_ptr == nullptr) {
+ return ERR(NULL_POINTER);
+ }
+
+ code_item = art_method->GetCodeItem();
+ dex_file = art_method->GetDexFile();
+ DCHECK(code_item != nullptr) << art_method->PrettyMethod() << " " << dex_file->GetLocation();
+ }
+
+ LineNumberContext context;
+ bool success = dex_file->DecodeDebugPositionInfo(code_item, CollectLineNumbers, &context);
+ if (!success) {
+ return ERR(ABSENT_INFORMATION);
+ }
+
+ unsigned char* data;
+ jlong mem_size = context.size() * sizeof(jvmtiLineNumberEntry);
+ jvmtiError alloc_error = env->Allocate(mem_size, &data);
+ if (alloc_error != ERR(NONE)) {
+ return alloc_error;
+ }
+ *table_ptr = reinterpret_cast<jvmtiLineNumberEntry*>(data);
+ memcpy(*table_ptr, context.data(), mem_size);
+ *entry_count_ptr = static_cast<jint>(context.size());
+
+ return ERR(NONE);
+}
+
} // namespace openjdkjvmti
diff --git a/runtime/openjdkjvmti/ti_method.h b/runtime/openjdkjvmti/ti_method.h
index 43f11f9..fb2fbb2 100644
--- a/runtime/openjdkjvmti/ti_method.h
+++ b/runtime/openjdkjvmti/ti_method.h
@@ -52,6 +52,11 @@
static jvmtiError GetMethodModifiers(jvmtiEnv* env,
jmethodID method,
jint* modifiers_ptr);
+
+ static jvmtiError GetLineNumberTable(jvmtiEnv* env,
+ jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLineNumberEntry** table_ptr);
};
} // namespace openjdkjvmti
diff --git a/test/153-reference-stress/expected.txt b/test/153-reference-stress/expected.txt
new file mode 100644
index 0000000..7ef22e9
--- /dev/null
+++ b/test/153-reference-stress/expected.txt
@@ -0,0 +1 @@
+PASS
diff --git a/test/153-reference-stress/info.txt b/test/153-reference-stress/info.txt
new file mode 100644
index 0000000..6bc0040
--- /dev/null
+++ b/test/153-reference-stress/info.txt
@@ -0,0 +1 @@
+Tests java.lang.ref.Reference.get() and GC running in parallel.
diff --git a/test/153-reference-stress/src/Main.java b/test/153-reference-stress/src/Main.java
new file mode 100644
index 0000000..fc6f9cc
--- /dev/null
+++ b/test/153-reference-stress/src/Main.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+import java.lang.ref.WeakReference;
+
+public class Main {
+ static final int numWeakReferences = 16 * 1024;
+ static WeakReference[] weakReferences = new WeakReference[numWeakReferences];
+ static volatile boolean done = false;
+ static Object keepAlive;
+
+ public static void main(String[] args) throws Exception {
+ // Try to call Reference.get repeatedly while the GC is running.
+ Thread gcThread = new GcThread();
+ Thread[] readerThread = new ReaderThread[4];
+ for (int i = 0; i < readerThread.length; ++i) {
+ readerThread[i] = new ReaderThread();
+ }
+ gcThread.start();
+ for (int i = 0; i < readerThread.length; ++i) {
+ readerThread[i].start();
+ }
+ gcThread.join();
+ for (int i = 0; i < readerThread.length; ++i) {
+ readerThread[i].join();
+ }
+ System.out.println("PASS");
+ }
+
+ static class GcThread extends Thread {
+ GcThread() {
+ Object temp = new Object();
+ for (int j = 0; j < weakReferences.length; ++j) {
+ weakReferences[j] = new WeakReference(temp);
+ }
+ }
+ public void run() {
+ for (int i = 0; i < 1000; ++i) {
+ Object o = new Object();
+ for (int j = 0; j < weakReferences.length; ++j) {
+ weakReferences[j] = new WeakReference(o);
+ }
+ }
+ done = true;
+ }
+ }
+
+ static class ReaderThread extends Thread {
+ public void run() {
+ while (!done) {
+ for (int j = 0; j < weakReferences.length; ++j) {
+ keepAlive = weakReferences[j].get();
+ }
+ for (int j = 0; j < weakReferences.length; ++j) {
+ weakReferences[j].clear();
+ }
+ }
+ }
+ }
+}
diff --git a/test/616-cha-regression-proxy-method/expected.txt b/test/616-cha-regression-proxy-method/expected.txt
new file mode 100644
index 0000000..6a5618e
--- /dev/null
+++ b/test/616-cha-regression-proxy-method/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/616-cha-regression-proxy-method/info.txt b/test/616-cha-regression-proxy-method/info.txt
new file mode 100644
index 0000000..386a07f
--- /dev/null
+++ b/test/616-cha-regression-proxy-method/info.txt
@@ -0,0 +1 @@
+Regression test for Class Hierarchy Analysis (CHA) on visiting proxy method frame.
diff --git a/test/616-cha-regression-proxy-method/src/Main.java b/test/616-cha-regression-proxy-method/src/Main.java
new file mode 100644
index 0000000..19c92be
--- /dev/null
+++ b/test/616-cha-regression-proxy-method/src/Main.java
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+class Main1 {
+ void foo(int i) {
+ if (i != 1) {
+ printError("error1");
+ }
+ }
+
+ void printError(String msg) {
+ System.out.println(msg);
+ }
+}
+
+class Main2 extends Main1 {
+ void foo(int i) {
+ if (i != 2) {
+ printError("error2");
+ }
+ }
+}
+
+class Proxied implements Runnable {
+ public void run() {
+ synchronized(Main.class) {
+ Main.sOtherThreadStarted = true;
+ // Wait for Main2 to be linked and deoptimization is triggered.
+ try {
+ Main.class.wait();
+ } catch (Exception e) {
+ }
+ }
+ }
+}
+
+class MyInvocationHandler implements InvocationHandler {
+ private final Proxied proxied;
+
+ public MyInvocationHandler(Proxied proxied) {
+ this.proxied = proxied;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return method.invoke(proxied, args);
+ }
+}
+
+public class Main {
+ static Main1 sMain1;
+ static Main1 sMain2;
+ static volatile boolean sOtherThreadStarted;
+
+ // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
+ // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
+ // After Dummy.createMain2() which links in Main2, live testOverride() on stack
+ // should be deoptimized.
+ static void testOverride() {
+ sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
+
+ // Wait for the other thread to start.
+ while (!sOtherThreadStarted);
+ // Create an Main2 instance and assign it to sMain2.
+ // sMain1 is kept the same.
+ sMain2 = Dummy.createMain2();
+ // Wake up the other thread.
+ synchronized(Main.class) {
+ Main.class.notify();
+ }
+
+ // There should be a deoptimization here right after Main2 is linked by
+ // calling Dummy.createMain2(), even though sMain1 didn't change.
+ // The behavior here would be different if inline-cache is used, which
+ // doesn't deoptimize since sMain1 still hits the type cache.
+ sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
+ if (sMain2 != null) {
+ sMain2.foo(sMain2.getClass() == Main1.class ? 1 : 2);
+ }
+ }
+
+ // Test scenarios under which CHA-based devirtualization happens,
+ // and class loading that overrides a method can invalidate compiled code.
+ // Also create a proxy method such that a proxy method's frame is visited
+ // during stack walking.
+ public static void main(String[] args) {
+ System.loadLibrary(args[0]);
+ // sMain1 is an instance of Main1. Main2 hasn't bee loaded yet.
+ sMain1 = new Main1();
+
+ // Create another thread that calls a proxy method.
+ new Thread() {
+ public void run() {
+ Runnable proxy = (Runnable)Proxy.newProxyInstance(
+ Proxied.class.getClassLoader(),
+ new Class[] { Runnable.class },
+ new MyInvocationHandler(new Proxied()));
+ proxy.run();
+ }
+ }.start();
+
+ ensureJitCompiled(Main.class, "testOverride");
+ // This will create Main2 instance in the middle of testOverride().
+ testOverride();
+ }
+
+ private static native void ensureJitCompiled(Class<?> itf, String method_name);
+}
+
+// Put createMain2() in another class to avoid class loading due to verifier.
+class Dummy {
+ static Main1 createMain2() {
+ return new Main2();
+ }
+}
diff --git a/test/616-cha/src/Main.java b/test/616-cha/src/Main.java
index 787318d..b617944 100644
--- a/test/616-cha/src/Main.java
+++ b/test/616-cha/src/Main.java
@@ -179,7 +179,7 @@
}
}
- // Test scanerios under which CHA-based devirtualization happens,
+ // Test scenarios under which CHA-based devirtualization happens,
// and class loading that overrides a method can invalidate compiled code.
// Also test pure non-overriding case, which is more for checking generated
// code form.
@@ -206,11 +206,6 @@
// sMain1 is an instance of Main1. Main2 hasn't bee loaded yet.
sMain1 = new Main1();
- // Loop enough to get testOverride() JITed.
- for (int i=0; i<100; i++) {
- testOverride(false, false, false);
- }
-
ensureJitCompiled(Main.class, "testOverride");
testOverride(false, false, true);
@@ -244,7 +239,7 @@
private static native boolean hasSingleImplementation(Class<?> clazz, String method_name);
}
-// Do it in another class to avoid class loading due to verifier.
+// Put createMain2() in another class to avoid class loading due to verifier.
class Dummy {
static Main1 createMain2() {
return new Main2();
diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt
index 77c77ca..f8c97ce 100644
--- a/test/911-get-stack-trace/expected.txt
+++ b/test/911-get-stack-trace/expected.txt
@@ -3,206 +3,206 @@
###################
From top
---------
- getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1
- print (Ljava/lang/Thread;II)V 0
- printOrWait (IILMain$ControlData;)V 6
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- doTest ()V 38
- main ([Ljava/lang/String;)V 6
+ getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
+ print (Ljava/lang/Thread;II)V 0 124
+ printOrWait (IILMain$ControlData;)V 6 151
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ doTest ()V 38 34
+ main ([Ljava/lang/String;)V 6 24
---------
- print (Ljava/lang/Thread;II)V 0
- printOrWait (IILMain$ControlData;)V 6
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- doTest ()V 42
- main ([Ljava/lang/String;)V 6
+ print (Ljava/lang/Thread;II)V 0 124
+ printOrWait (IILMain$ControlData;)V 6 151
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ doTest ()V 42 35
+ main ([Ljava/lang/String;)V 6 24
---------
- getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1
- print (Ljava/lang/Thread;II)V 0
- printOrWait (IILMain$ControlData;)V 6
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
+ getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
+ print (Ljava/lang/Thread;II)V 0 124
+ printOrWait (IILMain$ControlData;)V 6 151
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
---------
- printOrWait (IILMain$ControlData;)V 6
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
+ printOrWait (IILMain$ControlData;)V 6 151
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
From bottom
---------
- main ([Ljava/lang/String;)V 6
+ main ([Ljava/lang/String;)V 6 24
---------
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- doTest ()V 65
- main ([Ljava/lang/String;)V 6
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ doTest ()V 65 41
+ main ([Ljava/lang/String;)V 6 24
---------
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
################################
### Other thread (suspended) ###
################################
From top
---------
- wait ()V -1
- printOrWait (IILMain$ControlData;)V 24
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- run ()V 4
+ wait ()V -1 -2
+ printOrWait (IILMain$ControlData;)V 24 157
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ run ()V 4 54
---------
- printOrWait (IILMain$ControlData;)V 24
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- run ()V 4
+ printOrWait (IILMain$ControlData;)V 24 157
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ run ()V 4 54
---------
- wait ()V -1
- printOrWait (IILMain$ControlData;)V 24
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
+ wait ()V -1 -2
+ printOrWait (IILMain$ControlData;)V 24 157
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
---------
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
From bottom
---------
- run ()V 4
+ run ()V 4 54
---------
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- run ()V 4
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ run ()V 4 54
---------
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
###########################
### Other thread (live) ###
###########################
From top
---------
- printOrWait (IILMain$ControlData;)V 44
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- run ()V 4
+ printOrWait (IILMain$ControlData;)V 44 164
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ run ()V 4 88
---------
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- run ()V 4
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ run ()V 4 88
---------
- printOrWait (IILMain$ControlData;)V 44
- baz (IIILMain$ControlData;)Ljava/lang/Object; 2
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
+ printOrWait (IILMain$ControlData;)V 44 164
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
---------
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
From bottom
---------
- run ()V 4
+ run ()V 4 88
---------
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- run ()V 4
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ run ()V 4 88
---------
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
- foo (IIILMain$ControlData;)I 0
- baz (IIILMain$ControlData;)Ljava/lang/Object; 9
- bar (IIILMain$ControlData;)J 0
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
+ foo (IIILMain$ControlData;)I 0 131
+ baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144
+ bar (IIILMain$ControlData;)J 0 136
diff --git a/test/911-get-stack-trace/stack_trace.cc b/test/911-get-stack-trace/stack_trace.cc
index b5b5678..9092f2f 100644
--- a/test/911-get-stack-trace/stack_trace.cc
+++ b/test/911-get-stack-trace/stack_trace.cc
@@ -32,6 +32,23 @@
namespace art {
namespace Test911GetStackTrace {
+static jint FindLineNumber(jint line_number_count,
+ jvmtiLineNumberEntry* line_number_table,
+ jlocation location) {
+ if (line_number_table == nullptr) {
+ return -2;
+ }
+
+ jint line_number = -1;
+ for (jint i = 0; i != line_number_count; ++i) {
+ if (line_number_table[i].start_location > location) {
+ return line_number;
+ }
+ line_number = line_number_table[i].line_number;
+ }
+ return line_number;
+}
+
extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace(
JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thread, jint start, jint max) {
std::unique_ptr<jvmtiFrameInfo[]> frames(new jvmtiFrameInfo[max]);
@@ -61,6 +78,26 @@
}
}
+ jint line_number_count;
+ jvmtiLineNumberEntry* line_number_table;
+ {
+ jvmtiError line_result = jvmti_env->GetLineNumberTable(frames[method_index].method,
+ &line_number_count,
+ &line_number_table);
+ if (line_result != JVMTI_ERROR_NONE) {
+ // Accept absent info and native method errors.
+ if (line_result != JVMTI_ERROR_ABSENT_INFORMATION &&
+ line_result != JVMTI_ERROR_NATIVE_METHOD) {
+ char* err;
+ jvmti_env->GetErrorName(line_result, &err);
+ printf("Failure running GetLineNumberTable: %s\n", err);
+ return nullptr;
+ }
+ line_number_table = nullptr;
+ line_number_count = 0;
+ }
+ }
+
auto inner_callback = [&](jint component_index) -> jstring {
switch (component_index) {
case 0:
@@ -69,11 +106,17 @@
return (sig == nullptr) ? nullptr : env->NewStringUTF(sig);
case 2:
return env->NewStringUTF(StringPrintf("%" PRId64, frames[method_index].location).c_str());
+ case 3: {
+ jint line_number = FindLineNumber(line_number_count,
+ line_number_table,
+ frames[method_index].location);
+ return env->NewStringUTF(StringPrintf("%d", line_number).c_str());
+ }
}
LOG(FATAL) << "Unreachable";
UNREACHABLE();
};
- jobjectArray inner_array = CreateObjectArray(env, 3, "java/lang/String", inner_callback);
+ jobjectArray inner_array = CreateObjectArray(env, 4, "java/lang/String", inner_callback);
if (name != nullptr) {
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(name));
@@ -84,6 +127,9 @@
if (gen != nullptr) {
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(gen));
}
+ if (line_number_table != nullptr) {
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(line_number_table));
+ }
return inner_array;
};
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index b515130..c02999b 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -492,6 +492,24 @@
$(PICTEST_TYPES),$(DEBUGGABLE_TYPES), $(TEST_ART_BROKEN_TRACING_RUN_TESTS),$(ALL_ADDRESS_SIZES))
endif
+TEST_ART_BROKEN_TRACING_RUN_TESTS :=
+
+# These tests expect JIT compilation, which is suppressed when tracing.
+TEST_ART_BROKEN_JIT_TRACING_RUN_TESTS := \
+ 604-hot-static-interface \
+ 612-jit-dex-cache \
+ 613-inlining-dex-cache \
+ 616-cha \
+ 626-set-resolved-string \
+
+ifneq (,$(filter trace stream,$(TRACE_TYPES)))
+ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
+ jit,$(RELOCATE_TYPES),trace stream,$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES), \
+ $(PICTEST_TYPES),$(DEBUGGABLE_TYPES), $(TEST_ART_BROKEN_JIT_TRACING_RUN_TESTS),$(ALL_ADDRESS_SIZES))
+endif
+
+TEST_ART_BROKEN_JIT_TRACING_RUN_TESTS :=
+
# Known broken tests for the interpreter.
# CFI unwinding expects managed frames.
# 629 requires compilation.