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