[Interpreter] Inline the collection of feedback for StrictEqual bytecode handler.

The feedback collection was decoupled from the actual comparison in the
compare bytecode handlers. This involves checks on the type of operands both
when collecting the feedback and when performing the operation. To avoid this
the type feedback is collected inline with the actual comparison.

This cl inlines the type feedback collection for the StrictEqual bytecode
handler. The other compare operations will be handled in subsequent cls.

Bug:

Change-Id: I429ed3c58b344c1c492e743c190bf16ab991ce6e
Reviewed-on: https://chromium-review.googlesource.com/483399
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Commit-Queue: Mythri Alle <mythria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44919}
This commit is contained in:
Mythri 2017-04-24 16:42:52 +01:00 committed by Commit Bot
parent 6cc6672fde
commit f0756b5cc5
3 changed files with 108 additions and 14 deletions

View File

@ -7036,9 +7036,22 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode,
namespace {
void GenerateEqual_Same(CodeStubAssembler* assembler, Node* value,
CodeStubAssembler::Label* if_equal,
CodeStubAssembler::Label* if_notequal) {
Node* CollectFeedbackForString(CodeStubAssembler* assembler,
Node* instance_type) {
Node* feedback = assembler->SelectSmiConstant(
assembler->Word32Equal(
assembler->Word32And(
instance_type, assembler->Int32Constant(kIsNotInternalizedMask)),
assembler->Int32Constant(kInternalizedTag)),
CompareOperationFeedback::kInternalizedString,
CompareOperationFeedback::kString);
return feedback;
}
void GenerateEqual_Same(
CodeStubAssembler* assembler, Node* value,
CodeStubAssembler::Label* if_equal, CodeStubAssembler::Label* if_notequal,
CodeStubAssembler::Variable* var_type_feedback = nullptr) {
// In case of abstract or strict equality checks, we need additional checks
// for NaN values because they are not considered equal, even if both the
// left and the right hand side reference exactly the same value.
@ -7062,6 +7075,11 @@ void GenerateEqual_Same(CodeStubAssembler* assembler, Node* value,
assembler->BIND(&if_valueisnumber);
{
if (var_type_feedback != NULL) {
var_type_feedback->Bind(
assembler->SmiConstant(CompareOperationFeedback::kNumber));
}
// Convert {value} (and therefore {rhs}) to floating point value.
Node* value_value = assembler->LoadHeapNumberValue(value);
@ -7070,10 +7088,40 @@ void GenerateEqual_Same(CodeStubAssembler* assembler, Node* value,
}
assembler->BIND(&if_valueisnotnumber);
if (var_type_feedback != NULL) {
// Collect type feedback.
Node* instance_type = assembler->LoadMapInstanceType(value_map);
Label if_valueisstring(assembler), if_valueisnotstring(assembler);
assembler->Branch(assembler->IsStringInstanceType(instance_type),
&if_valueisstring, &if_valueisnotstring);
assembler->BIND(&if_valueisstring);
{
var_type_feedback->Bind(
CollectFeedbackForString(assembler, instance_type));
assembler->Goto(if_equal);
}
assembler->Bind(&if_valueisnotstring);
{
assembler->GotoIfNot(assembler->IsJSReceiverInstanceType(instance_type),
if_equal);
var_type_feedback->Bind(
assembler->SmiConstant(CompareOperationFeedback::kReceiver));
assembler->Goto(if_equal);
}
} else {
assembler->Goto(if_equal);
}
}
assembler->BIND(&if_valueissmi);
if (var_type_feedback != NULL) {
var_type_feedback->Bind(
assembler->SmiConstant(CompareOperationFeedback::kSignedSmall));
}
assembler->Goto(if_equal);
}
} // namespace
@ -7528,7 +7576,8 @@ Node* CodeStubAssembler::Equal(Node* lhs, Node* rhs, Node* context) {
return result.value();
}
Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs,
Variable* var_type_feedback) {
// Here's pseudo-code for the algorithm below in case of kDontNegateResult
// mode; for kNegateResult mode we properly negate the result.
//
@ -7576,6 +7625,10 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
Label if_equal(this), if_notequal(this), end(this);
VARIABLE(result, MachineRepresentation::kTagged);
if (var_type_feedback != NULL) {
var_type_feedback->Bind(SmiConstant(CompareOperationFeedback::kAny));
}
// Check if {lhs} and {rhs} refer to the same object.
Label if_same(this), if_notsame(this);
Branch(WordEqual(lhs, rhs), &if_same, &if_notsame);
@ -7584,7 +7637,7 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
{
// The {lhs} and {rhs} reference the exact same value, yet we need special
// treatment for HeapNumber, as NaN is not equal to NaN.
GenerateEqual_Same(this, lhs, &if_equal, &if_notequal);
GenerateEqual_Same(this, lhs, &if_equal, &if_notequal, var_type_feedback);
}
BIND(&if_notsame);
@ -7617,6 +7670,11 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
Node* lhs_value = LoadHeapNumberValue(lhs);
Node* rhs_value = SmiToFloat64(rhs);
if (var_type_feedback != NULL) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kNumber));
}
// Perform a floating point comparison of {lhs} and {rhs}.
Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal);
}
@ -7636,6 +7694,11 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
Node* lhs_value = LoadHeapNumberValue(lhs);
Node* rhs_value = LoadHeapNumberValue(rhs);
if (var_type_feedback != NULL) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kNumber));
}
// Perform a floating point comparison of {lhs} and {rhs}.
Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal);
}
@ -7659,6 +7722,9 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
// Load the instance type of {lhs}.
Node* lhs_instance_type = LoadMapInstanceType(lhs_map);
// Load the instance type of {rhs}.
Node* rhs_instance_type = LoadInstanceType(rhs);
// Check if {lhs} is a String.
Label if_lhsisstring(this), if_lhsisnotstring(this);
Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring,
@ -7666,9 +7732,6 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
BIND(&if_lhsisstring);
{
// Load the instance type of {rhs}.
Node* rhs_instance_type = LoadInstanceType(rhs);
// Check if {rhs} is also a String.
Label if_rhsisstring(this, Label::kDeferred),
if_rhsisnotstring(this);
@ -7678,6 +7741,13 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
BIND(&if_rhsisstring);
{
Callable callable = CodeFactory::StringEqual(isolate());
if (var_type_feedback != NULL) {
Node* lhs_feedback =
CollectFeedbackForString(this, lhs_instance_type);
Node* rhs_feedback =
CollectFeedbackForString(this, rhs_instance_type);
var_type_feedback->Bind(SmiOr(lhs_feedback, rhs_feedback));
}
result.Bind(CallStub(callable, NoContextConstant(), lhs, rhs));
Goto(&end);
}
@ -7687,6 +7757,12 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
}
BIND(&if_lhsisnotstring);
GotoIfNot(IsJSReceiverInstanceType(lhs_instance_type), &if_notequal);
GotoIfNot(IsJSReceiverInstanceType(rhs_instance_type), &if_notequal);
if (var_type_feedback != NULL) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kReceiver));
}
Goto(&if_notequal);
}
}
@ -7703,6 +7779,10 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
BIND(&if_rhsissmi);
if (var_type_feedback != NULL) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kSignedSmall));
}
Goto(&if_notequal);
BIND(&if_rhsisnotsmi);
@ -7720,6 +7800,11 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) {
Node* lhs_value = SmiToFloat64(lhs);
Node* rhs_value = LoadHeapNumberValue(rhs);
if (var_type_feedback != NULL) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kNumber));
}
// Perform a floating point comparison of {lhs} and {rhs}.
Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal);
}

