[webkit-reviews] review granted: [Bug 227989] for-in should only emit one loop in bytecode : [Attachment 435019] Patch
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Fri Aug 6 04:05:53 PDT 2021
Yusuke Suzuki <ysuzuki at apple.com> has granted Keith Miller
<keith_miller at apple.com>'s request for review:
Bug 227989: for-in should only emit one loop in bytecode
https://bugs.webkit.org/show_bug.cgi?id=227989
Attachment 435019: Patch
https://bugs.webkit.org/attachment.cgi?id=435019&action=review
--- Comment #24 from Yusuke Suzuki <ysuzuki at apple.com> ---
Comment on attachment 435019
--> https://bugs.webkit.org/attachment.cgi?id=435019
Patch
View in context: https://bugs.webkit.org/attachment.cgi?id=435019&action=review
r=me
> Source/JavaScriptCore/dfg/DFGClobberize.h:343
> + case EnumeratorNextUpdatePropertyName:
To define PureValue, you need to pass valid OpInfos too. In this node's case,
seenModes info is missing in PureValue.
> Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:-1124
> -
Can we share the code with setJSArraySaneChainIfPossible?
It looks like this is very similar and having the exact same long comment.
> Source/JavaScriptCore/dfg/DFGNode.h:3273
> + EnumeratorMetadata enumeratorMetadata()
> + {
> + return m_opInfo2.as<EnumeratorMetadata>();
> + }
How about returning OptionSet from this function?
> Source/JavaScriptCore/dfg/DFGOperations.cpp:2481
> + JSValue result = bitwise_cast<JSValue>(static_cast<uint64_t>(mode) << 32
| index | JSValue::NumberTag);
This is making broken JSInt32 (this pattern never appears in the valid number).
I think we should mimic double's pattern instead.
For example, we can make it DoubleEncodeOffset | static_cast<uint64_t>(mode) <<
32 | index. This is better since this is still a valid JSValue double's bit
pattern.
> Source/JavaScriptCore/dfg/DFGOperations.cpp:2483
> + JSValue result = JSValue(mode, index);
I think we can do the same thing for 32bit too: I mean, let's just encode mode
and index into double value bit pattern.
In 32bit case, we are not using offset. So, `uint64_t value =
static_cast<uint64_t>(mode) << 32 | index` can be a valid JSValue double
pattern in 32bit, correct?
So, we can make DFG AI valid.
> Source/JavaScriptCore/dfg/DFGOperations.cpp:2517
> + scope.assertNoException();
RETURN_IF_EXCEPTION(scope, { }); is better since there is terminated exception.
> Source/JavaScriptCore/dfg/DFGOperations.cpp:2534
> + return
JSValue::encode(jsBoolean(base.getObject()->hasProperty(globalObject, index)));
Use `jsCast<JSObject*>` instead of getObject since we already checked this is
an object.
> Source/JavaScriptCore/dfg/DFGOperations.cpp:2550
> + return
JSValue::encode(jsBoolean(base.getObject()->hasOwnProperty(globalObject,
index)));
Use `jsCast<JSObject*>` instead of getObject since we already checked this is
an object.
> Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp:473
> Edge child1 = m_graph.child(node, 0);
This clause does not include `EnumeratorGetByVal` while we are checking
`node->op() == EnumeratorGetByVal`. Is it missing?
> Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp:1233
> + // This can actually return a JS null but we branch of that case
in the same basic block so we don't want to mess with
> + // fixup's logic.
I think we can make valid JSValue double bit pattern anytime, so we do not need
to have this comment.
> Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:2669
> + else
Add ASSERT for else case with expected format type.
> Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:13490
> +#if USE(JSVALUE64)
> + m_jit.move(TrustedImm64(JSValue::NumberTag |
static_cast<uint64_t>(JSPropertyNameEnumerator::IndexedMode) << 32),
resultRegs.payloadGPR());
> + m_jit.or64(scratch.gpr(), resultRegs.payloadGPR());
> +#else
> + m_jit.move(TrustedImm32(JSPropertyNameEnumerator::IndexedMode),
resultRegs.tagGPR());
> +#endif
Ditto. We should make it valid double bit pattern.
> Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:13519
> +#if USE(JSVALUE64)
> + m_jit.or64(TrustedImm64(JSValue::NumberTag |
static_cast<uint64_t>(JSPropertyNameEnumerator::OwnStructureMode) << 32),
resultRegs.payloadGPR());
> +#else
> + m_jit.move(TrustedImm32(JSPropertyNameEnumerator::OwnStructureMode),
resultRegs.tagGPR());
> +#endif
Ditto. We should make it valid double bit pattern.
> Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:13560
> + m_jit.rshift64(pairGPR, TrustedImm32(32), resultGPR);
We have double-offset (or NumberTag in the current code). In ARM64, we can use
bit-extract to get appropriate bits easily.
> Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:13063
> + m_out.appendTo(increment);
Don't we need to get lastNext here and append it later as
m_out.appendTo(continuation, lastNext) ?
> Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:13096
> + m_out.appendTo(increment);
Don't we need to get lastNext here and append it later as
m_out.appendTo(continuation, lastNext) ?
> Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:13102
> + setJSValue(m_out.bitOr(m_out.zeroExt(index, Int64),
m_out.constInt64(JSValue::NumberTag |
static_cast<uint64_t>(JSPropertyNameEnumerator::OwnStructureMode) << 32)));
Should we remove some bits from NumberTag here? If we use full NumberTag, the
generated bit pattern becomes broken Int32 (this bit pattern never appears in
the usual JSValue). I think we should make it look like some sort of Encoded
Double.
Like adding double-offset instead.
> Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:13169
> + cachedNameResult =
m_out.anchor(m_out.zeroExtPtr(m_out.loadPtr(m_out.baseIndex(m_heaps.WriteBarrie
rBuffer_bufferContents.atAnyIndex(), namesVector, m_out.zeroExt(index, Int64),
ScalePtr))));
m_out.zeroExtPtr is not necessary since this is the result of loadPtr.
> Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:13185
> + m_out.appendTo(continuation);
Don't we need to get lastNext here and append it later as
m_out.appendTo(continuation, lastNext) ?
> Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:13189
> + LValue result = m_out.phi(Int64);
> + ASSERT(outOfBoundsResult || cachedNameResult || operationResult);
> + m_out.addIncomingToPhiIfSet(result, outOfBoundsResult,
cachedNameResult, operationResult);
Why not using existing Vector<ValueFromBlock, N> results, and m_out.phi(Int64,
results)?
We can just append LValue only when it exists. And then we can pass this vector
to `m_out.phi`. So we do not need to check whether each ValueFromBlock is
nullptr or not.
> Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:13223
> + m_out.appendTo(checkIsCellBlock);
Don't we need to get lastNext here and append it later as
m_out.appendTo(continuation, lastNext) ?
> Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:13294
> + LValue result = m_out.phi(Int64, genericICResult, outOfLineResult,
inlineResult);
> + if (badStructureSlowPathResult)
> + m_out.addIncomingToPhi(result, badStructureSlowPathResult);
> + setJSValue(result);
Ditto. Why not using existing Vector<ValueFromBlock, N> results, and
m_out.phi(Int64, results)?
> Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:13315
> + m_out.appendTo(isNamedBlock);
Don't we need to get lastNext here and append it later as
m_out.appendTo(continuation, lastNext) ?
> Source/JavaScriptCore/runtime/CommonSlowPaths.cpp:1029
> + RETURN_PROFILED(baseValue.getObject()->getDirect(index <
enumerator->cachedInlineCapacity() ? index : index -
enumerator->cachedInlineCapacity() + firstOutOfLineOffset));
Let's just use `jsCast<JSObject*>` instead of getObject() since we know that
this is JSObject*.
> Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp:177
> + scope.assertNoException();
Since there is termination exception, I suggest just using
RETURN_IF_EXCEPTION(scope, nullptr);
> Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp:202
> + scope.assertNoException();
Since there is termination exception, I suggest just using
RETURN_IF_EXCEPTION(scope, nullptr);
> Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp:209
> + scope.assertNoException();
Since there is termination exception, I suggest just using
RETURN_IF_EXCEPTION(scope, nullptr);
More information about the webkit-reviews
mailing list