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 <math.h>
38 : #include <string.h>
39 : #include <cmath>
40 :
41 : #include "src/api.h"
42 : #include "src/assembler-inl.h"
43 : #include "src/base/cpu.h"
44 : #include "src/base/functional.h"
45 : #include "src/base/ieee754.h"
46 : #include "src/base/lazy-instance.h"
47 : #include "src/base/platform/platform.h"
48 : #include "src/base/utils/random-number-generator.h"
49 : #include "src/codegen.h"
50 : #include "src/compiler/code-assembler.h"
51 : #include "src/counters.h"
52 : #include "src/debug/debug.h"
53 : #include "src/deoptimizer.h"
54 : #include "src/disassembler.h"
55 : #include "src/execution.h"
56 : #include "src/ic/ic.h"
57 : #include "src/ic/stub-cache.h"
58 : #include "src/interpreter/bytecodes.h"
59 : #include "src/interpreter/interpreter.h"
60 : #include "src/isolate.h"
61 : #include "src/ostreams.h"
62 : #include "src/regexp/jsregexp.h"
63 : #include "src/regexp/regexp-macro-assembler.h"
64 : #include "src/regexp/regexp-stack.h"
65 : #include "src/register-configuration.h"
66 : #include "src/runtime/runtime.h"
67 : #include "src/simulator.h" // For flushing instruction cache.
68 : #include "src/snapshot/serializer-common.h"
69 : #include "src/string-search.h"
70 : #include "src/wasm/wasm-external-refs.h"
71 :
72 : // Include native regexp-macro-assembler.
73 : #ifndef V8_INTERPRETED_REGEXP
74 : #if V8_TARGET_ARCH_IA32
75 : #include "src/regexp/ia32/regexp-macro-assembler-ia32.h" // NOLINT
76 : #elif V8_TARGET_ARCH_X64
77 : #include "src/regexp/x64/regexp-macro-assembler-x64.h" // NOLINT
78 : #elif V8_TARGET_ARCH_ARM64
79 : #include "src/regexp/arm64/regexp-macro-assembler-arm64.h" // NOLINT
80 : #elif V8_TARGET_ARCH_ARM
81 : #include "src/regexp/arm/regexp-macro-assembler-arm.h" // NOLINT
82 : #elif V8_TARGET_ARCH_PPC
83 : #include "src/regexp/ppc/regexp-macro-assembler-ppc.h" // NOLINT
84 : #elif V8_TARGET_ARCH_MIPS
85 : #include "src/regexp/mips/regexp-macro-assembler-mips.h" // NOLINT
86 : #elif V8_TARGET_ARCH_MIPS64
87 : #include "src/regexp/mips64/regexp-macro-assembler-mips64.h" // NOLINT
88 : #elif V8_TARGET_ARCH_S390
89 : #include "src/regexp/s390/regexp-macro-assembler-s390.h" // NOLINT
90 : #else // Unknown architecture.
91 : #error "Unknown architecture."
92 : #endif // Target architecture.
93 : #endif // V8_INTERPRETED_REGEXP
94 :
95 : #ifdef V8_INTL_SUPPORT
96 : #include "src/intl.h"
97 : #endif // V8_INTL_SUPPORT
98 :
99 : namespace v8 {
100 : namespace internal {
101 :
102 : // -----------------------------------------------------------------------------
103 : // Common double constants.
104 :
105 : struct DoubleConstant BASE_EMBEDDED {
106 : double min_int;
107 : double one_half;
108 : double minus_one_half;
109 : double negative_infinity;
110 : uint64_t the_hole_nan;
111 : double uint32_bias;
112 : };
113 :
114 : static DoubleConstant double_constants;
115 :
116 : static struct V8_ALIGNED(16) {
117 : uint32_t a;
118 : uint32_t b;
119 : uint32_t c;
120 : uint32_t d;
121 : } float_absolute_constant = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
122 :
123 : static struct V8_ALIGNED(16) {
124 : uint32_t a;
125 : uint32_t b;
126 : uint32_t c;
127 : uint32_t d;
128 : } float_negate_constant = {0x80000000, 0x80000000, 0x80000000, 0x80000000};
129 :
130 : static struct V8_ALIGNED(16) {
131 : uint64_t a;
132 : uint64_t b;
133 : } double_absolute_constant = {V8_UINT64_C(0x7FFFFFFFFFFFFFFF),
134 : V8_UINT64_C(0x7FFFFFFFFFFFFFFF)};
135 :
136 : static struct V8_ALIGNED(16) {
137 : uint64_t a;
138 : uint64_t b;
139 : } double_negate_constant = {V8_UINT64_C(0x8000000000000000),
140 : V8_UINT64_C(0x8000000000000000)};
141 :
142 : const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
143 :
144 : // -----------------------------------------------------------------------------
145 : // Implementation of AssemblerBase
146 :
147 1708918 : AssemblerBase::IsolateData::IsolateData(Isolate* isolate)
148 : : serializer_enabled_(isolate->serializer_enabled())
149 : #if V8_TARGET_ARCH_X64
150 : ,
151 : code_range_start_(
152 3417836 : isolate->heap()->memory_allocator()->code_range()->start())
153 : #endif
154 : {
155 1708918 : }
156 :
157 1708946 : AssemblerBase::AssemblerBase(IsolateData isolate_data, void* buffer,
158 : int buffer_size)
159 : : isolate_data_(isolate_data),
160 : enabled_cpu_features_(0),
161 : emit_debug_code_(FLAG_debug_code),
162 : predictable_code_size_(false),
163 : constant_pool_available_(false),
164 1708946 : jump_optimization_info_(nullptr) {
165 1708946 : own_buffer_ = buffer == nullptr;
166 1708946 : if (buffer_size == 0) buffer_size = kMinimalBufferSize;
167 : DCHECK_GT(buffer_size, 0);
168 1708946 : if (own_buffer_) buffer = NewArray<byte>(buffer_size);
169 1709031 : buffer_ = static_cast<byte*>(buffer);
170 1709031 : buffer_size_ = buffer_size;
171 1709031 : pc_ = buffer_;
172 1709031 : }
173 :
174 1709024 : AssemblerBase::~AssemblerBase() {
175 1709024 : if (own_buffer_) DeleteArray(buffer_);
176 1709024 : }
177 :
178 221943560 : void AssemblerBase::FlushICache(Isolate* isolate, void* start, size_t size) {
179 443887334 : if (size == 0) return;
180 :
181 : #if defined(USE_SIMULATOR)
182 : base::LockGuard<base::Mutex> lock_guard(isolate->simulator_i_cache_mutex());
183 : Simulator::FlushICache(isolate->simulator_i_cache(), start, size);
184 : #else
185 221990691 : CpuFeatures::FlushICache(start, size);
186 : #endif // USE_SIMULATOR
187 : }
188 :
189 0 : void AssemblerBase::Print(Isolate* isolate) {
190 0 : OFStream os(stdout);
191 0 : v8::internal::Disassembler::Decode(isolate, &os, buffer_, pc_, nullptr);
192 0 : }
193 :
194 : // -----------------------------------------------------------------------------
195 : // Implementation of PredictableCodeSizeScope
196 :
197 0 : PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler)
198 0 : : PredictableCodeSizeScope(assembler, -1) {}
199 :
200 0 : PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler,
201 : int expected_size)
202 : : assembler_(assembler),
203 : expected_size_(expected_size),
204 : start_offset_(assembler->pc_offset()),
205 0 : old_value_(assembler->predictable_code_size()) {
206 : assembler_->set_predictable_code_size(true);
207 0 : }
208 :
209 0 : PredictableCodeSizeScope::~PredictableCodeSizeScope() {
210 : // TODO(svenpanne) Remove the 'if' when everything works.
211 0 : if (expected_size_ >= 0) {
212 0 : CHECK_EQ(expected_size_, assembler_->pc_offset() - start_offset_);
213 : }
214 0 : assembler_->set_predictable_code_size(old_value_);
215 0 : }
216 :
217 : // -----------------------------------------------------------------------------
218 : // Implementation of CpuFeatureScope
219 :
220 : #ifdef DEBUG
221 : CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
222 : CheckPolicy check)
223 : : assembler_(assembler) {
224 : DCHECK_IMPLIES(check == kCheckSupported, CpuFeatures::IsSupported(f));
225 : old_enabled_ = assembler_->enabled_cpu_features();
226 : assembler_->EnableCpuFeature(f);
227 : }
228 :
229 : CpuFeatureScope::~CpuFeatureScope() {
230 : assembler_->set_enabled_cpu_features(old_enabled_);
231 : }
232 : #endif
233 :
234 : bool CpuFeatures::initialized_ = false;
235 : unsigned CpuFeatures::supported_ = 0;
236 : unsigned CpuFeatures::icache_line_size_ = 0;
237 : unsigned CpuFeatures::dcache_line_size_ = 0;
238 :
239 : // -----------------------------------------------------------------------------
240 : // Implementation of RelocInfoWriter and RelocIterator
241 : //
242 : // Relocation information is written backwards in memory, from high addresses
243 : // towards low addresses, byte by byte. Therefore, in the encodings listed
244 : // below, the first byte listed it at the highest address, and successive
245 : // bytes in the record are at progressively lower addresses.
246 : //
247 : // Encoding
248 : //
249 : // The most common modes are given single-byte encodings. Also, it is
250 : // easy to identify the type of reloc info and skip unwanted modes in
251 : // an iteration.
252 : //
253 : // The encoding relies on the fact that there are fewer than 14
254 : // different relocation modes using standard non-compact encoding.
255 : //
256 : // The first byte of a relocation record has a tag in its low 2 bits:
257 : // Here are the record schemes, depending on the low tag and optional higher
258 : // tags.
259 : //
260 : // Low tag:
261 : // 00: embedded_object: [6-bit pc delta] 00
262 : //
263 : // 01: code_target: [6-bit pc delta] 01
264 : //
265 : // 10: short_data_record: [6-bit pc delta] 10 followed by
266 : // [8-bit data delta]
267 : //
268 : // 11: long_record [6 bit reloc mode] 11
269 : // followed by pc delta
270 : // followed by optional data depending on type.
271 : //
272 : // If a pc delta exceeds 6 bits, it is split into a remainder that fits into
273 : // 6 bits and a part that does not. The latter is encoded as a long record
274 : // with PC_JUMP as pseudo reloc info mode. The former is encoded as part of
275 : // the following record in the usual way. The long pc jump record has variable
276 : // length:
277 : // pc-jump: [PC_JUMP] 11
278 : // [7 bits data] 0
279 : // ...
280 : // [7 bits data] 1
281 : // (Bits 6..31 of pc delta, with leading zeroes
282 : // dropped, and last non-zero chunk tagged with 1.)
283 :
284 : const int kTagBits = 2;
285 : const int kTagMask = (1 << kTagBits) - 1;
286 : const int kLongTagBits = 6;
287 :
288 : const int kEmbeddedObjectTag = 0;
289 : const int kCodeTargetTag = 1;
290 : const int kLocatableTag = 2;
291 : const int kDefaultTag = 3;
292 :
293 : const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
294 : const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
295 : const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
296 :
297 : const int kChunkBits = 7;
298 : const int kChunkMask = (1 << kChunkBits) - 1;
299 : const int kLastChunkTagBits = 1;
300 : const int kLastChunkTagMask = 1;
301 : const int kLastChunkTag = 1;
302 :
303 186865 : void RelocInfo::set_wasm_context_reference(Isolate* isolate, Address address,
304 : ICacheFlushMode icache_flush_mode) {
305 : DCHECK(IsWasmContextReference(rmode_));
306 186865 : set_embedded_address(isolate, address, icache_flush_mode);
307 186865 : }
308 :
309 5627 : void RelocInfo::set_global_handle(Isolate* isolate, Address address,
310 : ICacheFlushMode icache_flush_mode) {
311 : DCHECK_EQ(rmode_, WASM_GLOBAL_HANDLE);
312 5627 : set_embedded_address(isolate, address, icache_flush_mode);
313 5627 : }
314 :
315 5627 : Address RelocInfo::global_handle() const {
316 : DCHECK_EQ(rmode_, WASM_GLOBAL_HANDLE);
317 5627 : return embedded_address();
318 : }
319 :
320 0 : uint32_t RelocInfo::wasm_function_table_size_reference() const {
321 : DCHECK(IsWasmFunctionTableSizeReference(rmode_));
322 0 : return embedded_size();
323 : }
324 :
325 12 : Address RelocInfo::wasm_context_reference() const {
326 : DCHECK(IsWasmContextReference(rmode_));
327 12 : return embedded_address();
328 : }
329 :
330 1266 : void RelocInfo::update_wasm_function_table_size_reference(
331 : Isolate* isolate, uint32_t old_size, uint32_t new_size,
332 : ICacheFlushMode icache_flush_mode) {
333 : DCHECK(IsWasmFunctionTableSizeReference(rmode_));
334 1266 : set_embedded_size(isolate, new_size, icache_flush_mode);
335 1266 : }
336 :
337 9612634 : void RelocInfo::set_target_address(Isolate* isolate, Address target,
338 : WriteBarrierMode write_barrier_mode,
339 16147257 : ICacheFlushMode icache_flush_mode) {
340 : DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
341 : Assembler::set_target_address_at(isolate, pc_, host_, target,
342 9612634 : icache_flush_mode);
343 28837523 : if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != nullptr &&
344 9612255 : IsCodeTarget(rmode_)) {
345 6534623 : Code* target_code = Code::GetCodeFromTargetAddress(target);
346 : host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
347 6534623 : target_code);
348 : }
349 9612634 : }
350 :
351 16208972 : uint32_t RelocInfoWriter::WriteLongPCJump(uint32_t pc_delta) {
352 : // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
353 : // Otherwise write a variable length PC jump for the bits that do
354 : // not fit in the kSmallPCDeltaBits bits.
355 32417944 : if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
356 : WriteMode(RelocInfo::PC_JUMP);
357 1327651 : uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
358 : DCHECK_GT(pc_jump, 0);
359 : // Write kChunkBits size chunks of the pc_jump.
360 2655663 : for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
361 1328012 : byte b = pc_jump & kChunkMask;
362 1328012 : *--pos_ = b << kLastChunkTagBits;
363 : }
364 : // Tag the last chunk so it can be identified.
365 1327651 : *pos_ = *pos_ | kLastChunkTag;
366 : // Return the remaining kSmallPCDeltaBits of the pc_delta.
367 1327651 : return pc_delta & kSmallPCDeltaMask;
368 : }
369 :
370 : void RelocInfoWriter::WriteShortTaggedPC(uint32_t pc_delta, int tag) {
371 : // Write a byte of tagged pc-delta, possibly preceded by an explicit pc-jump.
372 11266685 : pc_delta = WriteLongPCJump(pc_delta);
373 11266735 : *--pos_ = pc_delta << kTagBits | tag;
374 : }
375 :
376 : void RelocInfoWriter::WriteShortData(intptr_t data_delta) {
377 236611 : *--pos_ = static_cast<byte>(data_delta);
378 : }
379 :
380 : void RelocInfoWriter::WriteMode(RelocInfo::Mode rmode) {
381 : STATIC_ASSERT(RelocInfo::NUMBER_OF_MODES <= (1 << kLongTagBits));
382 6269961 : *--pos_ = static_cast<int>((rmode << kTagBits) | kDefaultTag);
383 : }
384 :
385 4942304 : void RelocInfoWriter::WriteModeAndPC(uint32_t pc_delta, RelocInfo::Mode rmode) {
386 : // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
387 4942304 : pc_delta = WriteLongPCJump(pc_delta);
388 : WriteMode(rmode);
389 4942310 : *--pos_ = pc_delta;
390 4942310 : }
391 :
392 : void RelocInfoWriter::WriteIntData(int number) {
393 2860478 : for (int i = 0; i < kIntSize; i++) {
394 2860478 : *--pos_ = static_cast<byte>(number);
395 : // Signed right shift is arithmetic shift. Tested in test-utils.cc.
396 2860478 : number = number >> kBitsPerByte;
397 : }
398 : }
399 :
400 : void RelocInfoWriter::WriteData(intptr_t data_delta) {
401 0 : for (int i = 0; i < kIntptrSize; i++) {
402 0 : *--pos_ = static_cast<byte>(data_delta);
403 : // Signed right shift is arithmetic shift. Tested in test-utils.cc.
404 0 : data_delta = data_delta >> kBitsPerByte;
405 : }
406 : }
407 :
408 33369765 : void RelocInfoWriter::Write(const RelocInfo* rinfo) {
409 : RelocInfo::Mode rmode = rinfo->rmode();
410 : #ifdef DEBUG
411 : byte* begin_pos = pos_;
412 : #endif
413 : DCHECK(rinfo->rmode() < RelocInfo::NUMBER_OF_MODES);
414 : DCHECK_GE(rinfo->pc() - last_pc_, 0);
415 : // Use unsigned delta-encoding for pc.
416 16208988 : uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
417 :
418 : // The two most common modes are given small tags, and usually fit in a byte.
419 16208988 : if (rmode == RelocInfo::EMBEDDED_OBJECT) {
420 : WriteShortTaggedPC(pc_delta, kEmbeddedObjectTag);
421 11211285 : } else if (rmode == RelocInfo::CODE_TARGET) {
422 : WriteShortTaggedPC(pc_delta, kCodeTargetTag);
423 : DCHECK_LE(begin_pos - pos_, RelocInfo::kMaxCallSize);
424 5178914 : } else if (rmode == RelocInfo::DEOPT_REASON) {
425 : DCHECK(rinfo->data() < (1 << kBitsPerByte));
426 : WriteShortTaggedPC(pc_delta, kLocatableTag);
427 : WriteShortData(rinfo->data());
428 : } else {
429 4942303 : WriteModeAndPC(pc_delta, rmode);
430 4942312 : if (RelocInfo::IsComment(rmode)) {
431 : WriteData(rinfo->data());
432 9884621 : } else if (RelocInfo::IsConstPool(rmode) ||
433 9648011 : RelocInfo::IsVeneerPool(rmode) || RelocInfo::IsDeoptId(rmode) ||
434 9174795 : RelocInfo::IsDeoptPosition(rmode) ||
435 : RelocInfo::IsWasmProtectedLanding(rmode)) {
436 715119 : WriteIntData(static_cast<int>(rinfo->data()));
437 : }
438 : }
439 16209047 : last_pc_ = rinfo->pc();
440 16209047 : last_mode_ = rmode;
441 : #ifdef DEBUG
442 : DCHECK_LE(begin_pos - pos_, kMaxSize);
443 : #endif
444 16209047 : }
445 :
446 : inline int RelocIterator::AdvanceGetTag() {
447 613238966 : return *--pos_ & kTagMask;
448 : }
449 :
450 : inline RelocInfo::Mode RelocIterator::GetMode() {
451 : return static_cast<RelocInfo::Mode>((*pos_ >> kTagBits) &
452 373383402 : ((1 << kLongTagBits) - 1));
453 : }
454 :
455 : inline void RelocIterator::ReadShortTaggedPC() {
456 239855564 : rinfo_.pc_ += *pos_ >> kTagBits;
457 : }
458 :
459 : inline void RelocIterator::AdvanceReadPC() {
460 244391818 : rinfo_.pc_ += *--pos_;
461 : }
462 :
463 0 : void RelocIterator::AdvanceReadInt() {
464 : int x = 0;
465 41232 : for (int i = 0; i < kIntSize; i++) {
466 41232 : x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
467 : }
468 10308 : rinfo_.data_ = x;
469 0 : }
470 :
471 0 : void RelocIterator::AdvanceReadData() {
472 : intptr_t x = 0;
473 0 : for (int i = 0; i < kIntptrSize; i++) {
474 0 : x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
475 : }
476 0 : rinfo_.data_ = x;
477 0 : }
478 :
479 128991587 : void RelocIterator::AdvanceReadLongPCJump() {
480 : // Read the 32-kSmallPCDeltaBits most significant bits of the
481 : // pc jump in kChunkBits bit chunks and shift them into place.
482 : // Stop when the last chunk is encountered.
483 : uint32_t pc_jump = 0;
484 128992158 : for (int i = 0; i < kIntSize; i++) {
485 128992155 : byte pc_jump_part = *--pos_;
486 128992155 : pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
487 128992155 : if ((pc_jump_part & kLastChunkTagMask) == 1) break;
488 : }
489 : // The least significant kSmallPCDeltaBits bits will be added
490 : // later.
491 128991587 : rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
492 128991587 : }
493 :
494 : inline void RelocIterator::ReadShortData() {
495 6 : uint8_t unsigned_b = *pos_;
496 6 : rinfo_.data_ = unsigned_b;
497 : }
498 :
499 1008272004 : void RelocIterator::next() {
500 : DCHECK(!done());
501 : // Basically, do the opposite of RelocInfoWriter::Write.
502 : // Reading of data is as far as possible avoided for unwanted modes,
503 : // but we must always update the pc.
504 : //
505 : // We exit this loop by returning when we find a mode we want.
506 1197709433 : while (pos_ > end_) {
507 : int tag = AdvanceGetTag();
508 613238966 : if (tag == kEmbeddedObjectTag) {
509 : ReadShortTaggedPC();
510 20018899 : if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
511 593220067 : } else if (tag == kCodeTargetTag) {
512 : ReadShortTaggedPC();
513 218543368 : if (SetMode(RelocInfo::CODE_TARGET)) return;
514 374676699 : } else if (tag == kLocatableTag) {
515 : ReadShortTaggedPC();
516 : Advance();
517 1293297 : if (SetMode(RelocInfo::DEOPT_REASON)) {
518 : ReadShortData();
519 : return;
520 : }
521 : } else {
522 : DCHECK_EQ(tag, kDefaultTag);
523 : RelocInfo::Mode rmode = GetMode();
524 373383402 : if (rmode == RelocInfo::PC_JUMP) {
525 128991584 : AdvanceReadLongPCJump();
526 : } else {
527 : AdvanceReadPC();
528 244391818 : if (RelocInfo::IsComment(rmode)) {
529 0 : if (SetMode(rmode)) {
530 : AdvanceReadData();
531 : return;
532 : }
533 : Advance(kIntptrSize);
534 488783512 : } else if (RelocInfo::IsConstPool(rmode) ||
535 244391717 : RelocInfo::IsVeneerPool(rmode) ||
536 243098435 : RelocInfo::IsDeoptId(rmode) ||
537 484903671 : RelocInfo::IsDeoptPosition(rmode) ||
538 : RelocInfo::IsWasmProtectedLanding(rmode)) {
539 3896683 : if (SetMode(rmode)) {
540 : AdvanceReadInt();
541 : return;
542 : }
543 : Advance(kIntSize);
544 240495135 : } else if (SetMode(static_cast<RelocInfo::Mode>(rmode))) {
545 : return;
546 : }
547 : }
548 : }
549 : }
550 60445845 : done_ = true;
551 : }
552 :
553 60613419 : RelocIterator::RelocIterator(Code* code, int mode_mask) {
554 60613419 : rinfo_.host_ = code;
555 60613419 : rinfo_.pc_ = code->instruction_start();
556 60613419 : rinfo_.data_ = 0;
557 : // Relocation info is read backwards.
558 121226838 : pos_ = code->relocation_start() + code->relocation_size();
559 60613419 : end_ = code->relocation_start();
560 60613419 : done_ = false;
561 60613419 : mode_mask_ = mode_mask;
562 60613419 : if (mode_mask_ == 0) pos_ = end_;
563 60613419 : next();
564 60613462 : }
565 :
566 0 : RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
567 0 : rinfo_.pc_ = desc.buffer;
568 0 : rinfo_.data_ = 0;
569 : // Relocation info is read backwards.
570 0 : pos_ = desc.buffer + desc.buffer_size;
571 0 : end_ = pos_ - desc.reloc_size;
572 0 : done_ = false;
573 0 : mode_mask_ = mode_mask;
574 0 : if (mode_mask_ == 0) pos_ = end_;
575 0 : next();
576 0 : }
577 :
578 : // -----------------------------------------------------------------------------
579 : // Implementation of RelocInfo
580 :
581 : #ifdef DEBUG
582 : bool RelocInfo::RequiresRelocation(Isolate* isolate, const CodeDesc& desc) {
583 : // Ensure there are no code targets or embedded objects present in the
584 : // deoptimization entries, they would require relocation after code
585 : // generation.
586 : int mode_mask = RelocInfo::kCodeTargetMask |
587 : RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
588 : RelocInfo::kApplyMask;
589 : RelocIterator it(desc, mode_mask);
590 : return !it.done();
591 : }
592 : #endif
593 :
594 : #ifdef ENABLE_DISASSEMBLER
595 : const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
596 : switch (rmode) {
597 : case NONE32:
598 : return "no reloc 32";
599 : case NONE64:
600 : return "no reloc 64";
601 : case EMBEDDED_OBJECT:
602 : return "embedded object";
603 : case CODE_TARGET:
604 : return "code target";
605 : case RUNTIME_ENTRY:
606 : return "runtime entry";
607 : case COMMENT:
608 : return "comment";
609 : case EXTERNAL_REFERENCE:
610 : return "external reference";
611 : case INTERNAL_REFERENCE:
612 : return "internal reference";
613 : case INTERNAL_REFERENCE_ENCODED:
614 : return "encoded internal reference";
615 : case DEOPT_SCRIPT_OFFSET:
616 : return "deopt script offset";
617 : case DEOPT_INLINING_ID:
618 : return "deopt inlining id";
619 : case DEOPT_REASON:
620 : return "deopt reason";
621 : case DEOPT_ID:
622 : return "deopt index";
623 : case CONST_POOL:
624 : return "constant pool";
625 : case VENEER_POOL:
626 : return "veneer pool";
627 : case WASM_CONTEXT_REFERENCE:
628 : return "wasm context reference";
629 : case WASM_FUNCTION_TABLE_SIZE_REFERENCE:
630 : return "wasm function table size reference";
631 : case WASM_PROTECTED_INSTRUCTION_LANDING:
632 : return "wasm protected instruction landing";
633 : case WASM_GLOBAL_HANDLE:
634 : return "global handle";
635 : case NUMBER_OF_MODES:
636 : case PC_JUMP:
637 : UNREACHABLE();
638 : }
639 : return "unknown relocation type";
640 : }
641 :
642 : void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT
643 : os << static_cast<const void*>(pc_) << " " << RelocModeName(rmode_);
644 : if (IsComment(rmode_)) {
645 : os << " (" << reinterpret_cast<char*>(data_) << ")";
646 : } else if (rmode_ == DEOPT_SCRIPT_OFFSET || rmode_ == DEOPT_INLINING_ID) {
647 : os << " (" << data() << ")";
648 : } else if (rmode_ == DEOPT_REASON) {
649 : os << " ("
650 : << DeoptimizeReasonToString(static_cast<DeoptimizeReason>(data_)) << ")";
651 : } else if (rmode_ == EMBEDDED_OBJECT) {
652 : os << " (" << Brief(target_object()) << ")";
653 : } else if (rmode_ == EXTERNAL_REFERENCE) {
654 : ExternalReferenceEncoder ref_encoder(isolate);
655 : os << " ("
656 : << ref_encoder.NameOfAddress(isolate, target_external_reference())
657 : << ") (" << static_cast<const void*>(target_external_reference())
658 : << ")";
659 : } else if (IsCodeTarget(rmode_)) {
660 : Code* code = Code::GetCodeFromTargetAddress(target_address());
661 : os << " (" << Code::Kind2String(code->kind()) << ") ("
662 : << static_cast<const void*>(target_address()) << ")";
663 : } else if (IsRuntimeEntry(rmode_) && isolate->deoptimizer_data() != nullptr) {
664 : // Depotimization bailouts are stored as runtime entries.
665 : int id = Deoptimizer::GetDeoptimizationId(
666 : isolate, target_address(), Deoptimizer::EAGER);
667 : if (id != Deoptimizer::kNotDeoptimizationEntry) {
668 : os << " (deoptimization bailout " << id << ")";
669 : }
670 : } else if (IsConstPool(rmode_)) {
671 : os << " (size " << static_cast<int>(data_) << ")";
672 : }
673 :
674 : os << "\n";
675 : }
676 : #endif // ENABLE_DISASSEMBLER
677 :
678 : #ifdef VERIFY_HEAP
679 : void RelocInfo::Verify(Isolate* isolate) {
680 : switch (rmode_) {
681 : case EMBEDDED_OBJECT:
682 : Object::VerifyPointer(target_object());
683 : break;
684 : case CODE_TARGET: {
685 : // convert inline target address to code object
686 : Address addr = target_address();
687 : CHECK_NOT_NULL(addr);
688 : // Check that we can find the right code object.
689 : Code* code = Code::GetCodeFromTargetAddress(addr);
690 : Object* found = isolate->FindCodeObject(addr);
691 : CHECK(found->IsCode());
692 : CHECK(code->address() == HeapObject::cast(found)->address());
693 : break;
694 : }
695 : case INTERNAL_REFERENCE:
696 : case INTERNAL_REFERENCE_ENCODED: {
697 : Address target = target_internal_reference();
698 : Address pc = target_internal_reference_address();
699 : Code* code = Code::cast(isolate->FindCodeObject(pc));
700 : CHECK(target >= code->instruction_start());
701 : CHECK(target <= code->instruction_end());
702 : break;
703 : }
704 : case RUNTIME_ENTRY:
705 : case COMMENT:
706 : case EXTERNAL_REFERENCE:
707 : case DEOPT_SCRIPT_OFFSET:
708 : case DEOPT_INLINING_ID:
709 : case DEOPT_REASON:
710 : case DEOPT_ID:
711 : case CONST_POOL:
712 : case VENEER_POOL:
713 : case WASM_CONTEXT_REFERENCE:
714 : case WASM_FUNCTION_TABLE_SIZE_REFERENCE:
715 : case WASM_GLOBAL_HANDLE:
716 : case WASM_PROTECTED_INSTRUCTION_LANDING:
717 : // TODO(eholk): make sure the protected instruction is in range.
718 : case NONE32:
719 : case NONE64:
720 : break;
721 : case NUMBER_OF_MODES:
722 : case PC_JUMP:
723 : UNREACHABLE();
724 : break;
725 : }
726 : }
727 : #endif // VERIFY_HEAP
728 :
729 : // Implementation of ExternalReference
730 :
731 32290037 : static ExternalReference::Type BuiltinCallTypeForResultSize(int result_size) {
732 32290037 : switch (result_size) {
733 : case 1:
734 : return ExternalReference::BUILTIN_CALL;
735 : case 2:
736 55703 : return ExternalReference::BUILTIN_CALL_PAIR;
737 : }
738 0 : UNREACHABLE();
739 : }
740 :
741 53977 : void ExternalReference::SetUp() {
742 53977 : double_constants.min_int = kMinInt;
743 53977 : double_constants.one_half = 0.5;
744 53977 : double_constants.minus_one_half = -0.5;
745 53977 : double_constants.the_hole_nan = kHoleNanInt64;
746 53977 : double_constants.negative_infinity = -V8_INFINITY;
747 : double_constants.uint32_bias =
748 53977 : static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1;
749 53977 : }
750 :
751 12570562 : ExternalReference::ExternalReference(Address address, Isolate* isolate)
752 12570562 : : address_(Redirect(isolate, address)) {}
753 :
754 169757 : ExternalReference::ExternalReference(
755 : ApiFunction* fun, Type type = ExternalReference::BUILTIN_CALL,
756 : Isolate* isolate = nullptr)
757 169757 : : address_(Redirect(isolate, fun->address(), type)) {}
758 :
759 32288438 : ExternalReference::ExternalReference(Runtime::FunctionId id, Isolate* isolate)
760 32288438 : : ExternalReference(Runtime::FunctionForId(id), isolate) {}
761 :
762 32290048 : ExternalReference::ExternalReference(const Runtime::Function* f,
763 : Isolate* isolate)
764 : : address_(Redirect(isolate, f->entry,
765 64580096 : BuiltinCallTypeForResultSize(f->result_size))) {}
766 :
767 583497 : ExternalReference ExternalReference::isolate_address(Isolate* isolate) {
768 583497 : return ExternalReference(isolate);
769 : }
770 :
771 55342 : ExternalReference ExternalReference::builtins_address(Isolate* isolate) {
772 55342 : return ExternalReference(isolate->builtins()->builtins_table_address());
773 : }
774 :
775 56241 : ExternalReference ExternalReference::interpreter_dispatch_table_address(
776 56241 : Isolate* isolate) {
777 56241 : return ExternalReference(isolate->interpreter()->dispatch_table_address());
778 : }
779 :
780 0 : ExternalReference ExternalReference::interpreter_dispatch_counters(
781 0 : Isolate* isolate) {
782 : return ExternalReference(
783 0 : isolate->interpreter()->bytecode_dispatch_counters_table());
784 : }
785 :
786 55373 : ExternalReference ExternalReference::bytecode_size_table_address(
787 : Isolate* isolate) {
788 : return ExternalReference(
789 55373 : interpreter::Bytecodes::bytecode_size_table_address());
790 : }
791 :
792 0 : ExternalReference::ExternalReference(StatsCounter* counter)
793 0 : : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
794 :
795 194942 : ExternalReference::ExternalReference(IsolateAddressId id, Isolate* isolate)
796 194942 : : address_(isolate->get_address_from_id(id)) {}
797 :
798 322 : ExternalReference::ExternalReference(const SCTableReference& table_ref)
799 322 : : address_(table_ref.address()) {}
800 :
801 55342 : ExternalReference ExternalReference::
802 : incremental_marking_record_write_function(Isolate* isolate) {
803 : return ExternalReference(Redirect(
804 : isolate,
805 55342 : FUNCTION_ADDR(IncrementalMarking::RecordWriteFromCode)));
806 : }
807 :
808 55435 : ExternalReference ExternalReference::store_buffer_overflow_function(
809 : Isolate* isolate) {
810 : return ExternalReference(Redirect(
811 : isolate,
812 55435 : FUNCTION_ADDR(StoreBuffer::StoreBufferOverflow)));
813 : }
814 :
815 58822 : ExternalReference ExternalReference::delete_handle_scope_extensions(
816 : Isolate* isolate) {
817 : return ExternalReference(Redirect(
818 : isolate,
819 58822 : FUNCTION_ADDR(HandleScope::DeleteExtensions)));
820 : }
821 :
822 55838 : ExternalReference ExternalReference::get_date_field_function(
823 : Isolate* isolate) {
824 55838 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(JSDate::GetField)));
825 : }
826 :
827 55528 : ExternalReference ExternalReference::date_cache_stamp(Isolate* isolate) {
828 55528 : return ExternalReference(isolate->date_cache()->stamp_address());
829 : }
830 :
831 0 : void ExternalReference::set_redirector(
832 : Isolate* isolate, ExternalReferenceRedirector* redirector) {
833 : // We can't stack them.
834 : DCHECK_NULL(isolate->external_reference_redirector());
835 : isolate->set_external_reference_redirector(
836 : reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector));
837 0 : }
838 :
839 55579 : ExternalReference ExternalReference::stress_deopt_count(Isolate* isolate) {
840 55579 : return ExternalReference(isolate->stress_deopt_count_address());
841 : }
842 :
843 93743 : ExternalReference ExternalReference::new_deoptimizer_function(
844 : Isolate* isolate) {
845 : return ExternalReference(
846 93743 : Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
847 : }
848 :
849 93743 : ExternalReference ExternalReference::compute_output_frames_function(
850 : Isolate* isolate) {
851 : return ExternalReference(
852 93743 : Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
853 : }
854 :
855 55317 : ExternalReference ExternalReference::wasm_f32_trunc(Isolate* isolate) {
856 : return ExternalReference(
857 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::f32_trunc_wrapper)));
858 : }
859 55317 : ExternalReference ExternalReference::wasm_f32_floor(Isolate* isolate) {
860 : return ExternalReference(
861 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::f32_floor_wrapper)));
862 : }
863 55317 : ExternalReference ExternalReference::wasm_f32_ceil(Isolate* isolate) {
864 : return ExternalReference(
865 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::f32_ceil_wrapper)));
866 : }
867 55317 : ExternalReference ExternalReference::wasm_f32_nearest_int(Isolate* isolate) {
868 : return ExternalReference(
869 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::f32_nearest_int_wrapper)));
870 : }
871 :
872 55317 : ExternalReference ExternalReference::wasm_f64_trunc(Isolate* isolate) {
873 : return ExternalReference(
874 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::f64_trunc_wrapper)));
875 : }
876 :
877 55317 : ExternalReference ExternalReference::wasm_f64_floor(Isolate* isolate) {
878 : return ExternalReference(
879 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::f64_floor_wrapper)));
880 : }
881 :
882 55317 : ExternalReference ExternalReference::wasm_f64_ceil(Isolate* isolate) {
883 : return ExternalReference(
884 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::f64_ceil_wrapper)));
885 : }
886 :
887 55317 : ExternalReference ExternalReference::wasm_f64_nearest_int(Isolate* isolate) {
888 : return ExternalReference(
889 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::f64_nearest_int_wrapper)));
890 : }
891 :
892 55317 : ExternalReference ExternalReference::wasm_int64_to_float32(Isolate* isolate) {
893 : return ExternalReference(
894 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::int64_to_float32_wrapper)));
895 : }
896 :
897 55317 : ExternalReference ExternalReference::wasm_uint64_to_float32(Isolate* isolate) {
898 : return ExternalReference(
899 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::uint64_to_float32_wrapper)));
900 : }
901 :
902 55317 : ExternalReference ExternalReference::wasm_int64_to_float64(Isolate* isolate) {
903 : return ExternalReference(
904 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::int64_to_float64_wrapper)));
905 : }
906 :
907 55317 : ExternalReference ExternalReference::wasm_uint64_to_float64(Isolate* isolate) {
908 : return ExternalReference(
909 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::uint64_to_float64_wrapper)));
910 : }
911 :
912 55317 : ExternalReference ExternalReference::wasm_float32_to_int64(Isolate* isolate) {
913 : return ExternalReference(
914 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::float32_to_int64_wrapper)));
915 : }
916 :
917 55317 : ExternalReference ExternalReference::wasm_float32_to_uint64(Isolate* isolate) {
918 : return ExternalReference(
919 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::float32_to_uint64_wrapper)));
920 : }
921 :
922 55317 : ExternalReference ExternalReference::wasm_float64_to_int64(Isolate* isolate) {
923 : return ExternalReference(
924 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::float64_to_int64_wrapper)));
925 : }
926 :
927 55317 : ExternalReference ExternalReference::wasm_float64_to_uint64(Isolate* isolate) {
928 : return ExternalReference(
929 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::float64_to_uint64_wrapper)));
930 : }
931 :
932 55316 : ExternalReference ExternalReference::wasm_int64_div(Isolate* isolate) {
933 : return ExternalReference(
934 55316 : Redirect(isolate, FUNCTION_ADDR(wasm::int64_div_wrapper)));
935 : }
936 :
937 55316 : ExternalReference ExternalReference::wasm_int64_mod(Isolate* isolate) {
938 : return ExternalReference(
939 55316 : Redirect(isolate, FUNCTION_ADDR(wasm::int64_mod_wrapper)));
940 : }
941 :
942 55317 : ExternalReference ExternalReference::wasm_uint64_div(Isolate* isolate) {
943 : return ExternalReference(
944 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::uint64_div_wrapper)));
945 : }
946 :
947 55317 : ExternalReference ExternalReference::wasm_uint64_mod(Isolate* isolate) {
948 : return ExternalReference(
949 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::uint64_mod_wrapper)));
950 : }
951 :
952 55317 : ExternalReference ExternalReference::wasm_word32_ctz(Isolate* isolate) {
953 : return ExternalReference(
954 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::word32_ctz_wrapper)));
955 : }
956 :
957 55317 : ExternalReference ExternalReference::wasm_word64_ctz(Isolate* isolate) {
958 : return ExternalReference(
959 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::word64_ctz_wrapper)));
960 : }
961 :
962 55317 : ExternalReference ExternalReference::wasm_word32_popcnt(Isolate* isolate) {
963 : return ExternalReference(
964 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::word32_popcnt_wrapper)));
965 : }
966 :
967 55317 : ExternalReference ExternalReference::wasm_word64_popcnt(Isolate* isolate) {
968 : return ExternalReference(
969 55317 : Redirect(isolate, FUNCTION_ADDR(wasm::word64_popcnt_wrapper)));
970 : }
971 :
972 6290 : static void f64_acos_wrapper(double* param) {
973 6290 : WriteDoubleValue(param, base::ieee754::acos(ReadDoubleValue(param)));
974 6290 : }
975 :
976 55329 : ExternalReference ExternalReference::f64_acos_wrapper_function(
977 : Isolate* isolate) {
978 55329 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_acos_wrapper)));
979 : }
980 :
981 6290 : static void f64_asin_wrapper(double* param) {
982 6290 : WriteDoubleValue(param, base::ieee754::asin(ReadDoubleValue(param)));
983 6290 : }
984 :
985 55330 : ExternalReference ExternalReference::f64_asin_wrapper_function(
986 : Isolate* isolate) {
987 55330 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_asin_wrapper)));
988 : }
989 :
990 55330 : ExternalReference ExternalReference::wasm_float64_pow(Isolate* isolate) {
991 : return ExternalReference(
992 55330 : Redirect(isolate, FUNCTION_ADDR(wasm::float64_pow_wrapper)));
993 : }
994 :
995 73203 : ExternalReference ExternalReference::wasm_set_thread_in_wasm_flag(
996 : Isolate* isolate) {
997 : return ExternalReference(
998 73203 : Redirect(isolate, FUNCTION_ADDR(wasm::set_thread_in_wasm_flag)));
999 : }
1000 :
1001 73202 : ExternalReference ExternalReference::wasm_clear_thread_in_wasm_flag(
1002 : Isolate* isolate) {
1003 : return ExternalReference(
1004 73202 : Redirect(isolate, FUNCTION_ADDR(wasm::clear_thread_in_wasm_flag)));
1005 : }
1006 :
1007 42 : static void f64_mod_wrapper(double* param0, double* param1) {
1008 : WriteDoubleValue(param0,
1009 : Modulo(ReadDoubleValue(param0), ReadDoubleValue(param1)));
1010 42 : }
1011 :
1012 55341 : ExternalReference ExternalReference::f64_mod_wrapper_function(
1013 : Isolate* isolate) {
1014 55341 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_mod_wrapper)));
1015 : }
1016 :
1017 90238 : ExternalReference ExternalReference::wasm_call_trap_callback_for_testing(
1018 : Isolate* isolate) {
1019 : return ExternalReference(
1020 90238 : Redirect(isolate, FUNCTION_ADDR(wasm::call_trap_callback_for_testing)));
1021 : }
1022 :
1023 55310 : ExternalReference ExternalReference::log_enter_external_function(
1024 : Isolate* isolate) {
1025 : return ExternalReference(
1026 55310 : Redirect(isolate, FUNCTION_ADDR(Logger::EnterExternal)));
1027 : }
1028 :
1029 55310 : ExternalReference ExternalReference::log_leave_external_function(
1030 : Isolate* isolate) {
1031 : return ExternalReference(
1032 55310 : Redirect(isolate, FUNCTION_ADDR(Logger::LeaveExternal)));
1033 : }
1034 :
1035 299623 : ExternalReference ExternalReference::roots_array_start(Isolate* isolate) {
1036 299623 : return ExternalReference(isolate->heap()->roots_array_start());
1037 : }
1038 :
1039 55528 : ExternalReference ExternalReference::allocation_sites_list_address(
1040 : Isolate* isolate) {
1041 55528 : return ExternalReference(isolate->heap()->allocation_sites_list_address());
1042 : }
1043 :
1044 1715717 : ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
1045 1715717 : return ExternalReference(isolate->stack_guard()->address_of_jslimit());
1046 : }
1047 :
1048 55321 : ExternalReference ExternalReference::address_of_real_stack_limit(
1049 : Isolate* isolate) {
1050 55321 : return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
1051 : }
1052 :
1053 686848 : ExternalReference ExternalReference::address_of_regexp_stack_limit(
1054 686848 : Isolate* isolate) {
1055 686848 : return ExternalReference(isolate->regexp_stack()->limit_address());
1056 : }
1057 :
1058 55435 : ExternalReference ExternalReference::address_of_regexp_dotall_flag(
1059 : Isolate* isolate) {
1060 55435 : return ExternalReference(&FLAG_harmony_regexp_dotall);
1061 : }
1062 :
1063 55373 : ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) {
1064 55373 : return ExternalReference(isolate->heap()->store_buffer_top_address());
1065 : }
1066 :
1067 55342 : ExternalReference ExternalReference::heap_is_marking_flag_address(
1068 : Isolate* isolate) {
1069 55342 : return ExternalReference(isolate->heap()->IsMarkingFlagAddress());
1070 : }
1071 :
1072 227347 : ExternalReference ExternalReference::new_space_allocation_top_address(
1073 : Isolate* isolate) {
1074 227347 : return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
1075 : }
1076 :
1077 192861 : ExternalReference ExternalReference::new_space_allocation_limit_address(
1078 : Isolate* isolate) {
1079 192861 : return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
1080 : }
1081 :
1082 56844 : ExternalReference ExternalReference::old_space_allocation_top_address(
1083 : Isolate* isolate) {
1084 56844 : return ExternalReference(isolate->heap()->OldSpaceAllocationTopAddress());
1085 : }
1086 :
1087 55511 : ExternalReference ExternalReference::old_space_allocation_limit_address(
1088 : Isolate* isolate) {
1089 55511 : return ExternalReference(isolate->heap()->OldSpaceAllocationLimitAddress());
1090 : }
1091 :
1092 58822 : ExternalReference ExternalReference::handle_scope_level_address(
1093 : Isolate* isolate) {
1094 58822 : return ExternalReference(HandleScope::current_level_address(isolate));
1095 : }
1096 :
1097 58822 : ExternalReference ExternalReference::handle_scope_next_address(
1098 : Isolate* isolate) {
1099 58822 : return ExternalReference(HandleScope::current_next_address(isolate));
1100 : }
1101 :
1102 58822 : ExternalReference ExternalReference::handle_scope_limit_address(
1103 : Isolate* isolate) {
1104 58822 : return ExternalReference(HandleScope::current_limit_address(isolate));
1105 : }
1106 :
1107 58822 : ExternalReference ExternalReference::scheduled_exception_address(
1108 : Isolate* isolate) {
1109 58822 : return ExternalReference(isolate->scheduled_exception_address());
1110 : }
1111 :
1112 107928 : ExternalReference ExternalReference::address_of_pending_message_obj(
1113 : Isolate* isolate) {
1114 107928 : return ExternalReference(isolate->pending_message_obj_address());
1115 : }
1116 :
1117 55335 : ExternalReference ExternalReference::address_of_min_int() {
1118 55335 : return ExternalReference(reinterpret_cast<void*>(&double_constants.min_int));
1119 : }
1120 :
1121 55335 : ExternalReference ExternalReference::address_of_one_half() {
1122 55335 : return ExternalReference(reinterpret_cast<void*>(&double_constants.one_half));
1123 : }
1124 :
1125 55311 : ExternalReference ExternalReference::address_of_minus_one_half() {
1126 : return ExternalReference(
1127 55311 : reinterpret_cast<void*>(&double_constants.minus_one_half));
1128 : }
1129 :
1130 55311 : ExternalReference ExternalReference::address_of_negative_infinity() {
1131 : return ExternalReference(
1132 55311 : reinterpret_cast<void*>(&double_constants.negative_infinity));
1133 : }
1134 :
1135 55317 : ExternalReference ExternalReference::address_of_the_hole_nan() {
1136 : return ExternalReference(
1137 55317 : reinterpret_cast<void*>(&double_constants.the_hole_nan));
1138 : }
1139 :
1140 55311 : ExternalReference ExternalReference::address_of_uint32_bias() {
1141 : return ExternalReference(
1142 55311 : reinterpret_cast<void*>(&double_constants.uint32_bias));
1143 : }
1144 :
1145 55316 : ExternalReference ExternalReference::address_of_float_abs_constant() {
1146 55316 : return ExternalReference(reinterpret_cast<void*>(&float_absolute_constant));
1147 : }
1148 :
1149 55317 : ExternalReference ExternalReference::address_of_float_neg_constant() {
1150 55317 : return ExternalReference(reinterpret_cast<void*>(&float_negate_constant));
1151 : }
1152 :
1153 55317 : ExternalReference ExternalReference::address_of_double_abs_constant() {
1154 55317 : return ExternalReference(reinterpret_cast<void*>(&double_absolute_constant));
1155 : }
1156 :
1157 55317 : ExternalReference ExternalReference::address_of_double_neg_constant() {
1158 55317 : return ExternalReference(reinterpret_cast<void*>(&double_negate_constant));
1159 : }
1160 :
1161 58822 : ExternalReference ExternalReference::is_profiling_address(Isolate* isolate) {
1162 58822 : return ExternalReference(isolate->is_profiling_address());
1163 : }
1164 :
1165 58791 : ExternalReference ExternalReference::invoke_function_callback(
1166 : Isolate* isolate) {
1167 : Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
1168 : ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL;
1169 : ApiFunction thunk_fun(thunk_address);
1170 58791 : return ExternalReference(&thunk_fun, thunk_type, isolate);
1171 : }
1172 :
1173 55342 : ExternalReference ExternalReference::invoke_accessor_getter_callback(
1174 : Isolate* isolate) {
1175 : Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
1176 : ExternalReference::Type thunk_type =
1177 : ExternalReference::PROFILING_GETTER_CALL;
1178 : ApiFunction thunk_fun(thunk_address);
1179 55342 : return ExternalReference(&thunk_fun, thunk_type, isolate);
1180 : }
1181 :
1182 : #ifndef V8_INTERPRETED_REGEXP
1183 :
1184 242437 : ExternalReference ExternalReference::re_check_stack_guard_state(
1185 : Isolate* isolate) {
1186 : Address function;
1187 : #if V8_TARGET_ARCH_X64
1188 : function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
1189 : #elif V8_TARGET_ARCH_IA32
1190 : function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
1191 : #elif V8_TARGET_ARCH_ARM64
1192 : function = FUNCTION_ADDR(RegExpMacroAssemblerARM64::CheckStackGuardState);
1193 : #elif V8_TARGET_ARCH_ARM
1194 : function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
1195 : #elif V8_TARGET_ARCH_PPC
1196 : function = FUNCTION_ADDR(RegExpMacroAssemblerPPC::CheckStackGuardState);
1197 : #elif V8_TARGET_ARCH_MIPS
1198 : function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
1199 : #elif V8_TARGET_ARCH_MIPS64
1200 : function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
1201 : #elif V8_TARGET_ARCH_S390
1202 : function = FUNCTION_ADDR(RegExpMacroAssemblerS390::CheckStackGuardState);
1203 : #else
1204 : UNREACHABLE();
1205 : #endif
1206 242437 : return ExternalReference(Redirect(isolate, function));
1207 : }
1208 :
1209 148859 : ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
1210 : return ExternalReference(
1211 148859 : Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
1212 : }
1213 :
1214 55576 : ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
1215 : Isolate* isolate) {
1216 : return ExternalReference(Redirect(
1217 : isolate,
1218 55576 : FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
1219 : }
1220 :
1221 60358 : ExternalReference ExternalReference::re_word_character_map() {
1222 : return ExternalReference(
1223 60358 : NativeRegExpMacroAssembler::word_character_map_address());
1224 : }
1225 :
1226 55621 : ExternalReference ExternalReference::address_of_static_offsets_vector(
1227 : Isolate* isolate) {
1228 : return ExternalReference(
1229 55621 : reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector()));
1230 : }
1231 :
1232 55621 : ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
1233 55621 : Isolate* isolate) {
1234 : return ExternalReference(
1235 55621 : isolate->regexp_stack()->memory_address());
1236 : }
1237 :
1238 55621 : ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
1239 55621 : Isolate* isolate) {
1240 55621 : return ExternalReference(isolate->regexp_stack()->memory_size_address());
1241 : }
1242 :
1243 : #endif // V8_INTERPRETED_REGEXP
1244 :
1245 55379 : ExternalReference ExternalReference::ieee754_acos_function(Isolate* isolate) {
1246 : return ExternalReference(
1247 55379 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::acos), BUILTIN_FP_CALL));
1248 : }
1249 :
1250 55378 : ExternalReference ExternalReference::ieee754_acosh_function(Isolate* isolate) {
1251 : return ExternalReference(Redirect(
1252 55378 : isolate, FUNCTION_ADDR(base::ieee754::acosh), BUILTIN_FP_FP_CALL));
1253 : }
1254 :
1255 55379 : ExternalReference ExternalReference::ieee754_asin_function(Isolate* isolate) {
1256 : return ExternalReference(
1257 55379 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::asin), BUILTIN_FP_CALL));
1258 : }
1259 :
1260 55378 : ExternalReference ExternalReference::ieee754_asinh_function(Isolate* isolate) {
1261 : return ExternalReference(Redirect(
1262 55378 : isolate, FUNCTION_ADDR(base::ieee754::asinh), BUILTIN_FP_FP_CALL));
1263 : }
1264 :
1265 55392 : ExternalReference ExternalReference::ieee754_atan_function(Isolate* isolate) {
1266 : return ExternalReference(
1267 55392 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::atan), BUILTIN_FP_CALL));
1268 : }
1269 :
1270 55378 : ExternalReference ExternalReference::ieee754_atanh_function(Isolate* isolate) {
1271 : return ExternalReference(Redirect(
1272 55378 : isolate, FUNCTION_ADDR(base::ieee754::atanh), BUILTIN_FP_FP_CALL));
1273 : }
1274 :
1275 55402 : ExternalReference ExternalReference::ieee754_atan2_function(Isolate* isolate) {
1276 : return ExternalReference(Redirect(
1277 55402 : isolate, FUNCTION_ADDR(base::ieee754::atan2), BUILTIN_FP_FP_CALL));
1278 : }
1279 :
1280 55378 : ExternalReference ExternalReference::ieee754_cbrt_function(Isolate* isolate) {
1281 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(base::ieee754::cbrt),
1282 55378 : BUILTIN_FP_FP_CALL));
1283 : }
1284 :
1285 55567 : ExternalReference ExternalReference::ieee754_cos_function(Isolate* isolate) {
1286 : return ExternalReference(
1287 55567 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::cos), BUILTIN_FP_CALL));
1288 : }
1289 :
1290 55386 : ExternalReference ExternalReference::ieee754_cosh_function(Isolate* isolate) {
1291 : return ExternalReference(
1292 55386 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::cosh), BUILTIN_FP_CALL));
1293 : }
1294 :
1295 55392 : ExternalReference ExternalReference::ieee754_exp_function(Isolate* isolate) {
1296 : return ExternalReference(
1297 55392 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::exp), BUILTIN_FP_CALL));
1298 : }
1299 :
1300 55378 : ExternalReference ExternalReference::ieee754_expm1_function(Isolate* isolate) {
1301 : return ExternalReference(Redirect(
1302 55378 : isolate, FUNCTION_ADDR(base::ieee754::expm1), BUILTIN_FP_FP_CALL));
1303 : }
1304 :
1305 55543 : ExternalReference ExternalReference::ieee754_log_function(Isolate* isolate) {
1306 : return ExternalReference(
1307 55543 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::log), BUILTIN_FP_CALL));
1308 : }
1309 :
1310 55378 : ExternalReference ExternalReference::ieee754_log1p_function(Isolate* isolate) {
1311 : return ExternalReference(
1312 55378 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::log1p), BUILTIN_FP_CALL));
1313 : }
1314 :
1315 55378 : ExternalReference ExternalReference::ieee754_log10_function(Isolate* isolate) {
1316 : return ExternalReference(
1317 55378 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::log10), BUILTIN_FP_CALL));
1318 : }
1319 :
1320 55378 : ExternalReference ExternalReference::ieee754_log2_function(Isolate* isolate) {
1321 : return ExternalReference(
1322 55378 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::log2), BUILTIN_FP_CALL));
1323 : }
1324 :
1325 55567 : ExternalReference ExternalReference::ieee754_sin_function(Isolate* isolate) {
1326 : return ExternalReference(
1327 55567 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::sin), BUILTIN_FP_CALL));
1328 : }
1329 :
1330 55386 : ExternalReference ExternalReference::ieee754_sinh_function(Isolate* isolate) {
1331 : return ExternalReference(
1332 55386 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::sinh), BUILTIN_FP_CALL));
1333 : }
1334 :
1335 55392 : ExternalReference ExternalReference::ieee754_tan_function(Isolate* isolate) {
1336 : return ExternalReference(
1337 55392 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::tan), BUILTIN_FP_CALL));
1338 : }
1339 :
1340 55386 : ExternalReference ExternalReference::ieee754_tanh_function(Isolate* isolate) {
1341 : return ExternalReference(
1342 55386 : Redirect(isolate, FUNCTION_ADDR(base::ieee754::tanh), BUILTIN_FP_CALL));
1343 : }
1344 :
1345 2338295 : void* libc_memchr(void* string, int character, size_t search_length) {
1346 2338295 : return memchr(string, character, search_length);
1347 : }
1348 :
1349 55403 : ExternalReference ExternalReference::libc_memchr_function(Isolate* isolate) {
1350 55403 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memchr)));
1351 : }
1352 :
1353 957 : void* libc_memcpy(void* dest, const void* src, size_t n) {
1354 957 : return memcpy(dest, src, n);
1355 : }
1356 :
1357 55342 : ExternalReference ExternalReference::libc_memcpy_function(Isolate* isolate) {
1358 55342 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memcpy)));
1359 : }
1360 :
1361 105 : void* libc_memmove(void* dest, const void* src, size_t n) {
1362 105 : return memmove(dest, src, n);
1363 : }
1364 :
1365 55342 : ExternalReference ExternalReference::libc_memmove_function(Isolate* isolate) {
1366 55342 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memmove)));
1367 : }
1368 :
1369 167080 : void* libc_memset(void* dest, int byte, size_t n) {
1370 : DCHECK_EQ(static_cast<char>(byte), byte);
1371 167080 : return memset(dest, byte, n);
1372 : }
1373 :
1374 55341 : ExternalReference ExternalReference::libc_memset_function(Isolate* isolate) {
1375 55341 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memset)));
1376 : }
1377 :
1378 55311 : ExternalReference ExternalReference::printf_function(Isolate* isolate) {
1379 55311 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(std::printf)));
1380 : }
1381 :
1382 : template <typename SubjectChar, typename PatternChar>
1383 221614 : ExternalReference ExternalReference::search_string_raw(Isolate* isolate) {
1384 : auto f = SearchStringRaw<SubjectChar, PatternChar>;
1385 221614 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f)));
1386 : }
1387 :
1388 56086 : ExternalReference ExternalReference::orderedhashmap_gethash_raw(
1389 : Isolate* isolate) {
1390 : auto f = OrderedHashMap::GetHash;
1391 56086 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f)));
1392 : }
1393 :
1394 55373 : ExternalReference ExternalReference::get_or_create_hash_raw(Isolate* isolate) {
1395 : typedef Smi* (*GetOrCreateHash)(Isolate * isolate, Object * key);
1396 : GetOrCreateHash f = Object::GetOrCreateHash;
1397 55373 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f)));
1398 : }
1399 :
1400 55537 : ExternalReference ExternalReference::try_internalize_string_function(
1401 : Isolate* isolate) {
1402 : return ExternalReference(Redirect(
1403 55537 : isolate, FUNCTION_ADDR(StringTable::LookupStringIfExists_NoAllocate)));
1404 : }
1405 :
1406 55311 : ExternalReference ExternalReference::check_object_type(Isolate* isolate) {
1407 55311 : return ExternalReference(Redirect(isolate, FUNCTION_ADDR(CheckObjectType)));
1408 : }
1409 :
1410 : #ifdef V8_INTL_SUPPORT
1411 55341 : ExternalReference ExternalReference::intl_convert_one_byte_to_lower(
1412 : Isolate* isolate) {
1413 : return ExternalReference(
1414 55341 : Redirect(isolate, FUNCTION_ADDR(ConvertOneByteToLower)));
1415 : }
1416 :
1417 55341 : ExternalReference ExternalReference::intl_to_latin1_lower_table(
1418 : Isolate* isolate) {
1419 55341 : uint8_t* ptr = const_cast<uint8_t*>(ToLatin1LowerTable());
1420 55341 : return ExternalReference(reinterpret_cast<Address>(ptr));
1421 : }
1422 : #endif // V8_INTL_SUPPORT
1423 :
1424 : // Explicit instantiations for all combinations of 1- and 2-byte strings.
1425 : template ExternalReference
1426 : ExternalReference::search_string_raw<const uint8_t, const uint8_t>(Isolate*);
1427 : template ExternalReference
1428 : ExternalReference::search_string_raw<const uint8_t, const uc16>(Isolate*);
1429 : template ExternalReference
1430 : ExternalReference::search_string_raw<const uc16, const uint8_t>(Isolate*);
1431 : template ExternalReference
1432 : ExternalReference::search_string_raw<const uc16, const uc16>(Isolate*);
1433 :
1434 0 : ExternalReference ExternalReference::page_flags(Page* page) {
1435 0 : return ExternalReference(reinterpret_cast<Address>(page) +
1436 0 : MemoryChunk::kFlagsOffset);
1437 : }
1438 :
1439 0 : ExternalReference ExternalReference::ForDeoptEntry(Address entry) {
1440 0 : return ExternalReference(entry);
1441 : }
1442 :
1443 55311 : ExternalReference ExternalReference::cpu_features() {
1444 : DCHECK(CpuFeatures::initialized_);
1445 55311 : return ExternalReference(&CpuFeatures::supported_);
1446 : }
1447 :
1448 56952 : ExternalReference ExternalReference::promise_hook_or_debug_is_active_address(
1449 : Isolate* isolate) {
1450 56952 : return ExternalReference(isolate->promise_hook_or_debug_is_active_address());
1451 : }
1452 :
1453 56718 : ExternalReference ExternalReference::debug_is_active_address(
1454 56718 : Isolate* isolate) {
1455 56718 : return ExternalReference(isolate->debug()->is_active_address());
1456 : }
1457 :
1458 55590 : ExternalReference ExternalReference::debug_hook_on_function_call_address(
1459 55590 : Isolate* isolate) {
1460 55590 : return ExternalReference(isolate->debug()->hook_on_function_call_address());
1461 : }
1462 :
1463 55509 : ExternalReference ExternalReference::runtime_function_table_address(
1464 : Isolate* isolate) {
1465 : return ExternalReference(
1466 55509 : const_cast<Runtime::Function*>(Runtime::RuntimeFunctionTable(isolate)));
1467 : }
1468 :
1469 0 : double power_helper(Isolate* isolate, double x, double y) {
1470 0 : int y_int = static_cast<int>(y);
1471 0 : if (y == y_int) {
1472 0 : return power_double_int(x, y_int); // Returns 1 if exponent is 0.
1473 : }
1474 0 : if (y == 0.5) {
1475 0 : lazily_initialize_fast_sqrt(isolate);
1476 : return (std::isinf(x)) ? V8_INFINITY
1477 0 : : fast_sqrt(x + 0.0, isolate); // Convert -0 to +0.
1478 : }
1479 0 : if (y == -0.5) {
1480 0 : lazily_initialize_fast_sqrt(isolate);
1481 : return (std::isinf(x)) ? 0 : 1.0 / fast_sqrt(x + 0.0,
1482 0 : isolate); // Convert -0 to +0.
1483 : }
1484 0 : return power_double_double(x, y);
1485 : }
1486 :
1487 : // Helper function to compute x^y, where y is known to be an
1488 : // integer. Uses binary decomposition to limit the number of
1489 : // multiplications; see the discussion in "Hacker's Delight" by Henry
1490 : // S. Warren, Jr., figure 11-6, page 213.
1491 0 : double power_double_int(double x, int y) {
1492 0 : double m = (y < 0) ? 1 / x : x;
1493 0 : unsigned n = (y < 0) ? -y : y;
1494 : double p = 1;
1495 0 : while (n != 0) {
1496 0 : if ((n & 1) != 0) p *= m;
1497 0 : m *= m;
1498 0 : if ((n & 2) != 0) p *= m;
1499 0 : m *= m;
1500 0 : n >>= 2;
1501 : }
1502 0 : return p;
1503 : }
1504 :
1505 2812 : double power_double_double(double x, double y) {
1506 : // The checks for special cases can be dropped in ia32 because it has already
1507 : // been done in generated code before bailing out here.
1508 2965 : if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) {
1509 : return std::numeric_limits<double>::quiet_NaN();
1510 : }
1511 2294 : return Pow(x, y);
1512 : }
1513 :
1514 0 : double modulo_double_double(double x, double y) { return Modulo(x, y); }
1515 :
1516 55342 : ExternalReference ExternalReference::power_double_double_function(
1517 : Isolate* isolate) {
1518 : return ExternalReference(Redirect(isolate,
1519 : FUNCTION_ADDR(power_double_double),
1520 55342 : BUILTIN_FP_FP_CALL));
1521 : }
1522 :
1523 55311 : ExternalReference ExternalReference::mod_two_doubles_operation(
1524 : Isolate* isolate) {
1525 : return ExternalReference(Redirect(
1526 55311 : isolate, FUNCTION_ADDR(modulo_double_double), BUILTIN_FP_FP_CALL));
1527 : }
1528 :
1529 55404 : ExternalReference ExternalReference::debug_last_step_action_address(
1530 55404 : Isolate* isolate) {
1531 55404 : return ExternalReference(isolate->debug()->last_step_action_address());
1532 : }
1533 :
1534 55342 : ExternalReference ExternalReference::debug_suspended_generator_address(
1535 55342 : Isolate* isolate) {
1536 55342 : return ExternalReference(isolate->debug()->suspended_generator_address());
1537 : }
1538 :
1539 55993 : ExternalReference ExternalReference::debug_restart_fp_address(
1540 55993 : Isolate* isolate) {
1541 55993 : return ExternalReference(isolate->debug()->restart_fp_address());
1542 : }
1543 :
1544 589 : ExternalReference ExternalReference::fixed_typed_array_base_data_offset() {
1545 : return ExternalReference(reinterpret_cast<void*>(
1546 589 : FixedTypedArrayBase::kDataOffset - kHeapObjectTag));
1547 : }
1548 :
1549 679340 : bool operator==(ExternalReference lhs, ExternalReference rhs) {
1550 679340 : return lhs.address() == rhs.address();
1551 : }
1552 :
1553 0 : bool operator!=(ExternalReference lhs, ExternalReference rhs) {
1554 0 : return !(lhs == rhs);
1555 : }
1556 :
1557 2600501 : size_t hash_value(ExternalReference reference) {
1558 2600505 : return base::hash<Address>()(reference.address());
1559 : }
1560 :
1561 0 : std::ostream& operator<<(std::ostream& os, ExternalReference reference) {
1562 : os << static_cast<const void*>(reference.address());
1563 0 : const Runtime::Function* fn = Runtime::FunctionForEntry(reference.address());
1564 0 : if (fn) os << "<" << fn->name << ".entry>";
1565 0 : return os;
1566 : }
1567 :
1568 36 : ConstantPoolBuilder::ConstantPoolBuilder(int ptr_reach_bits,
1569 108 : int double_reach_bits) {
1570 36 : info_[ConstantPoolEntry::INTPTR].entries.reserve(64);
1571 36 : info_[ConstantPoolEntry::INTPTR].regular_reach_bits = ptr_reach_bits;
1572 36 : info_[ConstantPoolEntry::DOUBLE].regular_reach_bits = double_reach_bits;
1573 36 : }
1574 :
1575 942 : ConstantPoolEntry::Access ConstantPoolBuilder::NextAccess(
1576 : ConstantPoolEntry::Type type) const {
1577 942 : const PerTypeEntryInfo& info = info_[type];
1578 :
1579 942 : if (info.overflow()) return ConstantPoolEntry::OVERFLOWED;
1580 :
1581 822 : int dbl_count = info_[ConstantPoolEntry::DOUBLE].regular_count;
1582 822 : int dbl_offset = dbl_count * kDoubleSize;
1583 822 : int ptr_count = info_[ConstantPoolEntry::INTPTR].regular_count;
1584 822 : int ptr_offset = ptr_count * kPointerSize + dbl_offset;
1585 :
1586 822 : if (type == ConstantPoolEntry::DOUBLE) {
1587 : // Double overflow detection must take into account the reach for both types
1588 378 : int ptr_reach_bits = info_[ConstantPoolEntry::INTPTR].regular_reach_bits;
1589 1134 : if (!is_uintn(dbl_offset, info.regular_reach_bits) ||
1590 246 : (ptr_count > 0 &&
1591 246 : !is_uintn(ptr_offset + kDoubleSize - kPointerSize, ptr_reach_bits))) {
1592 : return ConstantPoolEntry::OVERFLOWED;
1593 : }
1594 : } else {
1595 : DCHECK(type == ConstantPoolEntry::INTPTR);
1596 888 : if (!is_uintn(ptr_offset, info.regular_reach_bits)) {
1597 : return ConstantPoolEntry::OVERFLOWED;
1598 : }
1599 : }
1600 :
1601 720 : return ConstantPoolEntry::REGULAR;
1602 : }
1603 :
1604 684 : ConstantPoolEntry::Access ConstantPoolBuilder::AddEntry(
1605 5064 : ConstantPoolEntry& entry, ConstantPoolEntry::Type type) {
1606 : DCHECK(!emitted_label_.is_bound());
1607 684 : PerTypeEntryInfo& info = info_[type];
1608 : const int entry_size = ConstantPoolEntry::size(type);
1609 : bool merged = false;
1610 :
1611 684 : if (entry.sharing_ok()) {
1612 : // Try to merge entries
1613 660 : std::vector<ConstantPoolEntry>::iterator it = info.shared_entries.begin();
1614 660 : int end = static_cast<int>(info.shared_entries.size());
1615 8568 : for (int i = 0; i < end; i++, it++) {
1616 3696 : if ((entry_size == kPointerSize) ? entry.value() == it->value()
1617 : : entry.value64() == it->value64()) {
1618 : // Merge with found entry.
1619 : entry.set_merged_index(i);
1620 : merged = true;
1621 72 : break;
1622 : }
1623 : }
1624 : }
1625 :
1626 : // By definition, merged entries have regular access.
1627 : DCHECK(!merged || entry.merged_index() < info.regular_count);
1628 : ConstantPoolEntry::Access access =
1629 684 : (merged ? ConstantPoolEntry::REGULAR : NextAccess(type));
1630 :
1631 : // Enforce an upper bound on search time by limiting the search to
1632 : // unique sharable entries which fit in the regular section.
1633 684 : if (entry.sharing_ok() && !merged && access == ConstantPoolEntry::REGULAR) {
1634 408 : info.shared_entries.push_back(entry);
1635 : } else {
1636 336 : info.entries.push_back(entry);
1637 : }
1638 :
1639 : // We're done if we found a match or have already triggered the
1640 : // overflow state.
1641 1296 : if (merged || info.overflow()) return access;
1642 :
1643 492 : if (access == ConstantPoolEntry::REGULAR) {
1644 432 : info.regular_count++;
1645 : } else {
1646 60 : info.overflow_start = static_cast<int>(info.entries.size()) - 1;
1647 : }
1648 :
1649 : return access;
1650 : }
1651 :
1652 0 : void ConstantPoolBuilder::EmitSharedEntries(Assembler* assm,
1653 : ConstantPoolEntry::Type type) {
1654 0 : PerTypeEntryInfo& info = info_[type];
1655 0 : std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
1656 : const int entry_size = ConstantPoolEntry::size(type);
1657 0 : int base = emitted_label_.pos();
1658 : DCHECK_GT(base, 0);
1659 0 : int shared_end = static_cast<int>(shared_entries.size());
1660 : std::vector<ConstantPoolEntry>::iterator shared_it = shared_entries.begin();
1661 0 : for (int i = 0; i < shared_end; i++, shared_it++) {
1662 0 : int offset = assm->pc_offset() - base;
1663 : shared_it->set_offset(offset); // Save offset for merged entries.
1664 : if (entry_size == kPointerSize) {
1665 0 : assm->dp(shared_it->value());
1666 : } else {
1667 : assm->dq(shared_it->value64());
1668 : }
1669 : DCHECK(is_uintn(offset, info.regular_reach_bits));
1670 :
1671 : // Patch load sequence with correct offset.
1672 : assm->PatchConstantPoolAccessInstruction(shared_it->position(), offset,
1673 0 : ConstantPoolEntry::REGULAR, type);
1674 : }
1675 0 : }
1676 :
1677 0 : void ConstantPoolBuilder::EmitGroup(Assembler* assm,
1678 : ConstantPoolEntry::Access access,
1679 : ConstantPoolEntry::Type type) {
1680 0 : PerTypeEntryInfo& info = info_[type];
1681 : const bool overflow = info.overflow();
1682 0 : std::vector<ConstantPoolEntry>& entries = info.entries;
1683 : std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
1684 : const int entry_size = ConstantPoolEntry::size(type);
1685 0 : int base = emitted_label_.pos();
1686 : DCHECK_GT(base, 0);
1687 : int begin;
1688 : int end;
1689 :
1690 0 : if (access == ConstantPoolEntry::REGULAR) {
1691 : // Emit any shared entries first
1692 0 : EmitSharedEntries(assm, type);
1693 : }
1694 :
1695 0 : if (access == ConstantPoolEntry::REGULAR) {
1696 : begin = 0;
1697 0 : end = overflow ? info.overflow_start : static_cast<int>(entries.size());
1698 : } else {
1699 : DCHECK(access == ConstantPoolEntry::OVERFLOWED);
1700 0 : if (!overflow) return;
1701 0 : begin = info.overflow_start;
1702 0 : end = static_cast<int>(entries.size());
1703 : }
1704 :
1705 : std::vector<ConstantPoolEntry>::iterator it = entries.begin();
1706 0 : if (begin > 0) std::advance(it, begin);
1707 0 : for (int i = begin; i < end; i++, it++) {
1708 : // Update constant pool if necessary and get the entry's offset.
1709 : int offset;
1710 : ConstantPoolEntry::Access entry_access;
1711 0 : if (!it->is_merged()) {
1712 : // Emit new entry
1713 : offset = assm->pc_offset() - base;
1714 : entry_access = access;
1715 : if (entry_size == kPointerSize) {
1716 0 : assm->dp(it->value());
1717 : } else {
1718 : assm->dq(it->value64());
1719 : }
1720 : } else {
1721 : // Retrieve offset from shared entry.
1722 : offset = shared_entries[it->merged_index()].offset();
1723 : entry_access = ConstantPoolEntry::REGULAR;
1724 : }
1725 :
1726 : DCHECK(entry_access == ConstantPoolEntry::OVERFLOWED ||
1727 : is_uintn(offset, info.regular_reach_bits));
1728 :
1729 : // Patch load sequence with correct offset.
1730 : assm->PatchConstantPoolAccessInstruction(it->position(), offset,
1731 0 : entry_access, type);
1732 : }
1733 : }
1734 :
1735 : // Emit and return position of pool. Zero implies no constant pool.
1736 0 : int ConstantPoolBuilder::Emit(Assembler* assm) {
1737 0 : bool emitted = emitted_label_.is_bound();
1738 : bool empty = IsEmpty();
1739 :
1740 0 : if (!emitted) {
1741 : // Mark start of constant pool. Align if necessary.
1742 0 : if (!empty) assm->DataAlign(kDoubleSize);
1743 0 : assm->bind(&emitted_label_);
1744 0 : if (!empty) {
1745 : // Emit in groups based on access and type.
1746 : // Emit doubles first for alignment purposes.
1747 0 : EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::DOUBLE);
1748 0 : EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::INTPTR);
1749 0 : if (info_[ConstantPoolEntry::DOUBLE].overflow()) {
1750 0 : assm->DataAlign(kDoubleSize);
1751 : EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
1752 0 : ConstantPoolEntry::DOUBLE);
1753 : }
1754 0 : if (info_[ConstantPoolEntry::INTPTR].overflow()) {
1755 : EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
1756 0 : ConstantPoolEntry::INTPTR);
1757 : }
1758 : }
1759 : }
1760 :
1761 0 : return !empty ? emitted_label_.pos() : 0;
1762 : }
1763 :
1764 43091 : HeapObjectRequest::HeapObjectRequest(double heap_number, int offset)
1765 43091 : : kind_(kHeapNumber), offset_(offset) {
1766 43091 : value_.heap_number = heap_number;
1767 : DCHECK(!IsSmiDouble(value_.heap_number));
1768 43091 : }
1769 :
1770 45553 : HeapObjectRequest::HeapObjectRequest(CodeStub* code_stub, int offset)
1771 45553 : : kind_(kCodeStub), offset_(offset) {
1772 45553 : value_.code_stub = code_stub;
1773 : DCHECK_NOT_NULL(value_.code_stub);
1774 45553 : }
1775 :
1776 : // Platform specific but identical code for all the platforms.
1777 :
1778 236610 : void Assembler::RecordDeoptReason(DeoptimizeReason reason,
1779 : SourcePosition position, int id) {
1780 : EnsureSpace ensure_space(this);
1781 236610 : RecordRelocInfo(RelocInfo::DEOPT_SCRIPT_OFFSET, position.ScriptOffset());
1782 236610 : RecordRelocInfo(RelocInfo::DEOPT_INLINING_ID, position.InliningId());
1783 236611 : RecordRelocInfo(RelocInfo::DEOPT_REASON, static_cast<int>(reason));
1784 236611 : RecordRelocInfo(RelocInfo::DEOPT_ID, id);
1785 236611 : }
1786 :
1787 1527904 : void Assembler::RecordComment(const char* msg) {
1788 1527904 : if (FLAG_code_comments) {
1789 : EnsureSpace ensure_space(this);
1790 0 : RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
1791 : }
1792 1527904 : }
1793 :
1794 0 : void Assembler::DataAlign(int m) {
1795 : DCHECK(m >= 2 && base::bits::IsPowerOfTwo(m));
1796 0 : while ((pc_offset() & (m - 1)) != 0) {
1797 0 : db(0);
1798 : }
1799 0 : }
1800 :
1801 88646 : void Assembler::RequestHeapObject(HeapObjectRequest request) {
1802 88646 : request.set_offset(pc_offset());
1803 : heap_object_requests_.push_front(request);
1804 88654 : }
1805 :
1806 : namespace {
1807 : int caller_saved_codes[kNumJSCallerSaved];
1808 : }
1809 :
1810 53977 : void SetUpJSCallerSavedCodeData() {
1811 : int i = 0;
1812 917609 : for (int r = 0; r < kNumRegs; r++)
1813 863632 : if ((kJSCallerSaved & (1 << r)) != 0) caller_saved_codes[i++] = r;
1814 :
1815 : DCHECK_EQ(i, kNumJSCallerSaved);
1816 53977 : }
1817 :
1818 0 : int JSCallerSavedCode(int n) {
1819 : DCHECK(0 <= n && n < kNumJSCallerSaved);
1820 0 : return caller_saved_codes[n];
1821 : }
1822 :
1823 : } // namespace internal
1824 : } // namespace v8
|