// 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);
namespace internal {
// Forward declarations
+class CompilationInfo;
class DeferredCode;
class RegisterAllocator;
class RegisterFile;
// 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);
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);
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) {
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;
int start_position_;
int end_position_;
bool is_expression_;
- int loop_nesting_;
int function_token_position_;
Handle<String> inferred_name_;
bool try_full_codegen_;
// 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);
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();
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.
// 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());
}
} 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);
// Does not yet generate code.
}
- return CodeGenerator::MakeCode(literal, script, is_eval);
+ return CodeGenerator::MakeCode(literal, script, is_eval, info);
}
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()) {
}
-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.
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()));
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.
script,
Handle<Context>::null(),
false,
- shared,
- receiver);
+ info);
// Check for stack-overflow exception.
if (code.is_null()) {
// 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;
(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);
// 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.
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
// 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
} 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).
// 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();
#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:
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
- Handle<Object> receiver_;
+ CompilationInfo* info_;
bool has_supported_syntax_;
DISALLOW_COPY_AND_ASSIGN(FastCodeGenSyntaxChecker);
#include "api.h"
#include "arguments.h"
#include "bootstrapper.h"
+#include "codegen.h"
#include "compiler.h"
#include "debug.h"
#include "execution.h"
}
-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;
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;
}
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;
}
// 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);
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);
}
// 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);
namespace internal {
// Forward declarations
+class CompilationInfo;
class DeferredCode;
class RegisterAllocator;
class RegisterFile;
// 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);
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
}
-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();
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);
}
// 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);
namespace internal {
// Forward declarations
+class CompilationInfo;
class DeferredCode;
class RegisterAllocator;
class RegisterFile;
// 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);
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