// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_CODEGEN_SIGNATURE_H_ #define V8_CODEGEN_SIGNATURE_H_ #include "src/base/functional.h" #include "src/base/iterator.h" #include "src/codegen/machine-type.h" #include "src/zone/zone.h" namespace v8 { namespace internal { // Describes the inputs and outputs of a function or call. template class Signature : public ZoneObject { public: constexpr Signature(size_t return_count, size_t parameter_count, const T* reps) : return_count_(return_count), parameter_count_(parameter_count), reps_(reps) { DCHECK_EQ(kReturnCountOffset, offsetof(Signature, return_count_)); DCHECK_EQ(kParameterCountOffset, offsetof(Signature, parameter_count_)); DCHECK_EQ(kRepsOffset, offsetof(Signature, reps_)); STATIC_ASSERT(std::is_standard_layout>::value); } size_t return_count() const { return return_count_; } size_t parameter_count() const { return parameter_count_; } T GetParam(size_t index) const { DCHECK_LT(index, parameter_count_); return reps_[return_count_ + index]; } T GetReturn(size_t index = 0) const { DCHECK_LT(index, return_count_); return reps_[index]; } // Iteration support. base::iterator_range parameters() const { return {reps_ + return_count_, reps_ + return_count_ + parameter_count_}; } base::iterator_range returns() const { return {reps_, reps_ + return_count_}; } base::iterator_range all() const { return {reps_, reps_ + return_count_ + parameter_count_}; } bool operator==(const Signature& other) const { if (this == &other) return true; if (parameter_count() != other.parameter_count()) return false; if (return_count() != other.return_count()) return false; return std::equal(all().begin(), all().end(), other.all().begin()); } bool operator!=(const Signature& other) const { return !(*this == other); } // For incrementally building signatures. class Builder { public: Builder(Zone* zone, size_t return_count, size_t parameter_count) : return_count_(return_count), parameter_count_(parameter_count), zone_(zone), rcursor_(0), pcursor_(0), buffer_(zone->NewArray( static_cast(return_count + parameter_count))) {} const size_t return_count_; const size_t parameter_count_; void AddReturn(T val) { DCHECK_LT(rcursor_, return_count_); buffer_[rcursor_++] = val; } void AddParam(T val) { DCHECK_LT(pcursor_, parameter_count_); buffer_[return_count_ + pcursor_++] = val; } void AddParamAt(size_t index, T val) { DCHECK_LT(index, parameter_count_); buffer_[return_count_ + index] = val; pcursor_ = std::max(pcursor_, index + 1); } Signature* Build() { DCHECK_EQ(rcursor_, return_count_); DCHECK_EQ(pcursor_, parameter_count_); return zone_->New>(return_count_, parameter_count_, buffer_); } private: Zone* zone_; size_t rcursor_; size_t pcursor_; T* buffer_; }; static constexpr size_t kReturnCountOffset = 0; static constexpr size_t kParameterCountOffset = kReturnCountOffset + kSizetSize; static constexpr size_t kRepsOffset = kParameterCountOffset + kSizetSize; protected: size_t return_count_; size_t parameter_count_; const T* reps_; }; using MachineSignature = Signature; template size_t hash_value(const Signature& sig) { size_t hash = base::hash_combine(sig.parameter_count(), sig.return_count()); for (const T& t : sig.all()) hash = base::hash_combine(hash, t); return hash; } } // namespace internal } // namespace v8 #endif // V8_CODEGEN_SIGNATURE_H_