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 <math.h>  // For cos, log, pow, sin, tan, etc.
     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_zero;
     95   double zero;
     96   double uint8_max_value;
     97   double negative_infinity;
     98   double canonical_non_hole_nan;
     99   double the_hole_nan;
    100 };
    101 
    102 struct InitializeDoubleConstants {
    103   static void Construct(DoubleConstant* double_constants) {
    104     double_constants->min_int = kMinInt;
    105     double_constants->one_half = 0.5;
    106     double_constants->minus_zero = -0.0;
    107     double_constants->uint8_max_value = 255;
    108     double_constants->zero = 0.0;
    109     double_constants->canonical_non_hole_nan = OS::nan_value();
    110     double_constants->the_hole_nan = BitCast<double>(kHoleNanInt64);
    111     double_constants->negative_infinity = -V8_INFINITY;
    112   }
    113 };
    114 
    115 static LazyInstance<DoubleConstant, InitializeDoubleConstants>::type
    116     double_constants = LAZY_INSTANCE_INITIALIZER;
    117 
    118 const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
    119 
    120 // -----------------------------------------------------------------------------
    121 // Implementation of AssemblerBase
    122 
    123 AssemblerBase::AssemblerBase(Isolate* isolate)
    124     : isolate_(isolate),
    125       jit_cookie_(0) {
    126   if (FLAG_mask_constants_with_cookie && isolate != NULL)  {
    127     jit_cookie_ = V8::RandomPrivate(isolate);
    128   }
    129 }
    130 
    131 
    132 // -----------------------------------------------------------------------------
    133 // Implementation of Label
    134 
    135 int Label::pos() const {
    136   if (pos_ < 0) return -pos_ - 1;
    137   if (pos_ > 0) return  pos_ - 1;
    138   UNREACHABLE();
    139   return 0;
    140 }
    141 
    142 
    143 // -----------------------------------------------------------------------------
    144 // Implementation of RelocInfoWriter and RelocIterator
    145 //
    146 // Relocation information is written backwards in memory, from high addresses
    147 // towards low addresses, byte by byte.  Therefore, in the encodings listed
    148 // below, the first byte listed it at the highest address, and successive
    149 // bytes in the record are at progressively lower addresses.
    150 //
    151 // Encoding
    152 //
    153 // The most common modes are given single-byte encodings.  Also, it is
    154 // easy to identify the type of reloc info and skip unwanted modes in
    155 // an iteration.
    156 //
    157 // The encoding relies on the fact that there are fewer than 14
    158 // different non-compactly encoded relocation modes.
    159 //
    160 // The first byte of a relocation record has a tag in its low 2 bits:
    161 // Here are the record schemes, depending on the low tag and optional higher
    162 // tags.
    163 //
    164 // Low tag:
    165 //   00: embedded_object:      [6-bit pc delta] 00
    166 //
    167 //   01: code_target:          [6-bit pc delta] 01
    168 //
    169 //   10: short_data_record:    [6-bit pc delta] 10 followed by
    170 //                             [6-bit data delta] [2-bit data type tag]
    171 //
    172 //   11: long_record           [2-bit high tag][4 bit middle_tag] 11
    173 //                             followed by variable data depending on type.
    174 //
    175 //  2-bit data type tags, used in short_data_record and data_jump long_record:
    176 //   code_target_with_id: 00
    177 //   position:            01
    178 //   statement_position:  10
    179 //   comment:             11 (not used in short_data_record)
    180 //
    181 //  Long record format:
    182 //    4-bit middle_tag:
    183 //      0000 - 1100 : Short record for RelocInfo::Mode middle_tag + 2
    184 //         (The middle_tag encodes rmode - RelocInfo::LAST_COMPACT_ENUM,
    185 //          and is between 0000 and 1100)
    186 //        The format is:
    187 //                              00 [4 bit middle_tag] 11 followed by
    188 //                              00 [6 bit pc delta]
    189 //
    190 //      1101: not used (would allow one more relocation mode to be added)
    191 //      1110: long_data_record
    192 //        The format is:       [2-bit data_type_tag] 1110 11
    193 //                             signed intptr_t, lowest byte written first
    194 //                             (except data_type code_target_with_id, which
    195 //                             is followed by a signed int, not intptr_t.)
    196 //
    197 //      1111: long_pc_jump
    198 //        The format is:
    199 //          pc-jump:             00 1111 11,
    200 //                               00 [6 bits pc delta]
    201 //        or
    202 //          pc-jump (variable length):
    203 //                               01 1111 11,
    204 //                               [7 bits data] 0
    205 //                                  ...
    206 //                               [7 bits data] 1
    207 //               (Bits 6..31 of pc delta, with leading zeroes
    208 //                dropped, and last non-zero chunk tagged with 1.)
    209 
    210 
    211 const int kMaxRelocModes = 14;
    212 
    213 const int kTagBits = 2;
    214 const int kTagMask = (1 << kTagBits) - 1;
    215 const int kExtraTagBits = 4;
    216 const int kLocatableTypeTagBits = 2;
    217 const int kSmallDataBits = kBitsPerByte - kLocatableTypeTagBits;
    218 
    219 const int kEmbeddedObjectTag = 0;
    220 const int kCodeTargetTag = 1;
    221 const int kLocatableTag = 2;
    222 const int kDefaultTag = 3;
    223 
    224 const int kPCJumpExtraTag = (1 << kExtraTagBits) - 1;
    225 
    226 const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
    227 const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
    228 const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
    229 
    230 const int kVariableLengthPCJumpTopTag = 1;
    231 const int kChunkBits = 7;
    232 const int kChunkMask = (1 << kChunkBits) - 1;
    233 const int kLastChunkTagBits = 1;
    234 const int kLastChunkTagMask = 1;
    235 const int kLastChunkTag = 1;
    236 
    237 
    238 const int kDataJumpExtraTag = kPCJumpExtraTag - 1;
    239 
    240 const int kCodeWithIdTag = 0;
    241 const int kNonstatementPositionTag = 1;
    242 const int kStatementPositionTag = 2;
    243 const int kCommentTag = 3;
    244 
    245 
    246 uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
    247   // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
    248   // Otherwise write a variable length PC jump for the bits that do
    249   // not fit in the kSmallPCDeltaBits bits.
    250   if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
    251   WriteExtraTag(kPCJumpExtraTag, kVariableLengthPCJumpTopTag);
    252   uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
    253   ASSERT(pc_jump > 0);
    254   // Write kChunkBits size chunks of the pc_jump.
    255   for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
    256     byte b = pc_jump & kChunkMask;
    257     *--pos_ = b << kLastChunkTagBits;
    258   }
    259   // Tag the last chunk so it can be identified.
    260   *pos_ = *pos_ | kLastChunkTag;
    261   // Return the remaining kSmallPCDeltaBits of the pc_delta.
    262   return pc_delta & kSmallPCDeltaMask;
    263 }
    264 
    265 
    266 void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
    267   // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump.
    268   pc_delta = WriteVariableLengthPCJump(pc_delta);
    269   *--pos_ = pc_delta << kTagBits | tag;
    270 }
    271 
    272 
    273 void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) {
    274   *--pos_ = static_cast<byte>(data_delta << kLocatableTypeTagBits | tag);
    275 }
    276 
    277 
    278 void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
    279   *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) |
    280                              extra_tag << kTagBits |
    281                              kDefaultTag);
    282 }
    283 
    284 
    285 void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
    286   // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
    287   pc_delta = WriteVariableLengthPCJump(pc_delta);
    288   WriteExtraTag(extra_tag, 0);
    289   *--pos_ = pc_delta;
    290 }
    291 
    292 
    293 void RelocInfoWriter::WriteExtraTaggedIntData(int data_delta, int top_tag) {
    294   WriteExtraTag(kDataJumpExtraTag, top_tag);
    295   for (int i = 0; i < kIntSize; i++) {
    296     *--pos_ = static_cast<byte>(data_delta);
    297     // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
    298     data_delta = data_delta >> kBitsPerByte;
    299   }
    300 }
    301 
    302 void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
    303   WriteExtraTag(kDataJumpExtraTag, top_tag);
    304   for (int i = 0; i < kIntptrSize; i++) {
    305     *--pos_ = static_cast<byte>(data_delta);
    306     // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
    307     data_delta = data_delta >> kBitsPerByte;
    308   }
    309 }
    310 
    311 
    312 void RelocInfoWriter::Write(const RelocInfo* rinfo) {
    313 #ifdef DEBUG
    314   byte* begin_pos = pos_;
    315 #endif
    316   ASSERT(rinfo->pc() - last_pc_ >= 0);
    317   ASSERT(RelocInfo::NUMBER_OF_MODES - RelocInfo::LAST_COMPACT_ENUM <=
    318          kMaxRelocModes);
    319   // Use unsigned delta-encoding for pc.
    320   uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
    321   RelocInfo::Mode rmode = rinfo->rmode();
    322 
    323   // The two most common modes are given small tags, and usually fit in a byte.
    324   if (rmode == RelocInfo::EMBEDDED_OBJECT) {
    325     WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
    326   } else if (rmode == RelocInfo::CODE_TARGET) {
    327     WriteTaggedPC(pc_delta, kCodeTargetTag);
    328     ASSERT(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
    329   } else if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
    330     // Use signed delta-encoding for id.
    331     ASSERT(static_cast<int>(rinfo->data()) == rinfo->data());
    332     int id_delta = static_cast<int>(rinfo->data()) - last_id_;
    333     // Check if delta is small enough to fit in a tagged byte.
    334     if (is_intn(id_delta, kSmallDataBits)) {
    335       WriteTaggedPC(pc_delta, kLocatableTag);
    336       WriteTaggedData(id_delta, kCodeWithIdTag);
    337     } else {
    338       // Otherwise, use costly encoding.
    339       WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
    340       WriteExtraTaggedIntData(id_delta, kCodeWithIdTag);
    341     }
    342     last_id_ = static_cast<int>(rinfo->data());
    343   } else if (RelocInfo::IsPosition(rmode)) {
    344     // Use signed delta-encoding for position.
    345     ASSERT(static_cast<int>(rinfo->data()) == rinfo->data());
    346     int pos_delta = static_cast<int>(rinfo->data()) - last_position_;
    347     int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag
    348                                                       : kStatementPositionTag;
    349     // Check if delta is small enough to fit in a tagged byte.
    350     if (is_intn(pos_delta, kSmallDataBits)) {
    351       WriteTaggedPC(pc_delta, kLocatableTag);
    352       WriteTaggedData(pos_delta, pos_type_tag);
    353     } else {
    354       // Otherwise, use costly encoding.
    355       WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
    356       WriteExtraTaggedIntData(pos_delta, pos_type_tag);
    357     }
    358     last_position_ = static_cast<int>(rinfo->data());
    359   } else if (RelocInfo::IsComment(rmode)) {
    360     // Comments are normally not generated, so we use the costly encoding.
    361     WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
    362     WriteExtraTaggedData(rinfo->data(), kCommentTag);
    363     ASSERT(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
    364   } else {
    365     ASSERT(rmode > RelocInfo::LAST_COMPACT_ENUM);
    366     int saved_mode = rmode - RelocInfo::LAST_COMPACT_ENUM;
    367     // For all other modes we simply use the mode as the extra tag.
    368     // None of these modes need a data component.
    369     ASSERT(saved_mode < kPCJumpExtraTag && saved_mode < kDataJumpExtraTag);
    370     WriteExtraTaggedPC(pc_delta, saved_mode);
    371   }
    372   last_pc_ = rinfo->pc();
    373 #ifdef DEBUG
    374   ASSERT(begin_pos - pos_ <= kMaxSize);
    375 #endif
    376 }
    377 
    378 
    379 inline int RelocIterator::AdvanceGetTag() {
    380   return *--pos_ & kTagMask;
    381 }
    382 
    383 
    384 inline int RelocIterator::GetExtraTag() {
    385   return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
    386 }
    387 
    388 
    389 inline int RelocIterator::GetTopTag() {
    390   return *pos_ >> (kTagBits + kExtraTagBits);
    391 }
    392 
    393 
    394 inline void RelocIterator::ReadTaggedPC() {
    395   rinfo_.pc_ += *pos_ >> kTagBits;
    396 }
    397 
    398 
    399 inline void RelocIterator::AdvanceReadPC() {
    400   rinfo_.pc_ += *--pos_;
    401 }
    402 
    403 
    404 void RelocIterator::AdvanceReadId() {
    405   int x = 0;
    406   for (int i = 0; i < kIntSize; i++) {
    407     x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
    408   }
    409   last_id_ += x;
    410   rinfo_.data_ = last_id_;
    411 }
    412 
    413 
    414 void RelocIterator::AdvanceReadPosition() {
    415   int x = 0;
    416   for (int i = 0; i < kIntSize; i++) {
    417     x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
    418   }
    419   last_position_ += x;
    420   rinfo_.data_ = last_position_;
    421 }
    422 
    423 
    424 void RelocIterator::AdvanceReadData() {
    425   intptr_t x = 0;
    426   for (int i = 0; i < kIntptrSize; i++) {
    427     x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
    428   }
    429   rinfo_.data_ = x;
    430 }
    431 
    432 
    433 void RelocIterator::AdvanceReadVariableLengthPCJump() {
    434   // Read the 32-kSmallPCDeltaBits most significant bits of the
    435   // pc jump in kChunkBits bit chunks and shift them into place.
    436   // Stop when the last chunk is encountered.
    437   uint32_t pc_jump = 0;
    438   for (int i = 0; i < kIntSize; i++) {
    439     byte pc_jump_part = *--pos_;
    440     pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
    441     if ((pc_jump_part & kLastChunkTagMask) == 1) break;
    442   }
    443   // The least significant kSmallPCDeltaBits bits will be added
    444   // later.
    445   rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
    446 }
    447 
    448 
    449 inline int RelocIterator::GetLocatableTypeTag() {
    450   return *pos_ & ((1 << kLocatableTypeTagBits) - 1);
    451 }
    452 
    453 
    454 inline void RelocIterator::ReadTaggedId() {
    455   int8_t signed_b = *pos_;
    456   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
    457   last_id_ += signed_b >> kLocatableTypeTagBits;
    458   rinfo_.data_ = last_id_;
    459 }
    460 
    461 
    462 inline void RelocIterator::ReadTaggedPosition() {
    463   int8_t signed_b = *pos_;
    464   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
    465   last_position_ += signed_b >> kLocatableTypeTagBits;
    466   rinfo_.data_ = last_position_;
    467 }
    468 
    469 
    470 static inline RelocInfo::Mode GetPositionModeFromTag(int tag) {
    471   ASSERT(tag == kNonstatementPositionTag ||
    472          tag == kStatementPositionTag);
    473   return (tag == kNonstatementPositionTag) ?
    474          RelocInfo::POSITION :
    475          RelocInfo::STATEMENT_POSITION;
    476 }
    477 
    478 
    479 void RelocIterator::next() {
    480   ASSERT(!done());
    481   // Basically, do the opposite of RelocInfoWriter::Write.
    482   // Reading of data is as far as possible avoided for unwanted modes,
    483   // but we must always update the pc.
    484   //
    485   // We exit this loop by returning when we find a mode we want.
    486   while (pos_ > end_) {
    487     int tag = AdvanceGetTag();
    488     if (tag == kEmbeddedObjectTag) {
    489       ReadTaggedPC();
    490       if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
    491     } else if (tag == kCodeTargetTag) {
    492       ReadTaggedPC();
    493       if (SetMode(RelocInfo::CODE_TARGET)) return;
    494     } else if (tag == kLocatableTag) {
    495       ReadTaggedPC();
    496       Advance();
    497       int locatable_tag = GetLocatableTypeTag();
    498       if (locatable_tag == kCodeWithIdTag) {
    499         if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
    500           ReadTaggedId();
    501           return;
    502         }
    503       } else {
    504         // Compact encoding is never used for comments,
    505         // so it must be a position.
    506         ASSERT(locatable_tag == kNonstatementPositionTag ||
    507                locatable_tag == kStatementPositionTag);
    508         if (mode_mask_ & RelocInfo::kPositionMask) {
    509           ReadTaggedPosition();
    510           if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
    511         }
    512       }
    513     } else {
    514       ASSERT(tag == kDefaultTag);
    515       int extra_tag = GetExtraTag();
    516       if (extra_tag == kPCJumpExtraTag) {
    517         int top_tag = GetTopTag();
    518         if (top_tag == kVariableLengthPCJumpTopTag) {
    519           AdvanceReadVariableLengthPCJump();
    520         } else {
    521           AdvanceReadPC();
    522         }
    523       } else if (extra_tag == kDataJumpExtraTag) {
    524         int locatable_tag = GetTopTag();
    525         if (locatable_tag == kCodeWithIdTag) {
    526           if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
    527             AdvanceReadId();
    528             return;
    529           }
    530           Advance(kIntSize);
    531         } else if (locatable_tag != kCommentTag) {
    532           ASSERT(locatable_tag == kNonstatementPositionTag ||
    533                  locatable_tag == kStatementPositionTag);
    534           if (mode_mask_ & RelocInfo::kPositionMask) {
    535             AdvanceReadPosition();
    536             if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
    537           } else {
    538             Advance(kIntSize);
    539           }
    540         } else {
    541           ASSERT(locatable_tag == kCommentTag);
    542           if (SetMode(RelocInfo::COMMENT)) {
    543             AdvanceReadData();
    544             return;
    545           }
    546           Advance(kIntptrSize);
    547         }
    548       } else {
    549         AdvanceReadPC();
    550         int rmode = extra_tag + RelocInfo::LAST_COMPACT_ENUM;
    551         if (SetMode(static_cast<RelocInfo::Mode>(rmode))) return;
    552       }
    553     }
    554   }
    555   done_ = true;
    556 }
    557 
    558 
    559 RelocIterator::RelocIterator(Code* code, int mode_mask) {
    560   rinfo_.host_ = code;
    561   rinfo_.pc_ = code->instruction_start();
    562   rinfo_.data_ = 0;
    563   // Relocation info is read backwards.
    564   pos_ = code->relocation_start() + code->relocation_size();
    565   end_ = code->relocation_start();
    566   done_ = false;
    567   mode_mask_ = mode_mask;
    568   last_id_ = 0;
    569   last_position_ = 0;
    570   if (mode_mask_ == 0) pos_ = end_;
    571   next();
    572 }
    573 
    574 
    575 RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
    576   rinfo_.pc_ = desc.buffer;
    577   rinfo_.data_ = 0;
    578   // Relocation info is read backwards.
    579   pos_ = desc.buffer + desc.buffer_size;
    580   end_ = pos_ - desc.reloc_size;
    581   done_ = false;
    582   mode_mask_ = mode_mask;
    583   last_id_ = 0;
    584   last_position_ = 0;
    585   if (mode_mask_ == 0) pos_ = end_;
    586   next();
    587 }
    588 
    589 
    590 // -----------------------------------------------------------------------------
    591 // Implementation of RelocInfo
    592 
    593 
    594 #ifdef ENABLE_DISASSEMBLER
    595 const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
    596   switch (rmode) {
    597     case RelocInfo::NONE:
    598       return "no reloc";
    599     case RelocInfo::EMBEDDED_OBJECT:
    600       return "embedded object";
    601     case RelocInfo::CONSTRUCT_CALL:
    602       return "code target (js construct call)";
    603     case RelocInfo::CODE_TARGET_CONTEXT:
    604       return "code target (context)";
    605     case RelocInfo::DEBUG_BREAK:
    606 #ifndef ENABLE_DEBUGGER_SUPPORT
    607       UNREACHABLE();
    608 #endif
    609       return "debug break";
    610     case RelocInfo::CODE_TARGET:
    611       return "code target";
    612     case RelocInfo::CODE_TARGET_WITH_ID:
    613       return "code target with id";
    614     case RelocInfo::GLOBAL_PROPERTY_CELL:
    615       return "global property cell";
    616     case RelocInfo::RUNTIME_ENTRY:
    617       return "runtime entry";
    618     case RelocInfo::JS_RETURN:
    619       return "js return";
    620     case RelocInfo::COMMENT:
    621       return "comment";
    622     case RelocInfo::POSITION:
    623       return "position";
    624     case RelocInfo::STATEMENT_POSITION:
    625       return "statement position";
    626     case RelocInfo::EXTERNAL_REFERENCE:
    627       return "external reference";
    628     case RelocInfo::INTERNAL_REFERENCE:
    629       return "internal reference";
    630     case RelocInfo::DEBUG_BREAK_SLOT:
    631 #ifndef ENABLE_DEBUGGER_SUPPORT
    632       UNREACHABLE();
    633 #endif
    634       return "debug break slot";
    635     case RelocInfo::NUMBER_OF_MODES:
    636       UNREACHABLE();
    637       return "number_of_modes";
    638   }
    639   return "unknown relocation type";
    640 }
    641 
    642 
    643 void RelocInfo::Print(FILE* out) {
    644   PrintF(out, "%p  %s", pc_, RelocModeName(rmode_));
    645   if (IsComment(rmode_)) {
    646     PrintF(out, "  (%s)", reinterpret_cast<char*>(data_));
    647   } else if (rmode_ == EMBEDDED_OBJECT) {
    648     PrintF(out, "  (");
    649     target_object()->ShortPrint(out);
    650     PrintF(out, ")");
    651   } else if (rmode_ == EXTERNAL_REFERENCE) {
    652     ExternalReferenceEncoder ref_encoder;
    653     PrintF(out, " (%s)  (%p)",
    654            ref_encoder.NameOfAddress(*target_reference_address()),
    655            *target_reference_address());
    656   } else if (IsCodeTarget(rmode_)) {
    657     Code* code = Code::GetCodeFromTargetAddress(target_address());
    658     PrintF(out, " (%s)  (%p)", Code::Kind2String(code->kind()),
    659            target_address());
    660     if (rmode_ == CODE_TARGET_WITH_ID) {
    661       PrintF(" (id=%d)", static_cast<int>(data_));
    662     }
    663   } else if (IsPosition(rmode_)) {
    664     PrintF(out, "  (%" V8_PTR_PREFIX "d)", data());
    665   } else if (rmode_ == RelocInfo::RUNTIME_ENTRY &&
    666              Isolate::Current()->deoptimizer_data() != NULL) {
    667     // Depotimization bailouts are stored as runtime entries.
    668     int id = Deoptimizer::GetDeoptimizationId(
    669         target_address(), Deoptimizer::EAGER);
    670     if (id != Deoptimizer::kNotDeoptimizationEntry) {
    671       PrintF(out, "  (deoptimization bailout %d)", id);
    672     }
    673   }
    674 
    675   PrintF(out, "\n");
    676 }
    677 #endif  // ENABLE_DISASSEMBLER
    678 
    679 
    680 #ifdef DEBUG
    681 void RelocInfo::Verify() {
    682   switch (rmode_) {
    683     case EMBEDDED_OBJECT:
    684       Object::VerifyPointer(target_object());
    685       break;
    686     case GLOBAL_PROPERTY_CELL:
    687       Object::VerifyPointer(target_cell());
    688       break;
    689     case DEBUG_BREAK:
    690 #ifndef ENABLE_DEBUGGER_SUPPORT
    691       UNREACHABLE();
    692       break;
    693 #endif
    694     case CONSTRUCT_CALL:
    695     case CODE_TARGET_CONTEXT:
    696     case CODE_TARGET_WITH_ID:
    697     case CODE_TARGET: {
    698       // convert inline target address to code object
    699       Address addr = target_address();
    700       ASSERT(addr != NULL);
    701       // Check that we can find the right code object.
    702       Code* code = Code::GetCodeFromTargetAddress(addr);
    703       Object* found = HEAP->FindCodeObject(addr);
    704       ASSERT(found->IsCode());
    705       ASSERT(code->address() == HeapObject::cast(found)->address());
    706       break;
    707     }
    708     case RUNTIME_ENTRY:
    709     case JS_RETURN:
    710     case COMMENT:
    711     case POSITION:
    712     case STATEMENT_POSITION:
    713     case EXTERNAL_REFERENCE:
    714     case INTERNAL_REFERENCE:
    715     case DEBUG_BREAK_SLOT:
    716     case NONE:
    717       break;
    718     case NUMBER_OF_MODES:
    719       UNREACHABLE();
    720       break;
    721   }
    722 }
    723 #endif  // DEBUG
    724 
    725 
    726 // -----------------------------------------------------------------------------
    727 // Implementation of ExternalReference
    728 
    729 ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate)
    730   : address_(Redirect(isolate, Builtins::c_function_address(id))) {}
    731 
    732 
    733 ExternalReference::ExternalReference(
    734     ApiFunction* fun,
    735     Type type = ExternalReference::BUILTIN_CALL,
    736     Isolate* isolate = NULL)
    737   : address_(Redirect(isolate, fun->address(), type)) {}
    738 
    739 
    740 ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate)
    741   : address_(isolate->builtins()->builtin_address(name)) {}
    742 
    743 
    744 ExternalReference::ExternalReference(Runtime::FunctionId id,
    745                                      Isolate* isolate)
    746   : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
    747 
    748 
    749 ExternalReference::ExternalReference(const Runtime::Function* f,
    750                                      Isolate* isolate)
    751   : address_(Redirect(isolate, f->entry)) {}
    752 
    753 
    754 ExternalReference ExternalReference::isolate_address() {
    755   return ExternalReference(Isolate::Current());
    756 }
    757 
    758 
    759 ExternalReference::ExternalReference(const IC_Utility& ic_utility,
    760                                      Isolate* isolate)
    761   : address_(Redirect(isolate, ic_utility.address())) {}
    762 
    763 #ifdef ENABLE_DEBUGGER_SUPPORT
    764 ExternalReference::ExternalReference(const Debug_Address& debug_address,
    765                                      Isolate* isolate)
    766   : address_(debug_address.address(isolate)) {}
    767 #endif
    768 
    769 ExternalReference::ExternalReference(StatsCounter* counter)
    770   : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
    771 
    772 
    773 ExternalReference::ExternalReference(Isolate::AddressId id, Isolate* isolate)
    774   : address_(isolate->get_address_from_id(id)) {}
    775 
    776 
    777 ExternalReference::ExternalReference(const SCTableReference& table_ref)
    778   : address_(table_ref.address()) {}
    779 
    780 
    781 ExternalReference ExternalReference::
    782     incremental_marking_record_write_function(Isolate* isolate) {
    783   return ExternalReference(Redirect(
    784       isolate,
    785       FUNCTION_ADDR(IncrementalMarking::RecordWriteFromCode)));
    786 }
    787 
    788 
    789 ExternalReference ExternalReference::
    790     incremental_evacuation_record_write_function(Isolate* isolate) {
    791   return ExternalReference(Redirect(
    792       isolate,
    793       FUNCTION_ADDR(IncrementalMarking::RecordWriteForEvacuationFromCode)));
    794 }
    795 
    796 
    797 ExternalReference ExternalReference::
    798     store_buffer_overflow_function(Isolate* isolate) {
    799   return ExternalReference(Redirect(
    800       isolate,
    801       FUNCTION_ADDR(StoreBuffer::StoreBufferOverflow)));
    802 }
    803 
    804 
    805 ExternalReference ExternalReference::flush_icache_function(Isolate* isolate) {
    806   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(CPU::FlushICache)));
    807 }
    808 
    809 
    810 ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) {
    811   return
    812       ExternalReference(Redirect(isolate, FUNCTION_ADDR(Runtime::PerformGC)));
    813 }
    814 
    815 
    816 ExternalReference ExternalReference::fill_heap_number_with_random_function(
    817     Isolate* isolate) {
    818   return ExternalReference(Redirect(
    819       isolate,
    820       FUNCTION_ADDR(V8::FillHeapNumberWithRandom)));
    821 }
    822 
    823 
    824 ExternalReference ExternalReference::delete_handle_scope_extensions(
    825     Isolate* isolate) {
    826   return ExternalReference(Redirect(
    827       isolate,
    828       FUNCTION_ADDR(HandleScope::DeleteExtensions)));
    829 }
    830 
    831 
    832 ExternalReference ExternalReference::random_uint32_function(
    833     Isolate* isolate) {
    834   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(V8::Random)));
    835 }
    836 
    837 
    838 ExternalReference ExternalReference::get_date_field_function(
    839     Isolate* isolate) {
    840   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(JSDate::GetField)));
    841 }
    842 
    843 
    844 ExternalReference ExternalReference::date_cache_stamp(Isolate* isolate) {
    845   return ExternalReference(isolate->date_cache()->stamp_address());
    846 }
    847 
    848 
    849 ExternalReference ExternalReference::transcendental_cache_array_address(
    850     Isolate* isolate) {
    851   return ExternalReference(
    852       isolate->transcendental_cache()->cache_array_address());
    853 }
    854 
    855 
    856 ExternalReference ExternalReference::new_deoptimizer_function(
    857     Isolate* isolate) {
    858   return ExternalReference(
    859       Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
    860 }
    861 
    862 
    863 ExternalReference ExternalReference::compute_output_frames_function(
    864     Isolate* isolate) {
    865   return ExternalReference(
    866       Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
    867 }
    868 
    869 
    870 ExternalReference ExternalReference::keyed_lookup_cache_keys(Isolate* isolate) {
    871   return ExternalReference(isolate->keyed_lookup_cache()->keys_address());
    872 }
    873 
    874 
    875 ExternalReference ExternalReference::keyed_lookup_cache_field_offsets(
    876     Isolate* isolate) {
    877   return ExternalReference(
    878       isolate->keyed_lookup_cache()->field_offsets_address());
    879 }
    880 
    881 
    882 ExternalReference ExternalReference::roots_array_start(Isolate* isolate) {
    883   return ExternalReference(isolate->heap()->roots_array_start());
    884 }
    885 
    886 
    887 ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
    888   return ExternalReference(isolate->stack_guard()->address_of_jslimit());
    889 }
    890 
    891 
    892 ExternalReference ExternalReference::address_of_real_stack_limit(
    893     Isolate* isolate) {
    894   return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
    895 }
    896 
    897 
    898 ExternalReference ExternalReference::address_of_regexp_stack_limit(
    899     Isolate* isolate) {
    900   return ExternalReference(isolate->regexp_stack()->limit_address());
    901 }
    902 
    903 
    904 ExternalReference ExternalReference::new_space_start(Isolate* isolate) {
    905   return ExternalReference(isolate->heap()->NewSpaceStart());
    906 }
    907 
    908 
    909 ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) {
    910   return ExternalReference(isolate->heap()->store_buffer()->TopAddress());
    911 }
    912 
    913 
    914 ExternalReference ExternalReference::new_space_mask(Isolate* isolate) {
    915   return ExternalReference(reinterpret_cast<Address>(
    916       isolate->heap()->NewSpaceMask()));
    917 }
    918 
    919 
    920 ExternalReference ExternalReference::new_space_allocation_top_address(
    921     Isolate* isolate) {
    922   return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
    923 }
    924 
    925 
    926 ExternalReference ExternalReference::heap_always_allocate_scope_depth(
    927     Isolate* isolate) {
    928   Heap* heap = isolate->heap();
    929   return ExternalReference(heap->always_allocate_scope_depth_address());
    930 }
    931 
    932 
    933 ExternalReference ExternalReference::new_space_allocation_limit_address(
    934     Isolate* isolate) {
    935   return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
    936 }
    937 
    938 
    939 ExternalReference ExternalReference::handle_scope_level_address() {
    940   return ExternalReference(HandleScope::current_level_address());
    941 }
    942 
    943 
    944 ExternalReference ExternalReference::handle_scope_next_address() {
    945   return ExternalReference(HandleScope::current_next_address());
    946 }
    947 
    948 
    949 ExternalReference ExternalReference::handle_scope_limit_address() {
    950   return ExternalReference(HandleScope::current_limit_address());
    951 }
    952 
    953 
    954 ExternalReference ExternalReference::scheduled_exception_address(
    955     Isolate* isolate) {
    956   return ExternalReference(isolate->scheduled_exception_address());
    957 }
    958 
    959 
    960 ExternalReference ExternalReference::address_of_min_int() {
    961   return ExternalReference(reinterpret_cast<void*>(
    962       &double_constants.Pointer()->min_int));
    963 }
    964 
    965 
    966 ExternalReference ExternalReference::address_of_one_half() {
    967   return ExternalReference(reinterpret_cast<void*>(
    968       &double_constants.Pointer()->one_half));
    969 }
    970 
    971 
    972 ExternalReference ExternalReference::address_of_minus_zero() {
    973   return ExternalReference(reinterpret_cast<void*>(
    974       &double_constants.Pointer()->minus_zero));
    975 }
    976 
    977 
    978 ExternalReference ExternalReference::address_of_zero() {
    979   return ExternalReference(reinterpret_cast<void*>(
    980       &double_constants.Pointer()->zero));
    981 }
    982 
    983 
    984 ExternalReference ExternalReference::address_of_uint8_max_value() {
    985   return ExternalReference(reinterpret_cast<void*>(
    986       &double_constants.Pointer()->uint8_max_value));
    987 }
    988 
    989 
    990 ExternalReference ExternalReference::address_of_negative_infinity() {
    991   return ExternalReference(reinterpret_cast<void*>(
    992       &double_constants.Pointer()->negative_infinity));
    993 }
    994 
    995 
    996 ExternalReference ExternalReference::address_of_canonical_non_hole_nan() {
    997   return ExternalReference(reinterpret_cast<void*>(
    998       &double_constants.Pointer()->canonical_non_hole_nan));
    999 }
   1000 
   1001 
   1002 ExternalReference ExternalReference::address_of_the_hole_nan() {
   1003   return ExternalReference(reinterpret_cast<void*>(
   1004       &double_constants.Pointer()->the_hole_nan));
   1005 }
   1006 
   1007 
   1008 #ifndef V8_INTERPRETED_REGEXP
   1009 
   1010 ExternalReference ExternalReference::re_check_stack_guard_state(
   1011     Isolate* isolate) {
   1012   Address function;
   1013 #ifdef V8_TARGET_ARCH_X64
   1014   function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
   1015 #elif V8_TARGET_ARCH_IA32
   1016   function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
   1017 #elif V8_TARGET_ARCH_ARM
   1018   function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
   1019 #elif V8_TARGET_ARCH_MIPS
   1020   function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
   1021 #else
   1022   UNREACHABLE();
   1023 #endif
   1024   return ExternalReference(Redirect(isolate, function));
   1025 }
   1026 
   1027 ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
   1028   return ExternalReference(
   1029       Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
   1030 }
   1031 
   1032 ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
   1033     Isolate* isolate) {
   1034   return ExternalReference(Redirect(
   1035       isolate,
   1036       FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
   1037 }
   1038 
   1039 ExternalReference ExternalReference::re_word_character_map() {
   1040   return ExternalReference(
   1041       NativeRegExpMacroAssembler::word_character_map_address());
   1042 }
   1043 
   1044 ExternalReference ExternalReference::address_of_static_offsets_vector(
   1045     Isolate* isolate) {
   1046   return ExternalReference(
   1047       OffsetsVector::static_offsets_vector_address(isolate));
   1048 }
   1049 
   1050 ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
   1051     Isolate* isolate) {
   1052   return ExternalReference(
   1053       isolate->regexp_stack()->memory_address());
   1054 }
   1055 
   1056 ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
   1057     Isolate* isolate) {
   1058   return ExternalReference(isolate->regexp_stack()->memory_size_address());
   1059 }
   1060 
   1061 #endif  // V8_INTERPRETED_REGEXP
   1062 
   1063 
   1064 static double add_two_doubles(double x, double y) {
   1065   return x + y;
   1066 }
   1067 
   1068 
   1069 static double sub_two_doubles(double x, double y) {
   1070   return x - y;
   1071 }
   1072 
   1073 
   1074 static double mul_two_doubles(double x, double y) {
   1075   return x * y;
   1076 }
   1077 
   1078 
   1079 static double div_two_doubles(double x, double y) {
   1080   return x / y;
   1081 }
   1082 
   1083 
   1084 static double mod_two_doubles(double x, double y) {
   1085   return modulo(x, y);
   1086 }
   1087 
   1088 
   1089 static double math_sin_double(double x) {
   1090   return sin(x);
   1091 }
   1092 
   1093 
   1094 static double math_cos_double(double x) {
   1095   return cos(x);
   1096 }
   1097 
   1098 
   1099 static double math_tan_double(double x) {
   1100   return tan(x);
   1101 }
   1102 
   1103 
   1104 static double math_log_double(double x) {
   1105   return log(x);
   1106 }
   1107 
   1108 
   1109 ExternalReference ExternalReference::math_sin_double_function(
   1110     Isolate* isolate) {
   1111   return ExternalReference(Redirect(isolate,
   1112                                     FUNCTION_ADDR(math_sin_double),
   1113                                     BUILTIN_FP_CALL));
   1114 }
   1115 
   1116 
   1117 ExternalReference ExternalReference::math_cos_double_function(
   1118     Isolate* isolate) {
   1119   return ExternalReference(Redirect(isolate,
   1120                                     FUNCTION_ADDR(math_cos_double),
   1121                                     BUILTIN_FP_CALL));
   1122 }
   1123 
   1124 
   1125 ExternalReference ExternalReference::math_tan_double_function(
   1126     Isolate* isolate) {
   1127   return ExternalReference(Redirect(isolate,
   1128                                     FUNCTION_ADDR(math_tan_double),
   1129                                     BUILTIN_FP_CALL));
   1130 }
   1131 
   1132 
   1133 ExternalReference ExternalReference::math_log_double_function(
   1134     Isolate* isolate) {
   1135   return ExternalReference(Redirect(isolate,
   1136                                     FUNCTION_ADDR(math_log_double),
   1137                                     BUILTIN_FP_CALL));
   1138 }
   1139 
   1140 
   1141 // Helper function to compute x^y, where y is known to be an
   1142 // integer. Uses binary decomposition to limit the number of
   1143 // multiplications; see the discussion in "Hacker's Delight" by Henry
   1144 // S. Warren, Jr., figure 11-6, page 213.
   1145 double power_double_int(double x, int y) {
   1146   double m = (y < 0) ? 1 / x : x;
   1147   unsigned n = (y < 0) ? -y : y;
   1148   double p = 1;
   1149   while (n != 0) {
   1150     if ((n & 1) != 0) p *= m;
   1151     m *= m;
   1152     if ((n & 2) != 0) p *= m;
   1153     m *= m;
   1154     n >>= 2;
   1155   }
   1156   return p;
   1157 }
   1158 
   1159 
   1160 double power_double_double(double x, double y) {
   1161   // The checks for special cases can be dropped in ia32 because it has already
   1162   // been done in generated code before bailing out here.
   1163   if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) return OS::nan_value();
   1164   return pow(x, y);
   1165 }
   1166 
   1167 
   1168 ExternalReference ExternalReference::power_double_double_function(
   1169     Isolate* isolate) {
   1170   return ExternalReference(Redirect(isolate,
   1171                                     FUNCTION_ADDR(power_double_double),
   1172                                     BUILTIN_FP_FP_CALL));
   1173 }
   1174 
   1175 
   1176 ExternalReference ExternalReference::power_double_int_function(
   1177     Isolate* isolate) {
   1178   return ExternalReference(Redirect(isolate,
   1179                                     FUNCTION_ADDR(power_double_int),
   1180                                     BUILTIN_FP_INT_CALL));
   1181 }
   1182 
   1183 
   1184 static int native_compare_doubles(double y, double x) {
   1185   if (x == y) return EQUAL;
   1186   return x < y ? LESS : GREATER;
   1187 }
   1188 
   1189 
   1190 bool EvalComparison(Token::Value op, double op1, double op2) {
   1191   ASSERT(Token::IsCompareOp(op));
   1192   switch (op) {
   1193     case Token::EQ:
   1194     case Token::EQ_STRICT: return (op1 == op2);
   1195     case Token::NE: return (op1 != op2);
   1196     case Token::LT: return (op1 < op2);
   1197     case Token::GT: return (op1 > op2);
   1198     case Token::LTE: return (op1 <= op2);
   1199     case Token::GTE: return (op1 >= op2);
   1200     default:
   1201       UNREACHABLE();
   1202       return false;
   1203   }
   1204 }
   1205 
   1206 
   1207 ExternalReference ExternalReference::double_fp_operation(
   1208     Token::Value operation, Isolate* isolate) {
   1209   typedef double BinaryFPOperation(double x, double y);
   1210   BinaryFPOperation* function = NULL;
   1211   switch (operation) {
   1212     case Token::ADD:
   1213       function = &add_two_doubles;
   1214       break;
   1215     case Token::SUB:
   1216       function = &sub_two_doubles;
   1217       break;
   1218     case Token::MUL:
   1219       function = &mul_two_doubles;
   1220       break;
   1221     case Token::DIV:
   1222       function = &div_two_doubles;
   1223       break;
   1224     case Token::MOD:
   1225       function = &mod_two_doubles;
   1226       break;
   1227     default:
   1228       UNREACHABLE();
   1229   }
   1230   return ExternalReference(Redirect(isolate,
   1231                                     FUNCTION_ADDR(function),
   1232                                     BUILTIN_FP_FP_CALL));
   1233 }
   1234 
   1235 
   1236 ExternalReference ExternalReference::compare_doubles(Isolate* isolate) {
   1237   return ExternalReference(Redirect(isolate,
   1238                                     FUNCTION_ADDR(native_compare_doubles),
   1239                                     BUILTIN_COMPARE_CALL));
   1240 }
   1241 
   1242 
   1243 #ifdef ENABLE_DEBUGGER_SUPPORT
   1244 ExternalReference ExternalReference::debug_break(Isolate* isolate) {
   1245   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug_Break)));
   1246 }
   1247 
   1248 
   1249 ExternalReference ExternalReference::debug_step_in_fp_address(
   1250     Isolate* isolate) {
   1251   return ExternalReference(isolate->debug()->step_in_fp_addr());
   1252 }
   1253 #endif
   1254 
   1255 
   1256 void PositionsRecorder::RecordPosition(int pos) {
   1257   ASSERT(pos != RelocInfo::kNoPosition);
   1258   ASSERT(pos >= 0);
   1259   state_.current_position = pos;
   1260 #ifdef ENABLE_GDB_JIT_INTERFACE
   1261   if (gdbjit_lineinfo_ != NULL) {
   1262     gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false);
   1263   }
   1264 #endif
   1265 }
   1266 
   1267 
   1268 void PositionsRecorder::RecordStatementPosition(int pos) {
   1269   ASSERT(pos != RelocInfo::kNoPosition);
   1270   ASSERT(pos >= 0);
   1271   state_.current_statement_position = pos;
   1272 #ifdef ENABLE_GDB_JIT_INTERFACE
   1273   if (gdbjit_lineinfo_ != NULL) {
   1274     gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true);
   1275   }
   1276 #endif
   1277 }
   1278 
   1279 
   1280 bool PositionsRecorder::WriteRecordedPositions() {
   1281   bool written = false;
   1282 
   1283   // Write the statement position if it is different from what was written last
   1284   // time.
   1285   if (state_.current_statement_position != state_.written_statement_position) {
   1286     EnsureSpace ensure_space(assembler_);
   1287     assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
   1288                                 state_.current_statement_position);
   1289     state_.written_statement_position = state_.current_statement_position;
   1290     written = true;
   1291   }
   1292 
   1293   // Write the position if it is different from what was written last time and
   1294   // also different from the written statement position.
   1295   if (state_.current_position != state_.written_position &&
   1296       state_.current_position != state_.written_statement_position) {
   1297     EnsureSpace ensure_space(assembler_);
   1298     assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
   1299     state_.written_position = state_.current_position;
   1300     written = true;
   1301   }
   1302 
   1303   // Return whether something was written.
   1304   return written;
   1305 }
   1306 
   1307 } }  // namespace v8::internal
   1308