v8/src/fast-codegen.cc
kmillikin@chromium.org 2b62886dab Refactor the selection of code generator and add the possibility of a
simpler backend for non-toplevel code.

Review URL: http://codereview.chromium.org/549158

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3721 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2010-01-27 15:23:48 +00:00

307 lines
7.8 KiB
C++

// 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 "fast-codegen.h"
#include "scopes.h"
namespace v8 {
namespace internal {
#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 FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun) {
Scope* scope = fun->scope();
// We do not support stack or heap slots (both of which require
// allocation).
if (scope->num_stack_slots() > 0) {
BAILOUT("Function has stack-allocated locals");
}
if (scope->num_heap_slots() > 0) {
BAILOUT("Function has context-allocated locals");
}
VisitDeclarations(scope->declarations());
CHECK_BAILOUT;
// We do not support empty function bodies.
if (fun->body()->is_empty()) BAILOUT("Function has an empty body");
VisitStatements(fun->body());
}
void FastCodeGenSyntaxChecker::VisitDeclarations(
ZoneList<Declaration*>* decls) {
if (!decls->is_empty()) BAILOUT("Function has declarations");
}
void FastCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) {
for (int i = 0, len = stmts->length(); i < len; i++) {
Visit(stmts->at(i));
CHECK_BAILOUT;
}
}
void FastCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) {
UNREACHABLE();
}
void FastCodeGenSyntaxChecker::VisitBlock(Block* stmt) {
VisitStatements(stmt->statements());
}
void FastCodeGenSyntaxChecker::VisitExpressionStatement(
ExpressionStatement* stmt) {
Visit(stmt->expression());
}
void FastCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) {
// Supported.
}
void FastCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) {
BAILOUT("IfStatement");
}
void FastCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) {
BAILOUT("Continuestatement");
}
void FastCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) {
BAILOUT("BreakStatement");
}
void FastCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) {
BAILOUT("ReturnStatement");
}
void FastCodeGenSyntaxChecker::VisitWithEnterStatement(
WithEnterStatement* stmt) {
BAILOUT("WithEnterStatement");
}
void FastCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) {
BAILOUT("WithExitStatement");
}
void FastCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) {
BAILOUT("SwitchStatement");
}
void FastCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
BAILOUT("DoWhileStatement");
}
void FastCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) {
BAILOUT("WhileStatement");
}
void FastCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) {
BAILOUT("ForStatement");
}
void FastCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) {
BAILOUT("ForInStatement");
}
void FastCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) {
BAILOUT("TryCatchStatement");
}
void FastCodeGenSyntaxChecker::VisitTryFinallyStatement(
TryFinallyStatement* stmt) {
BAILOUT("TryFinallyStatement");
}
void FastCodeGenSyntaxChecker::VisitDebuggerStatement(
DebuggerStatement* stmt) {
BAILOUT("DebuggerStatement");
}
void FastCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
BAILOUT("FunctionLiteral");
}
void FastCodeGenSyntaxChecker::VisitFunctionBoilerplateLiteral(
FunctionBoilerplateLiteral* expr) {
BAILOUT("FunctionBoilerplateLiteral");
}
void FastCodeGenSyntaxChecker::VisitConditional(Conditional* expr) {
BAILOUT("Conditional");
}
void FastCodeGenSyntaxChecker::VisitSlot(Slot* expr) {
UNREACHABLE();
}
void FastCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) {
// Only global variable references are supported.
Variable* var = expr->var();
if (!var->is_global()) BAILOUT("Non-global variable");
}
void FastCodeGenSyntaxChecker::VisitLiteral(Literal* expr) {
BAILOUT("Literal");
}
void FastCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
BAILOUT("RegExpLiteral");
}
void FastCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) {
BAILOUT("ObjectLiteral");
}
void FastCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) {
BAILOUT("ArrayLiteral");
}
void FastCodeGenSyntaxChecker::VisitCatchExtensionObject(
CatchExtensionObject* expr) {
BAILOUT("CatchExtensionObject");
}
void FastCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
// Simple assignments to (named) this properties are supported.
if (expr->op() != Token::ASSIGN) BAILOUT("Non-simple assignment");
Property* prop = expr->target()->AsProperty();
if (prop == NULL) BAILOUT("Non-property assignment");
VariableProxy* proxy = prop->obj()->AsVariableProxy();
if (proxy == NULL || !proxy->var()->is_this()) {
BAILOUT("Non-this-property assignment");
}
if (!prop->key()->IsPropertyName()) {
BAILOUT("Non-named-property assignment");
}
Visit(expr->value());
}
void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) {
BAILOUT("Throw");
}
void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) {
BAILOUT("Property");
}
void FastCodeGenSyntaxChecker::VisitCall(Call* expr) {
BAILOUT("Call");
}
void FastCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) {
BAILOUT("CallNew");
}
void FastCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) {
BAILOUT("CallRuntime");
}
void FastCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) {
BAILOUT("UnaryOperation");
}
void FastCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) {
BAILOUT("CountOperation");
}
void FastCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) {
BAILOUT("BinaryOperation");
}
void FastCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) {
BAILOUT("CompareOperation");
}
void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) {
BAILOUT("ThisFunction");
}
#undef BAILOUT
#undef CHECK_BAILOUT
} } // namespace v8::internal