[viewcompiler] Add support for static field put to DexBuilder
Bug: 111895153 Change-Id: I12b38fa520790debec545d7d1f6b3522a65ce03b
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 //
|
||||
///////////////
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user