Add abstraction for uint32_t string index.
Test: m test-art-host
Change-Id: I917c2881702fe3df112c713f06980f2278ced7ed
return target_dex_file_;
}
- uint32_t TargetStringIndex() const {
+ dex::StringIndex TargetStringIndex() const {
DCHECK(patch_type_ == Type::kString ||
patch_type_ == Type::kStringRelative ||
patch_type_ == Type::kStringBssEntry);
- return string_idx_;
+ return dex::StringIndex(string_idx_);
}
const DexFile* TargetDexCacheDexFile() const {
uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
for (uint32_t i = 0; i < parameters_size; ++i) {
uint32_t id = DecodeUnsignedLeb128P1(&stream);
- names.push_back(mi->dex_file->StringDataByIdx(id));
+ names.push_back(mi->dex_file->StringDataByIdx(dex::StringIndex(id)));
}
}
}
switch (inst->Opcode()) {
case Instruction::CONST_STRING:
case Instruction::CONST_STRING_JUMBO: {
- uint32_t string_index = (inst->Opcode() == Instruction::CONST_STRING)
+ dex::StringIndex string_index((inst->Opcode() == Instruction::CONST_STRING)
? inst->VRegB_21c()
- : inst->VRegB_31c();
+ : inst->VRegB_31c());
mirror::String* string = class_linker->ResolveString(dex_file, string_index, dex_cache);
CHECK(string != nullptr) << "Could not allocate a string when forcing determinism";
break;
ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(soa.Self(), dex);
EXPECT_EQ(dex.NumStringIds(), dex_cache->NumStrings());
for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
- const mirror::String* string = dex_cache->GetResolvedString(i);
+ const mirror::String* string = dex_cache->GetResolvedString(dex::StringIndex(i));
EXPECT_TRUE(string != nullptr) << "string_idx=" << i;
}
EXPECT_EQ(dex.NumTypeIds(), dex_cache->NumResolvedTypes());
InternTable* const intern_table = runtime->GetInternTable();
for (size_t i = 0, count = dex_file->NumStringIds(); i < count; ++i) {
uint32_t utf16_length;
- const char* utf8_data = dex_file->StringDataAndUtf16LengthByIdx(i, &utf16_length);
+ const char* utf8_data = dex_file->StringDataAndUtf16LengthByIdx(dex::StringIndex(i),
+ &utf16_length);
mirror::String* string = intern_table->LookupStrong(self, utf16_length, utf8_data).Ptr();
TryAssignBinSlot(work_stack, string, oat_index);
}
offset + patch.LiteralOffset(),
target_offset);
} else if (patch.GetType() == LinkerPatch::Type::kStringRelative) {
- uint32_t target_offset = string_index_to_offset_map_.Get(patch.TargetStringIndex());
+ uint32_t target_offset =
+ string_index_to_offset_map_.Get(patch.TargetStringIndex().index_);
patcher_->PatchPcRelativeReference(&patched_code_,
patch,
offset + patch.LiteralOffset(),
LocationSummary* locations = instruction_->GetLocations();
DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
HLoadString* load = instruction_->AsLoadString();
- const uint32_t string_index = load->GetStringIndex();
+ const uint32_t string_index = load->GetStringIndex().index_;
Register out = locations->Out().AsRegister<Register>();
Register temp = locations->GetTemp(0).AsRegister<Register>();
constexpr bool call_saves_everything_except_r0 = (!kUseReadBarrier || kUseBakerReadBarrier);
case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorARM::PcRelativePatchInfo* labels =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex().index_);
__ BindTrackedLabel(&labels->movw_label);
__ movw(out, /* placeholder */ 0u);
__ BindTrackedLabel(&labels->movt_label);
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
Register temp = locations->GetTemp(0).AsRegister<Register>();
CodeGeneratorARM::PcRelativePatchInfo* labels =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex().index_);
__ BindTrackedLabel(&labels->movw_label);
__ movw(temp, /* placeholder */ 0u);
__ BindTrackedLabel(&labels->movt_label);
DCHECK(load_kind == HLoadString::LoadKind::kDexCacheViaMethod);
InvokeRuntimeCallingConvention calling_convention;
DCHECK_EQ(calling_convention.GetRegisterAt(0), out);
- __ LoadImmediate(calling_convention.GetRegisterAt(0), load->GetStringIndex());
+ __ LoadImmediate(calling_convention.GetRegisterAt(0), load->GetStringIndex().index_);
codegen_->InvokeRuntime(kQuickResolveString, load, load->GetDexPc());
CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
}
}
Literal* CodeGeneratorARM::DeduplicateBootImageStringLiteral(const DexFile& dex_file,
- uint32_t string_index) {
+ dex::StringIndex string_index) {
return boot_image_string_patches_.GetOrCreate(
StringReference(&dex_file, string_index),
[this]() { return __ NewLiteral<uint32_t>(/* placeholder */ 0u); });
}
Literal* CodeGeneratorARM::DeduplicateJitStringLiteral(const DexFile& dex_file,
- uint32_t string_index) {
+ dex::StringIndex string_index) {
jit_string_roots_.Overwrite(StringReference(&dex_file, string_index), /* placeholder */ 0u);
return jit_string_patches_.GetOrCreate(
StringReference(&dex_file, string_index),
uint32_t literal_offset = literal->GetLabel()->Position();
linker_patches->push_back(LinkerPatch::StringPatch(literal_offset,
target_string.dex_file,
- target_string.string_index));
+ target_string.string_index.index_));
}
if (!GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(pc_relative_string_patches_,
PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
uint32_t element_offset);
- Literal* DeduplicateBootImageStringLiteral(const DexFile& dex_file, uint32_t string_index);
+ Literal* DeduplicateBootImageStringLiteral(const DexFile& dex_file,
+ dex::StringIndex string_index);
Literal* DeduplicateBootImageTypeLiteral(const DexFile& dex_file, dex::TypeIndex type_index);
Literal* DeduplicateBootImageAddressLiteral(uint32_t address);
Literal* DeduplicateDexCacheAddressLiteral(uint32_t address);
- Literal* DeduplicateJitStringLiteral(const DexFile& dex_file, uint32_t string_index);
+ Literal* DeduplicateJitStringLiteral(const DexFile& dex_file, dex::StringIndex string_index);
void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE;
SaveLiveRegisters(codegen, locations);
InvokeRuntimeCallingConvention calling_convention;
- const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex();
+ const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex().index_;
__ Mov(calling_convention.GetRegisterAt(0).W(), string_index);
arm64_codegen->InvokeRuntime(kQuickResolveString, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
}
vixl::aarch64::Literal<uint32_t>* CodeGeneratorARM64::DeduplicateBootImageStringLiteral(
- const DexFile& dex_file, uint32_t string_index) {
+ const DexFile& dex_file, dex::StringIndex string_index) {
return boot_image_string_patches_.GetOrCreate(
StringReference(&dex_file, string_index),
[this]() { return __ CreateLiteralDestroyedWithPool<uint32_t>(/* placeholder */ 0u); });
}
vixl::aarch64::Literal<uint32_t>* CodeGeneratorARM64::DeduplicateJitStringLiteral(
- const DexFile& dex_file, uint32_t string_index) {
+ const DexFile& dex_file, dex::StringIndex string_index) {
jit_string_roots_.Overwrite(StringReference(&dex_file, string_index), /* placeholder */ 0u);
return jit_string_patches_.GetOrCreate(
StringReference(&dex_file, string_index),
vixl::aarch64::Literal<uint32_t>* literal = entry.second;
linker_patches->push_back(LinkerPatch::StringPatch(literal->GetOffset(),
target_string.dex_file,
- target_string.string_index));
+ target_string.string_index.index_));
}
if (!GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(pc_relative_string_patches_,
case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
// Add ADRP with its PC-relative String patch.
const DexFile& dex_file = load->GetDexFile();
- uint32_t string_index = load->GetStringIndex();
+ uint32_t string_index = load->GetStringIndex().index_;
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
vixl::aarch64::Label* adrp_label = codegen_->NewPcRelativeStringPatch(dex_file, string_index);
codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
case HLoadString::LoadKind::kBssEntry: {
// Add ADRP with its PC-relative String .bss entry patch.
const DexFile& dex_file = load->GetDexFile();
- uint32_t string_index = load->GetStringIndex();
+ uint32_t string_index = load->GetStringIndex().index_;
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
UseScratchRegisterScope temps(codegen_->GetVIXLAssembler());
Register temp = temps.AcquireX();
// TODO: Re-add the compiler code to do string dex cache lookup again.
InvokeRuntimeCallingConvention calling_convention;
DCHECK_EQ(calling_convention.GetRegisterAt(0).GetCode(), out.GetCode());
- __ Mov(calling_convention.GetRegisterAt(0).W(), load->GetStringIndex());
+ __ Mov(calling_convention.GetRegisterAt(0).W(), load->GetStringIndex().index_);
codegen_->InvokeRuntime(kQuickResolveString, load, load->GetDexPc());
CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
}
uint32_t element_offset,
vixl::aarch64::Label* adrp_label = nullptr);
- vixl::aarch64::Literal<uint32_t>* DeduplicateBootImageStringLiteral(const DexFile& dex_file,
- uint32_t string_index);
+ vixl::aarch64::Literal<uint32_t>* DeduplicateBootImageStringLiteral(
+ const DexFile& dex_file,
+ dex::StringIndex string_index);
vixl::aarch64::Literal<uint32_t>* DeduplicateBootImageTypeLiteral(const DexFile& dex_file,
dex::TypeIndex type_index);
vixl::aarch64::Literal<uint32_t>* DeduplicateBootImageAddressLiteral(uint64_t address);
vixl::aarch64::Literal<uint64_t>* DeduplicateDexCacheAddressLiteral(uint64_t address);
vixl::aarch64::Literal<uint32_t>* DeduplicateJitStringLiteral(const DexFile& dex_file,
- uint32_t string_index);
+ dex::StringIndex string_index);
void EmitAdrpPlaceholder(vixl::aarch64::Label* fixup_label, vixl::aarch64::Register reg);
void EmitAddPlaceholder(vixl::aarch64::Label* fixup_label,
// TODO: Re-add the compiler code to do string dex cache lookup again.
DCHECK_EQ(load->GetLoadKind(), HLoadString::LoadKind::kDexCacheViaMethod);
InvokeRuntimeCallingConventionARMVIXL calling_convention;
- __ Mov(calling_convention.GetRegisterAt(0), load->GetStringIndex());
+ __ Mov(calling_convention.GetRegisterAt(0), load->GetStringIndex().index_);
codegen_->InvokeRuntime(kQuickResolveString, load, load->GetDexPc());
CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
}
InvokeRuntimeCallingConvention calling_convention;
HLoadString* load = instruction_->AsLoadString();
- const uint32_t string_index = load->GetStringIndex();
+ const uint32_t string_index = load->GetStringIndex().index_;
__ LoadConst32(calling_convention.GetRegisterAt(0), string_index);
mips_codegen->InvokeRuntime(kQuickResolveString, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
uint32_t literal_offset = __ GetLabelLocation(literal->GetLabel());
linker_patches->push_back(LinkerPatch::StringPatch(literal_offset,
target_string.dex_file,
- target_string.string_index));
+ target_string.string_index.index_));
}
for (const auto& entry : boot_image_type_patches_) {
const TypeReference& target_type = entry.first;
}
Literal* CodeGeneratorMIPS::DeduplicateBootImageStringLiteral(const DexFile& dex_file,
- uint32_t string_index) {
+ dex::StringIndex string_index) {
return boot_image_string_patches_.GetOrCreate(
StringReference(&dex_file, string_index),
[this]() { return __ NewLiteral<uint32_t>(/* placeholder */ 0u); });
DCHECK(!kEmitCompilerReadBarrier);
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorMIPS::PcRelativePatchInfo* info =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex().index_);
codegen_->EmitPcRelativeAddressPlaceholder(info, out, base_or_current_method_reg);
return; // No dex cache slow path.
}
case HLoadString::LoadKind::kBssEntry: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorMIPS::PcRelativePatchInfo* info =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex().index_);
codegen_->EmitPcRelativeAddressPlaceholder(info, out, base_or_current_method_reg);
__ LoadFromOffset(kLoadWord, out, out, 0);
SlowPathCodeMIPS* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathMIPS(load);
// TODO: Re-add the compiler code to do string dex cache lookup again.
DCHECK(load_kind == HLoadString::LoadKind::kDexCacheViaMethod);
InvokeRuntimeCallingConvention calling_convention;
- __ LoadConst32(calling_convention.GetRegisterAt(0), load->GetStringIndex());
+ __ LoadConst32(calling_convention.GetRegisterAt(0), load->GetStringIndex().index_);
codegen_->InvokeRuntime(kQuickResolveString, load, load->GetDexPc());
CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
}
#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS_H_
#include "code_generator.h"
+#include "dex_file_types.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "parallel_move_resolver.h"
PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
uint32_t element_offset);
- Literal* DeduplicateBootImageStringLiteral(const DexFile& dex_file, uint32_t string_index);
+ Literal* DeduplicateBootImageStringLiteral(const DexFile& dex_file,
+ dex::StringIndex string_index);
Literal* DeduplicateBootImageTypeLiteral(const DexFile& dex_file, dex::TypeIndex type_index);
Literal* DeduplicateBootImageAddressLiteral(uint32_t address);
SaveLiveRegisters(codegen, locations);
InvokeRuntimeCallingConvention calling_convention;
- const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex();
+ const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex().index_;
__ LoadConst32(calling_convention.GetRegisterAt(0), string_index);
mips64_codegen->InvokeRuntime(kQuickResolveString,
instruction_,
SaveLiveRegisters(codegen, locations);
InvokeRuntimeCallingConvention calling_convention;
- const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex();
+ const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex().index_;
__ movl(calling_convention.GetRegisterAt(0), Immediate(string_index));
x86_codegen->InvokeRuntime(kQuickResolveString, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
void CodeGeneratorX86::RecordBootStringPatch(HLoadString* load_string) {
DCHECK(GetCompilerOptions().IsBootImage());
- string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex());
+ string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex().index_);
__ Bind(&string_patches_.back().label);
}
Label* CodeGeneratorX86::NewStringBssEntryPatch(HLoadString* load_string) {
DCHECK(!GetCompilerOptions().IsBootImage());
- string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex());
+ string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex().index_);
return &string_patches_.back().label;
}
}
}
-Label* CodeGeneratorX86::NewJitRootStringPatch(const DexFile& dex_file, uint32_t dex_index) {
+Label* CodeGeneratorX86::NewJitRootStringPatch(const DexFile& dex_file,
+ dex::StringIndex dex_index) {
jit_string_roots_.Overwrite(StringReference(&dex_file, dex_index), /* placeholder */ 0u);
// Add a patch entry and return the label.
- jit_string_patches_.emplace_back(dex_file, dex_index);
+ jit_string_patches_.emplace_back(dex_file, dex_index.index_);
PatchInfo<Label>* info = &jit_string_patches_.back();
return &info->label;
}
// TODO: Re-add the compiler code to do string dex cache lookup again.
InvokeRuntimeCallingConvention calling_convention;
DCHECK_EQ(calling_convention.GetRegisterAt(0), out);
- __ movl(calling_convention.GetRegisterAt(0), Immediate(load->GetStringIndex()));
+ __ movl(calling_convention.GetRegisterAt(0), Immediate(load->GetStringIndex().index_));
codegen_->InvokeRuntime(kQuickResolveString, load, load->GetDexPc());
CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
}
void CodeGeneratorX86::EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) {
for (const PatchInfo<Label>& info : jit_string_patches_) {
- const auto& it = jit_string_roots_.find(StringReference(&info.dex_file, info.index));
+ const auto& it = jit_string_roots_.find(StringReference(&info.dex_file,
+ dex::StringIndex(info.index)));
DCHECK(it != jit_string_roots_.end());
size_t index_in_table = it->second;
uint32_t code_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
#include "arch/x86/instruction_set_features_x86.h"
#include "base/enums.h"
#include "code_generator.h"
+#include "dex_file_types.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "parallel_move_resolver.h"
void RecordTypePatch(HLoadClass* load_class);
Label* NewStringBssEntryPatch(HLoadString* load_string);
Label* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file, uint32_t element_offset);
- Label* NewJitRootStringPatch(const DexFile& dex_file, uint32_t dex_index);
+ Label* NewJitRootStringPatch(const DexFile& dex_file, dex::StringIndex dex_index);
void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE;
__ Bind(GetEntryLabel());
SaveLiveRegisters(codegen, locations);
- const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex();
+ const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex().index_;
// Custom calling convention: RAX serves as both input and output.
__ movl(CpuRegister(RAX), Immediate(string_index));
x86_64_codegen->InvokeRuntime(kQuickResolveString,
void CodeGeneratorX86_64::RecordBootStringPatch(HLoadString* load_string) {
DCHECK(GetCompilerOptions().IsBootImage());
- string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex());
+ string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex().index_);
__ Bind(&string_patches_.back().label);
}
Label* CodeGeneratorX86_64::NewStringBssEntryPatch(HLoadString* load_string) {
DCHECK(!GetCompilerOptions().IsBootImage());
- string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex());
+ string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex().index_);
return &string_patches_.back().label;
}
}
}
-Label* CodeGeneratorX86_64::NewJitRootStringPatch(const DexFile& dex_file, uint32_t dex_index) {
+Label* CodeGeneratorX86_64::NewJitRootStringPatch(const DexFile& dex_file,
+ dex::StringIndex dex_index) {
jit_string_roots_.Overwrite(StringReference(&dex_file, dex_index), /* placeholder */ 0u);
// Add a patch entry and return the label.
- jit_string_patches_.emplace_back(dex_file, dex_index);
+ jit_string_patches_.emplace_back(dex_file, dex_index.index_);
PatchInfo<Label>* info = &jit_string_patches_.back();
return &info->label;
}
// TODO: Re-add the compiler code to do string dex cache lookup again.
// Custom calling convention: RAX serves as both input and output.
- __ movl(CpuRegister(RAX), Immediate(load->GetStringIndex()));
+ __ movl(CpuRegister(RAX), Immediate(load->GetStringIndex().index_));
codegen_->InvokeRuntime(kQuickResolveString,
load,
load->GetDexPc());
void CodeGeneratorX86_64::EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) {
for (const PatchInfo<Label>& info : jit_string_patches_) {
- const auto& it = jit_string_roots_.find(StringReference(&info.dex_file, info.index));
+ const auto& it = jit_string_roots_.find(StringReference(&info.dex_file,
+ dex::StringIndex(info.index)));
DCHECK(it != jit_string_roots_.end());
size_t index_in_table = it->second;
uint32_t code_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
void RecordTypePatch(HLoadClass* load_class);
Label* NewStringBssEntryPatch(HLoadString* load_string);
Label* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file, uint32_t element_offset);
- Label* NewJitRootStringPatch(const DexFile& dex_file, uint32_t dex_index);
+ Label* NewJitRootStringPatch(const DexFile& dex_file, dex::StringIndex dex_index);
void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE;
}
case Instruction::CONST_STRING: {
- uint32_t string_index = instruction.VRegB_21c();
+ dex::StringIndex string_index(instruction.VRegB_21c());
AppendInstruction(
new (arena_) HLoadString(graph_->GetCurrentMethod(), string_index, *dex_file_, dex_pc));
UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
}
case Instruction::CONST_STRING_JUMBO: {
- uint32_t string_index = instruction.VRegB_31c();
+ dex::StringIndex string_index(instruction.VRegB_31c());
AppendInstruction(
new (arena_) HLoadString(graph_->GetCurrentMethod(), string_index, *dex_file_, dex_pc));
UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction());
};
HLoadString(HCurrentMethod* current_method,
- uint32_t string_index,
+ dex::StringIndex string_index,
const DexFile& dex_file,
uint32_t dex_pc)
: HInstruction(SideEffectsForArchRuntimeCalls(), dex_pc),
void SetLoadKindWithStringReference(LoadKind load_kind,
const DexFile& dex_file,
- uint32_t string_index) {
+ dex::StringIndex string_index) {
DCHECK(HasStringReference(load_kind));
load_data_.dex_file_ = &dex_file;
string_index_ = string_index;
const DexFile& GetDexFile() const;
- uint32_t GetStringIndex() const {
+ dex::StringIndex GetStringIndex() const {
DCHECK(HasStringReference(GetLoadKind()) || /* For slow paths. */ !IsInDexCache());
return string_index_;
}
bool InstructionDataEquals(const HInstruction* other) const OVERRIDE;
- size_t ComputeHashCode() const OVERRIDE { return string_index_; }
+ size_t ComputeHashCode() const OVERRIDE { return string_index_.index_; }
// Will call the runtime if we need to load the string through
// the dex cache and the string is not guaranteed to be there yet.
// String index serves also as the hash code and it's also needed for slow-paths,
// so it must not be overwritten with other load data.
- uint32_t string_index_;
+ dex::StringIndex string_index_;
union {
const DexFile* dex_file_; // For string reference.
DCHECK(!load_string->IsInDexCache());
const DexFile& dex_file = load_string->GetDexFile();
- uint32_t string_index = load_string->GetStringIndex();
+ dex::StringIndex string_index = load_string->GetStringIndex();
HLoadString::LoadKind desired_load_kind = HLoadString::LoadKind::kDexCacheViaMethod;
uint64_t address = 0u; // String or dex cache element address.
#include <memory>
+#include "dex_file_types.h"
#include "gtest/gtest.h"
#include "utils/test_dex_file_builder.h"
builder1.AddString("String1");
std::unique_ptr<const DexFile> dex_file1 = builder1.Build("dummy location 1");
ASSERT_EQ(1u, dex_file1->NumStringIds());
- ASSERT_STREQ("String1", dex_file1->GetStringData(dex_file1->GetStringId(0)));
- StringReference sr1(dex_file1.get(), 0);
+ ASSERT_STREQ("String1", dex_file1->GetStringData(dex_file1->GetStringId(dex::StringIndex(0))));
+ StringReference sr1(dex_file1.get(), dex::StringIndex(0));
TestDexFileBuilder builder2;
builder2.AddString("String2");
std::unique_ptr<const DexFile> dex_file2 = builder2.Build("dummy location 2");
ASSERT_EQ(1u, dex_file2->NumStringIds());
- ASSERT_STREQ("String2", dex_file2->GetStringData(dex_file2->GetStringId(0)));
- StringReference sr2(dex_file2.get(), 0);
+ ASSERT_STREQ("String2", dex_file2->GetStringData(dex_file2->GetStringId(dex::StringIndex(0))));
+ StringReference sr2(dex_file2.get(), dex::StringIndex(0));
StringReferenceValueComparator cmp;
EXPECT_TRUE(cmp(sr1, sr2)); // "String1" < "String2" is true.
std::unique_ptr<const DexFile> dex_file1 = builder1.Build("dummy location 1");
ASSERT_EQ(arraysize(kDexFile1Strings), dex_file1->NumStringIds());
for (size_t index = 0; index != arraysize(kDexFile1Strings); ++index) {
- ASSERT_STREQ(kDexFile1Strings[index], dex_file1->GetStringData(dex_file1->GetStringId(index)));
+ ASSERT_STREQ(kDexFile1Strings[index],
+ dex_file1->GetStringData(dex_file1->GetStringId(dex::StringIndex(index))));
}
TestDexFileBuilder builder2;
std::unique_ptr<const DexFile> dex_file2 = builder2.Build("dummy location 1");
ASSERT_EQ(arraysize(kDexFile2Strings), dex_file2->NumStringIds());
for (size_t index = 0; index != arraysize(kDexFile2Strings); ++index) {
- ASSERT_STREQ(kDexFile2Strings[index], dex_file2->GetStringData(dex_file2->GetStringId(index)));
+ ASSERT_STREQ(kDexFile2Strings[index],
+ dex_file2->GetStringData(dex_file2->GetStringId(dex::StringIndex(index))));
}
StringReferenceValueComparator cmp;
for (size_t index1 = 0; index1 != arraysize(kDexFile1Strings); ++index1) {
for (size_t index2 = 0; index2 != arraysize(kDexFile2Strings); ++index2) {
- StringReference sr1(dex_file1.get(), index1);
- StringReference sr2(dex_file2.get(), index2);
+ StringReference sr1(dex_file1.get(), dex::StringIndex(index1));
+ StringReference sr2(dex_file2.get(), dex::StringIndex(index2));
EXPECT_EQ(expectedCmp12[index1][index2], cmp(sr1, sr2)) << index1 << " " << index2;
EXPECT_EQ(expectedCmp21[index2][index1], cmp(sr2, sr1)) << index1 << " " << index2;
}
};
ASSERT_EQ(arraysize(expected_strings), dex_file->NumStringIds());
for (size_t i = 0; i != arraysize(expected_strings); ++i) {
- EXPECT_STREQ(expected_strings[i], dex_file->GetStringData(dex_file->GetStringId(i))) << i;
+ EXPECT_STREQ(expected_strings[i],
+ dex_file->GetStringData(dex_file->GetStringId(dex::StringIndex(i)))) << i;
}
static const char* const expected_types[] = {
ScopedObjectAccess soa(Thread::Current());
LoadDexFile(&soa);
- uint32_t id_Main1 = verifier_deps_->GetIdFromString(*primary_dex_file_, "LMain;");
- ASSERT_LT(id_Main1, primary_dex_file_->NumStringIds());
+ dex::StringIndex id_Main1 = verifier_deps_->GetIdFromString(*primary_dex_file_, "LMain;");
+ ASSERT_LT(id_Main1.index_, primary_dex_file_->NumStringIds());
ASSERT_EQ("LMain;", verifier_deps_->GetStringFromId(*primary_dex_file_, id_Main1));
- uint32_t id_Main2 = verifier_deps_->GetIdFromString(*primary_dex_file_, "LMain;");
- ASSERT_LT(id_Main2, primary_dex_file_->NumStringIds());
+ dex::StringIndex id_Main2 = verifier_deps_->GetIdFromString(*primary_dex_file_, "LMain;");
+ ASSERT_LT(id_Main2.index_, primary_dex_file_->NumStringIds());
ASSERT_EQ("LMain;", verifier_deps_->GetStringFromId(*primary_dex_file_, id_Main2));
- uint32_t id_Lorem1 = verifier_deps_->GetIdFromString(*primary_dex_file_, "Lorem ipsum");
- ASSERT_GE(id_Lorem1, primary_dex_file_->NumStringIds());
+ dex::StringIndex id_Lorem1 = verifier_deps_->GetIdFromString(*primary_dex_file_, "Lorem ipsum");
+ ASSERT_GE(id_Lorem1.index_, primary_dex_file_->NumStringIds());
ASSERT_EQ("Lorem ipsum", verifier_deps_->GetStringFromId(*primary_dex_file_, id_Lorem1));
- uint32_t id_Lorem2 = verifier_deps_->GetIdFromString(*primary_dex_file_, "Lorem ipsum");
- ASSERT_GE(id_Lorem2, primary_dex_file_->NumStringIds());
+ dex::StringIndex id_Lorem2 = verifier_deps_->GetIdFromString(*primary_dex_file_, "Lorem ipsum");
+ ASSERT_GE(id_Lorem2.index_, primary_dex_file_->NumStringIds());
ASSERT_EQ("Lorem ipsum", verifier_deps_->GetStringFromId(*primary_dex_file_, id_Lorem2));
ASSERT_EQ(id_Main1, id_Main2);
bool found = false;
for (const auto& entry : deps->fields_) {
if (!entry.IsResolved()) {
+ constexpr dex::StringIndex kStringIndexZero(0); // We know there is a class there.
deps->fields_.insert(VerifierDeps::FieldResolution(0 /* we know there is a field there */,
VerifierDeps::kUnresolvedMarker - 1,
- 0 /* we know there is a class there */));
+ kStringIndexZero));
found = true;
break;
}
VerifierDeps::DexFileDeps* deps = decoded_deps.GetDexFileDeps(*primary_dex_file_);
bool found = false;
for (const auto& entry : deps->fields_) {
- static constexpr uint32_t kNewTypeIndex = 0;
+ constexpr dex::StringIndex kNewTypeIndex(0);
if (entry.GetDeclaringClassIndex() != kNewTypeIndex) {
deps->fields_.insert(VerifierDeps::FieldResolution(entry.GetDexFieldIndex(),
entry.GetAccessFlags(),
std::set<VerifierDeps::MethodResolution>* methods = GetMethods(deps, resolution_kind);
for (const auto& entry : *methods) {
if (!entry.IsResolved()) {
+ constexpr dex::StringIndex kStringIndexZero(0); // We know there is a class there.
methods->insert(VerifierDeps::MethodResolution(0 /* we know there is a method there */,
VerifierDeps::kUnresolvedMarker - 1,
- 0 /* we know there is a class there */));
+ kStringIndexZero));
found = true;
break;
}
bool found = false;
std::set<VerifierDeps::MethodResolution>* methods = GetMethods(deps, resolution_kind);
for (const auto& entry : *methods) {
- static constexpr uint32_t kNewTypeIndex = 0;
+ constexpr dex::StringIndex kNewTypeIndex(0);
if (entry.IsResolved() && entry.GetDeclaringClassIndex() != kNewTypeIndex) {
methods->insert(VerifierDeps::MethodResolution(entry.GetDexMethodIndex(),
entry.GetAccessFlags(),
case DexFile::kDexAnnotationString: {
const u4 idx = static_cast<u4>(readVarWidth(data, arg, false));
if (gOptions.outputFormat == OUTPUT_PLAIN) {
- dumpEscapedString(pDexFile->StringDataByIdx(idx));
+ dumpEscapedString(pDexFile->StringDataByIdx(dex::StringIndex(idx)));
} else {
- dumpXmlAttribute(pDexFile->StringDataByIdx(idx));
+ dumpXmlAttribute(pDexFile->StringDataByIdx(dex::StringIndex(idx)));
}
break;
}
for (u4 i = 0; i < size; i++) {
const u4 name_idx = DecodeUnsignedLeb128(data);
fputc(' ', gOutFile);
- fputs(pDexFile->StringDataByIdx(name_idx), gOutFile);
+ fputs(pDexFile->StringDataByIdx(dex::StringIndex(name_idx)), gOutFile);
fputc('=', gOutFile);
dumpEncodedValue(pDexFile, data);
}
fprintf(gOutFile, "superclass_idx : %d\n", pClassDef.superclass_idx_.index_);
fprintf(gOutFile, "interfaces_off : %d (0x%06x)\n",
pClassDef.interfaces_off_, pClassDef.interfaces_off_);
- fprintf(gOutFile, "source_file_idx : %d\n", pClassDef.source_file_idx_);
+ fprintf(gOutFile, "source_file_idx : %d\n", pClassDef.source_file_idx_.index_);
fprintf(gOutFile, "annotations_off : %d (0x%06x)\n",
pClassDef.annotations_off_, pClassDef.annotations_off_);
fprintf(gOutFile, "class_data_off : %d (0x%06x)\n",
break;
case Instruction::kIndexStringRef:
if (index < pDexFile->GetHeader().string_ids_size_) {
- const char* st = pDexFile->StringDataByIdx(index);
+ const char* st = pDexFile->StringDataByIdx(dex::StringIndex(index));
outSize = snprintf(buf.get(), bufSize, "\"%s\" // string@%0*x", st, width, index);
} else {
outSize = snprintf(buf.get(), bufSize, "<string?> // string@%0*x", width, index);
// End of class.
if (gOptions.outputFormat == OUTPUT_PLAIN) {
const char* fileName;
- if (pClassDef.source_file_idx_ != DexFile::kDexNoIndex) {
+ if (pClassDef.source_file_idx_.IsValid()) {
fileName = pDexFile->StringDataByIdx(pClassDef.source_file_idx_);
} else {
fileName = "unknown";
}
fprintf(gOutFile, " source_file_idx : %d (%s)\n\n",
- pClassDef.source_file_idx_, fileName);
+ pClassDef.source_file_idx_.index_, fileName);
} else if (gOptions.outputFormat == OUTPUT_XML) {
fprintf(gOutFile, "</class>\n");
}
}
void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) {
- const DexFile::StringId& disk_string_id = dex_file.GetStringId(i);
+ const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i));
StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id));
string_datas_.AddItem(string_data, disk_string_id.string_data_off_);
void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i));
- TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_));
+ TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_.index_));
type_ids_.AddIndexedItem(type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i);
}
const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
- ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_),
+ ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_.index_),
GetTypeId(disk_proto_id.return_type_idx_.index_),
parameter_type_list);
proto_ids_.AddIndexedItem(proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i);
const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_.index_),
GetTypeId(disk_field_id.type_idx_.index_),
- GetStringId(disk_field_id.name_idx_));
+ GetStringId(disk_field_id.name_idx_.index_));
field_ids_.AddIndexedItem(field_id, FieldIdsOffset() + i * FieldId::ItemSize(), 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_),
- GetStringId(disk_method_id.name_idx_));
+ GetStringId(disk_method_id.name_idx_.index_));
method_ids_.AddIndexedItem(method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i);
}
const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_);
- const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_);
+ const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_);
// Annotations.
AnnotationsDirectoryItem* annotations = nullptr;
const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
const DexFile::ClassDef& pClassDef = pDexFile->GetClassDef(idx);
const char* fileName;
- if (pClassDef.source_file_idx_ == DexFile::kDexNoIndex) {
+ if (!pClassDef.source_file_idx_.IsValid()) {
fileName = nullptr;
} else {
fileName = pDexFile->StringDataByIdx(pClassDef.source_file_idx_);
const Instruction* inst = Instruction::At(code_ptr);
switch (inst->Opcode()) {
case Instruction::CONST_STRING: {
- const uint32_t string_index = inst->VRegB_21c();
+ const dex::StringIndex string_index(inst->VRegB_21c());
unique_string_ids_from_code_.insert(StringReference(&dex_file, string_index));
++num_string_ids_from_code_;
break;
}
case Instruction::CONST_STRING_JUMBO: {
- const uint32_t string_index = inst->VRegB_31c();
+ const dex::StringIndex string_index(inst->VRegB_31c());
unique_string_ids_from_code_.insert(StringReference(&dex_file, string_index));
++num_string_ids_from_code_;
break;
ObjPtr<mirror::String> ArtField::ResolveGetStringName(Thread* self,
const DexFile& dex_file,
- uint32_t string_idx,
+ dex::StringIndex string_idx,
ObjPtr<mirror::DexCache> dex_cache) {
StackHandleScope<1> hs(self);
return Runtime::Current()->GetClassLinker()->ResolveString(dex_file,
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::String> ResolveGetStringName(Thread* self,
const DexFile& dex_file,
- uint32_t string_idx,
+ dex::StringIndex string_idx,
ObjPtr<mirror::DexCache> dex_cache)
REQUIRES_SHARED(Locks::mutator_lock_);
return array_class.Ptr();
}
-inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx, ArtMethod* referrer) {
+inline mirror::String* ClassLinker::ResolveString(dex::StringIndex string_idx,
+ ArtMethod* referrer) {
Thread::PoisonObjectPointersIfDebug();
ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
// MethodVerifier refuses methods with string_idx out of bounds.
- DCHECK_LT(string_idx, declaring_class->GetDexFile().NumStringIds());
+ DCHECK_LT(string_idx.index_, declaring_class->GetDexFile().NumStringIds());
ObjPtr<mirror::String> string =
mirror::StringDexCachePair::Lookup(declaring_class->GetDexCacheStrings(),
- string_idx,
+ string_idx.index_,
mirror::DexCache::kDexCacheStringCacheSize).Read();
if (UNLIKELY(string == nullptr)) {
StackHandleScope<1> hs(Thread::Current());
}
mirror::String* ClassLinker::ResolveString(const DexFile& dex_file,
- uint32_t string_idx,
+ dex::StringIndex string_idx,
Handle<mirror::DexCache> dex_cache) {
DCHECK(dex_cache.Get() != nullptr);
Thread::PoisonObjectPointersIfDebug();
}
mirror::String* ClassLinker::LookupString(const DexFile& dex_file,
- uint32_t string_idx,
+ dex::StringIndex string_idx,
Handle<mirror::DexCache> dex_cache) {
DCHECK(dex_cache.Get() != nullptr);
ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
}
uint32_t utf16_length;
const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
- ObjPtr<mirror::String> string = intern_table_->LookupStrong(Thread::Current(), utf16_length, utf8_data);
+ ObjPtr<mirror::String> string =
+ intern_table_->LookupStrong(Thread::Current(), utf16_length, utf8_data);
if (string != nullptr) {
dex_cache->SetResolvedString(string_idx, string);
}
// Resolve a String with the given index from the DexFile, storing the
// result in the DexCache. The referrer is used to identify the
// target DexCache and ClassLoader to use for resolution.
- mirror::String* ResolveString(uint32_t string_idx, ArtMethod* referrer)
+ mirror::String* ResolveString(dex::StringIndex string_idx, ArtMethod* referrer)
REQUIRES_SHARED(Locks::mutator_lock_);
// Resolve a String with the given index from the DexFile, storing the
// result in the DexCache.
- mirror::String* ResolveString(const DexFile& dex_file, uint32_t string_idx,
+ mirror::String* ResolveString(const DexFile& dex_file,
+ dex::StringIndex string_idx,
Handle<mirror::DexCache> dex_cache)
REQUIRES_SHARED(Locks::mutator_lock_);
// Find a String with the given index from the DexFile, storing the
// result in the DexCache if found. Return null if not found.
- mirror::String* LookupString(const DexFile& dex_file, uint32_t string_idx,
+ mirror::String* LookupString(const DexFile& dex_file,
+ dex::StringIndex string_idx,
Handle<mirror::DexCache> dex_cache)
REQUIRES_SHARED(Locks::mutator_lock_);
return GetStringDataAndUtf16Length(string_id, &ignored);
}
-inline const char* DexFile::StringDataAndUtf16LengthByIdx(uint32_t idx,
+inline const char* DexFile::StringDataAndUtf16LengthByIdx(dex::StringIndex idx,
uint32_t* utf16_length) const {
- if (idx == kDexNoIndex) {
+ if (!idx.IsValid()) {
*utf16_length = 0;
return nullptr;
}
return GetStringDataAndUtf16Length(string_id, utf16_length);
}
-inline const char* DexFile::StringDataByIdx(uint32_t idx) const {
+inline const char* DexFile::StringDataByIdx(dex::StringIndex idx) const {
uint32_t unicode_length;
return StringDataAndUtf16LengthByIdx(idx, &unicode_length);
}
(RoundUp(reinterpret_cast<uintptr_t>(insns_end_), 4)) + offset;
}
-static inline bool DexFileStringEquals(const DexFile* df1, uint32_t sidx1,
- const DexFile* df2, uint32_t sidx2) {
+static inline bool DexFileStringEquals(const DexFile* df1, dex::StringIndex sidx1,
+ const DexFile* df2, dex::StringIndex sidx2) {
uint32_t s1_len; // Note: utf16 length != mutf8 length.
const char* s1_data = df1->StringDataAndUtf16LengthByIdx(sidx1, &s1_len);
uint32_t s2_len;
namespace art {
+static_assert(sizeof(dex::StringIndex) == sizeof(uint32_t), "StringIndex size is wrong");
+static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex not trivial");
static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
const DexFile::TypeId& type) const {
// 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 uint32_t name_idx = GetIndexForStringId(name);
+ const dex::StringIndex name_idx = GetIndexForStringId(name);
const dex::TypeIndex type_idx = GetIndexForTypeId(type);
int32_t lo = 0;
int32_t hi = NumFieldIds() - 1;
const DexFile::ProtoId& signature) const {
// 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 uint32_t name_idx = GetIndexForStringId(name);
+ const dex::StringIndex name_idx = GetIndexForStringId(name);
const uint16_t proto_idx = GetIndexForProtoId(signature);
int32_t lo = 0;
int32_t hi = NumMethodIds() - 1;
int32_t hi = NumStringIds() - 1;
while (hi >= lo) {
int32_t mid = (hi + lo) / 2;
- const DexFile::StringId& str_id = GetStringId(mid);
+ const DexFile::StringId& str_id = GetStringId(dex::StringIndex(mid));
const char* str = GetStringData(str_id);
int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str);
if (compare > 0) {
int32_t hi = NumStringIds() - 1;
while (hi >= lo) {
int32_t mid = (hi + lo) / 2;
- const DexFile::StringId& str_id = GetStringId(mid);
+ const DexFile::StringId& str_id = GetStringId(dex::StringIndex(mid));
const char* str = GetStringData(str_id);
int compare = CompareModifiedUtf8ToUtf16AsCodePointValues(str, string, length);
if (compare > 0) {
return nullptr;
}
-const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
+const DexFile::TypeId* DexFile::FindTypeId(dex::StringIndex string_idx) const {
int32_t lo = 0;
int32_t hi = NumTypeIds() - 1;
while (hi >= lo) {
}
uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
const char* descriptor = it.GetDescriptor();
- local_in_reg[arg_reg].name_ = StringDataByIdx(name_idx);
+ local_in_reg[arg_reg].name_ = StringDataByIdx(dex::StringIndex(name_idx));
local_in_reg[arg_reg].descriptor_ = descriptor;
local_in_reg[arg_reg].signature_ = nullptr;
local_in_reg[arg_reg].start_address_ = 0;
local_cb(context, local_in_reg[reg]);
}
- local_in_reg[reg].name_ = StringDataByIdx(name_idx);
+ local_in_reg[reg].name_ = StringDataByIdx(dex::StringIndex(name_idx));
local_in_reg[reg].descriptor_ =
StringByTypeIdx(dex::TypeIndex(dchecked_integral_cast<uint16_t>(descriptor_idx)));;
- local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
+ local_in_reg[reg].signature_ = StringDataByIdx(dex::StringIndex(signature_idx));
local_in_reg[reg].start_address_ = address;
local_in_reg[reg].reg_ = reg;
local_in_reg[reg].is_live_ = true;
break;
case DBG_SET_FILE: {
uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
- entry.source_file_ = StringDataByIdx(name_idx);
+ entry.source_file_ = StringDataByIdx(dex::StringIndex(name_idx));
break;
}
default: {
namespace dex {
+std::ostream& operator<<(std::ostream& os, const StringIndex& index) {
+ os << "StringIndex[" << index.index_ << "]";
+ return os;
+}
+
std::ostream& operator<<(std::ostream& os, const TypeIndex& index) {
os << "TypeIndex[" << index.index_ << "]";
return os;
// Raw type_id_item.
struct TypeId {
- uint32_t descriptor_idx_; // index into string_ids
+ dex::StringIndex descriptor_idx_; // index into string_ids
private:
DISALLOW_COPY_AND_ASSIGN(TypeId);
// Raw field_id_item.
struct FieldId {
- dex::TypeIndex class_idx_; // index into type_ids_ array for defining class
- dex::TypeIndex type_idx_; // index into type_ids_ array for field type
- uint32_t name_idx_; // index into string_ids_ array for field name
+ dex::TypeIndex class_idx_; // index into type_ids_ array for defining class
+ dex::TypeIndex type_idx_; // index into type_ids_ array for field type
+ dex::StringIndex name_idx_; // index into string_ids_ array for field name
private:
DISALLOW_COPY_AND_ASSIGN(FieldId);
// Raw proto_id_item.
struct ProtoId {
- uint32_t shorty_idx_; // index into string_ids array for shorty descriptor
+ dex::StringIndex shorty_idx_; // index into string_ids array for shorty descriptor
dex::TypeIndex return_type_idx_; // index into type_ids array for return type
- uint16_t pad_; // padding = 0
- uint32_t parameters_off_; // file offset to type_list for parameter types
+ uint16_t pad_; // padding = 0
+ uint32_t parameters_off_; // file offset to type_list for parameter types
private:
DISALLOW_COPY_AND_ASSIGN(ProtoId);
// 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
- uint32_t name_idx_; // index into string_ids_ array for method name
+ uint16_t proto_idx_; // index into proto_ids_ array for method prototype
+ dex::StringIndex name_idx_; // index into string_ids_ array for method name
private:
DISALLOW_COPY_AND_ASSIGN(MethodId);
dex::TypeIndex superclass_idx_; // index into type_ids_ array for superclass
uint16_t pad2_; // padding = 0
uint32_t interfaces_off_; // file offset to TypeList
- uint32_t source_file_idx_; // index into string_ids_ for source file name
+ dex::StringIndex source_file_idx_; // index into string_ids_ for source file name
uint32_t annotations_off_; // file offset to annotations_directory_item
uint32_t class_data_off_; // file offset to class_data_item
uint32_t static_values_off_; // file offset to EncodedArray
}
// Returns the StringId at the specified index.
- const StringId& GetStringId(uint32_t idx) const {
- DCHECK_LT(idx, NumStringIds()) << GetLocation();
- return string_ids_[idx];
+ const StringId& GetStringId(dex::StringIndex idx) const {
+ DCHECK_LT(idx.index_, NumStringIds()) << GetLocation();
+ return string_ids_[idx.index_];
}
- uint32_t GetIndexForStringId(const StringId& string_id) const {
+ dex::StringIndex GetIndexForStringId(const StringId& string_id) const {
CHECK_GE(&string_id, string_ids_) << GetLocation();
CHECK_LT(&string_id, string_ids_ + header_->string_ids_size_) << GetLocation();
- return &string_id - string_ids_;
+ return dex::StringIndex(&string_id - string_ids_);
}
int32_t GetStringLength(const StringId& string_id) const;
const char* GetStringData(const StringId& string_id) const;
// Index version of GetStringDataAndUtf16Length.
- const char* StringDataAndUtf16LengthByIdx(uint32_t idx, uint32_t* utf16_length) const;
+ const char* StringDataAndUtf16LengthByIdx(dex::StringIndex idx, uint32_t* utf16_length) const;
- const char* StringDataByIdx(uint32_t idx) const;
+ const char* StringDataByIdx(dex::StringIndex idx) const;
// Looks up a string id for a given modified utf8 string.
const StringId* FindStringId(const char* string) const;
const char* GetTypeDescriptor(const TypeId& type_id) const;
// Looks up a type for the given string index
- const TypeId* FindTypeId(uint32_t string_idx) const;
+ const TypeId* FindTypeId(dex::StringIndex string_idx) const;
// Returns the number of field identifiers in the .dex file.
size_t NumFieldIds() const {
void* context) const;
const char* GetSourceFile(const ClassDef& class_def) const {
- if (class_def.source_file_idx_ == 0xffffffff) {
+ if (!class_def.source_file_idx_.IsValid()) {
return nullptr;
} else {
return StringDataByIdx(class_def.source_file_idx_);
while (size != 0) {
uint32_t element_name_index = DecodeUnsignedLeb128(&annotation);
- const char* element_name = dex_file.GetStringData(dex_file.GetStringId(element_name_index));
+ const char* element_name =
+ dex_file.GetStringData(dex_file.GetStringId(dex::StringIndex(element_name_index)));
if (strcmp(name, element_name) == 0) {
return annotation;
}
StackHandleScope<1> hs(self);
Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
element_object = Runtime::Current()->GetClassLinker()->ResolveString(
- klass->GetDexFile(), index, dex_cache);
+ klass->GetDexFile(), dex::StringIndex(index), dex_cache);
set_object = true;
if (element_object == nullptr) {
return false;
ScopedObjectAccessUnchecked soa(self);
StackHandleScope<5> hs(self);
uint32_t element_name_index = DecodeUnsignedLeb128(annotation);
- const char* name = dex_file.StringDataByIdx(element_name_index);
+ const char* name = dex_file.StringDataByIdx(dex::StringIndex(element_name_index));
Handle<mirror::String> string_name(
hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, name)));
case kDouble: field->SetDouble<kTransactionActive>(field->GetDeclaringClass(), jval_.d); break;
case kNull: field->SetObject<kTransactionActive>(field->GetDeclaringClass(), nullptr); break;
case kString: {
- mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, *dex_cache_);
+ mirror::String* resolved = linker_->ResolveString(dex_file_,
+ dex::StringIndex(jval_.i),
+ *dex_cache_);
field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
break;
}
const char* type_str = java_lang_dex_file_->StringByTypeIdx(dex::TypeIndex(i));
const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
ASSERT_TRUE(type_str_id != nullptr);
- uint32_t type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
+ dex::StringIndex type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
ASSERT_EQ(type_id, java_lang_dex_file_->FindTypeId(type_str));
ASSERT_TRUE(type_id != nullptr);
namespace art {
namespace dex {
+class StringIndex {
+ public:
+ uint32_t index_;
+
+ constexpr StringIndex() : index_(std::numeric_limits<decltype(index_)>::max()) {}
+ explicit constexpr StringIndex(uint32_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());
+ }
+
+ bool operator==(const StringIndex& other) const {
+ return index_ == other.index_;
+ }
+ bool operator!=(const StringIndex& other) const {
+ return index_ != other.index_;
+ }
+ bool operator<(const StringIndex& other) const {
+ return index_ < other.index_;
+ }
+ bool operator<=(const StringIndex& other) const {
+ return index_ <= other.index_;
+ }
+ bool operator>(const StringIndex& other) const {
+ return index_ > other.index_;
+ }
+ bool operator>=(const StringIndex& other) const {
+ return index_ >= other.index_;
+ }
+};
+std::ostream& operator<<(std::ostream& os, const StringIndex& index);
+
class TypeIndex {
public:
uint16_t index_;
- TypeIndex() : index_(std::numeric_limits<decltype(index_)>::max()) {}
- explicit TypeIndex(uint16_t idx) : index_(idx) {}
+ 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();
namespace std {
+template<> struct hash<art::dex::StringIndex> {
+ size_t operator()(const art::dex::StringIndex& index) const {
+ return hash<uint32_t>()(index.index_);
+ }
+};
+
template<> struct hash<art::dex::TypeIndex> {
size_t operator()(const art::dex::TypeIndex& index) const {
return hash<uint16_t>()(index.index_);
return true;
}
-const char* DexFileVerifier::CheckLoadStringByIdx(uint32_t idx, const char* error_string) {
- if (UNLIKELY(!CheckIndex(idx, dex_file_->NumStringIds(), error_string))) {
+const char* DexFileVerifier::CheckLoadStringByIdx(dex::StringIndex idx, const char* error_string) {
+ if (UNLIKELY(!CheckIndex(idx.index_, dex_file_->NumStringIds(), error_string))) {
return nullptr;
}
return dex_file_->StringDataByIdx(idx);
if (UNLIKELY(!CheckIndex(type_idx.index_, dex_file_->NumTypeIds(), error_string))) {
return nullptr;
}
- const DexFile::TypeId& type_id = dex_file_->GetTypeId(type_idx);
- uint32_t idx = type_id.descriptor_idx_;
- return CheckLoadStringByIdx(idx, error_string);
+ return CheckLoadStringByIdx(dex_file_->GetTypeId(type_idx).descriptor_idx_, error_string);
}
const DexFile::FieldId* DexFileVerifier::CheckLoadFieldId(uint32_t idx, const char* error_string) {
const DexFile::TypeId* prev_item = reinterpret_cast<const DexFile::TypeId*>(previous_item_);
if (UNLIKELY(prev_item->descriptor_idx_ >= item->descriptor_idx_)) {
ErrorStringPrintf("Out-of-order type_ids: %x then %x",
- prev_item->descriptor_idx_, item->descriptor_idx_);
+ prev_item->descriptor_idx_.index_,
+ item->descriptor_idx_.index_);
return false;
}
}
static std::string GetStringOrError(const uint8_t* const begin,
const DexFile::Header* const header,
- uint32_t string_idx) {
+ dex::StringIndex string_idx) {
// The `string_idx` is not guaranteed to be valid yet.
- if (header->string_ids_size_ <= string_idx) {
+ if (header->string_ids_size_ <= string_idx.index_) {
return "(error)";
}
const DexFile::StringId* string_id =
- reinterpret_cast<const DexFile::StringId*>(begin + header->string_ids_off_) + string_idx;
+ reinterpret_cast<const DexFile::StringId*>(begin + header->string_ids_off_)
+ + string_idx.index_;
// Assume that the data is OK at this point. String data has been checked at this point.
}
uint32_t string_idx =
(reinterpret_cast<const DexFile::MethodId*>(begin + header->method_ids_off_) +
- method_index)->name_idx_;
+ method_index)->name_idx_.index_;
if (string_idx >= header->string_ids_size_) {
*error_msg = "String index not available for method flags verification";
return false;
// Load a string by (type) index. Checks whether the index is in bounds, printing the error if
// not. If there is an error, null is returned.
- const char* CheckLoadStringByIdx(uint32_t idx, const char* error_fmt);
+ const char* CheckLoadStringByIdx(dex::StringIndex idx, const char* error_fmt);
const char* CheckLoadStringByTypeIdx(dex::TypeIndex type_idx, const char* error_fmt);
// Load a field/method Id by index. Checks whether the index is in bounds, printing the error if
"method_id_name_idx",
[](DexFile* dex_file) {
DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
- method_id->name_idx_ = 0xFF;
+ method_id->name_idx_ = dex::StringIndex(0xFF);
},
"String index not available for method flags verification");
}
while (it.HasNextDirectMethod() || it.HasNextVirtualMethod()) {
uint32_t method_index = it.GetMemberIndex();
- uint32_t name_index = dex_file->GetMethodId(method_index).name_idx_;
+ dex::StringIndex name_index = dex_file->GetMethodId(method_index).name_idx_;
const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
const char* str = dex_file->GetStringData(string_id);
if (strcmp(name, str) == 0) {
uint32_t method_idx;
FindMethodData(dex_file, "foo", &method_idx);
auto* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(method_idx));
- method_id->name_idx_ = dex_file->NumStringIds();
+ method_id->name_idx_ = dex::StringIndex(dex_file->NumStringIds());
},
"Method may have only one of public/protected/private, LMethodFlags;.(error)");
}
while (it.HasNextStaticField() || it.HasNextInstanceField()) {
uint32_t field_index = it.GetMemberIndex();
- uint32_t name_index = dex_file->GetFieldId(field_index).name_idx_;
+ dex::StringIndex name_index = dex_file->GetFieldId(field_index).name_idx_;
const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
const char* str = dex_file->GetStringData(string_id);
if (strcmp(name, str) == 0) {
// Swap the proto parameters and shorties to break the ordering.
std::swap(const_cast<uint32_t&>(proto1.parameters_off_),
const_cast<uint32_t&>(proto2.parameters_off_));
- std::swap(const_cast<uint32_t&>(proto1.shorty_idx_),
- const_cast<uint32_t&>(proto2.shorty_idx_));
+ std::swap(const_cast<dex::StringIndex&>(proto1.shorty_idx_),
+ const_cast<dex::StringIndex&>(proto2.shorty_idx_));
} else {
// Copy the proto parameters and shorty to create duplicate proto id.
const_cast<uint32_t&>(proto1.parameters_off_) = proto2.parameters_off_;
- const_cast<uint32_t&>(proto1.shorty_idx_) = proto2.shorty_idx_;
+ const_cast<dex::StringIndex&>(proto1.shorty_idx_) = proto2.shorty_idx_;
}
},
"Out-of-order proto_id arguments");
if (file != nullptr) {
uint32_t string_idx = VRegB_21c();
if (string_idx < file->NumStringIds()) {
- os << StringPrintf("const-string v%d, %s // string@%d",
- VRegA_21c(),
- PrintableString(file->StringDataByIdx(string_idx)).c_str(),
- string_idx);
+ os << StringPrintf(
+ "const-string v%d, %s // string@%d",
+ VRegA_21c(),
+ PrintableString(file->StringDataByIdx(dex::StringIndex(string_idx))).c_str(),
+ string_idx);
} else {
os << StringPrintf("const-string v%d, <<invalid-string-idx-%d>> // string@%d",
VRegA_21c(),
uint32_t string_idx = VRegB_31c();
if (file != nullptr) {
if (string_idx < file->NumStringIds()) {
- os << StringPrintf("%s v%d, %s // string@%d",
- opcode,
- VRegA_31c(),
- PrintableString(file->StringDataByIdx(string_idx)).c_str(),
- string_idx);
+ os << StringPrintf(
+ "%s v%d, %s // string@%d",
+ opcode,
+ VRegA_31c(),
+ PrintableString(file->StringDataByIdx(dex::StringIndex(string_idx))).c_str(),
+ string_idx);
} else {
os << StringPrintf("%s v%d, <<invalid-string-idx-%d>> // string@%d",
opcode,
return h_class.Get();
}
-inline mirror::String* ResolveStringFromCode(ArtMethod* referrer, uint32_t string_idx) {
+inline mirror::String* ResolveStringFromCode(ArtMethod* referrer, dex::StringIndex string_idx) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
return class_linker->ResolveString(string_idx, referrer);
}
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
-inline mirror::String* ResolveStringFromCode(ArtMethod* referrer, uint32_t string_idx)
+inline mirror::String* ResolveStringFromCode(ArtMethod* referrer, dex::StringIndex string_idx)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
// TODO: Change art_quick_resolve_string on MIPS and MIPS64 to kSaveEverything.
(kRuntimeISA == kMips || kRuntimeISA == kMips64) ? Runtime::kSaveRefsOnly
: Runtime::kSaveEverything);
- mirror::String* result = ResolveStringFromCode(caller, string_idx);
+ mirror::String* result = ResolveStringFromCode(caller, dex::StringIndex(string_idx));
if (LIKELY(result != nullptr)) {
// For AOT code, we need a write barrier for the class loader that holds
// the GC roots in the .bss.
// java.lang.String class is initialized.
static inline ObjPtr<mirror::String> ResolveString(Thread* self,
ShadowFrame& shadow_frame,
- uint32_t string_idx)
+ dex::StringIndex string_idx)
REQUIRES_SHARED(Locks::mutator_lock_) {
ObjPtr<mirror::Class> java_lang_string_class = mirror::String::GetJavaLangString();
if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
ArtMethod* method = shadow_frame.GetMethod();
ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass();
// MethodVerifier refuses methods with string_idx out of bounds.
- DCHECK_LT(string_idx % mirror::DexCache::kDexCacheStringCacheSize,
+ DCHECK_LT(string_idx.index_ % mirror::DexCache::kDexCacheStringCacheSize,
declaring_class->GetDexFile().NumStringIds());
ObjPtr<mirror::String> string_ptr =
mirror::StringDexCachePair::Lookup(declaring_class->GetDexCacheStrings(),
- string_idx,
+ string_idx.index_,
mirror::DexCache::kDexCacheStringCacheSize).Read();
if (UNLIKELY(string_ptr == nullptr)) {
StackHandleScope<1> hs(self);
break;
case Instruction::CONST_STRING: {
PREAMBLE();
- ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, inst->VRegB_21c());
+ ObjPtr<mirror::String> s = ResolveString(self,
+ shadow_frame,
+ dex::StringIndex(inst->VRegB_21c()));
if (UNLIKELY(s == nullptr)) {
HANDLE_PENDING_EXCEPTION();
} else {
}
case Instruction::CONST_STRING_JUMBO: {
PREAMBLE();
- ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, inst->VRegB_31c());
+ ObjPtr<mirror::String> s = ResolveString(self,
+ shadow_frame,
+ dex::StringIndex(inst->VRegB_31c()));
if (UNLIKELY(s == nullptr)) {
HANDLE_PENDING_EXCEPTION();
} else {
ShadowFrame* shadow_frame,
Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<mirror::String> s = ResolveString(self, *shadow_frame, index);
+ ObjPtr<mirror::String> s = ResolveString(self, *shadow_frame, dex::StringIndex(index));
if (UNLIKELY(s == nullptr)) {
return true;
}
return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
}
-inline mirror::String* DexCache::GetResolvedString(uint32_t string_idx) {
- DCHECK_LT(string_idx, GetDexFile()->NumStringIds());
- return StringDexCachePair::Lookup(GetStrings(), string_idx, NumStrings()).Read();
+inline mirror::String* DexCache::GetResolvedString(dex::StringIndex string_idx) {
+ DCHECK_LT(string_idx.index_, GetDexFile()->NumStringIds());
+ return StringDexCachePair::Lookup(GetStrings(), string_idx.index_, NumStrings()).Read();
}
-inline void DexCache::SetResolvedString(uint32_t string_idx, ObjPtr<mirror::String> resolved) {
- StringDexCachePair::Assign(GetStrings(), string_idx, resolved.Ptr(), NumStrings());
+inline void DexCache::SetResolvedString(dex::StringIndex string_idx,
+ ObjPtr<mirror::String> resolved) {
+ StringDexCachePair::Assign(GetStrings(), string_idx.index_, resolved.Ptr(), NumStrings());
Runtime* const runtime = Runtime::Current();
if (UNLIKELY(runtime->IsActiveTransaction())) {
DCHECK(runtime->IsAotCompiler());
runtime->GetHeap()->WriteBarrierEveryFieldOf(this);
}
-inline void DexCache::ClearString(uint32_t string_idx) {
- const uint32_t slot_idx = string_idx % NumStrings();
+inline void DexCache::ClearString(dex::StringIndex string_idx) {
+ const uint32_t slot_idx = string_idx.index_ % NumStrings();
DCHECK(Runtime::Current()->IsAotCompiler());
StringDexCacheType* slot = &GetStrings()[slot_idx];
// This is racy but should only be called from the transactional interpreter.
- if (slot->load(std::memory_order_relaxed).index == string_idx) {
+ if (slot->load(std::memory_order_relaxed).index == string_idx.index_) {
StringDexCachePair cleared(
nullptr,
StringDexCachePair::InvalidIndexForSlot(slot_idx));
return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_method_types_);
}
- mirror::String* GetResolvedString(uint32_t string_idx) ALWAYS_INLINE
+ mirror::String* GetResolvedString(dex::StringIndex string_idx) ALWAYS_INLINE
REQUIRES_SHARED(Locks::mutator_lock_);
- void SetResolvedString(uint32_t string_idx, ObjPtr<mirror::String> resolved) ALWAYS_INLINE
+ void SetResolvedString(dex::StringIndex string_idx, ObjPtr<mirror::String> resolved) ALWAYS_INLINE
REQUIRES_SHARED(Locks::mutator_lock_);
// Clear a string for a string_idx, used to undo string intern transactions to make sure
// the string isn't kept live.
- void ClearString(uint32_t string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
+ void ClearString(dex::StringIndex string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
Class* GetResolvedType(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
// Based on ClassLinker::ResolveString.
static void PreloadDexCachesResolveString(
- Handle<mirror::DexCache> dex_cache, uint32_t string_idx, StringTable& strings)
+ Handle<mirror::DexCache> dex_cache, dex::StringIndex string_idx, StringTable& strings)
REQUIRES_SHARED(Locks::mutator_lock_) {
ObjPtr<mirror::String> string = dex_cache->GetResolvedString(string_idx);
if (string != nullptr) {
continue;
}
for (size_t j = 0; j < dex_cache->NumStrings(); j++) {
- ObjPtr<mirror::String> string = dex_cache->GetResolvedString(j);
+ ObjPtr<mirror::String> string = dex_cache->GetResolvedString(dex::StringIndex(j));
if (string != nullptr) {
filled->num_strings++;
}
if (kPreloadDexCachesStrings) {
for (size_t j = 0; j < dex_cache->NumStrings(); j++) {
- PreloadDexCachesResolveString(dex_cache, j, strings);
+ PreloadDexCachesResolveString(dex_cache, dex::StringIndex(j), strings);
}
}
ScopedFastNativeObjectAccess soa(env);
ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
CHECK_LT(static_cast<size_t>(string_index), dex_cache->GetDexFile()->NumStringIds());
- return soa.AddLocalReference<jobject>(dex_cache->GetResolvedString(string_index));
+ return soa.AddLocalReference<jobject>(
+ dex_cache->GetResolvedString(dex::StringIndex(string_index)));
}
static void DexCache_setResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index,
ScopedFastNativeObjectAccess soa(env);
ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
CHECK_LT(static_cast<size_t>(string_index), dex_cache->GetDexFile()->NumStringIds());
- dex_cache->SetResolvedString(string_index, soa.Decode<mirror::String>(string));
+ dex_cache->SetResolvedString(dex::StringIndex(string_index), soa.Decode<mirror::String>(string));
}
static JNINativeMethod gMethods[] = {
preinitialization_transaction_->RecordWeakStringRemoval(s);
}
-void Runtime::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, uint32_t string_idx) const {
+void Runtime::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
+ dex::StringIndex string_idx) const {
DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_->RecordResolveString(dex_cache, string_idx);
#include "arch/instruction_set.h"
#include "base/macros.h"
+#include "dex_file_types.h"
#include "experimental_flags.h"
#include "gc_root.h"
#include "instrumentation.h"
REQUIRES(Locks::intern_table_lock_);
void RecordWeakStringRemoval(ObjPtr<mirror::String> s) const
REQUIRES(Locks::intern_table_lock_);
- void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, uint32_t string_idx) const
+ void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx) const
REQUIRES_SHARED(Locks::mutator_lock_);
void SetFaultMessage(const std::string& message) REQUIRES(!fault_message_lock_);
#include "base/logging.h"
#include "dex_file-inl.h"
+#include "dex_file_types.h"
#include "utf-inl.h"
namespace art {
// A string is located by its DexFile and the string_ids_ table index into that DexFile.
struct StringReference {
- StringReference(const DexFile* file, uint32_t index) : dex_file(file), string_index(index) { }
+ StringReference(const DexFile* file, dex::StringIndex index)
+ : dex_file(file), string_index(index) { }
const char* GetStringData() const {
return dex_file->GetStringData(dex_file->GetStringId(string_index));
}
const DexFile* dex_file;
- uint32_t string_index;
+ dex::StringIndex string_index;
};
// Compare only the reference and not the string contents.
array_log.LogValue(index, value);
}
-void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, uint32_t string_idx) {
+void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
+ dex::StringIndex string_idx) {
DCHECK(dex_cache != nullptr);
- DCHECK_LT(string_idx, dex_cache->GetDexFile()->NumStringIds());
+ DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
MutexLock mu(Thread::Current(), log_lock_);
resolve_string_logs_.push_back(ResolveStringLog(dex_cache, string_idx));
}
}
Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
- uint32_t string_idx)
+ dex::StringIndex string_idx)
: dex_cache_(dex_cache),
string_idx_(string_idx) {
DCHECK(dex_cache != nullptr);
- DCHECK_LT(string_idx_, dex_cache->GetDexFile()->NumStringIds());
+ DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
}
void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
#include "base/macros.h"
#include "base/mutex.h"
#include "base/value_object.h"
+#include "dex_file_types.h"
#include "gc_root.h"
#include "object_callbacks.h"
#include "offsets.h"
REQUIRES(!log_lock_);
// Record resolve string.
- void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, uint32_t string_idx)
+ void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!log_lock_);
class ResolveStringLog : public ValueObject {
public:
- ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, uint32_t string_idx);
+ ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
void Undo() REQUIRES_SHARED(Locks::mutator_lock_);
private:
GcRoot<mirror::DexCache> dex_cache_;
- const uint32_t string_idx_;
+ const dex::StringIndex string_idx_;
};
void LogInternedString(const InternStringLog& log)
namespace art {
-static const size_t kDexNoIndex = DexFile::kDexNoIndex; // Make copy to prevent linking errors.
-
class TransactionTest : public CommonRuntimeTest {
public:
// Tests failing class initialization due to native call with transaction rollback.
static const char* kResolvedString = "ResolvedString";
const DexFile::StringId* string_id = dex_file->FindStringId(kResolvedString);
ASSERT_TRUE(string_id != nullptr);
- uint32_t string_idx = dex_file->GetIndexForStringId(*string_id);
- ASSERT_NE(string_idx, kDexNoIndex);
+ dex::StringIndex string_idx = dex_file->GetIndexForStringId(*string_id);
+ ASSERT_TRUE(string_idx.IsValid());
// String should only get resolved by the initializer.
EXPECT_TRUE(class_linker_->LookupString(*dex_file, string_idx, h_dex_cache) == nullptr);
EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
}
}
-uint32_t VerifierDeps::GetClassDescriptorStringId(const DexFile& dex_file,
- ObjPtr<mirror::Class> klass) {
+dex::StringIndex VerifierDeps::GetClassDescriptorStringId(const DexFile& dex_file,
+ ObjPtr<mirror::Class> klass) {
DCHECK(klass != nullptr);
ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();
// Array and proxy classes do not have a dex cache.
}
// Try to find the string descriptor of the class. type_idx is a best guess of a matching string id.
-static uint32_t TryGetClassDescriptorStringId(const DexFile& dex_file,
- dex::TypeIndex type_idx,
- ObjPtr<mirror::Class> klass)
+static dex::StringIndex TryGetClassDescriptorStringId(const DexFile& dex_file,
+ dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (!klass->IsArrayClass()) {
const DexFile::TypeId& type_id = dex_file.GetTypeId(type_idx);
return type_id.descriptor_idx_;
}
}
- return DexFile::kDexNoIndex;
+ return dex::StringIndex::Invalid();
}
-uint32_t VerifierDeps::GetMethodDeclaringClassStringId(const DexFile& dex_file,
- uint32_t dex_method_index,
- ArtMethod* method) {
+dex::StringIndex VerifierDeps::GetMethodDeclaringClassStringId(const DexFile& dex_file,
+ uint32_t dex_method_index,
+ ArtMethod* method) {
static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
if (method == nullptr) {
- return VerifierDeps::kUnresolvedMarker;
+ return dex::StringIndex(VerifierDeps::kUnresolvedMarker);
}
- const uint32_t string_id = TryGetClassDescriptorStringId(
+ const dex::StringIndex string_id = TryGetClassDescriptorStringId(
dex_file,
dex_file.GetMethodId(dex_method_index).class_idx_,
method->GetDeclaringClass());
- if (string_id != DexFile::kDexNoIndex) {
+ if (string_id.IsValid()) {
// Got lucky using the original dex file, return based on the input dex file.
DCHECK_EQ(GetClassDescriptorStringId(dex_file, method->GetDeclaringClass()), string_id);
return string_id;
return GetClassDescriptorStringId(dex_file, method->GetDeclaringClass());
}
-uint32_t VerifierDeps::GetFieldDeclaringClassStringId(const DexFile& dex_file,
- uint32_t dex_field_idx,
- ArtField* field) {
+dex::StringIndex VerifierDeps::GetFieldDeclaringClassStringId(const DexFile& dex_file,
+ uint32_t dex_field_idx,
+ ArtField* field) {
static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
if (field == nullptr) {
- return VerifierDeps::kUnresolvedMarker;
+ return dex::StringIndex(VerifierDeps::kUnresolvedMarker);
}
- const uint32_t string_id = TryGetClassDescriptorStringId(
+ const dex::StringIndex string_id = TryGetClassDescriptorStringId(
dex_file,
dex_file.GetFieldId(dex_field_idx).class_idx_,
field->GetDeclaringClass());
- if (string_id != DexFile::kDexNoIndex) {
+ if (string_id.IsValid()) {
// Got lucky using the original dex file, return based on the input dex file.
DCHECK_EQ(GetClassDescriptorStringId(dex_file, field->GetDeclaringClass()), string_id);
return string_id;
return false;
}
-uint32_t VerifierDeps::GetIdFromString(const DexFile& dex_file, const std::string& str) {
+dex::StringIndex VerifierDeps::GetIdFromString(const DexFile& dex_file, const std::string& str) {
const DexFile::StringId* string_id = dex_file.FindStringId(str.c_str());
if (string_id != nullptr) {
// String is in the DEX file. Return its ID.
{
ReaderMutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
if (FindExistingStringId(deps->strings_, str, &found_id)) {
- return num_ids_in_dex + found_id;
+ return dex::StringIndex(num_ids_in_dex + found_id);
}
}
{
WriterMutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
if (FindExistingStringId(deps->strings_, str, &found_id)) {
- return num_ids_in_dex + found_id;
+ return dex::StringIndex(num_ids_in_dex + found_id);
}
deps->strings_.push_back(str);
- uint32_t new_id = num_ids_in_dex + deps->strings_.size() - 1;
- CHECK_GE(new_id, num_ids_in_dex); // check for overflows
+ dex::StringIndex new_id(num_ids_in_dex + deps->strings_.size() - 1);
+ CHECK_GE(new_id.index_, num_ids_in_dex); // check for overflows
DCHECK_EQ(str, singleton->GetStringFromId(dex_file, new_id));
return new_id;
}
}
-std::string VerifierDeps::GetStringFromId(const DexFile& dex_file, uint32_t string_id) const {
+std::string VerifierDeps::GetStringFromId(const DexFile& dex_file, dex::StringIndex string_id)
+ const {
uint32_t num_ids_in_dex = dex_file.NumStringIds();
- if (string_id < num_ids_in_dex) {
+ if (string_id.index_ < num_ids_in_dex) {
return std::string(dex_file.StringDataByIdx(string_id));
} else {
const DexFileDeps* deps = GetDexFileDeps(dex_file);
DCHECK(deps != nullptr);
- string_id -= num_ids_in_dex;
- CHECK_LT(string_id, deps->strings_.size());
- return deps->strings_[string_id];
+ string_id.index_ -= num_ids_in_dex;
+ CHECK_LT(string_id.index_, deps->strings_.size());
+ return deps->strings_[string_id.index_];
}
}
}
// Get string IDs for both descriptors and store in the appropriate set.
- uint32_t destination_id = GetClassDescriptorStringId(dex_file, destination);
- uint32_t source_id = GetClassDescriptorStringId(dex_file, source);
+ dex::StringIndex destination_id = GetClassDescriptorStringId(dex_file, destination);
+ dex::StringIndex source_id = GetClassDescriptorStringId(dex_file, source);
if (is_assignable) {
dex_deps->assignable_types_.emplace(TypeAssignability(destination_id, source_id));
template<> inline uint32_t Encode<dex::TypeIndex>(dex::TypeIndex in) {
return in.index_;
}
+template<> inline uint32_t Encode<dex::StringIndex>(dex::StringIndex in) {
+ return in.index_;
+}
template<typename T> inline T Decode(uint32_t in);
template<> inline dex::TypeIndex Decode<dex::TypeIndex>(uint32_t in) {
return dex::TypeIndex(in);
}
+template<> inline dex::StringIndex Decode<dex::StringIndex>(uint32_t in) {
+ return dex::StringIndex(in);
+}
template<typename T1, typename T2>
static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2>& t) {
static inline void DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2, T3>* t) {
T1 v1 = Decode<T1>(DecodeUint32WithOverflowCheck(in, end));
T2 v2 = Decode<T2>(DecodeUint32WithOverflowCheck(in, end));
- T3 v3 = Decode<T2>(DecodeUint32WithOverflowCheck(in, end));
+ T3 v3 = Decode<T3>(DecodeUint32WithOverflowCheck(in, end));
*t = std::make_tuple(v1, v2, v3);
}
uint16_t GetAccessFlags() const { return std::get<1>(*this); }
};
- using FieldResolutionBase = std::tuple<uint32_t, uint16_t, uint32_t>;
+ using FieldResolutionBase = std::tuple<uint32_t, uint16_t, dex::StringIndex>;
struct FieldResolution : public FieldResolutionBase {
FieldResolution() = default;
FieldResolution(const FieldResolution&) = default;
- FieldResolution(uint32_t field_idx, uint16_t access_flags, uint32_t declaring_class_idx)
+ FieldResolution(uint32_t field_idx, uint16_t access_flags, dex::StringIndex declaring_class_idx)
: FieldResolutionBase(field_idx, access_flags, declaring_class_idx) {}
bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
uint32_t GetDexFieldIndex() const { return std::get<0>(*this); }
uint16_t GetAccessFlags() const { return std::get<1>(*this); }
- uint32_t GetDeclaringClassIndex() const { return std::get<2>(*this); }
+ dex::StringIndex GetDeclaringClassIndex() const { return std::get<2>(*this); }
};
- using MethodResolutionBase = std::tuple<uint32_t, uint16_t, uint32_t>;
+ using MethodResolutionBase = std::tuple<uint32_t, uint16_t, dex::StringIndex>;
struct MethodResolution : public MethodResolutionBase {
MethodResolution() = default;
MethodResolution(const MethodResolution&) = default;
- MethodResolution(uint32_t method_idx, uint16_t access_flags, uint32_t declaring_class_idx)
+ MethodResolution(uint32_t method_idx,
+ uint16_t access_flags,
+ dex::StringIndex declaring_class_idx)
: MethodResolutionBase(method_idx, access_flags, declaring_class_idx) {}
bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
uint32_t GetDexMethodIndex() const { return std::get<0>(*this); }
uint16_t GetAccessFlags() const { return std::get<1>(*this); }
- uint32_t GetDeclaringClassIndex() const { return std::get<2>(*this); }
+ dex::StringIndex GetDeclaringClassIndex() const { return std::get<2>(*this); }
};
- using TypeAssignabilityBase = std::tuple<uint32_t, uint32_t>;
+ using TypeAssignabilityBase = std::tuple<dex::StringIndex, dex::StringIndex>;
struct TypeAssignability : public TypeAssignabilityBase {
TypeAssignability() = default;
TypeAssignability(const TypeAssignability&) = default;
- TypeAssignability(uint32_t destination_idx, uint32_t source_idx)
+ TypeAssignability(dex::StringIndex destination_idx, dex::StringIndex source_idx)
: TypeAssignabilityBase(destination_idx, source_idx) {}
- uint32_t GetDestination() const { return std::get<0>(*this); }
- uint32_t GetSource() const { return std::get<1>(*this); }
+ dex::StringIndex GetDestination() const { return std::get<0>(*this); }
+ dex::StringIndex GetSource() const { return std::get<1>(*this); }
};
// Data structure representing dependencies collected during verification of
// string ID. If not, an ID is assigned to the string and cached in `strings_`
// of the corresponding DexFileDeps structure (either provided or inferred from
// `dex_file`).
- uint32_t GetIdFromString(const DexFile& dex_file, const std::string& str)
+ dex::StringIndex GetIdFromString(const DexFile& dex_file, const std::string& str)
REQUIRES(!Locks::verifier_deps_lock_);
// Returns the string represented by `id`.
- std::string GetStringFromId(const DexFile& dex_file, uint32_t string_id) const;
+ std::string GetStringFromId(const DexFile& dex_file, dex::StringIndex string_id) const;
// Returns the bytecode access flags of `element` (bottom 16 bits), or
// `kUnresolvedMarker` if `element` is null.
// Returns a string ID of the descriptor of the declaring class of `element`,
// or `kUnresolvedMarker` if `element` is null.
- uint32_t GetMethodDeclaringClassStringId(const DexFile& dex_file,
- uint32_t dex_method_idx,
- ArtMethod* method)
+ dex::StringIndex GetMethodDeclaringClassStringId(const DexFile& dex_file,
+ uint32_t dex_method_idx,
+ ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_);
- uint32_t GetFieldDeclaringClassStringId(const DexFile& dex_file,
- uint32_t dex_field_idx,
- ArtField* field)
+ dex::StringIndex GetFieldDeclaringClassStringId(const DexFile& dex_file,
+ uint32_t dex_field_idx,
+ ArtField* field)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns a string ID of the descriptor of the class.
- uint32_t GetClassDescriptorStringId(const DexFile& dex_file, ObjPtr<mirror::Class> klass)
+ dex::StringIndex GetClassDescriptorStringId(const DexFile& dex_file, ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::verifier_deps_lock_);