Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_TRANSACTION_H_
     18 #define ART_RUNTIME_TRANSACTION_H_
     19 
     20 #include "base/macros.h"
     21 #include "base/mutex.h"
     22 #include "base/value_object.h"
     23 #include "dex_file_types.h"
     24 #include "gc_root.h"
     25 #include "object_callbacks.h"
     26 #include "offsets.h"
     27 #include "primitive.h"
     28 #include "safe_map.h"
     29 
     30 #include <list>
     31 #include <map>
     32 
     33 namespace art {
     34 namespace mirror {
     35 class Array;
     36 class DexCache;
     37 class Object;
     38 class String;
     39 }
     40 class InternTable;
     41 
     42 class Transaction FINAL {
     43  public:
     44   static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError";
     45   static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
     46 
     47   Transaction();
     48   ~Transaction();
     49 
     50   void Abort(const std::string& abort_message)
     51       REQUIRES(!log_lock_)
     52       REQUIRES_SHARED(Locks::mutator_lock_);
     53   void ThrowAbortError(Thread* self, const std::string* abort_message)
     54       REQUIRES(!log_lock_)
     55       REQUIRES_SHARED(Locks::mutator_lock_);
     56   bool IsAborted() REQUIRES(!log_lock_);
     57 
     58   // Record object field changes.
     59   void RecordWriteFieldBoolean(mirror::Object* obj,
     60                                MemberOffset field_offset,
     61                                uint8_t value,
     62                                bool is_volatile)
     63       REQUIRES(!log_lock_);
     64   void RecordWriteFieldByte(mirror::Object* obj,
     65                             MemberOffset field_offset,
     66                             int8_t value,
     67                             bool is_volatile)
     68       REQUIRES(!log_lock_);
     69   void RecordWriteFieldChar(mirror::Object* obj,
     70                             MemberOffset field_offset,
     71                             uint16_t value,
     72                             bool is_volatile)
     73       REQUIRES(!log_lock_);
     74   void RecordWriteFieldShort(mirror::Object* obj,
     75                              MemberOffset field_offset,
     76                              int16_t value,
     77                              bool is_volatile)
     78       REQUIRES(!log_lock_);
     79   void RecordWriteField32(mirror::Object* obj,
     80                           MemberOffset field_offset,
     81                           uint32_t value,
     82                           bool is_volatile)
     83       REQUIRES(!log_lock_);
     84   void RecordWriteField64(mirror::Object* obj,
     85                           MemberOffset field_offset,
     86                           uint64_t value,
     87                           bool is_volatile)
     88       REQUIRES(!log_lock_);
     89   void RecordWriteFieldReference(mirror::Object* obj,
     90                                  MemberOffset field_offset,
     91                                  mirror::Object* value,
     92                                  bool is_volatile)
     93       REQUIRES(!log_lock_);
     94 
     95   // Record array change.
     96   void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
     97       REQUIRES(!log_lock_)
     98       REQUIRES_SHARED(Locks::mutator_lock_);
     99 
    100   // Record intern string table changes.
    101   void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
    102       REQUIRES(Locks::intern_table_lock_)
    103       REQUIRES(!log_lock_);
    104   void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
    105       REQUIRES(Locks::intern_table_lock_)
    106       REQUIRES(!log_lock_);
    107   void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
    108       REQUIRES(Locks::intern_table_lock_)
    109       REQUIRES(!log_lock_);
    110   void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
    111       REQUIRES(Locks::intern_table_lock_)
    112       REQUIRES(!log_lock_);
    113 
    114   // Record resolve string.
    115   void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
    116       REQUIRES_SHARED(Locks::mutator_lock_)
    117       REQUIRES(!log_lock_);
    118 
    119   // Abort transaction by undoing all recorded changes.
    120   void Rollback()
    121       REQUIRES_SHARED(Locks::mutator_lock_)
    122       REQUIRES(!log_lock_);
    123 
    124   void VisitRoots(RootVisitor* visitor)
    125       REQUIRES(!log_lock_)
    126       REQUIRES_SHARED(Locks::mutator_lock_);
    127 
    128  private:
    129   class ObjectLog : public ValueObject {
    130    public:
    131     void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
    132     void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
    133     void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
    134     void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
    135     void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
    136     void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
    137     void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
    138 
    139     void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
    140     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
    141 
    142     size_t Size() const {
    143       return field_values_.size();
    144     }
    145 
    146     ObjectLog() = default;
    147     ObjectLog(ObjectLog&& log) = default;
    148 
    149    private:
    150     enum FieldValueKind {
    151       kBoolean,
    152       kByte,
    153       kChar,
    154       kShort,
    155       k32Bits,
    156       k64Bits,
    157       kReference
    158     };
    159     struct FieldValue : public ValueObject {
    160       // TODO use JValue instead ?
    161       uint64_t value;
    162       FieldValueKind kind;
    163       bool is_volatile;
    164 
    165       FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
    166       FieldValue(FieldValue&& log) = default;
    167 
    168      private:
    169       DISALLOW_COPY_AND_ASSIGN(FieldValue);
    170     };
    171 
    172     void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
    173     void UndoFieldWrite(mirror::Object* obj,
    174                         MemberOffset field_offset,
    175                         const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
    176 
    177     // Maps field's offset to its value.
    178     std::map<uint32_t, FieldValue> field_values_;
    179 
    180     DISALLOW_COPY_AND_ASSIGN(ObjectLog);
    181   };
    182 
    183   class ArrayLog : public ValueObject {
    184    public:
    185     void LogValue(size_t index, uint64_t value);
    186 
    187     void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
    188 
    189     size_t Size() const {
    190       return array_values_.size();
    191     }
    192 
    193     ArrayLog() = default;
    194     ArrayLog(ArrayLog&& log) = default;
    195 
    196    private:
    197     void UndoArrayWrite(mirror::Array* array,
    198                         Primitive::Type array_type,
    199                         size_t index,
    200                         uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
    201 
    202     // Maps index to value.
    203     // TODO use JValue instead ?
    204     std::map<size_t, uint64_t> array_values_;
    205 
    206     DISALLOW_COPY_AND_ASSIGN(ArrayLog);
    207   };
    208 
    209   class InternStringLog : public ValueObject {
    210    public:
    211     enum StringKind {
    212       kStrongString,
    213       kWeakString
    214     };
    215     enum StringOp {
    216       kInsert,
    217       kRemove
    218     };
    219     InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
    220 
    221     void Undo(InternTable* intern_table) const
    222         REQUIRES_SHARED(Locks::mutator_lock_)
    223         REQUIRES(Locks::intern_table_lock_);
    224     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
    225 
    226     InternStringLog() = default;
    227     InternStringLog(InternStringLog&& log) = default;
    228 
    229    private:
    230     mutable GcRoot<mirror::String> str_;
    231     const StringKind string_kind_;
    232     const StringOp string_op_;
    233 
    234     DISALLOW_COPY_AND_ASSIGN(InternStringLog);
    235   };
    236 
    237   class ResolveStringLog : public ValueObject {
    238    public:
    239     ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
    240 
    241     void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
    242 
    243     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
    244 
    245    private:
    246     GcRoot<mirror::DexCache> dex_cache_;
    247     const dex::StringIndex string_idx_;
    248 
    249     DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
    250   };
    251 
    252   void LogInternedString(InternStringLog&& log)
    253       REQUIRES(Locks::intern_table_lock_)
    254       REQUIRES(!log_lock_);
    255 
    256   void UndoObjectModifications()
    257       REQUIRES(log_lock_)
    258       REQUIRES_SHARED(Locks::mutator_lock_);
    259   void UndoArrayModifications()
    260       REQUIRES(log_lock_)
    261       REQUIRES_SHARED(Locks::mutator_lock_);
    262   void UndoInternStringTableModifications()
    263       REQUIRES(Locks::intern_table_lock_)
    264       REQUIRES(log_lock_)
    265       REQUIRES_SHARED(Locks::mutator_lock_);
    266   void UndoResolveStringModifications()
    267       REQUIRES(log_lock_)
    268       REQUIRES_SHARED(Locks::mutator_lock_);
    269 
    270   void VisitObjectLogs(RootVisitor* visitor)
    271       REQUIRES(log_lock_)
    272       REQUIRES_SHARED(Locks::mutator_lock_);
    273   void VisitArrayLogs(RootVisitor* visitor)
    274       REQUIRES(log_lock_)
    275       REQUIRES_SHARED(Locks::mutator_lock_);
    276   void VisitInternStringLogs(RootVisitor* visitor)
    277       REQUIRES(log_lock_)
    278       REQUIRES_SHARED(Locks::mutator_lock_);
    279   void VisitResolveStringLogs(RootVisitor* visitor)
    280       REQUIRES(log_lock_)
    281       REQUIRES_SHARED(Locks::mutator_lock_);
    282 
    283   const std::string& GetAbortMessage() REQUIRES(!log_lock_);
    284 
    285   Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
    286   std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
    287   std::map<mirror::Array*, ArrayLog> array_logs_  GUARDED_BY(log_lock_);
    288   std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
    289   std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
    290   bool aborted_ GUARDED_BY(log_lock_);
    291   std::string abort_message_ GUARDED_BY(log_lock_);
    292 
    293   DISALLOW_COPY_AND_ASSIGN(Transaction);
    294 };
    295 
    296 }  // namespace art
    297 
    298 #endif  // ART_RUNTIME_TRANSACTION_H_
    299