Commit 3cef77bc authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[wasm-gc] Add ref,optref,eqref value types

And a new flag --experimental-wasm-gc, which doesn't do anything yet.

Bug: v8:7748
Change-Id: I927d1d90559249db3ee9f8d240775d45098e52a6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2154197
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67215}
parent d111a291
......@@ -2061,6 +2061,9 @@ Node* WasmGraphBuilder::Throw(uint32_t exception_index,
case wasm::ValueType::kFuncRef:
case wasm::ValueType::kNullRef:
case wasm::ValueType::kExnRef:
case wasm::ValueType::kRef:
case wasm::ValueType::kOptRef:
case wasm::ValueType::kEqRef:
STORE_FIXED_ARRAY_SLOT_ANY(values_array, index, value);
++index;
break;
......@@ -2202,6 +2205,9 @@ Node* WasmGraphBuilder::GetExceptionValues(Node* except_obj,
case wasm::ValueType::kFuncRef:
case wasm::ValueType::kNullRef:
case wasm::ValueType::kExnRef:
case wasm::ValueType::kRef:
case wasm::ValueType::kOptRef:
case wasm::ValueType::kEqRef:
value = LOAD_FIXED_ARRAY_SLOT_ANY(values_array, index);
++index;
break;
......@@ -5332,6 +5338,11 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
case wasm::ValueType::kNullRef:
case wasm::ValueType::kExnRef:
return node;
case wasm::ValueType::kRef:
case wasm::ValueType::kOptRef:
case wasm::ValueType::kEqRef:
// TODO(7748): Implement
UNIMPLEMENTED();
case wasm::ValueType::kStmt:
case wasm::ValueType::kBottom:
UNREACHABLE();
......
......@@ -17,6 +17,7 @@
#include "src/runtime/runtime-utils.h"
#include "src/trap-handler/trap-handler.h"
#include "src/wasm/module-compiler.h"
#include "src/wasm/value-type.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-constants.h"
#include "src/wasm/wasm-debug.h"
......@@ -253,7 +254,10 @@ RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
case wasm::ValueType::kAnyRef:
case wasm::ValueType::kFuncRef:
case wasm::ValueType::kNullRef:
case wasm::ValueType::kExnRef: {
case wasm::ValueType::kExnRef:
case wasm::ValueType::kRef:
case wasm::ValueType::kOptRef:
case wasm::ValueType::kEqRef: {
DCHECK_EQ(sig->GetParam(i).element_size_bytes(), kSystemPointerSize);
Handle<Object> ref(
Object(base::ReadUnalignedValue<Address>(arg_buf_ptr)), isolate);
......
......@@ -988,7 +988,7 @@ class LiftoffAssembler : public TurboAssembler {
ValueType local_types_[kInlineLocalTypes];
ValueType* more_local_types_;
};
static_assert(sizeof(ValueType) == 1,
static_assert(sizeof(ValueType) == 4,
"Reconsider this inlining if ValueType gets bigger");
CacheState cache_state_;
int max_used_spill_offset_ = StaticStackFrameSize();
......
......@@ -1711,6 +1711,22 @@ class ModuleDecoderImpl : public Decoder {
case kLocalExnRef:
if (enabled_features_.has_eh()) return kWasmExnRef;
break;
case kLocalRef:
if (enabled_features_.has_gc()) return ValueType(ValueType::kRef);
break;
case kLocalOptRef:
if (enabled_features_.has_gc()) {
return ValueType(ValueType::kOptRef);
}
break;
case kLocalEqRef:
if (enabled_features_.has_gc()) {
return ValueType(ValueType::kEqRef);
}
break;
case kLocalI31Ref:
case kLocalRttRef:
UNIMPLEMENTED(); // TODO(7748): Add i31ref and rttref.
default:
break;
}
......
......@@ -751,7 +751,10 @@ void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global,
case ValueType::kAnyRef:
case ValueType::kFuncRef:
case ValueType::kNullRef:
case ValueType::kExnRef: {
case ValueType::kExnRef:
case ValueType::kRef:
case ValueType::kOptRef:
case ValueType::kEqRef: {
DCHECK_IMPLIES(global.type == kWasmNullRef, value->GetRef()->IsNull());
tagged_globals_->set(global.offset, *value->GetRef());
break;
......
......@@ -5,6 +5,7 @@
#ifndef V8_WASM_VALUE_TYPE_H_
#define V8_WASM_VALUE_TYPE_H_
#include "src/base/bit-field.h"
#include "src/codegen/machine-type.h"
#include "src/wasm/wasm-constants.h"
......@@ -30,6 +31,10 @@ class Simd128;
// \ \ \ \ /
// ------------ Bottom
// Format: kind, log2Size, code, machineType, shortName, typeName
//
// Some of these types are from proposals that are not standardized yet:
// - "ref" types per https://github.com/WebAssembly/function-references
// - "optref"/"eqref" per https://github.com/WebAssembly/gc
#define FOREACH_VALUE_TYPE(V) \
V(Stmt, -1, Void, None, 'v', "<stmt>") \
V(I32, 2, I32, Int32, 'i', "i32") \
......@@ -41,6 +46,9 @@ class Simd128;
V(FuncRef, kSystemPointerSizeLog2, FuncRef, TaggedPointer, 'a', "funcref") \
V(NullRef, kSystemPointerSizeLog2, NullRef, TaggedPointer, 'n', "nullref") \
V(ExnRef, kSystemPointerSizeLog2, ExnRef, TaggedPointer, 'e', "exn") \
V(Ref, kSystemPointerSizeLog2, Ref, TaggedPointer, '*', "ref") \
V(OptRef, kSystemPointerSizeLog2, OptRef, TaggedPointer, 'o', "optref") \
V(EqRef, kSystemPointerSizeLog2, EqRef, TaggedPointer, 'q', "eqref") \
V(Bottom, -1, Void, None, '*', "<bot>")
class ValueType {
......@@ -51,15 +59,28 @@ class ValueType {
#undef DEF_ENUM
};
constexpr ValueType() : kind_(kStmt) {}
explicit constexpr ValueType(Kind kind) : kind_(kind) {}
constexpr ValueType() : bit_field_(KindField::encode(kStmt)) {}
explicit constexpr ValueType(Kind kind)
: bit_field_(KindField::encode(kind)) {
DCHECK(kind != kRef && kind != kOptRef);
}
constexpr ValueType(Kind kind, uint32_t ref_index)
: bit_field_(KindField::encode(kind) | RefIndexField::encode(ref_index)) {
DCHECK(kind == kRef || kind == kOptRef);
}
constexpr Kind kind() const { return kind_; }
constexpr Kind kind() const { return KindField::decode(bit_field_); }
constexpr uint32_t ref_index() const {
#if V8_HAS_CXX14_CONSTEXPR
DCHECK(kind() == kRef || kind() == kOptRef);
#endif
return RefIndexField::decode(bit_field_);
}
constexpr int element_size_log2() const {
#if V8_HAS_CXX14_CONSTEXPR
DCHECK_NE(kStmt, kind_);
DCHECK_NE(kBottom, kind_);
DCHECK_NE(kStmt, kind());
DCHECK_NE(kBottom, kind());
#endif
constexpr int kElementSizeLog2[] = {
......@@ -68,29 +89,31 @@ class ValueType {
#undef ELEM_SIZE_LOG2
};
return kElementSizeLog2[kind_];
return kElementSizeLog2[kind()];
}
constexpr int element_size_bytes() const { return 1 << element_size_log2(); }
constexpr bool operator==(ValueType other) const {
return kind_ == other.kind_;
return bit_field_ == other.bit_field_;
}
constexpr bool operator!=(ValueType other) const {
return kind_ != other.kind_;
return bit_field_ != other.bit_field_;
}
bool IsSubTypeOf(ValueType other) const {
return (*this == other) || (kind_ == kNullRef && other.kind_ == kAnyRef) ||
(kind_ == kFuncRef && other.kind_ == kAnyRef) ||
(kind_ == kExnRef && other.kind_ == kAnyRef) ||
(kind_ == kNullRef && other.kind_ == kFuncRef) ||
(kind_ == kNullRef && other.kind_ == kExnRef);
return (*this == other) ||
(kind() == kNullRef && other.kind() == kAnyRef) ||
(kind() == kFuncRef && other.kind() == kAnyRef) ||
(kind() == kExnRef && other.kind() == kAnyRef) ||
(kind() == kNullRef && other.kind() == kFuncRef) ||
(kind() == kNullRef && other.kind() == kExnRef);
}
bool IsReferenceType() const {
return kind_ == kAnyRef || kind_ == kFuncRef || kind_ == kNullRef ||
kind_ == kExnRef;
return kind() == kAnyRef || kind() == kFuncRef || kind() == kNullRef ||
kind() == kExnRef || kind() == kRef || kind() == kOptRef ||
kind() == kEqRef;
}
static ValueType CommonSubType(ValueType a, ValueType b) {
......@@ -107,7 +130,7 @@ class ValueType {
}
ValueTypeCode value_type_code() const {
DCHECK_NE(kBottom, kind_);
DCHECK_NE(kBottom, kind());
constexpr ValueTypeCode kValueTypeCode[] = {
#define TYPE_CODE(kind, log2Size, code, ...) kLocal##code,
......@@ -115,11 +138,11 @@ class ValueType {
#undef TYPE_CODE
};
return kValueTypeCode[kind_];
return kValueTypeCode[kind()];
}
MachineType machine_type() const {
DCHECK_NE(kBottom, kind_);
DCHECK_NE(kBottom, kind());
constexpr MachineType kMachineType[] = {
#define MACH_TYPE(kind, log2Size, code, machineType, ...) \
......@@ -128,7 +151,7 @@ class ValueType {
#undef MACH_TYPE
};
return kMachineType[kind_];
return kMachineType[kind()];
}
MachineRepresentation machine_representation() {
......@@ -163,7 +186,7 @@ class ValueType {
#undef SHORT_NAME
};
return kShortName[kind_];
return kShortName[kind()];
}
constexpr const char* type_name() const {
......@@ -174,13 +197,14 @@ class ValueType {
#undef TYPE_NAME
};
return kTypeName[kind_];
return kTypeName[kind()];
}
private:
Kind kind_ : 8;
// TODO(jkummerow): Add and use the following for reference types:
// uint32_t ref_index_ : 24;
using KindField = base::BitField<Kind, 0, 8>;
using RefIndexField = base::BitField<uint32_t, 8, 24>;
uint32_t bit_field_;
};
static_assert(sizeof(ValueType) <= kUInt32Size,
......@@ -200,8 +224,7 @@ constexpr ValueType kWasmI64 = ValueType(ValueType::kI64);
constexpr ValueType kWasmF32 = ValueType(ValueType::kF32);
constexpr ValueType kWasmF64 = ValueType(ValueType::kF64);
constexpr ValueType kWasmAnyRef = ValueType(ValueType::kAnyRef);
// TODO(jkummerow): introduce ValueType::kEqRef
constexpr ValueType kWasmEqRef = ValueType(ValueType::kAnyRef);
constexpr ValueType kWasmEqRef = ValueType(ValueType::kEqRef);
constexpr ValueType kWasmExnRef = ValueType(ValueType::kExnRef);
constexpr ValueType kWasmFuncRef = ValueType(ValueType::kFuncRef);
constexpr ValueType kWasmNullRef = ValueType(ValueType::kNullRef);
......
......@@ -27,7 +27,13 @@
\
/* No official proposal (yet?). */ \
/* V8 side owner: clemensb */ \
V(compilation_hints, "compilation hints section", false)
V(compilation_hints, "compilation hints section", false) \
\
/* GC proposal (early prototype, might change dramatically) */ \
/* Official proposal: https://github.com/WebAssembly/gc */ \
/* Prototype engineering spec: https://bit.ly/3cWcm6Q */ \
/* V8 side owner: jkummerow */ \
V(gc, "garbage collection", false)
// #############################################################################
// Staged features (disabled by default, but enabled via --wasm-staging (also
......
......@@ -1468,7 +1468,10 @@ class ThreadImpl {
case ValueType::kAnyRef:
case ValueType::kFuncRef:
case ValueType::kNullRef:
case ValueType::kExnRef: {
case ValueType::kExnRef:
case ValueType::kRef:
case ValueType::kOptRef:
case ValueType::kEqRef: {
val = WasmValue(isolate_->factory()->null_value());
break;
}
......@@ -2890,6 +2893,11 @@ class ThreadImpl {
encoded_values->set(encoded_index++, *anyref);
break;
}
case ValueType::kRef:
case ValueType::kOptRef:
case ValueType::kEqRef:
// TODO(7748): Implement these.
UNIMPLEMENTED();
case ValueType::kStmt:
case ValueType::kBottom:
UNREACHABLE();
......@@ -2995,6 +3003,11 @@ class ThreadImpl {
value = WasmValue(anyref);
break;
}
case ValueType::kRef:
case ValueType::kOptRef:
case ValueType::kEqRef:
// TODO(7748): Implement these.
UNIMPLEMENTED();
case ValueType::kStmt:
case ValueType::kBottom:
UNREACHABLE();
......@@ -3456,7 +3469,11 @@ class ThreadImpl {
case ValueType::kAnyRef:
case ValueType::kFuncRef:
case ValueType::kNullRef:
case ValueType::kExnRef: {
case ValueType::kExnRef:
case ValueType::kRef:
case ValueType::kOptRef:
case ValueType::kEqRef: {
// TODO(7748): Type checks or DCHECKs for ref types?
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.
......@@ -3868,7 +3885,10 @@ class ThreadImpl {
case ValueType::kFuncRef:
case ValueType::kExnRef:
case ValueType::kNullRef:
PrintF("(func|null|exn)ref:unimplemented");
case ValueType::kRef:
case ValueType::kOptRef:
case ValueType::kEqRef:
PrintF("(func|null|exn|opt|eq|)ref:unimplemented");
break;
case ValueType::kBottom:
UNREACHABLE();
......
......@@ -1360,6 +1360,11 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
break;
}
case i::wasm::ValueType::kRef:
case i::wasm::ValueType::kOptRef:
case i::wasm::ValueType::kEqRef:
// TODO(7748): Implement these.
UNIMPLEMENTED();
case i::wasm::ValueType::kStmt:
case i::wasm::ValueType::kS128:
case i::wasm::ValueType::kBottom:
......@@ -1808,6 +1813,11 @@ void WebAssemblyGlobalGetValueCommon(
receiver->GetRef()->IsNull());
return_value.Set(Utils::ToLocal(receiver->GetRef()));
break;
case i::wasm::ValueType::kRef:
case i::wasm::ValueType::kOptRef:
case i::wasm::ValueType::kEqRef:
// TODO(7748): Implement these.
UNIMPLEMENTED();
case i::wasm::ValueType::kBottom:
case i::wasm::ValueType::kStmt:
case i::wasm::ValueType::kS128:
......@@ -1893,6 +1903,11 @@ void WebAssemblyGlobalSetValue(
}
break;
}
case i::wasm::ValueType::kRef:
case i::wasm::ValueType::kOptRef:
case i::wasm::ValueType::kEqRef:
// TODO(7748): Implement these.
UNIMPLEMENTED();
case i::wasm::ValueType::kBottom:
case i::wasm::ValueType::kStmt:
case i::wasm::ValueType::kS128:
......
......@@ -1730,6 +1730,9 @@ uint32_t WasmExceptionPackage::GetEncodedSize(
case wasm::ValueType::kFuncRef:
case wasm::ValueType::kNullRef:
case wasm::ValueType::kExnRef:
case wasm::ValueType::kRef:
case wasm::ValueType::kOptRef:
case wasm::ValueType::kEqRef:
encoded_size += 1;
break;
case wasm::ValueType::kStmt:
......
......@@ -106,6 +106,9 @@ bool InterpretWasmModuleForTesting(Isolate* isolate,
case ValueType::kFuncRef:
case ValueType::kNullRef:
case ValueType::kExnRef:
case ValueType::kRef:
case ValueType::kOptRef:
case ValueType::kEqRef:
arguments[i] =
WasmValue(Handle<Object>::cast(isolate->factory()->null_value()));
break;
......
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