| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_RAW_OBJECT_H_ | 5 #ifndef VM_RAW_OBJECT_H_ |
| 6 #define VM_RAW_OBJECT_H_ | 6 #define VM_RAW_OBJECT_H_ |
| 7 | 7 |
| 8 #include "vm/assert.h" | 8 #include "vm/assert.h" |
| 9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
| 10 #include "vm/snapshot.h" | 10 #include "vm/snapshot.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 kFreeListElement, | 84 kFreeListElement, |
| 85 kNumOfObjectKinds = kFreeListElement | 85 kNumOfObjectKinds = kFreeListElement |
| 86 }; | 86 }; |
| 87 | 87 |
| 88 enum ObjectAlignment { | 88 enum ObjectAlignment { |
| 89 // Alignment offsets are used to determine object age. | 89 // Alignment offsets are used to determine object age. |
| 90 kNewObjectAlignmentOffset = kWordSize, | 90 kNewObjectAlignmentOffset = kWordSize, |
| 91 kOldObjectAlignmentOffset = 0, | 91 kOldObjectAlignmentOffset = 0, |
| 92 // Object sizes are aligned to kObjectAlignment. | 92 // Object sizes are aligned to kObjectAlignment. |
| 93 kObjectAlignment = 2 * kWordSize, | 93 kObjectAlignment = 2 * kWordSize, |
| 94 kObjectAlignmentLog2 = kWordSizeLog2 + 1, |
| 94 kObjectAlignmentMask = kObjectAlignment - 1, | 95 kObjectAlignmentMask = kObjectAlignment - 1, |
| 95 }; | 96 }; |
| 96 | 97 |
| 97 enum { | 98 enum { |
| 98 kSmiTag = 0, | 99 kSmiTag = 0, |
| 99 kHeapObjectTag = 1, | 100 kHeapObjectTag = 1, |
| 100 kSmiTagSize = 1, | 101 kSmiTagSize = 1, |
| 101 kSmiTagMask = 1, | 102 kSmiTagMask = 1, |
| 102 kSmiTagShift = 1, | 103 kSmiTagShift = 1, |
| 103 }; | 104 }; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 126 ASSERT(IsHeapObject()); \ | 127 ASSERT(IsHeapObject()); \ |
| 127 return reinterpret_cast<Raw##object*>( \ | 128 return reinterpret_cast<Raw##object*>( \ |
| 128 reinterpret_cast<uword>(this) - kHeapObjectTag); \ | 129 reinterpret_cast<uword>(this) - kHeapObjectTag); \ |
| 129 } \ | 130 } \ |
| 130 SNAPSHOT_WRITER_SUPPORT() \ | 131 SNAPSHOT_WRITER_SUPPORT() \ |
| 131 | 132 |
| 132 | 133 |
| 133 // RawObject is the base class of all raw objects, even though it carries the | 134 // RawObject is the base class of all raw objects, even though it carries the |
| 134 // class_ field not all raw objects are allocated in the heap and thus cannot | 135 // class_ field not all raw objects are allocated in the heap and thus cannot |
| 135 // be dereferenced (e.g. RawSmi). | 136 // be dereferenced (e.g. RawSmi). |
| 136 // | |
| 137 // The tags field which is a part of the object header uses the following | |
| 138 // bit fields for storing tags. | |
| 139 // | |
| 140 // bit 0 - SmiTag | |
| 141 // bit 1 - Mark bit. | |
| 142 // bit 2 - Canonical object. | |
| 143 // bit 3 - Created from a full snapshot. | |
| 144 // | |
| 145 class RawObject { | 137 class RawObject { |
| 146 public: | 138 public: |
| 139 // The tags field which is a part of the object header uses the following |
| 140 // bit fields for storing tags. |
| 141 enum TagBits { |
| 142 kFreeBit = 0, |
| 143 kMarkBit = 1, |
| 144 kCanonicalBit = 2, |
| 145 kFromSnapshotBit = 3, |
| 146 kReservedBit10K = 4, |
| 147 kReservedBit100K = 5, |
| 148 kReservedBit1M = 6, |
| 149 kReservedBit10M = 7, |
| 150 kSizeTagBit = 8, |
| 151 kSizeTagSize = 8, |
| 152 }; |
| 153 |
| 154 // Encodes the object size in the tag in units of object alignment. |
| 155 class SizeTag { |
| 156 public: |
| 157 static const intptr_t kMaxSizeTag = |
| 158 ((1 << RawObject::kSizeTagSize) - 1) << kObjectAlignmentLog2; |
| 159 |
| 160 static uword encode(intptr_t size) { |
| 161 return SizeBits::encode(SizeToTagValue(size)); |
| 162 } |
| 163 |
| 164 static intptr_t decode(uword tag) { |
| 165 return TagValueToSize(SizeBits::decode(tag)); |
| 166 } |
| 167 |
| 168 static uword update(intptr_t size, uword tag) { |
| 169 return SizeBits::update(SizeToTagValue(size), tag); |
| 170 } |
| 171 |
| 172 private: |
| 173 // The actual unscaled bit field used within the tag field. |
| 174 class SizeBits : public BitField<intptr_t, kSizeTagBit, kSizeTagSize> {}; |
| 175 |
| 176 static intptr_t SizeToTagValue(intptr_t size) { |
| 177 ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
| 178 return (size > kMaxSizeTag) ? 0 : (size >> kObjectAlignmentLog2); |
| 179 } |
| 180 static intptr_t TagValueToSize(intptr_t value) { |
| 181 return value << kObjectAlignmentLog2; |
| 182 } |
| 183 }; |
| 184 |
| 147 bool IsHeapObject() const { | 185 bool IsHeapObject() const { |
| 148 uword value = reinterpret_cast<uword>(this); | 186 uword value = reinterpret_cast<uword>(this); |
| 149 return (value & kSmiTagMask) == kHeapObjectTag; | 187 return (value & kSmiTagMask) == kHeapObjectTag; |
| 150 } | 188 } |
| 151 | 189 |
| 152 bool IsNewObject() const { | 190 bool IsNewObject() const { |
| 153 uword addr = reinterpret_cast<uword>(this); | 191 uword addr = reinterpret_cast<uword>(this); |
| 154 return (addr & kNewObjectAlignmentOffset) == kNewObjectAlignmentOffset; | 192 return (addr & kNewObjectAlignmentOffset) == kNewObjectAlignmentOffset; |
| 155 } | 193 } |
| 156 bool IsOldObject() const { | 194 bool IsOldObject() const { |
| 157 uword addr = reinterpret_cast<uword>(this); | 195 uword addr = reinterpret_cast<uword>(this); |
| 158 return (addr & kNewObjectAlignmentOffset) == kOldObjectAlignmentOffset; | 196 return (addr & kNewObjectAlignmentOffset) == kOldObjectAlignmentOffset; |
| 159 } | 197 } |
| 160 | 198 |
| 161 // Support for GC marking bit. | 199 // Support for GC marking bit. |
| 162 bool IsMarked() const { | 200 bool IsMarked() const { |
| 163 return MarkBit::decode(ptr()->tags_); | 201 return MarkBit::decode(ptr()->tags_); |
| 164 } | 202 } |
| 165 void SetMarkBit() { | 203 void SetMarkBit() { |
| 166 ASSERT(!IsMarked()); | 204 ASSERT(!IsMarked()); |
| 167 intptr_t tags = ptr()->tags_; | 205 uword tags = ptr()->tags_; |
| 168 ptr()->tags_ = MarkBit::update(true, tags); | 206 ptr()->tags_ = MarkBit::update(true, tags); |
| 169 } | 207 } |
| 170 void ClearMarkBit() { | 208 void ClearMarkBit() { |
| 171 ASSERT(IsMarked()); | 209 ASSERT(IsMarked()); |
| 172 intptr_t tags = ptr()->tags_; | 210 uword tags = ptr()->tags_; |
| 173 ptr()->tags_ = MarkBit::update(false, tags); | 211 ptr()->tags_ = MarkBit::update(false, tags); |
| 174 } | 212 } |
| 175 | 213 |
| 176 // Support for object tags. | 214 // Support for object tags. |
| 177 bool IsCanonical() const { | 215 bool IsCanonical() const { |
| 178 return CanonicalObjectTag::decode(ptr()->tags_); | 216 return CanonicalObjectTag::decode(ptr()->tags_); |
| 179 } | 217 } |
| 180 void SetCanonical() { | 218 void SetCanonical() { |
| 181 intptr_t tags = ptr()->tags_; | 219 uword tags = ptr()->tags_; |
| 182 ptr()->tags_ = CanonicalObjectTag::update(true, tags); | 220 ptr()->tags_ = CanonicalObjectTag::update(true, tags); |
| 183 } | 221 } |
| 184 bool IsCreatedFromSnapshot() { | 222 bool IsCreatedFromSnapshot() const { |
| 185 return CreatedFromSnapshotTag::decode(ptr()->tags_); | 223 return CreatedFromSnapshotTag::decode(ptr()->tags_); |
| 186 } | 224 } |
| 187 void SetCreatedFromSnapshot() { | 225 void SetCreatedFromSnapshot() { |
| 188 intptr_t tags = ptr()->tags_; | 226 uword tags = ptr()->tags_; |
| 189 ptr()->tags_ = CreatedFromSnapshotTag::update(true, tags); | 227 ptr()->tags_ = CreatedFromSnapshotTag::update(true, tags); |
| 190 } | 228 } |
| 191 | 229 |
| 230 intptr_t Size() const { |
| 231 uword tags = ptr()->tags_; |
| 232 intptr_t result = SizeTag::decode(tags); |
| 233 if ((result != 0) && !FreeBit::decode(tags)) { |
| 234 ASSERT(result == SizeFromClass()); |
| 235 return result; |
| 236 } |
| 237 result = SizeFromClass(); |
| 238 ASSERT((result > SizeTag::kMaxSizeTag) || FreeBit::decode(tags)); |
| 239 return result; |
| 240 } |
| 241 |
| 192 void Validate() const; | 242 void Validate() const; |
| 193 intptr_t Size() const; | |
| 194 intptr_t VisitPointers(ObjectPointerVisitor* visitor); | 243 intptr_t VisitPointers(ObjectPointerVisitor* visitor); |
| 195 | 244 |
| 196 static RawObject* FromAddr(uword addr) { | 245 static RawObject* FromAddr(uword addr) { |
| 197 // We expect the untagged address here. | 246 // We expect the untagged address here. |
| 198 ASSERT((addr & kSmiTagMask) != kHeapObjectTag); | 247 ASSERT((addr & kSmiTagMask) != kHeapObjectTag); |
| 199 return reinterpret_cast<RawObject*>(addr + kHeapObjectTag); | 248 return reinterpret_cast<RawObject*>(addr + kHeapObjectTag); |
| 200 } | 249 } |
| 201 | 250 |
| 202 static uword ToAddr(RawObject* raw_obj) { | 251 static uword ToAddr(RawObject* raw_obj) { |
| 203 return reinterpret_cast<uword>(raw_obj->ptr()); | 252 return reinterpret_cast<uword>(raw_obj->ptr()); |
| 204 } | 253 } |
| 205 | 254 |
| 206 static bool IsCreatedFromSnapshot(intptr_t value) { | 255 static bool IsCreatedFromSnapshot(intptr_t value) { |
| 207 return CreatedFromSnapshotTag::decode(value); | 256 return CreatedFromSnapshotTag::decode(value); |
| 208 } | 257 } |
| 209 | 258 |
| 210 static bool IsCanonical(intptr_t value) { | 259 static bool IsCanonical(intptr_t value) { |
| 211 return CanonicalObjectTag::decode(value); | 260 return CanonicalObjectTag::decode(value); |
| 212 } | 261 } |
| 213 | 262 |
| 214 protected: | 263 protected: |
| 215 RawClass* class_; | 264 RawClass* class_; |
| 216 intptr_t tags_; // Various object tags (bits). | 265 uword tags_; // Various object tags (bits). |
| 217 | 266 |
| 218 private: | 267 private: |
| 219 enum { | 268 class FreeBit : public BitField<bool, kFreeBit, 1> {}; |
| 220 kMarkBit = 1, | |
| 221 kCanonicalBit = 2, | |
| 222 kFromSnapshotBit = 3, | |
| 223 }; | |
| 224 | 269 |
| 225 class MarkBit : public BitField<bool, kMarkBit, 1> {}; | 270 class MarkBit : public BitField<bool, kMarkBit, 1> {}; |
| 226 | 271 |
| 227 class CanonicalObjectTag : public BitField<bool, kCanonicalBit, 1> {}; | 272 class CanonicalObjectTag : public BitField<bool, kCanonicalBit, 1> {}; |
| 228 | 273 |
| 229 class CreatedFromSnapshotTag : public BitField<bool, kFromSnapshotBit, 1> {}; | 274 class CreatedFromSnapshotTag : public BitField<bool, kFromSnapshotBit, 1> {}; |
| 230 | 275 |
| 231 RawObject* ptr() const { | 276 RawObject* ptr() const { |
| 232 ASSERT(IsHeapObject()); | 277 ASSERT(IsHeapObject()); |
| 233 return reinterpret_cast<RawObject*>( | 278 return reinterpret_cast<RawObject*>( |
| 234 reinterpret_cast<uword>(this) - kHeapObjectTag); | 279 reinterpret_cast<uword>(this) - kHeapObjectTag); |
| 235 } | 280 } |
| 236 | 281 |
| 282 intptr_t SizeFromClass() const; |
| 283 |
| 237 friend class Object; | 284 friend class Object; |
| 238 friend class Array; | 285 friend class Array; |
| 239 friend class SnapshotWriter; | 286 friend class SnapshotWriter; |
| 240 friend class SnapshotReader; | 287 friend class SnapshotReader; |
| 241 friend class MarkingVisitor; | 288 friend class MarkingVisitor; |
| 242 | 289 |
| 243 DISALLOW_ALLOCATION(); | 290 DISALLOW_ALLOCATION(); |
| 244 DISALLOW_IMPLICIT_CONSTRUCTORS(RawObject); | 291 DISALLOW_IMPLICIT_CONSTRUCTORS(RawObject); |
| 245 }; | 292 }; |
| 246 | 293 |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 intptr_t type_; // Uninitialized, simple or complex. | 961 intptr_t type_; // Uninitialized, simple or complex. |
| 915 intptr_t flags_; // Represents global/local, case insensitive, multiline. | 962 intptr_t flags_; // Represents global/local, case insensitive, multiline. |
| 916 | 963 |
| 917 // Variable length data follows here. | 964 // Variable length data follows here. |
| 918 uint8_t data_[0]; | 965 uint8_t data_[0]; |
| 919 }; | 966 }; |
| 920 | 967 |
| 921 } // namespace dart | 968 } // namespace dart |
| 922 | 969 |
| 923 #endif // VM_RAW_OBJECT_H_ | 970 #endif // VM_RAW_OBJECT_H_ |
| OLD | NEW |