Temporarily move the ia32 fast code generator into the platform-specific directory.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Feb 2010 09:17:37 +0000 (09:17 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Feb 2010 09:17:37 +0000 (09:17 +0000)
This allows us to make changes to one platform without affecting the others.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3907 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/SConscript
src/fast-codegen.h
src/ia32/fast-codegen-ia32.cc
src/ia32/fast-codegen-ia32.h [new file with mode: 0644]
tools/gyp/v8.gyp
tools/visual_studio/v8_base.vcproj

index 1a81cc73caeb65720d30aef650235b34be95250c..73de193ad57ed52567575c36a7fc027374861132 100755 (executable)
@@ -57,7 +57,6 @@ SOURCES = {
     disassembler.cc
     execution.cc
     factory.cc
-    fast-codegen.cc
     flags.cc
     frame-element.cc
     frames.cc
@@ -109,6 +108,7 @@ SOURCES = {
     zone.cc
     """),
   'arch:arm': Split("""
+    fast-codegen.cc
     arm/builtins-arm.cc
     arm/codegen-arm.cc
     arm/constants-arm.cc
@@ -133,6 +133,7 @@ SOURCES = {
     arm/assembler-thumb2.cc
     """),
   'arch:mips': Split("""
+    fast-codegen.cc
     mips/assembler-mips.cc
     mips/builtins-mips.cc
     mips/codegen-mips.cc
@@ -169,6 +170,7 @@ SOURCES = {
     ia32/virtual-frame-ia32.cc
     """),
   'arch:x64': Split("""
+    fast-codegen.cc
     x64/assembler-x64.cc
     x64/builtins-x64.cc
     x64/codegen-x64.cc
index 96ee5dddb8cf0e692cf2726c3e1f2002f989e48f..f39da21ad7da6e2f9a292e033d4dab841b4198ab 100644 (file)
 #ifndef V8_FAST_CODEGEN_H_
 #define V8_FAST_CODEGEN_H_
 
+#if V8_TARGET_ARCH_IA32
+#include "ia32/fast-codegen-ia32.h"
+#else
+
 #include "v8.h"
 
 #include "ast.h"
@@ -152,4 +156,6 @@ class FastCodeGenerator: public AstVisitor {
 
 } }  // namespace v8::internal
 
+#endif  // V8_TARGET_ARCH_IA32
+
 #endif  // V8_FAST_CODEGEN_H_
index 9bab75aa613146cca05e3d4284be64d3a468b17d..0257dc5292399d98529e19313a57acf90662b7da 100644 (file)
 
 #include "codegen-inl.h"
 #include "fast-codegen.h"
+#include "data-flow.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(CompilationInfo* info) {
+  info_ = info;
+
+  // We do not specialize if we do not have a receiver or if it is not a
+  // JS object with fast mode properties.
+  if (!info->has_receiver()) BAILOUT("No receiver");
+  if (!info->receiver()->IsJSObject()) BAILOUT("Receiver is not an object");
+  Handle<JSObject> object = Handle<JSObject>::cast(info->receiver());
+  if (!object->HasFastProperties()) BAILOUT("Receiver is in dictionary mode");
+
+  // We do not support stack or heap slots (both of which require
+  // allocation).
+  Scope* scope = info->scope();
+  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 (info->function()->body()->is_empty()) {
+    BAILOUT("Function has an empty body");
+  }
+  VisitStatements(info->function()->body());
+}
+
+
+void FastCodeGenSyntaxChecker::VisitDeclarations(
+    ZoneList<Declaration*>* decls) {
+  if (!decls->is_empty()) BAILOUT("Function has declarations");
+}
+
+
+void FastCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) {
+  if (stmts->length() != 1) {
+    BAILOUT("Function body is not a singleton statement.");
+  }
+  Visit(stmts->at(0));
+}
+
+
+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() || var->is_this()) BAILOUT("Non-global variable");
+
+  // Check if the global variable is existing and non-deletable.
+  if (info()->has_global_object()) {
+    LookupResult lookup;
+    info()->global_object()->Lookup(*expr->name(), &lookup);
+    if (!lookup.IsProperty()) {
+      BAILOUT("Non-existing global variable");
+    }
+    // We do not handle global variables with accessors or interceptors.
+    if (lookup.type() != NORMAL) {
+      BAILOUT("Global variable with accessors or interceptors.");
+    }
+    // We do not handle deletable global variables.
+    if (!lookup.IsDontDelete()) {
+      BAILOUT("Deletable 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");
+  }
+
+  // We will only specialize for fields on the object itself.
+  // Expression::IsPropertyName implies that the name is a literal
+  // symbol but we do not assume that.
+  Literal* key = prop->key()->AsLiteral();
+  if (key != NULL && key->handle()->IsString()) {
+    Handle<Object> receiver = info()->receiver();
+    Handle<String> name = Handle<String>::cast(key->handle());
+    LookupResult lookup;
+    receiver->Lookup(*name, &lookup);
+    if (!lookup.IsProperty()) {
+      BAILOUT("Assigned property not found at compile time");
+    }
+    if (lookup.holder() != *receiver) BAILOUT("Non-own property assignment");
+    if (!lookup.type() == FIELD) BAILOUT("Non-field property assignment");
+  } else {
+    UNREACHABLE();
+    BAILOUT("Unexpected non-string-literal property key");
+  }
+
+  Visit(expr->value());
+}
+
+
+void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) {
+  BAILOUT("Throw");
+}
+
+
+void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) {
+  // We support named this property references.
+  VariableProxy* proxy = expr->obj()->AsVariableProxy();
+  if (proxy == NULL || !proxy->var()->is_this()) {
+    BAILOUT("Non-this-property reference");
+  }
+  if (!expr->key()->IsPropertyName()) {
+    BAILOUT("Non-named-property reference");
+  }
+
+  // We will only specialize for fields on the object itself.
+  // Expression::IsPropertyName implies that the name is a literal
+  // symbol but we do not assume that.
+  Literal* key = expr->key()->AsLiteral();
+  if (key != NULL && key->handle()->IsString()) {
+    Handle<Object> receiver = info()->receiver();
+    Handle<String> name = Handle<String>::cast(key->handle());
+    LookupResult lookup;
+    receiver->Lookup(*name, &lookup);
+    if (!lookup.IsProperty()) {
+      BAILOUT("Referenced property not found at compile time");
+    }
+    if (lookup.holder() != *receiver) BAILOUT("Non-own property reference");
+    if (!lookup.type() == FIELD) BAILOUT("Non-field property reference");
+  } else {
+    UNREACHABLE();
+    BAILOUT("Unexpected non-string-literal property key");
+  }
+}
+
+
+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) {
+  // We support bitwise OR.
+  switch (expr->op()) {
+    case Token::COMMA:
+      BAILOUT("BinaryOperation COMMA");
+    case Token::OR:
+      BAILOUT("BinaryOperation OR");
+    case Token::AND:
+      BAILOUT("BinaryOperation AND");
+
+    case Token::BIT_OR:
+      // We support expressions nested on the left because they only require
+      // a pair of registers to keep all intermediate values in registers
+      // (i.e., the expression stack has height no more than two).
+      if (!expr->right()->IsLeaf()) BAILOUT("expression nested on right");
+
+      // We do not allow subexpressions with side effects because we
+      // (currently) bail out to the beginning of the full function.  The
+      // only expressions with side effects that we would otherwise handle
+      // are assignments.
+      if (expr->left()->AsAssignment() != NULL ||
+          expr->right()->AsAssignment() != NULL) {
+        BAILOUT("subexpression of binary operation has side effects");
+      }
+
+      Visit(expr->left());
+      CHECK_BAILOUT;
+      Visit(expr->right());
+      break;
+
+    case Token::BIT_XOR:
+      BAILOUT("BinaryOperation BIT_XOR");
+    case Token::BIT_AND:
+      BAILOUT("BinaryOperation BIT_AND");
+    case Token::SHL:
+      BAILOUT("BinaryOperation SHL");
+    case Token::SAR:
+      BAILOUT("BinaryOperation SAR");
+    case Token::SHR:
+      BAILOUT("BinaryOperation SHR");
+    case Token::ADD:
+      BAILOUT("BinaryOperation ADD");
+    case Token::SUB:
+      BAILOUT("BinaryOperation SUB");
+    case Token::MUL:
+      BAILOUT("BinaryOperation MUL");
+    case Token::DIV:
+      BAILOUT("BinaryOperation DIV");
+    case Token::MOD:
+      BAILOUT("BinaryOperation MOD");
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void FastCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) {
+  BAILOUT("CompareOperation");
+}
+
+
+void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) {
+  BAILOUT("ThisFunction");
+}
+
+#undef BAILOUT
+#undef CHECK_BAILOUT
+
+
 #define __ ACCESS_MASM(masm())
 
+Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) {
+  // Label the AST before calling MakeCodePrologue, so AST node numbers are
+  // printed with the AST.
+  AstLabeler labeler;
+  labeler.Label(info);
+
+  LivenessAnalyzer analyzer;
+  analyzer.Analyze(info->function());
+
+  CodeGenerator::MakeCodePrologue(info);
+
+  const int kInitialBufferSize = 4 * KB;
+  MacroAssembler masm(NULL, kInitialBufferSize);
+
+  // Generate the fast-path code.
+  FastCodeGenerator fast_cgen(&masm);
+  fast_cgen.Generate(info);
+  if (fast_cgen.HasStackOverflow()) {
+    ASSERT(!Top::has_pending_exception());
+    return Handle<Code>::null();
+  }
+
+  // Generate the full code for the function in bailout mode, using the same
+  // macro assembler.
+  CodeGenerator cgen(&masm);
+  CodeGeneratorScope scope(&cgen);
+  cgen.Generate(info, CodeGenerator::SECONDARY);
+  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(&masm, flags, info);
+}
+
+
+void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
+  UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitBlock(Block* stmt) {
+  VisitStatements(stmt->statements());
+}
+
+
+void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
+  Visit(stmt->expression());
+}
+
+
+void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
+  // Nothing to do.
+}
+
+
+void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) {
+  UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
+  UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
+  UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitReturnStatement(ReturnStatement* 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::VisitSlot(Slot* expr) {
+  UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
+  ASSERT(expr->var()->is_global() && !expr->var()->is_this());
+  // Check if we can compile a global variable load directly from the cell.
+  ASSERT(info()->has_global_object());
+  LookupResult lookup;
+  info()->global_object()->Lookup(*expr->name(), &lookup);
+  // We only support normal (non-accessor/interceptor) DontDelete properties
+  // for now.
+  ASSERT(lookup.IsProperty());
+  ASSERT_EQ(NORMAL, lookup.type());
+  ASSERT(lookup.IsDontDelete());
+  Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup));
+
+  // Global variable lookups do not have side effects, so we do not need to
+  // emit code if we are in an effect context.
+  if (!destination().is(no_reg)) {
+    Comment cmnt(masm(), ";; Global");
+    if (FLAG_print_ir) {
+      SmartPointer<char> name = expr->name()->ToCString();
+      PrintF("%d: t%d = Global(%s)  // last_use = %d\n", expr->num(),
+             expr->num(), *name, expr->var_def()->last_use()->num());
+    }
+    EmitGlobalVariableLoad(cell);
+  }
+}
+
+
+void FastCodeGenerator::VisitLiteral(Literal* 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::VisitAssignment(Assignment* expr) {
+  // Known to be a simple this property assignment.  Effectively a unary
+  // operation.
+  { Register my_destination = destination();
+    set_destination(accumulator0());
+    Visit(expr->value());
+    set_destination(my_destination);
+  }
+
+  Property* prop = expr->target()->AsProperty();
+  ASSERT_NOT_NULL(prop);
+  ASSERT_NOT_NULL(prop->obj()->AsVariableProxy());
+  ASSERT(prop->obj()->AsVariableProxy()->var()->is_this());
+  ASSERT(prop->key()->IsPropertyName());
+  Handle<String> name =
+      Handle<String>::cast(prop->key()->AsLiteral()->handle());
+
+  Comment cmnt(masm(), ";; Store to this");
+  if (FLAG_print_ir) {
+    SmartPointer<char> name_string = name->ToCString();
+    PrintF("%d: ", expr->num());
+    if (!destination().is(no_reg)) PrintF("t%d = ", expr->num());
+    PrintF("Store(this, \"%s\", t%d)  // last_use(this) = %d\n", *name_string,
+           expr->value()->num(),
+           expr->var_def()->last_use()->num());
+  }
+
+  EmitThisPropertyStore(name);
+}
+
+
+void FastCodeGenerator::VisitThrow(Throw* expr) {
+  UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitProperty(Property* expr) {
+  ASSERT_NOT_NULL(expr->obj()->AsVariableProxy());
+  ASSERT(expr->obj()->AsVariableProxy()->var()->is_this());
+  ASSERT(expr->key()->IsPropertyName());
+  if (!destination().is(no_reg)) {
+    Handle<String> name =
+        Handle<String>::cast(expr->key()->AsLiteral()->handle());
+
+    Comment cmnt(masm(), ";; Load from this");
+    if (FLAG_print_ir) {
+      SmartPointer<char> name_string = name->ToCString();
+      PrintF("%d: t%d = Load(this, \"%s\")  // last_use(this) = %d\n",
+             expr->num(), expr->num(), *name_string,
+             expr->var_def()->last_use()->num());
+    }
+    EmitThisPropertyLoad(name);
+  }
+}
+
+
+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) {
+  // We support limited binary operations: bitwise OR only allowed to be
+  // nested on the left.
+  ASSERT(expr->op() == Token::BIT_OR);
+  ASSERT(expr->right()->IsLeaf());
+
+  { Register my_destination = destination();
+    set_destination(accumulator1());
+    Visit(expr->left());
+    set_destination(accumulator0());
+    Visit(expr->right());
+    set_destination(my_destination);
+  }
+
+  Comment cmnt(masm(), ";; BIT_OR");
+  if (FLAG_print_ir) {
+    PrintF("%d: ", expr->num());
+    if (!destination().is(no_reg)) PrintF("t%d = ", expr->num());
+    PrintF("BIT_OR(t%d, t%d)\n", expr->left()->num(), expr->right()->num());
+  }
+  EmitBitOr();
+}
+
+
+void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
+  UNREACHABLE();
+}
+
+
+void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
+  UNREACHABLE();
+}
+
 Register FastCodeGenerator::accumulator0() { return eax; }
 Register FastCodeGenerator::accumulator1() { return edx; }
 Register FastCodeGenerator::scratch0() { return ecx; }
