Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70445d0d authored by Eric Holk's avatar Eric Holk
Browse files

[viewcompiler] Add support for static field put to DexBuilder

Bug: 111895153
Change-Id: I12b38fa520790debec545d7d1f6b3522a65ce03b
parent 3092f99a
Loading
Loading
Loading
Loading
+30 −7
Original line number Diff line number Diff line
@@ -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());
  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 {
+6 −0
Original line number Diff line number Diff line
@@ -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 //
  ///////////////
+10 −0
Original line number Diff line number Diff line
@@ -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);
  }
}
+16 −0
Original line number Diff line number Diff line
@@ -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<const char>(), image.size());