OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #include <sstream> | 5 #include <sstream> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
| 9 #include "src/base/bits.h" |
9 #include "src/layout-descriptor.h" | 10 #include "src/layout-descriptor.h" |
10 | 11 |
| 12 using v8::base::bits::CountTrailingZeros32; |
| 13 |
11 namespace v8 { | 14 namespace v8 { |
12 namespace internal { | 15 namespace internal { |
13 | 16 |
14 Handle<LayoutDescriptor> LayoutDescriptor::New( | 17 Handle<LayoutDescriptor> LayoutDescriptor::New( |
15 Handle<Map> map, Handle<DescriptorArray> descriptors, int num_descriptors) { | 18 Handle<Map> map, Handle<DescriptorArray> descriptors, int num_descriptors) { |
16 Isolate* isolate = descriptors->GetIsolate(); | 19 Isolate* isolate = descriptors->GetIsolate(); |
17 if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate); | 20 if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate); |
18 | 21 |
19 int inobject_properties = map->inobject_properties(); | 22 int inobject_properties = map->inobject_properties(); |
20 if (inobject_properties == 0) return handle(FastPointerLayout(), isolate); | 23 if (inobject_properties == 0) return handle(FastPointerLayout(), isolate); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 layout_descriptor->DataSize()); | 139 layout_descriptor->DataSize()); |
137 return new_layout_descriptor; | 140 return new_layout_descriptor; |
138 } else { | 141 } else { |
139 // Fast layout. | 142 // Fast layout. |
140 uint32_t value = | 143 uint32_t value = |
141 static_cast<uint32_t>(Smi::cast(*layout_descriptor)->value()); | 144 static_cast<uint32_t>(Smi::cast(*layout_descriptor)->value()); |
142 new_layout_descriptor->set(0, value); | 145 new_layout_descriptor->set(0, value); |
143 return new_layout_descriptor; | 146 return new_layout_descriptor; |
144 } | 147 } |
145 } | 148 } |
| 149 |
| 150 |
| 151 bool LayoutDescriptor::IsTagged(int field_index, int max_sequence_length, |
| 152 int* out_sequence_length) { |
| 153 DCHECK(max_sequence_length > 0); |
| 154 if (IsFastPointerLayout()) { |
| 155 *out_sequence_length = max_sequence_length; |
| 156 return true; |
| 157 } |
| 158 |
| 159 int layout_word_index; |
| 160 int layout_bit_index; |
| 161 |
| 162 if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) { |
| 163 // Out of bounds queries are considered tagged. |
| 164 *out_sequence_length = max_sequence_length; |
| 165 return true; |
| 166 } |
| 167 uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index; |
| 168 |
| 169 uint32_t value = IsSlowLayout() |
| 170 ? get_scalar(layout_word_index) |
| 171 : static_cast<uint32_t>(Smi::cast(this)->value()); |
| 172 |
| 173 bool is_tagged = (value & layout_mask) == 0; |
| 174 if (!is_tagged) value = ~value; // Count set bits instead of cleared bits. |
| 175 value = value & ~(layout_mask - 1); // Clear bits we are not interested in. |
| 176 int sequence_length = CountTrailingZeros32(value) - layout_bit_index; |
| 177 |
| 178 if (layout_bit_index + sequence_length == kNumberOfBits) { |
| 179 // This is a contiguous sequence till the end of current word, proceed |
| 180 // counting in the subsequent words. |
| 181 if (IsSlowLayout()) { |
| 182 int len = length(); |
| 183 ++layout_word_index; |
| 184 for (; layout_word_index < len; layout_word_index++) { |
| 185 value = get_scalar(layout_word_index); |
| 186 bool cur_is_tagged = (value & 1) == 0; |
| 187 if (cur_is_tagged != is_tagged) break; |
| 188 if (!is_tagged) value = ~value; // Count set bits instead. |
| 189 int cur_sequence_length = CountTrailingZeros32(value); |
| 190 sequence_length += cur_sequence_length; |
| 191 if (sequence_length >= max_sequence_length) break; |
| 192 if (cur_sequence_length != kNumberOfBits) break; |
| 193 } |
| 194 } |
| 195 if (is_tagged && (field_index + sequence_length == capacity())) { |
| 196 // The contiguous sequence of tagged fields lasts till the end of the |
| 197 // layout descriptor which means that all the fields starting from |
| 198 // field_index are tagged. |
| 199 sequence_length = std::numeric_limits<int>::max(); |
| 200 } |
| 201 } |
| 202 *out_sequence_length = Min(sequence_length, max_sequence_length); |
| 203 return is_tagged; |
| 204 } |
| 205 |
| 206 |
| 207 Handle<LayoutDescriptor> LayoutDescriptor::NewForTesting(Isolate* isolate, |
| 208 int length) { |
| 209 return New(isolate, length); |
| 210 } |
| 211 |
| 212 |
| 213 LayoutDescriptor* LayoutDescriptor::SetTaggedForTesting(int field_index, |
| 214 bool tagged) { |
| 215 return SetTagged(field_index, tagged); |
| 216 } |
| 217 |
| 218 |
| 219 bool LayoutDescriptorHelper::IsTagged( |
| 220 int offset_in_bytes, int end_offset, |
| 221 int* out_end_of_contiguous_region_offset) { |
| 222 DCHECK(IsAligned(offset_in_bytes, kPointerSize)); |
| 223 DCHECK(IsAligned(end_offset, kPointerSize)); |
| 224 DCHECK(offset_in_bytes < end_offset); |
| 225 if (all_fields_tagged_) { |
| 226 *out_end_of_contiguous_region_offset = end_offset; |
| 227 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset); |
| 228 return true; |
| 229 } |
| 230 int max_sequence_length = (end_offset - offset_in_bytes) / kPointerSize; |
| 231 int field_index = Max(0, (offset_in_bytes - header_size_) / kPointerSize); |
| 232 int sequence_length; |
| 233 bool tagged = layout_descriptor_->IsTagged(field_index, max_sequence_length, |
| 234 &sequence_length); |
| 235 DCHECK(sequence_length > 0); |
| 236 if (offset_in_bytes < header_size_) { |
| 237 // Object headers do not contain non-tagged fields. Check if the contiguous |
| 238 // region continues after the header. |
| 239 if (tagged) { |
| 240 // First field is tagged, calculate end offset from there. |
| 241 *out_end_of_contiguous_region_offset = |
| 242 header_size_ + sequence_length * kPointerSize; |
| 243 |
| 244 } else { |
| 245 *out_end_of_contiguous_region_offset = header_size_; |
| 246 } |
| 247 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset); |
| 248 return true; |
| 249 } |
| 250 *out_end_of_contiguous_region_offset = |
| 251 offset_in_bytes + sequence_length * kPointerSize; |
| 252 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset); |
| 253 return tagged; |
| 254 } |
146 } | 255 } |
147 } // namespace v8::internal | 256 } // namespace v8::internal |
OLD | NEW |