summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.common_build.mk4
-rw-r--r--cmdline/cmdline_parser_test.cc12
-rw-r--r--cmdline/cmdline_types.h4
-rw-r--r--compiler/dex/quick/dex_file_method_inliner.cc49
-rw-r--r--compiler/dex/quick/dex_file_method_inliner.h9
-rw-r--r--compiler/dex/quick/quick_compiler.cc42
-rw-r--r--compiler/image_test.cc2
-rw-r--r--compiler/optimizing/bounds_check_elimination.h4
-rw-r--r--compiler/optimizing/graph_visualizer.cc2
-rw-r--r--compiler/optimizing/intrinsics.cc50
-rw-r--r--compiler/optimizing/intrinsics_arm.cc24
-rw-r--r--compiler/optimizing/intrinsics_arm64.cc24
-rw-r--r--compiler/optimizing/intrinsics_list.h12
-rw-r--r--compiler/optimizing/intrinsics_mips.cc15
-rw-r--r--compiler/optimizing/intrinsics_mips64.cc14
-rw-r--r--compiler/optimizing/intrinsics_x86.cc18
-rw-r--r--compiler/optimizing/intrinsics_x86_64.cc16
-rw-r--r--compiler/optimizing/nodes.cc5
-rw-r--r--oatdump/oatdump.cc2
-rw-r--r--patchoat/patchoat.cc2
-rw-r--r--runtime/class_linker.cc18
-rw-r--r--runtime/class_linker.h2
-rw-r--r--runtime/class_linker_test.cc38
-rw-r--r--runtime/dex_file.h1
-rw-r--r--runtime/dex_file_verifier.cc14
-rw-r--r--runtime/experimental_flags.h5
-rw-r--r--runtime/gc/accounting/mod_union_table_test.cc9
-rw-r--r--runtime/gc/collector/concurrent_copying.cc7
-rw-r--r--runtime/gc/collector/garbage_collector.h4
-rw-r--r--runtime/gc/collector/mark_compact.h2
-rw-r--r--runtime/gc/collector/mark_sweep.cc4
-rw-r--r--runtime/gc/collector/mark_sweep.h2
-rw-r--r--runtime/gc/collector/semi_space.h4
-rw-r--r--runtime/gc/heap.cc28
-rw-r--r--runtime/gc/heap.h44
-rw-r--r--runtime/gc/space/dlmalloc_space.cc2
-rw-r--r--runtime/gc/space/image_space.cc6
-rw-r--r--runtime/gc/space/rosalloc_space.cc8
-rw-r--r--runtime/gc/space/space_create_test.cc6
-rw-r--r--runtime/gc/space/space_test.h7
-rw-r--r--runtime/image-inl.h47
-rw-r--r--runtime/image.cc18
-rw-r--r--runtime/image.h3
-rw-r--r--runtime/intern_table.cc1
-rw-r--r--runtime/mirror/dex_cache.cc6
-rw-r--r--runtime/mirror/dex_cache.h7
-rw-r--r--runtime/native/dalvik_system_VMDebug.cc47
-rw-r--r--runtime/oat_file_manager.cc13
-rw-r--r--runtime/parsed_options.cc11
-rw-r--r--runtime/quick/inline_method_analyser.h8
-rw-r--r--runtime/runtime.cc2
-rw-r--r--runtime/runtime_options.def2
-rw-r--r--runtime/verifier/method_verifier.cc37
-rw-r--r--test/048-reflect-v8/run19
-rw-r--r--test/449-checker-bce/src/Main.java49
-rw-r--r--test/530-checker-loops/src/Main.java570
-rwxr-xr-xtest/960-default-smali/run17
-rwxr-xr-xtest/961-default-iface-resolution-generated/run17
-rwxr-xr-xtest/962-iface-static/run17
-rwxr-xr-xtest/963-default-range-smali/run17
-rwxr-xr-xtest/964-default-iface-init-generated/run17
-rwxr-xr-xtest/965-default-verify/run17
-rwxr-xr-xtest/966-default-conflict/run17
-rwxr-xr-xtest/967-default-ame/run17
-rwxr-xr-xtest/968-default-partial-compile-generated/run17
-rwxr-xr-xtest/969-iface-super/run17
-rwxr-xr-xtest/970-iface-super-resolution-generated/run17
-rwxr-xr-xtest/971-iface-super/run17
-rw-r--r--tools/libcore_failures.txt1
69 files changed, 776 insertions, 790 deletions
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk
index eec471e457..dc5385309a 100644
--- a/build/Android.common_build.mk
+++ b/build/Android.common_build.mk
@@ -318,6 +318,10 @@ ifeq ($(ART_USE_READ_BARRIER),true)
art_cflags += -DART_READ_BARRIER_TYPE_IS_$(ART_READ_BARRIER_TYPE)=1
art_asflags += -DART_USE_READ_BARRIER=1
art_asflags += -DART_READ_BARRIER_TYPE_IS_$(ART_READ_BARRIER_TYPE)=1
+
+ # Temporarily override -fstack-protector-strong with -fstack-protector to avoid a major
+ # slowdown with the read barrier config. b/26744236.
+ art_cflags += -fstack-protector
endif
ifeq ($(ART_USE_TLAB),true)
diff --git a/cmdline/cmdline_parser_test.cc b/cmdline/cmdline_parser_test.cc
index fe83ba9e14..dc2c9c954a 100644
--- a/cmdline/cmdline_parser_test.cc
+++ b/cmdline/cmdline_parser_test.cc
@@ -535,7 +535,7 @@ TEST_F(CmdlineParserTest, TestProfilerOptions) {
/* -Xexperimental:_ */
TEST_F(CmdlineParserTest, TestExperimentalFlags) {
- // Off by default
+ // Default
EXPECT_SINGLE_PARSE_DEFAULT_VALUE(ExperimentalFlags::kNone,
"",
M::Experimental);
@@ -549,16 +549,6 @@ TEST_F(CmdlineParserTest, TestExperimentalFlags) {
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 97c672c560..740199d541 100644
--- a/cmdline/cmdline_types.h
+++ b/cmdline/cmdline_types.h
@@ -847,11 +847,9 @@ template<>
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/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index 3766093fa8..22b178ce7d 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -37,13 +37,21 @@ namespace { // anonymous namespace
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 @@ static_assert(arraysize(kIntrinsicIsStatic) == kInlineOpNop,
"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 @@ const char* const DexFileMethodInliner::kNameCacheNames[] = {
"equals", // kNameCacheEquals
"getCharsNoCheck", // kNameCacheGetCharsNoCheck
"isEmpty", // kNameCacheIsEmpty
+ "isInfinite", // kNameCacheIsInfinite
+ "isNaN", // kNameCacheIsNaN
"indexOf", // kNameCacheIndexOf
"length", // kNameCacheLength
"<init>", // kNameCacheInit
@@ -296,10 +314,14 @@ const char* const DexFileMethodInliner::kNameCacheNames[] = {
"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 @@ const DexFileMethodInliner::ProtoDef DexFileMethodInliner::kProtoCacheDefs[] = {
{ 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 @@ const DexFileMethodInliner::ProtoDef DexFileMethodInliner::kProtoCacheDefs[] = {
{ 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 @@ const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods
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 @@ const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods
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 @@ bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) {
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 28036237d7..59b8a533ae 100644
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ b/compiler/dex/quick/dex_file_method_inliner.h
@@ -190,6 +190,8 @@ class DexFileMethodInliner {
kNameCacheEquals,
kNameCacheGetCharsNoCheck,
kNameCacheIsEmpty,
+ kNameCacheIsInfinite,
+ kNameCacheIsNaN,
kNameCacheIndexOf,
kNameCacheLength,
kNameCacheInit,
@@ -225,10 +227,14 @@ class DexFileMethodInliner {
kNameCachePutOrderedObject,
kNameCacheArrayCopy,
kNameCacheBitCount,
+ kNameCacheCompare,
+ kNameCacheHighestOneBit,
+ kNameCacheLowestOneBit,
kNameCacheNumberOfLeadingZeros,
kNameCacheNumberOfTrailingZeros,
kNameCacheRotateRight,
kNameCacheRotateLeft,
+ kNameCacheSignum,
kNameCacheLast
};
@@ -247,8 +253,10 @@ class DexFileMethodInliner {
kProtoCacheF_F,
kProtoCacheFF_F,
kProtoCacheD_J,
+ kProtoCacheD_Z,
kProtoCacheJ_D,
kProtoCacheF_I,
+ kProtoCacheF_Z,
kProtoCacheI_F,
kProtoCacheII_I,
kProtoCacheI_C,
@@ -263,6 +271,7 @@ class DexFileMethodInliner {
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 ebc9a2c9ea..027290f9b1 100644
--- a/compiler/dex/quick/quick_compiler.cc
+++ b/compiler/dex/quick/quick_compiler.cc
@@ -486,11 +486,6 @@ static const size_t kUnsupportedOpcodesSize[] = {
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 @@ static bool CanCompileShorty(const char* shorty, InstructionSet instruction_set)
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 @@ bool QuickCompiler::CanCompileMethod(uint32_t method_idx,
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/image_test.cc b/compiler/image_test.cc
index b8416751c5..b65fb36167 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -181,7 +181,7 @@ void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
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 b9df686ffd..6dc53207ea 100644
--- a/compiler/optimizing/bounds_check_elimination.h
+++ b/compiler/optimizing/bounds_check_elimination.h
@@ -29,13 +29,13 @@ class BoundsCheckElimination : public HOptimization {
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 32c3a925e0..280516252b 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 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
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 5caf077858..a6be324730 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -131,6 +131,16 @@ static Intrinsics GetIntrinsic(InlineMethod method) {
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 @@ static Intrinsics GetIntrinsic(InlineMethod method) {
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 @@ static Intrinsics GetIntrinsic(InlineMethod method) {
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 e72f927e44..97fe5872bf 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -1580,13 +1580,9 @@ void IntrinsicCodeGeneratorARM::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED)
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(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)
+
+// 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 8cf2d4f393..c888f01841 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -1465,11 +1465,7 @@ void IntrinsicCodeGeneratorARM64::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED
}
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(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)
+
+// 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 ea380347da..88217b308e 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 81112b1a34..0d9cf091cc 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -1013,6 +1013,21 @@ UNIMPLEMENTED_INTRINSIC(MathNextAfter)
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 769c4228c4..cba84fa3e3 100644
--- a/compiler/optimizing/intrinsics_mips64.cc
+++ b/compiler/optimizing/intrinsics_mips64.cc
@@ -1760,6 +1760,20 @@ 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_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 3f5688b0db..acc40bc998 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -2593,11 +2593,27 @@ void IntrinsicCodeGeneratorX86::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED)
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 23a628f243..6ccc5d1e01 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -2592,6 +2592,22 @@ void IntrinsicCodeGeneratorX86_64::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSE
}
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 adf8734214..92f758d61d 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2221,10 +2221,7 @@ void HInvoke::SetIntrinsic(Intrinsics intrinsic,
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/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 7b9ce5bd1b..57b52fcdd8 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -40,7 +40,7 @@
#include "gc/space/image_space.h"
#include "gc/space/large_object_space.h"
#include "gc/space/space-inl.h"
-#include "image.h"
+#include "image-inl.h"
#include "indenter.h"
#include "linker/buffered_output_stream.h"
#include "linker/file_output_stream.h"
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 7e4ce917db..1668dc5f25 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -35,7 +35,7 @@
#include "elf_file.h"
#include "elf_file_impl.h"
#include "gc/space/image_space.h"
-#include "image.h"
+#include "image-inl.h"
#include "mirror/abstract_method.h"
#include "mirror/object-inl.h"
#include "mirror/method.h"
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index ff38394038..bb709e8774 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -53,6 +53,7 @@
#include "gc/heap.h"
#include "gc/space/image_space.h"
#include "handle_scope-inl.h"
+#include "image-inl.h"
#include "intern_table.h"
#include "interpreter/interpreter.h"
#include "jit/jit.h"
@@ -2926,19 +2927,19 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file,
CHECK(dex_cache.Get() != nullptr) << dex_file.GetLocation();
// For app images, the dex cache location may be a suffix of the dex file location since the
// dex file location is an absolute path.
- const size_t dex_cache_length = dex_cache->GetLocation()->GetLength();
+ const std::string dex_cache_location = dex_cache->GetLocation()->ToModifiedUtf8();
+ const size_t dex_cache_length = dex_cache_location.length();
CHECK_GT(dex_cache_length, 0u) << dex_file.GetLocation();
std::string dex_file_location = dex_file.GetLocation();
CHECK_GE(dex_file_location.length(), dex_cache_length)
- << dex_cache->GetLocation()->ToModifiedUtf8() << " " << dex_file.GetLocation();
+ << dex_cache_location << " " << dex_file.GetLocation();
// Take suffix.
const std::string dex_file_suffix = dex_file_location.substr(
dex_file_location.length() - dex_cache_length,
dex_cache_length);
// Example dex_cache location is SettingsProvider.apk and
// dex file location is /system/priv-app/SettingsProvider/SettingsProvider.apk
- CHECK(dex_cache->GetLocation()->Equals(dex_file_suffix))
- << dex_cache->GetLocation()->ToModifiedUtf8() << " " << dex_file.GetLocation();
+ CHECK_EQ(dex_cache_location, dex_file_suffix);
// Clean up pass to remove null dex caches.
// Null dex caches can occur due to class unloading and we are lazily removing null entries.
JavaVMExt* const vm = self->GetJniEnv()->vm;
@@ -5973,15 +5974,6 @@ bool ClassLinker::LinkInterfaceMethods(
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/class_linker.h b/runtime/class_linker.h
index d503dd4704..4975c29742 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -1063,8 +1063,8 @@ class ClassLinker {
friend class ImageWriter; // for GetClassRoots
friend class JniCompilerTest; // for GetRuntimeQuickGenericJniStub
friend class JniInternalTest; // for GetRuntimeQuickGenericJniStub
+ ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName); // for DexLock, and RegisterDexFileLocked
ART_FRIEND_TEST(mirror::DexCacheTest, Open); // for AllocDexCache
-
DISALLOW_COPY_AND_ASSIGN(ClassLinker);
};
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 471d7ca5e6..40dfda9316 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -1201,4 +1201,42 @@ TEST_F(ClassLinkerTest, IsBootStrapClassLoaded) {
EXPECT_FALSE(statics.Get()->IsBootStrapClassLoaded());
}
+// Regression test for b/26799552.
+TEST_F(ClassLinkerTest, RegisterDexFileName) {
+ ScopedObjectAccess soa(Thread::Current());
+ StackHandleScope<2> hs(soa.Self());
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ MutableHandle<mirror::DexCache> dex_cache(hs.NewHandle<mirror::DexCache>(nullptr));
+ {
+ ReaderMutexLock mu(soa.Self(), *class_linker->DexLock());
+ for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
+ dex_cache.Assign(down_cast<mirror::DexCache*>(soa.Self()->DecodeJObject(data.weak_root)));
+ if (dex_cache.Get() != nullptr) {
+ break;
+ }
+ }
+ ASSERT_TRUE(dex_cache.Get() != nullptr);
+ }
+ // Make a copy of the dex cache and change the name.
+ dex_cache.Assign(dex_cache->Clone(soa.Self())->AsDexCache());
+ const uint16_t data[] = { 0x20AC, 0x20A1 };
+ Handle<mirror::String> location(hs.NewHandle(mirror::String::AllocFromUtf16(soa.Self(),
+ arraysize(data),
+ data)));
+ dex_cache->SetLocation(location.Get());
+ const DexFile* old_dex_file = dex_cache->GetDexFile();
+
+ DexFile* dex_file = new DexFile(old_dex_file->Begin(),
+ old_dex_file->Size(),
+ location->ToModifiedUtf8(),
+ 0u,
+ nullptr,
+ nullptr);
+ {
+ WriterMutexLock mu(soa.Self(), *class_linker->DexLock());
+ // Check that inserting with a UTF16 name works.
+ class_linker->RegisterDexFileLocked(*dex_file, dex_cache);
+ }
+}
+
} // namespace art
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 968b37ba86..200121e61f 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -1260,6 +1260,7 @@ class DexFile {
mutable std::unique_ptr<TypeLookupTable> lookup_table_;
friend class DexFileVerifierTest;
+ ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName); // for constructor
};
struct DexFileReference {
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index 727f4fc659..7a852e216e 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -2538,20 +2538,6 @@ bool DexFileVerifier::CheckMethodAccessFlags(uint32_t method_index,
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/experimental_flags.h b/runtime/experimental_flags.h
index 2e674e95c6..198f3fa56e 100644
--- a/runtime/experimental_flags.h
+++ b/runtime/experimental_flags.h
@@ -27,7 +27,6 @@ struct ExperimentalFlags {
enum {
kNone = 0x0000,
kLambdas = 0x0001,
- kDefaultMethods = 0x0002,
};
constexpr ExperimentalFlags() : value_(0x0000) {}
@@ -69,10 +68,6 @@ inline std::ostream& operator<<(std::ostream& stream, const ExperimentalFlags& e
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 edab1b0a60..349d6ffaa9 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 @@ void ModUnionTableTest::RunTest(ModUnionTableFactory::TableType type) {
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 @@ void ModUnionTableTest::RunTest(ModUnionTableFactory::TableType type) {
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 bcfcb89e62..9397c3585a 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -24,6 +24,7 @@
#include "gc/reference_processor.h"
#include "gc/space/image_space.h"
#include "gc/space/space-inl.h"
+#include "image-inl.h"
#include "intern_table.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
@@ -2066,8 +2067,9 @@ mirror::Object* ConcurrentCopying::MarkNonMoving(mirror::Object* ref) {
}
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 +2077,8 @@ void ConcurrentCopying::FinishPhase() {
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 954c80ec7b..580486aa68 100644
--- a/runtime/gc/collector/garbage_collector.h
+++ b/runtime/gc/collector/garbage_collector.h
@@ -153,7 +153,9 @@ class GarbageCollector : public RootVisitor, public IsMarkedVisitor, public Mark
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 8a12094168..48311570b5 100644
--- a/runtime/gc/collector/mark_compact.h
+++ b/runtime/gc/collector/mark_compact.h
@@ -106,7 +106,7 @@ class MarkCompact : public GarbageCollector {
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 5427f88563..64c8e9af04 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -1467,7 +1467,9 @@ void MarkSweep::FinishPhase() {
}
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 245f96bdb3..b61bef7317 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -85,7 +85,7 @@ class MarkSweep : public GarbageCollector {
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 a905904115..0199e1ae56 100644
--- a/runtime/gc/collector/semi_space.h
+++ b/runtime/gc/collector/semi_space.h
@@ -135,7 +135,9 @@ class SemiSpace : public GarbageCollector {
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 8cd8d73ba5..137540afd2 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -801,6 +801,7 @@ bool Heap::IsCompilingBoot() const {
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 @@ void Heap::TrimSpaces(Thread* self) {
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 @@ std::string Heap::DumpSpaces() const {
}
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 @@ void Heap::RecordFreeRevoke() {
}
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::GrowForUtilization(collector::GarbageCollector* collector_ran,
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::ClampGrowthLimit() {
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 1b7e2c9f0d..c02e2d3864 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -308,7 +308,10 @@ class Heap {
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 @@ class Heap {
// 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 @@ class Heap {
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 @@ class Heap {
// 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 @@ class Heap {
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 @@ class Heap {
}
// 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 @@ class Heap {
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 @@ class Heap {
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 e754a52e7e..455d28e229 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -319,7 +319,7 @@ void DlMallocSpace::LogFragmentationAllocFailure(std::ostream& os,
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/image_space.cc b/runtime/gc/space/image_space.cc
index 9ff3d8db75..891e280ab2 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -30,6 +30,7 @@
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "gc/accounting/space_bitmap-inl.h"
+#include "image-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "oat_file.h"
@@ -1032,11 +1033,12 @@ static bool RelocateInPlace(ImageHeader& image_header,
bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_object_visitor);
FixupObjectAdapter fixup_adapter(boot_image, boot_oat, app_image, app_oat);
// Fixup image roots.
- CHECK(app_image.ContainsSource(reinterpret_cast<uintptr_t>(image_header.GetImageRoots())));
+ CHECK(app_image.ContainsSource(reinterpret_cast<uintptr_t>(
+ image_header.GetImageRoots<kWithoutReadBarrier>())));
image_header.RelocateImageObjects(app_image.Delta());
CHECK_EQ(image_header.GetImageBegin(), target_base);
// Fix up dex cache DexFile pointers.
- auto* dex_caches = image_header.GetImageRoot(ImageHeader::kDexCaches)->
+ auto* dex_caches = image_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)->
AsObjectArray<mirror::DexCache>();
for (int32_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
mirror::DexCache* dex_cache = dex_caches->Get(i);
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index 49126d2c02..fd4d0a1a47 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -247,7 +247,10 @@ size_t RosAllocSpace::FreeList(Thread* self, size_t num_ptrs, mirror::Object** p
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 @@ void RosAllocSpace::Clear() {
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 aea2d9f895..170f927e9b 100644
--- a/runtime/gc/space/space_create_test.cc
+++ b/runtime/gc/space/space_create_test.cc
@@ -170,7 +170,11 @@ TEST_P(SpaceCreateTest, ZygoteSpaceTestBody) {
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 e588eb3efa..20ef44a77d 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 @@ class SpaceTest : public Super {
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/image-inl.h b/runtime/image-inl.h
new file mode 100644
index 0000000000..e3307d87b6
--- /dev/null
+++ b/runtime/image-inl.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_IMAGE_INL_H_
+#define ART_RUNTIME_IMAGE_INL_H_
+
+#include "image.h"
+
+namespace art {
+
+template <ReadBarrierOption kReadBarrierOption>
+inline mirror::Object* ImageHeader::GetImageRoot(ImageRoot image_root) const {
+ mirror::ObjectArray<mirror::Object>* image_roots = GetImageRoots<kReadBarrierOption>();
+ return image_roots->Get<kVerifyNone, kReadBarrierOption>(static_cast<int32_t>(image_root));
+}
+
+template <ReadBarrierOption kReadBarrierOption>
+inline mirror::ObjectArray<mirror::Object>* ImageHeader::GetImageRoots() const {
+ // Need a read barrier as it's not visited during root scan.
+ // Pass in the address of the local variable to the read barrier
+ // rather than image_roots_ because it won't move (asserted below)
+ // and it's a const member.
+ mirror::ObjectArray<mirror::Object>* image_roots =
+ reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(image_roots_);
+ mirror::ObjectArray<mirror::Object>* result =
+ ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::Object>, kReadBarrierOption>(
+ &image_roots);
+ DCHECK_EQ(image_roots, result);
+ return image_roots;
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_IMAGE_INL_H_
diff --git a/runtime/image.cc b/runtime/image.cc
index 2fed4d3bd3..de00343451 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -128,24 +128,6 @@ const char* ImageHeader::GetMagic() const {
return reinterpret_cast<const char*>(magic_);
}
-mirror::Object* ImageHeader::GetImageRoot(ImageRoot image_root) const {
- return GetImageRoots()->Get(image_root);
-}
-
-mirror::ObjectArray<mirror::Object>* ImageHeader::GetImageRoots() const {
- // Need a read barrier as it's not visited during root scan.
- // Pass in the address of the local variable to the read barrier
- // rather than image_roots_ because it won't move (asserted below)
- // and it's a const member.
- mirror::ObjectArray<mirror::Object>* image_roots =
- reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(image_roots_);
- mirror::ObjectArray<mirror::Object>* result =
- ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::Object>, kWithReadBarrier>(
- &image_roots);
- DCHECK_EQ(image_roots, result);
- return result;
-}
-
ArtMethod* ImageHeader::GetImageMethod(ImageMethod index) const {
CHECK_LT(static_cast<size_t>(index), kImageMethodsCount);
return reinterpret_cast<ArtMethod*>(image_methods_[index]);
diff --git a/runtime/image.h b/runtime/image.h
index b3f177bc8f..c449e43243 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -212,8 +212,11 @@ class PACKED(4) ImageHeader {
return GetImageSection(kSectionArtMethods);
}
+ template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
mirror::Object* GetImageRoot(ImageRoot image_root) const
SHARED_REQUIRES(Locks::mutator_lock_);
+
+ template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
mirror::ObjectArray<mirror::Object>* GetImageRoots() const
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc
index 96854dad0e..74a2532a5d 100644
--- a/runtime/intern_table.cc
+++ b/runtime/intern_table.cc
@@ -22,6 +22,7 @@
#include "gc/collector/garbage_collector.h"
#include "gc/space/image_space.h"
#include "gc/weak_root_state.h"
+#include "image-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index 7b058d0c92..692c6cb0c1 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -50,7 +50,7 @@ void DexCache::Init(const DexFile* dex_file,
CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
SetDexFile(dex_file);
- SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
+ SetLocation(location);
SetStrings(strings);
SetResolvedTypes(resolved_types);
SetResolvedMethods(resolved_methods);
@@ -79,5 +79,9 @@ void DexCache::Fixup(ArtMethod* trampoline, size_t pointer_size) {
}
}
+void DexCache::SetLocation(mirror::String* location) {
+ SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 5ed061f6a4..0002076ce0 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -191,11 +191,12 @@ class MANAGED DexCache FINAL : public Object {
return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_));
}
- void SetDexFile(const DexFile* dex_file) SHARED_REQUIRES(Locks::mutator_lock_)
- ALWAYS_INLINE {
- return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file);
+ void SetDexFile(const DexFile* dex_file) SHARED_REQUIRES(Locks::mutator_lock_) {
+ SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file);
}
+ void SetLocation(mirror::String* location) SHARED_REQUIRES(Locks::mutator_lock_);
+
// NOTE: Get/SetElementPtrSize() are intended for working with ArtMethod** and ArtField**
// provided by GetResolvedMethods/Fields() and ArtMethod::GetDexCacheResolvedMethods(),
// so they need to be public.
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index 8febb62a5f..8f108faa1f 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -314,32 +314,33 @@ static void VMDebug_getHeapSpaceStats(JNIEnv* env, jclass, jlongArray data) {
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_manager.cc b/runtime/oat_file_manager.cc
index b34b5505eb..de90f0aa04 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::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
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 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
/*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 341be9aab0..aa64ee3702 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -565,13 +565,6 @@ bool ParsedOptions::DoParse(const RuntimeOptions& options,
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 @@ void ParsedOptions::Usage(const char* fmt, ...) {
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 ca456c2861..1bb816bb20 100644
--- a/runtime/quick/inline_method_analyser.h
+++ b/runtime/quick/inline_method_analyser.h
@@ -37,13 +37,21 @@ class MethodVerifier;
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.cc b/runtime/runtime.cc
index f138c811d7..0c06ca672c 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -71,7 +71,7 @@
#include "gc/space/image_space.h"
#include "gc/space/space-inl.h"
#include "handle_scope-inl.h"
-#include "image.h"
+#include "image-inl.h"
#include "instrumentation.h"
#include "intern_table.h"
#include "interpreter/interpreter.h"
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index c5b009d2cd..308f3bafc2 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -113,7 +113,7 @@ RUNTIME_OPTIONS_KEY (unsigned int, ZygoteMaxFailedBoots, 10)
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 7e0f3371bc..2890a9826e 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -608,7 +608,6 @@ SafeMap<uint32_t, std::set<uint32_t>>& MethodVerifier::FindStringInitMap() {
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 @@ bool MethodVerifier::Verify() {
}
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 @@ bool MethodVerifier::Verify() {
// 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 @@ ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(
// 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 ba3318a1fd..0000000000
--- 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 3e6d1f4d94..06cfd0a606 100644
--- a/test/449-checker-bce/src/Main.java
+++ b/test/449-checker-bce/src/Main.java
@@ -622,28 +622,39 @@ public class Main {
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 f1d9a37c88..deff279f77 100644
--- a/test/530-checker-loops/src/Main.java
+++ b/test/530-checker-loops/src/Main.java
@@ -26,7 +26,7 @@ public class Main {
//
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after)
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after)
- /// CHECK: BoundsCheck
/// CHECK-NOT: Deoptimize
private static int linearByTwoSkip2(int x[]) {
int result = 0;
@@ -270,7 +272,7 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
- /// CHECK: BoundsCheck
/// CHECK-NOT: Deoptimize
private static int linearWithVeryLargePositiveStride() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
@@ -323,7 +327,7 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
- /// CHECK: BoundsCheck
/// CHECK-NOT: Deoptimize
private static int linearWithVeryLargeNegativeStride() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
@@ -359,7 +365,7 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// CHECK-START: int Main.linearShort() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.linearShort() BCE (after)
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.linearShort() BCE (after)
- /// CHECK: BoundsCheck
/// CHECK-NOT: Deoptimize
private static int linearShort() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
@@ -437,7 +445,7 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// CHECK-START: int Main.justOOBUp() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justOOBUp() BCE (after)
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justOOBUp() BCE (after)
- /// CHECK: BoundsCheck
/// CHECK-NOT: Deoptimize
private static int justOOBUp() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
@@ -774,7 +727,7 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// CHECK-START: int Main.justOOBDown() BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justOOBDown() BCE (after)
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int Main.justOOBDown() BCE (after)
- /// CHECK: BoundsCheck
/// CHECK-NOT: Deoptimize
private static int justOOBDown() {
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
@@ -835,66 +790,74 @@ public class Main {
}
/// CHECK-START: void Main.lowerOOB(int[]) BCE (before)
- /// CHECK: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
- /// CHECK: BoundsCheck
/// 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-DAG: BoundsCheck
//
/// CHECK-START: void Main.upperOOB(int[]) BCE (after)
- /// CHECK: BoundsCheck
/// 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-DAG: BoundsCheck
//
/// CHECK-START: void Main.doWhileUpOOB() BCE (after)
- /// CHECK: BoundsCheck
/// 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-DAG: BoundsCheck
//
/// CHECK-START: void Main.doWhileDownOOB() BCE (after)
- /// CHECK: BoundsCheck
/// 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 @@ public class Main {
}
/// CHECK-START: int[] Main.multiply2() BCE (before)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int[] Main.multiply2() BCE (after)
+ /// CHECK-DAG: BoundsCheck
//
/// CHECK-START: int[] Main.multiply2() BCE (after)
- /// CHECK: BoundsCheck
- /// CHECK: ArrayGet
- /// CHECK: ArraySet
+ /// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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 @@ public class Main {
}
/// 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-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-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 @@ public class Main {
}
/// 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-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-NOT: Deoptimize
static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) {
int result = 0;
@@ -1107,42 +1054,21 @@ public class Main {
}
/// 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 @@ public class Main {
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.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 (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.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 @@ public class Main {
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 22f68006e7..0000000000
--- 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 22f68006e7..0000000000
--- 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 d37737f3da..0000000000
--- 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 d37737f3da..0000000000
--- 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 22f68006e7..0000000000
--- 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 8944ea92d3..0000000000
--- 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 8944ea92d3..0000000000
--- 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 8944ea92d3..0000000000
--- 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 6d2930d463..0000000000
--- 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 8944ea92d3..0000000000
--- 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 6d2930d463..0000000000
--- 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 6d2930d463..0000000000
--- 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/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 351e99e8d4..6d67f8477d 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -260,6 +260,7 @@
"dalvik.system.JniTest#testPassingShorts",
"dalvik.system.JniTest#testPassingThis",
"libcore.util.NativeAllocationRegistryTest#testBadSize",
+ "libcore.util.NativeAllocationRegistryTest#testEarlyFree",
"libcore.util.NativeAllocationRegistryTest#testNativeAllocationAllocatorAndNoSharedRegistry",
"libcore.util.NativeAllocationRegistryTest#testNativeAllocationAllocatorAndSharedRegistry",
"libcore.util.NativeAllocationRegistryTest#testNativeAllocationNoAllocatorAndNoSharedRegistry",