V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
assembler.cc
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/code-stubs.h"
39 #include "src/deoptimizer.h"
40 #include "src/disassembler.h"
41 #include "src/isolate.h"
42 #include "src/ostreams.h"
43 #include "src/simulator.h" // For flushing instruction cache.
44 #include "src/snapshot/embedded-data.h"
45 #include "src/snapshot/serializer-common.h"
46 #include "src/snapshot/snapshot.h"
47 #include "src/string-constants.h"
48 
49 namespace v8 {
50 namespace internal {
51 
52 AssemblerOptions AssemblerOptions::EnableV8AgnosticCode() const {
53  AssemblerOptions options = *this;
54  options.v8_agnostic_code = true;
55  options.record_reloc_info_for_serialization = false;
56  options.enable_root_array_delta_access = false;
57  // Inherit |enable_simulator_code| value.
58  options.isolate_independent_code = false;
59  options.inline_offheap_trampolines = false;
60  // Inherit |code_range_start| value.
61  // Inherit |use_pc_relative_calls_and_jumps| value.
62  return options;
63 }
64 
65 AssemblerOptions AssemblerOptions::Default(
66  Isolate* isolate, bool explicitly_support_serialization) {
67  AssemblerOptions options;
68  const bool serializer =
69  isolate->serializer_enabled() || explicitly_support_serialization;
70  const bool generating_embedded_builtin =
71  isolate->ShouldLoadConstantsFromRootList();
72  options.record_reloc_info_for_serialization = serializer;
73  options.enable_root_array_delta_access =
74  !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  !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  options.code_range_start = code_range.begin();
87 #endif
88  return options;
89 }
90 
91 // -----------------------------------------------------------------------------
92 // Implementation of AssemblerBase
93 
94 AssemblerBase::AssemblerBase(const AssemblerOptions& options, void* buffer,
95  int buffer_size)
96  : options_(options),
97  enabled_cpu_features_(0),
98  emit_debug_code_(FLAG_debug_code),
99  predictable_code_size_(false),
100  constant_pool_available_(false),
101  jump_optimization_info_(nullptr) {
102  own_buffer_ = buffer == nullptr;
103  if (buffer_size == 0) buffer_size = kMinimalBufferSize;
104  DCHECK_GT(buffer_size, 0);
105  if (own_buffer_) buffer = NewArray<byte>(buffer_size);
106  buffer_ = static_cast<byte*>(buffer);
107  buffer_size_ = buffer_size;
108  pc_ = buffer_;
109 }
110 
111 AssemblerBase::~AssemblerBase() {
112  if (own_buffer_) DeleteArray(buffer_);
113 }
114 
115 void AssemblerBase::FlushICache(void* start, size_t size) {
116  if (size == 0) return;
117 
118 #if defined(USE_SIMULATOR)
119  base::MutexGuard lock_guard(Simulator::i_cache_mutex());
120  Simulator::FlushICache(Simulator::i_cache(), start, size);
121 #else
122  CpuFeatures::FlushICache(start, size);
123 #endif // USE_SIMULATOR
124 }
125 
126 void AssemblerBase::Print(Isolate* isolate) {
127  StdoutStream os;
128  v8::internal::Disassembler::Decode(isolate, &os, buffer_, pc_);
129 }
130 
131 // -----------------------------------------------------------------------------
132 // Implementation of PredictableCodeSizeScope
133 
134 PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler,
135  int expected_size)
136  : assembler_(assembler),
137  expected_size_(expected_size),
138  start_offset_(assembler->pc_offset()),
139  old_value_(assembler->predictable_code_size()) {
140  assembler_->set_predictable_code_size(true);
141 }
142 
143 PredictableCodeSizeScope::~PredictableCodeSizeScope() {
144  CHECK_EQ(expected_size_, assembler_->pc_offset() - start_offset_);
145  assembler_->set_predictable_code_size(old_value_);
146 }
147 
148 // -----------------------------------------------------------------------------
149 // Implementation of CpuFeatureScope
150 
151 #ifdef DEBUG
152 CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
153  CheckPolicy check)
154  : assembler_(assembler) {
155  DCHECK_IMPLIES(check == kCheckSupported, CpuFeatures::IsSupported(f));
156  old_enabled_ = assembler_->enabled_cpu_features();
157  assembler_->EnableCpuFeature(f);
158 }
159 
160 CpuFeatureScope::~CpuFeatureScope() {
161  assembler_->set_enabled_cpu_features(old_enabled_);
162 }
163 #endif
164 
165 bool CpuFeatures::initialized_ = false;
166 unsigned CpuFeatures::supported_ = 0;
167 unsigned CpuFeatures::icache_line_size_ = 0;
168 unsigned CpuFeatures::dcache_line_size_ = 0;
169 
170 HeapObjectRequest::HeapObjectRequest(double heap_number, int offset)
171  : kind_(kHeapNumber), offset_(offset) {
172  value_.heap_number = heap_number;
173  DCHECK(!IsSmiDouble(value_.heap_number));
174 }
175 
176 HeapObjectRequest::HeapObjectRequest(CodeStub* code_stub, int offset)
177  : kind_(kCodeStub), offset_(offset) {
178  value_.code_stub = code_stub;
179  DCHECK_NOT_NULL(value_.code_stub);
180 }
181 
182 HeapObjectRequest::HeapObjectRequest(const StringConstantBase* string,
183  int offset)
184  : kind_(kStringConstant), offset_(offset) {
185  value_.string = string;
186  DCHECK_NOT_NULL(value_.string);
187 }
188 
189 // Platform specific but identical code for all the platforms.
190 
191 void Assembler::RecordDeoptReason(DeoptimizeReason reason,
192  SourcePosition position, int id) {
193  EnsureSpace ensure_space(this);
194  RecordRelocInfo(RelocInfo::DEOPT_SCRIPT_OFFSET, position.ScriptOffset());
195  RecordRelocInfo(RelocInfo::DEOPT_INLINING_ID, position.InliningId());
196  RecordRelocInfo(RelocInfo::DEOPT_REASON, static_cast<int>(reason));
197  RecordRelocInfo(RelocInfo::DEOPT_ID, id);
198 }
199 
200 void Assembler::RecordComment(const char* msg) {
201  if (FLAG_code_comments) {
202  EnsureSpace ensure_space(this);
203  RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
204  }
205 }
206 
207 void Assembler::DataAlign(int m) {
208  DCHECK(m >= 2 && base::bits::IsPowerOfTwo(m));
209  while ((pc_offset() & (m - 1)) != 0) {
210  db(0);
211  }
212 }
213 
214 void AssemblerBase::RequestHeapObject(HeapObjectRequest request) {
215  DCHECK(!options().v8_agnostic_code);
216  request.set_offset(pc_offset());
217  heap_object_requests_.push_front(request);
218 }
219 
220 int AssemblerBase::AddCodeTarget(Handle<Code> target) {
221  DCHECK(!options().v8_agnostic_code);
222  int current = static_cast<int>(code_targets_.size());
223  if (current > 0 && !target.is_null() &&
224  code_targets_.back().address() == target.address()) {
225  // Optimization if we keep jumping to the same code target.
226  return current - 1;
227  } else {
228  code_targets_.push_back(target);
229  return current;
230  }
231 }
232 
233 Handle<Code> AssemblerBase::GetCodeTarget(intptr_t code_target_index) const {
234  DCHECK(!options().v8_agnostic_code);
235  DCHECK_LE(0, code_target_index);
236  DCHECK_LT(code_target_index, code_targets_.size());
237  return code_targets_[code_target_index];
238 }
239 
240 void AssemblerBase::UpdateCodeTarget(intptr_t code_target_index,
241  Handle<Code> code) {
242  DCHECK(!options().v8_agnostic_code);
243  DCHECK_LE(0, code_target_index);
244  DCHECK_LT(code_target_index, code_targets_.size());
245  code_targets_[code_target_index] = code;
246 }
247 
248 void AssemblerBase::ReserveCodeTargetSpace(size_t num_of_code_targets) {
249  code_targets_.reserve(num_of_code_targets);
250 }
251 
252 } // namespace internal
253 } // namespace v8
Definition: libplatform.h:13