[wasm] Move {GetGlobalValue} out of the interpreter

This will allow us to reuse this method in other contexts.
This CL also contains smaller refactorings that helped to move the
code. E.g. the WASMVALUE_CTYPES macro (defined in value-type.h)
replaces the WASM_CTYPES macro (from wasm-interpreter.cc).

R=mstarzinger@chromium.org

Bug: v8:9676
Change-Id: Id788f843af9a09eb940593afa1639f12b652c514
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1876054
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64534}
This commit is contained in:
Clemens Backes 2019-10-24 10:30:59 +02:00 committed by Commit Bot
parent 5bba668004
commit 334dd91987
7 changed files with 57 additions and 69 deletions

View File

@ -16,6 +16,9 @@ class Signature;
namespace wasm { namespace wasm {
// Type for holding simd values, defined in wasm-value.h.
class Simd128;
// Type lattice: For any two types connected by a line, the type at the bottom // Type lattice: For any two types connected by a line, the type at the bottom
// is a subtype of the other type. // is a subtype of the other type.
// //
@ -40,6 +43,13 @@ enum ValueType : uint8_t {
kWasmBottom, kWasmBottom,
}; };
#define FOREACH_WASMVALUE_CTYPES(V) \
V(kWasmI32, int32_t) \
V(kWasmI64, int64_t) \
V(kWasmF32, float) \
V(kWasmF64, double) \
V(kWasmS128, Simd128)
using FunctionSig = Signature<ValueType>; using FunctionSig = Signature<ValueType>;
inline size_t hash_value(ValueType type) { return static_cast<size_t>(type); } inline size_t hash_value(ValueType type) { return static_cast<size_t>(type); }

View File

@ -380,11 +380,8 @@ class InterpreterHandle {
.Assert(); .Assert();
} }
DCHECK_EQ(1, interpreter()->GetThreadCount()); auto& globals = module()->globals;
WasmInterpreter::Thread* thread = interpreter()->GetThread(0); if (!globals.empty()) {
uint32_t global_count = thread->GetGlobalCount();
if (global_count > 0) {
Handle<JSObject> globals_obj = Handle<JSObject> globals_obj =
isolate_->factory()->NewJSObjectWithNullProto(); isolate_->factory()->NewJSObjectWithNullProto();
Handle<String> globals_name = Handle<String> globals_name =
@ -393,10 +390,11 @@ class InterpreterHandle {
globals_name, globals_obj, NONE) globals_name, globals_obj, NONE)
.Assert(); .Assert();
for (uint32_t i = 0; i < global_count; ++i) { for (uint32_t i = 0; i < globals.size(); ++i) {
const char* label = "global#%d"; const char* label = "global#%d";
Handle<String> name = PrintFToOneByteString<true>(isolate_, label, i); Handle<String> name = PrintFToOneByteString<true>(isolate_, label, i);
WasmValue value = thread->GetGlobalValue(i); WasmValue value =
WasmInstanceObject::GetGlobalValue(instance, globals[i]);
Handle<Object> value_obj = WasmValueToValueObject(isolate_, value); Handle<Object> value_obj = WasmValueToValueObject(isolate_, value);
JSObject::SetOwnPropertyIgnoreAttributes(globals_obj, name, value_obj, JSObject::SetOwnPropertyIgnoreAttributes(globals_obj, name, value_obj,
NONE) NONE)

View File

@ -51,9 +51,6 @@ using base::WriteUnalignedValue;
#define FOREACH_INTERNAL_OPCODE(V) V(Breakpoint, 0xFF) #define FOREACH_INTERNAL_OPCODE(V) V(Breakpoint, 0xFF)
#define WASM_CTYPES(V) \
V(I32, int32_t) V(I64, int64_t) V(F32, float) V(F64, double) V(S128, Simd128)
#define FOREACH_SIMPLE_BINOP(V) \ #define FOREACH_SIMPLE_BINOP(V) \
V(I32Add, uint32_t, +) \ V(I32Add, uint32_t, +) \
V(I32Sub, uint32_t, -) \ V(I32Sub, uint32_t, -) \
@ -1295,40 +1292,6 @@ class ThreadImpl {
return WasmInterpreter::Thread::HANDLED; return WasmInterpreter::Thread::HANDLED;
} }
uint32_t GetGlobalCount() {
return static_cast<uint32_t>(module()->globals.size());
}
WasmValue GetGlobalValue(uint32_t index) {
auto& global = module()->globals[index];
switch (global.type) {
#define CASE_TYPE(wasm, ctype) \
case kWasm##wasm: { \
byte* ptr = \
WasmInstanceObject::GetGlobalStorage(instance_object_, global); \
return WasmValue( \
ReadLittleEndianValue<ctype>(reinterpret_cast<Address>(ptr))); \
break; \
}
WASM_CTYPES(CASE_TYPE)
#undef CASE_TYPE
case kWasmAnyRef:
case kWasmFuncRef:
case kWasmExnRef: {
HandleScope handle_scope(isolate_); // Avoid leaking handles.
Handle<FixedArray> global_buffer; // The buffer of the global.
uint32_t global_index; // The index into the buffer.
std::tie(global_buffer, global_index) =
WasmInstanceObject::GetGlobalBufferAndIndex(instance_object_,
global);
Handle<Object> value(global_buffer->get(global_index), isolate_);
return WasmValue(handle_scope.CloseAndEscape(value));
}
default:
UNREACHABLE();
}
}
private: private:
// Handle a thrown exception. Returns whether the exception was handled inside // Handle a thrown exception. Returns whether the exception was handled inside
// the current activation. Unwinds the interpreted stack accordingly. // the current activation. Unwinds the interpreted stack accordingly.
@ -1490,11 +1453,11 @@ class ThreadImpl {
for (auto p : code->locals.type_list) { for (auto p : code->locals.type_list) {
WasmValue val; WasmValue val;
switch (p) { switch (p) {
#define CASE_TYPE(wasm, ctype) \ #define CASE_TYPE(valuetype, ctype) \
case kWasm##wasm: \ case valuetype: \
val = WasmValue(ctype{}); \ val = WasmValue(ctype{}); \
break; break;
WASM_CTYPES(CASE_TYPE) FOREACH_WASMVALUE_CTYPES(CASE_TYPE)
#undef CASE_TYPE #undef CASE_TYPE
case kWasmAnyRef: case kWasmAnyRef:
case kWasmFuncRef: case kWasmFuncRef:
@ -3311,7 +3274,8 @@ class ThreadImpl {
GlobalIndexImmediate<Decoder::kNoValidate> imm(&decoder, GlobalIndexImmediate<Decoder::kNoValidate> imm(&decoder,
code->at(pc)); code->at(pc));
HandleScope handle_scope(isolate_); HandleScope handle_scope(isolate_);
Push(GetGlobalValue(imm.index)); Push(WasmInstanceObject::GetGlobalValue(
instance_object_, module()->globals[imm.index]));
len = 1 + imm.length; len = 1 + imm.length;
break; break;
} }
@ -3320,15 +3284,15 @@ class ThreadImpl {
code->at(pc)); code->at(pc));
auto& global = module()->globals[imm.index]; auto& global = module()->globals[imm.index];
switch (global.type) { switch (global.type) {
#define CASE_TYPE(wasm, ctype) \ #define CASE_TYPE(valuetype, ctype) \
case kWasm##wasm: { \ case valuetype: { \
byte* ptr = \ uint8_t* ptr = \
WasmInstanceObject::GetGlobalStorage(instance_object_, global); \ WasmInstanceObject::GetGlobalStorage(instance_object_, global); \
WriteLittleEndianValue<ctype>(reinterpret_cast<Address>(ptr), \ WriteLittleEndianValue<ctype>(reinterpret_cast<Address>(ptr), \
Pop().to<ctype>()); \ Pop().to<ctype>()); \
break; \ break; \
} }
WASM_CTYPES(CASE_TYPE) FOREACH_WASMVALUE_CTYPES(CASE_TYPE)
#undef CASE_TYPE #undef CASE_TYPE
case kWasmAnyRef: case kWasmAnyRef:
case kWasmFuncRef: case kWasmFuncRef:
@ -4069,12 +4033,6 @@ WasmValue WasmInterpreter::Thread::GetReturnValue(int index) {
TrapReason WasmInterpreter::Thread::GetTrapReason() { TrapReason WasmInterpreter::Thread::GetTrapReason() {
return ToImpl(this)->GetTrapReason(); return ToImpl(this)->GetTrapReason();
} }
uint32_t WasmInterpreter::Thread::GetGlobalCount() {
return ToImpl(this)->GetGlobalCount();
}
WasmValue WasmInterpreter::Thread::GetGlobalValue(uint32_t index) {
return ToImpl(this)->GetGlobalValue(index);
}
bool WasmInterpreter::Thread::PossibleNondeterminism() { bool WasmInterpreter::Thread::PossibleNondeterminism() {
return ToImpl(this)->PossibleNondeterminism(); return ToImpl(this)->PossibleNondeterminism();
} }
@ -4259,7 +4217,6 @@ void InterpretedFrameDeleter::operator()(InterpretedFrame* ptr) {
#undef TRACE #undef TRACE
#undef LANE #undef LANE
#undef FOREACH_INTERNAL_OPCODE #undef FOREACH_INTERNAL_OPCODE
#undef WASM_CTYPES
#undef FOREACH_SIMPLE_BINOP #undef FOREACH_SIMPLE_BINOP
#undef FOREACH_OTHER_BINOP #undef FOREACH_OTHER_BINOP
#undef FOREACH_I32CONV_FLOATOP #undef FOREACH_I32CONV_FLOATOP

View File

@ -139,9 +139,6 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
WasmValue GetReturnValue(int index = 0); WasmValue GetReturnValue(int index = 0);
TrapReason GetTrapReason(); TrapReason GetTrapReason();
uint32_t GetGlobalCount();
WasmValue GetGlobalValue(uint32_t index);
// Returns true if the thread executed an instruction which may produce // Returns true if the thread executed an instruction which may produce
// nondeterministic results, e.g. float div, float sqrt, and float mul, // nondeterministic results, e.g. float div, float sqrt, and float mul,
// where the sign bit of a NaN is nondeterministic. // where the sign bit of a NaN is nondeterministic.

View File

@ -27,6 +27,7 @@
#include "src/wasm/wasm-limits.h" #include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-module.h" #include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h" #include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-value.h"
#define TRACE_IFT(...) \ #define TRACE_IFT(...) \
do { \ do { \
@ -1626,6 +1627,30 @@ WasmInstanceObject::GetGlobalBufferAndIndex(Handle<WasmInstanceObject> instance,
return {handle(instance->tagged_globals_buffer(), isolate), global.offset}; return {handle(instance->tagged_globals_buffer(), isolate), global.offset};
} }
// static
wasm::WasmValue WasmInstanceObject::GetGlobalValue(
Handle<WasmInstanceObject> instance, const wasm::WasmGlobal& global) {
Isolate* isolate = instance->GetIsolate();
if (wasm::ValueTypes::IsReferenceType(global.type)) {
Handle<FixedArray> global_buffer; // The buffer of the global.
uint32_t global_index = 0; // The index into the buffer.
std::tie(global_buffer, global_index) =
GetGlobalBufferAndIndex(instance, global);
return wasm::WasmValue(handle(global_buffer->get(global_index), isolate));
}
Address ptr = reinterpret_cast<Address>(GetGlobalStorage(instance, global));
using wasm::Simd128;
switch (global.type) {
#define CASE_TYPE(valuetype, ctype) \
case wasm::valuetype: \
return wasm::WasmValue(base::ReadLittleEndianValue<ctype>(ptr));
FOREACH_WASMVALUE_CTYPES(CASE_TYPE)
#undef CASE_TYPE
default:
UNREACHABLE();
}
}
// static // static
Handle<WasmExceptionObject> WasmExceptionObject::New( Handle<WasmExceptionObject> WasmExceptionObject::New(
Isolate* isolate, const wasm::FunctionSig* sig, Isolate* isolate, const wasm::FunctionSig* sig,

View File

@ -569,6 +569,10 @@ class WasmInstanceObject : public JSObject {
static std::pair<Handle<FixedArray>, uint32_t> GetGlobalBufferAndIndex( static std::pair<Handle<FixedArray>, uint32_t> GetGlobalBufferAndIndex(
Handle<WasmInstanceObject>, const wasm::WasmGlobal&); Handle<WasmInstanceObject>, const wasm::WasmGlobal&);
// Get the value of a global in the given instance.
static wasm::WasmValue GetGlobalValue(Handle<WasmInstanceObject>,
const wasm::WasmGlobal&);
OBJECT_CONSTRUCTORS(WasmInstanceObject, JSObject); OBJECT_CONSTRUCTORS(WasmInstanceObject, JSObject);
private: private:

View File

@ -32,11 +32,8 @@ FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE)
class Simd128 { class Simd128 {
public: public:
Simd128() : val_() { Simd128() = default;
for (size_t i = 0; i < 16; i++) {
val_[i] = 0;
}
}
#define DEFINE_SIMD_TYPE_SPECIFIC_METHODS(cType, sType, name, size) \ #define DEFINE_SIMD_TYPE_SPECIFIC_METHODS(cType, sType, name, size) \
explicit Simd128(sType val) { \ explicit Simd128(sType val) { \
base::WriteUnalignedValue<sType>(reinterpret_cast<Address>(val_), val); \ base::WriteUnalignedValue<sType>(reinterpret_cast<Address>(val_), val); \
@ -48,7 +45,7 @@ class Simd128 {
#undef DEFINE_SIMD_TYPE_SPECIFIC_METHODS #undef DEFINE_SIMD_TYPE_SPECIFIC_METHODS
private: private:
uint8_t val_[16]; uint8_t val_[16] = {0};
}; };
// Macro for defining WasmValue methods for different types. // Macro for defining WasmValue methods for different types.