diff --git a/src/ia32/fast-codegen-ia32.h b/src/ia32/fast-codegen-ia32.h
new file mode 100644 (file)
index 0000000..6072caa
--- /dev/null
@@ -0,0 +1,150 @@
+// 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.
+
+#ifndef V8_FAST_CODEGEN_IA32_H_
+#define V8_FAST_CODEGEN_IA32_H_
+
+namespace v8 {
+namespace internal {
+
+class FastCodeGenSyntaxChecker: public AstVisitor {
+ public:
+  explicit FastCodeGenSyntaxChecker()
+      : info_(NULL), has_supported_syntax_(true) {
+  }
+
+  void Check(CompilationInfo* info);
+
+  CompilationInfo* info() { return info_; }
+  bool has_supported_syntax() { return has_supported_syntax_; }
+
+ private:
+  void VisitDeclarations(ZoneList<Declaration*>* decls);
+  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
+
+  CompilationInfo* info_;
+  bool has_supported_syntax_;
+
+  DISALLOW_COPY_AND_ASSIGN(FastCodeGenSyntaxChecker);
+};
+
+
+class FastCodeGenerator: public AstVisitor {
+ public:
+  explicit FastCodeGenerator(MacroAssembler* masm)
+      : masm_(masm), info_(NULL), destination_(no_reg), smi_bits_(0) {
+  }
+
+  static Handle<Code> MakeCode(CompilationInfo* info);
+
+  void Generate(CompilationInfo* compilation_info);
+
+ private:
+  MacroAssembler* masm() { return masm_; }
+  CompilationInfo* info() { return info_; }
+  Label* bailout() { return &bailout_; }
+
+  Register destination() { return destination_; }
+  void set_destination(Register reg) { destination_ = reg; }
+
+  FunctionLiteral* function() { return info_->function(); }
+  Scope* scope() { return info_->scope(); }
+
+  // Platform-specific fixed registers, all guaranteed distinct.
+  Register accumulator0();
+  Register accumulator1();
+  Register scratch0();
+  Register scratch1();
+  Register receiver_reg();
+  Register context_reg();
+
+  Register other_accumulator(Register reg) {
+    ASSERT(reg.is(accumulator0()) || reg.is(accumulator1()));
+    return (reg.is(accumulator0())) ? accumulator1() : accumulator0();
+  }
+
+  // Flags are true if the respective register is statically known to hold a
+  // smi.  We do not track every register, only the accumulator registers.
+  bool is_smi(Register reg) {
+    ASSERT(!reg.is(no_reg));
+    return (smi_bits_ & reg.bit()) != 0;
+  }
+  void set_as_smi(Register reg) {
+    ASSERT(!reg.is(no_reg));
+    smi_bits_ = smi_bits_ | reg.bit();
+  }
+  void clear_as_smi(Register reg) {
+    ASSERT(!reg.is(no_reg));
+    smi_bits_ = smi_bits_ & ~reg.bit();
+  }
+
+  // AST node visit functions.
+#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
+  AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+  // Emit code to load the receiver from the stack into receiver_reg.
+  void EmitLoadReceiver();
+
+  // Emit code to load a global variable directly from a global property
+  // cell into the destination register.
+  void EmitGlobalVariableLoad(Handle<Object> cell);
+
+  // Emit a store to an own property of this.  The stored value is expected
+  // in accumulator0 and the receiver in receiver_reg.  The receiver
+  // register is preserved and the result (the stored value) is left in the
+  // destination register.
+  void EmitThisPropertyStore(Handle<String> name);
+
+  // Emit a load from an own property of this.  The receiver is expected in
+  // receiver_reg.  The receiver register is preserved and the result is
+  // left in the destination register.
+  void EmitThisPropertyLoad(Handle<String> name);
+
+  // Emit a bitwise or operation.  The left operand is in accumulator1 and
+  // the right is in accumulator0.  The result should be left in the
+  // destination register.
+  void EmitBitOr();
+
+  MacroAssembler* masm_;
+  CompilationInfo* info_;
+  Label bailout_;
+  Register destination_;
+  uint32_t smi_bits_;
+
+  DISALLOW_COPY_AND_ASSIGN(FastCodeGenerator);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_FAST_CODEGEN_IA32_H_
index 9fea73ce8c72f7d538259f3e742cf3e3a806e5ef..c9766d2f5cd4da59f579eaccee56186d6c279d37 100644 (file)
         '../../src/execution.h',
         '../../src/factory.cc',
         '../../src/factory.h',
-        '../../src/fast-codegen.cc',
         '../../src/fast-codegen.h',
         '../../src/flag-definitions.h',
         '../../src/flags.cc',
             '../../src/arm',
           ],
           'sources': [
+            '../../src/fast-codegen.cc',
             '../../src/arm/assembler-arm-inl.h',
             '../../src/arm/assembler-arm.cc',
             '../../src/arm/assembler-arm.h',
             '../../src/ia32/debug-ia32.cc',
             '../../src/ia32/disasm-ia32.cc',
             '../../src/ia32/fast-codegen-ia32.cc',
+            '../../src/ia32/fast-codegen-ia32.h',
             '../../src/ia32/frames-ia32.cc',
             '../../src/ia32/frames-ia32.h',
             '../../src/ia32/full-codegen-ia32.cc',
             '../../src/x64',
           ],
           'sources': [
+            '../../src/fast-codegen.cc',
             '../../src/x64/assembler-x64-inl.h',
             '../../src/x64/assembler-x64.cc',
             '../../src/x64/assembler-x64.h',
index fdb6cd0c66159af86a5da7b668e0cac8eddd9b69..85935288e1862ce1303abb0cb3c9393acfe13198 100644 (file)
                                 >
                         </File>
                         <File
-                                RelativePath="..\..\src\fast-codegen.cc"
+                                RelativePath="..\..\src\ia32\fast-codegen-ia32.h"
                                 >
                         </File>
                         <File