View File

@ -1325,7 +1325,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* Equal(Node* lhs, Node* rhs, Node* context);
Node* StrictEqual(Node* lhs, Node* rhs);
Node* StrictEqual(Node* lhs, Node* rhs, Variable* var_type_feedback = NULL);
// ECMA#sec-samevalue
// Similar to StrictEqual except that NaNs are treated as equal and minus zero

View File

@ -2158,7 +2158,6 @@ class InterpreterCompareOpAssembler : public InterpreterAssembler {
result = SelectBooleanConstant(SmiLessThanOrEqual(rhs, lhs));
break;
case Token::EQ:
case Token::EQ_STRICT:
result = SelectBooleanConstant(WordEqual(lhs, rhs));
break;
default:
@ -2255,8 +2254,7 @@ class InterpreterCompareOpAssembler : public InterpreterAssembler {
result = SelectBooleanConstant(
Float64GreaterThanOrEqual(lhs_float, rhs_float));
break;
case Token::EQ:
case Token::EQ_STRICT: {
case Token::EQ: {
Label check_nan(this);
var_result.Bind(BooleanConstant(false));
Branch(Float64Equal(lhs_float, rhs_float), &check_nan,
@ -2445,7 +2443,18 @@ IGNITION_HANDLER(TestEqual, InterpreterCompareOpAssembler) {
//
// Test if the value in the <src> register is strictly equal to the accumulator.
IGNITION_HANDLER(TestEqualStrict, InterpreterCompareOpAssembler) {
CompareOpWithFeedback(Token::Value::EQ_STRICT);
Node* reg_index = BytecodeOperandReg(0);
Node* lhs = LoadRegister(reg_index);
Node* rhs = GetAccumulator();
Variable var_type_feedback(this, MachineRepresentation::kTaggedSigned);
Node* result = StrictEqual(lhs, rhs, &var_type_feedback);
Node* slot_index = BytecodeOperandIdx(1);
Node* feedback_vector = LoadFeedbackVector();
UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index);
SetAccumulator(result);
Dispatch();
}
// TestLessThan <src>