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
|