Ignore:
Timestamp:
Jun 13, 2021, 11:29:46 AM (4 years ago)
Author:
[email protected]
Message:

https://bugs.webkit.org/show_bug.cgi?id=226576
<rdar://problem/78810362>

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/short-circuit-read-modify-write-cant-write-dst-before-tdz-check.js: Added.

(let.result.eval.try.captureV):
(catch):

Source/JavaScriptCore:

ShortCircuitReadModifyResolveNode can't emit a value into
its result until after it emits a TDZ check. We were temporarily
storing the result of the get_from_scope into the dst. Then
we'd emit the TDZ check. The TDZ check can throw, and it could
lead to us returning TDZ from the eval itself. Instead, we need
to use a temporary to emit a TDZ check on. Only after the TDZ check
passes can we move the temporary into the result.

  • bytecompiler/NodesCodegen.cpp:

(JSC::ShortCircuitReadModifyResolveNode::emitBytecode):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r278591 r278819  
    35293529    RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    35303530
    3531     RefPtr<RegisterID> result = generator.tempDestination(dst);
    3532 
    3533     generator.emitGetFromScope(result.get(), scope.get(), var, ThrowIfNotFound);
    3534     generator.emitTDZCheckIfNecessary(var, result.get(), nullptr);
     3531    RefPtr<RegisterID> uncheckedResult = generator.newTemporary();
     3532
     3533    generator.emitGetFromScope(uncheckedResult.get(), scope.get(), var, ThrowIfNotFound);
     3534    generator.emitTDZCheckIfNecessary(var, uncheckedResult.get(), nullptr);
    35353535
    35363536    Ref<Label> afterAssignment = generator.newLabel();
    3537     emitShortCircuitAssignment(generator, result.get(), m_operator, afterAssignment.get());
    3538 
    3539     generator.emitNode(result.get(), m_right); // Execute side effects first.
     3537    emitShortCircuitAssignment(generator, uncheckedResult.get(), m_operator, afterAssignment.get());
     3538
     3539    generator.emitNode(uncheckedResult.get(), m_right); // Execute side effects first.
    35403540
    35413541    bool threwException = isReadOnly ? generator.emitReadOnlyExceptionIfNeeded(var) : false;
     
    35453545
    35463546    if (!isReadOnly) {
    3547         result = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
    3548         generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
     3547        generator.emitPutToScope(scope.get(), var, uncheckedResult.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
     3548        generator.emitProfileType(uncheckedResult.get(), var, divotStart(), divotEnd());
    35493549    }
    35503550
    35513551    generator.emitLabel(afterAssignment.get());
    3552     return generator.move(dst, result.get());
     3552    return generator.move(generator.finalDestination(dst, uncheckedResult.get()), uncheckedResult.get());
    35533553}
    35543554
Note: See TracChangeset for help on using the changeset viewer.