disassembler.cc
execution.cc
factory.cc
+ fast-codegen.cc
flags.cc
frame-element.cc
frames.cc
if (lit != NULL &&
lit->name()->Equals(Heap::empty_string()) &&
loop_depth() == 0) {
- lit->set_try_fast_codegen(true);
+ lit->set_try_full_codegen(true);
}
VisitForValue(fun, kStack);
// Load global receiver object.
loop_nesting_(0),
function_token_position_(RelocInfo::kNoPosition),
inferred_name_(Heap::empty_string()),
- try_fast_codegen_(false) {
+ try_full_codegen_(false) {
#ifdef DEBUG
already_compiled_ = false;
#endif
inferred_name_ = inferred_name;
}
- bool try_fast_codegen() { return try_fast_codegen_; }
- void set_try_fast_codegen(bool flag) { try_fast_codegen_ = flag; }
+ bool try_full_codegen() { return try_full_codegen_; }
+ void set_try_full_codegen(bool flag) { try_full_codegen_ = flag; }
#ifdef DEBUG
void mark_as_compiled() {
int loop_nesting_;
int function_token_position_;
Handle<String> inferred_name_;
- bool try_fast_codegen_;
+ bool try_full_codegen_;
#ifdef DEBUG
bool already_compiled_;
#endif
#include "compilation-cache.h"
#include "compiler.h"
#include "debug.h"
+#include "fast-codegen.h"
#include "full-codegen.h"
#include "oprofile-agent.h"
#include "rewriter.h"
return Handle<Code>::null();
}
- // Generate code and return it.
- if (FLAG_fast_compiler) {
- // If there is no shared function info, try the fast code
- // generator for code in the global scope. Otherwise obey the
- // explicit hint in the shared function info.
- // If always_fast_compiler is true, always try the fast compiler.
- if (shared.is_null() && !literal->scope()->is_global_scope() &&
- !FLAG_always_fast_compiler) {
- if (FLAG_trace_bailout) PrintF("Non-global scope\n");
- } else if (!shared.is_null() && !shared->try_fast_codegen() &&
- !FLAG_always_fast_compiler) {
- if (FLAG_trace_bailout) PrintF("No hint to try fast\n");
- } else {
- FullCodeGenSyntaxChecker checker;
- checker.Check(literal);
- if (checker.has_supported_syntax()) {
- return FullCodeGenerator::MakeCode(literal, script, is_eval);
- }
+ // Generate code and return it. Code generator selection is governed by
+ // which backends are enabled and whether the function is considered
+ // run-once code or not:
+ //
+ // --full-compiler enables the dedicated backend for code we expect to be
+ // run once
+ // --fast-compiler enables a speculative optimizing backend (for
+ // non-run-once code)
+ //
+ // The normal choice of backend can be overridden with the flags
+ // --always-full-compiler and --always-fast-compiler, which are mutually
+ // incompatible.
+ CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
+
+ bool is_run_once = (shared.is_null())
+ ? literal->scope()->is_global_scope()
+ : (shared->is_toplevel() || shared->try_full_codegen());
+
+ if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) {
+ FullCodeGenSyntaxChecker checker;
+ checker.Check(literal);
+ if (checker.has_supported_syntax()) {
+ return FullCodeGenerator::MakeCode(literal, script, is_eval);
}
+ } else if (FLAG_always_fast_compiler ||
+ (FLAG_fast_compiler && !is_run_once)) {
+ FastCodeGenSyntaxChecker checker;
+ checker.Check(literal);
+ // Does not yet generate code.
}
+
return CodeGenerator::MakeCode(literal, script, is_eval);
}
return Handle<JSFunction>::null();
}
- // Generate code and return it.
+ // Generate code and return it. The way that the compilation mode
+ // is controlled by the command-line flags is described in
+ // the static helper function MakeCode.
+ CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
+ bool is_run_once = literal->try_full_codegen();
bool is_compiled = false;
- if (FLAG_always_fast_compiler ||
- (FLAG_fast_compiler && literal->try_fast_codegen())) {
+ if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) {
FullCodeGenSyntaxChecker checker;
checker.Check(literal);
if (checker.has_supported_syntax()) {
false); // Not eval.
is_compiled = true;
}
+ } else if (FLAG_always_fast_compiler ||
+ (FLAG_fast_compiler && !is_run_once)) {
+ FastCodeGenSyntaxChecker checker;
+ checker.Check(literal);
+ // Generate no code.
}
if (!is_compiled) {
- // We didn't try the fast compiler, or we failed to select it.
+ // We fall back to the classic V8 code generator.
code = CodeGenerator::MakeCode(literal,
script,
false); // Not eval.
fun->shared()->SetThisPropertyAssignmentsInfo(
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
- fun->shared()->set_try_fast_codegen(lit->try_fast_codegen());
+ fun->shared()->set_try_full_codegen(lit->try_full_codegen());
}
--- /dev/null
+// 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
--- /dev/null
+// 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_H_
+#define V8_FAST_CODEGEN_H_
+
+#include "v8.h"
+
+#include "ast.h"
+
+namespace v8 {
+namespace internal {
+
+class FastCodeGenSyntaxChecker: public AstVisitor {
+ public:
+ FastCodeGenSyntaxChecker() : has_supported_syntax_(true) {}
+
+ void Check(FunctionLiteral* fun);
+
+ 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
+
+ bool has_supported_syntax_;
+
+ DISALLOW_COPY_AND_ASSIGN(FastCodeGenSyntaxChecker);
+};
+
+
+} } // namespace v8::internal
+
+#endif // V8_FAST_CODEGEN_H_
DEFINE_bool(strict, false, "strict error checking")
DEFINE_int(min_preparse_length, 1024,
"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")
+DEFINE_bool(full_compiler, true, "enable dedicated backend for run-once code")
+DEFINE_bool(fast_compiler, false, "enable speculative optimizing backend")
+DEFINE_bool(always_full_compiler, false,
+ "try to use the dedicated run-once backend for all code")
DEFINE_bool(always_fast_compiler, false,
- "always try using the fast compiler")
+ "try to use the speculative optimizing backend for all code")
+DEFINE_bool(trace_bailout, false,
+ "print reasons for falling back to using the classic V8 backend")
// compilation-cache.cc
DEFINE_bool(compilation_cache, true, "enable compilation cache")
void FullCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) {
- if (!FLAG_always_fast_compiler) BAILOUT("ForStatement");
+ if (!FLAG_always_full_compiler) BAILOUT("ForStatement");
if (stmt->init() != NULL) {
Visit(stmt->init());
CHECK_BAILOUT;
// (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_
+#ifndef V8_FULL_CODEGEN_H_
+#define V8_FULL_CODEGEN_H_
#include "v8.h"
} } // namespace v8::internal
-#endif // V8_FAST_CODEGEN_H_
+#endif // V8_FULL_CODEGEN_H_
} else {
// Call to some other expression. If the expression is an anonymous
// function literal not called in a loop, mark it as one that should
- // also use the fast code generator.
+ // also use the full code generator.
FunctionLiteral* lit = fun->AsFunctionLiteral();
if (lit != NULL &&
lit->name()->Equals(Heap::empty_string()) &&
loop_depth() == 0) {
- lit->set_try_fast_codegen(true);
+ lit->set_try_full_codegen(true);
}
VisitForValue(fun, kStack);
// Load global receiver object.
kHasOnlySimpleThisPropertyAssignments)
BOOL_ACCESSORS(SharedFunctionInfo,
compiler_hints,
- try_fast_codegen,
- kTryFastCodegen)
+ try_full_codegen,
+ kTryFullCodegen)
INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
// this.x = y; where y is either a constant or refers to an argument.
inline bool has_only_simple_this_property_assignments();
- inline bool try_fast_codegen();
- inline void set_try_fast_codegen(bool flag);
+ inline bool try_full_codegen();
+ inline void set_try_full_codegen(bool flag);
// For functions which only contains this property assignments this provides
// access to the names for the properties assigned.
// Bit positions in compiler_hints.
static const int kHasOnlySimpleThisPropertyAssignments = 0;
- static const int kTryFastCodegen = 1;
+ static const int kTryFullCodegen = 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
};
if (lit != NULL &&
lit->name()->Equals(Heap::empty_string()) &&
loop_depth() == 0) {
- lit->set_try_fast_codegen(true);
+ lit->set_try_full_codegen(true);
}
VisitForValue(fun, kStack);
// Load global receiver object.
'../../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/flags.h',