[wasm] Explicit opt-out of stack checks and traps
We've been passing a context to the compiler, which turns out to be solely used to determine if we're executing in a specific cctest configuration. This change adds a configuration to the graph builder that we can use to explicitly opt out of stack checks and traps. CcTests default to opting out, except for the few that don't. Bug: Change-Id: I4724e31c2a62e9b3ab4feadb788287c374b39f53 Reviewed-on: https://chromium-review.googlesource.com/585779 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Mircea Trofin <mtrofin@chromium.org> Cr-Commit-Position: refs/heads/master@{#46943}
This commit is contained in:
parent
44f88dcd87
commit
be915fd7d1
@ -192,10 +192,12 @@ Node* WasmGraphBuilder::Int64Constant(int64_t value) {
|
||||
|
||||
void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
|
||||
Node** effect, Node** control) {
|
||||
if (FLAG_wasm_no_stack_checks) return;
|
||||
// We do not generate stack checks for cctests.
|
||||
if (!module_ || (module_->instance && module_->instance->context.is_null()))
|
||||
// TODO(mtrofin): "!module_" happens when we generate a wrapper.
|
||||
// We should factor wrappers separately from wasm codegen.
|
||||
if (FLAG_wasm_no_stack_checks || !module_ ||
|
||||
!has_runtime_exception_support_) {
|
||||
return;
|
||||
}
|
||||
if (effect == nullptr) effect = effect_;
|
||||
if (control == nullptr) control = control_;
|
||||
|
||||
@ -828,9 +830,8 @@ Node* WasmGraphBuilder::BranchExpectFalse(Node* cond, Node** true_node,
|
||||
BranchHint::kFalse);
|
||||
}
|
||||
|
||||
namespace {
|
||||
Builtins::Name GetBuiltinIdForTrap(bool in_cctest, wasm::TrapReason reason) {
|
||||
if (in_cctest) {
|
||||
Builtins::Name WasmGraphBuilder::GetBuiltinIdForTrap(wasm::TrapReason reason) {
|
||||
if (!has_runtime_exception_support_) {
|
||||
// We use Builtins::builtin_count as a marker to tell the code generator
|
||||
// to generate a call to a testing c-function instead of a runtime
|
||||
// function. This code should only be called from a cctest.
|
||||
@ -847,14 +848,10 @@ Builtins::Name GetBuiltinIdForTrap(bool in_cctest, wasm::TrapReason reason) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Node* WasmGraphBuilder::TrapIfTrue(wasm::TrapReason reason, Node* cond,
|
||||
wasm::WasmCodePosition position) {
|
||||
// TODO(wasm): Introduce a testing flag instead of trying to infer it here.
|
||||
bool in_cctest =
|
||||
!module_ || (module_->instance && module_->instance->context.is_null());
|
||||
int32_t trap_id = GetBuiltinIdForTrap(in_cctest, reason);
|
||||
Builtins::Name trap_id = GetBuiltinIdForTrap(reason);
|
||||
Node* node = graph()->NewNode(jsgraph()->common()->TrapIf(trap_id), cond,
|
||||
Effect(), Control());
|
||||
*control_ = node;
|
||||
@ -864,10 +861,7 @@ Node* WasmGraphBuilder::TrapIfTrue(wasm::TrapReason reason, Node* cond,
|
||||
|
||||
Node* WasmGraphBuilder::TrapIfFalse(wasm::TrapReason reason, Node* cond,
|
||||
wasm::WasmCodePosition position) {
|
||||
// TODO(wasm): Introduce a testing flag instead of trying to infer it here.
|
||||
bool in_cctest =
|
||||
!module_ || (module_->instance && module_->instance->context.is_null());
|
||||
int32_t trap_id = GetBuiltinIdForTrap(in_cctest, reason);
|
||||
Builtins::Name trap_id = GetBuiltinIdForTrap(reason);
|
||||
|
||||
Node* node = graph()->NewNode(jsgraph()->common()->TrapUnless(trap_id), cond,
|
||||
Effect(), Control());
|
||||
|
@ -280,6 +280,10 @@ class WasmGraphBuilder {
|
||||
|
||||
wasm::ModuleEnv* module_env() const { return module_; }
|
||||
|
||||
void SetRuntimeExceptionSupport(bool value) {
|
||||
has_runtime_exception_support_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kDefaultBufferSize = 16;
|
||||
|
||||
@ -299,6 +303,10 @@ class WasmGraphBuilder {
|
||||
Node* def_buffer_[kDefaultBufferSize];
|
||||
bool has_simd_ = false;
|
||||
bool needs_stack_check_ = false;
|
||||
// If the runtime doesn't support exception propagation,
|
||||
// we won't generate stack checks, and trap handling will also
|
||||
// be generated differently.
|
||||
bool has_runtime_exception_support_ = true;
|
||||
|
||||
wasm::FunctionSig* sig_;
|
||||
SetOncePointer<const Operator> allocate_heap_number_operator_;
|
||||
@ -440,6 +448,7 @@ class WasmGraphBuilder {
|
||||
Node** parameters, int parameter_count);
|
||||
|
||||
Node* BuildModifyThreadInWasmFlag(bool new_value);
|
||||
Builtins::Name GetBuiltinIdForTrap(wasm::TrapReason reason);
|
||||
};
|
||||
|
||||
V8_EXPORT_PRIVATE CallDescriptor* GetWasmCallDescriptor(Zone* zone,
|
||||
|
@ -330,7 +330,6 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObject(
|
||||
Vector<const byte> asm_js_offset_table_bytes) {
|
||||
Factory* factory = isolate_->factory();
|
||||
WasmInstance temp_instance(module_.get());
|
||||
temp_instance.context = isolate_->native_context();
|
||||
temp_instance.mem_size = WasmModule::kPageSize * module_->min_mem_pages;
|
||||
temp_instance.mem_start = nullptr;
|
||||
temp_instance.globals_start = nullptr;
|
||||
@ -2062,7 +2061,6 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
|
||||
|
||||
Factory* factory = job_->isolate_->factory();
|
||||
job_->temp_instance_.reset(new WasmInstance(module_.get()));
|
||||
job_->temp_instance_->context = job_->context_;
|
||||
job_->temp_instance_->mem_size =
|
||||
WasmModule::kPageSize * module_->min_mem_pages;
|
||||
job_->temp_instance_->mem_start = nullptr;
|
||||
|
@ -229,7 +229,6 @@ struct WasmInstance {
|
||||
|
||||
const WasmModule* module; // static representation of the module.
|
||||
// -- Heap allocated --------------------------------------------------------
|
||||
Handle<Context> context; // JavaScript native context.
|
||||
std::vector<Handle<FixedArray>> function_tables; // indirect function tables.
|
||||
std::vector<Handle<FixedArray>>
|
||||
signature_tables; // indirect signature tables.
|
||||
@ -248,8 +247,6 @@ struct WasmInstance {
|
||||
function_code(m->functions.size()) {}
|
||||
|
||||
void ReopenHandles(Isolate* isolate) {
|
||||
context = handle(*context, isolate);
|
||||
|
||||
for (auto& table : function_tables) {
|
||||
table = handle(*table, isolate);
|
||||
}
|
||||
|
@ -125,9 +125,8 @@ TEST(CollectDetailedWasmStack_ExplicitThrowFromJs) {
|
||||
// Trigger a trap in wasm, stack should be JS -> wasm -> wasm.
|
||||
TEST(CollectDetailedWasmStack_WasmError) {
|
||||
TestSignatures sigs;
|
||||
WasmRunner<int> r(kExecuteCompiled);
|
||||
// Set the execution context, such that a runtime error can be thrown.
|
||||
r.SetModuleContext();
|
||||
// Create a WasmRunner with stack checks and traps enabled.
|
||||
WasmRunner<int> r(kExecuteCompiled, "main", true);
|
||||
|
||||
BUILD(r, WASM_UNREACHABLE);
|
||||
uint32_t wasm_index_1 = r.function()->func_index;
|
||||
|
@ -64,10 +64,9 @@ void CheckExceptionInfos(Handle<Object> exc,
|
||||
|
||||
// Trigger a trap for executing unreachable.
|
||||
TEST(Unreachable) {
|
||||
WasmRunner<void> r(kExecuteCompiled);
|
||||
// Create a WasmRunner with stack checks and traps enabled.
|
||||
WasmRunner<void> r(kExecuteCompiled, "main", true);
|
||||
TestSignatures sigs;
|
||||
// Set the execution context, such that a runtime error can be thrown.
|
||||
r.SetModuleContext();
|
||||
|
||||
BUILD(r, WASM_UNREACHABLE);
|
||||
uint32_t wasm_index = r.function()->func_index;
|
||||
@ -99,10 +98,9 @@ TEST(Unreachable) {
|
||||
|
||||
// Trigger a trap for loading from out-of-bounds.
|
||||
TEST(IllegalLoad) {
|
||||
WasmRunner<void> r(kExecuteCompiled);
|
||||
WasmRunner<void> r(kExecuteCompiled, "main", true);
|
||||
TestSignatures sigs;
|
||||
// Set the execution context, such that a runtime error can be thrown.
|
||||
r.SetModuleContext();
|
||||
|
||||
r.module().AddMemory(0L);
|
||||
|
||||
BUILD(r, WASM_IF(WASM_ONE, WASM_SEQ(WASM_LOAD_MEM(MachineType::Int32(),
|
||||
|
@ -356,10 +356,13 @@ class TestingModule : public ModuleEnv {
|
||||
inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module,
|
||||
FunctionSig* sig,
|
||||
SourcePositionTable* source_position_table,
|
||||
const byte* start, const byte* end) {
|
||||
const byte* start, const byte* end,
|
||||
bool runtime_exception_support = false) {
|
||||
compiler::WasmGraphBuilder builder(
|
||||
module, zone, jsgraph, CEntryStub(jsgraph->isolate(), 1).GetCode(), sig,
|
||||
source_position_table);
|
||||
builder.SetRuntimeExceptionSupport(runtime_exception_support);
|
||||
|
||||
DecodeResult result =
|
||||
BuildTFGraph(zone->allocator(), &builder, sig, start, end);
|
||||
if (result.failed()) {
|
||||
@ -550,7 +553,8 @@ class WasmFunctionCompiler : private GraphAndBuilders {
|
||||
|
||||
// Build the TurboFan graph.
|
||||
TestBuildingGraph(zone(), &jsgraph, testing_module_, sig,
|
||||
&source_position_table_, start, end);
|
||||
&source_position_table_, start, end,
|
||||
runtime_exception_support_);
|
||||
Handle<Code> code = Compile();
|
||||
testing_module_->SetFunctionCode(function_index(), code);
|
||||
|
||||
@ -586,7 +590,8 @@ class WasmFunctionCompiler : private GraphAndBuilders {
|
||||
friend class WasmRunnerBase;
|
||||
|
||||
explicit WasmFunctionCompiler(Zone* zone, FunctionSig* sig,
|
||||
TestingModule* module, const char* name)
|
||||
TestingModule* module, const char* name,
|
||||
bool runtime_exception_support)
|
||||
: GraphAndBuilders(zone),
|
||||
jsgraph(module->isolate(), this->graph(), this->common(), nullptr,
|
||||
nullptr, this->machine()),
|
||||
@ -595,7 +600,8 @@ class WasmFunctionCompiler : private GraphAndBuilders {
|
||||
testing_module_(module),
|
||||
local_decls(zone, sig),
|
||||
source_position_table_(this->graph()),
|
||||
interpreter_(module->interpreter()) {
|
||||
interpreter_(module->interpreter()),
|
||||
runtime_exception_support_(runtime_exception_support) {
|
||||
// Get a new function from the testing module.
|
||||
int index = module->AddFunction(sig, Handle<Code>::null(), name);
|
||||
function_ = testing_module_->GetFunctionAt(index);
|
||||
@ -651,16 +657,19 @@ class WasmFunctionCompiler : private GraphAndBuilders {
|
||||
LocalDeclEncoder local_decls;
|
||||
SourcePositionTable source_position_table_;
|
||||
WasmInterpreter* interpreter_;
|
||||
bool runtime_exception_support_ = false;
|
||||
};
|
||||
|
||||
// A helper class to build a module around Wasm bytecode, generate machine
|
||||
// code, and run that code.
|
||||
class WasmRunnerBase : public HandleAndZoneScope {
|
||||
public:
|
||||
explicit WasmRunnerBase(WasmExecutionMode execution_mode, int num_params)
|
||||
explicit WasmRunnerBase(WasmExecutionMode execution_mode, int num_params,
|
||||
bool runtime_exception_support)
|
||||
: zone_(&allocator_, ZONE_NAME),
|
||||
module_(&zone_, execution_mode),
|
||||
wrapper_(&zone_, num_params) {}
|
||||
wrapper_(&zone_, num_params),
|
||||
runtime_exception_support_(runtime_exception_support) {}
|
||||
|
||||
// Builds a graph from the given Wasm code and generates the machine
|
||||
// code and call wrapper for that graph. This method must not be called
|
||||
@ -683,8 +692,8 @@ class WasmRunnerBase : public HandleAndZoneScope {
|
||||
// Returns the index of the previously built function.
|
||||
WasmFunctionCompiler& NewFunction(FunctionSig* sig,
|
||||
const char* name = nullptr) {
|
||||
functions_.emplace_back(
|
||||
new WasmFunctionCompiler(&zone_, sig, &module_, name));
|
||||
functions_.emplace_back(new WasmFunctionCompiler(
|
||||
&zone_, sig, &module_, name, runtime_exception_support_));
|
||||
return *functions_.back();
|
||||
}
|
||||
|
||||
@ -702,16 +711,6 @@ class WasmRunnerBase : public HandleAndZoneScope {
|
||||
TestingModule& module() { return module_; }
|
||||
Zone* zone() { return &zone_; }
|
||||
|
||||
// Set the context, such that e.g. runtime functions can be called.
|
||||
void SetModuleContext() {
|
||||
if (!module_.instance->context.is_null()) {
|
||||
CHECK(module_.instance->context.is_identical_to(
|
||||
main_isolate()->native_context()));
|
||||
return;
|
||||
}
|
||||
module_.instance->context = main_isolate()->native_context();
|
||||
}
|
||||
|
||||
bool interpret() { return module_.interpret(); }
|
||||
|
||||
private:
|
||||
@ -752,6 +751,7 @@ class WasmRunnerBase : public HandleAndZoneScope {
|
||||
WasmFunctionWrapper wrapper_;
|
||||
bool compiled_ = false;
|
||||
bool possible_nondeterminism_ = false;
|
||||
bool runtime_exception_support_ = false;
|
||||
|
||||
public:
|
||||
// This field has to be static. Otherwise, gcc complains about the use in
|
||||
@ -763,8 +763,10 @@ template <typename ReturnType, typename... ParamTypes>
|
||||
class WasmRunner : public WasmRunnerBase {
|
||||
public:
|
||||
explicit WasmRunner(WasmExecutionMode execution_mode,
|
||||
const char* main_fn_name = "main")
|
||||
: WasmRunnerBase(execution_mode, sizeof...(ParamTypes)) {
|
||||
const char* main_fn_name = "main",
|
||||
bool runtime_exception_support = false)
|
||||
: WasmRunnerBase(execution_mode, sizeof...(ParamTypes),
|
||||
runtime_exception_support) {
|
||||
NewFunction<ReturnType, ParamTypes...>(main_fn_name);
|
||||
if (!interpret()) {
|
||||
wrapper_.Init<ReturnType, ParamTypes...>(functions_[0]->descriptor());
|
||||
|
Loading…
Reference in New Issue
Block a user