Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8313711: Cherry-pick WebKit 616.1 stabilization fixes #6

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 @@ -155,13 +155,24 @@ list(APPEND JavaScriptCore_SOURCES
${JavaScriptCore_DERIVED_SOURCES_DIR}/JSCBuiltins.cpp
)

add_custom_command(
find_program(TOUCH_EXECUTABLE touch)
if (TOUCH_EXECUTABLE)
add_custom_command(
OUTPUT ${JavaScriptCore_DERIVED_SOURCES_DIR}/JSCBytecodeCacheVersion.cpp
MAIN_DEPENDENCY ${JAVASCRIPTCORE_DIR}/runtime/JSCBytecodeCacheVersion.cpp.in
COMMAND ${PERL_EXECUTABLE} -pe s/CACHED_TYPES_CKSUM/__TIMESTAMP__/ ${JAVASCRIPTCORE_DIR}/runtime/JSCBytecodeCacheVersion.cpp.in > ${JavaScriptCore_DERIVED_SOURCES_DIR}/JSCBytecodeCacheVersion.cpp
COMMAND ${TOUCH_EXECUTABLE} -r ${JAVASCRIPTCORE_DIR}/runtime/JSCBytecodeCacheVersion.cpp.in ${JavaScriptCore_DERIVED_SOURCES_DIR}/JSCBytecodeCacheVersion.cpp
VERBATIM
)

)
else ()
message(WARNING "Unable to find touch executable; ${JavaScriptCore_DERIVED_SOURCES_DIR}/JSCBytecodeCacheVersion.cpp is built non-reproducibly from ${JAVASCRIPTCORE_DIR}/runtime/JSCBytecodeCacheVersion.cpp.in")
add_custom_command(
OUTPUT ${JavaScriptCore_DERIVED_SOURCES_DIR}/JSCBytecodeCacheVersion.cpp
MAIN_DEPENDENCY ${JAVASCRIPTCORE_DIR}/runtime/JSCBytecodeCacheVersion.cpp.in
COMMAND ${PERL_EXECUTABLE} -pe s/CACHED_TYPES_CKSUM/__TIMESTAMP__/ ${JAVASCRIPTCORE_DIR}/runtime/JSCBytecodeCacheVersion.cpp.in > ${JavaScriptCore_DERIVED_SOURCES_DIR}/JSCBytecodeCacheVersion.cpp
VERBATIM
)
endif ()

set(JavaScriptCore_FRAMEWORKS
WTF
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,16 @@ class DuplicateTails {
if (block->last()->type() != Void) // Demoting doesn't handle terminals with values.
continue;

candidates.add(block);
bool canCopyBlock = true;
for (Value* value : *block) {
if (value->kind().isCloningForbidden()) {
canCopyBlock = false;
break;
}
}

if (canCopyBlock)
candidates.add(block);
}

// Collect the set of values that must be de-SSA'd.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ void Kind::dump(PrintStream& out) const
out.print(comma, "Traps");
if (isSensitiveToNaN())
out.print(comma, "SensitiveToNaN");
if (isCloningForbidden())
out.print(comma, "CloningForbidden");
if (comma.didPrint())
out.print(">");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,29 @@ class Kind {
m_isSensitiveToNaN = isSensitiveToNaN;
}

static constexpr bool hasCloningForbidden(Opcode opcode)
{
switch (opcode) {
case Patchpoint:
return true;
default:
return false;
}
}
bool hasCloningForbidden() const
{
return hasCloningForbidden(m_opcode);
}
bool isCloningForbidden() const
{
return m_cloningForbidden;
}
void setIsCloningForbidden(bool isCloningForbidden)
{
ASSERT(hasCloningForbidden());
m_cloningForbidden = isCloningForbidden;
}

// Rules for adding new properties:
// - Put the accessors here.
// - hasBlah() should check if the opcode allows for your property.
Expand All @@ -189,7 +212,8 @@ class Kind {
return m_opcode == other.m_opcode
&& m_isChill == other.m_isChill
&& m_traps == other.m_traps
&& m_isSensitiveToNaN == other.m_isSensitiveToNaN;
&& m_isSensitiveToNaN == other.m_isSensitiveToNaN
&& m_cloningForbidden == other.m_cloningForbidden;
}

bool operator!=(const Kind& other) const
Expand All @@ -203,7 +227,7 @@ class Kind {
{
// It's almost certainly more important that this hash function is cheap to compute than
// anything else. We can live with some kind hash collisions.
return m_opcode + (static_cast<unsigned>(m_isChill) << 16) + (static_cast<unsigned>(m_traps) << 7) + (static_cast<unsigned>(m_isSensitiveToNaN) << 24);
return m_opcode + (static_cast<unsigned>(m_isChill) << 16) + (static_cast<unsigned>(m_traps) << 7) + (static_cast<unsigned>(m_isSensitiveToNaN) << 24) + (static_cast<unsigned>(m_cloningForbidden) << 13);
}

Kind(WTF::HashTableDeletedValueType)
Expand All @@ -222,6 +246,7 @@ class Kind {
bool m_isChill : 1 { false };
bool m_traps : 1 { false };
bool m_isSensitiveToNaN : 1 { false };
bool m_cloningForbidden : 1 { false };
};

// For every flag 'foo' you add, it's customary to create a Kind B3::foo(Kind) function that makes
Expand Down Expand Up @@ -250,6 +275,12 @@ inline Kind sensitiveToNaN(Kind kind)
return kind;
}

inline Kind cloningForbidden(Kind kind)
{
kind.setIsCloningForbidden(true);
return kind;
}

struct KindHash {
static unsigned hash(const Kind& key) { return key.hash(); }
static bool equal(const Kind& a, const Kind& b) { return a == b; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ void PatchpointValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const
out.print(comma, "numFPScratchRegisters = ", numFPScratchRegisters);
}

PatchpointValue::PatchpointValue(Type type, Origin origin)
: Base(CheckedOpcode, Patchpoint, type, origin)
PatchpointValue::PatchpointValue(Type type, Origin origin, Kind kind)
: Base(CheckedOpcode, kind, type, origin)
, effects(Effects::forCall())
{
ASSERT(accepts(kind));
if (!type.isTuple())
resultConstraints.append(type == Void ? ValueRep::WarmAny : ValueRep::SomeRegister);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class PatchpointValue final : public StackmapValue {
public:
typedef StackmapValue Base;

static bool accepts(Kind kind) { return kind == Patchpoint; }
static bool accepts(Kind kind) { return kind.opcode() == Patchpoint; }

~PatchpointValue() final;

Expand Down Expand Up @@ -71,7 +71,8 @@ class PatchpointValue final : public StackmapValue {
friend class Value;

static Opcode opcodeFromConstructor(Type, Origin) { return Patchpoint; }
JS_EXPORT_PRIVATE PatchpointValue(Type, Origin);
static Opcode opcodeFromConstructor(Type, Origin, Kind) { return Patchpoint; }
JS_EXPORT_PRIVATE PatchpointValue(Type, Origin, Kind = Patchpoint);
};

} } // namespace JSC::B3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class IntRange {
: m_min(min)
, m_max(max)
{
ASSERT(m_min <= m_max);
}

template<typename T>
Expand Down Expand Up @@ -448,9 +449,15 @@ class IntRange {
{
ASSERT(m_min >= INT32_MIN);
ASSERT(m_max <= INT32_MAX);
int32_t min = m_min;
int32_t max = m_max;
return IntRange(static_cast<uint64_t>(static_cast<uint32_t>(min)), static_cast<uint64_t>(static_cast<uint32_t>(max)));
uint64_t min = static_cast<uint64_t>(static_cast<uint32_t>(m_min));
uint64_t max = static_cast<uint64_t>(static_cast<uint32_t>(m_max));
if (m_max < 0 || m_min >= 0) {
// m_min = -2, m_max = -1 then should return [0xFFFF_FFFE, 0xFFFF_FFFF]
// m_min = 1, m_max = 2 then should return [1, 2]
return IntRange(min, max);
}
// m_min = a negative integer, m_max >= 0 then should return [0, 0xFFFF_FFFF]
return IntRange(0, std::numeric_limits<uint32_t>::max());
}

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ ALWAYS_INLINE size_t Value::adjacencyListOffset() const

ALWAYS_INLINE Value* Value::cloneImpl() const
{
ASSERT(!kind().isCloningForbidden());
#define VALUE_TYPE_CLONE(ValueType) allocate<ValueType>(*static_cast<const ValueType*>(this))
DISPATCH_ON_KIND(VALUE_TYPE_CLONE);
#undef VALUE_TYPE_CLONE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,23 @@ ObjectPropertyCondition generateCondition(
break;
}
case PropertyCondition::Equivalence: {
JSValue value;
{
Locker<JSCellLock> cellLocker { NoLockingNecessary };
if (concurrency != Concurrency::MainThread) {
cellLocker = Locker { object->cellLock() };
if (object->structure() != structure)
return ObjectPropertyCondition();
// The structure might change from now on, but we are guaranteed to have a sane view of the butterfly.
}
unsigned attributes;
PropertyOffset offset = structure->get(vm, concurrency, uid, attributes);
if (offset == invalidOffset)
return ObjectPropertyCondition();
JSValue value = object->getDirect(concurrency, structure, offset);
value = object->getDirect(cellLocker, concurrency, structure, offset);
if (!value)
return ObjectPropertyCondition();
}
result = ObjectPropertyCondition::equivalence(vm, owner, object, uid, value);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,6 @@ void PropertyCondition::dump(PrintStream& out) const
dumpInContext(out, nullptr);
}

ALWAYS_INLINE static bool nonStructurePropertyMayBecomeReadOnlyWithoutTransition(Structure* structure, UniquedStringImpl* uid)
{
switch (structure->typeInfo().type()) {
case ArrayType:
case DerivedArrayType:
return uid == structure->vm().propertyNames->length.impl();

case RegExpObjectType:
return uid == structure->vm().propertyNames->lastIndex.impl();

default:
return false;
}
}

bool PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint(
Concurrency concurrency, Structure* structure, JSObject* base) const
{
Expand Down Expand Up @@ -201,9 +186,13 @@ bool PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint(
}
return false;
}
} else if (nonStructurePropertyMayBecomeReadOnlyWithoutTransition(structure, uid())) {
} else if (structure->typeInfo().overridesPut() && JSObject::mightBeSpecialProperty(structure->vm(), structure->typeInfo().type(), uid())) {
if (PropertyConditionInternal::verbose)
dataLog("Invalid because its put() override may treat ", uid(), " property as read-only.\n");
dataLog("Invalid because its put() override may treat ", uid(), " property as special non-structure one.\n");
return false;
} else if (structure->hasNonReifiedStaticProperties() && structure->classInfoForCells()->hasStaticReadOnlyOrGetterSetterProperty(uid())) {
if (PropertyConditionInternal::verbose)
dataLog("Invalid because we expected not to have a setter, but we have one in non-reified static property table: ", uid(), ".\n");
return false;
}

Expand Down Expand Up @@ -282,6 +271,9 @@ bool PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint(
}

case Equivalence: {
Locker<JSCellLock> cellLocker { NoLockingNecessary };
if (concurrency != Concurrency::MainThread && base)
cellLocker = Locker { base->cellLock() };
if (!base || base->structure() != structure) {
// Conservatively return false, since we cannot verify this one without having the
// object.
Expand All @@ -306,8 +298,8 @@ bool PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint(
return false;
}

JSValue currentValue = base->getDirect(concurrency, structure, currentOffset);
if (currentValue != requiredValue()) {
JSValue currentValue = base->getDirect(cellLocker, concurrency, structure, currentOffset);
if (currentValue != requiredValue() || !currentValue) {
if (PropertyConditionInternal::verbose) {
dataLog(
"Invalid because the value is ", currentValue, " but we require ", requiredValue(),
Expand Down Expand Up @@ -510,9 +502,13 @@ bool PropertyCondition::isValidValueForPresence(JSValue value) const

PropertyCondition PropertyCondition::attemptToMakeEquivalenceWithoutBarrier(JSObject* base) const
{
JSValue value;
{
Locker cellLocker { base->cellLock() };
Structure* structure = base->structure();

JSValue value = base->getDirectConcurrently(structure, offset());
value = base->getDirectConcurrently(cellLocker, structure, offset());
}
if (!isValidValueForPresence(value))
return PropertyCondition();
return equivalenceWithoutBarrier(uid(), value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1326,11 +1326,12 @@ JSValue Graph::tryGetConstantProperty(
// incompatible with the getDirect we're trying to do. The easiest way to do that is to
// determine if the structure belongs to the proven set.

Locker cellLock { object->cellLock() };
Structure* structure = object->structure();
if (!structureSet.toStructureSet().contains(structure))
return JSValue();

return object->getDirectConcurrently(structure, offset);
return object->getDirectConcurrently(cellLock, structure, offset);
}

JSValue Graph::tryGetConstantProperty(JSValue base, Structure* structure, PropertyOffset offset)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,19 @@ class PreciseLocalClobberizeAdaptor {
case CreateRest: {
bool isForwardingNode = false;
bool isPhantomNode = false;
bool mayReadArguments = false;
switch (m_node->op()) {
case ForwardVarargs:
// This is used iff allInlineFramesAreTailCalls, so we will
// actually do a real tail call and destroy our frame.
case TailCallForwardVarargs:
isForwardingNode = true;
break;
case CallForwardVarargs:
case ConstructForwardVarargs:
case TailCallForwardVarargs:
case TailCallForwardVarargsInlinedCaller:
isForwardingNode = true;
mayReadArguments = true;
break;
case PhantomDirectArguments:
case PhantomClonedArguments:
Expand All @@ -210,6 +216,9 @@ class PreciseLocalClobberizeAdaptor {
if (isPhantomNode && m_graph.m_plan.isFTL())
break;

if (mayReadArguments)
readWorld(m_node);

if (isForwardingNode && m_node->hasArgumentsChild() && m_node->argumentsChild()
&& (m_node->argumentsChild()->op() == PhantomNewArrayWithSpread || m_node->argumentsChild()->op() == PhantomSpread)) {
if (m_node->argumentsChild()->op() == PhantomNewArrayWithSpread)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8830,7 +8830,7 @@ void SpeculativeJIT::compileGetTypedArrayByteOffset(Node* node)
#if USE(LARGE_TYPED_ARRAYS)
load64(Address(baseGPR, JSArrayBufferView::offsetOfByteOffset()), resultGPR);
// AI promises that the result of GetTypedArrayByteOffset will be Int32, so we must uphold that promise here.
speculationCheck(ExitKind::Overflow, JSValueRegs(), nullptr, branch32(Above, resultGPR, TrustedImm32(std::numeric_limits<int32_t>::max())));
speculationCheck(ExitKind::Overflow, JSValueRegs(), nullptr, branch64(Above, resultGPR, TrustedImm32(std::numeric_limits<int32_t>::max())));
#else
load32(Address(baseGPR, JSArrayBufferView::offsetOfByteOffset()), resultGPR);
#endif
Expand All @@ -8856,7 +8856,7 @@ void SpeculativeJIT::compileGetTypedArrayByteOffset(Node* node)
#if USE(LARGE_TYPED_ARRAYS)
load64(Address(baseGPR, JSArrayBufferView::offsetOfByteOffset()), resultGPR);
// AI promises that the result of GetTypedArrayByteOffset will be Int32, so we must uphold that promise here.
speculationCheck(ExitKind::Overflow, JSValueRegs(), nullptr, branch32(Above, resultGPR, TrustedImm32(std::numeric_limits<int32_t>::max())));
speculationCheck(ExitKind::Overflow, JSValueRegs(), nullptr, branch64(Above, resultGPR, TrustedImm32(std::numeric_limits<int32_t>::max())));
#else
load32(Address(baseGPR, JSArrayBufferView::offsetOfByteOffset()), resultGPR);
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ ScriptCallStack::ScriptCallStack(Vector<ScriptCallFrame>&& frames, bool truncate
, m_truncated(truncated)
, m_parentStackTrace(parentStackTrace)
{
ASSERT(m_frames.size() < maxCallStackSizeToCapture);
ASSERT(m_frames.size() <= maxCallStackSizeToCapture);
}

ScriptCallStack::~ScriptCallStack()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,14 @@ void InspectorConsoleAgent::addConsoleMessage(std::unique_ptr<ConsoleMessage> co
if (m_enabled)
previousMessage->updateRepeatCountInConsole(*m_frontendDispatcher);
} else {
ConsoleMessage* newMessage = consoleMessage.get();
m_consoleMessages.append(WTFMove(consoleMessage));
if (m_enabled) {
auto generatePreview = !m_isAddingMessageToFrontend;
SetForScope isAddingMessageToFrontend(m_isAddingMessageToFrontend, true);

newMessage->addToFrontend(*m_frontendDispatcher, m_injectedScriptManager, generatePreview);
consoleMessage->addToFrontend(*m_frontendDispatcher, m_injectedScriptManager, generatePreview);
}

m_consoleMessages.append(WTFMove(consoleMessage));
if (m_consoleMessages.size() >= maximumConsoleMessages) {
m_expiredConsoleMessageCount += expireConsoleMessagesStep;
m_consoleMessages.remove(0, expireConsoleMessagesStep);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2384,7 +2384,7 @@ static void handleVarargsCheckpoint(VM& vm, CallFrame* callFrame, JSGlobalObject
unsigned firstVarArg = bytecode.m_firstVarArg;

MarkedArgumentBuffer args;
args.fill(argumentCountIncludingThis - 1, [&] (JSValue* buffer) {
args.fill(vm, argumentCountIncludingThis - 1, [&](JSValue* buffer) {
loadVarargs(globalObject, buffer, callFrame->r(bytecode.m_arguments).jsValue(), firstVarArg, argumentCountIncludingThis - 1);
});
if (args.hasOverflowed()) {
Expand Down
Loading