Introduce ToNumber stub and use it in non-optimized code for to-number conversion.

This stub is used for increment/decrement operations and unary plus.
The resulting code is more compact and faster than calling a JS builtin.


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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6527 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent afd09062
...@@ -55,6 +55,28 @@ static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, ...@@ -55,6 +55,28 @@ static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
Register rhs); Register rhs);
void ToNumberStub::Generate(MacroAssembler* masm) {
// The ToNumber stub takes one argument in eax.
Label check_heap_number, call_builtin;
__ tst(r0, Operand(kSmiTagMask));
__ b(ne, &check_heap_number);
__ Ret();
__ bind(&check_heap_number);
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(r1, ip);
__ b(ne, &call_builtin);
__ Ret();
__ bind(&call_builtin);
__ pop(r2); // Pop return address.
__ push(r0);
__ push(r2); // Push return address.
__ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_JS);
}
void FastNewClosureStub::Generate(MacroAssembler* masm) { void FastNewClosureStub::Generate(MacroAssembler* masm) {
// Create a new closure from the given function info in new // Create a new closure from the given function info in new
// space. Set the context to the current context in cp. // space. Set the context to the current context in cp.
......
...@@ -3057,8 +3057,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { ...@@ -3057,8 +3057,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
Label no_conversion; Label no_conversion;
__ tst(result_register(), Operand(kSmiTagMask)); __ tst(result_register(), Operand(kSmiTagMask));
__ b(eq, &no_conversion); __ b(eq, &no_conversion);
__ push(r0); ToNumberStub convert_stub;
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); __ CallStub(&convert_stub);
__ bind(&no_conversion); __ bind(&no_conversion);
context()->Plug(result_register()); context()->Plug(result_register());
break; break;
...@@ -3177,8 +3177,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -3177,8 +3177,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Call ToNumber only if operand is not a smi. // Call ToNumber only if operand is not a smi.
Label no_conversion; Label no_conversion;
__ JumpIfSmi(r0, &no_conversion); __ JumpIfSmi(r0, &no_conversion);
__ push(r0); ToNumberStub convert_stub;
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); __ CallStub(&convert_stub);
__ bind(&no_conversion); __ bind(&no_conversion);
// Save result for postfix expressions. // Save result for postfix expressions.
......
...@@ -59,6 +59,7 @@ namespace internal { ...@@ -59,6 +59,7 @@ namespace internal {
V(GenericUnaryOp) \ V(GenericUnaryOp) \
V(RevertToNumber) \ V(RevertToNumber) \
V(ToBoolean) \ V(ToBoolean) \
V(ToNumber) \
V(CounterOp) \ V(CounterOp) \
V(ArgumentsAccess) \ V(ArgumentsAccess) \
V(RegExpExec) \ V(RegExpExec) \
...@@ -260,6 +261,19 @@ class StackCheckStub : public CodeStub { ...@@ -260,6 +261,19 @@ class StackCheckStub : public CodeStub {
}; };
class ToNumberStub: public CodeStub {
public:
ToNumberStub() { }
void Generate(MacroAssembler* masm);
private:
Major MajorKey() { return ToNumber; }
int MinorKey() { return 0; }
const char* GetName() { return "ToNumberStub"; }
};
class FastNewClosureStub : public CodeStub { class FastNewClosureStub : public CodeStub {
public: public:
void Generate(MacroAssembler* masm); void Generate(MacroAssembler* masm);
......
...@@ -38,6 +38,28 @@ namespace v8 { ...@@ -38,6 +38,28 @@ namespace v8 {
namespace internal { namespace internal {
#define __ ACCESS_MASM(masm) #define __ ACCESS_MASM(masm)
void ToNumberStub::Generate(MacroAssembler* masm) {
// The ToNumber stub takes one argument in eax.
NearLabel check_heap_number, call_builtin;
__ test(eax, Immediate(kSmiTagMask));
__ j(not_zero, &check_heap_number);
__ ret(0);
__ bind(&check_heap_number);
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
__ cmp(Operand(ebx), Immediate(Factory::heap_number_map()));
__ j(not_equal, &call_builtin);
__ ret(0);
__ bind(&call_builtin);
__ pop(ecx); // Pop return address.
__ push(eax);
__ push(ecx); // Push return address.
__ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
}
void FastNewClosureStub::Generate(MacroAssembler* masm) { void FastNewClosureStub::Generate(MacroAssembler* masm) {
// Create a new closure from the given function info in new // Create a new closure from the given function info in new
// space. Set the context to the current context in esi. // space. Set the context to the current context in esi.
......
...@@ -3747,8 +3747,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { ...@@ -3747,8 +3747,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
Label no_conversion; Label no_conversion;
__ test(result_register(), Immediate(kSmiTagMask)); __ test(result_register(), Immediate(kSmiTagMask));
__ j(zero, &no_conversion); __ j(zero, &no_conversion);
__ push(result_register()); ToNumberStub convert_stub;
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); __ CallStub(&convert_stub);
__ bind(&no_conversion); __ bind(&no_conversion);
context()->Plug(result_register()); context()->Plug(result_register());
break; break;
...@@ -3868,8 +3868,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -3868,8 +3868,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ test(eax, Immediate(kSmiTagMask)); __ test(eax, Immediate(kSmiTagMask));
__ j(zero, &no_conversion); __ j(zero, &no_conversion);
} }
__ push(eax); ToNumberStub convert_stub;
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); __ CallStub(&convert_stub);
__ bind(&no_conversion); __ bind(&no_conversion);
// Save result for postfix expressions. // Save result for postfix expressions.
......
...@@ -37,6 +37,28 @@ namespace v8 { ...@@ -37,6 +37,28 @@ namespace v8 {
namespace internal { namespace internal {
#define __ ACCESS_MASM(masm) #define __ ACCESS_MASM(masm)
void ToNumberStub::Generate(MacroAssembler* masm) {
// The ToNumber stub takes one argument in eax.
NearLabel check_heap_number, call_builtin;
__ SmiTest(rax);
__ j(not_zero, &check_heap_number);
__ Ret();
__ bind(&check_heap_number);
__ Move(rbx, Factory::heap_number_map());
__ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
__ j(not_equal, &call_builtin);
__ Ret();
__ bind(&call_builtin);
__ pop(rcx); // Pop return address.
__ push(rax);
__ push(rcx); // Push return address.
__ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
}
void FastNewClosureStub::Generate(MacroAssembler* masm) { void FastNewClosureStub::Generate(MacroAssembler* masm) {
// Create a new closure from the given function info in new // Create a new closure from the given function info in new
// space. Set the context to the current context in rsi. // space. Set the context to the current context in rsi.
......
...@@ -3063,8 +3063,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { ...@@ -3063,8 +3063,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
Label no_conversion; Label no_conversion;
Condition is_smi = masm_->CheckSmi(result_register()); Condition is_smi = masm_->CheckSmi(result_register());
__ j(is_smi, &no_conversion); __ j(is_smi, &no_conversion);
__ push(result_register()); ToNumberStub convert_stub;
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); __ CallStub(&convert_stub);
__ bind(&no_conversion); __ bind(&no_conversion);
context()->Plug(result_register()); context()->Plug(result_register());
break; break;
...@@ -3180,8 +3180,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -3180,8 +3180,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Condition is_smi; Condition is_smi;
is_smi = masm_->CheckSmi(rax); is_smi = masm_->CheckSmi(rax);
__ j(is_smi, &no_conversion); __ j(is_smi, &no_conversion);
__ push(rax); ToNumberStub convert_stub;
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); __ CallStub(&convert_stub);
__ bind(&no_conversion); __ bind(&no_conversion);
// Save result for postfix expressions. // Save result for postfix expressions.
......
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