| Index: src/layout-descriptor.cc
|
| diff --git a/src/layout-descriptor.cc b/src/layout-descriptor.cc
|
| index e2d66039fd6492149dade607e21e6dac31218846..77b8ec4d1f63a01b35527815812e4a540ac0e065 100644
|
| --- a/src/layout-descriptor.cc
|
| +++ b/src/layout-descriptor.cc
|
| @@ -6,8 +6,11 @@
|
|
|
| #include "src/v8.h"
|
|
|
| +#include "src/base/bits.h"
|
| #include "src/layout-descriptor.h"
|
|
|
| +using v8::base::bits::CountTrailingZeros32;
|
| +
|
| namespace v8 {
|
| namespace internal {
|
|
|
| @@ -143,5 +146,111 @@ Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity(
|
| return new_layout_descriptor;
|
| }
|
| }
|
| +
|
| +
|
| +bool LayoutDescriptor::IsTagged(int field_index, int max_sequence_length,
|
| + int* out_sequence_length) {
|
| + DCHECK(max_sequence_length > 0);
|
| + if (IsFastPointerLayout()) {
|
| + *out_sequence_length = max_sequence_length;
|
| + return true;
|
| + }
|
| +
|
| + int layout_word_index;
|
| + int layout_bit_index;
|
| +
|
| + if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
|
| + // Out of bounds queries are considered tagged.
|
| + *out_sequence_length = max_sequence_length;
|
| + return true;
|
| + }
|
| + uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;
|
| +
|
| + uint32_t value = IsSlowLayout()
|
| + ? get_scalar(layout_word_index)
|
| + : static_cast<uint32_t>(Smi::cast(this)->value());
|
| +
|
| + bool is_tagged = (value & layout_mask) == 0;
|
| + if (!is_tagged) value = ~value; // Count set bits instead of cleared bits.
|
| + value = value & ~(layout_mask - 1); // Clear bits we are not interested in.
|
| + int sequence_length = CountTrailingZeros32(value) - layout_bit_index;
|
| +
|
| + if (layout_bit_index + sequence_length == kNumberOfBits) {
|
| + // This is a contiguous sequence till the end of current word, proceed
|
| + // counting in the subsequent words.
|
| + if (IsSlowLayout()) {
|
| + int len = length();
|
| + ++layout_word_index;
|
| + for (; layout_word_index < len; layout_word_index++) {
|
| + value = get_scalar(layout_word_index);
|
| + bool cur_is_tagged = (value & 1) == 0;
|
| + if (cur_is_tagged != is_tagged) break;
|
| + if (!is_tagged) value = ~value; // Count set bits instead.
|
| + int cur_sequence_length = CountTrailingZeros32(value);
|
| + sequence_length += cur_sequence_length;
|
| + if (sequence_length >= max_sequence_length) break;
|
| + if (cur_sequence_length != kNumberOfBits) break;
|
| + }
|
| + }
|
| + if (is_tagged && (field_index + sequence_length == capacity())) {
|
| + // The contiguous sequence of tagged fields lasts till the end of the
|
| + // layout descriptor which means that all the fields starting from
|
| + // field_index are tagged.
|
| + sequence_length = std::numeric_limits<int>::max();
|
| + }
|
| + }
|
| + *out_sequence_length = Min(sequence_length, max_sequence_length);
|
| + return is_tagged;
|
| +}
|
| +
|
| +
|
| +Handle<LayoutDescriptor> LayoutDescriptor::NewForTesting(Isolate* isolate,
|
| + int length) {
|
| + return New(isolate, length);
|
| +}
|
| +
|
| +
|
| +LayoutDescriptor* LayoutDescriptor::SetTaggedForTesting(int field_index,
|
| + bool tagged) {
|
| + return SetTagged(field_index, tagged);
|
| +}
|
| +
|
| +
|
| +bool LayoutDescriptorHelper::IsTagged(
|
| + int offset_in_bytes, int end_offset,
|
| + int* out_end_of_contiguous_region_offset) {
|
| + DCHECK(IsAligned(offset_in_bytes, kPointerSize));
|
| + DCHECK(IsAligned(end_offset, kPointerSize));
|
| + DCHECK(offset_in_bytes < end_offset);
|
| + if (all_fields_tagged_) {
|
| + *out_end_of_contiguous_region_offset = end_offset;
|
| + DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
|
| + return true;
|
| + }
|
| + int max_sequence_length = (end_offset - offset_in_bytes) / kPointerSize;
|
| + int field_index = Max(0, (offset_in_bytes - header_size_) / kPointerSize);
|
| + int sequence_length;
|
| + bool tagged = layout_descriptor_->IsTagged(field_index, max_sequence_length,
|
| + &sequence_length);
|
| + DCHECK(sequence_length > 0);
|
| + if (offset_in_bytes < header_size_) {
|
| + // Object headers do not contain non-tagged fields. Check if the contiguous
|
| + // region continues after the header.
|
| + if (tagged) {
|
| + // First field is tagged, calculate end offset from there.
|
| + *out_end_of_contiguous_region_offset =
|
| + header_size_ + sequence_length * kPointerSize;
|
| +
|
| + } else {
|
| + *out_end_of_contiguous_region_offset = header_size_;
|
| + }
|
| + DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
|
| + return true;
|
| + }
|
| + *out_end_of_contiguous_region_offset =
|
| + offset_in_bytes + sequence_length * kPointerSize;
|
| + DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
|
| + return tagged;
|
| +}
|
| }
|
| } // namespace v8::internal
|
|
|