| Index: src/asmjs/asm-types.cc
|
| diff --git a/src/asmjs/asm-types.cc b/src/asmjs/asm-types.cc
|
| index 3804d439b127747c2523216acd7e92eeda78eb10..8f3c9a51e68b7e780bae102093095b45ba2072bd 100644
|
| --- a/src/asmjs/asm-types.cc
|
| +++ b/src/asmjs/asm-types.cc
|
| @@ -2,10 +2,12 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "src/v8.h"
|
| -
|
| #include "src/asmjs/asm-types.h"
|
|
|
| +#include <cinttypes>
|
| +
|
| +#include "src/v8.h"
|
| +
|
| namespace v8 {
|
| namespace internal {
|
| namespace wasm {
|
| @@ -15,10 +17,6 @@ AsmCallableType* AsmType::AsCallableType() {
|
| return nullptr;
|
| }
|
|
|
| - DCHECK(this->AsFunctionType() != nullptr ||
|
| - this->AsOverloadedFunctionType() != nullptr ||
|
| - this->AsFFIType() != nullptr ||
|
| - this->AsFunctionTableType() != nullptr);
|
| return reinterpret_cast<AsmCallableType*>(this);
|
| }
|
|
|
| @@ -58,16 +56,18 @@ bool AsmType::IsExactly(AsmType* that) {
|
| bool AsmType::IsA(AsmType* that) {
|
| // IsA is used for querying inheritance relationships. Therefore it is only
|
| // meaningful for basic types.
|
| - AsmValueType* tavt = that->AsValueType();
|
| - if (tavt != nullptr) {
|
| - AsmValueType* avt = this->AsValueType();
|
| - if (avt == nullptr) {
|
| - return false;
|
| + if (auto* avt = this->AsValueType()) {
|
| + if (auto* tavt = that->AsValueType()) {
|
| + return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
|
| }
|
| - return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
|
| + return false;
|
| + }
|
| +
|
| + if (auto* as_callable = this->AsCallableType()) {
|
| + return as_callable->IsA(that);
|
| }
|
|
|
| - // TODO(jpp): is it useful to allow non-value types to be tested with IsA?
|
| + UNREACHABLE();
|
| return that == this;
|
| }
|
|
|
| @@ -138,11 +138,11 @@ AsmType* AsmType::StoreType() {
|
| }
|
| }
|
|
|
| -std::string AsmFunctionType::Name() {
|
| - if (IsFroundType()) {
|
| - return "fround";
|
| - }
|
| +bool AsmCallableType::IsA(AsmType* other) {
|
| + return other->AsCallableType() == this;
|
| +}
|
|
|
| +std::string AsmFunctionType::Name() {
|
| std::string ret;
|
| ret += "(";
|
| for (size_t ii = 0; ii < args_.size(); ++ii) {
|
| @@ -151,54 +151,30 @@ std::string AsmFunctionType::Name() {
|
| ret += ", ";
|
| }
|
| }
|
| - if (IsMinMaxType()) {
|
| - DCHECK_EQ(args_.size(), 2);
|
| - ret += "...";
|
| - }
|
| ret += ") -> ";
|
| ret += return_type_->Name();
|
| return ret;
|
| }
|
|
|
| namespace {
|
| -class AsmFroundType final : public AsmFunctionType {
|
| +class AsmFroundType final : public AsmCallableType {
|
| public:
|
| - bool IsFroundType() const override { return true; }
|
| -
|
| - private:
|
| friend AsmType;
|
|
|
| - explicit AsmFroundType(Zone* zone)
|
| - : AsmFunctionType(zone, AsmType::Float()) {}
|
| + AsmFroundType() : AsmCallableType() {}
|
|
|
| - AsmType* ValidateCall(AsmType* return_type,
|
| - const ZoneVector<AsmType*>& args) override;
|
| bool CanBeInvokedWith(AsmType* return_type,
|
| const ZoneVector<AsmType*>& args) override;
|
| +
|
| + std::string Name() override { return "fround"; }
|
| };
|
| } // namespace
|
|
|
| AsmType* AsmType::FroundType(Zone* zone) {
|
| - auto* Fround = new (zone) AsmFroundType(zone);
|
| + auto* Fround = new (zone) AsmFroundType();
|
| return reinterpret_cast<AsmType*>(Fround);
|
| }
|
|
|
| -// TODO(jpp): Remove this method.
|
| -AsmType* AsmFroundType::ValidateCall(AsmType* return_type,
|
| - const ZoneVector<AsmType*>& args) {
|
| - if (args.size() != 1) {
|
| - return AsmType::None();
|
| - }
|
| -
|
| - auto* arg = args[0];
|
| - if (!arg->IsA(AsmType::Floatish()) && !arg->IsA(AsmType::DoubleQ()) &&
|
| - !arg->IsA(AsmType::Signed()) && !arg->IsA(AsmType::Unsigned())) {
|
| - return AsmType::None();
|
| - }
|
| -
|
| - return AsmType::Float();
|
| -}
|
| -
|
| bool AsmFroundType::CanBeInvokedWith(AsmType* return_type,
|
| const ZoneVector<AsmType*>& args) {
|
| if (args.size() != 1) {
|
| @@ -215,41 +191,16 @@ bool AsmFroundType::CanBeInvokedWith(AsmType* return_type,
|
| }
|
|
|
| namespace {
|
| -class AsmMinMaxType final : public AsmFunctionType {
|
| - public:
|
| - bool IsMinMaxType() const override { return true; }
|
| -
|
| +class AsmMinMaxType final : public AsmCallableType {
|
| private:
|
| friend AsmType;
|
|
|
| - AsmMinMaxType(Zone* zone, AsmType* dest, AsmType* src)
|
| - : AsmFunctionType(zone, dest) {
|
| - AddArgument(src);
|
| - AddArgument(src);
|
| - }
|
| -
|
| - AsmType* ValidateCall(AsmType* return_type,
|
| - const ZoneVector<AsmType*>& args) override {
|
| - if (!ReturnType()->IsExactly(return_type)) {
|
| - return AsmType::None();
|
| - }
|
| -
|
| - if (args.size() < 2) {
|
| - return AsmType::None();
|
| - }
|
| -
|
| - for (size_t ii = 0; ii < Arguments().size(); ++ii) {
|
| - if (!Arguments()[0]->IsExactly(args[ii])) {
|
| - return AsmType::None();
|
| - }
|
| - }
|
| -
|
| - return ReturnType();
|
| - }
|
| + AsmMinMaxType(AsmType* dest, AsmType* src)
|
| + : AsmCallableType(), return_type_(dest), arg_(src) {}
|
|
|
| bool CanBeInvokedWith(AsmType* return_type,
|
| const ZoneVector<AsmType*>& args) override {
|
| - if (!ReturnType()->IsExactly(return_type)) {
|
| + if (!return_type_->IsExactly(return_type)) {
|
| return false;
|
| }
|
|
|
| @@ -257,36 +208,32 @@ class AsmMinMaxType final : public AsmFunctionType {
|
| return false;
|
| }
|
|
|
| - auto* arg_type = Arguments()[0];
|
| - for (size_t ii = 0; ii < Arguments().size(); ++ii) {
|
| - if (!args[ii]->IsA(arg_type)) {
|
| + for (size_t ii = 0; ii < args.size(); ++ii) {
|
| + if (!args[ii]->IsA(arg_)) {
|
| return false;
|
| }
|
| }
|
|
|
| return true;
|
| }
|
| +
|
| + std::string Name() override {
|
| + return "(" + arg_->Name() + ", " + arg_->Name() + "...) -> " +
|
| + return_type_->Name();
|
| + }
|
| +
|
| + AsmType* return_type_;
|
| + AsmType* arg_;
|
| };
|
| } // namespace
|
|
|
| AsmType* AsmType::MinMaxType(Zone* zone, AsmType* dest, AsmType* src) {
|
| DCHECK(dest->AsValueType() != nullptr);
|
| DCHECK(src->AsValueType() != nullptr);
|
| - auto* MinMax = new (zone) AsmMinMaxType(zone, dest, src);
|
| + auto* MinMax = new (zone) AsmMinMaxType(dest, src);
|
| return reinterpret_cast<AsmType*>(MinMax);
|
| }
|
|
|
| -AsmType* AsmFFIType::ValidateCall(AsmType* return_type,
|
| - const ZoneVector<AsmType*>& args) {
|
| - for (size_t ii = 0; ii < args.size(); ++ii) {
|
| - if (!args[ii]->IsA(AsmType::Extern())) {
|
| - return AsmType::None();
|
| - }
|
| - }
|
| -
|
| - return return_type;
|
| -}
|
| -
|
| bool AsmFFIType::CanBeInvokedWith(AsmType* return_type,
|
| const ZoneVector<AsmType*>& args) {
|
| if (return_type->IsExactly(AsmType::Float())) {
|
| @@ -302,23 +249,26 @@ bool AsmFFIType::CanBeInvokedWith(AsmType* return_type,
|
| return true;
|
| }
|
|
|
| -AsmType* AsmFunctionType::ValidateCall(AsmType* return_type,
|
| - const ZoneVector<AsmType*>& args) {
|
| - if (!return_type_->IsExactly(return_type)) {
|
| - return AsmType::None();
|
| +bool AsmFunctionType::IsA(AsmType* other) {
|
| + auto* that = other->AsFunctionType();
|
| + if (that == nullptr) {
|
| + return false;
|
| + }
|
| + if (!return_type_->IsExactly(that->return_type_)) {
|
| + return false;
|
| }
|
|
|
| - if (args_.size() != args.size()) {
|
| - return AsmType::None();
|
| + if (args_.size() != that->args_.size()) {
|
| + return false;
|
| }
|
|
|
| for (size_t ii = 0; ii < args_.size(); ++ii) {
|
| - if (!args_[ii]->IsExactly(args[ii])) {
|
| - return AsmType::None();
|
| + if (!args_[ii]->IsExactly(that->args_[ii])) {
|
| + return false;
|
| }
|
| }
|
|
|
| - return return_type_;
|
| + return true;
|
| }
|
|
|
| bool AsmFunctionType::CanBeInvokedWith(AsmType* return_type,
|
| @@ -353,19 +303,6 @@ std::string AsmOverloadedFunctionType::Name() {
|
| return ret;
|
| }
|
|
|
| -AsmType* AsmOverloadedFunctionType::ValidateCall(
|
| - AsmType* return_type, const ZoneVector<AsmType*>& args) {
|
| - for (size_t ii = 0; ii < overloads_.size(); ++ii) {
|
| - auto* validated_type =
|
| - overloads_[ii]->AsCallableType()->ValidateCall(return_type, args);
|
| - if (validated_type != AsmType::None()) {
|
| - return validated_type;
|
| - }
|
| - }
|
| -
|
| - return AsmType::None();
|
| -}
|
| -
|
| bool AsmOverloadedFunctionType::CanBeInvokedWith(
|
| AsmType* return_type, const ZoneVector<AsmType*>& args) {
|
| for (size_t ii = 0; ii < overloads_.size(); ++ii) {
|
| @@ -378,7 +315,7 @@ bool AsmOverloadedFunctionType::CanBeInvokedWith(
|
| }
|
|
|
| void AsmOverloadedFunctionType::AddOverload(AsmType* overload) {
|
| - DCHECK(overload->AsFunctionType() != nullptr);
|
| + DCHECK(overload->AsCallableType() != nullptr);
|
| overloads_.push_back(overload);
|
| }
|
|
|
| @@ -388,13 +325,23 @@ AsmFunctionTableType::AsmFunctionTableType(size_t length, AsmType* signature)
|
| DCHECK(signature_->AsFunctionType() != nullptr);
|
| }
|
|
|
| -std::string AsmFunctionTableType::Name() {
|
| - return signature_->Name() + "[" + std::to_string(length_) + "]";
|
| +namespace {
|
| +// ToString is used for reporting function tables' names. It converts its
|
| +// argument to uint32_t because asm.js integers are 32-bits, thus effectively
|
| +// limiting the max function table's length.
|
| +std::string ToString(size_t s) {
|
| + auto u32 = static_cast<uint32_t>(s);
|
| + // 16 bytes is more than enough to represent a 32-bit integer as a base 10
|
| + // string.
|
| + char digits[16];
|
| + int length = base::OS::SNPrintF(digits, arraysize(digits), "%" PRIu32, u32);
|
| + DCHECK_NE(length, -1);
|
| + return std::string(digits, length);
|
| }
|
| +} // namespace
|
|
|
| -AsmType* AsmFunctionTableType::ValidateCall(AsmType* return_type,
|
| - const ZoneVector<AsmType*>& args) {
|
| - return signature_->AsCallableType()->ValidateCall(return_type, args);
|
| +std::string AsmFunctionTableType::Name() {
|
| + return "(" + signature_->Name() + ")[" + ToString(length_) + "]";
|
| }
|
|
|
| bool AsmFunctionTableType::CanBeInvokedWith(AsmType* return_type,
|
|
|