Chromium Code Reviews| 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/layout-descriptor.h" | 9 #include "src/layout-descriptor.h" |
| 10 | 10 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 layout_descriptor->DataSize()); | 136 layout_descriptor->DataSize()); |
| 137 return new_layout_descriptor; | 137 return new_layout_descriptor; |
| 138 } else { | 138 } else { |
| 139 // Fast layout. | 139 // Fast layout. |
| 140 uint32_t value = | 140 uint32_t value = |
| 141 static_cast<uint32_t>(Smi::cast(*layout_descriptor)->value()); | 141 static_cast<uint32_t>(Smi::cast(*layout_descriptor)->value()); |
| 142 new_layout_descriptor->set(0, value); | 142 new_layout_descriptor->set(0, value); |
| 143 return new_layout_descriptor; | 143 return new_layout_descriptor; |
| 144 } | 144 } |
| 145 } | 145 } |
| 146 | |
| 147 | |
| 148 // Number of trailing zeros, Seal’s algorithm. | |
| 149 int ntz32(uint32_t x) { | |
|
Hannes Payer (out of office)
2014/11/25 17:20:13
Can we move this to utils or some global place tha
Igor Sheludko
2014/12/10 18:22:04
I removed it in favor of v8::base::bits::CountTrai
| |
| 150 const char u = -1; // Unused cell. | |
| 151 static char table[64] = {32, 0, 1, 12, 2, 6, u, 13, 3, u, 7, u, u, | |
| 152 u, u, 14, 10, 4, u, u, 8, u, u, 25, u, u, | |
| 153 u, u, u, 21, 27, 15, 31, 11, 5, u, u, u, u, | |
| 154 u, 9, u, u, 24, u, u, 20, 26, 30, u, u, u, | |
| 155 u, 23, u, 19, 29, u, 22, 18, 28, 17, 16, u}; | |
| 156 x = (x & -x) * 0x0450FBAF; | |
| 157 return table[x >> 26]; | |
| 158 } | |
| 159 | |
| 160 | |
| 161 bool LayoutDescriptor::IsTagged(int field_index, int max_sequence_length, | |
| 162 int* out_sequence_length) { | |
| 163 DCHECK(max_sequence_length > 0); | |
| 164 if (IsFastPointerLayout()) { | |
| 165 *out_sequence_length = max_sequence_length; | |
| 166 return true; | |
| 167 } | |
| 168 | |
| 169 int layout_word_index; | |
| 170 int layout_bit_index; | |
| 171 | |
| 172 if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) { | |
| 173 // Out of bounds queries are considered tagged. | |
| 174 *out_sequence_length = max_sequence_length; | |
| 175 return true; | |
| 176 } | |
| 177 uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index; | |
| 178 | |
| 179 uint32_t value = IsSlowLayout() | |
| 180 ? get_scalar(layout_word_index) | |
| 181 : static_cast<uint32_t>(Smi::cast(this)->value()); | |
| 182 | |
| 183 bool is_tagged = (value & layout_mask) == 0; | |
| 184 if (!is_tagged) value = ~value; // Count set bits instead of cleared bits. | |
| 185 value = value & ~(layout_mask - 1); // Clear bits we are not interested in. | |
| 186 int sequence_length = ntz32(value) - layout_bit_index; | |
| 187 | |
| 188 if (layout_bit_index + sequence_length == kNumberOfBits) { | |
| 189 // This is a contiguous sequence till the end of current word, proceed | |
| 190 // counting in the subsequent words. | |
| 191 if (IsSlowLayout()) { | |
| 192 int len = length(); | |
| 193 ++layout_word_index; | |
| 194 for (; layout_word_index < len; layout_word_index++) { | |
| 195 value = get_scalar(layout_word_index); | |
| 196 bool cur_is_tagged = (value & 1) == 0; | |
| 197 if (cur_is_tagged != is_tagged) break; | |
| 198 if (!is_tagged) value = ~value; // Count set bits instead. | |
| 199 int cur_sequence_length = ntz32(value); | |
| 200 sequence_length += cur_sequence_length; | |
| 201 if (sequence_length >= max_sequence_length) break; | |
| 202 if (cur_sequence_length != kNumberOfBits) break; | |
| 203 } | |
| 204 } | |
| 205 if (is_tagged && (field_index + sequence_length == capacity())) { | |
| 206 // The contiguous sequence of tagged fields lasts till the end of the | |
| 207 // layout descriptor which means that all the fields starting from | |
| 208 // field_index are tagged. | |
| 209 sequence_length = std::numeric_limits<int>::max(); | |
| 210 } | |
| 211 } | |
| 212 *out_sequence_length = Min(sequence_length, max_sequence_length); | |
| 213 return is_tagged; | |
| 214 } | |
| 215 | |
| 216 | |
| 217 Handle<LayoutDescriptor> LayoutDescriptor::NewForTesting(Isolate* isolate, | |
| 218 int length) { | |
| 219 return New(isolate, length); | |
| 220 } | |
| 221 | |
| 222 | |
| 223 LayoutDescriptor* LayoutDescriptor::SetTaggedForTesting(int field_index, | |
| 224 bool tagged) { | |
| 225 return SetTagged(field_index, tagged); | |
| 226 } | |
| 227 | |
| 228 | |
| 229 bool LayoutDescriptorHelper::IsTagged( | |
| 230 int offset_in_bytes, int end_offset, | |
| 231 int* out_end_of_contiguous_region_offset) { | |
| 232 DCHECK(IsAligned(offset_in_bytes, kPointerSize)); | |
| 233 DCHECK(IsAligned(end_offset, kPointerSize)); | |
| 234 DCHECK(offset_in_bytes < end_offset); | |
| 235 if (all_fields_tagged_) { | |
| 236 *out_end_of_contiguous_region_offset = end_offset; | |
| 237 return true; | |
| 238 } | |
| 239 int max_sequence_length = (end_offset - offset_in_bytes) / kPointerSize; | |
| 240 int field_index = Max(0, (offset_in_bytes - header_size_) / kPointerSize); | |
| 241 int sequence_length; | |
| 242 bool tagged = layout_descriptor_->IsTagged(field_index, max_sequence_length, | |
| 243 &sequence_length); | |
| 244 DCHECK(sequence_length > 0); | |
| 245 if (offset_in_bytes < header_size_) { | |
| 246 // Object headers do not contain non-tagged fields. Check if the contiguous | |
| 247 // region continues after the header. | |
| 248 if (tagged) { | |
| 249 // First field is tagged, calculate end offset from there. | |
| 250 *out_end_of_contiguous_region_offset = | |
| 251 header_size_ + sequence_length * kPointerSize; | |
| 252 | |
| 253 } else { | |
| 254 *out_end_of_contiguous_region_offset = header_size_; | |
| 255 } | |
| 256 return true; | |
| 257 } | |
| 258 *out_end_of_contiguous_region_offset = | |
| 259 offset_in_bytes + sequence_length * kPointerSize; | |
| 260 return tagged; | |
| 261 } | |
| 146 } | 262 } |
| 147 } // namespace v8::internal | 263 } // namespace v8::internal |
| OLD | NEW |