/*
* Copyright (C) 2014 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_COMPILER_DEX_MIR_FIELD_INFO_H_
#define ART_COMPILER_DEX_MIR_FIELD_INFO_H_
#include "base/macros.h"
#include "dex_file.h"
#include "offsets.h"
namespace art {
class CompilerDriver;
class DexCompilationUnit;
/*
* Field info is calculated from the perspective of the compilation unit that accesses
* the field and stored in that unit's MIRGraph. Therefore it does not need to reference the
* dex file or method for which it has been calculated. However, we do store the declaring
* field index, class index and dex file of the resolved field to help distinguish between fields.
*/
class MirFieldInfo {
public:
uint16_t FieldIndex() const {
return field_idx_;
}
bool IsStatic() const {
return (flags_ & kFlagIsStatic) != 0u;
}
bool IsResolved() const {
return declaring_dex_file_ != nullptr;
}
const DexFile* DeclaringDexFile() const {
return declaring_dex_file_;
}
uint16_t DeclaringClassIndex() const {
return declaring_class_idx_;
}
uint16_t DeclaringFieldIndex() const {
return declaring_field_idx_;
}
bool IsVolatile() const {
return (flags_ & kFlagIsVolatile) != 0u;
}
protected:
enum {
kBitIsStatic = 0,
kBitIsVolatile,
kFieldInfoBitEnd
};
static constexpr uint16_t kFlagIsVolatile = 1u << kBitIsVolatile;
static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
MirFieldInfo(uint16_t field_idx, uint16_t flags)
: field_idx_(field_idx),
flags_(flags),
declaring_field_idx_(0u),
declaring_class_idx_(0u),
declaring_dex_file_(nullptr) {
}
// Make copy-ctor/assign/dtor protected to avoid slicing.
MirFieldInfo(const MirFieldInfo& other) = default;
MirFieldInfo& operator=(const MirFieldInfo& other) = default;
~MirFieldInfo() = default;
// The field index in the compiling method's dex file.
uint16_t field_idx_;
// Flags, for volatility and derived class data.
uint16_t flags_;
// The field index in the dex file that defines field, 0 if unresolved.
uint16_t declaring_field_idx_;
// The type index of the class declaring the field, 0 if unresolved.
uint16_t declaring_class_idx_;
// The dex file that defines the class containing the field and the field, nullptr if unresolved.
const DexFile* declaring_dex_file_;
};
class MirIFieldLoweringInfo : public MirFieldInfo {
public:
// For each requested instance field retrieve the field's declaring location (dex file, class
// index and field index) and volatility and compute whether we can fast path the access
// with IGET/IPUT. For fast path fields, retrieve the field offset.
static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
MirIFieldLoweringInfo* field_infos, size_t count)
LOCKS_EXCLUDED(Locks::mutator_lock_);
// Construct an unresolved instance field lowering info.
explicit MirIFieldLoweringInfo(uint16_t field_idx)
: MirFieldInfo(field_idx, kFlagIsVolatile), // Without kFlagIsStatic.
field_offset_(0u) {
}
bool FastGet() const {
return (flags_ & kFlagFastGet) != 0u;
}
bool FastPut() const {
return (flags_ & kFlagFastPut) != 0u;
}
MemberOffset FieldOffset() const {
return field_offset_;
}
private:
enum {
kBitFastGet = kFieldInfoBitEnd,
kBitFastPut,
kIFieldLoweringInfoBitEnd
};
COMPILE_ASSERT(kIFieldLoweringInfoBitEnd <= 16, too_many_flags);
static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
// The member offset of the field, 0u if unresolved.
MemberOffset field_offset_;
friend class GlobalValueNumberingTest;
friend class LocalValueNumberingTest;
};
class MirSFieldLoweringInfo : public MirFieldInfo {
public:
// For each requested static field retrieve the field's declaring location (dex file, class
// index and field index) and volatility and compute whether we can fast path the access with
// IGET/IPUT. For fast path fields (at least for IGET), retrieve the information needed for
// the field access, i.e. the field offset, whether the field is in the same class as the
// method being compiled, whether the declaring class can be safely assumed to be initialized
// and the type index of the declaring class in the compiled method's dex file.
static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
MirSFieldLoweringInfo* field_infos, size_t count)
LOCKS_EXCLUDED(Locks::mutator_lock_);
// Construct an unresolved static field lowering info.
explicit MirSFieldLoweringInfo(uint16_t field_idx)
: MirFieldInfo(field_idx, kFlagIsVolatile | kFlagIsStatic),
field_offset_(0u),
storage_index_(DexFile::kDexNoIndex) {
}
bool FastGet() const {
return (flags_ & kFlagFastGet) != 0u;
}
bool FastPut() const {
return (flags_ & kFlagFastPut) != 0u;
}
bool IsReferrersClass() const {
return (flags_ & kFlagIsReferrersClass) != 0u;
}
bool IsInitialized() const {
return (flags_ & kFlagIsInitialized) != 0u;
}
MemberOffset FieldOffset() const {
return field_offset_;
}
uint32_t StorageIndex() const {
return storage_index_;
}
private:
enum {
kBitFastGet = kFieldInfoBitEnd,
kBitFastPut,
kBitIsReferrersClass,
kBitIsInitialized,
kSFieldLoweringInfoBitEnd
};
COMPILE_ASSERT(kSFieldLoweringInfoBitEnd <= 16, too_many_flags);
static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
static constexpr uint16_t kFlagIsInitialized = 1u << kBitIsInitialized;
// The member offset of the field, 0u if unresolved.
MemberOffset field_offset_;
// The type index of the declaring class in the compiling method's dex file,
// -1 if the field is unresolved or there's no appropriate TypeId in that dex file.
uint32_t storage_index_;
friend class ClassInitCheckEliminationTest;
friend class GlobalValueNumberingTest;
friend class LocalValueNumberingTest;
};
} // namespace art
#endif // ART_COMPILER_DEX_MIR_FIELD_INFO_H_