Commit 05675403 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[bigint,csa] Record BigInt type feedback in comparison operations.

R=jkummerow@chromium.org

Bug: v8:6791
Change-Id: I6664ce5b9d208f2cb1e8320c9cc9a67a682316a7
Reviewed-on: https://chromium-review.googlesource.com/817316
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50022}
parent a30dbf67
......@@ -8513,11 +8513,6 @@ Node* CodeStubAssembler::RelationalComparison(Operation op, Node* lhs,
BIND(&if_lhsisbigint);
{
if (var_type_feedback != nullptr) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kAny));
}
Label if_rhsisheapnumber(this), if_rhsisbigint(this),
if_rhsisnotnumeric(this);
GotoIf(IsHeapNumberMap(rhs_map), &if_rhsisheapnumber);
......@@ -8527,6 +8522,10 @@ Node* CodeStubAssembler::RelationalComparison(Operation op, Node* lhs,
BIND(&if_rhsisheapnumber);
{
if (var_type_feedback != nullptr) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kAny));
}
result.Bind(CallRuntime(Runtime::kBigIntCompareToNumber,
NoContextConstant(), SmiConstant(op), lhs,
rhs));
......@@ -8535,6 +8534,10 @@ Node* CodeStubAssembler::RelationalComparison(Operation op, Node* lhs,
BIND(&if_rhsisbigint);
{
if (var_type_feedback != nullptr) {
CombineFeedback(var_type_feedback,
SmiConstant(CompareOperationFeedback::kBigInt));
}
result.Bind(CallRuntime(Runtime::kBigIntCompareToBigInt,
NoContextConstant(), SmiConstant(op), lhs,
rhs));
......@@ -8543,6 +8546,10 @@ Node* CodeStubAssembler::RelationalComparison(Operation op, Node* lhs,
BIND(&if_rhsisnotnumeric);
{
if (var_type_feedback != nullptr) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kAny));
}
// Convert the {rhs} to a Numeric; we don't need to perform
// dedicated ToPrimitive(rhs, hint Number) operation, as the
// ToNumeric(rhs) will by itself already invoke ToPrimitive with
......@@ -8767,10 +8774,11 @@ void CodeStubAssembler::GenerateEqual_Same(Node* value, Label* if_equal,
if (var_type_feedback != nullptr) {
Node* instance_type = LoadMapInstanceType(value_map);
Label if_string(this), if_receiver(this), if_symbol(this),
Label if_string(this), if_receiver(this), if_symbol(this), if_bigint(this),
if_other(this, Label::kDeferred);
GotoIf(IsStringInstanceType(instance_type), &if_string);
GotoIf(IsJSReceiverInstanceType(instance_type), &if_receiver);
GotoIf(IsBigIntInstanceType(instance_type), &if_bigint);
Branch(IsSymbolInstanceType(instance_type), &if_symbol, &if_other);
BIND(&if_string);
......@@ -8794,8 +8802,12 @@ void CodeStubAssembler::GenerateEqual_Same(Node* value, Label* if_equal,
Goto(if_equal);
}
// TODO(neis): Introduce BigInt CompareOperationFeedback and collect here
// and elsewhere?
BIND(&if_bigint);
{
CombineFeedback(var_type_feedback,
SmiConstant(CompareOperationFeedback::kBigInt));
Goto(if_equal);
}
BIND(&if_other);
{
......@@ -9008,10 +9020,6 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context,
BIND(&if_left_bigint);
{
if (var_type_feedback != nullptr) {
var_type_feedback->Bind(SmiConstant(CompareOperationFeedback::kAny));
}
Label if_right_heapnumber(this), if_right_bigint(this),
if_right_string(this), if_right_boolean(this);
GotoIf(IsHeapNumberMap(right_map), &if_right_heapnumber);
......@@ -9023,6 +9031,10 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context,
BIND(&if_right_heapnumber);
{
if (var_type_feedback != nullptr) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kAny));
}
result.Bind(CallRuntime(Runtime::kBigIntEqualToNumber,
NoContextConstant(), left, right));
Goto(&end);
......@@ -9030,6 +9042,10 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context,
BIND(&if_right_bigint);
{
if (var_type_feedback != nullptr) {
CombineFeedback(var_type_feedback,
SmiConstant(CompareOperationFeedback::kBigInt));
}
result.Bind(CallRuntime(Runtime::kBigIntEqualToBigInt,
NoContextConstant(), left, right));
Goto(&end);
......@@ -9037,6 +9053,10 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context,
BIND(&if_right_string);
{
if (var_type_feedback != nullptr) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kAny));
}
result.Bind(CallRuntime(Runtime::kBigIntEqualToString,
NoContextConstant(), left, right));
Goto(&end);
......@@ -9044,6 +9064,10 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context,
BIND(&if_right_boolean);
{
if (var_type_feedback != nullptr) {
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kAny));
}
var_right.Bind(LoadObjectField(right, Oddball::kToNumberOffset));
Goto(&loop);
}
......@@ -9383,10 +9407,8 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs,
BIND(&if_rhsisbigint);
{
if (var_type_feedback != nullptr) {
CSA_ASSERT(
this,
WordEqual(var_type_feedback->value(),
SmiConstant(CompareOperationFeedback::kAny)));
var_type_feedback->Bind(
SmiConstant(CompareOperationFeedback::kBigInt));
}
result.Bind(CallRuntime(Runtime::kBigIntEqualToBigInt,
NoContextConstant(), lhs, rhs));
......
......@@ -644,6 +644,7 @@ struct JSOperatorGlobalCache final {
k##Name##InternalizedStringOperator; \
Name##Operator<CompareOperationHint::kString> k##Name##StringOperator; \
Name##Operator<CompareOperationHint::kSymbol> k##Name##SymbolOperator; \
Name##Operator<CompareOperationHint::kBigInt> k##Name##BigIntOperator; \
Name##Operator<CompareOperationHint::kReceiver> k##Name##ReceiverOperator; \
Name##Operator<CompareOperationHint::kAny> k##Name##AnyOperator;
COMPARE_OP_LIST(COMPARE_OP)
......@@ -706,6 +707,8 @@ BINARY_OP_LIST(BINARY_OP)
return &cache_.k##Name##StringOperator; \
case CompareOperationHint::kSymbol: \
return &cache_.k##Name##SymbolOperator; \
case CompareOperationHint::kBigInt: \
return &cache_.k##Name##BigIntOperator; \
case CompareOperationHint::kReceiver: \
return &cache_.k##Name##ReceiverOperator; \
case CompareOperationHint::kAny: \
......
......@@ -90,6 +90,7 @@ class JSSpeculativeBinopBuilder final {
case CompareOperationHint::kNone:
case CompareOperationHint::kString:
case CompareOperationHint::kSymbol:
case CompareOperationHint::kBigInt:
case CompareOperationHint::kReceiver:
case CompareOperationHint::kInternalizedString:
break;
......
......@@ -47,6 +47,7 @@ class JSBinopReduction final {
case CompareOperationHint::kNone:
case CompareOperationHint::kString:
case CompareOperationHint::kSymbol:
case CompareOperationHint::kBigInt:
case CompareOperationHint::kReceiver:
case CompareOperationHint::kInternalizedString:
break;
......
......@@ -198,6 +198,8 @@ CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
return CompareOperationHint::kString;
case CompareOperationFeedback::kSymbol:
return CompareOperationHint::kSymbol;
case CompareOperationFeedback::kBigInt:
return CompareOperationHint::kBigInt;
case CompareOperationFeedback::kReceiver:
return CompareOperationHint::kReceiver;
default:
......
......@@ -1286,6 +1286,7 @@ class BinaryOperationFeedback {
// kSignedSmall -> kNumber -> kNumberOrOddball -> kAny
// kInternalizedString -> kString -> kAny
// kSymbol -> kAny
// kBigInt -> kAny
// kReceiver -> kAny
//
// This is distinct from BinaryOperationFeedback on purpose, because the
......@@ -1301,6 +1302,7 @@ class CompareOperationFeedback {
kString = 0x18,
kSymbol = 0x20,
kReceiver = 0x40,
kBigInt = 0x80,
kAny = 0xff
};
};
......
......@@ -45,6 +45,8 @@ std::ostream& operator<<(std::ostream& os, CompareOperationHint hint) {
return os << "String";
case CompareOperationHint::kSymbol:
return os << "Symbol";
case CompareOperationHint::kBigInt:
return os << "BigInt";
case CompareOperationHint::kReceiver:
return os << "Receiver";
case CompareOperationHint::kAny:
......
......@@ -38,6 +38,7 @@ enum class CompareOperationHint : uint8_t {
kInternalizedString,
kString,
kSymbol,
kBigInt,
kReceiver,
kAny
};
......
......@@ -1822,6 +1822,49 @@ TEST(InterpreterHeapNumberComparisons) {
}
}
TEST(InterpreterBigIntComparisons) {
// This test only checks that the recorded type feedback is kBigInt.
AstBigInt inputs[] = {AstBigInt("0"), AstBigInt("-42"),
AstBigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")};
for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
Token::Value comparison = kComparisonTypes[c];
for (size_t i = 0; i < arraysize(inputs); i++) {
for (size_t j = 0; j < arraysize(inputs); j++) {
HandleAndZoneScope handles;
Isolate* isolate = handles.main_isolate();
Zone* zone = handles.main_zone();
AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
isolate->heap()->HashSeed());
FeedbackVectorSpec feedback_spec(zone);
BytecodeArrayBuilder builder(zone, 1, 1, &feedback_spec);
FeedbackSlot slot = feedback_spec.AddCompareICSlot();
Handle<i::FeedbackMetadata> metadata =
NewFeedbackMetadata(isolate, &feedback_spec);
Register r0(0);
builder.LoadLiteral(inputs[i])
.StoreAccumulatorInRegister(r0)
.LoadLiteral(inputs[j])
.CompareOperation(comparison, r0, GetIndex(slot))
.Return();
ast_factory.Internalize(isolate);
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
CHECK(return_value->IsBoolean());
Object* feedback = callable.vector()->Get(slot);
CHECK(feedback->IsSmi());
CHECK_EQ(CompareOperationFeedback::kBigInt,
static_cast<Smi*>(feedback)->value());
}
}
}
}
TEST(InterpreterStringComparisons) {
HandleAndZoneScope handles;
Isolate* isolate = handles.main_isolate();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment