Commit 1bf5ac8c authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Extract WasmVal to own header and rename to WasmValue

This allows to reuse the class e.g. in the baseline compiler.

R=titzer@chromium.org

Change-Id: I7251af16e8c74f267834a9cefb676edf3c9f3a07
Reviewed-on: https://chromium-review.googlesource.com/570020Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46735}
parent 10c6fb56
......@@ -2011,6 +2011,7 @@ v8_source_set("v8_base") {
"src/wasm/wasm-result.h",
"src/wasm/wasm-text.cc",
"src/wasm/wasm-text.h",
"src/wasm/wasm-value.h",
"src/zone/accounting-allocator.cc",
"src/zone/accounting-allocator.h",
"src/zone/zone-allocator.h",
......
......@@ -1452,6 +1452,7 @@
'wasm/wasm-result.h',
'wasm/wasm-text.cc',
'wasm/wasm-text.h',
'wasm/wasm-value.h',
'zone/accounting-allocator.cc',
'zone/accounting-allocator.h',
'zone/zone-segment.cc',
......
......@@ -40,8 +40,8 @@ Handle<String> PrintFToOneByteString(Isolate* isolate, const char* format,
: isolate->factory()->NewStringFromOneByte(name).ToHandleChecked();
}
Handle<Object> WasmValToValueObject(Isolate* isolate, WasmVal value) {
switch (value.type) {
Handle<Object> WasmValueToValueObject(Isolate* isolate, WasmValue value) {
switch (value.type()) {
case kWasmI32:
if (Smi::IsValid(value.to<int32_t>()))
return handle(Smi::FromInt(value.to<int32_t>()), isolate);
......@@ -197,14 +197,14 @@ class InterpreterHandle {
FunctionSig* sig = module()->functions[func_index].sig;
DCHECK_GE(kMaxInt, sig->parameter_count());
int num_params = static_cast<int>(sig->parameter_count());
ScopedVector<WasmVal> wasm_args(num_params);
ScopedVector<WasmValue> wasm_args(num_params);
uint8_t* arg_buf_ptr = arg_buffer;
for (int i = 0; i < num_params; ++i) {
uint32_t param_size = 1 << ElementSizeLog2Of(sig->GetParam(i));
#define CASE_ARG_TYPE(type, ctype) \
case type: \
DCHECK_EQ(param_size, sizeof(ctype)); \
wasm_args[i] = WasmVal(ReadUnalignedValue<ctype>(arg_buf_ptr)); \
#define CASE_ARG_TYPE(type, ctype) \
case type: \
DCHECK_EQ(param_size, sizeof(ctype)); \
wasm_args[i] = WasmValue(ReadUnalignedValue<ctype>(arg_buf_ptr)); \
break;
switch (sig->GetParam(i)) {
CASE_ARG_TYPE(kWasmI32, uint32_t)
......@@ -264,7 +264,7 @@ class InterpreterHandle {
// TODO(wasm): Handle multi-value returns.
DCHECK_EQ(1, kV8MaxWasmFunctionReturns);
if (sig->return_count()) {
WasmVal ret_val = thread->GetReturnValue(0);
WasmValue ret_val = thread->GetReturnValue(0);
#define CASE_RET_TYPE(type, ctype) \
case type: \
DCHECK_EQ(1 << ElementSizeLog2Of(sig->GetReturn(0)), sizeof(ctype)); \
......@@ -498,8 +498,8 @@ class InterpreterHandle {
const char* label = i < num_params ? "arg#%d" : "local#%d";
name = PrintFToOneByteString<true>(isolate_, label, i);
}
WasmVal value = frame->GetLocalValue(i);
Handle<Object> value_obj = WasmValToValueObject(isolate_, value);
WasmValue value = frame->GetLocalValue(i);
Handle<Object> value_obj = WasmValueToValueObject(isolate_, value);
JSObject::SetOwnPropertyIgnoreAttributes(
locals_obj, name.ToHandleChecked(), value_obj, NONE)
.Assert();
......@@ -519,8 +519,8 @@ class InterpreterHandle {
stack_obj, NONE)
.Assert();
for (int i = 0; i < stack_count; ++i) {
WasmVal value = frame->GetStackValue(i);
Handle<Object> value_obj = WasmValToValueObject(isolate_, value);
WasmValue value = frame->GetStackValue(i);
Handle<Object> value_obj = WasmValueToValueObject(isolate_, value);
JSObject::SetOwnElementIgnoreAttributes(
stack_obj, static_cast<uint32_t>(i), value_obj, NONE)
.Assert();
......
......@@ -587,11 +587,11 @@ inline double ExecuteF64ReinterpretI64(int64_t a, TrapReason* trap) {
return bit_cast<double>(a);
}
inline int32_t ExecuteI32ReinterpretF32(WasmVal a) {
inline int32_t ExecuteI32ReinterpretF32(WasmValue a) {
return a.to_unchecked<int32_t>();
}
inline int64_t ExecuteI64ReinterpretF64(WasmVal a) {
inline int64_t ExecuteI64ReinterpretF64(WasmValue a) {
return a.to_unchecked<int64_t>();
}
......@@ -1037,8 +1037,8 @@ class CodeMap {
}
};
Handle<Object> WasmValToNumber(Factory* factory, WasmVal val,
wasm::ValueType type) {
Handle<Object> WasmValueToNumber(Factory* factory, WasmValue val,
wasm::ValueType type) {
switch (type) {
case kWasmI32:
return factory->NewNumberFromInt(val.to<int32_t>());
......@@ -1058,15 +1058,15 @@ Handle<Object> WasmValToNumber(Factory* factory, WasmVal val,
// Convert JS value to WebAssembly, spec here:
// https://github.com/WebAssembly/design/blob/master/JS.md#towebassemblyvalue
WasmVal ToWebAssemblyValue(Isolate* isolate, Handle<Object> value,
wasm::ValueType type) {
WasmValue ToWebAssemblyValue(Isolate* isolate, Handle<Object> value,
wasm::ValueType type) {
switch (type) {
case kWasmI32: {
MaybeHandle<Object> maybe_i32 = Object::ToInt32(isolate, value);
// TODO(clemensh): Handle failure here (unwind).
int32_t value;
CHECK(maybe_i32.ToHandleChecked()->ToInt32(&value));
return WasmVal(value);
return WasmValue(value);
}
case kWasmI64:
// If the signature contains i64, a type error was thrown before.
......@@ -1074,18 +1074,18 @@ WasmVal ToWebAssemblyValue(Isolate* isolate, Handle<Object> value,
case kWasmF32: {
MaybeHandle<Object> maybe_number = Object::ToNumber(value);
// TODO(clemensh): Handle failure here (unwind).
return WasmVal(
return WasmValue(
static_cast<float>(maybe_number.ToHandleChecked()->Number()));
}
case kWasmF64: {
MaybeHandle<Object> maybe_number = Object::ToNumber(value);
// TODO(clemensh): Handle failure here (unwind).
return WasmVal(maybe_number.ToHandleChecked()->Number());
return WasmValue(maybe_number.ToHandleChecked()->Number());
}
default:
// TODO(wasm): Handle simd.
UNIMPLEMENTED();
return WasmVal();
return WasmValue();
}
}
......@@ -1111,7 +1111,7 @@ class ThreadImpl {
WasmInterpreter::State state() { return state_; }
void InitFrame(const WasmFunction* function, WasmVal* args) {
void InitFrame(const WasmFunction* function, WasmValue* args) {
DCHECK_EQ(current_activation().fp, frames_.size());
InterpreterCode* code = codemap()->GetCode(function);
size_t num_params = function->sig->parameter_count();
......@@ -1155,8 +1155,8 @@ class ThreadImpl {
return static_cast<int>(frames_.size());
}
WasmVal GetReturnValue(uint32_t index) {
if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef);
WasmValue GetReturnValue(uint32_t index) {
if (state_ == WasmInterpreter::TRAPPED) return WasmValue(0xdeadbeef);
DCHECK_EQ(WasmInterpreter::FINISHED, state_);
Activation act = current_activation();
// Current activation must be finished.
......@@ -1164,12 +1164,12 @@ class ThreadImpl {
return GetStackValue(act.sp + index);
}
WasmVal GetStackValue(sp_t index) {
WasmValue GetStackValue(sp_t index) {
DCHECK_GT(StackHeight(), index);
return stack_start_[index];
}
void SetStackValue(sp_t index, WasmVal value) {
void SetStackValue(sp_t index, WasmValue value) {
DCHECK_GT(StackHeight(), index);
stack_start_[index] = value;
}
......@@ -1262,9 +1262,9 @@ class ThreadImpl {
CodeMap* codemap_;
WasmInstance* instance_;
Zone* zone_;
WasmVal* stack_start_ = nullptr; // Start of allocated stack space.
WasmVal* stack_limit_ = nullptr; // End of allocated stack space.
WasmVal* sp_ = nullptr; // Current stack pointer.
WasmValue* stack_start_ = nullptr; // Start of allocated stack space.
WasmValue* stack_limit_ = nullptr; // End of allocated stack space.
WasmValue* sp_ = nullptr; // Current stack pointer.
ZoneVector<Frame> frames_;
WasmInterpreter::State state_ = WasmInterpreter::STOPPED;
pc_t break_pc_ = kInvalidPc;
......@@ -1305,11 +1305,11 @@ class ThreadImpl {
pc_t InitLocals(InterpreterCode* code) {
for (auto p : code->locals.type_list) {
WasmVal val;
WasmValue val;
switch (p) {
#define CASE_TYPE(wasm, ctype) \
case kWasm##wasm: \
val = WasmVal(static_cast<ctype>(0)); \
#define CASE_TYPE(wasm, ctype) \
case kWasm##wasm: \
val = WasmValue(static_cast<ctype>(0)); \
break;
WASM_CTYPES(CASE_TYPE)
#undef CASE_TYPE
......@@ -1365,7 +1365,7 @@ class ThreadImpl {
bool DoReturn(Decoder* decoder, InterpreterCode** code, pc_t* pc, pc_t* limit,
size_t arity) {
DCHECK_GT(frames_.size(), 0);
WasmVal* sp_dest = stack_start_ + frames_.back().sp;
WasmValue* sp_dest = stack_start_ + frames_.back().sp;
frames_.pop_back();
if (frames_.size() == current_activation().fp) {
// A return from the last frame terminates the execution.
......@@ -1402,7 +1402,7 @@ class ThreadImpl {
// Copies {arity} values on the top of the stack down the stack to {dest},
// dropping the values in-between.
void DoStackTransfer(WasmVal* dest, size_t arity) {
void DoStackTransfer(WasmValue* dest, size_t arity) {
// before: |---------------| pop_count | arity |
// ^ 0 ^ dest ^ sp_
//
......@@ -1429,7 +1429,7 @@ class ThreadImpl {
return false;
}
byte* addr = instance()->mem_start + operand.offset + index;
WasmVal result(static_cast<ctype>(ReadLittleEndianValue<mtype>(addr)));
WasmValue result(static_cast<ctype>(ReadLittleEndianValue<mtype>(addr)));
Push(result);
len = 1 + operand.length;
......@@ -1440,7 +1440,7 @@ class ThreadImpl {
bool ExecuteStore(Decoder* decoder, InterpreterCode* code, pc_t pc,
int& len) {
MemoryAccessOperand<false> operand(decoder, code->at(pc), sizeof(ctype));
WasmVal val = Pop();
WasmValue val = Pop();
uint32_t index = Pop().to<uint32_t>();
if (!BoundsCheck<mtype>(instance()->mem_size, operand.offset, index)) {
......@@ -1562,7 +1562,7 @@ class ThreadImpl {
}
case kExprIf: {
BlockTypeOperand<false> operand(&decoder, code->at(pc));
WasmVal cond = Pop();
WasmValue cond = Pop();
bool is_true = cond.to<uint32_t>() != 0;
if (is_true) {
// fall through to the true block.
......@@ -1580,9 +1580,9 @@ class ThreadImpl {
break;
}
case kExprSelect: {
WasmVal cond = Pop();
WasmVal fval = Pop();
WasmVal tval = Pop();
WasmValue cond = Pop();
WasmValue fval = Pop();
WasmValue tval = Pop();
Push(cond.to<int32_t>() != 0 ? tval : fval);
break;
}
......@@ -1594,7 +1594,7 @@ class ThreadImpl {
}
case kExprBrIf: {
BreakDepthOperand<false> operand(&decoder, code->at(pc));
WasmVal cond = Pop();
WasmValue cond = Pop();
bool is_true = cond.to<uint32_t>() != 0;
if (is_true) {
len = DoBreak(code, pc, operand.depth);
......@@ -1633,25 +1633,25 @@ class ThreadImpl {
}
case kExprI32Const: {
ImmI32Operand<false> operand(&decoder, code->at(pc));
Push(WasmVal(operand.value));
Push(WasmValue(operand.value));
len = 1 + operand.length;
break;
}
case kExprI64Const: {
ImmI64Operand<false> operand(&decoder, code->at(pc));
Push(WasmVal(operand.value));
Push(WasmValue(operand.value));
len = 1 + operand.length;
break;
}
case kExprF32Const: {
ImmF32Operand<false> operand(&decoder, code->at(pc));
Push(WasmVal(operand.value));
Push(WasmValue(operand.value));
len = 1 + operand.length;
break;
}
case kExprF64Const: {
ImmF64Operand<false> operand(&decoder, code->at(pc));
Push(WasmVal(operand.value));
Push(WasmValue(operand.value));
len = 1 + operand.length;
break;
}
......@@ -1663,14 +1663,14 @@ class ThreadImpl {
}
case kExprSetLocal: {
LocalIndexOperand<false> operand(&decoder, code->at(pc));
WasmVal val = Pop();
WasmValue val = Pop();
SetStackValue(frames_.back().sp + operand.index, val);
len = 1 + operand.length;
break;
}
case kExprTeeLocal: {
LocalIndexOperand<false> operand(&decoder, code->at(pc));
WasmVal val = Pop();
WasmValue val = Pop();
SetStackValue(frames_.back().sp + operand.index, val);
Push(val);
len = 1 + operand.length;
......@@ -1743,11 +1743,11 @@ class ThreadImpl {
GlobalIndexOperand<false> operand(&decoder, code->at(pc));
const WasmGlobal* global = &module()->globals[operand.index];
byte* ptr = instance()->globals_start + global->offset;
WasmVal val;
WasmValue val;
switch (global->type) {
#define CASE_TYPE(wasm, ctype) \
case kWasm##wasm: \
val = WasmVal(*reinterpret_cast<ctype*>(ptr)); \
#define CASE_TYPE(wasm, ctype) \
case kWasm##wasm: \
val = WasmValue(*reinterpret_cast<ctype*>(ptr)); \
break;
WASM_CTYPES(CASE_TYPE)
#undef CASE_TYPE
......@@ -1762,7 +1762,7 @@ class ThreadImpl {
GlobalIndexOperand<false> operand(&decoder, code->at(pc));
const WasmGlobal* global = &module()->globals[operand.index];
byte* ptr = instance()->globals_start + global->offset;
WasmVal val = Pop();
WasmValue val = Pop();
switch (global->type) {
#define CASE_TYPE(wasm, ctype) \
case kWasm##wasm: \
......@@ -1827,7 +1827,7 @@ class ThreadImpl {
/* TODO(titzer): alignment for asmjs load mem? */ \
result = static_cast<ctype>(*reinterpret_cast<mtype*>(addr)); \
} \
Push(WasmVal(result)); \
Push(WasmValue(result)); \
break; \
}
ASMJS_LOAD_CASE(I32AsmjsLoadMem8S, int32_t, int8_t, 0);
......@@ -1843,7 +1843,7 @@ class ThreadImpl {
#define ASMJS_STORE_CASE(name, ctype, mtype) \
case kExpr##name: { \
WasmVal val = Pop(); \
WasmValue val = Pop(); \
uint32_t index = Pop().to<uint32_t>(); \
if (BoundsCheck<mtype>(instance()->mem_size, 0, index)) { \
byte* addr = instance()->mem_start + index; \
......@@ -1863,15 +1863,15 @@ class ThreadImpl {
case kExprGrowMemory: {
MemoryIndexOperand<false> operand(&decoder, code->at(pc));
uint32_t delta_pages = Pop().to<uint32_t>();
Push(WasmVal(ExecuteGrowMemory(
Push(WasmValue(ExecuteGrowMemory(
delta_pages, codemap_->maybe_instance(), instance())));
len = 1 + operand.length;
break;
}
case kExprMemorySize: {
MemoryIndexOperand<false> operand(&decoder, code->at(pc));
Push(WasmVal(static_cast<uint32_t>(instance()->mem_size /
WasmModule::kPageSize)));
Push(WasmValue(static_cast<uint32_t>(instance()->mem_size /
WasmModule::kPageSize)));
len = 1 + operand.length;
break;
}
......@@ -1879,37 +1879,37 @@ class ThreadImpl {
// specially to guarantee that the quiet bit of a NaN is preserved on
// ia32 by the reinterpret casts.
case kExprI32ReinterpretF32: {
WasmVal val = Pop();
Push(WasmVal(ExecuteI32ReinterpretF32(val)));
WasmValue val = Pop();
Push(WasmValue(ExecuteI32ReinterpretF32(val)));
possible_nondeterminism_ |= std::isnan(val.to<float>());
break;
}
case kExprI64ReinterpretF64: {
WasmVal val = Pop();
Push(WasmVal(ExecuteI64ReinterpretF64(val)));
WasmValue val = Pop();
Push(WasmValue(ExecuteI64ReinterpretF64(val)));
possible_nondeterminism_ |= std::isnan(val.to<double>());
break;
}
#define EXECUTE_SIMPLE_BINOP(name, ctype, op) \
case kExpr##name: { \
WasmVal rval = Pop(); \
WasmVal lval = Pop(); \
WasmVal result(lval.to<ctype>() op rval.to<ctype>()); \
Push(result); \
break; \
#define EXECUTE_SIMPLE_BINOP(name, ctype, op) \
case kExpr##name: { \
WasmValue rval = Pop(); \
WasmValue lval = Pop(); \
WasmValue result(lval.to<ctype>() op rval.to<ctype>()); \
Push(result); \
break; \
}
FOREACH_SIMPLE_BINOP(EXECUTE_SIMPLE_BINOP)
#undef EXECUTE_SIMPLE_BINOP
#define EXECUTE_OTHER_BINOP(name, ctype) \
case kExpr##name: { \
TrapReason trap = kTrapCount; \
volatile ctype rval = Pop().to<ctype>(); \
volatile ctype lval = Pop().to<ctype>(); \
WasmVal result(Execute##name(lval, rval, &trap)); \
if (trap != kTrapCount) return DoTrap(trap, pc); \
Push(result); \
break; \
#define EXECUTE_OTHER_BINOP(name, ctype) \
case kExpr##name: { \
TrapReason trap = kTrapCount; \
volatile ctype rval = Pop().to<ctype>(); \
volatile ctype lval = Pop().to<ctype>(); \
WasmValue result(Execute##name(lval, rval, &trap)); \
if (trap != kTrapCount) return DoTrap(trap, pc); \
Push(result); \
break; \
}
FOREACH_OTHER_BINOP(EXECUTE_OTHER_BINOP)
#undef EXECUTE_OTHER_BINOP
......@@ -1920,7 +1920,7 @@ class ThreadImpl {
TrapReason trap = kTrapCount;
volatile float rval = Pop().to<float>();
volatile float lval = Pop().to<float>();
WasmVal result(ExecuteF32CopySign(lval, rval, &trap));
WasmValue result(ExecuteF32CopySign(lval, rval, &trap));
Push(result);
possible_nondeterminism_ |= std::isnan(rval);
break;
......@@ -1931,7 +1931,7 @@ class ThreadImpl {
TrapReason trap = kTrapCount;
volatile double rval = Pop().to<double>();
volatile double lval = Pop().to<double>();
WasmVal result(ExecuteF64CopySign(lval, rval, &trap));
WasmValue result(ExecuteF64CopySign(lval, rval, &trap));
Push(result);
possible_nondeterminism_ |= std::isnan(rval);
break;
......@@ -1940,7 +1940,7 @@ class ThreadImpl {
case kExpr##name: { \
TrapReason trap = kTrapCount; \
volatile ctype val = Pop().to<ctype>(); \
WasmVal result(Execute##name(val, &trap)); \
WasmValue result(Execute##name(val, &trap)); \
if (trap != kTrapCount) return DoTrap(trap, pc); \
Push(result); \
break; \
......@@ -1976,7 +1976,7 @@ class ThreadImpl {
CommitPc(pc);
}
WasmVal Pop() {
WasmValue Pop() {
DCHECK_GT(frames_.size(), 0);
DCHECK_GT(StackHeight(), frames_.back().llimit()); // can't pop into locals
return *--sp_;
......@@ -1990,22 +1990,22 @@ class ThreadImpl {
sp_ -= n;
}
WasmVal PopArity(size_t arity) {
if (arity == 0) return WasmVal();
WasmValue PopArity(size_t arity) {
if (arity == 0) return WasmValue();
CHECK_EQ(1, arity);
return Pop();
}
void Push(WasmVal val) {
DCHECK_NE(kWasmStmt, val.type);
void Push(WasmValue val) {
DCHECK_NE(kWasmStmt, val.type());
DCHECK_LE(1, stack_limit_ - sp_);
*sp_++ = val;
}
void Push(WasmVal* vals, size_t arity) {
void Push(WasmValue* vals, size_t arity) {
DCHECK_LE(arity, stack_limit_ - sp_);
for (WasmVal *val = vals, *end = vals + arity; val != end; ++val) {
DCHECK_NE(kWasmStmt, val->type);
for (WasmValue *val = vals, *end = vals + arity; val != end; ++val) {
DCHECK_NE(kWasmStmt, val->type());
}
memcpy(sp_, vals, arity * sizeof(*sp_));
sp_ += arity;
......@@ -2017,7 +2017,7 @@ class ThreadImpl {
size_t requested_size =
base::bits::RoundUpToPowerOfTwo64((sp_ - stack_start_) + size);
size_t new_size = Max(size_t{8}, Max(2 * old_size, requested_size));
WasmVal* new_stack = zone_->NewArray<WasmVal>(new_size);
WasmValue* new_stack = zone_->NewArray<WasmValue>(new_size);
memcpy(new_stack, stack_start_, old_size * sizeof(*sp_));
sp_ = new_stack + (sp_ - stack_start_);
stack_start_ = new_stack;
......@@ -2040,8 +2040,8 @@ class ThreadImpl {
PrintF(" l%zu:", i);
else
PrintF(" s%zu:", i);
WasmVal val = GetStackValue(i);
switch (val.type) {
WasmValue val = GetStackValue(i);
switch (val.type()) {
case kWasmI32:
PrintF("i32:%d", val.to<int32_t>());
break;
......@@ -2111,10 +2111,10 @@ class ThreadImpl {
// Get all arguments as JS values.
std::vector<Handle<Object>> args;
args.reserve(num_args);
WasmVal* wasm_args = sp_ - num_args;
WasmValue* wasm_args = sp_ - num_args;
for (int i = 0; i < num_args; ++i) {
args.push_back(WasmValToNumber(isolate->factory(), wasm_args[i],
signature->GetParam(i)));
args.push_back(WasmValueToNumber(isolate->factory(), wasm_args[i],
signature->GetParam(i)));
}
// The receiver is the global proxy if in sloppy mode (default), undefined
......@@ -2270,13 +2270,13 @@ class InterpretedFrameImpl {
return static_cast<int>(frame_size) - GetLocalCount();
}
WasmVal GetLocalValue(int index) const {
WasmValue GetLocalValue(int index) const {
DCHECK_LE(0, index);
DCHECK_GT(GetLocalCount(), index);
return thread_->GetStackValue(static_cast<int>(frame()->sp) + index);
}
WasmVal GetStackValue(int index) const {
WasmValue GetStackValue(int index) const {
DCHECK_LE(0, index);
// Index must be within the number of stack values of this frame.
DCHECK_GT(GetStackHeight(), index);
......@@ -2356,7 +2356,7 @@ WasmInterpreter::State WasmInterpreter::Thread::state() {
return ToImpl(this)->state();
}
void WasmInterpreter::Thread::InitFrame(const WasmFunction* function,
WasmVal* args) {
WasmValue* args) {
ToImpl(this)->InitFrame(function, args);
}
WasmInterpreter::State WasmInterpreter::Thread::Run(int num_steps) {
......@@ -2380,7 +2380,7 @@ std::unique_ptr<InterpretedFrame> WasmInterpreter::Thread::GetFrame(int index) {
return std::unique_ptr<InterpretedFrame>(
ToFrame(new InterpretedFrameImpl(ToImpl(this), index)));
}
WasmVal WasmInterpreter::Thread::GetReturnValue(int index) {
WasmValue WasmInterpreter::Thread::GetReturnValue(int index) {
return ToImpl(this)->GetReturnValue(index);
}
TrapReason WasmInterpreter::Thread::GetTrapReason() {
......@@ -2497,12 +2497,12 @@ size_t WasmInterpreter::GetMemorySize() {
return internals_->instance_->mem_size;
}
WasmVal WasmInterpreter::ReadMemory(size_t offset) {
WasmValue WasmInterpreter::ReadMemory(size_t offset) {
UNIMPLEMENTED();
return WasmVal();
return WasmValue();
}
void WasmInterpreter::WriteMemory(size_t offset, WasmVal val) {
void WasmInterpreter::WriteMemory(size_t offset, WasmValue val) {
UNIMPLEMENTED();
}
......@@ -2551,10 +2551,10 @@ int InterpretedFrame::GetLocalCount() const {
int InterpretedFrame::GetStackHeight() const {
return ToImpl(this)->GetStackHeight();
}
WasmVal InterpretedFrame::GetLocalValue(int index) const {
WasmValue InterpretedFrame::GetLocalValue(int index) const {
return ToImpl(this)->GetLocalValue(index);
}
WasmVal InterpretedFrame::GetStackValue(int index) const {
WasmValue InterpretedFrame::GetStackValue(int index) const {
return ToImpl(this)->GetStackValue(index);
}
......
......@@ -6,6 +6,7 @@
#define V8_WASM_INTERPRETER_H_
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-value.h"
#include "src/zone/zone-containers.h"
namespace v8 {
......@@ -43,66 +44,6 @@ struct ControlTransferEntry {
using ControlTransferMap = ZoneMap<pc_t, ControlTransferEntry>;
// Macro for defining union members.
#define FOREACH_UNION_MEMBER(V) \
V(i32, kWasmI32, int32_t) \
V(u32, kWasmI32, uint32_t) \
V(i64, kWasmI64, int64_t) \
V(u64, kWasmI64, uint64_t) \
V(f32, kWasmF32, float) \
V(f64, kWasmF64, double)
// Representation of values within the interpreter.
struct WasmVal {
ValueType type;
union {
#define DECLARE_FIELD(field, localtype, ctype) ctype field;
FOREACH_UNION_MEMBER(DECLARE_FIELD)
#undef DECLARE_FIELD
} val;
WasmVal() : type(kWasmStmt) {}
#define DECLARE_CONSTRUCTOR(field, localtype, ctype) \
explicit WasmVal(ctype v) : type(localtype) { val.field = v; }
FOREACH_UNION_MEMBER(DECLARE_CONSTRUCTOR)
#undef DECLARE_CONSTRUCTOR
bool operator==(const WasmVal& other) const {
if (type != other.type) return false;
#define CHECK_VAL_EQ(field, localtype, ctype) \
if (type == localtype) { \
return val.field == other.val.field; \
}
FOREACH_UNION_MEMBER(CHECK_VAL_EQ)
#undef CHECK_VAL_EQ
UNREACHABLE();
}
template <typename T>
inline T to() const {
UNREACHABLE();
}
template <typename T>
inline T to_unchecked() const {
UNREACHABLE();
}
};
#define DECLARE_CASTS(field, localtype, ctype) \
template <> \
inline ctype WasmVal::to_unchecked() const { \
return val.field; \
} \
template <> \
inline ctype WasmVal::to() const { \
CHECK_EQ(localtype, type); \
return val.field; \
}
FOREACH_UNION_MEMBER(DECLARE_CASTS)
#undef DECLARE_CAST
// Representation of frames within the interpreter.
//
// Layout of a frame:
......@@ -126,8 +67,8 @@ class InterpretedFrame {
int GetParameterCount() const;
int GetLocalCount() const;
int GetStackHeight() const;
WasmVal GetLocalValue(int index) const;
WasmVal GetStackValue(int index) const;
WasmValue GetLocalValue(int index) const;
WasmValue GetStackValue(int index) const;
private:
friend class WasmInterpreter;
......@@ -182,7 +123,7 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
// Execution control.
State state();
void InitFrame(const WasmFunction* function, WasmVal* args);
void InitFrame(const WasmFunction* function, WasmValue* args);
// Pass -1 as num_steps to run till completion, pause or breakpoint.
State Run(int num_steps = -1);
State Step() { return Run(1); }
......@@ -198,7 +139,7 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
int GetFrameCount();
// The InterpretedFrame is only valid as long as the Thread is paused.
std::unique_ptr<InterpretedFrame> GetFrame(int index);
WasmVal GetReturnValue(int index = 0);
WasmValue GetReturnValue(int index = 0);
TrapReason GetTrapReason();
// Returns true if the thread executed an instruction which may produce
......@@ -259,8 +200,8 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
// Memory access.
//==========================================================================
size_t GetMemorySize();
WasmVal ReadMemory(size_t offset);
void WriteMemory(size_t offset, WasmVal val);
WasmValue ReadMemory(size_t offset);
void WriteMemory(size_t offset, WasmValue val);
// Update the memory region, e.g. after external GrowMemory.
void UpdateMemory(byte* mem_start, uint32_t mem_size);
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_WASM_VALUE_H_
#define V8_WASM_VALUE_H_
#include "src/wasm/wasm-opcodes.h"
#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
namespace wasm {
// Macro for defining WasmValue union members.
#define FOREACH_WASMVAL_UNION_MEMBER(V) \
V(i32, kWasmI32, int32_t) \
V(u32, kWasmI32, uint32_t) \
V(i64, kWasmI64, int64_t) \
V(u64, kWasmI64, uint64_t) \
V(f32, kWasmF32, float) \
V(f64, kWasmF64, double)
// A wasm value with type information.
class WasmValue {
public:
WasmValue() : type_(kWasmStmt) {}
#define DEFINE_TYPE_SPECIFIC_METHODS(field, localtype, ctype) \
explicit WasmValue(ctype v) : type_(localtype) { value_.field = v; } \
ctype to_##field() const { \
DCHECK_EQ(localtype, type_); \
return value_.field; \
}
FOREACH_WASMVAL_UNION_MEMBER(DEFINE_TYPE_SPECIFIC_METHODS)
#undef DEFINE_TYPE_SPECIFIC_METHODS
ValueType type() const { return type_; }
bool operator==(const WasmValue& other) const {
if (type_ != other.type_) return false;
#define CHECK_VALUE_EQ(field, localtype, ctype) \
if (type_ == localtype) { \
return value_.field == other.value_.field; \
}
FOREACH_WASMVAL_UNION_MEMBER(CHECK_VALUE_EQ)
#undef CHECK_VALUE_EQ
UNREACHABLE();
}
template <typename T>
inline T to() const {
static_assert(sizeof(T) == -1, "Do only use this method with valid types");
}
template <typename T>
inline T to_unchecked() const {
static_assert(sizeof(T) == -1, "Do only use this method with valid types");
}
private:
ValueType type_;
union {
#define DECLARE_FIELD(field, localtype, ctype) ctype field;
FOREACH_WASMVAL_UNION_MEMBER(DECLARE_FIELD)
#undef DECLARE_FIELD
} value_;
};
#define DECLARE_CAST(field, localtype, ctype) \
template <> \
inline ctype WasmValue::to_unchecked() const { \
return value_.field; \
} \
template <> \
inline ctype WasmValue::to() const { \
return to_##field(); \
}
FOREACH_WASMVAL_UNION_MEMBER(DECLARE_CAST)
#undef DECLARE_CAST
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_VALUE_H_
......@@ -196,7 +196,7 @@ TEST(Breakpoint_I32Add) {
FOR_UINT32_INPUTS(a) {
for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) {
thread->Reset();
WasmVal args[] = {WasmVal(*a), WasmVal(b)};
WasmValue args[] = {WasmValue(*a), WasmValue(b)};
thread->InitFrame(r.function(), args);
for (int i = 0; i < kNumBreakpoints; i++) {
......@@ -231,7 +231,7 @@ TEST(Step_I32Mul) {
FOR_UINT32_INPUTS(a) {
for (uint32_t b = 33; b < 3000000000u; b += 1000000000u) {
thread->Reset();
WasmVal args[] = {WasmVal(*a), WasmVal(b)};
WasmValue args[] = {WasmValue(*a), WasmValue(b)};
thread->InitFrame(r.function(), args);
// Run instructions one by one.
......@@ -273,7 +273,7 @@ TEST(Breakpoint_I32And_disable) {
interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[0],
do_break);
thread->Reset();
WasmVal args[] = {WasmVal(*a), WasmVal(b)};
WasmValue args[] = {WasmValue(*a), WasmValue(b)};
thread->InitFrame(r.function(), args);
if (do_break) {
......
......@@ -160,7 +160,7 @@ void SetBreakpoint(WasmRunnerBase& runner, int function_index, int byte_offset,
// Wrapper with operator<<.
struct WasmValWrapper {
WasmVal val;
WasmValue val;
bool operator==(const WasmValWrapper& other) const {
return val == other.val;
......@@ -170,7 +170,7 @@ struct WasmValWrapper {
// Only needed in debug builds. Avoid unused warning otherwise.
#ifdef DEBUG
std::ostream& operator<<(std::ostream& out, const WasmValWrapper& wrapper) {
switch (wrapper.val.type) {
switch (wrapper.val.type()) {
case kWasmI32:
out << "i32: " << wrapper.val.to<int32_t>();
break;
......@@ -193,8 +193,8 @@ std::ostream& operator<<(std::ostream& out, const WasmValWrapper& wrapper) {
class CollectValuesBreakHandler : public debug::DebugDelegate {
public:
struct BreakpointValues {
std::vector<WasmVal> locals;
std::vector<WasmVal> stack;
std::vector<WasmValue> locals;
std::vector<WasmValue> stack;
};
explicit CollectValuesBreakHandler(
......@@ -244,21 +244,21 @@ class CollectValuesBreakHandler : public debug::DebugDelegate {
}
};
// Special template to explicitly cast to WasmVal.
// Special template to explicitly cast to WasmValue.
template <typename Arg>
WasmVal MakeWasmVal(Arg arg) {
return WasmVal(arg);
WasmValue MakeWasmVal(Arg arg) {
return WasmValue(arg);
}
// Translate long to i64 (ambiguous otherwise).
template <>
WasmVal MakeWasmVal(long arg) { // NOLINT: allow long parameter
return WasmVal(static_cast<int64_t>(arg));
WasmValue MakeWasmVal(long arg) { // NOLINT: allow long parameter
return WasmValue(static_cast<int64_t>(arg));
}
template <typename... Args>
std::vector<WasmVal> wasmVec(Args... args) {
std::array<WasmVal, sizeof...(args)> arr{{MakeWasmVal(args)...}};
return std::vector<WasmVal>{arr.begin(), arr.end()};
std::vector<WasmValue> wasmVec(Args... args) {
std::array<WasmValue, sizeof...(args)> arr{{MakeWasmVal(args)...}};
return std::vector<WasmValue>{arr.begin(), arr.end()};
}
} // namespace
......
......@@ -797,12 +797,12 @@ class WasmRunner : public WasmRunnerBase {
ReturnType CallInterpreter(ParamTypes... p) {
WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
thread->Reset();
std::array<WasmVal, sizeof...(p)> args{{WasmVal(p)...}};
std::array<WasmValue, sizeof...(p)> args{{WasmValue(p)...}};
thread->InitFrame(function(), args.data());
WasmInterpreter::HeapObjectsScope heap_objects_scope(
interpreter(), module().instance_object());
if (thread->Run() == WasmInterpreter::FINISHED) {
WasmVal val = thread->GetReturnValue();
WasmValue val = thread->GetReturnValue();
possible_nondeterminism_ |= thread->PossibleNondeterminism();
return val.to<ReturnType>();
} else if (thread->state() == WasmInterpreter::TRAPPED) {
......
......@@ -84,7 +84,7 @@ int32_t CompileAndRunAsmWasmModule(Isolate* isolate, const byte* module_start,
int32_t InterpretWasmModule(Isolate* isolate,
Handle<WasmInstanceObject> instance,
ErrorThrower* thrower, int32_t function_index,
WasmVal* args, bool* possible_nondeterminism) {
WasmValue* args, bool* possible_nondeterminism) {
// Don't execute more than 16k steps.
constexpr int kMaxNumSteps = 16 * 1024;
......@@ -101,7 +101,7 @@ int32_t InterpretWasmModule(Isolate* isolate,
*possible_nondeterminism = thread->PossibleNondeterminism();
if (interpreter_result == WasmInterpreter::FINISHED) {
WasmVal val = thread->GetReturnValue();
WasmValue val = thread->GetReturnValue();
return val.to<int32_t>();
} else if (thread->state() == WasmInterpreter::TRAPPED) {
return 0xdeadbeef;
......
......@@ -45,7 +45,7 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
int32_t InterpretWasmModule(Isolate* isolate,
Handle<WasmInstanceObject> instance,
ErrorThrower* thrower, int32_t function_index,
WasmVal* args, bool* possible_nondeterminism);
WasmValue* args, bool* possible_nondeterminism);
// Runs the module instance with arguments.
int32_t RunWasmModuleForTesting(Isolate* isolate, Handle<JSObject> instance,
......
......@@ -39,27 +39,28 @@ class WasmCallFuzzer : public WasmExecutionFuzzer {
}
static void add_argument(
v8::internal::Isolate* isolate, ValueType type, WasmVal* interpreter_args,
v8::internal::Isolate* isolate, ValueType type,
WasmValue* interpreter_args,
v8::internal::Handle<v8::internal::Object>* compiler_args, int* argc,
const uint8_t** data, size_t* size, bool* ok) {
if (!(*ok)) return;
switch (type) {
case kWasmF32: {
float value = read_value<float>(data, size, ok);
interpreter_args[*argc] = WasmVal(value);
interpreter_args[*argc] = WasmValue(value);
compiler_args[*argc] =
isolate->factory()->NewNumber(static_cast<double>(value));
break;
}
case kWasmF64: {
double value = read_value<double>(data, size, ok);
interpreter_args[*argc] = WasmVal(value);
interpreter_args[*argc] = WasmValue(value);
compiler_args[*argc] = isolate->factory()->NewNumber(value);
break;
}
case kWasmI32: {
int32_t value = read_value<int32_t>(data, size, ok);
interpreter_args[*argc] = WasmVal(value);
interpreter_args[*argc] = WasmValue(value);
compiler_args[*argc] =
isolate->factory()->NewNumber(static_cast<double>(value));
break;
......@@ -73,7 +74,7 @@ class WasmCallFuzzer : public WasmExecutionFuzzer {
virtual bool GenerateModule(
Isolate* isolate, Zone* zone, const uint8_t* data, size_t size,
ZoneBuffer& buffer, int32_t& num_args,
std::unique_ptr<WasmVal[]>& interpreter_args,
std::unique_ptr<WasmValue[]>& interpreter_args,
std::unique_ptr<Handle<Object>[]>& compiler_args) override {
bool ok = true;
uint8_t num_functions =
......@@ -81,7 +82,7 @@ class WasmCallFuzzer : public WasmExecutionFuzzer {
ValueType types[] = {kWasmF32, kWasmF64, kWasmI32, kWasmI64};
interpreter_args.reset(new WasmVal[3]);
interpreter_args.reset(new WasmValue[3]);
compiler_args.reset(new Handle<Object>[3]);
WasmModuleBuilder builder(zone);
......
......@@ -21,7 +21,7 @@ class WasmCodeFuzzer : public WasmExecutionFuzzer {
virtual bool GenerateModule(
Isolate* isolate, Zone* zone, const uint8_t* data, size_t size,
ZoneBuffer& buffer, int32_t& num_args,
std::unique_ptr<WasmVal[]>& interpreter_args,
std::unique_ptr<WasmValue[]>& interpreter_args,
std::unique_ptr<Handle<Object>[]>& compiler_args) override {
TestSignatures sigs;
WasmModuleBuilder builder(zone);
......@@ -33,7 +33,8 @@ class WasmCodeFuzzer : public WasmExecutionFuzzer {
builder.WriteTo(buffer);
num_args = 3;
interpreter_args.reset(new WasmVal[3]{WasmVal(1), WasmVal(2), WasmVal(3)});
interpreter_args.reset(
new WasmValue[3]{WasmValue(1), WasmValue(2), WasmValue(3)});
compiler_args.reset(new Handle<Object>[3]{
handle(Smi::FromInt(1), isolate), handle(Smi::FromInt(2), isolate),
......
......@@ -302,7 +302,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
virtual bool GenerateModule(
Isolate* isolate, Zone* zone, const uint8_t* data, size_t size,
ZoneBuffer& buffer, int32_t& num_args,
std::unique_ptr<WasmVal[]>& interpreter_args,
std::unique_ptr<WasmValue[]>& interpreter_args,
std::unique_ptr<Handle<Object>[]>& compiler_args) override {
TestSignatures sigs;
......@@ -321,7 +321,8 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
builder.WriteTo(buffer);
num_args = 3;
interpreter_args.reset(new WasmVal[3]{WasmVal(1), WasmVal(2), WasmVal(3)});
interpreter_args.reset(
new WasmValue[3]{WasmValue(1), WasmValue(2), WasmValue(3)});
compiler_args.reset(new Handle<Object>[3]{
handle(Smi::FromInt(1), isolate), handle(Smi::FromInt(1), isolate),
......
......@@ -111,7 +111,7 @@ int WasmExecutionFuzzer::FuzzWasmModule(
ZoneBuffer buffer(&zone);
int32_t num_args = 0;
std::unique_ptr<WasmVal[]> interpreter_args;
std::unique_ptr<WasmValue[]> interpreter_args;
std::unique_ptr<Handle<Object>[]> compiler_args;
if (!GenerateModule(i_isolate, &zone, data, size, buffer, num_args,
interpreter_args, compiler_args)) {
......
......@@ -29,7 +29,7 @@ class WasmExecutionFuzzer {
virtual bool GenerateModule(
Isolate* isolate, Zone* zone, const uint8_t* data, size_t size,
ZoneBuffer& buffer, int32_t& num_args,
std::unique_ptr<WasmVal[]>& interpreter_args,
std::unique_ptr<WasmValue[]>& interpreter_args,
std::unique_ptr<Handle<Object>[]>& compiler_args) = 0;
};
......
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