diff options
Diffstat (limited to 'startop/view_compiler/dex_builder.h')
-rw-r--r-- | startop/view_compiler/dex_builder.h | 84 |
1 files changed, 69 insertions, 15 deletions
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h index adf82bf9a01a..757d863461f0 100644 --- a/startop/view_compiler/dex_builder.h +++ b/startop/view_compiler/dex_builder.h @@ -73,7 +73,7 @@ class TypeDescriptor { bool operator<(const TypeDescriptor& rhs) const { return descriptor_ < rhs.descriptor_; } private: - TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {} + explicit TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {} const std::string descriptor_; }; @@ -83,7 +83,7 @@ class TypeDescriptor { class Prototype { public: template <typename... TypeDescriptors> - Prototype(TypeDescriptor return_type, TypeDescriptors... param_types) + explicit Prototype(TypeDescriptor return_type, TypeDescriptors... param_types) : return_type_{return_type}, param_types_{param_types...} {} // Encode this prototype into the dex file. @@ -142,14 +142,18 @@ class Instruction { // The operation performed by this instruction. These are virtual instructions that do not // correspond exactly to DEX instructions. enum class Op { - kReturn, - kReturnObject, - kMove, - kInvokeVirtual, - kInvokeDirect, kBindLabel, kBranchEqz, - kNew + kBranchNEqz, + kCheckCast, + kInvokeDirect, + kInvokeInterface, + kInvokeStatic, + kInvokeVirtual, + kMove, + kNew, + kReturn, + kReturnObject, }; //////////////////////// @@ -163,19 +167,60 @@ class Instruction { // For most instructions, which take some number of arguments and have an optional return value. template <typename... T> static inline Instruction OpWithArgs(Op opcode, std::optional<const Value> dest, T... args) { - return Instruction{opcode, /*method_id*/ 0, dest, args...}; + return Instruction{opcode, /*method_id=*/0, /*result_is_object=*/false, dest, args...}; + } + + // A cast instruction. Basically, `(type)val` + static inline Instruction Cast(Value val, Value type) { + DCHECK(type.is_type()); + return OpWithArgs(Op::kCheckCast, val, type); } + // For method calls. template <typename... T> static inline Instruction InvokeVirtual(size_t method_id, std::optional<const Value> dest, Value this_arg, T... args) { - return Instruction{Op::kInvokeVirtual, method_id, dest, this_arg, args...}; + return Instruction{ + Op::kInvokeVirtual, method_id, /*result_is_object=*/false, dest, this_arg, args...}; + } + // Returns an object + template <typename... T> + static inline Instruction InvokeVirtualObject(size_t method_id, std::optional<const Value> dest, + Value this_arg, T... args) { + return Instruction{ + Op::kInvokeVirtual, method_id, /*result_is_object=*/true, dest, this_arg, args...}; } // For direct calls (basically, constructors). template <typename... T> static inline Instruction InvokeDirect(size_t method_id, std::optional<const Value> dest, Value this_arg, T... args) { - return Instruction{Op::kInvokeDirect, method_id, dest, this_arg, args...}; + return Instruction{ + Op::kInvokeDirect, method_id, /*result_is_object=*/false, dest, this_arg, args...}; + } + // Returns an object + template <typename... T> + static inline Instruction InvokeDirectObject(size_t method_id, std::optional<const Value> dest, + Value this_arg, T... args) { + return Instruction{ + Op::kInvokeDirect, method_id, /*result_is_object=*/true, dest, this_arg, args...}; + } + // For static calls. + template <typename... T> + static inline Instruction InvokeStatic(size_t method_id, std::optional<const Value> dest, + T... args) { + return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/false, dest, args...}; + } + // Returns an object + template <typename... T> + static inline Instruction InvokeStaticObject(size_t method_id, std::optional<const Value> dest, + T... args) { + return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/true, dest, args...}; + } + // For static calls. + template <typename... T> + static inline Instruction InvokeInterface(size_t method_id, std::optional<const Value> dest, + T... args) { + return Instruction{Op::kInvokeInterface, method_id, /*result_is_object=*/false, dest, args...}; } /////////////// @@ -184,21 +229,27 @@ class Instruction { Op opcode() const { return opcode_; } size_t method_id() const { return method_id_; } + bool result_is_object() const { return result_is_object_; } const std::optional<const Value>& dest() const { return dest_; } const std::vector<const Value>& args() const { return args_; } private: inline Instruction(Op opcode, size_t method_id, std::optional<const Value> dest) - : opcode_{opcode}, method_id_{method_id}, dest_{dest}, args_{} {} + : opcode_{opcode}, method_id_{method_id}, result_is_object_{false}, dest_{dest}, args_{} {} template <typename... T> - inline constexpr Instruction(Op opcode, size_t method_id, std::optional<const Value> dest, - T... args) - : opcode_{opcode}, method_id_{method_id}, dest_{dest}, args_{args...} {} + inline constexpr Instruction(Op opcode, size_t method_id, bool result_is_object, + std::optional<const Value> dest, T... args) + : opcode_{opcode}, + method_id_{method_id}, + result_is_object_{result_is_object}, + dest_{dest}, + args_{args...} {} const Op opcode_; // The index of the method to invoke, for kInvokeVirtual and similar opcodes. const size_t method_id_{0}; + const bool result_is_object_; const std::optional<const Value> dest_; const std::vector<const Value> args_; }; @@ -244,6 +295,8 @@ class MethodBuilder { // TODO: add builders for more instructions + DexBuilder* dex_file() const { return dex_; } + private: void EncodeInstructions(); void EncodeInstruction(const Instruction& instruction); @@ -257,6 +310,7 @@ class MethodBuilder { void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode); void EncodeBranch(art::Instruction::Code op, const Instruction& instruction); void EncodeNew(const Instruction& instruction); + void EncodeCast(const Instruction& instruction); // Low-level instruction format encoding. See // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of |