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 61namespace v8 { 62namespace internal { 63 64 65// ----------------------------------------------------------------------------- 66// Implementation of Label 67 68int 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// 117const int kMaxRelocModes = 14; 118 119const int kTagBits = 2; 120const int kTagMask = (1 << kTagBits) - 1; 121const int kExtraTagBits = 4; 122const int kPositionTypeTagBits = 1; 123const int kSmallDataBits = kBitsPerByte - kPositionTypeTagBits; 124 125const int kEmbeddedObjectTag = 0; 126const int kCodeTargetTag = 1; 127const int kPositionTag = 2; 128const int kDefaultTag = 3; 129 130const int kPCJumpTag = (1 << kExtraTagBits) - 1; 131 132const int kSmallPCDeltaBits = kBitsPerByte - kTagBits; 133const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1; 134 135const int kVariableLengthPCJumpTopTag = 1; 136const int kChunkBits = 7; 137const int kChunkMask = (1 << kChunkBits) - 1; 138const int kLastChunkTagBits = 1; 139const int kLastChunkTagMask = 1; 140const int kLastChunkTag = 1; 141 142 143const int kDataJumpTag = kPCJumpTag - 1; 144 145const int kNonstatementPositionTag = 0; 146const int kStatementPositionTag = 1; 147const int kCommentTag = 2; 148 149 150uint32_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 170void 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 177void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) { 178 *--pos_ = static_cast<byte>(data_delta << kPositionTypeTagBits | tag); 179} 180 181 182void 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 189void 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 197void 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 207void 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 259inline int RelocIterator::AdvanceGetTag() { 260 return *--pos_ & kTagMask; 261} 262 263 264inline int RelocIterator::GetExtraTag() { 265 return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1); 266} 267 268 269inline int RelocIterator::GetTopTag() { 270 return *pos_ >> (kTagBits + kExtraTagBits); 271} 272 273 274inline void RelocIterator::ReadTaggedPC() { 275 rinfo_.pc_ += *pos_ >> kTagBits; 276} 277 278 279inline void RelocIterator::AdvanceReadPC() { 280 rinfo_.pc_ += *--pos_; 281} 282 283 284void 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 293void 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 309inline int RelocIterator::GetPositionTypeTag() { 310 return *pos_ & ((1 << kPositionTypeTagBits) - 1); 311} 312 313 314inline 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 321inline 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 333void 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 390RelocIterator::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 403RelocIterator::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 421const 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 462void 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 488void 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 532ExternalReference::ExternalReference(Builtins::CFunctionId id) 533 : address_(Redirect(Builtins::c_function_address(id))) {} 534 535 536ExternalReference::ExternalReference(ApiFunction* fun) 537 : address_(Redirect(fun->address())) {} 538 539 540ExternalReference::ExternalReference(Builtins::Name name) 541 : address_(Builtins::builtin_address(name)) {} 542 543 544ExternalReference::ExternalReference(Runtime::FunctionId id) 545 : address_(Redirect(Runtime::FunctionForId(id)->entry)) {} 546 547 548ExternalReference::ExternalReference(Runtime::Function* f) 549 : address_(Redirect(f->entry)) {} 550 551 552ExternalReference::ExternalReference(const IC_Utility& ic_utility) 553 : address_(Redirect(ic_utility.address())) {} 554 555#ifdef ENABLE_DEBUGGER_SUPPORT 556ExternalReference::ExternalReference(const Debug_Address& debug_address) 557 : address_(debug_address.address()) {} 558#endif 559 560ExternalReference::ExternalReference(StatsCounter* counter) 561 : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {} 562 563 564ExternalReference::ExternalReference(Top::AddressId id) 565 : address_(Top::get_address_from_id(id)) {} 566 567 568ExternalReference::ExternalReference(const SCTableReference& table_ref) 569 : address_(table_ref.address()) {} 570 571 572ExternalReference ExternalReference::perform_gc_function() { 573 return ExternalReference(Redirect(FUNCTION_ADDR(Runtime::PerformGC))); 574} 575 576 577ExternalReference ExternalReference::random_positive_smi_function() { 578 return ExternalReference(Redirect(FUNCTION_ADDR(V8::RandomPositiveSmi))); 579} 580 581 582ExternalReference ExternalReference::transcendental_cache_array_address() { 583 return ExternalReference(TranscendentalCache::cache_array_address()); 584} 585 586 587ExternalReference ExternalReference::keyed_lookup_cache_keys() { 588 return ExternalReference(KeyedLookupCache::keys_address()); 589} 590 591 592ExternalReference ExternalReference::keyed_lookup_cache_field_offsets() { 593 return ExternalReference(KeyedLookupCache::field_offsets_address()); 594} 595 596 597ExternalReference ExternalReference::the_hole_value_location() { 598 return ExternalReference(Factory::the_hole_value().location()); 599} 600 601 602ExternalReference ExternalReference::roots_address() { 603 return ExternalReference(Heap::roots_address()); 604} 605 606 607ExternalReference ExternalReference::address_of_stack_limit() { 608 return ExternalReference(StackGuard::address_of_jslimit()); 609} 610 611 612ExternalReference ExternalReference::address_of_real_stack_limit() { 613 return ExternalReference(StackGuard::address_of_real_jslimit()); 614} 615 616 617ExternalReference ExternalReference::address_of_regexp_stack_limit() { 618 return ExternalReference(RegExpStack::limit_address()); 619} 620 621 622ExternalReference ExternalReference::new_space_start() { 623 return ExternalReference(Heap::NewSpaceStart()); 624} 625 626 627ExternalReference ExternalReference::new_space_mask() { 628 return ExternalReference(reinterpret_cast<Address>(Heap::NewSpaceMask())); 629} 630 631 632ExternalReference ExternalReference::new_space_allocation_top_address() { 633 return ExternalReference(Heap::NewSpaceAllocationTopAddress()); 634} 635 636 637ExternalReference ExternalReference::heap_always_allocate_scope_depth() { 638 return ExternalReference(Heap::always_allocate_scope_depth_address()); 639} 640 641 642ExternalReference ExternalReference::new_space_allocation_limit_address() { 643 return ExternalReference(Heap::NewSpaceAllocationLimitAddress()); 644} 645 646 647ExternalReference ExternalReference::handle_scope_extensions_address() { 648 return ExternalReference(HandleScope::current_extensions_address()); 649} 650 651 652ExternalReference ExternalReference::handle_scope_next_address() { 653 return ExternalReference(HandleScope::current_next_address()); 654} 655 656 657ExternalReference ExternalReference::handle_scope_limit_address() { 658 return ExternalReference(HandleScope::current_limit_address()); 659} 660 661 662ExternalReference ExternalReference::scheduled_exception_address() { 663 return ExternalReference(Top::scheduled_exception_address()); 664} 665 666 667#ifdef V8_NATIVE_REGEXP 668 669ExternalReference 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 683ExternalReference ExternalReference::re_grow_stack() { 684 return ExternalReference( 685 Redirect(FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack))); 686} 687 688ExternalReference ExternalReference::re_case_insensitive_compare_uc16() { 689 return ExternalReference(Redirect( 690 FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16))); 691} 692 693ExternalReference ExternalReference::re_word_character_map() { 694 return ExternalReference( 695 NativeRegExpMacroAssembler::word_character_map_address()); 696} 697 698ExternalReference ExternalReference::address_of_static_offsets_vector() { 699 return ExternalReference(OffsetsVector::static_offsets_vector_address()); 700} 701 702ExternalReference ExternalReference::address_of_regexp_stack_memory_address() { 703 return ExternalReference(RegExpStack::memory_address()); 704} 705 706ExternalReference ExternalReference::address_of_regexp_stack_memory_size() { 707 return ExternalReference(RegExpStack::memory_size_address()); 708} 709 710#endif 711 712 713static double add_two_doubles(double x, double y) { 714 return x + y; 715} 716 717 718static double sub_two_doubles(double x, double y) { 719 return x - y; 720} 721 722 723static double mul_two_doubles(double x, double y) { 724 return x * y; 725} 726 727 728static double div_two_doubles(double x, double y) { 729 return x / y; 730} 731 732 733static double mod_two_doubles(double x, double y) { 734 return modulo(x, y); 735} 736 737 738static int native_compare_doubles(double y, double x) { 739 if (x == y) return EQUAL; 740 return x < y ? LESS : GREATER; 741} 742 743 744ExternalReference 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 772ExternalReference ExternalReference::compare_doubles() { 773 return ExternalReference(Redirect(FUNCTION_ADDR(native_compare_doubles), 774 false)); 775} 776 777 778ExternalReferenceRedirector* ExternalReference::redirector_ = NULL; 779 780 781#ifdef ENABLE_DEBUGGER_SUPPORT 782ExternalReference ExternalReference::debug_break() { 783 return ExternalReference(Redirect(FUNCTION_ADDR(Debug::Break))); 784} 785 786 787ExternalReference ExternalReference::debug_step_in_fp_address() { 788 return ExternalReference(Debug::step_in_fp_addr()); 789} 790#endif 791 792} } // namespace v8::internal 793