| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #ifndef RUNTIME_VM_COMPILER_ASSEMBLER_OBJECT_POOL_BUILDER_H_ |
| #define RUNTIME_VM_COMPILER_ASSEMBLER_OBJECT_POOL_BUILDER_H_ |
| |
| #include "platform/globals.h" |
| #include "vm/bitfield.h" |
| #include "vm/hash_map.h" |
| |
| namespace dart { |
| |
| class Object; |
| |
| namespace compiler { |
| |
| class ExternalLabel; |
| |
| bool IsSameObject(const Object& a, const Object& b); |
| |
| struct ObjectPoolBuilderEntry { |
| enum Patchability { |
| kPatchable, |
| kNotPatchable, |
| }; |
| |
| enum EntryType { |
| kTaggedObject, |
| kImmediate, |
| kNativeFunction, |
| kNativeFunctionWrapper, |
| kNativeEntryData, |
| }; |
| |
| using TypeBits = BitField<uint8_t, EntryType, 0, 7>; |
| using PatchableBit = BitField<uint8_t, Patchability, TypeBits::kNextBit, 1>; |
| |
| static inline uint8_t EncodeTraits(EntryType type, Patchability patchable) { |
| return TypeBits::encode(type) | PatchableBit::encode(patchable); |
| } |
| |
| ObjectPoolBuilderEntry() : raw_value_(), entry_bits_(0), equivalence_() {} |
| ObjectPoolBuilderEntry(const Object* obj, Patchability patchable) |
| : ObjectPoolBuilderEntry(obj, obj, patchable) {} |
| ObjectPoolBuilderEntry(const Object* obj, |
| const Object* eqv, |
| Patchability patchable) |
| : obj_(obj), |
| entry_bits_(EncodeTraits(kTaggedObject, patchable)), |
| equivalence_(eqv) {} |
| ObjectPoolBuilderEntry(uword value, EntryType info, Patchability patchable) |
| : raw_value_(value), |
| entry_bits_(EncodeTraits(info, patchable)), |
| equivalence_() {} |
| |
| EntryType type() const { return TypeBits::decode(entry_bits_); } |
| |
| Patchability patchable() const { return PatchableBit::decode(entry_bits_); } |
| |
| union { |
| const Object* obj_; |
| uword raw_value_; |
| }; |
| uint8_t entry_bits_; |
| const Object* equivalence_; |
| }; |
| |
| // Pair type parameter for DirectChainedHashMap used for the constant pool. |
| class ObjIndexPair { |
| public: |
| // Typedefs needed for the DirectChainedHashMap template. |
| typedef ObjectPoolBuilderEntry Key; |
| typedef intptr_t Value; |
| typedef ObjIndexPair Pair; |
| |
| static const intptr_t kNoIndex = -1; |
| |
| ObjIndexPair() |
| : key_(reinterpret_cast<uword>(nullptr), |
| ObjectPoolBuilderEntry::kTaggedObject, |
| ObjectPoolBuilderEntry::kPatchable), |
| value_(kNoIndex) {} |
| |
| ObjIndexPair(Key key, Value value) : value_(value) { |
| key_.entry_bits_ = key.entry_bits_; |
| if (key.type() == ObjectPoolBuilderEntry::kTaggedObject) { |
| key_.obj_ = key.obj_; |
| key_.equivalence_ = key.equivalence_; |
| } else { |
| key_.raw_value_ = key.raw_value_; |
| } |
| } |
| |
| static Key KeyOf(Pair kv) { return kv.key_; } |
| |
| static Value ValueOf(Pair kv) { return kv.value_; } |
| |
| static intptr_t Hashcode(Key key); |
| |
| static inline bool IsKeyEqual(Pair kv, Key key) { |
| if (kv.key_.entry_bits_ != key.entry_bits_) return false; |
| if (kv.key_.type() == ObjectPoolBuilderEntry::kTaggedObject) { |
| return IsSameObject(*kv.key_.obj_, *key.obj_) && |
| IsSameObject(*kv.key_.equivalence_, *key.equivalence_); |
| } |
| return kv.key_.raw_value_ == key.raw_value_; |
| } |
| |
| private: |
| Key key_; |
| Value value_; |
| }; |
| |
| class ObjectPoolBuilder : public ValueObject { |
| public: |
| ObjectPoolBuilder() : zone_(nullptr) {} |
| ~ObjectPoolBuilder() { |
| if (zone_ != nullptr) { |
| Reset(); |
| zone_ = nullptr; |
| } |
| } |
| |
| // Clears all existing entries in this object pool builder. |
| // |
| // Note: Any code which has been compiled via this builder might use offsets |
| // into the pool which are not correct anymore. |
| void Reset(); |
| |
| // Initialize this object pool builder with a [zone]. |
| // |
| // Any objects added later on will be referenced using handles from [zone]. |
| void InitializeWithZone(Zone* zone) { |
| ASSERT(object_pool_.length() == 0); |
| ASSERT(zone_ == nullptr && zone != nullptr); |
| zone_ = zone; |
| } |
| |
| intptr_t AddObject(const Object& obj, |
| ObjectPoolBuilderEntry::Patchability patchable = |
| ObjectPoolBuilderEntry::kNotPatchable); |
| intptr_t AddImmediate(uword imm); |
| |
| intptr_t FindObject(const Object& obj, |
| ObjectPoolBuilderEntry::Patchability patchable = |
| ObjectPoolBuilderEntry::kNotPatchable); |
| intptr_t FindObject(const Object& obj, const Object& equivalence); |
| intptr_t FindImmediate(uword imm); |
| intptr_t FindNativeFunction(const ExternalLabel* label, |
| ObjectPoolBuilderEntry::Patchability patchable); |
| intptr_t FindNativeFunctionWrapper( |
| const ExternalLabel* label, |
| ObjectPoolBuilderEntry::Patchability patchable); |
| |
| intptr_t CurrentLength() const { return object_pool_.length(); } |
| ObjectPoolBuilderEntry& EntryAt(intptr_t i) { return object_pool_[i]; } |
| const ObjectPoolBuilderEntry& EntryAt(intptr_t i) const { |
| return object_pool_[i]; |
| } |
| |
| intptr_t AddObject(ObjectPoolBuilderEntry entry); |
| |
| private: |
| intptr_t FindObject(ObjectPoolBuilderEntry entry); |
| |
| // Objects and jump targets. |
| GrowableArray<ObjectPoolBuilderEntry> object_pool_; |
| |
| // Hashmap for fast lookup in object pool. |
| DirectChainedHashMap<ObjIndexPair> object_pool_index_table_; |
| |
| // The zone used for allocating the handles we keep in the map and array (or |
| // NULL, in which case allocations happen using the zone active at the point |
| // of insertion). |
| Zone* zone_; |
| }; |
| |
| } // namespace compiler |
| |
| } // namespace dart |
| |
| namespace dart { |
| using compiler::ObjectPoolBuilder; |
| } |
| |
| #endif // RUNTIME_VM_COMPILER_ASSEMBLER_OBJECT_POOL_BUILDER_H_ |