// Copyright 2010 the V8 project authors. 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. // * Redistributions 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 Google Inc. nor the names of its // 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. #include "v8.h" #include "bootstrapper.h" #include "codegen-inl.h" #include "compiler.h" #include "debug.h" #include "ic-inl.h" #include "parser.h" #include "regexp-macro-assembler.h" #include "register-allocator-inl.h" #include "scopes.h" namespace v8 { namespace internal { #define __ ACCESS_MASM(masm_) // ------------------------------------------------------------------------- // Platform-specific DeferredCode functions. void DeferredCode::SaveRegisters() { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { int action = registers_[i]; if (action == kPush) { __ push(RegisterAllocator::ToRegister(i)); } else if (action != kIgnore && (action & kSyncedFlag) == 0) { __ movq(Operand(rbp, action), RegisterAllocator::ToRegister(i)); } } } void DeferredCode::RestoreRegisters() { // Restore registers in reverse order due to the stack. for (int i = RegisterAllocator::kNumRegisters - 1; i >= 0; i--) { int action = registers_[i]; if (action == kPush) { __ pop(RegisterAllocator::ToRegister(i)); } else if (action != kIgnore) { action &= ~kSyncedFlag; __ movq(RegisterAllocator::ToRegister(i), Operand(rbp, action)); } } } // ------------------------------------------------------------------------- // CodeGenState implementation. CodeGenState::CodeGenState(CodeGenerator* owner) : owner_(owner), destination_(NULL), previous_(NULL) { owner_->set_state(this); } CodeGenState::CodeGenState(CodeGenerator* owner, ControlDestination* destination) : owner_(owner), destination_(destination), previous_(owner->state()) { owner_->set_state(this); } CodeGenState::~CodeGenState() { ASSERT(owner_->state() == this); owner_->set_state(previous_); } // ------------------------------------------------------------------------- // Deferred code objects // // These subclasses of DeferredCode add pieces of code to the end of generated // code. They are branched to from the generated code, and // keep some slower code out of the main body of the generated code. // Many of them call a code stub or a runtime function. class DeferredInlineSmiAdd: public DeferredCode { public: DeferredInlineSmiAdd(Register dst, Smi* value, OverwriteMode overwrite_mode) : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { set_comment("[ DeferredInlineSmiAdd"); } virtual void Generate(); private: Register dst_; Smi* value_; OverwriteMode overwrite_mode_; }; // The result of value + src is in dst. It either overflowed or was not // smi tagged. Undo the speculative addition and call the appropriate // specialized stub for add. The result is left in dst. class DeferredInlineSmiAddReversed: public DeferredCode { public: DeferredInlineSmiAddReversed(Register dst, Smi* value, OverwriteMode overwrite_mode) : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { set_comment("[ DeferredInlineSmiAddReversed"); } virtual void Generate(); private: Register dst_; Smi* value_; OverwriteMode overwrite_mode_; }; class DeferredInlineSmiSub: public DeferredCode { public: DeferredInlineSmiSub(Register dst, Smi* value, OverwriteMode overwrite_mode) : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { set_comment("[ DeferredInlineSmiSub"); } virtual void Generate(); private: Register dst_; Smi* value_; OverwriteMode overwrite_mode_; }; // Call the appropriate binary operation stub to compute src op value // and leave the result in dst. class DeferredInlineSmiOperation: public DeferredCode { public: DeferredInlineSmiOperation(Token::Value op, Register dst, Register src, Smi* value, OverwriteMode overwrite_mode) : op_(op), dst_(dst), src_(src), value_(value), overwrite_mode_(overwrite_mode) { set_comment("[ DeferredInlineSmiOperation"); } virtual void Generate(); private: Token::Value op_; Register dst_; Register src_; Smi* value_; OverwriteMode overwrite_mode_; }; class FloatingPointHelper : public AllStatic { public: // Code pattern for loading a floating point value. Input value must // be either a smi or a heap number object (fp value). Requirements: // operand on TOS+1. Returns operand as floating point number on FPU // stack. static void LoadFloatOperand(MacroAssembler* masm, Register scratch); // Code pattern for loading a floating point value. Input value must // be either a smi or a heap number object (fp value). Requirements: // operand in src register. Returns operand as floating point number // in XMM register static void LoadFloatOperand(MacroAssembler* masm, Register src, XMMRegister dst); // Code pattern for loading floating point values. Input values must // be either smi or heap number objects (fp values). Requirements: // operand_1 in rdx, operand_2 in rax; Returns operands as // floating point numbers in XMM registers. static void LoadFloatOperands(MacroAssembler* masm, XMMRegister dst1, XMMRegister dst2); // Similar to LoadFloatOperands, assumes that the operands are smis. static void LoadFloatOperandsFromSmis(MacroAssembler* masm, XMMRegister dst1, XMMRegister dst2); // Code pattern for loading floating point values onto the fp stack. // Input values must be either smi or heap number objects (fp values). // Requirements: // Register version: operands in registers lhs and rhs. // Stack version: operands on TOS+1 and TOS+2. // Returns operands as floating point numbers on fp stack. static void LoadFloatOperands(MacroAssembler* masm, Register lhs, Register rhs); // Test if operands are smi or number objects (fp). Requirements: // operand_1 in rax, operand_2 in rdx; falls through on float or smi // operands, jumps to the non_float label otherwise. static void CheckNumberOperands(MacroAssembler* masm, Label* non_float); // Takes the operands in rdx and rax and loads them as integers in rax // and rcx. static void LoadAsIntegers(MacroAssembler* masm, bool use_sse3, Label* operand_conversion_failure); }; // ----------------------------------------------------------------------------- // CodeGenerator implementation. CodeGenerator::CodeGenerator(int buffer_size, Handle