// Copyright 2006-2008 Google 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. // * 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 "prettyprinter.h" #include "scopeinfo.h" #include "scopes.h" #include "runtime.h" namespace v8 { namespace internal { DEFINE_bool(trace, false, "trace function calls"); DEFINE_bool(defer_negation, true, "defer negation operation"); DECLARE_bool(debug_info); DECLARE_bool(debug_code); #ifdef ENABLE_DISASSEMBLER DEFINE_bool(print_code, false, "print generated code"); #endif #ifdef DEBUG DECLARE_bool(gc_greedy); DEFINE_bool(trace_codegen, false, "print name of functions for which code is generated"); DEFINE_bool(print_builtin_code, false, "print generated code for builtins"); DEFINE_bool(print_source, false, "pretty print source code"); DEFINE_bool(print_builtin_source, false, "pretty print source code for builtins"); DEFINE_bool(print_ast, false, "print source AST"); DEFINE_bool(print_builtin_ast, false, "print source AST for builtins"); DEFINE_bool(trace_calls, false, "trace calls"); DEFINE_bool(trace_builtin_calls, false, "trace builtins calls"); DEFINE_string(stop_at, "", "function name where to insert a breakpoint"); #endif // DEBUG DEFINE_bool(check_stack, true, "check stack for overflow, interrupt, breakpoint"); #define TOS (Operand(esp, 0)) class Ia32CodeGenerator; // Mode to overwrite BinaryExpression values. enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; // ----------------------------------------------------------------------------- // Reference support // A reference is a C++ stack-allocated object that keeps an ECMA // reference on the execution stack while in scope. For variables // the reference is empty, indicating that it isn't necessary to // store state on the stack for keeping track of references to those. // For properties, we keep either one (named) or two (indexed) values // on the execution stack to represent the reference. class Reference BASE_EMBEDDED { public: enum Type { ILLEGAL = -1, EMPTY = 0, NAMED = 1, KEYED = 2 }; Reference(Ia32CodeGenerator* cgen, Expression* expression); ~Reference(); Expression* expression() const { return expression_; } Type type() const { return type_; } void set_type(Type value) { ASSERT(type_ == ILLEGAL); type_ = value; } int size() const { return type_; } bool is_illegal() const { return type_ == ILLEGAL; } private: Ia32CodeGenerator* cgen_; Expression* expression_; Type type_; }; // ----------------------------------------------------------------------------- // Code generation state class CodeGenState BASE_EMBEDDED { public: enum AccessType { UNDEFINED, LOAD, LOAD_TYPEOF_EXPR, STORE, INIT_CONST }; CodeGenState() : access_(UNDEFINED), ref_(NULL), true_target_(NULL), false_target_(NULL) { } CodeGenState(AccessType access, Reference* ref, Label* true_target, Label* false_target) : access_(access), ref_(ref), true_target_(true_target), false_target_(false_target) { } AccessType access() const { return access_; } Reference* ref() const { return ref_; } Label* true_target() const { return true_target_; } Label* false_target() const { return false_target_; } private: AccessType access_; Reference* ref_; Label* true_target_; Label* false_target_; }; // ----------------------------------------------------------------------------- // Ia32CodeGenerator class Ia32CodeGenerator: public CodeGenerator { public: static Handle MakeCode(FunctionLiteral* fun, Handle