LCOV - code coverage report
Current view: top level - src - layout-descriptor.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 87 87 100.0 %
Date: 2019-04-19 Functions: 11 11 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             : namespace v8 {
      14             : namespace internal {
      15             : 
      16    12356226 : Handle<LayoutDescriptor> LayoutDescriptor::New(
      17             :     Isolate* isolate, Handle<Map> map, Handle<DescriptorArray> descriptors,
      18             :     int num_descriptors) {
      19             :   if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate);
      20             : 
      21             :   int layout_descriptor_length =
      22             :       CalculateCapacity(*map, *descriptors, num_descriptors);
      23             : 
      24    12356232 :   if (layout_descriptor_length == 0) {
      25             :     // No double fields were found, use fast pointer layout.
      26             :     return handle(FastPointerLayout(), isolate);
      27             :   }
      28             : 
      29             :   // Initially, layout descriptor corresponds to an object with all fields
      30             :   // tagged.
      31             :   Handle<LayoutDescriptor> layout_descriptor_handle =
      32             :       LayoutDescriptor::New(isolate, layout_descriptor_length);
      33             : 
      34             :   LayoutDescriptor layout_descriptor = Initialize(
      35             :       *layout_descriptor_handle, *map, *descriptors, num_descriptors);
      36             : 
      37             :   return handle(layout_descriptor, isolate);
      38             : }
      39             : 
      40     6193560 : Handle<LayoutDescriptor> LayoutDescriptor::ShareAppend(
      41             :     Isolate* isolate, Handle<Map> map, PropertyDetails details) {
      42             :   DCHECK(map->owns_descriptors());
      43             :   Handle<LayoutDescriptor> layout_descriptor(map->GetLayoutDescriptor(),
      44             :                                              isolate);
      45             : 
      46    12387123 :   if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
      47             :     DCHECK(details.location() != kField ||
      48             :            layout_descriptor->IsTagged(details.field_index()));
      49     6184404 :     return layout_descriptor;
      50             :   }
      51             :   int field_index = details.field_index();
      52             :   layout_descriptor = LayoutDescriptor::EnsureCapacity(
      53        9157 :       isolate, layout_descriptor, field_index + details.field_width_in_words());
      54             : 
      55             :   DisallowHeapAllocation no_allocation;
      56             :   LayoutDescriptor layout_desc = *layout_descriptor;
      57             :   layout_desc = layout_desc->SetRawData(field_index);
      58             :   if (details.field_width_in_words() > 1) {
      59             :     layout_desc = layout_desc->SetRawData(field_index + 1);
      60             :   }
      61             :   return handle(layout_desc, isolate);
      62             : }
      63             : 
      64       30920 : Handle<LayoutDescriptor> LayoutDescriptor::AppendIfFastOrUseFull(
      65             :     Isolate* isolate, Handle<Map> map, PropertyDetails details,
      66             :     Handle<LayoutDescriptor> full_layout_descriptor) {
      67             :   DisallowHeapAllocation no_allocation;
      68             :   LayoutDescriptor layout_descriptor = map->layout_descriptor();
      69       30920 :   if (layout_descriptor->IsSlowLayout()) {
      70        2200 :     return full_layout_descriptor;
      71             :   }
      72       57440 :   if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
      73             :     DCHECK(details.location() != kField ||
      74             :            layout_descriptor->IsTagged(details.field_index()));
      75             :     return handle(layout_descriptor, isolate);
      76             :   }
      77             :   int field_index = details.field_index();
      78             :   int new_capacity = field_index + details.field_width_in_words();
      79        2627 :   if (new_capacity > layout_descriptor->capacity()) {
      80             :     // Current map's layout descriptor runs out of space, so use the full
      81             :     // layout descriptor.
      82          62 :     return full_layout_descriptor;
      83             :   }
      84             : 
      85             :   layout_descriptor = layout_descriptor->SetRawData(field_index);
      86             :   if (details.field_width_in_words() > 1) {
      87             :     layout_descriptor = layout_descriptor->SetRawData(field_index + 1);
      88             :   }
      89             :   return handle(layout_descriptor, isolate);
      90             : }
      91             : 
      92             : 
      93        9157 : Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity(
      94             :     Isolate* isolate, Handle<LayoutDescriptor> layout_descriptor,
      95             :     int new_capacity) {
      96             :   int old_capacity = layout_descriptor->capacity();
      97        9157 :   if (new_capacity <= old_capacity) {
      98        9079 :     return layout_descriptor;
      99             :   }
     100             :   Handle<LayoutDescriptor> new_layout_descriptor =
     101             :       LayoutDescriptor::New(isolate, new_capacity);
     102             :   DCHECK(new_layout_descriptor->IsSlowLayout());
     103             : 
     104          78 :   if (layout_descriptor->IsSlowLayout()) {
     105          20 :     memcpy(new_layout_descriptor->GetDataStartAddress(),
     106             :            layout_descriptor->GetDataStartAddress(),
     107             :            layout_descriptor->DataSize());
     108          20 :     return new_layout_descriptor;
     109             :   } else {
     110             :     // Fast layout.
     111          58 :     uint32_t value = static_cast<uint32_t>(Smi::ToInt(*layout_descriptor));
     112             :     new_layout_descriptor->set_layout_word(0, value);
     113          58 :     return new_layout_descriptor;
     114             :   }
     115             : }
     116             : 
     117             : 
     118      553579 : bool LayoutDescriptor::IsTagged(int field_index, int max_sequence_length,
     119             :                                 int* out_sequence_length) {
     120             :   DCHECK_GT(max_sequence_length, 0);
     121      553579 :   if (IsFastPointerLayout()) {
     122         490 :     *out_sequence_length = max_sequence_length;
     123         490 :     return true;
     124             :   }
     125             : 
     126             :   int layout_word_index;
     127             :   int layout_bit_index;
     128             : 
     129      553089 :   if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
     130             :     // Out of bounds queries are considered tagged.
     131         200 :     *out_sequence_length = max_sequence_length;
     132         200 :     return true;
     133             :   }
     134      552889 :   uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;
     135             : 
     136             :   uint32_t value = IsSlowLayout() ? get_layout_word(layout_word_index)
     137      960598 :                                   : static_cast<uint32_t>(Smi::ToInt(*this));
     138             : 
     139      552889 :   bool is_tagged = (value & layout_mask) == 0;
     140      552889 :   if (!is_tagged) value = ~value;  // Count set bits instead of cleared bits.
     141      552889 :   value = value & ~(layout_mask - 1);  // Clear bits we are not interested in.
     142             :   int sequence_length;
     143      552889 :   if (IsSlowLayout()) {
     144      145115 :     sequence_length = base::bits::CountTrailingZeros(value) - layout_bit_index;
     145             : 
     146      145115 :     if (layout_bit_index + sequence_length == kBitsPerLayoutWord) {
     147             :       // This is a contiguous sequence till the end of current word, proceed
     148             :       // counting in the subsequent words.
     149      112956 :       ++layout_word_index;
     150             :       int num_words = number_of_layout_words();
     151      672312 :       for (; layout_word_index < num_words; layout_word_index++) {
     152             :         value = get_layout_word(layout_word_index);
     153      370568 :         bool cur_is_tagged = (value & 1) == 0;
     154      370568 :         if (cur_is_tagged != is_tagged) break;
     155      369680 :         if (!is_tagged) value = ~value;  // Count set bits instead.
     156      369680 :         int cur_sequence_length = base::bits::CountTrailingZeros(value);
     157      369680 :         sequence_length += cur_sequence_length;
     158      369680 :         if (sequence_length >= max_sequence_length) break;
     159      290062 :         if (cur_sequence_length != kBitsPerLayoutWord) break;
     160             :       }
     161      164572 :       if (is_tagged && (field_index + sequence_length == capacity())) {
     162             :         // The contiguous sequence of tagged fields lasts till the end of the
     163             :         // layout descriptor which means that all the fields starting from
     164             :         // field_index are tagged.
     165             :         sequence_length = std::numeric_limits<int>::max();
     166             :       }
     167             :     }
     168             :   } else {  // Fast layout.
     169             :     sequence_length = Min(base::bits::CountTrailingZeros(value),
     170      407774 :                           static_cast<unsigned>(kBitsInSmiLayout)) -
     171      407774 :                       layout_bit_index;
     172      479456 :     if (is_tagged && (field_index + sequence_length == capacity())) {
     173             :       // The contiguous sequence of tagged fields lasts till the end of the
     174             :       // layout descriptor which means that all the fields starting from
     175             :       // field_index are tagged.
     176             :       sequence_length = std::numeric_limits<int>::max();
     177             :     }
     178             :   }
     179      552889 :   *out_sequence_length = Min(sequence_length, max_sequence_length);
     180      552889 :   return is_tagged;
     181             : }
     182             : 
     183             : 
     184         215 : Handle<LayoutDescriptor> LayoutDescriptor::NewForTesting(Isolate* isolate,
     185             :                                                          int length) {
     186         215 :   return New(isolate, length);
     187             : }
     188             : 
     189      147020 : LayoutDescriptor LayoutDescriptor::SetTaggedForTesting(int field_index,
     190             :                                                        bool tagged) {
     191      147020 :   return SetTagged(field_index, tagged);
     192             : }
     193             : 
     194      407652 : bool LayoutDescriptorHelper::IsTagged(
     195             :     int offset_in_bytes, int end_offset,
     196             :     int* out_end_of_contiguous_region_offset) {
     197             :   DCHECK(IsAligned(offset_in_bytes, kTaggedSize));
     198             :   DCHECK(IsAligned(end_offset, kTaggedSize));
     199             :   DCHECK(offset_in_bytes < end_offset);
     200      407652 :   if (all_fields_tagged_) {
     201        1130 :     *out_end_of_contiguous_region_offset = end_offset;
     202             :     DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
     203        1130 :     return true;
     204             :   }
     205      406522 :   int max_sequence_length = (end_offset - offset_in_bytes) / kTaggedSize;
     206      406522 :   int field_index = Max(0, (offset_in_bytes - header_size_) / kTaggedSize);
     207             :   int sequence_length;
     208      406522 :   bool tagged = layout_descriptor_->IsTagged(field_index, max_sequence_length,
     209      406522 :                                              &sequence_length);
     210             :   DCHECK_GT(sequence_length, 0);
     211      410584 :   if (offset_in_bytes < header_size_) {
     212             :     // Object headers do not contain non-tagged fields. Check if the contiguous
     213             :     // region continues after the header.
     214      179178 :     if (tagged) {
     215             :       // First field is tagged, calculate end offset from there.
     216             :       *out_end_of_contiguous_region_offset =
     217       20776 :           header_size_ + sequence_length * kTaggedSize;
     218             : 
     219             :     } else {
     220      158402 :       *out_end_of_contiguous_region_offset = header_size_;
     221             :     }
     222             :     DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
     223             :     return true;
     224             :   }
     225             :   *out_end_of_contiguous_region_offset =
     226      231406 :       offset_in_bytes + sequence_length * kTaggedSize;
     227             :   DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
     228      231406 :   return tagged;
     229             : }
     230             : 
     231        5427 : LayoutDescriptor LayoutDescriptor::Trim(Heap* heap, Map map,
     232             :                                         DescriptorArray descriptors,
     233             :                                         int num_descriptors) {
     234             :   DisallowHeapAllocation no_allocation;
     235             :   // Fast mode descriptors are never shared and therefore always fully
     236             :   // correspond to their map.
     237        5427 :   if (!IsSlowLayout()) return *this;
     238             : 
     239             :   int layout_descriptor_length =
     240             :       CalculateCapacity(map, descriptors, num_descriptors);
     241             :   // It must not become fast-mode descriptor here, because otherwise it has to
     242             :   // be fast pointer layout descriptor already but it's is slow mode now.
     243             :   DCHECK_LT(kBitsInSmiLayout, layout_descriptor_length);
     244             : 
     245             :   // Trim, clean and reinitialize this slow-mode layout descriptor.
     246             :   int new_backing_store_length =
     247             :       GetSlowModeBackingStoreLength(layout_descriptor_length);
     248             :   int backing_store_length = length();
     249          23 :   if (new_backing_store_length != backing_store_length) {
     250             :     DCHECK_LT(new_backing_store_length, backing_store_length);
     251           5 :     int delta = backing_store_length - new_backing_store_length;
     252           5 :     heap->RightTrimFixedArray(*this, delta);
     253             :   }
     254          23 :   memset(GetDataStartAddress(), 0, DataSize());
     255             :   LayoutDescriptor layout_descriptor =
     256             :       Initialize(*this, map, descriptors, num_descriptors);
     257             :   DCHECK_EQ(*this, layout_descriptor);
     258          23 :   return layout_descriptor;
     259             : }
     260             : 
     261        6845 : bool LayoutDescriptor::IsConsistentWithMap(Map map, bool check_tail) {
     262             :   if (FLAG_unbox_double_fields) {
     263        6845 :     DescriptorArray descriptors = map->instance_descriptors();
     264             :     int nof_descriptors = map->NumberOfOwnDescriptors();
     265             :     int last_field_index = 0;
     266      730505 :     for (int i = 0; i < nof_descriptors; i++) {
     267      361830 :       PropertyDetails details = descriptors->GetDetails(i);
     268      394170 :       if (details.location() != kField) continue;
     269      329490 :       FieldIndex field_index = FieldIndex::ForDescriptor(map, i);
     270             :       bool tagged_expected =
     271      550680 :           !field_index.is_inobject() || !details.representation().IsDouble();
     272      988470 :       for (int bit = 0; bit < details.field_width_in_words(); bit++) {
     273      329490 :         bool tagged_actual = IsTagged(details.field_index() + bit);
     274             :         DCHECK_EQ(tagged_expected, tagged_actual);
     275      329490 :         if (tagged_actual != tagged_expected) return false;
     276             :       }
     277             :       last_field_index =
     278             :           Max(last_field_index,
     279             :               details.field_index() + details.field_width_in_words());
     280             :     }
     281             :     if (check_tail) {
     282             :       int n = capacity();
     283             :       for (int i = last_field_index; i < n; i++) {
     284             :         DCHECK(IsTagged(i));
     285             :       }
     286             :     }
     287             :   }
     288        6845 :   return true;
     289             : }
     290             : }  // namespace internal
     291      122036 : }  // namespace v8

Generated by: LCOV version 1.10