Commit 9c056981 authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Port eval resolve in call optimization from classic to full codegen.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6998 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f0cf78f0
......@@ -2132,6 +2132,29 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
int arg_count) {
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
} else {
__ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
}
__ push(r1);
// Push the receiver of the enclosing function and do runtime call.
__ ldr(r1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
__ push(r1);
// Push the strict mode flag.
__ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
__ push(r1);
__ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
? Runtime::kResolvePossiblyDirectEvalNoLookup
: Runtime::kResolvePossiblyDirectEval, 4);
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
......@@ -2161,26 +2184,31 @@ void FullCodeGenerator::VisitCall(Call* expr) {
VisitForStackValue(args->at(i));
}
// Push copy of the function - found below the arguments.
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(r1);
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
__ push(r1);
} else {
__ push(r2);
// If we know that eval can only be shadowed by eval-introduced
// variables we attempt to load the global eval function directly
// in generated code. If we succeed, there is no need to perform a
// context lookup in the runtime system.
Label done;
if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
Label slow;
EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
NOT_INSIDE_TYPEOF,
&slow);
// Push the function and resolve eval.
__ push(r0);
EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
__ jmp(&done);
__ bind(&slow);
}
// Push the receiver of the enclosing function and do runtime call.
__ ldr(r1,
MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
__ push(r1);
// Push the strict mode flag.
__ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
// Push copy of the function (found below the arguments) and
// resolve eval.
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(r1);
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
if (done.is_linked()) {
__ bind(&done);
}
// The runtime call returns a pair of values in r0 (function) and
// r1 (receiver). Touch up the stack with the right values.
......
......@@ -421,6 +421,14 @@ class FullCodeGenerator: public AstVisitor {
Label* done);
void EmitVariableLoad(Variable* expr);
enum ResolveEvalFlag {
SKIP_CONTEXT_LOOKUP,
PERFORM_CONTEXT_LOOKUP
};
// Expects the arguments and the function already pushed.
void EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, int arg_count);
// Platform-specific support for allocating a new closure based on
// the given function info.
void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure);
......
......@@ -2050,6 +2050,27 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
int arg_count) {
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ push(Operand(esp, arg_count * kPointerSize));
} else {
__ push(Immediate(Factory::undefined_value()));
}
// Push the receiver of the enclosing function.
__ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
// Push the strict mode flag.
__ push(Immediate(Smi::FromInt(strict_mode_flag())));
__ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
? Runtime::kResolvePossiblyDirectEvalNoLookup
: Runtime::kResolvePossiblyDirectEval, 4);
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
......@@ -2078,21 +2099,30 @@ void FullCodeGenerator::VisitCall(Call* expr) {
VisitForStackValue(args->at(i));
}
// Push copy of the function - found below the arguments.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ push(Operand(esp, arg_count * kPointerSize));
} else {
__ push(Immediate(Factory::undefined_value()));
// If we know that eval can only be shadowed by eval-introduced
// variables we attempt to load the global eval function directly
// in generated code. If we succeed, there is no need to perform a
// context lookup in the runtime system.
Label done;
if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
Label slow;
EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
NOT_INSIDE_TYPEOF,
&slow);
// Push the function and resolve eval.
__ push(eax);
EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
__ jmp(&done);
__ bind(&slow);
}
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
// Push the strict mode flag.
__ push(Immediate(Smi::FromInt(strict_mode_flag())));
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
// Push copy of the function (found below the arguments) and
// resolve eval.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
if (done.is_linked()) {
__ bind(&done);
}
// The runtime call returns a pair of values in eax (function) and
// edx (receiver). Touch up the stack with the right values.
......
......@@ -2034,6 +2034,27 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
int arg_count) {
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ push(Operand(rsp, arg_count * kPointerSize));
} else {
__ PushRoot(Heap::kUndefinedValueRootIndex);
}
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
// Push the strict mode flag.
__ Push(Smi::FromInt(strict_mode_flag()));
__ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
? Runtime::kResolvePossiblyDirectEvalNoLookup
: Runtime::kResolvePossiblyDirectEval, 4);
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
......@@ -2061,21 +2082,30 @@ void FullCodeGenerator::VisitCall(Call* expr) {
VisitForStackValue(args->at(i));
}
// Push copy of the function - found below the arguments.
__ push(Operand(rsp, (arg_count + 1) * kPointerSize));
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ push(Operand(rsp, arg_count * kPointerSize));
} else {
__ PushRoot(Heap::kUndefinedValueRootIndex);
// If we know that eval can only be shadowed by eval-introduced
// variables we attempt to load the global eval function directly
// in generated code. If we succeed, there is no need to perform a
// context lookup in the runtime system.
Label done;
if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
Label slow;
EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
NOT_INSIDE_TYPEOF,
&slow);
// Push the function and resolve eval.
__ push(rax);
EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
__ jmp(&done);
__ bind(&slow);
}
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
// Push the strict mode flag.
__ Push(Smi::FromInt(strict_mode_flag()));
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
// Push copy of the function (found below the arguments) and
// resolve eval.
__ push(Operand(rsp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
if (done.is_linked()) {
__ bind(&done);
}
// The runtime call returns a pair of values in rax (function) and
// rdx (receiver). Touch up the stack with the right values.
......
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