Index: src/ia32/code-stubs-ia32.cc |
=================================================================== |
--- src/ia32/code-stubs-ia32.cc (revision 6280) |
+++ src/ia32/code-stubs-ia32.cc (working copy) |
@@ -1773,40 +1773,12 @@ |
void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) { |
- Label call_runtime; |
ASSERT(operands_type_ == TRBinaryOpIC::STRING); |
ASSERT(op_ == Token::ADD); |
- // If one of the arguments is a string, call the string add stub. |
- // Otherwise, transition to the generic TRBinaryOpIC type. |
- // Registers containing left and right operands respectively. |
- Register left = edx; |
- Register right = eax; |
- |
- // Test if left operand is a string. |
- NearLabel left_not_string; |
- __ test(left, Immediate(kSmiTagMask)); |
- __ j(zero, &left_not_string); |
- __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
- __ j(above_equal, &left_not_string); |
- |
- StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
- GenerateRegisterArgsPush(masm); |
- __ TailCallStub(&string_add_left_stub); |
- |
- // Left operand is not a string, test right. |
- __ bind(&left_not_string); |
- __ test(right, Immediate(kSmiTagMask)); |
- __ j(zero, &call_runtime); |
- __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
- __ j(above_equal, &call_runtime); |
- |
- StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); |
- GenerateRegisterArgsPush(masm); |
- __ TailCallStub(&string_add_right_stub); |
- |
- // Neither argument is a string. |
- __ bind(&call_runtime); |
+ // Try to add arguments as strings, otherwise, transition to the generic |
+ // TRBinaryOpIC type. |
+ GenerateAddStrings(masm); |
GenerateTypeTransition(masm); |
} |
@@ -1967,49 +1939,7 @@ |
// If an allocation fails, or SHR or MOD hit a hard case, |
// use the runtime system to get the correct result. |
__ bind(&call_runtime); |
- |
- switch (op_) { |
- case Token::ADD: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); |
- break; |
- case Token::SUB: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); |
- break; |
- case Token::MUL: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION); |
- break; |
- case Token::DIV: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION); |
- break; |
- case Token::MOD: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); |
- break; |
- case Token::BIT_OR: |
- __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION); |
- break; |
- case Token::BIT_AND: |
- __ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION); |
- break; |
- case Token::BIT_XOR: |
- __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION); |
- break; |
- case Token::SAR: |
- __ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION); |
- break; |
- case Token::SHL: |
- __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION); |
- break; |
- case Token::SHR: |
- __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
- break; |
- default: |
- UNREACHABLE(); |
- } |
+ GenerateCallRuntime(masm); |
} |
@@ -2149,49 +2079,7 @@ |
// If an allocation fails, or SHR or MOD hit a hard case, |
// use the runtime system to get the correct result. |
__ bind(&call_runtime); |
- |
- switch (op_) { |
- case Token::ADD: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); |
- break; |
- case Token::SUB: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); |
- break; |
- case Token::MUL: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION); |
- break; |
- case Token::DIV: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION); |
- break; |
- case Token::MOD: |
- GenerateRegisterArgsPush(masm); |
- __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); |
- break; |
- case Token::BIT_OR: |
- __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION); |
- break; |
- case Token::BIT_AND: |
- __ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION); |
- break; |
- case Token::BIT_XOR: |
- __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION); |
- break; |
- case Token::SAR: |
- __ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION); |
- break; |
- case Token::SHL: |
- __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION); |
- break; |
- case Token::SHR: |
- __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
- break; |
- default: |
- UNREACHABLE(); |
- } |
+ GenerateCallRuntime(masm); |
} |
@@ -2345,41 +2233,56 @@ |
// If all else fails, use the runtime system to get the correct |
// result. |
__ bind(&call_runtime); |
- switch (op_) { |
- case Token::ADD: { |
- GenerateRegisterArgsPush(masm); |
- // Test for string arguments before calling runtime. |
- // Registers containing left and right operands respectively. |
- Register lhs, rhs; |
- lhs = edx; |
- rhs = eax; |
- // Test if left operand is a string. |
- NearLabel lhs_not_string; |
- __ test(lhs, Immediate(kSmiTagMask)); |
- __ j(zero, &lhs_not_string); |
- __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, ecx); |
- __ j(above_equal, &lhs_not_string); |
+ // Try to add strings before calling runtime. |
+ if (op_ == Token::ADD) { |
+ GenerateAddStrings(masm); |
+ } |
- StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
- __ TailCallStub(&string_add_left_stub); |
+ // Generate the runtime call. |
+ GenerateCallRuntime(masm); |
+} |
- NearLabel call_add_runtime; |
- // Left operand is not a string, test right. |
- __ bind(&lhs_not_string); |
- __ test(rhs, Immediate(kSmiTagMask)); |
- __ j(zero, &call_add_runtime); |
- __ CmpObjectType(rhs, FIRST_NONSTRING_TYPE, ecx); |
- __ j(above_equal, &call_add_runtime); |
- StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); |
- __ TailCallStub(&string_add_right_stub); |
+void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
+ // If one of the arguments is a string, call the string add stub. |
+ // Registers containing left and right operands respectively. |
+ NearLabel left_not_string, neither_string; |
+ Register left = edx; |
+ Register right = eax; |
- // Neither argument is a string. |
- __ bind(&call_add_runtime); |
+ // Test if left operand is a string. |
+ __ test(left, Immediate(kSmiTagMask)); |
+ __ j(zero, &left_not_string); |
+ __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
+ __ j(above_equal, &left_not_string); |
+ |
+ StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
+ GenerateRegisterArgsPush(masm); |
+ __ TailCallStub(&string_add_left_stub); |
+ |
+ // Left operand is not a string, test right. |
+ __ bind(&left_not_string); |
+ __ test(right, Immediate(kSmiTagMask)); |
+ __ j(zero, &neither_string); |
+ __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
+ __ j(above_equal, &neither_string); |
+ |
+ StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); |
+ GenerateRegisterArgsPush(masm); |
+ __ TailCallStub(&string_add_right_stub); |
+ |
+ // Neither argument is a string. |
+ __ bind(&neither_string); |
+} |
+ |
+ |
+void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { |
+ switch (op_) { |
+ case Token::ADD: |
+ GenerateRegisterArgsPush(masm); |
__ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); |
break; |
- } |
case Token::SUB: |
GenerateRegisterArgsPush(masm); |
__ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); |
@@ -2393,6 +2296,7 @@ |
__ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION); |
break; |
case Token::MOD: |
+ GenerateRegisterArgsPush(masm); |
__ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); |
break; |
case Token::BIT_OR: |