[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