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/safe_map.h"
     23 #include "base/value_object.h"
     24 #include "dex/dex_file_types.h"
     25 #include "dex/primitive.h"
     26 #include "gc_root.h"
     27 #include "offsets.h"
     28 
     29 #include <list>
     30 #include <map>
     31 
     32 namespace art {
     33 namespace mirror {
     34 class Array;
     35 class Class;
     36 class DexCache;
     37 class Object;
     38 class String;
     39 }  // namespace mirror
     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   explicit Transaction(bool strict, mirror::Class* root);
     49   ~Transaction();
     50 
     51   void Abort(const std::string& abort_message)
     52       REQUIRES(!log_lock_)
     53       REQUIRES_SHARED(Locks::mutator_lock_);
     54   void ThrowAbortError(Thread* self, const std::string* abort_message)
     55       REQUIRES(!log_lock_)
     56       REQUIRES_SHARED(Locks::mutator_lock_);
     57   bool IsAborted() REQUIRES(!log_lock_);
     58 
     59   // If the transaction is rollbacking. Transactions will set this flag when they start rollbacking,
     60   // because the nested transaction should be disabled when rollbacking to restore the memory.
     61   bool IsRollingBack();
     62 
     63   // If the transaction is in strict mode, then all access of static fields will be constrained,
     64   // one class's clinit will not be allowed to read or modify another class's static fields, unless
     65   // the transaction is aborted.
     66   bool IsStrict() REQUIRES(!log_lock_);
     67 
     68   // Record object field changes.
     69   void RecordWriteFieldBoolean(mirror::Object* obj,
     70                                MemberOffset field_offset,
     71                                uint8_t value,
     72                                bool is_volatile)
     73       REQUIRES(!log_lock_);
     74   void RecordWriteFieldByte(mirror::Object* obj,
     75                             MemberOffset field_offset,
     76                             int8_t value,
     77                             bool is_volatile)
     78       REQUIRES(!log_lock_);
     79   void RecordWriteFieldChar(mirror::Object* obj,
     80                             MemberOffset field_offset,
     81                             uint16_t value,
     82                             bool is_volatile)
     83       REQUIRES(!log_lock_);
     84   void RecordWriteFieldShort(mirror::Object* obj,
     85                              MemberOffset field_offset,
     86                              int16_t value,
     87                              bool is_volatile)
     88       REQUIRES(!log_lock_);
     89   void RecordWriteField32(mirror::Object* obj,
     90                           MemberOffset field_offset,
     91                           uint32_t value,
     92                           bool is_volatile)
     93       REQUIRES(!log_lock_);
     94   void RecordWriteField64(mirror::Object* obj,
     95                           MemberOffset field_offset,
     96                           uint64_t value,
     97                           bool is_volatile)
     98       REQUIRES(!log_lock_);
     99   void RecordWriteFieldReference(mirror::Object* obj,
    100                                  MemberOffset field_offset,
    101                                  mirror::Object* value,
    102                                  bool is_volatile)
    103       REQUIRES(!log_lock_);
    104 
    105   // Record array change.
    106   void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
    107       REQUIRES(!log_lock_)
    108       REQUIRES_SHARED(Locks::mutator_lock_);
    109 
    110   // Record intern string table changes.
    111   void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
    112       REQUIRES(Locks::intern_table_lock_)
    113       REQUIRES(!log_lock_);
    114   void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
    115       REQUIRES(Locks::intern_table_lock_)
    116       REQUIRES(!log_lock_);
    117   void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
    118       REQUIRES(Locks::intern_table_lock_)
    119       REQUIRES(!log_lock_);
    120   void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
    121       REQUIRES(Locks::intern_table_lock_)
    122       REQUIRES(!log_lock_);
    123 
    124   // Record resolve string.
    125   void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
    126       REQUIRES_SHARED(Locks::mutator_lock_)
    127       REQUIRES(!log_lock_);
    128 
    129   // Abort transaction by undoing all recorded changes.
    130   void Rollback()
    131       REQUIRES_SHARED(Locks::mutator_lock_)
    132       REQUIRES(!log_lock_);
    133 
    134   void VisitRoots(RootVisitor* visitor)
    135       REQUIRES(!log_lock_)
    136       REQUIRES_SHARED(Locks::mutator_lock_);
    137 
    138   bool ReadConstraint(mirror::Object* obj, ArtField* field)
    139       REQUIRES(!log_lock_)
    140       REQUIRES_SHARED(Locks::mutator_lock_);
    141 
    142   bool WriteConstraint(mirror::Object* obj, ArtField* field)
    143       REQUIRES(!log_lock_)
    144       REQUIRES_SHARED(Locks::mutator_lock_);
    145 
    146  private:
    147   class ObjectLog : public ValueObject {
    148    public:
    149     void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
    150     void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
    151     void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
    152     void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
    153     void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
    154     void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
    155     void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
    156 
    157     void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
    158     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
    159 
    160     size_t Size() const {
    161       return field_values_.size();
    162     }
    163 
    164     ObjectLog() = default;
    165     ObjectLog(ObjectLog&& log) = default;
    166 
    167    private:
    168     enum FieldValueKind {
    169       kBoolean,
    170       kByte,
    171       kChar,
    172       kShort,
    173       k32Bits,
    174       k64Bits,
    175       kReference
    176     };
    177     struct FieldValue : public ValueObject {
    178       // TODO use JValue instead ?
    179       uint64_t value;
    180       FieldValueKind kind;
    181       bool is_volatile;
    182 
    183       FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
    184       FieldValue(FieldValue&& log) = default;
    185 
    186      private:
    187       DISALLOW_COPY_AND_ASSIGN(FieldValue);
    188     };
    189 
    190     void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
    191     void UndoFieldWrite(mirror::Object* obj,
    192                         MemberOffset field_offset,
    193                         const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
    194 
    195     // Maps field's offset to its value.
    196     std::map<uint32_t, FieldValue> field_values_;
    197 
    198     DISALLOW_COPY_AND_ASSIGN(ObjectLog);
    199   };
    200 
    201   class ArrayLog : public ValueObject {
    202    public:
    203     void LogValue(size_t index, uint64_t value);
    204 
    205     void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
    206 
    207     size_t Size() const {
    208       return array_values_.size();
    209     }
    210 
    211     ArrayLog() = default;
    212     ArrayLog(ArrayLog&& log) = default;
    213 
    214    private:
    215     void UndoArrayWrite(mirror::Array* array,
    216                         Primitive::Type array_type,
    217                         size_t index,
    218                         uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
    219 
    220     // Maps index to value.
    221     // TODO use JValue instead ?
    222     std::map<size_t, uint64_t> array_values_;
    223 
    224     DISALLOW_COPY_AND_ASSIGN(ArrayLog);
    225   };
    226 
    227   class InternStringLog : public ValueObject {
    228    public:
    229     enum StringKind {
    230       kStrongString,
    231       kWeakString
    232     };
    233     enum StringOp {
    234       kInsert,
    235       kRemove
    236     };
    237     InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
    238 
    239     void Undo(InternTable* intern_table) const
    240         REQUIRES_SHARED(Locks::mutator_lock_)
    241         REQUIRES(Locks::intern_table_lock_);
    242     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
    243 
    244     InternStringLog() = default;
    245     InternStringLog(InternStringLog&& log) = default;
    246 
    247    private:
    248     mutable GcRoot<mirror::String> str_;
    249     const StringKind string_kind_;
    250     const StringOp string_op_;
    251 
    252     DISALLOW_COPY_AND_ASSIGN(InternStringLog);
    253   };
    254 
    255   class ResolveStringLog : public ValueObject {
    256    public:
    257     ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
    258 
    259     void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
    260 
    261     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
    262 
    263    private:
    264     GcRoot<mirror::DexCache> dex_cache_;
    265     const dex::StringIndex string_idx_;
    266 
    267     DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
    268   };
    269 
    270   void LogInternedString(InternStringLog&& log)
    271       REQUIRES(Locks::intern_table_lock_)
    272       REQUIRES(!log_lock_);
    273 
    274   void UndoObjectModifications()
    275       REQUIRES(log_lock_)
    276       REQUIRES_SHARED(Locks::mutator_lock_);
    277   void UndoArrayModifications()
    278       REQUIRES(log_lock_)
    279       REQUIRES_SHARED(Locks::mutator_lock_);
    280   void UndoInternStringTableModifications()
    281       REQUIRES(Locks::intern_table_lock_)
    282       REQUIRES(log_lock_)
    283       REQUIRES_SHARED(Locks::mutator_lock_);
    284   void UndoResolveStringModifications()
    285       REQUIRES(log_lock_)
    286       REQUIRES_SHARED(Locks::mutator_lock_);
    287 
    288   void VisitObjectLogs(RootVisitor* visitor)
    289       REQUIRES(log_lock_)
    290       REQUIRES_SHARED(Locks::mutator_lock_);
    291   void VisitArrayLogs(RootVisitor* visitor)
    292       REQUIRES(log_lock_)
    293       REQUIRES_SHARED(Locks::mutator_lock_);
    294   void VisitInternStringLogs(RootVisitor* visitor)
    295       REQUIRES(log_lock_)
    296       REQUIRES_SHARED(Locks::mutator_lock_);
    297   void VisitResolveStringLogs(RootVisitor* visitor)
    298       REQUIRES(log_lock_)
    299       REQUIRES_SHARED(Locks::mutator_lock_);
    300 
    301   const std::string& GetAbortMessage() REQUIRES(!log_lock_);
    302 
    303   Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
    304   std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
    305   std::map<mirror::Array*, ArrayLog> array_logs_  GUARDED_BY(log_lock_);
    306   std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
    307   std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
    308   bool aborted_ GUARDED_BY(log_lock_);
    309   bool rolling_back_;  // Single thread, no race.
    310   bool strict_ GUARDED_BY(log_lock_);
    311   std::string abort_message_ GUARDED_BY(log_lock_);
    312   mirror::Class* root_ GUARDED_BY(log_lock_);
    313 
    314   DISALLOW_COPY_AND_ASSIGN(Transaction);
    315 };
    316 
    317 }  // namespace art
    318 
    319 #endif  // ART_RUNTIME_TRANSACTION_H_
    320