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.h52
1 files changed, 47 insertions, 5 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 74a4acae3f..455f4e338d 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -26,6 +26,7 @@
#include "base/arena_object.h"
#include "base/stl_util.h"
#include "dex/compiler_enums.h"
+#include "dex_file.h"
#include "entrypoints/quick/quick_entrypoints_enum.h"
#include "handle.h"
#include "handle_scope.h"
@@ -1930,6 +1931,14 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> {
environment_ = environment;
}
+ void InsertRawEnvironment(HEnvironment* environment) {
+ DCHECK(environment_ != nullptr);
+ DCHECK_EQ(environment->GetHolder(), this);
+ DCHECK(environment->GetParent() == nullptr);
+ environment->parent_ = environment_;
+ environment_ = environment;
+ }
+
void RemoveEnvironment();
// Set the environment of this instruction, copying it from `environment`. While
@@ -5089,8 +5098,13 @@ class HInstanceFieldSet FINAL : public HTemplateInstruction<2> {
class HArrayGet FINAL : public HExpression<2> {
public:
- HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type, uint32_t dex_pc)
+ HArrayGet(HInstruction* array,
+ HInstruction* index,
+ Primitive::Type type,
+ uint32_t dex_pc,
+ bool is_string_char_at = false)
: HExpression(type, SideEffects::ArrayReadOfType(type), dex_pc) {
+ SetPackedFlag<kFlagIsStringCharAt>(is_string_char_at);
SetRawInputAt(0, array);
SetRawInputAt(1, index);
}
@@ -5124,12 +5138,24 @@ class HArrayGet FINAL : public HExpression<2> {
return result;
}
+ bool IsStringCharAt() const { return GetPackedFlag<kFlagIsStringCharAt>(); }
+
HInstruction* GetArray() const { return InputAt(0); }
HInstruction* GetIndex() const { return InputAt(1); }
DECLARE_INSTRUCTION(ArrayGet);
private:
+ // We treat a String as an array, creating the HArrayGet from String.charAt()
+ // intrinsic in the instruction simplifier. We can always determine whether
+ // a particular HArrayGet is actually a String.charAt() by looking at the type
+ // of the input but that requires holding the mutator lock, so we prefer to use
+ // a flag, so that code generators don't need to do the locking.
+ static constexpr size_t kFlagIsStringCharAt = kNumberOfExpressionPackedBits;
+ static constexpr size_t kNumberOfArrayGetPackedBits = kFlagIsStringCharAt + 1;
+ static_assert(kNumberOfArrayGetPackedBits <= HInstruction::kMaxNumberOfPackedBits,
+ "Too many packed fields.");
+
DISALLOW_COPY_AND_ASSIGN(HArrayGet);
};
@@ -5235,8 +5261,9 @@ class HArraySet FINAL : public HTemplateInstruction<3> {
class HArrayLength FINAL : public HExpression<1> {
public:
- HArrayLength(HInstruction* array, uint32_t dex_pc)
+ HArrayLength(HInstruction* array, uint32_t dex_pc, bool is_string_length = false)
: HExpression(Primitive::kPrimInt, SideEffects::None(), dex_pc) {
+ SetPackedFlag<kFlagIsStringLength>(is_string_length);
// Note that arrays do not change length, so the instruction does not
// depend on any write.
SetRawInputAt(0, array);
@@ -5250,7 +5277,6 @@ class HArrayLength FINAL : public HExpression<1> {
return obj == InputAt(0);
}
- void MarkAsStringLength() { SetPackedFlag<kFlagIsStringLength>(); }
bool IsStringLength() const { return GetPackedFlag<kFlagIsStringLength>(); }
DECLARE_INSTRUCTION(ArrayLength);
@@ -5273,8 +5299,12 @@ class HBoundsCheck FINAL : public HExpression<2> {
public:
// `HBoundsCheck` can trigger GC, as it may call the `IndexOutOfBoundsException`
// constructor.
- HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
- : HExpression(index->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
+ HBoundsCheck(HInstruction* index,
+ HInstruction* length,
+ uint32_t dex_pc,
+ uint32_t string_char_at_method_index = DexFile::kDexNoIndex)
+ : HExpression(index->GetType(), SideEffects::CanTriggerGC(), dex_pc),
+ string_char_at_method_index_(string_char_at_method_index) {
DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(index->GetType()));
SetRawInputAt(0, index);
SetRawInputAt(1, length);
@@ -5289,11 +5319,23 @@ class HBoundsCheck FINAL : public HExpression<2> {
bool CanThrow() const OVERRIDE { return true; }
+ bool IsStringCharAt() const { return GetStringCharAtMethodIndex() != DexFile::kDexNoIndex; }
+ uint32_t GetStringCharAtMethodIndex() const { return string_char_at_method_index_; }
+
HInstruction* GetIndex() const { return InputAt(0); }
DECLARE_INSTRUCTION(BoundsCheck);
private:
+ // We treat a String as an array, creating the HBoundsCheck from String.charAt()
+ // intrinsic in the instruction simplifier. We want to include the String.charAt()
+ // in the stack trace if we actually throw the StringIndexOutOfBoundsException,
+ // so we need to create an HEnvironment which will be translated to an InlineInfo
+ // indicating the extra stack frame. Since we add this HEnvironment quite late,
+ // in the PrepareForRegisterAllocation pass, we need to remember the method index
+ // from the invoke as we don't want to look again at the dex bytecode.
+ uint32_t string_char_at_method_index_; // DexFile::kDexNoIndex if regular array.
+
DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
};