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 { ...@@ -187,7 +187,7 @@ namespace array {
AddStringLength(buffer.totalStringLength, str.length); AddStringLength(buffer.totalStringLength, str.length);
let index: intptr = buffer.index; let index: intptr = buffer.index;
const fixedArray: FixedArray = const fixedArray: FixedArray =
StoreAndGrowFixedArray<String>(buffer.fixedArray, index++, str); StoreAndGrowFixedArray(buffer.fixedArray, index++, str);
const isOneByte: bool = const isOneByte: bool =
HasOnlyOneByteChars(str.instanceType) & buffer.isOneByte; HasOnlyOneByteChars(str.instanceType) & buffer.isOneByte;
return Buffer{fixedArray, index, totalStringLength, isOneByte}; return Buffer{fixedArray, index, totalStringLength, isOneByte};
...@@ -211,7 +211,7 @@ namespace array { ...@@ -211,7 +211,7 @@ namespace array {
let index: intptr = buffer.index; let index: intptr = buffer.index;
let fixedArray: FixedArray = buffer.fixedArray; let fixedArray: FixedArray = buffer.fixedArray;
if (write) deferred { if (write) deferred {
fixedArray = StoreAndGrowFixedArray<Smi>( fixedArray = StoreAndGrowFixedArray(
buffer.fixedArray, index++, Convert<Smi>(nofSeparatorsInt)); buffer.fixedArray, index++, Convert<Smi>(nofSeparatorsInt));
} }
return Buffer{fixedArray, index, totalStringLength, buffer.isOneByte}; return Buffer{fixedArray, index, totalStringLength, buffer.isOneByte};
...@@ -421,7 +421,7 @@ namespace array { ...@@ -421,7 +421,7 @@ namespace array {
// If no open slots were found, grow the stack and add receiver to the end. // If no open slots were found, grow the stack and add receiver to the end.
const newStack: FixedArray = const newStack: FixedArray =
StoreAndGrowFixedArray<JSReceiver>(stack, capacity, receiver); StoreAndGrowFixedArray(stack, capacity, receiver);
SetJoinStack(newStack); SetJoinStack(newStack);
return True; return True;
} }
......
...@@ -63,8 +63,8 @@ namespace array { ...@@ -63,8 +63,8 @@ namespace array {
while (lower < upper) { while (lower < upper) {
const lowerValue: T = LoadElement<Accessor, T>(elements, lower); const lowerValue: T = LoadElement<Accessor, T>(elements, lower);
const upperValue: T = LoadElement<Accessor, T>(elements, upper); const upperValue: T = LoadElement<Accessor, T>(elements, upper);
StoreElement<Accessor, T>(elements, lower, upperValue); StoreElement<Accessor>(elements, lower, upperValue);
StoreElement<Accessor, T>(elements, upper, lowerValue); StoreElement<Accessor>(elements, upper, lowerValue);
++lower; ++lower;
--upper; --upper;
} }
......
...@@ -66,6 +66,38 @@ std::ostream& operator<<(std::ostream& os, const Generic& g) { ...@@ -66,6 +66,38 @@ std::ostream& operator<<(std::ostream& os, const Generic& g) {
return os; 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 torque
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -349,6 +349,9 @@ class Generic : public Declarable { ...@@ -349,6 +349,9 @@ class Generic : public Declarable {
if (it != specializations_.end()) return it->second; if (it != specializations_.end()) return it->second;
return base::nullopt; return base::nullopt;
} }
base::Optional<TypeVector> InferSpecializationTypes(
const TypeVector& explicit_specialization_types,
const TypeVector& arguments);
private: private:
friend class Declarations; friend class Declarations;
...@@ -356,6 +359,8 @@ class Generic : public Declarable { ...@@ -356,6 +359,8 @@ 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>>
......
...@@ -1313,13 +1313,14 @@ Callable* ImplementationVisitor::LookupCall( ...@@ -1313,13 +1313,14 @@ Callable* ImplementationVisitor::LookupCall(
std::vector<Signature> overload_signatures; std::vector<Signature> overload_signatures;
for (Declarable* declarable : Declarations::Lookup(name)) { for (Declarable* declarable : Declarations::Lookup(name)) {
if (Generic* generic = Generic::DynamicCast(declarable)) { if (Generic* generic = Generic::DynamicCast(declarable)) {
if (generic->generic_parameters().size() != specialization_types.size()) { base::Optional<TypeVector> inferred_specialization_types =
continue; generic->InferSpecializationTypes(specialization_types,
} parameter_types);
if (!inferred_specialization_types) continue;
overloads.push_back(generic); overloads.push_back(generic);
overload_signatures.push_back( overload_signatures.push_back(
DeclarationVisitor().MakeSpecializedSignature( DeclarationVisitor().MakeSpecializedSignature(
SpecializationKey{generic, specialization_types})); SpecializationKey{generic, *inferred_specialization_types}));
} else if (Callable* callable = Callable::DynamicCast(declarable)) { } else if (Callable* callable = Callable::DynamicCast(declarable)) {
overloads.push_back(callable); overloads.push_back(callable);
overload_signatures.push_back(callable->signature()); overload_signatures.push_back(callable->signature());
...@@ -1378,7 +1379,8 @@ Callable* ImplementationVisitor::LookupCall( ...@@ -1378,7 +1379,8 @@ Callable* ImplementationVisitor::LookupCall(
if (Generic* generic = Generic::DynamicCast(overloads[best])) { if (Generic* generic = Generic::DynamicCast(overloads[best])) {
result = GetOrCreateSpecialization( result = GetOrCreateSpecialization(
SpecializationKey{generic, specialization_types}); SpecializationKey{generic, *generic->InferSpecializationTypes(
specialization_types, parameter_types)});
} else { } else {
result = Callable::cast(overloads[best]); result = Callable::cast(overloads[best]);
} }
......
...@@ -421,7 +421,7 @@ namespace test { ...@@ -421,7 +421,7 @@ namespace test {
macro TypeswitchExample(x: Number | FixedArray): int32 { macro TypeswitchExample(x: Number | FixedArray): int32 {
let result: int32 = 0; let result: int32 = 0;
typeswitch (IncrementIfSmi<(Number | FixedArray)>(x)) { typeswitch (IncrementIfSmi(x)) {
case (x: FixedArray): { case (x: FixedArray): {
result = result + 1; result = result + 1;
} }
...@@ -432,7 +432,7 @@ namespace test { ...@@ -432,7 +432,7 @@ namespace test {
result = result * 10; result = result * 10;
typeswitch (IncrementIfSmi<(Number | FixedArray)>(x)) { typeswitch (IncrementIfSmi(x)) {
case (x: Smi): { case (x: Smi): {
result = result + Convert<int32>(x); 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