[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:
Clemens Hammacher 2017-03-16 11:23:59 +01:00 committed by Commit Bot
parent 928bb02cad
commit f424837386
8 changed files with 45 additions and 47 deletions

View File

@ -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_; }

View File

@ -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 =

View File

@ -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;

View File

@ -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");

View File

@ -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);

View File

@ -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) };

View File

@ -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.

View File

@ -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";