// -------------------------------------------------------------------------
// CodeGenerator implementation
-CodeGenerator::CodeGenerator(MacroAssembler* masm,
- Handle<Script> script,
- bool is_eval)
- : is_eval_(is_eval),
- script_(script),
- deferred_(8),
+CodeGenerator::CodeGenerator(MacroAssembler* masm)
+ : deferred_(8),
masm_(masm),
- scope_(NULL),
+ info_(NULL),
frame_(NULL),
allocator_(NULL),
cc_reg_(al),
}
+Scope* CodeGenerator::scope() { return info_->function()->scope(); }
+
+
// Calling conventions:
// fp: caller's frame pointer
// sp: stack pointer
// r1: called JS function
// cp: callee's context
-void CodeGenerator::Generate(FunctionLiteral* fun,
- Mode mode,
- CompilationInfo* info) {
+void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// Record the position for debugging purposes.
- CodeForFunctionPosition(fun);
-
- ZoneList<Statement*>* body = fun->body();
+ CodeForFunctionPosition(info->function());
// Initialize state.
- ASSERT(scope_ == NULL);
- scope_ = fun->scope();
+ info_ = info;
ASSERT(allocator_ == NULL);
RegisterAllocator register_allocator(this);
allocator_ = ®ister_allocator;
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
- fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ stop("stop-at");
}
frame_->AllocateStackSlots();
VirtualFrame::SpilledScope spilled_scope;
- int heap_slots = scope_->num_heap_slots();
+ int heap_slots = scope()->num_heap_slots();
if (heap_slots > 0) {
// Allocate local context.
// Get outer context and create a new context based on it.
// 3) don't copy parameter operand code from SlotOperand!
{
Comment cmnt2(masm_, "[ copy context parameters into .context");
-
// Note that iteration order is relevant here! If we have the same
// parameter twice (e.g., function (x, y, x)), and that parameter
// needs to be copied into the context, it must be the last argument
// order: such a parameter is copied repeatedly into the same
// context location and thus the last value is what is seen inside
// the function.
- for (int i = 0; i < scope_->num_parameters(); i++) {
- Variable* par = scope_->parameter(i);
+ for (int i = 0; i < scope()->num_parameters(); i++) {
+ Variable* par = scope()->parameter(i);
Slot* slot = par->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
- // No parameters in global scope.
- ASSERT(!scope_->is_global_scope());
+ ASSERT(!scope()->is_global_scope()); // no parameters in global scope
__ ldr(r1, frame_->ParameterAt(i));
// Loads r2 with context; used below in RecordWrite.
__ str(r1, SlotOperand(slot, r2));
// Store the arguments object. This must happen after context
// initialization because the arguments object may be stored in the
// context.
- if (scope_->arguments() != NULL) {
+ if (scope()->arguments() != NULL) {
Comment cmnt(masm_, "[ allocate arguments object");
- ASSERT(scope_->arguments_shadow() != NULL);
- Variable* arguments = scope_->arguments()->var();
- Variable* shadow = scope_->arguments_shadow()->var();
+ ASSERT(scope()->arguments_shadow() != NULL);
+ Variable* arguments = scope()->arguments()->var();
+ Variable* shadow = scope()->arguments_shadow()->var();
ASSERT(arguments != NULL && arguments->slot() != NULL);
ASSERT(shadow != NULL && shadow->slot() != NULL);
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
__ ldr(r2, frame_->Function());
// The receiver is below the arguments, the return address, and the
// frame pointer on the stack.
- const int kReceiverDisplacement = 2 + scope_->num_parameters();
+ const int kReceiverDisplacement = 2 + scope()->num_parameters();
__ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize));
- __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
+ __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
frame_->Adjust(3);
__ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit());
frame_->CallStub(&stub, 3);
}
// Initialize ThisFunction reference if present.
- if (scope_->is_function_scope() && scope_->function() != NULL) {
+ if (scope()->is_function_scope() && scope()->function() != NULL) {
__ mov(ip, Operand(Factory::the_hole_value()));
frame_->EmitPush(ip);
- StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT);
+ StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT);
}
} else {
// When used as the secondary compiler for splitting, r1, cp,
// Generate code to 'execute' declarations and initialize functions
// (source elements). In case of an illegal redeclaration we need to
// handle that instead of processing the declarations.
- if (scope_->HasIllegalRedeclaration()) {
+ if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ illegal redeclarations");
- scope_->VisitIllegalRedeclaration(this);
+ scope()->VisitIllegalRedeclaration(this);
} else {
Comment cmnt(masm_, "[ declarations");
- ProcessDeclarations(scope_->declarations());
+ ProcessDeclarations(scope()->declarations());
// Bail out if a stack-overflow exception occurred when processing
// declarations.
if (HasStackOverflow()) return;
// Compile the body of the function in a vanilla state. Don't
// bother compiling all the code if the scope has an illegal
// redeclaration.
- if (!scope_->HasIllegalRedeclaration()) {
+ if (!scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ function body");
#ifdef DEBUG
bool is_builtin = Bootstrapper::IsActive();
// Ignore the return value.
}
#endif
- VisitStatementsAndSpill(body);
+ VisitStatementsAndSpill(info->function()->body());
}
}
// Generate the return sequence if necessary.
if (has_valid_frame() || function_return_.is_linked()) {
if (!function_return_.is_linked()) {
- CodeForReturnPosition(fun);
+ CodeForReturnPosition(info->function());
}
// exit
// r0: result
// Calculate the exact length of the return sequence and make sure that
// the constant pool is not emitted inside of the return sequence.
- int32_t sp_delta = (scope_->num_parameters() + 1) * kPointerSize;
+ int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
int return_sequence_length = Assembler::kJSReturnSequenceLength;
if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) {
// Additional mov instruction generated.
}
allocator_ = NULL;
- scope_ = NULL;
}
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
- Compiler::BuildBoilerplate(node, script_, this);
+ Compiler::BuildBoilerplate(node, script(), this);
// Check for stack-overflow exception.
if (HasStackOverflow()) {
ASSERT(frame_->height() == original_height);
// Seed the result with the formal parameters count, which will be used
// in case no arguments adaptor frame is found below the current frame.
- __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
+ __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
// Load the key into r1 and the formal parameters count into r0.
LoadAndSpill(args->at(0));
frame_->EmitPop(r1);
- __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
+ __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
// Call the shared stub to get to arguments[key].
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
- static Handle<Code> MakeCode(FunctionLiteral* fun,
- Handle<Script> script,
- bool is_eval,
- CompilationInfo* info);
+ static Handle<Code> MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
- static void MakeCodePrologue(FunctionLiteral* fun);
+ static void MakeCodePrologue(CompilationInfo* info);
// Allocate and install the code.
- static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
- MacroAssembler* masm,
+ static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
Code::Flags flags,
- Handle<Script> script);
+ CompilationInfo* info);
#ifdef ENABLE_LOGGING_AND_PROFILING
static bool ShouldGenerateLog(Expression* type);
// Accessors
MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
- Handle<Script> script() { return script_; }
+ inline Handle<Script> script();
bool has_valid_frame() const { return frame_ != NULL; }
private:
// Construction/Destruction
- CodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval);
+ CodeGenerator(MacroAssembler* masm);
// Accessors
- Scope* scope() const { return scope_; }
+ inline bool is_eval();
+ Scope* scope();
// Generating deferred code.
void ProcessDeferred();
- bool is_eval() { return is_eval_; }
-
// State
bool has_cc() const { return cc_reg_ != al; }
JumpTarget* true_target() const { return state_->true_target(); }
inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
- void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
+ void Generate(CompilationInfo* info, Mode mode);
// The following are used by class Reference.
void LoadReference(Reference* ref);
bool HasValidEntryRegisters();
#endif
- bool is_eval_; // Tells whether code is generated for eval.
-
- Handle<Script> script_;
List<DeferredCode*> deferred_;
// Assembler
MacroAssembler* masm_; // to generate code
+ CompilationInfo* info_;
+
// Code generation state
- Scope* scope_;
VirtualFrame* frame_;
RegisterAllocator* allocator_;
Condition cc_reg_;
void FastCodeGenerator::EmitLoadReceiver(Register reg) {
// Offset 2 is due to return address and saved frame pointer.
- int index = 2 + function()->scope()->num_parameters();
+ int index = 2 + scope()->num_parameters();
__ ldr(reg, MemOperand(sp, index * kPointerSize));
}
}
-void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
- ASSERT(function_ == NULL);
+void FastCodeGenerator::Generate(CompilationInfo* info) {
ASSERT(info_ == NULL);
- function_ = fun;
info_ = info;
// Save the caller's frame pointer and set up our own.
// Receiver (this) is allocated to r1 if there are this properties.
if (has_this_properties()) EmitReceiverMapCheck();
- VisitStatements(fun->body());
+ VisitStatements(function()->body());
Comment return_cmnt(masm(), ";; Return(<undefined>)");
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
Comment epilogue_cmnt(masm(), ";; Epilogue");
__ mov(sp, fp);
__ ldm(ia_w, sp, fp.bit() | lr.bit());
- int32_t sp_delta = (fun->scope()->num_parameters() + 1) * kPointerSize;
+ int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
__ add(sp, sp, Operand(sp_delta));
__ Jump(lr);
//
// The function builds a JS frame. Please see JavaScriptFrameConstants in
// frames-arm.h for its layout.
-void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
- function_ = fun;
- SetFunctionPosition(fun);
+void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
+ ASSERT(info_ == NULL);
+ info_ = info;
+ SetFunctionPosition(function());
if (mode == PRIMARY) {
- int locals_count = fun->scope()->num_stack_slots();
+ int locals_count = scope()->num_stack_slots();
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
if (locals_count > 0) {
bool function_in_register = true;
// Possibly allocate a local context.
- if (fun->scope()->num_heap_slots() > 0) {
+ if (scope()->num_heap_slots() > 0) {
Comment cmnt(masm_, "[ Allocate local context");
// Argument to NewContext is the function, which is in r1.
__ push(r1);
// passed to us. It's saved in the stack and kept live in cp.
__ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Copy any necessary parameters into the context.
- int num_parameters = fun->scope()->num_parameters();
+ int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = fun->scope()->parameter(i)->slot();
+ Slot* slot = scope()->parameter(i)->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
}
}
- Variable* arguments = fun->scope()->arguments()->AsVariable();
+ Variable* arguments = scope()->arguments()->AsVariable();
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
__ mov(r3, r1);
}
// Receiver is just before the parameters on the caller's stack.
- __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset +
- fun->num_parameters() * kPointerSize));
- __ mov(r1, Operand(Smi::FromInt(fun->num_parameters())));
+ int offset = scope()->num_parameters() * kPointerSize;
+ __ add(r2, fp,
+ Operand(StandardFrameConstants::kCallerSPOffset + offset));
+ __ mov(r1, Operand(Smi::FromInt(scope()->num_parameters())));
__ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit());
// Arguments to ArgumentsAccessStub:
__ mov(r3, r0);
Move(arguments->slot(), r0, r1, r2);
Slot* dot_arguments_slot =
- fun->scope()->arguments_shadow()->AsVariable()->slot();
+ scope()->arguments_shadow()->AsVariable()->slot();
Move(dot_arguments_slot, r3, r1, r2);
}
}
}
{ Comment cmnt(masm_, "[ Declarations");
- VisitDeclarations(fun->scope()->declarations());
+ VisitDeclarations(scope()->declarations());
}
if (FLAG_trace) {
{ Comment cmnt(masm_, "[ Body");
ASSERT(loop_depth() == 0);
- VisitStatements(fun->body());
+ VisitStatements(function()->body());
ASSERT(loop_depth() == 0);
}
// body.
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
}
- EmitReturnSequence(function_->end_position());
+ EmitReturnSequence(function()->end_position());
}
// Calculate the exact length of the return sequence and make sure that
// the constant pool is not emitted inside of the return sequence.
- int num_parameters = function_->scope()->num_parameters();
+ int num_parameters = scope()->num_parameters();
int32_t sp_delta = (num_parameters + 1) * kPointerSize;
int return_sequence_length = Assembler::kJSReturnSequenceLength;
if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) {
return MemOperand(fp, SlotOffset(slot));
case Slot::CONTEXT: {
int context_chain_length =
- function_->scope()->ContextChainLength(slot->var()->scope());
+ scope()->ContextChainLength(slot->var()->scope());
__ LoadContext(scratch, context_chain_length);
return CodeGenerator::ContextOperand(scratch, slot->index());
}
// this specific context.
// The variable in the decl always resides in the current context.
- ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
+ ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ ldr(r1,
// Call the runtime to declare the globals.
// The context is the first argument.
__ mov(r1, Operand(pairs));
- __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0)));
+ __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
__ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit());
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
- Compiler::BuildBoilerplate(expr, script_, this);
+ Compiler::BuildBoilerplate(expr, script(), this);
if (HasStackOverflow()) return;
ASSERT(boilerplate->IsBoilerplate());
#define V8_CODEGEN_INL_H_
#include "codegen.h"
+#include "compiler.h"
#include "register-allocator-inl.h"
#if V8_TARGET_ARCH_IA32
#define __ ACCESS_MASM(masm_)
+Handle<Script> CodeGenerator::script() { return info_->script(); }
+bool CodeGenerator::is_eval() { return info_->is_eval(); }
+
+
// -----------------------------------------------------------------------------
// Support for "structured" code comments.
//
}
-void CodeGenerator::MakeCodePrologue(FunctionLiteral* fun) {
+void CodeGenerator::MakeCodePrologue(CompilationInfo* info) {
#ifdef DEBUG
bool print_source = false;
bool print_ast = false;
if (FLAG_trace_codegen || print_source || print_ast) {
PrintF("*** Generate code for %s function: ", ftype);
- fun->name()->ShortPrint();
+ info->function()->name()->ShortPrint();
PrintF(" ***\n");
}
if (print_source) {
- PrintF("--- Source from AST ---\n%s\n", PrettyPrinter().PrintProgram(fun));
+ PrintF("--- Source from AST ---\n%s\n",
+ PrettyPrinter().PrintProgram(info->function()));
}
if (print_ast) {
- PrintF("--- AST ---\n%s\n", AstPrinter().PrintProgram(fun));
+ PrintF("--- AST ---\n%s\n",
+ AstPrinter().PrintProgram(info->function()));
}
if (print_json_ast) {
JsonAstBuilder builder;
- PrintF("%s", builder.BuildProgram(fun));
+ PrintF("%s", builder.BuildProgram(info->function()));
}
#endif // DEBUG
}
-Handle<Code> CodeGenerator::MakeCodeEpilogue(FunctionLiteral* fun,
- MacroAssembler* masm,
+Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
Code::Flags flags,
- Handle<Script> script) {
+ CompilationInfo* info) {
// Allocate and install the code.
CodeDesc desc;
masm->GetCode(&desc);
- ZoneScopeInfo sinfo(fun->scope());
+ ZoneScopeInfo sinfo(info->scope());
Handle<Code> code =
Factory::NewCode(desc, &sinfo, flags, masm->CodeObject());
: FLAG_print_code;
if (print_code) {
// Print the source code if available.
+ Handle<Script> script = info->script();
+ FunctionLiteral* function = info->function();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
PrintF("--- Raw source ---\n");
StringInputBuffer stream(String::cast(script->source()));
- stream.Seek(fun->start_position());
+ stream.Seek(function->start_position());
// fun->end_position() points to the last character in the stream. We
// need to compensate by adding one to calculate the length.
- int source_len = fun->end_position() - fun->start_position() + 1;
+ int source_len =
+ function->end_position() - function->start_position() + 1;
for (int i = 0; i < source_len; i++) {
if (stream.has_more()) PrintF("%c", stream.GetNext());
}
PrintF("\n\n");
}
PrintF("--- Code ---\n");
- code->Disassemble(*fun->name()->ToCString());
+ code->Disassemble(*function->name()->ToCString());
}
#endif // ENABLE_DISASSEMBLER
// Generate the code. Takes a function literal, generates code for it, assemble
// all the pieces into a Code object. This function is only to be called by
// the compiler.cc code.
-Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
- Handle<Script> script,
- bool is_eval,
- CompilationInfo* info) {
+Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
+ Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length();
Counters::total_old_codegen_source_size.Increment(len);
}
- MakeCodePrologue(fun);
+ MakeCodePrologue(info);
// Generate code.
const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize);
- CodeGenerator cgen(&masm, script, is_eval);
+ CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen);
- cgen.Generate(fun, PRIMARY, info);
+ cgen.Generate(info, PRIMARY);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
- return MakeCodeEpilogue(fun, cgen.masm(), flags, script);
+ return MakeCodeEpilogue(cgen.masm(), flags, info);
}
namespace internal {
-static Handle<Code> MakeCode(FunctionLiteral* literal,
- Handle<Script> script,
- Handle<Context> context,
- bool is_eval,
- CompilationInfo* info) {
- ASSERT(literal != NULL);
-
+static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
+ FunctionLiteral* function = info->function();
+ ASSERT(function != NULL);
// Rewrite the AST by introducing .result assignments where needed.
- if (!Rewriter::Process(literal) || !AnalyzeVariableUsage(literal)) {
+ if (!Rewriter::Process(function) || !AnalyzeVariableUsage(function)) {
// Signal a stack overflow by returning a null handle. The stack
// overflow exception will be thrown by the caller.
return Handle<Code>::null();
// the top scope only contains the single lazily compiled function,
// so this doesn't re-allocate variables repeatedly.
HistogramTimerScope timer(&Counters::variable_allocation);
- Scope* top = literal->scope();
+ Scope* top = info->scope();
while (top->outer_scope() != NULL) top = top->outer_scope();
top->AllocateVariables(context);
}
if (Bootstrapper::IsActive() ?
FLAG_print_builtin_scopes :
FLAG_print_scopes) {
- literal->scope()->Print();
+ info->scope()->Print();
}
#endif
// Optimize the AST.
- if (!Rewriter::Optimize(literal)) {
+ if (!Rewriter::Optimize(function)) {
// Signal a stack overflow by returning a null handle. The stack
// overflow exception will be thrown by the caller.
return Handle<Code>::null();
Handle<SharedFunctionInfo> shared = info->shared_info();
bool is_run_once = (shared.is_null())
- ? literal->scope()->is_global_scope()
+ ? info->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);
+ checker.Check(function);
if (checker.has_supported_syntax()) {
- return FullCodeGenerator::MakeCode(literal, script, is_eval);
+ return FullCodeGenerator::MakeCode(info);
}
} else if (FLAG_always_fast_compiler ||
(FLAG_fast_compiler && !is_run_once)) {
FastCodeGenSyntaxChecker checker;
- checker.Check(literal, info);
+ checker.Check(info);
if (checker.has_supported_syntax()) {
- return FastCodeGenerator::MakeCode(literal, script, is_eval, info);
+ return FastCodeGenerator::MakeCode(info);
}
}
- return CodeGenerator::MakeCode(literal, script, is_eval, info);
+ return CodeGenerator::MakeCode(info);
}
HistogramTimerScope timer(rate);
// Compile the code.
- 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);
+ CompilationInfo info(lit, script, is_eval);
+ Handle<Code> code = MakeCode(context, &info);
// Check for stack-overflow exceptions.
if (code.is_null()) {
// 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()));
int start_position = shared->start_position();
int end_position = shared->end_position();
// Generate the AST for the lazily compiled function. The AST may be
// NULL in case of parser stack overflow.
- FunctionLiteral* lit = MakeLazyAST(script, name,
+ FunctionLiteral* lit = MakeLazyAST(info->script(),
+ name,
start_position,
end_position,
is_expression);
ASSERT(Top::has_pending_exception());
return false;
}
+ info->set_function(lit);
// Measure how long it takes to do the lazy compilation; only take
// the rest of the function into account to avoid overlap with the
HistogramTimerScope timer(&Counters::compile_lazy);
// Compile the code.
- Handle<Code> code = MakeCode(lit,
- script,
- Handle<Context>::null(),
- false,
- info);
+ Handle<Code> code = MakeCode(Handle<Context>::null(), info);
// Check for stack-overflow exception.
if (code.is_null()) {
if (Logger::is_logging() || OProfileAgent::is_enabled()) {
Handle<String> func_name(name->length() > 0 ?
*name : shared->inferred_name());
+ Handle<Script> script = info->script();
if (script->name()->IsString()) {
int line_num = GetScriptLineNumber(script, start_position) + 1;
LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG, *code, *func_name,
// 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.
+ CompilationInfo info(literal, script, false);
CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
bool is_run_once = literal->try_full_codegen();
FullCodeGenSyntaxChecker checker;
checker.Check(literal);
if (checker.has_supported_syntax()) {
- code = FullCodeGenerator::MakeCode(literal,
- script,
- false); // Not eval.
+ code = FullCodeGenerator::MakeCode(&info);
is_compiled = true;
}
} else if (FLAG_always_fast_compiler ||
// Since we are not lazily compiling we do not have a receiver to
// specialize for.
FastCodeGenSyntaxChecker checker;
- checker.Check(literal, &info);
+ checker.Check(&info);
if (checker.has_supported_syntax()) {
- code = FastCodeGenerator::MakeCode(literal, script, false, &info);
+ code = FastCodeGenerator::MakeCode(&info);
is_compiled = true;
}
}
if (!is_compiled) {
// We fall back to the classic V8 code generator.
- code = CodeGenerator::MakeCode(literal,
- script,
- false, // Not eval.
- &info);
+ code = CodeGenerator::MakeCode(&info);
}
// Check for stack-overflow exception.
namespace v8 {
namespace internal {
-// CompilationInfo encapsulates some information known at compile time.
+// CompilationInfo encapsulates some information known at compile time. It
+// is constructed based on the resources available 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),
+ // Lazy compilation of a JSFunction.
+ CompilationInfo(Handle<JSFunction> closure,
+ int loop_nesting,
+ Handle<Object> receiver)
+ : closure_(closure),
+ function_(NULL),
+ is_eval_(false),
loop_nesting_(loop_nesting),
- has_this_properties_(false),
- has_globals_(false) {
+ receiver_(receiver) {
+ Initialize();
+ ASSERT(!closure_.is_null() &&
+ shared_info_.is_null() &&
+ script_.is_null());
}
- Handle<SharedFunctionInfo> shared_info() { return shared_info_; }
+ // Lazy compilation based on SharedFunctionInfo.
+ explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info)
+ : shared_info_(shared_info),
+ function_(NULL),
+ is_eval_(false),
+ loop_nesting_(0) {
+ Initialize();
+ ASSERT(closure_.is_null() &&
+ !shared_info_.is_null() &&
+ script_.is_null());
+ }
- bool has_receiver() { return !receiver_.is_null(); }
- Handle<Object> receiver() { return receiver_; }
+ // Eager compilation.
+ CompilationInfo(FunctionLiteral* literal, Handle<Script> script, bool is_eval)
+ : script_(script),
+ function_(literal),
+ is_eval_(is_eval),
+ loop_nesting_(0) {
+ Initialize();
+ ASSERT(closure_.is_null() &&
+ shared_info_.is_null() &&
+ !script_.is_null());
+ }
+
+ // We can only get a JSFunction if we actually have one.
+ Handle<JSFunction> closure() { return closure_; }
+ // We can get a SharedFunctionInfo from a JSFunction or if we actually
+ // have one.
+ Handle<SharedFunctionInfo> shared_info() {
+ if (!closure().is_null()) {
+ return Handle<SharedFunctionInfo>(closure()->shared());
+ } else {
+ return shared_info_;
+ }
+ }
+
+ // We can always get a script. Either we have one or we can get a shared
+ // function info.
+ Handle<Script> script() {
+ if (!script_.is_null()) {
+ return script_;
+ } else {
+ ASSERT(shared_info()->script()->IsScript());
+ return Handle<Script>(Script::cast(shared_info()->script()));
+ }
+ }
+
+ // There should always be a function literal, but it may be set after
+ // construction (for lazy compilation).
+ FunctionLiteral* function() { return function_; }
+ void set_function(FunctionLiteral* literal) {
+ ASSERT(function_ == NULL);
+ function_ = literal;
+ }
+
+ // Simple accessors.
+ bool is_eval() { return is_eval_; }
int loop_nesting() { return loop_nesting_; }
+ bool has_receiver() { return !receiver_.is_null(); }
+ Handle<Object> receiver() { return receiver_; }
+ // Accessors for mutable fields, possibly set by analysis passes with
+ // default values given by Initialize.
bool has_this_properties() { return has_this_properties_; }
void set_has_this_properties(bool flag) { has_this_properties_ = flag; }
bool has_globals() { return has_globals_; }
void set_has_globals(bool flag) { has_globals_ = flag; }
+ // Derived accessors.
+ Scope* scope() { return function()->scope(); }
+
private:
+ void Initialize() {
+ has_this_properties_ = false;
+ has_globals_ = false;
+ }
+
+ Handle<JSFunction> closure_;
Handle<SharedFunctionInfo> shared_info_;
- Handle<Object> receiver_;
+ Handle<Script> script_;
+
+ FunctionLiteral* function_;
+
+ bool is_eval_;
int loop_nesting_;
+
+ Handle<Object> receiver_;
+
bool has_this_properties_;
bool has_globals_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
namespace internal {
-void AstLabeler::Label(FunctionLiteral* fun) {
- VisitStatements(fun->body());
+void AstLabeler::Label(CompilationInfo* info) {
+ info_ = info;
+ VisitStatements(info_->function()->body());
}
ASSERT(prop->key()->IsPropertyName());
VariableProxy* proxy = prop->obj()->AsVariableProxy();
if (proxy != NULL && proxy->var()->is_this()) {
- has_this_properties_ = true;
+ info()->set_has_this_properties(true);
} else {
Visit(prop->obj());
}
#define V8_DATAFLOW_H_
#include "ast.h"
-#include "scopes.h"
+#include "compiler.h"
namespace v8 {
namespace internal {
// their evaluation order (post-order left-to-right traversal).
class AstLabeler: public AstVisitor {
public:
- AstLabeler() : next_number_(0), has_this_properties_(false) {}
+ AstLabeler() : next_number_(0) {}
- void Label(FunctionLiteral* fun);
-
- bool has_this_properties() { return has_this_properties_; }
+ void Label(CompilationInfo* info);
private:
+ CompilationInfo* info() { return info_; }
+
void VisitDeclarations(ZoneList<Declaration*>* decls);
void VisitStatements(ZoneList<Statement*>* stmts);
// Traversal number for labelling AST nodes.
int next_number_;
- bool has_this_properties_;
+ CompilationInfo* info_;
DISALLOW_COPY_AND_ASSIGN(AstLabeler);
};
} while (false)
-void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun,
- CompilationInfo* info) {
+void FastCodeGenSyntaxChecker::Check(CompilationInfo* info) {
info_ = info;
// We do not specialize if we do not have a receiver or if it is not a
// We do not support stack or heap slots (both of which require
// allocation).
- Scope* scope = fun->scope();
+ Scope* scope = info->scope();
if (scope->num_stack_slots() > 0) {
BAILOUT("Function has stack-allocated locals");
}
CHECK_BAILOUT;
// We do not support empty function bodies.
- if (fun->body()->is_empty()) BAILOUT("Function has an empty body");
- VisitStatements(fun->body());
+ if (info->function()->body()->is_empty()) {
+ BAILOUT("Function has an empty body");
+ }
+ VisitStatements(info->function()->body());
}
#define __ ACCESS_MASM(masm())
-Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
- Handle<Script> script,
- bool is_eval,
- CompilationInfo* info) {
+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(fun);
- info->set_has_this_properties(labeler.has_this_properties());
+ labeler.Label(info);
- CodeGenerator::MakeCodePrologue(fun);
+ CodeGenerator::MakeCodePrologue(info);
const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize);
// Generate the fast-path code.
- FastCodeGenerator fast_cgen(&masm, script, is_eval);
- fast_cgen.Generate(fun, info);
+ 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, script, is_eval);
+ CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen);
- cgen.Generate(fun, CodeGenerator::SECONDARY, info);
+ 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(fun, &masm, flags, script);
+ return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
}
: info_(NULL), has_supported_syntax_(true) {
}
- void Check(FunctionLiteral* fun, CompilationInfo* info);
+ void Check(CompilationInfo* info);
CompilationInfo* info() { return info_; }
bool has_supported_syntax() { return has_supported_syntax_; }
class FastCodeGenerator: public AstVisitor {
public:
- FastCodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval)
- : masm_(masm),
- script_(script),
- is_eval_(is_eval),
- function_(NULL),
- info_(NULL) {
- }
+ FastCodeGenerator(MacroAssembler* masm) : masm_(masm), info_(NULL) {}
- static Handle<Code> MakeCode(FunctionLiteral* fun,
- Handle<Script> script,
- bool is_eval,
- CompilationInfo* info);
+ static Handle<Code> MakeCode(CompilationInfo* info);
- void Generate(FunctionLiteral* fun, CompilationInfo* info);
+ void Generate(CompilationInfo* info);
private:
MacroAssembler* masm() { return masm_; }
- FunctionLiteral* function() { return function_; }
Label* bailout() { return &bailout_; }
bool has_receiver() { return !info_->receiver().is_null(); }
Handle<Object> receiver() { return info_->receiver(); }
bool has_this_properties() { return info_->has_this_properties(); }
+ FunctionLiteral* function() { return info_->function(); }
+ Scope* scope() { return info_->scope(); }
// AST node visit functions.
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
void EmitThisPropertyStore(Handle<String> name);
MacroAssembler* masm_;
- Handle<Script> script_;
- bool is_eval_;
- FunctionLiteral* function_;
CompilationInfo* info_;
Label bailout_;
#define __ ACCESS_MASM(masm())
-Handle<Code> FullCodeGenerator::MakeCode(FunctionLiteral* fun,
- Handle<Script> script,
- bool is_eval) {
+Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
+ Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length();
Counters::total_full_codegen_source_size.Increment(len);
}
- CodeGenerator::MakeCodePrologue(fun);
+ CodeGenerator::MakeCodePrologue(info);
const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize);
- FullCodeGenerator cgen(&masm, script, is_eval);
- cgen.Generate(fun, PRIMARY);
+ FullCodeGenerator cgen(&masm);
+ cgen.Generate(info, PRIMARY);
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(fun, &masm, flags, script);
+ return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
}
// Adjust by a (parameter or local) base offset.
switch (slot->type()) {
case Slot::PARAMETER:
- offset += (function_->scope()->num_parameters() + 1) * kPointerSize;
+ offset += (scope()->num_parameters() + 1) * kPointerSize;
break;
case Slot::LOCAL:
offset += JavaScriptFrameConstants::kLocal0Offset;
}
} else {
Handle<JSFunction> function =
- Compiler::BuildBoilerplate(decl->fun(), script_, this);
+ Compiler::BuildBoilerplate(decl->fun(), script(), this);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
array->set(j++, *function);
SECONDARY
};
- FullCodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval)
+ FullCodeGenerator(MacroAssembler* masm)
: masm_(masm),
- script_(script),
- is_eval_(is_eval),
- function_(NULL),
+ info_(NULL),
nesting_stack_(NULL),
loop_depth_(0),
location_(kStack),
false_label_(NULL) {
}
- static Handle<Code> MakeCode(FunctionLiteral* fun,
- Handle<Script> script,
- bool is_eval);
+ static Handle<Code> MakeCode(CompilationInfo* info);
- void Generate(FunctionLiteral* fun, Mode mode);
+ void Generate(CompilationInfo* info, Mode mode);
private:
class Breakable;
}
MacroAssembler* masm() { return masm_; }
+
+ Handle<Script> script() { return info_->script(); }
+ bool is_eval() { return info_->is_eval(); }
+ FunctionLiteral* function() { return info_->function(); }
+ Scope* scope() { return info_->scope(); }
+
static Register result_register();
static Register context_register();
void EmitLogicalOperation(BinaryOperation* expr);
MacroAssembler* masm_;
- Handle<Script> script_;
- bool is_eval_;
-
- FunctionLiteral* function_;
+ CompilationInfo* info_;
Label return_label_;
NestedStatement* nesting_stack_;
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) {
- CompilationInfo info(shared, Handle<Object>::null(), 0);
+ CompilationInfo info(shared);
return CompileLazyHelper(&info, flag);
}
bool CompileLazy(Handle<JSFunction> function,
Handle<Object> receiver,
ClearExceptionFlag flag) {
- Handle<SharedFunctionInfo> shared(function->shared());
- CompilationInfo info(shared, receiver, 0);
+ CompilationInfo info(function, 0, receiver);
bool result = CompileLazyHelper(&info, flag);
LOG(FunctionCreateEvent(*function));
return result;
bool CompileLazyInLoop(Handle<JSFunction> function,
Handle<Object> receiver,
ClearExceptionFlag flag) {
- Handle<SharedFunctionInfo> shared(function->shared());
- CompilationInfo info(shared, receiver, 1);
+ CompilationInfo info(function, 1, receiver);
bool result = CompileLazyHelper(&info, flag);
LOG(FunctionCreateEvent(*function));
return result;
// -------------------------------------------------------------------------
// CodeGenerator implementation
-CodeGenerator::CodeGenerator(MacroAssembler* masm,
- Handle<Script> script,
- bool is_eval)
- : is_eval_(is_eval),
- script_(script),
- deferred_(8),
+CodeGenerator::CodeGenerator(MacroAssembler* masm)
+ : deferred_(8),
masm_(masm),
- scope_(NULL),
+ info_(NULL),
frame_(NULL),
allocator_(NULL),
state_(NULL),
}
+Scope* CodeGenerator::scope() { return info_->function()->scope(); }
+
+
// Calling conventions:
// ebp: caller's frame pointer
// esp: stack pointer
// edi: called JS function
// esi: callee's context
-void CodeGenerator::Generate(FunctionLiteral* fun,
- Mode mode,
- CompilationInfo* info) {
+void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// Record the position for debugging purposes.
- CodeForFunctionPosition(fun);
-
- ZoneList<Statement*>* body = fun->body();
+ CodeForFunctionPosition(info->function());
// Initialize state.
- ASSERT(scope_ == NULL);
- scope_ = fun->scope();
+ info_ = info;
ASSERT(allocator_ == NULL);
RegisterAllocator register_allocator(this);
allocator_ = ®ister_allocator;
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
- fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ int3();
}
frame_->AllocateStackSlots();
// Allocate the local context if needed.
- int heap_slots = scope_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
if (heap_slots > 0) {
Comment cmnt(masm_, "[ allocate local context");
// Allocate local context.
// 3) don't copy parameter operand code from SlotOperand!
{
Comment cmnt2(masm_, "[ copy context parameters into .context");
-
// Note that iteration order is relevant here! If we have the same
// parameter twice (e.g., function (x, y, x)), and that parameter
// needs to be copied into the context, it must be the last argument
// order: such a parameter is copied repeatedly into the same
// context location and thus the last value is what is seen inside
// the function.
- for (int i = 0; i < scope_->num_parameters(); i++) {
- Variable* par = scope_->parameter(i);
+ for (int i = 0; i < scope()->num_parameters(); i++) {
+ Variable* par = scope()->parameter(i);
Slot* slot = par->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
// The use of SlotOperand below is safe in unspilled code
// because the slot is guaranteed to be a context slot.
//
// There are no parameters in the global scope.
- ASSERT(!scope_->is_global_scope());
+ ASSERT(!scope()->is_global_scope());
frame_->PushParameterAt(i);
Result value = frame_->Pop();
value.ToRegister();
}
// Initialize ThisFunction reference if present.
- if (scope_->is_function_scope() && scope_->function() != NULL) {
+ if (scope()->is_function_scope() && scope()->function() != NULL) {
frame_->Push(Factory::the_hole_value());
- StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT);
+ StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT);
}
} else {
// When used as the secondary compiler for splitting, ebp, esi,
// Generate code to 'execute' declarations and initialize functions
// (source elements). In case of an illegal redeclaration we need to
// handle that instead of processing the declarations.
- if (scope_->HasIllegalRedeclaration()) {
+ if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ illegal redeclarations");
- scope_->VisitIllegalRedeclaration(this);
+ scope()->VisitIllegalRedeclaration(this);
} else {
Comment cmnt(masm_, "[ declarations");
- ProcessDeclarations(scope_->declarations());
+ ProcessDeclarations(scope()->declarations());
// Bail out if a stack-overflow exception occurred when processing
// declarations.
if (HasStackOverflow()) return;
// Compile the body of the function in a vanilla state. Don't
// bother compiling all the code if the scope has an illegal
// redeclaration.
- if (!scope_->HasIllegalRedeclaration()) {
+ if (!scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ function body");
#ifdef DEBUG
bool is_builtin = Bootstrapper::IsActive();
// Ignore the return value.
}
#endif
- VisitStatements(body);
+ VisitStatements(info->function()->body());
// Handle the return from the function.
if (has_valid_frame()) {
// If there is a valid frame, control flow can fall off the end of
// the body. In that case there is an implicit return statement.
ASSERT(!function_return_is_shadowed_);
- CodeForReturnPosition(fun);
+ CodeForReturnPosition(info->function());
frame_->PrepareForReturn();
Result undefined(Factory::undefined_value());
if (function_return_.is_bound()) {
// There is no need to delete the register allocator, it is a
// stack-allocated local.
allocator_ = NULL;
- scope_ = NULL;
}
}
-ArgumentsAllocationMode CodeGenerator::ArgumentsMode() const {
- if (scope_->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
- ASSERT(scope_->arguments_shadow() != NULL);
+ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
+ if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
+ ASSERT(scope()->arguments_shadow() != NULL);
// We don't want to do lazy arguments allocation for functions that
// have heap-allocated contexts, because it interfers with the
// uninitialized const tracking in the context objects.
- return (scope_->num_heap_slots() > 0)
+ return (scope()->num_heap_slots() > 0)
? EAGER_ARGUMENTS_ALLOCATION
: LAZY_ARGUMENTS_ALLOCATION;
}
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
frame_->PushFunction();
frame_->PushReceiverSlotAddress();
- frame_->Push(Smi::FromInt(scope_->num_parameters()));
+ frame_->Push(Smi::FromInt(scope()->num_parameters()));
Result result = frame_->CallStub(&stub, 3);
frame_->Push(&result);
}
- Variable* arguments = scope_->arguments()->var();
- Variable* shadow = scope_->arguments_shadow()->var();
+ Variable* arguments = scope()->arguments()->var();
+ Variable* shadow = scope()->arguments_shadow()->var();
ASSERT(arguments != NULL && arguments->slot() != NULL);
ASSERT(shadow != NULL && shadow->slot() != NULL);
JumpTarget done;
// Load the receiver and the existing arguments object onto the
// expression stack. Avoid allocating the arguments object here.
Load(receiver);
- LoadFromSlot(scope_->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
+ LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
// Emit the source position information after having loaded the
// receiver and the arguments.
__ j(equal, &adapted);
// No arguments adaptor frame. Copy fixed number of arguments.
- __ mov(eax, Immediate(scope_->num_parameters()));
- for (int i = 0; i < scope_->num_parameters(); i++) {
+ __ mov(eax, Immediate(scope()->num_parameters()));
+ for (int i = 0; i < scope()->num_parameters(); i++) {
__ push(frame_->ParameterAt(i));
}
__ jmp(&invoke);
// Leave the frame and return popping the arguments and the
// receiver.
frame_->Exit();
- masm_->ret((scope_->num_parameters() + 1) * kPointerSize);
+ masm_->ret((scope()->num_parameters() + 1) * kPointerSize);
DeleteFrame();
#ifdef ENABLE_DEBUGGER_SUPPORT
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
- Compiler::BuildBoilerplate(node, script_, this);
+ Compiler::BuildBoilerplate(node, script(), this);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
InstantiateBoilerplate(boilerplate);
ASSERT(args->length() == 0);
// ArgumentsAccessStub takes the parameter count as an input argument
// in register eax. Create a constant result for it.
- Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
+ Result count(Handle<Smi>(Smi::FromInt(scope()->num_parameters())));
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
Result result = frame_->CallStub(&stub, &count);
Load(args->at(0));
Result key = frame_->Pop();
// Explicitly create a constant result.
- Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
+ Result count(Handle<Smi>(Smi::FromInt(scope()->num_parameters())));
// Call the shared stub to get to arguments[key].
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
Result result = frame_->CallStub(&stub, &key, &count);
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
- static Handle<Code> MakeCode(FunctionLiteral* fun,
- Handle<Script> script,
- bool is_eval,
- CompilationInfo* info);
+ static Handle<Code> MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
- static void MakeCodePrologue(FunctionLiteral* fun);
+ static void MakeCodePrologue(CompilationInfo* info);
// Allocate and install the code.
- static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
- MacroAssembler* masm,
+ static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
Code::Flags flags,
- Handle<Script> script);
+ CompilationInfo* info);
#ifdef ENABLE_LOGGING_AND_PROFILING
static bool ShouldGenerateLog(Expression* type);
// Accessors
MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
- Handle<Script> script() { return script_; }
+ inline Handle<Script> script();
bool has_valid_frame() const { return frame_ != NULL; }
private:
// Construction/Destruction
- CodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval);
+ CodeGenerator(MacroAssembler* masm);
// Accessors
- Scope* scope() const { return scope_; }
- bool is_eval() { return is_eval_; }
+ inline bool is_eval();
+ Scope* scope();
// Generating deferred code.
void ProcessDeferred();
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
- void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
+ void Generate(CompilationInfo* info, Mode mode);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
void GenerateReturnSequence(Result* return_value);
// Returns the arguments allocation mode.
- ArgumentsAllocationMode ArgumentsMode() const;
+ ArgumentsAllocationMode ArgumentsMode();
// Store the arguments object and allocate it if necessary.
Result StoreArgumentsObject(bool initial);
bool HasValidEntryRegisters();
#endif
- bool is_eval_; // Tells whether code is generated for eval.
- Handle<Script> script_;
ZoneList<DeferredCode*> deferred_;
// Assembler
MacroAssembler* masm_; // to generate code
+ CompilationInfo* info_;
+
// Code generation state
- Scope* scope_;
VirtualFrame* frame_;
RegisterAllocator* allocator_;
CodeGenState* state_;
}
-void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
- ASSERT(function_ == NULL);
+void FastCodeGenerator::Generate(CompilationInfo* info) {
ASSERT(info_ == NULL);
- function_ = fun;
info_ = info;
// Save the caller's frame pointer and set up our own.
// Receiver (this) is allocated to edx if there are this properties.
if (has_this_properties()) EmitReceiverMapCheck();
- VisitStatements(fun->body());
+ VisitStatements(function()->body());
Comment return_cmnt(masm(), ";; Return(<undefined>)");
__ mov(eax, Factory::undefined_value());
Comment epilogue_cmnt(masm(), ";; Epilogue");
__ mov(esp, ebp);
__ pop(ebp);
- __ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
+ __ ret((scope()->num_parameters() + 1) * kPointerSize);
__ bind(&bailout_);
}
//
// The function builds a JS frame. Please see JavaScriptFrameConstants in
// frames-ia32.h for its layout.
-void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
- function_ = fun;
- SetFunctionPosition(fun);
+void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
+ ASSERT(info_ == NULL);
+ info_ = info;
+ SetFunctionPosition(function());
if (mode == PRIMARY) {
__ push(ebp); // Caller's frame pointer.
__ push(edi); // Callee's JS Function.
{ Comment cmnt(masm_, "[ Allocate locals");
- int locals_count = fun->scope()->num_stack_slots();
+ int locals_count = scope()->num_stack_slots();
if (locals_count == 1) {
__ push(Immediate(Factory::undefined_value()));
} else if (locals_count > 1) {
bool function_in_register = true;
// Possibly allocate a local context.
- if (fun->scope()->num_heap_slots() > 0) {
+ if (scope()->num_heap_slots() > 0) {
Comment cmnt(masm_, "[ Allocate local context");
// Argument to NewContext is the function, which is still in edi.
__ push(edi);
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
// Copy parameters into context if necessary.
- int num_parameters = fun->scope()->num_parameters();
+ int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = fun->scope()->parameter(i)->slot();
+ Slot* slot = scope()->parameter(i)->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
}
}
- Variable* arguments = fun->scope()->arguments()->AsVariable();
+ Variable* arguments = scope()->arguments()->AsVariable();
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
__ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
- __ lea(edx, Operand(ebp, StandardFrameConstants::kCallerSPOffset +
- fun->num_parameters() * kPointerSize));
+ int offset = scope()->num_parameters() * kPointerSize;
+ __ lea(edx,
+ Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
__ push(edx);
- __ push(Immediate(Smi::FromInt(fun->num_parameters())));
+ __ push(Immediate(Smi::FromInt(scope()->num_parameters())));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
__ mov(ecx, eax); // Duplicate result.
Move(arguments->slot(), eax, ebx, edx);
Slot* dot_arguments_slot =
- fun->scope()->arguments_shadow()->AsVariable()->slot();
+ scope()->arguments_shadow()->AsVariable()->slot();
Move(dot_arguments_slot, ecx, ebx, edx);
}
}
{ Comment cmnt(masm_, "[ Declarations");
- VisitDeclarations(fun->scope()->declarations());
+ VisitDeclarations(scope()->declarations());
}
{ Comment cmnt(masm_, "[ Stack check");
{ Comment cmnt(masm_, "[ Body");
ASSERT(loop_depth() == 0);
- VisitStatements(fun->body());
+ VisitStatements(function()->body());
ASSERT(loop_depth() == 0);
}
{ Comment cmnt(masm_, "[ return <undefined>;");
// Emit a 'return undefined' in case control fell off the end of the body.
__ mov(eax, Factory::undefined_value());
- EmitReturnSequence(function_->end_position());
+ EmitReturnSequence(function()->end_position());
}
}
// patch with the code required by the debugger.
__ mov(esp, ebp);
__ pop(ebp);
- __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
+ __ ret((scope()->num_parameters() + 1) * kPointerSize);
#ifdef ENABLE_DEBUGGER_SUPPORT
// Check that the size of the code used for returning matches what is
// expected by the debugger.
return Operand(ebp, SlotOffset(slot));
case Slot::CONTEXT: {
int context_chain_length =
- function_->scope()->ContextChainLength(slot->var()->scope());
+ scope()->ContextChainLength(slot->var()->scope());
__ LoadContext(scratch, context_chain_length);
return CodeGenerator::ContextOperand(scratch, slot->index());
}
// this specific context.
// The variable in the decl always resides in the current context.
- ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
+ ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ mov(ebx,
// Call the runtime to declare the globals.
__ push(esi); // The context is the first argument.
__ push(Immediate(pairs));
- __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0)));
+ __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
- Compiler::BuildBoilerplate(expr, script_, this);
+ Compiler::BuildBoilerplate(expr, script(), this);
if (HasStackOverflow()) return;
ASSERT(boilerplate->IsBoilerplate());
// -----------------------------------------------------------------------------
// CodeGenerator implementation.
-CodeGenerator::CodeGenerator(MacroAssembler* masm,
- Handle<Script> script,
- bool is_eval)
- : is_eval_(is_eval),
- script_(script),
- deferred_(8),
+CodeGenerator::CodeGenerator(MacroAssembler* masm)
+ : deferred_(8),
masm_(masm),
- scope_(NULL),
+ info_(NULL),
frame_(NULL),
allocator_(NULL),
state_(NULL),
}
+Scope* CodeGenerator::scope() { return info_->function()->scope(); }
+
+
void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals. The inevitable call
// will sync frame elements to memory anyway, so we do it eagerly to
}
-void CodeGenerator::Generate(FunctionLiteral* function,
- Mode mode,
- CompilationInfo* info) {
+void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// Record the position for debugging purposes.
- CodeForFunctionPosition(function);
- ZoneList<Statement*>* body = function->body();
+ CodeForFunctionPosition(info->function());
// Initialize state.
- ASSERT(scope_ == NULL);
- scope_ = function->scope();
+ info_ = info;
ASSERT(allocator_ == NULL);
RegisterAllocator register_allocator(this);
allocator_ = ®ister_allocator;
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
- function->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ int3();
}
frame_->AllocateStackSlots();
// Allocate the local context if needed.
- int heap_slots = scope_->num_heap_slots();
+ int heap_slots = scope()->num_heap_slots();
if (heap_slots > 0) {
Comment cmnt(masm_, "[ allocate local context");
// Allocate local context.
// 3) don't copy parameter operand code from SlotOperand!
{
Comment cmnt2(masm_, "[ copy context parameters into .context");
-
// Note that iteration order is relevant here! If we have the same
// parameter twice (e.g., function (x, y, x)), and that parameter
// needs to be copied into the context, it must be the last argument
// order: such a parameter is copied repeatedly into the same
// context location and thus the last value is what is seen inside
// the function.
- for (int i = 0; i < scope_->num_parameters(); i++) {
- Variable* par = scope_->parameter(i);
+ for (int i = 0; i < scope()->num_parameters(); i++) {
+ Variable* par = scope()->parameter(i);
Slot* slot = par->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
// The use of SlotOperand below is safe in unspilled code
// because the slot is guaranteed to be a context slot.
//
// There are no parameters in the global scope.
- ASSERT(!scope_->is_global_scope());
+ ASSERT(!scope()->is_global_scope());
frame_->PushParameterAt(i);
Result value = frame_->Pop();
value.ToRegister();
}
// Initialize ThisFunction reference if present.
- if (scope_->is_function_scope() && scope_->function() != NULL) {
+ if (scope()->is_function_scope() && scope()->function() != NULL) {
frame_->Push(Factory::the_hole_value());
- StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT);
+ StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT);
}
} else {
// When used as the secondary compiler for splitting, rbp, rsi,
// Generate code to 'execute' declarations and initialize functions
// (source elements). In case of an illegal redeclaration we need to
// handle that instead of processing the declarations.
- if (scope_->HasIllegalRedeclaration()) {
+ if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ illegal redeclarations");
- scope_->VisitIllegalRedeclaration(this);
+ scope()->VisitIllegalRedeclaration(this);
} else {
Comment cmnt(masm_, "[ declarations");
- ProcessDeclarations(scope_->declarations());
+ ProcessDeclarations(scope()->declarations());
// Bail out if a stack-overflow exception occurred when processing
// declarations.
if (HasStackOverflow()) return;
// Compile the body of the function in a vanilla state. Don't
// bother compiling all the code if the scope has an illegal
// redeclaration.
- if (!scope_->HasIllegalRedeclaration()) {
+ if (!scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ function body");
#ifdef DEBUG
bool is_builtin = Bootstrapper::IsActive();
// Ignore the return value.
}
#endif
- VisitStatements(body);
+ VisitStatements(info->function()->body());
// Handle the return from the function.
if (has_valid_frame()) {
// If there is a valid frame, control flow can fall off the end of
// the body. In that case there is an implicit return statement.
ASSERT(!function_return_is_shadowed_);
- CodeForReturnPosition(function);
+ CodeForReturnPosition(info->function());
frame_->PrepareForReturn();
Result undefined(Factory::undefined_value());
if (function_return_.is_bound()) {
// There is no need to delete the register allocator, it is a
// stack-allocated local.
allocator_ = NULL;
- scope_ = NULL;
}
void CodeGenerator::GenerateReturnSequence(Result* return_value) {
// Leave the frame and return popping the arguments and the
// receiver.
frame_->Exit();
- masm_->ret((scope_->num_parameters() + 1) * kPointerSize);
+ masm_->ret((scope()->num_parameters() + 1) * kPointerSize);
#ifdef ENABLE_DEBUGGER_SUPPORT
// Add padding that will be overwritten by a debugger breakpoint.
// frame_->Exit() generates "movq rsp, rbp; pop rbp; ret k"
// Load the receiver and the existing arguments object onto the
// expression stack. Avoid allocating the arguments object here.
Load(receiver);
- LoadFromSlot(scope_->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
+ LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
// Emit the source position information after having loaded the
// receiver and the arguments.
__ j(equal, &adapted);
// No arguments adaptor frame. Copy fixed number of arguments.
- __ movq(rax, Immediate(scope_->num_parameters()));
- for (int i = 0; i < scope_->num_parameters(); i++) {
+ __ movq(rax, Immediate(scope()->num_parameters()));
+ for (int i = 0; i < scope()->num_parameters(); i++) {
__ push(frame_->ParameterAt(i));
}
__ jmp(&invoke);
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
- Compiler::BuildBoilerplate(node, script_, this);
+ Compiler::BuildBoilerplate(node, script(), this);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
InstantiateBoilerplate(boilerplate);
Load(args->at(0));
Result key = frame_->Pop();
// Explicitly create a constant result.
- Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
+ Result count(Handle<Smi>(Smi::FromInt(scope()->num_parameters())));
// Call the shared stub to get to arguments[key].
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
Result result = frame_->CallStub(&stub, &key, &count);
ASSERT(args->length() == 0);
// ArgumentsAccessStub takes the parameter count as an input argument
// in register eax. Create a constant result for it.
- Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
+ Result count(Handle<Smi>(Smi::FromInt(scope()->num_parameters())));
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
Result result = frame_->CallStub(&stub, &count);
}
-ArgumentsAllocationMode CodeGenerator::ArgumentsMode() const {
- if (scope_->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
- ASSERT(scope_->arguments_shadow() != NULL);
+ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
+ if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
+ ASSERT(scope()->arguments_shadow() != NULL);
// We don't want to do lazy arguments allocation for functions that
// have heap-allocated contexts, because it interfers with the
// uninitialized const tracking in the context objects.
- return (scope_->num_heap_slots() > 0)
+ return (scope()->num_heap_slots() > 0)
? EAGER_ARGUMENTS_ALLOCATION
: LAZY_ARGUMENTS_ALLOCATION;
}
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
frame_->PushFunction();
frame_->PushReceiverSlotAddress();
- frame_->Push(Smi::FromInt(scope_->num_parameters()));
+ frame_->Push(Smi::FromInt(scope()->num_parameters()));
Result result = frame_->CallStub(&stub, 3);
frame_->Push(&result);
}
- Variable* arguments = scope_->arguments()->var();
- Variable* shadow = scope_->arguments_shadow()->var();
+ Variable* arguments = scope()->arguments()->var();
+ Variable* shadow = scope()->arguments_shadow()->var();
ASSERT(arguments != NULL && arguments->slot() != NULL);
ASSERT(shadow != NULL && shadow->slot() != NULL);
JumpTarget done;
// We have to skip storing into the arguments slot if it has
// already been written to. This can happen if the a function
// has a local variable named 'arguments'.
- LoadFromSlot(scope_->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
+ LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
Result probe = frame_->Pop();
if (probe.is_constant()) {
// We have to skip updating the arguments object if it has been
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
- static Handle<Code> MakeCode(FunctionLiteral* fun,
- Handle<Script> script,
- bool is_eval,
- CompilationInfo* info);
+ static Handle<Code> MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
- static void MakeCodePrologue(FunctionLiteral* fun);
+ static void MakeCodePrologue(CompilationInfo* info);
// Allocate and install the code.
- static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
- MacroAssembler* masm,
+ static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
Code::Flags flags,
- Handle<Script> script);
+ CompilationInfo* info);
#ifdef ENABLE_LOGGING_AND_PROFILING
static bool ShouldGenerateLog(Expression* type);
// Accessors
MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
- Handle<Script> script() { return script_; }
+ inline Handle<Script> script();
bool has_valid_frame() const { return frame_ != NULL; }
private:
// Construction/Destruction
- CodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval);
+ CodeGenerator(MacroAssembler* masm);
// Accessors
- Scope* scope() const { return scope_; }
+ inline bool is_eval();
+ Scope* scope();
// Generating deferred code.
void ProcessDeferred();
- bool is_eval() { return is_eval_; }
-
// State
ControlDestination* destination() const { return state_->destination(); }
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
- void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
+ void Generate(CompilationInfo* info, Mode mode);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
void GenerateReturnSequence(Result* return_value);
// Returns the arguments allocation mode.
- ArgumentsAllocationMode ArgumentsMode() const;
+ ArgumentsAllocationMode ArgumentsMode();
// Store the arguments object and allocate it if necessary.
Result StoreArgumentsObject(bool initial);
bool HasValidEntryRegisters();
#endif
- bool is_eval_; // Tells whether code is generated for eval.
- Handle<Script> script_;
ZoneList<DeferredCode*> deferred_;
// Assembler
MacroAssembler* masm_; // to generate code
+ CompilationInfo* info_;
+
// Code generation state
- Scope* scope_;
VirtualFrame* frame_;
RegisterAllocator* allocator_;
CodeGenState* state_;
void FastCodeGenerator::EmitLoadReceiver(Register reg) {
// Offset 2 is due to return address and saved frame pointer.
- int index = 2 + function()->scope()->num_parameters();
+ int index = 2 + scope()->num_parameters();
__ movq(reg, Operand(rbp, index * kPointerSize));
}
}
-void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
- ASSERT(function_ == NULL);
+void FastCodeGenerator::Generate(CompilationInfo* info) {
ASSERT(info_ == NULL);
- function_ = fun;
info_ = info;
// Save the caller's frame pointer and set up our own.
// Receiver (this) is allocated to rdx if there are this properties.
if (has_this_properties()) EmitReceiverMapCheck();
- VisitStatements(fun->body());
+ VisitStatements(info->function()->body());
Comment return_cmnt(masm(), ";; Return(<undefined>)");
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
Comment epilogue_cmnt(masm(), ";; Epilogue");
__ movq(rsp, rbp);
__ pop(rbp);
- __ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
+ __ ret((scope()->num_parameters() + 1) * kPointerSize);
__ bind(&bailout_);
}
//
// The function builds a JS frame. Please see JavaScriptFrameConstants in
// frames-x64.h for its layout.
-void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
- function_ = fun;
- SetFunctionPosition(fun);
+void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
+ ASSERT(info_ == NULL);
+ info_ = info;
+ SetFunctionPosition(function());
if (mode == PRIMARY) {
__ push(rbp); // Caller's frame pointer.
__ push(rdi); // Callee's JS Function.
{ Comment cmnt(masm_, "[ Allocate locals");
- int locals_count = fun->scope()->num_stack_slots();
+ int locals_count = scope()->num_stack_slots();
if (locals_count == 1) {
__ PushRoot(Heap::kUndefinedValueRootIndex);
} else if (locals_count > 1) {
bool function_in_register = true;
// Possibly allocate a local context.
- if (fun->scope()->num_heap_slots() > 0) {
+ if (scope()->num_heap_slots() > 0) {
Comment cmnt(masm_, "[ Allocate local context");
// Argument to NewContext is the function, which is still in rdi.
__ push(rdi);
__ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
// Copy any necessary parameters into the context.
- int num_parameters = fun->scope()->num_parameters();
+ int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = fun->scope()->parameter(i)->slot();
+ Slot* slot = scope()->parameter(i)->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
}
// Possibly allocate an arguments object.
- Variable* arguments = fun->scope()->arguments()->AsVariable();
+ Variable* arguments = scope()->arguments()->AsVariable();
if (arguments != NULL) {
// Arguments object must be allocated after the context object, in
// case the "arguments" or ".arguments" variables are in the context.
__ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
}
// The receiver is just before the parameters on the caller's stack.
- __ lea(rdx, Operand(rbp, StandardFrameConstants::kCallerSPOffset +
- fun->num_parameters() * kPointerSize));
+ int offset = scope()->num_parameters() * kPointerSize;
+ __ lea(rdx,
+ Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
__ push(rdx);
- __ Push(Smi::FromInt(fun->num_parameters()));
+ __ Push(Smi::FromInt(scope()->num_parameters()));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
__ movq(rcx, rax);
Move(arguments->slot(), rax, rbx, rdx);
Slot* dot_arguments_slot =
- fun->scope()->arguments_shadow()->AsVariable()->slot();
+ scope()->arguments_shadow()->AsVariable()->slot();
Move(dot_arguments_slot, rcx, rbx, rdx);
}
}
{ Comment cmnt(masm_, "[ Declarations");
- VisitDeclarations(fun->scope()->declarations());
+ VisitDeclarations(scope()->declarations());
}
{ Comment cmnt(masm_, "[ Stack check");
{ Comment cmnt(masm_, "[ Body");
ASSERT(loop_depth() == 0);
- VisitStatements(fun->body());
+ VisitStatements(function()->body());
ASSERT(loop_depth() == 0);
}
{ Comment cmnt(masm_, "[ return <undefined>;");
// Emit a 'return undefined' in case control fell off the end of the body.
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
- EmitReturnSequence(function_->end_position());
+ EmitReturnSequence(function()->end_position());
}
}
// patch with the code required by the debugger.
__ movq(rsp, rbp);
__ pop(rbp);
- __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
+ __ ret((scope()->num_parameters() + 1) * kPointerSize);
#ifdef ENABLE_DEBUGGER_SUPPORT
// Add padding that will be overwritten by a debugger breakpoint. We
// have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
return Operand(rbp, SlotOffset(slot));
case Slot::CONTEXT: {
int context_chain_length =
- function_->scope()->ContextChainLength(slot->var()->scope());
+ scope()->ContextChainLength(slot->var()->scope());
__ LoadContext(scratch, context_chain_length);
return CodeGenerator::ContextOperand(scratch, slot->index());
}
// this specific context.
// The variable in the decl always resides in the current context.
- ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
+ ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ movq(rbx,
// Call the runtime to declare the globals.
__ push(rsi); // The context is the first argument.
__ Push(pairs);
- __ Push(Smi::FromInt(is_eval_ ? 1 : 0));
+ __ Push(Smi::FromInt(is_eval() ? 1 : 0));
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
- Compiler::BuildBoilerplate(expr, script_, this);
+ Compiler::BuildBoilerplate(expr, script(), this);
if (HasStackOverflow()) return;
ASSERT(boilerplate->IsBoilerplate());