Bug 175895 - [DFG] Add constant folding rule to convert CompareStrictEq(Untyped, Untyped [with non string cell constant]) to CompareEqPtr(Untyped)
Summary: [DFG] Add constant folding rule to convert CompareStrictEq(Untyped, Untyped [...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Yusuke Suzuki
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2017-08-23 11:34 PDT by Yusuke Suzuki
Modified: 2017-08-29 17:31 PDT (History)
7 users (show)

See Also:


Attachments
Patch (3.93 KB, patch)
2017-08-26 03:01 PDT, Yusuke Suzuki
no flags Details | Formatted Diff | Diff
Patch (5.57 KB, patch)
2017-08-26 17:50 PDT, Yusuke Suzuki
saam: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Yusuke Suzuki 2017-08-23 11:34:08 PDT
...
Comment 1 Yusuke Suzuki 2017-08-23 11:35:32 PDT
We start holding map bucket in js property. And we perform CompareSrictEq onto this.
Current DFG code looks nice. But we can optimize further by introducing SpecCellOther fixup and CellOtherUse.
Comment 2 Yusuke Suzuki 2017-08-23 11:36:34 PDT
Or, we can say NotStringCellUse.
Comment 3 Yusuke Suzuki 2017-08-26 02:51:44 PDT
Maybe, this is simpler.
Comment 4 Yusuke Suzuki 2017-08-26 03:01:24 PDT
Created attachment 319134 [details]
Patch
Comment 5 Saam Barati 2017-08-26 09:25:08 PDT
Comment on attachment 319134 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=319134&action=review

> Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp:82
> +            if (!m_node->isBinaryUseKind(UntypedUse))

Why does this matter? It seems like your rewriting rule should work regardless? Or is this just because of the use kinds CompareEqPtr supports? If so, you can just convert this to a Check and then imagery the CompareEqPtr after that

> Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp:88
> +

I think AI would be better at proving this than what you’re doing here. Maybe write such a rule in AI/constant folding?
Comment 6 Yusuke Suzuki 2017-08-26 17:19:28 PDT
Comment on attachment 319134 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=319134&action=review

>> Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp:82
>> +            if (!m_node->isBinaryUseKind(UntypedUse))
> 
> Why does this matter? It seems like your rewriting rule should work regardless? Or is this just because of the use kinds CompareEqPtr supports? If so, you can just convert this to a Check and then imagery the CompareEqPtr after that

In the other cases, we do not need to convert CompareStrictEq to CompareEqPtr. It is already fast and optimized enough in DFG speculative JIT.
And DFGSpeculativeJIT curretnly only supports CompareEqPtr(Untyped). I do not think CompareEqPtr(VariousType) is worth adding.

>> Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp:88
>> +
> 
> I think AI would be better at proving this than what you’re doing here. Maybe write such a rule in AI/constant folding?

OK, I'll move this to AI/constant folding.
Comment 7 Yusuke Suzuki 2017-08-26 17:50:36 PDT
Created attachment 319144 [details]
Patch
Comment 8 Saam Barati 2017-08-26 19:40:26 PDT
Comment on attachment 319134 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=319134&action=review

>>> Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp:82
>>> +            if (!m_node->isBinaryUseKind(UntypedUse))
>> 
>> Why does this matter? It seems like your rewriting rule should work regardless? Or is this just because of the use kinds CompareEqPtr supports? If so, you can just convert this to a Check and then imagery the CompareEqPtr after that
> 
> In the other cases, we do not need to convert CompareStrictEq to CompareEqPtr. It is already fast and optimized enough in DFG speculative JIT.
> And DFGSpeculativeJIT curretnly only supports CompareEqPtr(Untyped). I do not think CompareEqPtr(VariousType) is worth adding.

My point was that all you need to do to make this work is keep convert it to a CompareEqPtr and and add a Check right before the CompareEqPtr.
Also, it’s worth making sure this doesn’t need to be aware of document.all
Comment 9 Yusuke Suzuki 2017-08-26 20:03:47 PDT
Comment on attachment 319134 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=319134&action=review

>>>> Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp:82
>>>> +            if (!m_node->isBinaryUseKind(UntypedUse))
>>> 
>>> Why does this matter? It seems like your rewriting rule should work regardless? Or is this just because of the use kinds CompareEqPtr supports? If so, you can just convert this to a Check and then imagery the CompareEqPtr after that
>> 
>> In the other cases, we do not need to convert CompareStrictEq to CompareEqPtr. It is already fast and optimized enough in DFG speculative JIT.
>> And DFGSpeculativeJIT curretnly only supports CompareEqPtr(Untyped). I do not think CompareEqPtr(VariousType) is worth adding.
> 
> My point was that all you need to do to make this work is keep convert it to a CompareEqPtr and and add a Check right before the CompareEqPtr.
> Also, it’s worth making sure this doesn’t need to be aware of document.all

One concern is that it can hurt efficiency in 32bit environment. In 32bit, if we have CompareStrictEq(ObjectType, ObjectConstant), we can perform 32bit pointer comparison.
However, if we convert it to Check(Object) and CompareEqPtr(Untyped), it needs to perform 64bit comparison against JSValue. It is efficient in 64bit environment (since we can perform 64bit comparison), but it is not in 32bit environment.
I think the current conversion rule is good in efficiency. CompareStrictEq(Untyped, Untyped) anyway needs to perform JSValue comparison. If we can convert it to ComparePtrEq, it is always more efficient than CompareStrictEq.

One solution is adding CompareEqPtr(ObjectUse) etc. in 32bit environment (I don't think adding it to 64bit is good, since it can add an additional cell type check that is not necessary right now.) But I do not think it is worth adding.

I will add masquarade as undefined check too.
Comment 10 Yusuke Suzuki 2017-08-26 20:07:20 PDT
Comment on attachment 319134 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=319134&action=review

>>>>> Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp:82
>>>>> +            if (!m_node->isBinaryUseKind(UntypedUse))
>>>> 
>>>> Why does this matter? It seems like your rewriting rule should work regardless? Or is this just because of the use kinds CompareEqPtr supports? If so, you can just convert this to a Check and then imagery the CompareEqPtr after that
>>> 
>>> In the other cases, we do not need to convert CompareStrictEq to CompareEqPtr. It is already fast and optimized enough in DFG speculative JIT.
>>> And DFGSpeculativeJIT curretnly only supports CompareEqPtr(Untyped). I do not think CompareEqPtr(VariousType) is worth adding.
>> 
>> My point was that all you need to do to make this work is keep convert it to a CompareEqPtr and and add a Check right before the CompareEqPtr.
>> Also, it’s worth making sure this doesn’t need to be aware of document.all
> 
> One concern is that it can hurt efficiency in 32bit environment. In 32bit, if we have CompareStrictEq(ObjectType, ObjectConstant), we can perform 32bit pointer comparison.
> However, if we convert it to Check(Object) and CompareEqPtr(Untyped), it needs to perform 64bit comparison against JSValue. It is efficient in 64bit environment (since we can perform 64bit comparison), but it is not in 32bit environment.
> I think the current conversion rule is good in efficiency. CompareStrictEq(Untyped, Untyped) anyway needs to perform JSValue comparison. If we can convert it to ComparePtrEq, it is always more efficient than CompareStrictEq.
> 
> One solution is adding CompareEqPtr(ObjectUse) etc. in 32bit environment (I don't think adding it to 64bit is good, since it can add an additional cell type check that is not necessary right now.) But I do not think it is worth adding.
> 
> I will add masquarade as undefined check too.

Ah, I do not need to add masquerade as undefined case since it is CompareStrictEq.
Comment 11 Saam Barati 2017-08-29 11:37:26 PDT
Comment on attachment 319144 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=319144&action=review

r=me

> Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp:158
> +                    if (isNonStringCellConstant(child1Constant)) {
> +                        node->convertToCompareEqPtr(m_graph.freezeStrong(child1Constant.asCell()), node->child2());
> +                        changed = true;
> +                    } else if (isNonStringCellConstant(child2Constant)) {
> +                        node->convertToCompareEqPtr(m_graph.freezeStrong(child2Constant.asCell()), node->child1());
> +                        changed = true;
> +                    }

When we do BigInt, we need to make sure we change this rule...
Comment 12 Saam Barati 2017-08-29 11:38:33 PDT
(In reply to Yusuke Suzuki from comment #9)
> Comment on attachment 319134 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=319134&action=review
> 
> >>>> Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp:82
> >>>> +            if (!m_node->isBinaryUseKind(UntypedUse))
> >>> 
> >>> Why does this matter? It seems like your rewriting rule should work regardless? Or is this just because of the use kinds CompareEqPtr supports? If so, you can just convert this to a Check and then imagery the CompareEqPtr after that
> >> 
> >> In the other cases, we do not need to convert CompareStrictEq to CompareEqPtr. It is already fast and optimized enough in DFG speculative JIT.
> >> And DFGSpeculativeJIT curretnly only supports CompareEqPtr(Untyped). I do not think CompareEqPtr(VariousType) is worth adding.
> > 
> > My point was that all you need to do to make this work is keep convert it to a CompareEqPtr and and add a Check right before the CompareEqPtr.
> > Also, it’s worth making sure this doesn’t need to be aware of document.all
> 
> One concern is that it can hurt efficiency in 32bit environment. In 32bit,
> if we have CompareStrictEq(ObjectType, ObjectConstant), we can perform 32bit
> pointer comparison.
> However, if we convert it to Check(Object) and CompareEqPtr(Untyped), it
> needs to perform 64bit comparison against JSValue. It is efficient in 64bit
> environment (since we can perform 64bit comparison), but it is not in 32bit
> environment.
> I think the current conversion rule is good in efficiency.
> CompareStrictEq(Untyped, Untyped) anyway needs to perform JSValue
> comparison. If we can convert it to ComparePtrEq, it is always more
> efficient than CompareStrictEq.
> 
> One solution is adding CompareEqPtr(ObjectUse) etc. in 32bit environment (I
> don't think adding it to 64bit is good, since it can add an additional cell
> type check that is not necessary right now.) But I do not think it is worth
> adding.
> 
> I will add masquarade as undefined check too.

Yeah this makes sense. Also, you're totally right that ComapreStrictEq(ObjectUse:, some other use) is already fast.
Comment 13 Yusuke Suzuki 2017-08-29 17:11:40 PDT
Comment on attachment 319144 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=319144&action=review

>> Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp:158
>> +                    }
> 
> When we do BigInt, we need to make sure we change this rule...

Yeah. Or we can take the similar approach to the current Symbol: interning BigInt cells by WeakGCMap to ensure the pointer comparison works.
Comment 14 Saam Barati 2017-08-29 17:14:52 PDT
(In reply to Yusuke Suzuki from comment #13)
> Comment on attachment 319144 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=319144&action=review
> 
> >> Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp:158
> >> +                    }
> > 
> > When we do BigInt, we need to make sure we change this rule...
> 
> Yeah. Or we can take the similar approach to the current Symbol: interning
> BigInt cells by WeakGCMap to ensure the pointer comparison works.

I don't think we'd want to intern these. That'll mean every math operation over them is doing some sort of hash-consing.
Comment 15 Yusuke Suzuki 2017-08-29 17:16:56 PDT
Comment on attachment 319144 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=319144&action=review

>>>> Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp:158
>>>> +                    }
>>> 
>>> When we do BigInt, we need to make sure we change this rule...
>> 
>> Yeah. Or we can take the similar approach to the current Symbol: interning BigInt cells by WeakGCMap to ensure the pointer comparison works.
> 
> I don't think we'd want to intern these. That'll mean every math operation over them is doing some sort of hash-consing.

OK, I'll add FIXME about it for the future BigInt integration :)
Comment 16 Yusuke Suzuki 2017-08-29 17:29:45 PDT
Committed r221328: <http://trac.webkit.org/changeset/221328>
Comment 17 Radar WebKit Bug Importer 2017-08-29 17:31:26 PDT
<rdar://problem/34148115>