Commit a9a1a3bb authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] add references to HeapObject fields.

This adds references to HeapObject fields to Torque.
The syntax is based on Rust (which is essentially C pointer syntax).

The type &T is a reference to T (which must be a scalar type for now).
We can create references from field access expressions, using the
addressof(&) operator:
  &obj.fieldname
To read or assign a reference, we use the dereference(*) operator:
  *someref = *otherref

This CL also uses references internally normal class field accesses,
but only if there is no overload for field accessor functions.
This allows to have overloaded field accessors for a subtype like
FastJSArray. However, there is a change in behavior in that an
operator ".fieldname" will stop reference creation and will therefore
also stop write access to a class field of the same name. That's why
this CL had to add a write overload ".length=" for FastJSArray.

References desugar to a pair of a tagged HeapObject pointer and an
untagged offset into this HeapObject. On the CSA-side, they are
represented by the C++ struct

struct TorqueReference {
  TNode<HeapObject> object;
  TNode<IntPtrT> offset;
};

Bug: v8:7793
Change-Id: Ica6468d47847bd68fb6b85f731cf8fbe142fa401
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1557151
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60780}
parent de6a07dc
...@@ -39,12 +39,12 @@ type int31 extends int32 ...@@ -39,12 +39,12 @@ type int31 extends int32
type uint31 extends uint32 type uint31 extends uint32
generates 'TNode<Uint32T>' constexpr 'uint31_t'; generates 'TNode<Uint32T>' constexpr 'uint31_t';
type int16 extends int31 type int16 extends int31
generates 'TNode<Int32T>' constexpr 'int16_t'; generates 'TNode<Int16T>' constexpr 'int16_t';
type uint16 extends uint31 type uint16 extends uint31
generates 'TNode<Uint32T>' constexpr 'uint16_t'; generates 'TNode<Uint16T>' constexpr 'uint16_t';
type int8 extends int16 generates 'TNode<Int32T>' constexpr 'int8_t'; type int8 extends int16 generates 'TNode<Int8T>' constexpr 'int8_t';
type uint8 extends uint16 type uint8 extends uint16
generates 'TNode<Uint32T>' constexpr 'uint8_t'; generates 'TNode<Uint8T>' constexpr 'uint8_t';
type int64 generates 'TNode<Int64T>' constexpr 'int64_t'; type int64 generates 'TNode<Int64T>' constexpr 'int64_t';
type intptr generates 'TNode<IntPtrT>' constexpr 'intptr_t'; type intptr generates 'TNode<IntPtrT>' constexpr 'intptr_t';
type uintptr generates 'TNode<UintPtrT>' constexpr 'uintptr_t'; type uintptr generates 'TNode<UintPtrT>' constexpr 'uintptr_t';
...@@ -1760,6 +1760,11 @@ extern operator '.elements_kind' macro LoadElementsKind(JSTypedArray): ...@@ -1760,6 +1760,11 @@ extern operator '.elements_kind' macro LoadElementsKind(JSTypedArray):
ElementsKind; ElementsKind;
extern operator '.length' macro LoadFastJSArrayLength(FastJSArray): Smi; extern operator '.length' macro LoadFastJSArrayLength(FastJSArray): Smi;
operator '.length=' macro StoreFastJSArrayLength(
array: FastJSArray, length: Smi) {
const array: JSArray = array;
array.length = length;
}
extern operator '.objects[]' macro LoadFixedArrayElement( extern operator '.objects[]' macro LoadFixedArrayElement(
FixedArray, intptr): Object; FixedArray, intptr): Object;
......
...@@ -851,6 +851,54 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -851,6 +851,54 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
LoadObjectField(object, offset, MachineType::AnyTagged())); LoadObjectField(object, offset, MachineType::AnyTagged()));
} }
// Reference is the CSA-equivalent of a Torque reference value,
// representing an inner pointer into a HeapObject.
struct Reference {
TNode<HeapObject> object;
TNode<IntPtrT> offset;
std::tuple<TNode<HeapObject>, TNode<IntPtrT>> Flatten() const {
return std::make_tuple(object, offset);
}
};
template <class T, typename std::enable_if<
std::is_convertible<TNode<T>, TNode<Object>>::value,
int>::type = 0>
TNode<T> LoadReference(Reference reference) {
return CAST(LoadObjectField(reference.object, reference.offset,
MachineTypeOf<T>::value));
}
template <class T, typename std::enable_if<
std::is_convertible<TNode<T>, TNode<UntaggedT>>::value,
int>::type = 0>
TNode<T> LoadReference(Reference reference) {
return UncheckedCast<T>(LoadObjectField(reference.object, reference.offset,
MachineTypeOf<T>::value));
}
template <class T, typename std::enable_if<
std::is_convertible<TNode<T>, TNode<Object>>::value,
int>::type = 0>
void StoreReference(Reference reference, TNode<T> value) {
int const_offset;
if (std::is_same<T, Smi>::value) {
StoreObjectFieldNoWriteBarrier(reference.object, reference.offset, value);
} else if (std::is_same<T, Map>::value &&
ToInt32Constant(reference.offset, const_offset) &&
const_offset == HeapObject::kMapOffset) {
StoreMap(reference.object, value);
} else {
StoreObjectField(reference.object, reference.offset, value);
}
}
template <class T, typename std::enable_if<
std::is_convertible<TNode<T>, TNode<UntaggedT>>::value,
int>::type = 0>
void StoreReference(Reference reference, TNode<T> value) {
StoreObjectFieldNoWriteBarrier<T>(reference.object, reference.offset,
value);
}
// Tag a smi and store it. // Tag a smi and store it.
void StoreAndTagSmi(Node* base, int offset, Node* value); void StoreAndTagSmi(Node* base, int offset, Node* value);
...@@ -2882,7 +2930,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -2882,7 +2930,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Update the type feedback vector. // Update the type feedback vector.
void UpdateFeedback(Node* feedback, Node* feedback_vector, Node* slot_id); void UpdateFeedback(Node* feedback, Node* feedback_vector, Node* slot_id);
// Report that there was a feedback update, performing any tasks that should // Report that there was a feedback update, performing any tasks that should
// be done after a feedback update. // be done after a feedback update.
void ReportFeedbackUpdate(SloppyTNode<FeedbackVector> feedback_vector, void ReportFeedbackUpdate(SloppyTNode<FeedbackVector> feedback_vector,
......
...@@ -107,6 +107,18 @@ struct Int32T : Word32T { ...@@ -107,6 +107,18 @@ struct Int32T : Word32T {
struct Uint32T : Word32T { struct Uint32T : Word32T {
static constexpr MachineType kMachineType = MachineType::Uint32(); static constexpr MachineType kMachineType = MachineType::Uint32();
}; };
struct Int16T : Int32T {
static constexpr MachineType kMachineType = MachineType::Int16();
};
struct Uint16T : Uint32T {
static constexpr MachineType kMachineType = MachineType::Uint16();
};
struct Int8T : Int16T {
static constexpr MachineType kMachineType = MachineType::Int8();
};
struct Uint8T : Uint16T {
static constexpr MachineType kMachineType = MachineType::Uint8();
};
struct Word64T : IntegralT { struct Word64T : IntegralT {
static const MachineRepresentation kMachineRepresentation = static const MachineRepresentation kMachineRepresentation =
......
...@@ -20,8 +20,6 @@ namespace torque { ...@@ -20,8 +20,6 @@ namespace torque {
#define AST_EXPRESSION_NODE_KIND_LIST(V) \ #define AST_EXPRESSION_NODE_KIND_LIST(V) \
V(CallExpression) \ V(CallExpression) \
V(CallMethodExpression) \ V(CallMethodExpression) \
V(LoadObjectFieldExpression) \
V(StoreObjectFieldExpression) \
V(IntrinsicCallExpression) \ V(IntrinsicCallExpression) \
V(StructExpression) \ V(StructExpression) \
V(LogicalOrExpression) \ V(LogicalOrExpression) \
...@@ -33,6 +31,7 @@ namespace torque { ...@@ -33,6 +31,7 @@ namespace torque {
V(NumberLiteralExpression) \ V(NumberLiteralExpression) \
V(FieldAccessExpression) \ V(FieldAccessExpression) \
V(ElementAccessExpression) \ V(ElementAccessExpression) \
V(DereferenceExpression) \
V(AssignmentExpression) \ V(AssignmentExpression) \
V(IncrementDecrementExpression) \ V(IncrementDecrementExpression) \
V(NewExpression) \ V(NewExpression) \
...@@ -43,7 +42,8 @@ namespace torque { ...@@ -43,7 +42,8 @@ namespace torque {
#define AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \ #define AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \
V(BasicTypeExpression) \ V(BasicTypeExpression) \
V(FunctionTypeExpression) \ V(FunctionTypeExpression) \
V(UnionTypeExpression) V(UnionTypeExpression) \
V(ReferenceTypeExpression)
#define AST_STATEMENT_NODE_KIND_LIST(V) \ #define AST_STATEMENT_NODE_KIND_LIST(V) \
V(BlockStatement) \ V(BlockStatement) \
...@@ -222,31 +222,6 @@ struct IdentifierExpression : LocationExpression { ...@@ -222,31 +222,6 @@ struct IdentifierExpression : LocationExpression {
std::vector<TypeExpression*> generic_arguments; std::vector<TypeExpression*> generic_arguments;
}; };
struct LoadObjectFieldExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(LoadObjectFieldExpression)
LoadObjectFieldExpression(SourcePosition pos, Expression* base,
std::string field_name)
: Expression(kKind, pos),
base(std::move(base)),
field_name(std::move(field_name)) {}
Expression* base;
std::string field_name;
};
struct StoreObjectFieldExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(StoreObjectFieldExpression)
StoreObjectFieldExpression(SourcePosition pos, Expression* base,
std::string field_name, Expression* value)
: Expression(kKind, pos),
base(std::move(base)),
field_name(std::move(field_name)),
value(std::move(value)) {}
Expression* base;
std::string field_name;
Expression* value;
size_t offset;
};
struct IntrinsicCallExpression : Expression { struct IntrinsicCallExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(IntrinsicCallExpression) DEFINE_AST_NODE_LEAF_BOILERPLATE(IntrinsicCallExpression)
IntrinsicCallExpression(SourcePosition pos, std::string name, IntrinsicCallExpression(SourcePosition pos, std::string name,
...@@ -376,15 +351,25 @@ struct FieldAccessExpression : LocationExpression { ...@@ -376,15 +351,25 @@ struct FieldAccessExpression : LocationExpression {
Identifier* field; Identifier* field;
}; };
struct DereferenceExpression : LocationExpression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(DereferenceExpression)
DereferenceExpression(SourcePosition pos, Expression* reference)
: LocationExpression(kKind, pos), reference(reference) {}
Expression* reference;
};
struct AssignmentExpression : Expression { struct AssignmentExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(AssignmentExpression) DEFINE_AST_NODE_LEAF_BOILERPLATE(AssignmentExpression)
AssignmentExpression(SourcePosition pos, LocationExpression* location, AssignmentExpression(SourcePosition pos, Expression* location,
Expression* value)
: AssignmentExpression(pos, location, base::nullopt, value) {}
AssignmentExpression(SourcePosition pos, Expression* location,
base::Optional<std::string> op, Expression* value) base::Optional<std::string> op, Expression* value)
: Expression(kKind, pos), : Expression(kKind, pos),
location(location), location(location),
op(std::move(op)), op(std::move(op)),
value(value) {} value(value) {}
LocationExpression* location; Expression* location;
base::Optional<std::string> op; base::Optional<std::string> op;
Expression* value; Expression* value;
}; };
...@@ -393,10 +378,10 @@ enum class IncrementDecrementOperator { kIncrement, kDecrement }; ...@@ -393,10 +378,10 @@ enum class IncrementDecrementOperator { kIncrement, kDecrement };
struct IncrementDecrementExpression : Expression { struct IncrementDecrementExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(IncrementDecrementExpression) DEFINE_AST_NODE_LEAF_BOILERPLATE(IncrementDecrementExpression)
IncrementDecrementExpression(SourcePosition pos, LocationExpression* location, IncrementDecrementExpression(SourcePosition pos, Expression* location,
IncrementDecrementOperator op, bool postfix) IncrementDecrementOperator op, bool postfix)
: Expression(kKind, pos), location(location), op(op), postfix(postfix) {} : Expression(kKind, pos), location(location), op(op), postfix(postfix) {}
LocationExpression* location; Expression* location;
IncrementDecrementOperator op; IncrementDecrementOperator op;
bool postfix; bool postfix;
}; };
...@@ -480,6 +465,13 @@ struct UnionTypeExpression : TypeExpression { ...@@ -480,6 +465,13 @@ struct UnionTypeExpression : TypeExpression {
TypeExpression* b; TypeExpression* b;
}; };
struct ReferenceTypeExpression : TypeExpression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ReferenceTypeExpression)
ReferenceTypeExpression(SourcePosition pos, TypeExpression* referenced_type)
: TypeExpression(kKind, pos), referenced_type(referenced_type) {}
TypeExpression* referenced_type;
};
struct ExpressionStatement : Statement { struct ExpressionStatement : Statement {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExpressionStatement) DEFINE_AST_NODE_LEAF_BOILERPLATE(ExpressionStatement)
ExpressionStatement(SourcePosition pos, Expression* expression) ExpressionStatement(SourcePosition pos, Expression* expression)
......
...@@ -307,7 +307,9 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, ...@@ -307,7 +307,9 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
std::string catch_name = std::string catch_name =
PreCallableExceptionPreparation(instruction.catch_block); PreCallableExceptionPreparation(instruction.catch_block);
out_ << " "; out_ << " ";
if (return_type->IsStructType()) { bool needs_flattening =
return_type->IsStructType() || return_type->IsReferenceType();
if (needs_flattening) {
out_ << "std::tie("; out_ << "std::tie(";
PrintCommaSeparatedList(out_, results); PrintCommaSeparatedList(out_, results);
out_ << ") = "; out_ << ") = ";
...@@ -315,12 +317,14 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, ...@@ -315,12 +317,14 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
if (results.size() == 1) { if (results.size() == 1) {
out_ << results[0] << " = ca_.UncheckedCast<" out_ << results[0] << " = ca_.UncheckedCast<"
<< return_type->GetGeneratedTNodeTypeName() << ">("; << return_type->GetGeneratedTNodeTypeName() << ">(";
} else {
DCHECK_EQ(0, results.size());
} }
} }
out_ << instruction.macro->external_assembler_name() << "(state_)." out_ << instruction.macro->external_assembler_name() << "(state_)."
<< instruction.macro->ExternalName() << "("; << instruction.macro->ExternalName() << "(";
PrintCommaSeparatedList(out_, args); PrintCommaSeparatedList(out_, args);
if (return_type->IsStructType()) { if (needs_flattening) {
out_ << ").Flatten();\n"; out_ << ").Flatten();\n";
} else { } else {
if (results.size() == 1) out_ << ")"; if (results.size() == 1) out_ << ")";
...@@ -695,69 +699,49 @@ void CSAGenerator::EmitInstruction(const UnsafeCastInstruction& instruction, ...@@ -695,69 +699,49 @@ void CSAGenerator::EmitInstruction(const UnsafeCastInstruction& instruction,
} }
void CSAGenerator::EmitInstruction( void CSAGenerator::EmitInstruction(
const LoadObjectFieldInstruction& instruction, Stack<std::string>* stack) { const CreateFieldReferenceInstruction& instruction,
Stack<std::string>* stack) {
const Field& field = const Field& field =
instruction.class_type->LookupField(instruction.field_name); instruction.class_type->LookupField(instruction.field_name);
std::string result_name = FreshNodeName(); std::string offset_name = FreshNodeName();
stack->Push(offset_name);
size_t field_size;
std::string size_string;
std::string machine_type;
std::tie(field_size, size_string, machine_type) =
field.GetFieldSizeInformation();
out_ << " compiler::TNode<IntPtrT> " << offset_name
<< " = ca_.IntPtrConstant(";
if (instruction.class_type->IsExtern()) { if (instruction.class_type->IsExtern()) {
out_ << field.name_and_type.type->GetGeneratedTypeName() << " " out_ << field.aggregate->GetGeneratedTNodeTypeName() << "::k"
<< result_name << " = ca_.UncheckedCast<" << CamelifyString(field.name_and_type.name) << "Offset";
<< field.name_and_type.type->GetGeneratedTNodeTypeName()
<< ">(CodeStubAssembler(state_).LoadObjectField(" << stack->Top()
<< ", " << field.aggregate->GetGeneratedTNodeTypeName() << "::k"
<< CamelifyString(field.name_and_type.name) << "Offset, "
<< machine_type + "));\n";
} else { } else {
out_ << field.name_and_type.type->GetGeneratedTypeName() << " " out_ << "FixedArray::kHeaderSize + " << field.offset;
<< result_name << " = ca_.UncheckedCast<"
<< field.name_and_type.type->GetGeneratedTNodeTypeName()
<< ">(CodeStubAssembler(state_).UnsafeLoadFixedArrayElement("
<< stack->Top() << ", " << (field.offset / kTaggedSize) << "));\n";
} }
stack->Poke(stack->AboveTop() - 1, result_name); out_ << ");\n"
<< " USE(" << stack->Top() << ");\n";
} }
void CSAGenerator::EmitInstruction( void CSAGenerator::EmitInstruction(const LoadReferenceInstruction& instruction,
const StoreObjectFieldInstruction& instruction, Stack<std::string>* stack) { Stack<std::string>* stack) {
auto value = stack->Pop(); std::string result_name = FreshNodeName();
auto object = stack->Pop();
stack->Push(value); std::string offset = stack->Pop();
const Field& field = std::string object = stack->Pop();
instruction.class_type->LookupField(instruction.field_name); stack->Push(result_name);
if (instruction.class_type->IsExtern()) {
if (field.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType())) { out_ << " " << instruction.type->GetGeneratedTypeName() << result_name
if (field.offset == 0) { << " = CodeStubAssembler(state_).LoadReference<"
out_ << " CodeStubAssembler(state_).StoreMap(" << object << ", " << instruction.type->GetGeneratedTNodeTypeName()
<< value << ");\n"; << ">(CodeStubAssembler::Reference{" << object << ", " << offset
} else { << "});\n";
out_ << " CodeStubAssembler(state_).StoreObjectField(" << object }
<< ", " << field.offset << ", " << value << ");\n";
} void CSAGenerator::EmitInstruction(const StoreReferenceInstruction& instruction,
} else { Stack<std::string>* stack) {
size_t field_size; std::string value = stack->Pop();
std::string size_string; std::string offset = stack->Pop();
std::string machine_type; std::string object = stack->Pop();
std::tie(field_size, size_string, machine_type) =
field.GetFieldSizeInformation(); out_ << " CodeStubAssembler(state_).StoreReference(CodeStubAssembler::"
if (field.offset == 0) { "Reference{"
ReportError("the first field in a class object must be a map"); << object << ", " << offset << "}, " << value << ");\n";
}
out_ << " CodeStubAssembler(state_).StoreObjectFieldNoWriteBarrier("
<< object << ", " << field.offset << ", " << value << ", "
<< machine_type << ".representation());\n";
}
} else {
out_ << " CodeStubAssembler(state_).UnsafeStoreFixedArrayElement("
<< object << ", " << (field.offset / kTaggedSize) << ", " << value
<< ");\n";
}
} }
// static // static
...@@ -778,6 +762,11 @@ void CSAGenerator::EmitCSAValue(VisitResult result, ...@@ -778,6 +762,11 @@ void CSAGenerator::EmitCSAValue(VisitResult result,
out); out);
} }
out << "}"; out << "}";
} else if (result.type()->IsReferenceType()) {
DCHECK_EQ(2, result.stack_range().Size());
size_t offset = result.stack_range().begin().offset;
out << "CodeStubAssembler::Reference{" << values.Peek(BottomOffset{offset})
<< ", " << values.Peek(BottomOffset{offset + 1}) << "}";
} else { } else {
DCHECK_EQ(1, result.stack_range().Size()); DCHECK_EQ(1, result.stack_range().Size());
out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName() out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName()
......
...@@ -64,23 +64,37 @@ std::ostream& operator<<(std::ostream& os, const Generic& g) { ...@@ -64,23 +64,37 @@ std::ostream& operator<<(std::ostream& os, const Generic& g) {
return os; return os;
} }
base::Optional<const Type*> Generic::InferTypeArgument( namespace {
size_t i, const TypeVector& arguments) { base::Optional<const Type*> InferTypeArgument(const std::string& to_infer,
const std::string type_name = declaration()->generic_parameters[i]->value; TypeExpression* parameter,
const std::vector<TypeExpression*>& parameters = const Type* argument) {
declaration()->callable->signature->parameters.types; BasicTypeExpression* basic = BasicTypeExpression::DynamicCast(parameter);
size_t j = declaration()->callable->signature->parameters.implicit_count; if (basic && basic->namespace_qualification.empty() && !basic->is_constexpr &&
for (size_t i = 0; i < arguments.size() && j < parameters.size(); ++i, ++j) { basic->name == to_infer) {
BasicTypeExpression* basic = return argument;
BasicTypeExpression::DynamicCast(parameters[j]);
if (basic && basic->namespace_qualification.empty() &&
!basic->is_constexpr && basic->name == type_name) {
return arguments[i];
} }
auto* ref = ReferenceTypeExpression::DynamicCast(parameter);
if (ref && argument->IsReferenceType()) {
return InferTypeArgument(to_infer, ref->referenced_type,
ReferenceType::cast(argument)->referenced_type());
} }
return base::nullopt; return base::nullopt;
} }
base::Optional<const Type*> InferTypeArgument(
const std::string& to_infer, const std::vector<TypeExpression*>& parameters,
const TypeVector& arguments) {
for (size_t i = 0; i < arguments.size() && i < parameters.size(); ++i) {
if (base::Optional<const Type*> inferred =
InferTypeArgument(to_infer, parameters[i], arguments[i])) {
return *inferred;
}
}
return base::nullopt;
}
} // namespace
base::Optional<TypeVector> Generic::InferSpecializationTypes( base::Optional<TypeVector> Generic::InferSpecializationTypes(
const TypeVector& explicit_specialization_types, const TypeVector& explicit_specialization_types,
const TypeVector& arguments) { const TypeVector& arguments) {
...@@ -91,7 +105,15 @@ base::Optional<TypeVector> Generic::InferSpecializationTypes( ...@@ -91,7 +105,15 @@ base::Optional<TypeVector> Generic::InferSpecializationTypes(
} }
for (size_t i = explicit_specialization_types.size(); for (size_t i = explicit_specialization_types.size();
i < type_parameter_count; ++i) { i < type_parameter_count; ++i) {
base::Optional<const Type*> inferred = InferTypeArgument(i, arguments); const std::string type_name = declaration()->generic_parameters[i]->value;
size_t implicit_count =
declaration()->callable->signature->parameters.implicit_count;
const std::vector<TypeExpression*>& parameters =
declaration()->callable->signature->parameters.types;
std::vector<TypeExpression*> explicit_parameters(
parameters.begin() + implicit_count, parameters.end());
base::Optional<const Type*> inferred =
InferTypeArgument(type_name, explicit_parameters, arguments);
if (!inferred) return base::nullopt; if (!inferred) return base::nullopt;
result.push_back(*inferred); result.push_back(*inferred);
} }
......
...@@ -421,8 +421,6 @@ class Generic : public Declarable { ...@@ -421,8 +421,6 @@ class Generic : public Declarable {
: Declarable(Declarable::kGeneric), : Declarable(Declarable::kGeneric),
name_(name), name_(name),
declaration_(declaration) {} declaration_(declaration) {}
base::Optional<const Type*> InferTypeArgument(size_t i,
const TypeVector& arguments);
std::string name_; std::string name_;
std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>> std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>>
......
...@@ -561,24 +561,22 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods( ...@@ -561,24 +561,22 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
std::string camel_field_name = CamelifyString(field.name_and_type.name); std::string camel_field_name = CamelifyString(field.name_and_type.name);
std::string load_macro_name = std::string load_macro_name =
"Load" + class_type->name() + camel_field_name; "Load" + class_type->name() + camel_field_name;
std::string load_operator_name = "." + field.name_and_type.name;
Signature load_signature; Signature load_signature;
load_signature.parameter_names.push_back(MakeNode<Identifier>("o")); load_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
load_signature.parameter_types.types.push_back(class_type); load_signature.parameter_types.types.push_back(class_type);
load_signature.parameter_types.var_args = false; load_signature.parameter_types.var_args = false;
load_signature.return_type = field.name_and_type.type; load_signature.return_type = field.name_and_type.type;
Statement* load_body = Statement* load_body =
MakeNode<ReturnStatement>(MakeNode<LoadObjectFieldExpression>( MakeNode<ReturnStatement>(MakeNode<FieldAccessExpression>(
parameter, field.name_and_type.name)); parameter, MakeNode<Identifier>(field.name_and_type.name)));
Declarations::DeclareMacro(load_macro_name, base::nullopt, load_signature, Declarations::DeclareMacro(load_macro_name, base::nullopt, load_signature,
false, load_body, load_operator_name); false, load_body);
// Store accessor // Store accessor
IdentifierExpression* value = MakeNode<IdentifierExpression>( IdentifierExpression* value = MakeNode<IdentifierExpression>(
std::vector<std::string>{}, MakeNode<Identifier>(std::string{"v"})); std::vector<std::string>{}, MakeNode<Identifier>(std::string{"v"}));
std::string store_macro_name = std::string store_macro_name =
"Store" + class_type->name() + camel_field_name; "Store" + class_type->name() + camel_field_name;
std::string store_operator_name = "." + field.name_and_type.name + "=";
Signature store_signature; Signature store_signature;
store_signature.parameter_names.push_back(MakeNode<Identifier>("o")); store_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
store_signature.parameter_names.push_back(MakeNode<Identifier>("v")); store_signature.parameter_names.push_back(MakeNode<Identifier>("v"));
...@@ -588,10 +586,12 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods( ...@@ -588,10 +586,12 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
// TODO(danno): Store macros probably should return their value argument // TODO(danno): Store macros probably should return their value argument
store_signature.return_type = TypeOracle::GetVoidType(); store_signature.return_type = TypeOracle::GetVoidType();
Statement* store_body = Statement* store_body =
MakeNode<ExpressionStatement>(MakeNode<StoreObjectFieldExpression>( MakeNode<ExpressionStatement>(MakeNode<AssignmentExpression>(
parameter, field.name_and_type.name, value)); MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name)),
value));
Declarations::DeclareMacro(store_macro_name, base::nullopt, store_signature, Declarations::DeclareMacro(store_macro_name, base::nullopt, store_signature,
false, store_body, store_operator_name); false, store_body);
} }
DeclareMethods(class_type, class_declaration->methods); DeclareMethods(class_type, class_declaration->methods);
......
...@@ -91,9 +91,14 @@ const Type* Declarations::GetType(TypeExpression* type_expression) { ...@@ -91,9 +91,14 @@ const Type* Declarations::GetType(TypeExpression* type_expression) {
alias->GetDeclarationPosition()); alias->GetDeclarationPosition());
} }
return alias->type(); return alias->type();
} else if (auto* union_type = UnionTypeExpression::cast(type_expression)) { } else if (auto* union_type =
UnionTypeExpression::DynamicCast(type_expression)) {
return TypeOracle::GetUnionType(GetType(union_type->a), return TypeOracle::GetUnionType(GetType(union_type->a),
GetType(union_type->b)); GetType(union_type->b));
} else if (auto* reference_type =
ReferenceTypeExpression::DynamicCast(type_expression)) {
return TypeOracle::GetReferenceType(
GetType(reference_type->referenced_type));
} else { } else {
auto* function_type_exp = FunctionTypeExpression::cast(type_expression); auto* function_type_exp = FunctionTypeExpression::cast(type_expression);
TypeVector argument_types; TypeVector argument_types;
......
...@@ -46,7 +46,6 @@ enum class ParseResultHolderBase::TypeId { ...@@ -46,7 +46,6 @@ enum class ParseResultHolderBase::TypeId {
kExpressionPtr, kExpressionPtr,
kIdentifierPtr, kIdentifierPtr,
kOptionalIdentifierPtr, kOptionalIdentifierPtr,
kLocationExpressionPtr,
kStatementPtr, kStatementPtr,
kDeclarationPtr, kDeclarationPtr,
kTypeExpressionPtr, kTypeExpressionPtr,
......
This diff is collapsed.
...@@ -41,6 +41,14 @@ class LocationReference { ...@@ -41,6 +41,14 @@ class LocationReference {
result.temporary_description_ = std::move(description); result.temporary_description_ = std::move(description);
return result; return result;
} }
// A heap reference, that is, a tagged value and an offset to encode an inner
// pointer.
static LocationReference HeapReference(VisitResult heap_reference) {
LocationReference result;
DCHECK(heap_reference.type()->IsReferenceType());
result.heap_reference_ = std::move(heap_reference);
return result;
}
static LocationReference ArrayAccess(VisitResult base, VisitResult offset) { static LocationReference ArrayAccess(VisitResult base, VisitResult offset) {
LocationReference result; LocationReference result;
result.eval_function_ = std::string{"[]"}; result.eval_function_ = std::string{"[]"};
...@@ -89,6 +97,18 @@ class LocationReference { ...@@ -89,6 +97,18 @@ class LocationReference {
DCHECK(IsTemporary()); DCHECK(IsTemporary());
return *temporary_; return *temporary_;
} }
bool IsHeapReference() const { return heap_reference_.has_value(); }
const VisitResult& heap_reference() const {
DCHECK(IsHeapReference());
return *heap_reference_;
}
const Type* ReferencedType() const {
if (IsHeapReference()) {
return ReferenceType::cast(heap_reference().type())->referenced_type();
}
return GetVisitResult().type();
}
const VisitResult& GetVisitResult() const { const VisitResult& GetVisitResult() const {
if (IsVariableAccess()) return variable(); if (IsVariableAccess()) return variable();
...@@ -131,6 +151,7 @@ class LocationReference { ...@@ -131,6 +151,7 @@ class LocationReference {
base::Optional<VisitResult> variable_; base::Optional<VisitResult> variable_;
base::Optional<VisitResult> temporary_; base::Optional<VisitResult> temporary_;
base::Optional<std::string> temporary_description_; base::Optional<std::string> temporary_description_;
base::Optional<VisitResult> heap_reference_;
base::Optional<std::string> eval_function_; base::Optional<std::string> eval_function_;
base::Optional<std::string> assign_function_; base::Optional<std::string> assign_function_;
VisitResultVector call_arguments_; VisitResultVector call_arguments_;
...@@ -287,6 +308,7 @@ class ImplementationVisitor : public FileVisitor { ...@@ -287,6 +308,7 @@ class ImplementationVisitor : public FileVisitor {
LocationReference GetLocationReference(Expression* location); LocationReference GetLocationReference(Expression* location);
LocationReference GetLocationReference(IdentifierExpression* expr); LocationReference GetLocationReference(IdentifierExpression* expr);
LocationReference GetLocationReference(DereferenceExpression* expr);
LocationReference GetLocationReference(FieldAccessExpression* expr); LocationReference GetLocationReference(FieldAccessExpression* expr);
LocationReference GetLocationReference(ElementAccessExpression* expr); LocationReference GetLocationReference(ElementAccessExpression* expr);
...@@ -294,15 +316,7 @@ class ImplementationVisitor : public FileVisitor { ...@@ -294,15 +316,7 @@ class ImplementationVisitor : public FileVisitor {
VisitResult GetBuiltinCode(Builtin* builtin); VisitResult GetBuiltinCode(Builtin* builtin);
VisitResult Visit(IdentifierExpression* expr); VisitResult Visit(LocationExpression* expr);
VisitResult Visit(FieldAccessExpression* expr) {
StackScope scope(this);
return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr)));
}
VisitResult Visit(ElementAccessExpression* expr) {
StackScope scope(this);
return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr)));
}
void VisitAllDeclarables(); void VisitAllDeclarables();
void Visit(Declarable* delarable); void Visit(Declarable* delarable);
...@@ -320,8 +334,6 @@ class ImplementationVisitor : public FileVisitor { ...@@ -320,8 +334,6 @@ class ImplementationVisitor : public FileVisitor {
VisitResult Visit(CallExpression* expr, bool is_tail = false); VisitResult Visit(CallExpression* expr, bool is_tail = false);
VisitResult Visit(CallMethodExpression* expr); VisitResult Visit(CallMethodExpression* expr);
VisitResult Visit(IntrinsicCallExpression* intrinsic); VisitResult Visit(IntrinsicCallExpression* intrinsic);
VisitResult Visit(LoadObjectFieldExpression* expr);
VisitResult Visit(StoreObjectFieldExpression* expr);
const Type* Visit(TailCallStatement* stmt); const Type* Visit(TailCallStatement* stmt);
VisitResult Visit(ConditionalExpression* expr); VisitResult Visit(ConditionalExpression* expr);
...@@ -465,7 +477,10 @@ class ImplementationVisitor : public FileVisitor { ...@@ -465,7 +477,10 @@ class ImplementationVisitor : public FileVisitor {
const Container& declaration_container, const Container& declaration_container,
const TypeVector& types, const TypeVector& types,
const std::vector<Binding<LocalLabel>*>& labels, const std::vector<Binding<LocalLabel>*>& labels,
const TypeVector& specialization_types); const TypeVector& specialization_types,
bool silence_errors = false);
bool TestLookupCallable(const QualifiedName& name,
const TypeVector& parameter_types);
template <class Container> template <class Container>
Callable* LookupCallable(const QualifiedName& name, Callable* LookupCallable(const QualifiedName& name,
......
...@@ -21,6 +21,19 @@ namespace torque { ...@@ -21,6 +21,19 @@ namespace torque {
TORQUE_INSTRUCTION_LIST(TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS) TORQUE_INSTRUCTION_LIST(TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS)
#undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS #undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS
namespace {
void ExpectType(const Type* expected, const Type* actual) {
if (expected != actual) {
ReportError("expected type ", *expected, " but found ", *actual);
}
}
void ExpectSubtype(const Type* subtype, const Type* supertype) {
if (!subtype->IsSubtypeOf(supertype)) {
ReportError("type ", *subtype, " is not a subtype of ", *supertype);
}
}
} // namespace
void PeekInstruction::TypeInstruction(Stack<const Type*>* stack, void PeekInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const { ControlFlowGraph* cfg) const {
const Type* type = stack->Peek(slot); const Type* type = stack->Peek(slot);
...@@ -29,9 +42,7 @@ void PeekInstruction::TypeInstruction(Stack<const Type*>* stack, ...@@ -29,9 +42,7 @@ void PeekInstruction::TypeInstruction(Stack<const Type*>* stack,
const TopType* top_type = TopType::cast(type); const TopType* top_type = TopType::cast(type);
ReportError("use of " + top_type->reason()); ReportError("use of " + top_type->reason());
} }
if (!type->IsSubtypeOf(*widened_type)) { ExpectSubtype(type, *widened_type);
ReportError("type ", *type, " is not a subtype of ", **widened_type);
}
type = *widened_type; type = *widened_type;
} }
stack->Push(type); stack->Push(type);
...@@ -41,9 +52,7 @@ void PokeInstruction::TypeInstruction(Stack<const Type*>* stack, ...@@ -41,9 +52,7 @@ void PokeInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const { ControlFlowGraph* cfg) const {
const Type* type = stack->Top(); const Type* type = stack->Top();
if (widened_type) { if (widened_type) {
if (!type->IsSubtypeOf(*widened_type)) { ExpectSubtype(type, *widened_type);
ReportError("type ", type, " is not a subtype of ", *widened_type);
}
type = *widened_type; type = *widened_type;
} }
stack->Poke(slot, type); stack->Poke(slot, type);
...@@ -281,39 +290,26 @@ void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack, ...@@ -281,39 +290,26 @@ void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack,
stack->Poke(stack->AboveTop() - 1, destination_type); stack->Poke(stack->AboveTop() - 1, destination_type);
} }
void LoadObjectFieldInstruction::TypeInstruction(Stack<const Type*>* stack, void CreateFieldReferenceInstruction::TypeInstruction(
Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
ExpectSubtype(stack->Pop(), class_type);
stack->Push(TypeOracle::GetHeapObjectType());
stack->Push(TypeOracle::GetIntPtrType());
}
void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const { ControlFlowGraph* cfg) const {
const ClassType* stack_class_type = ClassType::DynamicCast(stack->Top()); ExpectType(TypeOracle::GetIntPtrType(), stack->Pop());
if (!stack_class_type) { ExpectType(TypeOracle::GetHeapObjectType(), stack->Pop());
ReportError( DCHECK_EQ(std::vector<const Type*>{type}, LowerType(type));
"first argument to a LoadObjectFieldInstruction instruction isn't a " stack->Push(type);
"class");
}
if (stack_class_type != class_type) {
ReportError(
"first argument to a LoadObjectFieldInstruction doesn't match "
"instruction's type");
}
const Field& field = class_type->LookupField(field_name);
stack->Poke(stack->AboveTop() - 1, field.name_and_type.type);
} }
void StoreObjectFieldInstruction::TypeInstruction(Stack<const Type*>* stack, void StoreReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const { ControlFlowGraph* cfg) const {
auto value = stack->Pop(); ExpectSubtype(stack->Pop(), type);
const ClassType* stack_class_type = ClassType::DynamicCast(stack->Top()); ExpectType(TypeOracle::GetIntPtrType(), stack->Pop());
if (!stack_class_type) { ExpectType(TypeOracle::GetHeapObjectType(), stack->Pop());
ReportError(
"first argument to a StoreObjectFieldInstruction instruction isn't a "
"class");
}
if (stack_class_type != class_type) {
ReportError(
"first argument to a StoreObjectFieldInstruction doesn't match "
"instruction's type");
}
stack->Pop();
stack->Push(value);
} }
bool CallRuntimeInstruction::IsBlockTerminator() const { bool CallRuntimeInstruction::IsBlockTerminator() const {
......
...@@ -30,8 +30,9 @@ class RuntimeFunction; ...@@ -30,8 +30,9 @@ class RuntimeFunction;
V(DeleteRangeInstruction) \ V(DeleteRangeInstruction) \
V(PushUninitializedInstruction) \ V(PushUninitializedInstruction) \
V(PushBuiltinPointerInstruction) \ V(PushBuiltinPointerInstruction) \
V(LoadObjectFieldInstruction) \ V(CreateFieldReferenceInstruction) \
V(StoreObjectFieldInstruction) \ V(LoadReferenceInstruction) \
V(StoreReferenceInstruction) \
V(CallCsaMacroInstruction) \ V(CallCsaMacroInstruction) \
V(CallIntrinsicInstruction) \ V(CallIntrinsicInstruction) \
V(NamespaceConstantInstruction) \ V(NamespaceConstantInstruction) \
...@@ -203,22 +204,25 @@ struct NamespaceConstantInstruction : InstructionBase { ...@@ -203,22 +204,25 @@ struct NamespaceConstantInstruction : InstructionBase {
NamespaceConstant* constant; NamespaceConstant* constant;
}; };
struct LoadObjectFieldInstruction : InstructionBase { struct CreateFieldReferenceInstruction : InstructionBase {
TORQUE_INSTRUCTION_BOILERPLATE() TORQUE_INSTRUCTION_BOILERPLATE()
LoadObjectFieldInstruction(const ClassType* class_type, CreateFieldReferenceInstruction(const ClassType* class_type,
std::string field_name) std::string field_name)
: class_type(class_type), field_name(std::move(field_name)) {} : class_type(class_type), field_name(std::move(field_name)) {}
const ClassType* class_type; const ClassType* class_type;
std::string field_name; std::string field_name;
}; };
struct StoreObjectFieldInstruction : InstructionBase { struct LoadReferenceInstruction : InstructionBase {
TORQUE_INSTRUCTION_BOILERPLATE() TORQUE_INSTRUCTION_BOILERPLATE()
StoreObjectFieldInstruction(const ClassType* class_type, explicit LoadReferenceInstruction(const Type* type) : type(type) {}
std::string field_name) const Type* type;
: class_type(class_type), field_name(std::move(field_name)) {} };
const ClassType* class_type;
std::string field_name; struct StoreReferenceInstruction : InstructionBase {
TORQUE_INSTRUCTION_BOILERPLATE()
explicit StoreReferenceInstruction(const Type* type) : type(type) {}
const Type* type;
}; };
struct CallIntrinsicInstruction : InstructionBase { struct CallIntrinsicInstruction : InstructionBase {
......
...@@ -68,10 +68,6 @@ V8_EXPORT_PRIVATE const ParseResultTypeId ...@@ -68,10 +68,6 @@ V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<base::Optional<Identifier*>>::id = ParseResultHolder<base::Optional<Identifier*>>::id =
ParseResultTypeId::kOptionalIdentifierPtr; ParseResultTypeId::kOptionalIdentifierPtr;
template <> template <>
V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<LocationExpression*>::id =
ParseResultTypeId::kLocationExpressionPtr;
template <>
V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<Statement*>::id = V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<Statement*>::id =
ParseResultTypeId::kStatementPtr; ParseResultTypeId::kStatementPtr;
template <> template <>
...@@ -261,7 +257,7 @@ Expression* MakeCall(const std::string& callee, ...@@ -261,7 +257,7 @@ Expression* MakeCall(const std::string& callee,
} }
base::Optional<ParseResult> MakeCall(ParseResultIterator* child_results) { base::Optional<ParseResult> MakeCall(ParseResultIterator* child_results) {
auto callee = child_results->NextAs<LocationExpression*>(); auto callee = child_results->NextAs<Expression*>();
auto args = child_results->NextAs<std::vector<Expression*>>(); auto args = child_results->NextAs<std::vector<Expression*>>();
auto otherwise = child_results->NextAs<std::vector<Statement*>>(); auto otherwise = child_results->NextAs<std::vector<Statement*>>();
IdentifierExpression* target = IdentifierExpression::cast(callee); IdentifierExpression* target = IdentifierExpression::cast(callee);
...@@ -694,6 +690,13 @@ base::Optional<ParseResult> MakeFunctionTypeExpression( ...@@ -694,6 +690,13 @@ base::Optional<ParseResult> MakeFunctionTypeExpression(
return ParseResult{result}; return ParseResult{result};
} }
base::Optional<ParseResult> MakeReferenceTypeExpression(
ParseResultIterator* child_results) {
auto referenced_type = child_results->NextAs<TypeExpression*>();
TypeExpression* result = MakeNode<ReferenceTypeExpression>(referenced_type);
return ParseResult{result};
}
base::Optional<ParseResult> MakeUnionTypeExpression( base::Optional<ParseResult> MakeUnionTypeExpression(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto a = child_results->NextAs<TypeExpression*>(); auto a = child_results->NextAs<TypeExpression*>();
...@@ -1001,7 +1004,7 @@ base::Optional<ParseResult> MakeIdentifierExpression( ...@@ -1001,7 +1004,7 @@ base::Optional<ParseResult> MakeIdentifierExpression(
auto name = child_results->NextAs<Identifier*>(); auto name = child_results->NextAs<Identifier*>();
auto generic_arguments = auto generic_arguments =
child_results->NextAs<std::vector<TypeExpression*>>(); child_results->NextAs<std::vector<TypeExpression*>>();
LocationExpression* result = MakeNode<IdentifierExpression>( Expression* result = MakeNode<IdentifierExpression>(
std::move(namespace_qualification), name, std::move(generic_arguments)); std::move(namespace_qualification), name, std::move(generic_arguments));
return ParseResult{result}; return ParseResult{result};
} }
...@@ -1010,7 +1013,7 @@ base::Optional<ParseResult> MakeFieldAccessExpression( ...@@ -1010,7 +1013,7 @@ base::Optional<ParseResult> MakeFieldAccessExpression(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto object = child_results->NextAs<Expression*>(); auto object = child_results->NextAs<Expression*>();
auto field = child_results->NextAs<Identifier*>(); auto field = child_results->NextAs<Identifier*>();
LocationExpression* result = MakeNode<FieldAccessExpression>(object, field); Expression* result = MakeNode<FieldAccessExpression>(object, field);
return ParseResult{result}; return ParseResult{result};
} }
...@@ -1018,7 +1021,14 @@ base::Optional<ParseResult> MakeElementAccessExpression( ...@@ -1018,7 +1021,14 @@ base::Optional<ParseResult> MakeElementAccessExpression(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto object = child_results->NextAs<Expression*>(); auto object = child_results->NextAs<Expression*>();
auto field = child_results->NextAs<Expression*>(); auto field = child_results->NextAs<Expression*>();
LocationExpression* result = MakeNode<ElementAccessExpression>(object, field); Expression* result = MakeNode<ElementAccessExpression>(object, field);
return ParseResult{result};
}
base::Optional<ParseResult> MakeDereferenceExpression(
ParseResultIterator* child_results) {
auto reference = child_results->NextAs<Expression*>();
Expression* result = MakeNode<DereferenceExpression>(reference);
return ParseResult{result}; return ParseResult{result};
} }
...@@ -1033,7 +1043,7 @@ base::Optional<ParseResult> MakeStructExpression( ...@@ -1033,7 +1043,7 @@ base::Optional<ParseResult> MakeStructExpression(
base::Optional<ParseResult> MakeAssignmentExpression( base::Optional<ParseResult> MakeAssignmentExpression(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto location = child_results->NextAs<LocationExpression*>(); auto location = child_results->NextAs<Expression*>();
auto op = child_results->NextAs<base::Optional<std::string>>(); auto op = child_results->NextAs<base::Optional<std::string>>();
auto value = child_results->NextAs<Expression*>(); auto value = child_results->NextAs<Expression*>();
Expression* result = Expression* result =
...@@ -1057,7 +1067,7 @@ base::Optional<ParseResult> MakeStringLiteralExpression( ...@@ -1057,7 +1067,7 @@ base::Optional<ParseResult> MakeStringLiteralExpression(
base::Optional<ParseResult> MakeIncrementDecrementExpressionPostfix( base::Optional<ParseResult> MakeIncrementDecrementExpressionPostfix(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto location = child_results->NextAs<LocationExpression*>(); auto location = child_results->NextAs<Expression*>();
auto op = child_results->NextAs<IncrementDecrementOperator>(); auto op = child_results->NextAs<IncrementDecrementOperator>();
Expression* result = Expression* result =
MakeNode<IncrementDecrementExpression>(location, op, true); MakeNode<IncrementDecrementExpression>(location, op, true);
...@@ -1067,7 +1077,7 @@ base::Optional<ParseResult> MakeIncrementDecrementExpressionPostfix( ...@@ -1067,7 +1077,7 @@ base::Optional<ParseResult> MakeIncrementDecrementExpressionPostfix(
base::Optional<ParseResult> MakeIncrementDecrementExpressionPrefix( base::Optional<ParseResult> MakeIncrementDecrementExpressionPrefix(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto op = child_results->NextAs<IncrementDecrementOperator>(); auto op = child_results->NextAs<IncrementDecrementOperator>();
auto location = child_results->NextAs<LocationExpression*>(); auto location = child_results->NextAs<Expression*>();
Expression* result = Expression* result =
MakeNode<IncrementDecrementExpression>(location, op, false); MakeNode<IncrementDecrementExpression>(location, op, false);
return ParseResult{result}; return ParseResult{result};
...@@ -1284,7 +1294,8 @@ struct TorqueGrammar : Grammar { ...@@ -1284,7 +1294,8 @@ struct TorqueGrammar : Grammar {
MakeBasicTypeExpression), MakeBasicTypeExpression),
Rule({Token("builtin"), Token("("), typeList, Token(")"), Token("=>"), Rule({Token("builtin"), Token("("), typeList, Token(")"), Token("=>"),
&simpleType}, &simpleType},
MakeFunctionTypeExpression)}; MakeFunctionTypeExpression),
Rule({Token("&"), &simpleType}, MakeReferenceTypeExpression)};
// Result: TypeExpression* // Result: TypeExpression*
Symbol type = {Rule({&simpleType}), Rule({&type, Token("|"), &simpleType}, Symbol type = {Rule({&simpleType}), Rule({&type, Token("|"), &simpleType},
...@@ -1397,20 +1408,13 @@ struct TorqueGrammar : Grammar { ...@@ -1397,20 +1408,13 @@ struct TorqueGrammar : Grammar {
YieldIntegralConstant<IncrementDecrementOperator, YieldIntegralConstant<IncrementDecrementOperator,
IncrementDecrementOperator::kDecrement>)}; IncrementDecrementOperator::kDecrement>)};
// Result: LocationExpression* // Result: Expression*
Symbol identifierExpression = { Symbol identifierExpression = {
Rule({List<std::string>(Sequence({&identifier, Token("::")})), &name, Rule({List<std::string>(Sequence({&identifier, Token("::")})), &name,
TryOrDefault<TypeList>(&genericSpecializationTypeList)}, TryOrDefault<TypeList>(&genericSpecializationTypeList)},
MakeIdentifierExpression), MakeIdentifierExpression),
}; };
// Result: LocationExpression*
Symbol locationExpression = {
Rule({&identifierExpression}),
Rule({&primaryExpression, Token("."), &name}, MakeFieldAccessExpression),
Rule({&primaryExpression, Token("["), expression, Token("]")},
MakeElementAccessExpression)};
// Result: std::vector<Expression*> // Result: std::vector<Expression*>
Symbol argumentList = {Rule( Symbol argumentList = {Rule(
{Token("("), List<Expression*>(expression, Token(",")), Token(")")})}; {Token("("), List<Expression*>(expression, Token(",")), Token(")")})};
...@@ -1446,8 +1450,10 @@ struct TorqueGrammar : Grammar { ...@@ -1446,8 +1450,10 @@ struct TorqueGrammar : Grammar {
Rule({&callExpression}), Rule({&callExpression}),
Rule({&callMethodExpression}), Rule({&callMethodExpression}),
Rule({&intrinsicCallExpression}), Rule({&intrinsicCallExpression}),
Rule({&locationExpression}, Rule({&identifierExpression}),
CastParseResult<LocationExpression*, Expression*>), Rule({&primaryExpression, Token("."), &name}, MakeFieldAccessExpression),
Rule({&primaryExpression, Token("["), expression, Token("]")},
MakeElementAccessExpression),
Rule({&decimalLiteral}, MakeNumberLiteralExpression), Rule({&decimalLiteral}, MakeNumberLiteralExpression),
Rule({&stringLiteral}, MakeStringLiteralExpression), Rule({&stringLiteral}, MakeStringLiteralExpression),
Rule({&simpleType, &initializerList}, MakeStructExpression), Rule({&simpleType, &initializerList}, MakeStructExpression),
...@@ -1457,11 +1463,13 @@ struct TorqueGrammar : Grammar { ...@@ -1457,11 +1463,13 @@ struct TorqueGrammar : Grammar {
// Result: Expression* // Result: Expression*
Symbol unaryExpression = { Symbol unaryExpression = {
Rule({&primaryExpression}), Rule({&primaryExpression}),
Rule({OneOf({"+", "-", "!", "~"}), &unaryExpression}, MakeUnaryOperator), Rule({OneOf({"+", "-", "!", "~", "&"}), &unaryExpression},
MakeUnaryOperator),
Rule({Token("*"), &unaryExpression}, MakeDereferenceExpression),
Rule({Token("..."), &unaryExpression}, MakeSpreadExpression), Rule({Token("..."), &unaryExpression}, MakeSpreadExpression),
Rule({&incrementDecrementOperator, &locationExpression}, Rule({&incrementDecrementOperator, &unaryExpression},
MakeIncrementDecrementExpressionPrefix), MakeIncrementDecrementExpressionPrefix),
Rule({&locationExpression, &incrementDecrementOperator}, Rule({&unaryExpression, &incrementDecrementOperator},
MakeIncrementDecrementExpressionPostfix)}; MakeIncrementDecrementExpressionPostfix)};
// Result: Expression* // Result: Expression*
...@@ -1521,7 +1529,7 @@ struct TorqueGrammar : Grammar { ...@@ -1521,7 +1529,7 @@ struct TorqueGrammar : Grammar {
// Result: Expression* // Result: Expression*
Symbol assignmentExpression = { Symbol assignmentExpression = {
Rule({&conditionalExpression}), Rule({&conditionalExpression}),
Rule({&locationExpression, &assignmentOperator, &assignmentExpression}, Rule({&conditionalExpression, &assignmentOperator, &assignmentExpression},
MakeAssignmentExpression)}; MakeAssignmentExpression)};
// Result: Statement* // Result: Statement*
......
...@@ -58,6 +58,10 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -58,6 +58,10 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return result; return result;
} }
static const ReferenceType* GetReferenceType(const Type* referenced_type) {
return Get().reference_types_.Add(ReferenceType(referenced_type));
}
static const std::vector<const BuiltinPointerType*>& static const std::vector<const BuiltinPointerType*>&
AllBuiltinPointerTypes() { AllBuiltinPointerTypes() {
return Get().all_builtin_pointer_types_; return Get().all_builtin_pointer_types_;
...@@ -117,6 +121,10 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -117,6 +121,10 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return Get().GetBuiltinType(OBJECT_TYPE_STRING); return Get().GetBuiltinType(OBJECT_TYPE_STRING);
} }
static const Type* GetHeapObjectType() {
return Get().GetBuiltinType(HEAP_OBJECT_TYPE_STRING);
}
static const Type* GetJSObjectType() { static const Type* GetJSObjectType() {
return Get().GetBuiltinType(JSOBJECT_TYPE_STRING); return Get().GetBuiltinType(JSOBJECT_TYPE_STRING);
} }
...@@ -207,6 +215,7 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -207,6 +215,7 @@ class TypeOracle : public ContextualClass<TypeOracle> {
Deduplicator<BuiltinPointerType> function_pointer_types_; Deduplicator<BuiltinPointerType> function_pointer_types_;
std::vector<const BuiltinPointerType*> all_builtin_pointer_types_; std::vector<const BuiltinPointerType*> all_builtin_pointer_types_;
Deduplicator<UnionType> union_types_; Deduplicator<UnionType> union_types_;
Deduplicator<ReferenceType> reference_types_;
std::vector<std::unique_ptr<Type>> nominal_types_; std::vector<std::unique_ptr<Type>> nominal_types_;
std::vector<std::unique_ptr<Type>> struct_types_; std::vector<std::unique_ptr<Type>> struct_types_;
std::vector<std::unique_ptr<Type>> top_types_; std::vector<std::unique_ptr<Type>> top_types_;
......
...@@ -46,6 +46,13 @@ bool Type::IsSubtypeOf(const Type* supertype) const { ...@@ -46,6 +46,13 @@ bool Type::IsSubtypeOf(const Type* supertype) const {
return false; return false;
} }
base::Optional<const ClassType*> Type::ClassSupertype() const {
for (const Type* t = this; t != nullptr; t = t->parent()) {
if (auto* class_type = ClassType::DynamicCast(t)) return class_type;
}
return base::nullopt;
}
// static // static
const Type* Type::CommonSupertype(const Type* a, const Type* b) { const Type* Type::CommonSupertype(const Type* a, const Type* b) {
int diff = a->Depth() - b->Depth(); int diff = a->Depth() - b->Depth();
...@@ -158,19 +165,6 @@ std::string UnionType::GetGeneratedTNodeTypeNameImpl() const { ...@@ -158,19 +165,6 @@ std::string UnionType::GetGeneratedTNodeTypeNameImpl() const {
return parent()->GetGeneratedTNodeTypeName(); return parent()->GetGeneratedTNodeTypeName();
} }
const Type* UnionType::NonConstexprVersion() const {
if (IsConstexpr()) {
auto it = types_.begin();
UnionType result((*it)->NonConstexprVersion());
++it;
for (; it != types_.end(); ++it) {
result.Extend((*it)->NonConstexprVersion());
}
return TypeOracle::GetUnionType(std::move(result));
}
return this;
}
void UnionType::RecomputeParent() { void UnionType::RecomputeParent() {
const Type* parent = nullptr; const Type* parent = nullptr;
for (const Type* t : types_) { for (const Type* t : types_) {
...@@ -470,6 +464,9 @@ void AppendLoweredTypes(const Type* type, std::vector<const Type*>* result) { ...@@ -470,6 +464,9 @@ void AppendLoweredTypes(const Type* type, std::vector<const Type*>* result) {
for (const Field& field : s->fields()) { for (const Field& field : s->fields()) {
AppendLoweredTypes(field.name_and_type.type, result); AppendLoweredTypes(field.name_and_type.type, result);
} }
} else if (type->IsReferenceType()) {
result->push_back(TypeOracle::GetHeapObjectType());
result->push_back(TypeOracle::GetIntPtrType());
} else { } else {
result->push_back(type); result->push_back(type);
} }
......
...@@ -29,6 +29,7 @@ static const char* const ARGUMENTS_TYPE_STRING = "Arguments"; ...@@ -29,6 +29,7 @@ static const char* const ARGUMENTS_TYPE_STRING = "Arguments";
static const char* const CONTEXT_TYPE_STRING = "Context"; static const char* const CONTEXT_TYPE_STRING = "Context";
static const char* const MAP_TYPE_STRING = "Map"; static const char* const MAP_TYPE_STRING = "Map";
static const char* const OBJECT_TYPE_STRING = "Object"; static const char* const OBJECT_TYPE_STRING = "Object";
static const char* const HEAP_OBJECT_TYPE_STRING = "HeapObject";
static const char* const JSOBJECT_TYPE_STRING = "JSObject"; static const char* const JSOBJECT_TYPE_STRING = "JSObject";
static const char* const SMI_TYPE_STRING = "Smi"; static const char* const SMI_TYPE_STRING = "Smi";
static const char* const TAGGED_TYPE_STRING = "Tagged"; static const char* const TAGGED_TYPE_STRING = "Tagged";
...@@ -65,6 +66,7 @@ class TypeBase { ...@@ -65,6 +66,7 @@ class TypeBase {
kTopType, kTopType,
kAbstractType, kAbstractType,
kBuiltinPointerType, kBuiltinPointerType,
kReferenceType,
kUnionType, kUnionType,
kStructType, kStructType,
kClassType kClassType
...@@ -75,6 +77,7 @@ class TypeBase { ...@@ -75,6 +77,7 @@ class TypeBase {
bool IsBuiltinPointerType() const { bool IsBuiltinPointerType() const {
return kind() == Kind::kBuiltinPointerType; return kind() == Kind::kBuiltinPointerType;
} }
bool IsReferenceType() const { return kind() == Kind::kReferenceType; }
bool IsUnionType() const { return kind() == Kind::kUnionType; } bool IsUnionType() const { return kind() == Kind::kUnionType; }
bool IsStructType() const { return kind() == Kind::kStructType; } bool IsStructType() const { return kind() == Kind::kStructType; }
bool IsClassType() const { return kind() == Kind::kClassType; } bool IsClassType() const { return kind() == Kind::kClassType; }
...@@ -123,9 +126,13 @@ class Type : public TypeBase { ...@@ -123,9 +126,13 @@ class Type : public TypeBase {
bool IsVoidOrNever() const { return IsVoid() || IsNever(); } bool IsVoidOrNever() const { return IsVoid() || IsNever(); }
std::string GetGeneratedTypeName() const; std::string GetGeneratedTypeName() const;
std::string GetGeneratedTNodeTypeName() const; std::string GetGeneratedTNodeTypeName() const;
virtual bool IsConstexpr() const = 0; virtual bool IsConstexpr() const {
if (parent()) DCHECK(!parent()->IsConstexpr());
return false;
}
virtual bool IsTransient() const { return false; } virtual bool IsTransient() const { return false; }
virtual const Type* NonConstexprVersion() const = 0; virtual const Type* NonConstexprVersion() const { return this; }
base::Optional<const ClassType*> ClassSupertype() const;
static const Type* CommonSupertype(const Type* a, const Type* b); static const Type* CommonSupertype(const Type* a, const Type* b);
void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); } void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
...@@ -189,8 +196,6 @@ class TopType final : public Type { ...@@ -189,8 +196,6 @@ class TopType final : public Type {
std::string GetGeneratedTNodeTypeNameImpl() const override { std::string GetGeneratedTNodeTypeNameImpl() const override {
return source_type_->GetGeneratedTNodeTypeName(); return source_type_->GetGeneratedTNodeTypeName();
} }
bool IsConstexpr() const override { return false; }
const Type* NonConstexprVersion() const override { return nullptr; }
std::string ToExplicitString() const override { std::string ToExplicitString() const override {
std::stringstream s; std::stringstream s;
s << "inaccessible " + source_type_->ToString(); s << "inaccessible " + source_type_->ToString();
...@@ -268,11 +273,6 @@ class BuiltinPointerType final : public Type { ...@@ -268,11 +273,6 @@ class BuiltinPointerType final : public Type {
std::string GetGeneratedTNodeTypeNameImpl() const override { std::string GetGeneratedTNodeTypeNameImpl() const override {
return parent()->GetGeneratedTNodeTypeName(); return parent()->GetGeneratedTNodeTypeName();
} }
bool IsConstexpr() const override {
DCHECK(!parent()->IsConstexpr());
return false;
}
const Type* NonConstexprVersion() const override { return this; }
const TypeVector& parameter_types() const { return parameter_types_; } const TypeVector& parameter_types() const { return parameter_types_; }
const Type* return_type() const { return return_type_; } const Type* return_type() const { return return_type_; }
...@@ -304,6 +304,43 @@ class BuiltinPointerType final : public Type { ...@@ -304,6 +304,43 @@ class BuiltinPointerType final : public Type {
const size_t function_pointer_type_id_; const size_t function_pointer_type_id_;
}; };
class ReferenceType final : public Type {
public:
DECLARE_TYPE_BOILERPLATE(ReferenceType)
std::string MangledName() const override {
return "RT" + referenced_type_->MangledName();
}
std::string ToExplicitString() const override {
std::string s = referenced_type_->ToString();
if (s.find(' ') != std::string::npos) {
s = "(" + s + ")";
}
return "&" + s;
}
std::string GetGeneratedTypeNameImpl() const override {
return "CodeStubAssembler::Reference";
}
std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); }
const Type* referenced_type() const { return referenced_type_; }
friend size_t hash_value(const ReferenceType& p) {
return base::hash_combine(static_cast<size_t>(Kind::kReferenceType),
p.referenced_type_);
}
bool operator==(const ReferenceType& other) const {
return referenced_type_ == other.referenced_type_;
}
private:
friend class TypeOracle;
explicit ReferenceType(const Type* referenced_type)
: Type(Kind::kReferenceType, nullptr),
referenced_type_(referenced_type) {}
const Type* const referenced_type_;
};
bool operator<(const Type& a, const Type& b); bool operator<(const Type& a, const Type& b);
struct TypeLess { struct TypeLess {
bool operator()(const Type* const a, const Type* const b) const { bool operator()(const Type* const a, const Type* const b) const {
...@@ -321,12 +358,6 @@ class UnionType final : public Type { ...@@ -321,12 +358,6 @@ class UnionType final : public Type {
} }
std::string GetGeneratedTNodeTypeNameImpl() const override; std::string GetGeneratedTNodeTypeNameImpl() const override;
bool IsConstexpr() const override {
DCHECK_EQ(false, parent()->IsConstexpr());
return false;
}
const Type* NonConstexprVersion() const override;
friend size_t hash_value(const UnionType& p) { friend size_t hash_value(const UnionType& p) {
size_t result = 0; size_t result = 0;
for (const Type* t : p.types_) { for (const Type* t : p.types_) {
...@@ -407,9 +438,7 @@ class AggregateType : public Type { ...@@ -407,9 +438,7 @@ class AggregateType : public Type {
std::string MangledName() const override { return name_; } std::string MangledName() const override { return name_; }
std::string GetGeneratedTypeNameImpl() const override { UNREACHABLE(); } std::string GetGeneratedTypeNameImpl() const override { UNREACHABLE(); }
std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); } std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); }
const Type* NonConstexprVersion() const override { return this; }
bool IsConstexpr() const override { return false; }
virtual bool HasIndexedField() const { return false; } virtual bool HasIndexedField() const { return false; }
void SetFields(std::vector<Field> fields) { fields_ = std::move(fields); } void SetFields(std::vector<Field> fields) { fields_ = std::move(fields); }
......
...@@ -472,6 +472,20 @@ TEST(TestNewFixedArrayFromSpread) { ...@@ -472,6 +472,20 @@ TEST(TestNewFixedArrayFromSpread) {
ft.Call(); ft.Call();
} }
TEST(TestReferences) {
CcTest::InitializeVM();
Isolate* isolate(CcTest::i_isolate());
i::HandleScope scope(isolate);
CodeAssemblerTester asm_tester(isolate);
TestTorqueAssembler m(asm_tester.state());
{
m.TestReferences();
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -858,4 +858,28 @@ namespace test { ...@@ -858,4 +858,28 @@ namespace test {
const i = TestIterator{count: 5}; const i = TestIterator{count: 5};
return new FixedArray{map: kFixedArrayMap, length: 5, objects: ...i}; return new FixedArray{map: kFixedArrayMap, length: 5, objects: ...i};
} }
class SmiPair {
GetA():&Smi {
return & this.a;
}
a: Smi;
b: Smi;
}
macro Swap<T: type>(a:&T, b:&T) {
const tmp = * a;
* a = * b;
* b = tmp;
}
macro TestReferences() {
const array = new SmiPair{a: 7, b: 2};
const ref:&Smi = & array.a;
* ref = 3 + * ref;
-- * ref;
Swap(& array.b, array.GetA());
check(array.a == 2);
check(array.b == 9);
}
} }
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