Merge "Revert "ART: Refactor typedef to using""
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index e77d621..2ca15f7 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -622,7 +622,7 @@
// otherwise return a fall-back info that should be used instead.
virtual HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke) = 0;
+ ArtMethod* method) = 0;
// Generate a call to a static or direct method.
virtual void GenerateStaticOrDirectCall(
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index d56f7aa..25eadcd 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -4053,7 +4053,7 @@
HInvokeStaticOrDirect::DispatchInfo CodeGeneratorARM64::GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke ATTRIBUTE_UNUSED) {
+ ArtMethod* method ATTRIBUTE_UNUSED) {
// On ARM64 we support all dispatch types.
return desired_dispatch_info;
}
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 2e7a20b..1ba58b1 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -557,7 +557,7 @@
// otherwise return a fall-back info that should be used instead.
HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke) override;
+ ArtMethod* method) override;
void GenerateStaticOrDirectCall(
HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 3580975..d5149b3 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -8650,7 +8650,7 @@
// otherwise return a fall-back info that should be used instead.
HInvokeStaticOrDirect::DispatchInfo CodeGeneratorARMVIXL::GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke ATTRIBUTE_UNUSED) {
+ ArtMethod* method ATTRIBUTE_UNUSED) {
return desired_dispatch_info;
}
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 33502d4..5edca87 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -547,7 +547,7 @@
// otherwise return a fall-back info that should be used instead.
HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke) override;
+ ArtMethod* method) override;
void GenerateStaticOrDirectCall(
HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index d74a7a7..1cf5515 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -7964,7 +7964,7 @@
HInvokeStaticOrDirect::DispatchInfo CodeGeneratorMIPS::GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke ATTRIBUTE_UNUSED) {
+ ArtMethod* method ATTRIBUTE_UNUSED) {
return desired_dispatch_info;
}
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index bf95893..5080731 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -563,7 +563,7 @@
// otherwise return a fall-back info that should be used instead.
HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke) override;
+ ArtMethod* method) override;
void GenerateStaticOrDirectCall(
HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 7c89808..27534b0 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -6059,7 +6059,7 @@
HInvokeStaticOrDirect::DispatchInfo CodeGeneratorMIPS64::GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke ATTRIBUTE_UNUSED) {
+ ArtMethod* method ATTRIBUTE_UNUSED) {
// On MIPS64 we support all dispatch types.
return desired_dispatch_info;
}
diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h
index ddc154d..52f3a62 100644
--- a/compiler/optimizing/code_generator_mips64.h
+++ b/compiler/optimizing/code_generator_mips64.h
@@ -541,7 +541,7 @@
// otherwise return a fall-back info that should be used instead.
HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke) override;
+ ArtMethod* method) override;
void GenerateStaticOrDirectCall(
HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 6a27081..6c77232 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -4785,7 +4785,7 @@
HInvokeStaticOrDirect::DispatchInfo CodeGeneratorX86::GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke ATTRIBUTE_UNUSED) {
+ ArtMethod* method ATTRIBUTE_UNUSED) {
return desired_dispatch_info;
}
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 6154771..93b0461 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -410,7 +410,7 @@
// otherwise return a fall-back info that should be used instead.
HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke) override;
+ ArtMethod* method) override;
// Generate a call to a static or direct method.
void GenerateStaticOrDirectCall(
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 489652b..39d9789 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -978,7 +978,7 @@
HInvokeStaticOrDirect::DispatchInfo CodeGeneratorX86_64::GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke ATTRIBUTE_UNUSED) {
+ ArtMethod* method ATTRIBUTE_UNUSED) {
return desired_dispatch_info;
}
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index f77a5c8..1e71397 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -409,7 +409,7 @@
// otherwise return a fall-back info that should be used instead.
HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
- HInvokeStaticOrDirect* invoke) override;
+ ArtMethod* method) override;
void GenerateStaticOrDirectCall(
HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 3ba7414..1be96fb 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -2022,13 +2022,11 @@
// optimization that could lead to a HDeoptimize. The following optimizations do not.
HDeadCodeElimination dce(callee_graph, inline_stats_, "dead_code_elimination$inliner");
HConstantFolding fold(callee_graph, "constant_folding$inliner");
- HSharpening sharpening(callee_graph, codegen_);
InstructionSimplifier simplify(callee_graph, codegen_, inline_stats_);
IntrinsicsRecognizer intrinsics(callee_graph, inline_stats_);
HOptimization* optimizations[] = {
&intrinsics,
- &sharpening,
&simplify,
&fold,
&dce,
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 034761d..72b6748 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -978,11 +978,8 @@
}
}
- HInvokeStaticOrDirect::DispatchInfo dispatch_info = {
- HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall,
- HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod,
- 0u
- };
+ HInvokeStaticOrDirect::DispatchInfo dispatch_info =
+ HSharpening::SharpenInvokeStaticOrDirect(resolved_method, code_generator_);
MethodReference target_method(resolved_method->GetDexFile(),
resolved_method->GetDexMethodIndex());
invoke = new (allocator_) HInvokeStaticOrDirect(allocator_,
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index bb96c21..7ee5ad0 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -2290,7 +2290,7 @@
// the invoke, as we would need to look it up in the current dex file, and it
// is unlikely that it exists. The most usual situation for such typed
// arraycopy methods is a direct pointer to the boot image.
- HSharpening::SharpenInvokeStaticOrDirect(invoke, codegen_);
+ invoke->SetDispatchInfo(HSharpening::SharpenInvokeStaticOrDirect(method, codegen_));
}
}
}
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index 142ddb5..75466a3 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -84,8 +84,6 @@
return HDeadCodeElimination::kDeadCodeEliminationPassName;
case OptimizationPass::kInliner:
return HInliner::kInlinerPassName;
- case OptimizationPass::kSharpening:
- return HSharpening::kSharpeningPassName;
case OptimizationPass::kSelectGenerator:
return HSelectGenerator::kSelectGeneratorPassName;
case OptimizationPass::kInstructionSimplifier:
@@ -148,7 +146,6 @@
X(OptimizationPass::kLoopOptimization);
X(OptimizationPass::kScheduling);
X(OptimizationPass::kSelectGenerator);
- X(OptimizationPass::kSharpening);
X(OptimizationPass::kSideEffectsAnalysis);
#ifdef ART_ENABLE_CODEGEN_arm
X(OptimizationPass::kInstructionSimplifierArm);
@@ -264,9 +261,6 @@
pass_name);
break;
}
- case OptimizationPass::kSharpening:
- opt = new (allocator) HSharpening(graph, codegen, pass_name);
- break;
case OptimizationPass::kSelectGenerator:
opt = new (allocator) HSelectGenerator(graph, handles, stats, pass_name);
break;
diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h
index 88b283c..c258d51 100644
--- a/compiler/optimizing/optimization.h
+++ b/compiler/optimizing/optimization.h
@@ -84,7 +84,6 @@
kLoopOptimization,
kScheduling,
kSelectGenerator,
- kSharpening,
kSideEffectsAnalysis,
#ifdef ART_ENABLE_CODEGEN_arm
kInstructionSimplifierArm,
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index ff1207a..5f6f71d 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -624,7 +624,6 @@
OptimizationDef optimizations[] = {
// Initial optimizations.
OptDef(OptimizationPass::kIntrinsicsRecognizer),
- OptDef(OptimizationPass::kSharpening),
OptDef(OptimizationPass::kConstantFolding),
OptDef(OptimizationPass::kInstructionSimplifier),
OptDef(OptimizationPass::kDeadCodeElimination,
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 5c2f57e..c864951 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -35,22 +35,6 @@
namespace art {
-bool HSharpening::Run() {
- // We don't care about the order of the blocks here.
- for (HBasicBlock* block : graph_->GetReversePostOrder()) {
- for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
- HInstruction* instruction = it.Current();
- if (instruction->IsInvokeStaticOrDirect()) {
- SharpenInvokeStaticOrDirect(instruction->AsInvokeStaticOrDirect(), codegen_);
- }
- // TODO: Move the sharpening of invoke-virtual/-interface/-super from HGraphBuilder
- // here. Rewrite it to avoid the CompilerDriver's reliance on verifier data
- // because we know the type better when inlining.
- }
- }
- return true;
-}
-
static bool IsInBootImage(ArtMethod* method) {
const std::vector<gc::space::ImageSpace*>& image_spaces =
Runtime::Current()->GetHeap()->GetBootImageSpaces();
@@ -72,17 +56,14 @@
return compiler_options.IsImageClass(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
}
-void HSharpening::SharpenInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke,
- CodeGenerator* codegen) {
- if (invoke->IsStringInit()) {
- // Not using the dex cache arrays. But we could still try to use a better dispatch...
- // TODO: Use direct_method and direct_code for the appropriate StringFactory method.
- return;
+HInvokeStaticOrDirect::DispatchInfo HSharpening::SharpenInvokeStaticOrDirect(
+ ArtMethod* callee, CodeGenerator* codegen) {
+ if (kIsDebugBuild) {
+ ScopedObjectAccess soa(Thread::Current()); // Required for GetDeclaringClass below.
+ DCHECK(callee != nullptr);
+ DCHECK(!(callee->IsConstructor() && callee->GetDeclaringClass()->IsStringClass()));
}
- ArtMethod* callee = invoke->GetResolvedMethod();
- DCHECK(callee != nullptr);
-
HInvokeStaticOrDirect::MethodLoadKind method_load_kind;
HInvokeStaticOrDirect::CodePtrLocation code_ptr_location;
uint64_t method_load_data = 0u;
@@ -141,9 +122,7 @@
HInvokeStaticOrDirect::DispatchInfo desired_dispatch_info = {
method_load_kind, code_ptr_location, method_load_data
};
- HInvokeStaticOrDirect::DispatchInfo dispatch_info =
- codegen->GetSupportedInvokeStaticOrDirectDispatch(desired_dispatch_info, invoke);
- invoke->SetDispatchInfo(dispatch_info);
+ return codegen->GetSupportedInvokeStaticOrDirectDispatch(desired_dispatch_info, callee);
}
HLoadClass::LoadKind HSharpening::ComputeLoadClassKind(
diff --git a/compiler/optimizing/sharpening.h b/compiler/optimizing/sharpening.h
index dc55eea..b818672 100644
--- a/compiler/optimizing/sharpening.h
+++ b/compiler/optimizing/sharpening.h
@@ -25,24 +25,13 @@
class CodeGenerator;
class DexCompilationUnit;
-// Optimization that tries to improve the way we dispatch methods and access types,
-// fields, etc. Besides actual method sharpening based on receiver type (for example
-// virtual->direct), this includes selecting the best available dispatch for
-// invoke-static/-direct based on code generator support.
-class HSharpening : public HOptimization {
+// Utility methods that try to improve the way we dispatch methods, and access
+// types and strings.
+class HSharpening {
public:
- HSharpening(HGraph* graph,
- CodeGenerator* codegen,
- const char* name = kSharpeningPassName)
- : HOptimization(graph, name),
- codegen_(codegen) { }
-
- bool Run() override;
-
- static constexpr const char* kSharpeningPassName = "sharpening";
-
- // Used by Sharpening and InstructionSimplifier.
- static void SharpenInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke, CodeGenerator* codegen);
+ // Used by the builder and InstructionSimplifier.
+ static HInvokeStaticOrDirect::DispatchInfo SharpenInvokeStaticOrDirect(
+ ArtMethod* callee, CodeGenerator* codegen);
// Used by the builder and the inliner.
static HLoadClass::LoadKind ComputeLoadClassKind(HLoadClass* load_class,
@@ -61,9 +50,6 @@
CodeGenerator* codegen,
const DexCompilationUnit& dex_compilation_unit,
VariableSizedHandleScope* handles);
-
- private:
- CodeGenerator* codegen_;
};
} // namespace art
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 1b603b5..19f1532 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -29,6 +29,8 @@
"base/hex_dump.cc",
"base/logging.cc",
"base/malloc_arena_pool.cc",
+ "base/membarrier.cc",
+ "base/memfd.cc",
"base/memory_region.cc",
"base/mem_map.cc",
// "base/mem_map_fuchsia.cc", put in target when fuchsia supported by soong
@@ -186,6 +188,8 @@
"base/indenter_test.cc",
"base/leb128_test.cc",
"base/logging_test.cc",
+ "base/memfd_test.cc",
+ "base/membarrier_test.cc",
"base/memory_region_test.cc",
"base/mem_map_test.cc",
"base/safe_copy_test.cc",
diff --git a/libartbase/base/membarrier.cc b/libartbase/base/membarrier.cc
new file mode 100644
index 0000000..490dbf3
--- /dev/null
+++ b/libartbase/base/membarrier.cc
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "membarrier.h"
+
+#include <errno.h>
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include "macros.h"
+
+#if defined(__BIONIC__)
+
+#include <atomic>
+#include <android/get_device_api_level.h>
+#include <linux/membarrier.h>
+
+#define CHECK_MEMBARRIER_CMD(art_value, membarrier_value) \
+ static_assert(static_cast<int>(art_value) == membarrier_value, "Bad value for " # art_value)
+CHECK_MEMBARRIER_CMD(art::MembarrierCommand::kQuery, MEMBARRIER_CMD_QUERY);
+CHECK_MEMBARRIER_CMD(art::MembarrierCommand::kGlobal, MEMBARRIER_CMD_SHARED);
+CHECK_MEMBARRIER_CMD(art::MembarrierCommand::kPrivateExpedited, MEMBARRIER_CMD_PRIVATE_EXPEDITED);
+CHECK_MEMBARRIER_CMD(art::MembarrierCommand::kRegisterPrivateExpedited,
+ MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED);
+CHECK_MEMBARRIER_CMD(art::MembarrierCommand::kPrivateExpedited, MEMBARRIER_CMD_PRIVATE_EXPEDITED);
+#undef CHECK_MEMBARRIER_CMD
+
+#endif // __BIONIC
+
+namespace art {
+
+#if defined(__NR_membarrier)
+
+int membarrier(MembarrierCommand command) {
+#if defined(__BIONIC__)
+ // Avoid calling membarrier on older Android versions where membarrier may be barred by secomp
+ // causing the current process to be killed. The probing here could be considered expensive so
+ // endeavour not to repeat too often.
+ static int api_level = android_get_device_api_level();
+ if (api_level < __ANDROID_API_Q__) {
+ errno = ENOSYS;
+ return -1;
+ }
+#endif // __BIONIC__
+ return syscall(__NR_membarrier, static_cast<int>(command), 0);
+}
+
+#else // __NR_membarrier
+
+int membarrier(MembarrierCommand command ATTRIBUTE_UNUSED) {
+ // In principle this could be supported on linux, but Android's prebuilt glibc does not include
+ // the system call number defintions (b/111199492).
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif // __NR_membarrier
+
+} // namespace art
diff --git a/libartbase/base/membarrier.h b/libartbase/base/membarrier.h
new file mode 100644
index 0000000..f829fc1
--- /dev/null
+++ b/libartbase/base/membarrier.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 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_LIBARTBASE_BASE_MEMBARRIER_H_
+#define ART_LIBARTBASE_BASE_MEMBARRIER_H_
+
+namespace art {
+ // Command types for the linux membarrier system call. Different Linux installation may include
+ // different subsets of these commands (at the same codepoints).
+ //
+ // Hardcoding these values is temporary until bionic and prebuilts glibc have an up to date
+ // linux/membarrier.h. The order and values follow the current linux definitions.
+ enum class MembarrierCommand : int {
+ // MEMBARRIER_CMD_QUERY
+ kQuery = 0,
+ // MEMBARRIER_CMD_GLOBAL
+ kGlobal = (1 << 0),
+ // MEMBARRIER_CMD_GLOBAL_EXPEDITED
+ kGlobalExpedited = (1 << 1),
+ // MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED
+ kRegisterGlobalExpedited = (1 << 2),
+ // MEMBARRIER_CMD_PRIVATE_EXPEDITED
+ kPrivateExpedited = (1 << 3),
+ // MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED
+ kRegisterPrivateExpedited = (1 << 4),
+ // MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE
+ kPrivateExpeditedSyncCore = (1 << 5),
+ // MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE
+ kRegisterPrivateExpeditedSyncCore = (1 << 6)
+ };
+
+ // Call membarrier(2) if available on platform and return result. This method can fail if the
+ // command is not supported by the kernel. The underlying system call is linux specific.
+ int membarrier(MembarrierCommand command);
+
+} // namespace art
+
+#endif // ART_LIBARTBASE_BASE_MEMBARRIER_H_
diff --git a/libartbase/base/membarrier_test.cc b/libartbase/base/membarrier_test.cc
new file mode 100644
index 0000000..3eedf14
--- /dev/null
+++ b/libartbase/base/membarrier_test.cc
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "membarrier.h"
+
+class ScopedErrnoCleaner {
+ public:
+ ScopedErrnoCleaner() { errno = 0; }
+ ~ScopedErrnoCleaner() { errno = 0; }
+};
+
+bool HasMembarrier(art::MembarrierCommand cmd) {
+ ScopedErrnoCleaner errno_cleaner;
+ int supported_cmds = art::membarrier(art::MembarrierCommand::kQuery);
+ return (supported_cmds > 0) && ((supported_cmds & static_cast<int>(cmd)) != 0);
+}
+
+TEST(membarrier, query) {
+ ScopedErrnoCleaner errno_cleaner;
+ int supported = art::membarrier(art::MembarrierCommand::kQuery);
+ if (errno == 0) {
+ ASSERT_LE(0, supported);
+ } else {
+ ASSERT_TRUE(errno == ENOSYS && supported == -1);
+ }
+}
+
+TEST(membarrier, global_barrier) {
+ if (!HasMembarrier(art::MembarrierCommand::kGlobal)) {
+ GTEST_LOG_(INFO) << "MembarrierCommand::kGlobal not supported, skipping test.";
+ return;
+ }
+ ASSERT_EQ(0, art::membarrier(art::MembarrierCommand::kGlobal));
+}
+
+static const char* MembarrierCommandToName(art::MembarrierCommand cmd) {
+#define CASE_VALUE(x) case (x): return #x;
+ switch (cmd) {
+ CASE_VALUE(art::MembarrierCommand::kQuery);
+ CASE_VALUE(art::MembarrierCommand::kGlobal);
+ CASE_VALUE(art::MembarrierCommand::kGlobalExpedited);
+ CASE_VALUE(art::MembarrierCommand::kRegisterGlobalExpedited);
+ CASE_VALUE(art::MembarrierCommand::kPrivateExpedited);
+ CASE_VALUE(art::MembarrierCommand::kRegisterPrivateExpedited);
+ CASE_VALUE(art::MembarrierCommand::kPrivateExpeditedSyncCore);
+ CASE_VALUE(art::MembarrierCommand::kRegisterPrivateExpeditedSyncCore);
+ }
+}
+
+static void TestRegisterAndBarrierCommands(art::MembarrierCommand membarrier_cmd_register,
+ art::MembarrierCommand membarrier_cmd_barrier) {
+ if (!HasMembarrier(membarrier_cmd_register)) {
+ GTEST_LOG_(INFO) << MembarrierCommandToName(membarrier_cmd_register)
+ << " not supported, skipping test.";
+ return;
+ }
+ if (!HasMembarrier(membarrier_cmd_barrier)) {
+ GTEST_LOG_(INFO) << MembarrierCommandToName(membarrier_cmd_barrier)
+ << " not supported, skipping test.";
+ return;
+ }
+
+ ScopedErrnoCleaner errno_cleaner;
+
+ // Check barrier use without prior registration.
+ if (membarrier_cmd_register == art::MembarrierCommand::kRegisterGlobalExpedited) {
+ // Global barrier use is always okay.
+ ASSERT_EQ(0, art::membarrier(membarrier_cmd_barrier));
+ } else {
+ // Private barrier should fail.
+ ASSERT_EQ(-1, art::membarrier(membarrier_cmd_barrier));
+ ASSERT_EQ(EPERM, errno);
+ errno = 0;
+ }
+
+ // Check registration for barrier succeeds.
+ ASSERT_EQ(0, art::membarrier(membarrier_cmd_register));
+
+ // Check barrier use after registration succeeds.
+ ASSERT_EQ(0, art::membarrier(membarrier_cmd_barrier));
+}
+
+TEST(membarrier, global_expedited) {
+ TestRegisterAndBarrierCommands(art::MembarrierCommand::kRegisterGlobalExpedited,
+ art::MembarrierCommand::kGlobalExpedited);
+}
+
+TEST(membarrier, private_expedited) {
+ TestRegisterAndBarrierCommands(art::MembarrierCommand::kRegisterPrivateExpedited,
+ art::MembarrierCommand::kPrivateExpedited);
+}
+
+TEST(membarrier, private_expedited_sync_core) {
+ TestRegisterAndBarrierCommands(art::MembarrierCommand::kRegisterPrivateExpeditedSyncCore,
+ art::MembarrierCommand::kPrivateExpeditedSyncCore);
+}
diff --git a/libartbase/base/memfd.cc b/libartbase/base/memfd.cc
new file mode 100644
index 0000000..1afcd7b
--- /dev/null
+++ b/libartbase/base/memfd.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "memfd.h"
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "macros.h"
+
+// When building for linux host, glibc in prebuilts does not include memfd_create system call
+// number. As a temporary testing measure, we add the definition here.
+#if defined(__linux__) && !defined(__NR_memfd_create)
+#if defined(__x86_64__)
+#define __NR_memfd_create 319
+#elif defined(__i386__)
+#define __NR_memfd_create 356
+#endif // defined(__i386__)
+#endif // defined(__linux__) && !defined(__NR_memfd_create)
+
+namespace art {
+
+#if defined(__NR_memfd_create)
+
+int memfd_create(const char* name, unsigned int flags) {
+ return syscall(__NR_memfd_create, name, flags);
+}
+
+#else // __NR_memfd_create
+
+int memfd_create(const char* name ATTRIBUTE_UNUSED, unsigned int flags ATTRIBUTE_UNUSED) {
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif // __NR_memfd_create
+
+} // namespace art
diff --git a/libartbase/base/memfd.h b/libartbase/base/memfd.h
new file mode 100644
index 0000000..4367198
--- /dev/null
+++ b/libartbase/base/memfd.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 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_LIBARTBASE_BASE_MEMFD_H_
+#define ART_LIBARTBASE_BASE_MEMFD_H_
+
+namespace art {
+
+ // Call memfd(2) if available on platform and return result.
+int memfd_create(const char* name, unsigned int flags);
+
+} // namespace art
+
+#endif // ART_LIBARTBASE_BASE_MEMFD_H_
diff --git a/libartbase/base/memfd_test.cc b/libartbase/base/memfd_test.cc
new file mode 100644
index 0000000..1edf3a1
--- /dev/null
+++ b/libartbase/base/memfd_test.cc
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "memfd.h"
+
+TEST(memfd, basic) {
+ errno = 0;
+ int fd = art::memfd_create("memfd_create_test", 0);
+ if (fd < 0) {
+ ASSERT_EQ(ENOSYS, errno);
+ GTEST_LOG_(INFO) << "memfd_create not supported, skipping test.";
+ return;
+ }
+ ASSERT_TRUE(close(fd) == 0 || errno != EBADF);
+}
diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc
index 74cc5b9..2242fe8 100644
--- a/libartbase/base/utils.cc
+++ b/libartbase/base/utils.cc
@@ -213,42 +213,4 @@
}
}
-bool FlushInstructionPipeline() {
- // membarrier(2) is only supported for target builds (b/111199492).
-#if defined(__BIONIC__)
- static constexpr int kSyncCoreMask =
- MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE |
- MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE;
- static bool have_probed = false;
- static bool have_sync_core = false;
-
- if (UNLIKELY(!have_probed)) {
- // Probe membarrier(2) commands supported by kernel.
- int commands = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
- if (commands >= 0) {
- have_sync_core = (commands & kSyncCoreMask) == kSyncCoreMask;
- if (have_sync_core) {
- // Register with kernel that we'll be using the private expedited sync core command.
- CheckedCall(syscall,
- "membarrier register sync core",
- __NR_membarrier,
- MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
- 0);
- }
- }
- have_probed = true;
- }
-
- if (have_sync_core) {
- CheckedCall(syscall,
- "membarrier sync core",
- __NR_membarrier,
- MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE,
- 0);
- return true;
- }
-#endif // defined(__BIONIC__)
- return false;
-}
-
} // namespace art
diff --git a/libartbase/base/utils.h b/libartbase/base/utils.h
index d85960d..e6a0459 100644
--- a/libartbase/base/utils.h
+++ b/libartbase/base/utils.h
@@ -162,9 +162,6 @@
__builtin___clear_cache(reinterpret_cast<char*>(begin), reinterpret_cast<char*>(end));
}
-// Flush instruction pipeline. Returns true on success, false if feature is unsupported.
-bool FlushInstructionPipeline();
-
template <typename T>
constexpr PointerSize ConvertToPointerSize(T any) {
if (any == 4 || any == 8) {
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 8f064a3..ee4a0f4 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1029,9 +1029,7 @@
if (obj->IsClass<kVerifyNone>()) {
mirror::Class* as_klass = obj->AsClass<kVerifyNone>();
FixupObjectAdapter visitor(boot_image_, boot_oat_, app_image_, app_oat_);
- as_klass->FixupNativePointers<kVerifyNone, kWithoutReadBarrier>(as_klass,
- pointer_size_,
- visitor);
+ as_klass->FixupNativePointers<kVerifyNone>(as_klass, pointer_size_, visitor);
// Deal with the pointer arrays. Use the helper function since multiple classes can reference
// the same arrays.
mirror::PointerArray* const vtable = as_klass->GetVTable<kVerifyNone, kWithoutReadBarrier>();
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index bcbdc3b..191795b 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -23,6 +23,7 @@
#include "base/enums.h"
#include "base/histogram-inl.h"
#include "base/logging.h" // For VLOG.
+#include "base/membarrier.h"
#include "base/mem_map.h"
#include "base/quasi_atomic.h"
#include "base/stl_util.h"
@@ -187,6 +188,11 @@
return nullptr;
}
+ // Register for membarrier expedited sync core if JIT will be generating code.
+ if (!used_only_for_profile_data) {
+ art::membarrier(art::MembarrierCommand::kRegisterPrivateExpeditedSyncCore);
+ }
+
// Decide how we should map the code and data sections.
// If we use the code cache just for profiling we do not need to map the code section as
// executable.
@@ -809,9 +815,8 @@
// shootdown (incidentally invalidating the CPU pipelines by sending an IPI to all cores to
// notify them of the TLB invalidation). Some architectures, notably ARM and ARM64, have
// hardware support that broadcasts TLB invalidations and so their kernels have no software
- // based TLB shootdown. FlushInstructionPipeline() is a wrapper around the Linux
- // membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED) syscall which does the appropriate flushing.
- FlushInstructionPipeline();
+ // based TLB shootdown.
+ art::membarrier(art::MembarrierCommand::kPrivateExpeditedSyncCore);
DCHECK(!Runtime::Current()->IsAotCompiler());
if (has_should_deoptimize_flag) {
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 8bdd561..a31a9144 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -189,8 +189,9 @@
T GetElementPtrSize(uint32_t idx, PointerSize ptr_size)
REQUIRES_SHARED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kVerifyNone>
void** ElementAddress(size_t index, PointerSize ptr_size) REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK_LT(index, static_cast<size_t>(GetLength()));
+ DCHECK_LT(index, static_cast<size_t>(GetLength<kVerifyFlags>()));
return reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(this) +
Array::DataOffset(static_cast<size_t>(ptr_size)).Uint32Value() +
static_cast<size_t>(ptr_size) * index);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 33822d1..df70fab 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -251,18 +251,14 @@
uint32_t num_direct,
uint32_t num_virtual) {
DCHECK_LE(num_direct + num_virtual, (new_methods == nullptr) ? 0 : new_methods->size());
- SetMethodsPtrInternal(new_methods);
+ SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, methods_),
+ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(new_methods)));
SetFieldShort<false>(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_),
dchecked_integral_cast<uint16_t>(num_direct + num_virtual));
SetFieldShort<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_),
dchecked_integral_cast<uint16_t>(num_direct));
}
-inline void Class::SetMethodsPtrInternal(LengthPrefixedArray<ArtMethod>* new_methods) {
- SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, methods_),
- static_cast<uint64_t>(reinterpret_cast<uintptr_t>(new_methods)));
-}
-
template<VerifyObjectFlags kVerifyFlags>
inline ArtMethod* Class::GetVirtualMethod(size_t i, PointerSize pointer_size) {
CheckPointerSize(pointer_size);
@@ -1069,49 +1065,42 @@
return arr != nullptr ? arr->size() : 0u;
}
-template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
+template <typename T, VerifyObjectFlags kVerifyFlags, typename Visitor>
+inline void Class::FixupNativePointer(
+ Class* dest, PointerSize pointer_size, const Visitor& visitor, MemberOffset member_offset) {
+ void** address =
+ reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(dest) + member_offset.Uint32Value());
+ T old_value = GetFieldPtrWithSize<T, kVerifyFlags>(member_offset, pointer_size);
+ T new_value = visitor(old_value, address);
+ if (old_value != new_value) {
+ dest->SetFieldPtrWithSize</* kTransactionActive */ false,
+ /* kCheckTransaction */ true,
+ kVerifyNone>(member_offset, new_value, pointer_size);
+ }
+}
+
+template <VerifyObjectFlags kVerifyFlags, typename Visitor>
inline void Class::FixupNativePointers(Class* dest,
PointerSize pointer_size,
const Visitor& visitor) {
- auto dest_address_fn = [dest](MemberOffset offset) {
- return reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(dest) + offset.Uint32Value());
- };
// Update the field arrays.
- LengthPrefixedArray<ArtField>* const sfields = GetSFieldsPtr();
- void** sfields_dest_address = dest_address_fn(OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
- LengthPrefixedArray<ArtField>* const new_sfields = visitor(sfields, sfields_dest_address);
- if (sfields != new_sfields) {
- dest->SetSFieldsPtrUnchecked(new_sfields);
- }
- LengthPrefixedArray<ArtField>* const ifields = GetIFieldsPtr();
- void** ifields_dest_address = dest_address_fn(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
- LengthPrefixedArray<ArtField>* const new_ifields = visitor(ifields, ifields_dest_address);
- if (ifields != new_ifields) {
- dest->SetIFieldsPtrUnchecked(new_ifields);
- }
+ FixupNativePointer<LengthPrefixedArray<ArtField>*, kVerifyFlags>(
+ dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
+ FixupNativePointer<LengthPrefixedArray<ArtField>*, kVerifyFlags>(
+ dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
// Update method array.
- LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
- void** methods_dest_address = dest_address_fn(OFFSET_OF_OBJECT_MEMBER(Class, methods_));
- LengthPrefixedArray<ArtMethod>* new_methods = visitor(methods, methods_dest_address);
- if (methods != new_methods) {
- dest->SetMethodsPtrInternal(new_methods);
- }
+ FixupNativePointer<LengthPrefixedArray<ArtMethod>*, kVerifyFlags>(
+ dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, methods_));
// Fix up embedded tables.
if (!IsTemp<kVerifyNone>() && ShouldHaveEmbeddedVTable<kVerifyNone>()) {
- for (int32_t i = 0, count = GetEmbeddedVTableLength(); i < count; ++i) {
- ArtMethod* method = GetEmbeddedVTableEntry(i, pointer_size);
- void** method_dest_addr = dest_address_fn(EmbeddedVTableEntryOffset(i, pointer_size));
- ArtMethod* new_method = visitor(method, method_dest_addr);
- if (method != new_method) {
- dest->SetEmbeddedVTableEntryUnchecked(i, new_method, pointer_size);
- }
+ for (int32_t i = 0, count = GetEmbeddedVTableLength<kVerifyFlags>(); i < count; ++i) {
+ FixupNativePointer<ArtMethod*, kVerifyFlags>(
+ dest, pointer_size, visitor, EmbeddedVTableEntryOffset(i, pointer_size));
}
}
if (!IsTemp<kVerifyNone>() && ShouldHaveImt<kVerifyNone>()) {
- ImTable* imt = GetImt(pointer_size);
- void** imt_dest_addr = dest_address_fn(ImtPtrOffset(pointer_size));
- ImTable* new_imt = visitor(imt, imt_dest_addr);
- dest->SetImt(new_imt, pointer_size);
+ FixupNativePointer<ImTable*, kVerifyFlags>(
+ dest, pointer_size, visitor, ImtPtrOffset(pointer_size));
}
}
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 3d434f1..f640d3b 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1263,14 +1263,14 @@
// the corresponding entry in dest if visitor(obj) != obj to prevent dirty memory. Dest should be
// initialized to a copy of *this to prevent issues. Does not visit the ArtMethod and ArtField
// roots.
- template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
- ReadBarrierOption kReadBarrierOption = kWithReadBarrier,
- typename Visitor>
+ template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, typename Visitor>
void FixupNativePointers(Class* dest, PointerSize pointer_size, const Visitor& visitor)
REQUIRES_SHARED(Locks::mutator_lock_);
private:
- ALWAYS_INLINE void SetMethodsPtrInternal(LengthPrefixedArray<ArtMethod>* new_methods)
+ template <typename T, VerifyObjectFlags kVerifyFlags, typename Visitor>
+ void FixupNativePointer(
+ Class* dest, PointerSize pointer_size, const Visitor& visitor, MemberOffset member_offset)
REQUIRES_SHARED(Locks::mutator_lock_);
ALWAYS_INLINE static ArraySlice<ArtMethod> GetMethodsSliceRangeUnchecked(
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index ed0beaf..22ccd20 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -401,12 +401,14 @@
return GetField32<kVerifyFlags>(NumResolvedTypesOffset());
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
size_t NumResolvedMethods() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetField32(NumResolvedMethodsOffset());
+ return GetField32<kVerifyFlags>(NumResolvedMethodsOffset());
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
size_t NumResolvedFields() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetField32(NumResolvedFieldsOffset());
+ return GetField32<kVerifyFlags>(NumResolvedFieldsOffset());
}
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
diff --git a/runtime/mirror/iftable.h b/runtime/mirror/iftable.h
index 9e3c9af..3d4c5a7 100644
--- a/runtime/mirror/iftable.h
+++ b/runtime/mirror/iftable.h
@@ -39,9 +39,15 @@
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ PointerArray* GetMethodArrayOrNull(int32_t i) REQUIRES_SHARED(Locks::mutator_lock_) {
+ return down_cast<PointerArray*>(
+ Get<kVerifyFlags, kReadBarrierOption>((i * kMax) + kMethodArray));
+ }
+
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
PointerArray* GetMethodArray(int32_t i) REQUIRES_SHARED(Locks::mutator_lock_) {
- auto* method_array = down_cast<PointerArray*>(Get<kVerifyFlags, kReadBarrierOption>(
- (i * kMax) + kMethodArray));
+ PointerArray* method_array = GetMethodArrayOrNull<kVerifyFlags, kReadBarrierOption>(i);
DCHECK(method_array != nullptr);
return method_array;
}
@@ -49,9 +55,8 @@
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
size_t GetMethodArrayCount(int32_t i) REQUIRES_SHARED(Locks::mutator_lock_) {
- auto* method_array = down_cast<PointerArray*>(
- Get<kVerifyFlags, kReadBarrierOption>((i * kMax) + kMethodArray));
- return method_array == nullptr ? 0u : method_array->GetLength();
+ PointerArray* method_array = GetMethodArrayOrNull<kVerifyFlags, kReadBarrierOption>(i);
+ return method_array == nullptr ? 0u : method_array->GetLength<kVerifyFlags>();
}
void SetMethodArray(int32_t i, ObjPtr<PointerArray> arr) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 1d2f47f..7d101bf 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -67,7 +67,7 @@
template<class T> template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline T* ObjectArray<T>::Get(int32_t i) {
- if (!CheckIsValidIndex(i)) {
+ if (!CheckIsValidIndex<kVerifyFlags>(i)) {
DCHECK(Thread::Current()->IsExceptionPending());
return nullptr;
}
diff --git a/test/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java
index e16fa69..b1bc51e 100644
--- a/test/478-checker-clinit-check-pruning/src/Main.java
+++ b/test/478-checker-clinit-check-pruning/src/Main.java
@@ -26,7 +26,7 @@
/// CHECK-START: void Main.invokeStaticInlined() builder (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [{{([ij]\d+,)?}}<<ClinitCheck>>]
/// CHECK-START: void Main.invokeStaticInlined() inliner (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
@@ -69,7 +69,7 @@
/// CHECK-START: void Main.invokeStaticNotInlined() builder (after)
/// CHECK: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
+ /// CHECK: InvokeStaticOrDirect [{{([ij]\d+,)?}}<<ClinitCheck>>]
/// CHECK-START: void Main.invokeStaticNotInlined() inliner (after)
/// CHECK: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
diff --git a/test/552-checker-sharpening/src/Main.java b/test/552-checker-sharpening/src/Main.java
index 746887f..0bceffd 100644
--- a/test/552-checker-sharpening/src/Main.java
+++ b/test/552-checker-sharpening/src/Main.java
@@ -41,10 +41,7 @@
return x;
}
- /// CHECK-START: int Main.testSimple(int) sharpening (before)
- /// CHECK: InvokeStaticOrDirect method_load_kind:RuntimeCall
-
- /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: int Main.testSimple(int) sharpening (after)
+ /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: int Main.testSimple(int) builder (after)
/// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry
/// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (before)
@@ -59,11 +56,7 @@
return $noinline$foo(x);
}
- /// CHECK-START: int Main.testDiamond(boolean, int) sharpening (before)
- /// CHECK: InvokeStaticOrDirect method_load_kind:RuntimeCall
- /// CHECK: InvokeStaticOrDirect method_load_kind:RuntimeCall
-
- /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: int Main.testDiamond(boolean, int) sharpening (after)
+ /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: int Main.testDiamond(boolean, int) builder (after)
/// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry
/// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry
@@ -194,18 +187,12 @@
}
/// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.String Main.$noinline$toHexString(int) builder (after)
- /// CHECK: InvokeStaticOrDirect method_load_kind:RuntimeCall
-
- /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.String Main.$noinline$toHexString(int) sharpening (after)
/// CHECK: InvokeStaticOrDirect method_load_kind:BootImageRelRo
public static String $noinline$toHexString(int value) {
return Integer.toString(value, 16);
}
/// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.String Main.$noinline$toHexStringIndirect(int) builder (after)
- /// CHECK: InvokeStaticOrDirect method_load_kind:RuntimeCall
-
- /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.String Main.$noinline$toHexStringIndirect(int) sharpening (after)
/// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry
/// CHECK-START-X86: java.lang.String Main.$noinline$toHexStringIndirect(int) pc_relative_fixups_x86 (before)
diff --git a/test/565-checker-rotate/smali/Main2.smali b/test/565-checker-rotate/smali/Main2.smali
index ca5027e..98eaf11 100644
--- a/test/565-checker-rotate/smali/Main2.smali
+++ b/test/565-checker-rotate/smali/Main2.smali
@@ -16,13 +16,12 @@
.super Ljava/lang/Object;
## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) intrinsics_recognition (after)
-## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
## CHECK: <<ArgVal:z\d+>> ParameterValue
## CHECK: <<ArgDist:i\d+>> ParameterValue
## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
## CHECK-DAG: <<One:i\d+>> IntConstant 1
## CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
-## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Val>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Val>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
## CHECK-DAG: Return [<<Result>>]
## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) instruction_simplifier (after)
@@ -92,14 +91,13 @@
.end method
## CHECK-START: int Main2.rotateRightBoolean(boolean, int) intrinsics_recognition (after)
-## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
## CHECK: <<ArgVal:z\d+>> ParameterValue
## CHECK: <<ArgDist:i\d+>> ParameterValue
## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
## CHECK-DAG: <<One:i\d+>> IntConstant 1
## CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
-## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Val>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
-## CHECK-DAG: Return [<<Result>>]
+## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Val>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
+## CHECK-DAG: Return [<<Result>>]
## CHECK-START: int Main2.rotateRightBoolean(boolean, int) instruction_simplifier (after)
## CHECK: <<ArgVal:z\d+>> ParameterValue
diff --git a/test/565-checker-rotate/src-art/Main.java b/test/565-checker-rotate/src-art/Main.java
index b9e1315..f6f281b 100644
--- a/test/565-checker-rotate/src-art/Main.java
+++ b/test/565-checker-rotate/src-art/Main.java
@@ -21,10 +21,9 @@
private static Class main2;
/// CHECK-START: int Main.rotateLeftByte(byte, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:b\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateLeftByte(byte, int) instruction_simplifier (after)
@@ -42,10 +41,9 @@
}
/// CHECK-START: int Main.rotateLeftShort(short, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:s\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateLeftShort(short, int) instruction_simplifier (after)
@@ -63,10 +61,9 @@
}
/// CHECK-START: int Main.rotateLeftChar(char, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:c\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateLeftChar(char, int) instruction_simplifier (after)
@@ -84,10 +81,9 @@
}
/// CHECK-START: int Main.rotateLeftInt(int, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:i\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateLeftInt(int, int) instruction_simplifier (after)
@@ -105,10 +101,9 @@
}
/// CHECK-START: long Main.rotateLeftLong(long, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:j\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:LongRotateLeft
+ /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:LongRotateLeft
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: long Main.rotateLeftLong(long, int) instruction_simplifier (after)
@@ -126,10 +121,9 @@
}
/// CHECK-START: int Main.rotateRightByte(byte, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:b\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateRightByte(byte, int) instruction_simplifier (after)
@@ -146,10 +140,9 @@
}
/// CHECK-START: int Main.rotateRightShort(short, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:s\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateRightShort(short, int) instruction_simplifier (after)
@@ -166,10 +159,9 @@
}
/// CHECK-START: int Main.rotateRightChar(char, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:c\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateRightChar(char, int) instruction_simplifier (after)
@@ -186,10 +178,9 @@
}
/// CHECK-START: int Main.rotateRightInt(int, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:i\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateRightInt(int, int) instruction_simplifier (after)
@@ -206,10 +197,9 @@
}
/// CHECK-START: long Main.rotateRightLong(long, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:j\d+>> ParameterValue
/// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:LongRotateRight
+ /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:LongRotateRight
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: long Main.rotateRightLong(long, int) instruction_simplifier (after)
@@ -227,10 +217,9 @@
/// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:i\d+>> ParameterValue
/// CHECK: <<ArgDist:b\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) instruction_simplifier (after)
@@ -248,10 +237,9 @@
}
/// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK: <<ArgVal:i\d+>> ParameterValue
/// CHECK: <<ArgDist:b\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) instruction_simplifier (after)
diff --git a/test/566-checker-signum/smali/Main2.smali b/test/566-checker-signum/smali/Main2.smali
index d99ad86..ec63cf8 100644
--- a/test/566-checker-signum/smali/Main2.smali
+++ b/test/566-checker-signum/smali/Main2.smali
@@ -16,11 +16,10 @@
.super Ljava/lang/Object;
## CHECK-START: int Main2.signBoolean(boolean) intrinsics_recognition (after)
-## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
## CHECK-DAG: <<One:i\d+>> IntConstant 1
## CHECK-DAG: <<Phi:i\d+>> Phi [<<One>>,<<Zero>>]
-## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Phi>>,<<Method>>] intrinsic:IntegerSignum
+## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Phi>>{{(,[ij]\d+)?}}] intrinsic:IntegerSignum
## CHECK-DAG: Return [<<Result>>]
## CHECK-START: int Main2.signBoolean(boolean) instruction_simplifier (after)
diff --git a/test/567-checker-compare/smali/Smali.smali b/test/567-checker-compare/smali/Smali.smali
index 8fc39f1..94b1f13 100644
--- a/test/567-checker-compare/smali/Smali.smali
+++ b/test/567-checker-compare/smali/Smali.smali
@@ -16,12 +16,11 @@
.super Ljava/lang/Object;
## CHECK-START: int Smali.compareBooleans(boolean, boolean) intrinsics_recognition (after)
-## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
## CHECK-DAG: <<One:i\d+>> IntConstant 1
## CHECK-DAG: <<PhiX:i\d+>> Phi [<<One>>,<<Zero>>]
## CHECK-DAG: <<PhiY:i\d+>> Phi [<<One>>,<<Zero>>]
-## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<PhiX>>,<<PhiY>>,<<Method>>] intrinsic:IntegerCompare
+## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<PhiX>>,<<PhiY>>{{(,[ij]\d+)?}}] intrinsic:IntegerCompare
## CHECK-DAG: Return [<<Result>>]
## CHECK-START: int Smali.compareBooleans(boolean, boolean) instruction_simplifier (after)
diff --git a/test/567-checker-compare/src/Main.java b/test/567-checker-compare/src/Main.java
index abfaf9f..f43ac30 100644
--- a/test/567-checker-compare/src/Main.java
+++ b/test/567-checker-compare/src/Main.java
@@ -22,9 +22,8 @@
/// CHECK-START: void Main.$opt$noinline$testReplaceInputWithItself(int) intrinsics_recognition (after)
/// CHECK-DAG: <<ArgX:i\d+>> ParameterValue
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Cmp:i\d+>> InvokeStaticOrDirect [<<ArgX>>,<<Zero>>,<<Method>>] intrinsic:IntegerCompare
+ /// CHECK-DAG: <<Cmp:i\d+>> InvokeStaticOrDirect [<<ArgX>>,<<Zero>>{{(,[ij]\d+)?}}] intrinsic:IntegerCompare
/// CHECK-DAG: GreaterThanOrEqual [<<Cmp>>,<<Zero>>]
/// CHECK-START: void Main.$opt$noinline$testReplaceInputWithItself(int) instruction_simplifier (after)
diff --git a/test/593-checker-boolean-2-integral-conv/smali/SmaliTests.smali b/test/593-checker-boolean-2-integral-conv/smali/SmaliTests.smali
index f74e88f..bd90fe7 100644
--- a/test/593-checker-boolean-2-integral-conv/smali/SmaliTests.smali
+++ b/test/593-checker-boolean-2-integral-conv/smali/SmaliTests.smali
@@ -210,14 +210,12 @@
.end method
## CHECK-START: int SmaliTests.longToIntOfBoolean() builder (after)
-## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
## CHECK-DAG: <<Sget:z\d+>> StaticFieldGet
-## CHECK-DAG: <<ZToJ:j\d+>> InvokeStaticOrDirect [<<Sget>>,<<Method>>]
+## CHECK-DAG: <<ZToJ:j\d+>> InvokeStaticOrDirect [<<Sget>>{{(,[ij]\d+)?}}]
## CHECK-DAG: <<JToI:i\d+>> TypeConversion [<<ZToJ>>]
## CHECK-DAG: Return [<<JToI>>]
## CHECK-START: int SmaliTests.longToIntOfBoolean() inliner (after)
-## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
## CHECK-DAG: <<One:i\d+>> IntConstant 1
## CHECK-DAG: <<Sget:z\d+>> StaticFieldGet
@@ -228,7 +226,6 @@
## CHECK-DAG: Return [<<JToI>>]
## CHECK-START: int SmaliTests.longToIntOfBoolean() select_generator (after)
-## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
## CHECK-DAG: <<One:i\d+>> IntConstant 1
## CHECK-DAG: <<Sget:z\d+>> StaticFieldGet
@@ -236,7 +233,6 @@
## CHECK-DAG: Return [<<Sel>>]
## CHECK-START: int SmaliTests.longToIntOfBoolean() instruction_simplifier$after_bce (after)
-## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
## CHECK-DAG: <<Sget:z\d+>> StaticFieldGet
## CHECK-DAG: Return [<<Sget>>]
.method public static longToIntOfBoolean()I
diff --git a/test/593-checker-boolean-2-integral-conv/src/Main.java b/test/593-checker-boolean-2-integral-conv/src/Main.java
index fdc0919..b085c42 100644
--- a/test/593-checker-boolean-2-integral-conv/src/Main.java
+++ b/test/593-checker-boolean-2-integral-conv/src/Main.java
@@ -100,14 +100,12 @@
}
/// CHECK-START: int Main.longToIntOfBoolean() builder (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK-DAG: <<Sget:z\d+>> StaticFieldGet
- /// CHECK-DAG: <<ZToJ:j\d+>> InvokeStaticOrDirect [<<Sget>>,<<Method>>]
+ /// CHECK-DAG: <<ZToJ:j\d+>> InvokeStaticOrDirect [<<Sget>>{{(,[ij]\d+)?}}]
/// CHECK-DAG: <<JToI:i\d+>> TypeConversion [<<ZToJ>>]
/// CHECK-DAG: Return [<<JToI>>]
/// CHECK-START: int Main.longToIntOfBoolean() inliner (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK-DAG: <<Zero:j\d+>> LongConstant 0
/// CHECK-DAG: <<One:j\d+>> LongConstant 1
/// CHECK-DAG: <<Sget:z\d+>> StaticFieldGet
@@ -123,7 +121,6 @@
/// CHECK-NOT: Phi
/// CHECK-START: int Main.longToIntOfBoolean() select_generator (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
/// CHECK-DAG: <<Zero:j\d+>> LongConstant 0
/// CHECK-DAG: <<One:j\d+>> LongConstant 1
/// CHECK-DAG: <<Sget:z\d+>> StaticFieldGet
@@ -135,7 +132,6 @@
// TODO: Re-enable checks below after simplifier is updated to handle this pattern: b/63064517
// CHECK-START: int Main.longToIntOfBoolean() instruction_simplifier$after_bce (after)
- // CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
// CHECK-DAG: <<Sget:z\d+>> StaticFieldGet
// CHECK-DAG: Return [<<Sget>>]
diff --git a/test/624-checker-stringops/src/Main.java b/test/624-checker-stringops/src/Main.java
index 4d98df8..3aa6e56 100644
--- a/test/624-checker-stringops/src/Main.java
+++ b/test/624-checker-stringops/src/Main.java
@@ -38,7 +38,7 @@
/// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOf loop:none
/// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:none
static int liveIndexOf() {
- int k = ABC.lastIndexOf('Z') + XYZ.lastIndexOf('Z'); // does LoadString before loops
+ int k = ABC.length() + XYZ.length(); // does LoadString before loops
for (char c = 'A'; c <= 'Z'; c++) {
k += ABC.indexOf(c);
}
@@ -290,7 +290,7 @@
}
public static void main(String[] args) throws Exception {
- expectEquals(1863, liveIndexOf());
+ expectEquals(1865, liveIndexOf());
expectEquals(29, deadIndexOf());
try {
diff --git a/test/testrunner/target_config.py b/test/testrunner/target_config.py
index 6f0d941..ad72945 100644
--- a/test/testrunner/target_config.py
+++ b/test/testrunner/target_config.py
@@ -70,40 +70,16 @@
'--gcstress',
'--gcverify']
},
- # TODO: Remove this configuration (which is a duplicate of
- # 'art-interpreter-gcstress-gcverify') when it is no longer used by any
- # continuous testing target (b/62611253).
- 'art-interpreter-gcstress' : {
- 'run-test' : ['--interpreter',
- '--gcstress',
- '--gcverify']
- },
'art-optimizing-gcstress-gcverify' : {
'run-test' : ['--optimizing',
'--gcstress',
'--gcverify']
},
- # TODO: Remove this configuration (which is a duplicate of
- # 'art-optimizing-gcstress-gcverify') when it is no longer used by any
- # continuous testing target (b/62611253).
- 'art-optimizing-gcstress' : {
- 'run-test' : ['--optimizing',
- '--gcstress',
- '--gcverify']
- },
'art-jit-gcstress-gcverify' : {
'run-test' : ['--jit',
'--gcstress',
'--gcverify']
},
- # TODO: Remove this configuration (which is a duplicate of
- # 'art-jit-gcstress-gcverify') when it is no longer used by any
- # continuous testing target (b/62611253).
- 'art-jit-gcstress' : {
- 'run-test' : ['--jit',
- '--gcstress',
- '--gcverify']
- },
'art-jit-on-first-use-gcstress' : {
'run-test' : ['--jit',
'--gcstress',
@@ -116,29 +92,6 @@
'ART_HEAP_POISONING' : 'true'
}
},
- # TODO: Remove this configuration (which is a duplicate of
- # 'art-read-barrier-heap-poisoning') when it is no longer used by any
- # continuous testing target (b/62611253).
- 'art-read-barrier' : {
- 'run-test': ['--interpreter',
- '--optimizing'],
- 'env' : {
- 'ART_HEAP_POISONING' : 'true'
- }
- },
- # TODO: Remove this configuration when it is no longer used by any
- # continuous testing target (b/62611253). This configuration is scheduled
- # for removal as it is now covered by 'art-interpreter-gcstress-gcverify'
- # and 'art-optimizing-gcstress-gcverify' -- except for heap poisoning, but
- # that's fine.
- 'art-read-barrier-gcstress' : {
- 'run-test' : ['--interpreter',
- '--optimizing',
- '--gcstress'],
- 'env' : {
- 'ART_HEAP_POISONING' : 'true'
- }
- },
'art-read-barrier-table-lookup' : {
'run-test' : ['--interpreter',
'--optimizing'],
diff --git a/tools/ahat/etc/ahat_api.txt b/tools/ahat/etc/ahat_api.txt
index 7aa994a..c82b314 100644
--- a/tools/ahat/etc/ahat_api.txt
+++ b/tools/ahat/etc/ahat_api.txt
@@ -73,6 +73,7 @@
method public com.android.ahat.heapdump.AhatInstance getAssociatedBitmapInstance();
method public com.android.ahat.heapdump.AhatClassObj getAssociatedClassForOverhead();
method public com.android.ahat.heapdump.AhatInstance getBaseline();
+ method public java.lang.String getBinderProxyInterfaceName();
method public java.lang.String getClassName();
method public com.android.ahat.heapdump.AhatClassObj getClassObj();
method public java.lang.String getDexCacheLocation(int);
diff --git a/tools/ahat/src/main/com/android/ahat/Summarizer.java b/tools/ahat/src/main/com/android/ahat/Summarizer.java
index ab88c04..877ecf4 100644
--- a/tools/ahat/src/main/com/android/ahat/Summarizer.java
+++ b/tools/ahat/src/main/com/android/ahat/Summarizer.java
@@ -112,6 +112,13 @@
formatted.append(" overhead for ");
formatted.append(summarize(cls));
}
+
+ // Annotate BinderProxy with its interface name.
+ String binderInterface = inst.getBinderProxyInterfaceName();
+ if (binderInterface != null) {
+ formatted.appendFormat(" for %s", binderInterface);
+ }
+
return formatted;
}
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java
index 0511798..141bdd9 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java
@@ -145,6 +145,21 @@
return null;
}
+ @Override public String getBinderProxyInterfaceName() {
+ if (isInstanceOfClass("android.os.BinderProxy")) {
+ for (AhatInstance inst : getReverseReferences()) {
+ String className = inst.getClassName();
+ if (className.endsWith("$Stub$Proxy")) {
+ Value value = inst.getField("mRemote");
+ if (value != null && value.asAhatInstance() == this) {
+ return className.substring(0, className.lastIndexOf("$Stub$Proxy"));
+ }
+ }
+ }
+ }
+ return null;
+ }
+
@Override public AhatInstance getAssociatedBitmapInstance() {
return getBitmapInfo() == null ? null : this;
}
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java
index c85a057..3aae11e 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java
@@ -490,6 +490,17 @@
}
/**
+ * Returns the name of the Binder proxy interface associated with this object. Only applies to
+ * instances of android.os.BinderProxy. If this is an instance of BinderProxy,
+ * returns the fully qualified binder interface name, otherwise returns null.
+ *
+ * @return the name of the binder interface associated with this object
+ */
+ public String getBinderProxyInterfaceName() {
+ return null;
+ }
+
+ /**
* Returns the android.graphics.Bitmap instance associated with this object.
* Instances of android.graphics.Bitmap return themselves. If this is a
* byte[] array containing pixel data for an instance of
diff --git a/tools/ahat/src/test-dump/DumpedStuff.java b/tools/ahat/src/test-dump/DumpedStuff.java
index 804a3a3..50b8878 100644
--- a/tools/ahat/src/test-dump/DumpedStuff.java
+++ b/tools/ahat/src/test-dump/DumpedStuff.java
@@ -124,6 +124,35 @@
}
}
+ private static class IDumpedManager {
+ public static class Stub {
+ public static class Proxy {
+ android.os.IBinder mRemote;
+ Proxy(android.os.IBinder binderProxy) {
+ mRemote = binderProxy;
+ }
+ }
+ }
+ }
+
+ private static class IBinderInterfaceImpostor {
+ public static class Stub {
+ public static class Proxy {
+ android.os.IBinder mFakeRemote = new android.os.BinderProxy();
+ Proxy(android.os.IBinder binderProxy) {
+ mFakeRemote = binderProxy;
+ }
+ }
+ }
+ }
+
+ private static class BinderProxyCarrier {
+ android.os.IBinder mRemote;
+ BinderProxyCarrier(android.os.IBinder binderProxy) {
+ mRemote = binderProxy;
+ }
+ }
+
public String basicString = "hello, world";
public String nonAscii = "Sigma (Ʃ) is not ASCII";
public String embeddedZero = "embedded\0..."; // Non-ASCII for string compression purposes.
@@ -158,6 +187,12 @@
public int[] modifiedArray;
public Object objectAllocatedAtKnownSite;
public Object objectAllocatedAtKnownSubSite;
+ public android.os.IBinder correctBinderProxy = new android.os.BinderProxy();
+ public android.os.IBinder imposedBinderProxy = new android.os.BinderProxy();
+ public android.os.IBinder carriedBinderProxy = new android.os.BinderProxy();
+ Object correctBinderProxyObject = new IDumpedManager.Stub.Proxy(correctBinderProxy);
+ Object impostorBinderProxyObject = new IBinderInterfaceImpostor.Stub.Proxy(imposedBinderProxy);
+ Object carrierBinderProxyObject = new BinderProxyCarrier(carriedBinderProxy);
// Allocate those objects that we need to not be GC'd before taking the heap
// dump.
diff --git a/tools/ahat/src/test-dump/android/os/BinderProxy.java b/tools/ahat/src/test-dump/android/os/BinderProxy.java
new file mode 100644
index 0000000..5f35c61
--- /dev/null
+++ b/tools/ahat/src/test-dump/android/os/BinderProxy.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/** Fake android.os.BinderProxy class that does absolutely nothing. */
+public class BinderProxy implements IBinder {}
diff --git a/tools/ahat/src/test-dump/android/os/IBinder.java b/tools/ahat/src/test-dump/android/os/IBinder.java
new file mode 100644
index 0000000..6f01468
--- /dev/null
+++ b/tools/ahat/src/test-dump/android/os/IBinder.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/** Fake android.os.IBinder that means nothing. */
+public interface IBinder {}
diff --git a/tools/ahat/src/test/com/android/ahat/InstanceTest.java b/tools/ahat/src/test/com/android/ahat/InstanceTest.java
index 196eb1e..57aa31f 100644
--- a/tools/ahat/src/test/com/android/ahat/InstanceTest.java
+++ b/tools/ahat/src/test/com/android/ahat/InstanceTest.java
@@ -549,4 +549,18 @@
// Other kinds of objects should not have associated classes for overhead.
assertNull(cls.getAssociatedClassForOverhead());
}
+
+ @Test
+ public void binderProxy() throws IOException {
+ TestDump dump = TestDump.getTestDump();
+
+ AhatInstance correctObj = dump.getDumpedAhatInstance("correctBinderProxy");
+ assertEquals("DumpedStuff$IDumpedManager", correctObj.getBinderProxyInterfaceName());
+
+ AhatInstance imposedObj = dump.getDumpedAhatInstance("imposedBinderProxy");
+ assertNull(imposedObj.getBinderProxyInterfaceName());
+
+ AhatInstance carriedObj = dump.getDumpedAhatInstance("carriedBinderProxy");
+ assertNull(carriedObj.getBinderProxyInterfaceName());
+ }
}
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 3ef78d5..d83c522 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -216,16 +216,6 @@
names: ["libcore.javax.crypto.spec.AlgorithmParametersTestGCM#testEncoding"]
},
{
- description: "Tests fail because mockito can not read android.os.Build$VERSION",
- result: EXEC_FAILED,
- bug: 111704422,
- names: ["libcore.java.lang.ThreadTest#testUncaughtExceptionPreHandler_calledBeforeDefaultHandler",
- "libcore.java.lang.ThreadTest#testUncaughtExceptionPreHandler_noDefaultHandler",
- "libcore.javax.crypto.CipherInputStreamTest#testCloseTwice",
- "libcore.libcore.io.BlockGuardOsTest#test_android_getaddrinfo_networkPolicy",
- "libcore.libcore.io.BlockGuardOsTest#test_checkNewMethodsInPosix"]
-},
-{
description: "fdsan doesn't exist on the host",
result: EXEC_FAILED,
modes: [host],
diff --git a/tools/veridex/appcompat.sh b/tools/veridex/appcompat.sh
index a24e84f..f57c8a4 100755
--- a/tools/veridex/appcompat.sh
+++ b/tools/veridex/appcompat.sh
@@ -45,8 +45,8 @@
fi
# Logic for setting out_dir from build/make/core/envsetup.mk:
-if [[ -z $OUT_DIR ]]; then
- if [[ -z $OUT_DIR_COMMON_BASE ]]; then
+if [[ -z "${OUT_DIR}" ]]; then
+ if [[ -z "${OUT_DIR_COMMON_BASE}" ]]; then
OUT=out
else
OUT=${OUT_DIR_COMMON_BASE}/${PWD##*/}
@@ -59,7 +59,7 @@
PACKAGING=${OUT}/target/common/obj/PACKAGING
fi
-if [ -z "$ANDROID_HOST_OUT" ] ; then
+if [[ -z "${ANDROID_HOST_OUT}" ]]; then
ANDROID_HOST_OUT=${OUT}/host/linux-x86
fi