LCOV - code coverage report
Current view: top level - src - assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 72 96 75.0 %
Date: 2019-01-20 Functions: 24 31 77.4 %

          Line data    Source code
       1             : // Copyright (c) 1994-2006 Sun Microsystems Inc.
       2             : // All Rights Reserved.
       3             : //
       4             : // Redistribution and use in source and binary forms, with or without
       5             : // modification, are permitted provided that the following conditions are
       6             : // met:
       7             : //
       8             : // - Redistributions of source code must retain the above copyright notice,
       9             : // this list of conditions and the following disclaimer.
      10             : //
      11             : // - Redistribution in binary form must reproduce the above copyright
      12             : // notice, this list of conditions and the following disclaimer in the
      13             : // documentation and/or other materials provided with the distribution.
      14             : //
      15             : // - Neither the name of Sun Microsystems or the names of contributors may
      16             : // be used to endorse or promote products derived from this software without
      17             : // specific prior written permission.
      18             : //
      19             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
      20             : // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
      21             : // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      22             : // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      23             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      24             : // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      25             : // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
      26             : // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
      27             : // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      28             : // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      29             : // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30             : 
      31             : // The original source code covered by the above license above has been
      32             : // modified significantly by Google Inc.
      33             : // Copyright 2012 the V8 project authors. All rights reserved.
      34             : 
      35             : #include "src/assembler.h"
      36             : 
      37             : #include "src/assembler-inl.h"
      38             : #include "src/deoptimizer.h"
      39             : #include "src/disassembler.h"
      40             : #include "src/isolate.h"
      41             : #include "src/ostreams.h"
      42             : #include "src/simulator.h"  // For flushing instruction cache.
      43             : #include "src/snapshot/embedded-data.h"
      44             : #include "src/snapshot/serializer-common.h"
      45             : #include "src/snapshot/snapshot.h"
      46             : #include "src/string-constants.h"
      47             : #include "src/vector.h"
      48             : 
      49             : namespace v8 {
      50             : namespace internal {
      51             : 
      52           0 : AssemblerOptions AssemblerOptions::EnableV8AgnosticCode() const {
      53           0 :   AssemblerOptions options = *this;
      54           0 :   options.v8_agnostic_code = true;
      55           0 :   options.record_reloc_info_for_serialization = false;
      56           0 :   options.enable_root_array_delta_access = false;
      57             :   // Inherit |enable_simulator_code| value.
      58           0 :   options.isolate_independent_code = false;
      59           0 :   options.inline_offheap_trampolines = false;
      60             :   // Inherit |code_range_start| value.
      61             :   // Inherit |use_pc_relative_calls_and_jumps| value.
      62           0 :   return options;
      63             : }
      64             : 
      65     2006392 : AssemblerOptions AssemblerOptions::Default(
      66     2006392 :     Isolate* isolate, bool explicitly_support_serialization) {
      67     2006392 :   AssemblerOptions options;
      68             :   const bool serializer =
      69     2006392 :       isolate->serializer_enabled() || explicitly_support_serialization;
      70             :   const bool generating_embedded_builtin =
      71             :       isolate->ShouldLoadConstantsFromRootList();
      72     2006392 :   options.record_reloc_info_for_serialization = serializer;
      73             :   options.enable_root_array_delta_access =
      74     2006392 :       !serializer && !generating_embedded_builtin;
      75             : #ifdef USE_SIMULATOR
      76             :   // Don't generate simulator specific code if we are building a snapshot, which
      77             :   // might be run on real hardware.
      78             :   options.enable_simulator_code = !serializer;
      79             : #endif
      80             :   options.inline_offheap_trampolines =
      81     2006392 :       FLAG_embedded_builtins && !serializer && !generating_embedded_builtin;
      82             : #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
      83     2006392 :   const base::AddressRegion& code_range =
      84     2006392 :       isolate->heap()->memory_allocator()->code_range();
      85             :   DCHECK_IMPLIES(code_range.begin() != kNullAddress, !code_range.is_empty());
      86     2006392 :   options.code_range_start = code_range.begin();
      87             : #endif
      88     2006392 :   return options;
      89             : }
      90             : 
      91             : namespace {
      92             : 
      93    11497745 : class DefaultAssemblerBuffer : public AssemblerBuffer {
      94             :  public:
      95             :   explicit DefaultAssemblerBuffer(int size)
      96     3832603 :       : buffer_(OwnedVector<uint8_t>::New(size)) {
      97             : #ifdef DEBUG
      98             :     ZapCode(reinterpret_cast<Address>(buffer_.start()), size);
      99             : #endif
     100             :   }
     101             : 
     102     7664914 :   byte* start() const override { return buffer_.start(); }
     103             : 
     104     7599359 :   int size() const override { return static_cast<int>(buffer_.size()); }
     105             : 
     106       40398 :   std::unique_ptr<AssemblerBuffer> Grow(int new_size) override {
     107             :     DCHECK_LT(size(), new_size);
     108       80796 :     return base::make_unique<DefaultAssemblerBuffer>(new_size);
     109             :   }
     110             : 
     111             :  private:
     112             :   OwnedVector<uint8_t> buffer_;
     113             : };
     114             : 
     115     5372478 : class ExternalAssemblerBufferImpl : public AssemblerBuffer {
     116             :  public:
     117             :   ExternalAssemblerBufferImpl(byte* start, int size)
     118     2686405 :       : start_(start), size_(size) {}
     119             : 
     120     2685866 :   byte* start() const override { return start_; }
     121             : 
     122     2876975 :   int size() const override { return size_; }
     123             : 
     124           0 :   std::unique_ptr<AssemblerBuffer> Grow(int new_size) override {
     125           0 :     FATAL("Cannot grow external assembler buffer");
     126             :   }
     127             : 
     128             :  private:
     129             :   byte* const start_;
     130             :   const int size_;
     131             : };
     132             : 
     133             : }  // namespace
     134             : 
     135     2685906 : std::unique_ptr<AssemblerBuffer> ExternalAssemblerBuffer(void* start,
     136             :                                                          int size) {
     137             :   return base::make_unique<ExternalAssemblerBufferImpl>(
     138     2686405 :       reinterpret_cast<byte*>(start), size);
     139             : }
     140             : 
     141      130462 : std::unique_ptr<AssemblerBuffer> NewAssemblerBuffer(int size) {
     142     7453409 :   return base::make_unique<DefaultAssemblerBuffer>(size);
     143             : }
     144             : 
     145             : // -----------------------------------------------------------------------------
     146             : // Implementation of AssemblerBase
     147             : 
     148     6477391 : AssemblerBase::AssemblerBase(const AssemblerOptions& options,
     149             :                              std::unique_ptr<AssemblerBuffer> buffer)
     150             :     : buffer_(std::move(buffer)),
     151             :       options_(options),
     152             :       enabled_cpu_features_(0),
     153             :       emit_debug_code_(FLAG_debug_code),
     154             :       predictable_code_size_(false),
     155             :       constant_pool_available_(false),
     156    12954782 :       jump_optimization_info_(nullptr) {
     157     6477391 :   if (!buffer_) buffer_ = NewAssemblerBuffer(kMinimalBufferSize);
     158     6477914 :   buffer_start_ = buffer_->start();
     159     6477661 :   pc_ = buffer_start_;
     160     6477661 : }
     161             : 
     162             : AssemblerBase::~AssemblerBase() = default;
     163             : 
     164    51684829 : void AssemblerBase::FlushICache(void* start, size_t size) {
     165   103369355 :   if (size == 0) return;
     166             : 
     167             : #if defined(USE_SIMULATOR)
     168             :   base::MutexGuard lock_guard(Simulator::i_cache_mutex());
     169             :   Simulator::FlushICache(Simulator::i_cache(), start, size);
     170             : #else
     171    51684945 :   CpuFeatures::FlushICache(start, size);
     172             : #endif  // USE_SIMULATOR
     173             : }
     174             : 
     175           0 : void AssemblerBase::Print(Isolate* isolate) {
     176           0 :   StdoutStream os;
     177           0 :   v8::internal::Disassembler::Decode(isolate, &os, buffer_start_, pc_);
     178           0 : }
     179             : 
     180             : // -----------------------------------------------------------------------------
     181             : // Implementation of PredictableCodeSizeScope
     182             : 
     183           0 : PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler,
     184             :                                                    int expected_size)
     185             :     : assembler_(assembler),
     186             :       expected_size_(expected_size),
     187             :       start_offset_(assembler->pc_offset()),
     188           0 :       old_value_(assembler->predictable_code_size()) {
     189             :   assembler_->set_predictable_code_size(true);
     190           0 : }
     191             : 
     192           0 : PredictableCodeSizeScope::~PredictableCodeSizeScope() {
     193           0 :   CHECK_EQ(expected_size_, assembler_->pc_offset() - start_offset_);
     194           0 :   assembler_->set_predictable_code_size(old_value_);
     195           0 : }
     196             : 
     197             : // -----------------------------------------------------------------------------
     198             : // Implementation of CpuFeatureScope
     199             : 
     200             : #ifdef DEBUG
     201             : CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
     202             :                                  CheckPolicy check)
     203             :     : assembler_(assembler) {
     204             :   DCHECK_IMPLIES(check == kCheckSupported, CpuFeatures::IsSupported(f));
     205             :   old_enabled_ = assembler_->enabled_cpu_features();
     206             :   assembler_->EnableCpuFeature(f);
     207             : }
     208             : 
     209             : CpuFeatureScope::~CpuFeatureScope() {
     210             :   assembler_->set_enabled_cpu_features(old_enabled_);
     211             : }
     212             : #endif
     213             : 
     214             : bool CpuFeatures::initialized_ = false;
     215             : unsigned CpuFeatures::supported_ = 0;
     216             : unsigned CpuFeatures::icache_line_size_ = 0;
     217             : unsigned CpuFeatures::dcache_line_size_ = 0;
     218             : 
     219       44208 : HeapObjectRequest::HeapObjectRequest(double heap_number, int offset)
     220       44208 :     : kind_(kHeapNumber), offset_(offset) {
     221       44208 :   value_.heap_number = heap_number;
     222             :   DCHECK(!IsSmiDouble(value_.heap_number));
     223       44208 : }
     224             : 
     225        2227 : HeapObjectRequest::HeapObjectRequest(const StringConstantBase* string,
     226             :                                      int offset)
     227        2227 :     : kind_(kStringConstant), offset_(offset) {
     228        2227 :   value_.string = string;
     229             :   DCHECK_NOT_NULL(value_.string);
     230        2227 : }
     231             : 
     232             : // Platform specific but identical code for all the platforms.
     233             : 
     234       88312 : void Assembler::RecordDeoptReason(DeoptimizeReason reason,
     235             :                                   SourcePosition position, int id) {
     236             :   EnsureSpace ensure_space(this);
     237       88312 :   RecordRelocInfo(RelocInfo::DEOPT_SCRIPT_OFFSET, position.ScriptOffset());
     238       88312 :   RecordRelocInfo(RelocInfo::DEOPT_INLINING_ID, position.InliningId());
     239       88312 :   RecordRelocInfo(RelocInfo::DEOPT_REASON, static_cast<int>(reason));
     240       88312 :   RecordRelocInfo(RelocInfo::DEOPT_ID, id);
     241       88312 : }
     242             : 
     243       19881 : void Assembler::DataAlign(int m) {
     244             :   DCHECK(m >= 2 && base::bits::IsPowerOfTwo(m));
     245       83857 :   while ((pc_offset() & (m - 1)) != 0) {
     246             :     // Pad with 0xcc (= int3 on ia32 and x64); the primary motivation is that
     247             :     // the disassembler expects to find valid instructions, but this is also
     248             :     // nice from a security point of view.
     249       12107 :     db(0xcc);
     250             :   }
     251       19881 : }
     252             : 
     253       46435 : void AssemblerBase::RequestHeapObject(HeapObjectRequest request) {
     254             :   DCHECK(!options().v8_agnostic_code);
     255             :   request.set_offset(pc_offset());
     256             :   heap_object_requests_.push_front(request);
     257       46435 : }
     258             : 
     259      954270 : int AssemblerBase::AddCodeTarget(Handle<Code> target) {
     260             :   DCHECK(!options().v8_agnostic_code);
     261     1908540 :   int current = static_cast<int>(code_targets_.size());
     262     2530319 :   if (current > 0 && !target.is_null() &&
     263             :       code_targets_.back().address() == target.address()) {
     264             :     // Optimization if we keep jumping to the same code target.
     265      392109 :     return current - 1;
     266             :   } else {
     267      562161 :     code_targets_.push_back(target);
     268      562164 :     return current;
     269             :   }
     270             : }
     271             : 
     272      954276 : Handle<Code> AssemblerBase::GetCodeTarget(intptr_t code_target_index) const {
     273             :   DCHECK(!options().v8_agnostic_code);
     274             :   DCHECK_LE(0, code_target_index);
     275             :   DCHECK_LT(code_target_index, code_targets_.size());
     276     1908552 :   return code_targets_[code_target_index];
     277             : }
     278             : 
     279           0 : void AssemblerBase::UpdateCodeTarget(intptr_t code_target_index,
     280             :                                      Handle<Code> code) {
     281             :   DCHECK(!options().v8_agnostic_code);
     282             :   DCHECK_LE(0, code_target_index);
     283             :   DCHECK_LT(code_target_index, code_targets_.size());
     284           0 :   code_targets_[code_target_index] = code;
     285           0 : }
     286             : 
     287     6478115 : void AssemblerBase::ReserveCodeTargetSpace(size_t num_of_code_targets) {
     288     6478115 :   code_targets_.reserve(num_of_code_targets);
     289     6478394 : }
     290             : 
     291     3957602 : int Assembler::WriteCodeComments() {
     292     3957602 :   if (!FLAG_code_comments || code_comments_writer_.entry_count() == 0) return 0;
     293         160 :   int offset = pc_offset();
     294          80 :   code_comments_writer_.Emit(this);
     295          80 :   int size = pc_offset() - offset;
     296             :   DCHECK_EQ(size, code_comments_writer_.section_size());
     297          80 :   return size;
     298             : }
     299             : 
     300             : }  // namespace internal
     301      183867 : }  // namespace v8

Generated by: LCOV version 1.10