Chromium Code Reviews| 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 // Review notes: | 5 // Review notes: |
| 6 // | 6 // |
| 7 // - The use of macros in these inline functions may seem superfluous | 7 // - The use of macros in these inline functions may seem superfluous |
| 8 // but it is absolutely needed to make sure gcc generates optimal | 8 // but it is absolutely needed to make sure gcc generates optimal |
| 9 // code. gcc is not happy when attempting to inline too deep. | 9 // code. gcc is not happy when attempting to inline too deep. |
| 10 // | 10 // |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 return Smi::FromInt(value >> 1); | 46 return Smi::FromInt(value >> 1); |
| 47 } | 47 } |
| 48 | 48 |
| 49 | 49 |
| 50 PropertyDetails PropertyDetails::AsDeleted() const { | 50 PropertyDetails PropertyDetails::AsDeleted() const { |
| 51 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1)); | 51 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1)); |
| 52 return PropertyDetails(smi); | 52 return PropertyDetails(smi); |
| 53 } | 53 } |
| 54 | 54 |
| 55 | 55 |
| 56 int PropertyDetails::field_width_in_words() const { | |
| 57 ASSERT(type() == FIELD); | |
| 58 if (!FLAG_unbox_double_fields) return 1; | |
| 59 if (kDoubleSize == kPointerSize) return 1; | |
| 60 return representation().IsDouble() ? kDoubleSize / kPointerSize : 1; | |
| 61 } | |
| 62 | |
| 63 | |
| 56 #define TYPE_CHECKER(type, instancetype) \ | 64 #define TYPE_CHECKER(type, instancetype) \ |
| 57 bool Object::Is##type() const { \ | 65 bool Object::Is##type() const { \ |
| 58 return Object::IsHeapObject() && \ | 66 return Object::IsHeapObject() && \ |
| 59 HeapObject::cast(this)->map()->instance_type() == instancetype; \ | 67 HeapObject::cast(this)->map()->instance_type() == instancetype; \ |
| 60 } | 68 } |
| 61 | 69 |
| 62 | 70 |
| 63 #define CAST_ACCESSOR(type) \ | 71 #define CAST_ACCESSOR(type) \ |
| 64 type* type::cast(Object* object) { \ | 72 type* type::cast(Object* object) { \ |
| 65 SLOW_ASSERT(object->Is##type()); \ | 73 SLOW_ASSERT(object->Is##type()); \ |
| (...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 708 bool Object::IsJSWeakCollection() const { | 716 bool Object::IsJSWeakCollection() const { |
| 709 return IsJSWeakMap() || IsJSWeakSet(); | 717 return IsJSWeakMap() || IsJSWeakSet(); |
| 710 } | 718 } |
| 711 | 719 |
| 712 | 720 |
| 713 bool Object::IsDescriptorArray() const { | 721 bool Object::IsDescriptorArray() const { |
| 714 return IsFixedArray(); | 722 return IsFixedArray(); |
| 715 } | 723 } |
| 716 | 724 |
| 717 | 725 |
| 726 bool Object::IsLayoutDescriptor() const { | |
| 727 return IsSmi() || IsFixedTypedArrayBase(); | |
| 728 } | |
| 729 | |
| 730 | |
| 718 bool Object::IsTransitionArray() const { | 731 bool Object::IsTransitionArray() const { |
| 719 return IsFixedArray(); | 732 return IsFixedArray(); |
| 720 } | 733 } |
| 721 | 734 |
| 722 | 735 |
| 723 bool Object::IsDeoptimizationInputData() const { | 736 bool Object::IsDeoptimizationInputData() const { |
| 724 // Must be a fixed array. | 737 // Must be a fixed array. |
| 725 if (!IsFixedArray()) return false; | 738 if (!IsFixedArray()) return false; |
| 726 | 739 |
| 727 // There's no sure way to detect the difference between a fixed array and | 740 // There's no sure way to detect the difference between a fixed array and |
| (...skipping 1268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1996 void JSObject::SetInternalField(int index, Smi* value) { | 2009 void JSObject::SetInternalField(int index, Smi* value) { |
| 1997 ASSERT(index < GetInternalFieldCount() && index >= 0); | 2010 ASSERT(index < GetInternalFieldCount() && index >= 0); |
| 1998 // Internal objects do follow immediately after the header, whereas in-object | 2011 // Internal objects do follow immediately after the header, whereas in-object |
| 1999 // properties are at the end of the object. Therefore there is no need | 2012 // properties are at the end of the object. Therefore there is no need |
| 2000 // to adjust the index here. | 2013 // to adjust the index here. |
| 2001 int offset = GetHeaderSize() + (kPointerSize * index); | 2014 int offset = GetHeaderSize() + (kPointerSize * index); |
| 2002 WRITE_FIELD(this, offset, value); | 2015 WRITE_FIELD(this, offset, value); |
| 2003 } | 2016 } |
| 2004 | 2017 |
| 2005 | 2018 |
| 2019 bool Map::IsUnboxedDoubleField(FieldIndex index) { | |
| 2020 if (!FLAG_unbox_double_fields) return false; | |
| 2021 if (index.is_hidden_field() || !index.is_inobject()) return false; | |
| 2022 return !layout_descriptor()->IsTagged(index.property_index()); | |
| 2023 } | |
| 2024 | |
| 2025 | |
| 2006 // Access fast-case object properties at index. The use of these routines | 2026 // Access fast-case object properties at index. The use of these routines |
| 2007 // is needed to correctly distinguish between properties stored in-object and | 2027 // is needed to correctly distinguish between properties stored in-object and |
| 2008 // properties stored in the properties array. | 2028 // properties stored in the properties array. |
| 2009 Object* JSObject::RawFastPropertyAt(FieldIndex index) { | 2029 Object* JSObject::RawFastPropertyAt(FieldIndex index) { |
| 2010 if (index.is_inobject()) { | 2030 if (index.is_inobject()) { |
| 2031 ASSERT(!map()->IsUnboxedDoubleField(index)); | |
| 2011 return READ_FIELD(this, index.offset()); | 2032 return READ_FIELD(this, index.offset()); |
| 2012 } else { | 2033 } else { |
| 2013 return properties()->get(index.outobject_array_index()); | 2034 return properties()->get(index.outobject_array_index()); |
| 2014 } | 2035 } |
| 2015 } | 2036 } |
| 2016 | 2037 |
| 2017 | 2038 |
| 2018 void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { | 2039 // Access fast-case object properties at index. The use of these routines |
| 2040 // is needed to correctly distinguish between properties stored in-object and | |
| 2041 // properties stored in the properties array. | |
| 2042 Handle<Object> JSObject::RawFastBoxedPropertyAt(Handle<JSObject> object, | |
| 2043 FieldIndex index) { | |
| 2044 Isolate* isolate = object->GetIsolate(); | |
| 2045 if (index.is_inobject()) { | |
| 2046 Map* map = object->map(); | |
| 2047 if (map->IsUnboxedDoubleField(index)) { | |
| 2048 double value = READ_DOUBLE_FIELD(*object, index.offset()); | |
| 2049 return isolate->factory()->NewHeapNumber(value, MUTABLE); | |
|
Toon Verwaest
2014/07/29 15:02:09
Should not call this for unboxed doubles.
We shoul
Igor Sheludko
2014/10/30 14:23:43
Done.
| |
| 2050 | |
| 2051 } else { | |
| 2052 return handle(READ_FIELD(*object, index.offset()), isolate); | |
| 2053 } | |
| 2054 } else { | |
| 2055 ASSERT(index.outobject_array_index() < object->properties()->length()); | |
| 2056 return handle(object->properties()->get(index.outobject_array_index()), | |
| 2057 isolate); | |
| 2058 } | |
| 2059 } | |
| 2060 | |
| 2061 | |
| 2062 double JSObject::RawFastDoublePropertyAt(FieldIndex index) { | |
| 2063 ASSERT(map()->IsUnboxedDoubleField(index)); | |
| 2064 return READ_DOUBLE_FIELD(this, index.offset()); | |
| 2065 } | |
| 2066 | |
| 2067 | |
| 2068 void JSObject::FastPropertyAtPut(Map* map, FieldIndex index, Object* value) { | |
| 2019 if (index.is_inobject()) { | 2069 if (index.is_inobject()) { |
| 2020 int offset = index.offset(); | 2070 int offset = index.offset(); |
| 2021 WRITE_FIELD(this, offset, value); | 2071 if (map->IsUnboxedDoubleField(index)) { |
|
Toon Verwaest
2014/07/29 15:02:08
Always go through FastDoublePropertyAtPut?
I would
Igor Sheludko
2014/10/30 14:23:43
I fixed callers of this methods where it makes sen
| |
| 2022 WRITE_BARRIER(GetHeap(), this, offset, value); | 2072 ASSERT(value->IsMutableHeapNumber()); |
| 2073 WRITE_DOUBLE_FIELD(this, offset, HeapNumber::cast(value)->value()); | |
| 2074 } else { | |
| 2075 WRITE_FIELD(this, offset, value); | |
| 2076 WRITE_BARRIER(GetHeap(), this, offset, value); | |
| 2077 } | |
| 2023 } else { | 2078 } else { |
| 2024 properties()->set(index.outobject_array_index(), value); | 2079 properties()->set(index.outobject_array_index(), value); |
| 2025 } | 2080 } |
| 2026 } | 2081 } |
| 2027 | 2082 |
| 2028 | 2083 |
| 2084 void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { | |
| 2085 FastPropertyAtPut(map(), index, value); | |
| 2086 } | |
| 2087 | |
| 2088 | |
| 2089 void JSObject::FastDoublePropertyAtPut(FieldIndex index, double value) { | |
| 2090 ASSERT(map()->IsUnboxedDoubleField(index)); | |
| 2091 WRITE_DOUBLE_FIELD(this, index.offset(), value); | |
| 2092 } | |
| 2093 | |
| 2094 | |
| 2029 int JSObject::GetInObjectPropertyOffset(int index) { | 2095 int JSObject::GetInObjectPropertyOffset(int index) { |
| 2030 return map()->GetInObjectPropertyOffset(index); | 2096 return map()->GetInObjectPropertyOffset(index); |
| 2031 } | 2097 } |
| 2032 | 2098 |
| 2033 | 2099 |
| 2034 Object* JSObject::InObjectPropertyAt(int index) { | 2100 Object* JSObject::InObjectPropertyAt(int index) { |
| 2035 int offset = GetInObjectPropertyOffset(index); | 2101 int offset = GetInObjectPropertyOffset(index); |
| 2036 return READ_FIELD(this, offset); | 2102 return READ_FIELD(this, offset); |
| 2037 } | 2103 } |
| 2038 | 2104 |
| (...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2736 bool DescriptorArray::IsEmpty() { | 2802 bool DescriptorArray::IsEmpty() { |
| 2737 ASSERT(length() >= kFirstIndex || | 2803 ASSERT(length() >= kFirstIndex || |
| 2738 this == GetHeap()->empty_descriptor_array()); | 2804 this == GetHeap()->empty_descriptor_array()); |
| 2739 return length() < kFirstIndex; | 2805 return length() < kFirstIndex; |
| 2740 } | 2806 } |
| 2741 | 2807 |
| 2742 | 2808 |
| 2743 void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) { | 2809 void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) { |
| 2744 WRITE_FIELD( | 2810 WRITE_FIELD( |
| 2745 this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors)); | 2811 this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors)); |
| 2812 if (FLAG_unbox_double_fields) drop_cached_layout_descriptor(); | |
|
Toon Verwaest
2014/07/29 15:02:08
This doesn't belong here
Igor Sheludko
2014/10/30 14:23:43
Done. I removed the whole layout descriptor cache
| |
| 2746 } | 2813 } |
| 2747 | 2814 |
| 2748 | 2815 |
| 2816 Object* DescriptorArray::cached_layout_descriptor() { | |
| 2817 ASSERT(FLAG_unbox_double_fields); | |
| 2818 ASSERT(length() >= kFirstIndex || IsEmpty()); | |
| 2819 if (length() == 0) return LayoutDescriptor::FastPointerLayout(); | |
| 2820 return get(kLayoutDescriptorCacheIndex); | |
| 2821 } | |
| 2822 | |
| 2823 | |
| 2824 void DescriptorArray::set_cached_layout_descriptor(LayoutDescriptor* cached) { | |
| 2825 ASSERT(FLAG_unbox_double_fields); | |
| 2826 ASSERT(length() >= kFirstIndex || IsEmpty()); | |
| 2827 if (length() > 0) set(kLayoutDescriptorCacheIndex, cached); | |
| 2828 } | |
| 2829 | |
| 2830 | |
| 2831 void DescriptorArray::drop_cached_layout_descriptor() { | |
| 2832 ASSERT(FLAG_unbox_double_fields); | |
| 2833 ASSERT(length() >= kFirstIndex || IsEmpty()); | |
| 2834 if (length() > 0) { | |
| 2835 set(kLayoutDescriptorCacheIndex, GetHeap()->undefined_value()); | |
| 2836 } | |
| 2837 } | |
| 2838 | |
| 2839 | |
| 2749 // Perform a binary search in a fixed array. Low and high are entry indices. If | 2840 // Perform a binary search in a fixed array. Low and high are entry indices. If |
| 2750 // there are three entries in this array it should be called with low=0 and | 2841 // there are three entries in this array it should be called with low=0 and |
| 2751 // high=2. | 2842 // high=2. |
| 2752 template<SearchMode search_mode, typename T> | 2843 template<SearchMode search_mode, typename T> |
| 2753 int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) { | 2844 int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) { |
| 2754 uint32_t hash = name->Hash(); | 2845 uint32_t hash = name->Hash(); |
| 2755 int limit = high; | 2846 int limit = high; |
| 2756 | 2847 |
| 2757 ASSERT(low <= high); | 2848 ASSERT(low <= high); |
| 2758 | 2849 |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3021 const WhitenessWitness&) { | 3112 const WhitenessWitness&) { |
| 3022 // Range check. | 3113 // Range check. |
| 3023 ASSERT(descriptor_number < number_of_descriptors()); | 3114 ASSERT(descriptor_number < number_of_descriptors()); |
| 3024 | 3115 |
| 3025 NoIncrementalWriteBarrierSet(this, | 3116 NoIncrementalWriteBarrierSet(this, |
| 3026 ToKeyIndex(descriptor_number), | 3117 ToKeyIndex(descriptor_number), |
| 3027 *desc->GetKey()); | 3118 *desc->GetKey()); |
| 3028 NoIncrementalWriteBarrierSet(this, | 3119 NoIncrementalWriteBarrierSet(this, |
| 3029 ToValueIndex(descriptor_number), | 3120 ToValueIndex(descriptor_number), |
| 3030 *desc->GetValue()); | 3121 *desc->GetValue()); |
| 3031 NoIncrementalWriteBarrierSet(this, | 3122 NoIncrementalWriteBarrierSet(this, ToDetailsIndex(descriptor_number), |
| 3032 ToDetailsIndex(descriptor_number), | |
| 3033 desc->GetDetails().AsSmi()); | 3123 desc->GetDetails().AsSmi()); |
| 3124 if (FLAG_unbox_double_fields) drop_cached_layout_descriptor(); | |
|
Toon Verwaest
2014/07/29 15:02:08
This doesn't belong here
Igor Sheludko
2014/10/30 14:23:43
Done.
| |
| 3034 } | 3125 } |
| 3035 | 3126 |
| 3036 | 3127 |
| 3037 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { | 3128 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { |
| 3038 // Range check. | 3129 // Range check. |
| 3039 ASSERT(descriptor_number < number_of_descriptors()); | 3130 ASSERT(descriptor_number < number_of_descriptors()); |
| 3040 | 3131 |
| 3041 set(ToKeyIndex(descriptor_number), *desc->GetKey()); | 3132 set(ToKeyIndex(descriptor_number), *desc->GetKey()); |
| 3042 set(ToValueIndex(descriptor_number), *desc->GetValue()); | 3133 set(ToValueIndex(descriptor_number), *desc->GetValue()); |
| 3043 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi()); | 3134 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi()); |
| 3135 if (FLAG_unbox_double_fields) drop_cached_layout_descriptor(); | |
|
Toon Verwaest
2014/07/29 15:02:09
This doesn't belong here
Igor Sheludko
2014/10/30 14:23:43
Done.
| |
| 3044 } | 3136 } |
| 3045 | 3137 |
| 3046 | 3138 |
| 3047 void DescriptorArray::Append(Descriptor* desc, | 3139 void DescriptorArray::Append(Descriptor* desc, |
| 3048 const WhitenessWitness& witness) { | 3140 const WhitenessWitness& witness) { |
| 3049 DisallowHeapAllocation no_gc; | 3141 DisallowHeapAllocation no_gc; |
| 3050 int descriptor_number = number_of_descriptors(); | 3142 int descriptor_number = number_of_descriptors(); |
| 3051 SetNumberOfDescriptors(descriptor_number + 1); | 3143 SetNumberOfDescriptors(descriptor_number + 1); |
| 3052 Set(descriptor_number, desc, witness); | 3144 Set(descriptor_number, desc, witness); |
| 3053 | 3145 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3098 ASSERT(!marking_->IsMarking() || | 3190 ASSERT(!marking_->IsMarking() || |
| 3099 Marking::Color(array) == Marking::WHITE_OBJECT); | 3191 Marking::Color(array) == Marking::WHITE_OBJECT); |
| 3100 } | 3192 } |
| 3101 | 3193 |
| 3102 | 3194 |
| 3103 DescriptorArray::WhitenessWitness::~WhitenessWitness() { | 3195 DescriptorArray::WhitenessWitness::~WhitenessWitness() { |
| 3104 marking_->LeaveNoMarkingScope(); | 3196 marking_->LeaveNoMarkingScope(); |
| 3105 } | 3197 } |
| 3106 | 3198 |
| 3107 | 3199 |
| 3200 LayoutDescriptor* LayoutDescriptor::FromSmi(Smi* smi) { | |
| 3201 return LayoutDescriptor::cast(smi); | |
| 3202 } | |
| 3203 | |
| 3204 | |
| 3205 Handle<LayoutDescriptor> LayoutDescriptor::New(Isolate* isolate, int length) { | |
| 3206 if (length <= kSmiValueSize) { | |
| 3207 // The whole bit vector fits into a smi. | |
| 3208 return handle(LayoutDescriptor::FromSmi(Smi::FromInt(0)), isolate); | |
| 3209 } | |
| 3210 | |
| 3211 length = (length + kNumberOfBits - 1) / kNumberOfBits; | |
| 3212 ASSERT(length > 0); | |
| 3213 | |
| 3214 if (SmiValuesAre32Bits() && (length & 1)) { | |
| 3215 ++length; // Make kPtrSize aligned | |
| 3216 } | |
| 3217 return Handle<LayoutDescriptor>::cast( | |
| 3218 isolate->factory()->NewFixedTypedArray(length, kExternalUint32Array)); | |
| 3219 } | |
| 3220 | |
| 3221 | |
| 3222 LayoutDescriptor* LayoutDescriptor::FastPointerLayout() { | |
| 3223 return LayoutDescriptor::FromSmi(Smi::FromInt(0)); | |
| 3224 } | |
| 3225 | |
| 3226 | |
| 3227 void LayoutDescriptor::GetIndexes(int field_index, int* layout_word_index, | |
| 3228 uint32_t* layout_mask) { | |
| 3229 *layout_word_index = field_index / kNumberOfBits; | |
| 3230 ASSERT((!IsSmi() && (*layout_word_index < length())) || | |
| 3231 (IsSmi() && (*layout_word_index < 32))); | |
| 3232 | |
| 3233 int layout_bit_index = field_index % kNumberOfBits; | |
| 3234 *layout_mask = static_cast<uint32_t>(1) << layout_bit_index; | |
| 3235 } | |
| 3236 | |
| 3237 | |
| 3238 LayoutDescriptor* LayoutDescriptor::SetTagged(int field_index, bool tagged) { | |
| 3239 int layout_word_index; | |
| 3240 uint32_t layout_mask; | |
| 3241 | |
| 3242 GetIndexes(field_index, &layout_word_index, &layout_mask); | |
| 3243 | |
| 3244 if (IsSlowLayout()) { | |
| 3245 uint32_t value = get_scalar(layout_word_index); | |
| 3246 if (tagged) { | |
| 3247 value &= ~layout_mask; | |
| 3248 } else { | |
| 3249 value |= layout_mask; | |
| 3250 } | |
| 3251 set(layout_word_index, value); | |
| 3252 return this; | |
| 3253 } else { | |
| 3254 uint32_t value = static_cast<uint32_t>(Smi::cast(this)->value()); | |
| 3255 if (tagged) { | |
| 3256 value &= ~layout_mask; | |
| 3257 } else { | |
| 3258 value |= layout_mask; | |
| 3259 } | |
| 3260 return LayoutDescriptor::FromSmi(Smi::FromInt(static_cast<int>(value))); | |
| 3261 } | |
| 3262 } | |
| 3263 | |
| 3264 | |
| 3265 bool LayoutDescriptor::IsTagged(int field_index) { | |
| 3266 if (IsFastPointerLayout()) return true; | |
| 3267 | |
| 3268 int layout_word_index; | |
| 3269 uint32_t layout_mask; | |
| 3270 | |
| 3271 GetIndexes(field_index, &layout_word_index, &layout_mask); | |
| 3272 | |
| 3273 if (IsSlowLayout()) { | |
| 3274 uint32_t value = get_scalar(layout_word_index); | |
| 3275 return (value & layout_mask) == 0; | |
| 3276 } else { | |
| 3277 uint32_t value = static_cast<uint32_t>(Smi::cast(this)->value()); | |
| 3278 return (value & layout_mask) == 0; | |
| 3279 } | |
| 3280 } | |
| 3281 | |
| 3282 | |
| 3283 bool LayoutDescriptor::IsFastPointerLayout() { | |
| 3284 return IsSmi() && (Smi::cast(this)->value() == 0); | |
| 3285 } | |
| 3286 | |
| 3287 | |
| 3288 bool LayoutDescriptor::IsSlowLayout() { return !IsSmi(); } | |
| 3289 | |
| 3290 | |
| 3291 LayoutDescriptor* LayoutDescriptor::cast_gc_safe(Object* object) { | |
| 3292 if (object->IsSmi()) { | |
| 3293 // Either fast mode or forwarding pointer. | |
| 3294 LayoutDescriptor* layout_desc = reinterpret_cast<LayoutDescriptor*>(object); | |
| 3295 return layout_desc; | |
| 3296 } | |
| 3297 | |
| 3298 // This is a mixed descriptor which is a fixed typed array. | |
| 3299 MapWord map_word = reinterpret_cast<HeapObject*>(object)->map_word(); | |
| 3300 if (map_word.IsForwardingAddress()) { | |
| 3301 // Mark-compact has already moved layout descriptor. | |
| 3302 object = map_word.ToForwardingAddress(); | |
| 3303 } | |
| 3304 return LayoutDescriptor::cast(object); | |
| 3305 } | |
| 3306 | |
| 3307 | |
| 3308 LayoutDescriptor* LayoutDescriptor::OptimizeFor(Map* map) { | |
|
Toon Verwaest
2014/07/29 15:02:08
You shouldn't need to "undo" installing an expensi
Igor Sheludko
2014/10/30 14:23:43
Done.
| |
| 3309 if (IsFastPointerLayout()) return this; | |
| 3310 | |
| 3311 // Try to "take" only a part of the descriptor that corresponds to | |
| 3312 // used in-object fields of given map. | |
| 3313 if (map->inobject_properties() == 0) return FastPointerLayout(); | |
| 3314 | |
| 3315 int last_used_inobject_field_index = | |
| 3316 Min(map->inobject_properties(), map->NextFreePropertyIndex()) - 1; | |
| 3317 if (last_used_inobject_field_index < 0) return FastPointerLayout(); | |
| 3318 | |
| 3319 // Check if all fields are tagged. | |
| 3320 int layout_word_index; | |
| 3321 uint32_t mask; | |
| 3322 GetIndexes(last_used_inobject_field_index, &layout_word_index, &mask); | |
| 3323 // Calculate |mask| for all the bits that correspond to |inobject| fields | |
| 3324 // of given |map|. | |
| 3325 mask = (mask << 1) - 1; | |
| 3326 | |
| 3327 if (IsSlowLayout()) { | |
| 3328 if (last_used_inobject_field_index < kSmiValueSize) { | |
| 3329 // "Take" a subset of bits from the first word. | |
| 3330 uint32_t value = get_scalar(0) & mask; | |
| 3331 return LayoutDescriptor::FromSmi(Smi::FromInt(static_cast<int>(value))); | |
| 3332 } | |
| 3333 | |
| 3334 // All the bit-words but the last one should be zero. | |
| 3335 for (int i = 0; i < layout_word_index; i++) { | |
| 3336 uint32_t value = get_scalar(i); | |
| 3337 if (value != 0) return this; | |
| 3338 } | |
| 3339 // Now check part of the last word we are interested in. | |
| 3340 uint32_t value = get_scalar(layout_word_index) & mask; | |
| 3341 if (value != 0) return this; | |
| 3342 | |
| 3343 // All the fields are tagged. | |
| 3344 return FastPointerLayout(); | |
| 3345 | |
| 3346 } else { | |
| 3347 // "Take" a subset of bits from the value. | |
| 3348 uint32_t value = static_cast<uint32_t>(Smi::cast(this)->value()) & mask; | |
| 3349 return LayoutDescriptor::FromSmi(Smi::FromInt(static_cast<int>(value))); | |
| 3350 } | |
| 3351 } | |
| 3352 | |
| 3353 | |
| 3354 // InobjectPropertiesHelper is a helper class for querying whether inobject | |
| 3355 // property at offset is Double or not. | |
| 3356 InobjectPropertiesHelper::InobjectPropertiesHelper(Map* map) | |
| 3357 : all_fields_tagged_(true), | |
| 3358 header_size_(0), | |
| 3359 inobject_properties_count_(0), | |
| 3360 layout_descriptor_(LayoutDescriptor::FastPointerLayout()) { | |
| 3361 if (!FLAG_unbox_double_fields) return; | |
| 3362 | |
| 3363 layout_descriptor_ = map->layout_descriptor_gc_safe(); | |
| 3364 if (layout_descriptor_->IsFastPointerLayout()) { | |
| 3365 return; | |
| 3366 } | |
| 3367 | |
| 3368 int inobject_properties = map->inobject_properties(); | |
| 3369 ASSERT(inobject_properties > 0); | |
| 3370 header_size_ = map->instance_size() - (inobject_properties * kPointerSize); | |
| 3371 ASSERT(header_size_ >= 0); | |
| 3372 | |
| 3373 all_fields_tagged_ = false; | |
| 3374 } | |
| 3375 | |
| 3376 | |
| 3377 bool InobjectPropertiesHelper::IsTagged(int offset_in_bytes) { | |
| 3378 ASSERT(IsAligned(offset_in_bytes, kPointerSize)); | |
| 3379 if (all_fields_tagged_) return true; | |
| 3380 // Object headers do not contain non-tagged fields. | |
| 3381 if (offset_in_bytes < header_size_) return true; | |
| 3382 int field_index = (offset_in_bytes - header_size_) / kPointerSize; | |
| 3383 | |
| 3384 return layout_descriptor_->IsTagged(field_index); | |
| 3385 } | |
| 3386 | |
| 3387 | |
| 3108 template<typename Derived, typename Shape, typename Key> | 3388 template<typename Derived, typename Shape, typename Key> |
| 3109 int HashTable<Derived, Shape, Key>::ComputeCapacity(int at_least_space_for) { | 3389 int HashTable<Derived, Shape, Key>::ComputeCapacity(int at_least_space_for) { |
| 3110 const int kMinCapacity = 32; | 3390 const int kMinCapacity = 32; |
| 3111 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); | 3391 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); |
| 3112 if (capacity < kMinCapacity) { | 3392 if (capacity < kMinCapacity) { |
| 3113 capacity = kMinCapacity; // Guarantee min capacity. | 3393 capacity = kMinCapacity; // Guarantee min capacity. |
| 3114 } | 3394 } |
| 3115 return capacity; | 3395 return capacity; |
| 3116 } | 3396 } |
| 3117 | 3397 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3218 CAST_ACCESSOR(JSObject) | 3498 CAST_ACCESSOR(JSObject) |
| 3219 CAST_ACCESSOR(JSProxy) | 3499 CAST_ACCESSOR(JSProxy) |
| 3220 CAST_ACCESSOR(JSReceiver) | 3500 CAST_ACCESSOR(JSReceiver) |
| 3221 CAST_ACCESSOR(JSRegExp) | 3501 CAST_ACCESSOR(JSRegExp) |
| 3222 CAST_ACCESSOR(JSSet) | 3502 CAST_ACCESSOR(JSSet) |
| 3223 CAST_ACCESSOR(JSSetIterator) | 3503 CAST_ACCESSOR(JSSetIterator) |
| 3224 CAST_ACCESSOR(JSTypedArray) | 3504 CAST_ACCESSOR(JSTypedArray) |
| 3225 CAST_ACCESSOR(JSValue) | 3505 CAST_ACCESSOR(JSValue) |
| 3226 CAST_ACCESSOR(JSWeakMap) | 3506 CAST_ACCESSOR(JSWeakMap) |
| 3227 CAST_ACCESSOR(JSWeakSet) | 3507 CAST_ACCESSOR(JSWeakSet) |
| 3508 CAST_ACCESSOR(LayoutDescriptor) | |
| 3228 CAST_ACCESSOR(Map) | 3509 CAST_ACCESSOR(Map) |
| 3229 CAST_ACCESSOR(MapCache) | 3510 CAST_ACCESSOR(MapCache) |
| 3230 CAST_ACCESSOR(Name) | 3511 CAST_ACCESSOR(Name) |
| 3231 CAST_ACCESSOR(NameDictionary) | 3512 CAST_ACCESSOR(NameDictionary) |
| 3232 CAST_ACCESSOR(NormalizedMapCache) | 3513 CAST_ACCESSOR(NormalizedMapCache) |
| 3233 CAST_ACCESSOR(Object) | 3514 CAST_ACCESSOR(Object) |
| 3234 CAST_ACCESSOR(ObjectHashTable) | 3515 CAST_ACCESSOR(ObjectHashTable) |
| 3235 CAST_ACCESSOR(Oddball) | 3516 CAST_ACCESSOR(Oddball) |
| 3236 CAST_ACCESSOR(OrderedHashMap) | 3517 CAST_ACCESSOR(OrderedHashMap) |
| 3237 CAST_ACCESSOR(OrderedHashSet) | 3518 CAST_ACCESSOR(OrderedHashSet) |
| (...skipping 1854 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5092 transitions->set_back_pointer_storage(map->GetBackPointer()); | 5373 transitions->set_back_pointer_storage(map->GetBackPointer()); |
| 5093 } else if (!map->transitions()->IsFullTransitionArray()) { | 5374 } else if (!map->transitions()->IsFullTransitionArray()) { |
| 5094 transitions = TransitionArray::ExtendToFullTransitionArray(map); | 5375 transitions = TransitionArray::ExtendToFullTransitionArray(map); |
| 5095 } else { | 5376 } else { |
| 5096 return; | 5377 return; |
| 5097 } | 5378 } |
| 5098 map->set_transitions(*transitions); | 5379 map->set_transitions(*transitions); |
| 5099 } | 5380 } |
| 5100 | 5381 |
| 5101 | 5382 |
| 5102 void Map::InitializeDescriptors(DescriptorArray* descriptors) { | 5383 LayoutDescriptor* Map::layout_descriptor_gc_safe() { |
| 5384 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); | |
| 5385 return LayoutDescriptor::cast_gc_safe(layout_desc); | |
| 5386 } | |
| 5387 | |
| 5388 | |
| 5389 // Rebuilds layout descriptor. Must be called after map layout parameters | |
| 5390 // (such as |instance_type|, |instance_size|, |instance_descriptors| and | |
| 5391 // |inobject_properties|) are fully initialized. | |
| 5392 // Note: |unused_property_fields| is allowed to be in inconsistent state. | |
| 5393 void Map::RebuildLayoutDescriptor(Handle<Map> map) { | |
|
Toon Verwaest
2014/07/29 15:02:08
Try to avoid introducing this method
Igor Sheludko
2014/10/30 14:23:43
Done.
| |
| 5394 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | |
| 5395 Handle<LayoutDescriptor> layout_desc = LayoutDescriptor::New(descriptors); | |
| 5396 | |
| 5397 map->InitializeDescriptors(*descriptors, *layout_desc); | |
| 5398 if (!FLAG_unbox_double_fields) { | |
| 5399 map->set_visitor_id(StaticVisitorBase::GetVisitorId(*map)); | |
| 5400 } | |
| 5401 } | |
| 5402 | |
| 5403 | |
| 5404 void Map::InitializeDescriptors(DescriptorArray* descriptors, | |
| 5405 LayoutDescriptor* layout_desc) { | |
| 5406 set_instance_descriptors(descriptors); | |
| 5407 if (FLAG_unbox_double_fields) { | |
| 5408 set_layout_descriptor(layout_desc->OptimizeFor(this)); | |
|
Toon Verwaest
2014/07/29 15:02:08
Only overwrite the layout descriptor if the curren
Igor Sheludko
2014/10/30 14:23:43
Done.
| |
| 5409 SLOW_ASSERT(layout_descriptor()->IsConsistentWithMap(this)); | |
| 5410 set_visitor_id(StaticVisitorBase::GetVisitorId(this)); | |
| 5411 } | |
| 5412 } | |
| 5413 | |
| 5414 | |
| 5415 void Map::InitializeOwnDescriptors(DescriptorArray* descriptors, | |
| 5416 LayoutDescriptor* layout_desc) { | |
| 5103 int len = descriptors->number_of_descriptors(); | 5417 int len = descriptors->number_of_descriptors(); |
| 5104 set_instance_descriptors(descriptors); | 5418 set_instance_descriptors(descriptors); |
| 5105 SetNumberOfOwnDescriptors(len); | 5419 SetNumberOfOwnDescriptors(len); |
| 5420 | |
| 5421 if (FLAG_unbox_double_fields) { | |
| 5422 set_layout_descriptor(layout_desc->OptimizeFor(this)); | |
|
Toon Verwaest
2014/07/29 15:02:09
Make sure the layout_desc that comes into this fun
Igor Sheludko
2014/10/30 14:23:43
Done.
| |
| 5423 SLOW_ASSERT(layout_descriptor()->IsConsistentWithMap(this)); | |
| 5424 set_visitor_id(StaticVisitorBase::GetVisitorId(this)); | |
| 5425 } | |
| 5106 } | 5426 } |
| 5107 | 5427 |
| 5108 | 5428 |
| 5109 ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset) | 5429 ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset) |
| 5430 ACCESSORS(Map, layout_descriptor, LayoutDescriptor, kLayoutDecriptorOffset) | |
| 5110 | 5431 |
| 5111 | 5432 |
| 5112 void Map::set_bit_field3(uint32_t bits) { | 5433 void Map::set_bit_field3(uint32_t bits) { |
| 5113 if (kInt32Size != kPointerSize) { | 5434 if (kInt32Size != kPointerSize) { |
| 5114 WRITE_UINT32_FIELD(this, kBitField3Offset + kInt32Size, 0); | 5435 WRITE_UINT32_FIELD(this, kBitField3Offset + kInt32Size, 0); |
| 5115 } | 5436 } |
| 5116 WRITE_UINT32_FIELD(this, kBitField3Offset, bits); | 5437 WRITE_UINT32_FIELD(this, kBitField3Offset, bits); |
| 5117 } | 5438 } |
| 5118 | 5439 |
| 5119 | 5440 |
| (...skipping 1966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7086 | 7407 |
| 7087 | 7408 |
| 7088 template<typename StaticVisitor> | 7409 template<typename StaticVisitor> |
| 7089 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() { | 7410 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() { |
| 7090 typedef v8::String::ExternalStringResource Resource; | 7411 typedef v8::String::ExternalStringResource Resource; |
| 7091 StaticVisitor::VisitExternalTwoByteString( | 7412 StaticVisitor::VisitExternalTwoByteString( |
| 7092 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); | 7413 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); |
| 7093 } | 7414 } |
| 7094 | 7415 |
| 7095 | 7416 |
| 7417 static void IterateBodyUsingLayoutDescriptor(HeapObject* object, | |
| 7418 int start_offset, int end_offset, | |
| 7419 ObjectVisitor* v) { | |
| 7420 ASSERT(FLAG_unbox_double_fields); | |
| 7421 ASSERT(IsAligned(start_offset, kPointerSize) && | |
| 7422 IsAligned(end_offset, kPointerSize)); | |
| 7423 | |
| 7424 InobjectPropertiesHelper helper(object->map()); | |
| 7425 ASSERT(!helper.all_fields_tagged()); | |
| 7426 | |
| 7427 for (int offset = start_offset; offset < end_offset; offset += kPointerSize) { | |
| 7428 // Visit all tagged fields. | |
| 7429 if (helper.IsTagged(offset)) { | |
| 7430 v->VisitPointers(HeapObject::RawField(object, offset), | |
|
Toon Verwaest
2014/07/29 15:02:08
VisitPointer?
Igor Sheludko
2014/10/30 14:23:43
Done.
| |
| 7431 HeapObject::RawField(object, offset + kPointerSize)); | |
| 7432 } | |
| 7433 } | |
| 7434 } | |
| 7435 | |
| 7436 | |
| 7096 template<int start_offset, int end_offset, int size> | 7437 template<int start_offset, int end_offset, int size> |
| 7097 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody( | 7438 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody( |
| 7098 HeapObject* obj, | 7439 HeapObject* obj, |
| 7099 ObjectVisitor* v) { | 7440 ObjectVisitor* v) { |
| 7441 if (!FLAG_unbox_double_fields || | |
| 7442 obj->map()->layout_descriptor()->IsFastPointerLayout()) { | |
| 7100 v->VisitPointers(HeapObject::RawField(obj, start_offset), | 7443 v->VisitPointers(HeapObject::RawField(obj, start_offset), |
| 7101 HeapObject::RawField(obj, end_offset)); | 7444 HeapObject::RawField(obj, end_offset)); |
| 7445 } else { | |
| 7446 IterateBodyUsingLayoutDescriptor(obj, start_offset, end_offset, v); | |
| 7447 } | |
| 7102 } | 7448 } |
| 7103 | 7449 |
| 7104 | 7450 |
| 7105 template<int start_offset> | 7451 template<int start_offset> |
| 7106 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj, | 7452 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj, |
| 7107 int object_size, | 7453 int object_size, |
| 7108 ObjectVisitor* v) { | 7454 ObjectVisitor* v) { |
| 7109 v->VisitPointers(HeapObject::RawField(obj, start_offset), | 7455 if (!FLAG_unbox_double_fields || |
| 7110 HeapObject::RawField(obj, object_size)); | 7456 obj->map()->layout_descriptor()->IsFastPointerLayout()) { |
| 7457 v->VisitPointers(HeapObject::RawField(obj, start_offset), | |
| 7458 HeapObject::RawField(obj, object_size)); | |
| 7459 } else { | |
| 7460 IterateBodyUsingLayoutDescriptor(obj, start_offset, object_size, v); | |
| 7461 } | |
| 7111 } | 7462 } |
| 7112 | 7463 |
| 7113 | 7464 |
| 7114 template<class Derived, class TableType> | 7465 template<class Derived, class TableType> |
| 7115 Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() { | 7466 Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() { |
| 7116 TableType* table(TableType::cast(this->table())); | 7467 TableType* table(TableType::cast(this->table())); |
| 7117 int index = Smi::cast(this->index())->value(); | 7468 int index = Smi::cast(this->index())->value(); |
| 7118 Object* key = table->KeyAt(index); | 7469 Object* key = table->KeyAt(index); |
| 7119 ASSERT(!key->IsTheHole()); | 7470 ASSERT(!key->IsTheHole()); |
| 7120 return key; | 7471 return key; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7170 #undef READ_SHORT_FIELD | 7521 #undef READ_SHORT_FIELD |
| 7171 #undef WRITE_SHORT_FIELD | 7522 #undef WRITE_SHORT_FIELD |
| 7172 #undef READ_BYTE_FIELD | 7523 #undef READ_BYTE_FIELD |
| 7173 #undef WRITE_BYTE_FIELD | 7524 #undef WRITE_BYTE_FIELD |
| 7174 #undef NOBARRIER_READ_BYTE_FIELD | 7525 #undef NOBARRIER_READ_BYTE_FIELD |
| 7175 #undef NOBARRIER_WRITE_BYTE_FIELD | 7526 #undef NOBARRIER_WRITE_BYTE_FIELD |
| 7176 | 7527 |
| 7177 } } // namespace v8::internal | 7528 } } // namespace v8::internal |
| 7178 | 7529 |
| 7179 #endif // V8_OBJECTS_INL_H_ | 7530 #endif // V8_OBJECTS_INL_H_ |
| OLD | NEW |