Commit f4248373 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Make signature iterable

This introduces iterators for the parameters and return types of a
signature. This required extending the constructor of iterator_range
for perfect forwarding.

I also moved the HasJSCompatibleSignature to a header file in order to
reuse it from the interpreter.

R=ahaas@chromium.org, titzer@chromium.org

Change-Id: Ie77f87ef87fdfd3138b2106640ac7c481cf247e6
Reviewed-on: https://chromium-review.googlesource.com/455777
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43854}
parent 928bb02c
...@@ -26,9 +26,10 @@ class iterator_range { ...@@ -26,9 +26,10 @@ class iterator_range {
typename std::iterator_traits<iterator>::difference_type difference_type; typename std::iterator_traits<iterator>::difference_type difference_type;
iterator_range() : begin_(), end_() {} iterator_range() : begin_(), end_() {}
template <typename ForwardIterator2> template <typename ForwardIterator1, typename ForwardIterator2>
iterator_range(ForwardIterator2 const& begin, ForwardIterator2 const& end) iterator_range(ForwardIterator1&& begin, ForwardIterator2&& end)
: begin_(begin), end_(end) {} : begin_(std::forward<ForwardIterator1>(begin)),
end_(std::forward<ForwardIterator2>(end)) {}
iterator begin() { return begin_; } iterator begin() { return begin_; }
iterator end() { return end_; } iterator end() { return end_; }
......
...@@ -2692,22 +2692,6 @@ Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() { ...@@ -2692,22 +2692,6 @@ Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() {
return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag); return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
} }
namespace {
bool IsJSCompatible(wasm::ValueType type) {
return type != wasm::kWasmI64 && type != wasm::kWasmS128;
}
bool HasJSCompatibleSignature(wasm::FunctionSig* sig) {
for (size_t i = 0; i < sig->parameter_count(); i++) {
if (!IsJSCompatible(sig->GetParam(i))) return false;
}
for (size_t i = 0; i < sig->return_count(); i++) {
if (!IsJSCompatible(sig->GetReturn(i))) return false;
}
return true;
}
} // namespace
void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code, void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code,
wasm::FunctionSig* sig) { wasm::FunctionSig* sig) {
int wasm_count = static_cast<int>(sig->parameter_count()); int wasm_count = static_cast<int>(sig->parameter_count());
...@@ -2725,7 +2709,7 @@ void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code, ...@@ -2725,7 +2709,7 @@ void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code,
Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"), Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"),
graph()->start()); graph()->start());
if (!HasJSCompatibleSignature(sig_)) { if (!wasm::IsJSCompatibleSignature(sig_)) {
// Throw a TypeError. Use the context of the calling javascript function // Throw a TypeError. Use the context of the calling javascript function
// (passed as a parameter), such that the generated code is context // (passed as a parameter), such that the generated code is context
// independent. // independent.
...@@ -2817,7 +2801,7 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target, ...@@ -2817,7 +2801,7 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target,
*effect_ = start; *effect_ = start;
*control_ = start; *control_ = start;
if (!HasJSCompatibleSignature(sig_)) { if (!wasm::IsJSCompatibleSignature(sig_)) {
// Throw a TypeError. Embedding the context is ok here, since this code is // Throw a TypeError. Embedding the context is ok here, since this code is
// regenerated at instantiation time. // regenerated at instantiation time.
Node* context = Node* context =
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef V8_SIGNATURE_H_ #ifndef V8_SIGNATURE_H_
#define V8_SIGNATURE_H_ #define V8_SIGNATURE_H_
#include "src/base/iterator.h"
#include "src/zone/zone.h" #include "src/zone/zone.h"
namespace v8 { namespace v8 {
...@@ -32,6 +33,17 @@ class Signature : public ZoneObject { ...@@ -32,6 +33,17 @@ class Signature : public ZoneObject {
return reps_[index]; return reps_[index];
} }
// Iteration support.
base::iterator_range<const T*> parameters() const {
return {reps_ + return_count_, reps_ + return_count_ + parameter_count_};
}
base::iterator_range<const T*> returns() const {
return {reps_, reps_ + return_count_};
}
base::iterator_range<const T*> all() const {
return {reps_, reps_ + return_count_ + parameter_count_};
}
bool Equals(const Signature* that) const { bool Equals(const Signature* that) const {
if (this == that) return true; if (this == that) return true;
if (this->parameter_count() != that->parameter_count()) return false; if (this->parameter_count() != that->parameter_count()) return false;
......
...@@ -177,10 +177,7 @@ class WasmDecoder : public Decoder { ...@@ -177,10 +177,7 @@ class WasmDecoder : public Decoder {
DCHECK_NOT_NULL(type_list); DCHECK_NOT_NULL(type_list);
// Initialize from signature. // Initialize from signature.
if (sig != nullptr) { if (sig != nullptr) {
type_list->reserve(sig->parameter_count()); type_list->assign(sig->parameters().begin(), sig->parameters().end());
for (size_t i = 0; i < sig->parameter_count(); ++i) {
type_list->push_back(sig->GetParam(i));
}
} }
// Decode local declarations, if any. // Decode local declarations, if any.
uint32_t entries = decoder->consume_u32v("local decls count"); uint32_t entries = decoder->consume_u32v("local decls count");
......
...@@ -334,12 +334,12 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { ...@@ -334,12 +334,12 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
for (FunctionSig* sig : signatures_) { for (FunctionSig* sig : signatures_) {
buffer.write_u8(kWasmFunctionTypeForm); buffer.write_u8(kWasmFunctionTypeForm);
buffer.write_size(sig->parameter_count()); buffer.write_size(sig->parameter_count());
for (size_t j = 0; j < sig->parameter_count(); j++) { for (auto param : sig->parameters()) {
buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(sig->GetParam(j))); buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(param));
} }
buffer.write_size(sig->return_count()); buffer.write_size(sig->return_count());
for (size_t j = 0; j < sig->return_count(); j++) { for (auto ret : sig->returns()) {
buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(sig->GetReturn(j))); buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(ret));
} }
} }
FixupSection(buffer, start); FixupSection(buffer, start);
......
...@@ -11,8 +11,6 @@ namespace v8 { ...@@ -11,8 +11,6 @@ namespace v8 {
namespace internal { namespace internal {
namespace wasm { namespace wasm {
typedef Signature<ValueType> FunctionSig;
#define CASE_OP(name, str) \ #define CASE_OP(name, str) \
case kExpr##name: \ case kExpr##name: \
return str; return str;
...@@ -269,17 +267,24 @@ bool WasmOpcodes::IsPrefixOpcode(WasmOpcode opcode) { ...@@ -269,17 +267,24 @@ bool WasmOpcodes::IsPrefixOpcode(WasmOpcode opcode) {
std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) { std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
if (sig.return_count() == 0) os << "v"; if (sig.return_count() == 0) os << "v";
for (size_t i = 0; i < sig.return_count(); ++i) { for (auto ret : sig.returns()) {
os << WasmOpcodes::ShortNameOf(sig.GetReturn(i)); os << WasmOpcodes::ShortNameOf(ret);
} }
os << "_"; os << "_";
if (sig.parameter_count() == 0) os << "v"; if (sig.parameter_count() == 0) os << "v";
for (size_t i = 0; i < sig.parameter_count(); ++i) { for (auto param : sig.parameters()) {
os << WasmOpcodes::ShortNameOf(sig.GetParam(i)); os << WasmOpcodes::ShortNameOf(param);
} }
return os; return os;
} }
bool IsJSCompatibleSignature(const FunctionSig* sig) {
for (auto type : sig->all()) {
if (type == wasm::kWasmI64 || type == wasm::kWasmS128) return false;
}
return true;
}
#define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name, #define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name,
enum WasmOpcodeSig { FOREACH_SIGNATURE(DECLARE_SIG_ENUM) }; enum WasmOpcodeSig { FOREACH_SIGNATURE(DECLARE_SIG_ENUM) };
......
...@@ -32,7 +32,7 @@ static const uint8_t kMultivalBlock = 0x41; ...@@ -32,7 +32,7 @@ static const uint8_t kMultivalBlock = 0x41;
// We reuse the internal machine type to represent WebAssembly types. // We reuse the internal machine type to represent WebAssembly types.
// A typedef improves readability without adding a whole new type system. // A typedef improves readability without adding a whole new type system.
typedef MachineRepresentation ValueType; using ValueType = MachineRepresentation;
constexpr ValueType kWasmStmt = MachineRepresentation::kNone; constexpr ValueType kWasmStmt = MachineRepresentation::kNone;
constexpr ValueType kWasmI32 = MachineRepresentation::kWord32; constexpr ValueType kWasmI32 = MachineRepresentation::kWord32;
constexpr ValueType kWasmI64 = MachineRepresentation::kWord64; constexpr ValueType kWasmI64 = MachineRepresentation::kWord64;
...@@ -44,12 +44,13 @@ constexpr ValueType kWasmS1x8 = MachineRepresentation::kSimd1x8; ...@@ -44,12 +44,13 @@ constexpr ValueType kWasmS1x8 = MachineRepresentation::kSimd1x8;
constexpr ValueType kWasmS1x16 = MachineRepresentation::kSimd1x16; constexpr ValueType kWasmS1x16 = MachineRepresentation::kSimd1x16;
constexpr ValueType kWasmVar = MachineRepresentation::kTagged; constexpr ValueType kWasmVar = MachineRepresentation::kTagged;
typedef Signature<ValueType> FunctionSig; using FunctionSig = Signature<ValueType>;
std::ostream& operator<<(std::ostream& os, const FunctionSig& function); std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
bool IsJSCompatibleSignature(const FunctionSig* sig);
typedef Vector<const char> WasmName; using WasmName = Vector<const char>;
typedef int WasmCodePosition; using WasmCodePosition = int;
constexpr WasmCodePosition kNoCodePosition = -1; constexpr WasmCodePosition kNoCodePosition = -1;
// Control expressions and blocks. // Control expressions and blocks.
......
...@@ -52,18 +52,16 @@ void wasm::PrintWasmText(const WasmModule *module, ...@@ -52,18 +52,16 @@ void wasm::PrintWasmText(const WasmModule *module,
os << " $"; os << " $";
os.write(fun_name.start(), fun_name.length()); os.write(fun_name.start(), fun_name.length());
} }
size_t param_count = fun->sig->parameter_count(); if (fun->sig->parameter_count()) {
if (param_count) {
os << " (param"; os << " (param";
for (size_t i = 0; i < param_count; ++i) for (auto param : fun->sig->parameters())
os << ' ' << WasmOpcodes::TypeName(fun->sig->GetParam(i)); os << ' ' << WasmOpcodes::TypeName(param);
os << ')'; os << ')';
} }
size_t return_count = fun->sig->return_count(); if (fun->sig->return_count()) {
if (return_count) {
os << " (result"; os << " (result";
for (size_t i = 0; i < return_count; ++i) for (auto ret : fun->sig->returns())
os << ' ' << WasmOpcodes::TypeName(fun->sig->GetReturn(i)); os << ' ' << WasmOpcodes::TypeName(ret);
os << ')'; os << ')';
} }
os << "\n"; os << "\n";
......
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