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
|