#include "dex_file-inl.h"
#include "dex_instruction.h"
#include "dex_instruction-inl.h"
+#include "dex_instruction_utils.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
#include "verifier/method_verifier-inl.h"
namespace art {
+namespace { // anonymous namespace
+
+// Helper class for matching a pattern.
+class Matcher {
+ public:
+ // Match function type.
+ typedef bool MatchFn(Matcher* matcher);
+
+ template <size_t size>
+ static bool Match(const DexFile::CodeItem* code_item, MatchFn* const (&pattern)[size]);
+
+ // Match and advance.
+
+ static bool Mark(Matcher* matcher);
+
+ template <bool (Matcher::*Fn)()>
+ static bool Required(Matcher* matcher);
+
+ template <bool (Matcher::*Fn)()>
+ static bool Repeated(Matcher* matcher); // On match, returns to the mark.
+
+ // Match an individual instruction.
+
+ template <Instruction::Code opcode> bool Opcode();
+ bool Const0();
+ bool IPutOnThis();
+
+ private:
+ explicit Matcher(const DexFile::CodeItem* code_item)
+ : code_item_(code_item),
+ instruction_(Instruction::At(code_item->insns_)),
+ pos_(0u),
+ mark_(0u) { }
+
+ static bool DoMatch(const DexFile::CodeItem* code_item, MatchFn* const* pattern, size_t size);
+
+ const DexFile::CodeItem* const code_item_;
+ const Instruction* instruction_;
+ size_t pos_;
+ size_t mark_;
+};
+
+template <size_t size>
+bool Matcher::Match(const DexFile::CodeItem* code_item, MatchFn* const (&pattern)[size]) {
+ return DoMatch(code_item, pattern, size);
+}
+
+bool Matcher::Mark(Matcher* matcher) {
+ matcher->pos_ += 1u; // Advance to the next match function before marking.
+ matcher->mark_ = matcher->pos_;
+ return true;
+}
+
+template <bool (Matcher::*Fn)()>
+bool Matcher::Required(Matcher* matcher) {
+ if (!(matcher->*Fn)()) {
+ return false;
+ }
+ matcher->pos_ += 1u;
+ matcher->instruction_ = matcher->instruction_->Next();
+ return true;
+}
+
+template <bool (Matcher::*Fn)()>
+bool Matcher::Repeated(Matcher* matcher) {
+ if (!(matcher->*Fn)()) {
+ // Didn't match optional instruction, try the next match function.
+ matcher->pos_ += 1u;
+ return true;
+ }
+ matcher->pos_ = matcher->mark_;
+ matcher->instruction_ = matcher->instruction_->Next();
+ return true;
+}
+
+template <Instruction::Code opcode>
+bool Matcher::Opcode() {
+ return instruction_->Opcode() == opcode;
+}
+
+// Match const 0.
+bool Matcher::Const0() {
+ return IsInstructionDirectConst(instruction_->Opcode()) &&
+ (instruction_->Opcode() == Instruction::CONST_WIDE ? instruction_->VRegB_51l() == 0
+ : instruction_->VRegB() == 0);
+}
+
+bool Matcher::IPutOnThis() {
+ DCHECK_NE(code_item_->ins_size_, 0u);
+ return IsInstructionIPut(instruction_->Opcode()) &&
+ instruction_->VRegB_22c() == code_item_->registers_size_ - code_item_->ins_size_;
+}
+
+bool Matcher::DoMatch(const DexFile::CodeItem* code_item, MatchFn* const* pattern, size_t size) {
+ Matcher matcher(code_item);
+ while (matcher.pos_ != size) {
+ if (!pattern[matcher.pos_](&matcher)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Used for a single invoke in a constructor. In that situation, the method verifier makes
+// sure we invoke a constructor either in the same class or superclass with at least "this".
+ArtMethod* GetTargetConstructor(ArtMethod* method, const Instruction* invoke_direct)
+ SHARED_REQUIRES(Locks::mutator_lock_) {
+ DCHECK_EQ(invoke_direct->Opcode(), Instruction::INVOKE_DIRECT);
+ DCHECK_EQ(invoke_direct->VRegC_35c(),
+ method->GetCodeItem()->registers_size_ - method->GetCodeItem()->ins_size_);
+ uint32_t method_index = invoke_direct->VRegB_35c();
+ size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+ ArtMethod* target_method =
+ method->GetDexCache()->GetResolvedMethod(method_index, pointer_size);
+ if (kIsDebugBuild && target_method != nullptr) {
+ CHECK(!target_method->IsStatic());
+ CHECK(target_method->IsConstructor());
+ CHECK(target_method->GetDeclaringClass() == method->GetDeclaringClass() ||
+ target_method->GetDeclaringClass() == method->GetDeclaringClass()->GetSuperClass());
+ }
+ return target_method;
+}
+
+// Return the forwarded arguments and check that all remaining arguments are zero.
+// If the check fails, return static_cast<size_t>(-1).
+size_t CountForwardedConstructorArguments(const DexFile::CodeItem* code_item,
+ const Instruction* invoke_direct,
+ uint16_t zero_vreg_mask) {
+ DCHECK_EQ(invoke_direct->Opcode(), Instruction::INVOKE_DIRECT);
+ size_t number_of_args = invoke_direct->VRegA_35c();
+ DCHECK_NE(number_of_args, 0u);
+ uint32_t args[Instruction::kMaxVarArgRegs];
+ invoke_direct->GetVarArgs(args);
+ uint16_t this_vreg = args[0];
+ DCHECK_EQ(this_vreg, code_item->registers_size_ - code_item->ins_size_); // Checked by verifier.
+ size_t forwarded = 1u;
+ while (forwarded < number_of_args &&
+ args[forwarded] == this_vreg + forwarded &&
+ (zero_vreg_mask & (1u << args[forwarded])) == 0) {
+ ++forwarded;
+ }
+ for (size_t i = forwarded; i != number_of_args; ++i) {
+ if ((zero_vreg_mask & (1u << args[i])) == 0) {
+ return static_cast<size_t>(-1);
+ }
+ }
+ return forwarded;
+}
+
+uint16_t GetZeroVRegMask(const Instruction* const0) {
+ DCHECK(IsInstructionDirectConst(const0->Opcode()));
+ DCHECK((const0->Opcode() == Instruction::CONST_WIDE) ? const0->VRegB_51l() == 0u
+ : const0->VRegB() == 0);
+ uint16_t base_mask = IsInstructionConstWide(const0->Opcode()) ? 3u : 1u;
+ return base_mask << const0->VRegA();
+}
+
+// We limit the number of IPUTs storing parameters. There can be any number
+// of IPUTs that store the value 0 as they are useless in a constructor as
+// the object always starts zero-initialized. We also eliminate all but the
+// last store to any field as they are not observable; not even if the field
+// is volatile as no reference to the object can escape from a constructor
+// with this pattern.
+static constexpr size_t kMaxConstructorIPuts = 3u;
+
+struct ConstructorIPutData {
+ ConstructorIPutData() : field_index(DexFile::kDexNoIndex16), arg(0u) { }
+
+ uint16_t field_index;
+ uint16_t arg;
+};
+
+bool RecordConstructorIPut(ArtMethod* method,
+ const Instruction* new_iput,
+ uint16_t this_vreg,
+ uint16_t zero_vreg_mask,
+ /*inout*/ ConstructorIPutData (&iputs)[kMaxConstructorIPuts])
+ SHARED_REQUIRES(Locks::mutator_lock_) {
+ DCHECK(IsInstructionIPut(new_iput->Opcode()));
+ uint32_t field_index = new_iput->VRegC_22c();
+ size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+ mirror::DexCache* dex_cache = method->GetDexCache();
+ ArtField* field = dex_cache->GetResolvedField(field_index, pointer_size);
+ if (UNLIKELY(field == nullptr)) {
+ return false;
+ }
+ // Remove previous IPUT to the same field, if any. Different field indexes may refer
+ // to the same field, so we need to compare resolved fields from the dex cache.
+ for (size_t old_pos = 0; old_pos != arraysize(iputs); ++old_pos) {
+ if (iputs[old_pos].field_index == DexFile::kDexNoIndex16) {
+ break;
+ }
+ ArtField* f = dex_cache->GetResolvedField(iputs[old_pos].field_index, pointer_size);
+ DCHECK(f != nullptr);
+ if (f == field) {
+ auto back_it = std::copy(iputs + old_pos + 1, iputs + arraysize(iputs), iputs + old_pos);
+ *back_it = ConstructorIPutData();
+ break;
+ }
+ }
+ // If the stored value isn't zero, record the IPUT.
+ if ((zero_vreg_mask & (1u << new_iput->VRegA_22c())) == 0u) {
+ size_t new_pos = 0;
+ while (new_pos != arraysize(iputs) && iputs[new_pos].field_index != DexFile::kDexNoIndex16) {
+ ++new_pos;
+ }
+ if (new_pos == arraysize(iputs)) {
+ return false; // Exceeded capacity of the output array.
+ }
+ iputs[new_pos].field_index = field_index;
+ iputs[new_pos].arg = new_iput->VRegA_22c() - this_vreg;
+ }
+ return true;
+}
+
+bool DoAnalyseConstructor(const DexFile::CodeItem* code_item,
+ ArtMethod* method,
+ /*inout*/ ConstructorIPutData (&iputs)[kMaxConstructorIPuts])
+ SHARED_REQUIRES(Locks::mutator_lock_) {
+ // On entry we should not have any IPUTs yet.
+ DCHECK_EQ(0, std::count_if(
+ iputs,
+ iputs + arraysize(iputs),
+ [](const ConstructorIPutData& iput_data) {
+ return iput_data.field_index != DexFile::kDexNoIndex16;
+ }));
+
+ // Limit the maximum number of code units we're willing to match.
+ static constexpr size_t kMaxCodeUnits = 16u;
+
+ // Limit the number of registers that the constructor may use to 16.
+ // Given that IPUTs must use low 16 registers and we do not match MOVEs,
+ // this is a reasonable limitation.
+ static constexpr size_t kMaxVRegs = 16u;
+
+ // We try to match a constructor that calls another constructor (either in
+ // superclass or in the same class) with the same parameters, or with some
+ // parameters truncated (allowed only for calls to superclass constructor)
+ // or with extra parameters with value 0 (with any type, including null).
+ // This call can be followed by optional IPUTs on "this" storing either one
+ // of the parameters or 0 and the code must then finish with RETURN_VOID.
+ // The called constructor must be either java.lang.Object.<init>() or it
+ // must also match the same pattern.
+ static Matcher::MatchFn* const kConstructorPattern[] = {
+ &Matcher::Mark,
+ &Matcher::Repeated<&Matcher::Const0>,
+ &Matcher::Required<&Matcher::Opcode<Instruction::INVOKE_DIRECT>>,
+ &Matcher::Mark,
+ &Matcher::Repeated<&Matcher::Const0>,
+ &Matcher::Repeated<&Matcher::IPutOnThis>,
+ &Matcher::Required<&Matcher::Opcode<Instruction::RETURN_VOID>>,
+ };
+
+ DCHECK(method != nullptr);
+ DCHECK(!method->IsStatic());
+ DCHECK(method->IsConstructor());
+ DCHECK(code_item != nullptr);
+ if (!method->GetDeclaringClass()->IsVerified() ||
+ code_item->insns_size_in_code_units_ > kMaxCodeUnits ||
+ code_item->registers_size_ > kMaxVRegs ||
+ !Matcher::Match(code_item, kConstructorPattern)) {
+ return false;
+ }
+
+ // Verify the invoke, prevent a few odd cases and collect IPUTs.
+ uint16_t this_vreg = code_item->registers_size_ - code_item->ins_size_;
+ uint16_t zero_vreg_mask = 0u;
+ for (const Instruction* instruction = Instruction::At(code_item->insns_);
+ instruction->Opcode() != Instruction::RETURN_VOID;
+ instruction = instruction->Next()) {
+ if (instruction->Opcode() == Instruction::INVOKE_DIRECT) {
+ ArtMethod* target_method = GetTargetConstructor(method, instruction);
+ if (target_method == nullptr) {
+ return false;
+ }
+ // We allow forwarding constructors only if they pass more arguments
+ // to prevent infinite recursion.
+ if (target_method->GetDeclaringClass() == method->GetDeclaringClass() &&
+ instruction->VRegA_35c() <= code_item->ins_size_) {
+ return false;
+ }
+ size_t forwarded = CountForwardedConstructorArguments(code_item, instruction, zero_vreg_mask);
+ if (forwarded == static_cast<size_t>(-1)) {
+ return false;
+ }
+ if (target_method->GetDeclaringClass()->IsObjectClass()) {
+ DCHECK_EQ(Instruction::At(target_method->GetCodeItem()->insns_)->Opcode(),
+ Instruction::RETURN_VOID);
+ } else {
+ const DexFile::CodeItem* target_code_item = target_method->GetCodeItem();
+ if (target_code_item == nullptr) {
+ return false; // Native constructor?
+ }
+ if (!DoAnalyseConstructor(target_code_item, target_method, iputs)) {
+ return false;
+ }
+ // Prune IPUTs with zero input.
+ auto kept_end = std::remove_if(
+ iputs,
+ iputs + arraysize(iputs),
+ [forwarded](const ConstructorIPutData& iput_data) {
+ return iput_data.arg >= forwarded;
+ });
+ std::fill(kept_end, iputs + arraysize(iputs), ConstructorIPutData());
+ // If we have any IPUTs from the call, check that the target method is in the same
+ // dex file (compare DexCache references), otherwise field_indexes would be bogus.
+ if (iputs[0].field_index != DexFile::kDexNoIndex16 &&
+ target_method->GetDexCache() != method->GetDexCache()) {
+ return false;
+ }
+ }
+ } else if (IsInstructionDirectConst(instruction->Opcode())) {
+ zero_vreg_mask |= GetZeroVRegMask(instruction);
+ if ((zero_vreg_mask & (1u << this_vreg)) != 0u) {
+ return false; // Overwriting `this` is unsupported.
+ }
+ } else {
+ DCHECK(IsInstructionIPut(instruction->Opcode()));
+ DCHECK_EQ(instruction->VRegB_22c(), this_vreg);
+ if (!RecordConstructorIPut(method, instruction, this_vreg, zero_vreg_mask, iputs)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+} // anonymous namespace
+
+bool AnalyseConstructor(const DexFile::CodeItem* code_item,
+ ArtMethod* method,
+ InlineMethod* result)
+ SHARED_REQUIRES(Locks::mutator_lock_) {
+ ConstructorIPutData iputs[kMaxConstructorIPuts];
+ if (!DoAnalyseConstructor(code_item, method, iputs)) {
+ return false;
+ }
+ static_assert(kMaxConstructorIPuts == 3, "Unexpected limit"); // Code below depends on this.
+ DCHECK(iputs[0].field_index != DexFile::kDexNoIndex16 ||
+ iputs[1].field_index == DexFile::kDexNoIndex16);
+ DCHECK(iputs[1].field_index != DexFile::kDexNoIndex16 ||
+ iputs[2].field_index == DexFile::kDexNoIndex16);
+
+#define STORE_IPUT(n) \
+ do { \
+ result->d.constructor_data.iput##n##_field_index = iputs[n].field_index; \
+ result->d.constructor_data.iput##n##_arg = iputs[n].arg; \
+ } while (false)
+
+ STORE_IPUT(0);
+ STORE_IPUT(1);
+ STORE_IPUT(2);
+#undef STORE_IPUT
+
+ result->opcode = kInlineOpConstructor;
+ result->flags = kInlineSpecial;
+ result->d.constructor_data.reserved = 0u;
+ return true;
+}
+
static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET), "iget type");
static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_WIDE), "iget_wide type");
static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_OBJECT),
case Instruction::CONST_16:
case Instruction::CONST_HIGH16:
// TODO: Support wide constants (RETURN_WIDE).
- return AnalyseConstMethod(code_item, result);
+ if (AnalyseConstMethod(code_item, result)) {
+ return true;
+ }
+ FALLTHROUGH_INTENDED;
+ case Instruction::CONST_WIDE:
+ case Instruction::CONST_WIDE_16:
+ case Instruction::CONST_WIDE_32:
+ case Instruction::CONST_WIDE_HIGH16:
+ case Instruction::INVOKE_DIRECT:
+ if (method != nullptr && !method->IsStatic() && method->IsConstructor()) {
+ return AnalyseConstructor(code_item, method, result);
+ }
+ return false;
case Instruction::IGET:
case Instruction::IGET_OBJECT:
case Instruction::IGET_BOOLEAN:
*/
public class Main {
- /// CHECK-START: void Main.staticNop() inliner (before)
- /// CHECK: InvokeStaticOrDirect
+ /// CHECK-START: void Main.staticNop() inliner (before)
+ /// CHECK: InvokeStaticOrDirect
- /// CHECK-START: void Main.staticNop() inliner (after)
- /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-START: void Main.staticNop() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
- public static void staticNop() {
- Second.staticNop(11);
- }
-
- /// CHECK-START: void Main.nop(Second) inliner (before)
- /// CHECK: InvokeVirtual
-
- /// CHECK-START: void Main.nop(Second) inliner (after)
- /// CHECK-NOT: InvokeVirtual
-
- public static void nop(Second s) {
- s.nop();
- }
-
- /// CHECK-START: java.lang.Object Main.staticReturnArg2(java.lang.String) inliner (before)
- /// CHECK-DAG: <<Value:l\d+>> ParameterValue
- /// CHECK-DAG: <<Ignored:i\d+>> IntConstant 77
- /// CHECK-DAG: <<ClinitCk:l\d+>> ClinitCheck
- // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
- /// CHECK-DAG: <<Invoke:l\d+>> InvokeStaticOrDirect [<<Ignored>>,<<Value>>{{(,[ij]\d+)?}},<<ClinitCk>>]
- /// CHECK-DAG: Return [<<Invoke>>]
+ public static void staticNop() {
+ Second.staticNop(11);
+ }
- /// CHECK-START: java.lang.Object Main.staticReturnArg2(java.lang.String) inliner (after)
- /// CHECK-DAG: <<Value:l\d+>> ParameterValue
- /// CHECK-DAG: Return [<<Value>>]
+ /// CHECK-START: void Main.nop(Second) inliner (before)
+ /// CHECK: InvokeVirtual
- /// CHECK-START: java.lang.Object Main.staticReturnArg2(java.lang.String) inliner (after)
- /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-START: void Main.nop(Second) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- public static Object staticReturnArg2(String value) {
- return Second.staticReturnArg2(77, value);
- }
+ public static void nop(Second s) {
+ s.nop();
+ }
- /// CHECK-START: long Main.returnArg1(Second, long) inliner (before)
- /// CHECK-DAG: <<Second:l\d+>> ParameterValue
- /// CHECK-DAG: <<Value:j\d+>> ParameterValue
- /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<Second>>]
- /// CHECK-DAG: <<Invoke:j\d+>> InvokeVirtual [<<NullCk>>,<<Value>>]
- /// CHECK-DAG: Return [<<Invoke>>]
+ /// CHECK-START: java.lang.Object Main.staticReturnArg2(java.lang.String) inliner (before)
+ /// CHECK-DAG: <<Value:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Ignored:i\d+>> IntConstant 77
+ /// CHECK-DAG: <<ClinitCk:l\d+>> ClinitCheck
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: <<Invoke:l\d+>> InvokeStaticOrDirect [<<Ignored>>,<<Value>>{{(,[ij]\d+)?}},<<ClinitCk>>]
+ /// CHECK-DAG: Return [<<Invoke>>]
- /// CHECK-START: long Main.returnArg1(Second, long) inliner (after)
- /// CHECK-DAG: <<Value:j\d+>> ParameterValue
- /// CHECK-DAG: Return [<<Value>>]
+ /// CHECK-START: java.lang.Object Main.staticReturnArg2(java.lang.String) inliner (after)
+ /// CHECK-DAG: <<Value:l\d+>> ParameterValue
+ /// CHECK-DAG: Return [<<Value>>]
- /// CHECK-START: long Main.returnArg1(Second, long) inliner (after)
- /// CHECK-NOT: InvokeVirtual
+ /// CHECK-START: java.lang.Object Main.staticReturnArg2(java.lang.String) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
- public static long returnArg1(Second s, long value) {
- return s.returnArg1(value);
- }
+ public static Object staticReturnArg2(String value) {
+ return Second.staticReturnArg2(77, value);
+ }
- /// CHECK-START: int Main.staticReturn9() inliner (before)
- /// CHECK: {{i\d+}} InvokeStaticOrDirect
+ /// CHECK-START: long Main.returnArg1(Second, long) inliner (before)
+ /// CHECK-DAG: <<Second:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Value:j\d+>> ParameterValue
+ /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<Second>>]
+ /// CHECK-DAG: <<Invoke:j\d+>> InvokeVirtual [<<NullCk>>,<<Value>>]
+ /// CHECK-DAG: Return [<<Invoke>>]
- /// CHECK-START: int Main.staticReturn9() inliner (before)
- /// CHECK-NOT: IntConstant 9
+ /// CHECK-START: long Main.returnArg1(Second, long) inliner (after)
+ /// CHECK-DAG: <<Value:j\d+>> ParameterValue
+ /// CHECK-DAG: Return [<<Value>>]
- /// CHECK-START: int Main.staticReturn9() inliner (after)
- /// CHECK-DAG: <<Const9:i\d+>> IntConstant 9
- /// CHECK-DAG: Return [<<Const9>>]
+ /// CHECK-START: long Main.returnArg1(Second, long) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- /// CHECK-START: int Main.staticReturn9() inliner (after)
- /// CHECK-NOT: InvokeStaticOrDirect
+ public static long returnArg1(Second s, long value) {
+ return s.returnArg1(value);
+ }
- public static int staticReturn9() {
- return Second.staticReturn9();
- }
-
- /// CHECK-START: int Main.return7(Second) inliner (before)
- /// CHECK: {{i\d+}} InvokeVirtual
-
- /// CHECK-START: int Main.return7(Second) inliner (before)
- /// CHECK-NOT: IntConstant 7
-
- /// CHECK-START: int Main.return7(Second) inliner (after)
- /// CHECK-DAG: <<Const7:i\d+>> IntConstant 7
- /// CHECK-DAG: Return [<<Const7>>]
-
- /// CHECK-START: int Main.return7(Second) inliner (after)
- /// CHECK-NOT: InvokeVirtual
-
- public static int return7(Second s) {
- return s.return7(null);
- }
+ /// CHECK-START: int Main.staticReturn9() inliner (before)
+ /// CHECK: {{i\d+}} InvokeStaticOrDirect
- /// CHECK-START: java.lang.String Main.staticReturnNull() inliner (before)
- /// CHECK: {{l\d+}} InvokeStaticOrDirect
+ /// CHECK-START: int Main.staticReturn9() inliner (before)
+ /// CHECK-NOT: IntConstant 9
- /// CHECK-START: java.lang.String Main.staticReturnNull() inliner (before)
- /// CHECK-NOT: NullConstant
+ /// CHECK-START: int Main.staticReturn9() inliner (after)
+ /// CHECK-DAG: <<Const9:i\d+>> IntConstant 9
+ /// CHECK-DAG: Return [<<Const9>>]
- /// CHECK-START: java.lang.String Main.staticReturnNull() inliner (after)
- /// CHECK-DAG: <<Null:l\d+>> NullConstant
- /// CHECK-DAG: Return [<<Null>>]
+ /// CHECK-START: int Main.staticReturn9() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
- /// CHECK-START: java.lang.String Main.staticReturnNull() inliner (after)
- /// CHECK-NOT: InvokeStaticOrDirect
+ public static int staticReturn9() {
+ return Second.staticReturn9();
+ }
- public static String staticReturnNull() {
- return Second.staticReturnNull();
- }
+ /// CHECK-START: int Main.return7(Second) inliner (before)
+ /// CHECK: {{i\d+}} InvokeVirtual
- /// CHECK-START: java.lang.Object Main.returnNull(Second) inliner (before)
- /// CHECK: {{l\d+}} InvokeVirtual
+ /// CHECK-START: int Main.return7(Second) inliner (before)
+ /// CHECK-NOT: IntConstant 7
- /// CHECK-START: java.lang.Object Main.returnNull(Second) inliner (before)
- /// CHECK-NOT: NullConstant
+ /// CHECK-START: int Main.return7(Second) inliner (after)
+ /// CHECK-DAG: <<Const7:i\d+>> IntConstant 7
+ /// CHECK-DAG: Return [<<Const7>>]
- /// CHECK-START: java.lang.Object Main.returnNull(Second) inliner (after)
- /// CHECK-DAG: <<Null:l\d+>> NullConstant
- /// CHECK-DAG: Return [<<Null>>]
+ /// CHECK-START: int Main.return7(Second) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- /// CHECK-START: java.lang.Object Main.returnNull(Second) inliner (after)
- /// CHECK-NOT: InvokeVirtual
+ public static int return7(Second s) {
+ return s.return7(null);
+ }
- public static Object returnNull(Second s) {
- return s.returnNull();
- }
+ /// CHECK-START: java.lang.String Main.staticReturnNull() inliner (before)
+ /// CHECK: {{l\d+}} InvokeStaticOrDirect
- /// CHECK-START: int Main.getInt(Second) inliner (before)
- /// CHECK: {{i\d+}} InvokeVirtual
+ /// CHECK-START: java.lang.String Main.staticReturnNull() inliner (before)
+ /// CHECK-NOT: NullConstant
- /// CHECK-START: int Main.getInt(Second) inliner (after)
- /// CHECK: {{i\d+}} InstanceFieldGet
+ /// CHECK-START: java.lang.String Main.staticReturnNull() inliner (after)
+ /// CHECK-DAG: <<Null:l\d+>> NullConstant
+ /// CHECK-DAG: Return [<<Null>>]
- /// CHECK-START: int Main.getInt(Second) inliner (after)
- /// CHECK-NOT: InvokeVirtual
+ /// CHECK-START: java.lang.String Main.staticReturnNull() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
- public static int getInt(Second s) {
- return s.getInstanceIntField();
- }
+ public static String staticReturnNull() {
+ return Second.staticReturnNull();
+ }
- /// CHECK-START: double Main.getDouble(Second) inliner (before)
- /// CHECK: {{d\d+}} InvokeVirtual
+ /// CHECK-START: java.lang.Object Main.returnNull(Second) inliner (before)
+ /// CHECK: {{l\d+}} InvokeVirtual
- /// CHECK-START: double Main.getDouble(Second) inliner (after)
- /// CHECK: {{d\d+}} InstanceFieldGet
+ /// CHECK-START: java.lang.Object Main.returnNull(Second) inliner (before)
+ /// CHECK-NOT: NullConstant
- /// CHECK-START: double Main.getDouble(Second) inliner (after)
- /// CHECK-NOT: InvokeVirtual
+ /// CHECK-START: java.lang.Object Main.returnNull(Second) inliner (after)
+ /// CHECK-DAG: <<Null:l\d+>> NullConstant
+ /// CHECK-DAG: Return [<<Null>>]
- public static double getDouble(Second s) {
- return s.getInstanceDoubleField(22);
- }
+ /// CHECK-START: java.lang.Object Main.returnNull(Second) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- /// CHECK-START: java.lang.Object Main.getObject(Second) inliner (before)
- /// CHECK: {{l\d+}} InvokeVirtual
+ public static Object returnNull(Second s) {
+ return s.returnNull();
+ }
- /// CHECK-START: java.lang.Object Main.getObject(Second) inliner (after)
- /// CHECK: {{l\d+}} InstanceFieldGet
+ /// CHECK-START: int Main.getInt(Second) inliner (before)
+ /// CHECK: {{i\d+}} InvokeVirtual
- /// CHECK-START: java.lang.Object Main.getObject(Second) inliner (after)
- /// CHECK-NOT: InvokeVirtual
+ /// CHECK-START: int Main.getInt(Second) inliner (after)
+ /// CHECK: {{i\d+}} InstanceFieldGet
- public static Object getObject(Second s) {
- return s.getInstanceObjectField(-1L);
- }
+ /// CHECK-START: int Main.getInt(Second) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- /// CHECK-START: java.lang.String Main.getString(Second) inliner (before)
- /// CHECK: {{l\d+}} InvokeVirtual
+ public static int getInt(Second s) {
+ return s.getInstanceIntField();
+ }
- /// CHECK-START: java.lang.String Main.getString(Second) inliner (after)
- /// CHECK: {{l\d+}} InstanceFieldGet
+ /// CHECK-START: double Main.getDouble(Second) inliner (before)
+ /// CHECK: {{d\d+}} InvokeVirtual
- /// CHECK-START: java.lang.String Main.getString(Second) inliner (after)
- /// CHECK-NOT: InvokeVirtual
+ /// CHECK-START: double Main.getDouble(Second) inliner (after)
+ /// CHECK: {{d\d+}} InstanceFieldGet
- public static String getString(Second s) {
- return s.getInstanceStringField(null, "whatever", 1234L);
- }
+ /// CHECK-START: double Main.getDouble(Second) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- /// CHECK-START: int Main.staticGetInt(Second) inliner (before)
- /// CHECK: {{i\d+}} InvokeStaticOrDirect
+ public static double getDouble(Second s) {
+ return s.getInstanceDoubleField(22);
+ }
- /// CHECK-START: int Main.staticGetInt(Second) inliner (after)
- /// CHECK: {{i\d+}} InvokeStaticOrDirect
+ /// CHECK-START: java.lang.Object Main.getObject(Second) inliner (before)
+ /// CHECK: {{l\d+}} InvokeVirtual
- /// CHECK-START: int Main.staticGetInt(Second) inliner (after)
- /// CHECK-NOT: InstanceFieldGet
+ /// CHECK-START: java.lang.Object Main.getObject(Second) inliner (after)
+ /// CHECK: {{l\d+}} InstanceFieldGet
- public static int staticGetInt(Second s) {
- return Second.staticGetInstanceIntField(s);
- }
+ /// CHECK-START: java.lang.Object Main.getObject(Second) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- /// CHECK-START: double Main.getDoubleFromParam(Second) inliner (before)
- /// CHECK: {{d\d+}} InvokeVirtual
+ public static Object getObject(Second s) {
+ return s.getInstanceObjectField(-1L);
+ }
- /// CHECK-START: double Main.getDoubleFromParam(Second) inliner (after)
- /// CHECK: {{d\d+}} InvokeVirtual
+ /// CHECK-START: java.lang.String Main.getString(Second) inliner (before)
+ /// CHECK: {{l\d+}} InvokeVirtual
- /// CHECK-START: double Main.getDoubleFromParam(Second) inliner (after)
- /// CHECK-NOT: InstanceFieldGet
+ /// CHECK-START: java.lang.String Main.getString(Second) inliner (after)
+ /// CHECK: {{l\d+}} InstanceFieldGet
- public static double getDoubleFromParam(Second s) {
- return s.getInstanceDoubleFieldFromParam(s);
- }
+ /// CHECK-START: java.lang.String Main.getString(Second) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- /// CHECK-START: int Main.getStaticInt(Second) inliner (before)
- /// CHECK: {{i\d+}} InvokeVirtual
+ public static String getString(Second s) {
+ return s.getInstanceStringField(null, "whatever", 1234L);
+ }
- /// CHECK-START: int Main.getStaticInt(Second) inliner (after)
- /// CHECK: {{i\d+}} InvokeVirtual
+ /// CHECK-START: int Main.staticGetInt(Second) inliner (before)
+ /// CHECK: {{i\d+}} InvokeStaticOrDirect
- /// CHECK-START: int Main.getStaticInt(Second) inliner (after)
- /// CHECK-NOT: InstanceFieldGet
- /// CHECK-NOT: StaticFieldGet
+ /// CHECK-START: int Main.staticGetInt(Second) inliner (after)
+ /// CHECK: {{i\d+}} InvokeStaticOrDirect
- public static int getStaticInt(Second s) {
- return s.getStaticIntField();
- }
+ /// CHECK-START: int Main.staticGetInt(Second) inliner (after)
+ /// CHECK-NOT: InstanceFieldGet
- /// CHECK-START: long Main.setLong(Second, long) inliner (before)
- /// CHECK: InvokeVirtual
+ public static int staticGetInt(Second s) {
+ return Second.staticGetInstanceIntField(s);
+ }
- /// CHECK-START: long Main.setLong(Second, long) inliner (after)
- /// CHECK: InstanceFieldSet
+ /// CHECK-START: double Main.getDoubleFromParam(Second) inliner (before)
+ /// CHECK: {{d\d+}} InvokeVirtual
- /// CHECK-START: long Main.setLong(Second, long) inliner (after)
- /// CHECK-NOT: InvokeVirtual
+ /// CHECK-START: double Main.getDoubleFromParam(Second) inliner (after)
+ /// CHECK: {{d\d+}} InvokeVirtual
- public static long setLong(Second s, long value) {
- s.setInstanceLongField(-1, value);
- return s.instanceLongField;
- }
+ /// CHECK-START: double Main.getDoubleFromParam(Second) inliner (after)
+ /// CHECK-NOT: InstanceFieldGet
- /// CHECK-START: long Main.setLongReturnArg2(Second, long, int) inliner (before)
- /// CHECK: InvokeVirtual
-
- /// CHECK-START: long Main.setLongReturnArg2(Second, long, int) inliner (after)
- /// CHECK-DAG: <<Second:l\d+>> ParameterValue
- /// CHECK-DAG: <<Value:j\d+>> ParameterValue
- /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue
- /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<Second>>]
- /// CHECK-DAG: InstanceFieldSet [<<NullCk>>,<<Value>>]
- /// CHECK-DAG: <<NullCk2:l\d+>> NullCheck [<<Second>>]
- /// CHECK-DAG: <<IGet:j\d+>> InstanceFieldGet [<<NullCk2>>]
- /// CHECK-DAG: <<Conv:j\d+>> TypeConversion [<<Arg2>>]
- /// CHECK-DAG: <<Add:j\d+>> Add [<<IGet>>,<<Conv>>]
- /// CHECK-DAG: Return [<<Add>>]
-
- /// CHECK-START: long Main.setLongReturnArg2(Second, long, int) inliner (after)
- /// CHECK-NOT: InvokeVirtual
-
- public static long setLongReturnArg2(Second s, long value, int arg2) {
- int result = s.setInstanceLongFieldReturnArg2(value, arg2);
- return s.instanceLongField + result;
- }
+ public static double getDoubleFromParam(Second s) {
+ return s.getInstanceDoubleFieldFromParam(s);
+ }
- /// CHECK-START: long Main.staticSetLong(Second, long) inliner (before)
- /// CHECK: InvokeStaticOrDirect
+ /// CHECK-START: int Main.getStaticInt(Second) inliner (before)
+ /// CHECK: {{i\d+}} InvokeVirtual
- /// CHECK-START: long Main.staticSetLong(Second, long) inliner (after)
- /// CHECK: InvokeStaticOrDirect
+ /// CHECK-START: int Main.getStaticInt(Second) inliner (after)
+ /// CHECK: {{i\d+}} InvokeVirtual
- /// CHECK-START: long Main.staticSetLong(Second, long) inliner (after)
- /// CHECK-NOT: InstanceFieldSet
+ /// CHECK-START: int Main.getStaticInt(Second) inliner (after)
+ /// CHECK-NOT: InstanceFieldGet
+ /// CHECK-NOT: StaticFieldGet
- public static long staticSetLong(Second s, long value) {
- Second.staticSetInstanceLongField(s, value);
- return s.instanceLongField;
- }
+ public static int getStaticInt(Second s) {
+ return s.getStaticIntField();
+ }
- /// CHECK-START: long Main.setLongThroughParam(Second, long) inliner (before)
- /// CHECK: InvokeVirtual
+ /// CHECK-START: long Main.setLong(Second, long) inliner (before)
+ /// CHECK: InvokeVirtual
- /// CHECK-START: long Main.setLongThroughParam(Second, long) inliner (after)
- /// CHECK: InvokeVirtual
+ /// CHECK-START: long Main.setLong(Second, long) inliner (after)
+ /// CHECK: InstanceFieldSet
- /// CHECK-START: long Main.setLongThroughParam(Second, long) inliner (after)
- /// CHECK-NOT: InstanceFieldSet
+ /// CHECK-START: long Main.setLong(Second, long) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- public static long setLongThroughParam(Second s, long value) {
- s.setInstanceLongFieldThroughParam(s, value);
- return s.instanceLongField;
- }
+ public static long setLong(Second s, long value) {
+ s.setInstanceLongField(-1, value);
+ return s.instanceLongField;
+ }
- /// CHECK-START: float Main.setStaticFloat(Second, float) inliner (before)
- /// CHECK: InvokeVirtual
+ /// CHECK-START: long Main.setLongReturnArg2(Second, long, int) inliner (before)
+ /// CHECK: InvokeVirtual
- /// CHECK-START: float Main.setStaticFloat(Second, float) inliner (after)
- /// CHECK: InvokeVirtual
+ /// CHECK-START: long Main.setLongReturnArg2(Second, long, int) inliner (after)
+ /// CHECK-DAG: <<Second:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Value:j\d+>> ParameterValue
+ /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue
+ /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<Second>>]
+ /// CHECK-DAG: InstanceFieldSet [<<NullCk>>,<<Value>>]
+ /// CHECK-DAG: <<NullCk2:l\d+>> NullCheck [<<Second>>]
+ /// CHECK-DAG: <<IGet:j\d+>> InstanceFieldGet [<<NullCk2>>]
+ /// CHECK-DAG: <<Conv:j\d+>> TypeConversion [<<Arg2>>]
+ /// CHECK-DAG: <<Add:j\d+>> Add [<<IGet>>,<<Conv>>]
+ /// CHECK-DAG: Return [<<Add>>]
- /// CHECK-START: float Main.setStaticFloat(Second, float) inliner (after)
- /// CHECK-NOT: InstanceFieldSet
- /// CHECK-NOT: StaticFieldSet
+ /// CHECK-START: long Main.setLongReturnArg2(Second, long, int) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
- public static float setStaticFloat(Second s, float value) {
- s.setStaticFloatField(value);
- return s.staticFloatField;
- }
+ public static long setLongReturnArg2(Second s, long value, int arg2) {
+ int result = s.setInstanceLongFieldReturnArg2(value, arg2);
+ return s.instanceLongField + result;
+ }
- /// CHECK-START: java.lang.Object Main.newObject() inliner (before)
- /// CHECK-DAG: <<Obj:l\d+>> NewInstance
- // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
- /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>{{(,[ij]\d+)?}}] method_name:java.lang.Object.<init>
+ /// CHECK-START: long Main.staticSetLong(Second, long) inliner (before)
+ /// CHECK: InvokeStaticOrDirect
- /// CHECK-START: java.lang.Object Main.newObject() inliner (after)
- /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-START: long Main.staticSetLong(Second, long) inliner (after)
+ /// CHECK: InvokeStaticOrDirect
- public static Object newObject() {
- return new Object();
- }
+ /// CHECK-START: long Main.staticSetLong(Second, long) inliner (after)
+ /// CHECK-NOT: InstanceFieldSet
- public static void main(String[] args) throws Exception {
- Second s = new Second();
-
- // Replaced NOP pattern.
- staticNop();
- nop(s);
- // Replaced "return arg" pattern.
- assertEquals("arbitrary string", staticReturnArg2("arbitrary string"));
- assertEquals(4321L, returnArg1(s, 4321L));
- // Replaced "return const" pattern.
- assertEquals(9, staticReturn9());
- assertEquals(7, return7(s));
- assertEquals(null, staticReturnNull());
- assertEquals(null, returnNull(s));
- // Replaced IGET pattern.
- assertEquals(42, getInt(s));
- assertEquals(-42.0, getDouble(s));
- assertEquals(null, getObject(s));
- assertEquals("dummy", getString(s));
- // Not replaced IGET pattern.
- assertEquals(42, staticGetInt(s));
- assertEquals(-42.0, getDoubleFromParam(s));
- // SGET.
- assertEquals(4242, getStaticInt(s));
- // Replaced IPUT pattern.
- assertEquals(111L, setLong(s, 111L));
- assertEquals(345L, setLongReturnArg2(s, 222L, 123));
- // Not replaced IPUT pattern.
- assertEquals(222L, staticSetLong(s, 222L));
- assertEquals(333L, setLongThroughParam(s, 333L));
- // SPUT.
- assertEquals(-11.5f, setStaticFloat(s, -11.5f));
-
- if (newObject() == null) {
- throw new AssertionError("new Object() cannot be null.");
- }
+ public static long staticSetLong(Second s, long value) {
+ Second.staticSetInstanceLongField(s, value);
+ return s.instanceLongField;
+ }
+
+ /// CHECK-START: long Main.setLongThroughParam(Second, long) inliner (before)
+ /// CHECK: InvokeVirtual
+
+ /// CHECK-START: long Main.setLongThroughParam(Second, long) inliner (after)
+ /// CHECK: InvokeVirtual
+
+ /// CHECK-START: long Main.setLongThroughParam(Second, long) inliner (after)
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static long setLongThroughParam(Second s, long value) {
+ s.setInstanceLongFieldThroughParam(s, value);
+ return s.instanceLongField;
+ }
+
+ /// CHECK-START: float Main.setStaticFloat(Second, float) inliner (before)
+ /// CHECK: InvokeVirtual
+
+ /// CHECK-START: float Main.setStaticFloat(Second, float) inliner (after)
+ /// CHECK: InvokeVirtual
+
+ /// CHECK-START: float Main.setStaticFloat(Second, float) inliner (after)
+ /// CHECK-NOT: InstanceFieldSet
+ /// CHECK-NOT: StaticFieldSet
+
+ public static float setStaticFloat(Second s, float value) {
+ s.setStaticFloatField(value);
+ return s.staticFloatField;
+ }
+
+ /// CHECK-START: java.lang.Object Main.newObject() inliner (before)
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>{{(,[ij]\d+)?}}] method_name:java.lang.Object.<init>
+
+ /// CHECK-START: java.lang.Object Main.newObject() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static Object newObject() {
+ return new Object();
+ }
+
+ /// CHECK-START: double Main.constructBase() inliner (before)
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBase() {
+ Base b = new Base();
+ return b.intField + b.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructBase(int) inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase(int) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructBase(int) inliner (after)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+
+ /// CHECK-START: double Main.constructBase(int) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBase(int intValue) {
+ Base b = new Base(intValue);
+ return b.intField + b.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructBaseWith0() inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBaseWith0() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBaseWith0() {
+ Base b = new Base(0);
+ return b.intField + b.doubleField;
+ }
+
+ /// CHECK-START: java.lang.String Main.constructBase(java.lang.String) inliner (before)
+ /// CHECK-DAG: <<Value:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: java.lang.String Main.constructBase(java.lang.String) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: java.lang.String Main.constructBase(java.lang.String) inliner (after)
+ /// CHECK-DAG: <<Value:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+
+ /// CHECK-START: java.lang.String Main.constructBase(java.lang.String) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static String constructBase(String stringValue) {
+ Base b = new Base(stringValue);
+ return b.stringField;
+ }
+
+ /// CHECK-START: java.lang.String Main.constructBaseWithNullString() inliner (before)
+ /// CHECK-DAG: <<Null:l\d+>> NullConstant
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Null>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: java.lang.String Main.constructBaseWithNullString() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: java.lang.String Main.constructBaseWithNullString() inliner (after)
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static String constructBaseWithNullString() {
+ String stringValue = null;
+ Base b = new Base(stringValue);
+ return b.stringField;
+ }
+
+ /// CHECK-START: double Main.constructBase(double, java.lang.Object) inliner (before)
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<OValue:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<DValue>>,<<OValue>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase(double, java.lang.Object) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructBase(double, java.lang.Object) inliner (after)
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<OValue:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<DValue>>]
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<OValue>>]
+
+ /// CHECK-START: double Main.constructBase(double, java.lang.Object) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBase(double doubleValue, Object objectValue) {
+ Base b = new Base(doubleValue, objectValue);
+ return (b.objectField != null) ? b.doubleField : -b.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructBase(int, double, java.lang.Object) inliner (before)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<OValue:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>,<<OValue>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase(int, double, java.lang.Object) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructBase(int, double, java.lang.Object) inliner (after)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<OValue:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<IValue>>]
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<DValue>>]
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<OValue>>]
+
+ /// CHECK-START: double Main.constructBase(int, double, java.lang.Object) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBase(int intValue, double doubleValue, Object objectValue) {
+ Base b = new Base(intValue, doubleValue, objectValue);
+ double tmp = b.intField + b.doubleField;
+ return (b.objectField != null) ? tmp : -tmp;
+ }
+
+ /// CHECK-START: double Main.constructBaseWith0DoubleNull(double) inliner (before)
+ /// CHECK-DAG: <<IValue:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<OValue:l\d+>> NullConstant
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>,<<OValue>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBaseWith0DoubleNull(double) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructBaseWith0DoubleNull(double) inliner (after)
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<DValue>>]
+
+ /// CHECK-START: double Main.constructBaseWith0DoubleNull(double) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBaseWith0DoubleNull(double doubleValue) {
+ Base b = new Base(0, doubleValue, null);
+ double tmp = b.intField + b.doubleField;
+ return (b.objectField != null) ? tmp : -tmp;
+ }
+
+ /// CHECK-START: double Main.constructBase(int, double, java.lang.Object, java.lang.String) inliner (before)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>,{{l\d+}},{{l\d+}}{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase(int, double, java.lang.Object, java.lang.String) inliner (after)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>,{{l\d+}},{{l\d+}}{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase(int, double, java.lang.Object, java.lang.String) inliner (after)
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBase(
+ int intValue, double doubleValue, Object objectValue, String stringValue) {
+ Base b = new Base(intValue, doubleValue, objectValue, stringValue);
+ double tmp = b.intField + b.doubleField;
+ tmp = (b.objectField != null) ? tmp : -tmp;
+ return (b.stringField != null) ? 2.0 * tmp : 0.5 * tmp;
+ }
+
+ /// CHECK-START: double Main.constructBase(double) inliner (before)
+ /// CHECK-DAG: <<Value:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase(double) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructBase(double) inliner (after)
+ /// CHECK-DAG: <<Value:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+
+ /// CHECK-START: double Main.constructBase(double) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBase(double doubleValue) {
+ Base b = new Base(doubleValue);
+ return b.intField + b.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructBaseWith0d() inliner (before)
+ /// CHECK-DAG: <<Value:d\d+>> DoubleConstant
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBaseWith0d() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBaseWith0d() {
+ Base b = new Base(0.0);
+ return b.intField + b.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructBase(java.lang.Object) inliner (before)
+ /// CHECK-DAG: <<OValue:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<OValue>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase(java.lang.Object) inliner (after)
+ /// CHECK-DAG: <<OValue:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<OValue>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase(java.lang.Object) inliner (after)
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBase(Object objectValue) {
+ Base b = new Base(objectValue);
+ double tmp = b.intField + b.doubleField;
+ return (b.objectField != null) ? tmp + 1.0 : tmp - 1.0;
+ }
+
+ /// CHECK-START: double Main.constructBase(int, long) inliner (before)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<JValue:j\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<JValue>>{{(,[ij]\d+)?}}] method_name:Base.<init>
+
+ /// CHECK-START: double Main.constructBase(int, long) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructBase(int, long) inliner (after)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<IValue>>]
+
+ /// CHECK-START: double Main.constructBase(int, long) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructBase(int intValue, long dummy) {
+ Base b = new Base(intValue, dummy);
+ return b.intField + b.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerived() inliner (before)
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerived() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerived() {
+ Derived d = new Derived();
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerived(int) inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerived(int) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructDerived(int) inliner (after)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+
+ /// CHECK-START: double Main.constructDerived(int) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerived(int intValue) {
+ Derived d = new Derived(intValue);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerivedWith0() inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerivedWith0() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerivedWith0() {
+ Derived d = new Derived(0);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: java.lang.String Main.constructDerived(java.lang.String) inliner (before)
+ /// CHECK-DAG: <<Value:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: java.lang.String Main.constructDerived(java.lang.String) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: java.lang.String Main.constructDerived(java.lang.String) inliner (after)
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static String constructDerived(String stringValue) {
+ Derived d = new Derived(stringValue);
+ return d.stringField;
+ }
+
+ /// CHECK-START: double Main.constructDerived(double) inliner (before)
+ /// CHECK-DAG: <<Value:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerived(double) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructDerived(double) inliner (after)
+ /// CHECK-DAG: <<Value:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+
+ /// CHECK-START: double Main.constructDerived(double) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerived(double doubleValue) {
+ Derived d = new Derived(doubleValue);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerivedWith0d() inliner (before)
+ /// CHECK-DAG: <<Value:d\d+>> DoubleConstant
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerivedWith0d() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerivedWith0d() {
+ Derived d = new Derived(0.0);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object) inliner (before)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<OValue:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>,<<OValue>>{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object) inliner (after)
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<DValue>>]
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerived(int intValue, double doubleValue, Object objectValue) {
+ Derived d = new Derived(intValue, doubleValue, objectValue);
+ double tmp = d.intField + d.doubleField;
+ return (d.objectField != null) ? tmp : -tmp;
+ }
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object, java.lang.String) inliner (before)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>,{{l\d+}},{{l\d+}}{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object, java.lang.String) inliner (after)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>,{{l\d+}},{{l\d+}}{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object, java.lang.String) inliner (after)
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerived(
+ int intValue, double doubleValue, Object objectValue, String stringValue) {
+ Derived d = new Derived(intValue, doubleValue, objectValue, stringValue);
+ double tmp = d.intField + d.doubleField;
+ tmp = (d.objectField != null) ? tmp : -tmp;
+ return (d.stringField != null) ? 2.0 * tmp : 0.5 * tmp;
+ }
+
+ /// CHECK-START: double Main.constructDerived(float) inliner (before)
+ /// CHECK-DAG: <<Value:f\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerived(float) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructDerived(float) inliner (after)
+ /// CHECK-DAG: <<Value:f\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+
+ /// CHECK-START: double Main.constructDerived(float) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerived(float floatValue) {
+ Derived d = new Derived(floatValue);
+ return d.intField + d.doubleField + d.floatField;
+ }
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object, float) inliner (before)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<OValue:l\d+>> ParameterValue
+ /// CHECK-DAG: <<FValue:f\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>,<<OValue>>,<<FValue>>{{(,[ij]\d+)?}}] method_name:Derived.<init>
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object, float) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object, float) inliner (after)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<FValue:f\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<IValue>>]
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<DValue>>]
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<FValue>>]
+
+ /// CHECK-START: double Main.constructDerived(int, double, java.lang.Object, float) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerived(
+ int intValue, double doubleValue, Object objectValue, float floatValue) {
+ Derived d = new Derived(intValue, doubleValue, objectValue, floatValue);
+ double tmp = d.intField + d.doubleField + d.floatField;
+ return (d.objectField != null) ? tmp : -tmp;
+ }
+
+ /// CHECK-START: int Main.constructBaseWithFinalField() inliner (before)
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>{{(,[ij]\d+)?}}] method_name:BaseWithFinalField.<init>
+
+ /// CHECK-START: int Main.constructBaseWithFinalField() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static int constructBaseWithFinalField() {
+ BaseWithFinalField b = new BaseWithFinalField();
+ return b.intField;
+ }
+
+ /// CHECK-START: int Main.constructBaseWithFinalField(int) inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:BaseWithFinalField.<init>
+
+ /// CHECK-START: int Main.constructBaseWithFinalField(int) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START: int Main.constructBaseWithFinalField(int) inliner (after)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+ /// CHECK-DAG: MemoryBarrier
+
+ /// CHECK-START: int Main.constructBaseWithFinalField(int) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static int constructBaseWithFinalField(int intValue) {
+ BaseWithFinalField b = new BaseWithFinalField(intValue);
+ return b.intField;
+ }
+
+ /// CHECK-START: int Main.constructBaseWithFinalFieldWith0() inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:BaseWithFinalField.<init>
+
+ /// CHECK-START: int Main.constructBaseWithFinalFieldWith0() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static int constructBaseWithFinalFieldWith0() {
+ BaseWithFinalField b = new BaseWithFinalField(0);
+ return b.intField;
+ }
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField() inliner (before)
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>{{(,[ij]\d+)?}}] method_name:DerivedWithFinalField.<init>
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerivedWithFinalField() {
+ DerivedWithFinalField d = new DerivedWithFinalField();
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(int) inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:DerivedWithFinalField.<init>
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(int) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(int) inliner (after)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+ /// CHECK-DAG: MemoryBarrier
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(int) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerivedWithFinalField(int intValue) {
+ DerivedWithFinalField d = new DerivedWithFinalField(intValue);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerivedWithFinalFieldWith0() inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:DerivedWithFinalField.<init>
+
+ /// CHECK-START: double Main.constructDerivedWithFinalFieldWith0() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerivedWithFinalFieldWith0() {
+ DerivedWithFinalField d = new DerivedWithFinalField(0);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(double) inliner (before)
+ /// CHECK-DAG: <<Value:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:DerivedWithFinalField.<init>
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(double) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(double) inliner (after)
+ /// CHECK-DAG: <<Value:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+ /// CHECK-DAG: MemoryBarrier
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(double) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerivedWithFinalField(double doubleValue) {
+ DerivedWithFinalField d = new DerivedWithFinalField(doubleValue);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerivedWithFinalFieldWith0d() inliner (before)
+ /// CHECK-DAG: <<Value:d\d+>> DoubleConstant
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:DerivedWithFinalField.<init>
+
+ /// CHECK-START: double Main.constructDerivedWithFinalFieldWith0d() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerivedWithFinalFieldWith0d() {
+ DerivedWithFinalField d = new DerivedWithFinalField(0.0);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(int, double) inliner (before)
+ /// CHECK-DAG: <<IValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<DValue:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>{{(,[ij]\d+)?}}] method_name:DerivedWithFinalField.<init>
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(int, double) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(int, double) inliner (after)
+ /// CHECK-DAG: <<Value:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Value>>]
+ /// CHECK-DAG: MemoryBarrier
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(int, double) inliner (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: double Main.constructDerivedWithFinalField(int, double) inliner (after)
+ /// CHECK-DAG: MemoryBarrier
+ /// CHECK-NOT: MemoryBarrier
+
+ public static double constructDerivedWithFinalField(int intValue, double doubleValue) {
+ DerivedWithFinalField d = new DerivedWithFinalField(intValue, doubleValue);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: double Main.constructDerivedWithFinalFieldWith0And0d() inliner (before)
+ /// CHECK-DAG: <<IValue:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<DValue:d\d+>> DoubleConstant
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<IValue>>,<<DValue>>{{(,[ij]\d+)?}}] method_name:DerivedWithFinalField.<init>
+
+ /// CHECK-START: double Main.constructDerivedWithFinalFieldWith0And0d() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static double constructDerivedWithFinalFieldWith0And0d() {
+ DerivedWithFinalField d = new DerivedWithFinalField(0, 0.0);
+ return d.intField + d.doubleField;
+ }
+
+ /// CHECK-START: int Main.constructDerivedInSecondDex() inliner (before)
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>{{(,[ij]\d+)?}}] method_name:DerivedInSecondDex.<init>
+
+ /// CHECK-START: int Main.constructDerivedInSecondDex() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static int constructDerivedInSecondDex() {
+ DerivedInSecondDex d = new DerivedInSecondDex();
+ return d.intField;
+ }
+
+ /// CHECK-START: int Main.constructDerivedInSecondDex(int) inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:DerivedInSecondDex.<init>
+
+ /// CHECK-START: int Main.constructDerivedInSecondDex(int) inliner (after)
+ /// CHECK-DAG: <<Value:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:DerivedInSecondDex.<init>
+
+ /// CHECK-START: int Main.constructDerivedInSecondDex(int) inliner (after)
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static int constructDerivedInSecondDex(int intValue) {
+ DerivedInSecondDex d = new DerivedInSecondDex(intValue);
+ return d.intField;
+ }
+
+ /// CHECK-START: int Main.constructDerivedInSecondDexWith0() inliner (before)
+ /// CHECK-DAG: <<Value:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:DerivedInSecondDex.<init>
+
+ /// CHECK-START: int Main.constructDerivedInSecondDexWith0() inliner (after)
+ /// CHECK-DAG: <<Value:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:DerivedInSecondDex.<init>
+
+ /// CHECK-START: int Main.constructDerivedInSecondDexWith0() inliner (after)
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static int constructDerivedInSecondDexWith0() {
+ DerivedInSecondDex d = new DerivedInSecondDex(0);
+ return d.intField;
+ }
+
+ /// CHECK-START: int Main.constructDerivedInSecondDex(long) inliner (before)
+ /// CHECK-DAG: <<Value:j\d+>> ParameterValue
+ /// CHECK-DAG: <<Obj:l\d+>> NewInstance
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>,<<Value>>{{(,[ij]\d+)?}}] method_name:DerivedInSecondDex.<init>
+
+ /// CHECK-START: int Main.constructDerivedInSecondDex(long) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: MemoryBarrier
+ /// CHECK-NOT: InstanceFieldSet
+
+ public static int constructDerivedInSecondDex(long dummy) {
+ DerivedInSecondDex d = new DerivedInSecondDex(dummy);
+ return d.intField;
+ }
+
+ public static void main(String[] args) throws Exception {
+ Second s = new Second();
+
+ // Replaced NOP pattern.
+ staticNop();
+ nop(s);
+ // Replaced "return arg" pattern.
+ assertEquals("arbitrary string", staticReturnArg2("arbitrary string"));
+ assertEquals(4321L, returnArg1(s, 4321L));
+ // Replaced "return const" pattern.
+ assertEquals(9, staticReturn9());
+ assertEquals(7, return7(s));
+ assertEquals(null, staticReturnNull());
+ assertEquals(null, returnNull(s));
+ // Replaced IGET pattern.
+ assertEquals(42, getInt(s));
+ assertEquals(-42.0, getDouble(s));
+ assertEquals(null, getObject(s));
+ assertEquals("dummy", getString(s));
+ // Not replaced IGET pattern.
+ assertEquals(42, staticGetInt(s));
+ assertEquals(-42.0, getDoubleFromParam(s));
+ // SGET.
+ assertEquals(4242, getStaticInt(s));
+ // Replaced IPUT pattern.
+ assertEquals(111L, setLong(s, 111L));
+ assertEquals(345L, setLongReturnArg2(s, 222L, 123));
+ // Not replaced IPUT pattern.
+ assertEquals(222L, staticSetLong(s, 222L));
+ assertEquals(333L, setLongThroughParam(s, 333L));
+ // SPUT.
+ assertEquals(-11.5f, setStaticFloat(s, -11.5f));
+
+ if (newObject() == null) {
+ throw new AssertionError("new Object() cannot be null.");
}
- private static void assertEquals(int expected, int actual) {
- if (expected != actual) {
- throw new AssertionError("Wrong result: " + expected + " != " + actual);
- }
+ assertEquals(0.0, constructBase());
+ assertEquals(42.0, constructBase(42));
+ assertEquals(0.0, constructBaseWith0());
+ assertEquals("something", constructBase("something"));
+ assertEquals(null, constructBaseWithNullString());
+ assertEquals(11.0, constructBase(11.0, new Object()));
+ assertEquals(-12.0, constructBase(12.0, null));
+ assertEquals(30.0, constructBase(17, 13.0, new Object()));
+ assertEquals(-34.0, constructBase(19, 15.0, null));
+ assertEquals(-22.5, constructBaseWith0DoubleNull(22.5));
+ assertEquals(-8.0, constructBase(2, 14.0, null, null));
+ assertEquals(-64.0, constructBase(4, 28.0, null, "dummy"));
+ assertEquals(13.0, constructBase(24, 2.0, new Object(), null));
+ assertEquals(30.0, constructBase(11, 4.0, new Object(), "dummy"));
+ assertEquals(43.0, constructBase(43.0));
+ assertEquals(0.0, constructBaseWith0d());
+ assertEquals(1.0, constructBase(new Object()));
+ assertEquals(-1.0, constructBase((Object) null));
+ assertEquals(123.0, constructBase(123, 65L));
+
+ assertEquals(0.0, constructDerived());
+ assertEquals(73.0, constructDerived(73));
+ assertEquals(0.0, constructDerivedWith0());
+ assertEquals(null, constructDerived("something else"));
+ assertEquals(18.0, constructDerived(18.0));
+ assertEquals(0.0, constructDerivedWith0d());
+ assertEquals(-7.0, constructDerived(5, 7.0, new Object()));
+ assertEquals(-4.0, constructDerived(9, 4.0, null));
+ assertEquals(0.0, constructDerived(1, 9.0, null, null));
+ assertEquals(0.0, constructDerived(2, 8.0, null, "dummy"));
+ assertEquals(0.0, constructDerived(3, 7.0, new Object(), null));
+ assertEquals(0.0, constructDerived(4, 6.0, new Object(), "dummy"));
+ assertEquals(17.0, constructDerived(17.0f));
+ assertEquals(-5.5, constructDerived(6, -7.0, new Object(), 6.5f));
+
+ assertEquals(0, constructBaseWithFinalField());
+ assertEquals(77, constructBaseWithFinalField(77));
+ assertEquals(0, constructBaseWithFinalFieldWith0());
+ assertEquals(0.0, constructDerivedWithFinalField());
+ assertEquals(-33.0, constructDerivedWithFinalField(-33));
+ assertEquals(0.0, constructDerivedWithFinalFieldWith0());
+ assertEquals(-44.0, constructDerivedWithFinalField(-44.0));
+ assertEquals(0.0, constructDerivedWithFinalFieldWith0d());
+ assertEquals(88, constructDerivedWithFinalField(22, 66.0));
+ assertEquals(0.0, constructDerivedWithFinalFieldWith0And0d());
+
+ assertEquals(0, constructDerivedInSecondDex());
+ assertEquals(123, constructDerivedInSecondDex(123));
+ assertEquals(0, constructDerivedInSecondDexWith0());
+ assertEquals(0, constructDerivedInSecondDex(7L));
+ }
+
+ private static void assertEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new AssertionError("Wrong result: " + expected + " != " + actual);
}
+ }
- private static void assertEquals(double expected, double actual) {
- if (expected != actual) {
- throw new AssertionError("Wrong result: " + expected + " != " + actual);
- }
+ private static void assertEquals(double expected, double actual) {
+ if (expected != actual) {
+ throw new AssertionError("Wrong result: " + expected + " != " + actual);
}
+ }
- private static void assertEquals(Object expected, Object actual) {
- if (expected != actual && (expected == null || !expected.equals(actual))) {
- throw new AssertionError("Wrong result: " + expected + " != " + actual);
- }
+ private static void assertEquals(Object expected, Object actual) {
+ if (expected != actual && (expected == null || !expected.equals(actual))) {
+ throw new AssertionError("Wrong result: " + expected + " != " + actual);
}
+ }
}