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 2006-2009 the V8 project authors. All rights reserved.
     34 
     35 #include "v8.h"
     36 
     37 #include "arguments.h"
     38 #include "deoptimizer.h"
     39 #include "execution.h"
     40 #include "ic-inl.h"
     41 #include "factory.h"
     42 #include "runtime.h"
     43 #include "runtime-profiler.h"
     44 #include "serialize.h"
     45 #include "stub-cache.h"
     46 #include "regexp-stack.h"
     47 #include "ast.h"
     48 #include "regexp-macro-assembler.h"
     49 #include "platform.h"
     50 // Include native regexp-macro-assembler.
     51 #ifndef V8_INTERPRETED_REGEXP
     52 #if V8_TARGET_ARCH_IA32
     53 #include "ia32/regexp-macro-assembler-ia32.h"
     54 #elif V8_TARGET_ARCH_X64
     55 #include "x64/regexp-macro-assembler-x64.h"
     56 #elif V8_TARGET_ARCH_ARM
     57 #include "arm/regexp-macro-assembler-arm.h"
     58 #elif V8_TARGET_ARCH_MIPS
     59 #include "mips/regexp-macro-assembler-mips.h"
     60 #else  // Unknown architecture.
     61 #error "Unknown architecture."
     62 #endif  // Target architecture.
     63 #endif  // V8_INTERPRETED_REGEXP
     64 
     65 namespace v8 {
     66 namespace internal {
     67 
     68 
     69 const double DoubleConstant::min_int = kMinInt;
     70 const double DoubleConstant::one_half = 0.5;
     71 const double DoubleConstant::minus_zero = -0.0;
     72 const double DoubleConstant::nan = OS::nan_value();
     73 const double DoubleConstant::negative_infinity = -V8_INFINITY;
     74 const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
     75 
     76 // -----------------------------------------------------------------------------
     77 // Implementation of AssemblerBase
     78 
     79 AssemblerBase::AssemblerBase(Isolate* isolate)
     80     : isolate_(isolate),
     81       jit_cookie_(0) {
     82   if (FLAG_mask_constants_with_cookie && isolate != NULL)  {
     83     jit_cookie_ = V8::RandomPrivate(isolate);
     84   }
     85 }
     86 
     87 
     88 // -----------------------------------------------------------------------------
     89 // Implementation of Label
     90 
     91 int Label::pos() const {
     92   if (pos_ < 0) return -pos_ - 1;
     93   if (pos_ > 0) return  pos_ - 1;
     94   UNREACHABLE();
     95   return 0;
     96 }
     97 
     98 
     99 // -----------------------------------------------------------------------------
    100 // Implementation of RelocInfoWriter and RelocIterator
    101 //
    102 // Encoding
    103 //
    104 // The most common modes are given single-byte encodings.  Also, it is
    105 // easy to identify the type of reloc info and skip unwanted modes in
    106 // an iteration.
    107 //
    108 // The encoding relies on the fact that there are less than 14
    109 // different relocation modes.
    110 //
    111 // embedded_object:    [6 bits pc delta] 00
    112 //
    113 // code_taget:         [6 bits pc delta] 01
    114 //
    115 // position:           [6 bits pc delta] 10,
    116 //                     [7 bits signed data delta] 0
    117 //
    118 // statement_position: [6 bits pc delta] 10,
    119 //                     [7 bits signed data delta] 1
    120 //
    121 // any nondata mode:   00 [4 bits rmode] 11,  // rmode: 0..13 only
    122 //                     00 [6 bits pc delta]
    123 //
    124 // pc-jump:            00 1111 11,
    125 //                     00 [6 bits pc delta]
    126 //
    127 // pc-jump:            01 1111 11,
    128 // (variable length)   7 - 26 bit pc delta, written in chunks of 7
    129 //                     bits, the lowest 7 bits written first.
    130 //
    131 // data-jump + pos:    00 1110 11,
    132 //                     signed intptr_t, lowest byte written first
    133 //
    134 // data-jump + st.pos: 01 1110 11,
    135 //                     signed intptr_t, lowest byte written first
    136 //
    137 // data-jump + comm.:  10 1110 11,
    138 //                     signed intptr_t, lowest byte written first
    139 //
    140 const int kMaxRelocModes = 14;
    141 
    142 const int kTagBits = 2;
    143 const int kTagMask = (1 << kTagBits) - 1;
    144 const int kExtraTagBits = 4;
    145 const int kPositionTypeTagBits = 1;
    146 const int kSmallDataBits = kBitsPerByte - kPositionTypeTagBits;
    147 
    148 const int kEmbeddedObjectTag = 0;
    149 const int kCodeTargetTag = 1;
    150 const int kPositionTag = 2;
    151 const int kDefaultTag = 3;
    152 
    153 const int kPCJumpTag = (1 << kExtraTagBits) - 1;
    154 
    155 const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
    156 const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
    157 const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
    158 
    159 const int kVariableLengthPCJumpTopTag = 1;
    160 const int kChunkBits = 7;
    161 const int kChunkMask = (1 << kChunkBits) - 1;
    162 const int kLastChunkTagBits = 1;
    163 const int kLastChunkTagMask = 1;
    164 const int kLastChunkTag = 1;
    165 
    166 
    167 const int kDataJumpTag = kPCJumpTag - 1;
    168 
    169 const int kNonstatementPositionTag = 0;
    170 const int kStatementPositionTag = 1;
    171 const int kCommentTag = 2;
    172 
    173 
    174 uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
    175   // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
    176   // Otherwise write a variable length PC jump for the bits that do
    177   // not fit in the kSmallPCDeltaBits bits.
    178   if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
    179   WriteExtraTag(kPCJumpTag, kVariableLengthPCJumpTopTag);
    180   uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
    181   ASSERT(pc_jump > 0);
    182   // Write kChunkBits size chunks of the pc_jump.
    183   for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
    184     byte b = pc_jump & kChunkMask;
    185     *--pos_ = b << kLastChunkTagBits;
    186   }
    187   // Tag the last chunk so it can be identified.
    188   *pos_ = *pos_ | kLastChunkTag;
    189   // Return the remaining kSmallPCDeltaBits of the pc_delta.
    190   return pc_delta & kSmallPCDeltaMask;
    191 }
    192 
    193 
    194 void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
    195   // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump.
    196   pc_delta = WriteVariableLengthPCJump(pc_delta);
    197   *--pos_ = pc_delta << kTagBits | tag;
    198 }
    199 
    200 
    201 void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) {
    202   *--pos_ = static_cast<byte>(data_delta << kPositionTypeTagBits | tag);
    203 }
    204 
    205 
    206 void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
    207   *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) |
    208                              extra_tag << kTagBits |
    209                              kDefaultTag);
    210 }
    211 
    212 
    213 void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
    214   // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
    215   pc_delta = WriteVariableLengthPCJump(pc_delta);
    216   WriteExtraTag(extra_tag, 0);
    217   *--pos_ = pc_delta;
    218 }
    219 
    220 
    221 void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
    222   WriteExtraTag(kDataJumpTag, top_tag);
    223   for (int i = 0; i < kIntptrSize; i++) {
    224     *--pos_ = static_cast<byte>(data_delta);
    225   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
    226     data_delta = data_delta >> kBitsPerByte;
    227   }
    228 }
    229 
    230 
    231 void RelocInfoWriter::Write(const RelocInfo* rinfo) {
    232 #ifdef DEBUG
    233   byte* begin_pos = pos_;
    234 #endif
    235   ASSERT(rinfo->pc() - last_pc_ >= 0);
    236   ASSERT(RelocInfo::NUMBER_OF_MODES <= kMaxRelocModes);
    237   // Use unsigned delta-encoding for pc.
    238   uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
    239   RelocInfo::Mode rmode = rinfo->rmode();
    240 
    241   // The two most common modes are given small tags, and usually fit in a byte.
    242   if (rmode == RelocInfo::EMBEDDED_OBJECT) {
    243     WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
    244   } else if (rmode == RelocInfo::CODE_TARGET) {
    245     WriteTaggedPC(pc_delta, kCodeTargetTag);
    246     ASSERT(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
    247   } else if (RelocInfo::IsPosition(rmode)) {
    248     // Use signed delta-encoding for data.
    249     intptr_t data_delta = rinfo->data() - last_data_;
    250     int pos_type_tag = rmode == RelocInfo::POSITION ? kNonstatementPositionTag
    251                                                     : kStatementPositionTag;
    252     // Check if data is small enough to fit in a tagged byte.
    253     // We cannot use is_intn because data_delta is not an int32_t.
    254     if (data_delta >= -(1 << (kSmallDataBits-1)) &&
    255         data_delta < 1 << (kSmallDataBits-1)) {
    256       WriteTaggedPC(pc_delta, kPositionTag);
    257       WriteTaggedData(data_delta, pos_type_tag);
    258       last_data_ = rinfo->data();
    259     } else {
    260       // Otherwise, use costly encoding.
    261       WriteExtraTaggedPC(pc_delta, kPCJumpTag);
    262       WriteExtraTaggedData(data_delta, pos_type_tag);
    263       last_data_ = rinfo->data();
    264     }
    265   } else if (RelocInfo::IsComment(rmode)) {
    266     // Comments are normally not generated, so we use the costly encoding.
    267     WriteExtraTaggedPC(pc_delta, kPCJumpTag);
    268     WriteExtraTaggedData(rinfo->data() - last_data_, kCommentTag);
    269     last_data_ = rinfo->data();
    270     ASSERT(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
    271   } else {
    272     // For all other modes we simply use the mode as the extra tag.
    273     // None of these modes need a data component.
    274     ASSERT(rmode < kPCJumpTag && rmode < kDataJumpTag);
    275     WriteExtraTaggedPC(pc_delta, rmode);
    276   }
    277   last_pc_ = rinfo->pc();
    278 #ifdef DEBUG
    279   ASSERT(begin_pos - pos_ <= kMaxSize);
    280 #endif
    281 }
    282 
    283 
    284 inline int RelocIterator::AdvanceGetTag() {
    285   return *--pos_ & kTagMask;
    286 }
    287 
    288 
    289 inline int RelocIterator::GetExtraTag() {
    290   return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
    291 }
    292 
    293 
    294 inline int RelocIterator::GetTopTag() {
    295   return *pos_ >> (kTagBits + kExtraTagBits);
    296 }
    297 
    298 
    299 inline void RelocIterator::ReadTaggedPC() {
    300   rinfo_.pc_ += *pos_ >> kTagBits;
    301 }
    302 
    303 
    304 inline void RelocIterator::AdvanceReadPC() {
    305   rinfo_.pc_ += *--pos_;
    306 }
    307 
    308 
    309 void RelocIterator::AdvanceReadData() {
    310   intptr_t x = 0;
    311   for (int i = 0; i < kIntptrSize; i++) {
    312     x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
    313   }
    314   rinfo_.data_ += x;
    315 }
    316 
    317 
    318 void RelocIterator::AdvanceReadVariableLengthPCJump() {
    319   // Read the 32-kSmallPCDeltaBits most significant bits of the
    320   // pc jump in kChunkBits bit chunks and shift them into place.
    321   // Stop when the last chunk is encountered.
    322   uint32_t pc_jump = 0;
    323   for (int i = 0; i < kIntSize; i++) {
    324     byte pc_jump_part = *--pos_;
    325     pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
    326     if ((pc_jump_part & kLastChunkTagMask) == 1) break;
    327   }
    328   // The least significant kSmallPCDeltaBits bits will be added
    329   // later.
    330   rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
    331 }
    332 
    333 
    334 inline int RelocIterator::GetPositionTypeTag() {
    335   return *pos_ & ((1 << kPositionTypeTagBits) - 1);
    336 }
    337 
    338 
    339 inline void RelocIterator::ReadTaggedData() {
    340   int8_t signed_b = *pos_;
    341   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
    342   rinfo_.data_ += signed_b >> kPositionTypeTagBits;
    343 }
    344 
    345 
    346 inline RelocInfo::Mode RelocIterator::DebugInfoModeFromTag(int tag) {
    347   if (tag == kStatementPositionTag) {
    348     return RelocInfo::STATEMENT_POSITION;
    349   } else if (tag == kNonstatementPositionTag) {
    350     return RelocInfo::POSITION;
    351   } else {
    352     ASSERT(tag == kCommentTag);
    353     return RelocInfo::COMMENT;
    354   }
    355 }
    356 
    357 
    358 void RelocIterator::next() {
    359   ASSERT(!done());
    360   // Basically, do the opposite of RelocInfoWriter::Write.
    361   // Reading of data is as far as possible avoided for unwanted modes,
    362   // but we must always update the pc.
    363   //
    364   // We exit this loop by returning when we find a mode we want.
    365   while (pos_ > end_) {
    366     int tag = AdvanceGetTag();
    367     if (tag == kEmbeddedObjectTag) {
    368       ReadTaggedPC();
    369       if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
    370     } else if (tag == kCodeTargetTag) {
    371       ReadTaggedPC();
    372       if (SetMode(RelocInfo::CODE_TARGET)) return;
    373     } else if (tag == kPositionTag) {
    374       ReadTaggedPC();
    375       Advance();
    376       // Check if we want source positions.
    377       if (mode_mask_ & RelocInfo::kPositionMask) {
    378         ReadTaggedData();
    379         if (SetMode(DebugInfoModeFromTag(GetPositionTypeTag()))) return;
    380       }
    381     } else {
    382       ASSERT(tag == kDefaultTag);
    383       int extra_tag = GetExtraTag();
    384       if (extra_tag == kPCJumpTag) {
    385         int top_tag = GetTopTag();
    386         if (top_tag == kVariableLengthPCJumpTopTag) {
    387           AdvanceReadVariableLengthPCJump();
    388         } else {
    389           AdvanceReadPC();
    390         }
    391       } else if (extra_tag == kDataJumpTag) {
    392         // Check if we want debug modes (the only ones with data).
    393         if (mode_mask_ & RelocInfo::kDebugMask) {
    394           int top_tag = GetTopTag();
    395           AdvanceReadData();
    396           if (SetMode(DebugInfoModeFromTag(top_tag))) return;
    397         } else {
    398           // Otherwise, just skip over the data.
    399           Advance(kIntptrSize);
    400         }
    401       } else {
    402         AdvanceReadPC();
    403         if (SetMode(static_cast<RelocInfo::Mode>(extra_tag))) return;
    404       }
    405     }
    406   }
    407   done_ = true;
    408 }
    409 
    410 
    411 RelocIterator::RelocIterator(Code* code, int mode_mask) {
    412   rinfo_.pc_ = code->instruction_start();
    413   rinfo_.data_ = 0;
    414   // Relocation info is read backwards.
    415   pos_ = code->relocation_start() + code->relocation_size();
    416   end_ = code->relocation_start();
    417   done_ = false;
    418   mode_mask_ = mode_mask;
    419   if (mode_mask_ == 0) pos_ = end_;
    420   next();
    421 }
    422 
    423 
    424 RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
    425   rinfo_.pc_ = desc.buffer;
    426   rinfo_.data_ = 0;
    427   // Relocation info is read backwards.
    428   pos_ = desc.buffer + desc.buffer_size;
    429   end_ = pos_ - desc.reloc_size;
    430   done_ = false;
    431   mode_mask_ = mode_mask;
    432   if (mode_mask_ == 0) pos_ = end_;
    433   next();
    434 }
    435 
    436 
    437 // -----------------------------------------------------------------------------
    438 // Implementation of RelocInfo
    439 
    440 
    441 #ifdef ENABLE_DISASSEMBLER
    442 const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
    443   switch (rmode) {
    444     case RelocInfo::NONE:
    445       return "no reloc";
    446     case RelocInfo::EMBEDDED_OBJECT:
    447       return "embedded object";
    448     case RelocInfo::CONSTRUCT_CALL:
    449       return "code target (js construct call)";
    450     case RelocInfo::CODE_TARGET_CONTEXT:
    451       return "code target (context)";
    452     case RelocInfo::DEBUG_BREAK:
    453 #ifndef ENABLE_DEBUGGER_SUPPORT
    454       UNREACHABLE();
    455 #endif
    456       return "debug break";
    457     case RelocInfo::CODE_TARGET:
    458       return "code target";
    459     case RelocInfo::GLOBAL_PROPERTY_CELL:
    460       return "global property cell";
    461     case RelocInfo::RUNTIME_ENTRY:
    462       return "runtime entry";
    463     case RelocInfo::JS_RETURN:
    464       return "js return";
    465     case RelocInfo::COMMENT:
    466       return "comment";
    467     case RelocInfo::POSITION:
    468       return "position";
    469     case RelocInfo::STATEMENT_POSITION:
    470       return "statement position";
    471     case RelocInfo::EXTERNAL_REFERENCE:
    472       return "external reference";
    473     case RelocInfo::INTERNAL_REFERENCE:
    474       return "internal reference";
    475     case RelocInfo::DEBUG_BREAK_SLOT:
    476 #ifndef ENABLE_DEBUGGER_SUPPORT
    477       UNREACHABLE();
    478 #endif
    479       return "debug break slot";
    480     case RelocInfo::NUMBER_OF_MODES:
    481       UNREACHABLE();
    482       return "number_of_modes";
    483   }
    484   return "unknown relocation type";
    485 }
    486 
    487 
    488 void RelocInfo::Print(FILE* out) {
    489   PrintF(out, "%p  %s", pc_, RelocModeName(rmode_));
    490   if (IsComment(rmode_)) {
    491     PrintF(out, "  (%s)", reinterpret_cast<char*>(data_));
    492   } else if (rmode_ == EMBEDDED_OBJECT) {
    493     PrintF(out, "  (");
    494     target_object()->ShortPrint(out);
    495     PrintF(out, ")");
    496   } else if (rmode_ == EXTERNAL_REFERENCE) {
    497     ExternalReferenceEncoder ref_encoder;
    498     PrintF(out, " (%s)  (%p)",
    499            ref_encoder.NameOfAddress(*target_reference_address()),
    500            *target_reference_address());
    501   } else if (IsCodeTarget(rmode_)) {
    502     Code* code = Code::GetCodeFromTargetAddress(target_address());
    503     PrintF(out, " (%s)  (%p)", Code::Kind2String(code->kind()),
    504            target_address());
    505   } else if (IsPosition(rmode_)) {
    506     PrintF(out, "  (%" V8_PTR_PREFIX "d)", data());
    507   } else if (rmode_ == RelocInfo::RUNTIME_ENTRY &&
    508              Isolate::Current()->deoptimizer_data() != NULL) {
    509     // Depotimization bailouts are stored as runtime entries.
    510     int id = Deoptimizer::GetDeoptimizationId(
    511         target_address(), Deoptimizer::EAGER);
    512     if (id != Deoptimizer::kNotDeoptimizationEntry) {
    513       PrintF(out, "  (deoptimization bailout %d)", id);
    514     }
    515   }
    516 
    517   PrintF(out, "\n");
    518 }
    519 #endif  // ENABLE_DISASSEMBLER
    520 
    521 
    522 #ifdef DEBUG
    523 void RelocInfo::Verify() {
    524   switch (rmode_) {
    525     case EMBEDDED_OBJECT:
    526       Object::VerifyPointer(target_object());
    527       break;
    528     case GLOBAL_PROPERTY_CELL:
    529       Object::VerifyPointer(target_cell());
    530       break;
    531     case DEBUG_BREAK:
    532 #ifndef ENABLE_DEBUGGER_SUPPORT
    533       UNREACHABLE();
    534       break;
    535 #endif
    536     case CONSTRUCT_CALL:
    537     case CODE_TARGET_CONTEXT:
    538     case CODE_TARGET: {
    539       // convert inline target address to code object
    540       Address addr = target_address();
    541       ASSERT(addr != NULL);
    542       // Check that we can find the right code object.
    543       Code* code = Code::GetCodeFromTargetAddress(addr);
    544       Object* found = HEAP->FindCodeObject(addr);
    545       ASSERT(found->IsCode());
    546       ASSERT(code->address() == HeapObject::cast(found)->address());
    547       break;
    548     }
    549     case RUNTIME_ENTRY:
    550     case JS_RETURN:
    551     case COMMENT:
    552     case POSITION:
    553     case STATEMENT_POSITION:
    554     case EXTERNAL_REFERENCE:
    555     case INTERNAL_REFERENCE:
    556     case DEBUG_BREAK_SLOT:
    557     case NONE:
    558       break;
    559     case NUMBER_OF_MODES:
    560       UNREACHABLE();
    561       break;
    562   }
    563 }
    564 #endif  // DEBUG
    565 
    566 
    567 // -----------------------------------------------------------------------------
    568 // Implementation of ExternalReference
    569 
    570 ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate)
    571   : address_(Redirect(isolate, Builtins::c_function_address(id))) {}
    572 
    573 
    574 ExternalReference::ExternalReference(
    575     ApiFunction* fun,
    576     Type type = ExternalReference::BUILTIN_CALL,
    577     Isolate* isolate = NULL)
    578   : address_(Redirect(isolate, fun->address(), type)) {}
    579 
    580 
    581 ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate)
    582   : address_(isolate->builtins()->builtin_address(name)) {}
    583 
    584 
    585 ExternalReference::ExternalReference(Runtime::FunctionId id,
    586                                      Isolate* isolate)
    587   : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
    588 
    589 
    590 ExternalReference::ExternalReference(const Runtime::Function* f,
    591                                      Isolate* isolate)
    592   : address_(Redirect(isolate, f->entry)) {}
    593 
    594 
    595 ExternalReference ExternalReference::isolate_address() {
    596   return ExternalReference(Isolate::Current());
    597 }
    598 
    599 
    600 ExternalReference::ExternalReference(const IC_Utility& ic_utility,
    601                                      Isolate* isolate)
    602   : address_(Redirect(isolate, ic_utility.address())) {}
    603 
    604 #ifdef ENABLE_DEBUGGER_SUPPORT
    605 ExternalReference::ExternalReference(const Debug_Address& debug_address,
    606                                      Isolate* isolate)
    607   : address_(debug_address.address(isolate)) {}
    608 #endif
    609 
    610 ExternalReference::ExternalReference(StatsCounter* counter)
    611   : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
    612 
    613 
    614 ExternalReference::ExternalReference(Isolate::AddressId id, Isolate* isolate)
    615   : address_(isolate->get_address_from_id(id)) {}
    616 
    617 
    618 ExternalReference::ExternalReference(const SCTableReference& table_ref)
    619   : address_(table_ref.address()) {}
    620 
    621 
    622 ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) {
    623   return ExternalReference(Redirect(isolate,
    624                                     FUNCTION_ADDR(Runtime::PerformGC)));
    625 }
    626 
    627 
    628 ExternalReference ExternalReference::fill_heap_number_with_random_function(
    629     Isolate* isolate) {
    630   return ExternalReference(Redirect(
    631       isolate,
    632       FUNCTION_ADDR(V8::FillHeapNumberWithRandom)));
    633 }
    634 
    635 
    636 ExternalReference ExternalReference::delete_handle_scope_extensions(
    637     Isolate* isolate) {
    638   return ExternalReference(Redirect(
    639       isolate,
    640       FUNCTION_ADDR(HandleScope::DeleteExtensions)));
    641 }
    642 
    643 
    644 ExternalReference ExternalReference::random_uint32_function(
    645     Isolate* isolate) {
    646   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(V8::Random)));
    647 }
    648 
    649 
    650 ExternalReference ExternalReference::transcendental_cache_array_address(
    651     Isolate* isolate) {
    652   return ExternalReference(
    653       isolate->transcendental_cache()->cache_array_address());
    654 }
    655 
    656 
    657 ExternalReference ExternalReference::new_deoptimizer_function(
    658     Isolate* isolate) {
    659   return ExternalReference(
    660       Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
    661 }
    662 
    663 
    664 ExternalReference ExternalReference::compute_output_frames_function(
    665     Isolate* isolate) {
    666   return ExternalReference(
    667       Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
    668 }
    669 
    670 
    671 ExternalReference ExternalReference::global_contexts_list(Isolate* isolate) {
    672   return ExternalReference(isolate->heap()->global_contexts_list_address());
    673 }
    674 
    675 
    676 ExternalReference ExternalReference::keyed_lookup_cache_keys(Isolate* isolate) {
    677   return ExternalReference(isolate->keyed_lookup_cache()->keys_address());
    678 }
    679 
    680 
    681 ExternalReference ExternalReference::keyed_lookup_cache_field_offsets(
    682     Isolate* isolate) {
    683   return ExternalReference(
    684       isolate->keyed_lookup_cache()->field_offsets_address());
    685 }
    686 
    687 
    688 ExternalReference ExternalReference::the_hole_value_location(Isolate* isolate) {
    689   return ExternalReference(isolate->factory()->the_hole_value().location());
    690 }
    691 
    692 
    693 ExternalReference ExternalReference::arguments_marker_location(
    694     Isolate* isolate) {
    695   return ExternalReference(isolate->factory()->arguments_marker().location());
    696 }
    697 
    698 
    699 ExternalReference ExternalReference::roots_address(Isolate* isolate) {
    700   return ExternalReference(isolate->heap()->roots_address());
    701 }
    702 
    703 
    704 ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
    705   return ExternalReference(isolate->stack_guard()->address_of_jslimit());
    706 }
    707 
    708 
    709 ExternalReference ExternalReference::address_of_real_stack_limit(
    710     Isolate* isolate) {
    711   return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
    712 }
    713 
    714 
    715 ExternalReference ExternalReference::address_of_regexp_stack_limit(
    716     Isolate* isolate) {
    717   return ExternalReference(isolate->regexp_stack()->limit_address());
    718 }
    719 
    720 
    721 ExternalReference ExternalReference::new_space_start(Isolate* isolate) {
    722   return ExternalReference(isolate->heap()->NewSpaceStart());
    723 }
    724 
    725 
    726 ExternalReference ExternalReference::new_space_mask(Isolate* isolate) {
    727   Address mask = reinterpret_cast<Address>(isolate->heap()->NewSpaceMask());
    728   return ExternalReference(mask);
    729 }
    730 
    731 
    732 ExternalReference ExternalReference::new_space_allocation_top_address(
    733     Isolate* isolate) {
    734   return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
    735 }
    736 
    737 
    738 ExternalReference ExternalReference::heap_always_allocate_scope_depth(
    739     Isolate* isolate) {
    740   Heap* heap = isolate->heap();
    741   return ExternalReference(heap->always_allocate_scope_depth_address());
    742 }
    743 
    744 
    745 ExternalReference ExternalReference::new_space_allocation_limit_address(
    746     Isolate* isolate) {
    747   return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
    748 }
    749 
    750 
    751 ExternalReference ExternalReference::handle_scope_level_address() {
    752   return ExternalReference(HandleScope::current_level_address());
    753 }
    754 
    755 
    756 ExternalReference ExternalReference::handle_scope_next_address() {
    757   return ExternalReference(HandleScope::current_next_address());
    758 }
    759 
    760 
    761 ExternalReference ExternalReference::handle_scope_limit_address() {
    762   return ExternalReference(HandleScope::current_limit_address());
    763 }
    764 
    765 
    766 ExternalReference ExternalReference::scheduled_exception_address(
    767     Isolate* isolate) {
    768   return ExternalReference(isolate->scheduled_exception_address());
    769 }
    770 
    771 
    772 ExternalReference ExternalReference::address_of_min_int() {
    773   return ExternalReference(reinterpret_cast<void*>(
    774       const_cast<double*>(&DoubleConstant::min_int)));
    775 }
    776 
    777 
    778 ExternalReference ExternalReference::address_of_one_half() {
    779   return ExternalReference(reinterpret_cast<void*>(
    780       const_cast<double*>(&DoubleConstant::one_half)));
    781 }
    782 
    783 
    784 ExternalReference ExternalReference::address_of_minus_zero() {
    785   return ExternalReference(reinterpret_cast<void*>(
    786       const_cast<double*>(&DoubleConstant::minus_zero)));
    787 }
    788 
    789 
    790 ExternalReference ExternalReference::address_of_negative_infinity() {
    791   return ExternalReference(reinterpret_cast<void*>(
    792       const_cast<double*>(&DoubleConstant::negative_infinity)));
    793 }
    794 
    795 
    796 ExternalReference ExternalReference::address_of_nan() {
    797   return ExternalReference(reinterpret_cast<void*>(
    798       const_cast<double*>(&DoubleConstant::nan)));
    799 }
    800 
    801 
    802 #ifndef V8_INTERPRETED_REGEXP
    803 
    804 ExternalReference ExternalReference::re_check_stack_guard_state(
    805     Isolate* isolate) {
    806   Address function;
    807 #ifdef V8_TARGET_ARCH_X64
    808   function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
    809 #elif V8_TARGET_ARCH_IA32
    810   function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
    811 #elif V8_TARGET_ARCH_ARM
    812   function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
    813 #elif V8_TARGET_ARCH_MIPS
    814   function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
    815 #else
    816   UNREACHABLE();
    817 #endif
    818   return ExternalReference(Redirect(isolate, function));
    819 }
    820 
    821 ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
    822   return ExternalReference(
    823       Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
    824 }
    825 
    826 ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
    827     Isolate* isolate) {
    828   return ExternalReference(Redirect(
    829       isolate,
    830       FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
    831 }
    832 
    833 ExternalReference ExternalReference::re_word_character_map() {
    834   return ExternalReference(
    835       NativeRegExpMacroAssembler::word_character_map_address());
    836 }
    837 
    838 ExternalReference ExternalReference::address_of_static_offsets_vector(
    839     Isolate* isolate) {
    840   return ExternalReference(
    841       OffsetsVector::static_offsets_vector_address(isolate));
    842 }
    843 
    844 ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
    845     Isolate* isolate) {
    846   return ExternalReference(
    847       isolate->regexp_stack()->memory_address());
    848 }
    849 
    850 ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
    851     Isolate* isolate) {
    852   return ExternalReference(isolate->regexp_stack()->memory_size_address());
    853 }
    854 
    855 #endif  // V8_INTERPRETED_REGEXP
    856 
    857 
    858 static double add_two_doubles(double x, double y) {
    859   return x + y;
    860 }
    861 
    862 
    863 static double sub_two_doubles(double x, double y) {
    864   return x - y;
    865 }
    866 
    867 
    868 static double mul_two_doubles(double x, double y) {
    869   return x * y;
    870 }
    871 
    872 
    873 static double div_two_doubles(double x, double y) {
    874   return x / y;
    875 }
    876 
    877 
    878 static double mod_two_doubles(double x, double y) {
    879   return modulo(x, y);
    880 }
    881 
    882 
    883 static double math_sin_double(double x) {
    884   return sin(x);
    885 }
    886 
    887 
    888 static double math_cos_double(double x) {
    889   return cos(x);
    890 }
    891 
    892 
    893 static double math_log_double(double x) {
    894   return log(x);
    895 }
    896 
    897 
    898 ExternalReference ExternalReference::math_sin_double_function(
    899     Isolate* isolate) {
    900   return ExternalReference(Redirect(isolate,
    901                                     FUNCTION_ADDR(math_sin_double),
    902                                     FP_RETURN_CALL));
    903 }
    904 
    905 
    906 ExternalReference ExternalReference::math_cos_double_function(
    907     Isolate* isolate) {
    908   return ExternalReference(Redirect(isolate,
    909                                     FUNCTION_ADDR(math_cos_double),
    910                                     FP_RETURN_CALL));
    911 }
    912 
    913 
    914 ExternalReference ExternalReference::math_log_double_function(
    915     Isolate* isolate) {
    916   return ExternalReference(Redirect(isolate,
    917                                     FUNCTION_ADDR(math_log_double),
    918                                     FP_RETURN_CALL));
    919 }
    920 
    921 
    922 // Helper function to compute x^y, where y is known to be an
    923 // integer. Uses binary decomposition to limit the number of
    924 // multiplications; see the discussion in "Hacker's Delight" by Henry
    925 // S. Warren, Jr., figure 11-6, page 213.
    926 double power_double_int(double x, int y) {
    927   double m = (y < 0) ? 1 / x : x;
    928   unsigned n = (y < 0) ? -y : y;
    929   double p = 1;
    930   while (n != 0) {
    931     if ((n & 1) != 0) p *= m;
    932     m *= m;
    933     if ((n & 2) != 0) p *= m;
    934     m *= m;
    935     n >>= 2;
    936   }
    937   return p;
    938 }
    939 
    940 
    941 double power_double_double(double x, double y) {
    942   int y_int = static_cast<int>(y);
    943   if (y == y_int) {
    944     return power_double_int(x, y_int);  // Returns 1.0 for exponent 0.
    945   }
    946   if (!isinf(x)) {
    947     if (y == 0.5) return sqrt(x + 0.0);  // -0 must be converted to +0.
    948     if (y == -0.5) return 1.0 / sqrt(x + 0.0);
    949   }
    950   if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
    951     return OS::nan_value();
    952   }
    953   return pow(x, y);
    954 }
    955 
    956 
    957 ExternalReference ExternalReference::power_double_double_function(
    958     Isolate* isolate) {
    959   return ExternalReference(Redirect(isolate,
    960                                     FUNCTION_ADDR(power_double_double),
    961                                     FP_RETURN_CALL));
    962 }
    963 
    964 
    965 ExternalReference ExternalReference::power_double_int_function(
    966     Isolate* isolate) {
    967   return ExternalReference(Redirect(isolate,
    968                                     FUNCTION_ADDR(power_double_int),
    969                                     FP_RETURN_CALL));
    970 }
    971 
    972 
    973 static int native_compare_doubles(double y, double x) {
    974   if (x == y) return EQUAL;
    975   return x < y ? LESS : GREATER;
    976 }
    977 
    978 
    979 ExternalReference ExternalReference::double_fp_operation(
    980     Token::Value operation, Isolate* isolate) {
    981   typedef double BinaryFPOperation(double x, double y);
    982   BinaryFPOperation* function = NULL;
    983   switch (operation) {
    984     case Token::ADD:
    985       function = &add_two_doubles;
    986       break;
    987     case Token::SUB:
    988       function = &sub_two_doubles;
    989       break;
    990     case Token::MUL:
    991       function = &mul_two_doubles;
    992       break;
    993     case Token::DIV:
    994       function = &div_two_doubles;
    995       break;
    996     case Token::MOD:
    997       function = &mod_two_doubles;
    998       break;
    999     default:
   1000       UNREACHABLE();
   1001   }
   1002   // Passing true as 2nd parameter indicates that they return an fp value.
   1003   return ExternalReference(Redirect(isolate,
   1004                                     FUNCTION_ADDR(function),
   1005                                     FP_RETURN_CALL));
   1006 }
   1007 
   1008 
   1009 ExternalReference ExternalReference::compare_doubles(Isolate* isolate) {
   1010   return ExternalReference(Redirect(isolate,
   1011                                     FUNCTION_ADDR(native_compare_doubles),
   1012                                     BUILTIN_CALL));
   1013 }
   1014 
   1015 
   1016 #ifdef ENABLE_DEBUGGER_SUPPORT
   1017 ExternalReference ExternalReference::debug_break(Isolate* isolate) {
   1018   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug_Break)));
   1019 }
   1020 
   1021 
   1022 ExternalReference ExternalReference::debug_step_in_fp_address(
   1023     Isolate* isolate) {
   1024   return ExternalReference(isolate->debug()->step_in_fp_addr());
   1025 }
   1026 #endif
   1027 
   1028 
   1029 void PositionsRecorder::RecordPosition(int pos) {
   1030   ASSERT(pos != RelocInfo::kNoPosition);
   1031   ASSERT(pos >= 0);
   1032   state_.current_position = pos;
   1033 #ifdef ENABLE_GDB_JIT_INTERFACE
   1034   if (gdbjit_lineinfo_ != NULL) {
   1035     gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false);
   1036   }
   1037 #endif
   1038 }
   1039 
   1040 
   1041 void PositionsRecorder::RecordStatementPosition(int pos) {
   1042   ASSERT(pos != RelocInfo::kNoPosition);
   1043   ASSERT(pos >= 0);
   1044   state_.current_statement_position = pos;
   1045 #ifdef ENABLE_GDB_JIT_INTERFACE
   1046   if (gdbjit_lineinfo_ != NULL) {
   1047     gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true);
   1048   }
   1049 #endif
   1050 }
   1051 
   1052 
   1053 bool PositionsRecorder::WriteRecordedPositions() {
   1054   bool written = false;
   1055 
   1056   // Write the statement position if it is different from what was written last
   1057   // time.
   1058   if (state_.current_statement_position != state_.written_statement_position) {
   1059     EnsureSpace ensure_space(assembler_);
   1060     assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
   1061                                 state_.current_statement_position);
   1062     state_.written_statement_position = state_.current_statement_position;
   1063     written = true;
   1064   }
   1065 
   1066   // Write the position if it is different from what was written last time and
   1067   // also different from the written statement position.
   1068   if (state_.current_position != state_.written_position &&
   1069       state_.current_position != state_.written_statement_position) {
   1070     EnsureSpace ensure_space(assembler_);
   1071     assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
   1072     state_.written_position = state_.current_position;
   1073     written = true;
   1074   }
   1075 
   1076   // Return whether something was written.
   1077   return written;
   1078 }
   1079 
   1080 } }  // namespace v8::internal
   1081