Commit f1a47d2b authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Inline %_ArgumentsLength.

This makes usage of cmov unnecessary.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4323 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ce1d3ca8
......@@ -3587,13 +3587,22 @@ void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 0);
// Seed the result with the formal parameters count, which will be used
// in case no arguments adaptor frame is found below the current frame.
Label exit;
// Get the number of formal parameters.
__ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
frame_->CallStub(&stub, 0);
// Check if the calling frame is an arguments adaptor frame.
__ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
__ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ b(ne, &exit);
// Arguments adaptor case: Read the arguments length from the
// adaptor frame.
__ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ bind(&exit);
frame_->EmitPush(r0);
}
......@@ -6791,26 +6800,6 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
}
void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
// Check if the calling frame is an arguments adaptor frame.
Label adaptor;
__ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
__ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ b(eq, &adaptor);
// Nothing to do: The formal number of parameters has already been
// passed in register r0 by calling function. Just return it.
__ Jump(lr);
// Arguments adaptor case: Read the arguments length from the
// adaptor frame and return it.
__ bind(&adaptor);
__ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ Jump(lr);
}
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// The displacement is the offset of the last parameter (if any)
// relative to the frame pointer.
......
......@@ -454,7 +454,6 @@ const char* GenericUnaryOpStub::GetName() {
void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
switch (type_) {
case READ_LENGTH: GenerateReadLength(masm); break;
case READ_ELEMENT: GenerateReadElement(masm); break;
case NEW_OBJECT: GenerateNewObject(masm); break;
}
......
......@@ -498,7 +498,6 @@ class JSConstructEntryStub : public JSEntryStub {
class ArgumentsAccessStub: public CodeStub {
public:
enum Type {
READ_LENGTH,
READ_ELEMENT,
NEW_OBJECT
};
......@@ -512,7 +511,6 @@ class ArgumentsAccessStub: public CodeStub {
int MinorKey() { return type_; }
void Generate(MacroAssembler* masm);
void GenerateReadLength(MacroAssembler* masm);
void GenerateReadElement(MacroAssembler* masm);
void GenerateNewObject(MacroAssembler* masm);
......
......@@ -6228,12 +6228,30 @@ void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
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())));
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
Result result = frame_->CallStub(&stub, &count);
Result fp = allocator_->Allocate();
Result result = allocator_->Allocate();
ASSERT(fp.is_valid() && result.is_valid());
Label exit;
// Get the number of formal parameters.
__ Set(result.reg(), Immediate(Smi::FromInt(scope()->num_parameters())));
// Check if the calling frame is an arguments adaptor frame.
__ mov(fp.reg(), Operand(ebp, StandardFrameConstants::kCallerFPOffset));
__ cmp(Operand(fp.reg(), StandardFrameConstants::kContextOffset),
Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ j(not_equal, &exit);
// Arguments adaptor case: Read the arguments length from the
// adaptor frame.
__ mov(result.reg(),
Operand(fp.reg(), ArgumentsAdaptorFrameConstants::kLengthOffset));
__ bind(&exit);
result.set_type_info(TypeInfo::Smi());
if (FLAG_debug_code) __ AbortIfNotSmi(result.reg());
frame_->Push(&result);
}
......@@ -10411,30 +10429,6 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
}
void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
// Check if the calling frame is an arguments adaptor frame.
__ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
__ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
__ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
// Arguments adaptor case: Read the arguments length from the
// adaptor frame and return it.
// Otherwise nothing to do: The number of formal parameters has already been
// passed in register eax by calling function. Just return it.
if (CpuFeatures::IsSupported(CMOV)) {
CpuFeatures::Scope use_cmov(CMOV);
__ cmov(equal, eax,
Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
} else {
Label exit;
__ j(not_equal, &exit);
__ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ bind(&exit);
}
__ ret(0);
}
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// The key is in edx and the parameter count is in eax.
......
......@@ -3772,12 +3772,32 @@ void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
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())));
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
Result result = frame_->CallStub(&stub, &count);
Result fp = allocator_->Allocate();
Result result = allocator_->Allocate();
ASSERT(fp.is_valid() && result.is_valid());
Label exit;
// Get the number of formal parameters.
__ Move(result.reg(), Smi::FromInt(scope()->num_parameters()));
// Check if the calling frame is an arguments adaptor frame.
__ movq(fp.reg(), Operand(rbp, StandardFrameConstants::kCallerFPOffset));
__ SmiCompare(Operand(fp.reg(), StandardFrameConstants::kContextOffset),
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ j(not_equal, &exit);
// Arguments adaptor case: Read the arguments length from the
// adaptor frame.
__ movq(result.reg(),
Operand(fp.reg(), ArgumentsAdaptorFrameConstants::kLengthOffset));
__ bind(&exit);
result.set_type_info(TypeInfo::Smi());
if (FLAG_debug_code) {
__ AbortIfNotSmi(result.reg(), "Computed arguments.length is not a smi.");
}
frame_->Push(&result);
}
......@@ -7787,23 +7807,6 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
}
void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
// Check if the calling frame is an arguments adaptor frame.
Label adaptor;
__ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
__ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset),
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
// Arguments adaptor case: Read the arguments length from the
// adaptor frame and return it.
// Otherwise nothing to do: The number of formal parameters has already been
// passed in register eax by calling function. Just return it.
__ cmovq(equal, rax,
Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ ret(0);
}
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// Check that stack should contain next handler, frame pointer, state and
// return address in that order.
......
......@@ -1660,6 +1660,15 @@ void MacroAssembler::AbortIfNotNumber(Register object, const char* msg) {
}
void MacroAssembler::AbortIfNotSmi(Register object, const char* msg) {
Label ok;
Condition is_smi = CheckSmi(object);
j(is_smi, &ok);
Assert(equal, msg);
bind(&ok);
}
Condition MacroAssembler::IsObjectStringType(Register heap_object,
Register map,
Register instance_type) {
......
......@@ -503,6 +503,9 @@ class MacroAssembler: public Assembler {
// Abort execution if argument is not a number. Used in debug code.
void AbortIfNotNumber(Register object, const char* msg);
// Abort execution if argument is not a smi. Used in debug code.
void AbortIfNotSmi(Register object, const char* msg);
// ---------------------------------------------------------------------------
// Exception handling
......
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