LCOV - code coverage report
Current view: top level - src - layout-descriptor-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 63 65 96.9 %
Date: 2017-10-20 Functions: 2 2 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             : #ifndef V8_LAYOUT_DESCRIPTOR_INL_H_
       6             : #define V8_LAYOUT_DESCRIPTOR_INL_H_
       7             : 
       8             : #include "src/layout-descriptor.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : 
      13             : LayoutDescriptor* LayoutDescriptor::FromSmi(Smi* smi) {
      14             :   return LayoutDescriptor::cast(smi);
      15             : }
      16             : 
      17             : 
      18             : Handle<LayoutDescriptor> LayoutDescriptor::New(Isolate* isolate, int length) {
      19     7528371 :   if (length <= kSmiValueSize) {
      20             :     // The whole bit vector fits into a smi.
      21             :     return handle(LayoutDescriptor::FromSmi(Smi::kZero), isolate);
      22             :   }
      23             :   int backing_store_length = GetSlowModeBackingStoreLength(length);
      24             :   Handle<LayoutDescriptor> result = Handle<LayoutDescriptor>::cast(
      25         462 :       isolate->factory()->NewByteArray(backing_store_length, TENURED));
      26         462 :   memset(result->GetDataStartAddress(), 0, result->DataSize());
      27             :   return result;
      28             : }
      29             : 
      30             : 
      31             : bool LayoutDescriptor::InobjectUnboxedField(int inobject_properties,
      32             :                                             PropertyDetails details) {
      33    67765183 :   if (details.location() != kField || !details.representation().IsDouble()) {
      34             :     return false;
      35             :   }
      36             :   // We care only about in-object properties.
      37       87689 :   return details.field_index() < inobject_properties;
      38             : }
      39             : 
      40             : 
      41             : LayoutDescriptor* LayoutDescriptor::FastPointerLayout() {
      42             :   return LayoutDescriptor::FromSmi(Smi::kZero);
      43             : }
      44             : 
      45             : 
      46             : bool LayoutDescriptor::GetIndexes(int field_index, int* layout_word_index,
      47             :                                   int* layout_bit_index) {
      48     3328405 :   if (static_cast<unsigned>(field_index) >= static_cast<unsigned>(capacity())) {
      49             :     return false;
      50             :   }
      51             : 
      52     1599182 :   *layout_word_index = field_index / kBitsPerLayoutWord;
      53     1599236 :   CHECK((!IsSmi() && (*layout_word_index < length())) ||
      54             :         (IsSmi() && (*layout_word_index < 1)));
      55             : 
      56     1599182 :   *layout_bit_index = field_index % kBitsPerLayoutWord;
      57             :   return true;
      58             : }
      59             : 
      60             : 
      61             : LayoutDescriptor* LayoutDescriptor::SetRawData(int field_index) {
      62             :   return SetTagged(field_index, false);
      63             : }
      64             : 
      65             : 
      66             : LayoutDescriptor* LayoutDescriptor::SetTagged(int field_index, bool tagged) {
      67             :   int layout_word_index = 0;
      68             :   int layout_bit_index = 0;
      69             : 
      70      201001 :   if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
      71           0 :     CHECK(false);
      72             :     return this;
      73             :   }
      74      201001 :   uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;
      75             : 
      76      201001 :   if (IsSlowLayout()) {
      77      179301 :     uint32_t value = get_layout_word(layout_word_index);
      78      173160 :     if (tagged) {
      79       80316 :       value &= ~layout_mask;
      80             :     } else {
      81       98985 :       value |= layout_mask;
      82             :     }
      83      179301 :     set_layout_word(layout_word_index, value);
      84             :     return this;
      85             :   } else {
      86       21700 :     uint32_t value = static_cast<uint32_t>(Smi::ToInt(this));
      87        3264 :     if (tagged) {
      88        1650 :       value &= ~layout_mask;
      89             :     } else {
      90       20050 :       value |= layout_mask;
      91             :     }
      92       21700 :     return LayoutDescriptor::FromSmi(Smi::FromInt(static_cast<int>(value)));
      93             :   }
      94             : }
      95             : 
      96             : 
      97             : bool LayoutDescriptor::IsTagged(int field_index) {
      98    33294158 :   if (IsFastPointerLayout()) return true;
      99             : 
     100             :   int layout_word_index;
     101             :   int layout_bit_index;
     102             : 
     103      773455 :   if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
     104             :     // All bits after Out of bounds queries
     105             :     return true;
     106             :   }
     107      703999 :   uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;
     108             : 
     109      704053 :   if (IsSlowLayout()) {
     110      421518 :     uint32_t value = get_layout_word(layout_word_index);
     111      421518 :     return (value & layout_mask) == 0;
     112             :   } else {
     113      282535 :     uint32_t value = static_cast<uint32_t>(Smi::ToInt(this));
     114      282535 :     return (value & layout_mask) == 0;
     115             :   }
     116             : }
     117             : 
     118             : 
     119             : bool LayoutDescriptor::IsFastPointerLayout() {
     120           6 :   return this == FastPointerLayout();
     121             : }
     122             : 
     123             : 
     124             : bool LayoutDescriptor::IsFastPointerLayout(Object* layout_descriptor) {
     125           6 :   return layout_descriptor == FastPointerLayout();
     126             : }
     127             : 
     128             : 
     129         102 : bool LayoutDescriptor::IsSlowLayout() { return !IsSmi(); }
     130             : 
     131             : 
     132             : int LayoutDescriptor::capacity() {
     133     1999424 :   return IsSlowLayout() ? (length() * kBitsPerByte) : kSmiValueSize;
     134             : }
     135             : 
     136             : 
     137             : LayoutDescriptor* LayoutDescriptor::cast_gc_safe(Object* object) {
     138             :   // The map word of the object can be a forwarding pointer during
     139             :   // object evacuation phase of GC. Since the layout descriptor methods
     140             :   // for checking whether a field is tagged or not do not depend on the
     141             :   // object map, it should be safe.
     142             :   return reinterpret_cast<LayoutDescriptor*>(object);
     143             : }
     144             : 
     145             : int LayoutDescriptor::GetSlowModeBackingStoreLength(int length) {
     146             :   DCHECK_LT(0, length);
     147             :   // We allocate kPointerSize rounded blocks of memory anyway so we increase
     148             :   // the length  of allocated array to utilize that "lost" space which could
     149             :   // also help to avoid layout descriptor reallocations.
     150         488 :   return RoundUp(length, kBitsPerByte * kPointerSize) / kBitsPerByte;
     151             : }
     152             : 
     153             : 
     154             : int LayoutDescriptor::CalculateCapacity(Map* map, DescriptorArray* descriptors,
     155             :                                         int num_descriptors) {
     156    11070584 :   int inobject_properties = map->GetInObjectProperties();
     157    11070583 :   if (inobject_properties == 0) return 0;
     158             : 
     159             :   DCHECK_LE(num_descriptors, descriptors->number_of_descriptors());
     160             : 
     161             :   int layout_descriptor_length;
     162             :   const int kMaxWordsPerField = kDoubleSize / kPointerSize;
     163             : 
     164     7645660 :   if (num_descriptors <= kSmiValueSize / kMaxWordsPerField) {
     165             :     // Even in the "worst" case (all fields are doubles) it would fit into
     166             :     // a Smi, so no need to calculate length.
     167             :     layout_descriptor_length = kSmiValueSize;
     168             : 
     169             :   } else {
     170             :     layout_descriptor_length = 0;
     171             : 
     172    37579687 :     for (int i = 0; i < num_descriptors; i++) {
     173    37579687 :       PropertyDetails details = descriptors->GetDetails(i);
     174    75149525 :       if (!InobjectUnboxedField(inobject_properties, details)) continue;
     175        9849 :       int field_index = details.field_index();
     176        9849 :       int field_width_in_words = details.field_width_in_words();
     177             :       layout_descriptor_length =
     178        9849 :           Max(layout_descriptor_length, field_index + field_width_in_words);
     179             :     }
     180             :   }
     181     7645660 :   layout_descriptor_length = Min(layout_descriptor_length, inobject_properties);
     182             :   return layout_descriptor_length;
     183             : }
     184             : 
     185             : 
     186             : LayoutDescriptor* LayoutDescriptor::Initialize(
     187             :     LayoutDescriptor* layout_descriptor, Map* map, DescriptorArray* descriptors,
     188             :     int num_descriptors) {
     189             :   DisallowHeapAllocation no_allocation;
     190     7528047 :   int inobject_properties = map->GetInObjectProperties();
     191             : 
     192    25294782 :   for (int i = 0; i < num_descriptors; i++) {
     193    25294781 :     PropertyDetails details = descriptors->GetDetails(i);
     194    25294782 :     if (!InobjectUnboxedField(inobject_properties, details)) {
     195             :       DCHECK(details.location() != kField ||
     196             :              layout_descriptor->IsTagged(details.field_index()));
     197    25282294 :       continue;
     198             :     }
     199       12488 :     int field_index = details.field_index();
     200             :     layout_descriptor = layout_descriptor->SetRawData(field_index);
     201       12488 :     if (details.field_width_in_words() > 1) {
     202           0 :       layout_descriptor = layout_descriptor->SetRawData(field_index + 1);
     203             :     }
     204             :   }
     205             :   return layout_descriptor;
     206             : }
     207             : 
     208             : 
     209             : // LayoutDescriptorHelper is a helper class for querying whether inobject
     210             : // property at offset is Double or not.
     211      243563 : LayoutDescriptorHelper::LayoutDescriptorHelper(Map* map)
     212             :     : all_fields_tagged_(true),
     213             :       header_size_(0),
     214      243563 :       layout_descriptor_(LayoutDescriptor::FastPointerLayout()) {
     215             :   if (!FLAG_unbox_double_fields) return;
     216             : 
     217      243563 :   layout_descriptor_ = map->layout_descriptor_gc_safe();
     218      243563 :   if (layout_descriptor_->IsFastPointerLayout()) {
     219             :     return;
     220             :   }
     221             : 
     222             :   int inobject_properties = map->GetInObjectProperties();
     223             :   DCHECK_GT(inobject_properties, 0);
     224      243695 :   header_size_ = map->instance_size() - (inobject_properties * kPointerSize);
     225             :   DCHECK_GE(header_size_, 0);
     226             : 
     227      243695 :   all_fields_tagged_ = false;
     228             : }
     229             : 
     230             : 
     231       97482 : bool LayoutDescriptorHelper::IsTagged(int offset_in_bytes) {
     232             :   DCHECK(IsAligned(offset_in_bytes, kPointerSize));
     233       97482 :   if (all_fields_tagged_) return true;
     234             :   // Object headers do not contain non-tagged fields.
     235       50640 :   if (offset_in_bytes < header_size_) return true;
     236       50496 :   int field_index = (offset_in_bytes - header_size_) / kPointerSize;
     237             : 
     238      100992 :   return layout_descriptor_->IsTagged(field_index);
     239             : }
     240             : }  // namespace internal
     241             : }  // namespace v8
     242             : 
     243             : #endif  // V8_LAYOUT_DESCRIPTOR_INL_H_

Generated by: LCOV version 1.10