Commit 6380476c authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm] Make wasm::ValueType independent of the MachineRepresentation

R=clemensh@chromium.org
CC=​titzer@chromium.org

Change-Id: I4951bf7ffc8baf51225e7bef60349186811b9f76
Reviewed-on: https://chromium-review.googlesource.com/1024037
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53020}
parent 08bfc14b
This diff is collapsed.
......@@ -176,8 +176,8 @@ class WasmGraphBuilder {
Node* Terminate(Node* effect, Node* control);
Node* Merge(unsigned count, Node** controls);
Node* Phi(wasm::ValueType type, unsigned count, Node** vals, Node* control);
Node* CreateOrMergeIntoPhi(wasm::ValueType type, Node* merge, Node* tnode,
Node* fnode);
Node* CreateOrMergeIntoPhi(MachineRepresentation rep, Node* merge,
Node* tnode, Node* fnode);
Node* CreateOrMergeIntoEffectPhi(Node* merge, Node* tnode, Node* fnode);
Node* EffectPhi(unsigned count, Node** effects, Node* control);
Node* NumberConstant(int32_t value);
......
......@@ -52,6 +52,8 @@ enum class MachineSemantic : uint8_t {
V8_EXPORT_PRIVATE inline int ElementSizeLog2Of(MachineRepresentation rep);
V8_EXPORT_PRIVATE inline int ElementSizeInBytes(MachineRepresentation rep);
class MachineType {
public:
constexpr MachineType()
......@@ -292,6 +294,10 @@ V8_EXPORT_PRIVATE inline int ElementSizeLog2Of(MachineRepresentation rep) {
UNREACHABLE();
}
V8_EXPORT_PRIVATE inline int ElementSizeInBytes(MachineRepresentation rep) {
return 1 << ElementSizeLog2Of(rep);
}
} // namespace internal
} // namespace v8
......
......@@ -2108,7 +2108,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
SimdLaneImmediate<validate> imm(this, this->pc_);
if (this->Validate(this->pc_, opcode, imm)) {
Value inputs[] = {Pop(0, ValueType::kSimd128)};
Value inputs[] = {Pop(0, kWasmS128)};
auto* result = Push(type);
CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
result);
......@@ -2121,8 +2121,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
if (this->Validate(this->pc_, opcode, imm)) {
Value inputs[2];
inputs[1] = Pop(1, type);
inputs[0] = Pop(0, ValueType::kSimd128);
auto* result = Push(ValueType::kSimd128);
inputs[0] = Pop(0, kWasmS128);
auto* result = Push(kWasmS128);
CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
result);
}
......@@ -2132,8 +2132,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
unsigned SimdShiftOp(WasmOpcode opcode) {
SimdShiftImmediate<validate> imm(this, this->pc_);
if (this->Validate(this->pc_, opcode, imm)) {
auto input = Pop(0, ValueType::kSimd128);
auto* result = Push(ValueType::kSimd128);
auto input = Pop(0, kWasmS128);
auto* result = Push(kWasmS128);
CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result);
}
return imm.length;
......@@ -2142,9 +2142,9 @@ class WasmFullDecoder : public WasmDecoder<validate> {
unsigned Simd8x16ShuffleOp() {
Simd8x16ShuffleImmediate<validate> imm(this, this->pc_);
if (this->Validate(this->pc_, imm)) {
auto input1 = Pop(1, ValueType::kSimd128);
auto input0 = Pop(0, ValueType::kSimd128);
auto* result = Push(ValueType::kSimd128);
auto input1 = Pop(1, kWasmS128);
auto input0 = Pop(0, kWasmS128);
auto* result = Push(kWasmS128);
CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
result);
}
......@@ -2155,23 +2155,23 @@ class WasmFullDecoder : public WasmDecoder<validate> {
unsigned len = 0;
switch (opcode) {
case kExprF32x4ExtractLane: {
len = SimdExtractLane(opcode, ValueType::kFloat32);
len = SimdExtractLane(opcode, kWasmF32);
break;
}
case kExprI32x4ExtractLane:
case kExprI16x8ExtractLane:
case kExprI8x16ExtractLane: {
len = SimdExtractLane(opcode, ValueType::kWord32);
len = SimdExtractLane(opcode, kWasmI32);
break;
}
case kExprF32x4ReplaceLane: {
len = SimdReplaceLane(opcode, ValueType::kFloat32);
len = SimdReplaceLane(opcode, kWasmF32);
break;
}
case kExprI32x4ReplaceLane:
case kExprI16x8ReplaceLane:
case kExprI8x16ReplaceLane: {
len = SimdReplaceLane(opcode, ValueType::kWord32);
len = SimdReplaceLane(opcode, kWasmI32);
break;
}
case kExprI32x4Shl:
......@@ -2218,11 +2218,11 @@ class WasmFullDecoder : public WasmDecoder<validate> {
if (sig != nullptr) {
MachineType memtype;
switch (opcode) {
#define CASE_ATOMIC_STORE_OP(Name, Type) \
case kExpr##Name: { \
memtype = MachineType::Type(); \
ret_type = MachineRepresentation::kNone; \
break; \
#define CASE_ATOMIC_STORE_OP(Name, Type) \
case kExpr##Name: { \
memtype = MachineType::Type(); \
ret_type = kWasmStmt; \
break; \
}
ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
#undef CASE_ATOMIC_OP
......@@ -2242,9 +2242,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
len += imm.length;
PopArgs(sig);
auto result = ret_type == MachineRepresentation::kNone
? nullptr
: Push(GetReturnType(sig));
auto result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig));
CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, vec2vec(args_), imm,
result);
} else {
......
......@@ -574,9 +574,9 @@ class WasmGraphBuildingInterface {
try_info->exception = if_exception;
} else {
DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
try_info->exception =
builder_->CreateOrMergeIntoPhi(kWasmI32, try_info->catch_env->control,
try_info->exception, if_exception);
try_info->exception = builder_->CreateOrMergeIntoPhi(
MachineRepresentation::kWord32, try_info->catch_env->control,
try_info->exception, if_exception);
}
SetEnv(success_env);
......@@ -618,7 +618,8 @@ class WasmGraphBuildingInterface {
DCHECK(val.type == old.type || val.type == kWasmVar);
old.node = first ? val.node
: builder_->CreateOrMergeIntoPhi(
old.type, target->control, old.node, val.node);
ValueTypes::MachineRepresentationFor(old.type),
target->control, old.node, val.node);
}
}
......@@ -670,7 +671,8 @@ class WasmGraphBuildingInterface {
// Merge locals.
for (int i = decoder->NumLocals() - 1; i >= 0; i--) {
to->locals[i] = builder_->CreateOrMergeIntoPhi(
decoder->GetLocalType(i), merge, to->locals[i], from->locals[i]);
ValueTypes::MachineRepresentationFor(decoder->GetLocalType(i)),
merge, to->locals[i], from->locals[i]);
}
// Merge the instance caches.
builder_->MergeInstanceCacheInto(&to->instance_cache,
......
......@@ -7,7 +7,7 @@
#include <map>
#include "src/machine-type.h"
#include "src/wasm/value-type.h"
namespace v8 {
namespace internal {
......@@ -17,7 +17,6 @@ class Signature;
namespace wasm {
using ValueType = MachineRepresentation;
using FunctionSig = Signature<ValueType>;
// A signature map canonicalizes signatures into a range of indices so that
......
......@@ -12,17 +12,16 @@ namespace v8 {
namespace internal {
namespace wasm {
// We reuse the internal machine type to represent WebAssembly types.
// A typedef improves readability without adding a whole new type system.
using ValueType = MachineRepresentation;
constexpr ValueType kWasmStmt = MachineRepresentation::kNone;
constexpr ValueType kWasmI32 = MachineRepresentation::kWord32;
constexpr ValueType kWasmI64 = MachineRepresentation::kWord64;
constexpr ValueType kWasmF32 = MachineRepresentation::kFloat32;
constexpr ValueType kWasmF64 = MachineRepresentation::kFloat64;
constexpr ValueType kWasmS128 = MachineRepresentation::kSimd128;
constexpr ValueType kWasmAnyRef = MachineRepresentation::kTaggedPointer;
constexpr ValueType kWasmVar = MachineRepresentation::kTagged;
enum ValueType : uint8_t {
kWasmStmt,
kWasmI32,
kWasmI64,
kWasmF32,
kWasmF64,
kWasmS128,
kWasmAnyRef,
kWasmVar,
};
// TODO(clemensh): Compute memtype and size from ValueType once we have c++14
// constexpr support.
......@@ -126,7 +125,7 @@ class StoreType {
constexpr unsigned size_log_2() const { return kStoreSizeLog2[val_]; }
constexpr unsigned size() const { return 1 << size_log_2(); }
constexpr ValueType value_type() const { return kValueType[val_]; }
constexpr ValueType mem_rep() const { return kMemRep[val_]; }
constexpr MachineRepresentation mem_rep() const { return kMemRep[val_]; }
static StoreType ForValueType(ValueType type) {
switch (type) {
......@@ -169,7 +168,37 @@ class StoreType {
class V8_EXPORT_PRIVATE ValueTypes {
public:
static byte MemSize(MachineType type) {
return MemSize(type.representation());
return 1 << i::ElementSizeLog2Of(type.representation());
}
static int ElementSizeInBytes(ValueType type) {
switch (type) {
case kWasmI32:
case kWasmF32:
return 4;
case kWasmI64:
case kWasmF64:
return 8;
case kWasmS128:
return 16;
default:
UNREACHABLE();
}
}
static int ElementSizeLog2Of(ValueType type) {
switch (type) {
case kWasmI32:
case kWasmF32:
return 2;
case kWasmI64:
case kWasmF64:
return 3;
case kWasmS128:
return 4;
default:
UNREACHABLE();
}
}
static byte MemSize(ValueType type) { return 1 << ElementSizeLog2Of(type); }
......@@ -216,6 +245,27 @@ class V8_EXPORT_PRIVATE ValueTypes {
}
}
static MachineRepresentation MachineRepresentationFor(ValueType type) {
switch (type) {
case kWasmI32:
return MachineRepresentation::kWord32;
case kWasmI64:
return MachineRepresentation::kWord64;
case kWasmF32:
return MachineRepresentation::kFloat32;
case kWasmF64:
return MachineRepresentation::kFloat64;
case kWasmAnyRef:
return MachineRepresentation::kTaggedPointer;
case kWasmS128:
return MachineRepresentation::kSimd128;
case kWasmStmt:
return MachineRepresentation::kNone;
default:
UNREACHABLE();
}
}
static ValueType ValueTypeFor(MachineType type) {
switch (type.representation()) {
case MachineRepresentation::kWord8:
......
......@@ -177,7 +177,8 @@ class InterpreterHandle {
ScopedVector<WasmValue> wasm_args(num_params);
Address arg_buf_ptr = arg_buffer;
for (int i = 0; i < num_params; ++i) {
uint32_t param_size = 1 << ElementSizeLog2Of(sig->GetParam(i));
uint32_t param_size = static_cast<uint32_t>(
ValueTypes::ElementSizeInBytes(sig->GetParam(i)));
#define CASE_ARG_TYPE(type, ctype) \
case type: \
DCHECK_EQ(param_size, sizeof(ctype)); \
......@@ -240,10 +241,11 @@ class InterpreterHandle {
DCHECK_EQ(1, kV8MaxWasmFunctionReturns);
if (sig->return_count()) {
WasmValue ret_val = thread->GetReturnValue(0);
#define CASE_RET_TYPE(type, ctype) \
case type: \
DCHECK_EQ(1 << ElementSizeLog2Of(sig->GetReturn(0)), sizeof(ctype)); \
WriteUnalignedValue<ctype>(arg_buffer, ret_val.to<ctype>()); \
#define CASE_RET_TYPE(type, ctype) \
case type: \
DCHECK_EQ(ValueTypes::ElementSizeInBytes(sig->GetReturn(0)), \
sizeof(ctype)); \
WriteUnalignedValue<ctype>(arg_buffer, ret_val.to<ctype>()); \
break;
switch (sig->GetReturn(0)) {
CASE_RET_TYPE(kWasmI32, uint32_t)
......
......@@ -2281,7 +2281,7 @@ class ThreadImpl {
size_t offset = 0;
WasmValue* wasm_args = sp_ - num_args;
for (int i = 0; i < num_args; ++i) {
uint32_t param_size = 1 << ElementSizeLog2Of(sig->GetParam(i));
int param_size = ValueTypes::ElementSizeInBytes(sig->GetParam(i));
if (arg_buffer.size() < offset + param_size) {
arg_buffer.resize(std::max(2 * arg_buffer.size(), offset + param_size));
}
......@@ -2307,9 +2307,9 @@ class ThreadImpl {
// Ensure that there is enough space in the arg_buffer to hold the return
// value(s).
uint32_t return_size = 0;
size_t return_size = 0;
for (ValueType t : sig->returns()) {
return_size += 1 << ElementSizeLog2Of(t);
return_size += ValueTypes::ElementSizeInBytes(t);
}
if (arg_buffer.size() < return_size) {
arg_buffer.resize(return_size);
......
......@@ -139,14 +139,14 @@ class LinkageAllocator {
// Stackslots are counted upwards starting from 0 (or the offset set by
// {SetStackOffset}.
int NumStackSlots(ValueType type) {
return 1 << std::max(0, ElementSizeLog2Of(type) - kPointerSizeLog2);
int NumStackSlots(MachineRepresentation type) {
return std::max(1, ElementSizeInBytes(type) / kPointerSize);
}
// Stackslots are counted upwards starting from 0 (or the offset set by
// {SetStackOffset}. If {type} needs more than
// one stack slot, the lowest used stack slot is returned.
int NextStackSlot(ValueType type) {
int NextStackSlot(MachineRepresentation type) {
int num_stack_slots = NumStackSlots(type);
int offset = stack_offset_;
stack_offset_ += num_stack_slots;
......
......@@ -71,17 +71,14 @@ BIT_FIELD_ACCESSORS(WasmGlobalObject, flags, type, WasmGlobalObject::TypeBits)
BIT_FIELD_ACCESSORS(WasmGlobalObject, flags, is_mutable,
WasmGlobalObject::IsMutableBit)
// static
uint32_t WasmGlobalObject::TypeSize(wasm::ValueType type) {
return 1U << ElementSizeLog2Of(type);
int WasmGlobalObject::type_size() const {
return wasm::ValueTypes::ElementSizeInBytes(type());
}
uint32_t WasmGlobalObject::type_size() const { return TypeSize(type()); }
Address WasmGlobalObject::address() const {
uint32_t buffer_size = 0;
DCHECK(array_buffer()->byte_length()->ToUint32(&buffer_size));
DCHECK(offset() + type_size() <= buffer_size);
DCHECK_LE(offset() + type_size(), buffer_size);
USE(buffer_size);
return Address(array_buffer()->backing_store()) + offset();
}
......
......@@ -633,7 +633,7 @@ MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
auto global_obj = Handle<WasmGlobalObject>::cast(
isolate->factory()->NewJSObject(global_ctor));
uint32_t type_size = TypeSize(type);
uint32_t type_size = wasm::ValueTypes::ElementSizeInBytes(type);
Handle<JSArrayBuffer> buffer;
if (!maybe_buffer.ToHandle(&buffer)) {
......
......@@ -12,6 +12,7 @@
#include "src/objects.h"
#include "src/objects/script.h"
#include "src/signature.h"
#include "src/wasm/value-type.h"
// Has to be the last include (doesn't have include guards)
#include "src/objects/object-macros.h"
......@@ -28,7 +29,6 @@ struct WasmModule;
class SignatureMap;
class WireBytesRef;
class WasmInterpreter;
using ValueType = MachineRepresentation;
using FunctionSig = Signature<ValueType>;
} // namespace wasm
......@@ -250,8 +250,7 @@ class WasmGlobalObject : public JSObject {
Isolate* isolate, MaybeHandle<JSArrayBuffer> buffer, wasm::ValueType type,
int32_t offset, bool is_mutable);
static inline uint32_t TypeSize(wasm::ValueType);
inline uint32_t type_size() const;
inline int type_size() const;
inline int32_t GetI32();
inline int64_t GetI64();
......
......@@ -570,6 +570,7 @@ enum TrapReason {
kTrapCount
#undef DECLARE_ENUM
};
// A collection of opcode-related static methods.
class V8_EXPORT_PRIVATE WasmOpcodes {
public:
......
......@@ -35,11 +35,11 @@ CallDescriptor* CreateCallDescriptor(Zone* zone, int return_count,
wasm::FunctionSig::Builder builder(zone, return_count, param_count);
for (int i = 0; i < param_count; i++) {
builder.AddParam(type.representation());
builder.AddParam(wasm::ValueTypes::ValueTypeFor(type));
}
for (int i = 0; i < return_count; i++) {
builder.AddReturn(type.representation());
builder.AddReturn(wasm::ValueTypes::ValueTypeFor(type));
}
return compiler::GetWasmCallDescriptor(zone, builder.Build());
}
......
......@@ -321,7 +321,7 @@ WASM_COMPILED_EXEC_TEST(WasmSimpleStepping) {
WASM_COMPILED_EXEC_TEST(WasmStepInAndOut) {
WasmRunner<int, int> runner(execution_mode);
WasmFunctionCompiler& f2 = runner.NewFunction<void>();
f2.AllocateLocal(ValueType::kWord32);
f2.AllocateLocal(kWasmI32);
// Call f2 via indirect call, because a direct call requires f2 to exist when
// we compile main, but we need to compile main first so that the order of
......@@ -360,9 +360,9 @@ WASM_COMPILED_EXEC_TEST(WasmStepInAndOut) {
WASM_COMPILED_EXEC_TEST(WasmGetLocalsAndStack) {
WasmRunner<void, int> runner(execution_mode);
runner.AllocateLocal(ValueType::kWord64);
runner.AllocateLocal(ValueType::kFloat32);
runner.AllocateLocal(ValueType::kFloat64);
runner.AllocateLocal(kWasmI64);
runner.AllocateLocal(kWasmF32);
runner.AllocateLocal(kWasmF64);
BUILD(runner,
// set [1] to 17
......
......@@ -74,16 +74,16 @@ bool InterpretWasmModuleForTesting(Isolate* isolate,
// Fill the parameters up with default values.
for (size_t i = argc; i < param_count; ++i) {
switch (signature->GetParam(i)) {
case MachineRepresentation::kWord32:
case kWasmI32:
arguments[i] = WasmValue(int32_t{0});
break;
case MachineRepresentation::kWord64:
case kWasmI64:
arguments[i] = WasmValue(int64_t{0});
break;
case MachineRepresentation::kFloat32:
case kWasmF32:
arguments[i] = WasmValue(0.0f);
break;
case MachineRepresentation::kFloat64:
case kWasmF64:
arguments[i] = WasmValue(0.0);
break;
default:
......
......@@ -135,14 +135,14 @@ CallDescriptor* CreateRandomCallDescriptor(Zone* zone, size_t return_count,
wasm::FunctionSig::Builder builder(zone, return_count, param_count);
for (size_t i = 0; i < param_count; i++) {
MachineType type = RandomType(input);
builder.AddParam(type.representation());
builder.AddParam(wasm::ValueTypes::ValueTypeFor(type));
}
// Read the end byte of the parameters.
input->NextInt8(1);
for (size_t i = 0; i < return_count; i++) {
MachineType type = RandomType(input);
builder.AddReturn(type.representation());
builder.AddReturn(wasm::ValueTypes::ValueTypeFor(type));
}
return compiler::GetWasmCallDescriptor(zone, builder.Build());
......
......@@ -11,6 +11,7 @@
#include "src/compiler/wasm-compiler.h"
#include "src/objects-inl.h"
#include "src/signature.h"
#include "src/wasm/value-type.h"
#include "src/wasm/wasm-module.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
......@@ -330,8 +331,8 @@ TEST_F(Int64LoweringTest, CallI64Return) {
int32_t function = 0x9999;
Node* context_address = Int32Constant(0);
Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
sig_builder.AddReturn(MachineRepresentation::kWord64);
wasm::FunctionSig::Builder sig_builder(zone(), 1, 0);
sig_builder.AddReturn(wasm::kWasmI64);
auto call_descriptor =
compiler::GetWasmCallDescriptor(zone(), sig_builder.Build());
......@@ -360,11 +361,11 @@ TEST_F(Int64LoweringTest, CallI64Parameter) {
int32_t function = 0x9999;
Node* context_address = Int32Constant(0);
Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 3);
sig_builder.AddReturn(MachineRepresentation::kWord32);
sig_builder.AddParam(MachineRepresentation::kWord64);
sig_builder.AddParam(MachineRepresentation::kWord32);
sig_builder.AddParam(MachineRepresentation::kWord64);
wasm::FunctionSig::Builder sig_builder(zone(), 1, 3);
sig_builder.AddReturn(wasm::kWasmI32);
sig_builder.AddParam(wasm::kWasmI64);
sig_builder.AddParam(wasm::kWasmI32);
sig_builder.AddParam(wasm::kWasmI64);
auto call_descriptor =
compiler::GetWasmCallDescriptor(zone(), sig_builder.Build());
......
......@@ -462,7 +462,7 @@ TEST_F(WasmModuleVerifyTest, OneI32Exception) {
const WasmException& e0 = result.val->exceptions.front();
EXPECT_EQ(1u, e0.sig->parameter_count());
EXPECT_EQ(MachineRepresentation::kWord32, e0.sig->GetParam(0));
EXPECT_EQ(kWasmI32, e0.sig->GetParam(0));
}
TEST_F(WasmModuleVerifyTest, TwoExceptions) {
......@@ -479,10 +479,10 @@ TEST_F(WasmModuleVerifyTest, TwoExceptions) {
EXPECT_EQ(2u, result.val->exceptions.size());
const WasmException& e0 = result.val->exceptions.front();
EXPECT_EQ(2u, e0.sig->parameter_count());
EXPECT_EQ(MachineRepresentation::kFloat32, e0.sig->GetParam(0));
EXPECT_EQ(MachineRepresentation::kWord64, e0.sig->GetParam(1));
EXPECT_EQ(kWasmF32, e0.sig->GetParam(0));
EXPECT_EQ(kWasmI64, e0.sig->GetParam(1));
const WasmException& e1 = result.val->exceptions.back();
EXPECT_EQ(MachineRepresentation::kWord32, e1.sig->GetParam(0));
EXPECT_EQ(kWasmI32, e1.sig->GetParam(0));
}
TEST_F(WasmModuleVerifyTest, Exception_invalid_type) {
......
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