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