Commit cf81ce23 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque]: Allow const-qualified struct and class fields

Const-qualified fields are allowed in both classes and structs.
In both cases, const fields can only be set via initialization
during construction.

Drive-by: unitialized -> uninitialized

Bug: v8:7793
Change-Id: Idec08df30f7897c756b7dd6f2b10bb6012fefb6a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1547853
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60592}
parent f0cfb7cc
......@@ -2019,11 +2019,11 @@ struct FastJSArrayWitness {
}
}
stable: JSArray;
const stable: JSArray;
unstable: FastJSArray;
map: Map;
hasDoubles: bool;
hasSmis: bool;
const map: Map;
const hasDoubles: bool;
const hasSmis: bool;
arrayIsPushable: bool;
}
......
......@@ -697,12 +697,14 @@ struct NameAndTypeExpression {
struct StructFieldExpression {
NameAndTypeExpression name_and_type;
bool const_qualified;
};
struct ClassFieldExpression {
NameAndTypeExpression name_and_type;
base::Optional<std::string> index;
bool weak;
bool const_qualified;
};
struct LabelAndTypes {
......
......@@ -464,13 +464,16 @@ void DeclarationVisitor::FinalizeStructFieldsAndMethods(
StructType* struct_type, StructDeclaration* struct_declaration) {
size_t offset = 0;
for (auto& field : struct_declaration->fields) {
CurrentSourcePosition::Scope position_activator(
field.name_and_type.type->pos);
const Type* field_type = Declarations::GetType(field.name_and_type.type);
struct_type->RegisterField({field.name_and_type.name->pos,
struct_type,
base::nullopt,
{field.name_and_type.name->value, field_type},
offset,
false});
false,
field.const_qualified});
offset += LoweredSlotCount(field_type);
}
CurrentSourcePosition::Scope position_activator(struct_declaration->pos);
......@@ -510,7 +513,8 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
index_field,
{field_expression.name_and_type.name->value, field_type},
class_offset,
field_expression.weak});
field_expression.weak,
field_expression.const_qualified});
} else {
if (seen_indexed_field) {
ReportError("cannot declare non-indexable field \"",
......@@ -524,7 +528,8 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
base::nullopt,
{field_expression.name_and_type.name->value, field_type},
class_offset,
field_expression.weak});
field_expression.weak,
field_expression.const_qualified});
size_t field_size;
std::string size_string;
std::string machine_type;
......@@ -598,6 +603,7 @@ void DeclarationVisitor::FinalizeStructsAndClasses() {
StructType* struct_type;
std::tie(scope, struct_declaration, struct_type) = current_struct_info;
CurrentScope::Scope scope_activator(scope);
CurrentSourcePosition::Scope position_activator(struct_declaration->pos);
FinalizeStructFieldsAndMethods(struct_type, struct_declaration);
}
......
......@@ -568,7 +568,7 @@ const Type* ImplementationVisitor::Visit(
TypeVector lowered_types = LowerType(*type);
for (const Type* type : lowered_types) {
assembler().Emit(PushUninitializedInstruction{TypeOracle::GetTopType(
"unitialized variable '" + stmt->name->value + "' of type " +
"uninitialized variable '" + stmt->name->value + "' of type " +
type->ToString() + " originally defined at " +
PositionAsString(stmt->pos),
type)});
......@@ -1149,7 +1149,7 @@ VisitResult ImplementationVisitor::TemporaryUninitializedStruct(
range.Extend(
TemporaryUninitializedStruct(struct_type, reason).stack_range());
} else {
std::string descriptor = "unitialized field '" + f.name_and_type.name +
std::string descriptor = "uninitialized field '" + f.name_and_type.name +
"' declared at " + PositionAsString(f.pos) +
" (" + reason + ")";
TypeVector lowered_types = LowerType(f.name_and_type.type);
......@@ -1314,8 +1314,8 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) {
InitializerResults initializer_results =
VisitInitializerResults(expr->parameters);
// Output the code to generate an unitialized object of the class size in the
// GC heap.
// Output the code to generate an uninitialized object of the class size in
// the GC heap.
VisitResult allocate_result;
if (class_type->IsExtern()) {
if (initializer_results.results.size() == 0) {
......@@ -1698,7 +1698,7 @@ VisitResult ImplementationVisitor::Visit(StructExpression* decl) {
ImplementationVisitor::VisitInitializerResults(decl->expressions);
const StructType* struct_type = StructType::cast(raw_type);
// Push unitialized 'this'
// Push uninitialized 'this'
VisitResult result = TemporaryUninitializedStruct(
struct_type, "it's not initialized in the struct " + struct_type->name());
......@@ -1728,13 +1728,20 @@ LocationReference ImplementationVisitor::GetLocationReference(
LocationReference reference = GetLocationReference(expr->object);
if (reference.IsVariableAccess() &&
reference.variable().type()->IsStructType()) {
const StructType* type = StructType::cast(reference.variable().type());
const Field& field = type->LookupField(expr->field->value);
if (GlobalContext::collect_language_server_data()) {
const StructType* type = StructType::cast(reference.variable().type());
const Field& field = type->LookupField(expr->field->value);
LanguageServerData::AddDefinition(expr->field->pos, field.pos);
}
return LocationReference::VariableAccess(
ProjectStructField(reference.variable(), expr->field->value));
if (field.const_qualified) {
VisitResult t_value =
ProjectStructField(reference.variable(), expr->field->value);
return LocationReference::Temporary(
t_value, "for constant field '" + field.name_and_type.name + "'");
} else {
return LocationReference::VariableAccess(
ProjectStructField(reference.variable(), expr->field->value));
}
}
if (reference.IsTemporary() && reference.temporary().type()->IsStructType()) {
if (GlobalContext::collect_language_server_data()) {
......
......@@ -1104,17 +1104,20 @@ base::Optional<ParseResult> MakeNameAndType(
base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
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}};
return ParseResult{
ClassFieldExpression{{name, type}, index, weak, const_qualified}};
}
base::Optional<ParseResult> MakeStructField(
ParseResultIterator* child_results) {
auto const_qualified = child_results->NextAs<bool>();
auto name = child_results->NextAs<Identifier*>();
auto type = child_results->NextAs<TypeExpression*>();
return ParseResult{StructFieldExpression{{name, type}}};
return ParseResult{StructFieldExpression{{name, type}, const_qualified}};
}
base::Optional<ParseResult> ExtractAssignmentOperator(
......@@ -1309,12 +1312,13 @@ struct TorqueGrammar : Grammar {
Optional<std::string>(Sequence({Token("["), &identifier, Token("]")}))};
Symbol classField = {
Rule({CheckIf(Token("weak")), &name, optionalArraySpecifier, Token(":"),
&type, Token(";")},
Rule({CheckIf(Token("weak")), CheckIf(Token("const")), &name,
optionalArraySpecifier, Token(":"), &type, Token(";")},
MakeClassField)};
Symbol structField = {
Rule({&name, Token(":"), &type, Token(";")}, MakeStructField)};
Rule({CheckIf(Token("const")), &name, Token(":"), &type, Token(";")},
MakeStructField)};
// Result: ParameterList
Symbol parameterListNoVararg = {
......
......@@ -176,6 +176,7 @@ struct Field {
NameAndType name_and_type;
size_t offset;
bool is_weak;
bool const_qualified;
};
std::ostream& operator<<(std::ostream& os, const Field& name_and_type);
......
......@@ -137,7 +137,7 @@
# messing up ability to see other failures on the waterfall.
'js1_5/extensions/regress-342960': [SKIP],
# This test uses a unitialized variable. A Bug has been filed:
# This test uses an uninitialized variable. A Bug has been filed:
# https://bugzilla.mozilla.org/show_bug.cgi?id=575575
'js1_5/Array/regress-465980-02': [SKIP],
......
......@@ -820,4 +820,22 @@ namespace test {
check(o.a == 6);
check(o.b == 5);
}
struct StructWithConst {
TestMethod1(): int32 {
return this.b;
}
TestMethod2(): Object {
return this.a;
}
a: Object;
const b: int32;
}
macro TestConstInStructs() {
const x = StructWithConst{Null, 1};
let y = StructWithConst{Null, 1};
y.a = Undefined;
const copy = x;
}
}
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