Introduce a stack-allocated structure to encapsulate compile-time information.

Use it to hold the possible shared function info, the possible
receiver, and the compilation loop nesting depth.  Remove loop nesting
from FunctionLiteral AST nodes.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3744 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 048fe9b9
......@@ -142,7 +142,7 @@ CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
// r1: called JS function
// cp: callee's context
void CodeGenerator::GenCode(FunctionLiteral* fun) {
void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
// Record the position for debugging purposes.
CodeForFunctionPosition(fun);
......
......@@ -32,6 +32,7 @@ namespace v8 {
namespace internal {
// Forward declarations
class CompilationInfo;
class DeferredCode;
class RegisterAllocator;
class RegisterFile;
......@@ -153,7 +154,8 @@ class CodeGenerator: public AstVisitor {
// be called by compiler.cc.
static Handle<Code> MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval);
bool is_eval,
CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(FunctionLiteral* fun);
......@@ -239,7 +241,7 @@ class CodeGenerator: public AstVisitor {
inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void GenCode(FunctionLiteral* fun);
void GenCode(FunctionLiteral* fun, CompilationInfo* info);
// The following are used by class Reference.
void LoadReference(Reference* ref);
......
......@@ -1331,7 +1331,6 @@ class FunctionLiteral: public Expression {
start_position_(start_position),
end_position_(end_position),
is_expression_(is_expression),
loop_nesting_(0),
function_token_position_(RelocInfo::kNoPosition),
inferred_name_(Heap::empty_string()),
try_full_codegen_(false) {
......@@ -1366,9 +1365,6 @@ class FunctionLiteral: public Expression {
bool AllowsLazyCompilation();
bool loop_nesting() const { return loop_nesting_; }
void set_loop_nesting(int nesting) { loop_nesting_ = nesting; }
Handle<String> inferred_name() const { return inferred_name_; }
void set_inferred_name(Handle<String> inferred_name) {
inferred_name_ = inferred_name;
......@@ -1396,7 +1392,6 @@ class FunctionLiteral: public Expression {
int start_position_;
int end_position_;
bool is_expression_;
int loop_nesting_;
int function_token_position_;
Handle<String> inferred_name_;
bool try_full_codegen_;
......
......@@ -216,7 +216,8 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(FunctionLiteral* fun,
// the compiler.cc code.
Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval) {
bool is_eval,
CompilationInfo* info) {
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length();
Counters::total_old_codegen_source_size.Increment(len);
......@@ -226,7 +227,7 @@ Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
const int kInitialBufferSize = 4 * KB;
CodeGenerator cgen(kInitialBufferSize, script, is_eval);
CodeGeneratorScope scope(&cgen);
cgen.GenCode(fun);
cgen.GenCode(fun, info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
......
......@@ -48,8 +48,7 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
Handle<Script> script,
Handle<Context> context,
bool is_eval,
Handle<SharedFunctionInfo> shared,
Handle<Object> receiver) {
CompilationInfo* info) {
ASSERT(literal != NULL);
// Rewrite the AST by introducing .result assignments where needed.
......@@ -98,6 +97,7 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
// incompatible.
CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
Handle<SharedFunctionInfo> shared = info->shared_info();
bool is_run_once = (shared.is_null())
? literal->scope()->is_global_scope()
: (shared->is_toplevel() || shared->try_full_codegen());
......@@ -110,8 +110,8 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
}
} else if (FLAG_always_fast_compiler ||
(FLAG_fast_compiler && !is_run_once)) {
FastCodeGenSyntaxChecker checker(receiver);
checker.Check(literal);
FastCodeGenSyntaxChecker checker;
checker.Check(literal, info);
if (checker.has_supported_syntax()) {
AstLabeler labeler;
labeler.Label(literal);
......@@ -119,7 +119,7 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
// Does not yet generate code.
}
return CodeGenerator::MakeCode(literal, script, is_eval);
return CodeGenerator::MakeCode(literal, script, is_eval, info);
}
......@@ -204,12 +204,10 @@ static Handle<JSFunction> MakeFunction(bool is_global,
HistogramTimerScope timer(rate);
// Compile the code.
Handle<Code> code = MakeCode(lit,
script,
context,
is_eval,
Handle<SharedFunctionInfo>::null(),
Handle<Object>::null()); // No receiver.
CompilationInfo info(Handle<SharedFunctionInfo>::null(),
Handle<Object>::null(), // No receiver.
0); // Not nested in a loop.
Handle<Code> code = MakeCode(lit, script, context, is_eval, &info);
// Check for stack-overflow exceptions.
if (code.is_null()) {
......@@ -370,9 +368,7 @@ Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
}
bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
Handle<Object> receiver,
int loop_nesting) {
bool Compiler::CompileLazy(CompilationInfo* info) {
CompilationZoneScope zone_scope(DELETE_ON_EXIT);
// The VM is in the COMPILER state until exiting this function.
......@@ -381,6 +377,7 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
PostponeInterruptsScope postpone;
// Compute name, source code and script data.
Handle<SharedFunctionInfo> shared = info->shared_info();
Handle<String> name(String::cast(shared->name()));
Handle<Script> script(Script::cast(shared->script()));
......@@ -402,9 +399,6 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
return false;
}
// Update the loop nesting in the function literal.
lit->set_loop_nesting(loop_nesting);
// Measure how long it takes to do the lazy compilation; only take
// the rest of the function into account to avoid overlap with the
// lazy parsing statistics.
......@@ -415,8 +409,7 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
script,
Handle<Context>::null(),
false,
shared,
receiver);
info);
// Check for stack-overflow exception.
if (code.is_null()) {
......@@ -497,6 +490,10 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
// 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.
CompilationInfo info(Handle<SharedFunctionInfo>::null(),
Handle<Object>::null(), // No receiver.
0); // Not nested in a loop.
CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
bool is_run_once = literal->try_full_codegen();
bool is_compiled = false;
......@@ -513,8 +510,8 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
(FLAG_fast_compiler && !is_run_once)) {
// Since we are not lazily compiling we do not have a receiver to
// specialize for.
FastCodeGenSyntaxChecker checker(Handle<Object>::null());
checker.Check(literal);
FastCodeGenSyntaxChecker checker;
checker.Check(literal, &info);
if (checker.has_supported_syntax()) {
AstLabeler label_nodes;
label_nodes.Label(literal);
......@@ -526,7 +523,8 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
// We fall back to the classic V8 code generator.
code = CodeGenerator::MakeCode(literal,
script,
false); // Not eval.
false, // Not eval.
&info);
}
// Check for stack-overflow exception.
......
......@@ -35,6 +35,31 @@
namespace v8 {
namespace internal {
// CompilationInfo encapsulates some information known at compile time.
class CompilationInfo BASE_EMBEDDED {
public:
CompilationInfo(Handle<SharedFunctionInfo> shared_info,
Handle<Object> receiver,
int loop_nesting)
: shared_info_(shared_info),
receiver_(receiver_),
loop_nesting_(loop_nesting) {
}
Handle<SharedFunctionInfo> shared_info() { return shared_info_; }
bool has_receiver() { return !receiver_.is_null(); }
Handle<Object> receiver() { return receiver_; }
int loop_nesting() { return loop_nesting_; }
private:
Handle<SharedFunctionInfo> shared_info_;
Handle<Object> receiver_;
int loop_nesting_;
};
// The V8 compiler
//
// General strategy: Source code is translated into an anonymous function w/o
......@@ -70,9 +95,7 @@ class Compiler : public AllStatic {
// Compile from function info (used for lazy compilation). Returns
// true on success and false if the compilation resulted in a stack
// overflow.
static bool CompileLazy(Handle<SharedFunctionInfo> shared,
Handle<Object> receiver,
int loop_nesting);
static bool CompileLazy(CompilationInfo* info);
// Compile a function boilerplate object (the function is possibly
// lazily compiled). Called recursively from a backend code
......
......@@ -49,9 +49,10 @@ namespace internal {
} while (false)
void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun) {
void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun,
CompilationInfo* info) {
// We do not specialize if we do not have a receiver.
if (receiver().is_null()) BAILOUT("No receiver");
if (!info->has_receiver()) BAILOUT("No receiver");
// We do not support stack or heap slots (both of which require
// allocation).
......@@ -253,10 +254,11 @@ void FastCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
// 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.holder() != *receiver()) BAILOUT("Non-own property assignment");
receiver->Lookup(*name, &lookup);
if (lookup.holder() != *receiver) BAILOUT("Non-own property assignment");
if (!lookup.type() == FIELD) BAILOUT("Non-field property assignment");
} else {
UNREACHABLE();
......
......@@ -31,19 +31,20 @@
#include "v8.h"
#include "ast.h"
#include "compiler.h"
namespace v8 {
namespace internal {
class FastCodeGenSyntaxChecker: public AstVisitor {
public:
explicit FastCodeGenSyntaxChecker(Handle<Object> receiver)
: receiver_(receiver), has_supported_syntax_(true) {
explicit FastCodeGenSyntaxChecker()
: info_(NULL), has_supported_syntax_(true) {
}
void Check(FunctionLiteral* fun);
void Check(FunctionLiteral* fun, CompilationInfo* info);
Handle<Object> receiver() { return receiver_; }
CompilationInfo* info() { return info_; }
bool has_supported_syntax() { return has_supported_syntax_; }
private:
......@@ -55,7 +56,7 @@ class FastCodeGenSyntaxChecker: public AstVisitor {
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
Handle<Object> receiver_;
CompilationInfo* info_;
bool has_supported_syntax_;
DISALLOW_COPY_AND_ASSIGN(FastCodeGenSyntaxChecker);
......
......@@ -31,6 +31,7 @@
#include "api.h"
#include "arguments.h"
#include "bootstrapper.h"
#include "codegen.h"
#include "compiler.h"
#include "debug.h"
#include "execution.h"
......@@ -672,13 +673,11 @@ bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
}
static bool CompileLazyHelper(Handle<SharedFunctionInfo> shared,
Handle<Object> receiver,
ClearExceptionFlag flag,
int loop_nesting) {
static bool CompileLazyHelper(CompilationInfo* info,
ClearExceptionFlag flag) {
// Compile the source information to a code object.
ASSERT(!shared->is_compiled());
bool result = Compiler::CompileLazy(shared, receiver, loop_nesting);
ASSERT(!info->shared_info()->is_compiled());
bool result = Compiler::CompileLazy(info);
ASSERT(result != Top::has_pending_exception());
if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
return result;
......@@ -687,16 +686,17 @@ static bool CompileLazyHelper(Handle<SharedFunctionInfo> shared,
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) {
return CompileLazyHelper(shared, Handle<Object>::null(), flag, 0);
CompilationInfo info(shared, Handle<Object>::null(), 0);
return CompileLazyHelper(&info, flag);
}
bool CompileLazy(Handle<JSFunction> function,
Handle<Object> receiver,
ClearExceptionFlag flag) {
// Compile the source information to a code object.
Handle<SharedFunctionInfo> shared(function->shared());
bool result = CompileLazyHelper(shared, receiver, flag, 0);
CompilationInfo info(shared, receiver, 0);
bool result = CompileLazyHelper(&info, flag);
LOG(FunctionCreateEvent(*function));
return result;
}
......@@ -705,9 +705,9 @@ bool CompileLazy(Handle<JSFunction> function,
bool CompileLazyInLoop(Handle<JSFunction> function,
Handle<Object> receiver,
ClearExceptionFlag flag) {
// Compile the source information to a code object.
Handle<SharedFunctionInfo> shared(function->shared());
bool result = CompileLazyHelper(shared, receiver, flag, 1);
CompilationInfo info(shared, receiver, 1);
bool result = CompileLazyHelper(&info, flag);
LOG(FunctionCreateEvent(*function));
return result;
}
......
......@@ -126,7 +126,7 @@ CodeGenerator::CodeGenerator(int buffer_size,
// edi: called JS function
// esi: callee's context
void CodeGenerator::GenCode(FunctionLiteral* fun) {
void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
// Record the position for debugging purposes.
CodeForFunctionPosition(fun);
......@@ -143,7 +143,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
set_in_spilled_code(false);
// Adjust for function-level loop nesting.
loop_nesting_ += fun->loop_nesting();
loop_nesting_ += info->loop_nesting();
JumpTarget::set_compiling_deferred_code(false);
......@@ -321,7 +321,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
}
// Adjust for function-level loop nesting.
loop_nesting_ -= fun->loop_nesting();
loop_nesting_ -= info->loop_nesting();
// Code generation state must be reset.
ASSERT(state_ == NULL);
......
......@@ -32,6 +32,7 @@ namespace v8 {
namespace internal {
// Forward declarations
class CompilationInfo;
class DeferredCode;
class RegisterAllocator;
class RegisterFile;
......@@ -297,7 +298,8 @@ class CodeGenerator: public AstVisitor {
// be called by compiler.cc.
static Handle<Code> MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval);
bool is_eval,
CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(FunctionLiteral* fun);
......@@ -378,7 +380,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void GenCode(FunctionLiteral* fun);
void GenCode(FunctionLiteral* fun, CompilationInfo* info);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
......
......@@ -278,7 +278,7 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
}
void CodeGenerator::GenCode(FunctionLiteral* function) {
void CodeGenerator::GenCode(FunctionLiteral* function, CompilationInfo* info) {
// Record the position for debugging purposes.
CodeForFunctionPosition(function);
ZoneList<Statement*>* body = function->body();
......@@ -294,7 +294,7 @@ void CodeGenerator::GenCode(FunctionLiteral* function) {
set_in_spilled_code(false);
// Adjust for function-level loop nesting.
loop_nesting_ += function->loop_nesting();
loop_nesting_ += info->loop_nesting();
JumpTarget::set_compiling_deferred_code(false);
......@@ -472,7 +472,7 @@ void CodeGenerator::GenCode(FunctionLiteral* function) {
}
// Adjust for function-level loop nesting.
loop_nesting_ -= function->loop_nesting();
loop_nesting_ -= info->loop_nesting();
// Code generation state must be reset.
ASSERT(state_ == NULL);
......
......@@ -32,6 +32,7 @@ namespace v8 {
namespace internal {
// Forward declarations
class CompilationInfo;
class DeferredCode;
class RegisterAllocator;
class RegisterFile;
......@@ -297,7 +298,8 @@ class CodeGenerator: public AstVisitor {
// be called by compiler.cc.
static Handle<Code> MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval);
bool is_eval,
CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(FunctionLiteral* fun);
......@@ -380,7 +382,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void GenCode(FunctionLiteral* fun);
void GenCode(FunctionLiteral* fun, CompilationInfo* info);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
......
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