[optimizing] Don't rely on the verifier for String.<init>.
Continue work on cutting the dependency on the verifier.
Change-Id: I0f95b1eb2e10fd8f6bf54817f1202bdf6dfdb0fe
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 59255d1..b628806 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -38,6 +38,7 @@
class HCurrentMethod;
class HDoubleConstant;
class HEnvironment;
+class HFakeString;
class HFloatConstant;
class HGraphBuilder;
class HGraphVisitor;
@@ -914,6 +915,7 @@
M(DoubleConstant, Constant) \
M(Equal, Condition) \
M(Exit, Instruction) \
+ M(FakeString, Instruction) \
M(FloatConstant, Constant) \
M(Goto, Instruction) \
M(GreaterThan, Condition) \
@@ -1339,8 +1341,7 @@
const uint32_t dex_pc_;
const InvokeType invoke_type_;
- // The instruction that holds this environment. Only used in debug mode
- // to ensure the graph is consistent.
+ // The instruction that holds this environment.
HInstruction* const holder_;
friend class HInstruction;
@@ -2730,9 +2731,11 @@
ClinitCheckRequirement clinit_check_requirement)
: HInvoke(arena,
number_of_arguments,
- // There is one extra argument for the HCurrentMethod node, and
- // potentially one other if the clinit check is explicit.
- clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 2u : 1u,
+ // There is one extra argument for the HCurrentMethod node, and
+ // potentially one other if the clinit check is explicit, and one other
+ // if the method is a string factory.
+ 1u + (clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u)
+ + (string_init_offset ? 1u : 0u),
return_type,
dex_pc,
dex_method_index,
@@ -2777,6 +2780,23 @@
DCHECK(IsStaticWithImplicitClinitCheck());
}
+ bool IsStringFactoryFor(HFakeString* str) const {
+ if (!IsStringInit()) return false;
+ // +1 for the current method.
+ if (InputCount() == (number_of_arguments_ + 1)) return false;
+ return InputAt(InputCount() - 1)->AsFakeString() == str;
+ }
+
+ void RemoveFakeStringArgumentAsLastInput() {
+ DCHECK(IsStringInit());
+ size_t last_input_index = InputCount() - 1;
+ HInstruction* last_input = InputAt(last_input_index);
+ DCHECK(last_input != nullptr);
+ DCHECK(last_input->IsFakeString()) << last_input->DebugName();
+ RemoveAsUserOfInput(last_input_index);
+ inputs_.DeleteAt(last_input_index);
+ }
+
// Is this a call to a static method whose declaring class has an
// explicit intialization check in the graph?
bool IsStaticWithExplicitClinitCheck() const {
@@ -4159,6 +4179,25 @@
DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
};
+/**
+ * A HInstruction used as a marker for the replacement of new + <init>
+ * of a String to a call to a StringFactory. Only baseline will see
+ * the node at code generation, where it will be be treated as null.
+ * When compiling non-baseline, `HFakeString` instructions are being removed
+ * in the instruction simplifier.
+ */
+class HFakeString : public HTemplateInstruction<0> {
+ public:
+ HFakeString() : HTemplateInstruction(SideEffects::None()) {}
+
+ Primitive::Type GetType() const OVERRIDE { return Primitive::kPrimNot; }
+
+ DECLARE_INSTRUCTION(FakeString);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HFakeString);
+};
+
class MoveOperands : public ArenaObject<kArenaAllocMisc> {
public:
MoveOperands(Location source,