[wasm] Refactor WasmFeatures

Make WasmFeatures a proper class which uses an EnumSet under the hood.
This way, it inherits all behaviour of EnumSet like comparison, merge,
etc.
Accesses change from being simple field access into the struct to
actually bit tests in the EnumSet.

R=mstarzinger@chromium.org

Bug: v8:10019
Change-Id: I768f92b90ac0294156f4482defba5ce00bc70165
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1934334
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65184}
This commit is contained in:
Clemens Backes 2019-11-26 17:25:14 +01:00 committed by Commit Bot
parent dcb828b46f
commit b83c5a06c5
45 changed files with 285 additions and 278 deletions

View File

@ -7247,7 +7247,7 @@ MaybeLocal<WasmModuleObject> WasmModuleObject::Compile(Isolate* isolate,
i::MaybeHandle<i::JSObject> maybe_compiled;
{
i::wasm::ErrorThrower thrower(i_isolate, "WasmModuleObject::Compile()");
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
maybe_compiled = i_isolate->wasm_engine()->SyncCompile(
i_isolate, enabled_features, &thrower,
i::wasm::ModuleWireBytes(start, start + length));

View File

@ -21,8 +21,10 @@ class EnumSet {
public:
constexpr EnumSet() = default;
EnumSet(std::initializer_list<E> init) {
for (E e : init) Add(e);
explicit constexpr EnumSet(std::initializer_list<E> init) {
T bits = 0;
for (E e : init) bits |= Mask(e);
bits_ = bits;
}
bool empty() const { return bits_ == 0; }

View File

@ -5485,7 +5485,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
case wasm::kWasmS128:
UNREACHABLE();
case wasm::kWasmI64: {
DCHECK(enabled_features_.bigint);
DCHECK(enabled_features_.has_bigint());
return BuildChangeInt64ToBigInt(node);
}
case wasm::kWasmF32:
@ -5590,7 +5590,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
break;
}
case wasm::kWasmI64: {
DCHECK(enabled_features_.bigint);
DCHECK(enabled_features_.has_bigint());
num = BuildChangeBigIntToInt64(node, js_context);
break;
}
@ -6600,7 +6600,7 @@ wasm::WasmCompilationResult CompileWasmMathIntrinsic(
wasm::CompilationEnv env(
nullptr, wasm::UseTrapHandler::kNoTrapHandler,
wasm::RuntimeExceptionSupport::kNoRuntimeExceptionSupport,
wasm::kAllWasmFeatures, wasm::LowerSimd::kNoLowerSimd);
wasm::WasmFeatures::All(), wasm::LowerSimd::kNoLowerSimd);
WasmGraphBuilder builder(&env, mcgraph->zone(), mcgraph, sig,
source_positions);
@ -6816,7 +6816,7 @@ MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate,
WasmWrapperGraphBuilder builder(zone.get(), &mcgraph, sig, nullptr,
StubCallMode::kCallBuiltinPointer,
wasm::WasmFeaturesFromIsolate(isolate));
wasm::WasmFeatures::FromIsolate(isolate));
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
builder.BuildJSToJSWrapper(isolate);
@ -6863,7 +6863,7 @@ MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
WasmWrapperGraphBuilder builder(zone.get(), &mcgraph, sig, nullptr,
StubCallMode::kCallBuiltinPointer,
wasm::WasmFeaturesFromIsolate(isolate));
wasm::WasmFeatures::FromIsolate(isolate));
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
builder.BuildCWasmEntry();

View File

@ -43,7 +43,7 @@ struct DecodeStruct;
using TFNode = compiler::Node;
using TFGraph = compiler::MachineGraph;
class WasmCode;
struct WasmFeatures;
class WasmFeatures;
enum class LoadTransformationKind : uint8_t;
} // namespace wasm

View File

