assembler.cc 8.75 KB
Newer Older
1
// Copyright (c) 1994-2006 Sun Microsystems Inc.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// - Redistribution in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// - Neither the name of Sun Microsystems or the names of contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The original source code covered by the above license above has been
// 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/code-stubs.h"
39
#include "src/deoptimizer.h"
40
#include "src/disassembler.h"
41
#include "src/instruction-stream.h"
42
#include "src/isolate.h"
43
#include "src/ostreams.h"
44
#include "src/simulator.h"  // For flushing instruction cache.
45
#include "src/snapshot/serializer-common.h"
46
#include "src/snapshot/snapshot.h"
47
#include "src/string-constants.h"
48

49 50
namespace v8 {
namespace internal {
51

52 53 54 55 56 57 58 59 60 61 62 63 64
AssemblerOptions AssemblerOptions::EnableV8AgnosticCode() const {
  AssemblerOptions options = *this;
  options.v8_agnostic_code = true;
  options.record_reloc_info_for_serialization = false;
  options.enable_root_array_delta_access = false;
  // Inherit |enable_simulator_code| value.
  options.isolate_independent_code = false;
  options.inline_offheap_trampolines = false;
  // Inherit |code_range_start| value.
  // Inherit |use_pc_relative_calls_and_jumps| value.
  return options;
}

65
AssemblerOptions AssemblerOptions::Default(
66
    Isolate* isolate, bool explicitly_support_serialization) {
67
  AssemblerOptions options;
68 69
  bool serializer =
      isolate->serializer_enabled() || explicitly_support_serialization;
70
  options.record_reloc_info_for_serialization = serializer;
71 72 73 74 75 76 77
  options.enable_root_array_delta_access = !serializer;
#ifdef USE_SIMULATOR
  // Don't generate simulator specific code if we are building a snapshot, which
  // might be run on real hardware.
  options.enable_simulator_code = !serializer;
#endif
  options.inline_offheap_trampolines = !serializer;
78

79
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
80 81 82 83
  const base::AddressRegion& code_range =
      isolate->heap()->memory_allocator()->code_range();
  DCHECK_IMPLIES(code_range.begin() != kNullAddress, !code_range.is_empty());
  options.code_range_start = code_range.begin();
84
#endif
85 86
  return options;
}
87

88 89 90 91
// -----------------------------------------------------------------------------
// Implementation of AssemblerBase

AssemblerBase::AssemblerBase(const AssemblerOptions& options, void* buffer,
92
                             int buffer_size)
93
    : options_(options),
94
      enabled_cpu_features_(0),
95
      emit_debug_code_(FLAG_debug_code),
96
      predictable_code_size_(false),
97 98
      constant_pool_available_(false),
      jump_optimization_info_(nullptr) {
99
  own_buffer_ = buffer == nullptr;
100
  if (buffer_size == 0) buffer_size = kMinimalBufferSize;
101
  DCHECK_GT(buffer_size, 0);
102
  if (own_buffer_) buffer = NewArray<byte>(buffer_size);
103 104 105 106 107 108
  buffer_ = static_cast<byte*>(buffer);
  buffer_size_ = buffer_size;
  pc_ = buffer_;
}

AssemblerBase::~AssemblerBase() {
109
  if (own_buffer_) DeleteArray(buffer_);
110 111
}

112
void AssemblerBase::FlushICache(void* start, size_t size) {
113 114 115
  if (size == 0) return;

#if defined(USE_SIMULATOR)
116
  base::MutexGuard lock_guard(Simulator::i_cache_mutex());
117
  Simulator::FlushICache(Simulator::i_cache(), start, size);
118 119 120 121 122
#else
  CpuFeatures::FlushICache(start, size);
#endif  // USE_SIMULATOR
}

123
void AssemblerBase::Print(Isolate* isolate) {
124
  StdoutStream os;
125
  v8::internal::Disassembler::Decode(isolate, &os, buffer_, pc_);
126 127
}

128 129 130 131 132 133 134 135 136 137 138 139 140
// -----------------------------------------------------------------------------
// Implementation of PredictableCodeSizeScope

PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler,
                                                   int expected_size)
    : assembler_(assembler),
      expected_size_(expected_size),
      start_offset_(assembler->pc_offset()),
      old_value_(assembler->predictable_code_size()) {
  assembler_->set_predictable_code_size(true);
}

PredictableCodeSizeScope::~PredictableCodeSizeScope() {
141
  CHECK_EQ(expected_size_, assembler_->pc_offset() - start_offset_);
142 143 144
  assembler_->set_predictable_code_size(old_value_);
}

145 146 147 148
// -----------------------------------------------------------------------------
// Implementation of CpuFeatureScope

#ifdef DEBUG
149 150
CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
                                 CheckPolicy check)
