LCOV - code coverage report
Current view: top level - src - layout-descriptor.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 82 82 100.0 %
Date: 2017-10-20 Functions: 10 10 100.0 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/layout-descriptor.h"
       6             : 
       7             : #include <sstream>
       8             : 
       9             : #include "src/base/bits.h"
      10             : #include "src/handles-inl.h"
      11             : #include "src/objects-inl.h"
      12             : 
      13             : using v8::base::bits::CountTrailingZeros32;
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18    11070558 : Handle<LayoutDescriptor> LayoutDescriptor::New(
      19             :     Handle<Map> map, Handle<DescriptorArray> descriptors, int num_descriptors) {
      20             :   Isolate* isolate = descriptors->GetIsolate();
      21             :   if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate);
      22             : 
      23             :   int layout_descriptor_length =
      24             :       CalculateCapacity(*map, *descriptors, num_descriptors);
      25             : 
      26    11070558 :   if (layout_descriptor_length == 0) {
      27             :     // No double fields were found, use fast pointer layout.
      28             :     return handle(FastPointerLayout(), isolate);
      29             :   }
      30             : 
      31             :   // Initially, layout descriptor corresponds to an object with all fields
      32             :   // tagged.
      33             :   Handle<LayoutDescriptor> layout_descriptor_handle =
      34             :       LayoutDescriptor::New(isolate, layout_descriptor_length);
      35             : 
      36             :   LayoutDescriptor* layout_descriptor = Initialize(
      37             :       *layout_descriptor_handle, *map, *descriptors, num_descriptors);
      38             : 
      39             :   return handle(layout_descriptor, isolate);
      40             : }
      41             : 
      42             : 
      43     4830770 : Handle<LayoutDescriptor> LayoutDescriptor::ShareAppend(
      44             :     Handle<Map> map, PropertyDetails details) {
      45             :   DCHECK(map->owns_descriptors());
      46             :   Isolate* isolate = map->GetIsolate();
      47             :   Handle<LayoutDescriptor> layout_descriptor(map->GetLayoutDescriptor(),
      48             :                                              isolate);
      49             : 
      50     4830770 :   if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
      51             :     DCHECK(details.location() != kField ||
      52             :            layout_descriptor->IsTagged(details.field_index()));
      53     4821443 :     return layout_descriptor;
      54             :   }
      55             :   int field_index = details.field_index();
      56             :   layout_descriptor = LayoutDescriptor::EnsureCapacity(
      57        9327 :       isolate, layout_descriptor, field_index + details.field_width_in_words());
      58             : 
      59             :   DisallowHeapAllocation no_allocation;
      60             :   LayoutDescriptor* layout_desc = *layout_descriptor;
      61             :   layout_desc = layout_desc->SetRawData(field_index);
      62             :   if (details.field_width_in_words() > 1) {
      63             :     layout_desc = layout_desc->SetRawData(field_index + 1);
      64             :   }
      65             :   return handle(layout_desc, isolate);
      66             : }
      67             : 
      68             : 
      69       62585 : Handle<LayoutDescriptor> LayoutDescriptor::AppendIfFastOrUseFull(
      70             :     Handle<Map> map, PropertyDetails details,
      71             :     Handle<LayoutDescriptor> full_layout_descriptor) {
      72             :   DisallowHeapAllocation no_allocation;
      73             :   LayoutDescriptor* layout_descriptor = map->layout_descriptor();
      74       62585 :   if (layout_descriptor->IsSlowLayout()) {
      75        2640 :     return full_layout_descriptor;
      76             :   }
      77       59945 :   if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
      78             :     DCHECK(details.location() != kField ||
      79             :            layout_descriptor->IsTagged(details.field_index()));
      80             :     return handle(layout_descriptor, map->GetIsolate());
      81             :   }
      82             :   int field_index = details.field_index();
      83             :   int new_capacity = field_index + details.field_width_in_words();
      84        2837 :   if (new_capacity > layout_descriptor->capacity()) {
      85             :     // Current map's layout descriptor runs out of space, so use the full
      86             :     // layout descriptor.
      87          75 :     return full_layout_descriptor;
      88             :   }
      89             : 
      90             :   layout_descriptor = layout_descriptor->SetRawData(field_index);
      91             :   if (details.field_width_in_words() > 1) {
      92             :     layout_descriptor = layout_descriptor->SetRawData(field_index + 1);
      93             :   }
      94             :   return handle(layout_descriptor, map->GetIsolate());
      95             : }
      96             : 
      97             : 
      98        9327 : Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity(
      99             :     Isolate* isolate, Handle<LayoutDescriptor> layout_descriptor,
     100             :     int new_capacity) {
     101             :   int old_capacity = layout_descriptor->capacity();
     102        9327 :   if (new_capacity <= old_capacity) {
     103        9235 :     return layout_descriptor;
     104             :   }
     105             :   Handle<LayoutDescriptor> new_layout_descriptor =
     106             :       LayoutDescriptor::New(isolate, new_capacity);
     107             :   DCHECK(new_layout_descriptor->IsSlowLayout());
     108             : 
     109          92 :   if (layout_descriptor->IsSlowLayout()) {
     110          24 :     memcpy(new_layout_descriptor->GetDataStartAddress(),
     111          24 :            layout_descriptor->GetDataStartAddress(),
     112          24 :            layout_descriptor->DataSize());
     113          24 :     return new_layout_descriptor;
     114             :   } else {
     115             :     // Fast layout.
     116          68 :     uint32_t value = static_cast<uint32_t>(Smi::ToInt(*layout_descriptor));
     117             :     new_layout_descriptor->set_layout_word(0, value);
     118          68 :     return new_layout_descriptor;
     119             :   }
     120             : }
     121             : 
     122             : 
     123      696418 : bool LayoutDescriptor::IsTagged(int field_index, int max_sequence_length,
     124             :                                 int* out_sequence_length) {
     125             :   DCHECK_GT(max_sequence_length, 0);
     126      696418 :   if (IsFastPointerLayout()) {
     127         588 :     *out_sequence_length = max_sequence_length;
     128         588 :     return true;
     129             :   }
     130             : 
     131             :   int layout_word_index;
     132             :   int layout_bit_index;
     133             : 
     134      695830 :   if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
     135             :     // Out of bounds queries are considered tagged.
     136         240 :     *out_sequence_length = max_sequence_length;
     137         240 :     return true;
     138             :   }
     139      695590 :   uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;
     140             : 
     141             :   uint32_t value = IsSlowLayout() ? get_layout_word(layout_word_index)
     142     1215758 :                                   : static_cast<uint32_t>(Smi::ToInt(this));
     143             : 
     144      695590 :   bool is_tagged = (value & layout_mask) == 0;
     145      695590 :   if (!is_tagged) value = ~value;  // Count set bits instead of cleared bits.
     146      695590 :   value = value & ~(layout_mask - 1);  // Clear bits we are not interested in.
     147      695590 :   int sequence_length = CountTrailingZeros32(value) - layout_bit_index;
     148             : 
     149      695590 :   if (layout_bit_index + sequence_length == kBitsPerLayoutWord) {
     150             :     // This is a contiguous sequence till the end of current word, proceed
     151             :     // counting in the subsequent words.
     152      172591 :     if (IsSlowLayout()) {
     153      135536 :       ++layout_word_index;
     154             :       int num_words = number_of_layout_words();
     155      471162 :       for (; layout_word_index < num_words; layout_word_index++) {
     156             :         value = get_layout_word(layout_word_index);
     157      444729 :         bool cur_is_tagged = (value & 1) == 0;
     158      444729 :         if (cur_is_tagged != is_tagged) break;
     159      443662 :         if (!is_tagged) value = ~value;  // Count set bits instead.
     160      443662 :         int cur_sequence_length = CountTrailingZeros32(value);
     161      443662 :         sequence_length += cur_sequence_length;
     162      443662 :         if (sequence_length >= max_sequence_length) break;
     163      348108 :         if (cur_sequence_length != kBitsPerLayoutWord) break;
     164             :       }
     165             :     }
     166      270691 :     if (is_tagged && (field_index + sequence_length == capacity())) {
     167             :       // The contiguous sequence of tagged fields lasts till the end of the
     168             :       // layout descriptor which means that all the fields starting from
     169             :       // field_index are tagged.
     170             :       sequence_length = std::numeric_limits<int>::max();
     171             :     }
     172             :   }
     173      695590 :   *out_sequence_length = Min(sequence_length, max_sequence_length);
     174      695590 :   return is_tagged;
     175             : }
     176             : 
     177             : 
     178         258 : Handle<LayoutDescriptor> LayoutDescriptor::NewForTesting(Isolate* isolate,
     179             :                                                          int length) {
     180         258 :   return New(isolate, length);
     181             : }
     182             : 
     183             : 
     184      176424 : LayoutDescriptor* LayoutDescriptor::SetTaggedForTesting(int field_index,
     185             :                                                         bool tagged) {
     186      176424 :   return SetTagged(field_index, tagged);
     187             : }
     188             : 
     189             : 
     190      520413 : bool LayoutDescriptorHelper::IsTagged(
     191             :     int offset_in_bytes, int end_offset,
     192             :     int* out_end_of_contiguous_region_offset) {
     193             :   DCHECK(IsAligned(offset_in_bytes, kPointerSize));
     194             :   DCHECK(IsAligned(end_offset, kPointerSize));
     195             :   DCHECK(offset_in_bytes < end_offset);
     196      520413 :   if (all_fields_tagged_) {
     197        1356 :     *out_end_of_contiguous_region_offset = end_offset;
     198             :     DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
     199        1356 :     return true;
     200             :   }
     201      519057 :   int max_sequence_length = (end_offset - offset_in_bytes) / kPointerSize;
     202      519057 :   int field_index = Max(0, (offset_in_bytes - header_size_) / kPointerSize);
     203             :   int sequence_length;
     204             :   bool tagged = layout_descriptor_->IsTagged(field_index, max_sequence_length,
     205      519057 :                                              &sequence_length);
     206             :   DCHECK_GT(sequence_length, 0);
     207      526571 :   if (offset_in_bytes < header_size_) {
     208             :     // Object headers do not contain non-tagged fields. Check if the contiguous
     209             :     // region continues after the header.
     210      244233 :     if (tagged) {
     211             :       // First field is tagged, calculate end offset from there.
     212             :       *out_end_of_contiguous_region_offset =
     213       16640 :           header_size_ + sequence_length * kPointerSize;
     214             : 
     215             :     } else {
     216      227593 :       *out_end_of_contiguous_region_offset = header_size_;
     217             :     }
     218             :     DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
     219             :     return true;
     220             :   }
     221             :   *out_end_of_contiguous_region_offset =
     222      282338 :       offset_in_bytes + sequence_length * kPointerSize;
     223             :   DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
     224      282338 :   return tagged;
     225             : }
     226             : 
     227             : 
     228        2797 : LayoutDescriptor* LayoutDescriptor::Trim(Heap* heap, Map* map,
     229             :                                          DescriptorArray* descriptors,
     230             :                                          int num_descriptors) {
     231             :   DisallowHeapAllocation no_allocation;
     232             :   // Fast mode descriptors are never shared and therefore always fully
     233             :   // correspond to their map.
     234        2797 :   if (!IsSlowLayout()) return this;
     235             : 
     236             :   int layout_descriptor_length =
     237             :       CalculateCapacity(map, descriptors, num_descriptors);
     238             :   // It must not become fast-mode descriptor here, because otherwise it has to
     239             :   // be fast pointer layout descriptor already but it's is slow mode now.
     240             :   DCHECK_LT(kSmiValueSize, layout_descriptor_length);
     241             : 
     242             :   // Trim, clean and reinitialize this slow-mode layout descriptor.
     243             :   int new_backing_store_length =
     244             :       GetSlowModeBackingStoreLength(layout_descriptor_length);
     245             :   int backing_store_length = length();
     246          26 :   if (new_backing_store_length != backing_store_length) {
     247             :     DCHECK_LT(new_backing_store_length, backing_store_length);
     248           6 :     int delta = backing_store_length - new_backing_store_length;
     249           6 :     heap->RightTrimFixedArray(this, delta);
     250             :   }
     251          26 :   memset(GetDataStartAddress(), 0, DataSize());
     252             :   LayoutDescriptor* layout_descriptor =
     253             :       Initialize(this, map, descriptors, num_descriptors);
     254             :   DCHECK_EQ(this, layout_descriptor);
     255             :   return layout_descriptor;
     256             : }
     257             : 
     258             : 
     259        8214 : bool LayoutDescriptor::IsConsistentWithMap(Map* map, bool check_tail) {
     260             :   if (FLAG_unbox_double_fields) {
     261             :     DescriptorArray* descriptors = map->instance_descriptors();
     262             :     int nof_descriptors = map->NumberOfOwnDescriptors();
     263             :     int last_field_index = 0;
     264      442410 :     for (int i = 0; i < nof_descriptors; i++) {
     265      434196 :       PropertyDetails details = descriptors->GetDetails(i);
     266      473004 :       if (details.location() != kField) continue;
     267      395388 :       FieldIndex field_index = FieldIndex::ForDescriptor(map, i);
     268             :       bool tagged_expected =
     269      660816 :           !field_index.is_inobject() || !details.representation().IsDouble();
     270      790776 :       for (int bit = 0; bit < details.field_width_in_words(); bit++) {
     271      395388 :         bool tagged_actual = IsTagged(details.field_index() + bit);
     272             :         DCHECK_EQ(tagged_expected, tagged_actual);
     273      395388 :         if (tagged_actual != tagged_expected) return false;
     274             :       }
     275             :       last_field_index =
     276             :           Max(last_field_index,
     277             :               details.field_index() + details.field_width_in_words());
     278             :     }
     279        8214 :     if (check_tail) {
     280             :       int n = capacity();
     281             :       for (int i = last_field_index; i < n; i++) {
     282             :         DCHECK(IsTagged(i));
     283             :       }
     284             :     }
     285             :   }
     286             :   return true;
     287             : }
     288             : }  // namespace internal
     289             : }  // namespace v8

Generated by: LCOV version 1.10