LibGC+Everywhere: Factor out a LibGC from LibJS

Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:

 * JS::NonnullGCPtr -> GC::Ref
 * JS::GCPtr -> GC::Ptr
 * JS::HeapFunction -> GC::Function
 * JS::CellImpl -> GC::Cell
 * JS::Handle -> GC::Root
This commit is contained in:
Shannon Booth 2024-11-15 04:01:23 +13:00 committed by Andreas Kling
commit f87041bf3a
Notes: github-actions[bot] 2024-11-15 13:50:17 +00:00
1722 changed files with 9939 additions and 9906 deletions

View file

@ -39,9 +39,9 @@ static bool record_inherits_from_cell(clang::CXXRecordDecl const& record)
if (!record.isCompleteDefinition())
return false;
bool inherits_from_cell = record.getQualifiedNameAsString() == "JS::CellImpl";
bool inherits_from_cell = record.getQualifiedNameAsString() == "GC::Cell";
record.forallBases([&](clang::CXXRecordDecl const* base) -> bool {
if (base->getQualifiedNameAsString() == "JS::CellImpl") {
if (base->getQualifiedNameAsString() == "GC::Cell") {
inherits_from_cell = true;
return false;
}
@ -58,12 +58,12 @@ static std::vector<clang::QualType> get_all_qualified_types(clang::QualType cons
auto specialization_name = template_specialization->getTemplateName().getAsTemplateDecl()->getQualifiedNameAsString();
// Do not unwrap GCPtr/NonnullGCPtr/MarkedVector
static std::unordered_set<std::string> gc_relevant_type_names {
"JS::GCPtr",
"JS::NonnullGCPtr",
"JS::RawGCPtr",
"JS::RawNonnullGCPtr",
"JS::MarkedVector",
"JS::Handle",
"GC::Ptr",
"GC::Ref",
"GC::RawPtr",
"GC::RawRef",
"GC::MarkedVector",
"GC::Root",
};
if (gc_relevant_type_names.contains(specialization_name)) {
@ -86,8 +86,8 @@ static std::vector<clang::QualType> get_all_qualified_types(clang::QualType cons
}
enum class OuterType {
GCPtr,
RawGCPtr,
Handle,
RawPtr,
Root,
Ptr,
Ref,
};
@ -109,12 +109,12 @@ static std::optional<QualTypeGCInfo> validate_qualified_type(clang::QualType con
auto template_type_name = specialization->getTemplateName().getAsTemplateDecl()->getQualifiedNameAsString();
OuterType outer_type;
if (template_type_name == "JS::GCPtr" || template_type_name == "JS::NonnullGCPtr") {
if (template_type_name == "GC::Ptr" || template_type_name == "GC::Ref") {
outer_type = OuterType::GCPtr;
} else if (template_type_name == "JS::RawGCPtr" || template_type_name == "JS::RawNonnullGCPtr") {
outer_type = OuterType::RawGCPtr;
} else if (template_type_name == "JS::Handle") {
outer_type = OuterType::Handle;
} else if (template_type_name == "GC::RawPtr" || template_type_name == "GC::RawRef") {
outer_type = OuterType::RawPtr;
} else if (template_type_name == "GC::Root") {
outer_type = OuterType::Root;
} else {
return {};
}
@ -173,7 +173,7 @@ bool LibJSGCVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* record)
// Cell triggers a bunch of warnings for its empty visit_edges implementation, but
// it doesn't have any members anyways so it's fine to just ignore.
auto qualified_name = record->getQualifiedNameAsString();
if (qualified_name == "JS::CellImpl")
if (qualified_name == "GC::Cell")
return true;
auto& diag_engine = m_context.getDiagnostics();
@ -192,29 +192,29 @@ bool LibJSGCVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* record)
if (outer_type == OuterType::Ptr || outer_type == OuterType::Ref) {
if (base_type_inherits_from_cell) {
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "%0 to JS::CellImpl type should be wrapped in %1");
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "%0 to GC::Cell type should be wrapped in %1");
auto builder = diag_engine.Report(field->getLocation(), diag_id);
if (outer_type == OuterType::Ref) {
builder << "reference"
<< "JS::NonnullGCPtr";
<< "GC::Ref";
} else {
builder << "pointer"
<< "JS::GCPtr";
<< "GC::Ptr";
}
}
} else if (outer_type == OuterType::GCPtr || outer_type == OuterType::RawGCPtr) {
} else if (outer_type == OuterType::GCPtr || outer_type == OuterType::RawPtr) {
if (!base_type_inherits_from_cell) {
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "Specialization type must inherit from JS::CellImpl");
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "Specialization type must inherit from GC::Cell");
diag_engine.Report(field->getLocation(), diag_id);
} else if (outer_type == OuterType::GCPtr) {
fields_that_need_visiting.push_back(field);
}
} else if (outer_type == OuterType::Handle) {
} else if (outer_type == OuterType::Root) {
if (record_is_cell && m_detect_invalid_function_members) {
// FIXME: Change this to an Error when all of the use cases get addressed and remove the plugin argument
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Warning, "Types inheriting from JS::CellImpl should not have %0 fields");
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Warning, "Types inheriting from GC::Cell should not have %0 fields");
auto builder = diag_engine.Report(field->getLocation(), diag_id);
builder << "JS::Handle";
builder << "GC::Root";
}
}
}
@ -227,7 +227,7 @@ bool LibJSGCVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* record)
clang::DeclarationName name = &m_context.Idents.get("visit_edges");
auto const* visit_edges_method = record->lookup(name).find_first<clang::CXXMethodDecl>();
if (!visit_edges_method && !fields_that_need_visiting.empty()) {
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "JS::Cell-inheriting class %0 contains a GC-allocated member %1 but has no visit_edges method");
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "GC::Cell-inheriting class %0 contains a GC-allocated member %1 but has no visit_edges method");
auto builder = diag_engine.Report(record->getLocation(), diag_id);
builder << record->getName()
<< fields_that_need_visiting[0];
@ -236,7 +236,7 @@ bool LibJSGCVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* record)
return true;
// Search for a call to Base::visit_edges. Note that this also has the nice side effect of
// ensuring the classes use JS_CELL/JS_OBJECT, as Base will not be defined if they do not.
// ensuring the classes use GC_CELL/GC_OBJECT, as Base will not be defined if they do not.
MatchFinder base_visit_edges_finder;
SimpleCollectMatchesCallback<clang::MemberExpr> base_visit_edges_callback("member-call");
@ -311,8 +311,8 @@ static std::optional<CellTypeWithOrigin> find_cell_type_with_origin(clang::CXXRe
if (auto const* base_record = base.getType()->getAsCXXRecordDecl()) {
auto base_name = base_record->getQualifiedNameAsString();
if (base_name == "JS::CellImpl")
return CellTypeWithOrigin { *base_record, LibJSCellMacro::Type::JSCell };
if (base_name == "GC::Cell")
return CellTypeWithOrigin { *base_record, LibJSCellMacro::Type::GCCell };
if (base_name == "JS::Object")
return CellTypeWithOrigin { *base_record, LibJSCellMacro::Type::JSObject };
@ -353,7 +353,7 @@ LibJSGCVisitor::CellMacroExpectation LibJSGCVisitor::get_record_cell_macro_expec
}
assert(false);
std::unreachable();
__builtin_unreachable();
}
void LibJSGCVisitor::validate_record_macros(clang::CXXRecordDecl const& record)
@ -362,7 +362,7 @@ void LibJSGCVisitor::validate_record_macros(clang::CXXRecordDecl const& record)
auto record_range = record.getSourceRange();
// FIXME: The current macro detection doesn't recursively search through macro expansion,
// so if the record itself is defined in a macro, the JS_CELL/etc won't be found
// so if the record itself is defined in a macro, the GC_CELL/etc won't be found
if (source_manager.isMacroBodyExpansion(record_range.getBegin()))
return;
@ -417,13 +417,13 @@ void LibJSGCVisitor::validate_record_macros(clang::CXXRecordDecl const& record)
continue;
if (found_macro) {
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "Record has multiple JS_CELL-like macro invocations");
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "Record has multiple GC_CELL-like macro invocations");
diag_engine.Report(record_range.getBegin(), diag_id);
}
found_macro = true;
if (macro.type != expected_cell_macro_type) {
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "Invalid JS-CELL-like macro invocation; expected %0");
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "Invalid GC-CELL-like macro invocation; expected %0");
auto builder = diag_engine.Report(macro.range.getBegin(), diag_id);
builder << LibJSCellMacro::type_name(expected_cell_macro_type);
}
@ -469,8 +469,8 @@ void LibJSGCASTConsumer::HandleTranslationUnit(clang::ASTContext& context)
char const* LibJSCellMacro::type_name(Type type)
{
switch (type) {
case Type::JSCell:
return "JS_CELL";
case Type::GCCell:
return "GC_CELL";
case Type::JSObject:
return "JS_OBJECT";
case Type::JSEnvironment:
@ -498,7 +498,7 @@ void LibJSPPCallbacks::MacroExpands(clang::Token const& name_token, clang::Macro
{
if (auto* ident_info = name_token.getIdentifierInfo()) {
static llvm::StringMap<LibJSCellMacro::Type> libjs_macro_types {
{ "JS_CELL", LibJSCellMacro::Type::JSCell },
{ "GC_CELL", LibJSCellMacro::Type::GCCell },
{ "JS_OBJECT", LibJSCellMacro::Type::JSObject },
{ "JS_ENVIRONMENT", LibJSCellMacro::Type::JSEnvironment },
{ "JS_PROTOTYPE_OBJECT", LibJSCellMacro::Type::JSPrototypeObject },

View file

@ -12,7 +12,7 @@
struct LibJSCellMacro {
enum class Type {
JSCell,
GCCell,
JSObject,
JSEnvironment,
JSPrototypeObject,