151
    : assembler_(assembler) {
152
  DCHECK_IMPLIES(check == kCheckSupported, CpuFeatures::IsSupported(f));
153
  old_enabled_ = assembler_->enabled_cpu_features();
154
  assembler_->EnableCpuFeature(f);
155 156 157 158 159 160 161
}

CpuFeatureScope::~CpuFeatureScope() {
  assembler_->set_enabled_cpu_features(old_enabled_);
}
#endif

162 163
bool CpuFeatures::initialized_ = false;
unsigned CpuFeatures::supported_ = 0;
164 165
unsigned CpuFeatures::icache_line_size_ = 0;
unsigned CpuFeatures::dcache_line_size_ = 0;
166

167 168 169 170 171 172 173 174 175 176 177
HeapObjectRequest::HeapObjectRequest(double heap_number, int offset)
    : kind_(kHeapNumber), offset_(offset) {
  value_.heap_number = heap_number;
  DCHECK(!IsSmiDouble(value_.heap_number));
}

HeapObjectRequest::HeapObjectRequest(CodeStub* code_stub, int offset)
    : kind_(kCodeStub), offset_(offset) {
  value_.code_stub = code_stub;
  DCHECK_NOT_NULL(value_.code_stub);
}
178

179 180 181 182 183 184 185
HeapObjectRequest::HeapObjectRequest(const StringConstantBase* string,
                                     int offset)
    : kind_(kStringConstant), offset_(offset) {
  value_.string = string;
  DCHECK_NOT_NULL(value_.string);
}

186 187
// Platform specific but identical code for all the platforms.

188 189
void Assembler::RecordDeoptReason(DeoptimizeReason reason,
                                  SourcePosition position, int id) {
190 191 192 193 194
  EnsureSpace ensure_space(this);
  RecordRelocInfo(RelocInfo::DEOPT_SCRIPT_OFFSET, position.ScriptOffset());
  RecordRelocInfo(RelocInfo::DEOPT_INLINING_ID, position.InliningId());
  RecordRelocInfo(RelocInfo::DEOPT_REASON, static_cast<int>(reason));
  RecordRelocInfo(RelocInfo::DEOPT_ID, id);
195 196 197 198 199 200 201 202 203
}

void Assembler::RecordComment(const char* msg) {
  if (FLAG_code_comments) {
    EnsureSpace ensure_space(this);
    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
  }
}

204
void Assembler::DataAlign(int m) {
205
  DCHECK(m >= 2 && base::bits::IsPowerOfTwo(m));
206 207 208 209
  while ((pc_offset() & (m - 1)) != 0) {
    db(0);
  }
}
210

211
void AssemblerBase::RequestHeapObject(HeapObjectRequest request) {
212
  DCHECK(!options().v8_agnostic_code);
213 214 215 216
  request.set_offset(pc_offset());
  heap_object_requests_.push_front(request);
}

217
int AssemblerBase::AddCodeTarget(Handle<Code> target) {
218
  DCHECK(!options().v8_agnostic_code);
219 220 221 222 223 224 225 226 227 228 229 230
  int current = static_cast<int>(code_targets_.size());
  if (current > 0 && !target.is_null() &&
      code_targets_.back().address() == target.address()) {
    // Optimization if we keep jumping to the same code target.
    return current - 1;
  } else {
    code_targets_.push_back(target);
    return current;
  }
}

Handle<Code> AssemblerBase::GetCodeTarget(intptr_t code_target_index) const {
231
  DCHECK(!options().v8_agnostic_code);
232 233 234 235 236 237 238
  DCHECK_LE(0, code_target_index);
  DCHECK_LT(code_target_index, code_targets_.size());
  return code_targets_[code_target_index];
}

void AssemblerBase::UpdateCodeTarget(intptr_t code_target_index,
                                     Handle<Code> code) {
239
  DCHECK(!options().v8_agnostic_code);
240 241 242 243 244
  DCHECK_LE(0, code_target_index);
  DCHECK_LT(code_target_index, code_targets_.size());
  code_targets_[code_target_index] = code;
}

245 246 247 248
void AssemblerBase::ReserveCodeTargetSpace(size_t num_of_code_targets) {
  code_targets_.reserve(num_of_code_targets);
}

249 250
}  // namespace internal
}  // namespace v8