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 "assembler.h" 36 37 #include <cmath> 38 #include "api.h" 39 #include "builtins.h" 40 #include "counters.h" 41 #include "cpu.h" 42 #include "debug.h" 43 #include "deoptimizer.h" 44 #include "execution.h" 45 #include "ic.h" 46 #include "isolate.h" 47 #include "jsregexp.h" 48 #include "lazy-instance.h" 49 #include "platform.h" 50 #include "regexp-macro-assembler.h" 51 #include "regexp-stack.h" 52 #include "runtime.h" 53 #include "serialize.h" 54 #include "store-buffer-inl.h" 55 #include "stub-cache.h" 56 #include "token.h" 57 58 #if V8_TARGET_ARCH_IA32 59 #include "ia32/assembler-ia32-inl.h" 60 #elif V8_TARGET_ARCH_X64 61 #include "x64/assembler-x64-inl.h" 62 #elif V8_TARGET_ARCH_ARM 63 #include "arm/assembler-arm-inl.h" 64 #elif V8_TARGET_ARCH_MIPS 65 #include "mips/assembler-mips-inl.h" 66 #else 67 #error "Unknown architecture." 68 #endif 69 70 // Include native regexp-macro-assembler. 71 #ifndef V8_INTERPRETED_REGEXP 72 #if V8_TARGET_ARCH_IA32 73 #include "ia32/regexp-macro-assembler-ia32.h" 74 #elif V8_TARGET_ARCH_X64 75 #include "x64/regexp-macro-assembler-x64.h" 76 #elif V8_TARGET_ARCH_ARM 77 #include "arm/regexp-macro-assembler-arm.h" 78 #elif V8_TARGET_ARCH_MIPS 79 #include "mips/regexp-macro-assembler-mips.h" 80 #else // Unknown architecture. 81 #error "Unknown architecture." 82 #endif // Target architecture. 83 #endif // V8_INTERPRETED_REGEXP 84 85 namespace v8 { 86 namespace internal { 87 88 // ----------------------------------------------------------------------------- 89 // Common double constants. 90 91 struct DoubleConstant BASE_EMBEDDED { 92 double min_int; 93 double one_half; 94 double minus_one_half; 95 double minus_zero; 96 double zero; 97 double uint8_max_value; 98 double negative_infinity; 99 double canonical_non_hole_nan; 100 double the_hole_nan; 101 }; 102 103 static DoubleConstant double_constants; 104 105 const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING"; 106 107 static bool math_exp_data_initialized = false; 108 static Mutex* math_exp_data_mutex = NULL; 109 static double* math_exp_constants_array = NULL; 110 static double* math_exp_log_table_array = NULL; 111 112 // ----------------------------------------------------------------------------- 113 // Implementation of AssemblerBase 114 115 AssemblerBase::AssemblerBase(Isolate* isolate, void* buffer, int buffer_size) 116 : isolate_(isolate), 117 jit_cookie_(0), 118 enabled_cpu_features_(0), 119 emit_debug_code_(FLAG_debug_code), 120 predictable_code_size_(false) { 121 if (FLAG_mask_constants_with_cookie && isolate != NULL) { 122 jit_cookie_ = V8::RandomPrivate(isolate); 123 } 124 125 if (buffer == NULL) { 126 // Do our own buffer management. 127 if (buffer_size <= kMinimalBufferSize) { 128 buffer_size = kMinimalBufferSize; 129 if (isolate->assembler_spare_buffer() != NULL) { 130 buffer = isolate->assembler_spare_buffer(); 131 isolate->set_assembler_spare_buffer(NULL); 132 } 133 } 134 if (buffer == NULL) buffer = NewArray<byte>(buffer_size); 135 own_buffer_ = true; 136 } else { 137 // Use externally provided buffer instead. 138 ASSERT(buffer_size > 0); 139 own_buffer_ = false; 140 } 141 buffer_ = static_cast<byte*>(buffer); 142 buffer_size_ = buffer_size; 143 144 pc_ = buffer_; 145 } 146 147 148 AssemblerBase::~AssemblerBase() { 149 if (own_buffer_) { 150 if (isolate() != NULL && 151 isolate()->assembler_spare_buffer() == NULL && 152 buffer_size_ == kMinimalBufferSize) { 153 isolate()->set_assembler_spare_buffer(buffer_); 154 } else { 155 DeleteArray(buffer_); 156 } 157 } 158 } 159 160 161 // ----------------------------------------------------------------------------- 162 // Implementation of PredictableCodeSizeScope 163 164 PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler, 165 int expected_size) 166 : assembler_(assembler), 167 expected_size_(expected_size), 168 start_offset_(assembler->pc_offset()), 169 old_value_(assembler->predictable_code_size()) { 170 assembler_->set_predictable_code_size(true); 171 } 172 173 174 PredictableCodeSizeScope::~PredictableCodeSizeScope() { 175 // TODO(svenpanne) Remove the 'if' when everything works. 176 if (expected_size_ >= 0) { 177 CHECK_EQ(expected_size_, assembler_->pc_offset() - start_offset_); 178 } 179 assembler_->set_predictable_code_size(old_value_); 180 } 181 182 183 // ----------------------------------------------------------------------------- 184 // Implementation of CpuFeatureScope 185 186 #ifdef DEBUG 187 CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f) 188 : assembler_(assembler) { 189 ASSERT(CpuFeatures::IsSafeForSnapshot(f)); 190 old_enabled_ = assembler_->enabled_cpu_features(); 191 uint64_t mask = static_cast<uint64_t>(1) << f; 192 // TODO(svenpanne) This special case below doesn't belong here! 193 #if V8_TARGET_ARCH_ARM 194 // ARMv7 is implied by VFP3. 195 if (f == VFP3) { 196 mask |= static_cast<uint64_t>(1) << ARMv7; 197 } 198 #endif 199 assembler_->set_enabled_cpu_features(old_enabled_ | mask); 200 } 201 202 203 CpuFeatureScope::~CpuFeatureScope() { 204 assembler_->set_enabled_cpu_features(old_enabled_); 205 } 206 #endif 207 208 209 // ----------------------------------------------------------------------------- 210 // Implementation of Label 211 212 int Label::pos() const { 213 if (pos_ < 0) return -pos_ - 1; 214 if (pos_ > 0) return pos_ - 1; 215 UNREACHABLE(); 216 return 0; 217 } 218 219 220 // ----------------------------------------------------------------------------- 221 // Implementation of RelocInfoWriter and RelocIterator 222 // 223 // Relocation information is written backwards in memory, from high addresses 224 // towards low addresses, byte by byte. Therefore, in the encodings listed 225 // below, the first byte listed it at the highest address, and successive 226 // bytes in the record are at progressively lower addresses. 227 // 228 // Encoding 229 // 230 // The most common modes are given single-byte encodings. Also, it is 231 // easy to identify the type of reloc info and skip unwanted modes in 232 // an iteration. 233 // 234 // The encoding relies on the fact that there are fewer than 14 235 // different relocation modes using standard non-compact encoding. 236 // 237 // The first byte of a relocation record has a tag in its low 2 bits: 238 // Here are the record schemes, depending on the low tag and optional higher 239 // tags. 240 // 241 // Low tag: 242 // 00: embedded_object: [6-bit pc delta] 00 243 // 244 // 01: code_target: [6-bit pc delta] 01 245 // 246 // 10: short_data_record: [6-bit pc delta] 10 followed by 247 // [6-bit data delta] [2-bit data type tag] 248 // 249 // 11: long_record [2-bit high tag][4 bit middle_tag] 11 250 // followed by variable data depending on type. 251 // 252 // 2-bit data type tags, used in short_data_record and data_jump long_record: 253 // code_target_with_id: 00 254 // position: 01 255 // statement_position: 10 256 // comment: 11 (not used in short_data_record) 257 // 258 // Long record format: 259 // 4-bit middle_tag: 260 // 0000 - 1100 : Short record for RelocInfo::Mode middle_tag + 2 261 // (The middle_tag encodes rmode - RelocInfo::LAST_COMPACT_ENUM, 262 // and is between 0000 and 1100) 263 // The format is: 264 // 00 [4 bit middle_tag] 11 followed by 265 // 00 [6 bit pc delta] 266 // 267 // 1101: constant pool. Used on ARM only for now. 268 // The format is: 11 1101 11 269 // signed int (size of the constant pool). 270 // 1110: long_data_record 271 // The format is: [2-bit data_type_tag] 1110 11 272 // signed intptr_t, lowest byte written first 273 // (except data_type code_target_with_id, which 274 // is followed by a signed int, not intptr_t.) 275 // 276 // 1111: long_pc_jump 277 // The format is: 278 // pc-jump: 00 1111 11, 279 // 00 [6 bits pc delta] 280 // or 281 // pc-jump (variable length): 282 // 01 1111 11, 283 // [7 bits data] 0 284 // ... 285 // [7 bits data] 1 286 // (Bits 6..31 of pc delta, with leading zeroes 287 // dropped, and last non-zero chunk tagged with 1.) 288 289 290 const int kMaxStandardNonCompactModes = 14; 291 292 const int kTagBits = 2; 293 const int kTagMask = (1 << kTagBits) - 1; 294 const int kExtraTagBits = 4; 295 const int kLocatableTypeTagBits = 2; 296 const int kSmallDataBits = kBitsPerByte - kLocatableTypeTagBits; 297 298 const int kEmbeddedObjectTag = 0; 299 const int kCodeTargetTag = 1; 300 const int kLocatableTag = 2; 301 const int kDefaultTag = 3; 302 303 const int kPCJumpExtraTag = (1 << kExtraTagBits) - 1; 304 305 const int kSmallPCDeltaBits = kBitsPerByte - kTagBits; 306 const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1; 307 const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask; 308 309 const int kVariableLengthPCJumpTopTag = 1; 310 const int kChunkBits = 7; 311 const int kChunkMask = (1 << kChunkBits) - 1; 312 const int kLastChunkTagBits = 1; 313 const int kLastChunkTagMask = 1; 314 const int kLastChunkTag = 1; 315 316 317 const int kDataJumpExtraTag = kPCJumpExtraTag - 1; 318 319 const int kCodeWithIdTag = 0; 320 const int kNonstatementPositionTag = 1; 321 const int kStatementPositionTag = 2; 322 const int kCommentTag = 3; 323 324 const int kConstPoolExtraTag = kPCJumpExtraTag - 2; 325 const int kConstPoolTag = 3; 326 327 328 uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) { 329 // Return if the pc_delta can fit in kSmallPCDeltaBits bits. 330 // Otherwise write a variable length PC jump for the bits that do 331 // not fit in the kSmallPCDeltaBits bits. 332 if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta; 333 WriteExtraTag(kPCJumpExtraTag, kVariableLengthPCJumpTopTag); 334 uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits; 335 ASSERT(pc_jump > 0); 336 // Write kChunkBits size chunks of the pc_jump. 337 for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) { 338 byte b = pc_jump & kChunkMask; 339 *--pos_ = b << kLastChunkTagBits; 340 } 341 // Tag the last chunk so it can be identified. 342 *pos_ = *pos_ | kLastChunkTag; 343 // Return the remaining kSmallPCDeltaBits of the pc_delta. 344 return pc_delta & kSmallPCDeltaMask; 345 } 346 347 348 void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) { 349 // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump. 350 pc_delta = WriteVariableLengthPCJump(pc_delta); 351 *--pos_ = pc_delta << kTagBits | tag; 352 } 353 354 355 void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) { 356 *--pos_ = static_cast<byte>(data_delta << kLocatableTypeTagBits | tag); 357 } 358 359 360 void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) { 361 *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) | 362 extra_tag << kTagBits | 363 kDefaultTag); 364 } 365 366 367 void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) { 368 // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump. 369 pc_delta = WriteVariableLengthPCJump(pc_delta); 370 WriteExtraTag(extra_tag, 0); 371 *--pos_ = pc_delta; 372 } 373 374 375 void RelocInfoWriter::WriteExtraTaggedIntData(int data_delta, int top_tag) { 376 WriteExtraTag(kDataJumpExtraTag, top_tag); 377 for (int i = 0; i < kIntSize; i++) { 378 *--pos_ = static_cast<byte>(data_delta); 379 // Signed right shift is arithmetic shift. Tested in test-utils.cc. 380 data_delta = data_delta >> kBitsPerByte; 381 } 382 } 383 384 385 void RelocInfoWriter::WriteExtraTaggedConstPoolData(int data) { 386 WriteExtraTag(kConstPoolExtraTag, kConstPoolTag); 387 for (int i = 0; i < kIntSize; i++) { 388 *--pos_ = static_cast<byte>(data); 389 // Signed right shift is arithmetic shift. Tested in test-utils.cc. 390 data = data >> kBitsPerByte; 391 } 392 } 393 394 395 void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) { 396 WriteExtraTag(kDataJumpExtraTag, top_tag); 397 for (int i = 0; i < kIntptrSize; i++) { 398 *--pos_ = static_cast<byte>(data_delta); 399 // Signed right shift is arithmetic shift. Tested in test-utils.cc. 400 data_delta = data_delta >> kBitsPerByte; 401 } 402 } 403 404 405 void RelocInfoWriter::Write(const RelocInfo* rinfo) { 406 #ifdef DEBUG 407 byte* begin_pos = pos_; 408 #endif 409 ASSERT(rinfo->rmode() < RelocInfo::NUMBER_OF_MODES); 410 ASSERT(rinfo->pc() - last_pc_ >= 0); 411 ASSERT(RelocInfo::LAST_STANDARD_NONCOMPACT_ENUM - RelocInfo::LAST_COMPACT_ENUM 412 <= kMaxStandardNonCompactModes); 413 // Use unsigned delta-encoding for pc. 414 uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_); 415 RelocInfo::Mode rmode = rinfo->rmode(); 416 417 // The two most common modes are given small tags, and usually fit in a byte. 418 if (rmode == RelocInfo::EMBEDDED_OBJECT) { 419 WriteTaggedPC(pc_delta, kEmbeddedObjectTag); 420 } else if (rmode == RelocInfo::CODE_TARGET) { 421 WriteTaggedPC(pc_delta, kCodeTargetTag); 422 ASSERT(begin_pos - pos_ <= RelocInfo::kMaxCallSize); 423 } else if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { 424 // Use signed delta-encoding for id. 425 ASSERT(static_cast<int>(rinfo->data()) == rinfo->data()); 426 int id_delta = static_cast<int>(rinfo->data()) - last_id_; 427 // Check if delta is small enough to fit in a tagged byte. 428 if (is_intn(id_delta, kSmallDataBits)) { 429 WriteTaggedPC(pc_delta, kLocatableTag); 430 WriteTaggedData(id_delta, kCodeWithIdTag); 431 } else { 432 // Otherwise, use costly encoding. 433 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag); 434 WriteExtraTaggedIntData(id_delta, kCodeWithIdTag); 435 } 436 last_id_ = static_cast<int>(rinfo->data()); 437 } else if (RelocInfo::IsPosition(rmode)) { 438 // Use signed delta-encoding for position. 439 ASSERT(static_cast<int>(rinfo->data()) == rinfo->data()); 440 int pos_delta = static_cast<int>(rinfo->data()) - last_position_; 441 int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag 442 : kStatementPositionTag; 443 // Check if delta is small enough to fit in a tagged byte. 444 if (is_intn(pos_delta, kSmallDataBits)) { 445 WriteTaggedPC(pc_delta, kLocatableTag); 446 WriteTaggedData(pos_delta, pos_type_tag); 447 } else { 448 // Otherwise, use costly encoding. 449 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag); 450 WriteExtraTaggedIntData(pos_delta, pos_type_tag); 451 } 452 last_position_ = static_cast<int>(rinfo->data()); 453 } else if (RelocInfo::IsComment(rmode)) { 454 // Comments are normally not generated, so we use the costly encoding. 455 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag); 456 WriteExtraTaggedData(rinfo->data(), kCommentTag); 457 ASSERT(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize); 458 } else if (RelocInfo::IsConstPool(rmode)) { 459 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag); 460 WriteExtraTaggedConstPoolData(static_cast<int>(rinfo->data())); 461 } else { 462 ASSERT(rmode > RelocInfo::LAST_COMPACT_ENUM); 463 int saved_mode = rmode - RelocInfo::LAST_COMPACT_ENUM; 464 // For all other modes we simply use the mode as the extra tag. 465 // None of these modes need a data component. 466 ASSERT(saved_mode < kPCJumpExtraTag && saved_mode < kDataJumpExtraTag); 467 WriteExtraTaggedPC(pc_delta, saved_mode); 468 } 469 last_pc_ = rinfo->pc(); 470 #ifdef DEBUG 471 ASSERT(begin_pos - pos_ <= kMaxSize); 472 #endif 473 } 474 475 476 inline int RelocIterator::AdvanceGetTag() { 477 return *--pos_ & kTagMask; 478 } 479 480 481 inline int RelocIterator::GetExtraTag() { 482 return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1); 483 } 484 485 486 inline int RelocIterator::GetTopTag() { 487 return *pos_ >> (kTagBits + kExtraTagBits); 488 } 489 490 491 inline void RelocIterator::ReadTaggedPC() { 492 rinfo_.pc_ += *pos_ >> kTagBits; 493 } 494 495 496 inline void RelocIterator::AdvanceReadPC() { 497 rinfo_.pc_ += *--pos_; 498 } 499 500 501 void RelocIterator::AdvanceReadId() { 502 int x = 0; 503 for (int i = 0; i < kIntSize; i++) { 504 x |= static_cast<int>(*--pos_) << i * kBitsPerByte; 505 } 506 last_id_ += x; 507 rinfo_.data_ = last_id_; 508 } 509 510 511 void RelocIterator::AdvanceReadConstPoolData() { 512 int x = 0; 513 for (int i = 0; i < kIntSize; i++) { 514 x |= static_cast<int>(*--pos_) << i * kBitsPerByte; 515 } 516 rinfo_.data_ = x; 517 } 518 519 520 void RelocIterator::AdvanceReadPosition() { 521 int x = 0; 522 for (int i = 0; i < kIntSize; i++) { 523 x |= static_cast<int>(*--pos_) << i * kBitsPerByte; 524 } 525 last_position_ += x; 526 rinfo_.data_ = last_position_; 527 } 528 529 530 void RelocIterator::AdvanceReadData() { 531 intptr_t x = 0; 532 for (int i = 0; i < kIntptrSize; i++) { 533 x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte; 534 } 535 rinfo_.data_ = x; 536 } 537 538 539 void RelocIterator::AdvanceReadVariableLengthPCJump() { 540 // Read the 32-kSmallPCDeltaBits most significant bits of the 541 // pc jump in kChunkBits bit chunks and shift them into place. 542 // Stop when the last chunk is encountered. 543 uint32_t pc_jump = 0; 544 for (int i = 0; i < kIntSize; i++) { 545 byte pc_jump_part = *--pos_; 546 pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits; 547 if ((pc_jump_part & kLastChunkTagMask) == 1) break; 548 } 549 // The least significant kSmallPCDeltaBits bits will be added 550 // later. 551 rinfo_.pc_ += pc_jump << kSmallPCDeltaBits; 552 } 553 554 555 inline int RelocIterator::GetLocatableTypeTag() { 556 return *pos_ & ((1 << kLocatableTypeTagBits) - 1); 557 } 558 559 560 inline void RelocIterator::ReadTaggedId() { 561 int8_t signed_b = *pos_; 562 // Signed right shift is arithmetic shift. Tested in test-utils.cc. 563 last_id_ += signed_b >> kLocatableTypeTagBits; 564 rinfo_.data_ = last_id_; 565 } 566 567 568 inline void RelocIterator::ReadTaggedPosition() { 569 int8_t signed_b = *pos_; 570 // Signed right shift is arithmetic shift. Tested in test-utils.cc. 571 last_position_ += signed_b >> kLocatableTypeTagBits; 572 rinfo_.data_ = last_position_; 573 } 574 575 576 static inline RelocInfo::Mode GetPositionModeFromTag(int tag) { 577 ASSERT(tag == kNonstatementPositionTag || 578 tag == kStatementPositionTag); 579 return (tag == kNonstatementPositionTag) ? 580 RelocInfo::POSITION : 581 RelocInfo::STATEMENT_POSITION; 582 } 583 584 585 void RelocIterator::next() { 586 ASSERT(!done()); 587 // Basically, do the opposite of RelocInfoWriter::Write. 588 // Reading of data is as far as possible avoided for unwanted modes, 589 // but we must always update the pc. 590 // 591 // We exit this loop by returning when we find a mode we want. 592 while (pos_ > end_) { 593 int tag = AdvanceGetTag(); 594 if (tag == kEmbeddedObjectTag) { 595 ReadTaggedPC(); 596 if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return; 597 } else if (tag == kCodeTargetTag) { 598 ReadTaggedPC(); 599 if (SetMode(RelocInfo::CODE_TARGET)) return; 600 } else if (tag == kLocatableTag) { 601 ReadTaggedPC(); 602 Advance(); 603 int locatable_tag = GetLocatableTypeTag(); 604 if (locatable_tag == kCodeWithIdTag) { 605 if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) { 606 ReadTaggedId(); 607 return; 608 } 609 } else { 610 // Compact encoding is never used for comments, 611 // so it must be a position. 612 ASSERT(locatable_tag == kNonstatementPositionTag || 613 locatable_tag == kStatementPositionTag); 614 if (mode_mask_ & RelocInfo::kPositionMask) { 615 ReadTaggedPosition(); 616 if (SetMode(GetPositionModeFromTag(locatable_tag))) return; 617 } 618 } 619 } else { 620 ASSERT(tag == kDefaultTag); 621 int extra_tag = GetExtraTag(); 622 if (extra_tag == kPCJumpExtraTag) { 623 if (GetTopTag() == kVariableLengthPCJumpTopTag) { 624 AdvanceReadVariableLengthPCJump(); 625 } else { 626 AdvanceReadPC(); 627 } 628 } else if (extra_tag == kDataJumpExtraTag) { 629 int locatable_tag = GetTopTag(); 630 if (locatable_tag == kCodeWithIdTag) { 631 if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) { 632 AdvanceReadId(); 633 return; 634 } 635 Advance(kIntSize); 636 } else if (locatable_tag != kCommentTag) { 637 ASSERT(locatable_tag == kNonstatementPositionTag || 638 locatable_tag == kStatementPositionTag); 639 if (mode_mask_ & RelocInfo::kPositionMask) { 640 AdvanceReadPosition(); 641 if (SetMode(GetPositionModeFromTag(locatable_tag))) return; 642 } else { 643 Advance(kIntSize); 644 } 645 } else { 646 ASSERT(locatable_tag == kCommentTag); 647 if (SetMode(RelocInfo::COMMENT)) { 648 AdvanceReadData(); 649 return; 650 } 651 Advance(kIntptrSize); 652 } 653 } else if ((extra_tag == kConstPoolExtraTag) && 654 (GetTopTag() == kConstPoolTag)) { 655 if (SetMode(RelocInfo::CONST_POOL)) { 656 AdvanceReadConstPoolData(); 657 return; 658 } 659 Advance(kIntSize); 660 } else { 661 AdvanceReadPC(); 662 int rmode = extra_tag + RelocInfo::LAST_COMPACT_ENUM; 663 if (SetMode(static_cast<RelocInfo::Mode>(rmode))) return; 664 } 665 } 666 } 667 if (code_age_sequence_ != NULL) { 668 byte* old_code_age_sequence = code_age_sequence_; 669 code_age_sequence_ = NULL; 670 if (SetMode(RelocInfo::CODE_AGE_SEQUENCE)) { 671 rinfo_.data_ = 0; 672 rinfo_.pc_ = old_code_age_sequence; 673 return; 674 } 675 } 676 done_ = true; 677 } 678 679 680 RelocIterator::RelocIterator(Code* code, int mode_mask) { 681 rinfo_.host_ = code; 682 rinfo_.pc_ = code->instruction_start(); 683 rinfo_.data_ = 0; 684 // Relocation info is read backwards. 685 pos_ = code->relocation_start() + code->relocation_size(); 686 end_ = code->relocation_start(); 687 done_ = false; 688 mode_mask_ = mode_mask; 689 last_id_ = 0; 690 last_position_ = 0; 691 byte* sequence = code->FindCodeAgeSequence(); 692 if (sequence != NULL && !Code::IsYoungSequence(sequence)) { 693 code_age_sequence_ = sequence; 694 } else { 695 code_age_sequence_ = NULL; 696 } 697 if (mode_mask_ == 0) pos_ = end_; 698 next(); 699 } 700 701 702 RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) { 703 rinfo_.pc_ = desc.buffer; 704 rinfo_.data_ = 0; 705 // Relocation info is read backwards. 706 pos_ = desc.buffer + desc.buffer_size; 707 end_ = pos_ - desc.reloc_size; 708 done_ = false; 709 mode_mask_ = mode_mask; 710 last_id_ = 0; 711 last_position_ = 0; 712 code_age_sequence_ = NULL; 713 if (mode_mask_ == 0) pos_ = end_; 714 next(); 715 } 716 717 718 // ----------------------------------------------------------------------------- 719 // Implementation of RelocInfo 720 721 722 #ifdef DEBUG 723 bool RelocInfo::RequiresRelocation(const CodeDesc& desc) { 724 // Ensure there are no code targets or embedded objects present in the 725 // deoptimization entries, they would require relocation after code 726 // generation. 727 int mode_mask = RelocInfo::kCodeTargetMask | 728 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | 729 RelocInfo::ModeMask(RelocInfo::CELL) | 730 RelocInfo::kApplyMask; 731 RelocIterator it(desc, mode_mask); 732 return !it.done(); 733 } 734 #endif 735 736 737 #ifdef ENABLE_DISASSEMBLER 738 const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) { 739 switch (rmode) { 740 case RelocInfo::NONE32: 741 return "no reloc 32"; 742 case RelocInfo::NONE64: 743 return "no reloc 64"; 744 case RelocInfo::EMBEDDED_OBJECT: 745 return "embedded object"; 746 case RelocInfo::CONSTRUCT_CALL: 747 return "code target (js construct call)"; 748 case RelocInfo::CODE_TARGET_CONTEXT: 749 return "code target (context)"; 750 case RelocInfo::DEBUG_BREAK: 751 #ifndef ENABLE_DEBUGGER_SUPPORT 752 UNREACHABLE(); 753 #endif 754 return "debug break"; 755 case RelocInfo::CODE_TARGET: 756 return "code target"; 757 case RelocInfo::CODE_TARGET_WITH_ID: 758 return "code target with id"; 759 case RelocInfo::CELL: 760 return "property cell"; 761 case RelocInfo::RUNTIME_ENTRY: 762 return "runtime entry"; 763 case RelocInfo::JS_RETURN: 764 return "js return"; 765 case RelocInfo::COMMENT: 766 return "comment"; 767 case RelocInfo::POSITION: 768 return "position"; 769 case RelocInfo::STATEMENT_POSITION: 770 return "statement position"; 771 case RelocInfo::EXTERNAL_REFERENCE: 772 return "external reference"; 773 case RelocInfo::INTERNAL_REFERENCE: 774 return "internal reference"; 775 case RelocInfo::CONST_POOL: 776 return "constant pool"; 777 case RelocInfo::DEBUG_BREAK_SLOT: 778 #ifndef ENABLE_DEBUGGER_SUPPORT 779 UNREACHABLE(); 780 #endif 781 return "debug break slot"; 782 case RelocInfo::CODE_AGE_SEQUENCE: 783 return "code_age_sequence"; 784 case RelocInfo::NUMBER_OF_MODES: 785 UNREACHABLE(); 786 return "number_of_modes"; 787 } 788 return "unknown relocation type"; 789 } 790 791 792 void RelocInfo::Print(Isolate* isolate, FILE* out) { 793 PrintF(out, "%p %s", pc_, RelocModeName(rmode_)); 794 if (IsComment(rmode_)) { 795 PrintF(out, " (%s)", reinterpret_cast<char*>(data_)); 796 } else if (rmode_ == EMBEDDED_OBJECT) { 797 PrintF(out, " ("); 798 target_object()->ShortPrint(out); 799 PrintF(out, ")"); 800 } else if (rmode_ == EXTERNAL_REFERENCE) { 801 ExternalReferenceEncoder ref_encoder; 802 PrintF(out, " (%s) (%p)", 803 ref_encoder.NameOfAddress(*target_reference_address()), 804 *target_reference_address()); 805 } else if (IsCodeTarget(rmode_)) { 806 Code* code = Code::GetCodeFromTargetAddress(target_address()); 807 PrintF(out, " (%s) (%p)", Code::Kind2String(code->kind()), 808 target_address()); 809 if (rmode_ == CODE_TARGET_WITH_ID) { 810 PrintF(" (id=%d)", static_cast<int>(data_)); 811 } 812 } else if (IsPosition(rmode_)) { 813 PrintF(out, " (%" V8_PTR_PREFIX "d)", data()); 814 } else if (IsRuntimeEntry(rmode_) && 815 isolate->deoptimizer_data() != NULL) { 816 // Depotimization bailouts are stored as runtime entries. 817 int id = Deoptimizer::GetDeoptimizationId( 818 isolate, target_address(), Deoptimizer::EAGER); 819 if (id != Deoptimizer::kNotDeoptimizationEntry) { 820 PrintF(out, " (deoptimization bailout %d)", id); 821 } 822 } 823 824 PrintF(out, "\n"); 825 } 826 #endif // ENABLE_DISASSEMBLER 827 828 829 #ifdef VERIFY_HEAP 830 void RelocInfo::Verify() { 831 switch (rmode_) { 832 case EMBEDDED_OBJECT: 833 Object::VerifyPointer(target_object()); 834 break; 835 case CELL: 836 Object::VerifyPointer(target_cell()); 837 break; 838 case DEBUG_BREAK: 839 #ifndef ENABLE_DEBUGGER_SUPPORT 840 UNREACHABLE(); 841 break; 842 #endif 843 case CONSTRUCT_CALL: 844 case CODE_TARGET_CONTEXT: 845 case CODE_TARGET_WITH_ID: 846 case CODE_TARGET: { 847 // convert inline target address to code object 848 Address addr = target_address(); 849 CHECK(addr != NULL); 850 // Check that we can find the right code object. 851 Code* code = Code::GetCodeFromTargetAddress(addr); 852 Object* found = code->GetIsolate()->FindCodeObject(addr); 853 CHECK(found->IsCode()); 854 CHECK(code->address() == HeapObject::cast(found)->address()); 855 break; 856 } 857 case RUNTIME_ENTRY: 858 case JS_RETURN: 859 case COMMENT: 860 case POSITION: 861 case STATEMENT_POSITION: 862 case EXTERNAL_REFERENCE: 863 case INTERNAL_REFERENCE: 864 case CONST_POOL: 865 case DEBUG_BREAK_SLOT: 866 case NONE32: 867 case NONE64: 868 break; 869 case NUMBER_OF_MODES: 870 UNREACHABLE(); 871 break; 872 case CODE_AGE_SEQUENCE: 873 ASSERT(Code::IsYoungSequence(pc_) || code_age_stub()->IsCode()); 874 break; 875 } 876 } 877 #endif // VERIFY_HEAP 878 879 880 // ----------------------------------------------------------------------------- 881 // Implementation of ExternalReference 882 883 void ExternalReference::SetUp() { 884 double_constants.min_int = kMinInt; 885 double_constants.one_half = 0.5; 886 double_constants.minus_one_half = -0.5; 887 double_constants.minus_zero = -0.0; 888 double_constants.uint8_max_value = 255; 889 double_constants.zero = 0.0; 890 double_constants.canonical_non_hole_nan = OS::nan_value(); 891 double_constants.the_hole_nan = BitCast<double>(kHoleNanInt64); 892 double_constants.negative_infinity = -V8_INFINITY; 893 894 math_exp_data_mutex = OS::CreateMutex(); 895 } 896 897 898 void ExternalReference::InitializeMathExpData() { 899 // Early return? 900 if (math_exp_data_initialized) return; 901 902 math_exp_data_mutex->Lock(); 903 if (!math_exp_data_initialized) { 904 // If this is changed, generated code must be adapted too. 905 const int kTableSizeBits = 11; 906 const int kTableSize = 1 << kTableSizeBits; 907 const double kTableSizeDouble = static_cast<double>(kTableSize); 908 909 math_exp_constants_array = new double[9]; 910 // Input values smaller than this always return 0. 911 math_exp_constants_array[0] = -708.39641853226408; 912 // Input values larger than this always return +Infinity. 913 math_exp_constants_array[1] = 709.78271289338397; 914 math_exp_constants_array[2] = V8_INFINITY; 915 // The rest is black magic. Do not attempt to understand it. It is 916 // loosely based on the "expd" function published at: 917 // http://herumi.blogspot.com/2011/08/fast-double-precision-exponential.html 918 const double constant3 = (1 << kTableSizeBits) / log(2.0); 919 math_exp_constants_array[3] = constant3; 920 math_exp_constants_array[4] = 921 static_cast<double>(static_cast<int64_t>(3) << 51); 922 math_exp_constants_array[5] = 1 / constant3; 923 math_exp_constants_array[6] = 3.0000000027955394; 924 math_exp_constants_array[7] = 0.16666666685227835; 925 math_exp_constants_array[8] = 1; 926 927 math_exp_log_table_array = new double[kTableSize]; 928 for (int i = 0; i < kTableSize; i++) { 929 double value = pow(2, i / kTableSizeDouble); 930 uint64_t bits = BitCast<uint64_t, double>(value); 931 bits &= (static_cast<uint64_t>(1) << 52) - 1; 932 double mantissa = BitCast<double, uint64_t>(bits); 933 math_exp_log_table_array[i] = mantissa; 934 } 935 936 math_exp_data_initialized = true; 937 } 938 math_exp_data_mutex->Unlock(); 939 } 940 941 942 void ExternalReference::TearDownMathExpData() { 943 delete[] math_exp_constants_array; 944 delete[] math_exp_log_table_array; 945 delete math_exp_data_mutex; 946 } 947 948 949 ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate) 950 : address_(Redirect(isolate, Builtins::c_function_address(id))) {} 951 952 953 ExternalReference::ExternalReference( 954 ApiFunction* fun, 955 Type type = ExternalReference::BUILTIN_CALL, 956 Isolate* isolate = NULL) 957 : address_(Redirect(isolate, fun->address(), type)) {} 958 959 960 ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate) 961 : address_(isolate->builtins()->builtin_address(name)) {} 962 963 964 ExternalReference::ExternalReference(Runtime::FunctionId id, 965 Isolate* isolate) 966 : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {} 967 968 969 ExternalReference::ExternalReference(const Runtime::Function* f, 970 Isolate* isolate) 971 : address_(Redirect(isolate, f->entry)) {} 972 973 974 ExternalReference ExternalReference::isolate_address(Isolate* isolate) { 975 return ExternalReference(isolate); 976 } 977 978 979 ExternalReference::ExternalReference(const IC_Utility& ic_utility, 980 Isolate* isolate) 981 : address_(Redirect(isolate, ic_utility.address())) {} 982 983 #ifdef ENABLE_DEBUGGER_SUPPORT 984 ExternalReference::ExternalReference(const Debug_Address& debug_address, 985 Isolate* isolate) 986 : address_(debug_address.address(isolate)) {} 987 #endif 988 989 ExternalReference::ExternalReference(StatsCounter* counter) 990 : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {} 991 992 993 ExternalReference::ExternalReference(Isolate::AddressId id, Isolate* isolate) 994 : address_(isolate->get_address_from_id(id)) {} 995 996 997 ExternalReference::ExternalReference(const SCTableReference& table_ref) 998 : address_(table_ref.address()) {} 999 1000 1001 ExternalReference ExternalReference:: 1002 incremental_marking_record_write_function(Isolate* isolate) { 1003 return ExternalReference(Redirect( 1004 isolate, 1005 FUNCTION_ADDR(IncrementalMarking::RecordWriteFromCode))); 1006 } 1007 1008 1009 ExternalReference ExternalReference:: 1010 incremental_evacuation_record_write_function(Isolate* isolate) { 1011 return ExternalReference(Redirect( 1012 isolate, 1013 FUNCTION_ADDR(IncrementalMarking::RecordWriteForEvacuationFromCode))); 1014 } 1015 1016 1017 ExternalReference ExternalReference:: 1018 store_buffer_overflow_function(Isolate* isolate) { 1019 return ExternalReference(Redirect( 1020 isolate, 1021 FUNCTION_ADDR(StoreBuffer::StoreBufferOverflow))); 1022 } 1023 1024 1025 ExternalReference ExternalReference::flush_icache_function(Isolate* isolate) { 1026 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(CPU::FlushICache))); 1027 } 1028 1029 1030 ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) { 1031 return 1032 ExternalReference(Redirect(isolate, FUNCTION_ADDR(Runtime::PerformGC))); 1033 } 1034 1035 1036 ExternalReference ExternalReference::fill_heap_number_with_random_function( 1037 Isolate* isolate) { 1038 return ExternalReference(Redirect( 1039 isolate, 1040 FUNCTION_ADDR(V8::FillHeapNumberWithRandom))); 1041 } 1042 1043 1044 ExternalReference ExternalReference::delete_handle_scope_extensions( 1045 Isolate* isolate) { 1046 return ExternalReference(Redirect( 1047 isolate, 1048 FUNCTION_ADDR(HandleScope::DeleteExtensions))); 1049 } 1050 1051 1052 ExternalReference ExternalReference::random_uint32_function( 1053 Isolate* isolate) { 1054 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(V8::Random))); 1055 } 1056 1057 1058 ExternalReference ExternalReference::get_date_field_function( 1059 Isolate* isolate) { 1060 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(JSDate::GetField))); 1061 } 1062 1063 1064 ExternalReference ExternalReference::get_make_code_young_function( 1065 Isolate* isolate) { 1066 return ExternalReference(Redirect( 1067 isolate, FUNCTION_ADDR(Code::MakeCodeAgeSequenceYoung))); 1068 } 1069 1070 1071 ExternalReference ExternalReference::date_cache_stamp(Isolate* isolate) { 1072 return ExternalReference(isolate->date_cache()->stamp_address()); 1073 } 1074 1075 1076 ExternalReference ExternalReference::stress_deopt_count(Isolate* isolate) { 1077 return ExternalReference(isolate->stress_deopt_count_address()); 1078 } 1079 1080 1081 ExternalReference ExternalReference::transcendental_cache_array_address( 1082 Isolate* isolate) { 1083 return ExternalReference( 1084 isolate->transcendental_cache()->cache_array_address()); 1085 } 1086 1087 1088 ExternalReference ExternalReference::new_deoptimizer_function( 1089 Isolate* isolate) { 1090 return ExternalReference( 1091 Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New))); 1092 } 1093 1094 1095 ExternalReference ExternalReference::compute_output_frames_function( 1096 Isolate* isolate) { 1097 return ExternalReference( 1098 Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames))); 1099 } 1100 1101 1102 ExternalReference ExternalReference::log_enter_external_function( 1103 Isolate* isolate) { 1104 return ExternalReference( 1105 Redirect(isolate, FUNCTION_ADDR(Logger::EnterExternal))); 1106 } 1107 1108 1109 ExternalReference ExternalReference::log_leave_external_function( 1110 Isolate* isolate) { 1111 return ExternalReference( 1112 Redirect(isolate, FUNCTION_ADDR(Logger::LeaveExternal))); 1113 } 1114 1115 1116 ExternalReference ExternalReference::keyed_lookup_cache_keys(Isolate* isolate) { 1117 return ExternalReference(isolate->keyed_lookup_cache()->keys_address()); 1118 } 1119 1120 1121 ExternalReference ExternalReference::keyed_lookup_cache_field_offsets( 1122 Isolate* isolate) { 1123 return ExternalReference( 1124 isolate->keyed_lookup_cache()->field_offsets_address()); 1125 } 1126 1127 1128 ExternalReference ExternalReference::roots_array_start(Isolate* isolate) { 1129 return ExternalReference(isolate->heap()->roots_array_start()); 1130 } 1131 1132 1133 ExternalReference ExternalReference::allocation_sites_list_address( 1134 Isolate* isolate) { 1135 return ExternalReference(isolate->heap()->allocation_sites_list_address()); 1136 } 1137 1138 1139 ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) { 1140 return ExternalReference(isolate->stack_guard()->address_of_jslimit()); 1141 } 1142 1143 1144 ExternalReference ExternalReference::address_of_real_stack_limit( 1145 Isolate* isolate) { 1146 return ExternalReference(isolate->stack_guard()->address_of_real_jslimit()); 1147 } 1148 1149 1150 ExternalReference ExternalReference::address_of_regexp_stack_limit( 1151 Isolate* isolate) { 1152 return ExternalReference(isolate->regexp_stack()->limit_address()); 1153 } 1154 1155 1156 ExternalReference ExternalReference::new_space_start(Isolate* isolate) { 1157 return ExternalReference(isolate->heap()->NewSpaceStart()); 1158 } 1159 1160 1161 ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) { 1162 return ExternalReference(isolate->heap()->store_buffer()->TopAddress()); 1163 } 1164 1165 1166 ExternalReference ExternalReference::new_space_mask(Isolate* isolate) { 1167 return ExternalReference(reinterpret_cast<Address>( 1168 isolate->heap()->NewSpaceMask())); 1169 } 1170 1171 1172 ExternalReference ExternalReference::new_space_allocation_top_address( 1173 Isolate* isolate) { 1174 return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress()); 1175 } 1176 1177 1178 ExternalReference ExternalReference::heap_always_allocate_scope_depth( 1179 Isolate* isolate) { 1180 Heap* heap = isolate->heap(); 1181 return ExternalReference(heap->always_allocate_scope_depth_address()); 1182 } 1183 1184 1185 ExternalReference ExternalReference::new_space_allocation_limit_address( 1186 Isolate* isolate) { 1187 return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress()); 1188 } 1189 1190 1191 ExternalReference ExternalReference::old_pointer_space_allocation_top_address( 1192 Isolate* isolate) { 1193 return ExternalReference( 1194 isolate->heap()->OldPointerSpaceAllocationTopAddress()); 1195 } 1196 1197 1198 ExternalReference ExternalReference::old_pointer_space_allocation_limit_address( 1199 Isolate* isolate) { 1200 return ExternalReference( 1201 isolate->heap()->OldPointerSpaceAllocationLimitAddress()); 1202 } 1203 1204 1205 ExternalReference ExternalReference::old_data_space_allocation_top_address( 1206 Isolate* isolate) { 1207 return ExternalReference( 1208 isolate->heap()->OldDataSpaceAllocationTopAddress()); 1209 } 1210 1211 1212 ExternalReference ExternalReference::old_data_space_allocation_limit_address( 1213 Isolate* isolate) { 1214 return ExternalReference( 1215 isolate->heap()->OldDataSpaceAllocationLimitAddress()); 1216 } 1217 1218 1219 ExternalReference ExternalReference:: 1220 new_space_high_promotion_mode_active_address(Isolate* isolate) { 1221 return ExternalReference( 1222 isolate->heap()->NewSpaceHighPromotionModeActiveAddress()); 1223 } 1224 1225 1226 ExternalReference ExternalReference::handle_scope_level_address( 1227 Isolate* isolate) { 1228 return ExternalReference(HandleScope::current_level_address(isolate)); 1229 } 1230 1231 1232 ExternalReference ExternalReference::handle_scope_next_address( 1233 Isolate* isolate) { 1234 return ExternalReference(HandleScope::current_next_address(isolate)); 1235 } 1236 1237 1238 ExternalReference ExternalReference::handle_scope_limit_address( 1239 Isolate* isolate) { 1240 return ExternalReference(HandleScope::current_limit_address(isolate)); 1241 } 1242 1243 1244 ExternalReference ExternalReference::scheduled_exception_address( 1245 Isolate* isolate) { 1246 return ExternalReference(isolate->scheduled_exception_address()); 1247 } 1248 1249 1250 ExternalReference ExternalReference::address_of_pending_message_obj( 1251 Isolate* isolate) { 1252 return ExternalReference(isolate->pending_message_obj_address()); 1253 } 1254 1255 1256 ExternalReference ExternalReference::address_of_has_pending_message( 1257 Isolate* isolate) { 1258 return ExternalReference(isolate->has_pending_message_address()); 1259 } 1260 1261 1262 ExternalReference ExternalReference::address_of_pending_message_script( 1263 Isolate* isolate) { 1264 return ExternalReference(isolate->pending_message_script_address()); 1265 } 1266 1267 1268 ExternalReference ExternalReference::address_of_min_int() { 1269 return ExternalReference(reinterpret_cast<void*>(&double_constants.min_int)); 1270 } 1271 1272 1273 ExternalReference ExternalReference::address_of_one_half() { 1274 return ExternalReference(reinterpret_cast<void*>(&double_constants.one_half)); 1275 } 1276 1277 1278 ExternalReference ExternalReference::address_of_minus_one_half() { 1279 return ExternalReference( 1280 reinterpret_cast<void*>(&double_constants.minus_one_half)); 1281 } 1282 1283 1284 ExternalReference ExternalReference::address_of_minus_zero() { 1285 return ExternalReference( 1286 reinterpret_cast<void*>(&double_constants.minus_zero)); 1287 } 1288 1289 1290 ExternalReference ExternalReference::address_of_zero() { 1291 return ExternalReference(reinterpret_cast<void*>(&double_constants.zero)); 1292 } 1293 1294 1295 ExternalReference ExternalReference::address_of_uint8_max_value() { 1296 return ExternalReference( 1297 reinterpret_cast<void*>(&double_constants.uint8_max_value)); 1298 } 1299 1300 1301 ExternalReference ExternalReference::address_of_negative_infinity() { 1302 return ExternalReference( 1303 reinterpret_cast<void*>(&double_constants.negative_infinity)); 1304 } 1305 1306 1307 ExternalReference ExternalReference::address_of_canonical_non_hole_nan() { 1308 return ExternalReference( 1309 reinterpret_cast<void*>(&double_constants.canonical_non_hole_nan)); 1310 } 1311 1312 1313 ExternalReference ExternalReference::address_of_the_hole_nan() { 1314 return ExternalReference( 1315 reinterpret_cast<void*>(&double_constants.the_hole_nan)); 1316 } 1317 1318 1319 #ifndef V8_INTERPRETED_REGEXP 1320 1321 ExternalReference ExternalReference::re_check_stack_guard_state( 1322 Isolate* isolate) { 1323 Address function; 1324 #if V8_TARGET_ARCH_X64 1325 function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState); 1326 #elif V8_TARGET_ARCH_IA32 1327 function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState); 1328 #elif V8_TARGET_ARCH_ARM 1329 function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState); 1330 #elif V8_TARGET_ARCH_MIPS 1331 function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState); 1332 #else 1333 UNREACHABLE(); 1334 #endif 1335 return ExternalReference(Redirect(isolate, function)); 1336 } 1337 1338 1339 ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) { 1340 return ExternalReference( 1341 Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack))); 1342 } 1343 1344 ExternalReference ExternalReference::re_case_insensitive_compare_uc16( 1345 Isolate* isolate) { 1346 return ExternalReference(Redirect( 1347 isolate, 1348 FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16))); 1349 } 1350 1351 1352 ExternalReference ExternalReference::re_word_character_map() { 1353 return ExternalReference( 1354 NativeRegExpMacroAssembler::word_character_map_address()); 1355 } 1356 1357 ExternalReference ExternalReference::address_of_static_offsets_vector( 1358 Isolate* isolate) { 1359 return ExternalReference( 1360 reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector())); 1361 } 1362 1363 ExternalReference ExternalReference::address_of_regexp_stack_memory_address( 1364 Isolate* isolate) { 1365 return ExternalReference( 1366 isolate->regexp_stack()->memory_address()); 1367 } 1368 1369 ExternalReference ExternalReference::address_of_regexp_stack_memory_size( 1370 Isolate* isolate) { 1371 return ExternalReference(isolate->regexp_stack()->memory_size_address()); 1372 } 1373 1374 #endif // V8_INTERPRETED_REGEXP 1375 1376 1377 static double add_two_doubles(double x, double y) { 1378 return x + y; 1379 } 1380 1381 1382 static double sub_two_doubles(double x, double y) { 1383 return x - y; 1384 } 1385 1386 1387 static double mul_two_doubles(double x, double y) { 1388 return x * y; 1389 } 1390 1391 1392 static double div_two_doubles(double x, double y) { 1393 return x / y; 1394 } 1395 1396 1397 static double mod_two_doubles(double x, double y) { 1398 return modulo(x, y); 1399 } 1400 1401 1402 static double math_sin_double(double x) { 1403 return sin(x); 1404 } 1405 1406 1407 static double math_cos_double(double x) { 1408 return cos(x); 1409 } 1410 1411 1412 static double math_tan_double(double x) { 1413 return tan(x); 1414 } 1415 1416 1417 static double math_log_double(double x) { 1418 return log(x); 1419 } 1420 1421 1422 ExternalReference ExternalReference::math_sin_double_function( 1423 Isolate* isolate) { 1424 return ExternalReference(Redirect(isolate, 1425 FUNCTION_ADDR(math_sin_double), 1426 BUILTIN_FP_CALL)); 1427 } 1428 1429 1430 ExternalReference ExternalReference::math_cos_double_function( 1431 Isolate* isolate) { 1432 return ExternalReference(Redirect(isolate, 1433 FUNCTION_ADDR(math_cos_double), 1434 BUILTIN_FP_CALL)); 1435 } 1436 1437 1438 ExternalReference ExternalReference::math_tan_double_function( 1439 Isolate* isolate) { 1440 return ExternalReference(Redirect(isolate, 1441 FUNCTION_ADDR(math_tan_double), 1442 BUILTIN_FP_CALL)); 1443 } 1444 1445 1446 ExternalReference ExternalReference::math_log_double_function( 1447 Isolate* isolate) { 1448 return ExternalReference(Redirect(isolate, 1449 FUNCTION_ADDR(math_log_double), 1450 BUILTIN_FP_CALL)); 1451 } 1452 1453 1454 ExternalReference ExternalReference::math_exp_constants(int constant_index) { 1455 ASSERT(math_exp_data_initialized); 1456 return ExternalReference( 1457 reinterpret_cast<void*>(math_exp_constants_array + constant_index)); 1458 } 1459 1460 1461 ExternalReference ExternalReference::math_exp_log_table() { 1462 ASSERT(math_exp_data_initialized); 1463 return ExternalReference(reinterpret_cast<void*>(math_exp_log_table_array)); 1464 } 1465 1466 1467 ExternalReference ExternalReference::page_flags(Page* page) { 1468 return ExternalReference(reinterpret_cast<Address>(page) + 1469 MemoryChunk::kFlagsOffset); 1470 } 1471 1472 1473 ExternalReference ExternalReference::ForDeoptEntry(Address entry) { 1474 return ExternalReference(entry); 1475 } 1476 1477 1478 double power_helper(double x, double y) { 1479 int y_int = static_cast<int>(y); 1480 if (y == y_int) { 1481 return power_double_int(x, y_int); // Returns 1 if exponent is 0. 1482 } 1483 if (y == 0.5) { 1484 return (std::isinf(x)) ? V8_INFINITY 1485 : fast_sqrt(x + 0.0); // Convert -0 to +0. 1486 } 1487 if (y == -0.5) { 1488 return (std::isinf(x)) ? 0 : 1.0 / fast_sqrt(x + 0.0); // Convert -0 to +0. 1489 } 1490 return power_double_double(x, y); 1491 } 1492 1493 1494 // Helper function to compute x^y, where y is known to be an 1495 // integer. Uses binary decomposition to limit the number of 1496 // multiplications; see the discussion in "Hacker's Delight" by Henry 1497 // S. Warren, Jr., figure 11-6, page 213. 1498 double power_double_int(double x, int y) { 1499 double m = (y < 0) ? 1 / x : x; 1500 unsigned n = (y < 0) ? -y : y; 1501 double p = 1; 1502 while (n != 0) { 1503 if ((n & 1) != 0) p *= m; 1504 m *= m; 1505 if ((n & 2) != 0) p *= m; 1506 m *= m; 1507 n >>= 2; 1508 } 1509 return p; 1510 } 1511 1512 1513 double power_double_double(double x, double y) { 1514 #if defined(__MINGW64_VERSION_MAJOR) && \ 1515 (!defined(__MINGW64_VERSION_RC) || __MINGW64_VERSION_RC < 1) 1516 // MinGW64 has a custom implementation for pow. This handles certain 1517 // special cases that are different. 1518 if ((x == 0.0 || std::isinf(x)) && std::isfinite(y)) { 1519 double f; 1520 if (modf(y, &f) != 0.0) return ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0; 1521 } 1522 1523 if (x == 2.0) { 1524 int y_int = static_cast<int>(y); 1525 if (y == y_int) return ldexp(1.0, y_int); 1526 } 1527 #endif 1528 1529 // The checks for special cases can be dropped in ia32 because it has already 1530 // been done in generated code before bailing out here. 1531 if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) { 1532 return OS::nan_value(); 1533 } 1534 return pow(x, y); 1535 } 1536 1537 1538 ExternalReference ExternalReference::power_double_double_function( 1539 Isolate* isolate) { 1540 return ExternalReference(Redirect(isolate, 1541 FUNCTION_ADDR(power_double_double), 1542 BUILTIN_FP_FP_CALL)); 1543 } 1544 1545 1546 ExternalReference ExternalReference::power_double_int_function( 1547 Isolate* isolate) { 1548 return ExternalReference(Redirect(isolate, 1549 FUNCTION_ADDR(power_double_int), 1550 BUILTIN_FP_INT_CALL)); 1551 } 1552 1553 1554 static int native_compare_doubles(double y, double x) { 1555 if (x == y) return EQUAL; 1556 return x < y ? LESS : GREATER; 1557 } 1558 1559 1560 bool EvalComparison(Token::Value op, double op1, double op2) { 1561 ASSERT(Token::IsCompareOp(op)); 1562 switch (op) { 1563 case Token::EQ: 1564 case Token::EQ_STRICT: return (op1 == op2); 1565 case Token::NE: return (op1 != op2); 1566 case Token::LT: return (op1 < op2); 1567 case Token::GT: return (op1 > op2); 1568 case Token::LTE: return (op1 <= op2); 1569 case Token::GTE: return (op1 >= op2); 1570 default: 1571 UNREACHABLE(); 1572 return false; 1573 } 1574 } 1575 1576 1577 ExternalReference ExternalReference::double_fp_operation( 1578 Token::Value operation, Isolate* isolate) { 1579 typedef double BinaryFPOperation(double x, double y); 1580 BinaryFPOperation* function = NULL; 1581 switch (operation) { 1582 case Token::ADD: 1583 function = &add_two_doubles; 1584 break; 1585 case Token::SUB: 1586 function = &sub_two_doubles; 1587 break; 1588 case Token::MUL: 1589 function = &mul_two_doubles; 1590 break; 1591 case Token::DIV: 1592 function = &div_two_doubles; 1593 break; 1594 case Token::MOD: 1595 function = &mod_two_doubles; 1596 break; 1597 default: 1598 UNREACHABLE(); 1599 } 1600 return ExternalReference(Redirect(isolate, 1601 FUNCTION_ADDR(function), 1602 BUILTIN_FP_FP_CALL)); 1603 } 1604 1605 1606 ExternalReference ExternalReference::compare_doubles(Isolate* isolate) { 1607 return ExternalReference(Redirect(isolate, 1608 FUNCTION_ADDR(native_compare_doubles), 1609 BUILTIN_COMPARE_CALL)); 1610 } 1611 1612 1613 #ifdef ENABLE_DEBUGGER_SUPPORT 1614 ExternalReference ExternalReference::debug_break(Isolate* isolate) { 1615 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug_Break))); 1616 } 1617 1618 1619 ExternalReference ExternalReference::debug_step_in_fp_address( 1620 Isolate* isolate) { 1621 return ExternalReference(isolate->debug()->step_in_fp_addr()); 1622 } 1623 #endif 1624 1625 1626 void PositionsRecorder::RecordPosition(int pos) { 1627 ASSERT(pos != RelocInfo::kNoPosition); 1628 ASSERT(pos >= 0); 1629 state_.current_position = pos; 1630 #ifdef ENABLE_GDB_JIT_INTERFACE 1631 if (gdbjit_lineinfo_ != NULL) { 1632 gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false); 1633 } 1634 #endif 1635 LOG_CODE_EVENT(assembler_->isolate(), 1636 CodeLinePosInfoAddPositionEvent(jit_handler_data_, 1637 assembler_->pc_offset(), 1638 pos)); 1639 } 1640 1641 1642 void PositionsRecorder::RecordStatementPosition(int pos) { 1643 ASSERT(pos != RelocInfo::kNoPosition); 1644 ASSERT(pos >= 0); 1645 state_.current_statement_position = pos; 1646 #ifdef ENABLE_GDB_JIT_INTERFACE 1647 if (gdbjit_lineinfo_ != NULL) { 1648 gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true); 1649 } 1650 #endif 1651 LOG_CODE_EVENT(assembler_->isolate(), 1652 CodeLinePosInfoAddStatementPositionEvent( 1653 jit_handler_data_, 1654 assembler_->pc_offset(), 1655 pos)); 1656 } 1657 1658 1659 bool PositionsRecorder::WriteRecordedPositions() { 1660 bool written = false; 1661 1662 // Write the statement position if it is different from what was written last 1663 // time. 1664 if (state_.current_statement_position != state_.written_statement_position) { 1665 EnsureSpace ensure_space(assembler_); 1666 assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION, 1667 state_.current_statement_position); 1668 state_.written_statement_position = state_.current_statement_position; 1669 written = true; 1670 } 1671 1672 // Write the position if it is different from what was written last time and 1673 // also different from the written statement position. 1674 if (state_.current_position != state_.written_position && 1675 state_.current_position != state_.written_statement_position) { 1676 EnsureSpace ensure_space(assembler_); 1677 assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position); 1678 state_.written_position = state_.current_position; 1679 written = true; 1680 } 1681 1682 // Return whether something was written. 1683 return written; 1684 } 1685 1686 } } // namespace v8::internal 1687