Skip to content
Draft
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
1 change: 1 addition & 0 deletions JSTests/BUN-TEST-DIFFERENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ Not upstream's: a sync neither brings nor changes them. Most are named `stress/b
| `stress/inline-cache-stub-freed-during-call-to-custom-setter.js` | an inline cache stub that has called native code stays until the call returns, also when the callee signed the return address that it saved (`JITStubRoutineSet::mark`). The setter of `$vm`'s `customAccessor` is compiled with `pac-ret` on ARM64 Linux in every build. On a processor without pointer authentication nothing is signed and the test passes whatever the code does |
| `stress/bun-return-address-of-function-is-signed.js` | with `ENABLE(RETURN_ADDRESS_SIGNING)` a function signs the return address that it saves in LLInt, Baseline, the DFG and the FTL alike: `$vm.returnAddressOfCallerIsSigned()` signs the address again and compares. Elsewhere, and on a processor without pointer authentication (`$vm.functionsSignReturnAddress()`), the test ends at once |
| `stress/bun-return-address-with-wrong-signature-is-not-returned-to.js` | with `ENABLE(RETURN_ADDRESS_SIGNING)` a function does not return once a bit of the signature of its saved return address was flipped, in each of the four tiers: the run must crash. Where nothing is signed the test crashes by itself |
| `stress/derived-constructor-this-initialized-by-another-arrow-function.js` | an arrow function or eval code of a derived constructor has the constructor's `this` once `super()` has returned, also when other code of the constructor called `super()` after it started: each kind of such code, each kind of read of `this` or of a super property, in every tier and from a bytecode cache. In such code a super property that comes before `super()` in the order of evaluation throws, and the `super()` behind it does not run. Upstream's open WebKit/WebKit#76967 makes that check in all code: once a sync brings it, `SuperNode::emitBytecode` needs only upstream's lines |
| the fr-CA block of `stress/intl-date-pattern-includes-literal-text.js` (the file is upstream's) | keeps the file's coverage on CLDR 49, where fr's pattern no longer has literal text: an `h` inside literal text is not mistaken for the hour field |
| the last block of `stress/regexp-test-sticky-first-char-filter.js` (the file is upstream's; nothing of upstream's text changes) | the first-character filter of a sticky `test()` comes from the first sets of the alternatives (`yarr/YarrFirstFollowSets.*`): behind a leading lookbehind, forward reference or lookahead, and in groups nested more than eight deep, a byte that passes the filter still reaches the matcher |

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,7 @@ JSC_DEFINE_JIT_OPERATION(operationAOTDirectEval, EncodedJSValue, (Instance* inst
.sourceOrigin = instance->state->modules->sourceOrigin(ModuleID(request.module)),
.lexicallyScopedFeatures = request.isStrict ? StrictModeLexicallyScopedFeature : NoLexicallyScopedFeatures,
.derivedContextType = request.allowsSuperCall ? DerivedContextType::DerivedConstructorContext : request.allowsSuperProperty ? DerivedContextType::DerivedMethodContext : DerivedContextType::None,
.derivedContextHasInnerSuperCall = !!request.isInDerivedConstructor,
.evalContextType = request.isInFieldInitializer ? EvalContextType::InstanceFieldEvalContext : request.isInFunction ? EvalContextType::FunctionEvalContext : EvalContextType::None,
.needsClassFieldInitializer = initializesInstances ? NeedsClassFieldInitializer::Yes : NeedsClassFieldInitializer::No,
.privateBrandRequirement = PrivateBrandRequirement::None,
Expand Down
7 changes: 6 additions & 1 deletion Source/JavaScriptCore/bytecode/ExecutableInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ enum class NeedsClassFieldInitializer : bool { No, Yes };
// FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized.
// https://bugs.webkit.org/show_bug.cgi?id=151547
struct ExecutableInfo {
ExecutableInfo(bool isConstructor, PrivateBrandRequirement privateBrandRequirement, bool isBuiltinFunction, ConstructorKind constructorKind, JSParserScriptMode scriptMode, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isArrowFunctionContext, bool isClassContext, EvalContextType evalContextType, bool isBuiltinDefaultClassConstructor = false)
ExecutableInfo(bool isConstructor, PrivateBrandRequirement privateBrandRequirement, bool isBuiltinFunction, ConstructorKind constructorKind, JSParserScriptMode scriptMode, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isArrowFunctionContext, bool isClassContext, EvalContextType evalContextType, bool isBuiltinDefaultClassConstructor = false, bool derivedContextHasInnerSuperCall = false)
: m_isConstructor(isConstructor)
, m_privateBrandRequirement(static_cast<unsigned>(privateBrandRequirement))
, m_isBuiltinFunction(isBuiltinFunction)
Expand All @@ -51,6 +51,7 @@ struct ExecutableInfo {
, m_isClassContext(isClassContext)
, m_evalContextType(static_cast<unsigned>(evalContextType))
, m_isBuiltinDefaultClassConstructor(isBuiltinDefaultClassConstructor)
, m_derivedContextHasInnerSuperCall(derivedContextHasInnerSuperCall)
{
ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
ASSERT(m_superBinding == static_cast<unsigned>(superBinding));
Expand All @@ -70,6 +71,7 @@ struct ExecutableInfo {
bool isClassContext() const { return m_isClassContext; }
NeedsClassFieldInitializer needsClassFieldInitializer() const { return static_cast<NeedsClassFieldInitializer>(m_needsClassFieldInitializer); }
bool isBuiltinDefaultClassConstructor() const { return m_isBuiltinDefaultClassConstructor; }
bool derivedContextHasInnerSuperCall() const { return m_derivedContextHasInnerSuperCall; }

private:
unsigned m_isConstructor : 1;
Expand All @@ -85,6 +87,9 @@ struct ExecutableInfo {
unsigned m_isClassContext : 1;
unsigned m_evalContextType : 2;
unsigned m_isBuiltinDefaultClassConstructor : 1;
// For an arrow function or eval code in DerivedConstructorContext: the constructor has a parent class, and an arrow
// function or eval code of the constructor can call super(). So |this| can get its value while this code runs.
unsigned m_derivedContextHasInnerSuperCall : 1;
};

} // namespace JSC
1 change: 1 addition & 0 deletions Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM& vm, Structure* structure, CodeType code
, m_hasTailCalls(false)
, m_constructorKind(static_cast<unsigned>(info.constructorKind()))
, m_derivedContextType(static_cast<unsigned>(info.derivedContextType()))
, m_derivedContextHasInnerSuperCall(info.derivedContextHasInnerSuperCall())
, m_evalContextType(static_cast<unsigned>(info.evalContextType()))
, m_codeType(static_cast<unsigned>(codeType))
, m_age(0)
Expand Down
2 changes: 2 additions & 0 deletions Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ class UnlinkedCodeBlock : public JSCell {
bool hasTailCalls() const { return m_hasTailCalls; }
void setHasTailCalls() { m_hasTailCalls = true; }
bool isBuiltinDefaultClassConstructor() const { return m_isBuiltinDefaultClassConstructor; }
bool derivedContextHasInnerSuperCall() const { return m_derivedContextHasInnerSuperCall; }

// Decoded on first use when the block came from a persistent bytecode cache.
// Any thread, including the collector's end phase (ErrorInstance::computeErrorInfo): the first call takes m_lock
Expand Down Expand Up @@ -445,6 +446,7 @@ class UnlinkedCodeBlock : public JSCell {
unsigned m_hasTailCalls : 1;
unsigned m_constructorKind : 2;
unsigned m_derivedContextType : 2;
unsigned m_derivedContextHasInnerSuperCall : 1;
unsigned m_evalContextType : 2;
unsigned m_codeType : 2;
unsigned m_age : 3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class UnlinkedCodeBlockGenerator {
SourceParseMode parseMode() const { return m_codeBlock->parseMode(); }
bool isArrowFunction() { return m_codeBlock->isArrowFunction(); }
DerivedContextType derivedContextType() const { return m_codeBlock->derivedContextType(); }
bool derivedContextHasInnerSuperCall() const { return m_codeBlock->derivedContextHasInnerSuperCall(); }
EvalContextType evalContextType() const { return m_codeBlock->evalContextType(); }
bool isArrowFunctionContext() const { return m_codeBlock->isArrowFunctionContext(); }
bool isClassContext() const { return m_codeBlock->isClassContext(); }
Expand Down
5 changes: 3 additions & 2 deletions Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static UnlinkedFunctionCodeBlock* generateUnlinkedFunctionCodeBlock(

bool isClassContext = executable->superBinding() == SuperBinding::Needed || executable->parseMode() == SourceParseMode::ClassFieldInitializerMode;

UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(vm, FunctionCode, ExecutableInfo(kind == CodeSpecializationKind::CodeForConstruct, executable->privateBrandRequirement(), functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), scriptMode, executable->superBinding(), parseMode, executable->derivedContextType(), executable->needsClassFieldInitializer(), false, isClassContext, executable->evalContextType(), executable->isBuiltinDefaultClassConstructor()), codeGenerationMode);
UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(vm, FunctionCode, ExecutableInfo(kind == CodeSpecializationKind::CodeForConstruct, executable->privateBrandRequirement(), functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), scriptMode, executable->superBinding(), parseMode, executable->derivedContextType(), executable->needsClassFieldInitializer(), false, isClassContext, executable->evalContextType(), executable->isBuiltinDefaultClassConstructor(), executable->derivedContextHasInnerSuperCall()), codeGenerationMode);

auto parentScopeTDZVariables = executable->parentScopeTDZVariables();
RefPtr<DeclaredNamesLink> parentDeclaredNames = executable->takeParentDeclaredNames();
Expand All @@ -87,7 +87,7 @@ static UnlinkedFunctionCodeBlock* generateUnlinkedFunctionCodeBlock(
return result;
}

UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM& vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, InlineAttribute inlineAttribute, JSParserScriptMode scriptMode, RefPtr<TDZEnvironmentLink> parentScopeTDZVariables, Vector<Identifier>&& generatorOrAsyncWrapperFunctionParameterNames, std::optional<PrivateNameEnvironment> parentPrivateNameEnvironment, DerivedContextType derivedContextType, EvalContextType evalContextType, NeedsClassFieldInitializer needsClassFieldInitializer, PrivateBrandRequirement privateBrandRequirement, bool isBuiltinDefaultClassConstructor)
UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM& vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, InlineAttribute inlineAttribute, JSParserScriptMode scriptMode, RefPtr<TDZEnvironmentLink> parentScopeTDZVariables, Vector<Identifier>&& generatorOrAsyncWrapperFunctionParameterNames, std::optional<PrivateNameEnvironment> parentPrivateNameEnvironment, DerivedContextType derivedContextType, EvalContextType evalContextType, NeedsClassFieldInitializer needsClassFieldInitializer, PrivateBrandRequirement privateBrandRequirement, bool isBuiltinDefaultClassConstructor, bool derivedContextHasInnerSuperCall)
: Base(vm, structure)
, m_hasCapturedVariables(false)
, m_unlinkedFunctionStart(node->functionStart())
Expand Down Expand Up @@ -117,6 +117,7 @@ UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM& vm, Structure* struct
, m_evalContextType(static_cast<unsigned>(evalContextType))
, m_hasName(!node->ident().isNull())
, m_isClass(false)
, m_derivedContextHasInnerSuperCall(derivedContextHasInnerSuperCall)
, m_nameIsDeferred(false)
, m_membersAreDeferred(false)
, m_scalarsAreDeferred(false)
Expand Down
8 changes: 5 additions & 3 deletions Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ class UnlinkedFunctionExecutable final : public JSCell {
return &vm.unlinkedFunctionExecutableSpace();
}

static UnlinkedFunctionExecutable* create(VM& vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, InlineAttribute inlineAttribute, JSParserScriptMode scriptMode, RefPtr<TDZEnvironmentLink> parentScopeTDZVariables, Vector<Identifier>&& generatorOrAsyncWrapperFunctionParameterNames, std::optional<PrivateNameEnvironment> parentPrivateNameEnvironment, DerivedContextType derivedContextType, EvalContextType evalContextType, NeedsClassFieldInitializer needsClassFieldInitializer, PrivateBrandRequirement privateBrandRequirement, bool isBuiltinDefaultClassConstructor = false)
static UnlinkedFunctionExecutable* create(VM& vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, InlineAttribute inlineAttribute, JSParserScriptMode scriptMode, RefPtr<TDZEnvironmentLink> parentScopeTDZVariables, Vector<Identifier>&& generatorOrAsyncWrapperFunctionParameterNames, std::optional<PrivateNameEnvironment> parentPrivateNameEnvironment, DerivedContextType derivedContextType, EvalContextType evalContextType, NeedsClassFieldInitializer needsClassFieldInitializer, PrivateBrandRequirement privateBrandRequirement, bool isBuiltinDefaultClassConstructor = false, bool derivedContextHasInnerSuperCall = false)
{
UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm))
UnlinkedFunctionExecutable(vm, vm.unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, inlineAttribute, scriptMode, WTF::move(parentScopeTDZVariables), WTF::move(generatorOrAsyncWrapperFunctionParameterNames), WTF::move(parentPrivateNameEnvironment), derivedContextType, evalContextType, needsClassFieldInitializer, privateBrandRequirement, isBuiltinDefaultClassConstructor);
UnlinkedFunctionExecutable(vm, vm.unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, inlineAttribute, scriptMode, WTF::move(parentScopeTDZVariables), WTF::move(generatorOrAsyncWrapperFunctionParameterNames), WTF::move(parentPrivateNameEnvironment), derivedContextType, evalContextType, needsClassFieldInitializer, privateBrandRequirement, isBuiltinDefaultClassConstructor, derivedContextHasInnerSuperCall);
instance->finishCreation(vm);
return instance;
}
Expand Down Expand Up @@ -279,6 +279,7 @@ class UnlinkedFunctionExecutable final : public JSCell {

JSC::DerivedContextType derivedContextType() const {return static_cast<JSC::DerivedContextType>(m_derivedContextType); }
EvalContextType evalContextType() const { return static_cast<EvalContextType>(m_evalContextType); }
bool derivedContextHasInnerSuperCall() const { return m_derivedContextHasInnerSuperCall; }

InlineAttribute inlineAttribute() const { return static_cast<InlineAttribute>(m_inlineAttribute); }

Expand Down Expand Up @@ -362,7 +363,7 @@ class UnlinkedFunctionExecutable final : public JSCell {
}

private:
UnlinkedFunctionExecutable(VM&, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, InlineAttribute, JSParserScriptMode, RefPtr<TDZEnvironmentLink>, Vector<Identifier>&&, std::optional<PrivateNameEnvironment>, JSC::DerivedContextType, EvalContextType, JSC::NeedsClassFieldInitializer, PrivateBrandRequirement, bool isBuiltinDefaultClassConstructor);
UnlinkedFunctionExecutable(VM&, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, InlineAttribute, JSParserScriptMode, RefPtr<TDZEnvironmentLink>, Vector<Identifier>&&, std::optional<PrivateNameEnvironment>, JSC::DerivedContextType, EvalContextType, JSC::NeedsClassFieldInitializer, PrivateBrandRequirement, bool isBuiltinDefaultClassConstructor, bool derivedContextHasInnerSuperCall);
UnlinkedFunctionExecutable(Decoder&, const CachedFunctionExecutable&);

DECLARE_VISIT_CHILDREN;
Expand Down Expand Up @@ -410,6 +411,7 @@ class UnlinkedFunctionExecutable final : public JSCell {
uint8_t m_evalContextType : 2;
uint8_t m_hasName : 1;
uint8_t m_isClass : 1;
uint8_t m_derivedContextHasInnerSuperCall : 1;
// Own bytes, not bits of the group above: the mutator clears these late, while compiler threads read that group.
bool m_nameIsDeferred { false }; // m_ecmaName is still in the cache record; implies m_membersAreDeferred
bool m_membersAreDeferred { false }; // TDZ variables + rare data are still in the cache record; the m_deferredMembers* union members are live
Expand Down
Loading
Loading