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 "execution.h" 39 #include "ic-inl.h" 40 #include "factory.h" 41 #include "runtime.h" 42 #include "serialize.h" 43 #include "stub-cache.h" 44 #include "regexp-stack.h" 45 #include "ast.h" 46 #include "regexp-macro-assembler.h" 47 #include "platform.h" 48 // Include native regexp-macro-assembler. 49 #ifdef V8_NATIVE_REGEXP 50 #if V8_TARGET_ARCH_IA32 51 #include "ia32/regexp-macro-assembler-ia32.h" 52 #elif V8_TARGET_ARCH_X64 53 #include "x64/regexp-macro-assembler-x64.h" 54 #elif V8_TARGET_ARCH_ARM 55 #include "arm/regexp-macro-assembler-arm.h" 56 #else // Unknown architecture. 57 #error "Unknown architecture." 58 #endif // Target architecture. 59 #endif // V8_NATIVE_REGEXP 60 61 namespace v8 { 62 namespace internal { 63 64 65 // ----------------------------------------------------------------------------- 66 // Implementation of Label 67 68 int Label::pos() const { 69 if (pos_ < 0) return -pos_ - 1; 70 if (pos_ > 0) return pos_ - 1; 71 UNREACHABLE(); 72 return 0; 73 } 74 75 76 // ----------------------------------------------------------------------------- 77 // Implementation of RelocInfoWriter and RelocIterator 78 // 79 // Encoding 80 // 81 // The most common modes are given single-byte encodings. Also, it is 82 // easy to identify the type of reloc info and skip unwanted modes in 83 // an iteration. 84 // 85 // The encoding relies on the fact that there are less than 14 86 // different relocation modes. 87 // 88 // embedded_object: [6 bits pc delta] 00 89 // 90 // code_taget: [6 bits pc delta] 01 91 // 92 // position: [6 bits pc delta] 10, 93 // [7 bits signed data delta] 0 94 // 95 // statement_position: [6 bits pc delta] 10, 96 // [7 bits signed data delta] 1 97 // 98 // any nondata mode: 00 [4 bits rmode] 11, // rmode: 0..13 only 99 // 00 [6 bits pc delta] 100 // 101 // pc-jump: 00 1111 11, 102 // 00 [6 bits pc delta] 103 // 104 // pc-jump: 01 1111 11, 105 // (variable length) 7 - 26 bit pc delta, written in chunks of 7 106 // bits, the lowest 7 bits written first. 107 // 108 // data-jump + pos: 00 1110 11, 109 // signed intptr_t, lowest byte written first 110 // 111 // data-jump + st.pos: 01 1110 11, 112 // signed intptr_t, lowest byte written first 113 // 114 // data-jump + comm.: 10 1110 11, 115 // signed intptr_t, lowest byte written first 116 // 117 const int kMaxRelocModes = 14; 118 119 const int kTagBits = 2; 120 const int kTagMask = (1 << kTagBits) - 1; 121 const int kExtraTagBits = 4; 122 const int kPositionTypeTagBits = 1; 123 const int kSmallDataBits = kBitsPerByte - kPositionTypeTagBits; 124 125 const int kEmbeddedObjectTag = 0; 126 const int kCodeTargetTag = 1; 127 const int kPositionTag = 2; 128 const int kDefaultTag = 3; 129 130 const int kPCJumpTag = (1 << kExtraTagBits) - 1; 131 132 const int kSmallPCDeltaBits = kBitsPerByte - kTagBits; 133 const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1; 134 135 const int kVariableLengthPCJumpTopTag = 1; 136 const int kChunkBits = 7; 137 const int kChunkMask = (1 << kChunkBits) - 1; 138 const int kLastChunkTagBits = 1; 139 const int kLastChunkTagMask = 1; 140 const int kLastChunkTag = 1; 141 142 143 const int kDataJumpTag = kPCJumpTag - 1; 144 145 const int kNonstatementPositionTag = 0; 146 const int kStatementPositionTag = 1; 147 const int kCommentTag = 2; 148 149 150 uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) { 151 // Return if the pc_delta can fit in kSmallPCDeltaBits bits. 152 // Otherwise write a variable length PC jump for the bits that do 153 // not fit in the kSmallPCDeltaBits bits. 154 if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta; 155 WriteExtraTag(kPCJumpTag, kVariableLengthPCJumpTopTag); 156 uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits; 157 ASSERT(pc_jump > 0); 158 // Write kChunkBits size chunks of the pc_jump. 159 for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) { 160 byte b = pc_jump & kChunkMask; 161 *--pos_ = b << kLastChunkTagBits; 162 } 163 // Tag the last chunk so it can be identified. 164 *pos_ = *pos_ | kLastChunkTag; 165 // Return the remaining kSmallPCDeltaBits of the pc_delta. 166 return pc_delta & kSmallPCDeltaMask; 167 } 168 169 170 void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) { 171 // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump. 172 pc_delta = WriteVariableLengthPCJump(pc_delta); 173 *--pos_ = pc_delta << kTagBits | tag; 174 } 175 176 177 void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) { 178 *--pos_ = static_cast<byte>(data_delta << kPositionTypeTagBits | tag); 179 } 180 181 182 void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) { 183 *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) | 184 extra_tag << kTagBits | 185 kDefaultTag); 186 } 187 188 189 void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) { 190 // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump. 191 pc_delta = WriteVariableLengthPCJump(pc_delta); 192 WriteExtraTag(extra_tag, 0); 193 *--pos_ = pc_delta; 194 } 195 196 197 void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) { 198 WriteExtraTag(kDataJumpTag, top_tag); 199 for (int i = 0; i < kIntptrSize; i++) { 200 *--pos_ = static_cast<byte>(data_delta); 201 // Signed right shift is arithmetic shift. Tested in test-utils.cc. 202 data_delta = data_delta >> kBitsPerByte; 203 } 204 } 205 206 207 void RelocInfoWriter::Write(const RelocInfo* rinfo) { 208 #ifdef DEBUG 209 byte* begin_pos = pos_; 210 #endif 211 Counters::reloc_info_count.Increment(); 212 ASSERT(rinfo->pc() - last_pc_ >= 0); 213 ASSERT(RelocInfo::NUMBER_OF_MODES < kMaxRelocModes); 214 // Use unsigned delta-encoding for pc. 215 uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_); 216 RelocInfo::Mode rmode = rinfo->rmode(); 217 218 // The two most common modes are given small tags, and usually fit in a byte. 219 if (rmode == RelocInfo::EMBEDDED_OBJECT) { 220 WriteTaggedPC(pc_delta, kEmbeddedObjectTag); 221 } else if (rmode == RelocInfo::CODE_TARGET) { 222 WriteTaggedPC(pc_delta, kCodeTargetTag); 223 } else if (RelocInfo::IsPosition(rmode)) { 224 // Use signed delta-encoding for data. 225 intptr_t data_delta = rinfo->data() - last_data_; 226 int pos_type_tag = rmode == RelocInfo::POSITION ? kNonstatementPositionTag 227 : kStatementPositionTag; 228 // Check if data is small enough to fit in a tagged byte. 229 // We cannot use is_intn because data_delta is not an int32_t. 230 if (data_delta >= -(1 << (kSmallDataBits-1)) && 231 data_delta < 1 << (kSmallDataBits-1)) { 232 WriteTaggedPC(pc_delta, kPositionTag); 233 WriteTaggedData(data_delta, pos_type_tag); 234 last_data_ = rinfo->data(); 235 } else { 236 // Otherwise, use costly encoding. 237 WriteExtraTaggedPC(pc_delta, kPCJumpTag); 238 WriteExtraTaggedData(data_delta, pos_type_tag); 239 last_data_ = rinfo->data(); 240 } 241 } else if (RelocInfo::IsComment(rmode)) { 242 // Comments are normally not generated, so we use the costly encoding. 243 WriteExtraTaggedPC(pc_delta, kPCJumpTag); 244 WriteExtraTaggedData(rinfo->data() - last_data_, kCommentTag); 245 last_data_ = rinfo->data(); 246 } else { 247 // For all other modes we simply use the mode as the extra tag. 248 // None of these modes need a data component. 249 ASSERT(rmode < kPCJumpTag && rmode < kDataJumpTag); 250 WriteExtraTaggedPC(pc_delta, rmode); 251 } 252 last_pc_ = rinfo->pc(); 253 #ifdef DEBUG 254 ASSERT(begin_pos - pos_ <= kMaxSize); 255 #endif 256 } 257 258 259 inline int RelocIterator::AdvanceGetTag() { 260 return *--pos_ & kTagMask; 261 } 262 263 264 inline int RelocIterator::GetExtraTag() { 265 return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1); 266 } 267 268 269 inline int RelocIterator::GetTopTag() { 270 return *pos_ >> (kTagBits + kExtraTagBits); 271 } 272 273 274 inline void RelocIterator::ReadTaggedPC() { 275 rinfo_.pc_ += *pos_ >> kTagBits; 276 } 277 278 279 inline void RelocIterator::AdvanceReadPC() { 280 rinfo_.pc_ += *--pos_; 281 } 282 283 284 void RelocIterator::AdvanceReadData() { 285 intptr_t x = 0; 286 for (int i = 0; i < kIntptrSize; i++) { 287 x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte; 288 } 289 rinfo_.data_ += x; 290 } 291 292 293 void RelocIterator::AdvanceReadVariableLengthPCJump() { 294 // Read the 32-kSmallPCDeltaBits most significant bits of the 295 // pc jump in kChunkBits bit chunks and shift them into place. 296 // Stop when the last chunk is encountered. 297 uint32_t pc_jump = 0; 298 for (int i = 0; i < kIntSize; i++) { 299 byte pc_jump_part = *--pos_; 300 pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits; 301 if ((pc_jump_part & kLastChunkTagMask) == 1) break; 302 } 303 // The least significant kSmallPCDeltaBits bits will be added 304 // later. 305 rinfo_.pc_ += pc_jump << kSmallPCDeltaBits; 306 } 307 308 309 inline int RelocIterator::GetPositionTypeTag() { 310 return *pos_ & ((1 << kPositionTypeTagBits) - 1); 311 } 312 313 314 inline void RelocIterator::ReadTaggedData() { 315 int8_t signed_b = *pos_; 316 // Signed right shift is arithmetic shift. Tested in test-utils.cc. 317 rinfo_.data_ += signed_b >> kPositionTypeTagBits; 318 } 319 320 321 inline RelocInfo::Mode RelocIterator::DebugInfoModeFromTag(int tag) { 322 if (tag == kStatementPositionTag) { 323 return RelocInfo::STATEMENT_POSITION; 324 } else if (tag == kNonstatementPositionTag) { 325 return RelocInfo::POSITION; 326 } else { 327 ASSERT(tag == kCommentTag); 328 return RelocInfo::COMMENT; 329 } 330 } 331 332 333 void RelocIterator::next() { 334 ASSERT(!done()); 335 // Basically, do the opposite of RelocInfoWriter::Write. 336 // Reading of data is as far as possible avoided for unwanted modes, 337 // but we must always update the pc. 338 // 339 // We exit this loop by returning when we find a mode we want. 340 while (pos_ > end_) { 341 int tag = AdvanceGetTag(); 342 if (tag == kEmbeddedObjectTag) { 343 ReadTaggedPC(); 344 if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return; 345 } else if (tag == kCodeTargetTag) { 346 ReadTaggedPC(); 347 if (SetMode(RelocInfo::CODE_TARGET)) return; 348 } else if (tag == kPositionTag) { 349 ReadTaggedPC(); 350 Advance(); 351 // Check if we want source positions. 352 if (mode_mask_ & RelocInfo::kPositionMask) { 353 // Check if we want this type of source position. 354 if (SetMode(DebugInfoModeFromTag(GetPositionTypeTag()))) { 355 // Finally read the data before returning. 356 ReadTaggedData(); 357 return; 358 } 359 } 360 } else { 361 ASSERT(tag == kDefaultTag); 362 int extra_tag = GetExtraTag(); 363 if (extra_tag == kPCJumpTag) { 364 int top_tag = GetTopTag(); 365 if (top_tag == kVariableLengthPCJumpTopTag) { 366 AdvanceReadVariableLengthPCJump(); 367 } else { 368 AdvanceReadPC(); 369 } 370 } else if (extra_tag == kDataJumpTag) { 371 // Check if we want debug modes (the only ones with data). 372 if (mode_mask_ & RelocInfo::kDebugMask) { 373 int top_tag = GetTopTag(); 374 AdvanceReadData(); 375 if (SetMode(DebugInfoModeFromTag(top_tag))) return; 376 } else { 377 // Otherwise, just skip over the data. 378 Advance(kIntptrSize); 379 } 380 } else { 381 AdvanceReadPC(); 382 if (SetMode(static_cast<RelocInfo::Mode>(extra_tag))) return; 383 } 384 } 385 } 386 done_ = true; 387 } 388 389 390 RelocIterator::RelocIterator(Code* code, int mode_mask) { 391 rinfo_.pc_ = code->instruction_start(); 392 rinfo_.data_ = 0; 393 // relocation info is read backwards 394 pos_ = code->relocation_start() + code->relocation_size(); 395 end_ = code->relocation_start(); 396 done_ = false; 397 mode_mask_ = mode_mask; 398 if (mode_mask_ == 0) pos_ = end_; 399 next(); 400 } 401 402 403 RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) { 404 rinfo_.pc_ = desc.buffer; 405 rinfo_.data_ = 0; 406 // relocation info is read backwards 407 pos_ = desc.buffer + desc.buffer_size; 408 end_ = pos_ - desc.reloc_size; 409 done_ = false; 410 mode_mask_ = mode_mask; 411 if (mode_mask_ == 0) pos_ = end_; 412 next(); 413 } 414 415 416 // ----------------------------------------------------------------------------- 417 // Implementation of RelocInfo 418 419 420 #ifdef ENABLE_DISASSEMBLER 421 const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) { 422 switch (rmode) { 423 case RelocInfo::NONE: 424 return "no reloc"; 425 case RelocInfo::EMBEDDED_OBJECT: 426 return "embedded object"; 427 case RelocInfo::EMBEDDED_STRING: 428 return "embedded string"; 429 case RelocInfo::CONSTRUCT_CALL: 430 return "code target (js construct call)"; 431 case RelocInfo::CODE_TARGET_CONTEXT: 432 return "code target (context)"; 433 case RelocInfo::DEBUG_BREAK: 434 #ifndef ENABLE_DEBUGGER_SUPPORT 435 UNREACHABLE(); 436 #endif 437 return "debug break"; 438 case RelocInfo::CODE_TARGET: 439 return "code target"; 440 case RelocInfo::RUNTIME_ENTRY: 441 return "runtime entry"; 442 case RelocInfo::JS_RETURN: 443 return "js return"; 444 case RelocInfo::COMMENT: 445 return "comment"; 446 case RelocInfo::POSITION: 447 return "position"; 448 case RelocInfo::STATEMENT_POSITION: 449 return "statement position"; 450 case RelocInfo::EXTERNAL_REFERENCE: 451 return "external reference"; 452 case RelocInfo::INTERNAL_REFERENCE: 453 return "internal reference"; 454 case RelocInfo::NUMBER_OF_MODES: 455 UNREACHABLE(); 456 return "number_of_modes"; 457 } 458 return "unknown relocation type"; 459 } 460 461 462 void RelocInfo::Print() { 463 PrintF("%p %s", pc_, RelocModeName(rmode_)); 464 if (IsComment(rmode_)) { 465 PrintF(" (%s)", data_); 466 } else if (rmode_ == EMBEDDED_OBJECT) { 467 PrintF(" ("); 468 target_object()->ShortPrint(); 469 PrintF(")"); 470 } else if (rmode_ == EXTERNAL_REFERENCE) { 471 ExternalReferenceEncoder ref_encoder; 472 PrintF(" (%s) (%p)", 473 ref_encoder.NameOfAddress(*target_reference_address()), 474 *target_reference_address()); 475 } else if (IsCodeTarget(rmode_)) { 476 Code* code = Code::GetCodeFromTargetAddress(target_address()); 477 PrintF(" (%s) (%p)", Code::Kind2String(code->kind()), target_address()); 478 } else if (IsPosition(rmode_)) { 479 PrintF(" (%d)", data()); 480 } 481 482 PrintF("\n"); 483 } 484 #endif // ENABLE_DISASSEMBLER 485 486 487 #ifdef DEBUG 488 void RelocInfo::Verify() { 489 switch (rmode_) { 490 case EMBEDDED_OBJECT: 491 Object::VerifyPointer(target_object()); 492 break; 493 case DEBUG_BREAK: 494 #ifndef ENABLE_DEBUGGER_SUPPORT 495 UNREACHABLE(); 496 break; 497 #endif 498 case CONSTRUCT_CALL: 499 case CODE_TARGET_CONTEXT: 500 case CODE_TARGET: { 501 // convert inline target address to code object 502 Address addr = target_address(); 503 ASSERT(addr != NULL); 504 // Check that we can find the right code object. 505 Code* code = Code::GetCodeFromTargetAddress(addr); 506 Object* found = Heap::FindCodeObject(addr); 507 ASSERT(found->IsCode()); 508 ASSERT(code->address() == HeapObject::cast(found)->address()); 509 break; 510 } 511 case RelocInfo::EMBEDDED_STRING: 512 case RUNTIME_ENTRY: 513 case JS_RETURN: 514 case COMMENT: 515 case POSITION: 516 case STATEMENT_POSITION: 517 case EXTERNAL_REFERENCE: 518 case INTERNAL_REFERENCE: 519 case NONE: 520 break; 521 case NUMBER_OF_MODES: 522 UNREACHABLE(); 523 break; 524 } 525 } 526 #endif // DEBUG 527 528 529 // ----------------------------------------------------------------------------- 530 // Implementation of ExternalReference 531 532 ExternalReference::ExternalReference(Builtins::CFunctionId id) 533 : address_(Redirect(Builtins::c_function_address(id))) {} 534 535 536 ExternalReference::ExternalReference(ApiFunction* fun) 537 : address_(Redirect(fun->address())) {} 538 539 540 ExternalReference::ExternalReference(Builtins::Name name) 541 : address_(Builtins::builtin_address(name)) {} 542 543 544 ExternalReference::ExternalReference(Runtime::FunctionId id) 545 : address_(Redirect(Runtime::FunctionForId(id)->entry)) {} 546 547 548 ExternalReference::ExternalReference(Runtime::Function* f) 549 : address_(Redirect(f->entry)) {} 550 551 552 ExternalReference::ExternalReference(const IC_Utility& ic_utility) 553 : address_(Redirect(ic_utility.address())) {} 554 555 #ifdef ENABLE_DEBUGGER_SUPPORT 556 ExternalReference::ExternalReference(const Debug_Address& debug_address) 557 : address_(debug_address.address()) {} 558 #endif 559 560 ExternalReference::ExternalReference(StatsCounter* counter) 561 : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {} 562 563 564 ExternalReference::ExternalReference(Top::AddressId id) 565 : address_(Top::get_address_from_id(id)) {} 566 567 568 ExternalReference::ExternalReference(const SCTableReference& table_ref) 569 : address_(table_ref.address()) {} 570 571 572 ExternalReference ExternalReference::perform_gc_function() { 573 return ExternalReference(Redirect(FUNCTION_ADDR(Runtime::PerformGC))); 574 } 575 576 577 ExternalReference ExternalReference::random_positive_smi_function() { 578 return ExternalReference(Redirect(FUNCTION_ADDR(V8::RandomPositiveSmi))); 579 } 580 581 582 ExternalReference ExternalReference::transcendental_cache_array_address() { 583 return ExternalReference(TranscendentalCache::cache_array_address()); 584 } 585 586 587 ExternalReference ExternalReference::keyed_lookup_cache_keys() { 588 return ExternalReference(KeyedLookupCache::keys_address()); 589 } 590 591 592 ExternalReference ExternalReference::keyed_lookup_cache_field_offsets() { 593 return ExternalReference(KeyedLookupCache::field_offsets_address()); 594 } 595 596 597 ExternalReference ExternalReference::the_hole_value_location() { 598 return ExternalReference(Factory::the_hole_value().location()); 599 } 600 601 602 ExternalReference ExternalReference::roots_address() { 603 return ExternalReference(Heap::roots_address()); 604 } 605 606 607 ExternalReference ExternalReference::address_of_stack_limit() { 608 return ExternalReference(StackGuard::address_of_jslimit()); 609 } 610 611 612 ExternalReference ExternalReference::address_of_real_stack_limit() { 613 return ExternalReference(StackGuard::address_of_real_jslimit()); 614 } 615 616 617 ExternalReference ExternalReference::address_of_regexp_stack_limit() { 618 return ExternalReference(RegExpStack::limit_address()); 619 } 620 621 622 ExternalReference ExternalReference::new_space_start() { 623 return ExternalReference(Heap::NewSpaceStart()); 624 } 625 626 627 ExternalReference ExternalReference::new_space_mask() { 628 return ExternalReference(reinterpret_cast<Address>(Heap::NewSpaceMask())); 629 } 630 631 632 ExternalReference ExternalReference::new_space_allocation_top_address() { 633 return ExternalReference(Heap::NewSpaceAllocationTopAddress()); 634 } 635 636 637 ExternalReference ExternalReference::heap_always_allocate_scope_depth() { 638 return ExternalReference(Heap::always_allocate_scope_depth_address()); 639 } 640 641 642 ExternalReference ExternalReference::new_space_allocation_limit_address() { 643 return ExternalReference(Heap::NewSpaceAllocationLimitAddress()); 644 } 645 646 647 ExternalReference ExternalReference::handle_scope_extensions_address() { 648 return ExternalReference(HandleScope::current_extensions_address()); 649 } 650 651 652 ExternalReference ExternalReference::handle_scope_next_address() { 653 return ExternalReference(HandleScope::current_next_address()); 654 } 655 656 657 ExternalReference ExternalReference::handle_scope_limit_address() { 658 return ExternalReference(HandleScope::current_limit_address()); 659 } 660 661 662 ExternalReference ExternalReference::scheduled_exception_address() { 663 return ExternalReference(Top::scheduled_exception_address()); 664 } 665 666 667 #ifdef V8_NATIVE_REGEXP 668 669 ExternalReference ExternalReference::re_check_stack_guard_state() { 670 Address function; 671 #ifdef V8_TARGET_ARCH_X64 672 function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState); 673 #elif V8_TARGET_ARCH_IA32 674 function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState); 675 #elif V8_TARGET_ARCH_ARM 676 function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState); 677 #else 678 UNREACHABLE(); 679 #endif 680 return ExternalReference(Redirect(function)); 681 } 682 683 ExternalReference ExternalReference::re_grow_stack() { 684 return ExternalReference( 685 Redirect(FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack))); 686 } 687 688 ExternalReference ExternalReference::re_case_insensitive_compare_uc16() { 689 return ExternalReference(Redirect( 690 FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16))); 691 } 692 693 ExternalReference ExternalReference::re_word_character_map() { 694 return ExternalReference( 695 NativeRegExpMacroAssembler::word_character_map_address()); 696 } 697 698 ExternalReference ExternalReference::address_of_static_offsets_vector() { 699 return ExternalReference(OffsetsVector::static_offsets_vector_address()); 700 } 701 702 ExternalReference ExternalReference::address_of_regexp_stack_memory_address() { 703 return ExternalReference(RegExpStack::memory_address()); 704 } 705 706 ExternalReference ExternalReference::address_of_regexp_stack_memory_size() { 707 return ExternalReference(RegExpStack::memory_size_address()); 708 } 709 710 #endif 711 712 713 static double add_two_doubles(double x, double y) { 714 return x + y; 715 } 716 717 718 static double sub_two_doubles(double x, double y) { 719 return x - y; 720 } 721 722 723 static double mul_two_doubles(double x, double y) { 724 return x * y; 725 } 726 727 728 static double div_two_doubles(double x, double y) { 729 return x / y; 730 } 731 732 733 static double mod_two_doubles(double x, double y) { 734 return modulo(x, y); 735 } 736 737 738 static int native_compare_doubles(double y, double x) { 739 if (x == y) return EQUAL; 740 return x < y ? LESS : GREATER; 741 } 742 743 744 ExternalReference ExternalReference::double_fp_operation( 745 Token::Value operation) { 746 typedef double BinaryFPOperation(double x, double y); 747 BinaryFPOperation* function = NULL; 748 switch (operation) { 749 case Token::ADD: 750 function = &add_two_doubles; 751 break; 752 case Token::SUB: 753 function = &sub_two_doubles; 754 break; 755 case Token::MUL: 756 function = &mul_two_doubles; 757 break; 758 case Token::DIV: 759 function = &div_two_doubles; 760 break; 761 case Token::MOD: 762 function = &mod_two_doubles; 763 break; 764 default: 765 UNREACHABLE(); 766 } 767 // Passing true as 2nd parameter indicates that they return an fp value. 768 return ExternalReference(Redirect(FUNCTION_ADDR(function), true)); 769 } 770 771 772 ExternalReference ExternalReference::compare_doubles() { 773 return ExternalReference(Redirect(FUNCTION_ADDR(native_compare_doubles), 774 false)); 775 } 776 777 778 ExternalReferenceRedirector* ExternalReference::redirector_ = NULL; 779 780 781 #ifdef ENABLE_DEBUGGER_SUPPORT 782 ExternalReference ExternalReference::debug_break() { 783 return ExternalReference(Redirect(FUNCTION_ADDR(Debug::Break))); 784 } 785 786 787 ExternalReference ExternalReference::debug_step_in_fp_address() { 788 return ExternalReference(Debug::step_in_fp_addr()); 789 } 790 #endif 791 792 } } // namespace v8::internal 793