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 "gc_root.h"
     24 #include "object_callbacks.h"
     25 #include "offsets.h"
     26 #include "primitive.h"
     27 #include "safe_map.h"
     28 
     29 #include <list>
     30 #include <map>
     31 
     32 namespace art {
     33 namespace mirror {
     34 class Array;
     35 class Object;
     36 class String;
     37 }
     38 class InternTable;
     39 
     40 class Transaction FINAL {
     41  public:
     42   static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError";
     43   static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
     44 
     45   Transaction();
     46   ~Transaction();
     47 
     48   void Abort(const std::string& abort_message)
     49       REQUIRES(!log_lock_)
     50       SHARED_REQUIRES(Locks::mutator_lock_);
     51   void ThrowAbortError(Thread* self, const std::string* abort_message)
     52       REQUIRES(!log_lock_)
     53       SHARED_REQUIRES(Locks::mutator_lock_);
     54   bool IsAborted() REQUIRES(!log_lock_);
     55 
     56   // Record object field changes.
     57   void RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset, uint8_t value,
     58                                bool is_volatile)
     59       REQUIRES(!log_lock_);
     60   void RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset, int8_t value,
     61                                bool is_volatile)
     62       REQUIRES(!log_lock_);
     63   void RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset, uint16_t value,
     64                             bool is_volatile)
     65       REQUIRES(!log_lock_);
     66   void RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset, int16_t value,
     67                              bool is_volatile)
     68       REQUIRES(!log_lock_);
     69   void RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
     70                           bool is_volatile)
     71       REQUIRES(!log_lock_);
     72   void RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
     73                           bool is_volatile)
     74       REQUIRES(!log_lock_);
     75   void RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
     76                                  mirror::Object* value, bool is_volatile)
     77       REQUIRES(!log_lock_);
     78 
     79   // Record array change.
     80   void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
     81       REQUIRES(!log_lock_)
     82       SHARED_REQUIRES(Locks::mutator_lock_);
     83 
     84   // Record intern string table changes.
     85   void RecordStrongStringInsertion(mirror::String* s)
     86       REQUIRES(Locks::intern_table_lock_)
     87       REQUIRES(!log_lock_);
     88   void RecordWeakStringInsertion(mirror::String* s)
     89       REQUIRES(Locks::intern_table_lock_)
     90       REQUIRES(!log_lock_);
     91   void RecordStrongStringRemoval(mirror::String* s)
     92       REQUIRES(Locks::intern_table_lock_)
     93       REQUIRES(!log_lock_);
     94   void RecordWeakStringRemoval(mirror::String* s)
     95       REQUIRES(Locks::intern_table_lock_)
     96       REQUIRES(!log_lock_);
     97 
     98   // Abort transaction by undoing all recorded changes.
     99   void Rollback()
    100       SHARED_REQUIRES(Locks::mutator_lock_)
    101       REQUIRES(!log_lock_);
    102 
    103   void VisitRoots(RootVisitor* visitor)
    104       REQUIRES(!log_lock_)
    105       SHARED_REQUIRES(Locks::mutator_lock_);
    106 
    107  private:
    108   class ObjectLog : public ValueObject {
    109    public:
    110     void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
    111     void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
    112     void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
    113     void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
    114     void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
    115     void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
    116     void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
    117 
    118     void Undo(mirror::Object* obj) SHARED_REQUIRES(Locks::mutator_lock_);
    119     void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_);
    120 
    121     size_t Size() const {
    122       return field_values_.size();
    123     }
    124 
    125    private:
    126     enum FieldValueKind {
    127       kBoolean,
    128       kByte,
    129       kChar,
    130       kShort,
    131       k32Bits,
    132       k64Bits,
    133       kReference
    134     };
    135     struct FieldValue : public ValueObject {
    136       // TODO use JValue instead ?
    137       uint64_t value;
    138       FieldValueKind kind;
    139       bool is_volatile;
    140     };
    141 
    142     void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
    143     void UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
    144                         const FieldValue& field_value) SHARED_REQUIRES(Locks::mutator_lock_);
    145 
    146     // Maps field's offset to its value.
    147     std::map<uint32_t, FieldValue> field_values_;
    148   };
    149 
    150   class ArrayLog : public ValueObject {
    151    public:
    152     void LogValue(size_t index, uint64_t value);
    153 
    154     void Undo(mirror::Array* obj) SHARED_REQUIRES(Locks::mutator_lock_);
    155 
    156     size_t Size() const {
    157       return array_values_.size();
    158     }
    159 
    160    private:
    161     void UndoArrayWrite(mirror::Array* array, Primitive::Type array_type, size_t index,
    162                         uint64_t value) SHARED_REQUIRES(Locks::mutator_lock_);
    163 
    164     // Maps index to value.
    165     // TODO use JValue instead ?
    166     std::map<size_t, uint64_t> array_values_;
    167   };
    168 
    169   class InternStringLog : public ValueObject {
    170    public:
    171     enum StringKind {
    172       kStrongString,
    173       kWeakString
    174     };
    175     enum StringOp {
    176       kInsert,
    177       kRemove
    178     };
    179     InternStringLog(mirror::String* s, StringKind kind, StringOp op)
    180       : str_(s), string_kind_(kind), string_op_(op) {
    181       DCHECK(s != nullptr);
    182     }
    183 
    184     void Undo(InternTable* intern_table)
    185         SHARED_REQUIRES(Locks::mutator_lock_)
    186         REQUIRES(Locks::intern_table_lock_);
    187     void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_);
    188 
    189    private:
    190     mirror::String* str_;
    191     const StringKind string_kind_;
    192     const StringOp string_op_;
    193   };
    194 
    195   void LogInternedString(const InternStringLog& log)
    196       REQUIRES(Locks::intern_table_lock_)
    197       REQUIRES(!log_lock_);
    198 
    199   void UndoObjectModifications()
    200       REQUIRES(log_lock_)
    201       SHARED_REQUIRES(Locks::mutator_lock_);
    202   void UndoArrayModifications()
    203       REQUIRES(log_lock_)
    204       SHARED_REQUIRES(Locks::mutator_lock_);
    205   void UndoInternStringTableModifications()
    206       REQUIRES(Locks::intern_table_lock_)
    207       REQUIRES(log_lock_)
    208       SHARED_REQUIRES(Locks::mutator_lock_);
    209 
    210   void VisitObjectLogs(RootVisitor* visitor)
    211       REQUIRES(log_lock_)
    212       SHARED_REQUIRES(Locks::mutator_lock_);
    213   void VisitArrayLogs(RootVisitor* visitor)
    214       REQUIRES(log_lock_)
    215       SHARED_REQUIRES(Locks::mutator_lock_);
    216   void VisitStringLogs(RootVisitor* visitor)
    217       REQUIRES(log_lock_)
    218       SHARED_REQUIRES(Locks::mutator_lock_);
    219 
    220   const std::string& GetAbortMessage() REQUIRES(!log_lock_);
    221 
    222   Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
    223   std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
    224   std::map<mirror::Array*, ArrayLog> array_logs_  GUARDED_BY(log_lock_);
    225   std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
    226   bool aborted_ GUARDED_BY(log_lock_);
    227   std::string abort_message_ GUARDED_BY(log_lock_);
    228 
    229   DISALLOW_COPY_AND_ASSIGN(Transaction);
    230 };
    231 
    232 }  // namespace art
    233 
    234 #endif  // ART_RUNTIME_TRANSACTION_H_
    235