Revert "[turbofan] Improve equality on NumberOrOddball"
This reverts commit 6204768bab
.
Reason for revert: A number of Clusterfuzz reports (e.g. https://bugs.chromium.org/p/chromium/issues/detail?id=1079474)
Original change's description:
> [turbofan] Improve equality on NumberOrOddball
>
> This CL cleans up CompareOperationFeedback by replacing it with a
> composable set of flags. The interpreter is changed to collect
> more specific feedback for abstract equality, especially if oddballs
> are involved.
>
> TurboFan is changed to construct SpeculativeNumberEqual operator
> instead of the generic JSEqual in many more cases. This change has
> shown a local speedup of a factor of 3-10, because the specific
> operator is way faster than calling into the generic builtin, but
> it also enables additional optimizations, further improving
> runtime performance.
>
> Bug: v8:5660
> Change-Id: I856752caa707e9a4f742c6e7a9c75552fb431d28
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2162854
> Reviewed-by: Mythri Alle <mythria@chromium.org>
> Reviewed-by: Georg Neis <neis@chromium.org>
> Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#67645}
TBR=rmcilroy@chromium.org,neis@chromium.org,mythria@chromium.org,nicohartmann@chromium.org
Change-Id: I3410310ed2b1ff2eaee70c1b91c3151d35866108
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:5660
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2190414
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67673}
This commit is contained in:
parent
f701df1f3c
commit
f4b98cc654
@ -11171,8 +11171,7 @@ void CodeStubAssembler::GenerateEqual_Same(SloppyTNode<Object> value,
|
||||
|
||||
BIND(&if_boolean);
|
||||
{
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kNumberOrOddball);
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kAny);
|
||||
Goto(if_equal);
|
||||
}
|
||||
|
||||
@ -11254,67 +11253,60 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
BIND(&if_left_smi);
|
||||
{
|
||||
Label if_right_smi(this), if_right_not_smi(this);
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kSignedSmall);
|
||||
Branch(TaggedIsSmi(right), &if_right_smi, &if_right_not_smi);
|
||||
|
||||
BIND(&if_right_smi);
|
||||
{
|
||||
// We have already checked for {left} and {right} being the same value,
|
||||
// so when we get here they must be different Smis.
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kSignedSmall);
|
||||
Goto(&if_notequal);
|
||||
}
|
||||
|
||||
BIND(&if_right_not_smi);
|
||||
TNode<Map> right_map = LoadMap(CAST(right));
|
||||
Label if_right_heapnumber(this), if_right_boolean(this),
|
||||
if_right_bigint(this, Label::kDeferred),
|
||||
if_right_receiver(this, Label::kDeferred);
|
||||
GotoIf(IsHeapNumberMap(right_map), &if_right_heapnumber);
|
||||
// {left} is Smi and {right} is not HeapNumber or Smi.
|
||||
if (var_type_feedback != nullptr) {
|
||||
*var_type_feedback = SmiConstant(CompareOperationFeedback::kAny);
|
||||
}
|
||||
GotoIf(IsBooleanMap(right_map), &if_right_boolean);
|
||||
TNode<Uint16T> right_type = LoadMapInstanceType(right_map);
|
||||
GotoIf(IsStringInstanceType(right_type), &do_right_stringtonumber);
|
||||
GotoIf(IsBigIntInstanceType(right_type), &if_right_bigint);
|
||||
Branch(IsJSReceiverInstanceType(right_type), &if_right_receiver,
|
||||
&if_notequal);
|
||||
|
||||
BIND(&if_right_heapnumber);
|
||||
{
|
||||
TNode<Map> right_map = LoadMap(CAST(right));
|
||||
Label if_right_heapnumber(this), if_right_oddball(this),
|
||||
if_right_bigint(this, Label::kDeferred),
|
||||
if_right_receiver(this, Label::kDeferred);
|
||||
GotoIf(IsHeapNumberMap(right_map), &if_right_heapnumber);
|
||||
var_left_float = SmiToFloat64(CAST(left));
|
||||
var_right_float = LoadHeapNumberValue(CAST(right));
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber);
|
||||
Goto(&do_float_comparison);
|
||||
}
|
||||
|
||||
// {left} is Smi and {right} is not HeapNumber or Smi.
|
||||
TNode<Uint16T> right_type = LoadMapInstanceType(right_map);
|
||||
GotoIf(IsStringInstanceType(right_type), &do_right_stringtonumber);
|
||||
GotoIf(IsOddballInstanceType(right_type), &if_right_oddball);
|
||||
GotoIf(IsBigIntInstanceType(right_type), &if_right_bigint);
|
||||
GotoIf(IsJSReceiverInstanceType(right_type), &if_right_receiver);
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kAny);
|
||||
Goto(&if_notequal);
|
||||
BIND(&if_right_boolean);
|
||||
{
|
||||
var_right = LoadObjectField(CAST(right), Oddball::kToNumberOffset);
|
||||
Goto(&loop);
|
||||
}
|
||||
|
||||
BIND(&if_right_heapnumber);
|
||||
{
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber);
|
||||
var_left_float = SmiToFloat64(CAST(left));
|
||||
var_right_float = LoadHeapNumberValue(CAST(right));
|
||||
Goto(&do_float_comparison);
|
||||
}
|
||||
BIND(&if_right_bigint);
|
||||
{
|
||||
result = CAST(CallRuntime(Runtime::kBigIntEqualToNumber,
|
||||
NoContextConstant(), right, left));
|
||||
Goto(&end);
|
||||
}
|
||||
|
||||
BIND(&if_right_oddball);
|
||||
{
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kOddball);
|
||||
GotoIfNot(IsBooleanMap(right_map), &if_notequal);
|
||||
var_right = LoadObjectField(CAST(right), Oddball::kToNumberOffset);
|
||||
Goto(&loop);
|
||||
}
|
||||
|
||||
BIND(&if_right_bigint);
|
||||
{
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kBigInt);
|
||||
result = CAST(CallRuntime(Runtime::kBigIntEqualToNumber,
|
||||
NoContextConstant(), right, left));
|
||||
Goto(&end);
|
||||
}
|
||||
|
||||
BIND(&if_right_receiver);
|
||||
{
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kReceiver);
|
||||
Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate());
|
||||
var_right = CallStub(callable, context, right);
|
||||
Goto(&loop);
|
||||
}
|
||||
BIND(&if_right_receiver);
|
||||
{
|
||||
Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate());
|
||||
var_right = CallStub(callable, context, right);
|
||||
Goto(&loop);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11353,30 +11345,27 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
BIND(&if_left_number);
|
||||
{
|
||||
Label if_right_not_number(this);
|
||||
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber);
|
||||
GotoIf(Word32NotEqual(left_type, right_type), &if_right_not_number);
|
||||
|
||||
var_left_float = LoadHeapNumberValue(CAST(left));
|
||||
var_right_float = LoadHeapNumberValue(CAST(right));
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber);
|
||||
Goto(&do_float_comparison);
|
||||
|
||||
BIND(&if_right_not_number);
|
||||
{
|
||||
Label if_right_oddball(this);
|
||||
|
||||
Label if_right_boolean(this);
|
||||
if (var_type_feedback != nullptr) {
|
||||
*var_type_feedback = SmiConstant(CompareOperationFeedback::kAny);
|
||||
}
|
||||
GotoIf(IsStringInstanceType(right_type), &do_right_stringtonumber);
|
||||
GotoIf(IsOddballInstanceType(right_type), &if_right_oddball);
|
||||
GotoIf(IsBooleanMap(right_map), &if_right_boolean);
|
||||
GotoIf(IsBigIntInstanceType(right_type), &use_symmetry);
|
||||
GotoIf(IsJSReceiverInstanceType(right_type), &use_symmetry);
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kAny);
|
||||
Goto(&if_notequal);
|
||||
Branch(IsJSReceiverInstanceType(right_type), &use_symmetry,
|
||||
&if_notequal);
|
||||
|
||||
BIND(&if_right_oddball);
|
||||
BIND(&if_right_boolean);
|
||||
{
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kOddball);
|
||||
GotoIfNot(IsBooleanMap(right_map), &if_notequal);
|
||||
var_right = LoadObjectField(CAST(right), Oddball::kToNumberOffset);
|
||||
Goto(&loop);
|
||||
}
|
||||
@ -11387,8 +11376,6 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
{
|
||||
Label if_right_heapnumber(this), if_right_bigint(this),
|
||||
if_right_string(this), if_right_boolean(this);
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kBigInt);
|
||||
|
||||
GotoIf(IsHeapNumberMap(right_map), &if_right_heapnumber);
|
||||
GotoIf(IsBigIntInstanceType(right_type), &if_right_bigint);
|
||||
GotoIf(IsStringInstanceType(right_type), &if_right_string);
|
||||
@ -11398,7 +11385,9 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
|
||||
BIND(&if_right_heapnumber);
|
||||
{
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber);
|
||||
if (var_type_feedback != nullptr) {
|
||||
*var_type_feedback = SmiConstant(CompareOperationFeedback::kAny);
|
||||
}
|
||||
result = CAST(CallRuntime(Runtime::kBigIntEqualToNumber,
|
||||
NoContextConstant(), left, right));
|
||||
Goto(&end);
|
||||
@ -11406,7 +11395,7 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
|
||||
BIND(&if_right_bigint);
|
||||
{
|
||||
// We already have BigInt feedback.
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kBigInt);
|
||||
result = CAST(CallRuntime(Runtime::kBigIntEqualToBigInt,
|
||||
NoContextConstant(), left, right));
|
||||
Goto(&end);
|
||||
@ -11414,7 +11403,9 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
|
||||
BIND(&if_right_string);
|
||||
{
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kString);
|
||||
if (var_type_feedback != nullptr) {
|
||||
*var_type_feedback = SmiConstant(CompareOperationFeedback::kAny);
|
||||
}
|
||||
result = CAST(CallRuntime(Runtime::kBigIntEqualToString,
|
||||
NoContextConstant(), left, right));
|
||||
Goto(&end);
|
||||
@ -11422,8 +11413,9 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
|
||||
BIND(&if_right_boolean);
|
||||
{
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kBoolean);
|
||||
if (var_type_feedback != nullptr) {
|
||||
*var_type_feedback = SmiConstant(CompareOperationFeedback::kAny);
|
||||
}
|
||||
var_right = LoadObjectField(CAST(right), Oddball::kToNumberOffset);
|
||||
Goto(&loop);
|
||||
}
|
||||
@ -11438,42 +11430,29 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
{
|
||||
// {left} is either Null or Undefined. Check if {right} is
|
||||
// undetectable (which includes Null and Undefined).
|
||||
Label if_right_undetectable(this), if_right_number_or_oddball(this),
|
||||
if_right_not_number_or_oddball_or_undetectable(this);
|
||||
GotoIf(IsUndetectableMap(right_map), &if_right_undetectable);
|
||||
GotoIf(IsHeapNumberInstanceType(right_type),
|
||||
&if_right_number_or_oddball);
|
||||
GotoIf(IsOddballInstanceType(right_type),
|
||||
&if_right_number_or_oddball);
|
||||
Goto(&if_right_not_number_or_oddball_or_undetectable);
|
||||
Label if_right_undetectable(this), if_right_not_undetectable(this);
|
||||
Branch(IsUndetectableMap(right_map), &if_right_undetectable,
|
||||
&if_right_not_undetectable);
|
||||
|
||||
BIND(&if_right_undetectable);
|
||||
{
|
||||
// If {right} is undetectable, it must be either also
|
||||
// Null or Undefined, or a Receiver (aka document.all).
|
||||
CombineFeedback(
|
||||
var_type_feedback,
|
||||
CompareOperationFeedback::kReceiverOrNullOrUndefined);
|
||||
if (var_type_feedback != nullptr) {
|
||||
// If {right} is undetectable, it must be either also
|
||||
// Null or Undefined, or a Receiver (aka document.all).
|
||||
*var_type_feedback = SmiConstant(
|
||||
CompareOperationFeedback::kReceiverOrNullOrUndefined);
|
||||
}
|
||||
Goto(&if_equal);
|
||||
}
|
||||
|
||||
BIND(&if_right_number_or_oddball);
|
||||
{
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kNumberOrOddball);
|
||||
Goto(&if_notequal);
|
||||
}
|
||||
|
||||
BIND(&if_right_not_number_or_oddball_or_undetectable);
|
||||
BIND(&if_right_not_undetectable);
|
||||
{
|
||||
if (var_type_feedback != nullptr) {
|
||||
// Track whether {right} is Null, Undefined or Receiver.
|
||||
CombineFeedback(
|
||||
var_type_feedback,
|
||||
*var_type_feedback = SmiConstant(
|
||||
CompareOperationFeedback::kReceiverOrNullOrUndefined);
|
||||
GotoIf(IsJSReceiverInstanceType(right_type), &if_notequal);
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kAny);
|
||||
*var_type_feedback = SmiConstant(CompareOperationFeedback::kAny);
|
||||
}
|
||||
Goto(&if_notequal);
|
||||
}
|
||||
@ -11481,8 +11460,9 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
|
||||
BIND(&if_left_boolean);
|
||||
{
|
||||
CombineFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kBoolean);
|
||||
if (var_type_feedback != nullptr) {
|
||||
*var_type_feedback = SmiConstant(CompareOperationFeedback::kAny);
|
||||
}
|
||||
|
||||
// If {right} is a Boolean too, it must be a different Boolean.
|
||||
GotoIf(TaggedEqual(right_map, left_map), &if_notequal);
|
||||
@ -11565,7 +11545,9 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
{
|
||||
// {right} is a Primitive, and neither Null or Undefined;
|
||||
// convert {left} to Primitive too.
|
||||
CombineFeedback(var_type_feedback, CompareOperationFeedback::kAny);
|
||||
if (var_type_feedback != nullptr) {
|
||||
*var_type_feedback = SmiConstant(CompareOperationFeedback::kAny);
|
||||
}
|
||||
Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate());
|
||||
var_left = CallStub(callable, context, left);
|
||||
Goto(&loop);
|
||||
@ -11576,12 +11558,6 @@ TNode<Oddball> CodeStubAssembler::Equal(SloppyTNode<Object> left,
|
||||
|
||||
BIND(&do_right_stringtonumber);
|
||||
{
|
||||
if (var_type_feedback != nullptr) {
|
||||
TNode<Map> right_map = LoadMap(CAST(right));
|
||||
TNode<Uint16T> right_type = LoadMapInstanceType(right_map);
|
||||
CombineFeedback(var_type_feedback,
|
||||
CollectFeedbackForString(right_type));
|
||||
}
|
||||
var_right = CallBuiltin(Builtins::kStringToNumber, context, right);
|
||||
Goto(&loop);
|
||||
}
|
||||
@ -11860,47 +11836,15 @@ TNode<Oddball> CodeStubAssembler::StrictEqual(
|
||||
|
||||
BIND(&if_lhsisoddball);
|
||||
{
|
||||
Label if_lhsisboolean(this), if_lhsisnotboolean(this);
|
||||
Branch(IsBooleanMap(lhs_map), &if_lhsisboolean,
|
||||
&if_lhsisnotboolean);
|
||||
|
||||
BIND(&if_lhsisboolean);
|
||||
{
|
||||
OverwriteFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kNumberOrOddball);
|
||||
GotoIf(IsBooleanMap(rhs_map), &if_notequal);
|
||||
Goto(&if_not_equivalent_types);
|
||||
}
|
||||
|
||||
BIND(&if_lhsisnotboolean);
|
||||
{
|
||||
Label if_rhsisheapnumber(this), if_rhsisnotheapnumber(this);
|
||||
|
||||
STATIC_ASSERT(LAST_PRIMITIVE_HEAP_OBJECT_TYPE ==
|
||||
ODDBALL_TYPE);
|
||||
GotoIf(Int32LessThan(rhs_instance_type,
|
||||
Int32Constant(ODDBALL_TYPE)),
|
||||
&if_not_equivalent_types);
|
||||
|
||||
Branch(IsHeapNumberMap(rhs_map), &if_rhsisheapnumber,
|
||||
&if_rhsisnotheapnumber);
|
||||
|
||||
BIND(&if_rhsisheapnumber);
|
||||
{
|
||||
OverwriteFeedback(
|
||||
var_type_feedback,
|
||||
CompareOperationFeedback::kNumberOrOddball);
|
||||
Goto(&if_not_equivalent_types);
|
||||
}
|
||||
|
||||
BIND(&if_rhsisnotheapnumber);
|
||||
{
|
||||
OverwriteFeedback(
|
||||
var_type_feedback,
|
||||
CompareOperationFeedback::kReceiverOrNullOrUndefined);
|
||||
Goto(&if_notequal);
|
||||
}
|
||||
}
|
||||
STATIC_ASSERT(LAST_PRIMITIVE_HEAP_OBJECT_TYPE == ODDBALL_TYPE);
|
||||
GotoIf(IsBooleanMap(rhs_map), &if_not_equivalent_types);
|
||||
GotoIf(Int32LessThan(rhs_instance_type,
|
||||
Int32Constant(ODDBALL_TYPE)),
|
||||
&if_not_equivalent_types);
|
||||
OverwriteFeedback(
|
||||
var_type_feedback,
|
||||
CompareOperationFeedback::kReceiverOrNullOrUndefined);
|
||||
Goto(&if_notequal);
|
||||
}
|
||||
|
||||
BIND(&if_lhsissymbol);
|
||||
@ -11956,14 +11900,7 @@ TNode<Oddball> CodeStubAssembler::StrictEqual(
|
||||
}
|
||||
|
||||
BIND(&if_rhsisnotnumber);
|
||||
{
|
||||
TNode<Uint16T> rhs_instance_type = LoadMapInstanceType(rhs_map);
|
||||
GotoIfNot(IsOddballInstanceType(rhs_instance_type),
|
||||
&if_not_equivalent_types);
|
||||
OverwriteFeedback(var_type_feedback,
|
||||
CompareOperationFeedback::kNumberOrOddball);
|
||||
Goto(&if_notequal);
|
||||
}
|
||||
Goto(&if_not_equivalent_types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1348,46 +1348,31 @@ class BinaryOperationFeedback {
|
||||
};
|
||||
|
||||
// Type feedback is encoded in such a way that, we can combine the feedback
|
||||
// at different points by performing an 'OR' operation.
|
||||
// at different points by performing an 'OR' operation. Type feedback moves
|
||||
// to a more generic type when we combine feedback.
|
||||
//
|
||||
// kSignedSmall -> kNumber -> kNumberOrOddball -> kAny
|
||||
// kReceiver -> kReceiverOrNullOrUndefined -> kAny
|
||||
// kInternalizedString -> kString -> kAny
|
||||
// kSymbol -> kAny
|
||||
// kBigInt -> kAny
|
||||
//
|
||||
// This is distinct from BinaryOperationFeedback on purpose, because the
|
||||
// feedback that matters differs greatly as well as the way it is consumed.
|
||||
class CompareOperationFeedback {
|
||||
enum {
|
||||
kSignedSmallFlag = 1 << 0,
|
||||
kOtherNumberFlag = 1 << 1,
|
||||
kBooleanFlag = 1 << 2,
|
||||
kOtherOddballFlag = 1 << 3,
|
||||
kNullOrUndefinedFlag = 1 << 4,
|
||||
kInternalizedStringFlag = 1 << 5,
|
||||
kOtherStringFlag = 1 << 6,
|
||||
kSymbolFlag = 1 << 7,
|
||||
kBigIntFlag = 1 << 8,
|
||||
kReceiverFlag = 1 << 9,
|
||||
kAnyMask = 0x3FF,
|
||||
};
|
||||
|
||||
public:
|
||||
enum Type {
|
||||
kNone = 0,
|
||||
|
||||
kBoolean = kBooleanFlag,
|
||||
kNullOrUndefined = kNullOrUndefinedFlag,
|
||||
kOddball = kBoolean | kOtherOddballFlag | kNullOrUndefined,
|
||||
|
||||
kSignedSmall = kSignedSmallFlag,
|
||||
kNumber = kSignedSmall | kOtherNumberFlag,
|
||||
kNumberOrOddball = kNumber | kOddball,
|
||||
|
||||
kInternalizedString = kInternalizedStringFlag,
|
||||
kString = kInternalizedString | kOtherStringFlag,
|
||||
|
||||
kReceiver = kReceiverFlag,
|
||||
kReceiverOrNullOrUndefined = kReceiver | kNullOrUndefined,
|
||||
|
||||
kBigInt = kBigIntFlag,
|
||||
kSymbol = kSymbolFlag,
|
||||
|
||||
kAny = kAnyMask,
|
||||
enum {
|
||||
kNone = 0x000,
|
||||
kSignedSmall = 0x001,
|
||||
kNumber = 0x003,
|
||||
kNumberOrOddball = 0x007,
|
||||
kInternalizedString = 0x008,
|
||||
kString = 0x018,
|
||||
kSymbol = 0x020,
|
||||
kBigInt = 0x040,
|
||||
kReceiver = 0x080,
|
||||
kReceiverOrNullOrUndefined = 0x180,
|
||||
kAny = 0x1ff
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1393,7 +1393,6 @@ void CodeAssemblerLabel::MergeVariables() {
|
||||
}
|
||||
// If the following asserts, then you've jumped to a label without a bound
|
||||
// variable along that path that expects to merge its value into a phi.
|
||||
// This can also occur if a label is bound that is never jumped to.
|
||||
DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
|
||||
count == merge_count_);
|
||||
USE(count);
|
||||
|
@ -887,12 +887,7 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node) {
|
||||
if (r.BothInputsAre(Type::Signed32()) ||
|
||||
r.BothInputsAre(Type::Unsigned32())) {
|
||||
return r.ChangeToPureOperator(simplified()->NumberEqual());
|
||||
} else if (r.GetCompareNumberOperationHint(&hint) &&
|
||||
hint != NumberOperationHint::kNumberOrOddball) {
|
||||
// SpeculativeNumberEqual[kNumberOrOddball] performs implicit conversion
|
||||
// of oddballs to numbers, so we must not generate it for strict equality.
|
||||
DCHECK(hint == NumberOperationHint::kNumber ||
|
||||
hint == NumberOperationHint::kSignedSmall);
|
||||
} else if (r.GetCompareNumberOperationHint(&hint)) {
|
||||
return r.ChangeToSpeculativeOperator(
|
||||
simplified()->SpeculativeNumberEqual(hint), Type::Boolean());
|
||||
} else if (r.BothInputsAre(Type::Number())) {
|
||||
|
@ -2054,6 +2054,11 @@ class RepresentationSelector {
|
||||
// This doesn't make sense for compare operations.
|
||||
UNREACHABLE();
|
||||
case NumberOperationHint::kNumberOrOddball:
|
||||
// Abstract and strict equality don't perform ToNumber conversions
|
||||
// on Oddballs, so make sure we don't accidentially sneak in a
|
||||
// hint with Oddball feedback here.
|
||||
DCHECK_NE(IrOpcode::kSpeculativeNumberEqual, node->opcode());
|
||||
V8_FALLTHROUGH;
|
||||
case NumberOperationHint::kNumber:
|
||||
VisitBinop<T>(node,
|
||||
CheckedUseInfoAsFloat64FromHint(
|
||||
|
@ -233,47 +233,32 @@ BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
|
||||
}
|
||||
|
||||
// Helper function to transform the feedback to CompareOperationHint.
|
||||
template <CompareOperationFeedback::Type Feedback>
|
||||
bool Is(int type_feedback) {
|
||||
return !(type_feedback & ~Feedback);
|
||||
}
|
||||
|
||||
CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
|
||||
if (Is<CompareOperationFeedback::kNone>(type_feedback)) {
|
||||
return CompareOperationHint::kNone;
|
||||
switch (type_feedback) {
|
||||
case CompareOperationFeedback::kNone:
|
||||
return CompareOperationHint::kNone;
|
||||
case CompareOperationFeedback::kSignedSmall:
|
||||
return CompareOperationHint::kSignedSmall;
|
||||
case CompareOperationFeedback::kNumber:
|
||||
return CompareOperationHint::kNumber;
|
||||
case CompareOperationFeedback::kNumberOrOddball:
|
||||
return CompareOperationHint::kNumberOrOddball;
|
||||
case CompareOperationFeedback::kInternalizedString:
|
||||
return CompareOperationHint::kInternalizedString;
|
||||
case CompareOperationFeedback::kString:
|
||||
return CompareOperationHint::kString;
|
||||
case CompareOperationFeedback::kSymbol:
|
||||
return CompareOperationHint::kSymbol;
|
||||
case CompareOperationFeedback::kBigInt:
|
||||
return CompareOperationHint::kBigInt;
|
||||
case CompareOperationFeedback::kReceiver:
|
||||
return CompareOperationHint::kReceiver;
|
||||
case CompareOperationFeedback::kReceiverOrNullOrUndefined:
|
||||
return CompareOperationHint::kReceiverOrNullOrUndefined;
|
||||
default:
|
||||
return CompareOperationHint::kAny;
|
||||
}
|
||||
|
||||
if (Is<CompareOperationFeedback::kSignedSmall>(type_feedback)) {
|
||||
return CompareOperationHint::kSignedSmall;
|
||||
} else if (Is<CompareOperationFeedback::kNumber>(type_feedback)) {
|
||||
return CompareOperationHint::kNumber;
|
||||
} else if (Is<CompareOperationFeedback::kNumberOrOddball>(type_feedback)) {
|
||||
return CompareOperationHint::kNumberOrOddball;
|
||||
}
|
||||
|
||||
if (Is<CompareOperationFeedback::kInternalizedString>(type_feedback)) {
|
||||
return CompareOperationHint::kInternalizedString;
|
||||
} else if (Is<CompareOperationFeedback::kString>(type_feedback)) {
|
||||
return CompareOperationHint::kString;
|
||||
}
|
||||
|
||||
if (Is<CompareOperationFeedback::kReceiver>(type_feedback)) {
|
||||
return CompareOperationHint::kReceiver;
|
||||
} else if (Is<CompareOperationFeedback::kReceiverOrNullOrUndefined>(
|
||||
type_feedback)) {
|
||||
return CompareOperationHint::kReceiverOrNullOrUndefined;
|
||||
}
|
||||
|
||||
if (Is<CompareOperationFeedback::kBigInt>(type_feedback)) {
|
||||
return CompareOperationHint::kBigInt;
|
||||
}
|
||||
|
||||
if (Is<CompareOperationFeedback::kSymbol>(type_feedback)) {
|
||||
return CompareOperationHint::kSymbol;
|
||||
}
|
||||
|
||||
DCHECK(Is<CompareOperationFeedback::kAny>(type_feedback));
|
||||
return CompareOperationHint::kAny;
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// Helper function to transform the feedback to ForInHint.
|
||||
|
@ -2087,6 +2087,7 @@ TEST(InterpreterMixedComparisons) {
|
||||
LoadStringAndAddSpace(&builder, &ast_factory, rhs_cstr,
|
||||
string_add_slot);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
CHECK_EQ(which_side, kLhsIsString);
|
||||
// Comparison with String on the lhs and HeapNumber on the rhs.
|
||||
@ -2120,19 +2121,9 @@ TEST(InterpreterMixedComparisons) {
|
||||
if (tester.HasFeedbackMetadata()) {
|
||||
MaybeObject feedback = callable.vector().Get(slot);
|
||||
CHECK(feedback->IsSmi());
|
||||
if (kComparisonTypes[c] == Token::Value::EQ) {
|
||||
// For sloppy equality, we have more precise feedback.
|
||||
CHECK_EQ(
|
||||
CompareOperationFeedback::kNumber |
|
||||
(string_type == kInternalizedStringConstant
|
||||
? CompareOperationFeedback::kInternalizedString
|
||||
: CompareOperationFeedback::kString),
|
||||
feedback->ToSmi().value());
|
||||
} else {
|
||||
// Comparison with a number and string collects kAny feedback.
|
||||
CHECK_EQ(CompareOperationFeedback::kAny,
|
||||
feedback->ToSmi().value());
|
||||
}
|
||||
// Comparison with a number and string collects kAny feedback.
|
||||
CHECK_EQ(CompareOperationFeedback::kAny,
|
||||
feedback->ToSmi().value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --opt --allow-natives-syntax
|
||||
|
||||
(function() {
|
||||
function test(a, b) {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(test);
|
||||
assertTrue(test(undefined, undefined));
|
||||
assertTrue(test(undefined, undefined));
|
||||
%OptimizeFunctionOnNextCall(test);
|
||||
assertTrue(test(undefined, undefined));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function test(a, b) {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(test);
|
||||
assertTrue(test(true, true));
|
||||
assertTrue(test(true, true));
|
||||
%OptimizeFunctionOnNextCall(test);
|
||||
assertFalse(test(true, 1));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function test(a, b) {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(test);
|
||||
assertTrue(test(true, true));
|
||||
assertTrue(test(true, true));
|
||||
%OptimizeFunctionOnNextCall(test);
|
||||
assertTrue(test(true, 1));
|
||||
})();
|
Loading…
Reference in New Issue
Block a user