LCOV - code coverage report
Current view: top level - src - constant-pool.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1 1 100.0 %
Date: 2019-04-18 Functions: 1 1 100.0 %

          Line data    Source code
       1             : // Copyright 2018 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/constant-pool.h"
       6             : #include "src/assembler-inl.h"
       7             : 
       8             : namespace v8 {
       9             : namespace internal {
      10             : 
      11             : #if defined(V8_TARGET_ARCH_PPC)
      12             : 
      13             : ConstantPoolBuilder::ConstantPoolBuilder(int ptr_reach_bits,
      14             :                                          int double_reach_bits) {
      15             :   info_[ConstantPoolEntry::INTPTR].entries.reserve(64);
      16             :   info_[ConstantPoolEntry::INTPTR].regular_reach_bits = ptr_reach_bits;
      17             :   info_[ConstantPoolEntry::DOUBLE].regular_reach_bits = double_reach_bits;
      18             : }
      19             : 
      20             : ConstantPoolEntry::Access ConstantPoolBuilder::NextAccess(
      21             :     ConstantPoolEntry::Type type) const {
      22             :   const PerTypeEntryInfo& info = info_[type];
      23             : 
      24             :   if (info.overflow()) return ConstantPoolEntry::OVERFLOWED;
      25             : 
      26             :   int dbl_count = info_[ConstantPoolEntry::DOUBLE].regular_count;
      27             :   int dbl_offset = dbl_count * kDoubleSize;
      28             :   int ptr_count = info_[ConstantPoolEntry::INTPTR].regular_count;
      29             :   int ptr_offset = ptr_count * kSystemPointerSize + dbl_offset;
      30             : 
      31             :   if (type == ConstantPoolEntry::DOUBLE) {
      32             :     // Double overflow detection must take into account the reach for both types
      33             :     int ptr_reach_bits = info_[ConstantPoolEntry::INTPTR].regular_reach_bits;
      34             :     if (!is_uintn(dbl_offset, info.regular_reach_bits) ||
      35             :         (ptr_count > 0 &&
      36             :          !is_uintn(ptr_offset + kDoubleSize - kSystemPointerSize,
      37             :                    ptr_reach_bits))) {
      38             :       return ConstantPoolEntry::OVERFLOWED;
      39             :     }
      40             :   } else {
      41             :     DCHECK(type == ConstantPoolEntry::INTPTR);
      42             :     if (!is_uintn(ptr_offset, info.regular_reach_bits)) {
      43             :       return ConstantPoolEntry::OVERFLOWED;
      44             :     }
      45             :   }
      46             : 
      47             :   return ConstantPoolEntry::REGULAR;
      48             : }
      49             : 
      50             : ConstantPoolEntry::Access ConstantPoolBuilder::AddEntry(
      51             :     ConstantPoolEntry& entry, ConstantPoolEntry::Type type) {
      52             :   DCHECK(!emitted_label_.is_bound());
      53             :   PerTypeEntryInfo& info = info_[type];
      54             :   const int entry_size = ConstantPoolEntry::size(type);
      55             :   bool merged = false;
      56             : 
      57             :   if (entry.sharing_ok()) {
      58             :     // Try to merge entries
      59             :     std::vector<ConstantPoolEntry>::iterator it = info.shared_entries.begin();
      60             :     int end = static_cast<int>(info.shared_entries.size());
      61             :     for (int i = 0; i < end; i++, it++) {
      62             :       if ((entry_size == kSystemPointerSize)
      63             :               ? entry.value() == it->value()
      64             :               : entry.value64() == it->value64()) {
      65             :         // Merge with found entry.
      66             :         entry.set_merged_index(i);
      67             :         merged = true;
      68             :         break;
      69             :       }
      70             :     }
      71             :   }
      72             : 
      73             :   // By definition, merged entries have regular access.
      74             :   DCHECK(!merged || entry.merged_index() < info.regular_count);
      75             :   ConstantPoolEntry::Access access =
      76             :       (merged ? ConstantPoolEntry::REGULAR : NextAccess(type));
      77             : 
      78             :   // Enforce an upper bound on search time by limiting the search to
      79             :   // unique sharable entries which fit in the regular section.
      80             :   if (entry.sharing_ok() && !merged && access == ConstantPoolEntry::REGULAR) {
      81             :     info.shared_entries.push_back(entry);
      82             :   } else {
      83             :     info.entries.push_back(entry);
      84             :   }
      85             : 
      86             :   // We're done if we found a match or have already triggered the
      87             :   // overflow state.
      88             :   if (merged || info.overflow()) return access;
      89             : 
      90             :   if (access == ConstantPoolEntry::REGULAR) {
      91             :     info.regular_count++;
      92             :   } else {
      93             :     info.overflow_start = static_cast<int>(info.entries.size()) - 1;
      94             :   }
      95             : 
      96             :   return access;
      97             : }
      98             : 
      99             : void ConstantPoolBuilder::EmitSharedEntries(Assembler* assm,
     100             :                                             ConstantPoolEntry::Type type) {
     101             :   PerTypeEntryInfo& info = info_[type];
     102             :   std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
     103             :   const int entry_size = ConstantPoolEntry::size(type);
     104             :   int base = emitted_label_.pos();
     105             :   DCHECK_GT(base, 0);
     106             :   int shared_end = static_cast<int>(shared_entries.size());
     107             :   std::vector<ConstantPoolEntry>::iterator shared_it = shared_entries.begin();
     108             :   for (int i = 0; i < shared_end; i++, shared_it++) {
     109             :     int offset = assm->pc_offset() - base;
     110             :     shared_it->set_offset(offset);  // Save offset for merged entries.
     111             :     if (entry_size == kSystemPointerSize) {
     112             :       assm->dp(shared_it->value());
     113             :     } else {
     114             :       assm->dq(shared_it->value64());
     115             :     }
     116             :     DCHECK(is_uintn(offset, info.regular_reach_bits));
     117             : 
     118             :     // Patch load sequence with correct offset.
     119             :     assm->PatchConstantPoolAccessInstruction(shared_it->position(), offset,
     120             :                                              ConstantPoolEntry::REGULAR, type);
     121             :   }
     122             : }
     123             : 
     124             : void ConstantPoolBuilder::EmitGroup(Assembler* assm,
     125             :                                     ConstantPoolEntry::Access access,
     126             :                                     ConstantPoolEntry::Type type) {
     127             :   PerTypeEntryInfo& info = info_[type];
     128             :   const bool overflow = info.overflow();
     129             :   std::vector<ConstantPoolEntry>& entries = info.entries;
     130             :   std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
     131             :   const int entry_size = ConstantPoolEntry::size(type);
     132             :   int base = emitted_label_.pos();
     133             :   DCHECK_GT(base, 0);
     134             :   int begin;
     135             :   int end;
     136             : 
     137             :   if (access == ConstantPoolEntry::REGULAR) {
     138             :     // Emit any shared entries first
     139             :     EmitSharedEntries(assm, type);
     140             :   }
     141             : 
     142             :   if (access == ConstantPoolEntry::REGULAR) {
     143             :     begin = 0;
     144             :     end = overflow ? info.overflow_start : static_cast<int>(entries.size());
     145             :   } else {
     146             :     DCHECK(access == ConstantPoolEntry::OVERFLOWED);
     147             :     if (!overflow) return;
     148             :     begin = info.overflow_start;
     149             :     end = static_cast<int>(entries.size());
     150             :   }
     151             : 
     152             :   std::vector<ConstantPoolEntry>::iterator it = entries.begin();
     153             :   if (begin > 0) std::advance(it, begin);
     154             :   for (int i = begin; i < end; i++, it++) {
     155             :     // Update constant pool if necessary and get the entry's offset.
     156             :     int offset;
     157             :     ConstantPoolEntry::Access entry_access;
     158             :     if (!it->is_merged()) {
     159             :       // Emit new entry
     160             :       offset = assm->pc_offset() - base;
     161             :       entry_access = access;
     162             :       if (entry_size == kSystemPointerSize) {
     163             :         assm->dp(it->value());
     164             :       } else {
     165             :         assm->dq(it->value64());
     166             :       }
     167             :     } else {
     168             :       // Retrieve offset from shared entry.
     169             :       offset = shared_entries[it->merged_index()].offset();
     170             :       entry_access = ConstantPoolEntry::REGULAR;
     171             :     }
     172             : 
     173             :     DCHECK(entry_access == ConstantPoolEntry::OVERFLOWED ||
     174             :            is_uintn(offset, info.regular_reach_bits));
     175             : 
     176             :     // Patch load sequence with correct offset.
     177             :     assm->PatchConstantPoolAccessInstruction(it->position(), offset,
     178             :                                              entry_access, type);
     179             :   }
     180             : }
     181             : 
     182             : // Emit and return size of pool.
     183             : int ConstantPoolBuilder::Emit(Assembler* assm) {
     184             :   bool emitted = emitted_label_.is_bound();
     185             :   bool empty = IsEmpty();
     186             : 
     187             :   if (!emitted) {
     188             :     // Mark start of constant pool.  Align if necessary.
     189             :     if (!empty) assm->DataAlign(kDoubleSize);
     190             :     assm->bind(&emitted_label_);
     191             :     if (!empty) {
     192             :       // Emit in groups based on access and type.
     193             :       // Emit doubles first for alignment purposes.
     194             :       EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::DOUBLE);
     195             :       EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::INTPTR);
     196             :       if (info_[ConstantPoolEntry::DOUBLE].overflow()) {
     197             :         assm->DataAlign(kDoubleSize);
     198             :         EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
     199             :                   ConstantPoolEntry::DOUBLE);
     200             :       }
     201             :       if (info_[ConstantPoolEntry::INTPTR].overflow()) {
     202             :         EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
     203             :                   ConstantPoolEntry::INTPTR);
     204             :       }
     205             :     }
     206             :   }
     207             : 
     208             :   return !empty ? (assm->pc_offset() - emitted_label_.pos()) : 0;
     209             : }
     210             : 
     211             : #endif  // defined(V8_TARGET_ARCH_PPC)
     212             : 
     213             : }  // namespace internal
     214      122036 : }  // namespace v8

Generated by: LCOV version 1.10