From 70445d0d89cb2b730e148cdb92e580585c1ef9c6 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 26 Jul 2019 09:37:46 -0700 Subject: [PATCH] [viewcompiler] Add support for static field put to DexBuilder Bug: 111895153 Change-Id: I12b38fa520790debec545d7d1f6b3522a65ce03b --- startop/view_compiler/dex_builder.cc | 35 +++++++++++++++---- startop/view_compiler/dex_builder.h | 6 ++++ .../android/startop/test/DexBuilderTest.java | 10 ++++++ .../view_compiler/dex_testcase_generator.cc | 16 +++++++++ 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc index 66bc698e21369..09f9c04d9e2c6 100644 --- a/startop/view_compiler/dex_builder.cc +++ b/startop/view_compiler/dex_builder.cc @@ -105,6 +105,9 @@ std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode) { case Instruction::Op::kGetStaticField: out << "kGetStaticField"; return out; + case Instruction::Op::kSetStaticField: + out << "kSetStaticField"; + return out; } } @@ -380,6 +383,7 @@ void MethodBuilder::EncodeInstruction(const Instruction& instruction) { case Instruction::Op::kCheckCast: return EncodeCast(instruction); case Instruction::Op::kGetStaticField: + case Instruction::Op::kSetStaticField: return EncodeStaticFieldOp(instruction); } } @@ -536,13 +540,32 @@ void MethodBuilder::EncodeCast(const Instruction& instruction) { } void MethodBuilder::EncodeStaticFieldOp(const Instruction& instruction) { - CHECK_EQ(Instruction::Op::kGetStaticField, instruction.opcode()); - CHECK(instruction.dest().has_value()); - CHECK(instruction.dest()->is_variable()); - CHECK_EQ(0, instruction.args().size()); + switch (instruction.opcode()) { + case Instruction::Op::kGetStaticField: { + CHECK(instruction.dest().has_value()); + CHECK(instruction.dest()->is_variable()); + CHECK_EQ(0, instruction.args().size()); - Encode21c( - ::art::Instruction::SGET, RegisterValue(*instruction.dest()), instruction.index_argument()); + Encode21c(::art::Instruction::SGET, + RegisterValue(*instruction.dest()), + instruction.index_argument()); + break; + } + case Instruction::Op::kSetStaticField: { + CHECK(!instruction.dest().has_value()); + const auto& args = instruction.args(); + CHECK_EQ(1, args.size()); + CHECK(args[0].is_variable()); + + Encode21c(::art::Instruction::SPUT, + RegisterValue(args[0]), + instruction.index_argument()); + break; + } + default: { + LOG(FATAL) << "Unsupported static field operation"; + } + } } size_t MethodBuilder::RegisterValue(const Value& value) const { diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h index a7ccb4a9452b3..3f9ac43ae5326 100644 --- a/startop/view_compiler/dex_builder.h +++ b/startop/view_compiler/dex_builder.h @@ -163,6 +163,7 @@ class Instruction { kNew, kReturn, kReturnObject, + kSetStaticField }; //////////////////////// @@ -237,6 +238,11 @@ class Instruction { return Instruction{Op::kGetStaticField, field_id, dest}; } + static inline Instruction SetStaticField(size_t field_id, Value value) { + return Instruction{Op::kSetStaticField, field_id, /*result_is_object=*/false, /*dest=*/{}, value}; + } + + /////////////// // Accessors // /////////////// diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java index df11bfafd3571..3138e71832261 100644 --- a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java +++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java @@ -180,4 +180,14 @@ public final class DexBuilderTest { TestClass.staticInteger = 5; Assert.assertEquals(5, method.invoke(null)); } + + @Test + public void setStaticField() throws Exception { + ClassLoader loader = loadDexFile("simple.dex"); + Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests"); + Method method = clazz.getMethod("setStaticField"); + TestClass.staticInteger = 5; + method.invoke(null); + Assert.assertEquals(7, TestClass.staticInteger); + } } diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc index 5227f8054765c..fee5e722bc55c 100644 --- a/startop/view_compiler/dex_testcase_generator.cc +++ b/startop/view_compiler/dex_testcase_generator.cc @@ -297,6 +297,22 @@ void GenerateSimpleTestCases(const string& outdir) { method.Encode(); }(readStaticField); + // Set a static field + // void setStaticField() { TestClass.staticInteger = 7; } + MethodBuilder setStaticField{ + cbuilder.CreateMethod("setStaticField", Prototype{TypeDescriptor::Void()})}; + [&](MethodBuilder& method) { + const ir::FieldDecl* field = + dex_file.GetOrAddField(TypeDescriptor::FromClassname("android.startop.test.TestClass"), + "staticInteger", + TypeDescriptor::Int()); + Value number{method.MakeRegister()}; + method.BuildConst4(number, 7); + method.AddInstruction(Instruction::SetStaticField(field->orig_index, number)); + method.BuildReturn(); + method.Encode(); + }(setStaticField); + slicer::MemView image{dex_file.CreateImage()}; std::ofstream out_file(outdir + "/simple.dex"); out_file.write(image.ptr(), image.size());