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