Index: src/ia32/code-stubs-ia32.cc |
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc |
index e6511a788c5c97f2c633e175367518f8305a42c6..275e8e29a1ee5ca8072b0a3d3c310132005c0f09 100644 |
--- a/src/ia32/code-stubs-ia32.cc |
+++ b/src/ia32/code-stubs-ia32.cc |
@@ -446,6 +446,9 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) { |
case TRBinaryOpIC::ODDBALL: |
GenerateOddballStub(masm); |
break; |
+ case TRBinaryOpIC::BOTH_STRING: |
+ GenerateBothStringStub(masm); |
+ break; |
case TRBinaryOpIC::STRING: |
GenerateStringStub(masm); |
break; |
@@ -909,6 +912,38 @@ void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) { |
} |
+void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) { |
+ Label call_runtime; |
+ ASSERT(operands_type_ == TRBinaryOpIC::BOTH_STRING); |
+ ASSERT(op_ == Token::ADD); |
+ // If both arguments are strings, call the string add stub. |
+ // Otherwise, do a transition. |
+ |
+ // Registers containing left and right operands respectively. |
+ Register left = edx; |
+ Register right = eax; |
+ |
+ // Test if left operand is a string. |
+ __ test(left, Immediate(kSmiTagMask)); |
+ __ j(zero, &call_runtime); |
+ __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
+ __ j(above_equal, &call_runtime); |
+ |
+ // Test if right operand is a string. |
+ __ test(right, Immediate(kSmiTagMask)); |
+ __ j(zero, &call_runtime); |
+ __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
+ __ j(above_equal, &call_runtime); |
+ |
+ StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); |
+ GenerateRegisterArgsPush(masm); |
+ __ TailCallStub(&string_add_stub); |
+ |
+ __ bind(&call_runtime); |
+ GenerateTypeTransition(masm); |
+} |
+ |
+ |
void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
Label call_runtime; |
ASSERT(operands_type_ == TRBinaryOpIC::INT32); |