LCOV - code coverage report
Current view: top level - src - assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 62 86 72.1 %
Date: 2019-04-18 Functions: 20 28 71.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/heap/heap-inl.h"  // For MemoryAllocator. TODO(jkummerow): Drop.
      41             : #include "src/isolate.h"
      42             : #include "src/ostreams.h"
      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     1785139 : AssemblerOptions AssemblerOptions::Default(
      66             :     Isolate* isolate, bool explicitly_support_serialization) {
      67     1785139 :   AssemblerOptions options;
      68             :   const bool serializer =
      69     1785139 :       isolate->serializer_enabled() || explicitly_support_serialization;
      70             :   const bool generating_embedded_builtin =
      71             :       isolate->IsGeneratingEmbeddedBuiltins();
      72     1785139 :   options.record_reloc_info_for_serialization = serializer;
      73             :   options.enable_root_array_delta_access =
      74     1785139 :       !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     1785139 :       FLAG_embedded_builtins && !serializer && !generating_embedded_builtin;
      82             : #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
      83             :   const base::AddressRegion& code_range =
      84             :       isolate->heap()->memory_allocator()->code_range();
      85             :   DCHECK_IMPLIES(code_range.begin() != kNullAddress, !code_range.is_empty());
      86     1785139 :   options.code_range_start = code_range.begin();
      87             : #endif
      88     1785139 :   return options;
      89             : }
      90             : 
      91             : namespace {
      92             : 
      93     3632890 : class DefaultAssemblerBuffer : public AssemblerBuffer {
      94             :  public:
      95             :   explicit DefaultAssemblerBuffer(int size)
      96     1816445 :       : buffer_(OwnedVector<uint8_t>::New(size)) {
      97             : #ifdef DEBUG
      98             :     ZapCode(reinterpret_cast<Address>(buffer_.start()), size);
      99             : #endif
     100             :   }
     101             : 
     102    10496910 :   byte* start() const override { return buffer_.start(); }
     103             : 
     104     3532454 :   int size() const override { return static_cast<int>(buffer_.size()); }
     105             : 
     106       42941 :   std::unique_ptr<AssemblerBuffer> Grow(int new_size) override {
     107             :     DCHECK_LT(size(), new_size);
     108       85882 :     return base::make_unique<DefaultAssemblerBuffer>(new_size);
     109             :   }
     110             : 
     111             :  private:
     112             :   OwnedVector<uint8_t> buffer_;
     113             : };
     114             : 
     115    76189018 : class ExternalAssemblerBufferImpl : public AssemblerBuffer {
     116             :  public:
     117             :   ExternalAssemblerBufferImpl(byte* start, int size)
     118    38095100 :       : start_(start), size_(size) {}
     119             : 
     120    38476553 :   byte* start() const override { return start_; }
     121             : 
     122    38286367 :   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    38093940 : std::unique_ptr<AssemblerBuffer> ExternalAssemblerBuffer(void* start,
     136             :                                                          int size) {
     137             :   return base::make_unique<ExternalAssemblerBufferImpl>(
     138    38095100 :       reinterpret_cast<byte*>(start), size);
     139             : }
     140             : 
     141      126947 : std::unique_ptr<AssemblerBuffer> NewAssemblerBuffer(int size) {
     142     3546992 :   return base::make_unique<DefaultAssemblerBuffer>(size);
     143             : }
     144             : 
     145             : // -----------------------------------------------------------------------------
     146             : // Implementation of AssemblerBase
     147             : 
     148    41305830 : 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    82611660 :       jump_optimization_info_(nullptr) {
     157    41305830 :   if (!buffer_) buffer_ = NewAssemblerBuffer(kMinimalBufferSize);
     158    41305846 :   buffer_start_ = buffer_->start();
     159    41305775 :   pc_ = buffer_start_;
     160    41305775 : }
     161             : 
     162             : AssemblerBase::~AssemblerBase() = default;
     163             : 
     164           0 : void AssemblerBase::Print(Isolate* isolate) {
     165           0 :   StdoutStream os;
     166           0 :   v8::internal::Disassembler::Decode(isolate, &os, buffer_start_, pc_);
     167           0 : }
     168             : 
     169             : // -----------------------------------------------------------------------------
     170             : // Implementation of PredictableCodeSizeScope
     171             : 
     172           0 : PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler,
     173             :                                                    int expected_size)
     174             :     : assembler_(assembler),
     175             :       expected_size_(expected_size),
     176             :       start_offset_(assembler->pc_offset()),
     177           0 :       old_value_(assembler->predictable_code_size()) {
     178             :   assembler_->set_predictable_code_size(true);
     179           0 : }
     180             : 
     181           0 : PredictableCodeSizeScope::~PredictableCodeSizeScope() {
     182           0 :   CHECK_EQ(expected_size_, assembler_->pc_offset() - start_offset_);
     183           0 :   assembler_->set_predictable_code_size(old_value_);
     184           0 : }
     185             : 
     186             : // -----------------------------------------------------------------------------
     187             : // Implementation of CpuFeatureScope
     188             : 
     189             : #ifdef DEBUG
     190             : CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
     191             :                                  CheckPolicy check)
     192             :     : assembler_(assembler) {
     193             :   DCHECK_IMPLIES(check == kCheckSupported, CpuFeatures::IsSupported(f));
     194             :   old_enabled_ = assembler_->enabled_cpu_features();
     195             :   assembler_->EnableCpuFeature(f);
     196             : }
     197             : 
     198             : CpuFeatureScope::~CpuFeatureScope() {
     199             :   assembler_->set_enabled_cpu_features(old_enabled_);
     200             : }
     201             : #endif
     202             : 
     203             : bool CpuFeatures::initialized_ = false;
     204             : unsigned CpuFeatures::supported_ = 0;
     205             : unsigned CpuFeatures::icache_line_size_ = 0;
     206             : unsigned CpuFeatures::dcache_line_size_ = 0;
     207             : 
     208       39591 : HeapObjectRequest::HeapObjectRequest(double heap_number, int offset)
     209       39591 :     : kind_(kHeapNumber), offset_(offset) {
     210       39591 :   value_.heap_number = heap_number;
     211             :   DCHECK(!IsSmiDouble(value_.heap_number));
     212       39591 : }
     213             : 
     214        2120 : HeapObjectRequest::HeapObjectRequest(const StringConstantBase* string,
     215             :                                      int offset)
     216        2120 :     : kind_(kStringConstant), offset_(offset) {
     217        2120 :   value_.string = string;
     218             :   DCHECK_NOT_NULL(value_.string);
     219        2120 : }
     220             : 
     221             : // Platform specific but identical code for all the platforms.
     222             : 
     223      101964 : void Assembler::RecordDeoptReason(DeoptimizeReason reason,
     224             :                                   SourcePosition position, int id) {
     225             :   EnsureSpace ensure_space(this);
     226      101964 :   RecordRelocInfo(RelocInfo::DEOPT_SCRIPT_OFFSET, position.ScriptOffset());
     227      101964 :   RecordRelocInfo(RelocInfo::DEOPT_INLINING_ID, position.InliningId());
     228      101964 :   RecordRelocInfo(RelocInfo::DEOPT_REASON, static_cast<int>(reason));
     229      101964 :   RecordRelocInfo(RelocInfo::DEOPT_ID, id);
     230      101964 : }
     231             : 
     232       20512 : void Assembler::DataAlign(int m) {
     233             :   DCHECK(m >= 2 && base::bits::IsPowerOfTwo(m));
     234       81142 :   while ((pc_offset() & (m - 1)) != 0) {
     235             :     // Pad with 0xcc (= int3 on ia32 and x64); the primary motivation is that
     236             :     // the disassembler expects to find valid instructions, but this is also
     237             :     // nice from a security point of view.
     238       30313 :     db(0xcc);
     239             :   }
     240       20514 : }
     241             : 
     242       41711 : void AssemblerBase::RequestHeapObject(HeapObjectRequest request) {
     243             :   DCHECK(!options().v8_agnostic_code);
     244             :   request.set_offset(pc_offset());
     245             :   heap_object_requests_.push_front(request);
     246       41711 : }
     247             : 
     248      898902 : int AssemblerBase::AddCodeTarget(Handle<Code> target) {
     249             :   DCHECK(!options().v8_agnostic_code);
     250      898902 :   int current = static_cast<int>(code_targets_.size());
     251     1636544 :   if (current > 0 && !target.is_null() &&
     252             :       code_targets_.back().address() == target.address()) {
     253             :     // Optimization if we keep jumping to the same code target.
     254      363046 :     return current - 1;
     255             :   } else {
     256      535856 :     code_targets_.push_back(target);
     257      535858 :     return current;
     258             :   }
     259             : }
     260             : 
     261      528407 : Handle<Code> AssemblerBase::GetCodeTarget(intptr_t code_target_index) const {
     262             :   DCHECK(!options().v8_agnostic_code);
     263             :   DCHECK_LE(0, code_target_index);
     264             :   DCHECK_LT(code_target_index, code_targets_.size());
     265     1056814 :   return code_targets_[code_target_index];
     266             : }
     267             : 
     268           0 : void AssemblerBase::UpdateCodeTarget(intptr_t code_target_index,
     269             :                                      Handle<Code> code) {
     270             :   DCHECK(!options().v8_agnostic_code);
     271             :   DCHECK_LE(0, code_target_index);
     272             :   DCHECK_LT(code_target_index, code_targets_.size());
     273           0 :   code_targets_[code_target_index] = code;
     274           0 : }
     275             : 
     276     3333268 : int Assembler::WriteCodeComments() {
     277     3333268 :   if (!FLAG_code_comments || code_comments_writer_.entry_count() == 0) return 0;
     278             :   int offset = pc_offset();
     279          83 :   code_comments_writer_.Emit(this);
     280          83 :   int size = pc_offset() - offset;
     281             :   DCHECK_EQ(size, code_comments_writer_.section_size());
     282          83 :   return size;
     283             : }
     284             : 
     285             : }  // namespace internal
     286      122036 : }  // namespace v8

Generated by: LCOV version 1.10