aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/wasm/baseline/liftoff-compiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/wasm/baseline/liftoff-compiler.cc')
-rw-r--r--deps/v8/src/wasm/baseline/liftoff-compiler.cc251
1 files changed, 153 insertions, 98 deletions
diff --git a/deps/v8/src/wasm/baseline/liftoff-compiler.cc b/deps/v8/src/wasm/baseline/liftoff-compiler.cc
index caf00a24ca..7a87ae1a95 100644
--- a/deps/v8/src/wasm/baseline/liftoff-compiler.cc
+++ b/deps/v8/src/wasm/baseline/liftoff-compiler.cc
@@ -174,7 +174,8 @@ class LiftoffCompiler {
compilation_zone_(compilation_zone),
safepoint_table_builder_(compilation_zone_) {}
- bool ok() const { return ok_; }
+ bool did_bailout() const { return bailout_reason_ != kSuccess; }
+ LiftoffBailoutReason bailout_reason() const { return bailout_reason_; }
void GetCode(CodeDesc* desc) {
asm_.GetCode(nullptr, desc, &safepoint_table_builder_,
@@ -195,30 +196,51 @@ class LiftoffCompiler {
return __ GetTotalFrameSlotCount();
}
- void unsupported(FullDecoder* decoder, const char* reason) {
- ok_ = false;
- TRACE("unsupported: %s\n", reason);
+ void unsupported(FullDecoder* decoder, LiftoffBailoutReason reason,
+ const char* detail) {
+ DCHECK_NE(kSuccess, reason);
+ if (did_bailout()) return;
+ bailout_reason_ = reason;
+ TRACE("unsupported: %s\n", detail);
decoder->errorf(decoder->pc_offset(), "unsupported liftoff operation: %s",
- reason);
+ detail);
UnuseLabels(decoder);
}
bool DidAssemblerBailout(FullDecoder* decoder) {
if (decoder->failed() || !__ did_bailout()) return false;
- unsupported(decoder, __ bailout_reason());
+ unsupported(decoder, __ bailout_reason(), __ bailout_detail());
return true;
}
+ LiftoffBailoutReason BailoutReasonForType(ValueType type) {
+ switch (type) {
+ case kWasmS128:
+ return kSimd;
+ case kWasmAnyRef:
+ case kWasmFuncRef:
+ case kWasmNullRef:
+ return kAnyRef;
+ case kWasmExnRef:
+ return kExceptionHandling;
+ case kWasmBottom:
+ return kMultiValue;
+ default:
+ return kOtherReason;
+ }
+ }
+
bool CheckSupportedType(FullDecoder* decoder,
Vector<const ValueType> supported_types,
ValueType type, const char* context) {
- char buffer[128];
// Check supported types.
for (ValueType supported : supported_types) {
if (type == supported) return true;
}
- SNPrintF(ArrayVector(buffer), "%s %s", ValueTypes::TypeName(type), context);
- unsupported(decoder, buffer);
+ LiftoffBailoutReason bailout_reason = BailoutReasonForType(type);
+ EmbeddedVector<char, 128> buffer;
+ SNPrintF(buffer, "%s %s", ValueTypes::TypeName(type), context);
+ unsupported(decoder, bailout_reason, buffer.begin());
return false;
}
@@ -394,17 +416,17 @@ class LiftoffCompiler {
DCHECK_EQ(__ num_locals(), __ cache_state()->stack_height());
}
- void GenerateOutOfLineCode(OutOfLineCode& ool) {
- __ bind(ool.label.get());
- const bool is_stack_check = ool.stub == WasmCode::kWasmStackGuard;
+ void GenerateOutOfLineCode(OutOfLineCode* ool) {
+ __ bind(ool->label.get());
+ const bool is_stack_check = ool->stub == WasmCode::kWasmStackGuard;
const bool is_mem_out_of_bounds =
- ool.stub == WasmCode::kThrowWasmTrapMemOutOfBounds;
+ ool->stub == WasmCode::kThrowWasmTrapMemOutOfBounds;
if (is_mem_out_of_bounds && env_->use_trap_handler) {
uint32_t pc = static_cast<uint32_t>(__ pc_offset());
DCHECK_EQ(pc, __ pc_offset());
protected_instructions_.emplace_back(
- trap_handler::ProtectedInstructionData{ool.pc, pc});
+ trap_handler::ProtectedInstructionData{ool->pc, pc});
}
if (!env_->runtime_exception_support) {
@@ -419,16 +441,16 @@ class LiftoffCompiler {
return;
}
- if (!ool.regs_to_save.is_empty()) __ PushRegisters(ool.regs_to_save);
+ if (!ool->regs_to_save.is_empty()) __ PushRegisters(ool->regs_to_save);
source_position_table_builder_.AddPosition(
- __ pc_offset(), SourcePosition(ool.position), false);
- __ CallRuntimeStub(ool.stub);
+ __ pc_offset(), SourcePosition(ool->position), false);
+ __ CallRuntimeStub(ool->stub);
safepoint_table_builder_.DefineSafepoint(&asm_, Safepoint::kNoLazyDeopt);
- DCHECK_EQ(ool.continuation.get()->is_bound(), is_stack_check);
- if (!ool.regs_to_save.is_empty()) __ PopRegisters(ool.regs_to_save);
+ DCHECK_EQ(ool->continuation.get()->is_bound(), is_stack_check);
+ if (!ool->regs_to_save.is_empty()) __ PopRegisters(ool->regs_to_save);
if (is_stack_check) {
- __ emit_jump(ool.continuation.get());
+ __ emit_jump(ool->continuation.get());
} else {
__ AssertUnreachable(AbortReason::kUnexpectedReturnFromWasmTrap);
}
@@ -437,7 +459,7 @@ class LiftoffCompiler {
void FinishFunction(FullDecoder* decoder) {
if (DidAssemblerBailout(decoder)) return;
for (OutOfLineCode& ool : out_of_line_code_) {
- GenerateOutOfLineCode(ool);
+ GenerateOutOfLineCode(&ool);
}
__ PatchPrepareStackFrame(pc_offset_stack_frame_construction_,
__ GetTotalFrameSlotCount());
@@ -449,7 +471,7 @@ class LiftoffCompiler {
}
void OnFirstError(FullDecoder* decoder) {
- ok_ = false;
+ if (!did_bailout()) bailout_reason_ = kDecodeError;
UnuseLabels(decoder);
asm_.AbortCompilation();
}
@@ -481,19 +503,20 @@ class LiftoffCompiler {
}
void Try(FullDecoder* decoder, Control* block) {
- unsupported(decoder, "try");
+ unsupported(decoder, kExceptionHandling, "try");
}
void Catch(FullDecoder* decoder, Control* block, Value* exception) {
- unsupported(decoder, "catch");
+ unsupported(decoder, kExceptionHandling, "catch");
}
void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
DCHECK_EQ(if_block, decoder->control_at(0));
DCHECK(if_block->is_if());
- if (if_block->start_merge.arity > 0 || if_block->end_merge.arity > 1)
- return unsupported(decoder, "multi-value if");
+ if (if_block->start_merge.arity > 0 || if_block->end_merge.arity > 1) {
+ return unsupported(decoder, kMultiValue, "multi-value if");
+ }
// Allocate the else state.
if_block->else_state = base::make_unique<ElseState>();
@@ -773,8 +796,23 @@ class LiftoffCompiler {
__ emit_i64_eqz(dst.gp(), src);
});
break;
+ case WasmOpcode::kExprI64Clz:
+ case WasmOpcode::kExprI64Ctz:
+ case WasmOpcode::kExprI64Popcnt:
+ return unsupported(decoder, kComplexOperation,
+ WasmOpcodes::OpcodeName(opcode));
+ case WasmOpcode::kExprI32SConvertSatF32:
+ case WasmOpcode::kExprI32UConvertSatF32:
+ case WasmOpcode::kExprI32SConvertSatF64:
+ case WasmOpcode::kExprI32UConvertSatF64:
+ case WasmOpcode::kExprI64SConvertSatF32:
+ case WasmOpcode::kExprI64UConvertSatF32:
+ case WasmOpcode::kExprI64SConvertSatF64:
+ case WasmOpcode::kExprI64UConvertSatF64:
+ return unsupported(decoder, kNonTrappingFloatToInt,
+ WasmOpcodes::OpcodeName(opcode));
default:
- return unsupported(decoder, WasmOpcodes::OpcodeName(opcode));
+ UNREACHABLE();
}
#undef CASE_I32_UNOP
#undef CASE_I32_SIGN_EXTENSION
@@ -1104,8 +1142,12 @@ class LiftoffCompiler {
}
});
break;
+ case WasmOpcode::kExprI64Rol:
+ case WasmOpcode::kExprI64Ror:
+ return unsupported(decoder, kComplexOperation,
+ WasmOpcodes::OpcodeName(opcode));
default:
- return unsupported(decoder, WasmOpcodes::OpcodeName(opcode));
+ UNREACHABLE();
}
#undef CASE_I32_BINOP
#undef CASE_I32_BINOPI
@@ -1153,11 +1195,11 @@ class LiftoffCompiler {
}
void RefNull(FullDecoder* decoder, Value* result) {
- unsupported(decoder, "ref_null");
+ unsupported(decoder, kAnyRef, "ref_null");
}
void RefFunc(FullDecoder* decoder, uint32_t function_index, Value* result) {
- unsupported(decoder, "func");
+ unsupported(decoder, kAnyRef, "func");
}
void Drop(FullDecoder* decoder, const Value& value) {
@@ -1169,7 +1211,9 @@ class LiftoffCompiler {
void ReturnImpl(FullDecoder* decoder) {
size_t num_returns = decoder->sig_->return_count();
- if (num_returns > 1) return unsupported(decoder, "multi-return");
+ if (num_returns > 1) {
+ return unsupported(decoder, kMultiValue, "multi-return");
+ }
if (num_returns > 0) __ MoveToReturnRegisters(decoder->sig_);
__ LeaveFrame(StackFrame::WASM_COMPILED);
__ DropStackSlotsAndRet(
@@ -1201,24 +1245,24 @@ class LiftoffCompiler {
}
}
- void SetLocalFromStackSlot(LiftoffAssembler::VarState& dst_slot,
+ void SetLocalFromStackSlot(LiftoffAssembler::VarState* dst_slot,
uint32_t local_index) {
auto& state = *__ cache_state();
- ValueType type = dst_slot.type();
- if (dst_slot.is_reg()) {
- LiftoffRegister slot_reg = dst_slot.reg();
+ ValueType type = dst_slot->type();
+ if (dst_slot->is_reg()) {
+ LiftoffRegister slot_reg = dst_slot->reg();
if (state.get_use_count(slot_reg) == 1) {
- __ Fill(dst_slot.reg(), state.stack_height() - 1, type);
+ __ Fill(dst_slot->reg(), state.stack_height() - 1, type);
return;
}
state.dec_used(slot_reg);
- dst_slot.MakeStack();
+ dst_slot->MakeStack();
}
DCHECK_EQ(type, __ local_type(local_index));
RegClass rc = reg_class_for(type);
LiftoffRegister dst_reg = __ GetUnusedRegister(rc);
__ Fill(dst_reg, __ cache_state()->stack_height() - 1, type);
- dst_slot = LiftoffAssembler::VarState(type, dst_reg);
+ *dst_slot = LiftoffAssembler::VarState(type, dst_reg);
__ cache_state()->inc_used(dst_reg);
}
@@ -1237,7 +1281,7 @@ class LiftoffCompiler {
target_slot = source_slot;
break;
case kStack:
- SetLocalFromStackSlot(target_slot, local_index);
+ SetLocalFromStackSlot(&target_slot, local_index);
break;
}
if (!is_tee) __ cache_state()->stack_state.pop_back();
@@ -1254,12 +1298,12 @@ class LiftoffCompiler {
}
Register GetGlobalBaseAndOffset(const WasmGlobal* global,
- LiftoffRegList& pinned, uint32_t* offset) {
- Register addr = pinned.set(__ GetUnusedRegister(kGpReg)).gp();
+ LiftoffRegList* pinned, uint32_t* offset) {
+ Register addr = pinned->set(__ GetUnusedRegister(kGpReg)).gp();
if (global->mutability && global->imported) {
LOAD_INSTANCE_FIELD(addr, ImportedMutableGlobals, kSystemPointerSize);
__ Load(LiftoffRegister(addr), addr, no_reg,
- global->index * sizeof(Address), kPointerLoadType, pinned);
+ global->index * sizeof(Address), kPointerLoadType, *pinned);
*offset = 0;
} else {
LOAD_INSTANCE_FIELD(addr, GlobalsStart, kSystemPointerSize);
@@ -1275,7 +1319,7 @@ class LiftoffCompiler {
return;
LiftoffRegList pinned;
uint32_t offset = 0;
- Register addr = GetGlobalBaseAndOffset(global, pinned, &offset);
+ Register addr = GetGlobalBaseAndOffset(global, &pinned, &offset);
LiftoffRegister value =
pinned.set(__ GetUnusedRegister(reg_class_for(global->type), pinned));
LoadType type = LoadType::ForValueType(global->type);
@@ -1290,20 +1334,20 @@ class LiftoffCompiler {
return;
LiftoffRegList pinned;
uint32_t offset = 0;
- Register addr = GetGlobalBaseAndOffset(global, pinned, &offset);
+ Register addr = GetGlobalBaseAndOffset(global, &pinned, &offset);
LiftoffRegister reg = pinned.set(__ PopToRegister(pinned));
StoreType type = StoreType::ForValueType(global->type);
__ Store(addr, no_reg, offset, reg, type, {}, nullptr, true);
}
- void GetTable(FullDecoder* decoder, const Value& index, Value* result,
- TableIndexImmediate<validate>& imm) {
- unsupported(decoder, "table_get");
+ void TableGet(FullDecoder* decoder, const Value& index, Value* result,
+ const TableIndexImmediate<validate>& imm) {
+ unsupported(decoder, kAnyRef, "table_get");
}
- void SetTable(FullDecoder* decoder, const Value& index, const Value& value,
- TableIndexImmediate<validate>& imm) {
- unsupported(decoder, "table_set");
+ void TableSet(FullDecoder* decoder, const Value& index, const Value& value,
+ const TableIndexImmediate<validate>& imm) {
+ unsupported(decoder, kAnyRef, "table_set");
}
void Unreachable(FullDecoder* decoder) {
@@ -1370,8 +1414,8 @@ class LiftoffCompiler {
// Generate a branch table case, potentially reusing previously generated
// stack transfer code.
void GenerateBrCase(FullDecoder* decoder, uint32_t br_depth,
- std::map<uint32_t, MovableLabel>& br_targets) {
- MovableLabel& label = br_targets[br_depth];
+ std::map<uint32_t, MovableLabel>* br_targets) {
+ MovableLabel& label = (*br_targets)[br_depth];
if (label.get()->is_bound()) {
__ jmp(label.get());
} else {
@@ -1384,13 +1428,13 @@ class LiftoffCompiler {
// TODO(wasm): Generate a real branch table (like TF TableSwitch).
void GenerateBrTable(FullDecoder* decoder, LiftoffRegister tmp,
LiftoffRegister value, uint32_t min, uint32_t max,
- BranchTableIterator<validate>& table_iterator,
- std::map<uint32_t, MovableLabel>& br_targets) {
+ BranchTableIterator<validate>* table_iterator,
+ std::map<uint32_t, MovableLabel>* br_targets) {
DCHECK_LT(min, max);
// Check base case.
if (max == min + 1) {
- DCHECK_EQ(min, table_iterator.cur_index());
- GenerateBrCase(decoder, table_iterator.next(), br_targets);
+ DCHECK_EQ(min, table_iterator->cur_index());
+ GenerateBrCase(decoder, table_iterator->next(), br_targets);
return;
}
@@ -1422,14 +1466,14 @@ class LiftoffCompiler {
__ emit_cond_jump(kUnsignedGreaterEqual, &case_default, kWasmI32,
value.gp(), tmp.gp());
- GenerateBrTable(decoder, tmp, value, 0, imm.table_count, table_iterator,
- br_targets);
+ GenerateBrTable(decoder, tmp, value, 0, imm.table_count, &table_iterator,
+ &br_targets);
__ bind(&case_default);
}
// Generate the default case.
- GenerateBrCase(decoder, table_iterator.next(), br_targets);
+ GenerateBrCase(decoder, table_iterator.next(), &br_targets);
DCHECK(!table_iterator.has_next());
}
@@ -1593,7 +1637,7 @@ class LiftoffCompiler {
}
Register AddMemoryMasking(Register index, uint32_t* offset,
- LiftoffRegList& pinned) {
+ LiftoffRegList* pinned) {
if (!FLAG_untrusted_code_mitigations || env_->use_trap_handler) {
return index;
}
@@ -1601,11 +1645,11 @@ class LiftoffCompiler {
// Make sure that we can overwrite {index}.
if (__ cache_state()->is_used(LiftoffRegister(index))) {
Register old_index = index;
- pinned.clear(LiftoffRegister(old_index));
- index = pinned.set(__ GetUnusedRegister(kGpReg, pinned)).gp();
+ pinned->clear(LiftoffRegister(old_index));
+ index = pinned->set(__ GetUnusedRegister(kGpReg, *pinned)).gp();
if (index != old_index) __ Move(index, old_index, kWasmI32);
}
- Register tmp = __ GetUnusedRegister(kGpReg, pinned).gp();
+ Register tmp = __ GetUnusedRegister(kGpReg, *pinned).gp();
__ emit_ptrsize_add(index, index, *offset);
LOAD_INSTANCE_FIELD(tmp, MemoryMask, kSystemPointerSize);
__ emit_ptrsize_and(index, index, tmp);
@@ -1625,7 +1669,7 @@ class LiftoffCompiler {
return;
}
uint32_t offset = imm.offset;
- index = AddMemoryMasking(index, &offset, pinned);
+ index = AddMemoryMasking(index, &offset, &pinned);
DEBUG_CODE_COMMENT("Load from memory");
Register addr = pinned.set(__ GetUnusedRegister(kGpReg, pinned)).gp();
LOAD_INSTANCE_FIELD(addr, MemoryStart, kSystemPointerSize);
@@ -1659,7 +1703,7 @@ class LiftoffCompiler {
return;
}
uint32_t offset = imm.offset;
- index = AddMemoryMasking(index, &offset, pinned);
+ index = AddMemoryMasking(index, &offset, &pinned);
DEBUG_CODE_COMMENT("Store to memory");
Register addr = pinned.set(__ GetUnusedRegister(kGpReg, pinned)).gp();
LOAD_INSTANCE_FIELD(addr, MemoryStart, kSystemPointerSize);
@@ -1720,12 +1764,14 @@ class LiftoffCompiler {
void CallDirect(FullDecoder* decoder,
const CallFunctionImmediate<validate>& imm,
const Value args[], Value returns[]) {
- if (imm.sig->return_count() > 1)
- return unsupported(decoder, "multi-return");
+ if (imm.sig->return_count() > 1) {
+ return unsupported(decoder, kMultiValue, "multi-return");
+ }
if (imm.sig->return_count() == 1 &&
!CheckSupportedType(decoder, kSupportedTypes, imm.sig->GetReturn(0),
- "return"))
+ "return")) {
return;
+ }
auto call_descriptor =
compiler::GetWasmCallDescriptor(compilation_zone_, imm.sig);
@@ -1783,10 +1829,10 @@ class LiftoffCompiler {
const CallIndirectImmediate<validate>& imm,
const Value args[], Value returns[]) {
if (imm.sig->return_count() > 1) {
- return unsupported(decoder, "multi-return");
+ return unsupported(decoder, kMultiValue, "multi-return");
}
if (imm.table_index != 0) {
- return unsupported(decoder, "table index != 0");
+ return unsupported(decoder, kAnyRef, "table index != 0");
}
if (imm.sig->return_count() == 1 &&
!CheckSupportedType(decoder, kSupportedTypes, imm.sig->GetReturn(0),
@@ -1918,96 +1964,99 @@ class LiftoffCompiler {
void ReturnCall(FullDecoder* decoder,
const CallFunctionImmediate<validate>& imm,
const Value args[]) {
- unsupported(decoder, "return_call");
+ unsupported(decoder, kTailCall, "return_call");
}
void ReturnCallIndirect(FullDecoder* decoder, const Value& index_val,
const CallIndirectImmediate<validate>& imm,
const Value args[]) {
- unsupported(decoder, "return_call_indirect");
+ unsupported(decoder, kTailCall, "return_call_indirect");
}
void SimdOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
Value* result) {
- unsupported(decoder, "simd");
+ unsupported(decoder, kSimd, "simd");
}
void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
const SimdLaneImmediate<validate>& imm,
const Vector<Value> inputs, Value* result) {
- unsupported(decoder, "simd");
+ unsupported(decoder, kSimd, "simd");
}
void SimdShiftOp(FullDecoder* decoder, WasmOpcode opcode,
const SimdShiftImmediate<validate>& imm, const Value& input,
Value* result) {
- unsupported(decoder, "simd");
+ unsupported(decoder, kSimd, "simd");
}
void Simd8x16ShuffleOp(FullDecoder* decoder,
const Simd8x16ShuffleImmediate<validate>& imm,
const Value& input0, const Value& input1,
Value* result) {
- unsupported(decoder, "simd");
+ unsupported(decoder, kSimd, "simd");
}
void Throw(FullDecoder* decoder, const ExceptionIndexImmediate<validate>&,
const Vector<Value>& args) {
- unsupported(decoder, "throw");
+ unsupported(decoder, kExceptionHandling, "throw");
}
void Rethrow(FullDecoder* decoder, const Value& exception) {
- unsupported(decoder, "rethrow");
+ unsupported(decoder, kExceptionHandling, "rethrow");
}
void BrOnException(FullDecoder* decoder, const Value& exception,
const ExceptionIndexImmediate<validate>& imm,
uint32_t depth, Vector<Value> values) {
- unsupported(decoder, "br_on_exn");
+ unsupported(decoder, kExceptionHandling, "br_on_exn");
}
void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
const MemoryAccessImmediate<validate>& imm, Value* result) {
- unsupported(decoder, "atomicop");
+ unsupported(decoder, kAtomics, "atomicop");
+ }
+ void AtomicFence(FullDecoder* decoder) {
+ unsupported(decoder, kAtomics, "atomic.fence");
}
void MemoryInit(FullDecoder* decoder,
const MemoryInitImmediate<validate>& imm, const Value& dst,
const Value& src, const Value& size) {
- unsupported(decoder, "memory.init");
+ unsupported(decoder, kBulkMemory, "memory.init");
}
void DataDrop(FullDecoder* decoder, const DataDropImmediate<validate>& imm) {
- unsupported(decoder, "data.drop");
+ unsupported(decoder, kBulkMemory, "data.drop");
}
void MemoryCopy(FullDecoder* decoder,
const MemoryCopyImmediate<validate>& imm, const Value& dst,
const Value& src, const Value& size) {
- unsupported(decoder, "memory.copy");
+ unsupported(decoder, kBulkMemory, "memory.copy");
}
void MemoryFill(FullDecoder* decoder,
const MemoryIndexImmediate<validate>& imm, const Value& dst,
const Value& value, const Value& size) {
- unsupported(decoder, "memory.fill");
+ unsupported(decoder, kBulkMemory, "memory.fill");
}
void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
Vector<Value> args) {
- unsupported(decoder, "table.init");
+ unsupported(decoder, kBulkMemory, "table.init");
}
void ElemDrop(FullDecoder* decoder, const ElemDropImmediate<validate>& imm) {
- unsupported(decoder, "elem.drop");
+ unsupported(decoder, kBulkMemory, "elem.drop");
}
void TableCopy(FullDecoder* decoder, const TableCopyImmediate<validate>& imm,
Vector<Value> args) {
- unsupported(decoder, "table.copy");
+ unsupported(decoder, kBulkMemory, "table.copy");
}
void TableGrow(FullDecoder* decoder, const TableIndexImmediate<validate>& imm,
- Value& value, Value& delta, Value* result) {
- unsupported(decoder, "table.grow");
+ const Value& value, const Value& delta, Value* result) {
+ unsupported(decoder, kAnyRef, "table.grow");
}
void TableSize(FullDecoder* decoder, const TableIndexImmediate<validate>& imm,
Value* result) {
- unsupported(decoder, "table.size");
+ unsupported(decoder, kAnyRef, "table.size");
}
void TableFill(FullDecoder* decoder, const TableIndexImmediate<validate>& imm,
- Value& start, Value& value, Value& count) {
- unsupported(decoder, "table.fill");
+ const Value& start, const Value& value, const Value& count) {
+ unsupported(decoder, kAnyRef, "table.fill");
}
private:
LiftoffAssembler asm_;
compiler::CallDescriptor* const descriptor_;
CompilationEnv* const env_;
- bool ok_ = true;
+ LiftoffBailoutReason bailout_reason_ = kSuccess;
std::vector<OutOfLineCode> out_of_line_code_;
SourcePositionTableBuilder source_position_table_builder_;
std::vector<trap_handler::ProtectedInstructionData> protected_instructions_;
@@ -2066,11 +2115,17 @@ WasmCompilationResult ExecuteLiftoffCompilation(AccountingAllocator* allocator,
decoder.Decode();
liftoff_compile_time_scope.reset();
LiftoffCompiler* compiler = &decoder.interface();
- if (decoder.failed()) {
- compiler->OnFirstError(&decoder);
- return WasmCompilationResult{};
- }
- if (!compiler->ok()) {
+ if (decoder.failed()) compiler->OnFirstError(&decoder);
+
+ // Check that the histogram for the bailout reasons has the correct size.
+ DCHECK_EQ(0, counters->liftoff_bailout_reasons()->min());
+ DCHECK_EQ(kNumBailoutReasons - 1, counters->liftoff_bailout_reasons()->max());
+ DCHECK_EQ(kNumBailoutReasons,
+ counters->liftoff_bailout_reasons()->num_buckets());
+ // Register the bailout reason (can also be {kSuccess}).
+ counters->liftoff_bailout_reasons()->AddSample(
+ static_cast<int>(compiler->bailout_reason()));
+ if (compiler->did_bailout()) {
// Liftoff compilation failed.
counters->liftoff_unsupported_functions()->Increment();
return WasmCompilationResult{};