Commit 3a8c8082 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] infer generic arguments

This allows to call generic callables without mentioning all type
parameters, if they can be deduced from the types passed as arguments.

Bug: v8:7793
Change-Id: Idb37bb6b93c48bd6344c5be19da4e5b19d29593f
Reviewed-on: https://chromium-review.googlesource.com/c/1335936Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57515}
parent 80e9f18a
......@@ -187,7 +187,7 @@ namespace array {
AddStringLength(buffer.totalStringLength, str.length);
let index: intptr = buffer.index;
const fixedArray: FixedArray =
StoreAndGrowFixedArray<String>(buffer.fixedArray, index++, str);
StoreAndGrowFixedArray(buffer.fixedArray, index++, str);
const isOneByte: bool =
HasOnlyOneByteChars(str.instanceType) & buffer.isOneByte;
return Buffer{fixedArray, index, totalStringLength, isOneByte};
......@@ -211,7 +211,7 @@ namespace array {
let index: intptr = buffer.index;
let fixedArray: FixedArray = buffer.fixedArray;
if (write) deferred {
fixedArray = StoreAndGrowFixedArray<Smi>(
fixedArray = StoreAndGrowFixedArray(
buffer.fixedArray, index++, Convert<Smi>(nofSeparatorsInt));
}
return Buffer{fixedArray, index, totalStringLength, buffer.isOneByte};
......@@ -421,7 +421,7 @@ namespace array {
// If no open slots were found, grow the stack and add receiver to the end.
const newStack: FixedArray =
StoreAndGrowFixedArray<JSReceiver>(stack, capacity, receiver);
StoreAndGrowFixedArray(stack, capacity, receiver);
SetJoinStack(newStack);
return True;
}
......
......@@ -63,8 +63,8 @@ namespace array {
while (lower < upper) {
const lowerValue: T = LoadElement<Accessor, T>(elements, lower);
const upperValue: T = LoadElement<Accessor, T>(elements, upper);
StoreElement<Accessor, T>(elements, lower, upperValue);
StoreElement<Accessor, T>(elements, upper, lowerValue);
StoreElement<Accessor>(elements, lower, upperValue);
StoreElement<Accessor>(elements, upper, lowerValue);
++lower;
--upper;
}
......
......@@ -66,6 +66,38 @@ std::ostream& operator<<(std::ostream& os, const Generic& g) {
return os;
}
base::Optional<const Type*> Generic::InferTypeArgument(
size_t i, const TypeVector& arguments) {
const std::string type_name = declaration()->generic_parameters[i];
const std::vector<TypeExpression*>& parameters =
declaration()->callable->signature->parameters.types;
for (size_t i = 0; i < arguments.size() && i < parameters.size(); ++i) {
BasicTypeExpression* basic =
BasicTypeExpression::DynamicCast(parameters[i]);
if (basic && !basic->is_constexpr && basic->name == type_name) {
return arguments[i];
}
}
return base::nullopt;
}
base::Optional<TypeVector> Generic::InferSpecializationTypes(
const TypeVector& explicit_specialization_types,
const TypeVector& arguments) {
TypeVector result = explicit_specialization_types;
size_t type_parameter_count = declaration()->generic_parameters.size();
if (explicit_specialization_types.size() > type_parameter_count) {
return base::nullopt;
}
for (size_t i = explicit_specialization_types.size();
i < type_parameter_count; ++i) {
base::Optional<const Type*> inferred = InferTypeArgument(i, arguments);
if (!inferred) return base::nullopt;
result.push_back(*inferred);
}
return result;
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -349,6 +349,9 @@ class Generic : public Declarable {
if (it != specializations_.end()) return it->second;
return base::nullopt;
}
base::Optional<TypeVector> InferSpecializationTypes(
const TypeVector& explicit_specialization_types,
const TypeVector& arguments);
private:
friend class Declarations;
......@@ -356,6 +359,8 @@ class Generic : public Declarable {
: Declarable(Declarable::kGeneric),
name_(name),
declaration_(declaration) {}
base::Optional<const Type*> InferTypeArgument(size_t i,
const TypeVector& arguments);
std::string name_;
std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>>
......
......@@ -1313,13 +1313,14 @@ Callable* ImplementationVisitor::LookupCall(
std::vector<Signature> overload_signatures;
for (Declarable* declarable : Declarations::Lookup(name)) {
if (Generic* generic = Generic::DynamicCast(declarable)) {
if (generic->generic_parameters().size() != specialization_types.size()) {
continue;
}
base::Optional<TypeVector> inferred_specialization_types =
generic->InferSpecializationTypes(specialization_types,
parameter_types);
if (!inferred_specialization_types) continue;
overloads.push_back(generic);
overload_signatures.push_back(
DeclarationVisitor().MakeSpecializedSignature(
SpecializationKey{generic, specialization_types}));
SpecializationKey{generic, *inferred_specialization_types}));
} else if (Callable* callable = Callable::DynamicCast(declarable)) {
overloads.push_back(callable);
overload_signatures.push_back(callable->signature());
......@@ -1378,7 +1379,8 @@ Callable* ImplementationVisitor::LookupCall(
if (Generic* generic = Generic::DynamicCast(overloads[best])) {
result = GetOrCreateSpecialization(
SpecializationKey{generic, specialization_types});
SpecializationKey{generic, *generic->InferSpecializationTypes(
specialization_types, parameter_types)});
} else {
result = Callable::cast(overloads[best]);
}
......
......@@ -421,7 +421,7 @@ namespace test {
macro TypeswitchExample(x: Number | FixedArray): int32 {
let result: int32 = 0;
typeswitch (IncrementIfSmi<(Number | FixedArray)>(x)) {
typeswitch (IncrementIfSmi(x)) {
case (x: FixedArray): {
result = result + 1;
}
......@@ -432,7 +432,7 @@ namespace test {
result = result * 10;
typeswitch (IncrementIfSmi<(Number | FixedArray)>(x)) {
typeswitch (IncrementIfSmi(x)) {
case (x: Smi): {
result = result + Convert<int32>(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