diff options
author | Eric Holk <eholk@google.com> | 2019-07-25 15:14:01 -0700 |
---|---|---|
committer | Eric Holk <eholk@google.com> | 2019-07-26 09:42:41 -0700 |
commit | 3092f99ae63f12f5c18d40f21616c98f2b6c62af (patch) | |
tree | 7b0114acfb0a8d85c1688ddca0c3913353de7d8b /startop/view_compiler/dex_builder.h | |
parent | a0b2086373140496b131233ea44979098b9dedff (diff) |
[viewcompiler] Add static field get instructions to DexBuilder
This allows us to generate code that can read static fields in a class. Once we
include several other field operations, we will be able to generate more
specialized inflation code in the view compiler.
Bug: 111895153
Change-Id: Ia11195b1cea6d5a3ddbc60d972922586a062c853
Diffstat (limited to 'startop/view_compiler/dex_builder.h')
-rw-r--r-- | startop/view_compiler/dex_builder.h | 59 |
1 files changed, 37 insertions, 22 deletions
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h index 541d80077bd3..a7ccb4a9452b 100644 --- a/startop/view_compiler/dex_builder.h +++ b/startop/view_compiler/dex_builder.h @@ -153,6 +153,7 @@ class Instruction { kBranchEqz, kBranchNEqz, kCheckCast, + kGetStaticField, kInvokeDirect, kInvokeInterface, kInvokeStatic, @@ -170,12 +171,12 @@ class Instruction { // For instructions with no return value and no arguments. static inline Instruction OpNoArgs(Op opcode) { - return Instruction{opcode, /*method_id*/ 0, /*dest*/ {}}; + return Instruction{opcode, /*index_argument*/ 0, /*dest*/ {}}; } // 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, /*result_is_object=*/false, dest, args...}; + return Instruction{opcode, /*index_argument=*/0, /*result_is_object=*/false, dest, args...}; } // A cast instruction. Basically, `(type)val` @@ -186,49 +187,54 @@ class Instruction { // For method calls. template <typename... T> - static inline Instruction InvokeVirtual(size_t method_id, std::optional<const Value> dest, + static inline Instruction InvokeVirtual(size_t index_argument, std::optional<const Value> dest, Value this_arg, T... args) { return Instruction{ - Op::kInvokeVirtual, method_id, /*result_is_object=*/false, dest, this_arg, args...}; + Op::kInvokeVirtual, index_argument, /*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, + static inline Instruction InvokeVirtualObject(size_t index_argument, std::optional<const Value> dest, Value this_arg, T... args) { return Instruction{ - Op::kInvokeVirtual, method_id, /*result_is_object=*/true, dest, this_arg, args...}; + Op::kInvokeVirtual, index_argument, /*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, + static inline Instruction InvokeDirect(size_t index_argument, std::optional<const Value> dest, Value this_arg, T... args) { return Instruction{ - Op::kInvokeDirect, method_id, /*result_is_object=*/false, dest, this_arg, args...}; + Op::kInvokeDirect, index_argument, /*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, + static inline Instruction InvokeDirectObject(size_t index_argument, std::optional<const Value> dest, Value this_arg, T... args) { return Instruction{ - Op::kInvokeDirect, method_id, /*result_is_object=*/true, dest, this_arg, args...}; + Op::kInvokeDirect, index_argument, /*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, + static inline Instruction InvokeStatic(size_t index_argument, std::optional<const Value> dest, T... args) { - return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/false, dest, args...}; + return Instruction{Op::kInvokeStatic, index_argument, /*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, + static inline Instruction InvokeStaticObject(size_t index_argument, std::optional<const Value> dest, T... args) { - return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/true, dest, args...}; + return Instruction{Op::kInvokeStatic, index_argument, /*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, + static inline Instruction InvokeInterface(size_t index_argument, std::optional<const Value> dest, T... args) { - return Instruction{Op::kInvokeInterface, method_id, /*result_is_object=*/false, dest, args...}; + return Instruction{Op::kInvokeInterface, index_argument, /*result_is_object=*/false, dest, args...}; + + } + + static inline Instruction GetStaticField(size_t field_id, Value dest) { + return Instruction{Op::kGetStaticField, field_id, dest}; } /////////////// @@ -236,27 +242,27 @@ class Instruction { /////////////// Op opcode() const { return opcode_; } - size_t method_id() const { return method_id_; } + size_t index_argument() const { return index_argument_; } 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}, result_is_object_{false}, dest_{dest}, args_{} {} + inline Instruction(Op opcode, size_t index_argument, std::optional<const Value> dest) + : opcode_{opcode}, index_argument_{index_argument}, result_is_object_{false}, dest_{dest}, args_{} {} template <typename... T> - inline constexpr Instruction(Op opcode, size_t method_id, bool result_is_object, + inline constexpr Instruction(Op opcode, size_t index_argument, bool result_is_object, std::optional<const Value> dest, T... args) : opcode_{opcode}, - method_id_{method_id}, + index_argument_{index_argument}, 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 size_t index_argument_{0}; const bool result_is_object_; const std::optional<const Value> dest_; const std::vector<const Value> args_; @@ -319,6 +325,7 @@ class MethodBuilder { void EncodeBranch(art::Instruction::Code op, const Instruction& instruction); void EncodeNew(const Instruction& instruction); void EncodeCast(const Instruction& instruction); + void EncodeStaticFieldOp(const Instruction& instruction); // Low-level instruction format encoding. See // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of @@ -481,6 +488,11 @@ class DexBuilder { // See the TypeDescriptor class for help generating these. GetOrAddType can be used to declare // imported classes. ir::Type* GetOrAddType(const std::string& descriptor); + inline ir::Type* GetOrAddType(TypeDescriptor descriptor) { + return GetOrAddType(descriptor.descriptor()); + } + + ir::FieldDecl* GetOrAddField(TypeDescriptor parent, const std::string& name, TypeDescriptor type); // Returns the method id for the method, creating it if it has not been created yet. const MethodDeclData& GetOrDeclareMethod(TypeDescriptor type, const std::string& name, @@ -526,6 +538,9 @@ class DexBuilder { // Keep track of already-encoded protos. std::map<Prototype, ir::Proto*> proto_map_; + + // Keep track of fields that have been declared + std::map<std::tuple<TypeDescriptor, std::string>, ir::FieldDecl*> field_decls_by_key_; }; template <typename... T> |