@ -567,16 +567,17 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
case JS_ERROR_TYPE:
return WriteJSError(Handle<JSObject>::cast(receiver));
case WASM_MODULE_OBJECT_TYPE: {
auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
if (!FLAG_wasm_disable_structured_cloning || enabled_features.threads) {
auto enabled_features = wasm::WasmFeatures::FromIsolate(isolate_);
if (!FLAG_wasm_disable_structured_cloning ||
enabled_features.has_threads()) {
// Only write WebAssembly modules if not disabled by a flag.
return WriteWasmModule(Handle<WasmModuleObject>::cast(receiver));
}
break;
}
case WASM_MEMORY_OBJECT_TYPE: {
auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
if (enabled_features.threads) {
auto enabled_features = wasm::WasmFeatures::FromIsolate(isolate_);
if (enabled_features.has_threads()) {
return WriteWasmMemory(Handle<WasmMemoryObject>::cast(receiver));
}
break;
@ -1939,8 +1940,9 @@ MaybeHandle<Object> ValueDeserializer::ReadJSError() {
}
MaybeHandle<JSObject> ValueDeserializer::ReadWasmModuleTransfer() {
auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
if ((FLAG_wasm_disable_structured_cloning && !enabled_features.threads) ||
auto enabled_features = wasm::WasmFeatures::FromIsolate(isolate_);
if ((FLAG_wasm_disable_structured_cloning &&
!enabled_features.has_threads()) ||
expect_inline_wasm()) {
return MaybeHandle<JSObject>();
}
@ -1963,8 +1965,9 @@ MaybeHandle<JSObject> ValueDeserializer::ReadWasmModuleTransfer() {
}
MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
if ((FLAG_wasm_disable_structured_cloning && !enabled_features.threads) ||
auto enabled_features = wasm::WasmFeatures::FromIsolate(isolate_);
if ((FLAG_wasm_disable_structured_cloning &&
!enabled_features.has_threads()) ||
!expect_inline_wasm()) {
return MaybeHandle<JSObject>();
}
@ -1999,7 +2002,7 @@ MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
if (result.is_null()) {
wasm::ErrorThrower thrower(isolate_, "ValueDeserializer::ReadWasmModule");
// TODO(titzer): are the current features appropriate for deserializing?
auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
auto enabled_features = wasm::WasmFeatures::FromIsolate(isolate_);
result = isolate_->wasm_engine()->SyncCompile(
isolate_, enabled_features, &thrower,
wasm::ModuleWireBytes(wire_bytes));
@ -2014,8 +2017,8 @@ MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
MaybeHandle<WasmMemoryObject> ValueDeserializer::ReadWasmMemory() {
uint32_t id = next_id_++;
auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
if (!enabled_features.threads) {
auto enabled_features = wasm::WasmFeatures::FromIsolate(isolate_);
if (!enabled_features.has_threads()) {
return MaybeHandle<WasmMemoryObject>();
}

View File

@ -17,7 +17,7 @@ namespace wasm {
struct CompilationEnv;
struct FunctionBody;
struct WasmFeatures;
class WasmFeatures;
// Note: If this list changes, also the histogram "V8.LiftoffBailoutReasons"
// on the chromium side needs to be updated.

View File

@ -970,7 +970,7 @@ auto Module::validate(Store* store_abs, const vec<byte_t>& binary) -> bool {
i::wasm::ModuleWireBytes bytes(
{reinterpret_cast<const uint8_t*>(binary.get()), binary.size()});
i::Isolate* isolate = impl(store_abs)->i_isolate();
i::wasm::WasmFeatures features = i::wasm::WasmFeaturesFromIsolate(isolate);
i::wasm::WasmFeatures features = i::wasm::WasmFeatures::FromIsolate(isolate);
return isolate->wasm_engine()->SyncValidate(isolate, features, bytes);
}
@ -980,7 +980,7 @@ auto Module::make(Store* store_abs, const vec<byte_t>& binary) -> own<Module> {
i::HandleScope scope(isolate);
i::wasm::ModuleWireBytes bytes(
{reinterpret_cast<const uint8_t*>(binary.get()), binary.size()});
i::wasm::WasmFeatures features = i::wasm::WasmFeaturesFromIsolate(isolate);
i::wasm::WasmFeatures features = i::wasm::WasmFeatures::FromIsolate(isolate);
i::wasm::ErrorThrower thrower(isolate, "ignored");
i::Handle<i::WasmModuleObject> module;
if (!isolate->wasm_engine()
@ -1763,7 +1763,8 @@ auto Table::make(Store* store_abs, const TableType* type, const Ref* ref)
i_type = i::wasm::kWasmFuncRef;
break;
case ANYREF:
DCHECK(i::wasm::WasmFeaturesFromFlags().anyref); // See Engine::make().
// See Engine::make().
DCHECK(i::wasm::WasmFeatures::FromFlags().has_anyref());
i_type = i::wasm::kWasmAnyRef;
break;
default:

View File

@ -43,19 +43,19 @@ struct WasmException;
#define RET_ON_PROTOTYPE_OPCODE(feat) \
DCHECK(!this->module_ || this->module_->origin == kWasmOrigin); \
if (!this->enabled_.feat) { \
if (!this->enabled_.has_##feat()) { \
this->error("Invalid opcode (enable with --experimental-wasm-" #feat ")"); \
} else { \
this->detected_->feat = true; \
this->detected_->Add(kFeature_##feat); \
}
#define CHECK_PROTOTYPE_OPCODE(feat) \
DCHECK(!this->module_ || this->module_->origin == kWasmOrigin); \
if (!this->enabled_.feat) { \
if (!this->enabled_.has_##feat()) { \
this->error("Invalid opcode (enable with --experimental-wasm-" #feat ")"); \
break; \
} else { \
this->detected_->feat = true; \
this->detected_->Add(kFeature_##feat); \
}
#define OPCODE_ERROR(opcode, message) \
@ -281,7 +281,7 @@ struct BlockTypeImmediate {
uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
if (!function_body_decoder::decode_local_type(val, &type)) {
// Handle multi-value blocks.
if (!VALIDATE(enabled.mv)) {
if (!VALIDATE(enabled.has_mv())) {
decoder->error(pc + 1, "invalid block type");
return;
}
@ -381,7 +381,8 @@ struct CallIndirectImmediate {
uint32_t len = 0;
sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
TableIndexImmediate<validate> table(decoder, pc + len);
if (!VALIDATE((table.index == 0 && table.length == 1) || enabled.anyref)) {
if (!VALIDATE((table.index == 0 && table.length == 1) ||
enabled.has_anyref())) {
decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
table.index);
}
@ -840,7 +841,7 @@ class WasmDecoder : public Decoder {
type = kWasmF64;
break;
case kLocalAnyRef:
if (enabled.anyref) {
if (enabled.has_anyref()) {
type = kWasmAnyRef;
break;
}
@ -849,7 +850,7 @@ class WasmDecoder : public Decoder {
"--experimental-wasm-anyref");
return false;
case kLocalFuncRef:
if (enabled.anyref) {
if (enabled.has_anyref()) {
type = kWasmFuncRef;
break;
}
@ -858,7 +859,7 @@ class WasmDecoder : public Decoder {
"--experimental-wasm-anyref");
return false;
case kLocalExnRef:
if (enabled.eh) {
if (enabled.has_eh()) {
type = kWasmExnRef;
break;
}
@ -867,7 +868,7 @@ class WasmDecoder : public Decoder {
"--experimental-wasm-eh");
return false;
case kLocalS128:
if (enabled.simd) {
if (enabled.has_simd()) {
type = kWasmS128;
break;
}
@ -1231,7 +1232,7 @@ class WasmDecoder : public Decoder {
}
case kExprCallIndirect:
case kExprReturnCallIndirect: {
CallIndirectImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
CallIndirectImmediate<validate> imm(WasmFeatures::All(), decoder, pc);
return 1 + imm.length;
}
@ -1239,7 +1240,7 @@ class WasmDecoder : public Decoder {
case kExprIf: // fall through
case kExprLoop:
case kExprBlock: {
BlockTypeImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
BlockTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc);
return 1 + imm.length;
}
@ -2569,7 +2570,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
for (int i = 0; i < br_arity; ++i) {
if (this->enabled_.anyref) {
if (this->enabled_.has_anyref()) {
// The expected type is the biggest common sub type of all targets.
(*result_types)[i] =
ValueTypes::CommonSubType((*result_types)[i], (*merge)[i].type);

View File

@ -35,7 +35,7 @@ BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
BodyLocalDecls* decls)
: Decoder(start, end) {
if (decls != nullptr) {
if (DecodeLocalDecls(kAllWasmFeatures, decls, start, end)) {
if (DecodeLocalDecls(WasmFeatures::All(), decls, start, end)) {
pc_ += decls->encoded_size;
if (pc_ > end_) pc_ = end_;
}
@ -61,9 +61,9 @@ unsigned OpcodeLength(const byte* pc, const byte* end) {
std::pair<uint32_t, uint32_t> StackEffect(const WasmModule* module,
FunctionSig* sig, const byte* pc,
const byte* end) {
WasmFeatures unused_detected_features;
WasmFeatures unused_detected_features = WasmFeatures::None();
WasmDecoder<Decoder::kNoValidate> decoder(
module, kAllWasmFeatures, &unused_detected_features, sig, pc, end);
module, WasmFeatures::All(), &unused_detected_features, sig, pc, end);
return decoder.StackEffect(pc);
}
@ -98,8 +98,8 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
const WasmModule* module, PrintLocals print_locals,
std::ostream& os, std::vector<int>* line_numbers) {
Zone zone(allocator, ZONE_NAME);
WasmFeatures unused_detected_features;
WasmDecoder<Decoder::kNoValidate> decoder(module, kAllWasmFeatures,
WasmFeatures unused_detected_features = WasmFeatures::None();
WasmDecoder<Decoder::kNoValidate> decoder(module, WasmFeatures::All(),
&unused_detected_features, body.sig,
body.start, body.end);
int line_nr = 0;
@ -208,7 +208,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
case kExprIf:
case kExprBlock:
case kExprTry: {
BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
BlockTypeImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(), &i,
i.pc());
os << " // @" << i.pc_offset();
if (decoder.Complete(imm)) {
@ -239,7 +239,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
break;
}
case kExprCallIndirect: {
CallIndirectImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
CallIndirectImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(), &i,
i.pc());
os << " // sig #" << imm.sig_index;
if (decoder.Complete(i.pc(), imm)) {

View File

@ -19,8 +19,8 @@ class BitVector; // forward declaration
namespace wasm {
class WasmFeatures;
struct WasmModule; // forward declaration of module interface.
struct WasmFeatures;
// A wrapper around the signature and bytes of a function.
struct FunctionBody {

View File

@ -295,7 +295,7 @@ Handle<Code> JSToWasmWrapperCompilationUnit::Finalize(Isolate* isolate) {
Handle<Code> JSToWasmWrapperCompilationUnit::CompileJSToWasmWrapper(
Isolate* isolate, FunctionSig* sig, bool is_import) {
// Run the compilation unit synchronously.
WasmFeatures enabled_features = WasmFeaturesFromIsolate(isolate);
WasmFeatures enabled_features = WasmFeatures::FromIsolate(isolate);
JSToWasmWrapperCompilationUnit unit(isolate, isolate->wasm_engine(), sig,
is_import, enabled_features);
unit.Execute();

View File

@ -20,8 +20,8 @@ class WasmGraphBuilder;
namespace wasm {
struct FunctionBody;
class WasmFeatures;
struct WasmModule;
struct WasmFeatures;
V8_EXPORT_PRIVATE DecodeResult
BuildTFGraph(AccountingAllocator* allocator, const WasmFeatures& enabled,

View File

@ -511,7 +511,7 @@ class CompilationStateImpl {
// Features detected to be used in this module. Features can be detected
// as a module is being compiled.
WasmFeatures detected_features_ = kNoWasmFeatures;
WasmFeatures detected_features_ = WasmFeatures::None();
// Abstraction over the storage of the wire bytes. Held in a shared_ptr so
// that background compilation jobs can keep the storage alive while
@ -557,7 +557,7 @@ CompilationStateImpl* BackgroundCompileScope::compilation_state() {
}
void UpdateFeatureUseCounts(Isolate* isolate, const WasmFeatures& detected) {
if (detected.threads) {
if (detected.has_threads()) {
isolate->CountUsage(v8::Isolate::UseCounterFeature::kWasmThreadOpcodes);
}
}
@ -641,7 +641,9 @@ CompileStrategy GetCompileStrategy(const WasmModule* module,
const WasmFeatures& enabled_features,
uint32_t func_index, bool lazy_module) {
if (lazy_module) return CompileStrategy::kLazy;
if (!enabled_features.compilation_hints) return CompileStrategy::kDefault;
if (!enabled_features.has_compilation_hints()) {
return CompileStrategy::kDefault;
}
auto* hint = GetCompilationHint(module, func_index);
if (hint == nullptr) return CompileStrategy::kDefault;
switch (hint->strategy) {
@ -680,7 +682,7 @@ ExecutionTierPair GetRequestedExecutionTiers(
result.top_tier = ExecutionTier::kTurbofan;
// Check if compilation hints override default tiering behaviour.
if (enabled_features.compilation_hints) {
if (enabled_features.has_compilation_hints()) {
const WasmCompilationHint* hint =
GetCompilationHint(module, func_index);
if (hint != nullptr) {
@ -1001,7 +1003,7 @@ bool ExecuteCompilationUnits(
std::shared_ptr<const WasmModule> module;
WasmEngine* wasm_engine = nullptr;
base::Optional<WasmCompilationUnit> unit;
WasmFeatures detected_features = kNoWasmFeatures;
WasmFeatures detected_features = WasmFeatures::None();
auto stop = [is_foreground, task_id,
&detected_features](BackgroundCompileScope& compile_scope) {
@ -1192,7 +1194,7 @@ void InitializeCompilationUnits(Isolate* isolate, NativeModule* native_module) {
int num_import_wrappers = AddImportWrapperUnits(native_module, &builder);
int num_export_wrappers =
AddExportWrapperUnits(isolate, isolate->wasm_engine(), native_module,
&builder, WasmFeaturesFromIsolate(isolate));
&builder, WasmFeatures::FromIsolate(isolate));
compilation_state->InitializeCompilationProgress(
lazy_module, num_import_wrappers + num_export_wrappers);
builder.Commit();
@ -1201,7 +1203,7 @@ void InitializeCompilationUnits(Isolate* isolate, NativeModule* native_module) {
bool MayCompriseLazyFunctions(const WasmModule* module,
const WasmFeatures& enabled_features,
bool lazy_module) {
if (lazy_module || enabled_features.compilation_hints) return true;
if (lazy_module || enabled_features.has_compilation_hints()) return true;
#ifdef ENABLE_SLOW_DCHECKS
int start = module->num_imported_functions;
int end = start + module->num_declared_functions;
@ -2503,7 +2505,7 @@ void CompilationStateImpl::OnBackgroundTaskStopped(
available_task_ids_.end(), task_id));
DCHECK_GT(max_background_tasks_, available_task_ids_.size());
available_task_ids_.push_back(task_id);
UnionFeaturesInto(&detected_features_, detected);
detected_features_.Add(detected);
}
// The background task could have stopped while we were adding new units, or
@ -2515,7 +2517,7 @@ void CompilationStateImpl::OnBackgroundTaskStopped(
void CompilationStateImpl::UpdateDetectedFeatures(
const WasmFeatures& detected) {
base::MutexGuard guard(&mutex_);
UnionFeaturesInto(&detected_features_, detected);
detected_features_.Add(detected);
}
void CompilationStateImpl::PublishDetectedFeatures(Isolate* isolate) {
@ -2620,7 +2622,7 @@ void CompileJsToWasmWrappers(Isolate* isolate, const WasmModule* module,
JSToWasmWrapperQueue queue;
JSToWasmWrapperUnitMap compilation_units;
WasmFeatures enabled_features = WasmFeaturesFromIsolate(isolate);
WasmFeatures enabled_features = WasmFeatures::FromIsolate(isolate);
// Prepare compilation units in the main thread.
for (auto exp : module->export_table) {

View File

@ -467,7 +467,7 @@ class ModuleDecoderImpl : public Decoder {
consume_bytes(static_cast<uint32_t>(end_ - start_), ".debug_info");
break;
case kCompilationHintsSectionCode:
if (enabled_features_.compilation_hints) {
if (enabled_features_.has_compilation_hints()) {
DecodeCompilationHintsSection();
} else {
// Ignore this section when feature was disabled. It is an optional
@ -476,14 +476,14 @@ class ModuleDecoderImpl : public Decoder {
}
break;
case kDataCountSectionCode:
if (enabled_features_.bulk_memory) {
if (enabled_features_.has_bulk_memory()) {
DecodeDataCountSection();
} else {
errorf(pc(), "unexpected section <%s>", SectionName(section_code));
}
break;
case kExceptionSectionCode:
if (enabled_features_.eh) {
if (enabled_features_.has_eh()) {
DecodeExceptionSection();
} else {
errorf(pc(), "unexpected section <%s>", SectionName(section_code));
@ -562,7 +562,7 @@ class ModuleDecoderImpl : public Decoder {
WasmTable* table = &module_->tables.back();
table->imported = true;
ValueType type = consume_reference_type();
if (!enabled_features_.anyref) {
if (!enabled_features_.has_anyref()) {
if (type != kWasmFuncRef) {
error(pc_ - 1, "invalid table type");
break;
@ -601,7 +601,7 @@ class ModuleDecoderImpl : public Decoder {
}
case kExternalException: {
// ===== Imported exception ==========================================
if (!enabled_features_.eh) {
if (!enabled_features_.has_eh()) {
errorf(pos, "unknown import kind 0x%02x", import->kind);
break;
}
@ -648,7 +648,8 @@ class ModuleDecoderImpl : public Decoder {
void DecodeTableSection() {
// TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the
// implementation of AnyRef landed.
uint32_t max_count = enabled_features_.anyref ? 100000 : kV8MaxWasmTables;
uint32_t max_count =
enabled_features_.has_anyref() ? 100000 : kV8MaxWasmTables;
uint32_t table_count = consume_count("table count", max_count);
for (uint32_t i = 0; ok() && i < table_count; i++) {
@ -745,7 +746,7 @@ class ModuleDecoderImpl : public Decoder {
break;
}
case kExternalException: {
if (!enabled_features_.eh) {
if (!enabled_features_.has_eh()) {
errorf(pos, "invalid export kind 0x%02x", exp->kind);
break;
}
@ -1238,7 +1239,7 @@ class ModuleDecoderImpl : public Decoder {
}
bool AddTable(WasmModule* module) {
if (enabled_features_.anyref) return true;
if (enabled_features_.has_anyref()) return true;
if (module->tables.size() > 0) {
error("At most one table is supported");
return false;
@ -1331,7 +1332,7 @@ class ModuleDecoderImpl : public Decoder {
wasm_decode, function_time);
TimedHistogramScope wasm_decode_function_time_scope(time_counter);
WasmFeatures unused_detected_features;
WasmFeatures unused_detected_features = WasmFeatures::None();
result = VerifyWasmCode(allocator, enabled_features_, module,
&unused_detected_features, body);
}
@ -1426,7 +1427,7 @@ class ModuleDecoderImpl : public Decoder {
uint8_t flags = consume_u8("resizable limits flags");
const byte* pos = pc();
*has_shared_memory = false;
if (enabled_features_.threads) {
if (enabled_features_.has_threads()) {
if (flags & 0xFC) {
errorf(pos - 1, "invalid memory limits flags");
} else if (flags == 3) {
@ -1544,7 +1545,7 @@ class ModuleDecoderImpl : public Decoder {
break;
}
case kExprRefNull: {
if (enabled_features_.anyref || enabled_features_.eh) {
if (enabled_features_.has_anyref() || enabled_features_.has_eh()) {
expr.kind = WasmInitExpr::kRefNullConst;
len = 0;
break;
@ -1552,7 +1553,7 @@ class ModuleDecoderImpl : public Decoder {
V8_FALLTHROUGH;
}
case kExprRefFunc: {
if (enabled_features_.anyref) {
if (enabled_features_.has_anyref()) {
FunctionIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
if (module->functions.size() <= imm.index) {
errorf(pc() - 1, "invalid function index: %u", imm.index);
@ -1607,16 +1608,16 @@ class ModuleDecoderImpl : public Decoder {
if (origin_ == kWasmOrigin) {
switch (t) {
case kLocalS128:
if (enabled_features_.simd) return kWasmS128;
if (enabled_features_.has_simd()) return kWasmS128;
break;
case kLocalFuncRef:
if (enabled_features_.anyref) return kWasmFuncRef;
if (enabled_features_.has_anyref()) return kWasmFuncRef;
break;
case kLocalAnyRef:
if (enabled_features_.anyref) return kWasmAnyRef;
if (enabled_features_.has_anyref()) return kWasmAnyRef;
break;
case kLocalExnRef:
if (enabled_features_.eh) return kWasmExnRef;
if (enabled_features_.has_eh()) return kWasmExnRef;
break;
default:
break;
@ -1635,13 +1636,13 @@ class ModuleDecoderImpl : public Decoder {
case kLocalFuncRef:
return kWasmFuncRef;
case kLocalAnyRef:
if (!enabled_features_.anyref) {
if (!enabled_features_.has_anyref()) {
error(pc_ - 1,
"Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
}
return kWasmAnyRef;
case kLocalExnRef:
if (!enabled_features_.eh) {
if (!enabled_features_.has_eh()) {
error(pc_ - 1,
"Invalid type. Set --experimental-wasm-eh to use 'ExnRef'");
}
@ -1666,7 +1667,7 @@ class ModuleDecoderImpl : public Decoder {
}
std::vector<ValueType> returns;
// parse return types
const size_t max_return_count = enabled_features_.mv
const size_t max_return_count = enabled_features_.has_mv()
? kV8MaxWasmFunctionMultiReturns
: kV8MaxWasmFunctionReturns;
uint32_t return_count = consume_count("return count", max_return_count);
@ -1704,7 +1705,7 @@ class ModuleDecoderImpl : public Decoder {
WasmInitExpr* offset) {
const byte* pos = pc();
uint8_t flag;
if (enabled_features_.bulk_memory || enabled_features_.anyref) {
if (enabled_features_.has_bulk_memory() || enabled_features_.has_anyref()) {
flag = consume_u8("flag");
} else {
uint32_t table_index = consume_u32v("table index");
@ -1735,18 +1736,18 @@ class ModuleDecoderImpl : public Decoder {
*functions_as_elements = flag & kFunctionsAsElementsMask;
bool has_table_index = flag & kHasTableIndexMask;
if (is_passive && !enabled_features_.bulk_memory) {
if (is_passive && !enabled_features_.has_bulk_memory()) {
error("Passive element segments require --experimental-wasm-bulk-memory");
return;
}
if (*functions_as_elements && !enabled_features_.bulk_memory) {
if (*functions_as_elements && !enabled_features_.has_bulk_memory()) {
error(
"Illegal segment flag. Did you forget "
"--experimental-wasm-bulk-memory?");
return;
}
if (flag != 0 && !enabled_features_.bulk_memory &&
!enabled_features_.anyref) {
if (flag != 0 && !enabled_features_.has_bulk_memory() &&
!enabled_features_.has_anyref()) {
error(
"Invalid segment flag. Did you forget "
"--experimental-wasm-bulk-memory or --experimental-wasm-anyref?");
@ -1800,13 +1801,14 @@ class ModuleDecoderImpl : public Decoder {
// Some flag values are only valid for specific proposals.
if (flag == SegmentFlags::kPassive) {
if (!enabled_features_.bulk_memory) {
if (!enabled_features_.has_bulk_memory()) {
error(
"Passive element segments require --experimental-wasm-bulk-memory");
return;
}
} else if (flag == SegmentFlags::kActiveWithIndex) {
if (!(enabled_features_.bulk_memory || enabled_features_.anyref)) {
if (!(enabled_features_.has_bulk_memory() ||
enabled_features_.has_anyref())) {
error(
"Element segments with table indices require "
"--experimental-wasm-bulk-memory or --experimental-wasm-anyref");

View File

@ -477,7 +477,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
// The bulk memory proposal changes the MVP behavior here; the segments are
// written as if `memory.init` and `table.init` are executed directly, and
// not bounds checked ahead of time.
if (!enabled_.bulk_memory) {
if (!enabled_.has_bulk_memory()) {
//--------------------------------------------------------------------------
// Check that indirect function table segments are within bounds.
//--------------------------------------------------------------------------
@ -657,7 +657,7 @@ void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
for (const WasmDataSegment& segment : module_->data_segments) {
uint32_t size = segment.source.length();
if (enabled_.bulk_memory) {
if (enabled_.has_bulk_memory()) {
if (size == 0) continue;
// Passive segments are not copied during instantiation.
if (!segment.active) continue;
@ -1130,7 +1130,7 @@ bool InstanceBuilder::ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
//
// However, the bigint proposal allows importing constant i64 values,
// as non WebAssembly.Global object.
if (global.type == kWasmI64 && !enabled_.bigint &&
if (global.type == kWasmI64 && !enabled_.has_bigint() &&
!value->IsWasmGlobalObject()) {
ReportLinkError("global import cannot have type i64", import_index,
module_name, import_name);
@ -1187,7 +1187,7 @@ bool InstanceBuilder::ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
return true;
}
if (enabled_.bigint && global.type == kWasmI64 && value->IsBigInt()) {
if (enabled_.has_bigint() && global.type == kWasmI64 && value->IsBigInt()) {
WriteGlobalValue(global, BigInt::cast(*value).AsInt64());
return true;
}
@ -1364,7 +1364,7 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
global.init.val.f64_const);
break;
case WasmInitExpr::kRefNullConst:
DCHECK(enabled_.anyref || enabled_.eh);
DCHECK(enabled_.has_anyref() || enabled_.has_eh());
if (global.imported) break; // We already initialized imported globals.
tagged_globals_->set(global.offset,
@ -1372,7 +1372,7 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
SKIP_WRITE_BARRIER);
break;
case WasmInitExpr::kRefFuncConst: {
DCHECK(enabled_.anyref);
DCHECK(enabled_.has_anyref());
auto function = WasmInstanceObject::GetOrCreateWasmExternalFunction(
isolate_, instance, global.init.val.function_index);
tagged_globals_->set(global.offset, *function);
@ -1385,7 +1385,7 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
module_->globals[global.init.val.global_index].offset;
TRACE("init [globals+%u] = [globals+%d]\n", global.offset, old_offset);
if (ValueTypes::IsReferenceType(global.type)) {
DCHECK(enabled_.anyref || enabled_.eh);
DCHECK(enabled_.has_anyref() || enabled_.has_eh());
tagged_globals_->set(new_offset, tagged_globals_->get(old_offset));
} else {
size_t size = (global.type == kWasmI64 || global.type == kWasmF64)
@ -1415,7 +1415,7 @@ bool InstanceBuilder::AllocateMemory() {
thrower_->RangeError("Out of memory: wasm memory too large");
return false;
}
auto shared = (module_->has_shared_memory && enabled_.threads)
auto shared = (module_->has_shared_memory && enabled_.has_threads())
? SharedFlag::kShared
: SharedFlag::kNotShared;
@ -1703,7 +1703,7 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
uint32_t dst = EvalUint32InitExpr(instance, elem_segment.offset);
uint32_t src = 0;
size_t count = elem_segment.entries.size();
if (enabled_.bulk_memory && count == 0) continue;
if (enabled_.has_bulk_memory() && count == 0) continue;
bool success = LoadElemSegmentImpl(
isolate_, instance,
@ -1711,7 +1711,7 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
instance->tables().get(elem_segment.table_index)),
isolate_),
table_index, elem_segment, dst, src, count);
if (enabled_.bulk_memory) {
if (enabled_.has_bulk_memory()) {
if (!success) {
thrower_->RuntimeError("table initializer is out of bounds");
// Break out instead of returning; we don't want to continue to

View File

@ -228,7 +228,7 @@ class InterpreterHandle {
// Copy back the return value.
#ifdef DEBUG
const int max_count = WasmFeaturesFromIsolate(isolate_).mv
const int max_count = WasmFeatures::FromIsolate(isolate_).has_mv()
? kV8MaxWasmFunctionMultiReturns
: kV8MaxWasmFunctionReturns;
#endif

View File

@ -242,8 +242,8 @@ MaybeHandle<AsmWasmData> WasmEngine::SyncCompileTranslatedAsmJs(
? kAsmJsSloppyOrigin
: kAsmJsStrictOrigin;
ModuleResult result =
DecodeWasmModule(kAsmjsWasmFeatures, bytes.start(), bytes.end(), false,
origin, isolate->counters(), allocator());
DecodeWasmModule(WasmFeatures::ForAsmjs(), bytes.start(), bytes.end(),
false, origin, isolate->counters(), allocator());
if (result.failed()) {
// This happens once in a while when we have missed some limit check
// in the asm parser. Output an error message to help diagnose, but crash.
@ -255,7 +255,7 @@ MaybeHandle<AsmWasmData> WasmEngine::SyncCompileTranslatedAsmJs(
// in {CompileToNativeModule}.
Handle<FixedArray> export_wrappers;
std::shared_ptr<NativeModule> native_module =
CompileToNativeModule(isolate, kAsmjsWasmFeatures, thrower,
CompileToNativeModule(isolate, WasmFeatures::ForAsmjs(), thrower,
std::move(result).value(), bytes, &export_wrappers);
if (!native_module) return {};
@ -427,7 +427,7 @@ std::shared_ptr<StreamingDecoder> WasmEngine::StartStreamingCompilation(
void WasmEngine::CompileFunction(Isolate* isolate, NativeModule* native_module,
uint32_t function_index, ExecutionTier tier) {
// Note we assume that "one-off" compilations can discard detected features.
WasmFeatures detected = kNoWasmFeatures;
WasmFeatures detected = WasmFeatures::None();
WasmCompilationUnit::CompileWasmFunction(
isolate, native_module, &detected,
&native_module->module()->functions[function_index], tier);

View File

@ -29,7 +29,7 @@ namespace wasm {
class AsyncCompileJob;
class ErrorThrower;
struct ModuleWireBytes;
struct WasmFeatures;
class WasmFeatures;
class V8_EXPORT_PRIVATE CompilationResultResolver {
public:

View File

@ -11,23 +11,22 @@ namespace v8 {
namespace internal {
namespace wasm {
void UnionFeaturesInto(WasmFeatures* dst, const WasmFeatures& src) {
#define DO_UNION(feat, desc, val) dst->feat |= src.feat;
FOREACH_WASM_FEATURE(DO_UNION);
#undef DO_UNION
}
WasmFeatures WasmFeaturesFromFlags() {
#define FLAG_REF(feat, desc, val) FLAG_experimental_wasm_##feat,
return WasmFeatures(FOREACH_WASM_FEATURE(FLAG_REF){});
// static
WasmFeatures WasmFeatures::FromFlags() {
WasmFeatures features = WasmFeatures::None();
#define FLAG_REF(feat, ...) \
if (FLAG_experimental_wasm_##feat) features.Add(kFeature_##feat);
FOREACH_WASM_FEATURE(FLAG_REF)
#undef FLAG_REF
return features;
}
WasmFeatures WasmFeaturesFromIsolate(Isolate* isolate) {
WasmFeatures features = WasmFeaturesFromFlags();
features.threads |=
isolate->AreWasmThreadsEnabled(handle(isolate->context(), isolate));
// static
WasmFeatures WasmFeatures::FromIsolate(Isolate* isolate) {
WasmFeatures features = WasmFeatures::FromFlags();
if (isolate->AreWasmThreadsEnabled(handle(isolate->context(), isolate))) {
features.Add(kFeature_threads);
}
return features;
}

View File

@ -6,6 +6,7 @@
#define V8_WASM_WASM_FEATURES_H_
// The feature flags are declared in their own header.
#include "src/base/enum-set.h"
#include "src/base/macros.h"
#include "src/wasm/wasm-feature-flags.h"
@ -14,64 +15,49 @@
namespace v8 {
namespace internal {
class Isolate;
namespace wasm {
// This is an empty type to indicate the end of the {WasmFeatures} struct. We
// use the {end_t} type there to avoid trailing commas that get generated by
// the macro generators. We considered the following alternatives:
// * Add "separators" to the {FOREACH_WASM_FEATURE_FLAGS} between entries. This
// does not work when we want to have different kinds of flags, e.g. for
// experimental, staging, and shipped features.
// * Use initialization lists, e.g. construct {WasmFeatures} with
// "WasmFeatures{true, true, ..., true,}". This solves the comma problem,
// because trailing commas are allowed here. However, we cannot
// default-initialize the fields of {WasmFeatures} anymore. This seems
// error-prone, because default-constructed {WasmFeatures} structs are already
// used in the code base.
// * Avoid the use of {constexpr}. With that we would be more flexible with how
// we generate {kAllWasmFeatures} and {kNoWasmFeatures}. These values may be
// used in performance-critical code, however, e.g. in the decoder or in the
// interpreter.
struct end_t {};
// Enabled or detected features.
struct WasmFeatures {
#define DECL_FIELD(feat, desc, val) bool feat = false;
FOREACH_WASM_FEATURE(DECL_FIELD)
#undef DECL_FIELD
// Marker for the end of the list, see the comment at {end_t}.
end_t end_;
#define DECL_PARAM(feat, desc, val) bool p##feat,
#define DO_INIT(feat, desc, val) feat(p##feat),
explicit constexpr WasmFeatures(FOREACH_WASM_FEATURE(DECL_PARAM) end_t)
: FOREACH_WASM_FEATURE(DO_INIT) end_() {}
#undef DECL_PARAM
#undef DO_INIT
constexpr WasmFeatures() = default;
enum WasmFeature {
#define DECL_FEATURE_ENUM(feat, ...) kFeature_##feat,
FOREACH_WASM_FEATURE(DECL_FEATURE_ENUM)
#undef DECL_FEATURE_ENUM
};
#define JUST_TRUE(feat, desc, val) true,
static constexpr WasmFeatures kAllWasmFeatures(
FOREACH_WASM_FEATURE(JUST_TRUE){});
#undef JUST_TRUE
// Enabled or detected features.
class WasmFeatures : public base::EnumSet<WasmFeature> {
public:
constexpr WasmFeatures() = default;
explicit constexpr WasmFeatures(std::initializer_list<WasmFeature> features)
: EnumSet(features) {}
#define JUST_FALSE(feat, desc, val) false,
static constexpr WasmFeatures kNoWasmFeatures(
FOREACH_WASM_FEATURE(JUST_FALSE){});
#undef JUST_FALSE
// Simplified getters. Use {has_foo()} instead of {contains(kFeature_foo)}.
#define DECL_FEATURE_GETTER(feat, ...) \
bool has_##feat() const { return contains(kFeature_##feat); }
FOREACH_WASM_FEATURE(DECL_FEATURE_GETTER)
#undef DECL_FEATURE_GETTER
static constexpr WasmFeatures kAsmjsWasmFeatures = kNoWasmFeatures;
static inline constexpr WasmFeatures All();
static inline constexpr WasmFeatures None();
static inline constexpr WasmFeatures ForAsmjs();
static WasmFeatures FromFlags();
static V8_EXPORT_PRIVATE WasmFeatures FromIsolate(Isolate*);
};
V8_EXPORT_PRIVATE WasmFeatures WasmFeaturesFromFlags();
// static
constexpr WasmFeatures WasmFeatures::All() {
#define LIST_FEATURE(feat, ...) kFeature_##feat,
return WasmFeatures({FOREACH_WASM_FEATURE(LIST_FEATURE)});
#undef LIST_FEATURE
}
// Enables features based on both commandline flags and the isolate.
// Precondition: A valid context must be set in {isolate->context()}.
V8_EXPORT_PRIVATE WasmFeatures WasmFeaturesFromIsolate(Isolate* isolate);
// static
constexpr WasmFeatures WasmFeatures::None() { return {}; }
V8_EXPORT_PRIVATE void UnionFeaturesInto(WasmFeatures* dst,
const WasmFeatures& src);
// static
constexpr WasmFeatures WasmFeatures::ForAsmjs() { return {}; }
} // namespace wasm
} // namespace internal

View File

@ -815,7 +815,7 @@ class SideTable : public ZoneObject {
case kExprBlock:
case kExprLoop: {
bool is_loop = opcode == kExprLoop;
BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
BlockTypeImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(), &i,
i.pc());
if (imm.type == kWasmBottom) {
imm.sig = module->signatures[imm.sig_index];
@ -831,7 +831,7 @@ class SideTable : public ZoneObject {
break;
}
case kExprIf: {
BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
BlockTypeImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(), &i,
i.pc());
if (imm.type == kWasmBottom) {
imm.sig = module->signatures[imm.sig_index];
@ -866,7 +866,7 @@ class SideTable : public ZoneObject {
break;
}
case kExprTry: {
BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
BlockTypeImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(), &i,
i.pc());
if (imm.type == kWasmBottom) {
imm.sig = module->signatures[imm.sig_index];
@ -1525,7 +1525,7 @@ class ThreadImpl {
return pc + 1 + imm.length;
}
case kExprCallIndirect: {
CallIndirectImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures,
CallIndirectImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(),
decoder, code->at(pc));
return pc + 1 + imm.length;
}
@ -3006,13 +3006,13 @@ class ThreadImpl {
case kExprBlock:
case kExprLoop:
case kExprTry: {
BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures,
BlockTypeImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(),
&decoder, code->at(pc));
len = 1 + imm.length;
break;
}
case kExprIf: {
BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures,
BlockTypeImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(),
&decoder, code->at(pc));
WasmValue cond = Pop();
bool is_true = cond.to<uint32_t>() != 0;
@ -3233,7 +3233,7 @@ class ThreadImpl {
case kExprCallIndirect: {
CallIndirectImmediate<Decoder::kNoValidate> imm(
kAllWasmFeatures, &decoder, code->at(pc));
WasmFeatures::All(), &decoder, code->at(pc));
uint32_t entry_index = Pop().to<uint32_t>();
CommitPc(pc); // TODO(wasm): Be more disciplined about committing PC.
ExternalCallResult result =
@ -3303,7 +3303,7 @@ class ThreadImpl {
case kExprReturnCallIndirect: {
CallIndirectImmediate<Decoder::kNoValidate> imm(
kAllWasmFeatures, &decoder, code->at(pc));
WasmFeatures::All(), &decoder, code->at(pc));
uint32_t entry_index = Pop().to<uint32_t>();
CommitPc(pc); // TODO(wasm): Be more disciplined about committing PC.
@ -3798,7 +3798,7 @@ class ThreadImpl {
const WasmCode* code,
FunctionSig* sig) {
int num_args = static_cast<int>(sig->parameter_count());
WasmFeatures enabled_features = WasmFeaturesFromIsolate(isolate);
WasmFeatures enabled_features = WasmFeatures::FromIsolate(isolate);
if (code->kind() == WasmCode::kWasmToJsWrapper &&
!IsJSCompatibleSignature(sig, enabled_features)) {

View File

@ -40,7 +40,7 @@ class WasmStreaming::WasmStreamingImpl {
std::shared_ptr<internal::wasm::CompilationResultResolver> resolver)
: isolate_(isolate), resolver_(std::move(resolver)) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
streaming_decoder_ = i_isolate->wasm_engine()->StartStreamingCompilation(
i_isolate, enabled_features, handle(i_isolate->context(), i_isolate),
api_method_name, resolver_);
@ -518,7 +518,7 @@ void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
// Asynchronous compilation handles copying wire bytes if necessary.
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
std::move(resolver), bytes, is_shared,
kAPIMethodName);
@ -633,7 +633,7 @@ void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
bool validated = false;
if (is_shared) {
// Make a copy of the wire bytes to avoid concurrent modification.
@ -676,7 +676,7 @@ void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (thrower.error()) {
return;
}
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
i::MaybeHandle<i::Object> module_obj;
if (is_shared) {
// Make a copy of the wire bytes to avoid concurrent modification.
@ -973,7 +973,7 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
// Asynchronous compilation handles copying wire bytes if necessary.
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
std::move(compilation_resolver), bytes,
is_shared, kAPIMethodName);
@ -1043,8 +1043,8 @@ bool GetInitialOrMinimumProperty(v8::Isolate* isolate, ErrorThrower* thrower,
result, lower_bound, upper_bound)) {
return false;
}
auto enabled_features = i::wasm::WasmFeaturesFromFlags();
if (!has_initial && enabled_features.type_reflection) {
auto enabled_features = i::wasm::WasmFeatures::FromFlags();
if (!has_initial && enabled_features.has_type_reflection()) {
if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
v8_str(isolate, "minimum"), &has_initial,
result, lower_bound, upper_bound)) {
@ -1084,10 +1084,10 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (!maybe.ToLocal(&value)) return;
v8::Local<v8::String> string;
if (!value->ToString(context).ToLocal(&string)) return;
auto enabled_features = i::wasm::WasmFeaturesFromFlags();
auto enabled_features = i::wasm::WasmFeatures::FromFlags();
if (string->StringEquals(v8_str(isolate, "anyfunc"))) {
type = i::wasm::kWasmFuncRef;
} else if (enabled_features.anyref &&
} else if (enabled_features.has_anyref() &&
string->StringEquals(v8_str(isolate, "anyref"))) {
type = i::wasm::kWasmAnyRef;
} else {
@ -1149,8 +1149,8 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
auto shared = i::SharedFlag::kNotShared;
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
if (enabled_features.threads) {
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
if (enabled_features.has_threads()) {
// Shared property of descriptor
Local<String> shared_key = v8_str(isolate, "shared");
v8::MaybeLocal<v8::Value> maybe_value =
@ -1209,13 +1209,13 @@ bool GetValueType(Isolate* isolate, MaybeLocal<Value> maybe,
*type = i::wasm::kWasmI64;
} else if (string->StringEquals(v8_str(isolate, "f64"))) {
*type = i::wasm::kWasmF64;
} else if (enabled_features.anyref &&
} else if (enabled_features.has_anyref() &&
string->StringEquals(v8_str(isolate, "anyref"))) {
*type = i::wasm::kWasmAnyRef;
} else if (enabled_features.anyref &&
} else if (enabled_features.has_anyref() &&
string->StringEquals(v8_str(isolate, "anyfunc"))) {
*type = i::wasm::kWasmFuncRef;
} else if (enabled_features.eh &&
} else if (enabled_features.has_eh() &&
string->StringEquals(v8_str(isolate, "exnref"))) {
*type = i::wasm::kWasmExnRef;
} else {
@ -1241,7 +1241,7 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
Local<Context> context = isolate->GetCurrentContext();
Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
// The descriptor's 'mutable'.
bool is_mutable = false;
@ -1298,7 +1298,7 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
case i::wasm::kWasmI64: {
int64_t i64_value = 0;
if (!value->IsUndefined()) {
if (!enabled_features.bigint) {
if (!enabled_features.has_bigint()) {
thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
return;
}
@ -1406,7 +1406,7 @@ void WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
Local<Object> function_type = Local<Object>::Cast(args[0]);
Local<Context> context = isolate->GetCurrentContext();
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
// Load the 'parameters' property of the function type.
Local<String> parameters_key = v8_str(isolate, "parameters");
@ -1445,7 +1445,7 @@ void WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
thrower.TypeError("Argument 0 contains results without 'length'");
return;
}
if (results_len > (enabled_features.mv
if (results_len > (enabled_features.has_mv()
? i::wasm::kV8MaxWasmFunctionMultiReturns
: i::wasm::kV8MaxWasmFunctionReturns)) {
thrower.TypeError("Argument 0 contains too many results");
@ -1756,8 +1756,8 @@ void WebAssemblyGlobalGetValueCommon(
return_value.Set(receiver->GetI32());
break;
case i::wasm::kWasmI64: {
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
if (enabled_features.bigint) {
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
if (enabled_features.has_bigint()) {
Local<BigInt> value = BigInt::New(isolate, receiver->GetI64());
return_value.Set(value);
@ -1820,8 +1820,8 @@ void WebAssemblyGlobalSetValue(
break;
}
case i::wasm::kWasmI64: {
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
if (enabled_features.bigint) {
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
if (enabled_features.has_bigint()) {
v8::Local<v8::BigInt> bigint_value;
if (!args[0]->ToBigInt(context).ToLocal(&bigint_value)) return;
receiver->SetI64(bigint_value->Int64Value());
@ -2056,8 +2056,9 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
v8_str(isolate, "WebAssembly.Instance"), ro_attributes);
// The context is not set up completely yet. That's why we cannot use
// {WasmFeaturesFromIsolate} and have to use {WasmFeaturesFromFlags} instead.
auto enabled_features = i::wasm::WasmFeaturesFromFlags();
// {WasmFeatures::FromIsolate} and have to use {WasmFeatures::FromFlags}
// instead.
auto enabled_features = i::wasm::WasmFeatures::FromFlags();
// Setup Table
Handle<JSFunction> table_constructor =
@ -2074,7 +2075,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
InstallFunc(isolate, table_constructor, "type", WebAssemblyTableType, 1);
}
JSObject::AddProperty(isolate, table_proto, factory->to_string_tag_symbol(),
@ -2093,7 +2094,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
InstallFunc(isolate, memory_constructor, "type", WebAssemblyMemoryType, 1);
}
JSObject::AddProperty(isolate, memory_proto, factory->to_string_tag_symbol(),
@ -2113,14 +2114,14 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0);
InstallGetterSetter(isolate, global_proto, "value", WebAssemblyGlobalGetValue,
WebAssemblyGlobalSetValue);
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
InstallFunc(isolate, global_constructor, "type", WebAssemblyGlobalType, 1);
}
JSObject::AddProperty(isolate, global_proto, factory->to_string_tag_symbol(),
v8_str(isolate, "WebAssembly.Global"), ro_attributes);
// Setup Exception
if (enabled_features.eh) {
if (enabled_features.has_eh()) {
Handle<JSFunction> exception_constructor = InstallConstructorFunc(
isolate, webassembly, "Exception", WebAssemblyException);
context->set_wasm_exception_constructor(*exception_constructor);
@ -2135,7 +2136,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
}
// Setup Function
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
Handle<JSFunction> function_constructor = InstallConstructorFunc(
isolate, webassembly, "Function", WebAssemblyFunction);
SetDummyInstanceTemplate(isolate, function_constructor);

View File

@ -295,7 +295,8 @@ Handle<JSObject> GetTypeForTable(Isolate* isolate, ValueType type,
// and then use that constant everywhere.
element = factory->InternalizeUtf8String("anyfunc");
} else {
DCHECK(WasmFeaturesFromFlags().anyref && type == ValueType::kWasmAnyRef);
DCHECK(WasmFeatures::FromFlags().has_anyref() &&
type == ValueType::kWasmAnyRef);
element = factory->InternalizeUtf8String("anyref");
}
@ -317,7 +318,7 @@ Handle<JSObject> GetTypeForTable(Isolate* isolate, ValueType type,
Handle<JSArray> GetImports(Isolate* isolate,
Handle<WasmModuleObject> module_object) {
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(isolate);
Factory* factory = isolate->factory();
Handle<String> module_string = factory->InternalizeUtf8String("module");
@ -352,14 +353,14 @@ Handle<JSArray> GetImports(Isolate* isolate,
Handle<JSObject> type_value;
switch (import.kind) {
case kExternalFunction:
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
auto& func = module->functions[import.index];
type_value = GetTypeForFunction(isolate, func.sig);
}
import_kind = function_string;
break;
case kExternalTable:
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
auto& table = module->tables[import.index];
base::Optional<uint32_t> maximum_size;
if (table.has_maximum_size) maximum_size.emplace(table.maximum_size);
@ -369,7 +370,7 @@ Handle<JSArray> GetImports(Isolate* isolate,
import_kind = table_string;
break;
case kExternalMemory:
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
DCHECK_EQ(0, import.index); // Only one memory supported.
base::Optional<uint32_t> maximum_size;
if (module->has_maximum_pages) {
@ -381,7 +382,7 @@ Handle<JSArray> GetImports(Isolate* isolate,
import_kind = memory_string;
break;
case kExternalGlobal:
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
auto& global = module->globals[import.index];
type_value =
GetTypeForGlobal(isolate, global.mutability, global.type);
@ -420,7 +421,7 @@ Handle<JSArray> GetImports(Isolate* isolate,
Handle<JSArray> GetExports(Isolate* isolate,
Handle<WasmModuleObject> module_object) {
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(isolate);
Factory* factory = isolate->factory();
Handle<String> name_string = factory->InternalizeUtf8String("name");
@ -452,14 +453,14 @@ Handle<JSArray> GetExports(Isolate* isolate,
Handle<JSObject> type_value;
switch (exp.kind) {
case kExternalFunction:
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
auto& func = module->functions[exp.index];
type_value = GetTypeForFunction(isolate, func.sig);
}
export_kind = function_string;
break;
case kExternalTable:
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
auto& table = module->tables[exp.index];
base::Optional<uint32_t> maximum_size;
if (table.has_maximum_size) maximum_size.emplace(table.maximum_size);
@ -469,7 +470,7 @@ Handle<JSArray> GetExports(Isolate* isolate,
export_kind = table_string;
break;
case kExternalMemory:
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
DCHECK_EQ(0, exp.index); // Only one memory supported.
base::Optional<uint32_t> maximum_size;
if (module->has_maximum_pages) {
@ -481,7 +482,7 @@ Handle<JSArray> GetExports(Isolate* isolate,
export_kind = memory_string;
break;
case kExternalGlobal:
if (enabled_features.type_reflection) {
if (enabled_features.has_type_reflection()) {
auto& global = module->globals[exp.index];
type_value =
GetTypeForGlobal(isolate, global.mutability, global.type);

View File

@ -28,7 +28,7 @@ class NativeModule;
class SignatureMap;
class WasmCode;
struct WasmException;
struct WasmFeatures;
class WasmFeatures;
struct WasmGlobal;
class WasmInterpreter;
struct WasmModule;

View File

@ -474,11 +474,11 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
bool IsJSCompatibleSignature(const FunctionSig* sig,
const WasmFeatures& enabled_features) {
if (!enabled_features.mv && sig->return_count() > 1) {
if (!enabled_features.has_mv() && sig->return_count() > 1) {
return false;
}
for (auto type : sig->all()) {
if (!enabled_features.bigint && type == kWasmI64) {
if (!enabled_features.has_bigint() && type == kWasmI64) {
return false;
}

View File

@ -15,7 +15,7 @@ namespace internal {
namespace wasm {
struct WasmFeatures;
class WasmFeatures;
std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
bool IsJSCompatibleSignature(const FunctionSig* sig, const WasmFeatures&);

View File

@ -498,7 +498,7 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
size_t code_section_size = reader->Read<size_t>();
if (code_section_size == 0) {
DCHECK(FLAG_wasm_lazy_compilation ||
native_module_->enabled_features().compilation_hints);
native_module_->enabled_features().has_compilation_hints());
native_module_->UseLazyStub(fn_index);
return true;
}
@ -608,7 +608,7 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule(
ModuleWireBytes wire_bytes(wire_bytes_vec);
// TODO(titzer): module features should be part of the serialization format.
WasmFeatures enabled_features = WasmFeaturesFromIsolate(isolate);
WasmFeatures enabled_features = WasmFeatures::FromIsolate(isolate);
ModuleResult decode_result =
DecodeWasmModule(enabled_features, wire_bytes.start(), wire_bytes.end(),
false, i::wasm::kWasmOrigin, isolate->counters(),

View File

@ -102,7 +102,7 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
case kExprIf:
case kExprBlock:
case kExprTry: {
BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
BlockTypeImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(), &i,
i.pc());
os << WasmOpcodes::OpcodeName(opcode);
if (imm.type == kWasmBottom) {
@ -142,7 +142,7 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
}
case kExprCallIndirect:
case kExprReturnCallIndirect: {
CallIndirectImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
CallIndirectImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(), &i,
i.pc());
DCHECK_EQ(0, imm.table_index);
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.sig_index;

View File

@ -169,6 +169,11 @@ class CcTest {
static v8::Local<v8::Context> NewContext(
CcTestExtensionFlags extension_flags,
v8::Isolate* isolate = CcTest::isolate());
static v8::Local<v8::Context> NewContext(
std::initializer_list<CcTestExtensionId> extensions,
v8::Isolate* isolate = CcTest::isolate()) {
return NewContext(CcTestExtensionFlags{extensions}, isolate);
}
static void TearDown();

View File

@ -126,7 +126,7 @@ std::shared_ptr<wasm::NativeModule> AllocateNativeModule(Isolate* isolate,
// WasmCallDescriptor assumes that code is on the native heap and not
// within a code object.
return isolate->wasm_engine()->NewNativeModule(
isolate, wasm::kAllWasmFeatures, std::move(module), code_size);
isolate, wasm::WasmFeatures::All(), std::move(module), code_size);
}
void TestReturnMultipleValues(MachineType type) {

View File

@ -968,7 +968,7 @@ TEST(AtomicOpDisassembly) {
testing::SetupIsolateForWasmModule(isolate);
ErrorThrower thrower(isolate, "Test");
auto enabled_features = WasmFeaturesFromIsolate(isolate);
auto enabled_features = WasmFeatures::FromIsolate(isolate);
Handle<WasmModuleObject> module_object =
isolate->wasm_engine()
->SyncCompile(isolate, enabled_features, &thrower,

View File

@ -131,7 +131,7 @@ class StreamTester {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
stream_ = i_isolate->wasm_engine()->StartStreamingCompilation(
i_isolate, kAllWasmFeatures, v8::Utils::OpenHandle(*context),
i_isolate, WasmFeatures::All(), v8::Utils::OpenHandle(*context),
"WebAssembly.compileStreaming()",
std::make_shared<TestResolver>(&state_, &error_message_,
&native_module_));
@ -263,9 +263,10 @@ STREAM_TEST(TestAllBytesArriveAOTCompilerFinishesFirst) {
size_t GetFunctionOffset(i::Isolate* isolate, const uint8_t* buffer,
size_t size, size_t index) {
ModuleResult result = DecodeWasmModule(
kAllWasmFeatures, buffer, buffer + size, false, ModuleOrigin::kWasmOrigin,
isolate->counters(), isolate->wasm_engine()->allocator());
ModuleResult result =
DecodeWasmModule(WasmFeatures::All(), buffer, buffer + size, false,
ModuleOrigin::kWasmOrigin, isolate->counters(),
isolate->wasm_engine()->allocator());
CHECK(result.ok());
const WasmFunction* func = &result.value()->functions[index];
return func->code.offset();

View File

@ -22,7 +22,7 @@ std::shared_ptr<NativeModule> NewModule(Isolate* isolate) {
std::shared_ptr<WasmModule> module(new WasmModule);
constexpr size_t kCodeSizeEstimate = 16384;
return isolate->wasm_engine()->NewNativeModule(
isolate, kAllWasmFeatures, std::move(module), kCodeSizeEstimate);
isolate, WasmFeatures::All(), std::move(module), kCodeSizeEstimate);
}
TEST(CacheHit) {

View File

@ -146,7 +146,7 @@ class WasmSerializationTest {
HandleScope scope(serialization_isolate);
testing::SetupIsolateForWasmModule(serialization_isolate);
auto enabled_features = WasmFeaturesFromIsolate(serialization_isolate);
auto enabled_features = WasmFeatures::FromIsolate(serialization_isolate);
MaybeHandle<WasmModuleObject> maybe_module_object =
serialization_isolate->wasm_engine()->SyncCompile(
serialization_isolate, enabled_features, &thrower,
@ -291,7 +291,7 @@ UNINITIALIZED_TEST(CompiledWasmModulesTransfer) {
Isolate* from_i_isolate = reinterpret_cast<Isolate*>(from_isolate);
testing::SetupIsolateForWasmModule(from_i_isolate);
ErrorThrower thrower(from_i_isolate, "TestCompiledWasmModulesTransfer");
auto enabled_features = WasmFeaturesFromIsolate(from_i_isolate);
auto enabled_features = WasmFeatures::FromIsolate(from_i_isolate);
MaybeHandle<WasmModuleObject> maybe_module_object =
from_i_isolate->wasm_engine()->SyncCompile(
from_i_isolate, enabled_features, &thrower,

View File

@ -187,7 +187,7 @@ void PumpMessageLoop(SharedEngineIsolate* isolate) {
Handle<WasmInstanceObject> CompileAndInstantiateAsync(
SharedEngineIsolate* isolate, ZoneBuffer* buffer) {
Handle<Object> maybe_instance = handle(Smi::zero(), isolate->isolate());
auto enabled_features = WasmFeaturesFromIsolate(isolate->isolate());
auto enabled_features = WasmFeatures::FromIsolate(isolate->isolate());
constexpr const char* kAPIMethodName = "Test.CompileAndInstantiateAsync";
isolate->isolate()->wasm_engine()->AsyncCompile(
isolate->isolate(), enabled_features,
@ -350,7 +350,7 @@ TEST(SharedEngineRunThreadedTierUp) {
threads.emplace_back(&engine, [module](SharedEngineIsolate* isolate) {
HandleScope scope(isolate->isolate());
Handle<WasmInstanceObject> instance = isolate->ImportInstance(module);
WasmFeatures detected = kNoWasmFeatures;
WasmFeatures detected = WasmFeatures::None();
WasmCompilationUnit::CompileWasmFunction(
isolate->isolate(), module.get(), &detected,
&module->module()->functions[0], ExecutionTier::kTurbofan);

View File

@ -22,7 +22,7 @@ TestingModuleBuilder::TestingModuleBuilder(
: test_module_(std::make_shared<WasmModule>()),
test_module_ptr_(test_module_.get()),
isolate_(CcTest::InitIsolateOnce()),
enabled_features_(WasmFeaturesFromIsolate(isolate_)),
enabled_features_(WasmFeatures::FromIsolate(isolate_)),
execution_tier_(tier),
runtime_exception_support_(exception_support),
lower_simd_(lower_simd) {
@ -346,14 +346,14 @@ void TestBuildingGraphWithBuilder(compiler::WasmGraphBuilder* builder,
WasmFeatures unused_detected_features;
FunctionBody body(sig, 0, start, end);
DecodeResult result =
BuildTFGraph(zone->allocator(), kAllWasmFeatures, nullptr, builder,
BuildTFGraph(zone->allocator(), WasmFeatures::All(), nullptr, builder,
&unused_detected_features, body, nullptr);
if (result.failed()) {
#ifdef DEBUG
if (!FLAG_trace_wasm_decoder) {
// Retry the compilation with the tracing flag on, to help in debugging.
FLAG_trace_wasm_decoder = true;
result = BuildTFGraph(zone->allocator(), kAllWasmFeatures, nullptr,
result = BuildTFGraph(zone->allocator(), WasmFeatures::All(), nullptr,
builder, &unused_detected_features, body, nullptr);
}
#endif

View File

@ -5,6 +5,8 @@
#ifndef V8_TEST_COMMON_FLAG_UTILS_H
#define V8_TEST_COMMON_FLAG_UTILS_H
#include "src/wasm/wasm-features.h"
namespace v8 {
namespace internal {
@ -26,6 +28,40 @@ class FlagScope {
#define EXPERIMENTAL_FLAG_SCOPE(flag) FLAG_SCOPE(experimental_wasm_##flag)
namespace wasm {
class WasmFeatureScope {
public:
explicit WasmFeatureScope(WasmFeatures* features, WasmFeature feature,
bool val = true)
: prev_(features->contains(feature)),
feature_(feature),
features_(features) {
set(val);
}
~WasmFeatureScope() { set(prev_); }
private:
void set(bool val) {
if (val) {
features_->Add(feature_);
} else {
features_->Remove(feature_);
}
}
bool const prev_;
WasmFeature const feature_;
WasmFeatures* const features_;
};
#define WASM_FEATURE_SCOPE(feat) \
WasmFeatureScope feat##_scope(&this->enabled_features_, kFeature_##feat)
#define WASM_FEATURE_SCOPE_VAL(feat, val) \
WasmFeatureScope feat##_scope(&this->enabled_features_, kFeature_##feat, val)
} // namespace wasm
} // namespace internal
} // namespace v8

View File

@ -29,7 +29,7 @@ uint32_t GetInitialMemSize(const WasmModule* module) {
MaybeHandle<WasmModuleObject> CompileForTesting(Isolate* isolate,
ErrorThrower* thrower,
const ModuleWireBytes& bytes) {
auto enabled_features = WasmFeaturesFromIsolate(isolate);
auto enabled_features = WasmFeatures::FromIsolate(isolate);
MaybeHandle<WasmModuleObject> module = isolate->wasm_engine()->SyncCompile(
isolate, enabled_features, thrower, bytes);
DCHECK_EQ(thrower->error(), module.is_null());
@ -50,7 +50,7 @@ std::shared_ptr<WasmModule> DecodeWasmModuleForTesting(
const byte* module_end, ModuleOrigin origin, bool verify_functions) {
// Decode the module, but don't verify function bodies, since we'll
// be compiling them anyway.
auto enabled_features = WasmFeaturesFromIsolate(isolate);
auto enabled_features = WasmFeatures::FromIsolate(isolate);
ModuleResult decoding_result = DecodeWasmModule(
enabled_features, module_start, module_end, verify_functions, origin,
isolate->counters(), isolate->wasm_engine()->allocator());

View File

@ -143,7 +143,7 @@ std::shared_ptr<wasm::NativeModule> AllocateNativeModule(i::Isolate* isolate,
// WasmCallDescriptor assumes that code is on the native heap and not
// within a code object.
return isolate->wasm_engine()->NewNativeModule(
isolate, i::wasm::kAllWasmFeatures, std::move(module), code_size);
isolate, i::wasm::WasmFeatures::All(), std::move(module), code_size);
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {

View File

@ -68,7 +68,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
testing::SetupIsolateForWasmModule(i_isolate);
bool done = false;
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
constexpr const char* kAPIMethodName = "WasmAsyncFuzzer.compile";
i_isolate->wasm_engine()->AsyncCompile(
i_isolate, enabled_features,

View File

@ -120,7 +120,7 @@ std::ostream& operator<<(std::ostream& os, const PrintName& name) {
void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes,
bool compiles) {
constexpr bool kVerifyFunctions = false;
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(isolate);
ModuleResult module_res = DecodeWasmModule(
enabled_features, wire_bytes.start(), wire_bytes.end(), kVerifyFunctions,
ModuleOrigin::kWasmOrigin, isolate->counters(),
@ -306,7 +306,7 @@ void WasmExecutionFuzzer::FuzzWasmModule(Vector<const uint8_t> data,
ModuleWireBytes wire_bytes(buffer.begin(), buffer.end());
// Compile with Turbofan here. Liftoff will be tested later.
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
MaybeHandle<WasmModuleObject> compiled_module;
{
// Explicitly enable Liftoff, disable tiering and set the tier_mask. This

View File

@ -53,7 +53,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
i::HandleScope scope(i_isolate);
i::wasm::ErrorThrower thrower(i_isolate, "wasm fuzzer");
i::Handle<i::WasmModuleObject> module_object;
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
bool compiles =
i_isolate->wasm_engine()
->SyncCompile(i_isolate, enabled_features, &thrower, wire_bytes)

View File

@ -60,7 +60,7 @@ class FunctionBodyDecoderTest : public TestWithZone {
using LocalsDecl = std::pair<uint32_t, ValueType>;
// All features are disabled by default and must be activated with
// a WASM_FEATURE_SCOPE in individual tests.
WasmFeatures enabled_features_;
WasmFeatures enabled_features_ = WasmFeatures::None();
FunctionBodyDecoderTest() : module(nullptr), local_decls(zone()) {}
@ -117,7 +117,7 @@ class FunctionBodyDecoderTest : public TestWithZone {
// Validate the code.
FunctionBody body(sig, 0, code.begin(), code.end());
WasmFeatures unused_detected_features;
WasmFeatures unused_detected_features = WasmFeatures::None();
DecodeResult result =
VerifyWasmCode(zone()->allocator(), enabled_features_, module,
&unused_detected_features, body);
@ -200,17 +200,6 @@ class FunctionBodyDecoderTest : public TestWithZone {
namespace {
class EnableBoolScope {
public:
bool prev_;
bool* ptr_;
explicit EnableBoolScope(bool* ptr) : prev_(*ptr), ptr_(ptr) { *ptr = true; }
~EnableBoolScope() { *ptr_ = prev_; }
};
#define WASM_FEATURE_SCOPE(feat) \
EnableBoolScope feat##_scope(&this->enabled_features_.feat);
constexpr size_t kMaxByteSizedLeb128 = 127;
// A helper for tests that require a module environment for functions,
@ -3075,7 +3064,7 @@ TEST_F(FunctionBodyDecoderTest, Regression709741) {
FunctionBody body(sigs.v_v(), 0, code, code + i);
WasmFeatures unused_detected_features;
DecodeResult result =
VerifyWasmCode(zone()->allocator(), kAllWasmFeatures, nullptr,
VerifyWasmCode(zone()->allocator(), WasmFeatures::All(), nullptr,
&unused_detected_features, body);
if (result.ok()) {
std::ostringstream str;
@ -3811,7 +3800,6 @@ TEST_F(BytecodeIteratorTest, WithLocalDecls) {
EXPECT_FALSE(iter.has_next());
}
#undef WASM_FEATURE_SCOPE
#undef B1
#undef B2
#undef B3

View File

@ -173,7 +173,7 @@ struct ValueTypePair {
class WasmModuleVerifyTest : public TestWithIsolateAndZone {
public:
WasmFeatures enabled_features_;
WasmFeatures enabled_features_ = WasmFeatures::None();
ModuleResult DecodeModule(const byte* module_start, const byte* module_end) {
// Add the wasm magic and version number automatically.
@ -199,25 +199,6 @@ class WasmModuleVerifyTest : public TestWithIsolateAndZone {
}
};
namespace {
class EnableBoolScope {
public:
bool prev_;
bool* ptr_;
explicit EnableBoolScope(bool* ptr, bool val = true)
: prev_(*ptr), ptr_(ptr) {
*ptr = val;
}
~EnableBoolScope() { *ptr_ = prev_; }
};
#define WASM_FEATURE_SCOPE(feat) \
EnableBoolScope feat##_scope(&this->enabled_features_.feat)
#define WASM_FEATURE_SCOPE_VAL(feat, val) \
EnableBoolScope feat##_scope(&this->enabled_features_.feat, val)
} // namespace
TEST_F(WasmModuleVerifyTest, WrongMagic) {
for (uint32_t x = 1; x; x <<= 1) {
const byte data[] = {U32_LE(kWasmMagic ^ x), U32_LE(kWasmVersion)};
@ -1426,7 +1407,7 @@ TEST_F(WasmModuleVerifyTest, TieringCompilationHints) {
class WasmSignatureDecodeTest : public TestWithZone {
public:
WasmFeatures enabled_features_;
WasmFeatures enabled_features_ = WasmFeatures::None();
FunctionSig* DecodeSig(const byte* start, const byte* end) {
return DecodeWasmSignatureForTesting(enabled_features_, zone(), start, end);
@ -2546,8 +2527,6 @@ TEST_F(WasmModuleVerifyTest, DataCountSegmentCount_omitted) {
EXPECT_NOT_OK(result, "data segments count 0 mismatch (1 expected)");
}
#undef WASM_FEATURE_SCOPE
#undef WASM_FEATURE_SCOPE_VAL
#undef EXPECT_INIT_EXPR
#undef EXPECT_INIT_EXPR_FAIL
#undef WASM_INIT_EXPR_I32V_1

View File

@ -58,7 +58,7 @@ TEST_F(WasmCapiTest, Traps) {
i::Isolate* isolate =
reinterpret_cast<::wasm::StoreImpl*>(store())->i_isolate();
ModuleResult result = DecodeWasmModule(
kAllWasmFeatures, wire_bytes()->begin(), wire_bytes()->end(), false,
WasmFeatures::All(), wire_bytes()->begin(), wire_bytes()->end(), false,
ModuleOrigin::kWasmOrigin, isolate->counters(),
isolate->wasm_engine()->allocator());
ASSERT_TRUE(result.ok());