Commit 44213b3e authored by Nico Hartmann's avatar Nico Hartmann Committed by Commit Bot

[Torque] Add @acquireRead and @releaseWrite annotations

This CL adds support for generating acquire/release accessors on class
fields. Adds first use of this new feature (@acquireRead and
@releaseWrite) on FunctionTemplateInfo::rare_data.

Bug: v8:7790, v8:11122
Change-Id: I98f533807ab784d8667fd43564fe84686d27830c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2679684Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarSeth Brenith <seth.brenith@microsoft.com>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72596}
parent 7119497d
......@@ -51,7 +51,7 @@ extern class FunctionTemplateInfo extends TemplateInfo {
// If any of the setters declared by DECL_RARE_ACCESSORS are used then a
// FunctionTemplateRareData will be stored here. Until then this contains
// undefined.
rare_data: FunctionTemplateRareData|Undefined;
@acquireRead @releaseWrite rare_data: FunctionTemplateRareData|Undefined;
shared_function_info: SharedFunctionInfo|Undefined;
// Internal field to store a flag bitfield.
flag: SmiTagged<FunctionTemplateInfoFlags>;
......
......@@ -931,8 +931,8 @@ struct ClassFieldExpression {
bool weak;
bool const_qualified;
bool generate_verify;
bool relaxed_read;
bool relaxed_write;
FieldSynchronization read_synchronization;
FieldSynchronization write_synchronization;
};
struct LabelAndTypes {
......
......@@ -110,6 +110,10 @@ static const char* const ANNOTATION_USE_PARENT_TYPE_CHECKER =
static const char* const ANNOTATION_RELAXED_WRITE = "@relaxedWrite";
// Generate C++ accessors with relaxed read semantics.
static const char* const ANNOTATION_RELAXED_READ = "@relaxedRead";
// Generate C++ accessors with release write semantics.
static const char* const ANNOTATION_RELEASE_WRITE = "@releaseWrite";
// Generate C++ accessors with acquire read semantics.
static const char* const ANNOTATION_ACQUIRE_READ = "@acquireRead";
inline bool IsConstexprName(const std::string& name) {
return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) ==
......@@ -158,6 +162,12 @@ using ClassFlags = base::Flags<ClassFlag>;
enum class StructFlag { kNone = 0, kExport = 1 << 0 };
using StructFlags = base::Flags<StructFlag>;
enum class FieldSynchronization {
kNone,
kRelaxed,
kAcquireRelease,
};
} // namespace torque
} // namespace internal
} // namespace v8
......
......@@ -4195,13 +4195,26 @@ void CppClassGenerator::EmitLoadFieldStatement(const Field& f) {
inl_ << " value = ";
if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
if (f.relaxed_read) {
if (f.read_synchronization == FieldSynchronization::kAcquireRelease) {
ReportError("Torque doesn't support @acquireRead on untagged data");
} else if (f.read_synchronization == FieldSynchronization::kRelaxed) {
ReportError("Torque doesn't support @relaxedRead on untagged data");
}
inl_ << "this->template ReadField<" << type_name << ">(" << offset
<< ");\n";
} else {
const char* load = f.relaxed_read ? "Relaxed_Load" : "load";
const char* load;
switch (f.read_synchronization) {
case FieldSynchronization::kNone:
load = "load";
break;
case FieldSynchronization::kRelaxed:
load = "Relaxed_Load";
break;
case FieldSynchronization::kAcquireRelease:
load = "Acquire_Load";
break;
}
bool is_smi = field_type->IsSubtypeOf(TypeOracle::GetSmiType());
const std::string load_type = is_smi ? "Smi" : type_name;
const char* postfix = is_smi ? ".value()" : "";
......@@ -4237,10 +4250,25 @@ void CppClassGenerator::EmitStoreFieldStatement(const Field& f) {
} else {
bool strong_pointer = field_type->IsSubtypeOf(TypeOracle::GetObjectType());
bool is_smi = field_type->IsSubtypeOf(TypeOracle::GetSmiType());
const char* write_macro =
strong_pointer
? (f.relaxed_write ? "RELAXED_WRITE_FIELD" : "WRITE_FIELD")
: "RELAXED_WRITE_WEAK_FIELD";
const char* write_macro;
if (!strong_pointer) {
if (f.write_synchronization == FieldSynchronization::kAcquireRelease) {
ReportError("Torque doesn't support @releaseWrite on weak fields");
}
write_macro = "RELAXED_WRITE_WEAK_FIELD";
} else {
switch (f.write_synchronization) {
case FieldSynchronization::kNone:
write_macro = "WRITE_FIELD";
break;
case FieldSynchronization::kRelaxed:
write_macro = "RELAXED_WRITE_FIELD";
break;
case FieldSynchronization::kAcquireRelease:
write_macro = "RELEASE_WRITE_FIELD";
break;
}
}
const std::string value_to_write = is_smi ? "Smi::FromInt(value)" : "value";
if (!is_smi) {
......
......@@ -1946,11 +1946,22 @@ base::Optional<ParseResult> MakeAnnotation(ParseResultIterator* child_results) {
base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
AnnotationSet annotations(child_results,
{ANNOTATION_NO_VERIFIER, ANNOTATION_RELAXED_WRITE,
ANNOTATION_RELAXED_READ},
ANNOTATION_RELAXED_READ, ANNOTATION_RELEASE_WRITE,
ANNOTATION_ACQUIRE_READ},
{ANNOTATION_IF, ANNOTATION_IFNOT});
bool generate_verify = !annotations.Contains(ANNOTATION_NO_VERIFIER);
bool relaxed_write = annotations.Contains(ANNOTATION_RELAXED_WRITE);
bool relaxed_read = annotations.Contains(ANNOTATION_RELAXED_READ);
FieldSynchronization write_synchronization = FieldSynchronization::kNone;
if (annotations.Contains(ANNOTATION_RELEASE_WRITE)) {
write_synchronization = FieldSynchronization::kAcquireRelease;
} else if (annotations.Contains(ANNOTATION_RELAXED_WRITE)) {
write_synchronization = FieldSynchronization::kRelaxed;
}
FieldSynchronization read_synchronization = FieldSynchronization::kNone;
if (annotations.Contains(ANNOTATION_ACQUIRE_READ)) {
read_synchronization = FieldSynchronization::kAcquireRelease;
} else if (annotations.Contains(ANNOTATION_RELAXED_READ)) {
read_synchronization = FieldSynchronization::kRelaxed;
}
std::vector<ConditionalAnnotation> conditions;
base::Optional<std::string> if_condition =
annotations.GetStringParam(ANNOTATION_IF);
......@@ -1974,8 +1985,8 @@ base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
weak,
const_qualified,
generate_verify,
relaxed_read,
relaxed_write}};
read_synchronization,
write_synchronization}};
}
base::Optional<ParseResult> MakeStructField(
......
......@@ -208,8 +208,8 @@ const StructType* TypeVisitor::ComputeType(
false,
field.const_qualified,
false,
false,
false};
FieldSynchronization::kNone,
FieldSynchronization::kNone};
auto optional_size = SizeOf(f.name_and_type.type);
struct_type->RegisterField(f);
// Offsets are assigned based on an assumption of no space between members.
......@@ -430,8 +430,8 @@ void TypeVisitor::VisitClassFieldsAndMethods(
field_expression.weak,
field_expression.const_qualified,
field_expression.generate_verify,
field_expression.relaxed_read,
field_expression.relaxed_write});
field_expression.read_synchronization,
field_expression.write_synchronization});
ResidueClass field_size = std::get<0>(field.GetFieldSizeInformation());
if (field.index) {
// Validate that a value at any index in a packed array is aligned
......
......@@ -229,8 +229,8 @@ struct Field {
bool is_weak;
bool const_qualified;
bool generate_verify;
bool relaxed_read;
bool relaxed_write;
FieldSynchronization read_synchronization;
FieldSynchronization write_synchronization;
};
std::ostream& operator<<(std::ostream& os, const Field& name_and_type);
......
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