Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2285,7 +2285,7 @@ void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mod
{
ConcurrentJSLocker locker(m_lock);
forEachStructureStubInfo([&](StructureStubInfo& stubInfo) {
stubInfo.reset(locker, this);
stubInfo.deref();
return IterationStatus::Continue;
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2828,7 +2828,7 @@ JSC_DEFINE_JIT_OPERATION(operationNewRegExpWithLastIndex, JSCell*, (JSGlobalObje
OPERATION_RETURN(scope, RegExpObject::create(vm, globalObject->regExpStructure(), regexp, JSValue::decode(encodedLastIndex)));
}

JSC_DEFINE_JIT_OPERATION(operationNewRegExpUntyped, JSObject*, (JSGlobalObject* globalObject, EncodedJSValue encodedContent, EncodedJSValue encodedFlags))
JSC_DEFINE_JIT_OPERATION(operationNewRegExpUntyped, JSObject*, (JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedContent, EncodedJSValue encodedFlags))
{
VM& vm = globalObject->vm();
CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
Expand All @@ -2840,10 +2840,11 @@ JSC_DEFINE_JIT_OPERATION(operationNewRegExpUntyped, JSObject*, (JSGlobalObject*
encodedFlags
};

OPERATION_RETURN(scope, constructRegExp(globalObject, ArgList { args, 2 }, globalObject->regExpConstructor()));
JSGlobalObject* regExpGlobalObject = structure->globalObject();
OPERATION_RETURN(scope, constructRegExp(regExpGlobalObject, ArgList { args, 2 }, regExpGlobalObject->regExpConstructor()));
}

JSC_DEFINE_JIT_OPERATION(operationNewRegExpString, JSObject*, (JSGlobalObject* globalObject, JSString* content, JSString* flags))
JSC_DEFINE_JIT_OPERATION(operationNewRegExpString, JSObject*, (JSGlobalObject* globalObject, Structure* structure, JSString* content, JSString* flags))
{
VM& vm = globalObject->vm();
CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
Expand All @@ -2854,7 +2855,8 @@ JSC_DEFINE_JIT_OPERATION(operationNewRegExpString, JSObject*, (JSGlobalObject* g
JSValue::encode(flags)
};

OPERATION_RETURN(scope, constructRegExp(globalObject, ArgList { args, 2 }, globalObject->regExpConstructor()));
JSGlobalObject* regExpGlobalObject = structure->globalObject();
OPERATION_RETURN(scope, constructRegExp(regExpGlobalObject, ArgList { args, 2 }, regExpGlobalObject->regExpConstructor()));
}

JSC_DEFINE_JIT_OPERATION(operationStringValueOf, JSString*, (JSGlobalObject* globalObject, EncodedJSValue encodedArgument))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSVa
JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndPutByVal, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, bool, uint32_t, JSPropertyNameEnumerator*));

JSC_DECLARE_JIT_OPERATION(operationNewRegExpWithLastIndex, JSCell*, (JSGlobalObject*, JSCell*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationNewRegExpUntyped, JSObject*, (JSGlobalObject*, EncodedJSValue, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationNewRegExpString, JSObject*, (JSGlobalObject*, JSString*, JSString*));
JSC_DECLARE_JIT_OPERATION(operationNewRegExpUntyped, JSObject*, (JSGlobalObject*, Structure*, EncodedJSValue, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationNewRegExpString, JSObject*, (JSGlobalObject*, Structure*, JSString*, JSString*));
JSC_DECLARE_JIT_OPERATION(operationNewArray, char*, (JSGlobalObject*, Structure*, void*, size_t));
JSC_DECLARE_JIT_OPERATION(operationNewEmptyArray, char*, (VM*, Structure*));
JSC_DECLARE_JIT_OPERATION(operationNewArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, Butterfly*));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11418,7 +11418,7 @@ void SpeculativeJIT::compileNewRegExpUntyped(Node* node)
flushRegisters();
GPRFlushedCallResult result(this);
GPRReg resultGPR = result.gpr();
callOperation(operationNewRegExpString, resultGPR, LinkableConstant::globalObject(*this, node), patternGPR, flagsGPR);
callOperation(operationNewRegExpString, resultGPR, LinkableConstant::globalObject(*this, node), TrustedImmPtr(node->structure()), patternGPR, flagsGPR);
cellResult(resultGPR, node);
return;
}
Expand All @@ -11432,7 +11432,7 @@ void SpeculativeJIT::compileNewRegExpUntyped(Node* node)
flushRegisters();
GPRFlushedCallResult result(this);
GPRReg resultGPR = result.gpr();
callOperation(operationNewRegExpUntyped, resultGPR, LinkableConstant::globalObject(*this, node), patternRegs, flagsRegs);
callOperation(operationNewRegExpUntyped, resultGPR, LinkableConstant::globalObject(*this, node), TrustedImmPtr(node->structure()), patternRegs, flagsRegs);
cellResult(resultGPR, node);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@ class StoreBarrierInsertionPhase : public Phase {
bool result = true;

UncheckedKeyHashMap<AbstractHeap, Node*> potentialStackEscapes;
auto escape = [&](Node* node) {
if (mode == PhaseMode::Global) {
m_interpreter->phiChildren()->forAllTransitiveIncomingValues(
node,
[&](Node* incoming) {
incoming->setEpoch(Epoch());
});
} else
node->setEpoch(Epoch());
};

for (m_nodeIndex = 0; m_nodeIndex < block->size(); ++m_nodeIndex) {
m_node = block->at(m_nodeIndex);
Expand Down Expand Up @@ -459,7 +469,7 @@ class StoreBarrierInsertionPhase : public Phase {
return;
potentialStackEscapes.removeIf([&] (const auto& entry) {
if (entry.key.overlaps(heap)) {
entry.value->setEpoch(Epoch());
escape(entry.value);
return true;
}
return false;
Expand All @@ -479,9 +489,6 @@ class StoreBarrierInsertionPhase : public Phase {
clobberize(m_graph, m_node, readFunc, writeFunc, NoOpClobberize());

if (wroteHeapOrStack) {
auto escape = [&] (Node* node) {
node->setEpoch(Epoch());
};

auto escapeToTheStack = [&] (Node* node) {
if (node->epoch() == m_currentEpoch) {
Expand Down Expand Up @@ -548,7 +555,7 @@ class StoreBarrierInsertionPhase : public Phase {

{
for (auto* node : potentialStackEscapes.values())
node->setEpoch(Epoch());
escape(node);
potentialStackEscapes.clear();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,10 @@ class StrengthReductionPhase : public Phase {
if (!flags)
break;

// NewRegExp node does not have an explicit structure, so don't reduce cross-realm RegExp.
if (m_node->structure().get() != m_graph.globalObjectFor(m_node->origin.semantic)->regExpStructure())
break;

auto* regExp = vm().regExpCache()->lookup(vm(), pattern, flags.value());
if (!regExp)
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5841,12 +5841,12 @@ IGNORE_CLANG_WARNINGS_END
#else
PatchpointValue* patchpoint = m_out.patchpoint(Int32);
#endif
if (typedArrayType.has_value() && typedArrayType.value() == TypeDataView) {
patchpoint->appendSomeRegister(base);
patchpoint->clobber(RegisterSetBuilder::macroClobberedGPRs());
patchpoint->numGPScratchRegisters = 2;
patchpoint->numGPScratchRegisters = 3;

if (typedArrayType.has_value() && typedArrayType.value() == TypeDataView) {
unsigned osrExitArgumentOffset = patchpoint->numChildren();
unsigned osrExitArgumentOffset = patchpoint->numChildren() + /* result */ 1;
OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(jsValueValue(base), m_node);
patchpoint->appendColdAnys(buildExitArguments(exitDescriptor, m_origin.forExit, jsValueValue(base)));

Expand All @@ -5862,19 +5862,24 @@ IGNORE_CLANG_WARNINGS_END
GPRReg baseGPR = params[1].gpr();
GPRReg scratch1GPR = params.gpScratch(0);
GPRReg scratch2GPR = params.gpScratch(1);
GPRReg scratch3GPR = params.gpScratch(2);

RefPtr<OSRExitHandle> handle = exitDescriptor->emitOSRExitLater(*state, OutOfBounds, origin, params, nodeIndex, osrExitArgumentOffset);
RefPtr<FTL::JITCode> jitCode = state->jitCode;

auto [outOfBounds, doneCases] = jit.loadDataViewByteLength(baseGPR, resultGPR, scratch1GPR, scratch2GPR, TypeDataView);
auto [outOfBounds, doneCases] = jit.loadDataViewByteLength(baseGPR, scratch1GPR, scratch2GPR, scratch3GPR, TypeDataView);
jit.addLinkTask([=, protectedJitCode = jitCode, outOfBoundsJump = outOfBounds](LinkBuffer& linkBuffer) {
linkBuffer.link(outOfBoundsJump, linkBuffer.locationOf<NoPtrTag>(handle->label));
});
doneCases.link(&jit);
jit.move(scratch1GPR, resultGPR);
});
return patchpoint;
}

patchpoint->appendSomeRegister(base);
patchpoint->clobber(RegisterSetBuilder::macroClobberedGPRs());
patchpoint->numGPScratchRegisters = 2;
patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
JIT_COMMENT(jit, "typedArrayLength");
AllowMacroScratchRegisterUsage allowScratch(jit);
Expand Down Expand Up @@ -9436,10 +9441,10 @@ IGNORE_CLANG_WARNINGS_END
{
JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
if (m_node->child1().useKind() == StringUse && m_node->child2().useKind() == StringUse) {
setJSValue(vmCall(pointerType(), operationNewRegExpString, weakPointer(globalObject), lowString(m_node->child1()), lowString(m_node->child2())));
setJSValue(vmCall(pointerType(), operationNewRegExpString, weakPointer(globalObject), weakStructure(m_node->structure()), lowString(m_node->child1()), lowString(m_node->child2())));
return;
}
setJSValue(vmCall(pointerType(), operationNewRegExpUntyped, weakPointer(globalObject), lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
setJSValue(vmCall(pointerType(), operationNewRegExpUntyped, weakPointer(globalObject), weakStructure(m_node->structure()), lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
}

void compileNewSymbol()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1423,16 +1423,23 @@ JSValue LiteralParser<CharType, reviverMode>::parseRecursively(VM& vm, uint8_t*
// This check avoids hash lookup and refcount churn in the common case of a matching single transition.
SUPPRESS_UNCOUNTED_ARG if (transition->transitionKind() == TransitionKind::PropertyAddition
&& !transition->transitionPropertyAttributes()
&& equalIdentifier(transition->transitionPropertyName(), m_lexer.currentToken())
&& (parserMode == StrictJSON || transition->transitionPropertyName() != vm.propertyNames->underscoreProto))
&& equalIdentifier(transition->transitionPropertyName(), m_lexer.currentToken())) {
if constexpr (parserMode == StrictJSON)
return ExistingProperty { transition, transition->transitionOffset() };
else if (transition->transitionPropertyName() != vm.propertyNames->underscoreProto && m_visitedUnderscoreProto.isEmpty())
return ExistingProperty { transition, transition->transitionOffset() };
}
} else if (!structure->isDictionary()) {
// This check avoids refcount churn in the common case of a cached Identifier.
if (SUPPRESS_UNCOUNTED_LOCAL AtomStringImpl* ident = existingIdentifier(vm, m_lexer.currentToken())) {
PropertyOffset offset = 0;
Structure* newStructure = Structure::addPropertyTransitionToExistingStructure(structure, ident, 0, offset);
if (newStructure && (parserMode == StrictJSON || newStructure->transitionPropertyName() != vm.propertyNames->underscoreProto)) [[likely]]
if (newStructure) [[likely]] {
if constexpr (parserMode == StrictJSON)
return ExistingProperty { newStructure, offset };
else if (newStructure->transitionPropertyName() != vm.propertyNames->underscoreProto && m_visitedUnderscoreProto.isEmpty())
return ExistingProperty { newStructure, offset };
}
return Identifier::fromString(vm, ident);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ bool hasCapacityToUseLargeGigacage();
v(Bool, forceAllFunctionsToUseSIMD, false, Normal, "Force all functions to act conservatively w.r.t fp/vector registers for testing."_s) \
v(Bool, useOMGInlining, true, Normal, "Use OMG inlining"_s) \
v(Bool, freeRetiredWasmCode, true, Normal, "free BBQ/OMG-OSR wasm code once it's no longer reachable."_s) \
v(Bool, useArrayAllocationSinking, true, Normal, nullptr) \
v(Bool, useArrayAllocationSinking, false, Normal, nullptr) \
v(Bool, dumpFTLCodeSize, false, Normal, nullptr) \
v(Bool, dumpOptimizationTracing, false, Normal, nullptr) \
v(Unsigned, markedBlockDumpInfoCount, 0, Normal, nullptr) /* FIXME: rdar://139998916 */ \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1038,11 +1038,12 @@ Structure* Structure::flattenDictionaryStructure(VM& vm, JSObject* object)
object->inlineStorageUnsafe() + inlineSize(),
(inlineCapacity() - inlineSize()) * sizeof(EncodedJSValue));

Butterfly* butterfly = object->butterfly();
if (Butterfly* butterfly = object->butterfly()) {
size_t preCapacity = butterfly->indexingHeader()->preCapacity(this);
void* base = butterfly->base(preCapacity, beforeOutOfLineCapacity);
void* startOfPropertyStorageSlots = reinterpret_cast<EncodedJSValue*>(base) + preCapacity;
gcSafeZeroMemory(static_cast<JSValue*>(startOfPropertyStorageSlots), (beforeOutOfLineCapacity - outOfLineSize()) * sizeof(EncodedJSValue));
}
checkOffsetConsistency();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3326,7 +3326,8 @@ StackMap BBQJIT::makeStackMap(const ControlData& data, Stack& enclosingStack)
}

RELEASE_ASSERT(stackMapIndex == numElements);
m_osrEntryScratchBufferSize = std::max(m_osrEntryScratchBufferSize, numElements + BBQCallee::extraOSRValuesForLoopIndex);
unsigned bufferSize = Context::scratchBufferSlotsPerValue(m_callee.savedFPWidth()) * (BBQCallee::extraOSRValuesForLoopIndex + numElements);
m_osrEntryScratchBufferSize = std::max(m_osrEntryScratchBufferSize, bufferSize);
return stackMap;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1623,8 +1623,8 @@ void BBQJIT::emitAllocateGCArrayUninitialized(GPRReg resultGPR, uint32_t typeInd
JIT_COMMENT(m_jit, "Do array allocation variable sized");

ASSERT(hasOneBitSet(elementSize));
m_jit.jitAssertIsInt32(sizeLocation.asGPR());
m_jit.lshift64(sizeLocation.asGPR(), TrustedImm32(getLSBSet(elementSize)), scratchGPR);
m_jit.zeroExtend32ToWord(sizeLocation.asGPR(), scratchGPR);
m_jit.lshift64(scratchGPR, TrustedImm32(getLSBSet(elementSize)), scratchGPR);
m_jit.add64(TrustedImm64(sizeof(JSWebAssemblyArray)), scratchGPR);

m_jit.emitAllocateVariableSized(resultGPR, JITAllocator::variableNonNull(), allocatorBufferBase, scratchGPR, scratchGPR, scratchGPR2, slowPath, AssemblyHelpers::SlowAllocationResult::UndefinedBehavior);
Expand Down Expand Up @@ -1983,6 +1983,7 @@ PartialResult WARN_UNUSED_RETURN BBQJIT::addArraySet(uint32_t typeIndex, Express
ASSERT(arrayref.asI64() == JSValue::encode(jsNull()));

LOG_INSTRUCTION("ArraySet", typeIndex, arrayref, index, value);
consume(index);
consume(value);
emitThrowException(ExceptionType::NullArraySet);
return { };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,18 @@ auto BBQJIT::emitCheckAndPrepareAndMaterializePointerApply(Value pointer, uint32
}
pointerLocation = Location::fromGPR(scratches.gpr(0));
emitMoveConst(pointer, pointerLocation);
} else {
} else
pointerLocation = loadIfNecessary(pointer);
m_jit.jitAssertIsInt32(pointerLocation.asGPR());
}
ASSERT(pointerLocation.isGPR());

switch (m_mode) {
case MemoryMode::BoundsChecking: {
// We're not using signal handling only when the memory is not shared.
// Regardless of signaling, we must check that no memory access exceeds the current memory size.
GPRReg pointerGPR = pointerLocation.asGPR();
if (boundary) {
m_jit.addPtr(TrustedImmPtr(boundary), pointerLocation.asGPR(), wasmScratchGPR);
pointerGPR = wasmScratchGPR;
}
throwExceptionIf(ExceptionType::OutOfBoundsMemoryAccess, m_jit.branchPtr(RelationalCondition::AboveOrEqual, pointerGPR, wasmBoundsCheckingSizeRegister));
m_jit.zeroExtend32ToWord(pointerLocation.asGPR(), wasmScratchGPR);
if (boundary)
m_jit.addPtr(TrustedImmPtr(boundary), wasmScratchGPR);
throwExceptionIf(ExceptionType::OutOfBoundsMemoryAccess, m_jit.branchPtr(RelationalCondition::AboveOrEqual, wasmScratchGPR, wasmBoundsCheckingSizeRegister));
break;
}

Expand All @@ -104,21 +100,29 @@ auto BBQJIT::emitCheckAndPrepareAndMaterializePointerApply(Value pointer, uint32
// any access equal to or greater than 4GiB will trap, no need to add the redzone.
if (uoffset >= Memory::fastMappedRedzoneBytes()) {
uint64_t maximum = m_info.memory.maximum() ? m_info.memory.maximum().bytes() : std::numeric_limits<uint32_t>::max();
GPRReg pointerGPR = pointerLocation.asGPR();
if (boundary) {
m_jit.addPtr(TrustedImmPtr(boundary), pointerLocation.asGPR(), wasmScratchGPR);
pointerGPR = wasmScratchGPR;
}
throwExceptionIf(ExceptionType::OutOfBoundsMemoryAccess, m_jit.branchPtr(RelationalCondition::AboveOrEqual, pointerGPR, TrustedImmPtr(static_cast<int64_t>(maximum))));
m_jit.zeroExtend32ToWord(pointerLocation.asGPR(), wasmScratchGPR);
if (boundary)
m_jit.addPtr(TrustedImmPtr(boundary), wasmScratchGPR);
throwExceptionIf(ExceptionType::OutOfBoundsMemoryAccess, m_jit.branchPtr(RelationalCondition::AboveOrEqual, wasmScratchGPR, TrustedImmPtr(static_cast<int64_t>(maximum))));
}
break;
}
}

if (!(static_cast<uint64_t>(uoffset) > static_cast<uint64_t>(std::numeric_limits<int32_t>::max()) || !B3::Air::Arg::isValidAddrForm(B3::Air::Move, uoffset, Width::Width128)))
return functor(CCallHelpers::BaseIndex(wasmBaseMemoryPointer, pointerLocation.asGPR(), CCallHelpers::TimesOne, static_cast<int32_t>(uoffset)));
bool canUseOffsetForm = static_cast<uint64_t>(uoffset) <= static_cast<uint64_t>(std::numeric_limits<int32_t>::max()) && B3::Air::Arg::isValidAddrForm(B3::Air::Move, uoffset, Width::Width128);
#if CPU(ARM64)
if (canUseOffsetForm)
return functor(CCallHelpers::BaseIndex(wasmBaseMemoryPointer, pointerLocation.asGPR(), CCallHelpers::TimesOne, static_cast<int32_t>(uoffset), CCallHelpers::Extend::ZExt32));

m_jit.addZeroExtend64(wasmBaseMemoryPointer, pointerLocation.asGPR(), wasmScratchGPR);
#else
m_jit.zeroExtend32ToWord(pointerLocation.asGPR(), wasmScratchGPR);
m_jit.addPtr(wasmBaseMemoryPointer, wasmScratchGPR);
#endif

if (canUseOffsetForm)
return functor(Address(wasmScratchGPR, static_cast<int32_t>(uoffset)));

m_jit.addPtr(wasmBaseMemoryPointer, pointerLocation.asGPR(), wasmScratchGPR);
m_jit.addPtr(TrustedImmPtr(static_cast<int64_t>(uoffset)), wasmScratchGPR);
return functor(Address(wasmScratchGPR));
}
Expand Down
Loading