Commit 3527e29e authored by kasperl@chromium.org's avatar kasperl@chromium.org

Remove the full codegen syntax checker completely but be

careful to avoid making code with loops run too slowly.
Review URL: http://codereview.chromium.org/3107033

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5324 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7b51dc7e
...@@ -1416,7 +1416,8 @@ class FunctionLiteral: public Expression { ...@@ -1416,7 +1416,8 @@ class FunctionLiteral: public Expression {
int num_parameters, int num_parameters,
int start_position, int start_position,
int end_position, int end_position,
bool is_expression) bool is_expression,
bool contains_loops)
: name_(name), : name_(name),
scope_(scope), scope_(scope),
body_(body), body_(body),
...@@ -1429,6 +1430,7 @@ class FunctionLiteral: public Expression { ...@@ -1429,6 +1430,7 @@ class FunctionLiteral: public Expression {
start_position_(start_position), start_position_(start_position),
end_position_(end_position), end_position_(end_position),
is_expression_(is_expression), is_expression_(is_expression),
contains_loops_(contains_loops),
function_token_position_(RelocInfo::kNoPosition), function_token_position_(RelocInfo::kNoPosition),
inferred_name_(Heap::empty_string()), inferred_name_(Heap::empty_string()),
try_full_codegen_(false) { try_full_codegen_(false) {
...@@ -1450,6 +1452,7 @@ class FunctionLiteral: public Expression { ...@@ -1450,6 +1452,7 @@ class FunctionLiteral: public Expression {
int start_position() const { return start_position_; } int start_position() const { return start_position_; }
int end_position() const { return end_position_; } int end_position() const { return end_position_; }
bool is_expression() const { return is_expression_; } bool is_expression() const { return is_expression_; }
bool contains_loops() const { return contains_loops_; }
int materialized_literal_count() { return materialized_literal_count_; } int materialized_literal_count() { return materialized_literal_count_; }
int expected_property_count() { return expected_property_count_; } int expected_property_count() { return expected_property_count_; }
...@@ -1490,6 +1493,7 @@ class FunctionLiteral: public Expression { ...@@ -1490,6 +1493,7 @@ class FunctionLiteral: public Expression {
int start_position_; int start_position_;
int end_position_; int end_position_;
bool is_expression_; bool is_expression_;
bool contains_loops_;
int function_token_position_; int function_token_position_;
Handle<String> inferred_name_; Handle<String> inferred_name_;
bool try_full_codegen_; bool try_full_codegen_;
......
...@@ -104,15 +104,9 @@ static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) { ...@@ -104,15 +104,9 @@ static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
bool is_run_once = (shared.is_null()) bool is_run_once = (shared.is_null())
? info->scope()->is_global_scope() ? info->scope()->is_global_scope()
: (shared->is_toplevel() || shared->try_full_codegen()); : (shared->is_toplevel() || shared->try_full_codegen());
bool use_full = FLAG_full_compiler && !function->contains_loops();
if (AlwaysFullCompiler()) { if (AlwaysFullCompiler() || (use_full && is_run_once)) {
return FullCodeGenerator::MakeCode(info); return FullCodeGenerator::MakeCode(info);
} else if (FLAG_full_compiler && is_run_once) {
FullCodeGenSyntaxChecker checker;
checker.Check(function);
if (checker.has_supported_syntax()) {
return FullCodeGenerator::MakeCode(info);
}
} }
AssignedVariablesAnalyzer ava(function); AssignedVariablesAnalyzer ava(function);
...@@ -476,21 +470,10 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, ...@@ -476,21 +470,10 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
CompilationInfo info(literal, script, false); CompilationInfo info(literal, script, false);
bool is_run_once = literal->try_full_codegen(); bool is_run_once = literal->try_full_codegen();
bool is_compiled = false; bool use_full = FLAG_full_compiler && !literal->contains_loops();
if (AlwaysFullCompiler() || (use_full && is_run_once)) {
if (AlwaysFullCompiler()) {
code = FullCodeGenerator::MakeCode(&info); code = FullCodeGenerator::MakeCode(&info);
is_compiled = true; } else {
} else if (FLAG_full_compiler && is_run_once) {
FullCodeGenSyntaxChecker checker;
checker.Check(literal);
if (checker.has_supported_syntax()) {
code = FullCodeGenerator::MakeCode(&info);
is_compiled = true;
}
}
if (!is_compiled) {
// We fall back to the classic V8 code generator. // We fall back to the classic V8 code generator.
AssignedVariablesAnalyzer ava(literal); AssignedVariablesAnalyzer ava(literal);
if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null(); if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null();
......
This diff is collapsed.
...@@ -36,29 +36,6 @@ ...@@ -36,29 +36,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class FullCodeGenSyntaxChecker: public AstVisitor {
public:
FullCodeGenSyntaxChecker() : 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(FullCodeGenSyntaxChecker);
};
// AST node visitor which can tell whether a given statement will be breakable // AST node visitor which can tell whether a given statement will be breakable
// when the code is compiled by the full compiler in the debugger. This means // when the code is compiled by the full compiler in the debugger. This means
// that there will be an IC (load/store/call) in the code generated for the // that there will be an IC (load/store/call) in the code generated for the
......
...@@ -341,9 +341,7 @@ class Parser { ...@@ -341,9 +341,7 @@ class Parser {
template <typename T, int initial_size> template <typename T, int initial_size>
class BufferedZoneList { class BufferedZoneList {
public: public:
BufferedZoneList() : list_(NULL), last_(NULL) {}
BufferedZoneList() :
list_(NULL), last_(NULL) {}
// Adds element at end of list. This element is buffered and can // Adds element at end of list. This element is buffered and can
// be read using last() or removed using RemoveLast until a new Add or until // be read using last() or removed using RemoveLast until a new Add or until
...@@ -414,6 +412,7 @@ class BufferedZoneList { ...@@ -414,6 +412,7 @@ class BufferedZoneList {
T* last_; T* last_;
}; };
// Accumulates RegExp atoms and assertions into lists of terms and alternatives. // Accumulates RegExp atoms and assertions into lists of terms and alternatives.
class RegExpBuilder: public ZoneObject { class RegExpBuilder: public ZoneObject {
public: public:
...@@ -652,6 +651,7 @@ class RegExpParser { ...@@ -652,6 +651,7 @@ class RegExpParser {
static const int kMaxCaptures = 1 << 16; static const int kMaxCaptures = 1 << 16;
static const uc32 kEndMarker = (1 << 21); static const uc32 kEndMarker = (1 << 21);
private: private:
enum SubexpressionType { enum SubexpressionType {
INITIAL, INITIAL,
...@@ -747,6 +747,10 @@ class TemporaryScope BASE_EMBEDDED { ...@@ -747,6 +747,10 @@ class TemporaryScope BASE_EMBEDDED {
void AddProperty() { expected_property_count_++; } void AddProperty() { expected_property_count_++; }
int expected_property_count() { return expected_property_count_; } int expected_property_count() { return expected_property_count_; }
void AddLoop() { loop_count_++; }
bool ContainsLoops() const { return loop_count_ > 0; }
private: private:
// Captures the number of literals that need materialization in the // Captures the number of literals that need materialization in the
// function. Includes regexp literals, and boilerplate for object // function. Includes regexp literals, and boilerplate for object
...@@ -756,9 +760,14 @@ class TemporaryScope BASE_EMBEDDED { ...@@ -756,9 +760,14 @@ class TemporaryScope BASE_EMBEDDED {
// Properties count estimation. // Properties count estimation.
int expected_property_count_; int expected_property_count_;
// Keeps track of assignments to properties of this. Used for
// optimizing constructors.
bool only_simple_this_property_assignments_; bool only_simple_this_property_assignments_;
Handle<FixedArray> this_property_assignments_; Handle<FixedArray> this_property_assignments_;
// Captures the number of loops inside the scope.
int loop_count_;
// Bookkeeping // Bookkeeping
Parser* parser_; Parser* parser_;
TemporaryScope* parent_; TemporaryScope* parent_;
...@@ -772,6 +781,7 @@ TemporaryScope::TemporaryScope(Parser* parser) ...@@ -772,6 +781,7 @@ TemporaryScope::TemporaryScope(Parser* parser)
expected_property_count_(0), expected_property_count_(0),
only_simple_this_property_assignments_(false), only_simple_this_property_assignments_(false),
this_property_assignments_(Factory::empty_fixed_array()), this_property_assignments_(Factory::empty_fixed_array()),
loop_count_(0),
parser_(parser), parser_(parser),
parent_(parser->temp_scope_) { parent_(parser->temp_scope_) {
parser->temp_scope_ = this; parser->temp_scope_ = this;
...@@ -1282,7 +1292,8 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, ...@@ -1282,7 +1292,8 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
0, 0,
0, 0,
source->length(), source->length(),
false)); false,
temp_scope.ContainsLoops()));
} else if (scanner().stack_overflow()) { } else if (scanner().stack_overflow()) {
Top::StackOverflow(); Top::StackOverflow();
} }
...@@ -1382,7 +1393,8 @@ FunctionLiteral* Parser::ParseJson(Handle<String> source) { ...@@ -1382,7 +1393,8 @@ FunctionLiteral* Parser::ParseJson(Handle<String> source) {
0, 0,
0, 0,
source->length(), source->length(),
false)); false,
temp_scope.ContainsLoops()));
} else if (scanner().stack_overflow()) { } else if (scanner().stack_overflow()) {
Top::StackOverflow(); Top::StackOverflow();
} }
...@@ -2653,6 +2665,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels, ...@@ -2653,6 +2665,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
// DoStatement :: // DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';' // 'do' Statement 'while' '(' Expression ')' ';'
temp_scope_->AddLoop();
DoWhileStatement* loop = NEW(DoWhileStatement(labels)); DoWhileStatement* loop = NEW(DoWhileStatement(labels));
Target target(this, loop); Target target(this, loop);
...@@ -2685,6 +2698,7 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { ...@@ -2685,6 +2698,7 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
// WhileStatement :: // WhileStatement ::
// 'while' '(' Expression ')' Statement // 'while' '(' Expression ')' Statement
temp_scope_->AddLoop();
WhileStatement* loop = NEW(WhileStatement(labels)); WhileStatement* loop = NEW(WhileStatement(labels));
Target target(this, loop); Target target(this, loop);
...@@ -2704,6 +2718,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { ...@@ -2704,6 +2718,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
// ForStatement :: // ForStatement ::
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
temp_scope_->AddLoop();
Statement* init = NULL; Statement* init = NULL;
Expect(Token::FOR, CHECK_OK); Expect(Token::FOR, CHECK_OK);
...@@ -3955,7 +3970,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, ...@@ -3955,7 +3970,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
num_parameters, num_parameters,
start_pos, start_pos,
end_pos, end_pos,
function_name->length() > 0)); function_name->length() > 0,
temp_scope.ContainsLoops()));
if (!is_pre_parsing_) { if (!is_pre_parsing_) {
function_literal->set_function_token_position(function_token_position); function_literal->set_function_token_position(function_token_position);
} }
......
...@@ -216,25 +216,25 @@ namespace internal { ...@@ -216,25 +216,25 @@ namespace internal {
class CodeGeneratorPatcher { class CodeGeneratorPatcher {
public: public:
CodeGeneratorPatcher() { CodeGeneratorPatcher() {
CodeGenerator::InlineRuntimeLUT genGetFramePointer = CodeGenerator::InlineRuntimeLUT gen_get_frame_pointer =
{&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer", 0}; {&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer", 0};
// _RandomHeapNumber is just used as a dummy function that has zero // _RandomHeapNumber is just used as a dummy function that has zero
// arguments, the same as the _GetFramePointer function we actually patch // arguments, the same as the _GetFramePointer function we actually patch
// in. // in.
bool result = CodeGenerator::PatchInlineRuntimeEntry( bool result = CodeGenerator::PatchInlineRuntimeEntry(
NewString("_RandomHeapNumber"), NewString("_RandomHeapNumber"),
genGetFramePointer, &oldInlineEntry); gen_get_frame_pointer, &old_inline_entry);
CHECK(result); CHECK(result);
} }
~CodeGeneratorPatcher() { ~CodeGeneratorPatcher() {
CHECK(CodeGenerator::PatchInlineRuntimeEntry( CHECK(CodeGenerator::PatchInlineRuntimeEntry(
NewString("_GetFramePointer"), NewString("_GetFramePointer"),
oldInlineEntry, NULL)); old_inline_entry, NULL));
} }
private: private:
CodeGenerator::InlineRuntimeLUT oldInlineEntry; CodeGenerator::InlineRuntimeLUT old_inline_entry;
}; };
} } // namespace v8::internal } } // namespace v8::internal
...@@ -273,9 +273,10 @@ static void CreateTraceCallerFunction(const char* func_name, ...@@ -273,9 +273,10 @@ static void CreateTraceCallerFunction(const char* func_name,
// StackTracer uses Top::c_entry_fp as a starting point for stack // StackTracer uses Top::c_entry_fp as a starting point for stack
// walking. // walking.
TEST(CFromJSStackTrace) { TEST(CFromJSStackTrace) {
// TODO(711) The hack of replacing the inline runtime function // TODO(711): The hack of replacing the inline runtime function
// RandomHeapNumber with GetFrameNumber does not work with the way the full // RandomHeapNumber with GetFrameNumber does not work with the way
// compiler generates inline runtime calls. // the full compiler generates inline runtime calls.
i::FLAG_full_compiler = false;
i::FLAG_always_full_compiler = false; i::FLAG_always_full_compiler = false;
TickSample sample; TickSample sample;
...@@ -313,9 +314,10 @@ TEST(CFromJSStackTrace) { ...@@ -313,9 +314,10 @@ TEST(CFromJSStackTrace) {
// Top::c_entry_fp value. In this case, StackTracer uses passed frame // Top::c_entry_fp value. In this case, StackTracer uses passed frame
// pointer value as a starting point for stack walking. // pointer value as a starting point for stack walking.
TEST(PureJSStackTrace) { TEST(PureJSStackTrace) {
// TODO(711) The hack of replacing the inline runtime function // TODO(711): The hack of replacing the inline runtime function
// RandomHeapNumber with GetFrameNumber does not work with the way the full // RandomHeapNumber with GetFrameNumber does not work with the way
// compiler generates inline runtime calls. // the full compiler generates inline runtime calls.
i::FLAG_full_compiler = false;
i::FLAG_always_full_compiler = false; i::FLAG_always_full_compiler = false;
TickSample sample; TickSample sample;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment