Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index ef07d96a9c655119cc1e37cc512f685bf2bd82e5..0bcc9adfb51e84d5b6fc1a156cf8279e5f93058d 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -7501,7 +7501,7 @@ HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
bool returns_original_input, |
CountOperation* expr) { |
// The input to the count operation is on top of the expression stack. |
- TypeInfo info = expr->type(); |
+ Handle<Type> info = expr->type(); |
Representation rep = Representation::FromType(info); |
if (rep.IsNone() || rep.IsTagged()) { |
rep = Representation::Smi(); |
@@ -7865,7 +7865,8 @@ HInstruction* HGraphBuilder::BuildBinaryOperation( |
Handle<Type> left_type, |
Handle<Type> right_type, |
Handle<Type> result_type, |
- Maybe<int> fixed_right_arg) { |
+ Maybe<int> fixed_right_arg, |
+ bool binop_stub) { |
Representation left_rep = Representation::FromType(left_type); |
Representation right_rep = Representation::FromType(right_type); |
@@ -7894,75 +7895,92 @@ HInstruction* HGraphBuilder::BuildBinaryOperation( |
right_rep = Representation::FromType(right_type); |
} |
+ if (binop_stub) { |
+ left = EnforceNumberType(left, left_type); |
+ right = EnforceNumberType(right, right_type); |
+ } |
+ |
Representation result_rep = Representation::FromType(result_type); |
- bool is_string_add = op == Token::ADD && |
- (left_type->Is(Type::String()) || |
- right_type->Is(Type::String())); |
+ bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
+ (right_rep.IsTagged() && !right_rep.IsSmi()); |
+ bool is_string_add = op == Token::ADD && |
+ (left_type->Is(Type::String()) || |
+ right_type->Is(Type::String())); |
HInstruction* instr = NULL; |
- switch (op) { |
- case Token::ADD: |
- if (is_string_add) { |
- StringAddFlags flags = STRING_ADD_CHECK_BOTH; |
- if (left_type->Is(Type::String())) { |
- BuildCheckHeapObject(left); |
- AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
- flags = STRING_ADD_CHECK_RIGHT; |
- } |
- if (right_type->Is(Type::String())) { |
- BuildCheckHeapObject(right); |
- AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
- flags = (flags == STRING_ADD_CHECK_BOTH) |
- ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; |
+ // Only the stub is allowed to call into the runtime, since otherwise we would |
+ // inline several instructions (including the two pushes) for every tagged |
+ // operation in optimized code, which is more expensive, than a stub call. |
+ if (binop_stub && is_non_primitive && !is_string_add) { |
+ HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); |
+ Add<HPushArgument>(left); |
+ Add<HPushArgument>(right); |
+ instr = NewUncasted<HInvokeFunction>(function, 2); |
+ } else { |
+ switch (op) { |
+ case Token::ADD: |
+ if (is_string_add) { |
+ StringAddFlags flags = STRING_ADD_CHECK_BOTH; |
+ if (left_type->Is(Type::String())) { |
+ BuildCheckHeapObject(left); |
+ AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
+ flags = STRING_ADD_CHECK_RIGHT; |
+ } |
+ if (right_type->Is(Type::String())) { |
+ BuildCheckHeapObject(right); |
+ AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
+ flags = (flags == STRING_ADD_CHECK_BOTH) |
+ ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; |
+ } |
+ instr = NewUncasted<HStringAdd>(left, right, flags); |
+ } else { |
+ instr = NewUncasted<HAdd>(left, right); |
} |
- instr = NewUncasted<HStringAdd>(left, right, flags); |
- } else { |
- instr = NewUncasted<HAdd>(left, right); |
- } |
- break; |
- case Token::SUB: |
- instr = NewUncasted<HSub>(left, right); |
- break; |
- case Token::MUL: |
- instr = NewUncasted<HMul>(left, right); |
- break; |
- case Token::MOD: |
- instr = NewUncasted<HMod>(left, right, fixed_right_arg); |
- break; |
- case Token::DIV: |
- instr = NewUncasted<HDiv>(left, right); |
- break; |
- case Token::BIT_XOR: |
- case Token::BIT_AND: |
- instr = NewUncasted<HBitwise>(op, left, right); |
- break; |
- case Token::BIT_OR: { |
- HValue* operand, *shift_amount; |
- if (left_type->Is(Type::Signed32()) && |
- right_type->Is(Type::Signed32()) && |
- MatchRotateRight(left, right, &operand, &shift_amount)) { |
- instr = NewUncasted<HRor>(operand, shift_amount); |
- } else { |
+ break; |
+ case Token::SUB: |
+ instr = NewUncasted<HSub>(left, right); |
+ break; |
+ case Token::MUL: |
+ instr = NewUncasted<HMul>(left, right); |
+ break; |
+ case Token::MOD: |
+ instr = NewUncasted<HMod>(left, right, fixed_right_arg); |
+ break; |
+ case Token::DIV: |
+ instr = NewUncasted<HDiv>(left, right); |
+ break; |
+ case Token::BIT_XOR: |
+ case Token::BIT_AND: |
instr = NewUncasted<HBitwise>(op, left, right); |
+ break; |
+ case Token::BIT_OR: { |
+ HValue* operand, *shift_amount; |
+ if (left_type->Is(Type::Signed32()) && |
+ right_type->Is(Type::Signed32()) && |
+ MatchRotateRight(left, right, &operand, &shift_amount)) { |
+ instr = NewUncasted<HRor>(operand, shift_amount); |
+ } else { |
+ instr = NewUncasted<HBitwise>(op, left, right); |
+ } |
+ break; |
} |
- break; |
+ case Token::SAR: |
+ instr = NewUncasted<HSar>(left, right); |
+ break; |
+ case Token::SHR: |
+ instr = NewUncasted<HShr>(left, right); |
+ if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
+ CanBeZero(right)) { |
+ graph()->RecordUint32Instruction(instr); |
+ } |
+ break; |
+ case Token::SHL: |
+ instr = NewUncasted<HShl>(left, right); |
+ break; |
+ default: |
+ UNREACHABLE(); |
} |
- case Token::SAR: |
- instr = NewUncasted<HSar>(left, right); |
- break; |
- case Token::SHR: |
- instr = NewUncasted<HShr>(left, right); |
- if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
- CanBeZero(right)) { |
- graph()->RecordUint32Instruction(instr); |
- } |
- break; |
- case Token::SHL: |
- instr = NewUncasted<HShl>(left, right); |
- break; |
- default: |
- UNREACHABLE(); |
} |
if (instr->IsBinaryOperation()) { |
@@ -7970,6 +7988,19 @@ HInstruction* HGraphBuilder::BuildBinaryOperation( |
binop->set_observed_input_representation(1, left_rep); |
binop->set_observed_input_representation(2, right_rep); |
binop->initialize_output_representation(result_rep); |
+ if (binop_stub) { |
+ // Stub should not call into stub. |
+ instr->SetFlag(HValue::kCannotBeTagged); |
+ // And should truncate on HForceRepresentation already. |
+ if (left->IsForceRepresentation()) { |
+ left->CopyFlag(HValue::kTruncatingToSmi, instr); |
+ left->CopyFlag(HValue::kTruncatingToInt32, instr); |
+ } |
+ if (right->IsForceRepresentation()) { |
+ right->CopyFlag(HValue::kTruncatingToSmi, instr); |
+ right->CopyFlag(HValue::kTruncatingToInt32, instr); |
+ } |
+ } |
} |
return instr; |
} |