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