summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/art.go28
-rw-r--r--compiler/optimizing/code_generator.cc2
-rw-r--r--compiler/optimizing/instruction_builder.cc18
-rw-r--r--compiler/optimizing/instruction_builder.h8
-rw-r--r--compiler/optimizing/nodes.h8
-rw-r--r--dexdump/dexdump.cc11
-rw-r--r--dexlayout/dex_ir.cc4
-rw-r--r--libartbase/Android.bp5
-rw-r--r--libartbase/arch/instruction_set.cc (renamed from runtime/arch/instruction_set.cc)25
-rw-r--r--libartbase/arch/instruction_set.h (renamed from runtime/arch/instruction_set.h)8
-rw-r--r--libartbase/arch/instruction_set_test.cc (renamed from runtime/arch/instruction_set_test.cc)0
-rw-r--r--libartbase/base/file_utils.cc (renamed from runtime/base/file_utils.cc)5
-rw-r--r--libartbase/base/file_utils.h (renamed from runtime/base/file_utils.h)7
-rw-r--r--libartbase/base/file_utils_test.cc (renamed from runtime/base/file_utils_test.cc)0
-rw-r--r--libdexfile/dex/dex_file-inl.h2
-rw-r--r--libdexfile/dex/dex_file.cc10
-rw-r--r--libdexfile/dex/dex_file.h14
-rw-r--r--libdexfile/dex/dex_file_types.h86
-rw-r--r--libdexfile/dex/dex_file_verifier.cc7
-rw-r--r--libdexfile/dex/dex_file_verifier.h2
-rw-r--r--libdexfile/dex/dex_file_verifier_test.cc11
-rw-r--r--libdexfile/dex/dex_instruction.cc20
-rw-r--r--patchoat/Android.bp1
-rw-r--r--runtime/Android.bp9
-rw-r--r--runtime/arch/code_offset.h2
-rw-r--r--runtime/arch/instruction_set_features.h2
-rw-r--r--runtime/art_method.cc17
-rw-r--r--runtime/art_method.h4
-rw-r--r--runtime/class_linker.cc4
-rw-r--r--runtime/class_linker.h4
-rw-r--r--runtime/common_dex_operations.h1
-rw-r--r--runtime/dex/art_dex_file_loader_test.cc213
-rw-r--r--runtime/elf_file.cc23
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc2
-rw-r--r--runtime/entrypoints/entrypoint_utils.h2
-rw-r--r--runtime/entrypoints/quick/quick_dexcache_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc54
-rw-r--r--runtime/hidden_api.cc14
-rw-r--r--runtime/hidden_api.h16
-rw-r--r--runtime/interpreter/interpreter_common.cc99
-rw-r--r--runtime/interpreter/interpreter_common.h2
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc2
-rw-r--r--runtime/interpreter/mterp/mterp.cc3
-rw-r--r--runtime/jvalue-inl.h2
-rw-r--r--runtime/jvalue.h3
-rw-r--r--runtime/method_handles-inl.h2
-rw-r--r--runtime/method_handles.cc1
-rw-r--r--runtime/mirror/dex_cache-inl.h14
-rw-r--r--runtime/mirror/dex_cache.h6
-rw-r--r--runtime/mirror/dex_cache_test.cc4
-rw-r--r--runtime/mirror/var_handle.cc53
-rw-r--r--runtime/mirror/var_handle.h28
-rw-r--r--runtime/mirror/var_handle_test.cc264
-rw-r--r--runtime/native/java_lang_reflect_Field.cc1
-rw-r--r--runtime/oat_file_assistant.cc6
-rw-r--r--runtime/oat_file_assistant_test.cc43
-rw-r--r--runtime/reflection.cc1
-rw-r--r--runtime/runtime.cc2
-rw-r--r--runtime/var_handles.cc78
-rw-r--r--runtime/var_handles.h35
-rw-r--r--runtime/verifier/method_verifier.cc10
-rw-r--r--runtime/well_known_classes.cc21
-rw-r--r--test/999-redefine-hiddenapi/api-blacklist.txt2
-rw-r--r--test/999-redefine-hiddenapi/build17
-rw-r--r--test/999-redefine-hiddenapi/expected.txt1
-rw-r--r--test/999-redefine-hiddenapi/info.txt1
-rwxr-xr-xtest/999-redefine-hiddenapi/run17
-rw-r--r--test/999-redefine-hiddenapi/src-ex/Test999.java25
-rw-r--r--test/999-redefine-hiddenapi/src-redefine/art/Test999.java25
-rwxr-xr-xtest/999-redefine-hiddenapi/src-redefine/gen.sh30
-rw-r--r--test/999-redefine-hiddenapi/src/Main.java111
-rw-r--r--test/999-redefine-hiddenapi/src/art/Redefinition.java91
-rw-r--r--test/Android.bp36
-rwxr-xr-xtest/etc/default-build5
-rw-r--r--test/knownfailures.json11
-rw-r--r--test/ti-stress/stress.cc5
-rw-r--r--tools/dexanalyze/dexanalyze.cc13
77 files changed, 1178 insertions, 543 deletions
diff --git a/build/art.go b/build/art.go
index 59480a0d0f..3dabce3975 100644
--- a/build/art.go
+++ b/build/art.go
@@ -278,6 +278,7 @@ func init() {
android.RegisterModuleType("art_cc_test", artTest)
android.RegisterModuleType("art_cc_test_library", artTestLibrary)
android.RegisterModuleType("art_cc_defaults", artDefaultsFactory)
+ android.RegisterModuleType("libart_cc_defaults", libartDefaultsFactory)
android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory)
android.RegisterModuleType("art_debug_defaults", artDebugDefaultsFactory)
}
@@ -304,6 +305,33 @@ func artDefaultsFactory() android.Module {
return module
}
+func libartDefaultsFactory() android.Module {
+ c := &codegenProperties{}
+ module := cc.DefaultsFactory(c)
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ codegen(ctx, c, true)
+
+ type props struct {
+ Target struct {
+ Android struct {
+ Shared_libs []string
+ }
+ }
+ }
+
+ p := &props{}
+ // TODO: express this in .bp instead b/79671158
+ if !envTrue(ctx, "ART_TARGET_LINUX") {
+ p.Target.Android.Shared_libs = []string {
+ "libmetricslogger",
+ }
+ }
+ ctx.AppendProperties(p)
+ })
+
+ return module
+}
+
func artLibrary() android.Module {
m, _ := cc.NewLibrary(android.HostAndDeviceSupported)
module := m.Init()
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index f57333741c..fb556f435a 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -771,7 +771,7 @@ void CodeGenerator::CreateLoadMethodTypeRuntimeCallLocationSummary(
void CodeGenerator::GenerateLoadMethodTypeRuntimeCall(HLoadMethodType* method_type) {
LocationSummary* locations = method_type->GetLocations();
- MoveConstant(locations->GetTemp(0), method_type->GetProtoIndex());
+ MoveConstant(locations->GetTemp(0), method_type->GetProtoIndex().index_);
CheckEntrypointTypes<kQuickResolveMethodType, void*, uint32_t>();
InvokeRuntime(kQuickResolveMethodType, method_type, method_type->GetDexPc());
}
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 35a39456a2..0e20a65a2d 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1055,7 +1055,7 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
bool HInstructionBuilder::BuildInvokePolymorphic(const Instruction& instruction ATTRIBUTE_UNUSED,
uint32_t dex_pc,
uint32_t method_idx,
- uint32_t proto_idx,
+ dex::ProtoIndex proto_idx,
uint32_t number_of_vreg_arguments,
bool is_range,
uint32_t* args,
@@ -1896,17 +1896,17 @@ bool HInstructionBuilder::LoadClassNeedsAccessCheck(Handle<mirror::Class> klass)
}
}
-void HInstructionBuilder::BuildLoadMethodHandle(uint16_t proto_idx, uint32_t dex_pc) {
+void HInstructionBuilder::BuildLoadMethodHandle(uint16_t method_handle_index, uint32_t dex_pc) {
const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
- HLoadMethodHandle* load_method_handle =
- new (allocator_) HLoadMethodHandle(graph_->GetCurrentMethod(), proto_idx, dex_file, dex_pc);
+ HLoadMethodHandle* load_method_handle = new (allocator_) HLoadMethodHandle(
+ graph_->GetCurrentMethod(), method_handle_index, dex_file, dex_pc);
AppendInstruction(load_method_handle);
}
-void HInstructionBuilder::BuildLoadMethodType(uint16_t proto_idx, uint32_t dex_pc) {
+void HInstructionBuilder::BuildLoadMethodType(dex::ProtoIndex proto_index, uint32_t dex_pc) {
const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
HLoadMethodType* load_method_type =
- new (allocator_) HLoadMethodType(graph_->GetCurrentMethod(), proto_idx, dex_file, dex_pc);
+ new (allocator_) HLoadMethodType(graph_->GetCurrentMethod(), proto_index, dex_file, dex_pc);
AppendInstruction(load_method_type);
}
@@ -2189,7 +2189,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction,
case Instruction::INVOKE_POLYMORPHIC: {
uint16_t method_idx = instruction.VRegB_45cc();
- uint16_t proto_idx = instruction.VRegH_45cc();
+ dex::ProtoIndex proto_idx(instruction.VRegH_45cc());
uint32_t number_of_vreg_arguments = instruction.VRegA_45cc();
uint32_t args[5];
instruction.GetVarArgs(args);
@@ -2205,7 +2205,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction,
case Instruction::INVOKE_POLYMORPHIC_RANGE: {
uint16_t method_idx = instruction.VRegB_4rcc();
- uint16_t proto_idx = instruction.VRegH_4rcc();
+ dex::ProtoIndex proto_idx(instruction.VRegH_4rcc());
uint32_t number_of_vreg_arguments = instruction.VRegA_4rcc();
uint32_t register_index = instruction.VRegC_4rcc();
return BuildInvokePolymorphic(instruction,
@@ -2949,7 +2949,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction,
}
case Instruction::CONST_METHOD_TYPE: {
- uint16_t proto_idx = instruction.VRegB_21c();
+ dex::ProtoIndex proto_idx(instruction.VRegB_21c());
BuildLoadMethodType(proto_idx, dex_pc);
UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
break;
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index 95ffa6b054..9d886a8ef2 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -178,7 +178,7 @@ class HInstructionBuilder : public ValueObject {
bool BuildInvokePolymorphic(const Instruction& instruction,
uint32_t dex_pc,
uint32_t method_idx,
- uint32_t proto_idx,
+ dex::ProtoIndex proto_idx,
uint32_t number_of_vreg_arguments,
bool is_range,
uint32_t* args,
@@ -240,11 +240,11 @@ class HInstructionBuilder : public ValueObject {
bool LoadClassNeedsAccessCheck(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Builds a `HLoadMethodHandle` loading the given `method_handle_idx`.
+ // Builds a `HLoadMethodHandle` loading the given `method_handle_index`.
void BuildLoadMethodHandle(uint16_t method_handle_idx, uint32_t dex_pc);
- // Builds a `HLoadMethodType` loading the given `proto_idx`.
- void BuildLoadMethodType(uint16_t proto_idx, uint32_t dex_pc);
+ // Builds a `HLoadMethodType` loading the given `proto_index`.
+ void BuildLoadMethodType(dex::ProtoIndex proto_index, uint32_t dex_pc);
// Returns the outer-most compiling method's class.
ObjPtr<mirror::Class> GetOutermostCompilingClass() const;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index a7c2d0b125..e786502dee 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -6548,7 +6548,7 @@ class HLoadMethodHandle FINAL : public HInstruction {
class HLoadMethodType FINAL : public HInstruction {
public:
HLoadMethodType(HCurrentMethod* current_method,
- uint16_t proto_idx,
+ dex::ProtoIndex proto_index,
const DexFile& dex_file,
uint32_t dex_pc)
: HInstruction(kLoadMethodType,
@@ -6556,7 +6556,7 @@ class HLoadMethodType FINAL : public HInstruction {
SideEffectsForArchRuntimeCalls(),
dex_pc),
special_input_(HUserRecord<HInstruction*>(current_method)),
- proto_idx_(proto_idx),
+ proto_index_(proto_index),
dex_file_(dex_file) {
}
@@ -6568,7 +6568,7 @@ class HLoadMethodType FINAL : public HInstruction {
bool IsClonable() const OVERRIDE { return true; }
- uint16_t GetProtoIndex() const { return proto_idx_; }
+ dex::ProtoIndex GetProtoIndex() const { return proto_index_; }
const DexFile& GetDexFile() const { return dex_file_; }
@@ -6585,7 +6585,7 @@ class HLoadMethodType FINAL : public HInstruction {
// The special input is the HCurrentMethod for kRuntimeCall.
HUserRecord<HInstruction*> special_input_;
- const uint16_t proto_idx_;
+ const dex::ProtoIndex proto_index_;
const DexFile& dex_file_;
};
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 9536381ed0..e72d49e05f 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -786,11 +786,10 @@ static void dumpLocalsCb(void* /*context*/, const DexFile::LocalInfo& entry) {
static std::unique_ptr<char[]> indexString(const DexFile* pDexFile,
const Instruction* pDecInsn,
size_t bufSize) {
- static const u4 kInvalidIndex = std::numeric_limits<u4>::max();
std::unique_ptr<char[]> buf(new char[bufSize]);
// Determine index and width of the string.
u4 index = 0;
- u4 secondary_index = kInvalidIndex;
+ u2 secondary_index = 0;
u4 width = 4;
switch (Instruction::FormatOf(pDecInsn->Opcode())) {
// SOME NOT SUPPORTED:
@@ -898,7 +897,7 @@ static std::unique_ptr<char[]> indexString(const DexFile* pDexFile,
signature.ToString().c_str());
}
if (secondary_index < pDexFile->GetHeader().proto_ids_size_) {
- const DexFile::ProtoId& protoId = pDexFile->GetProtoId(secondary_index);
+ const DexFile::ProtoId& protoId = pDexFile->GetProtoId(dex::ProtoIndex(secondary_index));
const Signature signature = pDexFile->GetProtoSignature(protoId);
proto = signature.ToString();
}
@@ -916,7 +915,7 @@ static std::unique_ptr<char[]> indexString(const DexFile* pDexFile,
break;
case Instruction::kIndexProtoRef:
if (index < pDexFile->GetHeader().proto_ids_size_) {
- const DexFile::ProtoId& protoId = pDexFile->GetProtoId(index);
+ const DexFile::ProtoId& protoId = pDexFile->GetProtoId(dex::ProtoIndex(index));
const Signature signature = pDexFile->GetProtoSignature(protoId);
const std::string& proto = signature.ToString();
outSize = snprintf(buf.get(), bufSize, "%s // proto@%0*x", proto.c_str(), width, index);
@@ -1705,7 +1704,7 @@ static void dumpCallSite(const DexFile* pDexFile, u4 idx) {
dex::StringIndex method_name_idx = static_cast<dex::StringIndex>(it.GetJavaValue().i);
const char* method_name = pDexFile->StringDataByIdx(method_name_idx);
it.Next();
- uint32_t method_type_idx = static_cast<uint32_t>(it.GetJavaValue().i);
+ dex::ProtoIndex method_type_idx = static_cast<dex::ProtoIndex>(it.GetJavaValue().i);
const DexFile::ProtoId& method_type_id = pDexFile->GetProtoId(method_type_idx);
std::string method_type = pDexFile->GetProtoSignature(method_type_id).ToString();
it.Next();
@@ -1763,7 +1762,7 @@ static void dumpCallSite(const DexFile* pDexFile, u4 idx) {
break;
case EncodedArrayValueIterator::ValueType::kMethodType: {
type = "MethodType";
- uint32_t proto_idx = static_cast<uint32_t>(it.GetJavaValue().i);
+ dex::ProtoIndex proto_idx = static_cast<dex::ProtoIndex>(it.GetJavaValue().i);
const DexFile::ProtoId& proto_id = pDexFile->GetProtoId(proto_idx);
value = pDexFile->GetProtoSignature(proto_id).ToString();
break;
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index 1525d537b7..b7d9db6da5 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -332,7 +332,7 @@ void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
}
void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
- const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
+ const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(dex::ProtoIndex(i));
const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
@@ -353,7 +353,7 @@ void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) {
void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) {
const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_.index_),
- GetProtoId(disk_method_id.proto_idx_),
+ GetProtoId(disk_method_id.proto_idx_.index_),
GetStringId(disk_method_id.name_idx_.index_));
AddIndexedItem(method_ids_, method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i);
}
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 065f3eb07a..c8a06ed3b0 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -19,11 +19,13 @@ cc_defaults {
defaults: ["art_defaults"],
host_supported: true,
srcs: [
+ "arch/instruction_set.cc",
"base/allocator.cc",
"base/arena_allocator.cc",
"base/arena_bit_vector.cc",
"base/bit_vector.cc",
"base/file_magic.cc",
+ "base/file_utils.cc",
"base/hex_dump.cc",
"base/logging.cc",
"base/malloc_arena_pool.cc",
@@ -80,6 +82,7 @@ gensrcs {
cmd: "$(location generate_operator_out) art/libartbase $(in) > $(out)",
tools: ["generate_operator_out"],
srcs: [
+ "arch/instruction_set.h",
"base/allocator.h",
"base/callee_save_type.h",
"base/unix_file/fd_file.h",
@@ -141,12 +144,14 @@ art_cc_test {
"art_gtest_defaults",
],
srcs: [
+ "arch/instruction_set_test.cc",
"base/arena_allocator_test.cc",
"base/bit_field_test.cc",
"base/bit_string_test.cc",
"base/bit_struct_test.cc",
"base/bit_utils_test.cc",
"base/bit_vector_test.cc",
+ "base/file_utils_test.cc",
"base/hash_set_test.cc",
"base/hex_dump_test.cc",
"base/histogram_test.cc",
diff --git a/runtime/arch/instruction_set.cc b/libartbase/arch/instruction_set.cc
index b848eb27fc..a187663062 100644
--- a/runtime/arch/instruction_set.cc
+++ b/libartbase/arch/instruction_set.cc
@@ -16,8 +16,6 @@
#include "instruction_set.h"
-// Explicitly include our own elf.h to avoid Linux and other dependencies.
-#include "../elf.h"
#include "android-base/logging.h"
#include "base/bit_utils.h"
#include "base/globals.h"
@@ -83,29 +81,6 @@ InstructionSet GetInstructionSetFromString(const char* isa_str) {
return InstructionSet::kNone;
}
-InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags) {
- switch (e_machine) {
- case EM_ARM:
- return InstructionSet::kArm;
- case EM_AARCH64:
- return InstructionSet::kArm64;
- case EM_386:
- return InstructionSet::kX86;
- case EM_X86_64:
- return InstructionSet::kX86_64;
- case EM_MIPS: {
- if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 ||
- (e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) {
- return InstructionSet::kMips;
- } else if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) {
- return InstructionSet::kMips64;
- }
- break;
- }
- }
- return InstructionSet::kNone;
-}
-
size_t GetInstructionSetAlignment(InstructionSet isa) {
switch (isa) {
case InstructionSet::kArm:
diff --git a/runtime/arch/instruction_set.h b/libartbase/arch/instruction_set.h
index 6434005dda..06bd53a6a9 100644
--- a/runtime/arch/instruction_set.h
+++ b/libartbase/arch/instruction_set.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_ARCH_INSTRUCTION_SET_H_
-#define ART_RUNTIME_ARCH_INSTRUCTION_SET_H_
+#ifndef ART_LIBARTBASE_ARCH_INSTRUCTION_SET_H_
+#define ART_LIBARTBASE_ARCH_INSTRUCTION_SET_H_
#include <iosfwd>
#include <string>
@@ -89,8 +89,6 @@ const char* GetInstructionSetString(InstructionSet isa);
// Note: Returns kNone when the string cannot be parsed to a known value.
InstructionSet GetInstructionSetFromString(const char* instruction_set);
-InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags);
-
// Fatal logging out of line to keep the header clean of logging.h.
NO_RETURN void InstructionSetAbort(InstructionSet isa);
@@ -299,4 +297,4 @@ static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
} // namespace art
-#endif // ART_RUNTIME_ARCH_INSTRUCTION_SET_H_
+#endif // ART_LIBARTBASE_ARCH_INSTRUCTION_SET_H_
diff --git a/runtime/arch/instruction_set_test.cc b/libartbase/arch/instruction_set_test.cc
index 12a117d7a1..12a117d7a1 100644
--- a/runtime/arch/instruction_set_test.cc
+++ b/libartbase/arch/instruction_set_test.cc
diff --git a/runtime/base/file_utils.cc b/libartbase/base/file_utils.cc
index 537216c198..9450e1e8c1 100644
--- a/runtime/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -47,7 +47,6 @@
#include "base/os.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
-#include "dex/dex_file_loader.h"
#if defined(__APPLE__)
#include <crt_externs.h>
@@ -64,6 +63,8 @@ namespace art {
using android::base::StringAppendF;
using android::base::StringPrintf;
+static constexpr const char* kClassesDex = "classes.dex";
+
bool ReadFileToString(const std::string& file_name, std::string* result) {
File file(file_name, O_RDONLY, false);
if (!file.IsOpened()) {
@@ -224,7 +225,7 @@ bool GetDalvikCacheFilename(const char* location, const char* cache_location,
!android::base::EndsWith(location, ".art") &&
!android::base::EndsWith(location, ".oat")) {
cache_file += "/";
- cache_file += DexFileLoader::kClassesDex;
+ cache_file += kClassesDex;
}
std::replace(cache_file.begin(), cache_file.end(), '/', '@');
*filename = StringPrintf("%s/%s", cache_location, cache_file.c_str());
diff --git a/runtime/base/file_utils.h b/libartbase/base/file_utils.h
index d4f6c576c0..063393bd3b 100644
--- a/runtime/base/file_utils.h
+++ b/libartbase/base/file_utils.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_BASE_FILE_UTILS_H_
-#define ART_RUNTIME_BASE_FILE_UTILS_H_
+#ifndef ART_LIBARTBASE_BASE_FILE_UTILS_H_
+#define ART_LIBARTBASE_BASE_FILE_UTILS_H_
#include <stdlib.h>
@@ -46,6 +46,7 @@ std::string GetDefaultBootImageLocation(std::string* error_msg);
// Returns the dalvik-cache location, with subdir appended. Returns the empty string if the cache
// could not be found.
std::string GetDalvikCache(const char* subdir);
+
// Return true if we found the dalvik cache and stored it in the dalvik_cache argument.
// have_android_data will be set to true if we have an ANDROID_DATA that exists,
// dalvik_cache_exists will be true if there is a dalvik-cache directory that is present.
@@ -79,4 +80,4 @@ bool LocationIsOnSystemFramework(const char* location);
} // namespace art
-#endif // ART_RUNTIME_BASE_FILE_UTILS_H_
+#endif // ART_LIBARTBASE_BASE_FILE_UTILS_H_
diff --git a/runtime/base/file_utils_test.cc b/libartbase/base/file_utils_test.cc
index e74dfe5e64..e74dfe5e64 100644
--- a/runtime/base/file_utils_test.cc
+++ b/libartbase/base/file_utils_test.cc
diff --git a/libdexfile/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h
index d1b32007c3..e78e8d7a44 100644
--- a/libdexfile/dex/dex_file-inl.h
+++ b/libdexfile/dex/dex_file-inl.h
@@ -127,7 +127,7 @@ inline const char* DexFile::GetReturnTypeDescriptor(const ProtoId& proto_id) con
return StringByTypeIdx(proto_id.return_type_idx_);
}
-inline const char* DexFile::GetShorty(uint32_t proto_idx) const {
+inline const char* DexFile::GetShorty(dex::ProtoIndex proto_idx) const {
const ProtoId& proto_id = GetProtoId(proto_idx);
return StringDataByIdx(proto_id.shorty_idx_);
}
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 8cfee6655e..9de260c862 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -281,7 +281,7 @@ const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_
// Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
const dex::TypeIndex class_idx = GetIndexForTypeId(declaring_klass);
const dex::StringIndex name_idx = GetIndexForStringId(name);
- const uint16_t proto_idx = GetIndexForProtoId(signature);
+ const dex::ProtoIndex proto_idx = GetIndexForProtoId(signature);
int32_t lo = 0;
int32_t hi = NumMethodIds() - 1;
while (hi >= lo) {
@@ -373,7 +373,8 @@ const DexFile::ProtoId* DexFile::FindProtoId(dex::TypeIndex return_type_idx,
int32_t hi = NumProtoIds() - 1;
while (hi >= lo) {
int32_t mid = (hi + lo) / 2;
- const DexFile::ProtoId& proto = GetProtoId(mid);
+ const dex::ProtoIndex proto_idx = static_cast<dex::ProtoIndex>(mid);
+ const DexFile::ProtoId& proto = GetProtoId(proto_idx);
int compare = return_type_idx.index_ - proto.return_type_idx_.index_;
if (compare == 0) {
DexFileParameterIterator it(*this, proto);
@@ -777,6 +778,11 @@ void EncodedArrayValueIterator::Next() {
namespace dex {
+std::ostream& operator<<(std::ostream& os, const ProtoIndex& index) {
+ os << "ProtoIndex[" << index.index_ << "]";
+ return os;
+}
+
std::ostream& operator<<(std::ostream& os, const StringIndex& index) {
os << "StringIndex[" << index.index_ << "]";
return os;
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index 4ca735ad66..87d2c48ff1 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -189,7 +189,7 @@ class DexFile {
// Raw method_id_item.
struct MethodId {
dex::TypeIndex class_idx_; // index into type_ids_ array for defining class
- uint16_t proto_idx_; // index into proto_ids_ array for method prototype
+ dex::ProtoIndex proto_idx_; // index into proto_ids_ array for method prototype
dex::StringIndex name_idx_; // index into string_ids_ array for method name
private:
@@ -692,15 +692,15 @@ class DexFile {
}
// Returns the ProtoId at the specified index.
- const ProtoId& GetProtoId(uint16_t idx) const {
- DCHECK_LT(idx, NumProtoIds()) << GetLocation();
- return proto_ids_[idx];
+ const ProtoId& GetProtoId(dex::ProtoIndex idx) const {
+ DCHECK_LT(idx.index_, NumProtoIds()) << GetLocation();
+ return proto_ids_[idx.index_];
}
- uint16_t GetIndexForProtoId(const ProtoId& proto_id) const {
+ dex::ProtoIndex GetIndexForProtoId(const ProtoId& proto_id) const {
CHECK_GE(&proto_id, proto_ids_) << GetLocation();
CHECK_LT(&proto_id, proto_ids_ + header_->proto_ids_size_) << GetLocation();
- return &proto_id - proto_ids_;
+ return dex::ProtoIndex(&proto_id - proto_ids_);
}
// Looks up a proto id for a given return type and signature type list
@@ -722,7 +722,7 @@ class DexFile {
const Signature CreateSignature(const StringPiece& signature) const;
// Returns the short form method descriptor for the given prototype.
- const char* GetShorty(uint32_t proto_idx) const;
+ const char* GetShorty(dex::ProtoIndex proto_idx) const;
const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
return DataPointer<TypeList>(proto_id.parameters_off_);
diff --git a/libdexfile/dex/dex_file_types.h b/libdexfile/dex/dex_file_types.h
index 2bb70ff261..d4fb3de504 100644
--- a/libdexfile/dex/dex_file_types.h
+++ b/libdexfile/dex/dex_file_types.h
@@ -25,72 +25,66 @@ namespace dex {
constexpr uint32_t kDexNoIndex = 0xFFFFFFFF;
-class StringIndex {
+template<typename T>
+class DexIndex {
public:
- uint32_t index_;
+ T index_;
- constexpr StringIndex() : index_(std::numeric_limits<decltype(index_)>::max()) {}
- explicit constexpr StringIndex(uint32_t idx) : index_(idx) {}
+ constexpr DexIndex() : index_(std::numeric_limits<decltype(index_)>::max()) {}
+ explicit constexpr DexIndex(T idx) : index_(idx) {}
bool IsValid() const {
return index_ != std::numeric_limits<decltype(index_)>::max();
}
- static StringIndex Invalid() {
- return StringIndex(std::numeric_limits<decltype(index_)>::max());
+ static constexpr DexIndex Invalid() {
+ return DexIndex(std::numeric_limits<decltype(index_)>::max());
}
-
- bool operator==(const StringIndex& other) const {
+ bool operator==(const DexIndex& other) const {
return index_ == other.index_;
}
- bool operator!=(const StringIndex& other) const {
+ bool operator!=(const DexIndex& other) const {
return index_ != other.index_;
}
- bool operator<(const StringIndex& other) const {
+ bool operator<(const DexIndex& other) const {
return index_ < other.index_;
}
- bool operator<=(const StringIndex& other) const {
+ bool operator<=(const DexIndex& other) const {
return index_ <= other.index_;
}
- bool operator>(const StringIndex& other) const {
+ bool operator>(const DexIndex& other) const {
return index_ > other.index_;
}
- bool operator>=(const StringIndex& other) const {
+ bool operator>=(const DexIndex& other) const {
return index_ >= other.index_;
}
};
-std::ostream& operator<<(std::ostream& os, const StringIndex& index);
-class TypeIndex {
+class ProtoIndex : public DexIndex<uint16_t> {
public:
- uint16_t index_;
-
- constexpr TypeIndex() : index_(std::numeric_limits<decltype(index_)>::max()) {}
- explicit constexpr TypeIndex(uint16_t idx) : index_(idx) {}
-
- bool IsValid() const {
- return index_ != std::numeric_limits<decltype(index_)>::max();
- }
- static TypeIndex Invalid() {
- return TypeIndex(std::numeric_limits<decltype(index_)>::max());
+ ProtoIndex() {}
+ explicit constexpr ProtoIndex(uint16_t index) : DexIndex<decltype(index_)>(index) {}
+ static constexpr ProtoIndex Invalid() {
+ return ProtoIndex(std::numeric_limits<decltype(index_)>::max());
}
+};
+std::ostream& operator<<(std::ostream& os, const ProtoIndex& index);
- bool operator==(const TypeIndex& other) const {
- return index_ == other.index_;
- }
- bool operator!=(const TypeIndex& other) const {
- return index_ != other.index_;
- }
- bool operator<(const TypeIndex& other) const {
- return index_ < other.index_;
- }
- bool operator<=(const TypeIndex& other) const {
- return index_ <= other.index_;
- }
- bool operator>(const TypeIndex& other) const {
- return index_ > other.index_;
+class StringIndex : public DexIndex<uint32_t> {
+ public:
+ StringIndex() {}
+ explicit constexpr StringIndex(uint32_t index) : DexIndex<decltype(index_)>(index) {}
+ static constexpr StringIndex Invalid() {
+ return StringIndex(std::numeric_limits<decltype(index_)>::max());
}
- bool operator>=(const TypeIndex& other) const {
- return index_ >= other.index_;
+};
+std::ostream& operator<<(std::ostream& os, const StringIndex& index);
+
+class TypeIndex : public DexIndex<uint16_t> {
+ public:
+ TypeIndex() {}
+ explicit constexpr TypeIndex(uint16_t index) : DexIndex<uint16_t>(index) {}
+ static constexpr TypeIndex Invalid() {
+ return TypeIndex(std::numeric_limits<decltype(index_)>::max());
}
};
std::ostream& operator<<(std::ostream& os, const TypeIndex& index);
@@ -100,15 +94,21 @@ std::ostream& operator<<(std::ostream& os, const TypeIndex& index);
namespace std {
+template<> struct hash<art::dex::ProtoIndex> {
+ size_t operator()(const art::dex::ProtoIndex& index) const {
+ return hash<decltype(index.index_)>()(index.index_);
+ }
+};
+
template<> struct hash<art::dex::StringIndex> {
size_t operator()(const art::dex::StringIndex& index) const {
- return hash<uint32_t>()(index.index_);
+ return hash<decltype(index.index_)>()(index.index_);
}
};
template<> struct hash<art::dex::TypeIndex> {
size_t operator()(const art::dex::TypeIndex& index) const {
- return hash<uint16_t>()(index.index_);
+ return hash<decltype(index.index_)>()(index.index_);
}
};
diff --git a/libdexfile/dex/dex_file_verifier.cc b/libdexfile/dex/dex_file_verifier.cc
index a32f64e49f..78db8b9a35 100644
--- a/libdexfile/dex/dex_file_verifier.cc
+++ b/libdexfile/dex/dex_file_verifier.cc
@@ -127,8 +127,9 @@ const DexFile::MethodId* DexFileVerifier::CheckLoadMethodId(uint32_t idx, const
return &dex_file_->GetMethodId(idx);
}
-const DexFile::ProtoId* DexFileVerifier::CheckLoadProtoId(uint32_t idx, const char* err_string) {
- if (UNLIKELY(!CheckIndex(idx, dex_file_->NumProtoIds(), err_string))) {
+const DexFile::ProtoId* DexFileVerifier::CheckLoadProtoId(dex::ProtoIndex idx,
+ const char* err_string) {
+ if (UNLIKELY(!CheckIndex(idx.index_, dex_file_->NumProtoIds(), err_string))) {
return nullptr;
}
return &dex_file_->GetProtoId(idx);
@@ -2208,7 +2209,7 @@ bool DexFileVerifier::CheckInterMethodIdItem() {
}
// Check that the proto id is valid.
- if (UNLIKELY(!CheckIndex(item->proto_idx_, dex_file_->NumProtoIds(),
+ if (UNLIKELY(!CheckIndex(item->proto_idx_.index_, dex_file_->NumProtoIds(),
"inter_method_id_item proto_idx"))) {
return false;
}
diff --git a/libdexfile/dex/dex_file_verifier.h b/libdexfile/dex/dex_file_verifier.h
index 04d8d71fa8..43d1093809 100644
--- a/libdexfile/dex/dex_file_verifier.h
+++ b/libdexfile/dex/dex_file_verifier.h
@@ -164,7 +164,7 @@ class DexFileVerifier {
// error if not. If there is an error, null is returned.
const DexFile::FieldId* CheckLoadFieldId(uint32_t idx, const char* error_fmt);
const DexFile::MethodId* CheckLoadMethodId(uint32_t idx, const char* error_fmt);
- const DexFile::ProtoId* CheckLoadProtoId(uint32_t idx, const char* error_fmt);
+ const DexFile::ProtoId* CheckLoadProtoId(dex::ProtoIndex idx, const char* error_fmt);
void ErrorStringPrintf(const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3))) COLD_ATTR;
diff --git a/libdexfile/dex/dex_file_verifier_test.cc b/libdexfile/dex/dex_file_verifier_test.cc
index f82081f8ee..c9bac0fef2 100644
--- a/libdexfile/dex/dex_file_verifier_test.cc
+++ b/libdexfile/dex/dex_file_verifier_test.cc
@@ -161,7 +161,7 @@ TEST_F(DexFileVerifierTest, MethodId) {
"method_id_proto_idx",
[](DexFile* dex_file) {
DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
- method_id->proto_idx_ = 0xFF;
+ method_id->proto_idx_ = dex::ProtoIndex(0xFF);
},
"inter_method_id_item proto_idx");
@@ -1425,12 +1425,13 @@ TEST_F(DexFileVerifierTest, ProtoOrdering) {
CHECK_LT(method_idx + 1u, dex_file->NumMethodIds());
CHECK_EQ(dex_file->GetMethodId(method_idx).name_idx_,
dex_file->GetMethodId(method_idx + 1).name_idx_);
- CHECK_EQ(dex_file->GetMethodId(method_idx).proto_idx_ + 1u,
- dex_file->GetMethodId(method_idx + 1).proto_idx_);
+ CHECK_EQ(dex_file->GetMethodId(method_idx).proto_idx_.index_ + 1u,
+ dex_file->GetMethodId(method_idx + 1).proto_idx_.index_);
// Their return types should be the same.
- uint32_t proto1_idx = dex_file->GetMethodId(method_idx).proto_idx_;
+ dex::ProtoIndex proto1_idx = dex_file->GetMethodId(method_idx).proto_idx_;
const DexFile::ProtoId& proto1 = dex_file->GetProtoId(proto1_idx);
- const DexFile::ProtoId& proto2 = dex_file->GetProtoId(proto1_idx + 1u);
+ dex::ProtoIndex proto2_idx(proto1_idx.index_ + 1u);
+ const DexFile::ProtoId& proto2 = dex_file->GetProtoId(proto2_idx);
CHECK_EQ(proto1.return_type_idx_, proto2.return_type_idx_);
// And the first should not have any parameters while the second should have some.
CHECK(!DexFileParameterIterator(*dex_file, proto1).HasNext());
diff --git a/libdexfile/dex/dex_instruction.cc b/libdexfile/dex/dex_instruction.cc
index 886218129e..8378211c43 100644
--- a/libdexfile/dex/dex_instruction.cc
+++ b/libdexfile/dex/dex_instruction.cc
@@ -467,10 +467,10 @@ std::string Instruction::DumpString(const DexFile* file) const {
case k45cc: {
uint32_t arg[kMaxVarArgRegs];
GetVarArgs(arg);
- uint32_t method_idx = VRegB_45cc();
- uint32_t proto_idx = VRegH_45cc();
+ uint16_t method_idx = VRegB_45cc();
+ dex::ProtoIndex proto_idx(VRegH_45cc());
os << opcode << " {";
- for (int i = 0; i < VRegA_45cc(); ++i) {
+ for (uint32_t i = 0; i < VRegA_45cc(); ++i) {
if (i != 0) {
os << ", ";
}
@@ -478,7 +478,8 @@ std::string Instruction::DumpString(const DexFile* file) const {
}
os << "}";
if (file != nullptr) {
- os << ", " << file->PrettyMethod(method_idx) << ", " << file->GetShorty(proto_idx)
+ os << ", " << file->PrettyMethod(method_idx)
+ << ", " << file->GetShorty(proto_idx)
<< " // ";
} else {
os << ", ";
@@ -490,18 +491,19 @@ std::string Instruction::DumpString(const DexFile* file) const {
switch (Opcode()) {
case INVOKE_POLYMORPHIC_RANGE: {
if (file != nullptr) {
- uint32_t method_idx = VRegB_4rcc();
- uint32_t proto_idx = VRegH_4rcc();
+ uint16_t method_idx = VRegB_4rcc();
+ dex::ProtoIndex proto_idx(VRegH_4rcc());
os << opcode << ", {v" << VRegC_4rcc() << " .. v" << (VRegC_4rcc() + VRegA_4rcc())
- << "}, " << file->PrettyMethod(method_idx) << ", " << file->GetShorty(proto_idx)
+ << "}, " << file->PrettyMethod(method_idx)
+ << ", " << file->GetShorty(dex::ProtoIndex(proto_idx))
<< " // method@" << method_idx << ", proto@" << proto_idx;
break;
}
}
FALLTHROUGH_INTENDED;
default: {
- uint32_t method_idx = VRegB_4rcc();
- uint32_t proto_idx = VRegH_4rcc();
+ uint16_t method_idx = VRegB_4rcc();
+ dex::ProtoIndex proto_idx(VRegH_4rcc());
os << opcode << ", {v" << VRegC_4rcc() << " .. v" << (VRegC_4rcc() + VRegA_4rcc())
<< "}, method@" << method_idx << ", proto@" << proto_idx;
}
diff --git a/patchoat/Android.bp b/patchoat/Android.bp
index 0e8e517cd4..1e2f328ffd 100644
--- a/patchoat/Android.bp
+++ b/patchoat/Android.bp
@@ -25,6 +25,7 @@ cc_defaults {
},
},
shared_libs: [
+ "libartbase",
"libbase",
"libcrypto", // For computing the digest of image file
],
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 64e6796ba0..0540b2087e 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -23,7 +23,7 @@ JIT_DEBUG_REGISTER_CODE_LDFLAGS = [
"-Wl,--keep-unique,__dex_debug_register_code"
]
-cc_defaults {
+libart_cc_defaults {
name: "libart_defaults",
defaults: ["art_defaults"],
host_supported: true,
@@ -32,7 +32,6 @@ cc_defaults {
"art_field.cc",
"art_method.cc",
"barrier.cc",
- "base/file_utils.cc",
"base/mem_map_arena_pool.cc",
"base/mutex.cc",
"base/quasi_atomic.cc",
@@ -196,6 +195,7 @@ cc_defaults {
"ti/agent.cc",
"trace.cc",
"transaction.cc",
+ "var_handles.cc",
"vdex_file.cc",
"verifier/instruction_flags.cc",
"verifier/method_verifier.cc",
@@ -207,7 +207,6 @@ cc_defaults {
"well_known_classes.cc",
"arch/context.cc",
- "arch/instruction_set.cc",
"arch/instruction_set_features.cc",
"arch/memcmp16.cc",
"arch/arm/instruction_set_features_arm.cc",
@@ -396,7 +395,6 @@ cc_defaults {
"libbacktrace",
"liblz4",
"liblog",
- "libmetricslogger",
// For atrace, properties, ashmem, set_sched_policy and socket_peer_is_trusted.
"libcutils",
// For common macros.
@@ -420,7 +418,6 @@ gensrcs {
cmd: "$(location generate_operator_out) art/runtime $(in) > $(out)",
tools: ["generate_operator_out"],
srcs: [
- "arch/instruction_set.h",
"base/mutex.h",
"class_loader_context.h",
"class_status.h",
@@ -531,7 +528,6 @@ art_cc_test {
],
srcs: [
"arch/arch_test.cc",
- "arch/instruction_set_test.cc",
"arch/instruction_set_features_test.cc",
"arch/memcmp16_test.cc",
"arch/stub_test.cc",
@@ -542,7 +538,6 @@ art_cc_test {
"arch/x86/instruction_set_features_x86_test.cc",
"arch/x86_64/instruction_set_features_x86_64_test.cc",
"barrier_test.cc",
- "base/file_utils_test.cc",
"base/mutex_test.cc",
"base/timing_logger_test.cc",
"cha_test.cc",
diff --git a/runtime/arch/code_offset.h b/runtime/arch/code_offset.h
index 8e8dde4c4c..f0c6d22ef2 100644
--- a/runtime/arch/code_offset.h
+++ b/runtime/arch/code_offset.h
@@ -21,9 +21,9 @@
#include <android-base/logging.h>
+#include "arch/instruction_set.h"
#include "base/bit_utils.h"
#include "base/macros.h"
-#include "instruction_set.h"
namespace art {
diff --git a/runtime/arch/instruction_set_features.h b/runtime/arch/instruction_set_features.h
index 5f1a507f7a..c31c927668 100644
--- a/runtime/arch/instruction_set_features.h
+++ b/runtime/arch/instruction_set_features.h
@@ -21,8 +21,8 @@
#include <ostream>
#include <vector>
+#include "arch/instruction_set.h"
#include "base/macros.h"
-#include "instruction_set.h"
namespace art {
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 87fcb20698..608e33cf65 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -710,6 +710,23 @@ bool ArtMethod::HasAnyCompiledCode() {
return GetOatMethodQuickCode(runtime->GetClassLinker()->GetImagePointerSize()) != nullptr;
}
+void ArtMethod::SetNotIntrinsic() {
+ if (!IsIntrinsic()) {
+ return;
+ }
+
+ // Query the hidden API access flags of the intrinsic.
+ HiddenApiAccessFlags::ApiList intrinsic_api_list = GetHiddenApiAccessFlags();
+
+ // Clear intrinsic-related access flags.
+ ClearAccessFlags(kAccIntrinsic | kAccIntrinsicBits);
+
+ // Re-apply hidden API access flags now that the method is not an intrinsic.
+ SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(GetAccessFlags(), intrinsic_api_list));
+ DCHECK_EQ(GetHiddenApiAccessFlags(), intrinsic_api_list);
+}
+
+
void ArtMethod::CopyFrom(ArtMethod* src, PointerSize image_pointer_size) {
memcpy(reinterpret_cast<void*>(this), reinterpret_cast<const void*>(src),
Size(image_pointer_size));
diff --git a/runtime/art_method.h b/runtime/art_method.h
index acaa4a68a1..012d706756 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -194,9 +194,7 @@ class ArtMethod FINAL {
return (GetAccessFlags() & kAccIntrinsicBits) >> kAccFlagsShift;
}
- void SetNotIntrinsic() REQUIRES_SHARED(Locks::mutator_lock_) {
- ClearAccessFlags(kAccIntrinsic | kAccIntrinsicBits);
- }
+ void SetNotIntrinsic() REQUIRES_SHARED(Locks::mutator_lock_);
bool IsCopied() {
static_assert((kAccCopied & (kAccIntrinsic | kAccIntrinsicBits)) == 0,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 9c8b4383dc..be9e08fbec 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -8174,7 +8174,7 @@ ArtField* ClassLinker::FindResolvedFieldJLS(ObjPtr<mirror::Class> klass,
ObjPtr<mirror::MethodType> ClassLinker::ResolveMethodType(
Thread* self,
- uint32_t proto_idx,
+ dex::ProtoIndex proto_idx,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader) {
DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
@@ -8236,7 +8236,7 @@ ObjPtr<mirror::MethodType> ClassLinker::ResolveMethodType(
}
ObjPtr<mirror::MethodType> ClassLinker::ResolveMethodType(Thread* self,
- uint32_t proto_idx,
+ dex::ProtoIndex proto_idx,
ArtMethod* referrer) {
StackHandleScope<2> hs(self);
Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 60cff9ee37..52ecf82c86 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -416,14 +416,14 @@ class ClassLinker {
// Resolve a method type with a given ID from the DexFile associated with a given DexCache
// and ClassLoader, storing the result in the DexCache.
ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self,
- uint32_t proto_idx,
+ dex::ProtoIndex proto_idx,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self,
- uint32_t proto_idx,
+ dex::ProtoIndex proto_idx,
ArtMethod* referrer)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/common_dex_operations.h b/runtime/common_dex_operations.h
index 37e074d552..9c2a40b50d 100644
--- a/runtime/common_dex_operations.h
+++ b/runtime/common_dex_operations.h
@@ -29,6 +29,7 @@
#include "instrumentation.h"
#include "interpreter/shadow_frame.h"
#include "interpreter/unstarted_runtime.h"
+#include "jvalue-inl.h"
#include "mirror/class.h"
#include "mirror/object.h"
#include "obj_ptr-inl.h"
diff --git a/runtime/dex/art_dex_file_loader_test.cc b/runtime/dex/art_dex_file_loader_test.cc
index 274a6df702..d353c26b35 100644
--- a/runtime/dex/art_dex_file_loader_test.cc
+++ b/runtime/dex/art_dex_file_loader_test.cc
@@ -43,48 +43,7 @@ static void Copy(const std::string& src, const std::string& dst) {
dst_stream << src_stream.rdbuf();
}
-class ArtDexFileLoaderTest : public CommonRuntimeTest {
- public:
- virtual void SetUp() {
- CommonRuntimeTest::SetUp();
-
- std::string dex_location = GetTestDexFileName("Main");
- std::string multidex_location = GetTestDexFileName("MultiDex");
-
- data_location_path_ = android_data_ + "/foo.jar";
- system_location_path_ = GetAndroidRoot() + "/foo.jar";
- system_framework_location_path_ = GetAndroidRoot() + "/framework/foo.jar";
- data_multi_location_path_ = android_data_ + "/multifoo.jar";
- system_multi_location_path_ = GetAndroidRoot() + "/multifoo.jar";
- system_framework_multi_location_path_ = GetAndroidRoot() + "/framework/multifoo.jar";
-
- Copy(dex_location, data_location_path_);
- Copy(dex_location, system_location_path_);
- Copy(dex_location, system_framework_location_path_);
-
- Copy(multidex_location, data_multi_location_path_);
- Copy(multidex_location, system_multi_location_path_);
- Copy(multidex_location, system_framework_multi_location_path_);
- }
-
- virtual void TearDown() {
- remove(data_location_path_.c_str());
- remove(system_location_path_.c_str());
- remove(system_framework_location_path_.c_str());
- remove(data_multi_location_path_.c_str());
- remove(system_multi_location_path_.c_str());
- remove(system_framework_multi_location_path_.c_str());
- CommonRuntimeTest::TearDown();
- }
-
- protected:
- std::string data_location_path_;
- std::string system_location_path_;
- std::string system_framework_location_path_;
- std::string data_multi_location_path_;
- std::string system_multi_location_path_;
- std::string system_framework_multi_location_path_;
-};
+class ArtDexFileLoaderTest : public CommonRuntimeTest {};
// TODO: Port OpenTestDexFile(s) need to be ported to use non-ART utilities, and
// the tests that depend upon them should be moved to dex_file_loader_test.cc
@@ -286,7 +245,7 @@ TEST_F(ArtDexFileLoaderTest, FindTypeId) {
TEST_F(ArtDexFileLoaderTest, FindProtoId) {
for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
- const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
+ const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(dex::ProtoIndex(i));
const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
std::vector<dex::TypeIndex> to_find_types;
if (to_find_tl != nullptr) {
@@ -297,7 +256,7 @@ TEST_F(ArtDexFileLoaderTest, FindProtoId) {
const DexFile::ProtoId* found =
java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
ASSERT_TRUE(found != nullptr);
- EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
+ EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), dex::ProtoIndex(i));
}
}
@@ -353,21 +312,24 @@ TEST_F(ArtDexFileLoaderTest, GetDexCanonicalLocation) {
ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
}
-TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile) {
+TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_DataDir) {
+ // Load file from a non-system directory and check that it is not flagged as framework.
+ std::string data_location_path = android_data_ + "/foo.jar";
+ ASSERT_FALSE(LocationIsOnSystemFramework(data_location_path.c_str()));
+
+ Copy(GetTestDexFileName("Main"), data_location_path);
+
ArtDexFileLoader loader;
- bool success;
- std::string error_msg;
std::vector<std::unique_ptr<const DexFile>> dex_files;
-
- // Load file from a non-system directory and check that it is not flagged as framework.
- ASSERT_FALSE(LocationIsOnSystemFramework(data_location_path_.c_str()));
- success = loader.Open(data_location_path_.c_str(),
- data_location_path_,
- /* verify */ false,
- /* verify_checksum */ false,
- &error_msg,
- &dex_files);
+ std::string error_msg;
+ bool success = loader.Open(data_location_path.c_str(),
+ data_location_path,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ &error_msg,
+ &dex_files);
ASSERT_TRUE(success) << error_msg;
+
ASSERT_GE(dex_files.size(), 1u);
for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
ASSERT_FALSE(dex_file->IsPlatformDexFile());
@@ -375,15 +337,27 @@ TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile) {
dex_files.clear();
+ ASSERT_EQ(0, remove(data_location_path.c_str()));
+}
+
+TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemDir) {
// Load file from a system, non-framework directory and check that it is not flagged as framework.
- ASSERT_FALSE(LocationIsOnSystemFramework(system_location_path_.c_str()));
- success = loader.Open(system_location_path_.c_str(),
- system_location_path_,
- /* verify */ false,
- /* verify_checksum */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success);
+ std::string system_location_path = GetAndroidRoot() + "/foo.jar";
+ ASSERT_FALSE(LocationIsOnSystemFramework(system_location_path.c_str()));
+
+ Copy(GetTestDexFileName("Main"), system_location_path);
+
+ ArtDexFileLoader loader;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ bool success = loader.Open(system_location_path.c_str(),
+ system_location_path,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ &error_msg,
+ &dex_files);
+ ASSERT_TRUE(success) << error_msg;
+
ASSERT_GE(dex_files.size(), 1u);
for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
ASSERT_FALSE(dex_file->IsPlatformDexFile());
@@ -391,15 +365,27 @@ TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile) {
dex_files.clear();
+ ASSERT_EQ(0, remove(system_location_path.c_str()));
+}
+
+TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemFrameworkDir) {
// Load file from a system/framework directory and check that it is flagged as a framework dex.
- ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_location_path_.c_str()));
- success = loader.Open(system_framework_location_path_.c_str(),
- system_framework_location_path_,
- /* verify */ false,
- /* verify_checksum */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success);
+ std::string system_framework_location_path = GetAndroidRoot() + "/framework/foo.jar";
+ ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_location_path.c_str()));
+
+ Copy(GetTestDexFileName("Main"), system_framework_location_path);
+
+ ArtDexFileLoader loader;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ bool success = loader.Open(system_framework_location_path.c_str(),
+ system_framework_location_path,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ &error_msg,
+ &dex_files);
+ ASSERT_TRUE(success) << error_msg;
+
ASSERT_GE(dex_files.size(), 1u);
for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
ASSERT_TRUE(dex_file->IsPlatformDexFile());
@@ -407,14 +393,27 @@ TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile) {
dex_files.clear();
+ ASSERT_EQ(0, remove(system_framework_location_path.c_str()));
+}
+
+TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_DataDir_MultiDex) {
// Load multidex file from a non-system directory and check that it is not flagged as framework.
- success = loader.Open(data_multi_location_path_.c_str(),
- data_multi_location_path_,
- /* verify */ false,
- /* verify_checksum */ false,
- &error_msg,
- &dex_files);
+ std::string data_multi_location_path = android_data_ + "/multifoo.jar";
+ ASSERT_FALSE(LocationIsOnSystemFramework(data_multi_location_path.c_str()));
+
+ Copy(GetTestDexFileName("MultiDex"), data_multi_location_path);
+
+ ArtDexFileLoader loader;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ bool success = loader.Open(data_multi_location_path.c_str(),
+ data_multi_location_path,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ &error_msg,
+ &dex_files);
ASSERT_TRUE(success) << error_msg;
+
ASSERT_GT(dex_files.size(), 1u);
for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
ASSERT_FALSE(dex_file->IsPlatformDexFile());
@@ -422,15 +421,28 @@ TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile) {
dex_files.clear();
+ ASSERT_EQ(0, remove(data_multi_location_path.c_str()));
+}
+
+TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemDir_MultiDex) {
// Load multidex file from a system, non-framework directory and check that it is not flagged
// as framework.
- success = loader.Open(system_multi_location_path_.c_str(),
- system_multi_location_path_,
- /* verify */ false,
- /* verify_checksum */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success);
+ std::string system_multi_location_path = GetAndroidRoot() + "/multifoo.jar";
+ ASSERT_FALSE(LocationIsOnSystemFramework(system_multi_location_path.c_str()));
+
+ Copy(GetTestDexFileName("MultiDex"), system_multi_location_path);
+
+ ArtDexFileLoader loader;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ bool success = loader.Open(system_multi_location_path.c_str(),
+ system_multi_location_path,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ &error_msg,
+ &dex_files);
+ ASSERT_TRUE(success) << error_msg;
+
ASSERT_GT(dex_files.size(), 1u);
for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
ASSERT_FALSE(dex_file->IsPlatformDexFile());
@@ -438,19 +450,36 @@ TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile) {
dex_files.clear();
+ ASSERT_EQ(0, remove(system_multi_location_path.c_str()));
+}
+
+TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemFrameworkDir_MultiDex) {
// Load multidex file from a system/framework directory and check that it is flagged as a
// framework dex.
- success = loader.Open(system_framework_multi_location_path_.c_str(),
- system_framework_multi_location_path_,
- /* verify */ false,
- /* verify_checksum */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success);
+ std::string system_framework_multi_location_path = GetAndroidRoot() + "/framework/multifoo.jar";
+ ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_multi_location_path.c_str()));
+
+ Copy(GetTestDexFileName("MultiDex"), system_framework_multi_location_path);
+
+ ArtDexFileLoader loader;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ bool success = loader.Open(system_framework_multi_location_path.c_str(),
+ system_framework_multi_location_path,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ &error_msg,
+ &dex_files);
+ ASSERT_TRUE(success) << error_msg;
+
ASSERT_GT(dex_files.size(), 1u);
for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
ASSERT_TRUE(dex_file->IsPlatformDexFile());
}
+
+ dex_files.clear();
+
+ ASSERT_EQ(0, remove(system_framework_multi_location_path.c_str()));
}
} // namespace art
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 719b4af293..026b5da748 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1073,6 +1073,29 @@ bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg)
return true;
}
+static InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags) {
+ switch (e_machine) {
+ case EM_ARM:
+ return InstructionSet::kArm;
+ case EM_AARCH64:
+ return InstructionSet::kArm64;
+ case EM_386:
+ return InstructionSet::kX86;
+ case EM_X86_64:
+ return InstructionSet::kX86_64;
+ case EM_MIPS: {
+ if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 ||
+ (e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) {
+ return InstructionSet::kMips;
+ } else if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) {
+ return InstructionSet::kMips64;
+ }
+ break;
+ }
+ }
+ return InstructionSet::kNone;
+}
+
template <typename ElfTypes>
bool ElfFileImpl<ElfTypes>::Load(File* file,
bool executable,
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index a58946ae66..7fc8db375b 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -268,7 +268,7 @@ ObjPtr<mirror::MethodHandle> ResolveMethodHandleFromCode(ArtMethod* referrer,
}
ObjPtr<mirror::MethodType> ResolveMethodTypeFromCode(ArtMethod* referrer,
- uint32_t proto_idx) {
+ dex::ProtoIndex proto_idx) {
Thread::PoisonObjectPointersIfDebug();
ObjPtr<mirror::MethodType> method_type =
referrer->GetDexCache()->GetResolvedMethodType(proto_idx);
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 0a3b5dfc93..e33de9c45a 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -158,7 +158,7 @@ ObjPtr<mirror::MethodHandle> ResolveMethodHandleFromCode(ArtMethod* referrer,
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
-ObjPtr<mirror::MethodType> ResolveMethodTypeFromCode(ArtMethod* referrer, uint32_t proto_idx)
+ObjPtr<mirror::MethodType> ResolveMethodTypeFromCode(ArtMethod* referrer, dex::ProtoIndex proto_idx)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index cf9ddd8aa8..fa536c77a9 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -200,7 +200,7 @@ extern "C" mirror::MethodType* artResolveMethodTypeFromCode(uint32_t proto_idx,
auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self,
CalleeSaveType::kSaveEverything);
ArtMethod* caller = caller_and_outer.caller;
- ObjPtr<mirror::MethodType> result = ResolveMethodTypeFromCode(caller, proto_idx);
+ ObjPtr<mirror::MethodType> result = ResolveMethodTypeFromCode(caller, dex::ProtoIndex(proto_idx));
return result.Ptr();
}
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 39429c5b41..0a186f4dc5 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -42,6 +42,7 @@
#include "mirror/method_handle_impl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
+#include "mirror/var_handle.h"
#include "oat_file.h"
#include "oat_quick_method_header.h"
#include "quick_exception_handler.h"
@@ -49,6 +50,7 @@
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread-inl.h"
+#include "var_handles.h"
#include "well_known_classes.h"
namespace art {
@@ -2766,7 +2768,7 @@ extern "C" uintptr_t artInvokePolymorphic(
const Instruction& inst = caller_method->DexInstructions().InstructionAt(dex_pc);
DCHECK(inst.Opcode() == Instruction::INVOKE_POLYMORPHIC ||
inst.Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE);
- const uint32_t proto_idx = inst.VRegH();
+ const dex::ProtoIndex proto_idx(inst.VRegH());
const char* shorty = caller_method->GetDexFile()->GetShorty(proto_idx);
const size_t shorty_length = strlen(shorty);
static const bool kMethodIsStatic = false; // invoke() and invokeExact() are not static.
@@ -2789,13 +2791,6 @@ extern "C" uintptr_t artInvokePolymorphic(
return static_cast<uintptr_t>('V');
}
- // TODO(oth): Ensure this path isn't taken for VarHandle accessors (b/65872996).
- DCHECK_EQ(resolved_method->GetDeclaringClass(),
- WellKnownClasses::ToClass(WellKnownClasses::java_lang_invoke_MethodHandle));
-
- Handle<mirror::MethodHandle> method_handle(hs.NewHandle(
- ObjPtr<mirror::MethodHandle>::DownCast(MakeObjPtr(receiver_handle.Get()))));
-
Handle<mirror::MethodType> method_type(
hs.NewHandle(linker->ResolveMethodType(self, proto_idx, caller_method)));
@@ -2835,24 +2830,43 @@ extern "C" uintptr_t artInvokePolymorphic(
// Call DoInvokePolymorphic with |is_range| = true, as shadow frame has argument registers in
// consecutive order.
RangeInstructionOperands operands(first_arg + 1, num_vregs - 1);
- bool isExact = (jni::EncodeArtMethod(resolved_method) ==
- WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact);
+ Intrinsics intrinsic = static_cast<Intrinsics>(resolved_method->GetIntrinsic());
bool success = false;
- if (isExact) {
- success = MethodHandleInvokeExact(self,
+ if (resolved_method->GetDeclaringClass() == mirror::MethodHandle::StaticClass()) {
+ Handle<mirror::MethodHandle> method_handle(hs.NewHandle(
+ ObjPtr<mirror::MethodHandle>::DownCast(MakeObjPtr(receiver_handle.Get()))));
+ if (intrinsic == Intrinsics::kMethodHandleInvokeExact) {
+ success = MethodHandleInvokeExact(self,
+ *shadow_frame,
+ method_handle,
+ method_type,
+ &operands,
+ result);
+ } else {
+ DCHECK_EQ(static_cast<uint32_t>(intrinsic),
+ static_cast<uint32_t>(Intrinsics::kMethodHandleInvoke));
+ success = MethodHandleInvoke(self,
+ *shadow_frame,
+ method_handle,
+ method_type,
+ &operands,
+ result);
+ }
+ } else {
+ DCHECK_EQ(mirror::VarHandle::StaticClass(), resolved_method->GetDeclaringClass());
+ Handle<mirror::VarHandle> var_handle(hs.NewHandle(
+ ObjPtr<mirror::VarHandle>::DownCast(MakeObjPtr(receiver_handle.Get()))));
+ mirror::VarHandle::AccessMode access_mode =
+ mirror::VarHandle::GetAccessModeByIntrinsic(intrinsic);
+ success = VarHandleInvokeAccessor(self,
*shadow_frame,
- method_handle,
+ var_handle,
method_type,
+ access_mode,
&operands,
result);
- } else {
- success = MethodHandleInvoke(self,
- *shadow_frame,
- method_handle,
- method_type,
- &operands,
- result);
}
+
DCHECK(success || self->IsExceptionPending());
// Pop transition record.
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index 9354d721b7..ee518ae1ea 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include <metricslogger/metrics_logger.h>
-
#include "hidden_api.h"
#include <nativehelper/scoped_local_ref.h>
@@ -24,11 +22,14 @@
#include "thread-current-inl.h"
#include "well_known_classes.h"
+#ifdef ART_TARGET_ANDROID
+#include <metricslogger/metrics_logger.h>
using android::metricslogger::ComplexEventLogger;
using android::metricslogger::ACTION_HIDDEN_API_ACCESSED;
using android::metricslogger::FIELD_HIDDEN_API_ACCESS_METHOD;
using android::metricslogger::FIELD_HIDDEN_API_ACCESS_DENIED;
using android::metricslogger::FIELD_HIDDEN_API_SIGNATURE;
+#endif
namespace art {
namespace hiddenapi {
@@ -137,6 +138,7 @@ void MemberSignature::WarnAboutAccess(AccessMethod access_method,
LOG(WARNING) << "Accessing hidden " << (type_ == kField ? "field " : "method ")
<< Dumpable<MemberSignature>(*this) << " (" << list << ", " << access_method << ")";
}
+#ifdef ART_TARGET_ANDROID
// Convert an AccessMethod enum to a value for logging from the proto enum.
// This method may look odd (the enum values are current the same), but it
// prevents coupling the internal enum to the proto enum (which should never
@@ -156,8 +158,10 @@ inline static int32_t GetEnumValueForLog(AccessMethod access_method) {
DCHECK(false);
}
}
+#endif
void MemberSignature::LogAccessToEventLog(AccessMethod access_method, Action action_taken) {
+#ifdef ART_TARGET_ANDROID
if (access_method == kLinking || access_method == kNone) {
// Linking warnings come from static analysis/compilation of the bytecode
// and can contain false positives (i.e. code that is never run). We choose
@@ -174,6 +178,10 @@ void MemberSignature::LogAccessToEventLog(AccessMethod access_method, Action act
Dump(signature_str);
log_maker.AddTaggedData(FIELD_HIDDEN_API_SIGNATURE, signature_str.str());
log_maker.Record();
+#else
+ UNUSED(access_method);
+ UNUSED(action_taken);
+#endif
}
static ALWAYS_INLINE bool CanUpdateMemberAccessFlags(ArtField*) {
@@ -228,7 +236,7 @@ Action GetMemberActionImpl(T* member,
}
}
- if (kIsTargetBuild) {
+ if (kIsTargetBuild && !kIsTargetLinux) {
uint32_t eventLogSampleRate = runtime->GetHiddenApiEventLogSampleRate();
// Assert that RAND_MAX is big enough, to ensure sampling below works as expected.
static_assert(RAND_MAX >= 0xffff, "RAND_MAX too small");
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 8e21fd3b8f..580224e439 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -95,6 +95,22 @@ inline Action GetActionFromAccessFlags(HiddenApiAccessFlags::ApiList api_list) {
}
}
+class ScopedHiddenApiEnforcementPolicySetting {
+ public:
+ explicit ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)
+ : initial_policy_(Runtime::Current()->GetHiddenApiEnforcementPolicy()) {
+ Runtime::Current()->SetHiddenApiEnforcementPolicy(new_policy);
+ }
+
+ ~ScopedHiddenApiEnforcementPolicySetting() {
+ Runtime::Current()->SetHiddenApiEnforcementPolicy(initial_policy_);
+ }
+
+ private:
+ const EnforcementPolicy initial_policy_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiEnforcementPolicySetting);
+};
+
// Implementation details. DO NOT ACCESS DIRECTLY.
namespace detail {
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 8a85ee41f8..5a50ec5586 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -24,7 +24,7 @@
#include "entrypoints/runtime_asm_entrypoints.h"
#include "intrinsics_enum.h"
#include "jit/jit.h"
-#include "jvalue.h"
+#include "jvalue-inl.h"
#include "method_handles-inl.h"
#include "method_handles.h"
#include "mirror/array-inl.h"
@@ -37,6 +37,7 @@
#include "stack.h"
#include "thread-inl.h"
#include "transaction.h"
+#include "var_handles.h"
#include "well_known_classes.h"
namespace art {
@@ -626,7 +627,8 @@ static bool DoMethodHandleInvokeCommon(Thread* self,
// The vRegH value gives the index of the proto_id associated with this
// signature polymorphic call site.
- const uint32_t callsite_proto_id = (is_range) ? inst->VRegH_4rcc() : inst->VRegH_45cc();
+ const uint16_t vRegH = (is_range) ? inst->VRegH_4rcc() : inst->VRegH_45cc();
+ const dex::ProtoIndex callsite_proto_id(vRegH);
// Call through to the classlinker and ask it to resolve the static type associated
// with the callsite. This information is stored in the dex cache so it's
@@ -724,38 +726,6 @@ bool DoMethodHandleInvoke(Thread* self,
}
}
-static bool DoVarHandleInvokeChecked(Thread* self,
- Handle<mirror::VarHandle> var_handle,
- Handle<mirror::MethodType> callsite_type,
- mirror::VarHandle::AccessMode access_mode,
- ShadowFrame& shadow_frame,
- InstructionOperands* operands,
- JValue* result)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- // TODO(oth): GetMethodTypeForAccessMode() allocates a MethodType()
- // which is only required if we need to convert argument and/or
- // return types.
- StackHandleScope<1> hs(self);
- Handle<mirror::MethodType> accessor_type(hs.NewHandle(
- var_handle->GetMethodTypeForAccessMode(self, access_mode)));
- const size_t num_vregs = accessor_type->NumberOfVRegs();
- const int num_params = accessor_type->GetPTypes()->GetLength();
- ShadowFrameAllocaUniquePtr accessor_frame =
- CREATE_SHADOW_FRAME(num_vregs, nullptr, shadow_frame.GetMethod(), shadow_frame.GetDexPC());
- ShadowFrameGetter getter(shadow_frame, operands);
- static const uint32_t kFirstDestinationReg = 0;
- ShadowFrameSetter setter(accessor_frame.get(), kFirstDestinationReg);
- if (!PerformConversions(self, callsite_type, accessor_type, &getter, &setter, num_params)) {
- return false;
- }
- RangeInstructionOperands accessor_operands(kFirstDestinationReg,
- kFirstDestinationReg + num_vregs);
- if (!var_handle->Access(access_mode, accessor_frame.get(), &accessor_operands, result)) {
- return false;
- }
- return ConvertReturnValue(callsite_type, accessor_type, result);
-}
-
static bool DoVarHandleInvokeCommon(Thread* self,
ShadowFrame& shadow_frame,
const Instruction* inst,
@@ -768,59 +738,43 @@ static bool DoVarHandleInvokeCommon(Thread* self,
return false;
}
- bool is_var_args = inst->HasVarArgs();
- const uint32_t vRegC = is_var_args ? inst->VRegC_45cc() : inst->VRegC_4rcc();
- ObjPtr<mirror::Object> receiver(shadow_frame.GetVRegReference(vRegC));
- if (receiver.IsNull()) {
- ThrowNullPointerExceptionFromDexPC();
- return false;
- }
-
StackHandleScope<2> hs(self);
- Handle<mirror::VarHandle> var_handle(hs.NewHandle(down_cast<mirror::VarHandle*>(receiver.Ptr())));
- if (!var_handle->IsAccessModeSupported(access_mode)) {
- ThrowUnsupportedOperationException();
- return false;
- }
-
- const uint32_t vRegH = is_var_args ? inst->VRegH_45cc() : inst->VRegH_4rcc();
+ bool is_var_args = inst->HasVarArgs();
+ const uint16_t vRegH = is_var_args ? inst->VRegH_45cc() : inst->VRegH_4rcc();
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
Handle<mirror::MethodType> callsite_type(hs.NewHandle(
- class_linker->ResolveMethodType(self, vRegH, shadow_frame.GetMethod())));
+ class_linker->ResolveMethodType(self, dex::ProtoIndex(vRegH), shadow_frame.GetMethod())));
// This implies we couldn't resolve one or more types in this VarHandle.
if (UNLIKELY(callsite_type == nullptr)) {
CHECK(self->IsExceptionPending());
return false;
}
- if (!var_handle->IsMethodTypeCompatible(access_mode, callsite_type.Get())) {
- ThrowWrongMethodTypeException(var_handle->GetMethodTypeForAccessMode(self, access_mode),
- callsite_type.Get());
- return false;
- }
-
+ const uint32_t vRegC = is_var_args ? inst->VRegC_45cc() : inst->VRegC_4rcc();
+ ObjPtr<mirror::Object> receiver(shadow_frame.GetVRegReference(vRegC));
+ Handle<mirror::VarHandle> var_handle(hs.NewHandle(down_cast<mirror::VarHandle*>(receiver.Ptr())));
if (is_var_args) {
uint32_t args[Instruction::kMaxVarArgRegs];
inst->GetVarArgs(args, inst_data);
VarArgsInstructionOperands all_operands(args, inst->VRegA_45cc());
NoReceiverInstructionOperands operands(&all_operands);
- return DoVarHandleInvokeChecked(self,
- var_handle,
- callsite_type,
- access_mode,
- shadow_frame,
- &operands,
- result);
+ return VarHandleInvokeAccessor(self,
+ shadow_frame,
+ var_handle,
+ callsite_type,
+ access_mode,
+ &operands,
+ result);
} else {
RangeInstructionOperands all_operands(inst->VRegC_4rcc(), inst->VRegA_4rcc());
NoReceiverInstructionOperands operands(&all_operands);
- return DoVarHandleInvokeChecked(self,
- var_handle,
- callsite_type,
- access_mode,
- shadow_frame,
- &operands,
- result);
+ return VarHandleInvokeAccessor(self,
+ shadow_frame,
+ var_handle,
+ callsite_type,
+ access_mode,
+ &operands,
+ result);
}
}
@@ -965,9 +919,10 @@ static bool GetArgumentForBootstrapMethod(Thread* self,
StackHandleScope<2> hs(self);
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
- uint32_t index = static_cast<uint32_t>(encoded_value->GetI());
+ dex::ProtoIndex proto_idx(encoded_value->GetC());
ClassLinker* cl = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::MethodType> o = cl->ResolveMethodType(self, index, dex_cache, class_loader);
+ ObjPtr<mirror::MethodType> o =
+ cl->ResolveMethodType(self, proto_idx, dex_cache, class_loader);
if (UNLIKELY(o.IsNull())) {
DCHECK(self->IsExceptionPending());
return false;
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 0818e06675..67a0349d7a 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -217,7 +217,7 @@ static inline ObjPtr<mirror::MethodHandle> ResolveMethodHandle(Thread* self,
}
static inline ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self,
- uint32_t method_type_index,
+ dex::ProtoIndex method_type_index,
ArtMethod* referrer)
REQUIRES_SHARED(Locks::mutator_lock_) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 283885e522..5c7838cd66 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -565,7 +565,7 @@ void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
PREAMBLE();
ClassLinker* cl = Runtime::Current()->GetClassLinker();
ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
- inst->VRegB_21c(),
+ dex::ProtoIndex(inst->VRegB_21c()),
shadow_frame.GetMethod());
if (UNLIKELY(mt == nullptr)) {
HANDLE_PENDING_EXCEPTION();
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index 2a9ef2ce98..1b39a7422d 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -408,7 +408,8 @@ extern "C" size_t MterpConstMethodType(uint32_t index,
ShadowFrame* shadow_frame,
Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<mirror::MethodType> mt = ResolveMethodType(self, index, shadow_frame->GetMethod());
+ ObjPtr<mirror::MethodType> mt =
+ ResolveMethodType(self, dex::ProtoIndex(index), shadow_frame->GetMethod());
if (UNLIKELY(mt == nullptr)) {
return true;
}
diff --git a/runtime/jvalue-inl.h b/runtime/jvalue-inl.h
index 25e34b2a74..5bd4f176f6 100644
--- a/runtime/jvalue-inl.h
+++ b/runtime/jvalue-inl.h
@@ -19,7 +19,7 @@
#include "jvalue.h"
-#include "obj_ptr.h"
+#include "obj_ptr-inl.h"
namespace art {
diff --git a/runtime/jvalue.h b/runtime/jvalue.h
index 266abcf399..b42d995d5c 100644
--- a/runtime/jvalue.h
+++ b/runtime/jvalue.h
@@ -33,7 +33,7 @@ union PACKED(alignof(mirror::Object*)) JValue {
// We default initialize JValue instances to all-zeros.
JValue() : j(0) {}
- template<typename T> static JValue FromPrimitive(T v);
+ template<typename T> ALWAYS_INLINE static JValue FromPrimitive(T v);
int8_t GetB() const { return b; }
void SetB(int8_t new_b) {
@@ -62,6 +62,7 @@ union PACKED(alignof(mirror::Object*)) JValue {
mirror::Object* GetL() const REQUIRES_SHARED(Locks::mutator_lock_) {
return l;
}
+ ALWAYS_INLINE
void SetL(ObjPtr<mirror::Object> new_l) REQUIRES_SHARED(Locks::mutator_lock_);
int16_t GetS() const { return s; }
diff --git a/runtime/method_handles-inl.h b/runtime/method_handles-inl.h
index 41c8384e0d..00a8c00880 100644
--- a/runtime/method_handles-inl.h
+++ b/runtime/method_handles-inl.h
@@ -22,7 +22,7 @@
#include "common_throws.h"
#include "dex/dex_instruction.h"
#include "interpreter/interpreter_common.h"
-#include "jvalue.h"
+#include "jvalue-inl.h"
#include "mirror/class.h"
#include "mirror/method_type.h"
#include "mirror/object.h"
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 64ab78997f..1d45aaeb2e 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -20,7 +20,6 @@
#include "common_dex_operations.h"
#include "jvalue-inl.h"
-#include "jvalue.h"
#include "mirror/emulated_stack_frame.h"
#include "mirror/method_handle_impl-inl.h"
#include "mirror/method_type.h"
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 7a4876c412..72f1443dfa 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -127,23 +127,23 @@ inline void DexCache::ClearResolvedType(dex::TypeIndex type_idx) {
}
}
-inline uint32_t DexCache::MethodTypeSlotIndex(uint32_t proto_idx) {
+inline uint32_t DexCache::MethodTypeSlotIndex(dex::ProtoIndex proto_idx) {
DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
- DCHECK_LT(proto_idx, GetDexFile()->NumProtoIds());
- const uint32_t slot_idx = proto_idx % kDexCacheMethodTypeCacheSize;
+ DCHECK_LT(proto_idx.index_, GetDexFile()->NumProtoIds());
+ const uint32_t slot_idx = proto_idx.index_ % kDexCacheMethodTypeCacheSize;
DCHECK_LT(slot_idx, NumResolvedMethodTypes());
return slot_idx;
}
-inline MethodType* DexCache::GetResolvedMethodType(uint32_t proto_idx) {
+inline MethodType* DexCache::GetResolvedMethodType(dex::ProtoIndex proto_idx) {
return GetResolvedMethodTypes()[MethodTypeSlotIndex(proto_idx)].load(
- std::memory_order_relaxed).GetObjectForIndex(proto_idx);
+ std::memory_order_relaxed).GetObjectForIndex(proto_idx.index_);
}
-inline void DexCache::SetResolvedMethodType(uint32_t proto_idx, MethodType* resolved) {
+inline void DexCache::SetResolvedMethodType(dex::ProtoIndex proto_idx, MethodType* resolved) {
DCHECK(resolved != nullptr);
GetResolvedMethodTypes()[MethodTypeSlotIndex(proto_idx)].store(
- MethodTypeDexCachePair(resolved, proto_idx), std::memory_order_relaxed);
+ MethodTypeDexCachePair(resolved, proto_idx.index_), std::memory_order_relaxed);
// TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this);
}
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index d940964edb..9aff9ec49a 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -307,9 +307,9 @@ class MANAGED DexCache FINAL : public Object {
ALWAYS_INLINE void ClearResolvedField(uint32_t idx, PointerSize ptr_size)
REQUIRES_SHARED(Locks::mutator_lock_);
- MethodType* GetResolvedMethodType(uint32_t proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
+ MethodType* GetResolvedMethodType(dex::ProtoIndex proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
- void SetResolvedMethodType(uint32_t proto_idx, MethodType* resolved)
+ void SetResolvedMethodType(dex::ProtoIndex proto_idx, MethodType* resolved)
REQUIRES_SHARED(Locks::mutator_lock_);
CallSite* GetResolvedCallSite(uint32_t call_site_idx) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -432,7 +432,7 @@ class MANAGED DexCache FINAL : public Object {
uint32_t TypeSlotIndex(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
uint32_t FieldSlotIndex(uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_);
uint32_t MethodSlotIndex(uint32_t method_idx) REQUIRES_SHARED(Locks::mutator_lock_);
- uint32_t MethodTypeSlotIndex(uint32_t proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
+ uint32_t MethodTypeSlotIndex(dex::ProtoIndex proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
private:
void Init(const DexFile* dex_file,
diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc
index d2bff2c19a..97e0ce6684 100644
--- a/runtime/mirror/dex_cache_test.cc
+++ b/runtime/mirror/dex_cache_test.cc
@@ -169,9 +169,9 @@ TEST_F(DexCacheMethodHandlesTest, TestResolvedMethodTypes) {
for (size_t i = 0; i < dex_file.NumProtoIds(); ++i) {
const MethodTypeDexCachePair pair = method_types_cache[i].load(std::memory_order_relaxed);
- if (pair.index == method1_id.proto_idx_) {
+ if (dex::ProtoIndex(pair.index) == method1_id.proto_idx_) {
ASSERT_EQ(method1_type.Get(), pair.object.Read());
- } else if (pair.index == method2_id.proto_idx_) {
+ } else if (dex::ProtoIndex(pair.index) == method2_id.proto_idx_) {
ASSERT_EQ(method2_type.Get(), pair.object.Read());
} else {
ASSERT_TRUE(false);
diff --git a/runtime/mirror/var_handle.cc b/runtime/mirror/var_handle.cc
index b309f596fd..d31e06cf36 100644
--- a/runtime/mirror/var_handle.cc
+++ b/runtime/mirror/var_handle.cc
@@ -1425,21 +1425,24 @@ int32_t VarHandle::GetAccessModesBitMask() {
return GetField32(AccessModesBitMaskOffset());
}
-bool VarHandle::IsMethodTypeCompatible(AccessMode access_mode, MethodType* method_type) {
- StackHandleScope<3> hs(Thread::Current());
- Handle<Class> mt_rtype(hs.NewHandle(method_type->GetRType()));
- Handle<VarHandle> vh(hs.NewHandle(this));
- Handle<Class> var_type(hs.NewHandle(vh->GetVarType()));
+VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode access_mode,
+ MethodType* method_type) {
+ MatchKind match = MatchKind::kExact;
+
+ ObjPtr<VarHandle> vh = this;
+ ObjPtr<Class> var_type = vh->GetVarType();
+ ObjPtr<Class> mt_rtype = method_type->GetRType();
AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
- // Check return type first.
- if (mt_rtype->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
- // The result of the operation will be discarded. The return type
- // of the VarHandle is immaterial.
- } else {
- ObjPtr<Class> vh_rtype(GetReturnType(access_mode_template, var_type.Get()));
- if (!IsReturnTypeConvertible(vh_rtype, mt_rtype.Get())) {
- return false;
+ // Check return type first. If the return type of the method
+ // of the VarHandle is immaterial.
+ if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid) {
+ ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type.Ptr());
+ if (vh_rtype != mt_rtype) {
+ if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) {
+ return MatchKind::kNone;
+ }
+ match = MatchKind::kWithConversions;
}
}
@@ -1447,21 +1450,25 @@ bool VarHandle::IsMethodTypeCompatible(AccessMode access_mode, MethodType* metho
ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters];
const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
access_mode_template,
- var_type.Get(),
+ var_type,
GetCoordinateType0(),
GetCoordinateType1());
if (vh_ptypes_count != method_type->GetPTypes()->GetLength()) {
- return false;
+ return MatchKind::kNone;
}
// Check the parameter types are compatible.
ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
for (int32_t i = 0; i < vh_ptypes_count; ++i) {
+ if (mt_ptypes->Get(i) == vh_ptypes[i]) {
+ continue;
+ }
if (!IsParameterTypeConvertible(mt_ptypes->Get(i), vh_ptypes[i])) {
- return false;
+ return MatchKind::kNone;
}
+ match = MatchKind::kWithConversions;
}
- return true;
+ return match;
}
bool VarHandle::IsInvokerMethodTypeCompatible(AccessMode access_mode,
@@ -1508,7 +1515,7 @@ bool VarHandle::IsInvokerMethodTypeCompatible(AccessMode access_mode,
MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self,
ObjPtr<VarHandle> var_handle,
AccessMode access_mode) {
- // This is a static as the var_handle might be moved by the GC during it's execution.
+ // This is a static method as the var_handle might be moved by the GC during it's execution.
AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
StackHandleScope<3> hs(self);
@@ -1540,7 +1547,7 @@ MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode acces
bool VarHandle::Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result) {
Class* klass = GetClass();
if (klass == FieldVarHandle::StaticClass()) {
@@ -1671,7 +1678,7 @@ ArtField* FieldVarHandle::GetField() {
bool FieldVarHandle::Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result) {
ShadowFrameGetter getter(*shadow_frame, operands);
ArtField* field = GetField();
@@ -1743,7 +1750,7 @@ GcRoot<Class> FieldVarHandle::static_class_;
bool ArrayElementVarHandle::Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result) {
ShadowFrameGetter getter(*shadow_frame, operands);
@@ -1856,7 +1863,7 @@ bool ByteArrayViewVarHandle::GetNativeByteOrder() {
bool ByteArrayViewVarHandle::Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result) {
ShadowFrameGetter getter(*shadow_frame, operands);
@@ -1965,7 +1972,7 @@ bool ByteBufferViewVarHandle::GetNativeByteOrder() {
bool ByteBufferViewVarHandle::Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result) {
ShadowFrameGetter getter(*shadow_frame, operands);
diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h
index d46d900a8d..eb3704ee48 100644
--- a/runtime/mirror/var_handle.h
+++ b/runtime/mirror/var_handle.h
@@ -99,14 +99,16 @@ class MANAGED VarHandle : public Object {
return (GetAccessModesBitMask() & (1u << static_cast<uint32_t>(accessMode))) != 0;
}
- // Returns true if the MethodType specified is compatible with the
- // method type associated with the specified AccessMode. The
- // supplied MethodType is assumed to be from the point of invocation
- // so it is valid for the supplied MethodType to have a void return
- // value when the return value for the AccessMode is non-void. This
- // corresponds to the result of the accessor being discarded.
- bool IsMethodTypeCompatible(AccessMode access_mode, MethodType* method_type)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ enum MatchKind : uint8_t {
+ kNone,
+ kWithConversions,
+ kExact
+ };
+
+ // Returns match information on the compatability between the exact method type for
+ // 'access_mode' and the provided 'method_type'.
+ MatchKind GetMethodTypeMatchForAccessMode(AccessMode access_mode, MethodType* method_type)
+ REQUIRES_SHARED(Locks::mutator_lock_);
// Returns true if the MethodType specified is compatible with the
// specified access_mode if the first parameter of method_type is
@@ -124,7 +126,7 @@ class MANAGED VarHandle : public Object {
bool Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -192,7 +194,7 @@ class MANAGED FieldVarHandle : public VarHandle {
public:
bool Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -225,7 +227,7 @@ class MANAGED ArrayElementVarHandle : public VarHandle {
public:
bool Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -248,7 +250,7 @@ class MANAGED ByteArrayViewVarHandle : public VarHandle {
public:
bool Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -281,7 +283,7 @@ class MANAGED ByteBufferViewVarHandle : public VarHandle {
public:
bool Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
- InstructionOperands* operands,
+ const InstructionOperands* const operands,
JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc
index d9fa07f207..005aba3edd 100644
--- a/runtime/mirror/var_handle_test.cc
+++ b/runtime/mirror/var_handle_test.cc
@@ -246,6 +246,47 @@ static MethodType* MethodTypeOf(const std::string& method_descriptor) {
return MethodType::Create(self, rtype, ptypes);
}
+static bool AccessModeMatch(VarHandle* vh,
+ VarHandle::AccessMode access_mode,
+ MethodType* method_type,
+ VarHandle::MatchKind expected_match)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return vh->GetMethodTypeMatchForAccessMode(access_mode, method_type) == expected_match;
+}
+
+template <typename VH>
+static bool AccessModeExactMatch(Handle<VH> vh,
+ VarHandle::AccessMode access_mode,
+ const char* descriptor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return AccessModeMatch(vh.Get(),
+ access_mode,
+ MethodTypeOf(descriptor),
+ VarHandle::MatchKind::kExact);
+}
+
+template <typename VH>
+static bool AccessModeWithConversionsMatch(Handle<VH> vh,
+ VarHandle::AccessMode access_mode,
+ const char* descriptor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return AccessModeMatch(vh.Get(),
+ access_mode,
+ MethodTypeOf(descriptor),
+ VarHandle::MatchKind::kWithConversions);
+}
+
+template <typename VH>
+static bool AccessModeNoMatch(Handle<VH> vh,
+ VarHandle::AccessMode access_mode,
+ const char* descriptor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return AccessModeMatch(vh.Get(),
+ access_mode,
+ MethodTypeOf(descriptor),
+ VarHandle::MatchKind::kNone);
+}
+
TEST_F(VarHandleTest, InstanceFieldVarHandle) {
Thread * const self = Thread::Current();
ScopedObjectAccess soa(self);
@@ -296,47 +337,53 @@ TEST_F(VarHandleTest, InstanceFieldVarHandle) {
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;)I")));
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;)V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)Z")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;)I"));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;)V"));
+ EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;)D"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)Z"));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;)V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)V")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;I)V"));
+ EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;S)V"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;)V"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)V"));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;II)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode,
- MethodTypeOf("(Ljava/lang/Integer;II)I")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)V")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;II)Z"));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;II)V"));
+ EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;II)Ljava/lang/Boolean;"));
+ EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;IB)V"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;II)I"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)V"));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;II)I")));
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;II)V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(IIII)V")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;II)I"));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;II)V"));
+ EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;II)J"));
+ EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;BS)F"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;I)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(IIII)V"));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)I")));
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)S")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;I)I"));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;I)V"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;I)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(II)S"));
}
// Check synthesized method types match expected forms.
@@ -430,48 +477,47 @@ TEST_F(VarHandleTest, StaticFieldVarHandle) {
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("()I")));
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("()V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("()Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)Z")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "()I"));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "()V"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "()Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)Z"));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(I)V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("()V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("()Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(F)V")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(I)V"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "()V"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "()Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(F)V"));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode,
- MethodTypeOf("(II)Ljava/lang/String;")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("()Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)V")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(II)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(II)Ljava/lang/String;"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "()Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)V"));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)I")));
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(ID)I")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)S")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(IIJ)V")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(II)I"));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(II)V"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(ID)I"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(II)S"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(IIJ)V"));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(I)I")));
- EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(I)V")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(I)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)V")));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(I)I"));
+ EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(I)V"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(I)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(II)V"));
}
// Check synthesized method types match expected forms.
@@ -594,50 +640,46 @@ TEST_F(VarHandleTest, ArrayElementVarHandle) {
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;I)Ljava/lang/String;")));
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;I)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;Ljava/lang/String;)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)Z")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;I)Ljava/lang/String;"));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;I)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;Ljava/lang/String;)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)Z"));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;I)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;I)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;I)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;I)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V"));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
- EXPECT_TRUE(
- vh->IsMethodTypeCompatible(
- access_mode,
- MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode,
- MethodTypeOf("([Ljava/lang/String;III)I")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;I)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;III)I"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;I)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V"));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;")));
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;II)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(III)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;"));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;II)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(III)V"));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String;")));
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String;"));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(II)V"));
}
// Check synthesized method types match expected forms.
@@ -747,50 +789,46 @@ TEST_F(VarHandleTest, ByteArrayViewVarHandle) {
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BI)C")));
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BI)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BC)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)Z")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BI)C"));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BI)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BC)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)Z"));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BIC)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BI)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BI)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BIC)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BI)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BI)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V"));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
- EXPECT_TRUE(
- vh->IsMethodTypeCompatible(
- access_mode,
- MethodTypeOf("([BICC)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode,
- MethodTypeOf("([BIII)I")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BI)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BICC)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BIII)I"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BI)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V"));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BICC)C")));
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BICC)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BII)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(III)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BICC)C"));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BICC)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BII)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(III)V"));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BIC)C")));
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BIC)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("([BIC)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BIC)C"));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BIC)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BIC)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(II)V"));
}
// Check synthesized method types match expected forms.
@@ -900,50 +938,46 @@ TEST_F(VarHandleTest, ByteBufferViewVarHandle) {
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;I)D")));
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;I)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;D)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)Z")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)D"));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;D)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)Z"));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;ID)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;I)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;I)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;ID)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V"));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
- EXPECT_TRUE(
- vh->IsMethodTypeCompatible(
- access_mode,
- MethodTypeOf("(Ljava/nio/ByteBuffer;IDD)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode,
- MethodTypeOf("(Ljava/nio/ByteBuffer;IDI)D")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;I)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Z)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;IDD)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;IDI)D"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V"));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;IDD)D")));
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;IDD)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;II)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(III)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;IDD)D"));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;IDD)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;II)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(III)V"));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;ID)D")));
- EXPECT_TRUE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;ID)V")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/nio/ByteBuffer;ID)Z")));
- EXPECT_FALSE(vh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)V")));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;ID)D"));
+ EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;ID)V"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;ID)Z"));
+ EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(II)V"));
}
// Check synthesized method types match expected forms.
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index e0afbee845..25599843e9 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -27,6 +27,7 @@
#include "dex/dex_file-inl.h"
#include "dex/dex_file_annotations.h"
#include "jni/jni_internal.h"
+#include "jvalue-inl.h"
#include "mirror/class-inl.h"
#include "mirror/field-inl.h"
#include "native_util.h"
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index c00e47f9b8..6c869cada5 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -36,6 +36,7 @@
#include "exec_utils.h"
#include "gc/heap.h"
#include "gc/space/image_space.h"
+#include "hidden_api.h"
#include "image.h"
#include "oat.h"
#include "runtime.h"
@@ -823,6 +824,11 @@ bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args,
argv.push_back("--compiler-filter=verify-none");
}
+ if (runtime->GetHiddenApiEnforcementPolicy() != hiddenapi::EnforcementPolicy::kNoChecks) {
+ argv.push_back("--runtime-arg");
+ argv.push_back("-Xhidden-api-checks");
+ }
+
if (runtime->MustRelocateIfPossible()) {
argv.push_back("--runtime-arg");
argv.push_back("-Xrelocate");
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 99bc0b2c6e..0b3c61d474 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -33,6 +33,7 @@
#include "class_loader_context.h"
#include "common_runtime_test.h"
#include "dexopt_test.h"
+#include "hidden_api.h"
#include "oat_file.h"
#include "oat_file_manager.h"
#include "scoped_thread_state_change-inl.h"
@@ -43,6 +44,8 @@ namespace art {
static const std::string kSpecialSharedLibrary = "&"; // NOLINT [runtime/string] [4]
static ClassLoaderContext* kSpecialSharedLibraryContext = nullptr;
+static constexpr char kDex2oatCmdLineHiddenApiArg[] = " --runtime-arg -Xhidden-api-checks";
+
class OatFileAssistantTest : public DexoptTest {
public:
void VerifyOptimizationStatus(const std::string& file,
@@ -1413,6 +1416,46 @@ TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
}
+TEST_F(OatFileAssistantTest, MakeUpToDateWithHiddenApiDisabled) {
+ hiddenapi::ScopedHiddenApiEnforcementPolicySetting hiddenapi_exemption(
+ hiddenapi::EnforcementPolicy::kNoChecks);
+
+ std::string dex_location = GetScratchDir() + "/TestDexHiddenApiDisabled.jar";
+ Copy(GetDexSrc1(), dex_location);
+
+ OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+ std::string error_msg;
+ int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
+ EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
+
+ std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
+ EXPECT_NE(nullptr, oat_file.get());
+
+ const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey);
+ EXPECT_NE(nullptr, cmd_line);
+ EXPECT_EQ(nullptr, strstr(cmd_line, kDex2oatCmdLineHiddenApiArg));
+}
+
+TEST_F(OatFileAssistantTest, MakeUpToDateWithHiddenApiEnabled) {
+ hiddenapi::ScopedHiddenApiEnforcementPolicySetting hiddenapi_exemption(
+ hiddenapi::EnforcementPolicy::kBlacklistOnly);
+
+ std::string dex_location = GetScratchDir() + "/TestDexHiddenApiEnabled.jar";
+ Copy(GetDexSrc1(), dex_location);
+
+ OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+ std::string error_msg;
+ int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
+ EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
+
+ std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
+ EXPECT_NE(nullptr, oat_file.get());
+
+ const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey);
+ EXPECT_NE(nullptr, cmd_line);
+ EXPECT_NE(nullptr, strstr(cmd_line, kDex2oatCmdLineHiddenApiArg));
+}
+
TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
std::string dex_location = GetScratchDir() + "/TestDex.jar";
std::string context_location = GetScratchDir() + "/ContextDex.jar";
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index dfa4b3daab..66eba1e1d4 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -25,6 +25,7 @@
#include "indirect_reference_table-inl.h"
#include "jni/java_vm_ext.h"
#include "jni/jni_internal.h"
+#include "jvalue-inl.h"
#include "mirror/class-inl.h"
#include "mirror/executable.h"
#include "mirror/object_array-inl.h"
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index b8775b874f..4142cb0c95 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1198,7 +1198,7 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
// As is, we're encoding some logic here about which specific policy to use, which would be better
// controlled by the framework.
hidden_api_policy_ = do_hidden_api_checks
- ? hiddenapi::EnforcementPolicy::kBlacklistOnly
+ ? hiddenapi::EnforcementPolicy::kDarkGreyAndBlackList
: hiddenapi::EnforcementPolicy::kNoChecks;
no_sig_chain_ = runtime_options.Exists(Opt::NoSigChain);
diff --git a/runtime/var_handles.cc b/runtime/var_handles.cc
new file mode 100644
index 0000000000..d71745e531
--- /dev/null
+++ b/runtime/var_handles.cc
@@ -0,0 +1,78 @@
+/*
+ * 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 "var_handles.h"
+
+#include "common_throws.h"
+#include "dex/dex_instruction.h"
+#include "handle.h"
+#include "method_handles-inl.h"
+#include "mirror/method_type.h"
+#include "mirror/var_handle.h"
+
+namespace art {
+
+bool VarHandleInvokeAccessor(Thread* self,
+ ShadowFrame& shadow_frame,
+ Handle<mirror::VarHandle> var_handle,
+ Handle<mirror::MethodType> callsite_type,
+ const mirror::VarHandle::AccessMode access_mode,
+ const InstructionOperands* const operands,
+ JValue* result) {
+ if (var_handle.IsNull()) {
+ ThrowNullPointerExceptionFromDexPC();
+ return false;
+ }
+
+ if (!var_handle->IsAccessModeSupported(access_mode)) {
+ ThrowUnsupportedOperationException();
+ return false;
+ }
+
+ mirror::VarHandle::MatchKind match_kind =
+ var_handle->GetMethodTypeMatchForAccessMode(access_mode, callsite_type.Get());
+ if (match_kind == mirror::VarHandle::MatchKind::kExact) {
+ return var_handle->Access(access_mode, &shadow_frame, operands, result);
+ }
+ if (match_kind == mirror::VarHandle::MatchKind::kNone) {
+ ThrowWrongMethodTypeException(var_handle->GetMethodTypeForAccessMode(self, access_mode),
+ callsite_type.Get());
+ return false;
+ }
+ DCHECK_EQ(mirror::VarHandle::MatchKind::kWithConversions, match_kind);
+
+ StackHandleScope<1> hs(self);
+ Handle<mirror::MethodType> accessor_type(hs.NewHandle(
+ var_handle->GetMethodTypeForAccessMode(self, access_mode)));
+ const size_t num_vregs = accessor_type->NumberOfVRegs();
+ const int num_params = accessor_type->GetPTypes()->GetLength();
+ ShadowFrameAllocaUniquePtr accessor_frame =
+ CREATE_SHADOW_FRAME(num_vregs, nullptr, shadow_frame.GetMethod(), shadow_frame.GetDexPC());
+ ShadowFrameGetter getter(shadow_frame, operands);
+ static const uint32_t kFirstDestinationReg = 0;
+ ShadowFrameSetter setter(accessor_frame.get(), kFirstDestinationReg);
+ if (!PerformConversions(self, callsite_type, accessor_type, &getter, &setter, num_params)) {
+ return false;
+ }
+ RangeInstructionOperands accessor_operands(kFirstDestinationReg,
+ kFirstDestinationReg + num_vregs);
+ if (!var_handle->Access(access_mode, accessor_frame.get(), &accessor_operands, result)) {
+ return false;
+ }
+ return ConvertReturnValue(callsite_type, accessor_type, result);
+}
+
+} // namespace art
diff --git a/runtime/var_handles.h b/runtime/var_handles.h
new file mode 100644
index 0000000000..2ff8405f03
--- /dev/null
+++ b/runtime/var_handles.h
@@ -0,0 +1,35 @@
+/*
+ * 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_RUNTIME_VAR_HANDLES_H_
+#define ART_RUNTIME_VAR_HANDLES_H_
+
+#include "mirror/var_handle.h"
+
+namespace art {
+
+bool VarHandleInvokeAccessor(Thread* self,
+ ShadowFrame& shadow_frame,
+ Handle<mirror::VarHandle> var_handle,
+ Handle<mirror::MethodType> callsite_type,
+ const mirror::VarHandle::AccessMode access_mode,
+ const InstructionOperands* const operands,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+} // namespace art
+
+#endif // ART_RUNTIME_VAR_HANDLES_H_
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 3518d2facd..91cec23dd5 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3086,7 +3086,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
DCHECK(HasFailures());
break;
}
- const uint32_t proto_idx = (is_range) ? inst->VRegH_4rcc() : inst->VRegH_45cc();
+ const uint16_t vRegH = (is_range) ? inst->VRegH_4rcc() : inst->VRegH_45cc();
+ const dex::ProtoIndex proto_idx(vRegH);
const char* return_descriptor =
dex_file_->GetReturnTypeDescriptor(dex_file_->GetProtoId(proto_idx));
const RegType& return_type =
@@ -3117,7 +3118,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
CallSiteArrayValueIterator it(*dex_file_, dex_file_->GetCallSiteId(call_site_idx));
it.Next(); // Skip to name.
it.Next(); // Skip to method type of the method handle
- const uint32_t proto_idx = static_cast<uint32_t>(it.GetJavaValue().i);
+ const dex::ProtoIndex proto_idx(it.GetJavaValue().c);
const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(proto_idx);
DexFileParameterIterator param_it(*dex_file_, proto_id);
// Treat method as static as it has yet to be determined.
@@ -4190,7 +4191,8 @@ ArtMethod* MethodVerifier::VerifyInvocationArgs(
if (UNLIKELY(method_type == METHOD_POLYMORPHIC)) {
// Process the signature of the calling site that is invoking the method handle.
- DexFileParameterIterator it(*dex_file_, dex_file_->GetProtoId(inst->VRegH()));
+ dex::ProtoIndex proto_idx(inst->VRegH());
+ DexFileParameterIterator it(*dex_file_, dex_file_->GetProtoId(proto_idx));
return VerifyInvocationArgsFromIterator(&it, inst, method_type, is_range, res_method);
} else {
// Process the target method's signature.
@@ -4208,8 +4210,6 @@ bool MethodVerifier::CheckSignaturePolymorphicMethod(ArtMethod* method) {
expected_return_descriptor = mirror::MethodHandle::GetReturnTypeDescriptor(method_name);
} else if (klass == mirror::VarHandle::StaticClass()) {
expected_return_descriptor = mirror::VarHandle::GetReturnTypeDescriptor(method_name);
- // TODO: add compiler support for VarHandle accessor methods (b/71781600)
- Fail(VERIFY_ERROR_FORCE_INTERPRETER);
} else {
Fail(VERIFY_ERROR_BAD_CLASS_HARD)
<< "Signature polymorphic method in unsuppported class: " << klass->PrettyDescriptor();
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index b79334ac7f..4843061be6 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -282,26 +282,9 @@ uint32_t WellKnownClasses::StringInitToEntryPoint(ArtMethod* string_init) {
}
#undef STRING_INIT_LIST
-class ScopedHiddenApiExemption {
- public:
- explicit ScopedHiddenApiExemption(Runtime* runtime)
- : runtime_(runtime),
- initial_policy_(runtime_->GetHiddenApiEnforcementPolicy()) {
- runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kNoChecks);
- }
-
- ~ScopedHiddenApiExemption() {
- runtime_->SetHiddenApiEnforcementPolicy(initial_policy_);
- }
-
- private:
- Runtime* runtime_;
- const hiddenapi::EnforcementPolicy initial_policy_;
- DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiExemption);
-};
-
void WellKnownClasses::Init(JNIEnv* env) {
- ScopedHiddenApiExemption hiddenapi_exemption(Runtime::Current());
+ hiddenapi::ScopedHiddenApiEnforcementPolicySetting hiddenapi_exemption(
+ hiddenapi::EnforcementPolicy::kNoChecks);
dalvik_annotation_optimization_CriticalNative =
CacheClass(env, "dalvik/annotation/optimization/CriticalNative");
diff --git a/test/999-redefine-hiddenapi/api-blacklist.txt b/test/999-redefine-hiddenapi/api-blacklist.txt
new file mode 100644
index 0000000000..63e37aa757
--- /dev/null
+++ b/test/999-redefine-hiddenapi/api-blacklist.txt
@@ -0,0 +1,2 @@
+Lart/Test999;->foo()V
+Lart/Test999;->bar:I
diff --git a/test/999-redefine-hiddenapi/build b/test/999-redefine-hiddenapi/build
new file mode 100644
index 0000000000..f4b029fb82
--- /dev/null
+++ b/test/999-redefine-hiddenapi/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+USE_HIDDENAPI=true ./default-build "$@"
diff --git a/test/999-redefine-hiddenapi/expected.txt b/test/999-redefine-hiddenapi/expected.txt
new file mode 100644
index 0000000000..6a5618ebc6
--- /dev/null
+++ b/test/999-redefine-hiddenapi/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/999-redefine-hiddenapi/info.txt b/test/999-redefine-hiddenapi/info.txt
new file mode 100644
index 0000000000..87bc30cf80
--- /dev/null
+++ b/test/999-redefine-hiddenapi/info.txt
@@ -0,0 +1 @@
+Tests that JVMTI class redefinition does not strip away hidden API access flags.
diff --git a/test/999-redefine-hiddenapi/run b/test/999-redefine-hiddenapi/run
new file mode 100755
index 0000000000..c6e62ae6cd
--- /dev/null
+++ b/test/999-redefine-hiddenapi/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+./default-run "$@" --jvmti
diff --git a/test/999-redefine-hiddenapi/src-ex/Test999.java b/test/999-redefine-hiddenapi/src-ex/Test999.java
new file mode 100644
index 0000000000..97495c5a47
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src-ex/Test999.java
@@ -0,0 +1,25 @@
+/*
+ * 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 art;
+
+public class Test999 {
+ public void foo() {
+ System.out.println("hello");
+ }
+
+ public int bar = 42;
+}
diff --git a/test/999-redefine-hiddenapi/src-redefine/art/Test999.java b/test/999-redefine-hiddenapi/src-redefine/art/Test999.java
new file mode 100644
index 0000000000..c1b838ccc7
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src-redefine/art/Test999.java
@@ -0,0 +1,25 @@
+/*
+ * 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 art;
+
+public class Test999 {
+ public void foo() {
+ System.out.println("Goodbye");
+ }
+
+ public int bar = 64;
+}
diff --git a/test/999-redefine-hiddenapi/src-redefine/gen.sh b/test/999-redefine-hiddenapi/src-redefine/gen.sh
new file mode 100755
index 0000000000..6948cbbfc3
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src-redefine/gen.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+set -e
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+TMP=`mktemp -d`
+
+CLASS "art/Test999"
+
+(cd "$TMP" && javac -d "${TMP}" "$DIR/${CLASS}.java" && d8 --output . "$TMP/${CLASS}.class")
+
+echo ' private static final byte[] CLASS_BYTES = Base64.getDecoder().decode('
+base64 "${TMP}/${CLASS}.class" | sed -E 's/^/ "/' | sed ':a;N;$!ba;s/\n/" +\n/g' | sed -E '$ s/$/");/'
+echo ' private static final byte[] DEX_BYTES = Base64.getDecoder().decode('
+base64 "${TMP}/classes.dex" | sed -E 's/^/ "/' | sed ':a;N;$!ba;s/\n/" +\n/g' | sed -E '$ s/$/");/'
+
+rm -rf "$TMP"
diff --git a/test/999-redefine-hiddenapi/src/Main.java b/test/999-redefine-hiddenapi/src/Main.java
new file mode 100644
index 0000000000..c6365ac234
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src/Main.java
@@ -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.
+ */
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.Base64;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+
+ // Run the initialization routine. This will enable hidden API checks in
+ // the runtime, in case they are not enabled by default.
+ init();
+
+ // Load the '-ex' APK and attach it to the boot class path.
+ appendToBootClassLoader(DEX_EXTRA);
+
+ // Find the test class in boot class loader and verify that its members are hidden.
+ Class<?> klass = Class.forName("art.Test999", true, BOOT_CLASS_LOADER);
+ assertMethodIsHidden(klass, "before redefinition");
+ assertFieldIsHidden(klass, "before redefinition");
+
+ // Redefine the class using JVMTI.
+ art.Redefinition.setTestConfiguration(art.Redefinition.Config.COMMON_REDEFINE);
+ art.Redefinition.doCommonClassRedefinition(klass, CLASS_BYTES, DEX_BYTES);
+
+ // Verify that the class members are still hidden.
+ assertMethodIsHidden(klass, "after redefinition");
+ assertFieldIsHidden(klass, "after redefinition");
+ }
+
+ private static void assertMethodIsHidden(Class<?> klass, String msg) throws Exception {
+ try {
+ klass.getDeclaredMethod("foo");
+ // Unexpected. Should have thrown NoSuchMethodException.
+ throw new Exception("Method should not be accessible " + msg);
+ } catch (NoSuchMethodException ex) {
+ // Expected.
+ }
+ }
+
+ private static void assertFieldIsHidden(Class<?> klass, String msg) throws Exception {
+ try {
+ klass.getDeclaredField("bar");
+ // Unexpected. Should have thrown NoSuchFieldException.
+ throw new Exception("Field should not be accessible " + msg);
+ } catch (NoSuchFieldException ex) {
+ // Expected.
+ }
+ }
+
+ private static final String DEX_EXTRA =
+ new File(System.getenv("DEX_LOCATION"), "999-redefine-hiddenapi-ex.jar").getAbsolutePath();
+
+ private static ClassLoader BOOT_CLASS_LOADER = Object.class.getClassLoader();
+
+ // Native functions. Note that these are implemented in 674-hiddenapi/hiddenapi.cc.
+ private static native void appendToBootClassLoader(String dexPath);
+ private static native void init();
+
+ /**
+ * base64 encoded class/dex file for
+ *
+ * public class Test999 {
+ * public void foo() {
+ * System.out.println("Goodbye");
+ * }
+ *
+ * public int bar = 64;
+ * }
+ */
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADUAIAoABwARCQAGABIJABMAFAgAFQoAFgAXBwAYBwAZAQADYmFyAQABSQEABjxpbml0" +
+ "PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAANmb28BAApTb3VyY2VGaWxlAQAMVGVz" +
+ "dDk5OS5qYXZhDAAKAAsMAAgACQcAGgwAGwAcAQAHR29vZGJ5ZQcAHQwAHgAfAQALYXJ0L1Rlc3Q5" +
+ "OTkBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lv" +
+ "L1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xh" +
+ "bmcvU3RyaW5nOylWACEABgAHAAAAAQABAAgACQAAAAIAAQAKAAsAAQAMAAAAJwACAAEAAAALKrcA" +
+ "ASoQQLUAArEAAAABAA0AAAAKAAIAAAATAAQAGAABAA4ACwABAAwAAAAlAAIAAQAAAAmyAAMSBLYA" +
+ "BbEAAAABAA0AAAAKAAIAAAAVAAgAFgABAA8AAAACABA=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQD0dZ+IWxOi+cJDSWjfTnUerlZj1Lll3ONIAwAAcAAAAHhWNBIAAAAAAAAAAJwCAAAQ" +
+ "AAAAcAAAAAcAAACwAAAAAgAAAMwAAAACAAAA5AAAAAQAAAD0AAAAAQAAABQBAAAUAgAANAEAAIYB" +
+ "AACOAQAAlwEAAJoBAACpAQAAwAEAANQBAADoAQAA/AEAAAoCAAANAgAAEQIAABYCAAAbAgAAIAIA" +
+ "ACkCAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAJAAAACQAAAAYAAAAAAAAACgAAAAYAAACAAQAA" +
+ "AQAAAAsAAAAFAAIADQAAAAEAAAAAAAAAAQAAAAwAAAACAAEADgAAAAMAAAAAAAAAAQAAAAEAAAAD" +
+ "AAAAAAAAAAgAAAAAAAAAhwIAAAAAAAACAAEAAQAAAHQBAAAIAAAAcBADAAEAEwBAAFkQAAAOAAMA" +
+ "AQACAAAAeQEAAAgAAABiAAEAGgEBAG4gAgAQAA4AEwAOQAAVAA54AAAAAQAAAAQABjxpbml0PgAH" +
+ "R29vZGJ5ZQABSQANTGFydC9UZXN0OTk5OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9s" +
+ "YW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AAxUZXN0" +
+ "OTk5LmphdmEAAVYAAlZMAANiYXIAA2ZvbwADb3V0AAdwcmludGxuAFx+fkQ4eyJtaW4tYXBpIjox" +
+ "LCJzaGEtMSI6IjU2YzJlMzBmNTIzM2I4NDRmZjZkZGQ4N2ZiNTNkMzRmYjE3MjM3ZGYiLCJ2ZXJz" +
+ "aW9uIjoidjEuMi4xNS1kZXYifQAAAQEBAAEAgYAEtAIBAdQCAAAAAAAOAAAAAAAAAAEAAAAAAAAA" +
+ "AQAAABAAAABwAAAAAgAAAAcAAACwAAAAAwAAAAIAAADMAAAABAAAAAIAAADkAAAABQAAAAQAAAD0" +
+ "AAAABgAAAAEAAAAUAQAAASAAAAIAAAA0AQAAAyAAAAIAAAB0AQAAARAAAAEAAACAAQAAAiAAABAA" +
+ "AACGAQAAACAAAAEAAACHAgAAAxAAAAEAAACYAgAAABAAAAEAAACcAgAA");
+}
diff --git a/test/999-redefine-hiddenapi/src/art/Redefinition.java b/test/999-redefine-hiddenapi/src/art/Redefinition.java
new file mode 100644
index 0000000000..1eec70b48c
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src/art/Redefinition.java
@@ -0,0 +1,91 @@
+/*
+ * 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 art;
+
+import java.util.ArrayList;
+// Common Redefinition functions. Placed here for use by CTS
+public class Redefinition {
+ public static final class CommonClassDefinition {
+ public final Class<?> target;
+ public final byte[] class_file_bytes;
+ public final byte[] dex_file_bytes;
+
+ public CommonClassDefinition(Class<?> target, byte[] class_file_bytes, byte[] dex_file_bytes) {
+ this.target = target;
+ this.class_file_bytes = class_file_bytes;
+ this.dex_file_bytes = dex_file_bytes;
+ }
+ }
+
+ // A set of possible test configurations. Test should set this if they need to.
+ // This must be kept in sync with the defines in ti-agent/common_helper.cc
+ public static enum Config {
+ COMMON_REDEFINE(0),
+ COMMON_RETRANSFORM(1),
+ COMMON_TRANSFORM(2);
+
+ private final int val;
+ private Config(int val) {
+ this.val = val;
+ }
+ }
+
+ public static void setTestConfiguration(Config type) {
+ nativeSetTestConfiguration(type.val);
+ }
+
+ private static native void nativeSetTestConfiguration(int type);
+
+ // Transforms the class
+ public static native void doCommonClassRedefinition(Class<?> target,
+ byte[] classfile,
+ byte[] dexfile);
+
+ public static void doMultiClassRedefinition(CommonClassDefinition... defs) {
+ ArrayList<Class<?>> classes = new ArrayList<>();
+ ArrayList<byte[]> class_files = new ArrayList<>();
+ ArrayList<byte[]> dex_files = new ArrayList<>();
+
+ for (CommonClassDefinition d : defs) {
+ classes.add(d.target);
+ class_files.add(d.class_file_bytes);
+ dex_files.add(d.dex_file_bytes);
+ }
+ doCommonMultiClassRedefinition(classes.toArray(new Class<?>[0]),
+ class_files.toArray(new byte[0][]),
+ dex_files.toArray(new byte[0][]));
+ }
+
+ public static void addMultiTransformationResults(CommonClassDefinition... defs) {
+ for (CommonClassDefinition d : defs) {
+ addCommonTransformationResult(d.target.getCanonicalName(),
+ d.class_file_bytes,
+ d.dex_file_bytes);
+ }
+ }
+
+ public static native void doCommonMultiClassRedefinition(Class<?>[] targets,
+ byte[][] classfiles,
+ byte[][] dexfiles);
+ public static native void doCommonClassRetransformation(Class<?>... target);
+ public static native void setPopRetransformations(boolean pop);
+ public static native void popTransformationFor(String name);
+ public static native void enableCommonRetransformation(boolean enable);
+ public static native void addCommonTransformationResult(String target_name,
+ byte[] class_bytes,
+ byte[] dex_bytes);
+}
diff --git a/test/Android.bp b/test/Android.bp
index 76189f62a9..84f2e224d5 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -370,22 +370,27 @@ cc_library_static {
}
art_cc_defaults {
- name: "libtistress-defaults",
+ name: "libtistress-srcs",
defaults: ["libartagent-defaults"],
srcs: [
"ti-stress/stress.cc",
],
+ header_libs: ["libopenjdkjvmti_headers"],
+}
+
+art_cc_defaults {
+ name: "libtistress-defaults",
+ defaults: ["libtistress-srcs"],
shared_libs: [
"libbase",
"slicer",
],
- header_libs: ["libopenjdkjvmti_headers"],
}
art_cc_test_library {
name: "libtistress",
defaults: ["libtistress-defaults"],
- shared_libs: ["libart"],
+ shared_libs: ["libartbase"],
}
art_cc_test_library {
@@ -394,7 +399,30 @@ art_cc_test_library {
"art_debug_defaults",
"libtistress-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: ["libartbased"],
+}
+
+art_cc_defaults {
+ name: "libtistress-static-defaults",
+ defaults: ["libtistress-srcs"],
+ static_libs: art_static_dependencies + [
+ "slicer",
+ ],
+}
+
+art_cc_test_library {
+ name: "libtistresss",
+ defaults: ["libtistress-static-defaults"],
+ static_libs: ["libartbase"],
+}
+
+art_cc_test_library {
+ name: "libtistressds",
+ defaults: [
+ "art_debug_defaults",
+ "libtistress-static-defaults"
+ ],
+ static_libs: ["libartbased"],
}
cc_defaults {
diff --git a/test/etc/default-build b/test/etc/default-build
index 8bb898c7c1..c61de0ab6e 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -561,6 +561,11 @@ fi
if [[ -d classes-ex ]] && [ ${NEED_DEX} = "true" ]; then
make_dex classes-ex
+ # Apply hiddenapi on the dex files if the test has API list file(s).
+ if [ ${USE_HIDDENAPI} = "true" -a ${HAS_HIDDENAPI_SPEC} = "true" ]; then
+ make_hiddenapi classes-ex.dex
+ fi
+
# quick shuffle so that the stored name is "classes.dex"
mv classes.dex classes-1.dex
mv classes-ex.dex classes.dex
diff --git a/test/knownfailures.json b/test/knownfailures.json
index f473a99a27..a202044786 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -454,7 +454,8 @@
"674-hiddenapi",
"649-vdex-duplicate-method",
"804-class-extends-itself",
- "921-hello-failure"
+ "921-hello-failure",
+ "999-redefine-hiddenapi"
],
"description": [
"Tests that use illegal dex files or otherwise break dexter assumptions"
@@ -471,7 +472,8 @@
"629-vdex-speed",
"647-jni-get-field-id",
"674-hiddenapi",
- "944-transform-classloaders"
+ "944-transform-classloaders",
+ "999-redefine-hiddenapi"
],
"description": [
"Tests that use custom class loaders or other features not supported ",
@@ -876,7 +878,6 @@
"667-jit-jni-stub",
"667-out-of-bounds",
"668-aiobe",
- "674-hiddenapi",
"674-hotness-compiled",
"674-vdex-uncompress",
"675-checker-unverified-method",
@@ -954,8 +955,10 @@
},
{
"tests": ["616-cha-unloading",
+ "674-hiddenapi",
"678-quickening",
- "679-locks"],
+ "679-locks",
+ "999-redefine-hiddenapi"],
"variant": "jvm",
"description": ["Doesn't run on RI."]
},
diff --git a/test/ti-stress/stress.cc b/test/ti-stress/stress.cc
index bbe74656dd..0eba7426c0 100644
--- a/test/ti-stress/stress.cc
+++ b/test/ti-stress/stress.cc
@@ -25,7 +25,6 @@
#include <jni.h>
#include "base/utils.h"
-#include "exec_utils.h"
#include "jvmti.h"
#pragma clang diagnostic push
@@ -920,4 +919,8 @@ extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm,
return 0;
}
+extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char* options, void* reserved) {
+ return Agent_OnLoad(vm, options, reserved);
+}
+
} // namespace art
diff --git a/tools/dexanalyze/dexanalyze.cc b/tools/dexanalyze/dexanalyze.cc
index a5f647cc56..c4aebc6f56 100644
--- a/tools/dexanalyze/dexanalyze.cc
+++ b/tools/dexanalyze/dexanalyze.cc
@@ -15,6 +15,7 @@
*/
#include <cstdint>
+#include <iostream>
#include <set>
#include <sstream>
@@ -31,6 +32,15 @@ namespace art {
class DexAnalyze {
static const int kExitCodeUsageError = 1;
+ static void StdoutLogger(android::base::LogId,
+ android::base::LogSeverity,
+ const char*,
+ const char*,
+ unsigned int,
+ const char* message) {
+ std::cout << message << std::endl;
+ }
+
static int Usage(char** argv) {
LOG(ERROR)
<< "Usage " << argv[0] << " [options] <dex files>\n"
@@ -105,6 +115,8 @@ class DexAnalyze {
public:
static int Run(int argc, char** argv) {
+ android::base::SetLogger(StdoutLogger);
+
Options options;
int result = options.Parse(argc, argv);
if (result != 0) {
@@ -154,7 +166,6 @@ class DexAnalyze {
} // namespace art
int main(int argc, char** argv) {
- android::base::SetLogger(android::base::StderrLogger);
return art::DexAnalyze::Run(argc, argv);
}