Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 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_INTERN_TABLE_H_
     18 #define ART_RUNTIME_INTERN_TABLE_H_
     19 
     20 #include <unordered_set>
     21 
     22 #include "base/allocator.h"
     23 #include "base/mutex.h"
     24 #include "gc_root.h"
     25 #include "object_callbacks.h"
     26 
     27 namespace art {
     28 
     29 enum VisitRootFlags : uint8_t;
     30 
     31 namespace mirror {
     32 class String;
     33 }  // namespace mirror
     34 class Transaction;
     35 
     36 /**
     37  * Used to intern strings.
     38  *
     39  * There are actually two tables: one that holds strong references to its strings, and one that
     40  * holds weak references. The former is used for string literals, for which there is an effective
     41  * reference from the constant pool. The latter is used for strings interned at runtime via
     42  * String.intern. Some code (XML parsers being a prime example) relies on being able to intern
     43  * arbitrarily many strings for the duration of a parse without permanently increasing the memory
     44  * footprint.
     45  */
     46 class InternTable {
     47  public:
     48   InternTable();
     49 
     50   // Interns a potentially new string in the 'strong' table. (See above.)
     51   mirror::String* InternStrong(int32_t utf16_length, const char* utf8_data)
     52       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     53 
     54   // Interns a potentially new string in the 'strong' table. (See above.)
     55   mirror::String* InternStrong(const char* utf8_data)
     56       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     57 
     58   // Interns a potentially new string in the 'strong' table. (See above.)
     59   mirror::String* InternStrong(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     60 
     61   // Interns a potentially new string in the 'weak' table. (See above.)
     62   mirror::String* InternWeak(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     63 
     64   void SweepInternTableWeaks(IsMarkedCallback* callback, void* arg)
     65       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     66 
     67   bool ContainsWeak(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     68 
     69   size_t Size() const;
     70   size_t StrongSize() const;
     71   size_t WeakSize() const;
     72 
     73   void VisitRoots(RootCallback* callback, void* arg, VisitRootFlags flags)
     74       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     75 
     76   void DumpForSigQuit(std::ostream& os) const;
     77 
     78   void DisallowNewInterns() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
     79   void AllowNewInterns() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     80 
     81  private:
     82   class StringHashEquals {
     83    public:
     84     std::size_t operator()(const GcRoot<mirror::String>& root) NO_THREAD_SAFETY_ANALYSIS;
     85     bool operator()(const GcRoot<mirror::String>& a, const GcRoot<mirror::String>& b)
     86         NO_THREAD_SAFETY_ANALYSIS;
     87   };
     88   typedef std::unordered_set<GcRoot<mirror::String>, StringHashEquals, StringHashEquals,
     89       TrackingAllocator<GcRoot<mirror::String>, kAllocatorTagInternTable>> Table;
     90 
     91   mirror::String* Insert(mirror::String* s, bool is_strong)
     92       LOCKS_EXCLUDED(Locks::intern_table_lock_)
     93       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     94 
     95   mirror::String* LookupStrong(mirror::String* s)
     96       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     97   mirror::String* LookupWeak(mirror::String* s)
     98       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     99   mirror::String* Lookup(Table* table, mirror::String* s)
    100       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    101   mirror::String* InsertStrong(mirror::String* s)
    102       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    103   mirror::String* InsertWeak(mirror::String* s)
    104       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    105   void RemoveStrong(mirror::String* s)
    106       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    107       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    108   void RemoveWeak(mirror::String* s)
    109       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    110       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    111   void Remove(Table* table, mirror::String* s)
    112       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    113       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    114 
    115   // Transaction rollback access.
    116   mirror::String* InsertStrongFromTransaction(mirror::String* s)
    117       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    118   mirror::String* InsertWeakFromTransaction(mirror::String* s)
    119       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    120   void RemoveStrongFromTransaction(mirror::String* s)
    121       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    122       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    123   void RemoveWeakFromTransaction(mirror::String* s)
    124       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    125       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    126   friend class Transaction;
    127 
    128   bool log_new_roots_ GUARDED_BY(Locks::intern_table_lock_);
    129   bool allow_new_interns_ GUARDED_BY(Locks::intern_table_lock_);
    130   ConditionVariable new_intern_condition_ GUARDED_BY(Locks::intern_table_lock_);
    131   // Since this contains (strong) roots, they need a read barrier to
    132   // enable concurrent intern table (strong) root scan. Do not
    133   // directly access the strings in it. Use functions that contain
    134   // read barriers.
    135   Table strong_interns_ GUARDED_BY(Locks::intern_table_lock_);
    136   std::vector<GcRoot<mirror::String>> new_strong_intern_roots_
    137       GUARDED_BY(Locks::intern_table_lock_);
    138   // Since this contains (weak) roots, they need a read barrier. Do
    139   // not directly access the strings in it. Use functions that contain
    140   // read barriers.
    141   Table weak_interns_ GUARDED_BY(Locks::intern_table_lock_);
    142 };
    143 
    144 }  // namespace art
    145 
    146 #endif  // ART_RUNTIME_INTERN_TABLE_H_
    147