// Copyright 2006-2008 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 "debug.h" #include "scopes.h" #include "runtime.h" namespace v8 { namespace internal { #define __ masm_-> // ------------------------------------------------------------------------- // VirtualFrame implementation. VirtualFrame::VirtualFrame(CodeGenerator* cgen) { ASSERT(cgen->scope() != NULL); masm_ = cgen->masm(); frame_local_count_ = cgen->scope()->num_stack_slots(); parameter_count_ = cgen->scope()->num_parameters(); } void VirtualFrame::Enter() { Comment cmnt(masm_, "[ Enter JS frame"); __ push(ebp); __ mov(ebp, Operand(esp)); // Store the context and the function in the frame. __ push(esi); __ push(edi); // Clear the function slot when generating debug code. if (FLAG_debug_code) { __ Set(edi, Immediate(reinterpret_cast(kZapValue))); } } void VirtualFrame::Exit() { Comment cmnt(masm_, "[ Exit JS frame"); // Record the location of the JS exit code for patching when setting // break point. __ RecordJSReturn(); // Avoid using the leave instruction here, because it is too // short. We need the return sequence to be a least the size of a // call instruction to support patching the exit code in the // debugger. See VisitReturnStatement for the full return sequence. __ mov(esp, Operand(ebp)); __ pop(ebp); } void VirtualFrame::AllocateLocals() { if (frame_local_count_ > 0) { Comment cmnt(masm_, "[ Allocate space for locals"); __ Set(eax, Immediate(Factory::undefined_value())); for (int i = 0; i < frame_local_count_; i++) { __ push(eax); } } } void VirtualFrame::Drop(int count) { ASSERT(count >= 0); if (count > 0) { __ add(Operand(esp), Immediate(count * kPointerSize)); } } void VirtualFrame::Pop() { __ add(Operand(esp), Immediate(kPointerSize)); } void VirtualFrame::Pop(Register reg) { __ pop(reg); } void VirtualFrame::Pop(Operand operand) { __ pop(operand); } void VirtualFrame::Push(Register reg) { __ push(reg); } void VirtualFrame::Push(Operand operand) { __ push(operand); } void VirtualFrame::Push(Immediate immediate) { __ push(immediate); } // ------------------------------------------------------------------------- // CodeGenState implementation. CodeGenState::CodeGenState(CodeGenerator* owner) : owner_(owner), typeof_state_(NOT_INSIDE_TYPEOF), true_target_(NULL), false_target_(NULL), previous_(NULL) { owner_->set_state(this); } CodeGenState::CodeGenState(CodeGenerator* owner, TypeofState typeof_state, Label* true_target, Label* false_target) : owner_(owner), typeof_state_(typeof_state), true_target_(true_target), false_target_(false_target), previous_(owner->state()) { owner_->set_state(this); } CodeGenState::~CodeGenState() { ASSERT(owner_->state() == this); owner_->set_state(previous_); } // ------------------------------------------------------------------------- // CodeGenerator implementation CodeGenerator::CodeGenerator(int buffer_size, Handle