Merge "Temporarily use -fstack-protector for the read barrier config."
diff --git a/cmdline/cmdline_parser_test.cc b/cmdline/cmdline_parser_test.cc
index fe83ba9..dc2c9c9 100644
--- a/cmdline/cmdline_parser_test.cc
+++ b/cmdline/cmdline_parser_test.cc
@@ -535,7 +535,7 @@
/* -Xexperimental:_ */
TEST_F(CmdlineParserTest, TestExperimentalFlags) {
- // Off by default
+ // Default
EXPECT_SINGLE_PARSE_DEFAULT_VALUE(ExperimentalFlags::kNone,
"",
M::Experimental);
@@ -549,16 +549,6 @@
EXPECT_SINGLE_PARSE_VALUE(ExperimentalFlags::kLambdas,
"-Xexperimental:lambdas",
M::Experimental);
- // Enabled explicitly
- EXPECT_SINGLE_PARSE_VALUE(ExperimentalFlags::kDefaultMethods,
- "-Xexperimental:default-methods",
- M::Experimental);
-
- // Enabled both
- EXPECT_SINGLE_PARSE_VALUE(ExperimentalFlags::kDefaultMethods | ExperimentalFlags::kLambdas,
- "-Xexperimental:default-methods "
- "-Xexperimental:lambdas",
- M::Experimental);
}
// -Xverify:_
diff --git a/cmdline/cmdline_types.h b/cmdline/cmdline_types.h
index 97c672c..740199d 100644
--- a/cmdline/cmdline_types.h
+++ b/cmdline/cmdline_types.h
@@ -847,11 +847,9 @@
struct CmdlineType<ExperimentalFlags> : CmdlineTypeParser<ExperimentalFlags> {
Result ParseAndAppend(const std::string& option, ExperimentalFlags& existing) {
if (option == "none") {
- existing = existing | ExperimentalFlags::kNone;
+ existing = ExperimentalFlags::kNone;
} else if (option == "lambdas") {
existing = existing | ExperimentalFlags::kLambdas;
- } else if (option == "default-methods") {
- existing = existing | ExperimentalFlags::kDefaultMethods;
} else {
return Result::Failure(std::string("Unknown option '") + option + "'");
}
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 4589736..6f32e07 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -258,9 +258,9 @@
ifeq ($$(art_ndebug_or_debug),ndebug)
LOCAL_MODULE := libart-compiler
ifeq ($$(art_static_or_shared), static)
- LOCAL_STATIC_LIBRARIES += libart liblz4
+ LOCAL_STATIC_LIBRARIES += libart liblz4 liblzma
else
- LOCAL_SHARED_LIBRARIES += libart liblz4
+ LOCAL_SHARED_LIBRARIES += libart liblz4 liblzma
endif
ifeq ($$(art_target_or_host),target)
LOCAL_FDO_SUPPORT := true
@@ -268,9 +268,9 @@
else # debug
LOCAL_MODULE := libartd-compiler
ifeq ($$(art_static_or_shared), static)
- LOCAL_STATIC_LIBRARIES += libartd liblz4
+ LOCAL_STATIC_LIBRARIES += libartd liblz4 liblzma
else
- LOCAL_SHARED_LIBRARIES += libartd liblz4
+ LOCAL_SHARED_LIBRARIES += libartd liblz4 liblzma
endif
endif
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index 3766093..22b178c 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -37,13 +37,21 @@
static constexpr bool kIntrinsicIsStatic[] = {
true, // kIntrinsicDoubleCvt
true, // kIntrinsicFloatCvt
+ true, // kIntrinsicFloatIsInfinite
+ true, // kIntrinsicDoubleIsInfinite
+ true, // kIntrinsicFloatIsNaN
+ true, // kIntrinsicDoubleIsNaN
true, // kIntrinsicReverseBits
true, // kIntrinsicReverseBytes
true, // kIntrinsicBitCount
+ true, // kIntrinsicCompare,
+ true, // kIntrinsicHighestOneBit
+ true, // kIntrinsicLowestOneBit
true, // kIntrinsicNumberOfLeadingZeros
true, // kIntrinsicNumberOfTrailingZeros
true, // kIntrinsicRotateRight
true, // kIntrinsicRotateLeft
+ true, // kIntrinsicSignum
true, // kIntrinsicAbsInt
true, // kIntrinsicAbsLong
true, // kIntrinsicAbsFloat
@@ -98,15 +106,23 @@
"arraysize of kIntrinsicIsStatic unexpected");
static_assert(kIntrinsicIsStatic[kIntrinsicDoubleCvt], "DoubleCvt must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicFloatCvt], "FloatCvt must be static");
+static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsInfinite], "FloatIsInfinite must be static");
+static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsInfinite], "DoubleIsInfinite must be static");
+static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsNaN], "FloatIsNaN must be static");
+static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsNaN], "DoubleIsNaN must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicReverseBits], "ReverseBits must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicReverseBytes], "ReverseBytes must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicBitCount], "BitCount must be static");
+static_assert(kIntrinsicIsStatic[kIntrinsicCompare], "Compare must be static");
+static_assert(kIntrinsicIsStatic[kIntrinsicHighestOneBit], "HighestOneBit must be static");
+static_assert(kIntrinsicIsStatic[kIntrinsicLowestOneBit], "LowestOneBit must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfLeadingZeros],
"NumberOfLeadingZeros must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfTrailingZeros],
"NumberOfTrailingZeros must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicRotateRight], "RotateRight must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicRotateLeft], "RotateLeft must be static");
+static_assert(kIntrinsicIsStatic[kIntrinsicSignum], "Signum must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicAbsInt], "AbsInt must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicAbsLong], "AbsLong must be static");
static_assert(kIntrinsicIsStatic[kIntrinsicAbsFloat], "AbsFloat must be static");
@@ -261,6 +277,8 @@
"equals", // kNameCacheEquals
"getCharsNoCheck", // kNameCacheGetCharsNoCheck
"isEmpty", // kNameCacheIsEmpty
+ "isInfinite", // kNameCacheIsInfinite
+ "isNaN", // kNameCacheIsNaN
"indexOf", // kNameCacheIndexOf
"length", // kNameCacheLength
"<init>", // kNameCacheInit
@@ -296,10 +314,14 @@
"putOrderedObject", // kNameCachePutOrderedObject
"arraycopy", // kNameCacheArrayCopy
"bitCount", // kNameCacheBitCount
+ "compare", // kNameCacheCompare
+ "highestOneBit", // kNameCacheHighestOneBit
+ "lowestOneBit", // kNameCacheLowestOneBit
"numberOfLeadingZeros", // kNameCacheNumberOfLeadingZeros
"numberOfTrailingZeros", // kNameCacheNumberOfTrailingZeros
"rotateRight", // kNameCacheRotateRight
"rotateLeft", // kNameCacheRotateLeft
+ "signum", // kNameCacheSignum
};
const DexFileMethodInliner::ProtoDef DexFileMethodInliner::kProtoCacheDefs[] = {
@@ -319,10 +341,14 @@
{ kClassCacheFloat, 2, { kClassCacheFloat, kClassCacheFloat } },
// kProtoCacheD_J
{ kClassCacheLong, 1, { kClassCacheDouble } },
+ // kProtoCacheD_Z
+ { kClassCacheBoolean, 1, { kClassCacheDouble } },
// kProtoCacheJ_D
{ kClassCacheDouble, 1, { kClassCacheLong } },
// kProtoCacheF_I
{ kClassCacheInt, 1, { kClassCacheFloat } },
+ // kProtoCacheF_Z
+ { kClassCacheBoolean, 1, { kClassCacheFloat } },
// kProtoCacheI_F
{ kClassCacheFloat, 1, { kClassCacheInt } },
// kProtoCacheII_I
@@ -351,6 +377,8 @@
{ kClassCacheVoid, 2, { kClassCacheLong, kClassCacheInt } },
// kProtoCacheJJ_J
{ kClassCacheLong, 2, { kClassCacheLong, kClassCacheLong } },
+ // kProtoCacheJJ_I
+ { kClassCacheInt, 2, { kClassCacheLong, kClassCacheLong } },
// kProtoCacheJJ_V
{ kClassCacheVoid, 2, { kClassCacheLong, kClassCacheLong } },
// kProtoCacheJS_V
@@ -444,6 +472,11 @@
INTRINSIC(JavaLangFloat, FloatToRawIntBits, F_I, kIntrinsicFloatCvt, 0),
INTRINSIC(JavaLangFloat, IntBitsToFloat, I_F, kIntrinsicFloatCvt, kIntrinsicFlagToFloatingPoint),
+ INTRINSIC(JavaLangFloat, IsInfinite, F_Z, kIntrinsicFloatIsInfinite, 0),
+ INTRINSIC(JavaLangDouble, IsInfinite, D_Z, kIntrinsicDoubleIsInfinite, 0),
+ INTRINSIC(JavaLangFloat, IsNaN, F_Z, kIntrinsicFloatIsNaN, 0),
+ INTRINSIC(JavaLangDouble, IsNaN, D_Z, kIntrinsicDoubleIsNaN, 0),
+
INTRINSIC(JavaLangInteger, ReverseBytes, I_I, kIntrinsicReverseBytes, k32),
INTRINSIC(JavaLangLong, ReverseBytes, J_J, kIntrinsicReverseBytes, k64),
INTRINSIC(JavaLangShort, ReverseBytes, S_S, kIntrinsicReverseBytes, kSignedHalf),
@@ -452,10 +485,18 @@
INTRINSIC(JavaLangInteger, BitCount, I_I, kIntrinsicBitCount, k32),
INTRINSIC(JavaLangLong, BitCount, J_I, kIntrinsicBitCount, k64),
+ INTRINSIC(JavaLangInteger, Compare, II_I, kIntrinsicCompare, k32),
+ INTRINSIC(JavaLangLong, Compare, JJ_I, kIntrinsicCompare, k64),
+ INTRINSIC(JavaLangInteger, HighestOneBit, I_I, kIntrinsicHighestOneBit, k32),
+ INTRINSIC(JavaLangLong, HighestOneBit, J_J, kIntrinsicHighestOneBit, k64),
+ INTRINSIC(JavaLangInteger, LowestOneBit, I_I, kIntrinsicLowestOneBit, k32),
+ INTRINSIC(JavaLangLong, LowestOneBit, J_J, kIntrinsicLowestOneBit, k64),
INTRINSIC(JavaLangInteger, NumberOfLeadingZeros, I_I, kIntrinsicNumberOfLeadingZeros, k32),
INTRINSIC(JavaLangLong, NumberOfLeadingZeros, J_I, kIntrinsicNumberOfLeadingZeros, k64),
INTRINSIC(JavaLangInteger, NumberOfTrailingZeros, I_I, kIntrinsicNumberOfTrailingZeros, k32),
INTRINSIC(JavaLangLong, NumberOfTrailingZeros, J_I, kIntrinsicNumberOfTrailingZeros, k64),
+ INTRINSIC(JavaLangInteger, Signum, I_I, kIntrinsicSignum, k32),
+ INTRINSIC(JavaLangLong, Signum, J_I, kIntrinsicSignum, k64),
INTRINSIC(JavaLangMath, Abs, I_I, kIntrinsicAbsInt, 0),
INTRINSIC(JavaLangStrictMath, Abs, I_I, kIntrinsicAbsInt, 0),
@@ -750,11 +791,19 @@
intrinsic.d.data & kIntrinsicFlagIsOrdered);
case kIntrinsicSystemArrayCopyCharArray:
return backend->GenInlinedArrayCopyCharArray(info);
+ case kIntrinsicFloatIsInfinite:
+ case kIntrinsicDoubleIsInfinite:
+ case kIntrinsicFloatIsNaN:
+ case kIntrinsicDoubleIsNaN:
case kIntrinsicBitCount:
+ case kIntrinsicCompare:
+ case kIntrinsicHighestOneBit:
+ case kIntrinsicLowestOneBit:
case kIntrinsicNumberOfLeadingZeros:
case kIntrinsicNumberOfTrailingZeros:
case kIntrinsicRotateRight:
case kIntrinsicRotateLeft:
+ case kIntrinsicSignum:
case kIntrinsicSystemArrayCopy:
return false; // not implemented in quick.
default:
diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h
index 2803623..59b8a53 100644
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ b/compiler/dex/quick/dex_file_method_inliner.h
@@ -190,6 +190,8 @@
kNameCacheEquals,
kNameCacheGetCharsNoCheck,
kNameCacheIsEmpty,
+ kNameCacheIsInfinite,
+ kNameCacheIsNaN,
kNameCacheIndexOf,
kNameCacheLength,
kNameCacheInit,
@@ -225,10 +227,14 @@
kNameCachePutOrderedObject,
kNameCacheArrayCopy,
kNameCacheBitCount,
+ kNameCacheCompare,
+ kNameCacheHighestOneBit,
+ kNameCacheLowestOneBit,
kNameCacheNumberOfLeadingZeros,
kNameCacheNumberOfTrailingZeros,
kNameCacheRotateRight,
kNameCacheRotateLeft,
+ kNameCacheSignum,
kNameCacheLast
};
@@ -247,8 +253,10 @@
kProtoCacheF_F,
kProtoCacheFF_F,
kProtoCacheD_J,
+ kProtoCacheD_Z,
kProtoCacheJ_D,
kProtoCacheF_I,
+ kProtoCacheF_Z,
kProtoCacheI_F,
kProtoCacheII_I,
kProtoCacheI_C,
@@ -263,6 +271,7 @@
kProtoCacheJB_V,
kProtoCacheJI_V,
kProtoCacheJJ_J,
+ kProtoCacheJJ_I,
kProtoCacheJJ_V,
kProtoCacheJS_V,
kProtoCacheObject_Z,
diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc
index ebc9a2c..027290f 100644
--- a/compiler/dex/quick/quick_compiler.cc
+++ b/compiler/dex/quick/quick_compiler.cc
@@ -486,11 +486,6 @@
static_assert(sizeof(kUnsupportedOpcodesSize) == 8 * sizeof(size_t),
"kUnsupportedOpcodesSize unexpected");
-static bool IsUnsupportedExperimentalLambdasOnly(size_t i) {
- DCHECK_LE(i, arraysize(kUnsupportedOpcodes));
- return kUnsupportedOpcodes[i] == kUnsupportedLambdaOpcodes;
-}
-
// The maximum amount of Dalvik register in a method for which we will start compiling. Tries to
// avoid an abort when we need to manage more SSA registers than we can.
static constexpr size_t kMaxAllowedDalvikRegisters = INT16_MAX / 2;
@@ -513,36 +508,6 @@
return true;
}
-// If the ISA has unsupported opcodes, should we skip scanning over them?
-//
-// Most of the time we're compiling non-experimental files, so scanning just slows
-// performance down by as much as 6% with 4 threads.
-// In the rare cases we compile experimental opcodes, the runtime has an option to enable it,
-// which will force scanning for any unsupported opcodes.
-static bool SkipScanningUnsupportedOpcodes(InstructionSet instruction_set) {
- Runtime* runtime = Runtime::Current();
- if (UNLIKELY(runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods))) {
- // Always need to scan opcodes if we have default methods since invoke-super for interface
- // methods is never going to be supported in the quick compiler.
- return false;
- } else if (UNLIKELY(kUnsupportedOpcodesSize[instruction_set] == 0U)) {
- // All opcodes are supported no matter what. Usually not the case
- // since experimental opcodes are not implemented in the quick compiler.
- return true;
- } else if (LIKELY(!Runtime::Current()->
- AreExperimentalFlagsEnabled(ExperimentalFlags::kLambdas))) {
- // Experimental opcodes are disabled.
- //
- // If all unsupported opcodes are experimental we don't need to do scanning.
- return IsUnsupportedExperimentalLambdasOnly(instruction_set);
- } else {
- // Experimental opcodes are enabled.
- //
- // Do the opcode scanning if the ISA has any unsupported opcodes.
- return false;
- }
-}
-
bool QuickCompiler::CanCompileInstruction(const MIR* mir,
const DexFile& dex_file) const {
switch (mir->dalvikInsn.opcode) {
@@ -572,11 +537,8 @@
return false;
}
- // Check whether we do have limitations at all.
- if (kSupportedTypes[cu->instruction_set] == nullptr &&
- SkipScanningUnsupportedOpcodes(cu->instruction_set)) {
- return true;
- }
+ // Since the quick compiler doesn't (and never will) support default methods we always need to
+ // scan opcodes.
// Check if we can compile the prototype.
const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index a64c9f1..73e6aa3 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -1158,9 +1158,13 @@
for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(); s++) {
StackMap stack_map = code_info.GetStackMapAt(s, encoding);
DCHECK(stack_map.IsValid());
- const uint32_t pc = stack_map.GetNativePcOffset(encoding);
- const int32_t dex = stack_map.GetDexPc(encoding);
- src_mapping_table_from_stack_maps.push_back({pc, dex});
+ // Emit only locations where we have local-variable information.
+ // In particular, skip mappings inside the prologue.
+ if (stack_map.HasDexRegisterMap(encoding)) {
+ const uint32_t pc = stack_map.GetNativePcOffset(encoding);
+ const int32_t dex = stack_map.GetDexPc(encoding);
+ src_mapping_table_from_stack_maps.push_back({pc, dex});
+ }
}
std::sort(src_mapping_table_from_stack_maps.begin(),
src_mapping_table_from_stack_maps.end());
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index b841675..b65fb36 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -181,7 +181,7 @@
ASSERT_NE(0U, bitmap_section.Size());
gc::Heap* heap = Runtime::Current()->GetHeap();
- ASSERT_TRUE(!heap->GetContinuousSpaces().empty());
+ ASSERT_TRUE(heap->HaveContinuousSpaces());
gc::space::ContinuousSpace* space = heap->GetNonMovingSpace();
ASSERT_FALSE(space->IsImageSpace());
ASSERT_TRUE(space != nullptr);
diff --git a/compiler/optimizing/bounds_check_elimination.h b/compiler/optimizing/bounds_check_elimination.h
index b9df686..6dc5320 100644
--- a/compiler/optimizing/bounds_check_elimination.h
+++ b/compiler/optimizing/bounds_check_elimination.h
@@ -29,13 +29,13 @@
BoundsCheckElimination(HGraph* graph,
const SideEffectsAnalysis& side_effects,
HInductionVarAnalysis* induction_analysis)
- : HOptimization(graph, kBoundsCheckEliminiationPassName),
+ : HOptimization(graph, kBoundsCheckEliminationPassName),
side_effects_(side_effects),
induction_analysis_(induction_analysis) {}
void Run() OVERRIDE;
- static constexpr const char* kBoundsCheckEliminiationPassName = "BCE";
+ static constexpr const char* kBoundsCheckEliminationPassName = "BCE";
private:
const SideEffectsAnalysis& side_effects_;
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 32c3a92..2805162 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -21,6 +21,7 @@
#include <cctype>
#include <sstream>
+#include "bounds_check_elimination.h"
#include "code_generator.h"
#include "dead_code_elimination.h"
#include "disassembler.h"
@@ -505,6 +506,7 @@
if (IsPass(LICM::kLoopInvariantCodeMotionPassName)
|| IsPass(HDeadCodeElimination::kFinalDeadCodeEliminationPassName)
|| IsPass(HDeadCodeElimination::kInitialDeadCodeEliminationPassName)
+ || IsPass(BoundsCheckElimination::kBoundsCheckEliminationPassName)
|| IsPass(SsaBuilder::kSsaBuilderPassName)) {
HLoopInformation* info = instruction->GetBlock()->GetLoopInformation();
if (info == nullptr) {
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 5caf077..a6be324 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -131,6 +131,16 @@
return ((method.d.data & kIntrinsicFlagToFloatingPoint) == 0) ?
Intrinsics::kFloatFloatToRawIntBits : Intrinsics::kFloatIntBitsToFloat;
+ // Floating-point tests.
+ case kIntrinsicFloatIsInfinite:
+ return Intrinsics::kFloatIsInfinite;
+ case kIntrinsicDoubleIsInfinite:
+ return Intrinsics::kDoubleIsInfinite;
+ case kIntrinsicFloatIsNaN:
+ return Intrinsics::kFloatIsNaN;
+ case kIntrinsicDoubleIsNaN:
+ return Intrinsics::kDoubleIsNaN;
+
// Bit manipulations.
case kIntrinsicReverseBits:
switch (GetType(method.d.data, true)) {
@@ -186,6 +196,36 @@
LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
UNREACHABLE();
}
+ case kIntrinsicCompare:
+ switch (GetType(method.d.data, true)) {
+ case Primitive::kPrimInt:
+ return Intrinsics::kIntegerCompare;
+ case Primitive::kPrimLong:
+ return Intrinsics::kLongCompare;
+ default:
+ LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
+ UNREACHABLE();
+ }
+ case kIntrinsicHighestOneBit:
+ switch (GetType(method.d.data, true)) {
+ case Primitive::kPrimInt:
+ return Intrinsics::kIntegerHighestOneBit;
+ case Primitive::kPrimLong:
+ return Intrinsics::kLongHighestOneBit;
+ default:
+ LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
+ UNREACHABLE();
+ }
+ case kIntrinsicLowestOneBit:
+ switch (GetType(method.d.data, true)) {
+ case Primitive::kPrimInt:
+ return Intrinsics::kIntegerLowestOneBit;
+ case Primitive::kPrimLong:
+ return Intrinsics::kLongLowestOneBit;
+ default:
+ LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
+ UNREACHABLE();
+ }
case kIntrinsicNumberOfLeadingZeros:
switch (GetType(method.d.data, true)) {
case Primitive::kPrimInt:
@@ -206,6 +246,16 @@
LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
UNREACHABLE();
}
+ case kIntrinsicSignum:
+ switch (GetType(method.d.data, true)) {
+ case Primitive::kPrimInt:
+ return Intrinsics::kIntegerSignum;
+ case Primitive::kPrimLong:
+ return Intrinsics::kLongSignum;
+ default:
+ LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
+ UNREACHABLE();
+ }
// Abs.
case kIntrinsicAbsDouble:
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index e72f927..97fe587 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -1580,13 +1580,9 @@
UNIMPLEMENTED_INTRINSIC(IntegerBitCount)
UNIMPLEMENTED_INTRINSIC(IntegerReverse)
UNIMPLEMENTED_INTRINSIC(IntegerReverseBytes)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
UNIMPLEMENTED_INTRINSIC(LongBitCount)
UNIMPLEMENTED_INTRINSIC(LongReverse)
UNIMPLEMENTED_INTRINSIC(LongReverseBytes)
-UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
-UNIMPLEMENTED_INTRINSIC(LongRotateRight)
UNIMPLEMENTED_INTRINSIC(ShortReverseBytes)
UNIMPLEMENTED_INTRINSIC(MathMinDoubleDouble)
UNIMPLEMENTED_INTRINSIC(MathMinFloatFloat)
@@ -1621,6 +1617,26 @@
UNIMPLEMENTED_INTRINSIC(MathTan)
UNIMPLEMENTED_INTRINSIC(MathTanh)
+UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
+UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
+UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
+
+UNIMPLEMENTED_INTRINSIC(IntegerCompare)
+UNIMPLEMENTED_INTRINSIC(LongCompare)
+UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerSignum)
+UNIMPLEMENTED_INTRINSIC(LongSignum)
+
+// Rotate operations are handled as HRor instructions.
+UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
+UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
+UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
+UNIMPLEMENTED_INTRINSIC(LongRotateRight)
+
#undef UNIMPLEMENTED_INTRINSIC
#undef __
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 8cf2d4f..c888f01 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -1465,11 +1465,7 @@
}
UNIMPLEMENTED_INTRINSIC(IntegerBitCount)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
UNIMPLEMENTED_INTRINSIC(LongBitCount)
-UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
-UNIMPLEMENTED_INTRINSIC(LongRotateRight)
UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
UNIMPLEMENTED_INTRINSIC(SystemArrayCopy)
UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
@@ -1493,6 +1489,26 @@
UNIMPLEMENTED_INTRINSIC(MathTan)
UNIMPLEMENTED_INTRINSIC(MathTanh)
+UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
+UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
+UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
+
+UNIMPLEMENTED_INTRINSIC(IntegerCompare)
+UNIMPLEMENTED_INTRINSIC(LongCompare)
+UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerSignum)
+UNIMPLEMENTED_INTRINSIC(LongSignum)
+
+// Rotate operations are handled as HRor instructions.
+UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
+UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
+UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
+UNIMPLEMENTED_INTRINSIC(LongRotateRight)
+
#undef UNIMPLEMENTED_INTRINSIC
#undef __
diff --git a/compiler/optimizing/intrinsics_list.h b/compiler/optimizing/intrinsics_list.h
index ea38034..88217b3 100644
--- a/compiler/optimizing/intrinsics_list.h
+++ b/compiler/optimizing/intrinsics_list.h
@@ -23,23 +23,35 @@
#define INTRINSICS_LIST(V) \
V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(DoubleIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(DoubleIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(FloatIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(FloatIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(FloatIntBitsToFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(IntegerReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(IntegerReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(IntegerBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(IntegerRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(IntegerRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(LongReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(LongReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(LongBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(LongRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(LongRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(ShortReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(MathAbsDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
V(MathAbsFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index 81112b1..0d9cf09 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -1013,6 +1013,21 @@
UNIMPLEMENTED_INTRINSIC(MathSinh)
UNIMPLEMENTED_INTRINSIC(MathTan)
UNIMPLEMENTED_INTRINSIC(MathTanh)
+
+UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
+UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
+UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
+
+UNIMPLEMENTED_INTRINSIC(IntegerCompare)
+UNIMPLEMENTED_INTRINSIC(LongCompare)
+UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerSignum)
+UNIMPLEMENTED_INTRINSIC(LongSignum)
+
#undef UNIMPLEMENTED_INTRINSIC
#undef __
diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc
index 769c422..cba84fa 100644
--- a/compiler/optimizing/intrinsics_mips64.cc
+++ b/compiler/optimizing/intrinsics_mips64.cc
@@ -1760,6 +1760,20 @@
UNIMPLEMENTED_INTRINSIC(MathTan)
UNIMPLEMENTED_INTRINSIC(MathTanh)
+UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
+UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
+UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
+
+UNIMPLEMENTED_INTRINSIC(IntegerCompare)
+UNIMPLEMENTED_INTRINSIC(LongCompare)
+UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerSignum)
+UNIMPLEMENTED_INTRINSIC(LongSignum)
+
#undef UNIMPLEMENTED_INTRINSIC
#undef __
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 3f5688b..acc40bc 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -2593,11 +2593,27 @@
UNIMPLEMENTED_INTRINSIC(MathRoundDouble)
UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
+UNIMPLEMENTED_INTRINSIC(SystemArrayCopy)
+
+UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
+UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
+UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
+
+UNIMPLEMENTED_INTRINSIC(IntegerCompare)
+UNIMPLEMENTED_INTRINSIC(LongCompare)
+UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerSignum)
+UNIMPLEMENTED_INTRINSIC(LongSignum)
+
+// Rotate operations are handled as HRor instructions.
UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
UNIMPLEMENTED_INTRINSIC(LongRotateRight)
UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
-UNIMPLEMENTED_INTRINSIC(SystemArrayCopy)
#undef UNIMPLEMENTED_INTRINSIC
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 23a628f..6ccc5d1 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -2592,6 +2592,22 @@
}
UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
+
+UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
+UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
+UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
+
+UNIMPLEMENTED_INTRINSIC(IntegerCompare)
+UNIMPLEMENTED_INTRINSIC(LongCompare)
+UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(IntegerSignum)
+UNIMPLEMENTED_INTRINSIC(LongSignum)
+
+// Rotate operations are handled as HRor instructions.
UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index adf8734..92f758d 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2221,10 +2221,7 @@
SetSideEffects(GetSideEffects().Union(SideEffects::CanTriggerGC()));
}
// Adjust method's exception status from intrinsic table.
- switch (exceptions) {
- case kNoThrow: SetCanThrow(false); break;
- case kCanThrow: SetCanThrow(true); break;
- }
+ SetCanThrow(exceptions == kCanThrow);
}
bool HNewInstance::IsStringAlloc() const {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 5246fd1..41c2f17 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -159,7 +159,7 @@
static ReferenceTypeInfo CreateInvalid() { return ReferenceTypeInfo(); }
- static bool IsValidHandle(TypeHandle handle) SHARED_REQUIRES(Locks::mutator_lock_) {
+ static bool IsValidHandle(TypeHandle handle) {
return handle.GetReference() != nullptr;
}
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index ff38394..85dfab6 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -5973,15 +5973,6 @@
Runtime* const runtime = Runtime::Current();
const bool is_interface = klass->IsInterface();
- // TODO It might in the future prove useful to make interfaces have full iftables, allowing a
- // faster invoke-super implementation in the interpreter/across dex-files.
- // We will just skip doing any of this on non-debug builds for speed.
- if (is_interface &&
- !kIsDebugBuild &&
- !runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods)) {
- return true;
- }
-
const bool has_superclass = klass->HasSuperClass();
const bool fill_tables = !is_interface;
const size_t super_ifcount = has_superclass ? klass->GetSuperClass()->GetIfTableCount() : 0U;
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index 727f4fc..7a852e2 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -2538,20 +2538,6 @@
return false;
}
- // Only the static initializer may have code in an interface.
- // TODO We should have some way determine whether to allow this experimental flag without the
- // runtime being started.
- // We assume experimental flags are enabled when running without a runtime to enable tools like
- // dexdump to handle dex files with these features.
- if (((class_access_flags & kAccInterface) != 0)
- && !is_clinit_by_name
- && Runtime::Current() != nullptr
- && !Runtime::Current()->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods)) {
- *error_msg = StringPrintf("Non-clinit interface method %" PRIu32 " should not have code",
- method_index);
- return false;
- }
-
// Instance constructors must not be synchronized and a few other flags.
if (is_init_by_name) {
static constexpr uint32_t kInitAllowed =
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 08c9b49..638fdb4 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1779,8 +1779,7 @@
void FinalizeHandleScope(Thread* self) SHARED_REQUIRES(Locks::mutator_lock_);
- StackReference<mirror::Object>* GetFirstHandleScopeEntry()
- SHARED_REQUIRES(Locks::mutator_lock_) {
+ StackReference<mirror::Object>* GetFirstHandleScopeEntry() {
return handle_scope_->GetHandle(0).GetReference();
}
diff --git a/runtime/experimental_flags.h b/runtime/experimental_flags.h
index 2e674e9..198f3fa 100644
--- a/runtime/experimental_flags.h
+++ b/runtime/experimental_flags.h
@@ -27,7 +27,6 @@
enum {
kNone = 0x0000,
kLambdas = 0x0001,
- kDefaultMethods = 0x0002,
};
constexpr ExperimentalFlags() : value_(0x0000) {}
@@ -69,10 +68,6 @@
stream << (started ? "|" : "") << "kLambdas";
started = true;
}
- if (e & ExperimentalFlags::kDefaultMethods) {
- stream << (started ? "|" : "") << "kDefaultMethods";
- started = true;
- }
if (!started) {
stream << "kNone";
}
diff --git a/runtime/gc/accounting/mod_union_table_test.cc b/runtime/gc/accounting/mod_union_table_test.cc
index edab1b0..349d6ff 100644
--- a/runtime/gc/accounting/mod_union_table_test.cc
+++ b/runtime/gc/accounting/mod_union_table_test.cc
@@ -22,6 +22,7 @@
#include "mirror/array-inl.h"
#include "space_bitmap-inl.h"
#include "thread-inl.h"
+#include "thread_list.h"
namespace art {
namespace gc {
@@ -184,7 +185,11 @@
std::unique_ptr<space::DlMallocSpace> other_space(space::DlMallocSpace::Create(
"other space", 128 * KB, 4 * MB, 4 * MB, nullptr, false));
ASSERT_TRUE(other_space.get() != nullptr);
- heap->AddSpace(other_space.get());
+ {
+ ScopedThreadSuspension sts(self, kSuspended);
+ ScopedSuspendAll ssa("Add image space");
+ heap->AddSpace(other_space.get());
+ }
std::unique_ptr<ModUnionTable> table(ModUnionTableFactory::Create(
type, space, other_space.get()));
ASSERT_TRUE(table.get() != nullptr);
@@ -253,6 +258,8 @@
std::ostringstream oss2;
table->Dump(oss2);
// Remove the space we added so it doesn't persist to the next test.
+ ScopedThreadSuspension sts(self, kSuspended);
+ ScopedSuspendAll ssa("Add image space");
heap->RemoveSpace(other_space.get());
}
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index bcfcb89..af7acbc 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -2066,8 +2066,9 @@
}
void ConcurrentCopying::FinishPhase() {
+ Thread* const self = Thread::Current();
{
- MutexLock mu(Thread::Current(), mark_stack_lock_);
+ MutexLock mu(self, mark_stack_lock_);
CHECK_EQ(pooled_mark_stacks_.size(), kMarkStackPoolSize);
}
region_space_ = nullptr;
@@ -2075,7 +2076,8 @@
MutexLock mu(Thread::Current(), skipped_blocks_lock_);
skipped_blocks_map_.clear();
}
- WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
+ ReaderMutexLock mu(self, *Locks::mutator_lock_);
+ WriterMutexLock mu2(self, *Locks::heap_bitmap_lock_);
heap_->ClearMarkedObjects();
}
diff --git a/runtime/gc/collector/garbage_collector.h b/runtime/gc/collector/garbage_collector.h
index 954c80e..580486a 100644
--- a/runtime/gc/collector/garbage_collector.h
+++ b/runtime/gc/collector/garbage_collector.h
@@ -153,7 +153,9 @@
void ResetCumulativeStatistics() REQUIRES(!pause_histogram_lock_);
// Swap the live and mark bitmaps of spaces that are active for the collector. For partial GC,
// this is the allocation space, for full GC then we swap the zygote bitmaps too.
- void SwapBitmaps() REQUIRES(Locks::heap_bitmap_lock_);
+ void SwapBitmaps()
+ REQUIRES(Locks::heap_bitmap_lock_)
+ SHARED_REQUIRES(Locks::mutator_lock_);
uint64_t GetTotalPausedTimeNs() REQUIRES(!pause_histogram_lock_);
int64_t GetTotalFreedBytes() const {
return total_freed_bytes_;
diff --git a/runtime/gc/collector/mark_compact.h b/runtime/gc/collector/mark_compact.h
index 8a12094..4831157 100644
--- a/runtime/gc/collector/mark_compact.h
+++ b/runtime/gc/collector/mark_compact.h
@@ -106,7 +106,7 @@
REQUIRES(Locks::mutator_lock_);
// Sweeps unmarked objects to complete the garbage collection.
- void Sweep(bool swap_bitmaps) REQUIRES(Locks::heap_bitmap_lock_);
+ void Sweep(bool swap_bitmaps) REQUIRES(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
// Sweeps unmarked objects to complete the garbage collection.
void SweepLargeObjects(bool swap_bitmaps) REQUIRES(Locks::heap_bitmap_lock_);
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 5427f88..64c8e9a 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -1467,7 +1467,9 @@
}
CHECK(mark_stack_->IsEmpty()); // Ensure that the mark stack is empty.
mark_stack_->Reset();
- WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
+ Thread* const self = Thread::Current();
+ ReaderMutexLock mu(self, *Locks::mutator_lock_);
+ WriterMutexLock mu2(self, *Locks::heap_bitmap_lock_);
heap_->ClearMarkedObjects();
}
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 245f96b..b61bef7 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -85,7 +85,7 @@
void Init();
// Find the default mark bitmap.
- void FindDefaultSpaceBitmap();
+ void FindDefaultSpaceBitmap() SHARED_REQUIRES(Locks::mutator_lock_);
// Marks all objects in the root set at the start of a garbage collection.
void MarkRoots(Thread* self)
diff --git a/runtime/gc/collector/semi_space.h b/runtime/gc/collector/semi_space.h
index a905904..0199e1a 100644
--- a/runtime/gc/collector/semi_space.h
+++ b/runtime/gc/collector/semi_space.h
@@ -135,7 +135,9 @@
REQUIRES(Locks::mutator_lock_);
// Sweeps unmarked objects to complete the garbage collection.
- virtual void Sweep(bool swap_bitmaps) REQUIRES(Locks::heap_bitmap_lock_);
+ virtual void Sweep(bool swap_bitmaps)
+ REQUIRES(Locks::heap_bitmap_lock_)
+ SHARED_REQUIRES(Locks::mutator_lock_);
// Sweeps unmarked objects to complete the garbage collection.
void SweepLargeObjects(bool swap_bitmaps) REQUIRES(Locks::heap_bitmap_lock_);
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 8cd8d73..137540a 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -801,6 +801,7 @@
if (!Runtime::Current()->IsAotCompiler()) {
return false;
}
+ ScopedObjectAccess soa(Thread::Current());
for (const auto& space : continuous_spaces_) {
if (space->IsImageSpace() || space->IsZygoteSpace()) {
return false;
@@ -1381,15 +1382,18 @@
uint64_t total_alloc_space_allocated = 0;
uint64_t total_alloc_space_size = 0;
uint64_t managed_reclaimed = 0;
- for (const auto& space : continuous_spaces_) {
- if (space->IsMallocSpace()) {
- gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
- if (malloc_space->IsRosAllocSpace() || !CareAboutPauseTimes()) {
- // Don't trim dlmalloc spaces if we care about pauses since this can hold the space lock
- // for a long period of time.
- managed_reclaimed += malloc_space->Trim();
+ {
+ ScopedObjectAccess soa(self);
+ for (const auto& space : continuous_spaces_) {
+ if (space->IsMallocSpace()) {
+ gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
+ if (malloc_space->IsRosAllocSpace() || !CareAboutPauseTimes()) {
+ // Don't trim dlmalloc spaces if we care about pauses since this can hold the space lock
+ // for a long period of time.
+ managed_reclaimed += malloc_space->Trim();
+ }
+ total_alloc_space_size += malloc_space->Size();
}
- total_alloc_space_size += malloc_space->Size();
}
}
total_alloc_space_allocated = GetBytesAllocated();
@@ -1520,6 +1524,7 @@
}
void Heap::DumpSpaces(std::ostream& stream) const {
+ ScopedObjectAccess soa(Thread::Current());
for (const auto& space : continuous_spaces_) {
accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
accounting::ContinuousSpaceBitmap* mark_bitmap = space->GetMarkBitmap();
@@ -1598,6 +1603,9 @@
}
space::RosAllocSpace* Heap::GetRosAllocSpace(gc::allocator::RosAlloc* rosalloc) const {
+ if (rosalloc_space_ != nullptr && rosalloc_space_->GetRosAlloc() == rosalloc) {
+ return rosalloc_space_;
+ }
for (const auto& space : continuous_spaces_) {
if (space->AsContinuousSpace()->IsRosAllocSpace()) {
if (space->AsContinuousSpace()->AsRosAllocSpace()->GetRosAlloc() == rosalloc) {
@@ -3530,7 +3538,8 @@
void Heap::ClampGrowthLimit() {
// Use heap bitmap lock to guard against races with BindLiveToMarkBitmap.
- WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
+ ScopedObjectAccess soa(Thread::Current());
+ WriterMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_);
capacity_ = growth_limit_;
for (const auto& space : continuous_spaces_) {
if (space->IsMallocSpace()) {
@@ -3546,6 +3555,7 @@
void Heap::ClearGrowthLimit() {
growth_limit_ = capacity_;
+ ScopedObjectAccess soa(Thread::Current());
for (const auto& space : continuous_spaces_) {
if (space->IsMallocSpace()) {
gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 1b7e2c9..c02e2d3 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -308,7 +308,10 @@
void ThreadFlipEnd(Thread* self) REQUIRES(!*thread_flip_lock_);
// Clear all of the mark bits, doesn't clear bitmaps which have the same live bits as mark bits.
- void ClearMarkedObjects() REQUIRES(Locks::heap_bitmap_lock_);
+ // Mutator lock is required for GetContinuousSpaces.
+ void ClearMarkedObjects()
+ REQUIRES(Locks::heap_bitmap_lock_)
+ SHARED_REQUIRES(Locks::mutator_lock_);
// Initiates an explicit garbage collection.
void CollectGarbage(bool clear_soft_references)
@@ -359,8 +362,12 @@
// due to usage by tests.
void SetSpaceAsDefault(space::ContinuousSpace* continuous_space)
REQUIRES(!Locks::heap_bitmap_lock_);
- void AddSpace(space::Space* space) REQUIRES(!Locks::heap_bitmap_lock_);
- void RemoveSpace(space::Space* space) REQUIRES(!Locks::heap_bitmap_lock_);
+ void AddSpace(space::Space* space)
+ REQUIRES(!Locks::heap_bitmap_lock_)
+ REQUIRES(Locks::mutator_lock_);
+ void RemoveSpace(space::Space* space)
+ REQUIRES(!Locks::heap_bitmap_lock_)
+ REQUIRES(Locks::mutator_lock_);
// Set target ideal heap utilization ratio, implements
// dalvik.system.VMRuntime.setTargetHeapUtilization.
@@ -378,7 +385,13 @@
void UpdateProcessState(ProcessState process_state)
REQUIRES(!*pending_task_lock_, !*gc_complete_lock_);
- const std::vector<space::ContinuousSpace*>& GetContinuousSpaces() const {
+ bool HaveContinuousSpaces() const NO_THREAD_SAFETY_ANALYSIS {
+ // No lock since vector empty is thread safe.
+ return !continuous_spaces_.empty();
+ }
+
+ const std::vector<space::ContinuousSpace*>& GetContinuousSpaces() const
+ SHARED_REQUIRES(Locks::mutator_lock_) {
return continuous_spaces_;
}
@@ -518,10 +531,13 @@
// get the space that corresponds to an object's address. Current implementation searches all
// spaces in turn. If fail_ok is false then failing to find a space will cause an abort.
// TODO: consider using faster data structure like binary tree.
- space::ContinuousSpace* FindContinuousSpaceFromObject(const mirror::Object*, bool fail_ok) const;
+ space::ContinuousSpace* FindContinuousSpaceFromObject(const mirror::Object*, bool fail_ok) const
+ SHARED_REQUIRES(Locks::mutator_lock_);
space::DiscontinuousSpace* FindDiscontinuousSpaceFromObject(const mirror::Object*,
- bool fail_ok) const;
- space::Space* FindSpaceFromObject(const mirror::Object*, bool fail_ok) const;
+ bool fail_ok) const
+ SHARED_REQUIRES(Locks::mutator_lock_);
+ space::Space* FindSpaceFromObject(const mirror::Object*, bool fail_ok) const
+ SHARED_REQUIRES(Locks::mutator_lock_);
void DumpForSigQuit(std::ostream& os) REQUIRES(!*gc_complete_lock_);
@@ -577,7 +593,9 @@
REQUIRES(Locks::heap_bitmap_lock_);
// Unbind any bound bitmaps.
- void UnBindBitmaps() REQUIRES(Locks::heap_bitmap_lock_);
+ void UnBindBitmaps()
+ REQUIRES(Locks::heap_bitmap_lock_)
+ SHARED_REQUIRES(Locks::mutator_lock_);
// Returns the boot image spaces. There may be multiple boot image spaces.
const std::vector<space::ImageSpace*>& GetBootImageSpaces() const {
@@ -604,7 +622,8 @@
}
// Return the corresponding rosalloc space.
- space::RosAllocSpace* GetRosAllocSpace(gc::allocator::RosAlloc* rosalloc) const;
+ space::RosAllocSpace* GetRosAllocSpace(gc::allocator::RosAlloc* rosalloc) const
+ SHARED_REQUIRES(Locks::mutator_lock_);
space::MallocSpace* GetNonMovingSpace() const {
return non_moving_space_;
@@ -962,7 +981,8 @@
void ProcessCards(TimingLogger* timings,
bool use_rem_sets,
bool process_alloc_space_cards,
- bool clear_alloc_space_cards);
+ bool clear_alloc_space_cards)
+ SHARED_REQUIRES(Locks::mutator_lock_);
// Push an object onto the allocation stack.
void PushOnAllocationStack(Thread* self, mirror::Object** obj)
@@ -1005,10 +1025,10 @@
REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !*backtrace_lock_);
// All-known continuous spaces, where objects lie within fixed bounds.
- std::vector<space::ContinuousSpace*> continuous_spaces_;
+ std::vector<space::ContinuousSpace*> continuous_spaces_ GUARDED_BY(Locks::mutator_lock_);
// All-known discontinuous spaces, where objects may be placed throughout virtual memory.
- std::vector<space::DiscontinuousSpace*> discontinuous_spaces_;
+ std::vector<space::DiscontinuousSpace*> discontinuous_spaces_ GUARDED_BY(Locks::mutator_lock_);
// All-known alloc spaces, where objects may be or have been allocated.
std::vector<space::AllocSpace*> alloc_spaces_;
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index e754a52..455d28e 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -319,7 +319,7 @@
namespace allocator {
// Implement the dlmalloc morecore callback.
-void* ArtDlMallocMoreCore(void* mspace, intptr_t increment) {
+void* ArtDlMallocMoreCore(void* mspace, intptr_t increment) SHARED_REQUIRES(Locks::mutator_lock_) {
Runtime* runtime = Runtime::Current();
Heap* heap = runtime->GetHeap();
::art::gc::space::DlMallocSpace* dlmalloc_space = heap->GetDlMallocSpace();
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index 49126d2..fd4d0a1 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -247,7 +247,10 @@
size_t RosAllocSpace::Trim() {
VLOG(heap) << "RosAllocSpace::Trim() ";
{
- MutexLock mu(Thread::Current(), lock_);
+ Thread* const self = Thread::Current();
+ // SOA required for Rosalloc::Trim() -> ArtRosAllocMoreCore() -> Heap::GetRosAllocSpace.
+ ScopedObjectAccess soa(self);
+ MutexLock mu(self, lock_);
// Trim to release memory at the end of the space.
rosalloc_->Trim();
}
@@ -373,7 +376,8 @@
namespace allocator {
// Callback from rosalloc when it needs to increase the footprint.
-void* ArtRosAllocMoreCore(allocator::RosAlloc* rosalloc, intptr_t increment) {
+void* ArtRosAllocMoreCore(allocator::RosAlloc* rosalloc, intptr_t increment)
+ SHARED_REQUIRES(Locks::mutator_lock_) {
Heap* heap = Runtime::Current()->GetHeap();
art::gc::space::RosAllocSpace* rosalloc_space = heap->GetRosAllocSpace(rosalloc);
DCHECK(rosalloc_space != nullptr);
diff --git a/runtime/gc/space/space_create_test.cc b/runtime/gc/space/space_create_test.cc
index aea2d9f..170f927 100644
--- a/runtime/gc/space/space_create_test.cc
+++ b/runtime/gc/space/space_create_test.cc
@@ -170,7 +170,11 @@
gc::Heap* heap = Runtime::Current()->GetHeap();
space::Space* old_space = space;
- heap->RemoveSpace(old_space);
+ {
+ ScopedThreadSuspension sts(self, kSuspended);
+ ScopedSuspendAll ssa("Add image space");
+ heap->RemoveSpace(old_space);
+ }
heap->RevokeAllThreadLocalBuffers();
space::ZygoteSpace* zygote_space = space->CreateZygoteSpace("alloc space",
heap->IsLowMemoryMode(),
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index e588eb3..20ef44a 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -27,6 +27,7 @@
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
#include "scoped_thread_state_change.h"
+#include "thread_list.h"
#include "zygote_space.h"
namespace art {
@@ -43,7 +44,11 @@
if (revoke) {
heap->RevokeAllThreadLocalBuffers();
}
- heap->AddSpace(space);
+ {
+ ScopedThreadStateChange sts(Thread::Current(), kSuspended);
+ ScopedSuspendAll ssa("Add image space");
+ heap->AddSpace(space);
+ }
heap->SetSpaceAsDefault(space);
}
diff --git a/runtime/handle.h b/runtime/handle.h
index 5b3bb60..a415373 100644
--- a/runtime/handle.h
+++ b/runtime/handle.h
@@ -70,13 +70,11 @@
return reinterpret_cast<jobject>(reference_);
}
- ALWAYS_INLINE StackReference<mirror::Object>* GetReference()
- SHARED_REQUIRES(Locks::mutator_lock_) {
+ ALWAYS_INLINE StackReference<mirror::Object>* GetReference() {
return reference_;
}
- ALWAYS_INLINE const StackReference<mirror::Object>* GetReference() const
- SHARED_REQUIRES(Locks::mutator_lock_) {
+ ALWAYS_INLINE const StackReference<mirror::Object>* GetReference() const {
return reference_;
}
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index e617348..d53a0e4 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -62,8 +62,7 @@
ALWAYS_INLINE mirror::Object* GetReference(size_t i) const
SHARED_REQUIRES(Locks::mutator_lock_);
- ALWAYS_INLINE Handle<mirror::Object> GetHandle(size_t i)
- SHARED_REQUIRES(Locks::mutator_lock_);
+ ALWAYS_INLINE Handle<mirror::Object> GetHandle(size_t i);
ALWAYS_INLINE MutableHandle<mirror::Object> GetMutableHandle(size_t i)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/interpreter/mterp/arm/footer.S b/runtime/interpreter/mterp/arm/footer.S
index 617f572..1dba856 100644
--- a/runtime/interpreter/mterp/arm/footer.S
+++ b/runtime/interpreter/mterp/arm/footer.S
@@ -150,12 +150,8 @@
b MterpDone
MterpReturn:
ldr r2, [rFP, #OFF_FP_RESULT_REGISTER]
- ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
str r0, [r2]
str r1, [r2, #4]
- mov r0, rSELF
- ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
- blne MterpSuspendCheck @ (self)
mov r0, #1 @ signal return to caller.
MterpDone:
add sp, sp, #4 @ un-align 64
diff --git a/runtime/interpreter/mterp/arm/op_check_cast.S b/runtime/interpreter/mterp/arm/op_check_cast.S
index 3e3ac70..24eba45 100644
--- a/runtime/interpreter/mterp/arm/op_check_cast.S
+++ b/runtime/interpreter/mterp/arm/op_check_cast.S
@@ -5,10 +5,10 @@
EXPORT_PC
FETCH r0, 1 @ r0<- BBBB
mov r1, rINST, lsr #8 @ r1<- AA
- GET_VREG r1, r1 @ r1<- object
+ VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
- bl MterpCheckCast @ (index, obj, method, self)
+ bl MterpCheckCast @ (index, &obj, method, self)
PREFETCH_INST 2
cmp r0, #0
bne MterpPossibleException
diff --git a/runtime/interpreter/mterp/arm/op_instance_of.S b/runtime/interpreter/mterp/arm/op_instance_of.S
index e94108c..d76f0b0 100644
--- a/runtime/interpreter/mterp/arm/op_instance_of.S
+++ b/runtime/interpreter/mterp/arm/op_instance_of.S
@@ -8,12 +8,12 @@
EXPORT_PC
FETCH r0, 1 @ r0<- CCCC
mov r1, rINST, lsr #12 @ r1<- B
- GET_VREG r1, r1 @ r1<- vB (object)
+ VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
mov r9, rINST, lsr #8 @ r9<- A+
and r9, r9, #15 @ r9<- A
- bl MterpInstanceOf @ (index, obj, method, self)
+ bl MterpInstanceOf @ (index, &obj, method, self)
ldr r1, [rSELF, #THREAD_EXCEPTION_OFFSET]
PREFETCH_INST 2
cmp r1, #0 @ exception pending?
diff --git a/runtime/interpreter/mterp/arm/op_return.S b/runtime/interpreter/mterp/arm/op_return.S
index a4ffd04..1888373 100644
--- a/runtime/interpreter/mterp/arm/op_return.S
+++ b/runtime/interpreter/mterp/arm/op_return.S
@@ -6,6 +6,10 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
GET_VREG r0, r2 @ r0<- vAA
mov r1, #0
diff --git a/runtime/interpreter/mterp/arm/op_return_void.S b/runtime/interpreter/mterp/arm/op_return_void.S
index f6dfd99..cbea2bf 100644
--- a/runtime/interpreter/mterp/arm/op_return_void.S
+++ b/runtime/interpreter/mterp/arm/op_return_void.S
@@ -1,5 +1,9 @@
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r0, #0
mov r1, #0
b MterpReturn
diff --git a/runtime/interpreter/mterp/arm/op_return_void_no_barrier.S b/runtime/interpreter/mterp/arm/op_return_void_no_barrier.S
index 7322940..2dde7ae 100644
--- a/runtime/interpreter/mterp/arm/op_return_void_no_barrier.S
+++ b/runtime/interpreter/mterp/arm/op_return_void_no_barrier.S
@@ -1,3 +1,7 @@
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r0, #0
mov r1, #0
b MterpReturn
diff --git a/runtime/interpreter/mterp/arm/op_return_wide.S b/runtime/interpreter/mterp/arm/op_return_wide.S
index 2881c87..cfab530 100644
--- a/runtime/interpreter/mterp/arm/op_return_wide.S
+++ b/runtime/interpreter/mterp/arm/op_return_wide.S
@@ -4,6 +4,10 @@
/* return-wide vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index 9975458..0afd276 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -274,13 +274,15 @@
return false;
}
-extern "C" bool MterpCheckCast(uint32_t index, Object* obj, art::ArtMethod* method,
- Thread* self)
+extern "C" bool MterpCheckCast(uint32_t index, StackReference<mirror::Object>* vreg_addr,
+ art::ArtMethod* method, Thread* self)
SHARED_REQUIRES(Locks::mutator_lock_) {
Class* c = ResolveVerifyAndClinit(index, method, self, false, false);
if (UNLIKELY(c == nullptr)) {
return true;
}
+ // Must load obj from vreg following ResolveVerifyAndClinit due to moving gc.
+ Object* obj = vreg_addr->AsMirrorPtr();
if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
ThrowClassCastException(c, obj->GetClass());
return true;
@@ -288,13 +290,15 @@
return false;
}
-extern "C" bool MterpInstanceOf(uint32_t index, Object* obj, art::ArtMethod* method,
- Thread* self)
+extern "C" bool MterpInstanceOf(uint32_t index, StackReference<mirror::Object>* vreg_addr,
+ art::ArtMethod* method, Thread* self)
SHARED_REQUIRES(Locks::mutator_lock_) {
Class* c = ResolveVerifyAndClinit(index, method, self, false, false);
if (UNLIKELY(c == nullptr)) {
return false; // Caller will check for pending exception. Return value unimportant.
}
+ // Must load obj from vreg following ResolveVerifyAndClinit due to moving gc.
+ Object* obj = vreg_addr->AsMirrorPtr();
return (obj != nullptr) && obj->InstanceOf(c);
}
@@ -505,8 +509,7 @@
uint64_t* new_value, Thread* self)
SHARED_REQUIRES(Locks::mutator_lock_) {
ScopedQuickEntrypointChecks sqec(self);
- ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
- sizeof(int64_t));
+ ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t));
if (LIKELY(field != nullptr)) {
// Compiled code can't use transactional mode.
field->Set64<false>(field->GetDeclaringClass(), *new_value);
@@ -524,8 +527,7 @@
extern "C" int artSet8InstanceFromMterp(uint32_t field_idx, mirror::Object* obj, uint8_t new_value,
ArtMethod* referrer)
SHARED_REQUIRES(Locks::mutator_lock_) {
- ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
- sizeof(int8_t));
+ ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t));
if (LIKELY(field != nullptr && obj != nullptr)) {
Primitive::Type type = field->GetTypeAsPrimitiveType();
if (type == Primitive::kPrimBoolean) {
@@ -582,7 +584,7 @@
}
extern "C" int artSetObjInstanceFromMterp(uint32_t field_idx, mirror::Object* obj,
- mirror::Object* new_value, ArtMethod* referrer)
+ mirror::Object* new_value, ArtMethod* referrer)
SHARED_REQUIRES(Locks::mutator_lock_) {
ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
sizeof(mirror::HeapReference<mirror::Object>));
diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S
index 9ae98a2..78c784b 100644
--- a/runtime/interpreter/mterp/out/mterp_arm.S
+++ b/runtime/interpreter/mterp/out/mterp_arm.S
@@ -599,6 +599,10 @@
/* File: arm/op_return_void.S */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r0, #0
mov r1, #0
b MterpReturn
@@ -615,6 +619,10 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
GET_VREG r0, r2 @ r0<- vAA
mov r1, #0
@@ -630,6 +638,10 @@
/* return-wide vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
@@ -648,6 +660,10 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
GET_VREG r0, r2 @ r0<- vAA
mov r1, #0
@@ -878,10 +894,10 @@
EXPORT_PC
FETCH r0, 1 @ r0<- BBBB
mov r1, rINST, lsr #8 @ r1<- AA
- GET_VREG r1, r1 @ r1<- object
+ VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
- bl MterpCheckCast @ (index, obj, method, self)
+ bl MterpCheckCast @ (index, &obj, method, self)
PREFETCH_INST 2
cmp r0, #0
bne MterpPossibleException
@@ -903,12 +919,12 @@
EXPORT_PC
FETCH r0, 1 @ r0<- CCCC
mov r1, rINST, lsr #12 @ r1<- B
- GET_VREG r1, r1 @ r1<- vB (object)
+ VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
mov r9, rINST, lsr #8 @ r9<- A+
and r9, r9, #15 @ r9<- A
- bl MterpInstanceOf @ (index, obj, method, self)
+ bl MterpInstanceOf @ (index, &obj, method, self)
ldr r1, [rSELF, #THREAD_EXCEPTION_OFFSET]
PREFETCH_INST 2
cmp r1, #0 @ exception pending?
@@ -3385,6 +3401,10 @@
.balign 128
.L_op_return_void_no_barrier: /* 0x73 */
/* File: arm/op_return_void_no_barrier.S */
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r0, #0
mov r1, #0
b MterpReturn
@@ -12183,12 +12203,8 @@
b MterpDone
MterpReturn:
ldr r2, [rFP, #OFF_FP_RESULT_REGISTER]
- ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
str r0, [r2]
str r1, [r2, #4]
- mov r0, rSELF
- ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
- blne MterpSuspendCheck @ (self)
mov r0, #1 @ signal return to caller.
MterpDone:
add sp, sp, #4 @ un-align 64
diff --git a/runtime/interpreter/mterp/out/mterp_x86.S b/runtime/interpreter/mterp/out/mterp_x86.S
index 923d502..e2918dc 100644
--- a/runtime/interpreter/mterp/out/mterp_x86.S
+++ b/runtime/interpreter/mterp/out/mterp_x86.S
@@ -575,6 +575,12 @@
/* File: x86/op_return_void.S */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
xorl %eax, %eax
xorl %ecx, %ecx
jmp MterpReturn
@@ -591,6 +597,12 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- vAA
xorl %ecx, %ecx
jmp MterpReturn
@@ -605,6 +617,12 @@
/* return-wide vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- v[AA+0]
GET_VREG_HIGH %ecx rINST # ecx <- v[AA+1]
jmp MterpReturn
@@ -622,6 +640,12 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- vAA
xorl %ecx, %ecx
jmp MterpReturn
@@ -827,13 +851,13 @@
EXPORT_PC
movzwl 2(rPC), %eax # eax <- BBBB
movl %eax, OUT_ARG0(%esp)
- GET_VREG %ecx rINST
+ leal VREG_ADDRESS(rINST), %ecx
movl %ecx, OUT_ARG1(%esp)
movl OFF_FP_METHOD(rFP),%eax
movl %eax, OUT_ARG2(%esp)
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp)
- call MterpCheckCast # (index, obj, method, self)
+ call MterpCheckCast # (index, &obj, method, self)
REFRESH_IBASE
testl %eax, %eax
jnz MterpPossibleException
@@ -855,13 +879,13 @@
movl %eax, OUT_ARG0(%esp)
movl rINST, %eax # eax <- BA
sarl $4, %eax # eax <- B
- GET_VREG %ecx %eax # Get object
+ leal VREG_ADDRESS(%eax), %ecx # Get object address
movl %ecx, OUT_ARG1(%esp)
movl OFF_FP_METHOD(rFP),%eax
movl %eax, OUT_ARG2(%esp)
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp)
- call MterpInstanceOf # (index, obj, method, self)
+ call MterpInstanceOf # (index, &obj, method, self)
movl rSELF, %ecx
REFRESH_IBASE_FROM_SELF %ecx
cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx)
@@ -3145,6 +3169,12 @@
.balign 128
.L_op_return_void_no_barrier: /* 0x73 */
/* File: x86/op_return_void_no_barrier.S */
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
xorl %eax, %eax
xorl %ecx, %ecx
jmp MterpReturn
@@ -12921,12 +12951,6 @@
movl OFF_FP_RESULT_REGISTER(rFP), %edx
movl %eax, (%edx)
movl %ecx, 4(%edx)
- movl rSELF, %eax
- testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
- jz 1f
- movl %eax, OUT_ARG0(%esp)
- call MterpSuspendCheck
-1:
mov $1, %eax
MterpDone:
/* Restore callee save register */
diff --git a/runtime/interpreter/mterp/x86/footer.S b/runtime/interpreter/mterp/x86/footer.S
index 8f79b37..a2a36c4 100644
--- a/runtime/interpreter/mterp/x86/footer.S
+++ b/runtime/interpreter/mterp/x86/footer.S
@@ -169,12 +169,6 @@
movl OFF_FP_RESULT_REGISTER(rFP), %edx
movl %eax, (%edx)
movl %ecx, 4(%edx)
- movl rSELF, %eax
- testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
- jz 1f
- movl %eax, OUT_ARG0(%esp)
- call MterpSuspendCheck
-1:
mov $$1, %eax
MterpDone:
/* Restore callee save register */
diff --git a/runtime/interpreter/mterp/x86/op_check_cast.S b/runtime/interpreter/mterp/x86/op_check_cast.S
index 3d85f5e..018432a 100644
--- a/runtime/interpreter/mterp/x86/op_check_cast.S
+++ b/runtime/interpreter/mterp/x86/op_check_cast.S
@@ -5,13 +5,13 @@
EXPORT_PC
movzwl 2(rPC), %eax # eax <- BBBB
movl %eax, OUT_ARG0(%esp)
- GET_VREG %ecx rINST
+ leal VREG_ADDRESS(rINST), %ecx
movl %ecx, OUT_ARG1(%esp)
movl OFF_FP_METHOD(rFP),%eax
movl %eax, OUT_ARG2(%esp)
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp)
- call MterpCheckCast # (index, obj, method, self)
+ call MterpCheckCast # (index, &obj, method, self)
REFRESH_IBASE
testl %eax, %eax
jnz MterpPossibleException
diff --git a/runtime/interpreter/mterp/x86/op_instance_of.S b/runtime/interpreter/mterp/x86/op_instance_of.S
index cfbd4a0..c9bfba5 100644
--- a/runtime/interpreter/mterp/x86/op_instance_of.S
+++ b/runtime/interpreter/mterp/x86/op_instance_of.S
@@ -10,13 +10,13 @@
movl %eax, OUT_ARG0(%esp)
movl rINST, %eax # eax <- BA
sarl $$4, %eax # eax <- B
- GET_VREG %ecx %eax # Get object
+ leal VREG_ADDRESS(%eax), %ecx # Get object address
movl %ecx, OUT_ARG1(%esp)
movl OFF_FP_METHOD(rFP),%eax
movl %eax, OUT_ARG2(%esp)
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp)
- call MterpInstanceOf # (index, obj, method, self)
+ call MterpInstanceOf # (index, &obj, method, self)
movl rSELF, %ecx
REFRESH_IBASE_FROM_SELF %ecx
cmpl $$0, THREAD_EXCEPTION_OFFSET(%ecx)
diff --git a/runtime/interpreter/mterp/x86/op_return.S b/runtime/interpreter/mterp/x86/op_return.S
index 1658322..183b3bf 100644
--- a/runtime/interpreter/mterp/x86/op_return.S
+++ b/runtime/interpreter/mterp/x86/op_return.S
@@ -6,6 +6,12 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- vAA
xorl %ecx, %ecx
jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86/op_return_void.S b/runtime/interpreter/mterp/x86/op_return_void.S
index b74446e..f3e24c7 100644
--- a/runtime/interpreter/mterp/x86/op_return_void.S
+++ b/runtime/interpreter/mterp/x86/op_return_void.S
@@ -1,5 +1,11 @@
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
xorl %eax, %eax
xorl %ecx, %ecx
jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86/op_return_void_no_barrier.S b/runtime/interpreter/mterp/x86/op_return_void_no_barrier.S
index abc7c4d..add4e20 100644
--- a/runtime/interpreter/mterp/x86/op_return_void_no_barrier.S
+++ b/runtime/interpreter/mterp/x86/op_return_void_no_barrier.S
@@ -1,3 +1,9 @@
+ movl rSELF, %eax
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
xorl %eax, %eax
xorl %ecx, %ecx
jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86/op_return_wide.S b/runtime/interpreter/mterp/x86/op_return_wide.S
index 00effd6..34a3380 100644
--- a/runtime/interpreter/mterp/x86/op_return_wide.S
+++ b/runtime/interpreter/mterp/x86/op_return_wide.S
@@ -4,6 +4,12 @@
/* return-wide vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- v[AA+0]
GET_VREG_HIGH %ecx rINST # ecx <- v[AA+1]
jmp MterpReturn
diff --git a/runtime/jdwp/jdwp_socket.cc b/runtime/jdwp/jdwp_socket.cc
index 1bc58ac..2507fe9 100644
--- a/runtime/jdwp/jdwp_socket.cc
+++ b/runtime/jdwp/jdwp_socket.cc
@@ -30,13 +30,13 @@
#include "base/stringprintf.h"
#include "jdwp/jdwp_priv.h"
-#define kBasePort 8000
-#define kMaxPort 8040
-
namespace art {
namespace JDWP {
+static constexpr uint16_t kBasePort = 8000;
+static constexpr uint16_t kMaxPort = 8040;
+
/*
* JDWP network state.
*
@@ -275,16 +275,33 @@
* Start by resolving the host name.
*/
#if defined(__linux__)
+ // Initial size of the work buffer used in gethostbyname_r.
+ //
+ // The call to gethostbyname_r below requires a user-allocated buffer,
+ // the size of which depends on the system. The initial implementation
+ // used to use a 128-byte buffer, but that was not enough on some
+ // systems (maybe because of IPv6), causing failures in JDWP host
+ // testing; thus it was increased to 256.
+ //
+ // However, we should not use a fixed size: gethostbyname_r's
+ // documentation states that if the work buffer is too small (i.e. if
+ // gethostbyname_r returns `ERANGE`), then the function should be
+ // called again with a bigger buffer. Which we do now, starting with
+ // an initial 256-byte buffer, and doubling it until gethostbyname_r
+ // accepts this size.
+ static constexpr size_t kInitialAuxBufSize = 256;
+
+ std::vector<char> auxBuf(kInitialAuxBufSize);
hostent he;
- // The size of the work buffer used in the gethostbyname_r call
- // below. It used to be 128, but this was not enough on some
- // configurations (maybe because of IPv6?), causing failures in JDWP
- // host testing; thus it was increased to 256.
- static constexpr size_t kAuxBufSize = 256;
- char auxBuf[kAuxBufSize];
int error;
- int cc = gethostbyname_r(options->host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
- if (cc != 0) {
+ int cc;
+ while ((cc = gethostbyname_r(
+ options->host.c_str(), &he, auxBuf.data(), auxBuf.size(), &pEntry, &error))
+ == ERANGE) {
+ // The work buffer `auxBuf` is too small; enlarge it.
+ auxBuf.resize(auxBuf.size() * 2);
+ }
+ if (cc != 0 || pEntry == nullptr) {
LOG(WARNING) << "gethostbyname_r('" << options->host << "') failed: " << hstrerror(error);
return false;
}
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 64b2c89..bec6e13 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -719,7 +719,7 @@
}
}
-void JitCodeCache::GetCompiledArtMethods(const std::set<const std::string>& dex_base_locations,
+void JitCodeCache::GetCompiledArtMethods(const std::set<std::string>& dex_base_locations,
std::vector<ArtMethod*>& methods) {
MutexLock mu(Thread::Current(), lock_);
for (auto it : method_code_map_) {
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index 67fa928..69fc553 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -153,7 +153,7 @@
void* MoreCore(const void* mspace, intptr_t increment);
// Adds to `methods` all the compiled ArtMethods which are part of any of the given dex locations.
- void GetCompiledArtMethods(const std::set<const std::string>& dex_base_locations,
+ void GetCompiledArtMethods(const std::set<std::string>& dex_base_locations,
std::vector<ArtMethod*>& methods)
REQUIRES(!lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index f3f5f95..b1a5a4b 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -42,13 +42,12 @@
ProfileSaver::ProfileSaver(const std::string& output_filename,
jit::JitCodeCache* jit_code_cache,
const std::vector<std::string>& code_paths)
- : output_filename_(output_filename),
- jit_code_cache_(jit_code_cache),
- tracked_dex_base_locations_(code_paths.begin(), code_paths.end()),
+ : jit_code_cache_(jit_code_cache),
code_cache_last_update_time_ns_(0),
shutting_down_(false),
wait_lock_("ProfileSaver wait lock"),
period_condition_("ProfileSaver period condition", wait_lock_) {
+ AddTrackedLocations(output_filename, code_paths);
}
void ProfileSaver::Run() {
@@ -86,8 +85,6 @@
}
bool ProfileSaver::ProcessProfilingInfo() {
- VLOG(profiler) << "Save profiling information to: " << output_filename_;
-
uint64_t last_update_time_ns = jit_code_cache_->GetLastUpdateTimeNs();
if (last_update_time_ns - code_cache_last_update_time_ns_
< kMinimumTimeBetweenCodeCacheUpdatesNs) {
@@ -99,18 +96,36 @@
uint64_t start = NanoTime();
code_cache_last_update_time_ns_ = last_update_time_ns;
- std::vector<ArtMethod*> methods;
+ SafeMap<std::string, std::set<std::string>> tracked_locations;
{
- ScopedObjectAccess soa(Thread::Current());
- jit_code_cache_->GetCompiledArtMethods(tracked_dex_base_locations_, methods);
+ // Make a copy so that we don't hold the lock while doing I/O.
+ MutexLock mu(Thread::Current(), *Locks::profiler_lock_);
+ tracked_locations = tracked_dex_base_locations_;
}
- if (methods.size() < kMinimumNrOrMethodsToSave) {
- VLOG(profiler) << "Not enough information to save. Nr of methods: " << methods.size();
- return false;
- }
+ for (const auto& it : tracked_locations) {
+ if (ShuttingDown(Thread::Current())) {
+ return true;
+ }
+ const std::string& filename = it.first;
+ const std::set<std::string>& locations = it.second;
+ std::vector<ArtMethod*> methods;
+ {
+ ScopedObjectAccess soa(Thread::Current());
+ jit_code_cache_->GetCompiledArtMethods(locations, methods);
+ }
+ if (methods.size() < kMinimumNrOrMethodsToSave) {
+ VLOG(profiler) << "Not enough information to save to: " << filename
+ <<" Nr of methods: " << methods.size();
+ return false;
+ }
- ProfileCompilationInfo::SaveProfilingInfo(output_filename_, methods);
- VLOG(profiler) << "Profile process time: " << PrettyDuration(NanoTime() - start);
+ if (!ProfileCompilationInfo::SaveProfilingInfo(filename, methods)) {
+ LOG(WARNING) << "Could not save profiling info to " << filename;
+ return false;
+ }
+
+ VLOG(profiler) << "Profile process time: " << PrettyDuration(NanoTime() - start);
+ }
return true;
}
@@ -137,9 +152,13 @@
DCHECK(jit_code_cache != nullptr);
MutexLock mu(Thread::Current(), *Locks::profiler_lock_);
- // Don't start two profile saver threads.
if (instance_ != nullptr) {
- DCHECK(false) << "Tried to start two profile savers";
+ // If we already have an instance, make sure it uses the same jit_code_cache.
+ // This may be called multiple times via Runtime::registerAppInfo (e.g. for
+ // apps which share the same runtime).
+ DCHECK_EQ(instance_->jit_code_cache_, jit_code_cache);
+ // Add the code_paths to the tracked locations.
+ instance_->AddTrackedLocations(output_filename, code_paths);
return;
}
@@ -161,7 +180,7 @@
{
MutexLock profiler_mutex(Thread::Current(), *Locks::profiler_lock_);
- VLOG(profiler) << "Stopping profile saver thread for file: " << instance_->output_filename_;
+ VLOG(profiler) << "Stopping profile saver thread";
profile_saver = instance_;
profiler_pthread = profiler_pthread_;
if (instance_ == nullptr) {
@@ -202,4 +221,15 @@
return instance_ != nullptr;
}
+void ProfileSaver::AddTrackedLocations(const std::string& output_filename,
+ const std::vector<std::string>& code_paths) {
+ auto it = tracked_dex_base_locations_.find(output_filename);
+ if (it == tracked_dex_base_locations_.end()) {
+ tracked_dex_base_locations_.Put(output_filename,
+ std::set<std::string>(code_paths.begin(), code_paths.end()));
+ } else {
+ it->second.insert(code_paths.begin(), code_paths.end());
+ }
+}
+
} // namespace art
diff --git a/runtime/jit/profile_saver.h b/runtime/jit/profile_saver.h
index d60142b..3342790 100644
--- a/runtime/jit/profile_saver.h
+++ b/runtime/jit/profile_saver.h
@@ -20,12 +20,14 @@
#include "base/mutex.h"
#include "jit_code_cache.h"
#include "offline_profiling_info.h"
+#include "safe_map.h"
namespace art {
class ProfileSaver {
public:
- // Starts the profile saver thread.
+ // Starts the profile saver thread if not already started.
+ // If the saver is already running it adds (output_filename, code_paths) to its tracked locations.
static void Start(const std::string& output_filename,
jit::JitCodeCache* jit_code_cache,
const std::vector<std::string>& code_paths)
@@ -58,14 +60,18 @@
// Returns true if the saver is shutting down (ProfileSaver::Stop() has been called).
bool ShuttingDown(Thread* self) REQUIRES(!Locks::profiler_lock_);
+ void AddTrackedLocations(const std::string& output_filename,
+ const std::vector<std::string>& code_paths)
+ REQUIRES(Locks::profiler_lock_);
+
// The only instance of the saver.
static ProfileSaver* instance_ GUARDED_BY(Locks::profiler_lock_);
// Profile saver thread.
static pthread_t profiler_pthread_ GUARDED_BY(Locks::profiler_lock_);
- const std::string output_filename_;
jit::JitCodeCache* jit_code_cache_;
- const std::set<const std::string> tracked_dex_base_locations_;
+ SafeMap<std::string, std::set<std::string>> tracked_dex_base_locations_
+ GUARDED_BY(Locks::profiler_lock_);
uint64_t code_cache_last_update_time_ns_;
bool shutting_down_ GUARDED_BY(Locks::profiler_lock_);
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index 8febb62..8f108fa 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -314,32 +314,33 @@
size_t largeObjectsSize = 0;
size_t largeObjectsUsed = 0;
gc::Heap* heap = Runtime::Current()->GetHeap();
- for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) {
- if (space->IsImageSpace()) {
- // Currently don't include the image space.
- } else if (space->IsZygoteSpace()) {
- gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace();
- zygoteSize += zygote_space->Size();
- zygoteUsed += zygote_space->GetBytesAllocated();
- } else if (space->IsMallocSpace()) {
- // This is a malloc space.
- gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
- allocSize += malloc_space->GetFootprint();
- allocUsed += malloc_space->GetBytesAllocated();
- } else if (space->IsBumpPointerSpace()) {
- ScopedObjectAccess soa(env);
- gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace();
- allocSize += bump_pointer_space->Size();
- allocUsed += bump_pointer_space->GetBytesAllocated();
+ {
+ ScopedObjectAccess soa(env);
+ for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) {
+ if (space->IsImageSpace()) {
+ // Currently don't include the image space.
+ } else if (space->IsZygoteSpace()) {
+ gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace();
+ zygoteSize += zygote_space->Size();
+ zygoteUsed += zygote_space->GetBytesAllocated();
+ } else if (space->IsMallocSpace()) {
+ // This is a malloc space.
+ gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
+ allocSize += malloc_space->GetFootprint();
+ allocUsed += malloc_space->GetBytesAllocated();
+ } else if (space->IsBumpPointerSpace()) {
+ gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace();
+ allocSize += bump_pointer_space->Size();
+ allocUsed += bump_pointer_space->GetBytesAllocated();
+ }
+ }
+ for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) {
+ if (space->IsLargeObjectSpace()) {
+ largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated();
+ largeObjectsUsed += largeObjectsSize;
+ }
}
}
- for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) {
- if (space->IsLargeObjectSpace()) {
- largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated();
- largeObjectsUsed += largeObjectsSize;
- }
- }
-
size_t allocFree = allocSize - allocUsed;
size_t zygoteFree = zygoteSize - zygoteUsed;
size_t largeObjectsFree = largeObjectsSize - largeObjectsUsed;
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 2bd5c76..a8f84a2 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -1026,7 +1026,7 @@
gc::space::ImageSpace* ret = gc::space::ImageSpace::CreateFromAppImage(art_file.c_str(),
oat_file,
&error_msg);
- if (ret == nullptr) {
+ if (ret == nullptr && (VLOG_IS_ON(image) || OS::FileExists(art_file.c_str()))) {
LOG(INFO) << "Failed to open app image " << art_file.c_str() << " " << error_msg;
}
return ret;
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index b34b550..de90f0a 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -30,6 +30,7 @@
#include "oat_file_assistant.h"
#include "scoped_thread_state_change.h"
#include "thread-inl.h"
+#include "thread_list.h"
namespace art {
@@ -376,7 +377,11 @@
std::string temp_error_msg;
// Add image space has a race condition since other threads could be reading from the
// spaces array.
- runtime->GetHeap()->AddSpace(image_space.get());
+ {
+ ScopedThreadSuspension sts(self, kSuspended);
+ ScopedSuspendAll ssa("Add image space");
+ runtime->GetHeap()->AddSpace(image_space.get());
+ }
added_image_space = true;
if (!runtime->GetClassLinker()->AddImageSpace(image_space.get(),
h_loader,
@@ -386,7 +391,11 @@
/*out*/&temp_error_msg)) {
LOG(INFO) << "Failed to add image file " << temp_error_msg;
dex_files.clear();
- runtime->GetHeap()->RemoveSpace(image_space.get());
+ {
+ ScopedThreadSuspension sts(self, kSuspended);
+ ScopedSuspendAll ssa("Remove image space");
+ runtime->GetHeap()->RemoveSpace(image_space.get());
+ }
added_image_space = false;
// Non-fatal, don't update error_msg.
}
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 341be9a..aa64ee3 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -565,13 +565,6 @@
args.Set(M::HeapGrowthLimit, args.GetOrDefault(M::MemoryMaximumSize));
}
- if (args.GetOrDefault(M::Experimental) & ExperimentalFlags::kDefaultMethods) {
- LOG(WARNING) << "Default method support has been enabled. The verifier will be less strict "
- << "in some cases. All existing invoke opcodes have an unstable updated "
- << "specification and are nearly guaranteed to change over time. Do not attempt "
- << "to write shipping code against the invoke opcodes with this flag.";
- }
-
if (args.GetOrDefault(M::Experimental) & ExperimentalFlags::kLambdas) {
LOG(WARNING) << "Experimental lambdas have been enabled. All lambda opcodes have "
<< "an unstable specification and are nearly guaranteed to change over time. "
@@ -698,8 +691,8 @@
UsageMessage(stream, " -X[no]image-dex2oat (Whether to create and use a boot image)\n");
UsageMessage(stream, " -Xno-dex-file-fallback "
"(Don't fall back to dex files without oat files)\n");
- UsageMessage(stream, " -Xexperimental:{lambdas,default-methods} "
- "(Enable new experimental dalvik opcodes and semantics, off by default)\n");
+ UsageMessage(stream, " -Xexperimental:lambdas "
+ "(Enable new and experimental dalvik opcodes and semantics)\n");
UsageMessage(stream, "\n");
UsageMessage(stream, "The following previously supported Dalvik options are ignored:\n");
diff --git a/runtime/quick/inline_method_analyser.h b/runtime/quick/inline_method_analyser.h
index ca456c2..1bb816b 100644
--- a/runtime/quick/inline_method_analyser.h
+++ b/runtime/quick/inline_method_analyser.h
@@ -37,13 +37,21 @@
enum InlineMethodOpcode : uint16_t {
kIntrinsicDoubleCvt,
kIntrinsicFloatCvt,
+ kIntrinsicFloatIsInfinite,
+ kIntrinsicDoubleIsInfinite,
+ kIntrinsicFloatIsNaN,
+ kIntrinsicDoubleIsNaN,
kIntrinsicReverseBits,
kIntrinsicReverseBytes,
kIntrinsicBitCount,
+ kIntrinsicCompare,
+ kIntrinsicHighestOneBit,
+ kIntrinsicLowestOneBit,
kIntrinsicNumberOfLeadingZeros,
kIntrinsicNumberOfTrailingZeros,
kIntrinsicRotateRight,
kIntrinsicRotateLeft,
+ kIntrinsicSignum,
kIntrinsicAbsInt,
kIntrinsicAbsLong,
kIntrinsicAbsFloat,
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index c5b009d..308f3ba 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -113,7 +113,7 @@
RUNTIME_OPTIONS_KEY (Unit, NoDexFileFallback)
RUNTIME_OPTIONS_KEY (std::string, CpuAbiList)
RUNTIME_OPTIONS_KEY (std::string, Fingerprint)
-RUNTIME_OPTIONS_KEY (ExperimentalFlags, Experimental, ExperimentalFlags::kNone) // -Xexperimental:{, lambdas, default-methods}
+RUNTIME_OPTIONS_KEY (ExperimentalFlags, Experimental, ExperimentalFlags::kNone) // -Xexperimental:{none, lambdas}
// Not parse-able from command line, but can be provided explicitly.
// (Do not add anything here that is defined in ParsedOptions::MakeParser)
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 7e0f337..2890a98 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -608,7 +608,6 @@
bool MethodVerifier::Verify() {
// Some older code doesn't correctly mark constructors as such. Test for this case by looking at
// the name.
- Runtime* runtime = Runtime::Current();
const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
const char* method_name = dex_file_->StringDataByIdx(method_id.name_idx_);
bool instance_constructor_by_name = strcmp("<init>", method_name) == 0;
@@ -678,12 +677,9 @@
}
if ((class_def_->GetJavaAccessFlags() & kAccInterface) != 0) {
// Interface methods must be public and abstract (if default methods are disabled).
- bool default_methods_supported =
- runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods);
- uint32_t kRequired = kAccPublic | (default_methods_supported ? 0 : kAccAbstract);
+ uint32_t kRequired = kAccPublic;
if ((method_access_flags_ & kRequired) != kRequired) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interface methods must be public"
- << (default_methods_supported ? "" : " and abstract");
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interface methods must be public";
return false;
}
// In addition to the above, interface methods must not be protected.
@@ -715,19 +711,14 @@
// default methods enabled we also allow other public, static, non-final methods to have code.
// Otherwise that is the only type of method allowed.
if (!(IsConstructor() && IsStatic())) {
- if (runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods)) {
- if (IsInstanceConstructor()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-static constructor";
- return false;
- } else if (method_access_flags_ & kAccFinal) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have final methods";
- return false;
- } else if (!(method_access_flags_ & kAccPublic)) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-public members";
- return false;
- }
- } else {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interface methods must be abstract";
+ if (IsInstanceConstructor()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-static constructor";
+ return false;
+ } else if (method_access_flags_ & kAccFinal) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have final methods";
+ return false;
+ } else if (!(method_access_flags_ & kAccPublic)) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-public members";
return false;
}
}
@@ -3713,12 +3704,10 @@
// Note: this check must be after the initializer check, as those are required to fail a class,
// while this check implies an IncompatibleClassChangeError.
if (klass->IsInterface()) {
- Runtime* runtime = Runtime::Current();
- const bool default_methods_supported =
- runtime == nullptr ||
- runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods);
+ // methods called on interfaces should be invoke-interface, invoke-super, or invoke-static.
if (method_type != METHOD_INTERFACE &&
- (!default_methods_supported || method_type != METHOD_STATIC)) {
+ method_type != METHOD_STATIC &&
+ method_type != METHOD_SUPER) {
Fail(VERIFY_ERROR_CLASS_CHANGE)
<< "non-interface method " << PrettyMethod(dex_method_idx, *dex_file_)
<< " is in an interface class " << PrettyClass(klass);
diff --git a/test/048-reflect-v8/run b/test/048-reflect-v8/run
deleted file mode 100644
index ba3318a..0000000
--- a/test/048-reflect-v8/run
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-
-# Ensure that the default methods are turned on for dalvikvm and dex2oat
-${RUN} "$@" --experimental default-methods
diff --git a/test/449-checker-bce/src/Main.java b/test/449-checker-bce/src/Main.java
index 3e6d1f4..06cfd0a 100644
--- a/test/449-checker-bce/src/Main.java
+++ b/test/449-checker-bce/src/Main.java
@@ -622,28 +622,39 @@
static int[][] mA;
/// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before)
- /// CHECK-DAG: NullCheck
- /// CHECK-DAG: ArrayLength
- /// CHECK-DAG: BoundsCheck
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: NullCheck
- /// CHECK-DAG: ArrayLength
- /// CHECK-DAG: BoundsCheck
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: InvokeStaticOrDirect
- /// CHECK-DAG: ArraySet
-
+ // Array references mA[i] and ..[j] both in inner loop.
+ /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Bounds1:i\d+>>] loop:<<InnerLoop:B\d+>>
+ /// CHECK-DAG: <<Array1>> NullCheck [<<Field1:l\d+>>] loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Len1:i\d+>> ArrayLength [<<Array1>>] loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Bounds1>> BoundsCheck [<<Index1:i\d+>>,<<Len1>>] loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Bounds2:i\d+>>] loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Array2>> NullCheck [<<Get1>>] loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Len2:i\d+>> ArrayLength [<<Array2>>] loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Bounds2>> BoundsCheck [<<Index2:i\d+>>,<<Len2>>] loop:<<InnerLoop>>
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>] loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop:B\d+>>
+ /// CHECK-DAG: <<Field1>> StaticFieldGet loop:none
+ /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
+ //
+ /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after)
+ // Array reference mA[i] hoisted to same level as deopt.
+ /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>>
+ /// CHECK-DAG: ArrayLength loop:<<OuterLoop>>
+ /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Index1:i\d+>>] loop:<<OuterLoop>>
+ // Array reference ..[j] still in inner loop, with a direct index.
+ /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Index2:i\d+>>] loop:<<InnerLoop:B\d+>>
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>] loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>>
+ /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop>>
+ // Synthetic phi.
+ /// CHECK-DAG: <<Array2>> Phi loop:<<OuterLoop>>
+ /// CHECK-DAG: <<Array1>> StaticFieldGet loop:none
+ /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
+ //
/// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after)
/// CHECK-NOT: NullCheck
- /// CHECK-NOT: ArrayLength
/// CHECK-NOT: BoundsCheck
- /// CHECK-DAG: ArrayGet
- /// CHECK-NOT: ArrayGet
- /// CHECK-DAG: InvokeStaticOrDirect
- /// CHECK-DAG: ArraySet
- /// CHECK-DAG: Exit
- /// CHECK-DAG: Deoptimize
-
static void dynamicBCEAndIntrinsic(int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
diff --git a/test/530-checker-loops/src/Main.java b/test/530-checker-loops/src/Main.java
index f1d9a37..deff279 100644
--- a/test/530-checker-loops/src/Main.java
+++ b/test/530-checker-loops/src/Main.java
@@ -26,7 +26,7 @@
//
/// CHECK-START: int Main.linear(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linear(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -40,7 +40,7 @@
}
/// CHECK-START: int Main.linearDown(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearDown(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -54,7 +54,7 @@
}
/// CHECK-START: int Main.linearObscure(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearObscure(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -69,7 +69,7 @@
}
/// CHECK-START: int Main.linearVeryObscure(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearVeryObscure(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -84,7 +84,7 @@
}
/// CHECK-START: int Main.hiddenStride(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.hiddenStride(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -101,7 +101,7 @@
}
/// CHECK-START: int Main.linearWhile(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearWhile(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -116,7 +116,7 @@
}
/// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -134,7 +134,7 @@
}
/// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -156,7 +156,7 @@
}
/// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -173,7 +173,7 @@
}
/// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -194,7 +194,7 @@
}
/// CHECK-START: int[] Main.linearWithParameter(int) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int[] Main.linearWithParameter(int) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -208,7 +208,7 @@
}
/// CHECK-START: int[] Main.linearCopy(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int[] Main.linearCopy(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -223,8 +223,8 @@
}
/// CHECK-START: int Main.linearByTwo(int[]) BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearByTwo(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -241,7 +241,7 @@
}
/// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -255,10 +255,12 @@
}
/// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after)
/// CHECK-NOT: Deoptimize
private static int linearByTwoSkip2(int x[]) {
int result = 0;
@@ -270,7 +272,7 @@
}
/// CHECK-START: int Main.linearWithCompoundStride() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearWithCompoundStride() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -287,7 +289,7 @@
}
/// CHECK-START: int Main.linearWithLargePositiveStride() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearWithLargePositiveStride() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -305,10 +307,12 @@
}
/// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
/// CHECK-NOT: Deoptimize
private static int linearWithVeryLargePositiveStride() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
@@ -323,7 +327,7 @@
}
/// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -341,10 +345,12 @@
}
/// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
/// CHECK-NOT: Deoptimize
private static int linearWithVeryLargeNegativeStride() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
@@ -359,7 +365,7 @@
}
/// CHECK-START: int Main.linearForNEUp() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearForNEUp() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -374,7 +380,7 @@
}
/// CHECK-START: int Main.linearForNEDown() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearForNEDown() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -389,7 +395,7 @@
}
/// CHECK-START: int Main.linearDoWhileUp() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearDoWhileUp() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -405,7 +411,7 @@
}
/// CHECK-START: int Main.linearDoWhileDown() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearDoWhileDown() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -421,10 +427,12 @@
}
/// CHECK-START: int Main.linearShort() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearShort() BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.linearShort() BCE (after)
/// CHECK-NOT: Deoptimize
private static int linearShort() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
@@ -437,7 +445,7 @@
}
/// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -458,20 +466,11 @@
}
/// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (after)
/// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
/// CHECK-NOT: Deoptimize
private static void linearTriangularOnTwoArrayLengths(int n) {
int[] a = new int[n];
@@ -488,20 +487,11 @@
}
/// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (after)
/// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
/// CHECK-NOT: Deoptimize
private static void linearTriangularOnOneArrayLength(int n) {
int[] a = new int[n];
@@ -518,20 +508,11 @@
}
/// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (after)
/// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
/// CHECK-NOT: Deoptimize
private static void linearTriangularOnParameter(int n) {
int[] a = new int[n];
@@ -548,32 +529,13 @@
}
/// CHECK-START: void Main.linearTriangularVariations(int) BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.linearTriangularVariations(int) BCE (after)
/// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
/// CHECK-NOT: Deoptimize
private static void linearTriangularVariations(int n) {
int[] a = new int[n];
@@ -616,22 +578,11 @@
}
/// CHECK-START: void Main.bubble(int[]) BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: If
- /// CHECK: ArraySet
- /// CHECK: ArraySet
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.bubble(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: If
- /// CHECK: ArraySet
- /// CHECK: ArraySet
/// CHECK-NOT: Deoptimize
private static void bubble(int[] a) {
for (int i = a.length; --i >= 0;) {
@@ -646,7 +597,7 @@
}
/// CHECK-START: int Main.periodicIdiom(int) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.periodicIdiom(int) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -664,7 +615,7 @@
}
/// CHECK-START: int Main.periodicSequence2(int) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.periodicSequence2(int) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -685,10 +636,10 @@
}
/// CHECK-START: int Main.periodicSequence4(int) BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.periodicSequence4(int) BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -713,7 +664,7 @@
}
/// CHECK-START: int Main.justRightUp1() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justRightUp1() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -728,7 +679,7 @@
}
/// CHECK-START: int Main.justRightUp2() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justRightUp2() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -743,7 +694,7 @@
}
/// CHECK-START: int Main.justRightUp3() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justRightUp3() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -758,10 +709,12 @@
}
/// CHECK-START: int Main.justOOBUp() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justOOBUp() BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justOOBUp() BCE (after)
/// CHECK-NOT: Deoptimize
private static int justOOBUp() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
@@ -774,7 +727,7 @@
}
/// CHECK-START: int Main.justRightDown1() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justRightDown1() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -789,7 +742,7 @@
}
/// CHECK-START: int Main.justRightDown2() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justRightDown2() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -804,7 +757,7 @@
}
/// CHECK-START: int Main.justRightDown3() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justRightDown3() BCE (after)
/// CHECK-NOT: BoundsCheck
@@ -819,10 +772,12 @@
}
/// CHECK-START: int Main.justOOBDown() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justOOBDown() BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justOOBDown() BCE (after)
/// CHECK-NOT: Deoptimize
private static int justOOBDown() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
@@ -835,66 +790,74 @@
}
/// CHECK-START: void Main.lowerOOB(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
/// CHECK-NOT: Deoptimize
private static void lowerOOB(int[] x) {
+ // OOB!
for (int i = -1; i < x.length; i++) {
sResult += x[i];
}
}
/// CHECK-START: void Main.upperOOB(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.upperOOB(int[]) BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
/// CHECK-NOT: Deoptimize
private static void upperOOB(int[] x) {
+ // OOB!
for (int i = 0; i <= x.length; i++) {
sResult += x[i];
}
}
/// CHECK-START: void Main.doWhileUpOOB() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.doWhileUpOOB() BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
/// CHECK-NOT: Deoptimize
private static void doWhileUpOOB() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int i = 0;
+ // OOB!
do {
sResult += x[i++];
} while (i <= x.length);
}
/// CHECK-START: void Main.doWhileDownOOB() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.doWhileDownOOB() BCE (after)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
/// CHECK-NOT: Deoptimize
private static void doWhileDownOOB() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int i = x.length - 1;
+ // OOB!
do {
sResult += x[i--];
} while (-1 <= i);
}
/// CHECK-START: int[] Main.multiply1() BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int[] Main.multiply1() BCE (after)
/// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
/// CHECK-NOT: Deoptimize
private static int[] multiply1() {
int[] a = new int[10];
@@ -912,21 +875,20 @@
}
/// CHECK-START: int[] Main.multiply2() BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int[] Main.multiply2() BCE (after)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int[] Main.multiply2() BCE (after)
+ /// CHECK-NOT: Deoptimize
static int[] multiply2() {
int[] a = new int[10];
try {
for (int i = -3; i <= 3; i++) {
for (int j = -3; j <= 3; j++) {
// Range [-9,9]: unsafe.
- a[i * j] += 1;
+ a[i * j] += 1;
}
}
} catch (Exception e) {
@@ -936,24 +898,19 @@
}
/// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (before)
- /// CHECK: StaticFieldGet
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: StaticFieldSet
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
//
/// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
- /// CHECK: StaticFieldGet
- /// CHECK-NOT: NullCheck
- /// CHECK-NOT: ArrayLength
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: StaticFieldSet
- /// CHECK: Exit
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
private static int linearDynamicBCE1(int[] x, int lo, int hi) {
int result = 0;
for (int i = lo; i < hi; i++) {
@@ -963,24 +920,19 @@
}
/// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (before)
- /// CHECK: StaticFieldGet
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: StaticFieldSet
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
//
/// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
- /// CHECK: StaticFieldGet
- /// CHECK-NOT: NullCheck
- /// CHECK-NOT: ArrayLength
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: StaticFieldSet
- /// CHECK: Exit
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
private static int linearDynamicBCE2(int[] x, int lo, int hi, int offset) {
int result = 0;
for (int i = lo; i < hi; i++) {
@@ -990,19 +942,19 @@
}
/// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (before)
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
//
/// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK-NOT: NullCheck
- /// CHECK-NOT: ArrayLength
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
private static int wrapAroundDynamicBCE(int[] x) {
int w = 9;
int result = 0;
@@ -1014,19 +966,19 @@
}
/// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (before)
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
//
/// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK-NOT: NullCheck
- /// CHECK-NOT: ArrayLength
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
private static int periodicDynamicBCE(int[] x) {
int k = 0;
int result = 0;
@@ -1038,20 +990,19 @@
}
/// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
//
/// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
- /// CHECK-NOT: NullCheck
- /// CHECK-NOT: ArrayLength
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: Exit
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
static int dynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
// This loop could be infinite for hi = max int. Since i is also used
// as subscript, however, dynamic bce can proceed.
@@ -1063,16 +1014,14 @@
}
/// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
//
/// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
/// CHECK-NOT: Deoptimize
static int noDynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
// As above, but now the index is not used as subscript,
@@ -1085,16 +1034,14 @@
}
/// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (before)
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
//
/// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
/// CHECK-NOT: Deoptimize
static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) {
int result = 0;
@@ -1107,42 +1054,21 @@
}
/// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (before)
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: NotEqual
- /// CHECK: If
- /// CHECK: If
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: If
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
//
/// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
- /// CHECK: NullCheck
- /// CHECK: ArrayLength
- /// CHECK: NotEqual
- /// CHECK: If
- /// CHECK: If
- /// CHECK-NOT: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: If
- /// CHECK: Deoptimize
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
- /// CHECK: BoundsCheck
- /// CHECK-NOT: BoundsCheck
- /// CHECK: Exit
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK-NOT: ArrayGet
+ // Order matters:
+ /// CHECK: Deoptimize loop:<<Loop:B\d+>>
+ // CHECK-NOT: Goto loop:<<Loop>>
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
+ /// CHECK: Goto loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
+ /// CHECK-DAG: Deoptimize loop:none
static int dynamicBCEAndConstantIndices(int[] x, int[][] a, int lo, int hi) {
// Deliberately test array length on a before the loop so that only bounds checks
// on constant subscripts remain, making them a viable candidate for hoisting.
@@ -1166,80 +1092,73 @@
return result;
}
- /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], java.lang.Integer[], int, int) BCE (before)
- /// CHECK: If
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ // For brevity, just test occurrence of at least one of each in the loop:
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
//
- /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], java.lang.Integer[], int, int) BCE (after)
- /// CHECK-DAG: If
- /// CHECK-NOT: BoundsCheck
- /// CHECK-DAG: ArrayGet
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: ArrayGet
- /// CHECK-DAG: Exit
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: ArrayGet
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: Deoptimize
- /// CHECK-DAG: ArrayGet
- static int dynamicBCEAndConstantIndicesAllTypes(int[] q,
- boolean[] r,
- byte[] s,
- char[] t,
- short[] u,
- int[] v,
- long[] w,
- float[] x,
- double[] y,
- Integer[] z, int lo, int hi) {
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-NOT: ArrayGet loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
+ /// CHECK-DAG: Deoptimize loop:none
+ static int dynamicBCEAndConstantIndicesAllPrimTypes(int[] q,
+ boolean[] r,
+ byte[] s,
+ char[] t,
+ short[] u,
+ int[] v,
+ long[] w,
+ float[] x,
+ double[] y, int lo, int hi) {
int result = 0;
for (int i = lo; i < hi; i++) {
+ // All constant index array references can be hoisted out of the loop during BCE on q[i].
result += q[i] + (r[0] ? 1 : 0) + (int) s[0] + (int) t[0] + (int) u[0] + (int) v[0] +
- (int) w[0] + (int) x[0] + (int) y[0] + (int) z[0];
+ (int) w[0] + (int) x[0] + (int) y[0];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
+ static int dynamicBCEAndConstantIndexRefType(int[] q, Integer[] z, int lo, int hi) {
+ int result = 0;
+ for (int i = lo; i < hi; i++) {
+ // Similar to above, but now implicit call to intValue() may prevent hoisting
+ // z[0] itself during BCE on q[i]. Therefore, we just check BCE on q[i].
+ result += q[i] + z[0];
}
return result;
}
@@ -1501,9 +1420,10 @@
long[] x6 = { 6 };
float[] x7 = { 7 };
double[] x8 = { 8 };
+ expectEquals(415,
+ dynamicBCEAndConstantIndicesAllPrimTypes(x, x1, x2, x3, x4, x5, x6, x7, x8, 0, 10));
Integer[] x9 = { 9 };
- expectEquals(505,
- dynamicBCEAndConstantIndicesAllTypes(x, x1, x2, x3, x4, x5, x6, x7, x8, x9, 0, 10));
+ expectEquals(145, dynamicBCEAndConstantIndexRefType(x, x9, 0, 10));
}
private static void expectEquals(int expected, int result) {
diff --git a/test/960-default-smali/run b/test/960-default-smali/run
deleted file mode 100755
index 22f6800..0000000
--- a/test/960-default-smali/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-${RUN} --experimental default-methods "$@"
diff --git a/test/961-default-iface-resolution-generated/run b/test/961-default-iface-resolution-generated/run
deleted file mode 100755
index 22f6800..0000000
--- a/test/961-default-iface-resolution-generated/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-${RUN} --experimental default-methods "$@"
diff --git a/test/962-iface-static/run b/test/962-iface-static/run
deleted file mode 100755
index d37737f..0000000
--- a/test/962-iface-static/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-${RUN} --experimental default-methods "$@"
diff --git a/test/963-default-range-smali/run b/test/963-default-range-smali/run
deleted file mode 100755
index d37737f..0000000
--- a/test/963-default-range-smali/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-${RUN} --experimental default-methods "$@"
diff --git a/test/964-default-iface-init-generated/run b/test/964-default-iface-init-generated/run
deleted file mode 100755
index 22f6800..0000000
--- a/test/964-default-iface-init-generated/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-${RUN} --experimental default-methods "$@"
diff --git a/test/965-default-verify/run b/test/965-default-verify/run
deleted file mode 100755
index 8944ea9..0000000
--- a/test/965-default-verify/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-${RUN} "$@" --experimental default-methods
diff --git a/test/966-default-conflict/run b/test/966-default-conflict/run
deleted file mode 100755
index 8944ea9..0000000
--- a/test/966-default-conflict/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-${RUN} "$@" --experimental default-methods
diff --git a/test/967-default-ame/run b/test/967-default-ame/run
deleted file mode 100755
index 8944ea9..0000000
--- a/test/967-default-ame/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-${RUN} "$@" --experimental default-methods
diff --git a/test/968-default-partial-compile-generated/run b/test/968-default-partial-compile-generated/run
deleted file mode 100755
index 6d2930d..0000000
--- a/test/968-default-partial-compile-generated/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-${RUN} "$@" --experimental default-methods
diff --git a/test/969-iface-super/run b/test/969-iface-super/run
deleted file mode 100755
index 8944ea9..0000000
--- a/test/969-iface-super/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-${RUN} "$@" --experimental default-methods
diff --git a/test/970-iface-super-resolution-generated/run b/test/970-iface-super-resolution-generated/run
deleted file mode 100755
index 6d2930d..0000000
--- a/test/970-iface-super-resolution-generated/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-${RUN} "$@" --experimental default-methods
diff --git a/test/971-iface-super/run b/test/971-iface-super/run
deleted file mode 100755
index 6d2930d..0000000
--- a/test/971-iface-super/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-${RUN} "$@" --experimental default-methods
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 36dd9f4..429af6a 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -525,16 +525,22 @@
TEST_ART_BROKEN_OPTIMIZING_DEBUGGABLE_RUN_TESTS :=
+# Tests that should fail in the read barrier configuration with the interpreter.
+# 004: Occasional timeout: "TEST TIMED OUT!" (b/26786154).
+# 141: Occasional failures: "Aborted" (b/25866001).
+TEST_ART_BROKEN_INTERPRETER_READ_BARRIER_RUN_TESTS := \
+ 004-ThreadStress \
+ 141-class-unload
-# Tests that should fail in the read barrier configuration with the default (Quick) compiler.
-# 137: Quick has no support for read barriers and punts to the
-# interpreter, but CFI unwinding expects managed frames.
-# 554: Quick does not support JIT profiling.
+# Tests that should fail in the read barrier configuration with the default (Quick) compiler (AOT).
+# Quick has no support for read barriers and punts to the interpreter, so this list is composed of
+# tests expected to fail with the interpreter, both on the concurrent collector and in general.
TEST_ART_BROKEN_DEFAULT_READ_BARRIER_RUN_TESTS := \
- 137-cfi \
- 554-jit-profile-file
+ $(TEST_ART_BROKEN_INTERPRETER_READ_BARRIER_RUN_TESTS) \
+ $(TEST_ART_BROKEN_INTERPRETER_RUN_TESTS)
-# Tests that should fail in the read barrier configuration with the Optimizing compiler.
+# Tests that should fail in the read barrier configuration with the Optimizing compiler (AOT).
+# 004: Occasional timeout: "TEST TIMED OUT!" (b/26786154).
# 484: Baker's fast path based read barrier compiler instrumentation generates code containing
# more parallel moves on x86, thus some Checker assertions may fail.
# 527: On ARM64, the read barrier instrumentation does not support the HArm64IntermediateAddress
@@ -542,16 +548,28 @@
# 537: Expects an array copy to be intrinsified on x86-64, but calling-on-slowpath intrinsics are
# not yet handled in the read barrier configuration.
TEST_ART_BROKEN_OPTIMIZING_READ_BARRIER_RUN_TESTS := \
+ 004-ThreadStress \
484-checker-register-hints \
527-checker-array-access-split \
537-checker-arraycopy
# Tests that should fail in the read barrier configuration with JIT.
+# 004: Occasional timeout: "TEST TIMED OUT!" (b/26786154).
# 141: Disabled because of intermittent failures on the ART Builtbot (b/25866001).
+# 496: Occasional timeout: "Fault message: timeout: the monitored command dumped core" (b/26786304).
TEST_ART_BROKEN_JIT_READ_BARRIER_RUN_TESTS := \
- 141-class-unload
+ 004-ThreadStress \
+ 141-class-unload \
+ 496-checker-inlining-and-class-loader
ifeq ($(ART_USE_READ_BARRIER),true)
+ ifneq (,$(filter interpreter,$(COMPILER_TYPES)))
+ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES), \
+ $(PREBUILD_TYPES),interpreter,$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES), \
+ $(JNI_TYPES),$(IMAGE_TYPES),$(PICTEST_TYPES),$(DEBUGGABLE_TYPES), \
+ $(TEST_ART_BROKEN_INTERPRETER_READ_BARRIER_RUN_TESTS),$(ALL_ADDRESS_SIZES))
+ endif
+
ifneq (,$(filter default,$(COMPILER_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES), \
$(PREBUILD_TYPES),default,$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES), \