OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_OBJECTS_H_ | 5 #ifndef V8_OBJECTS_H_ |
6 #define V8_OBJECTS_H_ | 6 #define V8_OBJECTS_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/assert-scope.h" | 9 #include "src/assert-scope.h" |
10 #include "src/builtins.h" | 10 #include "src/builtins.h" |
(...skipping 1416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1427 | 1427 |
1428 inline Representation OptimalRepresentation() { | 1428 inline Representation OptimalRepresentation() { |
1429 if (!FLAG_track_fields) return Representation::Tagged(); | 1429 if (!FLAG_track_fields) return Representation::Tagged(); |
1430 if (IsSmi()) { | 1430 if (IsSmi()) { |
1431 return Representation::Smi(); | 1431 return Representation::Smi(); |
1432 } else if (FLAG_track_double_fields && IsHeapNumber()) { | 1432 } else if (FLAG_track_double_fields && IsHeapNumber()) { |
1433 return Representation::Double(); | 1433 return Representation::Double(); |
1434 } else if (FLAG_track_computed_fields && IsUninitialized()) { | 1434 } else if (FLAG_track_computed_fields && IsUninitialized()) { |
1435 return Representation::None(); | 1435 return Representation::None(); |
1436 } else if (FLAG_track_heap_object_fields) { | 1436 } else if (FLAG_track_heap_object_fields) { |
1437 ASSERT(IsHeapObject()); | 1437 DCHECK(IsHeapObject()); |
1438 return Representation::HeapObject(); | 1438 return Representation::HeapObject(); |
1439 } else { | 1439 } else { |
1440 return Representation::Tagged(); | 1440 return Representation::Tagged(); |
1441 } | 1441 } |
1442 } | 1442 } |
1443 | 1443 |
1444 inline bool FitsRepresentation(Representation representation) { | 1444 inline bool FitsRepresentation(Representation representation) { |
1445 if (FLAG_track_fields && representation.IsNone()) { | 1445 if (FLAG_track_fields && representation.IsNone()) { |
1446 return false; | 1446 return false; |
1447 } else if (FLAG_track_fields && representation.IsSmi()) { | 1447 } else if (FLAG_track_fields && representation.IsSmi()) { |
(...skipping 1130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2578 | 2578 |
2579 // Maximal length of fast elements array that won't be checked for | 2579 // Maximal length of fast elements array that won't be checked for |
2580 // being dense enough on expansion. | 2580 // being dense enough on expansion. |
2581 static const int kMaxUncheckedFastElementsLength = 5000; | 2581 static const int kMaxUncheckedFastElementsLength = 5000; |
2582 | 2582 |
2583 // Same as above but for old arrays. This limit is more strict. We | 2583 // Same as above but for old arrays. This limit is more strict. We |
2584 // don't want to be wasteful with long lived objects. | 2584 // don't want to be wasteful with long lived objects. |
2585 static const int kMaxUncheckedOldFastElementsLength = 500; | 2585 static const int kMaxUncheckedOldFastElementsLength = 500; |
2586 | 2586 |
2587 // Note that Page::kMaxRegularHeapObjectSize puts a limit on | 2587 // Note that Page::kMaxRegularHeapObjectSize puts a limit on |
2588 // permissible values (see the ASSERT in heap.cc). | 2588 // permissible values (see the DCHECK in heap.cc). |
2589 static const int kInitialMaxFastElementArray = 100000; | 2589 static const int kInitialMaxFastElementArray = 100000; |
2590 | 2590 |
2591 // This constant applies only to the initial map of "$Object" aka | 2591 // This constant applies only to the initial map of "$Object" aka |
2592 // "global.Object" and not to arbitrary other JSObject maps. | 2592 // "global.Object" and not to arbitrary other JSObject maps. |
2593 static const int kInitialGlobalObjectUnusedPropertiesCount = 4; | 2593 static const int kInitialGlobalObjectUnusedPropertiesCount = 4; |
2594 | 2594 |
2595 static const int kMaxInstanceSize = 255 * kPointerSize; | 2595 static const int kMaxInstanceSize = 255 * kPointerSize; |
2596 // When extending the backing storage for property values, we increase | 2596 // When extending the backing storage for property values, we increase |
2597 // its size by more than the 1 entry necessary, so sequentially adding fields | 2597 // its size by more than the 1 entry necessary, so sequentially adding fields |
2598 // to the same object requires fewer allocations and copies. | 2598 // to the same object requires fewer allocations and copies. |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3254 LayoutSection section; | 3254 LayoutSection section; |
3255 if (is_extended_layout() && index >= first_extended_section_index()) { | 3255 if (is_extended_layout() && index >= first_extended_section_index()) { |
3256 section = EXTENDED_SECTION; | 3256 section = EXTENDED_SECTION; |
3257 offset = get_extended_section_header_offset() + kExtendedFirstOffset; | 3257 offset = get_extended_section_header_offset() + kExtendedFirstOffset; |
3258 } else { | 3258 } else { |
3259 section = SMALL_SECTION; | 3259 section = SMALL_SECTION; |
3260 offset = kFirstEntryOffset; | 3260 offset = kFirstEntryOffset; |
3261 } | 3261 } |
3262 | 3262 |
3263 // Add offsets for the preceding type sections. | 3263 // Add offsets for the preceding type sections. |
3264 ASSERT(index <= last_index(LAST_TYPE, section)); | 3264 DCHECK(index <= last_index(LAST_TYPE, section)); |
3265 for (Type type = FIRST_TYPE; index > last_index(type, section); | 3265 for (Type type = FIRST_TYPE; index > last_index(type, section); |
3266 type = next_type(type)) { | 3266 type = next_type(type)) { |
3267 offset += entry_size(type) * number_of_entries(type, section); | 3267 offset += entry_size(type) * number_of_entries(type, section); |
3268 } | 3268 } |
3269 | 3269 |
3270 // Add offset for the index in it's type. | 3270 // Add offset for the index in it's type. |
3271 Type type = get_type(index); | 3271 Type type = get_type(index); |
3272 offset += entry_size(type) * (index - first_index(type, section)); | 3272 offset += entry_size(type) * (index - first_index(type, section)); |
3273 return offset; | 3273 return offset; |
3274 } | 3274 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3316 void ConstantPoolIterateBody(ObjectVisitor* v); | 3316 void ConstantPoolIterateBody(ObjectVisitor* v); |
3317 | 3317 |
3318 DECLARE_PRINTER(ConstantPoolArray) | 3318 DECLARE_PRINTER(ConstantPoolArray) |
3319 DECLARE_VERIFIER(ConstantPoolArray) | 3319 DECLARE_VERIFIER(ConstantPoolArray) |
3320 | 3320 |
3321 private: | 3321 private: |
3322 inline int first_extended_section_index(); | 3322 inline int first_extended_section_index(); |
3323 inline int get_extended_section_header_offset(); | 3323 inline int get_extended_section_header_offset(); |
3324 | 3324 |
3325 inline static Type next_type(Type type) { | 3325 inline static Type next_type(Type type) { |
3326 ASSERT(type >= FIRST_TYPE && type < NUMBER_OF_TYPES); | 3326 DCHECK(type >= FIRST_TYPE && type < NUMBER_OF_TYPES); |
3327 int type_int = static_cast<int>(type); | 3327 int type_int = static_cast<int>(type); |
3328 return static_cast<Type>(++type_int); | 3328 return static_cast<Type>(++type_int); |
3329 } | 3329 } |
3330 | 3330 |
3331 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolArray); | 3331 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolArray); |
3332 }; | 3332 }; |
3333 | 3333 |
3334 | 3334 |
3335 // DescriptorArrays are fixed arrays used to hold instance descriptors. | 3335 // DescriptorArrays are fixed arrays used to hold instance descriptors. |
3336 // The format of the these objects is: | 3336 // The format of the these objects is: |
3337 // [0]: Number of descriptors | 3337 // [0]: Number of descriptors |
3338 // [1]: Either Smi(0) if uninitialized, or a pointer to small fixed array: | 3338 // [1]: Either Smi(0) if uninitialized, or a pointer to small fixed array: |
3339 // [0]: pointer to fixed array with enum cache | 3339 // [0]: pointer to fixed array with enum cache |
3340 // [1]: either Smi(0) or pointer to fixed array with indices | 3340 // [1]: either Smi(0) or pointer to fixed array with indices |
3341 // [2]: first key | 3341 // [2]: first key |
3342 // [2 + number of descriptors * kDescriptorSize]: start of slack | 3342 // [2 + number of descriptors * kDescriptorSize]: start of slack |
3343 class DescriptorArray: public FixedArray { | 3343 class DescriptorArray: public FixedArray { |
3344 public: | 3344 public: |
3345 // Returns true for both shared empty_descriptor_array and for smis, which the | 3345 // Returns true for both shared empty_descriptor_array and for smis, which the |
3346 // map uses to encode additional bit fields when the descriptor array is not | 3346 // map uses to encode additional bit fields when the descriptor array is not |
3347 // yet used. | 3347 // yet used. |
3348 inline bool IsEmpty(); | 3348 inline bool IsEmpty(); |
3349 | 3349 |
3350 // Returns the number of descriptors in the array. | 3350 // Returns the number of descriptors in the array. |
3351 int number_of_descriptors() { | 3351 int number_of_descriptors() { |
3352 ASSERT(length() >= kFirstIndex || IsEmpty()); | 3352 DCHECK(length() >= kFirstIndex || IsEmpty()); |
3353 int len = length(); | 3353 int len = length(); |
3354 return len == 0 ? 0 : Smi::cast(get(kDescriptorLengthIndex))->value(); | 3354 return len == 0 ? 0 : Smi::cast(get(kDescriptorLengthIndex))->value(); |
3355 } | 3355 } |
3356 | 3356 |
3357 int number_of_descriptors_storage() { | 3357 int number_of_descriptors_storage() { |
3358 int len = length(); | 3358 int len = length(); |
3359 return len == 0 ? 0 : (len - kFirstIndex) / kDescriptorSize; | 3359 return len == 0 ? 0 : (len - kFirstIndex) / kDescriptorSize; |
3360 } | 3360 } |
3361 | 3361 |
3362 int NumberOfSlackDescriptors() { | 3362 int NumberOfSlackDescriptors() { |
3363 return number_of_descriptors_storage() - number_of_descriptors(); | 3363 return number_of_descriptors_storage() - number_of_descriptors(); |
3364 } | 3364 } |
3365 | 3365 |
3366 inline void SetNumberOfDescriptors(int number_of_descriptors); | 3366 inline void SetNumberOfDescriptors(int number_of_descriptors); |
3367 inline int number_of_entries() { return number_of_descriptors(); } | 3367 inline int number_of_entries() { return number_of_descriptors(); } |
3368 | 3368 |
3369 bool HasEnumCache() { | 3369 bool HasEnumCache() { |
3370 return !IsEmpty() && !get(kEnumCacheIndex)->IsSmi(); | 3370 return !IsEmpty() && !get(kEnumCacheIndex)->IsSmi(); |
3371 } | 3371 } |
3372 | 3372 |
3373 void CopyEnumCacheFrom(DescriptorArray* array) { | 3373 void CopyEnumCacheFrom(DescriptorArray* array) { |
3374 set(kEnumCacheIndex, array->get(kEnumCacheIndex)); | 3374 set(kEnumCacheIndex, array->get(kEnumCacheIndex)); |
3375 } | 3375 } |
3376 | 3376 |
3377 FixedArray* GetEnumCache() { | 3377 FixedArray* GetEnumCache() { |
3378 ASSERT(HasEnumCache()); | 3378 DCHECK(HasEnumCache()); |
3379 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); | 3379 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); |
3380 return FixedArray::cast(bridge->get(kEnumCacheBridgeCacheIndex)); | 3380 return FixedArray::cast(bridge->get(kEnumCacheBridgeCacheIndex)); |
3381 } | 3381 } |
3382 | 3382 |
3383 bool HasEnumIndicesCache() { | 3383 bool HasEnumIndicesCache() { |
3384 if (IsEmpty()) return false; | 3384 if (IsEmpty()) return false; |
3385 Object* object = get(kEnumCacheIndex); | 3385 Object* object = get(kEnumCacheIndex); |
3386 if (object->IsSmi()) return false; | 3386 if (object->IsSmi()) return false; |
3387 FixedArray* bridge = FixedArray::cast(object); | 3387 FixedArray* bridge = FixedArray::cast(object); |
3388 return !bridge->get(kEnumCacheBridgeIndicesCacheIndex)->IsSmi(); | 3388 return !bridge->get(kEnumCacheBridgeIndicesCacheIndex)->IsSmi(); |
3389 } | 3389 } |
3390 | 3390 |
3391 FixedArray* GetEnumIndicesCache() { | 3391 FixedArray* GetEnumIndicesCache() { |
3392 ASSERT(HasEnumIndicesCache()); | 3392 DCHECK(HasEnumIndicesCache()); |
3393 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); | 3393 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); |
3394 return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex)); | 3394 return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex)); |
3395 } | 3395 } |
3396 | 3396 |
3397 Object** GetEnumCacheSlot() { | 3397 Object** GetEnumCacheSlot() { |
3398 ASSERT(HasEnumCache()); | 3398 DCHECK(HasEnumCache()); |
3399 return HeapObject::RawField(reinterpret_cast<HeapObject*>(this), | 3399 return HeapObject::RawField(reinterpret_cast<HeapObject*>(this), |
3400 kEnumCacheOffset); | 3400 kEnumCacheOffset); |
3401 } | 3401 } |
3402 | 3402 |
3403 void ClearEnumCache(); | 3403 void ClearEnumCache(); |
3404 | 3404 |
3405 // Initialize or change the enum cache, | 3405 // Initialize or change the enum cache, |
3406 // using the supplied storage for the small "bridge". | 3406 // using the supplied storage for the small "bridge". |
3407 void SetEnumCache(FixedArray* bridge_storage, | 3407 void SetEnumCache(FixedArray* bridge_storage, |
3408 FixedArray* new_cache, | 3408 FixedArray* new_cache, |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3630 // The prefix size indicates an amount of memory in the | 3630 // The prefix size indicates an amount of memory in the |
3631 // beginning of the backing storage that can be used for non-element | 3631 // beginning of the backing storage that can be used for non-element |
3632 // information by subclasses. | 3632 // information by subclasses. |
3633 | 3633 |
3634 template<typename Key> | 3634 template<typename Key> |
3635 class BaseShape { | 3635 class BaseShape { |
3636 public: | 3636 public: |
3637 static const bool UsesSeed = false; | 3637 static const bool UsesSeed = false; |
3638 static uint32_t Hash(Key key) { return 0; } | 3638 static uint32_t Hash(Key key) { return 0; } |
3639 static uint32_t SeededHash(Key key, uint32_t seed) { | 3639 static uint32_t SeededHash(Key key, uint32_t seed) { |
3640 ASSERT(UsesSeed); | 3640 DCHECK(UsesSeed); |
3641 return Hash(key); | 3641 return Hash(key); |
3642 } | 3642 } |
3643 static uint32_t HashForObject(Key key, Object* object) { return 0; } | 3643 static uint32_t HashForObject(Key key, Object* object) { return 0; } |
3644 static uint32_t SeededHashForObject(Key key, uint32_t seed, Object* object) { | 3644 static uint32_t SeededHashForObject(Key key, uint32_t seed, Object* object) { |
3645 ASSERT(UsesSeed); | 3645 DCHECK(UsesSeed); |
3646 return HashForObject(key, object); | 3646 return HashForObject(key, object); |
3647 } | 3647 } |
3648 }; | 3648 }; |
3649 | 3649 |
3650 template<typename Derived, typename Shape, typename Key> | 3650 template<typename Derived, typename Shape, typename Key> |
3651 class HashTable: public FixedArray { | 3651 class HashTable: public FixedArray { |
3652 public: | 3652 public: |
3653 // Wrapper methods | 3653 // Wrapper methods |
3654 inline uint32_t Hash(Key key) { | 3654 inline uint32_t Hash(Key key) { |
3655 if (Shape::UsesSeed) { | 3655 if (Shape::UsesSeed) { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3776 // Update the number of deleted elements in the hash table. | 3776 // Update the number of deleted elements in the hash table. |
3777 void SetNumberOfDeletedElements(int nod) { | 3777 void SetNumberOfDeletedElements(int nod) { |
3778 set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod)); | 3778 set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod)); |
3779 } | 3779 } |
3780 | 3780 |
3781 // Sets the capacity of the hash table. | 3781 // Sets the capacity of the hash table. |
3782 void SetCapacity(int capacity) { | 3782 void SetCapacity(int capacity) { |
3783 // To scale a computed hash code to fit within the hash table, we | 3783 // To scale a computed hash code to fit within the hash table, we |
3784 // use bit-wise AND with a mask, so the capacity must be positive | 3784 // use bit-wise AND with a mask, so the capacity must be positive |
3785 // and non-zero. | 3785 // and non-zero. |
3786 ASSERT(capacity > 0); | 3786 DCHECK(capacity > 0); |
3787 ASSERT(capacity <= kMaxCapacity); | 3787 DCHECK(capacity <= kMaxCapacity); |
3788 set(kCapacityIndex, Smi::FromInt(capacity)); | 3788 set(kCapacityIndex, Smi::FromInt(capacity)); |
3789 } | 3789 } |
3790 | 3790 |
3791 | 3791 |
3792 // Returns probe entry. | 3792 // Returns probe entry. |
3793 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) { | 3793 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) { |
3794 ASSERT(IsPowerOf2(size)); | 3794 DCHECK(IsPowerOf2(size)); |
3795 return (hash + GetProbeOffset(number)) & (size - 1); | 3795 return (hash + GetProbeOffset(number)) & (size - 1); |
3796 } | 3796 } |
3797 | 3797 |
3798 inline static uint32_t FirstProbe(uint32_t hash, uint32_t size) { | 3798 inline static uint32_t FirstProbe(uint32_t hash, uint32_t size) { |
3799 return hash & (size - 1); | 3799 return hash & (size - 1); |
3800 } | 3800 } |
3801 | 3801 |
3802 inline static uint32_t NextProbe( | 3802 inline static uint32_t NextProbe( |
3803 uint32_t last, uint32_t number, uint32_t size) { | 3803 uint32_t last, uint32_t number, uint32_t size) { |
3804 return (last + number) & (size - 1); | 3804 return (last + number) & (size - 1); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3952 return this->get(DerivedHashTable::EntryToIndex(entry) + 1); | 3952 return this->get(DerivedHashTable::EntryToIndex(entry) + 1); |
3953 } | 3953 } |
3954 | 3954 |
3955 // Set the value for entry. | 3955 // Set the value for entry. |
3956 void ValueAtPut(int entry, Object* value) { | 3956 void ValueAtPut(int entry, Object* value) { |
3957 this->set(DerivedHashTable::EntryToIndex(entry) + 1, value); | 3957 this->set(DerivedHashTable::EntryToIndex(entry) + 1, value); |
3958 } | 3958 } |
3959 | 3959 |
3960 // Returns the property details for the property at entry. | 3960 // Returns the property details for the property at entry. |
3961 PropertyDetails DetailsAt(int entry) { | 3961 PropertyDetails DetailsAt(int entry) { |
3962 ASSERT(entry >= 0); // Not found is -1, which is not caught by get(). | 3962 DCHECK(entry >= 0); // Not found is -1, which is not caught by get(). |
3963 return PropertyDetails( | 3963 return PropertyDetails( |
3964 Smi::cast(this->get(DerivedHashTable::EntryToIndex(entry) + 2))); | 3964 Smi::cast(this->get(DerivedHashTable::EntryToIndex(entry) + 2))); |
3965 } | 3965 } |
3966 | 3966 |
3967 // Set the details for entry. | 3967 // Set the details for entry. |
3968 void DetailsAtPut(int entry, PropertyDetails value) { | 3968 void DetailsAtPut(int entry, PropertyDetails value) { |
3969 this->set(DerivedHashTable::EntryToIndex(entry) + 2, value.AsSmi()); | 3969 this->set(DerivedHashTable::EntryToIndex(entry) + 2, value.AsSmi()); |
3970 } | 3970 } |
3971 | 3971 |
3972 // Sorting support | 3972 // Sorting support |
(...skipping 25 matching lines...) Expand all Loading... |
3998 PropertyAttributes filter, | 3998 PropertyAttributes filter, |
3999 SortMode sort_mode); | 3999 SortMode sort_mode); |
4000 // Fill in details for properties into storage. | 4000 // Fill in details for properties into storage. |
4001 void CopyKeysTo(FixedArray* storage, | 4001 void CopyKeysTo(FixedArray* storage, |
4002 int index, | 4002 int index, |
4003 PropertyAttributes filter, | 4003 PropertyAttributes filter, |
4004 SortMode sort_mode); | 4004 SortMode sort_mode); |
4005 | 4005 |
4006 // Accessors for next enumeration index. | 4006 // Accessors for next enumeration index. |
4007 void SetNextEnumerationIndex(int index) { | 4007 void SetNextEnumerationIndex(int index) { |
4008 ASSERT(index != 0); | 4008 DCHECK(index != 0); |
4009 this->set(kNextEnumerationIndexIndex, Smi::FromInt(index)); | 4009 this->set(kNextEnumerationIndexIndex, Smi::FromInt(index)); |
4010 } | 4010 } |
4011 | 4011 |
4012 int NextEnumerationIndex() { | 4012 int NextEnumerationIndex() { |
4013 return Smi::cast(this->get(kNextEnumerationIndexIndex))->value(); | 4013 return Smi::cast(this->get(kNextEnumerationIndexIndex))->value(); |
4014 } | 4014 } |
4015 | 4015 |
4016 // Creates a new dictionary. | 4016 // Creates a new dictionary. |
4017 MUST_USE_RESULT static Handle<Derived> New( | 4017 MUST_USE_RESULT static Handle<Derived> New( |
4018 Isolate* isolate, | 4018 Isolate* isolate, |
(...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4810 inline int get_int(int index); | 4810 inline int get_int(int index); |
4811 | 4811 |
4812 static int SizeFor(int length) { | 4812 static int SizeFor(int length) { |
4813 return OBJECT_POINTER_ALIGN(kHeaderSize + length); | 4813 return OBJECT_POINTER_ALIGN(kHeaderSize + length); |
4814 } | 4814 } |
4815 // We use byte arrays for free blocks in the heap. Given a desired size in | 4815 // We use byte arrays for free blocks in the heap. Given a desired size in |
4816 // bytes that is a multiple of the word size and big enough to hold a byte | 4816 // bytes that is a multiple of the word size and big enough to hold a byte |
4817 // array, this function returns the number of elements a byte array should | 4817 // array, this function returns the number of elements a byte array should |
4818 // have. | 4818 // have. |
4819 static int LengthFor(int size_in_bytes) { | 4819 static int LengthFor(int size_in_bytes) { |
4820 ASSERT(IsAligned(size_in_bytes, kPointerSize)); | 4820 DCHECK(IsAligned(size_in_bytes, kPointerSize)); |
4821 ASSERT(size_in_bytes >= kHeaderSize); | 4821 DCHECK(size_in_bytes >= kHeaderSize); |
4822 return size_in_bytes - kHeaderSize; | 4822 return size_in_bytes - kHeaderSize; |
4823 } | 4823 } |
4824 | 4824 |
4825 // Returns data start address. | 4825 // Returns data start address. |
4826 inline Address GetDataStartAddress(); | 4826 inline Address GetDataStartAddress(); |
4827 | 4827 |
4828 // Returns a pointer to the ByteArray object for a given data start address. | 4828 // Returns a pointer to the ByteArray object for a given data start address. |
4829 static inline ByteArray* FromDataStartAddress(Address address); | 4829 static inline ByteArray* FromDataStartAddress(Address address); |
4830 | 4830 |
4831 DECLARE_CAST(ByteArray) | 4831 DECLARE_CAST(ByteArray) |
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5738 | 5738 |
5739 // Relocate the code by delta bytes. Called to signal that this code | 5739 // Relocate the code by delta bytes. Called to signal that this code |
5740 // object has been moved by delta bytes. | 5740 // object has been moved by delta bytes. |
5741 void Relocate(intptr_t delta); | 5741 void Relocate(intptr_t delta); |
5742 | 5742 |
5743 // Migrate code described by desc. | 5743 // Migrate code described by desc. |
5744 void CopyFrom(const CodeDesc& desc); | 5744 void CopyFrom(const CodeDesc& desc); |
5745 | 5745 |
5746 // Returns the object size for a given body (used for allocation). | 5746 // Returns the object size for a given body (used for allocation). |
5747 static int SizeFor(int body_size) { | 5747 static int SizeFor(int body_size) { |
5748 ASSERT_SIZE_TAG_ALIGNED(body_size); | 5748 DCHECK_SIZE_TAG_ALIGNED(body_size); |
5749 return RoundUp(kHeaderSize + body_size, kCodeAlignment); | 5749 return RoundUp(kHeaderSize + body_size, kCodeAlignment); |
5750 } | 5750 } |
5751 | 5751 |
5752 // Calculate the size of the code object to report for log events. This takes | 5752 // Calculate the size of the code object to report for log events. This takes |
5753 // the layout of the code object into account. | 5753 // the layout of the code object into account. |
5754 int ExecutableSize() { | 5754 int ExecutableSize() { |
5755 // Check that the assumptions about the layout of the code object holds. | 5755 // Check that the assumptions about the layout of the code object holds. |
5756 ASSERT_EQ(static_cast<int>(instruction_start() - address()), | 5756 DCHECK_EQ(static_cast<int>(instruction_start() - address()), |
5757 Code::kHeaderSize); | 5757 Code::kHeaderSize); |
5758 return instruction_size() + Code::kHeaderSize; | 5758 return instruction_size() + Code::kHeaderSize; |
5759 } | 5759 } |
5760 | 5760 |
5761 // Locating source position. | 5761 // Locating source position. |
5762 int SourcePosition(Address pc); | 5762 int SourcePosition(Address pc); |
5763 int SourceStatementPosition(Address pc); | 5763 int SourceStatementPosition(Address pc); |
5764 | 5764 |
5765 DECLARE_CAST(Code) | 5765 DECLARE_CAST(Code) |
5766 | 5766 |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6199 } | 6199 } |
6200 | 6200 |
6201 inline bool is_observed() { | 6201 inline bool is_observed() { |
6202 return ((1 << kIsObserved) & bit_field()) != 0; | 6202 return ((1 << kIsObserved) & bit_field()) != 0; |
6203 } | 6203 } |
6204 | 6204 |
6205 inline void set_is_extensible(bool value); | 6205 inline void set_is_extensible(bool value); |
6206 inline bool is_extensible(); | 6206 inline bool is_extensible(); |
6207 | 6207 |
6208 inline void set_elements_kind(ElementsKind elements_kind) { | 6208 inline void set_elements_kind(ElementsKind elements_kind) { |
6209 ASSERT(elements_kind < kElementsKindCount); | 6209 DCHECK(elements_kind < kElementsKindCount); |
6210 ASSERT(kElementsKindCount <= (1 << Map::ElementsKindBits::kSize)); | 6210 DCHECK(kElementsKindCount <= (1 << Map::ElementsKindBits::kSize)); |
6211 set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind)); | 6211 set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind)); |
6212 ASSERT(this->elements_kind() == elements_kind); | 6212 DCHECK(this->elements_kind() == elements_kind); |
6213 } | 6213 } |
6214 | 6214 |
6215 inline ElementsKind elements_kind() { | 6215 inline ElementsKind elements_kind() { |
6216 return Map::ElementsKindBits::decode(bit_field2()); | 6216 return Map::ElementsKindBits::decode(bit_field2()); |
6217 } | 6217 } |
6218 | 6218 |
6219 // Tells whether the instance has fast elements that are only Smis. | 6219 // Tells whether the instance has fast elements that are only Smis. |
6220 inline bool has_fast_smi_elements() { | 6220 inline bool has_fast_smi_elements() { |
6221 return IsFastSmiElementsKind(elements_kind()); | 6221 return IsFastSmiElementsKind(elements_kind()); |
6222 } | 6222 } |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6397 | 6397 |
6398 inline int NumberOfProtoTransitions() { | 6398 inline int NumberOfProtoTransitions() { |
6399 FixedArray* cache = GetPrototypeTransitions(); | 6399 FixedArray* cache = GetPrototypeTransitions(); |
6400 if (cache->length() == 0) return 0; | 6400 if (cache->length() == 0) return 0; |
6401 return | 6401 return |
6402 Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value(); | 6402 Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value(); |
6403 } | 6403 } |
6404 | 6404 |
6405 inline void SetNumberOfProtoTransitions(int value) { | 6405 inline void SetNumberOfProtoTransitions(int value) { |
6406 FixedArray* cache = GetPrototypeTransitions(); | 6406 FixedArray* cache = GetPrototypeTransitions(); |
6407 ASSERT(cache->length() != 0); | 6407 DCHECK(cache->length() != 0); |
6408 cache->set(kProtoTransitionNumberOfEntriesOffset, Smi::FromInt(value)); | 6408 cache->set(kProtoTransitionNumberOfEntriesOffset, Smi::FromInt(value)); |
6409 } | 6409 } |
6410 | 6410 |
6411 // Lookup in the map's instance descriptors and fill out the result | 6411 // Lookup in the map's instance descriptors and fill out the result |
6412 // with the given holder if the name is found. The holder may be | 6412 // with the given holder if the name is found. The holder may be |
6413 // NULL when this function is used from the compiler. | 6413 // NULL when this function is used from the compiler. |
6414 inline void LookupDescriptor(JSObject* holder, | 6414 inline void LookupDescriptor(JSObject* holder, |
6415 Name* name, | 6415 Name* name, |
6416 LookupResult* result); | 6416 LookupResult* result); |
6417 | 6417 |
6418 inline void LookupTransition(JSObject* holder, | 6418 inline void LookupTransition(JSObject* holder, |
6419 Name* name, | 6419 Name* name, |
6420 LookupResult* result); | 6420 LookupResult* result); |
6421 | 6421 |
6422 inline PropertyDetails GetLastDescriptorDetails(); | 6422 inline PropertyDetails GetLastDescriptorDetails(); |
6423 | 6423 |
6424 // The size of transition arrays are limited so they do not end up in large | 6424 // The size of transition arrays are limited so they do not end up in large |
6425 // object space. Otherwise ClearNonLiveTransitions would leak memory while | 6425 // object space. Otherwise ClearNonLiveTransitions would leak memory while |
6426 // applying in-place right trimming. | 6426 // applying in-place right trimming. |
6427 inline bool CanHaveMoreTransitions(); | 6427 inline bool CanHaveMoreTransitions(); |
6428 | 6428 |
6429 int LastAdded() { | 6429 int LastAdded() { |
6430 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 6430 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
6431 ASSERT(number_of_own_descriptors > 0); | 6431 DCHECK(number_of_own_descriptors > 0); |
6432 return number_of_own_descriptors - 1; | 6432 return number_of_own_descriptors - 1; |
6433 } | 6433 } |
6434 | 6434 |
6435 int NumberOfOwnDescriptors() { | 6435 int NumberOfOwnDescriptors() { |
6436 return NumberOfOwnDescriptorsBits::decode(bit_field3()); | 6436 return NumberOfOwnDescriptorsBits::decode(bit_field3()); |
6437 } | 6437 } |
6438 | 6438 |
6439 void SetNumberOfOwnDescriptors(int number) { | 6439 void SetNumberOfOwnDescriptors(int number) { |
6440 ASSERT(number <= instance_descriptors()->number_of_descriptors()); | 6440 DCHECK(number <= instance_descriptors()->number_of_descriptors()); |
6441 set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number)); | 6441 set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number)); |
6442 } | 6442 } |
6443 | 6443 |
6444 inline Cell* RetrieveDescriptorsPointer(); | 6444 inline Cell* RetrieveDescriptorsPointer(); |
6445 | 6445 |
6446 int EnumLength() { | 6446 int EnumLength() { |
6447 return EnumLengthBits::decode(bit_field3()); | 6447 return EnumLengthBits::decode(bit_field3()); |
6448 } | 6448 } |
6449 | 6449 |
6450 void SetEnumLength(int length) { | 6450 void SetEnumLength(int length) { |
6451 if (length != kInvalidEnumCacheSentinel) { | 6451 if (length != kInvalidEnumCacheSentinel) { |
6452 ASSERT(length >= 0); | 6452 DCHECK(length >= 0); |
6453 ASSERT(length == 0 || instance_descriptors()->HasEnumCache()); | 6453 DCHECK(length == 0 || instance_descriptors()->HasEnumCache()); |
6454 ASSERT(length <= NumberOfOwnDescriptors()); | 6454 DCHECK(length <= NumberOfOwnDescriptors()); |
6455 } | 6455 } |
6456 set_bit_field3(EnumLengthBits::update(bit_field3(), length)); | 6456 set_bit_field3(EnumLengthBits::update(bit_field3(), length)); |
6457 } | 6457 } |
6458 | 6458 |
6459 inline bool owns_descriptors(); | 6459 inline bool owns_descriptors(); |
6460 inline void set_owns_descriptors(bool is_shared); | 6460 inline void set_owns_descriptors(bool is_shared); |
6461 inline bool has_instance_call_handler(); | 6461 inline bool has_instance_call_handler(); |
6462 inline void set_has_instance_call_handler(); | 6462 inline void set_has_instance_call_handler(); |
6463 inline void freeze(); | 6463 inline void freeze(); |
6464 inline bool is_frozen(); | 6464 inline bool is_frozen(); |
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7297 | 7297 |
7298 // Enable deoptimization support through recompiled code. | 7298 // Enable deoptimization support through recompiled code. |
7299 void EnableDeoptimizationSupport(Code* recompiled); | 7299 void EnableDeoptimizationSupport(Code* recompiled); |
7300 | 7300 |
7301 // Disable (further) attempted optimization of all functions sharing this | 7301 // Disable (further) attempted optimization of all functions sharing this |
7302 // shared function info. | 7302 // shared function info. |
7303 void DisableOptimization(BailoutReason reason); | 7303 void DisableOptimization(BailoutReason reason); |
7304 | 7304 |
7305 inline BailoutReason DisableOptimizationReason(); | 7305 inline BailoutReason DisableOptimizationReason(); |
7306 | 7306 |
7307 // Lookup the bailout ID and ASSERT that it exists in the non-optimized | 7307 // Lookup the bailout ID and DCHECK that it exists in the non-optimized |
7308 // code, returns whether it asserted (i.e., always true if assertions are | 7308 // code, returns whether it asserted (i.e., always true if assertions are |
7309 // disabled). | 7309 // disabled). |
7310 bool VerifyBailoutId(BailoutId id); | 7310 bool VerifyBailoutId(BailoutId id); |
7311 | 7311 |
7312 // [source code]: Source code for the function. | 7312 // [source code]: Source code for the function. |
7313 bool HasSourceCode() const; | 7313 bool HasSourceCode() const; |
7314 Handle<Object> GetSourceCode(); | 7314 Handle<Object> GetSourceCode(); |
7315 | 7315 |
7316 // Number of times the function was optimized. | 7316 // Number of times the function was optimized. |
7317 inline int opt_count(); | 7317 inline int opt_count(); |
(...skipping 1353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8671 | 8671 |
8672 inline void MarkZombie(); | 8672 inline void MarkZombie(); |
8673 | 8673 |
8674 inline bool MakePretenureDecision(PretenureDecision current_decision, | 8674 inline bool MakePretenureDecision(PretenureDecision current_decision, |
8675 double ratio, | 8675 double ratio, |
8676 bool maximum_size_scavenge); | 8676 bool maximum_size_scavenge); |
8677 | 8677 |
8678 inline bool DigestPretenuringFeedback(bool maximum_size_scavenge); | 8678 inline bool DigestPretenuringFeedback(bool maximum_size_scavenge); |
8679 | 8679 |
8680 ElementsKind GetElementsKind() { | 8680 ElementsKind GetElementsKind() { |
8681 ASSERT(!SitePointsToLiteral()); | 8681 DCHECK(!SitePointsToLiteral()); |
8682 int value = Smi::cast(transition_info())->value(); | 8682 int value = Smi::cast(transition_info())->value(); |
8683 return ElementsKindBits::decode(value); | 8683 return ElementsKindBits::decode(value); |
8684 } | 8684 } |
8685 | 8685 |
8686 void SetElementsKind(ElementsKind kind) { | 8686 void SetElementsKind(ElementsKind kind) { |
8687 int value = Smi::cast(transition_info())->value(); | 8687 int value = Smi::cast(transition_info())->value(); |
8688 set_transition_info(Smi::FromInt(ElementsKindBits::update(value, kind)), | 8688 set_transition_info(Smi::FromInt(ElementsKindBits::update(value, kind)), |
8689 SKIP_WRITE_BARRIER); | 8689 SKIP_WRITE_BARRIER); |
8690 } | 8690 } |
8691 | 8691 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8763 static const int kAllocationSiteOffset = HeapObject::kHeaderSize; | 8763 static const int kAllocationSiteOffset = HeapObject::kHeaderSize; |
8764 static const int kSize = kAllocationSiteOffset + kPointerSize; | 8764 static const int kSize = kAllocationSiteOffset + kPointerSize; |
8765 | 8765 |
8766 DECL_ACCESSORS(allocation_site, Object) | 8766 DECL_ACCESSORS(allocation_site, Object) |
8767 | 8767 |
8768 bool IsValid() { | 8768 bool IsValid() { |
8769 return allocation_site()->IsAllocationSite() && | 8769 return allocation_site()->IsAllocationSite() && |
8770 !AllocationSite::cast(allocation_site())->IsZombie(); | 8770 !AllocationSite::cast(allocation_site())->IsZombie(); |
8771 } | 8771 } |
8772 AllocationSite* GetAllocationSite() { | 8772 AllocationSite* GetAllocationSite() { |
8773 ASSERT(IsValid()); | 8773 DCHECK(IsValid()); |
8774 return AllocationSite::cast(allocation_site()); | 8774 return AllocationSite::cast(allocation_site()); |
8775 } | 8775 } |
8776 | 8776 |
8777 DECLARE_PRINTER(AllocationMemento) | 8777 DECLARE_PRINTER(AllocationMemento) |
8778 DECLARE_VERIFIER(AllocationMemento) | 8778 DECLARE_VERIFIER(AllocationMemento) |
8779 | 8779 |
8780 DECLARE_CAST(AllocationMemento) | 8780 DECLARE_CAST(AllocationMemento) |
8781 | 8781 |
8782 private: | 8782 private: |
8783 DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationMemento); | 8783 DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationMemento); |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9097 // Returns true if the string is flat and this structure contains content. | 9097 // Returns true if the string is flat and this structure contains content. |
9098 bool IsFlat() { return state_ != NON_FLAT; } | 9098 bool IsFlat() { return state_ != NON_FLAT; } |
9099 // Returns true if the structure contains ASCII content. | 9099 // Returns true if the structure contains ASCII content. |
9100 bool IsAscii() { return state_ == ASCII; } | 9100 bool IsAscii() { return state_ == ASCII; } |
9101 // Returns true if the structure contains two-byte content. | 9101 // Returns true if the structure contains two-byte content. |
9102 bool IsTwoByte() { return state_ == TWO_BYTE; } | 9102 bool IsTwoByte() { return state_ == TWO_BYTE; } |
9103 | 9103 |
9104 // Return the one byte content of the string. Only use if IsAscii() returns | 9104 // Return the one byte content of the string. Only use if IsAscii() returns |
9105 // true. | 9105 // true. |
9106 Vector<const uint8_t> ToOneByteVector() { | 9106 Vector<const uint8_t> ToOneByteVector() { |
9107 ASSERT_EQ(ASCII, state_); | 9107 DCHECK_EQ(ASCII, state_); |
9108 return Vector<const uint8_t>(onebyte_start, length_); | 9108 return Vector<const uint8_t>(onebyte_start, length_); |
9109 } | 9109 } |
9110 // Return the two-byte content of the string. Only use if IsTwoByte() | 9110 // Return the two-byte content of the string. Only use if IsTwoByte() |
9111 // returns true. | 9111 // returns true. |
9112 Vector<const uc16> ToUC16Vector() { | 9112 Vector<const uc16> ToUC16Vector() { |
9113 ASSERT_EQ(TWO_BYTE, state_); | 9113 DCHECK_EQ(TWO_BYTE, state_); |
9114 return Vector<const uc16>(twobyte_start, length_); | 9114 return Vector<const uc16>(twobyte_start, length_); |
9115 } | 9115 } |
9116 | 9116 |
9117 uc16 Get(int i) { | 9117 uc16 Get(int i) { |
9118 ASSERT(i < length_); | 9118 DCHECK(i < length_); |
9119 ASSERT(state_ != NON_FLAT); | 9119 DCHECK(state_ != NON_FLAT); |
9120 if (state_ == ASCII) return onebyte_start[i]; | 9120 if (state_ == ASCII) return onebyte_start[i]; |
9121 return twobyte_start[i]; | 9121 return twobyte_start[i]; |
9122 } | 9122 } |
9123 | 9123 |
9124 private: | 9124 private: |
9125 enum State { NON_FLAT, ASCII, TWO_BYTE }; | 9125 enum State { NON_FLAT, ASCII, TWO_BYTE }; |
9126 | 9126 |
9127 // Constructors only used by String::GetFlatContent(). | 9127 // Constructors only used by String::GetFlatContent(). |
9128 explicit FlatContent(const uint8_t* start, int length) | 9128 explicit FlatContent(const uint8_t* start, int length) |
9129 : onebyte_start(start), length_(length), state_(ASCII) { } | 9129 : onebyte_start(start), length_(length), state_(ASCII) { } |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9303 int from, | 9303 int from, |
9304 int to); | 9304 int to); |
9305 | 9305 |
9306 // The return value may point to the first aligned word containing the | 9306 // The return value may point to the first aligned word containing the |
9307 // first non-ascii character, rather than directly to the non-ascii character. | 9307 // first non-ascii character, rather than directly to the non-ascii character. |
9308 // If the return value is >= the passed length, the entire string was ASCII. | 9308 // If the return value is >= the passed length, the entire string was ASCII. |
9309 static inline int NonAsciiStart(const char* chars, int length) { | 9309 static inline int NonAsciiStart(const char* chars, int length) { |
9310 const char* start = chars; | 9310 const char* start = chars; |
9311 const char* limit = chars + length; | 9311 const char* limit = chars + length; |
9312 #ifdef V8_HOST_CAN_READ_UNALIGNED | 9312 #ifdef V8_HOST_CAN_READ_UNALIGNED |
9313 ASSERT(unibrow::Utf8::kMaxOneByteChar == 0x7F); | 9313 DCHECK(unibrow::Utf8::kMaxOneByteChar == 0x7F); |
9314 const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80; | 9314 const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80; |
9315 while (chars + sizeof(uintptr_t) <= limit) { | 9315 while (chars + sizeof(uintptr_t) <= limit) { |
9316 if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) { | 9316 if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) { |
9317 return static_cast<int>(chars - start); | 9317 return static_cast<int>(chars - start); |
9318 } | 9318 } |
9319 chars += sizeof(uintptr_t); | 9319 chars += sizeof(uintptr_t); |
9320 } | 9320 } |
9321 #endif | 9321 #endif |
9322 while (chars < limit) { | 9322 while (chars < limit) { |
9323 if (static_cast<uint8_t>(*chars) > unibrow::Utf8::kMaxOneByteChar) { | 9323 if (static_cast<uint8_t>(*chars) > unibrow::Utf8::kMaxOneByteChar) { |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9877 | 9877 |
9878 class Cell: public HeapObject { | 9878 class Cell: public HeapObject { |
9879 public: | 9879 public: |
9880 // [value]: value of the global property. | 9880 // [value]: value of the global property. |
9881 DECL_ACCESSORS(value, Object) | 9881 DECL_ACCESSORS(value, Object) |
9882 | 9882 |
9883 DECLARE_CAST(Cell) | 9883 DECLARE_CAST(Cell) |
9884 | 9884 |
9885 static inline Cell* FromValueAddress(Address value) { | 9885 static inline Cell* FromValueAddress(Address value) { |
9886 Object* result = FromAddress(value - kValueOffset); | 9886 Object* result = FromAddress(value - kValueOffset); |
9887 ASSERT(result->IsCell() || result->IsPropertyCell()); | 9887 DCHECK(result->IsCell() || result->IsPropertyCell()); |
9888 return static_cast<Cell*>(result); | 9888 return static_cast<Cell*>(result); |
9889 } | 9889 } |
9890 | 9890 |
9891 inline Address ValueAddress() { | 9891 inline Address ValueAddress() { |
9892 return address() + kValueOffset; | 9892 return address() + kValueOffset; |
9893 } | 9893 } |
9894 | 9894 |
9895 // Dispatched behavior. | 9895 // Dispatched behavior. |
9896 DECLARE_PRINTER(Cell) | 9896 DECLARE_PRINTER(Cell) |
9897 DECLARE_VERIFIER(Cell) | 9897 DECLARE_VERIFIER(Cell) |
(...skipping 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11260 } else { | 11260 } else { |
11261 value &= ~(1 << bit_position); | 11261 value &= ~(1 << bit_position); |
11262 } | 11262 } |
11263 return value; | 11263 return value; |
11264 } | 11264 } |
11265 }; | 11265 }; |
11266 | 11266 |
11267 } } // namespace v8::internal | 11267 } } // namespace v8::internal |
11268 | 11268 |
11269 #endif // V8_OBJECTS_H_ | 11269 #endif // V8_OBJECTS_H_ |
OLD | NEW |