| Index: src/ia32/codegen-ia32.cc
|
| diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
|
| index 0228be938564a94fa08f0b8829df8fa8e4ed7319..970a4ea8b6f360ebb68a58721af10cc08a1d5c61 100644
|
| --- a/src/ia32/codegen-ia32.cc
|
| +++ b/src/ia32/codegen-ia32.cc
|
| @@ -919,15 +919,15 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
|
| Result left = frame_->Pop();
|
|
|
| if (op == Token::ADD) {
|
| - bool left_is_string = left.static_type().is_jsstring();
|
| - bool right_is_string = right.static_type().is_jsstring();
|
| + bool left_is_string = left.is_constant() && left.handle()->IsString();
|
| + bool right_is_string = right.is_constant() && right.handle()->IsString();
|
| if (left_is_string || right_is_string) {
|
| frame_->Push(&left);
|
| frame_->Push(&right);
|
| Result answer;
|
| if (left_is_string) {
|
| if (right_is_string) {
|
| - // TODO(lrn): if (left.is_constant() && right.is_constant())
|
| + // TODO(lrn): if both are constant strings
|
| // -- do a compile time cons, if allocation during codegen is allowed.
|
| answer = frame_->CallRuntime(Runtime::kStringAdd, 2);
|
| } else {
|
| @@ -938,7 +938,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
|
| answer =
|
| frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2);
|
| }
|
| - answer.set_static_type(StaticType::jsstring());
|
| frame_->Push(&answer);
|
| return;
|
| }
|
| @@ -6854,9 +6853,45 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
|
| // result.
|
| __ bind(&call_runtime);
|
| switch (op_) {
|
| - case Token::ADD:
|
| + case Token::ADD: {
|
| + // Test for string arguments before calling runtime.
|
| + Label not_strings, both_strings, not_string1, string1;
|
| + Result answer;
|
| + __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
|
| + __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
|
| + __ test(eax, Immediate(kSmiTagMask));
|
| + __ j(zero, ¬_string1);
|
| + __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, eax);
|
| + __ j(above_equal, ¬_string1);
|
| +
|
| + // First argument is a a string, test second.
|
| + __ test(edx, Immediate(kSmiTagMask));
|
| + __ j(zero, &string1);
|
| + __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx);
|
| + __ j(above_equal, &string1);
|
| +
|
| + // First and second argument are strings.
|
| + __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2);
|
| +
|
| + // Only first argument is a string.
|
| + __ bind(&string1);
|
| + __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION);
|
| +
|
| + // First argument was not a string, test second.
|
| + __ bind(¬_string1);
|
| + __ test(edx, Immediate(kSmiTagMask));
|
| + __ j(zero, ¬_strings);
|
| + __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx);
|
| + __ j(above_equal, ¬_strings);
|
| +
|
| + // Only second argument is a string.
|
| + __ InvokeBuiltin(Builtins::STRING_ADD_RIGHT, JUMP_FUNCTION);
|
| +
|
| + __ bind(¬_strings);
|
| + // Neither argument is a string.
|
| __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
|
| break;
|
| + }
|
| case Token::SUB:
|
| __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
|
| break;
|
|
|