diff options
author | Eric Holk <eholk@google.com> | 2018-11-09 13:48:59 -0800 |
---|---|---|
committer | Eric Holk <eholk@google.com> | 2018-11-15 17:44:03 +0000 |
commit | 1c0f3f099cf6420af16a9ab29f3bdf6721ac78a3 (patch) | |
tree | fdbb0b490b40357607fc5673633c221669286a12 /startop/view_compiler/dex_builder.cc | |
parent | 2583def750214a34b674d128bc1763f742015dba (diff) |
[view_compiler] cleanup: Use format-specific bytecode encoding functions
This change corrals most of the bit shifting and ORing needed to encode Dex
instructions into EncodeXXX functions that follow the naming scheme at
https://source.android.com/devices/tech/dalvik/instruction-formats. Overall, it
makes the code easier to follow and probably even less error prone because we
only have to make the format right in one place.
Bug: 111895153
Change-Id: I902ec3c8bca6b5dc4ad900503af7aef58d4bbf5f
Diffstat (limited to 'startop/view_compiler/dex_builder.cc')
-rw-r--r-- | startop/view_compiler/dex_builder.cc | 57 |
1 files changed, 26 insertions, 31 deletions
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc index 1fde692451f1..906d64c1f619 100644 --- a/startop/view_compiler/dex_builder.cc +++ b/startop/view_compiler/dex_builder.cc @@ -301,11 +301,11 @@ void MethodBuilder::EncodeInstruction(const Instruction& instruction) { void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) { DCHECK(!instruction.dest().has_value()); if (instruction.args().size() == 0) { - buffer_.push_back(art::Instruction::RETURN_VOID); + Encode10x(art::Instruction::RETURN_VOID); } else { DCHECK_EQ(1, instruction.args().size()); size_t source = RegisterValue(instruction.args()[0]); - buffer_.push_back(opcode | source << 8); + Encode11x(opcode, source); } } @@ -320,44 +320,40 @@ void MethodBuilder::EncodeMove(const Instruction& instruction) { if (source.is_immediate()) { // TODO: support more registers DCHECK_LT(RegisterValue(*instruction.dest()), 16); - DCHECK_LT(source.value(), 16); - buffer_.push_back(art::Instruction::CONST_4 | (source.value() << 12) | - (RegisterValue(*instruction.dest()) << 8)); + Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value()); } else if (source.is_string()) { constexpr size_t kMaxRegisters = 256; DCHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters); DCHECK_LT(source.value(), 65536); // make sure we don't need a jumbo string - buffer_.push_back(::art::Instruction::CONST_STRING | (RegisterValue(*instruction.dest()) << 8)); - buffer_.push_back(source.value()); + Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value()); } else { UNIMPLEMENTED(FATAL); } } void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) { - // TODO: support more than one argument (i.e. the this argument) and change this to DCHECK_GE - DCHECK_LE(4, instruction.args().size()); - // So far we only support the 4-bit length field, so we support at most 15 arguments, even if we - // remove the earlier limits. - DCHECK_LT(16, instruction.args().size()); - - buffer_.push_back(instruction.args().size() << 12 | opcode); - buffer_.push_back(instruction.method_id()); - - // Encode up to four arguments - ::dex::u2 args = 0; - size_t arg_shift = 0; - for (const auto& arg : instruction.args()) { - DCHECK(arg.is_variable()); - args |= (0xf & RegisterValue(arg)) << arg_shift; - arg_shift += 4; + constexpr size_t kMaxArgs = 5; + + CHECK_LE(instruction.args().size(), kMaxArgs); + + uint8_t arguments[kMaxArgs]{}; + for (size_t i = 0; i < instruction.args().size(); ++i) { + CHECK(instruction.args()[i].is_variable()); + arguments[i] = RegisterValue(instruction.args()[i]); } - buffer_.push_back(args); + + Encode35c(opcode, + instruction.args().size(), + instruction.method_id(), + arguments[0], + arguments[1], + arguments[2], + arguments[3], + arguments[4]); // If there is a return value, add a move-result instruction if (instruction.dest().has_value()) { - size_t real_reg = RegisterValue(*instruction.dest()); - buffer_.push_back(real_reg << 8 | art::Instruction::MOVE_RESULT); + Encode11x(art::Instruction::MOVE_RESULT, RegisterValue(*instruction.dest())); } max_args_ = std::max(max_args_, instruction.args().size()); @@ -373,9 +369,9 @@ void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& i CHECK(branch_target.is_label()); size_t instruction_offset = buffer_.size(); - buffer_.push_back(op | (RegisterValue(test_value) << 8)); - size_t field_offset = buffer_.size(); - buffer_.push_back(LabelValue(branch_target, instruction_offset, field_offset)); + size_t field_offset = buffer_.size() + 1; + Encode21c( + op, RegisterValue(test_value), LabelValue(branch_target, instruction_offset, field_offset)); } void MethodBuilder::EncodeNew(const Instruction& instruction) { @@ -387,8 +383,7 @@ void MethodBuilder::EncodeNew(const Instruction& instruction) { const Value& type = instruction.args()[0]; DCHECK_LT(RegisterValue(*instruction.dest()), 256); DCHECK(type.is_type()); - buffer_.push_back(::art::Instruction::NEW_INSTANCE | (RegisterValue(*instruction.dest()) << 8)); - buffer_.push_back(type.value()); + Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value()); } size_t MethodBuilder::RegisterValue(const Value& value) const { |