diff options
Diffstat (limited to 'V8Binding/v8/src/assembler.cc')
-rw-r--r-- | V8Binding/v8/src/assembler.cc | 722 |
1 files changed, 0 insertions, 722 deletions
diff --git a/V8Binding/v8/src/assembler.cc b/V8Binding/v8/src/assembler.cc deleted file mode 100644 index d81b4b0..0000000 --- a/V8Binding/v8/src/assembler.cc +++ /dev/null @@ -1,722 +0,0 @@ -// Copyright (c) 1994-2006 Sun Microsystems Inc. -// All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// - Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// - Redistribution in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// - Neither the name of Sun Microsystems or the names of contributors may -// be used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// The original source code covered by the above license above has been -// modified significantly by Google Inc. -// Copyright 2006-2009 the V8 project authors. All rights reserved. - -#include "v8.h" - -#include "arguments.h" -#include "execution.h" -#include "ic-inl.h" -#include "factory.h" -#include "runtime.h" -#include "serialize.h" -#include "stub-cache.h" -#include "regexp-stack.h" -#include "ast.h" -#include "regexp-macro-assembler.h" -// Include native regexp-macro-assembler. -#ifdef V8_NATIVE_REGEXP -#if V8_TARGET_ARCH_IA32 -#include "ia32/regexp-macro-assembler-ia32.h" -#elif V8_TARGET_ARCH_X64 -#include "x64/regexp-macro-assembler-x64.h" -#elif V8_TARGET_ARCH_ARM -#include "arm/regexp-macro-assembler-arm.h" -#else // Unknown architecture. -#error "Unknown architecture." -#endif // Target architecture. -#endif // V8_NATIVE_REGEXP - -namespace v8 { -namespace internal { - - -// ----------------------------------------------------------------------------- -// Implementation of Label - -int Label::pos() const { - if (pos_ < 0) return -pos_ - 1; - if (pos_ > 0) return pos_ - 1; - UNREACHABLE(); - return 0; -} - - -// ----------------------------------------------------------------------------- -// Implementation of RelocInfoWriter and RelocIterator -// -// Encoding -// -// The most common modes are given single-byte encodings. Also, it is -// easy to identify the type of reloc info and skip unwanted modes in -// an iteration. -// -// The encoding relies on the fact that there are less than 14 -// different relocation modes. -// -// embedded_object: [6 bits pc delta] 00 -// -// code_taget: [6 bits pc delta] 01 -// -// position: [6 bits pc delta] 10, -// [7 bits signed data delta] 0 -// -// statement_position: [6 bits pc delta] 10, -// [7 bits signed data delta] 1 -// -// any nondata mode: 00 [4 bits rmode] 11, // rmode: 0..13 only -// 00 [6 bits pc delta] -// -// pc-jump: 00 1111 11, -// 00 [6 bits pc delta] -// -// pc-jump: 01 1111 11, -// (variable length) 7 - 26 bit pc delta, written in chunks of 7 -// bits, the lowest 7 bits written first. -// -// data-jump + pos: 00 1110 11, -// signed intptr_t, lowest byte written first -// -// data-jump + st.pos: 01 1110 11, -// signed intptr_t, lowest byte written first -// -// data-jump + comm.: 10 1110 11, -// signed intptr_t, lowest byte written first -// -const int kMaxRelocModes = 14; - -const int kTagBits = 2; -const int kTagMask = (1 << kTagBits) - 1; -const int kExtraTagBits = 4; -const int kPositionTypeTagBits = 1; -const int kSmallDataBits = kBitsPerByte - kPositionTypeTagBits; - -const int kEmbeddedObjectTag = 0; -const int kCodeTargetTag = 1; -const int kPositionTag = 2; -const int kDefaultTag = 3; - -const int kPCJumpTag = (1 << kExtraTagBits) - 1; - -const int kSmallPCDeltaBits = kBitsPerByte - kTagBits; -const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1; - -const int kVariableLengthPCJumpTopTag = 1; -const int kChunkBits = 7; -const int kChunkMask = (1 << kChunkBits) - 1; -const int kLastChunkTagBits = 1; -const int kLastChunkTagMask = 1; -const int kLastChunkTag = 1; - - -const int kDataJumpTag = kPCJumpTag - 1; - -const int kNonstatementPositionTag = 0; -const int kStatementPositionTag = 1; -const int kCommentTag = 2; - - -uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) { - // Return if the pc_delta can fit in kSmallPCDeltaBits bits. - // Otherwise write a variable length PC jump for the bits that do - // not fit in the kSmallPCDeltaBits bits. - if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta; - WriteExtraTag(kPCJumpTag, kVariableLengthPCJumpTopTag); - uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits; - ASSERT(pc_jump > 0); - // Write kChunkBits size chunks of the pc_jump. - for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) { - byte b = pc_jump & kChunkMask; - *--pos_ = b << kLastChunkTagBits; - } - // Tag the last chunk so it can be identified. - *pos_ = *pos_ | kLastChunkTag; - // Return the remaining kSmallPCDeltaBits of the pc_delta. - return pc_delta & kSmallPCDeltaMask; -} - - -void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) { - // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump. - pc_delta = WriteVariableLengthPCJump(pc_delta); - *--pos_ = pc_delta << kTagBits | tag; -} - - -void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) { - *--pos_ = data_delta << kPositionTypeTagBits | tag; -} - - -void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) { - *--pos_ = top_tag << (kTagBits + kExtraTagBits) | - extra_tag << kTagBits | - kDefaultTag; -} - - -void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) { - // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump. - pc_delta = WriteVariableLengthPCJump(pc_delta); - WriteExtraTag(extra_tag, 0); - *--pos_ = pc_delta; -} - - -void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) { - WriteExtraTag(kDataJumpTag, top_tag); - for (int i = 0; i < kIntptrSize; i++) { - *--pos_ = data_delta; - // Signed right shift is arithmetic shift. Tested in test-utils.cc. - data_delta = data_delta >> kBitsPerByte; - } -} - - -void RelocInfoWriter::Write(const RelocInfo* rinfo) { -#ifdef DEBUG - byte* begin_pos = pos_; -#endif - Counters::reloc_info_count.Increment(); - ASSERT(rinfo->pc() - last_pc_ >= 0); - ASSERT(RelocInfo::NUMBER_OF_MODES < kMaxRelocModes); - // Use unsigned delta-encoding for pc. - uint32_t pc_delta = rinfo->pc() - last_pc_; - RelocInfo::Mode rmode = rinfo->rmode(); - - // The two most common modes are given small tags, and usually fit in a byte. - if (rmode == RelocInfo::EMBEDDED_OBJECT) { - WriteTaggedPC(pc_delta, kEmbeddedObjectTag); - } else if (rmode == RelocInfo::CODE_TARGET) { - WriteTaggedPC(pc_delta, kCodeTargetTag); - } else if (RelocInfo::IsPosition(rmode)) { - // Use signed delta-encoding for data. - intptr_t data_delta = rinfo->data() - last_data_; - int pos_type_tag = rmode == RelocInfo::POSITION ? kNonstatementPositionTag - : kStatementPositionTag; - // Check if data is small enough to fit in a tagged byte. - // We cannot use is_intn because data_delta is not an int32_t. - if (data_delta >= -(1 << (kSmallDataBits-1)) && - data_delta < 1 << (kSmallDataBits-1)) { - WriteTaggedPC(pc_delta, kPositionTag); - WriteTaggedData(data_delta, pos_type_tag); - last_data_ = rinfo->data(); - } else { - // Otherwise, use costly encoding. - WriteExtraTaggedPC(pc_delta, kPCJumpTag); - WriteExtraTaggedData(data_delta, pos_type_tag); - last_data_ = rinfo->data(); - } - } else if (RelocInfo::IsComment(rmode)) { - // Comments are normally not generated, so we use the costly encoding. - WriteExtraTaggedPC(pc_delta, kPCJumpTag); - WriteExtraTaggedData(rinfo->data() - last_data_, kCommentTag); - last_data_ = rinfo->data(); - } else { - // For all other modes we simply use the mode as the extra tag. - // None of these modes need a data component. - ASSERT(rmode < kPCJumpTag && rmode < kDataJumpTag); - WriteExtraTaggedPC(pc_delta, rmode); - } - last_pc_ = rinfo->pc(); -#ifdef DEBUG - ASSERT(begin_pos - pos_ <= kMaxSize); -#endif -} - - -inline int RelocIterator::AdvanceGetTag() { - return *--pos_ & kTagMask; -} - - -inline int RelocIterator::GetExtraTag() { - return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1); -} - - -inline int RelocIterator::GetTopTag() { - return *pos_ >> (kTagBits + kExtraTagBits); -} - - -inline void RelocIterator::ReadTaggedPC() { - rinfo_.pc_ += *pos_ >> kTagBits; -} - - -inline void RelocIterator::AdvanceReadPC() { - rinfo_.pc_ += *--pos_; -} - - -void RelocIterator::AdvanceReadData() { - intptr_t x = 0; - for (int i = 0; i < kIntptrSize; i++) { - x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte; - } - rinfo_.data_ += x; -} - - -void RelocIterator::AdvanceReadVariableLengthPCJump() { - // Read the 32-kSmallPCDeltaBits most significant bits of the - // pc jump in kChunkBits bit chunks and shift them into place. - // Stop when the last chunk is encountered. - uint32_t pc_jump = 0; - for (int i = 0; i < kIntSize; i++) { - byte pc_jump_part = *--pos_; - pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits; - if ((pc_jump_part & kLastChunkTagMask) == 1) break; - } - // The least significant kSmallPCDeltaBits bits will be added - // later. - rinfo_.pc_ += pc_jump << kSmallPCDeltaBits; -} - - -inline int RelocIterator::GetPositionTypeTag() { - return *pos_ & ((1 << kPositionTypeTagBits) - 1); -} - - -inline void RelocIterator::ReadTaggedData() { - int8_t signed_b = *pos_; - // Signed right shift is arithmetic shift. Tested in test-utils.cc. - rinfo_.data_ += signed_b >> kPositionTypeTagBits; -} - - -inline RelocInfo::Mode RelocIterator::DebugInfoModeFromTag(int tag) { - if (tag == kStatementPositionTag) { - return RelocInfo::STATEMENT_POSITION; - } else if (tag == kNonstatementPositionTag) { - return RelocInfo::POSITION; - } else { - ASSERT(tag == kCommentTag); - return RelocInfo::COMMENT; - } -} - - -void RelocIterator::next() { - ASSERT(!done()); - // Basically, do the opposite of RelocInfoWriter::Write. - // Reading of data is as far as possible avoided for unwanted modes, - // but we must always update the pc. - // - // We exit this loop by returning when we find a mode we want. - while (pos_ > end_) { - int tag = AdvanceGetTag(); - if (tag == kEmbeddedObjectTag) { - ReadTaggedPC(); - if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return; - } else if (tag == kCodeTargetTag) { - ReadTaggedPC(); - if (*(reinterpret_cast<int*>(rinfo_.pc())) == 0x61) { - tag = 0; - } - if (SetMode(RelocInfo::CODE_TARGET)) return; - } else if (tag == kPositionTag) { - ReadTaggedPC(); - Advance(); - // Check if we want source positions. - if (mode_mask_ & RelocInfo::kPositionMask) { - // Check if we want this type of source position. - if (SetMode(DebugInfoModeFromTag(GetPositionTypeTag()))) { - // Finally read the data before returning. - ReadTaggedData(); - return; - } - } - } else { - ASSERT(tag == kDefaultTag); - int extra_tag = GetExtraTag(); - if (extra_tag == kPCJumpTag) { - int top_tag = GetTopTag(); - if (top_tag == kVariableLengthPCJumpTopTag) { - AdvanceReadVariableLengthPCJump(); - } else { - AdvanceReadPC(); - } - } else if (extra_tag == kDataJumpTag) { - // Check if we want debug modes (the only ones with data). - if (mode_mask_ & RelocInfo::kDebugMask) { - int top_tag = GetTopTag(); - AdvanceReadData(); - if (SetMode(DebugInfoModeFromTag(top_tag))) return; - } else { - // Otherwise, just skip over the data. - Advance(kIntptrSize); - } - } else { - AdvanceReadPC(); - if (SetMode(static_cast<RelocInfo::Mode>(extra_tag))) return; - } - } - } - done_ = true; -} - - -RelocIterator::RelocIterator(Code* code, int mode_mask) { - rinfo_.pc_ = code->instruction_start(); - rinfo_.data_ = 0; - // relocation info is read backwards - pos_ = code->relocation_start() + code->relocation_size(); - end_ = code->relocation_start(); - done_ = false; - mode_mask_ = mode_mask; - if (mode_mask_ == 0) pos_ = end_; - next(); -} - - -RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) { - rinfo_.pc_ = desc.buffer; - rinfo_.data_ = 0; - // relocation info is read backwards - pos_ = desc.buffer + desc.buffer_size; - end_ = pos_ - desc.reloc_size; - done_ = false; - mode_mask_ = mode_mask; - if (mode_mask_ == 0) pos_ = end_; - next(); -} - - -// ----------------------------------------------------------------------------- -// Implementation of RelocInfo - - -#ifdef ENABLE_DISASSEMBLER -const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) { - switch (rmode) { - case RelocInfo::NONE: - return "no reloc"; - case RelocInfo::EMBEDDED_OBJECT: - return "embedded object"; - case RelocInfo::EMBEDDED_STRING: - return "embedded string"; - case RelocInfo::CONSTRUCT_CALL: - return "code target (js construct call)"; - case RelocInfo::CODE_TARGET_CONTEXT: - return "code target (context)"; - case RelocInfo::CODE_TARGET: - return "code target"; - case RelocInfo::RUNTIME_ENTRY: - return "runtime entry"; - case RelocInfo::JS_RETURN: - return "js return"; - case RelocInfo::COMMENT: - return "comment"; - case RelocInfo::POSITION: - return "position"; - case RelocInfo::STATEMENT_POSITION: - return "statement position"; - case RelocInfo::EXTERNAL_REFERENCE: - return "external reference"; - case RelocInfo::INTERNAL_REFERENCE: - return "internal reference"; - case RelocInfo::NUMBER_OF_MODES: - UNREACHABLE(); - return "number_of_modes"; - } - return "unknown relocation type"; -} - - -void RelocInfo::Print() { - PrintF("%p %s", pc_, RelocModeName(rmode_)); - if (IsComment(rmode_)) { - PrintF(" (%s)", data_); - } else if (rmode_ == EMBEDDED_OBJECT) { - PrintF(" ("); - target_object()->ShortPrint(); - PrintF(")"); - } else if (rmode_ == EXTERNAL_REFERENCE) { - ExternalReferenceEncoder ref_encoder; - PrintF(" (%s) (%p)", - ref_encoder.NameOfAddress(*target_reference_address()), - *target_reference_address()); - } else if (IsCodeTarget(rmode_)) { - Code* code = Code::GetCodeFromTargetAddress(target_address()); - PrintF(" (%s) (%p)", Code::Kind2String(code->kind()), target_address()); - } else if (IsPosition(rmode_)) { - PrintF(" (%d)", data()); - } - - PrintF("\n"); -} -#endif // ENABLE_DISASSEMBLER - - -#ifdef DEBUG -void RelocInfo::Verify() { - switch (rmode_) { - case EMBEDDED_OBJECT: - Object::VerifyPointer(target_object()); - break; - case CONSTRUCT_CALL: - case CODE_TARGET_CONTEXT: - case CODE_TARGET: { - // convert inline target address to code object - Address addr = target_address(); - ASSERT(addr != NULL); - // Check that we can find the right code object. - Code* code = Code::GetCodeFromTargetAddress(addr); - Object* found = Heap::FindCodeObject(addr); - ASSERT(found->IsCode()); - ASSERT(code->address() == HeapObject::cast(found)->address()); - break; - } - case RelocInfo::EMBEDDED_STRING: - case RUNTIME_ENTRY: - case JS_RETURN: - case COMMENT: - case POSITION: - case STATEMENT_POSITION: - case EXTERNAL_REFERENCE: - case INTERNAL_REFERENCE: - case NONE: - break; - case NUMBER_OF_MODES: - UNREACHABLE(); - break; - } -} -#endif // DEBUG - - -// ----------------------------------------------------------------------------- -// Implementation of ExternalReference - -ExternalReference::ExternalReference(Builtins::CFunctionId id) - : address_(Redirect(Builtins::c_function_address(id))) {} - - -ExternalReference::ExternalReference(Builtins::Name name) - : address_(Builtins::builtin_address(name)) {} - - -ExternalReference::ExternalReference(Runtime::FunctionId id) - : address_(Redirect(Runtime::FunctionForId(id)->entry)) {} - - -ExternalReference::ExternalReference(Runtime::Function* f) - : address_(Redirect(f->entry)) {} - - -ExternalReference::ExternalReference(const IC_Utility& ic_utility) - : address_(Redirect(ic_utility.address())) {} - -#ifdef ENABLE_DEBUGGER_SUPPORT -ExternalReference::ExternalReference(const Debug_Address& debug_address) - : address_(debug_address.address()) {} -#endif - -ExternalReference::ExternalReference(StatsCounter* counter) - : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {} - - -ExternalReference::ExternalReference(Top::AddressId id) - : address_(Top::get_address_from_id(id)) {} - - -ExternalReference::ExternalReference(const SCTableReference& table_ref) - : address_(table_ref.address()) {} - - -ExternalReference ExternalReference::perform_gc_function() { - return ExternalReference(Redirect(FUNCTION_ADDR(Runtime::PerformGC))); -} - - -ExternalReference ExternalReference::builtin_passed_function() { - return ExternalReference(&Builtins::builtin_passed_function); -} - - -ExternalReference ExternalReference::random_positive_smi_function() { - return ExternalReference(Redirect(FUNCTION_ADDR(V8::RandomPositiveSmi))); -} - - -ExternalReference ExternalReference::the_hole_value_location() { - return ExternalReference(Factory::the_hole_value().location()); -} - - -ExternalReference ExternalReference::roots_address() { - return ExternalReference(Heap::roots_address()); -} - - -ExternalReference ExternalReference::address_of_stack_guard_limit() { - return ExternalReference(StackGuard::address_of_jslimit()); -} - - -ExternalReference ExternalReference::address_of_regexp_stack_limit() { - return ExternalReference(RegExpStack::limit_address()); -} - - -ExternalReference ExternalReference::new_space_start() { - return ExternalReference(Heap::NewSpaceStart()); -} - - -ExternalReference ExternalReference::new_space_allocation_top_address() { - return ExternalReference(Heap::NewSpaceAllocationTopAddress()); -} - - -ExternalReference ExternalReference::heap_always_allocate_scope_depth() { - return ExternalReference(Heap::always_allocate_scope_depth_address()); -} - - -ExternalReference ExternalReference::new_space_allocation_limit_address() { - return ExternalReference(Heap::NewSpaceAllocationLimitAddress()); -} - -#ifdef V8_NATIVE_REGEXP - -ExternalReference ExternalReference::re_check_stack_guard_state() { - Address function; -#ifdef V8_TARGET_ARCH_X64 - function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState); -#elif V8_TARGET_ARCH_IA32 - function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState); -#elif V8_TARGET_ARCH_ARM - function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState); -#else - UNREACHABLE("Unexpected architecture"); -#endif - return ExternalReference(Redirect(function)); -} - -ExternalReference ExternalReference::re_grow_stack() { - return ExternalReference( - Redirect(FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack))); -} - -ExternalReference ExternalReference::re_case_insensitive_compare_uc16() { - return ExternalReference(Redirect( - FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16))); -} - -#endif - - -static double add_two_doubles(double x, double y) { - return x + y; -} - - -static double sub_two_doubles(double x, double y) { - return x - y; -} - - -static double mul_two_doubles(double x, double y) { - return x * y; -} - - -static double div_two_doubles(double x, double y) { - return x / y; -} - - -static double mod_two_doubles(double x, double y) { - return fmod(x, y); -} - - -static int native_compare_doubles(double x, double y) { - if (x == y) return 0; - return x < y ? 1 : -1; -} - - -ExternalReference ExternalReference::double_fp_operation( - Token::Value operation) { - typedef double BinaryFPOperation(double x, double y); - BinaryFPOperation* function = NULL; - switch (operation) { - case Token::ADD: - function = &add_two_doubles; - break; - case Token::SUB: - function = &sub_two_doubles; - break; - case Token::MUL: - function = &mul_two_doubles; - break; - case Token::DIV: - function = &div_two_doubles; - break; - case Token::MOD: - function = &mod_two_doubles; - break; - default: - UNREACHABLE(); - } - // Passing true as 2nd parameter indicates that they return an fp value. - return ExternalReference(Redirect(FUNCTION_ADDR(function), true)); -} - - -ExternalReference ExternalReference::compare_doubles() { - return ExternalReference(Redirect(FUNCTION_ADDR(native_compare_doubles), - false)); -} - - -ExternalReferenceRedirector* ExternalReference::redirector_ = NULL; - - -#ifdef ENABLE_DEBUGGER_SUPPORT -ExternalReference ExternalReference::debug_break() { - return ExternalReference(Redirect(FUNCTION_ADDR(Debug::Break))); -} - - -ExternalReference ExternalReference::debug_step_in_fp_address() { - return ExternalReference(Debug::step_in_fp_addr()); -} -#endif - -} } // namespace v8::internal |