Merge "Fix longstanding bug around implicit NPEs and GC, version 2."
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index a13efca..a90ff3f 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -1394,37 +1394,12 @@
}
bool CodeGenerator::CanMoveNullCheckToUser(HNullCheck* null_check) {
- HInstruction* first_next_not_move = null_check->GetNextDisregardingMoves();
-
- return (first_next_not_move != nullptr)
- && first_next_not_move->CanDoImplicitNullCheckOn(null_check->InputAt(0));
+ return null_check->IsEmittedAtUseSite();
}
void CodeGenerator::MaybeRecordImplicitNullCheck(HInstruction* instr) {
- if (!compiler_options_.GetImplicitNullChecks()) {
- return;
- }
-
- // If we are from a static path don't record the pc as we can't throw NPE.
- // NB: having the checks here makes the code much less verbose in the arch
- // specific code generators.
- if (instr->IsStaticFieldSet() || instr->IsStaticFieldGet()) {
- return;
- }
-
- if (!instr->CanDoImplicitNullCheckOn(instr->InputAt(0))) {
- return;
- }
-
- // Find the first previous instruction which is not a move.
- HInstruction* first_prev_not_move = instr->GetPreviousDisregardingMoves();
-
- // If the instruction is a null check it means that `instr` is the first user
- // and needs to record the pc.
- if (first_prev_not_move != nullptr && first_prev_not_move->IsNullCheck()) {
- HNullCheck* null_check = first_prev_not_move->AsNullCheck();
- // TODO: The parallel moves modify the environment. Their changes need to be
- // reverted otherwise the stack maps at the throw point will not be correct.
+ HNullCheck* null_check = instr->GetImplicitNullCheck();
+ if (null_check != nullptr) {
RecordPcInfo(null_check, null_check->GetDexPc());
}
}
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 462225a..a460f77 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -5065,7 +5065,7 @@
return;
}
{
- // Ensure that between load and MaybeRecordImplicitNullCheck there are no pools emitted.
+ // Ensure that between load and RecordPcInfo there are no pools emitted.
EmissionCheckScope guard(GetVIXLAssembler(), kMaxMacroInstructionSizeInBytes);
Location obj = instruction->GetLocations()->InAt(0);
__ Ldr(wzr, HeapOperandFrom(obj, Offset(0)));
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index 86687e6..f186191 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -453,7 +453,7 @@
ASSERT_FALSE(equal->IsEmittedAtUseSite());
graph->BuildDominatorTree();
- PrepareForRegisterAllocation(graph).Run();
+ PrepareForRegisterAllocation(graph, *compiler_options_).Run();
ASSERT_TRUE(equal->IsEmittedAtUseSite());
auto hook_before_codegen = [](HGraph* graph_in) {
diff --git a/compiler/optimizing/codegen_test_utils.h b/compiler/optimizing/codegen_test_utils.h
index 9181126..8c062f0 100644
--- a/compiler/optimizing/codegen_test_utils.h
+++ b/compiler/optimizing/codegen_test_utils.h
@@ -288,7 +288,7 @@
{
ScopedArenaAllocator local_allocator(graph->GetArenaStack());
SsaLivenessAnalysis liveness(graph, codegen, &local_allocator);
- PrepareForRegisterAllocation(graph).Run();
+ PrepareForRegisterAllocation(graph, codegen->GetCompilerOptions()).Run();
liveness.Analyze();
std::unique_ptr<RegisterAllocator> register_allocator =
RegisterAllocator::Create(&local_allocator, codegen, liveness);
diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc
index 0fb90fb..60f513c 100644
--- a/compiler/optimizing/live_ranges_test.cc
+++ b/compiler/optimizing/live_ranges_test.cc
@@ -38,7 +38,7 @@
// on how instructions are ordered.
RemoveSuspendChecks(graph);
// `Inline` conditions into ifs.
- PrepareForRegisterAllocation(graph).Run();
+ PrepareForRegisterAllocation(graph, *compiler_options_).Run();
return graph;
}
diff --git a/compiler/optimizing/liveness_test.cc b/compiler/optimizing/liveness_test.cc
index 72f995e..f11f7a9 100644
--- a/compiler/optimizing/liveness_test.cc
+++ b/compiler/optimizing/liveness_test.cc
@@ -47,7 +47,7 @@
void LivenessTest::TestCode(const std::vector<uint16_t>& data, const char* expected) {
HGraph* graph = CreateCFG(data);
// `Inline` conditions into ifs.
- PrepareForRegisterAllocation(graph).Run();
+ PrepareForRegisterAllocation(graph, *compiler_options_).Run();
std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
liveness.Analyze();
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 8b9e1da..d88b036 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2079,6 +2079,19 @@
return false;
}
+ // If this instruction will do an implicit null check, return the `HNullCheck` associated
+ // with it. Otherwise return null.
+ HNullCheck* GetImplicitNullCheck() const {
+ // Find the first previous instruction which is not a move.
+ HInstruction* first_prev_not_move = GetPreviousDisregardingMoves();
+ if (first_prev_not_move != nullptr &&
+ first_prev_not_move->IsNullCheck() &&
+ first_prev_not_move->IsEmittedAtUseSite()) {
+ return first_prev_not_move->AsNullCheck();
+ }
+ return nullptr;
+ }
+
virtual bool IsActualObject() const {
return GetType() == DataType::Type::kReference;
}
@@ -4713,7 +4726,7 @@
bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
// TODO: Add implicit null checks in intrinsics.
- return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
+ return (obj == InputAt(0)) && !IsIntrinsic();
}
uint32_t GetVTableIndex() const { return vtable_index_; }
@@ -4753,7 +4766,7 @@
bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
// TODO: Add implicit null checks in intrinsics.
- return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
+ return (obj == InputAt(0)) && !IsIntrinsic();
}
bool NeedsDexCacheOfDeclaringClass() const OVERRIDE {
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index c40cbcf..f52b96d 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -570,7 +570,7 @@
{
PassScope scope(PrepareForRegisterAllocation::kPrepareForRegisterAllocationPassName,
pass_observer);
- PrepareForRegisterAllocation(graph, stats).Run();
+ PrepareForRegisterAllocation(graph, codegen->GetCompilerOptions(), stats).Run();
}
// Use local allocator shared by SSA liveness analysis and register allocator.
// (Register allocator creates new objects in the liveness data.)
diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc
index 060613d..fc81740 100644
--- a/compiler/optimizing/prepare_for_register_allocation.cc
+++ b/compiler/optimizing/prepare_for_register_allocation.cc
@@ -17,6 +17,7 @@
#include "prepare_for_register_allocation.h"
#include "dex/dex_file_types.h"
+#include "driver/compiler_options.h"
#include "jni/jni_internal.h"
#include "optimizing_compiler_stats.h"
#include "well_known_classes.h"
@@ -27,7 +28,7 @@
// Order does not matter.
for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
// No need to visit the phis.
- for (HInstructionIterator inst_it(block->GetInstructions()); !inst_it.Done();
+ for (HInstructionIteratorHandleChanges inst_it(block->GetInstructions()); !inst_it.Done();
inst_it.Advance()) {
inst_it.Current()->Accept(this);
}
@@ -50,6 +51,19 @@
void PrepareForRegisterAllocation::VisitNullCheck(HNullCheck* check) {
check->ReplaceWith(check->InputAt(0));
+ if (compiler_options_.GetImplicitNullChecks()) {
+ HInstruction* next = check->GetNext();
+
+ // The `PrepareForRegisterAllocation` pass removes `HBoundType` from the graph,
+ // so do it ourselves now to not prevent optimizations.
+ while (next->IsBoundType()) {
+ next = next->GetNext();
+ VisitBoundType(next->GetPrevious()->AsBoundType());
+ }
+ if (next->CanDoImplicitNullCheckOn(check->InputAt(0))) {
+ check->MarkEmittedAtUseSite();
+ }
+ }
}
void PrepareForRegisterAllocation::VisitDivZeroCheck(HDivZeroCheck* check) {
diff --git a/compiler/optimizing/prepare_for_register_allocation.h b/compiler/optimizing/prepare_for_register_allocation.h
index f6e4d3e..2978add 100644
--- a/compiler/optimizing/prepare_for_register_allocation.h
+++ b/compiler/optimizing/prepare_for_register_allocation.h
@@ -21,6 +21,7 @@
namespace art {
+class CompilerOptions;
class OptimizingCompilerStats;
/**
@@ -30,9 +31,11 @@
*/
class PrepareForRegisterAllocation : public HGraphDelegateVisitor {
public:
- explicit PrepareForRegisterAllocation(HGraph* graph,
- OptimizingCompilerStats* stats = nullptr)
- : HGraphDelegateVisitor(graph, stats) {}
+ PrepareForRegisterAllocation(HGraph* graph,
+ const CompilerOptions& compiler_options,
+ OptimizingCompilerStats* stats = nullptr)
+ : HGraphDelegateVisitor(graph, stats),
+ compiler_options_(compiler_options) {}
void Run();
@@ -56,6 +59,8 @@
bool CanMoveClinitCheck(HInstruction* input, HInstruction* user) const;
bool CanEmitConditionAt(HCondition* condition, HInstruction* user) const;
+ const CompilerOptions& compiler_options_;
+
DISALLOW_COPY_AND_ASSIGN(PrepareForRegisterAllocation);
};
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 2f782f3..62a70d6 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -103,9 +103,9 @@
ComputeLiveInAndLiveOutSets();
}
-static void RecursivelyProcessInputs(HInstruction* current,
- HInstruction* actual_user,
- BitVector* live_in) {
+void SsaLivenessAnalysis::RecursivelyProcessInputs(HInstruction* current,
+ HInstruction* actual_user,
+ BitVector* live_in) {
HInputsRef inputs = current->GetInputs();
for (size_t i = 0; i < inputs.size(); ++i) {
HInstruction* input = inputs[i];
@@ -131,11 +131,40 @@
// Check that the inlined input is not a phi. Recursing on loop phis could
// lead to an infinite loop.
DCHECK(!input->IsPhi());
+ DCHECK(!input->HasEnvironment());
RecursivelyProcessInputs(input, actual_user, live_in);
}
}
}
+void SsaLivenessAnalysis::ProcessEnvironment(HInstruction* current,
+ HInstruction* actual_user,
+ BitVector* live_in) {
+ for (HEnvironment* environment = current->GetEnvironment();
+ environment != nullptr;
+ environment = environment->GetParent()) {
+ // Handle environment uses. See statements (b) and (c) of the
+ // SsaLivenessAnalysis.
+ for (size_t i = 0, e = environment->Size(); i < e; ++i) {
+ HInstruction* instruction = environment->GetInstructionAt(i);
+ if (instruction == nullptr) {
+ continue;
+ }
+ bool should_be_live = ShouldBeLiveForEnvironment(current, instruction);
+ // If this environment use does not keep the instruction live, it does not
+ // affect the live range of that instruction.
+ if (should_be_live) {
+ CHECK(instruction->HasSsaIndex()) << instruction->DebugName();
+ live_in->SetBit(instruction->GetSsaIndex());
+ instruction->GetLiveInterval()->AddUse(current,
+ environment,
+ i,
+ actual_user);
+ }
+ }
+ }
+}
+
void SsaLivenessAnalysis::ComputeLiveRanges() {
// Do a post order visit, adding inputs of instructions live in the block where
// that instruction is defined, and killing instructions that are being visited.
@@ -186,32 +215,6 @@
current->GetLiveInterval()->SetFrom(current->GetLifetimePosition());
}
- // Process the environment first, because we know their uses come after
- // or at the same liveness position of inputs.
- for (HEnvironment* environment = current->GetEnvironment();
- environment != nullptr;
- environment = environment->GetParent()) {
- // Handle environment uses. See statements (b) and (c) of the
- // SsaLivenessAnalysis.
- for (size_t i = 0, e = environment->Size(); i < e; ++i) {
- HInstruction* instruction = environment->GetInstructionAt(i);
- if (instruction == nullptr) {
- continue;
- }
- bool should_be_live = ShouldBeLiveForEnvironment(current, instruction);
- // If this environment use does not keep the instruction live, it does not
- // affect the live range of that instruction.
- if (should_be_live) {
- CHECK(instruction->HasSsaIndex()) << instruction->DebugName();
- live_in->SetBit(instruction->GetSsaIndex());
- instruction->GetLiveInterval()->AddUse(current,
- environment,
- i,
- /* actual_user */ nullptr);
- }
- }
- }
-
// Process inputs of instructions.
if (current->IsEmittedAtUseSite()) {
if (kIsDebugBuild) {
@@ -224,6 +227,16 @@
DCHECK(!current->HasEnvironmentUses());
}
} else {
+ // Process the environment first, because we know their uses come after
+ // or at the same liveness position of inputs.
+ ProcessEnvironment(current, current, live_in);
+
+ // Special case implicit null checks. We want their environment uses to be
+ // emitted at the instruction doing the actual null check.
+ HNullCheck* check = current->GetImplicitNullCheck();
+ if (check != nullptr) {
+ ProcessEnvironment(check, current, live_in);
+ }
RecursivelyProcessInputs(current, current, live_in);
}
}
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 83ca5bd..cebd4ad 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -1252,6 +1252,13 @@
// Update the live_out set of the block and returns whether it has changed.
bool UpdateLiveOut(const HBasicBlock& block);
+ static void ProcessEnvironment(HInstruction* instruction,
+ HInstruction* actual_user,
+ BitVector* live_in);
+ static void RecursivelyProcessInputs(HInstruction* instruction,
+ HInstruction* actual_user,
+ BitVector* live_in);
+
// Returns whether `instruction` in an HEnvironment held by `env_holder`
// should be kept live by the HEnvironment.
static bool ShouldBeLiveForEnvironment(HInstruction* env_holder, HInstruction* instruction) {
diff --git a/test/565-checker-condition-liveness/src/Main.java b/test/565-checker-condition-liveness/src/Main.java
index 6b6619f..374e136 100644
--- a/test/565-checker-condition-liveness/src/Main.java
+++ b/test/565-checker-condition-liveness/src/Main.java
@@ -32,20 +32,20 @@
}
/// CHECK-START: void Main.testThrowIntoCatchBlock(int, java.lang.Object, int[]) liveness (after)
- /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[21,25]
- /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,21,25]
- /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,21,25]
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[21,25]
+ /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[25]
+ /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,25]
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,25]
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[25]
/// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10
/// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20
/// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24
/// CHECK-DAG: TryBoundary
/// CHECK-START-DEBUGGABLE: void Main.testThrowIntoCatchBlock(int, java.lang.Object, int[]) liveness (after)
- /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[11,21,25]
- /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,21,25]
- /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,21,25]
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[21,25]
+ /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[11,25]
+ /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,25]
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,25]
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[25]
/// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10
/// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20
/// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24
@@ -62,18 +62,18 @@
/// CHECK-START: void Main.testBoundsCheck(int, java.lang.Object, int[]) liveness (after)
/// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[]
- /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,17,21]
- /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,17,21]
+ /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,21]
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,21]
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[]
/// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10
/// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:16
/// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20
/// CHECK-START-DEBUGGABLE: void Main.testBoundsCheck(int, java.lang.Object, int[]) liveness (after)
- /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[11,17,21]
- /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,17,21]
- /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,17,21]
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[17,21]
+ /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[11,21]
+ /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,21]
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,21]
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[21]
/// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10
/// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:16
/// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20
@@ -83,20 +83,22 @@
/// CHECK-START: void Main.testDeoptimize(int, java.lang.Object, int[]) liveness (after)
/// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[25]
- /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[13,19,25]
- /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[13,19,25]
+ /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[13,21,25]
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[13,21,25]
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 env_uses:[25]
/// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:12
/// CHECK-DAG: NullCheck env:[[<<Const0>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:18
+ /// CHECK-DAG: ArrayLength liveness:20
/// CHECK-DAG: Deoptimize env:[[<<Const0>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24
/// CHECK-START-DEBUGGABLE: void Main.testDeoptimize(int, java.lang.Object, int[]) liveness (after)
- /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[13,19,25]
- /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[13,19,25]
- /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[13,19,25]
+ /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[13,21,25]
+ /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[13,21,25]
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[13,21,25]
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 env_uses:[19,25]
/// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:12
/// CHECK-DAG: NullCheck env:[[<<Const0>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:18
+ /// CHECK-DAG: ArrayLength liveness:20
/// CHECK-DAG: Deoptimize env:[[<<Const0>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24
//
// A value that's not live in compiled code may still be needed in interpreter,
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 9ade2b1..a280f85 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1039,12 +1039,6 @@
"description": ["Test timing out under gcstress possibly due to slower unwinding by libbacktrace"]
},
{
- "tests": ["624-checker-stringops"],
- "variant": "optimizing & gcstress | speed-profile & gcstress",
- "bug": "b/111545159",
- "description": ["Seem to expose some error with our gc when run in these configurations"]
- },
- {
"tests": ["021-string2"],
"variant": "jit & debuggable",
"bug": "b/109791792",
diff --git a/tools/libcore_gcstress_failures.txt b/tools/libcore_gcstress_failures.txt
index 6840f9e..965e85c 100644
--- a/tools/libcore_gcstress_failures.txt
+++ b/tools/libcore_gcstress_failures.txt
@@ -33,15 +33,5 @@
"org.apache.harmony.tests.java.util.WeakHashMapTest#test_keySet_hasNext",
"libcore.java.text.DecimalFormatTest#testCurrencySymbolSpacing",
"libcore.java.text.SimpleDateFormatTest#testLocales"]
-},
-{
- description: "GC crash",
- result: EXEC_FAILED,
- bug: 111545159,
- names: ["org.apache.harmony.tests.java.util.AbstractSequentialListTest#test_addAllILjava_util_Collection",
- "org.apache.harmony.tests.java.util.HashtableTest#test_putLjava_lang_ObjectLjava_lang_Object",
- "org.apache.harmony.tests.java.util.VectorTest#test_addAllILjava_util_Collection",
- "org.apache.harmony.tests.java.util.VectorTest#test_addAllLjava_util_Collection",
- "org.apache.harmony.tests.java.io.BufferedWriterTest#test_write_LStringII_Exception"]
}
]