From 888f6729be6a6f6fbe246cb5a9f122e2dbe455b7 Mon Sep 17 00:00:00 2001 From: Leon Clarke Date: Wed, 27 Jan 2010 15:57:47 +0000 Subject: Pull from svn bleeding_edge@3716 --- src/full-codegen.cc | 1168 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1168 insertions(+) create mode 100644 src/full-codegen.cc (limited to 'src/full-codegen.cc') diff --git a/src/full-codegen.cc b/src/full-codegen.cc new file mode 100644 index 00000000..0477ab90 --- /dev/null +++ b/src/full-codegen.cc @@ -0,0 +1,1168 @@ +// 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 "compiler.h" +#include "full-codegen.h" +#include "stub-cache.h" +#include "debug.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 FullCodeGenSyntaxChecker::Check(FunctionLiteral* fun) { + Scope* scope = fun->scope(); + + if (scope->num_heap_slots() > 0) { + // We support functions with a local context if they do not have + // parameters that need to be copied into the context. + for (int i = 0, len = scope->num_parameters(); i < len; i++) { + Slot* slot = scope->parameter(i)->slot(); + if (slot != NULL && slot->type() == Slot::CONTEXT) { + BAILOUT("Function has context-allocated parameters."); + } + } + } + + VisitDeclarations(scope->declarations()); + CHECK_BAILOUT; + + VisitStatements(fun->body()); +} + + +void FullCodeGenSyntaxChecker::VisitDeclarations( + ZoneList* decls) { + for (int i = 0; i < decls->length(); i++) { + Visit(decls->at(i)); + CHECK_BAILOUT; + } +} + + +void FullCodeGenSyntaxChecker::VisitStatements(ZoneList* stmts) { + for (int i = 0, len = stmts->length(); i < len; i++) { + Visit(stmts->at(i)); + CHECK_BAILOUT; + } +} + + +void FullCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) { + Property* prop = decl->proxy()->AsProperty(); + if (prop != NULL) { + Visit(prop->obj()); + Visit(prop->key()); + } + + if (decl->fun() != NULL) { + Visit(decl->fun()); + } +} + + +void FullCodeGenSyntaxChecker::VisitBlock(Block* stmt) { + VisitStatements(stmt->statements()); +} + + +void FullCodeGenSyntaxChecker::VisitExpressionStatement( + ExpressionStatement* stmt) { + Visit(stmt->expression()); +} + + +void FullCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) { + // Supported. +} + + +void FullCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) { + Visit(stmt->condition()); + CHECK_BAILOUT; + Visit(stmt->then_statement()); + CHECK_BAILOUT; + Visit(stmt->else_statement()); +} + + +void FullCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) { + // Supported. +} + + +void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) { + // Supported. +} + + +void FullCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) { + Visit(stmt->expression()); +} + + +void FullCodeGenSyntaxChecker::VisitWithEnterStatement( + WithEnterStatement* stmt) { + Visit(stmt->expression()); +} + + +void FullCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) { + // Supported. +} + + +void FullCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) { + BAILOUT("SwitchStatement"); +} + + +void FullCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) { + Visit(stmt->cond()); + CHECK_BAILOUT; + Visit(stmt->body()); +} + + +void FullCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) { + Visit(stmt->cond()); + CHECK_BAILOUT; + Visit(stmt->body()); +} + + +void FullCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) { + if (!FLAG_always_fast_compiler) BAILOUT("ForStatement"); + if (stmt->init() != NULL) { + Visit(stmt->init()); + CHECK_BAILOUT; + } + if (stmt->cond() != NULL) { + Visit(stmt->cond()); + CHECK_BAILOUT; + } + Visit(stmt->body()); + if (stmt->next() != NULL) { + CHECK_BAILOUT; + Visit(stmt->next()); + } +} + + +void FullCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) { + BAILOUT("ForInStatement"); +} + + +void FullCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) { + Visit(stmt->try_block()); + CHECK_BAILOUT; + Visit(stmt->catch_block()); +} + + +void FullCodeGenSyntaxChecker::VisitTryFinallyStatement( + TryFinallyStatement* stmt) { + Visit(stmt->try_block()); + CHECK_BAILOUT; + Visit(stmt->finally_block()); +} + + +void FullCodeGenSyntaxChecker::VisitDebuggerStatement( + DebuggerStatement* stmt) { + // Supported. +} + + +void FullCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) { + // Supported. +} + + +void FullCodeGenSyntaxChecker::VisitFunctionBoilerplateLiteral( + FunctionBoilerplateLiteral* expr) { + BAILOUT("FunctionBoilerplateLiteral"); +} + + +void FullCodeGenSyntaxChecker::VisitConditional(Conditional* expr) { + Visit(expr->condition()); + CHECK_BAILOUT; + Visit(expr->then_expression()); + CHECK_BAILOUT; + Visit(expr->else_expression()); +} + + +void FullCodeGenSyntaxChecker::VisitSlot(Slot* expr) { + UNREACHABLE(); +} + + +void FullCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) { + // Supported. +} + + +void FullCodeGenSyntaxChecker::VisitLiteral(Literal* expr) { + // Supported. +} + + +void FullCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) { + // Supported. +} + + +void FullCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) { + ZoneList* properties = expr->properties(); + + for (int i = 0, len = properties->length(); i < len; i++) { + ObjectLiteral::Property* property = properties->at(i); + if (property->IsCompileTimeValue()) continue; + Visit(property->key()); + CHECK_BAILOUT; + Visit(property->value()); + CHECK_BAILOUT; + } +} + + +void FullCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) { + ZoneList* subexprs = expr->values(); + for (int i = 0, len = subexprs->length(); i < len; i++) { + Expression* subexpr = subexprs->at(i); + if (subexpr->AsLiteral() != NULL) continue; + if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; + Visit(subexpr); + CHECK_BAILOUT; + } +} + + +void FullCodeGenSyntaxChecker::VisitCatchExtensionObject( + CatchExtensionObject* expr) { + Visit(expr->key()); + CHECK_BAILOUT; + Visit(expr->value()); +} + + +void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) { + Token::Value op = expr->op(); + if (op == Token::INIT_CONST) BAILOUT("initialize constant"); + + Variable* var = expr->target()->AsVariableProxy()->AsVariable(); + Property* prop = expr->target()->AsProperty(); + ASSERT(var == NULL || prop == NULL); + if (var != NULL) { + if (var->mode() == Variable::CONST) BAILOUT("Assignment to const"); + // All other variables are supported. + } else if (prop != NULL) { + Visit(prop->obj()); + CHECK_BAILOUT; + Visit(prop->key()); + CHECK_BAILOUT; + } else { + // This is a throw reference error. + BAILOUT("non-variable/non-property assignment"); + } + + Visit(expr->value()); +} + + +void FullCodeGenSyntaxChecker::VisitThrow(Throw* expr) { + Visit(expr->exception()); +} + + +void FullCodeGenSyntaxChecker::VisitProperty(Property* expr) { + Visit(expr->obj()); + CHECK_BAILOUT; + Visit(expr->key()); +} + + +void FullCodeGenSyntaxChecker::VisitCall(Call* expr) { + Expression* fun = expr->expression(); + ZoneList* args = expr->arguments(); + Variable* var = fun->AsVariableProxy()->AsVariable(); + + // Check for supported calls + if (var != NULL && var->is_possibly_eval()) { + BAILOUT("call to the identifier 'eval'"); + } else if (var != NULL && !var->is_this() && var->is_global()) { + // Calls to global variables are supported. + } else if (var != NULL && var->slot() != NULL && + var->slot()->type() == Slot::LOOKUP) { + BAILOUT("call to a lookup slot"); + } else if (fun->AsProperty() != NULL) { + Property* prop = fun->AsProperty(); + Visit(prop->obj()); + CHECK_BAILOUT; + Visit(prop->key()); + CHECK_BAILOUT; + } else { + // Otherwise the call is supported if the function expression is. + Visit(fun); + } + // Check all arguments to the call. + for (int i = 0; i < args->length(); i++) { + Visit(args->at(i)); + CHECK_BAILOUT; + } +} + + +void FullCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { + Visit(expr->expression()); + CHECK_BAILOUT; + ZoneList* args = expr->arguments(); + // Check all arguments to the call + for (int i = 0; i < args->length(); i++) { + Visit(args->at(i)); + CHECK_BAILOUT; + } +} + + +void FullCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { + // Check for inline runtime call + if (expr->name()->Get(0) == '_' && + CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { + BAILOUT("inlined runtime call"); + } + // Check all arguments to the call. (Relies on TEMP meaning STACK.) + for (int i = 0; i < expr->arguments()->length(); i++) { + Visit(expr->arguments()->at(i)); + CHECK_BAILOUT; + } +} + + +void FullCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { + switch (expr->op()) { + case Token::ADD: + case Token::NOT: + case Token::TYPEOF: + case Token::VOID: + Visit(expr->expression()); + break; + case Token::BIT_NOT: + BAILOUT("UnaryOperation: BIT_NOT"); + case Token::DELETE: + BAILOUT("UnaryOperation: DELETE"); + case Token::SUB: + BAILOUT("UnaryOperation: SUB"); + default: + UNREACHABLE(); + } +} + + +void FullCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { + Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); + Property* prop = expr->expression()->AsProperty(); + ASSERT(var == NULL || prop == NULL); + if (var != NULL) { + // All global variables are supported. + if (!var->is_global()) { + ASSERT(var->slot() != NULL); + Slot::Type type = var->slot()->type(); + if (type == Slot::LOOKUP) { + BAILOUT("CountOperation with lookup slot"); + } + } + } else if (prop != NULL) { + Visit(prop->obj()); + CHECK_BAILOUT; + Visit(prop->key()); + CHECK_BAILOUT; + } else { + // This is a throw reference error. + BAILOUT("CountOperation non-variable/non-property expression"); + } +} + + +void FullCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { + Visit(expr->left()); + CHECK_BAILOUT; + Visit(expr->right()); +} + + +void FullCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { + Visit(expr->left()); + CHECK_BAILOUT; + Visit(expr->right()); +} + + +void FullCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { + // Supported. +} + +#undef BAILOUT +#undef CHECK_BAILOUT + + +#define __ ACCESS_MASM(masm()) + +Handle FullCodeGenerator::MakeCode(FunctionLiteral* fun, + Handle