Merge V8 5.3.332.45.  DO NOT MERGE

Test: Manual

FPIIM-449

Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/wasm/asm-types.cc b/src/wasm/asm-types.cc
new file mode 100644
index 0000000..e5588ae
--- /dev/null
+++ b/src/wasm/asm-types.cc
@@ -0,0 +1,319 @@
+// Copyright 2016 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.
+
+#include "src/v8.h"
+
+#include "src/wasm/asm-types.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+AsmCallableType* AsmType::AsCallableType() {
+  if (AsValueType() != nullptr) {
+    return nullptr;
+  }
+
+  DCHECK(this->AsFunctionType() != nullptr ||
+         this->AsOverloadedFunctionType() != nullptr ||
+         this->AsFFIType() != nullptr ||
+         this->AsFunctionTableType() != nullptr);
+  return reinterpret_cast<AsmCallableType*>(this);
+}
+
+std::string AsmType::Name() {
+  AsmValueType* avt = this->AsValueType();
+  if (avt != nullptr) {
+    switch (avt->Bitset()) {
+#define RETURN_TYPE_NAME(CamelName, string_name, number, parent_types) \
+  case AsmValueType::kAsm##CamelName:                                  \
+    return string_name;
+      FOR_EACH_ASM_VALUE_TYPE_LIST(RETURN_TYPE_NAME)
+#undef RETURN_TYPE_NAME
+      default:
+        UNREACHABLE();
+    }
+  }
+
+  return this->AsCallableType()->Name();
+}
+
+bool AsmType::IsExactly(AsmType* that) {
+  // TODO(jpp): maybe this can become this == that.
+  AsmValueType* avt = this->AsValueType();
+  if (avt != nullptr) {
+    AsmValueType* tavt = that->AsValueType();
+    if (tavt == nullptr) {
+      return false;
+    }
+    return avt->Bitset() == tavt->Bitset();
+  }
+
+  // TODO(jpp): is it useful to allow non-value types to be tested with
+  // IsExactly?
+  return that == this;
+}
+
+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;
+    }
+    return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
+  }
+
+  // TODO(jpp): is it useful to allow non-value types to be tested with IsA?
+  return that == this;
+}
+
+int32_t AsmType::ElementSizeInBytes() {
+  auto* value = AsValueType();
+  if (value == nullptr) {
+    return AsmType::kNotHeapType;
+  }
+  switch (value->Bitset()) {
+    case AsmValueType::kAsmInt8Array:
+    case AsmValueType::kAsmUint8Array:
+      return 1;
+    case AsmValueType::kAsmInt16Array:
+    case AsmValueType::kAsmUint16Array:
+      return 2;
+    case AsmValueType::kAsmInt32Array:
+    case AsmValueType::kAsmUint32Array:
+    case AsmValueType::kAsmFloat32Array:
+      return 4;
+    case AsmValueType::kAsmFloat64Array:
+      return 8;
+    default:
+      return AsmType::kNotHeapType;
+  }
+}
+
+AsmType* AsmType::LoadType() {
+  auto* value = AsValueType();
+  if (value == nullptr) {
+    return AsmType::None();
+  }
+  switch (value->Bitset()) {
+    case AsmValueType::kAsmInt8Array:
+    case AsmValueType::kAsmUint8Array:
+    case AsmValueType::kAsmInt16Array:
+    case AsmValueType::kAsmUint16Array:
+    case AsmValueType::kAsmInt32Array:
+    case AsmValueType::kAsmUint32Array:
+      return AsmType::Intish();
+    case AsmValueType::kAsmFloat32Array:
+      return AsmType::FloatQ();
+    case AsmValueType::kAsmFloat64Array:
+      return AsmType::DoubleQ();
+    default:
+      return AsmType::None();
+  }
+}
+
+AsmType* AsmType::StoreType() {
+  auto* value = AsValueType();
+  if (value == nullptr) {
+    return AsmType::None();
+  }
+  switch (value->Bitset()) {
+    case AsmValueType::kAsmInt8Array:
+    case AsmValueType::kAsmUint8Array:
+    case AsmValueType::kAsmInt16Array:
+    case AsmValueType::kAsmUint16Array:
+    case AsmValueType::kAsmInt32Array:
+    case AsmValueType::kAsmUint32Array:
+      return AsmType::Intish();
+    case AsmValueType::kAsmFloat32Array:
+      return AsmType::FloatishDoubleQ();
+    case AsmValueType::kAsmFloat64Array:
+      return AsmType::FloatQDoubleQ();
+    default:
+      return AsmType::None();
+  }
+}
+
+std::string AsmFunctionType::Name() {
+  if (IsFroundType()) {
+    return "fround";
+  }
+
+  std::string ret;
+  ret += "(";
+  for (size_t ii = 0; ii < args_.size(); ++ii) {
+    ret += args_[ii]->Name();
+    if (ii != args_.size() - 1) {
+      ret += ", ";
+    }
+  }
+  if (IsMinMaxType()) {
+    DCHECK_EQ(args_.size(), 2);
+    ret += "...";
+  }
+  ret += ") -> ";
+  ret += return_type_->Name();
+  return ret;
+}
+
+namespace {
+class AsmFroundType final : public AsmFunctionType {
+ public:
+  bool IsFroundType() const override { return true; }
+
+ private:
+  friend AsmType;
+
+  explicit AsmFroundType(Zone* zone)
+      : AsmFunctionType(zone, AsmType::Float()) {}
+
+  AsmType* ValidateCall(AsmType* return_type,
+                        const ZoneVector<AsmType*>& args) override;
+};
+}  // namespace
+
+AsmType* AsmType::FroundType(Zone* zone) {
+  auto* Fround = new (zone) AsmFroundType(zone);
+  return reinterpret_cast<AsmType*>(Fround);
+}
+
+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();
+}
+
+namespace {
+class AsmMinMaxType final : public AsmFunctionType {
+ public:
+  bool IsMinMaxType() const override { return true; }
+
+ 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();
+  }
+};
+}  // 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);
+  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;
+}
+
+AsmType* AsmFunctionType::ValidateCall(AsmType* return_type,
+                                       const ZoneVector<AsmType*>& args) {
+  if (!return_type_->IsExactly(return_type)) {
+    return AsmType::None();
+  }
+
+  if (args_.size() != args.size()) {
+    return AsmType::None();
+  }
+
+  for (size_t ii = 0; ii < args_.size(); ++ii) {
+    if (!args_[ii]->IsExactly(args[ii])) {
+      return AsmType::None();
+    }
+  }
+
+  return return_type_;
+}
+
+std::string AsmOverloadedFunctionType::Name() {
+  std::string ret;
+
+  for (size_t ii = 0; ii < overloads_.size(); ++ii) {
+    if (ii != 0) {
+      ret += " /\\ ";
+    }
+    ret += overloads_[ii]->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();
+}
+
+void AsmOverloadedFunctionType::AddOverload(AsmType* overload) {
+  DCHECK(overload->AsFunctionType() != nullptr);
+  overloads_.push_back(overload);
+}
+
+AsmFunctionTableType::AsmFunctionTableType(size_t length, AsmType* signature)
+    : length_(length), signature_(signature) {
+  DCHECK(signature_ != nullptr);
+  DCHECK(signature_->AsFunctionType() != nullptr);
+}
+
+std::string AsmFunctionTableType::Name() {
+  return signature_->Name() + "[" + std::to_string(length_) + "]";
+}
+
+AsmType* AsmFunctionTableType::ValidateCall(AsmType* return_type,
+                                            const ZoneVector<AsmType*>& args) {
+  return signature_->AsCallableType()->ValidateCall(return_type, args);
+}
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8