Commit f56e2a02 authored by Eric Holk's avatar Eric Holk Committed by Commit Bot

[wasm] enable StoreMem_offset_oob_i64 test with trap handlers

The first part of this change updates StoreMem_offset_oob_i64 to use one page of
Wasm memory, rather than just a few bytes. Using less than a page was out of
spec for Wasm anyway, so this is better.

This required a small change in the test runner to set and clear the
thread_in_wasm flag around Wasm calls. This was accomplished by a
ThreadInWasmScope convenience class.

The majority of the changes are because the cctest environment does not support
runtime exceptions. In the code generator, where we used to throw a
WasmMemOutOfBounds exception, we now need to call out to the test hook instead
if runtime exceptions are not supported. This involved plumbing the
runtime_exception_support flag down to the code generator. Rather than adding
and shuffling around extra parameters everywhere, this CL packages the previous
protected instruction list in a new WasmCompilationData object that now includes
the runtime_exception_support flag as well.

Bug: v8:5277
Change-Id: Ic9c9e5a53a07a7773b58c0aee7c26bbd2ddf82f3
Reviewed-on: https://chromium-review.googlesource.com/989017
Commit-Queue: Eric Holk <eholk@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52368}
parent 6da12d42
...@@ -11,10 +11,10 @@ ...@@ -11,10 +11,10 @@
#include "src/compiler/code-generator-impl.h" #include "src/compiler/code-generator-impl.h"
#include "src/compiler/linkage.h" #include "src/compiler/linkage.h"
#include "src/compiler/pipeline.h" #include "src/compiler/pipeline.h"
#include "src/compiler/wasm-compiler.h"
#include "src/eh-frame.h" #include "src/eh-frame.h"
#include "src/frames.h" #include "src/frames.h"
#include "src/macro-assembler-inl.h" #include "src/macro-assembler-inl.h"
#include "src/trap-handler/trap-handler.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -37,13 +37,14 @@ class CodeGenerator::JumpTable final : public ZoneObject { ...@@ -37,13 +37,14 @@ class CodeGenerator::JumpTable final : public ZoneObject {
size_t const target_count_; size_t const target_count_;
}; };
CodeGenerator::CodeGenerator( CodeGenerator::CodeGenerator(Zone* codegen_zone, Frame* frame, Linkage* linkage,
Zone* codegen_zone, Frame* frame, Linkage* linkage, InstructionSequence* code, CompilationInfo* info,
InstructionSequence* code, CompilationInfo* info, Isolate* isolate, Isolate* isolate,
base::Optional<OsrHelper> osr_helper, int start_source_position, base::Optional<OsrHelper> osr_helper,
JumpOptimizationInfo* jump_opt, int start_source_position,
std::vector<trap_handler::ProtectedInstructionData>* protected_instructions, JumpOptimizationInfo* jump_opt,
PoisoningMitigationLevel poisoning_enabled) WasmCompilationData* wasm_compilation_data,
PoisoningMitigationLevel poisoning_enabled)
: zone_(codegen_zone), : zone_(codegen_zone),
isolate_(isolate), isolate_(isolate),
frame_access_state_(nullptr), frame_access_state_(nullptr),
...@@ -73,7 +74,7 @@ CodeGenerator::CodeGenerator( ...@@ -73,7 +74,7 @@ CodeGenerator::CodeGenerator(
osr_pc_offset_(-1), osr_pc_offset_(-1),
optimized_out_literal_id_(-1), optimized_out_literal_id_(-1),
source_position_table_builder_(info->SourcePositionRecordingMode()), source_position_table_builder_(info->SourcePositionRecordingMode()),
protected_instructions_(protected_instructions), wasm_compilation_data_(wasm_compilation_data),
result_(kSuccess), result_(kSuccess),
poisoning_enabled_(poisoning_enabled) { poisoning_enabled_(poisoning_enabled) {
for (int i = 0; i < code->InstructionBlockCount(); ++i) { for (int i = 0; i < code->InstructionBlockCount(); ++i) {
...@@ -89,13 +90,15 @@ CodeGenerator::CodeGenerator( ...@@ -89,13 +90,15 @@ CodeGenerator::CodeGenerator(
} }
} }
bool CodeGenerator::wasm_runtime_exception_support() const {
DCHECK(wasm_compilation_data_);
return wasm_compilation_data_->runtime_exception_support();
}
void CodeGenerator::AddProtectedInstructionLanding(uint32_t instr_offset, void CodeGenerator::AddProtectedInstructionLanding(uint32_t instr_offset,
uint32_t landing_offset) { uint32_t landing_offset) {
if (protected_instructions_ != nullptr) { DCHECK_NOT_NULL(wasm_compilation_data_);
trap_handler::ProtectedInstructionData data = {instr_offset, wasm_compilation_data_->AddProtectedInstruction(instr_offset, landing_offset);
landing_offset};
protected_instructions_->emplace_back(data);
}
} }
void CodeGenerator::CreateFrameAccessState(Frame* frame) { void CodeGenerator::CreateFrameAccessState(Frame* frame) {
......
...@@ -20,10 +20,6 @@ namespace internal { ...@@ -20,10 +20,6 @@ namespace internal {
class CompilationInfo; class CompilationInfo;
namespace trap_handler {
struct ProtectedInstructionData;
} // namespace trap_handler
namespace compiler { namespace compiler {
// Forward declarations. // Forward declarations.
...@@ -31,6 +27,7 @@ class DeoptimizationExit; ...@@ -31,6 +27,7 @@ class DeoptimizationExit;
class FrameAccessState; class FrameAccessState;
class Linkage; class Linkage;
class OutOfLineCode; class OutOfLineCode;
class WasmCompilationData;
struct BranchInfo { struct BranchInfo {
FlagsCondition condition; FlagsCondition condition;
...@@ -85,8 +82,7 @@ class CodeGenerator final : public GapResolver::Assembler { ...@@ -85,8 +82,7 @@ class CodeGenerator final : public GapResolver::Assembler {
Isolate* isolate, base::Optional<OsrHelper> osr_helper, Isolate* isolate, base::Optional<OsrHelper> osr_helper,
int start_source_position, int start_source_position,
JumpOptimizationInfo* jump_opt, JumpOptimizationInfo* jump_opt,
std::vector<trap_handler::ProtectedInstructionData>* WasmCompilationData* wasm_compilation_data,
protected_instructions,
PoisoningMitigationLevel poisoning_enabled); PoisoningMitigationLevel poisoning_enabled);
// Generate native code. After calling AssembleCode, call FinalizeCode to // Generate native code. After calling AssembleCode, call FinalizeCode to
...@@ -108,6 +104,8 @@ class CodeGenerator final : public GapResolver::Assembler { ...@@ -108,6 +104,8 @@ class CodeGenerator final : public GapResolver::Assembler {
void AddProtectedInstructionLanding(uint32_t instr_offset, void AddProtectedInstructionLanding(uint32_t instr_offset,
uint32_t landing_offset); uint32_t landing_offset);
bool wasm_runtime_exception_support() const;
SourcePosition start_source_position() const { SourcePosition start_source_position() const {
return start_source_position_; return start_source_position_;
} }
...@@ -414,7 +412,7 @@ class CodeGenerator final : public GapResolver::Assembler { ...@@ -414,7 +412,7 @@ class CodeGenerator final : public GapResolver::Assembler {
int osr_pc_offset_; int osr_pc_offset_;
int optimized_out_literal_id_; int optimized_out_literal_id_;
SourcePositionTableBuilder source_position_table_builder_; SourcePositionTableBuilder source_position_table_builder_;
std::vector<trap_handler::ProtectedInstructionData>* protected_instructions_; WasmCompilationData* wasm_compilation_data_;
CodeGenResult result_; CodeGenResult result_;
PoisoningMitigationLevel poisoning_enabled_; PoisoningMitigationLevel poisoning_enabled_;
}; };
......
...@@ -125,8 +125,7 @@ class PipelineData { ...@@ -125,8 +125,7 @@ class PipelineData {
PipelineData(ZoneStats* zone_stats, Isolate* isolate, CompilationInfo* info, PipelineData(ZoneStats* zone_stats, Isolate* isolate, CompilationInfo* info,
JSGraph* jsgraph, PipelineStatistics* pipeline_statistics, JSGraph* jsgraph, PipelineStatistics* pipeline_statistics,
SourcePositionTable* source_positions, SourcePositionTable* source_positions,
std::vector<trap_handler::ProtectedInstructionData>* WasmCompilationData* wasm_compilation_data)
protected_instructions)
: isolate_(isolate), : isolate_(isolate),
info_(info), info_(info),
debug_name_(info_->GetDebugName()), debug_name_(info_->GetDebugName()),
...@@ -145,7 +144,7 @@ class PipelineData { ...@@ -145,7 +144,7 @@ class PipelineData {
codegen_zone_(codegen_zone_scope_.zone()), codegen_zone_(codegen_zone_scope_.zone()),
register_allocation_zone_scope_(zone_stats_, ZONE_NAME), register_allocation_zone_scope_(zone_stats_, ZONE_NAME),
register_allocation_zone_(register_allocation_zone_scope_.zone()), register_allocation_zone_(register_allocation_zone_scope_.zone()),
protected_instructions_(protected_instructions) {} wasm_compilation_data_(wasm_compilation_data) {}
// For machine graph testing entry point. // For machine graph testing entry point.
PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Isolate* isolate, PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Isolate* isolate,
...@@ -344,7 +343,7 @@ class PipelineData { ...@@ -344,7 +343,7 @@ class PipelineData {
code_generator_ = new CodeGenerator( code_generator_ = new CodeGenerator(
codegen_zone(), frame(), linkage, sequence(), info(), isolate(), codegen_zone(), frame(), linkage, sequence(), info(), isolate(),
osr_helper_, start_source_position_, jump_optimization_info_, osr_helper_, start_source_position_, jump_optimization_info_,
protected_instructions_, wasm_compilation_data_,
info()->is_poison_loads() ? PoisoningMitigationLevel::kOn info()->is_poison_loads() ? PoisoningMitigationLevel::kOn
: PoisoningMitigationLevel::kOff); : PoisoningMitigationLevel::kOff);
} }
...@@ -417,8 +416,7 @@ class PipelineData { ...@@ -417,8 +416,7 @@ class PipelineData {
// Source position output for --trace-turbo. // Source position output for --trace-turbo.
std::string source_position_output_; std::string source_position_output_;
std::vector<trap_handler::ProtectedInstructionData>* protected_instructions_ = WasmCompilationData* wasm_compilation_data_ = nullptr;
nullptr;
JumpOptimizationInfo* jump_optimization_info_ = nullptr; JumpOptimizationInfo* jump_optimization_info_ = nullptr;
...@@ -887,15 +885,14 @@ class PipelineWasmCompilationJob final : public CompilationJob { ...@@ -887,15 +885,14 @@ class PipelineWasmCompilationJob final : public CompilationJob {
explicit PipelineWasmCompilationJob( explicit PipelineWasmCompilationJob(
CompilationInfo* info, Isolate* isolate, JSGraph* jsgraph, CompilationInfo* info, Isolate* isolate, JSGraph* jsgraph,
CallDescriptor* call_descriptor, SourcePositionTable* source_positions, CallDescriptor* call_descriptor, SourcePositionTable* source_positions,
std::vector<trap_handler::ProtectedInstructionData>* protected_insts, WasmCompilationData* wasm_compilation_data, bool asmjs_origin)
bool asmjs_origin)
: CompilationJob(isolate->stack_guard()->real_climit(), nullptr, info, : CompilationJob(isolate->stack_guard()->real_climit(), nullptr, info,
"TurboFan", State::kReadyToExecute), "TurboFan", State::kReadyToExecute),
zone_stats_(isolate->allocator()), zone_stats_(isolate->allocator()),
pipeline_statistics_(CreatePipelineStatistics( pipeline_statistics_(CreatePipelineStatistics(
Handle<Script>::null(), info, isolate, &zone_stats_)), Handle<Script>::null(), info, isolate, &zone_stats_)),
data_(&zone_stats_, isolate, info, jsgraph, pipeline_statistics_.get(), data_(&zone_stats_, isolate, info, jsgraph, pipeline_statistics_.get(),
source_positions, protected_insts), source_positions, wasm_compilation_data),
pipeline_(&data_), pipeline_(&data_),
linkage_(call_descriptor), linkage_(call_descriptor),
asmjs_origin_(asmjs_origin) {} asmjs_origin_(asmjs_origin) {}
...@@ -2088,11 +2085,11 @@ CompilationJob* Pipeline::NewCompilationJob(Handle<JSFunction> function, ...@@ -2088,11 +2085,11 @@ CompilationJob* Pipeline::NewCompilationJob(Handle<JSFunction> function,
CompilationJob* Pipeline::NewWasmCompilationJob( CompilationJob* Pipeline::NewWasmCompilationJob(
CompilationInfo* info, Isolate* isolate, JSGraph* jsgraph, CompilationInfo* info, Isolate* isolate, JSGraph* jsgraph,
CallDescriptor* call_descriptor, SourcePositionTable* source_positions, CallDescriptor* call_descriptor, SourcePositionTable* source_positions,
std::vector<trap_handler::ProtectedInstructionData>* protected_instructions, WasmCompilationData* wasm_compilation_data,
wasm::ModuleOrigin asmjs_origin) { wasm::ModuleOrigin asmjs_origin) {
return new PipelineWasmCompilationJob(info, isolate, jsgraph, call_descriptor, return new PipelineWasmCompilationJob(info, isolate, jsgraph, call_descriptor,
source_positions, source_positions, wasm_compilation_data,
protected_instructions, asmjs_origin); asmjs_origin);
} }
bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
......
...@@ -20,10 +20,6 @@ class CompilationJob; ...@@ -20,10 +20,6 @@ class CompilationJob;
class RegisterConfiguration; class RegisterConfiguration;
class JumpOptimizationInfo; class JumpOptimizationInfo;
namespace trap_handler {
struct ProtectedInstructionData;
} // namespace trap_handler
namespace wasm { namespace wasm {
enum ModuleOrigin : uint8_t; enum ModuleOrigin : uint8_t;
} // namespace wasm } // namespace wasm
...@@ -36,6 +32,7 @@ class Graph; ...@@ -36,6 +32,7 @@ class Graph;
class InstructionSequence; class InstructionSequence;
class Schedule; class Schedule;
class SourcePositionTable; class SourcePositionTable;
class WasmCompilationData;
class Pipeline : public AllStatic { class Pipeline : public AllStatic {
public: public:
...@@ -47,8 +44,7 @@ class Pipeline : public AllStatic { ...@@ -47,8 +44,7 @@ class Pipeline : public AllStatic {
static CompilationJob* NewWasmCompilationJob( static CompilationJob* NewWasmCompilationJob(
CompilationInfo* info, Isolate* isolate, JSGraph* jsgraph, CompilationInfo* info, Isolate* isolate, JSGraph* jsgraph,
CallDescriptor* call_descriptor, SourcePositionTable* source_positions, CallDescriptor* call_descriptor, SourcePositionTable* source_positions,
std::vector<trap_handler::ProtectedInstructionData>* WasmCompilationData* wasm_compilation_data,
protected_instructions,
wasm::ModuleOrigin wasm_origin); wasm::ModuleOrigin wasm_origin);
// Run the pipeline on a machine graph and generate code. The {schedule} must // Run the pipeline on a machine graph and generate code. The {schedule} must
......
...@@ -5066,6 +5066,18 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) { ...@@ -5066,6 +5066,18 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
return code; return code;
} }
WasmCompilationData::WasmCompilationData(
RuntimeExceptionSupport runtime_exception_support)
: protected_instructions_(
new std::vector<trap_handler::ProtectedInstructionData>()),
runtime_exception_support_(runtime_exception_support) {}
void WasmCompilationData::AddProtectedInstruction(uint32_t instr_offset,
uint32_t landing_offset) {
protected_instructions_->emplace_back(
trap_handler::ProtectedInstructionData{instr_offset, landing_offset});
}
SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
double* decode_ms) { double* decode_ms) {
base::ElapsedTimer decode_timer; base::ElapsedTimer decode_timer;
...@@ -5078,7 +5090,7 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( ...@@ -5078,7 +5090,7 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
new (tf_.jsgraph_->zone()) SourcePositionTable(tf_.jsgraph_->graph()); new (tf_.jsgraph_->zone()) SourcePositionTable(tf_.jsgraph_->graph());
WasmGraphBuilder builder(env_, tf_.jsgraph_->zone(), tf_.jsgraph_, WasmGraphBuilder builder(env_, tf_.jsgraph_->zone(), tf_.jsgraph_,
centry_stub_, func_body_.sig, source_position_table, centry_stub_, func_body_.sig, source_position_table,
runtime_exception_support_); wasm_compilation_data_.runtime_exception_support());
tf_.graph_construction_result_ = tf_.graph_construction_result_ =
wasm::BuildTFGraph(isolate_->allocator(), &builder, func_body_); wasm::BuildTFGraph(isolate_->allocator(), &builder, func_body_);
if (tf_.graph_construction_result_.failed()) { if (tf_.graph_construction_result_.failed()) {
...@@ -5149,11 +5161,9 @@ WasmCompilationUnit::WasmCompilationUnit( ...@@ -5149,11 +5161,9 @@ WasmCompilationUnit::WasmCompilationUnit(
counters_(counters ? counters : isolate->counters()), counters_(counters ? counters : isolate->counters()),
centry_stub_(centry_stub), centry_stub_(centry_stub),
func_index_(index), func_index_(index),
runtime_exception_support_(exception_support),
native_module_(native_module), native_module_(native_module),
lower_simd_(lower_simd), lower_simd_(lower_simd),
protected_instructions_( wasm_compilation_data_(exception_support),
new std::vector<trap_handler::ProtectedInstructionData>()),
mode_(mode) { mode_(mode) {
switch (mode_) { switch (mode_) {
case WasmCompilationUnit::CompilationMode::kLiftoff: case WasmCompilationUnit::CompilationMode::kLiftoff:
...@@ -5248,8 +5258,7 @@ void WasmCompilationUnit::ExecuteTurbofanCompilation() { ...@@ -5248,8 +5258,7 @@ void WasmCompilationUnit::ExecuteTurbofanCompilation() {
tf_.job_.reset(Pipeline::NewWasmCompilationJob( tf_.job_.reset(Pipeline::NewWasmCompilationJob(
tf_.info_.get(), isolate_, tf_.jsgraph_, call_descriptor, tf_.info_.get(), isolate_, tf_.jsgraph_, call_descriptor,
source_positions, protected_instructions_.get(), source_positions, &wasm_compilation_data_, env_->module->origin()));
env_->module->origin()));
ok_ = tf_.job_->ExecuteJob() == CompilationJob::SUCCEEDED; ok_ = tf_.job_->ExecuteJob() == CompilationJob::SUCCEEDED;
// TODO(bradnelson): Improve histogram handling of size_t. // TODO(bradnelson): Improve histogram handling of size_t.
counters()->wasm_compile_function_peak_memory_bytes()->AddSample( counters()->wasm_compile_function_peak_memory_bytes()->AddSample(
...@@ -5331,7 +5340,7 @@ wasm::WasmCode* WasmCompilationUnit::FinishTurbofanCompilation( ...@@ -5331,7 +5340,7 @@ wasm::WasmCode* WasmCompilationUnit::FinishTurbofanCompilation(
func_index_, func_index_,
tf_.job_->compilation_info()->wasm_code_desc()->safepoint_table_offset, tf_.job_->compilation_info()->wasm_code_desc()->safepoint_table_offset,
tf_.job_->compilation_info()->wasm_code_desc()->handler_table_offset, tf_.job_->compilation_info()->wasm_code_desc()->handler_table_offset,
std::move(protected_instructions_), wasm_compilation_data_.ReleaseProtectedInstructions(),
tf_.job_->compilation_info()->wasm_code_desc()->source_positions_table, tf_.job_->compilation_info()->wasm_code_desc()->source_positions_table,
wasm::WasmCode::kTurbofan); wasm::WasmCode::kTurbofan);
if (!code) return code; if (!code) return code;
...@@ -5355,8 +5364,9 @@ wasm::WasmCode* WasmCompilationUnit::FinishLiftoffCompilation( ...@@ -5355,8 +5364,9 @@ wasm::WasmCode* WasmCompilationUnit::FinishLiftoffCompilation(
wasm::WasmCode* code = native_module_->AddCode( wasm::WasmCode* code = native_module_->AddCode(
desc, liftoff_.asm_.GetTotalFrameSlotCount(), func_index_, desc, liftoff_.asm_.GetTotalFrameSlotCount(), func_index_,
liftoff_.safepoint_table_offset_, 0, std::move(protected_instructions_), liftoff_.safepoint_table_offset_, 0,
source_positions, wasm::WasmCode::kLiftoff); wasm_compilation_data_.ReleaseProtectedInstructions(), source_positions,
wasm::WasmCode::kLiftoff);
return code; return code;
} }
......
...@@ -91,6 +91,33 @@ enum RuntimeExceptionSupport : bool { ...@@ -91,6 +91,33 @@ enum RuntimeExceptionSupport : bool {
kNoRuntimeExceptionSupport = false kNoRuntimeExceptionSupport = false
}; };
// Information about Wasm compilation that needs to be plumbed through the
// different layers of the compiler.
class WasmCompilationData {
public:
explicit WasmCompilationData(RuntimeExceptionSupport);
void AddProtectedInstruction(uint32_t instr_offset, uint32_t landing_offset);
std::unique_ptr<std::vector<trap_handler::ProtectedInstructionData>>
ReleaseProtectedInstructions() {
return std::move(protected_instructions_);
}
RuntimeExceptionSupport runtime_exception_support() const {
return runtime_exception_support_;
}
private:
std::unique_ptr<std::vector<trap_handler::ProtectedInstructionData>>
protected_instructions_;
// See WasmGraphBuilder::runtime_exception_support_.
const RuntimeExceptionSupport runtime_exception_support_;
DISALLOW_COPY_AND_ASSIGN(WasmCompilationData);
};
class WasmCompilationUnit final { class WasmCompilationUnit final {
public: public:
enum class CompilationMode : uint8_t { kLiftoff, kTurbofan }; enum class CompilationMode : uint8_t { kLiftoff, kTurbofan };
...@@ -162,14 +189,11 @@ class WasmCompilationUnit final { ...@@ -162,14 +189,11 @@ class WasmCompilationUnit final {
Counters* counters_; Counters* counters_;
Handle<Code> centry_stub_; Handle<Code> centry_stub_;
int func_index_; int func_index_;
// See WasmGraphBuilder::runtime_exception_support_.
RuntimeExceptionSupport runtime_exception_support_;
bool ok_ = true; bool ok_ = true;
size_t memory_cost_ = 0; size_t memory_cost_ = 0;
wasm::NativeModule* native_module_; wasm::NativeModule* native_module_;
bool lower_simd_; bool lower_simd_;
std::unique_ptr<std::vector<trap_handler::ProtectedInstructionData>> WasmCompilationData wasm_compilation_data_;
protected_instructions_;
CompilationMode mode_; CompilationMode mode_;
// {liftoff_} is valid if mode_ == kLiftoff, tf_ if mode_ == kTurbofan. // {liftoff_} is valid if mode_ == kLiftoff, tf_ if mode_ == kTurbofan.
union { union {
......
...@@ -257,42 +257,83 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -257,42 +257,83 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
Zone* zone_; Zone* zone_;
}; };
class WasmOutOfLineTrap final : public OutOfLineCode { class WasmOutOfLineTrap : public OutOfLineCode {
public: public:
WasmOutOfLineTrap(CodeGenerator* gen, int pc, bool frame_elided, WasmOutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr)
Instruction* instr)
: OutOfLineCode(gen), : OutOfLineCode(gen),
gen_(gen), gen_(gen),
pc_(pc),
frame_elided_(frame_elided), frame_elided_(frame_elided),
instr_(instr) {} instr_(instr) {}
// TODO(eholk): Refactor this method to take the code generator as a void Generate() override {
// parameter. X64OperandConverter i(gen_, instr_);
void Generate() final {
gen_->AddProtectedInstructionLanding(pc_, __ pc_offset());
Builtins::Name trap_id =
static_cast<Builtins::Name>(i.InputInt32(instr_->InputCount() - 1));
GenerateWithTrapId(trap_id);
}
protected:
CodeGenerator* gen_;
void GenerateWithTrapId(Builtins::Name trap_id) {
bool old_has_frame = __ has_frame();
if (frame_elided_) { if (frame_elided_) {
__ set_has_frame(true);
__ EnterFrame(StackFrame::WASM_COMPILED); __ EnterFrame(StackFrame::WASM_COMPILED);
} }
GenerateCallToTrap(trap_id);
gen_->AssembleSourcePosition(instr_); if (frame_elided_) {
__ Call(__ isolate()->builtins()->builtin_handle( __ set_has_frame(old_has_frame);
Builtins::kThrowWasmTrapMemOutOfBounds), }
RelocInfo::CODE_TARGET);
ReferenceMap* reference_map = new (gen_->zone()) ReferenceMap(gen_->zone());
gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
__ AssertUnreachable(AbortReason::kUnexpectedReturnFromWasmTrap);
} }
private: private:
CodeGenerator* gen_; void GenerateCallToTrap(Builtins::Name trap_id) {
int pc_; if (!gen_->wasm_runtime_exception_support()) {
// We cannot test calls to the runtime in cctest/test-run-wasm.
// Therefore we emit a call to C here instead of a call to the runtime.
__ PrepareCallCFunction(0);
__ CallCFunction(
ExternalReference::wasm_call_trap_callback_for_testing(__ isolate()),
0);
__ LeaveFrame(StackFrame::WASM_COMPILED);
auto call_descriptor = gen_->linkage()->GetIncomingDescriptor();
size_t pop_size = call_descriptor->StackParameterCount() * kPointerSize;
// Use rcx as a scratch register, we return anyways immediately.
__ Ret(static_cast<int>(pop_size), rcx);
} else {
gen_->AssembleSourcePosition(instr_);
__ Call(__ isolate()->builtins()->builtin_handle(trap_id),
RelocInfo::CODE_TARGET);
ReferenceMap* reference_map =
new (gen_->zone()) ReferenceMap(gen_->zone());
gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
__ AssertUnreachable(AbortReason::kUnexpectedReturnFromWasmTrap);
}
}
bool frame_elided_; bool frame_elided_;
Instruction* instr_; Instruction* instr_;
}; };
class WasmProtectedInstructionTrap final : public WasmOutOfLineTrap {
public:
WasmProtectedInstructionTrap(CodeGenerator* gen, int pc, bool frame_elided,
Instruction* instr)
: WasmOutOfLineTrap(gen, frame_elided, instr), pc_(pc) {}
void Generate() final {
gen_->AddProtectedInstructionLanding(pc_, __ pc_offset());
GenerateWithTrapId(Builtins::kThrowWasmTrapMemOutOfBounds);
}
private:
int pc_;
};
void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen, void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen,
InstructionCode opcode, Instruction* instr, InstructionCode opcode, Instruction* instr,
X64OperandConverter& i, int pc) { X64OperandConverter& i, int pc) {
...@@ -300,7 +341,7 @@ void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen, ...@@ -300,7 +341,7 @@ void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen,
static_cast<MemoryAccessMode>(MiscField::decode(opcode)); static_cast<MemoryAccessMode>(MiscField::decode(opcode));
if (access_mode == kMemoryAccessProtected) { if (access_mode == kMemoryAccessProtected) {
const bool frame_elided = !codegen->frame_access_state()->has_frame(); const bool frame_elided = !codegen->frame_access_state()->has_frame();
new (zone) WasmOutOfLineTrap(codegen, pc, frame_elided, instr); new (zone) WasmProtectedInstructionTrap(codegen, pc, frame_elided, instr);
} }
} }
...@@ -2967,62 +3008,8 @@ void CodeGenerator::AssembleArchJump(RpoNumber target) { ...@@ -2967,62 +3008,8 @@ void CodeGenerator::AssembleArchJump(RpoNumber target) {
void CodeGenerator::AssembleArchTrap(Instruction* instr, void CodeGenerator::AssembleArchTrap(Instruction* instr,
FlagsCondition condition) { FlagsCondition condition) {
class OutOfLineTrap final : public OutOfLineCode {
public:
OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr)
: OutOfLineCode(gen),
frame_elided_(frame_elided),
instr_(instr),
gen_(gen) {}
void Generate() final {
X64OperandConverter i(gen_, instr_);
Builtins::Name trap_id =
static_cast<Builtins::Name>(i.InputInt32(instr_->InputCount() - 1));
bool old_has_frame = __ has_frame();
if (frame_elided_) {
__ set_has_frame(true);
__ EnterFrame(StackFrame::WASM_COMPILED);
}
GenerateCallToTrap(trap_id);
if (frame_elided_) {
__ set_has_frame(old_has_frame);
}
}
private:
void GenerateCallToTrap(Builtins::Name trap_id) {
if (trap_id == Builtins::builtin_count) {
// We cannot test calls to the runtime in cctest/test-run-wasm.
// Therefore we emit a call to C here instead of a call to the runtime.
__ PrepareCallCFunction(0);
__ CallCFunction(ExternalReference::wasm_call_trap_callback_for_testing(
__ isolate()),
0);
__ LeaveFrame(StackFrame::WASM_COMPILED);
auto call_descriptor = gen_->linkage()->GetIncomingDescriptor();
size_t pop_size = call_descriptor->StackParameterCount() * kPointerSize;
// Use rcx as a scratch register, we return anyways immediately.
__ Ret(static_cast<int>(pop_size), rcx);
} else {
gen_->AssembleSourcePosition(instr_);
__ Call(__ isolate()->builtins()->builtin_handle(trap_id),
RelocInfo::CODE_TARGET);
ReferenceMap* reference_map =
new (gen_->zone()) ReferenceMap(gen_->zone());
gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
__ AssertUnreachable(AbortReason::kUnexpectedReturnFromWasmTrap);
}
}
bool frame_elided_;
Instruction* instr_;
CodeGenerator* gen_;
};
bool frame_elided = !frame_access_state()->has_frame(); bool frame_elided = !frame_access_state()->has_frame();
auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr); auto ool = new (zone()) WasmOutOfLineTrap(this, frame_elided, instr);
Label* tlabel = ool->entry(); Label* tlabel = ool->entry();
Label end; Label end;
if (condition == kUnorderedEqual) { if (condition == kUnorderedEqual) {
......
...@@ -93,6 +93,12 @@ inline void ClearThreadInWasm() { ...@@ -93,6 +93,12 @@ inline void ClearThreadInWasm() {
} }
} }
class ThreadInWasmScope {
public:
ThreadInWasmScope() { SetThreadInWasm(); }
~ThreadInWasmScope() { ClearThreadInWasm(); }
};
bool RegisterDefaultSignalHandler(); bool RegisterDefaultSignalHandler();
V8_EXPORT_PRIVATE void RestoreOriginalSignalHandler(); V8_EXPORT_PRIVATE void RestoreOriginalSignalHandler();
......
...@@ -19,6 +19,8 @@ namespace v8 { ...@@ -19,6 +19,8 @@ namespace v8 {
namespace internal { namespace internal {
namespace wasm { namespace wasm {
using WasmCompilationData = compiler::WasmCompilationData;
constexpr auto kRegister = LiftoffAssembler::VarState::kRegister; constexpr auto kRegister = LiftoffAssembler::VarState::kRegister;
constexpr auto KIntConst = LiftoffAssembler::VarState::KIntConst; constexpr auto KIntConst = LiftoffAssembler::VarState::KIntConst;
constexpr auto kStack = LiftoffAssembler::VarState::kStack; constexpr auto kStack = LiftoffAssembler::VarState::kStack;
...@@ -121,10 +123,8 @@ class LiftoffCompiler { ...@@ -121,10 +123,8 @@ class LiftoffCompiler {
LiftoffCompiler(LiftoffAssembler* liftoff_asm, LiftoffCompiler(LiftoffAssembler* liftoff_asm,
compiler::CallDescriptor* call_descriptor, compiler::CallDescriptor* call_descriptor,
compiler::ModuleEnv* env, compiler::ModuleEnv* env,
compiler::RuntimeExceptionSupport runtime_exception_support,
SourcePositionTableBuilder* source_position_table_builder, SourcePositionTableBuilder* source_position_table_builder,
std::vector<trap_handler::ProtectedInstructionData>* WasmCompilationData* wasm_compilation_data,
protected_instructions,
Zone* compilation_zone, std::unique_ptr<Zone>* codegen_zone) Zone* compilation_zone, std::unique_ptr<Zone>* codegen_zone)
: asm_(liftoff_asm), : asm_(liftoff_asm),
descriptor_( descriptor_(
...@@ -135,9 +135,8 @@ class LiftoffCompiler { ...@@ -135,9 +135,8 @@ class LiftoffCompiler {
? env_->module->maximum_pages ? env_->module->maximum_pages
: wasm::kV8MaxWasmMemoryPages} * : wasm::kV8MaxWasmMemoryPages} *
wasm::kWasmPageSize), wasm::kWasmPageSize),
runtime_exception_support_(runtime_exception_support),
source_position_table_builder_(source_position_table_builder), source_position_table_builder_(source_position_table_builder),
protected_instructions_(protected_instructions), wasm_compilation_data_(wasm_compilation_data),
compilation_zone_(compilation_zone), compilation_zone_(compilation_zone),
codegen_zone_(codegen_zone), codegen_zone_(codegen_zone),
safepoint_table_builder_(compilation_zone_) {} safepoint_table_builder_(compilation_zone_) {}
...@@ -251,7 +250,10 @@ class LiftoffCompiler { ...@@ -251,7 +250,10 @@ class LiftoffCompiler {
} }
void StackCheck(wasm::WasmCodePosition position) { void StackCheck(wasm::WasmCodePosition position) {
if (FLAG_wasm_no_stack_checks || !runtime_exception_support_) return; if (FLAG_wasm_no_stack_checks ||
!wasm_compilation_data_->runtime_exception_support()) {
return;
}
out_of_line_code_.push_back( out_of_line_code_.push_back(
OutOfLineCode::StackCheck(position, __ cache_state()->used_registers)); OutOfLineCode::StackCheck(position, __ cache_state()->used_registers));
OutOfLineCode& ool = out_of_line_code_.back(); OutOfLineCode& ool = out_of_line_code_.back();
...@@ -332,7 +334,16 @@ class LiftoffCompiler { ...@@ -332,7 +334,16 @@ class LiftoffCompiler {
void GenerateOutOfLineCode(OutOfLineCode& ool) { void GenerateOutOfLineCode(OutOfLineCode& ool) {
__ bind(ool.label.get()); __ bind(ool.label.get());
const bool is_stack_check = ool.builtin == Builtins::kWasmStackGuard; const bool is_stack_check = ool.builtin == Builtins::kWasmStackGuard;
if (!runtime_exception_support_) { const bool is_mem_out_of_bounds =
ool.builtin == Builtins::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());
wasm_compilation_data_->AddProtectedInstruction(ool.pc, pc);
}
if (!wasm_compilation_data_->runtime_exception_support()) {
// We cannot test calls to the runtime in cctest/test-run-wasm. // We cannot test calls to the runtime in cctest/test-run-wasm.
// Therefore we emit a call to C here instead of a call to the runtime. // Therefore we emit a call to C here instead of a call to the runtime.
// In this mode, we never generate stack checks. // In this mode, we never generate stack checks.
...@@ -343,13 +354,6 @@ class LiftoffCompiler { ...@@ -343,13 +354,6 @@ class LiftoffCompiler {
return; return;
} }
if (!is_stack_check && 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});
}
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( source_position_table_builder_->AddPosition(
...@@ -1432,11 +1436,10 @@ class LiftoffCompiler { ...@@ -1432,11 +1436,10 @@ class LiftoffCompiler {
// {min_size_} and {max_size_} are cached values computed from the ModuleEnv. // {min_size_} and {max_size_} are cached values computed from the ModuleEnv.
const uint64_t min_size_; const uint64_t min_size_;
const uint64_t max_size_; const uint64_t max_size_;
const compiler::RuntimeExceptionSupport runtime_exception_support_;
bool ok_ = true; bool ok_ = true;
std::vector<OutOfLineCode> out_of_line_code_; std::vector<OutOfLineCode> out_of_line_code_;
SourcePositionTableBuilder* const source_position_table_builder_; SourcePositionTableBuilder* const source_position_table_builder_;
std::vector<trap_handler::ProtectedInstructionData>* protected_instructions_; WasmCompilationData* wasm_compilation_data_;
// Zone used to store information during compilation. The result will be // Zone used to store information during compilation. The result will be
// stored independently, such that this zone can die together with the // stored independently, such that this zone can die together with the
// LiftoffCompiler after compilation. // LiftoffCompiler after compilation.
...@@ -1487,9 +1490,8 @@ bool compiler::WasmCompilationUnit::ExecuteLiftoffCompilation() { ...@@ -1487,9 +1490,8 @@ bool compiler::WasmCompilationUnit::ExecuteLiftoffCompilation() {
base::in_place, counters()->liftoff_compile_time()); base::in_place, counters()->liftoff_compile_time());
wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::LiftoffCompiler> wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::LiftoffCompiler>
decoder(&zone, module, func_body_, &liftoff_.asm_, call_descriptor, env_, decoder(&zone, module, func_body_, &liftoff_.asm_, call_descriptor, env_,
runtime_exception_support_, &liftoff_.source_position_table_builder_, &wasm_compilation_data_,
&liftoff_.source_position_table_builder_, &zone, &liftoff_.codegen_zone_);
protected_instructions_.get(), &zone, &liftoff_.codegen_zone_);
decoder.Decode(); decoder.Decode();
liftoff_compile_time_scope.reset(); liftoff_compile_time_scope.reset();
if (!decoder.interface().ok()) { if (!decoder.interface().ok()) {
......
...@@ -1394,17 +1394,17 @@ WASM_EXEC_TEST(I64Rol) { ...@@ -1394,17 +1394,17 @@ WASM_EXEC_TEST(I64Rol) {
} }
WASM_EXEC_TEST(StoreMem_offset_oob_i64) { WASM_EXEC_TEST(StoreMem_offset_oob_i64) {
// TODO(eholk): Fix this test for the trap handler.
if (trap_handler::IsTrapHandlerEnabled()) return;
static const MachineType machineTypes[] = { static const MachineType machineTypes[] = {
MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(), MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(),
MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(), MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(),
MachineType::Int64(), MachineType::Uint64(), MachineType::Float32(), MachineType::Int64(), MachineType::Uint64(), MachineType::Float32(),
MachineType::Float64()}; MachineType::Float64()};
constexpr size_t num_bytes = kWasmPageSize;
for (size_t m = 0; m < arraysize(machineTypes); m++) { for (size_t m = 0; m < arraysize(machineTypes); m++) {
WasmRunner<int32_t, uint32_t> r(execution_mode); WasmRunner<int32_t, uint32_t> r(execution_mode);
byte* memory = r.builder().AddMemoryElems<byte>(32); byte* memory = r.builder().AddMemoryElems<byte>(num_bytes);
r.builder().RandomizeMemory(1119 + static_cast<int>(m)); r.builder().RandomizeMemory(1119 + static_cast<int>(m));
BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0), BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0),
...@@ -1412,7 +1412,7 @@ WASM_EXEC_TEST(StoreMem_offset_oob_i64) { ...@@ -1412,7 +1412,7 @@ WASM_EXEC_TEST(StoreMem_offset_oob_i64) {
WASM_ZERO); WASM_ZERO);
byte memsize = WasmOpcodes::MemSize(machineTypes[m]); byte memsize = WasmOpcodes::MemSize(machineTypes[m]);
uint32_t boundary = 24 - memsize; uint32_t boundary = num_bytes - 8 - memsize;
CHECK_EQ(0, r.Call(boundary)); // in bounds. CHECK_EQ(0, r.Call(boundary)); // in bounds.
CHECK_EQ(0, memcmp(&memory[0], &memory[8 + boundary], memsize)); CHECK_EQ(0, memcmp(&memory[0], &memory[8 + boundary], memsize));
......
...@@ -452,6 +452,7 @@ class WasmRunner : public WasmRunnerBase { ...@@ -452,6 +452,7 @@ class WasmRunner : public WasmRunnerBase {
ReturnType return_value = static_cast<ReturnType>(0xDEADBEEFDEADBEEF); ReturnType return_value = static_cast<ReturnType>(0xDEADBEEFDEADBEEF);
WasmRunnerBase::trap_happened = false; WasmRunnerBase::trap_happened = false;
auto trap_callback = []() -> void { auto trap_callback = []() -> void {
WasmRunnerBase::trap_happened = true; WasmRunnerBase::trap_happened = true;
set_trap_callback_for_testing(nullptr); set_trap_callback_for_testing(nullptr);
...@@ -466,8 +467,13 @@ class WasmRunner : public WasmRunnerBase { ...@@ -466,8 +467,13 @@ class WasmRunner : public WasmRunnerBase {
Handle<Code> wrapper_code = wrapper_.GetWrapperCode(); Handle<Code> wrapper_code = wrapper_.GetWrapperCode();
compiler::CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(), compiler::CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
wrapper_code, wrapper_.signature()); wrapper_code, wrapper_.signature());
int32_t result = runner.Call(static_cast<void*>(&p)..., int32_t result;
static_cast<void*>(&return_value)); {
trap_handler::ThreadInWasmScope scope;
result = runner.Call(static_cast<void*>(&p)...,
static_cast<void*>(&return_value));
}
CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result); CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
return WasmRunnerBase::trap_happened return WasmRunnerBase::trap_happened
? static_cast<ReturnType>(0xDEADBEEFDEADBEEF) ? static_cast<ReturnType>(0xDEADBEEFDEADBEEF)
......
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