Skip to content

Commit

Permalink
Cherry-pick 272448.422@safari-7618-branch (5bc92c9). https://bugs.web…
Browse files Browse the repository at this point in the history
…kit.org/show_bug.cgi?id=268409

    REGRESSION: JavaScriptCore: JSC::ScopedArguments::setIndexQuickly
    https://bugs.webkit.org/show_bug.cgi?id=268409
    rdar://121748005

    Reviewed by Yusuke Suzuki.

    A code inspection of the symbol table and scoped arguments code revealed that SymbolTable::cloneScopePart() doesn't
    properly copy the ScopedArgumentsTable from the source.  Since ScopedArguments point to the WatchpointSets in the
    related SymbolTable, we need to create new WatchpointSets in the cloned SymbolTable and have the ScopedArguments
    point to the related new WatchpointSets.

    This is a speculative fix.

    * Source/JavaScriptCore/runtime/ScopedArguments.h:
    * Source/JavaScriptCore/runtime/SymbolTable.cpp:
    (JSC::SymbolTable::cloneScopePart):
    (JSC::SymbolTable::hasScopedWatchpointSet):
    * Source/JavaScriptCore/runtime/SymbolTable.h:

    Canonical link: https://commits.webkit.org/272448.422@safari-7618-branch

Canonical link: https://commits.webkit.org/266719.410@webkitglib/2.42
  • Loading branch information
msaboff authored and aperezdc committed Mar 14, 2024
1 parent ad9e047 commit 4e1fab5
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 9 deletions.
6 changes: 5 additions & 1 deletion Source/JavaScriptCore/runtime/ScopedArguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,12 @@ class ScopedArguments final : public GenericArguments<ScopedArguments> {
m_scope->variableAt(m_table->get(i)).set(vm, m_scope.get(), value);

auto* watchpointSet = m_table->getWatchpointSet(i);
if (watchpointSet)
if (watchpointSet) {
#if ASSERT_ENABLED
ASSERT(m_scope->symbolTable()->hasScopedWatchpointSet(watchpointSet));
#endif
watchpointSet->touch(vm, "Write to ScopedArgument.");
}
} else
storage()[i - namedLength].set(vm, this, value);
}
Expand Down
58 changes: 50 additions & 8 deletions Source/JavaScriptCore/runtime/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "CodeBlock.h"
#include "JSCJSValueInlines.h"
#include "ResourceExhaustion.h"
#include "TypeProfiler.h"

#include <wtf/CommaPrinter.h>
Expand Down Expand Up @@ -145,19 +146,44 @@ SymbolTable* SymbolTable::cloneScopePart(VM& vm)
result->m_nestedLexicalScope = m_nestedLexicalScope;
result->m_scopeType = m_scopeType;

HashMap<VarOffset, uint32_t> varOffsetToArgIndexMap;

if (this->arguments()) {
// Copy the arguments, but not the WatchpointSets. We create new WatchpointSets as appropriate when we create the SymbolTableEntry
// copies below and propogate the new watchpointSets to the new ScopedArgumentsTable.
auto length = this->arguments()->length();
ScopedArgumentsTable* arguments = ScopedArgumentsTable::tryCreate(vm, length);
RELEASE_ASSERT_RESOURCE_AVAILABLE(arguments, MemoryExhaustion, "Crash intentionally because memory is exhausted.");

for (uint32_t index = 0; index < length; ++index) {
ScopeOffset offset = this->arguments()->get(index);

arguments->trySet(vm, index, offset);
if (this->arguments()->getWatchpointSet(index))
varOffsetToArgIndexMap.set(VarOffset(offset), index);
}

result->m_arguments.set(vm, result, arguments);
}

bool hasScopedArgumentWatchpoints = !varOffsetToArgIndexMap.isEmpty();

for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) {
if (!iter->value.varOffset().isScope())
continue;
result->m_map.add(
iter->key,
SymbolTableEntry(iter->value.varOffset(), iter->value.getAttributes()));
SymbolTableEntry entry(iter->value.varOffset(), iter->value.getAttributes());

if (hasScopedArgumentWatchpoints) {
auto findIter = varOffsetToArgIndexMap.find(iter->value.varOffset());
if (findIter != varOffsetToArgIndexMap.end())
result->prepareToWatchScopedArgument(entry, findIter->value);
}

result->m_map.add(iter->key, WTFMove(entry));
}

result->m_maxScopeOffset = m_maxScopeOffset;

if (ScopedArgumentsTable* arguments = this->arguments())
result->m_arguments.set(vm, result, arguments);


if (m_rareData) {
result->ensureRareData();

Expand Down Expand Up @@ -278,6 +304,22 @@ RefPtr<TypeSet> SymbolTable::globalTypeSetForVariable(const ConcurrentJSLocker&
return iter->value;
}

#if ASSERT_ENABLED
bool SymbolTable::hasScopedWatchpointSet(WatchpointSet* watchpointSet)
{
for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) {
if (!iter->value.varOffset().isScope())
continue;

auto* entryWatchpointSet = iter->value.watchpointSet();
if (entryWatchpointSet && entryWatchpointSet == watchpointSet)
return true;
}

return false;
}
#endif

SymbolTable::SymbolTableRareData& SymbolTable::ensureRareDataSlow()
{
auto rareData = makeUnique<SymbolTableRareData>();
Expand Down
4 changes: 4 additions & 0 deletions Source/JavaScriptCore/runtime/SymbolTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,10 @@ class SymbolTable final : public JSCell {

DECLARE_EXPORT_INFO;

#if ASSERT_ENABLED
bool hasScopedWatchpointSet(WatchpointSet*);
#endif

void finalizeUnconditionally(VM&, CollectionScope);
void dump(PrintStream&) const;

Expand Down

0 comments on commit 4e1fab5

Please sign in to comment.