diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 72213dc817..1440305430 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -1773,40 +1773,12 @@ void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 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 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { // 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 @@ void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { // 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 @@ void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { // If all else fails, use the runtime system to get the correct // result. __ bind(&call_runtime); + + // Try to add strings before calling runtime. + if (op_ == Token::ADD) { + GenerateAddStrings(masm); + } + + // Generate the runtime call. + GenerateCallRuntime(masm); +} + + +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; + + // 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: { + 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); - - StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); - __ TailCallStub(&string_add_left_stub); - - 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); - - // Neither argument is a string. - __ bind(&call_add_runtime); __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); break; - } case Token::SUB: GenerateRegisterArgsPush(masm); __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); @@ -2393,6 +2296,7 @@ void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION); break; case Token::MOD: + GenerateRegisterArgsPush(masm); __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); break; case Token::BIT_OR: diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h index 4a56d0d143..fe99dc944c 100644 --- a/src/ia32/code-stubs-ia32.h +++ b/src/ia32/code-stubs-ia32.h @@ -308,6 +308,8 @@ class TypeRecordingBinaryOpStub: public CodeStub { void GenerateHeapNumberStub(MacroAssembler* masm); void GenerateStringStub(MacroAssembler* masm); void GenerateGenericStub(MacroAssembler* masm); + void GenerateAddStrings(MacroAssembler* masm); + void GenerateCallRuntime(MacroAssembler* masm); void GenerateHeapResultAllocation(MacroAssembler* masm, Label* alloc_failure); void GenerateRegisterArgsPush(MacroAssembler* masm);