[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;
|
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() {
|
|||||||
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,
|
|||||||
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,
|
|||||||
*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 @@
|
|||||||
#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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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) {
|
|||||||
|
|
||||||
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;
|
|||||||
|
|
||||||
// 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;
|
|||||||
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,
|
|||||||
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";
|
||||||
|
Loading…
Reference in New Issue
Block a user