Commit d4e0b5ae authored by Seth Brenith's avatar Seth Brenith Committed by Commit Bot

[torque] Add support for conditionally-included class fields

This change introduces a new decorator syntax @ifdef which can be used
on any class fields in .tq files, and updates SharedFunctionInfo to use
it as an example.

Bug: v8:7793
Change-Id: I690ae2a10d6cab044eedf5b931e4f95e757ed469
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1536985
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Reviewed-by: 's avatarHannes Payer <hpayer@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61349}
parent e69460e6
......@@ -381,10 +381,8 @@ extern class SharedFunctionInfo extends HeapObject {
expected_nof_properties: uint16;
function_token_offset: int16;
flags: int32;
}
extern class SharedFunctionInfoWithID extends SharedFunctionInfo {
unique_id: int32;
@ifdef(V8_SFI_HAS_UNIQUE_ID) unique_id: int32;
}
extern class JSBoundFunction extends JSObject {
......
......@@ -85,6 +85,8 @@ constexpr int kStackSpaceRequiredForCompilation = 40;
// Some types of tracing require the SFI to store a unique ID.
#if defined(V8_TRACE_MAPS) || defined(V8_TRACE_IGNITION)
#define V8_SFI_HAS_UNIQUE_ID true
#else
#define V8_SFI_HAS_UNIQUE_ID false
#endif
#if defined(V8_OS_WIN) && defined(V8_TARGET_ARCH_X64)
......
......@@ -3553,8 +3553,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
}
share->set_script_or_debug_info(*undefined_value(), SKIP_WRITE_BARRIER);
#if V8_SFI_HAS_UNIQUE_ID
Handle<SharedFunctionInfoWithID>::cast(share)->set_unique_id(
isolate()->GetNextUniqueSharedFunctionInfoId());
share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());
#endif
// Set integer fields (smi or int, depending on the architecture).
......
......@@ -509,13 +509,8 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_MAP(UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE,
UncompiledDataWithPreparseData::kSize,
uncompiled_data_with_preparse_data)
#if V8_SFI_HAS_UNIQUE_ID
ALLOCATE_MAP(SHARED_FUNCTION_INFO_TYPE,
SharedFunctionInfoWithID::kAlignedSize, shared_function_info)
#else
ALLOCATE_MAP(SHARED_FUNCTION_INFO_TYPE, SharedFunctionInfo::kAlignedSize,
shared_function_info)
#endif
ALLOCATE_MAP(CODE_DATA_CONTAINER_TYPE, CodeDataContainer::kSize,
code_data_container)
......
......@@ -1671,7 +1671,7 @@ void Logger::MapEvent(const char* type, Map from, Map to, const char* reason,
SharedFunctionInfo sfi = SharedFunctionInfo::cast(name_or_sfi);
msg << sfi->DebugName();
#if V8_SFI_HAS_UNIQUE_ID
msg << " " << SharedFunctionInfoWithID::cast(sfi)->unique_id();
msg << " " << sfi->unique_id();
#endif // V8_SFI_HAS_UNIQUE_ID
}
}
......
......@@ -128,6 +128,9 @@ ACCESSORS(SharedFunctionInfo, name_or_scope_info, Object,
ACCESSORS(SharedFunctionInfo, script_or_debug_info, Object,
kScriptOrDebugInfoOffset)
#if V8_SFI_HAS_UNIQUE_ID
INT_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset)
#endif
UINT16_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
UINT16_ACCESSORS(SharedFunctionInfo, internal_formal_parameter_count,
kFormalParameterCountOffset)
......@@ -624,10 +627,6 @@ void SharedFunctionInfo::ClearPreparseData() {
DCHECK(HasUncompiledDataWithoutPreparseData());
}
OBJECT_CONSTRUCTORS_IMPL(SharedFunctionInfoWithID, SharedFunctionInfo)
CAST_ACCESSOR(SharedFunctionInfoWithID)
INT_ACCESSORS(SharedFunctionInfoWithID, unique_id, kUniqueIdOffset)
// static
void UncompiledData::Initialize(
UncompiledData data, String inferred_name, int start_position,
......
......@@ -315,6 +315,12 @@ class SharedFunctionInfo : public HeapObject {
// function. The value is only reliable when the function has been compiled.
DECL_UINT16_ACCESSORS(expected_nof_properties)
#if V8_SFI_HAS_UNIQUE_ID
// [unique_id] - For --trace-maps purposes, an identifier that's persistent
// even if the GC moves this SharedFunctionInfo.
DECL_INT_ACCESSORS(unique_id)
#endif
// [function data]: This field holds some additional data for function.
// Currently it has one of:
// - a FunctionTemplateInfo to make benefit the API [IsApiFunction()].
......@@ -706,14 +712,6 @@ class SharedFunctionInfo : public HeapObject {
// This is needed to set up the [[HomeObject]] on the function instance.
inline bool needs_home_object() const;
V8_INLINE bool IsSharedFunctionInfoWithID() const {
#if V8_SFI_HAS_UNIQUE_ID
return true;
#else
return false;
#endif
}
private:
// [name_or_scope_info]: Function name string, kNoSharedNameSentinel or
// ScopeInfo.
......@@ -748,23 +746,6 @@ class SharedFunctionInfo : public HeapObject {
OBJECT_CONSTRUCTORS(SharedFunctionInfo, HeapObject);
};
class SharedFunctionInfoWithID : public SharedFunctionInfo {
public:
// [unique_id] - For --trace-maps purposes, an identifier that's persistent
// even if the GC moves this SharedFunctionInfo.
DECL_INT_ACCESSORS(unique_id)
DECL_CAST(SharedFunctionInfoWithID)
DEFINE_FIELD_OFFSET_CONSTANTS(
SharedFunctionInfo::kSize,
TORQUE_GENERATED_SHARED_FUNCTION_INFO_WITH_ID_FIELDS)
static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
OBJECT_CONSTRUCTORS(SharedFunctionInfoWithID, SharedFunctionInfo);
};
// Printing support.
struct SourceCodeOf {
explicit SourceCodeOf(SharedFunctionInfo v, int max = -1)
......
......@@ -718,6 +718,7 @@ struct StructFieldExpression {
struct ClassFieldExpression {
NameAndTypeExpression name_and_type;
base::Optional<std::string> index;
base::Optional<std::string> conditional;
bool weak;
bool const_qualified;
};
......
......@@ -4,7 +4,9 @@
#include <cctype>
#include <set>
#include <unordered_map>
#include "src/globals.h"
#include "src/torque/constants.h"
#include "src/torque/earley-parser.h"
#include "src/torque/torque-parser.h"
......@@ -31,6 +33,27 @@ struct TypeswitchCase {
Statement* block;
};
class BuildFlags : public ContextualClass<BuildFlags> {
public:
BuildFlags() {
build_flags_["V8_SFI_HAS_UNIQUE_ID"] = V8_SFI_HAS_UNIQUE_ID;
build_flags_["TRUE_FOR_TESTING"] = true;
build_flags_["FALSE_FOR_TESTING"] = false;
}
static bool GetFlag(const std::string& name, const char* production) {
auto it = Get().build_flags_.find(name);
if (it == Get().build_flags_.end()) {
ReportError("Unknown flag used in ", production, ": ", name,
". Please add it to the list in BuildFlags.");
}
return it->second;
}
private:
std::unordered_map<std::string, bool> build_flags_;
};
DEFINE_CONTEXTUAL_VARIABLE(BuildFlags)
template <>
V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<std::string>::id =
ParseResultTypeId::kStdString;
......@@ -646,7 +669,16 @@ base::Optional<ParseResult> MakeClassDeclaration(
}
auto generates = child_results->NextAs<base::Optional<std::string>>();
auto methods = child_results->NextAs<std::vector<Declaration*>>();
auto fields = child_results->NextAs<std::vector<ClassFieldExpression>>();
auto fields_raw = child_results->NextAs<std::vector<ClassFieldExpression>>();
// Filter to only include fields that should be present based on decoration.
std::vector<ClassFieldExpression> fields;
std::copy_if(fields_raw.begin(), fields_raw.end(), std::back_inserter(fields),
[](const ClassFieldExpression& exp) {
return !exp.conditional.has_value() ||
BuildFlags::GetFlag(*exp.conditional, "@ifdef");
});
Declaration* result = MakeNode<ClassDeclaration>(
name, is_extern, generate_print, transient, std::move(extends),
std::move(generates), std::move(methods), fields);
......@@ -1224,13 +1256,14 @@ base::Optional<ParseResult> MakeNameAndExpressionFromExpression(
}
base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
auto conditional = child_results->NextAs<base::Optional<std::string>>();
auto weak = child_results->NextAs<bool>();
auto const_qualified = child_results->NextAs<bool>();
auto name = child_results->NextAs<Identifier*>();
auto index = child_results->NextAs<base::Optional<std::string>>();
auto type = child_results->NextAs<TypeExpression*>();
return ParseResult{
ClassFieldExpression{{name, type}, index, weak, const_qualified}};
return ParseResult{ClassFieldExpression{
{name, type}, index, conditional, weak, const_qualified}};
}
base::Optional<ParseResult> MakeStructField(
......@@ -1447,10 +1480,12 @@ struct TorqueGrammar : Grammar {
Symbol* optionalArraySpecifier =
Optional<std::string>(Sequence({Token("["), &identifier, Token("]")}));
Symbol classField = {
Rule({CheckIf(Token("weak")), CheckIf(Token("const")), &name,
optionalArraySpecifier, Token(":"), &type, Token(";")},
MakeClassField)};
Symbol classField = {Rule(
{Optional<std::string>(
Sequence({Token("@ifdef"), Token("("), &identifier, Token(")")})),
CheckIf(Token("weak")), CheckIf(Token("const")), &name,
optionalArraySpecifier, Token(":"), &type, Token(";")},
MakeClassField)};
Symbol structField = {
Rule({CheckIf(Token("const")), &name, Token(":"), &type, Token(";")},
......@@ -1815,7 +1850,10 @@ struct TorqueGrammar : Grammar {
} // namespace
void ParseTorque(const std::string& input) { TorqueGrammar().Parse(input); }
void ParseTorque(const std::string& input) {
BuildFlags::Scope build_flags_scope;
TorqueGrammar().Parse(input);
}
} // namespace torque
} // namespace internal
......
......@@ -784,6 +784,15 @@ namespace test {
i: uintptr;
}
// This class should throw alignment errors if @ifdef decorators aren't
// working.
extern class PreprocessingTest extends JSObject {
@ifdef(FALSE_FOR_TESTING) a: int8;
@ifdef(TRUE_FOR_TESTING) a: int16;
b: int16;
d: int32;
}
macro TestClassWithAllTypesLoadsAndStores(
t: TestClassWithAllTypes, r: RawPtr, v1: int8, v2: uint8, v3: int16,
v4: uint16) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment