Index: src/code-stubs.cc |
diff --git a/src/code-stubs.cc b/src/code-stubs.cc |
index 14e98beb675af2440b02b66d1ecd5181818bdade..08d8a7233ca591ed1eb98aaa25b6dd8e14aa351f 100644 |
--- a/src/code-stubs.cc |
+++ b/src/code-stubs.cc |
@@ -910,31 +910,42 @@ compiler::Node* AddStub::Generate(CodeStubAssembler* assembler, |
compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
compiler::Node* left, |
compiler::Node* right, |
- compiler::Node* context) { |
+ compiler::Node* context, |
+ compiler::Node* type_feedback_vector, |
+ compiler::Node* slot_id) { |
typedef CodeStubAssembler::Label Label; |
typedef compiler::Node Node; |
typedef CodeStubAssembler::Variable Variable; |
+ bool collect_type_feedback = (type_feedback_vector != NULL); |
+ |
// Shared entry for floating point subtraction. |
Label do_fsub(assembler), end(assembler); |
Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64), |
var_fsub_rhs(assembler, MachineRepresentation::kFloat64); |
+ Variable var_type_feedback(assembler, MachineRepresentation::kWord32); |
Benedikt Meurer
2016/08/08 04:56:13
I'm not sure if this will scale, because
(a) it'l
mythria
2016/08/08 07:17:36
Thanks Benedikt, I add a subtract stub that deals
|
// We might need to loop several times due to ToPrimitive and/or ToNumber |
// conversions. |
Variable var_lhs(assembler, MachineRepresentation::kTagged), |
var_rhs(assembler, MachineRepresentation::kTagged), |
var_result(assembler, MachineRepresentation::kTagged); |
- Variable* loop_vars[2] = {&var_lhs, &var_rhs}; |
- Label loop(assembler, 2, loop_vars); |
+ Variable* loop_vars[3] = {&var_lhs, &var_rhs, &var_type_feedback}; |
+ Label loop(assembler, 3, loop_vars); |
var_lhs.Bind(left); |
var_rhs.Bind(right); |
+ // Start with Smi and keep growing up the lattice. This would avoid |
+ // incorrectly collecting Smi type after the ToNumber conversion. |
+ var_type_feedback.Bind( |
+ assembler->Int32Constant(BinaryOpTypeFeedback::SmiType::encode(1))); |
assembler->Goto(&loop); |
+ |
assembler->Bind(&loop); |
{ |
// Load the current {lhs} and {rhs} values. |
Node* lhs = var_lhs.value(); |
Node* rhs = var_rhs.value(); |
+ Node* type_feedback = var_type_feedback.value(); |
// Check if the {lhs} is a Smi or a HeapObject. |
Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); |
@@ -959,13 +970,23 @@ compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
assembler->Bind(&if_overflow); |
{ |
+ // lhs, rhs - smi and result - number. combined - number. |
// The result doesn't fit into Smi range. |
+ Node* current_feedback = assembler->Int32Constant( |
+ BinaryOpTypeFeedback::NumberType::encode(1)); |
+ var_type_feedback.Bind( |
+ assembler->Word32Or(type_feedback, current_feedback)); |
var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); |
var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); |
assembler->Goto(&do_fsub); |
} |
assembler->Bind(&if_notoverflow); |
+ // lhs, rhs, result smi. combined - smi. |
+ Node* smi_feedback = |
+ assembler->Int32Constant(BinaryOpTypeFeedback::SmiType::encode(1)); |
+ var_type_feedback.Bind( |
+ assembler->Word32Or(type_feedback, smi_feedback)); |
var_result.Bind(assembler->Projection(0, pair)); |
assembler->Goto(&end); |
} |
@@ -984,6 +1005,10 @@ compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
assembler->Bind(&if_rhsisnumber); |
{ |
+ Node* current_feedback = assembler->Int32Constant( |
+ BinaryOpTypeFeedback::NumberType::encode(1)); |
+ var_type_feedback.Bind( |
+ assembler->Word32Or(type_feedback, current_feedback)); |
// Perform a floating point subtraction. |
var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); |
var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
@@ -992,6 +1017,10 @@ compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
assembler->Bind(&if_rhsisnotnumber); |
{ |
+ Node* current_feedback = assembler->Int32Constant( |
+ BinaryOpTypeFeedback::AnyType::encode(1)); |
+ var_type_feedback.Bind( |
+ assembler->Word32Or(type_feedback, current_feedback)); |
// Convert the {rhs} to a Number first. |
Callable callable = |
CodeFactory::NonNumberToNumber(assembler->isolate()); |
@@ -1022,6 +1051,10 @@ compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
assembler->Bind(&if_rhsissmi); |
{ |
+ Node* current_feedback = assembler->Int32Constant( |
+ BinaryOpTypeFeedback::NumberType::encode(1)); |
+ var_type_feedback.Bind( |
+ assembler->Word32Or(type_feedback, current_feedback)); |
// Perform a floating point subtraction. |
var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); |
@@ -1041,6 +1074,10 @@ compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
assembler->Bind(&if_rhsisnumber); |
{ |
+ Node* current_feedback = assembler->Int32Constant( |
+ BinaryOpTypeFeedback::NumberType::encode(1)); |
+ var_type_feedback.Bind( |
+ assembler->Word32Or(type_feedback, current_feedback)); |
// Perform a floating point subtraction. |
var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
@@ -1049,6 +1086,10 @@ compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
assembler->Bind(&if_rhsisnotnumber); |
{ |
+ Node* current_feedback = assembler->Int32Constant( |
+ BinaryOpTypeFeedback::AnyType::encode(1)); |
+ var_type_feedback.Bind( |
+ assembler->Word32Or(type_feedback, current_feedback)); |
// Convert the {rhs} to a Number first. |
Callable callable = |
CodeFactory::NonNumberToNumber(assembler->isolate()); |
@@ -1060,6 +1101,10 @@ compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
assembler->Bind(&if_lhsisnotnumber); |
{ |
+ Node* current_feedback = |
+ assembler->Int32Constant(BinaryOpTypeFeedback::AnyType::encode(1)); |
+ var_type_feedback.Bind( |
+ assembler->Word32Or(type_feedback, current_feedback)); |
// Convert the {lhs} to a Number first. |
Callable callable = |
CodeFactory::NonNumberToNumber(assembler->isolate()); |
@@ -1077,7 +1122,22 @@ compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
var_result.Bind(assembler->ChangeFloat64ToTagged(value)); |
assembler->Goto(&end); |
} |
+ |
assembler->Bind(&end); |
+ if (collect_type_feedback) { |
+ // Combine the current type with previous feedback and store it into the |
+ // feedback slot. |
+ Node* previous_feedback_smi = |
+ assembler->LoadFixedArrayElement(type_feedback_vector, slot_id); |
+ // TODO(mythria): Add a DCHECK to verify the loaded value is an Smi. |
+ // ASSERT (WordIsSmi(previous_feedback)); |
+ Node* previous_feedback = assembler->SmiUntag(previous_feedback_smi); |
+ Node* combined_feedback = |
+ assembler->Word32Or(previous_feedback, var_type_feedback.value()); |
+ assembler->StoreFixedArrayElement(type_feedback_vector, slot_id, |
+ assembler->SmiTag(combined_feedback), |
+ SKIP_WRITE_BARRIER); |
+ } |
return var_result.value(); |
} |