'codegen.cc', 'compilation-cache.cc', 'compiler.cc', 'contexts.cc',
'conversions.cc', 'counters.cc', 'dateparser.cc', 'debug.cc',
'debug-agent.cc', 'disassembler.cc', 'execution.cc', 'factory.cc',
- 'flags.cc', 'frame-element.cc', 'frames.cc', 'func-name-inferrer.cc',
- 'global-handles.cc', 'handles.cc', 'hashmap.cc', 'heap.cc',
- 'heap-profiler.cc', 'ic.cc', 'interpreter-irregexp.cc', 'jsregexp.cc',
- 'jump-target.cc', 'log.cc', 'log-utils.cc', 'mark-compact.cc',
- 'messages.cc', 'objects.cc', 'oprofile-agent.cc', 'parser.cc',
- 'property.cc', 'regexp-macro-assembler.cc',
- 'regexp-macro-assembler-irregexp.cc', 'regexp-stack.cc',
- 'register-allocator.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc',
- 'scopeinfo.cc', 'scopes.cc', 'serialize.cc', 'snapshot-common.cc',
- 'spaces.cc', 'string-stream.cc', 'stub-cache.cc', 'token.cc', 'top.cc',
- 'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc',
- 'v8.cc', 'v8threads.cc', 'variables.cc', 'version.cc',
+ 'flags.cc', 'frame-element.cc', 'frames.cc',
+ 'func-name-inferrer.cc', 'global-handles.cc', 'handles.cc',
+ 'hashmap.cc', 'heap.cc', 'heap-profiler.cc', 'ic.cc',
+ 'interpreter-irregexp.cc', 'jsregexp.cc', 'jump-target.cc', 'log.cc',
+ 'log-utils.cc', 'mark-compact.cc', 'messages.cc', 'objects.cc',
+ 'oprofile-agent.cc', 'parser.cc', 'property.cc',
+ 'regexp-macro-assembler.cc', 'regexp-macro-assembler-irregexp.cc',
+ 'regexp-stack.cc', 'register-allocator.cc', 'rewriter.cc', 'runtime.cc',
+ 'scanner.cc', 'scopeinfo.cc', 'scopes.cc', 'serialize.cc',
+ 'snapshot-common.cc', 'spaces.cc', 'string-stream.cc', 'stub-cache.cc',
+ 'token.cc', 'top.cc', 'unicode.cc', 'usage-analyzer.cc', 'utils.cc',
+ 'v8-counters.cc', 'v8.cc', 'v8threads.cc', 'variables.cc', 'version.cc',
'virtual-frame.cc', 'zone.cc'
],
'arch:arm': [
'arm/stub-cache-arm.cc', 'arm/virtual-frame-arm.cc'
],
'arch:ia32': [
- 'ia32/assembler-ia32.cc', 'ia32/builtins-ia32.cc',
+ 'fast-codegen.cc', 'ia32/assembler-ia32.cc', 'ia32/builtins-ia32.cc',
'ia32/codegen-ia32.cc', 'ia32/cpu-ia32.cc', 'ia32/disasm-ia32.cc',
- 'ia32/debug-ia32.cc', 'ia32/frames-ia32.cc', 'ia32/ic-ia32.cc',
- 'ia32/jump-target-ia32.cc', 'ia32/macro-assembler-ia32.cc',
- 'ia32/regexp-macro-assembler-ia32.cc',
+ 'ia32/debug-ia32.cc', 'ia32/fast-codegen-ia32.cc',
+ 'ia32/frames-ia32.cc', 'ia32/ic-ia32.cc', 'ia32/jump-target-ia32.cc',
+ 'ia32/macro-assembler-ia32.cc', 'ia32/regexp-macro-assembler-ia32.cc',
'ia32/register-allocator-ia32.cc', 'ia32/stub-cache-ia32.cc',
'ia32/virtual-frame-ia32.cc'
],
Handle<Script> script,
bool is_eval);
+ // Printing of AST, etc. as requested by flags.
+ static void MakeCodePrologue(FunctionLiteral* fun);
+
+ // Allocate and install the code.
+ static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
+ MacroAssembler* masm,
+ Code::Flags flags,
+ Handle<Script> script);
+
#ifdef ENABLE_LOGGING_AND_PROFILING
static bool ShouldGenerateLog(Expression* type);
#endif
}
-// Generate the code. Takes a function literal, generates code for it, assemble
-// all the pieces into a Code object. This function is only to be called by
-// the compiler.cc code.
-Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* flit,
- Handle<Script> script,
- bool is_eval) {
-#ifdef ENABLE_DISASSEMBLER
- bool print_code = Bootstrapper::IsActive()
- ? FLAG_print_builtin_code
- : FLAG_print_code;
-#endif
-
+void CodeGenerator::MakeCodePrologue(FunctionLiteral* fun) {
#ifdef DEBUG
bool print_source = false;
bool print_ast = false;
if (FLAG_trace_codegen || print_source || print_ast) {
PrintF("*** Generate code for %s function: ", ftype);
- flit->name()->ShortPrint();
+ fun->name()->ShortPrint();
PrintF(" ***\n");
}
if (print_source) {
- PrintF("--- Source from AST ---\n%s\n", PrettyPrinter().PrintProgram(flit));
+ PrintF("--- Source from AST ---\n%s\n", PrettyPrinter().PrintProgram(fun));
}
if (print_ast) {
- PrintF("--- AST ---\n%s\n", AstPrinter().PrintProgram(flit));
+ PrintF("--- AST ---\n%s\n", AstPrinter().PrintProgram(fun));
}
if (print_json_ast) {
JsonAstBuilder builder;
- PrintF("%s", builder.BuildProgram(flit));
+ PrintF("%s", builder.BuildProgram(fun));
}
#endif // DEBUG
+}
- // Generate code.
- const int initial_buffer_size = 4 * KB;
- CodeGenerator cgen(initial_buffer_size, script, is_eval);
- CodeGeneratorScope scope(&cgen);
- cgen.GenCode(flit);
- if (cgen.HasStackOverflow()) {
- ASSERT(!Top::has_pending_exception());
- return Handle<Code>::null();
- }
- // Allocate and install the code. Time the rest of this function as
- // code creation.
- HistogramTimerScope timer(&Counters::code_creation);
+Handle<Code> CodeGenerator::MakeCodeEpilogue(FunctionLiteral* fun,
+ MacroAssembler* masm,
+ Code::Flags flags,
+ Handle<Script> script) {
+ // Allocate and install the code.
CodeDesc desc;
- cgen.masm()->GetCode(&desc);
- ZoneScopeInfo sinfo(flit->scope());
- InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
- Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
- Handle<Code> code = Factory::NewCode(desc,
- &sinfo,
- flags,
- cgen.masm()->CodeObject());
+ masm->GetCode(&desc);
+ ZoneScopeInfo sinfo(fun->scope());
+ Handle<Code> code =
+ Factory::NewCode(desc, &sinfo, flags, masm->CodeObject());
// Add unresolved entries in the code to the fixup list.
- Bootstrapper::AddFixup(*code, cgen.masm());
+ Bootstrapper::AddFixup(*code, masm);
#ifdef ENABLE_DISASSEMBLER
+ bool print_code = Bootstrapper::IsActive()
+ ? FLAG_print_builtin_code
+ : FLAG_print_code;
if (print_code) {
// Print the source code if available.
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
PrintF("--- Raw source ---\n");
StringInputBuffer stream(String::cast(script->source()));
- stream.Seek(flit->start_position());
- // flit->end_position() points to the last character in the stream. We
+ stream.Seek(fun->start_position());
+ // fun->end_position() points to the last character in the stream. We
// need to compensate by adding one to calculate the length.
- int source_len = flit->end_position() - flit->start_position() + 1;
+ int source_len = fun->end_position() - fun->start_position() + 1;
for (int i = 0; i < source_len; i++) {
if (stream.has_more()) PrintF("%c", stream.GetNext());
}
PrintF("\n\n");
}
PrintF("--- Code ---\n");
- code->Disassemble(*flit->name()->ToCString());
+ code->Disassemble(*fun->name()->ToCString());
}
#endif // ENABLE_DISASSEMBLER
if (!code.is_null()) {
Counters::total_compiled_code_size.Increment(code->instruction_size());
}
-
return code;
}
+// Generate the code. Takes a function literal, generates code for it, assemble
+// all the pieces into a Code object. This function is only to be called by
+// the compiler.cc code.
+Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
+ Handle<Script> script,
+ bool is_eval) {
+ MakeCodePrologue(fun);
+ // Generate code.
+ const int kInitialBufferSize = 4 * KB;
+ CodeGenerator cgen(kInitialBufferSize, script, is_eval);
+ CodeGeneratorScope scope(&cgen);
+ cgen.GenCode(fun);
+ if (cgen.HasStackOverflow()) {
+ ASSERT(!Top::has_pending_exception());
+ return Handle<Code>::null();
+ }
+
+ InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
+ Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
+ return MakeCodeEpilogue(fun, cgen.masm(), flags, script);
+}
+
+
#ifdef ENABLE_LOGGING_AND_PROFILING
bool CodeGenerator::ShouldGenerateLog(Expression* type) {
// The contract to the shared code is that the the CodeGenerator is a subclass
// of Visitor and that the following methods are available publicly:
// MakeCode
+// MakeCodePrologue
+// MakeCodeEpilogue
// SetFunctionInfo
// masm
// frame
#include "compilation-cache.h"
#include "compiler.h"
#include "debug.h"
+#include "fast-codegen.h"
#include "oprofile-agent.h"
#include "rewriter.h"
#include "scopes.h"
namespace v8 {
namespace internal {
+#ifdef V8_TARGET_ARCH_IA32
+
+class CodeGenSelector: public AstVisitor {
+ public:
+ enum CodeGenTag { NORMAL, FAST };
+
+ CodeGenSelector() : has_supported_syntax_(true) {}
+
+ CodeGenTag Select(FunctionLiteral* fun);
+
+ private:
+ void VisitStatements(ZoneList<Statement*>* stmts);
+
+ // AST node visit functions.
+#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
+ AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+ bool has_supported_syntax_;
+
+ DISALLOW_COPY_AND_ASSIGN(CodeGenSelector);
+};
+
+#endif
+
+
static Handle<Code> MakeCode(FunctionLiteral* literal,
Handle<Script> script,
Handle<Context> context,
}
// Generate code and return it.
- Handle<Code> result = CodeGenerator::MakeCode(literal, script, is_eval);
- return result;
+#ifdef V8_TARGET_ARCH_IA32
+ if (FLAG_fast_compiler) {
+ CodeGenSelector selector;
+ CodeGenSelector::CodeGenTag code_gen = selector.Select(literal);
+ if (code_gen == CodeGenSelector::FAST) {
+ return FastCodeGenerator::MakeCode(literal, script);
+ }
+ ASSERT(code_gen == CodeGenSelector::NORMAL);
+ }
+#endif
+
+ return CodeGenerator::MakeCode(literal, script, is_eval);
}
}
+#ifdef V8_TARGET_ARCH_IA32
+
+CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
+ Scope* scope = fun->scope();
+
+ if (!scope->is_global_scope()) return NORMAL;
+ ASSERT(scope->num_heap_slots() == 0);
+ ASSERT(scope->arguments() == NULL);
+
+ if (!scope->declarations()->is_empty()) return NORMAL;
+ if (fun->materialized_literal_count() > 0) return NORMAL;
+ if (fun->body()->is_empty()) return NORMAL;
+
+ has_supported_syntax_ = true;
+ VisitStatements(fun->body());
+ return has_supported_syntax_ ? FAST : NORMAL;
+}
+
+
+#define BAILOUT(reason) \
+ do { \
+ if (FLAG_trace_bailout) { \
+ PrintF("%s\n", reason); \
+ } \
+ has_supported_syntax_ = false; \
+ return; \
+ } while (false)
+
+
+#define CHECK_BAILOUT \
+ do { \
+ if (!has_supported_syntax_) return; \
+ } while (false)
+
+
+void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
+ for (int i = 0, len = stmts->length(); i < len; i++) {
+ CHECK_BAILOUT;
+ Visit(stmts->at(i));
+ }
+}
+
+
+void CodeGenSelector::VisitDeclaration(Declaration* decl) {
+ BAILOUT("Declaration");
+}
+
+
+void CodeGenSelector::VisitBlock(Block* stmt) {
+ BAILOUT("Block");
+}
+
+
+void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) {
+ Visit(stmt->expression());
+}
+
+
+void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {
+ BAILOUT("EmptyStatement");
+}
+
+
+void CodeGenSelector::VisitIfStatement(IfStatement* stmt) {
+ BAILOUT("IfStatement");
+}
+
+
+void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {
+ BAILOUT("ContinueStatement");
+}
+
+
+void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {
+ BAILOUT("BreakStatement");
+}
+
+
+void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) {
+ Visit(stmt->expression());
+}
+
+
+void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) {
+ BAILOUT("WithEnterStatement");
+}
+
+
+void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {
+ BAILOUT("WithExitStatement");
+}
+
+
+void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) {
+ BAILOUT("SwitchStatement");
+}
+
+
+void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) {
+ BAILOUT("DoWhileStatement");
+}
+
+
+void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) {
+ BAILOUT("WhileStatement");
+}
+
+
+void CodeGenSelector::VisitForStatement(ForStatement* stmt) {
+ BAILOUT("ForStatement");
+}
+
+
+void CodeGenSelector::VisitForInStatement(ForInStatement* stmt) {
+ BAILOUT("ForInStatement");
+}
+
+
+void CodeGenSelector::VisitTryCatchStatement(TryCatchStatement* stmt) {
+ BAILOUT("TryCatchStatement");
+}
+
+
+void CodeGenSelector::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
+ BAILOUT("TryFinallyStatement");
+}
+
+
+void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {
+ BAILOUT("DebuggerStatement");
+}
+
+
+void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {
+ BAILOUT("FunctionLiteral");
+}
+
+
+void CodeGenSelector::VisitFunctionBoilerplateLiteral(
+ FunctionBoilerplateLiteral* expr) {
+ BAILOUT("FunctionBoilerplateLiteral");
+}
+
+
+void CodeGenSelector::VisitConditional(Conditional* expr) {
+ BAILOUT("Conditional");
+}
+
+
+void CodeGenSelector::VisitSlot(Slot* expr) {
+ Slot::Type type = expr->type();
+ if (type != Slot::PARAMETER && type != Slot::LOCAL) {
+ BAILOUT("non-parameter/non-local slot reference");
+ }
+}
+
+
+void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
+ Expression* rewrite = expr->var()->rewrite();
+ if (rewrite == NULL) BAILOUT("global variable reference");
+ Visit(rewrite);
+}
+
+
+void CodeGenSelector::VisitLiteral(Literal* expr) {
+ // All literals are supported.
+}
+
+
+void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {
+ BAILOUT("RegExpLiteral");
+}
+
+
+void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) {
+ BAILOUT("ObjectLiteral");
+}
+
+
+void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) {
+ BAILOUT("ArrayLiteral");
+}
+
+
+void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) {
+ BAILOUT("CatchExtensionObject");
+}
+
+
+void CodeGenSelector::VisitAssignment(Assignment* expr) {
+ // We support plain non-compound assignments to parameters and
+ // non-context (stack-allocated) locals.
+ if (expr->starts_initialization_block()) BAILOUT("initialization block");
+
+ Token::Value op = expr->op();
+ if (op == Token::INIT_CONST) BAILOUT("initialize constant");
+ if (op != Token::ASSIGN && op != Token::INIT_VAR) {
+ BAILOUT("compound assignment");
+ }
+
+ Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+ if (var == NULL || var->is_global()) BAILOUT("non-variable assignment");
+
+ ASSERT(var->slot() != NULL);
+ Slot::Type type = var->slot()->type();
+ if (type != Slot::PARAMETER && type != Slot::LOCAL) {
+ BAILOUT("non-parameter/non-local slot assignment");
+ }
+
+ Visit(expr->value());
+}
+
+
+void CodeGenSelector::VisitThrow(Throw* expr) {
+ BAILOUT("Throw");
+}
+
+
+void CodeGenSelector::VisitProperty(Property* expr) {
+ BAILOUT("Property");
+}
+
+
+void CodeGenSelector::VisitCall(Call* expr) {
+ BAILOUT("Call");
+}
+
+
+void CodeGenSelector::VisitCallNew(CallNew* expr) {
+ BAILOUT("CallNew");
+}
+
+
+void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
+ BAILOUT("CallRuntime");
+}
+
+
+void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
+ BAILOUT("UnaryOperation");
+}
+
+
+void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
+ BAILOUT("CountOperation");
+}
+
+
+void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
+ BAILOUT("BinaryOperation");
+}
+
+
+void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) {
+ BAILOUT("CompareOperation");
+}
+
+
+void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {
+ BAILOUT("ThisFunction");
+}
+
+#undef BAILOUT
+#undef CHECK_BAILOUT
+
+#endif // V8_TARGET_ARCH_IA32
+
+
} } // namespace v8::internal
--- /dev/null
+// Copyright 2009 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 "codegen-inl.h"
+#include "fast-codegen.h"
+
+namespace v8 {
+namespace internal {
+
+Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
+ Handle<Script> script) {
+ CodeGenerator::MakeCodePrologue(fun);
+ const int kInitialBufferSize = 4 * KB;
+ MacroAssembler masm(NULL, kInitialBufferSize);
+ FastCodeGenerator cgen(&masm);
+ cgen.Generate(fun);
+ if (cgen.HasStackOverflow()) {
+ ASSERT(!Top::has_pending_exception());
+ return Handle<Code>::null();
+ }
+ Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
+ return CodeGenerator::MakeCodeEpilogue(fun, &masm, flags, script);
+}
+
+
+int FastCodeGenerator::SlotOffset(Slot* slot) {
+ // Offset is negative because higher indexes are at lower addresses.
+ int offset = -slot->index() * kPointerSize;
+ // Adjust by a (parameter or local) base offset.
+ switch (slot->type()) {
+ case Slot::PARAMETER:
+ offset += (function_->scope()->num_parameters() + 1) * kPointerSize;
+ break;
+ case Slot::LOCAL:
+ offset += JavaScriptFrameConstants::kLocal0Offset;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return offset;
+}
+
+
+void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitBlock(Block* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitFunctionBoilerplateLiteral(
+ FunctionBoilerplateLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitConditional(Conditional* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitThrow(Throw* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitProperty(Property* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitCall(Call* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitCallNew(CallNew* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
+ UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
+ UNREACHABLE();
+}
+
+
+} } // namespace v8::internal
--- /dev/null
+// Copyright 2009 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.
+
+#ifndef V8_FAST_CODEGEN_H_
+#define V8_FAST_CODEGEN_H_
+
+#ifdef V8_TARGET_ARCH_IA32
+
+#include "v8.h"
+
+#include "ast.h"
+
+namespace v8 {
+namespace internal {
+
+class FastCodeGenerator: public AstVisitor {
+ public:
+ explicit FastCodeGenerator(MacroAssembler* masm)
+ : masm_(masm), function_(NULL) {
+ }
+
+ static Handle<Code> MakeCode(FunctionLiteral* fun, Handle<Script> script);
+
+ void Generate(FunctionLiteral* fun);
+
+ private:
+ int SlotOffset(Slot* slot);
+
+ // AST node visit functions.
+#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
+ AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+ MacroAssembler* masm_;
+ FunctionLiteral* function_;
+
+ DISALLOW_COPY_AND_ASSIGN(FastCodeGenerator);
+};
+
+} } // namespace v8::internal
+
+#endif // V8_TARGET_ARCH_IA32
+#endif // V8_FAST_CODEGEN_H_
// compiler.cc
DEFINE_bool(strict, false, "strict error checking")
DEFINE_int(min_preparse_length, 1024,
- "Minimum length for automatic enable preparsing")
+ "minimum length for automatic enable preparsing")
+DEFINE_bool(fast_compiler, true,
+ "use the fast-mode compiler for some top-level code")
+DEFINE_bool(trace_bailout, false,
+ "print reasons for failing to use fast compilation")
// compilation-cache.cc
DEFINE_bool(compilation_cache, true, "enable compilation cache")
Handle<Script> script,
bool is_eval);
+ // Printing of AST, etc. as requested by flags.
+ static void MakeCodePrologue(FunctionLiteral* fun);
+
+ // Allocate and install the code.
+ static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
+ MacroAssembler* masm,
+ Code::Flags flags,
+ Handle<Script> script);
+
#ifdef ENABLE_LOGGING_AND_PROFILING
static bool ShouldGenerateLog(Expression* type);
#endif
--- /dev/null
+// Copyright 2009 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 "codegen-inl.h"
+#include "fast-codegen.h"
+// #include "scopes.h"
+
+namespace v8 {
+namespace internal {
+
+#define __ ACCESS_MASM(masm_)
+
+// Generate code for a JS function. On entry to the function the receiver
+// and arguments have been pushed on the stack left to right, with the
+// return address on top of them. The actual argument count matches the
+// formal parameter count expected by the function.
+//
+// The live registers are:
+// o edi: the JS function object being called (ie, ourselves)
+// o esi: our context
+// o ebp: our caller's frame pointer
+//
+// The function builds a JS frame. Please see JavaScriptFrameConstants in
+// frames-ia32.h for its layout.
+void FastCodeGenerator::Generate(FunctionLiteral* fun) {
+ function_ = fun;
+
+ __ push(ebp); // Caller's frame pointer.
+ __ mov(ebp, esp);
+ __ push(esi); // Callee's context.
+ __ push(edi); // Callee's JS Function.
+
+ { Comment cmnt(masm_, "[ Allocate locals");
+ int locals_count = fun->scope()->num_stack_slots();
+ for (int i = 0; i < locals_count; i++) {
+ __ push(Immediate(Factory::undefined_value()));
+ }
+ }
+
+ { Comment cmnt(masm_, "[ Stack check");
+ Label ok;
+ ExternalReference stack_guard_limit =
+ ExternalReference::address_of_stack_guard_limit();
+ __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
+ __ j(above_equal, &ok, taken);
+ StackCheckStub stub;
+ __ CallStub(&stub);
+ __ bind(&ok);
+ }
+
+ { Comment cmnt(masm_, "[ Body");
+ VisitStatements(fun->body());
+ }
+
+ { Comment cmnt(masm_, "[ return <undefined>;");
+ // Emit a 'return undefined' in case control fell off the end of the
+ // body.
+ __ mov(eax, Factory::undefined_value());
+ __ RecordJSReturn();
+ // Do not use the leave instruction here because it is too short to
+ // patch with the code required by the debugger.
+ __ mov(esp, ebp);
+ __ pop(ebp);
+ __ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
+ }
+}
+
+
+void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
+ Comment cmnt(masm_, "[ ExpressionStatement");
+ Visit(stmt->expression());
+ __ pop(eax);
+}
+
+
+void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
+ Comment cmnt(masm_, "[ ReturnStatement");
+ Visit(stmt->expression());
+ __ pop(eax);
+ __ RecordJSReturn();
+ // Do not use the leave instruction here because it is too short to
+ // patch with the code required by the debugger.
+ __ mov(esp, ebp);
+ __ pop(ebp);
+ __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
+}
+
+
+void FastCodeGenerator::VisitSlot(Slot* expr) {
+ Comment cmnt(masm_, "[ Slot");
+ __ push(Operand(ebp, SlotOffset(expr)));
+}
+
+
+void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
+ Comment cmnt(masm_, "[ VariableProxy");
+ Expression* rewrite = expr->var()->rewrite();
+ ASSERT(rewrite != NULL);
+ Visit(rewrite);
+}
+
+
+void FastCodeGenerator::VisitLiteral(Literal* expr) {
+ Comment cmnt(masm_, "[ Literal");
+ __ push(Immediate(expr->handle()));
+}
+
+
+void FastCodeGenerator::VisitAssignment(Assignment* expr) {
+ Comment cmnt(masm_, "[ Assignment");
+ ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
+
+ Visit(expr->value());
+
+ Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+ ASSERT(var != NULL && var->slot() != NULL);
+ __ mov(eax, Operand(esp, 0));
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+}
+
+
+} } // namespace v8::internal
HT(variable_allocation, V8.VariableAllocation) \
HT(ast_optimization, V8.ASTOptimization) \
HT(code_generation, V8.CodeGeneration) \
- HT(deferred_code_generation, V8.DeferredCodeGeneration) \
- HT(code_creation, V8.CodeCreation)
+ HT(deferred_code_generation, V8.DeferredCodeGeneration)
+
// WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
// Intellisense to crash. It was broken into two macros (each of length 40
Handle<Script> script,
bool is_eval);
+ // Printing of AST, etc. as requested by flags.
+ static void MakeCodePrologue(FunctionLiteral* fun);
+
+ // Allocate and install the code.
+ static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
+ MacroAssembler* masm,
+ Code::Flags flags,
+ Handle<Script> script);
+
#ifdef ENABLE_LOGGING_AND_PROFILING
static bool ShouldGenerateLog(Expression* type);
#endif
'../../src/ia32',
],
'sources': [
+ '../../src/fast-codegen.cc',
+ '../../src/fast-codegen.h',
'../../src/ia32/assembler-ia32-inl.h',
'../../src/ia32/assembler-ia32.cc',
'../../src/ia32/assembler-ia32.h',
'../../src/ia32/cpu-ia32.cc',
'../../src/ia32/debug-ia32.cc',
'../../src/ia32/disasm-ia32.cc',
+ '../../src/ia32/fast-codegen.cc',
'../../src/ia32/frames-ia32.cc',
'../../src/ia32/frames-ia32.h',
'../../src/ia32/ic-ia32.cc',
RelativePath="..\..\src\factory.h"
>
</File>
+ <File
+ RelativePath="..\..\src\ia32\fast-codegen-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\fast-codegen.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\fast-codegen.h"
+ >
+ </File>
<File
RelativePath="..\..\src\flags.cc"
>