Home | History | Annotate | Download | only in src
      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