Commit 13f0ef5b authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Only emit StackCheck if function might call

For functions without any calls, there is no value in executing a stack
check. The current frame is materialized at that point anyway.
Note that for loops, we still emit additional stack checks in the loop
header.

For unity, the reduction in code size is moderate (0.53%), as only 4000
of the 34000 functions are leaf functions (no calls). However, we also
save some compile time and gain performance, so this is still worth
doing it.

Drive-by: Fix the effect chain generated in {StackCheck()}.

R=mstarzinger@chromium.org, ahaas@chromium.org

Change-Id: Ia6ec58d0ea46de02634c923cdf8e6e08d8902c59
Reviewed-on: https://chromium-review.googlesource.com/533333Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46013}
parent 71582719
......@@ -295,6 +295,7 @@ void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
jsgraph()->ExternalConstant(
ExternalReference::address_of_stack_limit(jsgraph()->isolate())),
jsgraph()->IntPtrConstant(0), *effect, *control);
*effect = limit;
Node* pointer = graph()->NewNode(jsgraph()->machine()->LoadStackPointer());
Node* check =
......@@ -302,7 +303,6 @@ void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
Diamond stack_check(graph(), jsgraph()->common(), check, BranchHint::kTrue);
stack_check.Chain(*control);
Node* effect_true = *effect;
Handle<Code> code = jsgraph()->isolate()->builtins()->WasmStackGuard();
CallInterfaceDescriptor idesc =
......@@ -318,13 +318,34 @@ void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
SetSourcePosition(call, position);
Node* ephi = graph()->NewNode(jsgraph()->common()->EffectPhi(2), effect_true,
Node* ephi = graph()->NewNode(jsgraph()->common()->EffectPhi(2), *effect,
call, stack_check.merge);
*control = stack_check.merge;
*effect = ephi;
}
void WasmGraphBuilder::PatchInStackCheckIfNeeded() {
if (!needs_stack_check_) return;
Node* start = graph()->start();
// Place a stack check which uses a dummy node as control and effect.
Node* dummy = graph()->NewNode(jsgraph()->common()->Dead());
Node* control = dummy;
Node* effect = dummy;
// The function-prologue stack check is associated with position 0, which
// is never a position of any instruction in the function.
StackCheck(0, &effect, &control);
// In testing, no steck checks were emitted. Nothing to rewire then.
if (effect == dummy) return;
// Now patch all control uses of {start} to use {control} and all effect uses
// to use {effect} instead. Then rewire the dummy node to use start instead.
NodeProperties::ReplaceUses(start, start, effect, control);
NodeProperties::ReplaceUses(dummy, nullptr, start, start);
}
Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
wasm::WasmCodePosition position) {
const Operator* op;
......@@ -1709,6 +1730,7 @@ Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction(
}
Node* WasmGraphBuilder::GrowMemory(Node* input) {
SetNeedsStackCheck();
Diamond check_input_range(
graph(), jsgraph()->common(),
graph()->NewNode(jsgraph()->machine()->Uint32LessThanOrEqual(), input,
......@@ -1734,6 +1756,7 @@ Node* WasmGraphBuilder::GrowMemory(Node* input) {
}
Node* WasmGraphBuilder::Throw(Node* input) {
SetNeedsStackCheck();
MachineOperatorBuilder* machine = jsgraph()->machine();
// Pass the thrown value as two SMIs:
......@@ -1757,6 +1780,7 @@ Node* WasmGraphBuilder::Throw(Node* input) {
}
Node* WasmGraphBuilder::Catch(Node* input, wasm::WasmCodePosition position) {
SetNeedsStackCheck();
CommonOperatorBuilder* common = jsgraph()->common();
Node* parameters[] = {input}; // caught value
......@@ -2154,6 +2178,7 @@ Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) {
Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args,
Node*** rets,
wasm::WasmCodePosition position) {
SetNeedsStackCheck();
const size_t params = sig->parameter_count();
const size_t extra = 2; // effect and control inputs.
const size_t count = 1 + params + extra;
......@@ -2907,6 +2932,7 @@ Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
Node* WasmGraphBuilder::CurrentMemoryPages() {
// CurrentMemoryPages can not be called from asm.js.
DCHECK_EQ(wasm::kWasmOrigin, module_->module->get_origin());
SetNeedsStackCheck();
Node* call =
BuildCallToRuntime(Runtime::kWasmMemorySize, jsgraph(), centry_stub_node_,
nullptr, 0, effect_, control_);
......
......@@ -164,6 +164,8 @@ class WasmGraphBuilder {
void StackCheck(wasm::WasmCodePosition position, Node** effect = nullptr,
Node** control = nullptr);
void PatchInStackCheckIfNeeded();
//-----------------------------------------------------------------------
// Operations that read and/or write {control} and {effect}.
//-----------------------------------------------------------------------
......@@ -279,6 +281,7 @@ class WasmGraphBuilder {
size_t cur_bufsize_;
Node* def_buffer_[kDefaultBufferSize];
bool has_simd_ = false;
bool needs_stack_check_ = false;
wasm::FunctionSig* sig_;
SetOncePointer<const Operator> allocate_heap_number_operator_;
......@@ -404,7 +407,10 @@ class WasmGraphBuilder {
int AddParameterNodes(Node** args, int pos, int param_count,
wasm::FunctionSig* sig);
void SetNeedsStackCheck() { needs_stack_check_ = true; }
};
} // namespace compiler
} // namespace internal
} // namespace v8
......
......@@ -617,6 +617,7 @@ class WasmFullDecoder : public WasmDecoder {
WasmDecoder::DecodeLocals(this, sig_, local_types_);
InitSsaEnv();
DecodeFunctionBody();
FinishFunction();
if (failed()) return TraceFailed();
......@@ -715,11 +716,6 @@ class WasmFullDecoder : public WasmDecoder {
ssa_env->control = start;
ssa_env->effect = start;
SetEnv("initial", ssa_env);
if (builder_) {
// The function-prologue stack check is associated with position 0, which
// is never a position of any instruction in the function.
builder_->StackCheck(0);
}
}
TFNode* DefaultValue(ValueType type) {
......@@ -1418,6 +1414,10 @@ class WasmFullDecoder : public WasmDecoder {
if (pc_ > end_ && ok()) error("Beyond end of code");
}
void FinishFunction() {
if (builder_) builder_->PatchInStackCheckIfNeeded();
}
void EndControl() {
ssa_env_->Kill(SsaEnv::kControlEnd);
if (!control_.empty()) {
......
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