summaryrefslogtreecommitdiff
path: root/compiler/optimizing/nodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/nodes.h')
-rw-r--r--compiler/optimizing/nodes.h151
1 files changed, 77 insertions, 74 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index e3f4d8f035..afa17cefa2 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -125,6 +125,11 @@ enum GraphAnalysisResult {
kAnalysisSuccess,
};
+template <typename T>
+static inline typename std::make_unsigned<T>::type MakeUnsigned(T x) {
+ return static_cast<typename std::make_unsigned<T>::type>(x);
+}
+
class HInstructionList : public ValueObject {
public:
HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
@@ -325,6 +330,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
invoke_type_(invoke_type),
in_ssa_form_(false),
should_generate_constructor_barrier_(should_generate_constructor_barrier),
+ number_of_cha_guards_(0),
instruction_set_(instruction_set),
cached_null_constant_(nullptr),
cached_int_constants_(std::less<int32_t>(), arena->Adapter(kArenaAllocConstantsMap)),
@@ -546,9 +552,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
}
bool HasShouldDeoptimizeFlag() const {
- // TODO: if all CHA guards can be eliminated, there is no need for the flag
- // even if cha_single_implementation_list_ is not empty.
- return !cha_single_implementation_list_.empty();
+ return number_of_cha_guards_ != 0;
}
bool HasTryCatch() const { return has_try_catch_; }
@@ -567,6 +571,10 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
ReferenceTypeInfo GetInexactObjectRti() const { return inexact_object_rti_; }
+ uint32_t GetNumberOfCHAGuards() { return number_of_cha_guards_; }
+ void SetNumberOfCHAGuards(uint32_t num) { number_of_cha_guards_ = num; }
+ void IncrementNumberOfCHAGuards() { number_of_cha_guards_++; }
+
private:
void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
void RemoveDeadBlocks(const ArenaBitVector& visited);
@@ -662,6 +670,10 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
const bool should_generate_constructor_barrier_;
+ // Number of CHA guards in the graph. Used to short-circuit the
+ // CHA guard optimization pass when there is no CHA guard left.
+ uint32_t number_of_cha_guards_;
+
const InstructionSet instruction_set_;
// Cached constants.
@@ -2342,6 +2354,32 @@ class HBackwardInstructionIterator : public ValueObject {
DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
};
+class HVariableInputSizeInstruction : public HInstruction {
+ public:
+ using HInstruction::GetInputRecords; // Keep the const version visible.
+ ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE {
+ return ArrayRef<HUserRecord<HInstruction*>>(inputs_);
+ }
+
+ void AddInput(HInstruction* input);
+ void InsertInputAt(size_t index, HInstruction* input);
+ void RemoveInputAt(size_t index);
+
+ protected:
+ HVariableInputSizeInstruction(SideEffects side_effects,
+ uint32_t dex_pc,
+ ArenaAllocator* arena,
+ size_t number_of_inputs,
+ ArenaAllocKind kind)
+ : HInstruction(side_effects, dex_pc),
+ inputs_(number_of_inputs, arena->Adapter(kind)) {}
+
+ ArenaVector<HUserRecord<HInstruction*>> inputs_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HVariableInputSizeInstruction);
+};
+
template<size_t N>
class HTemplateInstruction: public HInstruction {
public:
@@ -2433,15 +2471,19 @@ class HReturn FINAL : public HTemplateInstruction<1> {
DISALLOW_COPY_AND_ASSIGN(HReturn);
};
-class HPhi FINAL : public HInstruction {
+class HPhi FINAL : public HVariableInputSizeInstruction {
public:
HPhi(ArenaAllocator* arena,
uint32_t reg_number,
size_t number_of_inputs,
Primitive::Type type,
uint32_t dex_pc = kNoDexPc)
- : HInstruction(SideEffects::None(), dex_pc),
- inputs_(number_of_inputs, arena->Adapter(kArenaAllocPhiInputs)),
+ : HVariableInputSizeInstruction(
+ SideEffects::None(),
+ dex_pc,
+ arena,
+ number_of_inputs,
+ kArenaAllocPhiInputs),
reg_number_(reg_number) {
SetPackedField<TypeField>(ToPhiType(type));
DCHECK_NE(GetType(), Primitive::kPrimVoid);
@@ -2459,14 +2501,6 @@ class HPhi FINAL : public HInstruction {
bool IsCatchPhi() const { return GetBlock()->IsCatchBlock(); }
- using HInstruction::GetInputRecords; // Keep the const version visible.
- ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE FINAL {
- return ArrayRef<HUserRecord<HInstruction*>>(inputs_);
- }
-
- void AddInput(HInstruction* input);
- void RemoveInputAt(size_t index);
-
Primitive::Type GetType() const OVERRIDE { return GetPackedField<TypeField>(); }
void SetType(Primitive::Type new_type) {
// Make sure that only valid type changes occur. The following are allowed:
@@ -2522,7 +2556,6 @@ class HPhi FINAL : public HInstruction {
static_assert(kNumberOfPhiPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>;
- ArenaVector<HUserRecord<HInstruction*>> inputs_;
const uint32_t reg_number_;
DISALLOW_COPY_AND_ASSIGN(HPhi);
@@ -2899,14 +2932,20 @@ class HDeoptimize FINAL : public HTemplateInstruction<1> {
// if it's true, starts to do deoptimization.
// It has a 4-byte slot on stack.
// TODO: allocate a register for this flag.
-class HShouldDeoptimizeFlag FINAL : public HExpression<0> {
+class HShouldDeoptimizeFlag FINAL : public HVariableInputSizeInstruction {
public:
- // TODO: use SideEffects to aid eliminating some CHA guards.
- explicit HShouldDeoptimizeFlag(uint32_t dex_pc)
- : HExpression(Primitive::kPrimInt, SideEffects::None(), dex_pc) {
+ // CHA guards are only optimized in a separate pass and it has no side effects
+ // with regard to other passes.
+ HShouldDeoptimizeFlag(ArenaAllocator* arena, uint32_t dex_pc)
+ : HVariableInputSizeInstruction(SideEffects::None(), dex_pc, arena, 0, kArenaAllocCHA) {
}
- // We don't eliminate CHA guards yet.
+ Primitive::Type GetType() const OVERRIDE { return Primitive::kPrimInt; }
+
+ // We do all CHA guard elimination/motion in a single pass, after which there is no
+ // further guard elimination/motion since a guard might have been used for justification
+ // of the elimination of another guard. Therefore, we pretend this guard cannot be moved
+ // to avoid other optimizations trying to move it.
bool CanBeMoved() const OVERRIDE { return false; }
DECLARE_INSTRUCTION(ShouldDeoptimizeFlag);
@@ -3786,15 +3825,10 @@ enum IntrinsicExceptions {
kCanThrow // Intrinsic may throw exceptions.
};
-class HInvoke : public HInstruction {
+class HInvoke : public HVariableInputSizeInstruction {
public:
bool NeedsEnvironment() const OVERRIDE;
- using HInstruction::GetInputRecords; // Keep the const version visible.
- ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE {
- return ArrayRef<HUserRecord<HInstruction*>>(inputs_);
- }
-
void SetArgumentAt(size_t index, HInstruction* argument) {
SetRawInputAt(index, argument);
}
@@ -3873,12 +3907,14 @@ class HInvoke : public HInstruction {
uint32_t dex_method_index,
ArtMethod* resolved_method,
InvokeType invoke_type)
- : HInstruction(
- SideEffects::AllExceptGCDependency(), dex_pc), // Assume write/read on all fields/arrays.
+ : HVariableInputSizeInstruction(
+ SideEffects::AllExceptGCDependency(), // Assume write/read on all fields/arrays.
+ dex_pc,
+ arena,
+ number_of_arguments + number_of_other_inputs,
+ kArenaAllocInvokeInputs),
number_of_arguments_(number_of_arguments),
resolved_method_(resolved_method),
- inputs_(number_of_arguments + number_of_other_inputs,
- arena->Adapter(kArenaAllocInvokeInputs)),
dex_method_index_(dex_method_index),
intrinsic_(Intrinsics::kNone),
intrinsic_optimizations_(0) {
@@ -3889,7 +3925,6 @@ class HInvoke : public HInstruction {
uint32_t number_of_arguments_;
ArtMethod* const resolved_method_;
- ArenaVector<HUserRecord<HInstruction*>> inputs_;
const uint32_t dex_method_index_;
Intrinsics intrinsic_;
@@ -3947,12 +3982,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
// Used for app->boot calls with non-relocatable image and for JIT-compiled calls.
kDirectAddress,
- // Use ArtMethod* at an address that will be known at link time, embed the direct
- // address in the code. If the image is relocatable, emit .patch_oat entry.
- // Used for app->boot calls with relocatable image and boot->boot calls, whether
- // the image relocatable or not.
- kDirectAddressWithFixup,
-
// Load from resolved methods array in the dex cache using a PC-relative load.
// Used when we need to use the dex cache, for example for invoke-static that
// may cause class initialization (the entry may point to a resolution method),
@@ -3971,20 +4000,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
// Recursive call, use local PC-relative call instruction.
kCallSelf,
- // Use PC-relative call instruction patched at link time.
- // Used for calls within an oat file, boot->boot or app->app.
- kCallPCRelative,
-
- // Call to a known target address, embed the direct address in code.
- // Used for app->boot call with non-relocatable image and for JIT-compiled calls.
- kCallDirect,
-
- // Call to a target address that will be known at link time, embed the direct
- // address in code. If the image is relocatable, emit .patch_oat entry.
- // Used for app->boot calls with relocatable image and boot->boot calls, whether
- // the image relocatable or not.
- kCallDirectWithFixup,
-
// Use code pointer from the ArtMethod*.
// Used when we don't know the target code. This is also the last-resort-kind used when
// other kinds are unimplemented or impractical (i.e. slow) on a particular architecture.
@@ -4000,7 +4015,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
// - the method address for kDirectAddress
// - the dex cache arrays offset for kDexCachePcRel.
uint64_t method_load_data;
- uint64_t direct_code_ptr;
};
HInvokeStaticOrDirect(ArenaAllocator* arena,
@@ -4110,7 +4124,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
return false;
}
}
- bool HasDirectCodePtr() const { return GetCodePtrLocation() == CodePtrLocation::kCallDirect; }
QuickEntrypointEnum GetStringInitEntryPoint() const {
DCHECK(IsStringInit());
@@ -4127,11 +4140,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
return dispatch_info_.method_load_data;
}
- uint64_t GetDirectCodePtr() const {
- DCHECK(HasDirectCodePtr());
- return dispatch_info_.direct_code_ptr;
- }
-
ClinitCheckRequirement GetClinitCheckRequirement() const {
return GetPackedField<ClinitCheckRequirementField>();
}
@@ -4179,10 +4187,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
DECLARE_INSTRUCTION(InvokeStaticOrDirect);
- protected:
- void InsertInputAt(size_t index, HInstruction* input);
- void RemoveInputAt(size_t index);
-
private:
static constexpr size_t kFieldClinitCheckRequirement = kNumberOfInvokePackedBits;
static constexpr size_t kFieldClinitCheckRequirementSize =
@@ -5493,9 +5497,8 @@ class HLoadClass FINAL : public HInstruction {
// GetIncludePatchInformation().
kBootImageAddress,
- // Load from the resolved types array at an absolute address.
- // Used for classes outside the boot image referenced by JIT-compiled code.
- kDexCacheAddress,
+ // Load from the root table associated with the JIT compiled method.
+ kJitTableAddress,
// Load from resolved types array in the dex cache using a PC-relative load.
// Used for classes outside boot image when we know that we can access
@@ -5515,9 +5518,7 @@ class HLoadClass FINAL : public HInstruction {
const DexFile& dex_file,
bool is_referrers_class,
uint32_t dex_pc,
- bool needs_access_check,
- bool is_in_dex_cache,
- bool is_in_boot_image)
+ bool needs_access_check)
: HInstruction(SideEffectsForArchRuntimeCalls(), dex_pc),
special_input_(HUserRecord<HInstruction*>(current_method)),
type_index_(type_index),
@@ -5530,8 +5531,8 @@ class HLoadClass FINAL : public HInstruction {
SetPackedField<LoadKindField>(
is_referrers_class ? LoadKind::kReferrersClass : LoadKind::kDexCacheViaMethod);
SetPackedFlag<kFlagNeedsAccessCheck>(needs_access_check);
- SetPackedFlag<kFlagIsInDexCache>(is_in_dex_cache);
- SetPackedFlag<kFlagIsInBootImage>(is_in_boot_image);
+ SetPackedFlag<kFlagIsInDexCache>(false);
+ SetPackedFlag<kFlagIsInBootImage>(false);
SetPackedFlag<kFlagGenerateClInitCheck>(false);
}
@@ -5588,7 +5589,6 @@ class HLoadClass FINAL : public HInstruction {
NeedsAccessCheck();
}
-
bool CanThrow() const OVERRIDE {
return CanCallRuntime();
}
@@ -5613,7 +5613,9 @@ class HLoadClass FINAL : public HInstruction {
return load_data_.address;
}
- bool NeedsDexCacheOfDeclaringClass() const OVERRIDE { return !IsReferrersClass(); }
+ bool NeedsDexCacheOfDeclaringClass() const OVERRIDE {
+ return !IsReferrersClass();
+ }
static SideEffects SideEffectsForArchRuntimeCalls() {
return SideEffects::CanTriggerGC();
@@ -5672,7 +5674,8 @@ class HLoadClass FINAL : public HInstruction {
}
static bool HasAddress(LoadKind load_kind) {
- return load_kind == LoadKind::kBootImageAddress || load_kind == LoadKind::kDexCacheAddress;
+ return load_kind == LoadKind::kBootImageAddress ||
+ load_kind == LoadKind::kJitTableAddress;
}
static bool HasDexCacheReference(LoadKind load_kind) {
@@ -5691,7 +5694,7 @@ class HLoadClass FINAL : public HInstruction {
union {
uint32_t dex_cache_element_index; // Only for dex cache reference.
- uint64_t address; // Up to 64-bit, needed for kDexCacheAddress on 64-bit targets.
+ uint64_t address; // Up to 64-bit, needed for kJitTableAddress on 64-bit targets.
} load_data_;
ReferenceTypeInfo loaded_class_rti_;