[wasm] Use esp/rsp register directly in stack checks
This change helps mostly to reduce register pressure. By default, we compile LoadStackPointer into a move from the stack register into some general purpose register and then later use that register. This might trigger a spill to free up space, which is particularly costly in loops. Change-Id: I886233f890b7833f873fc24773f621add7cf0588 Reviewed-on: https://chromium-review.googlesource.com/1104351 Commit-Queue: Stephan Herhut <herhut@chromium.org> Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Cr-Commit-Position: refs/heads/master@{#54126}
This commit is contained in:
parent
a11b12bb25
commit
eb87b88a38
@ -1254,6 +1254,18 @@ void VisitWordCompare(InstructionSelector* selector, Node* node,
|
||||
selector->EmitWithContinuation(opcode, cont);
|
||||
return;
|
||||
}
|
||||
WasmStackCheckMatcher<Int32BinopMatcher, IrOpcode::kUint32LessThan> wasm_m(
|
||||
node);
|
||||
if (wasm_m.Matched()) {
|
||||
// This is a wasm stack check. By structure, we know that we can use the
|
||||
// stack pointer directly, as wasm code does not modify the stack at points
|
||||
// where stack checks are performed.
|
||||
Node* left = node->InputAt(0);
|
||||
LocationOperand esp(InstructionOperand::EXPLICIT, LocationOperand::REGISTER,
|
||||
InstructionSequence::DefaultRepresentation(),
|
||||
RegisterCode::kRegCode_esp);
|
||||
return VisitCompareWithMemoryOperand(selector, kIA32Cmp, left, esp, cont);
|
||||
}
|
||||
VisitWordCompare(selector, node, kIA32Cmp, cont);
|
||||
}
|
||||
|
||||
|
@ -743,6 +743,34 @@ struct V8_EXPORT_PRIVATE DiamondMatcher
|
||||
Node* if_false_;
|
||||
};
|
||||
|
||||
template <class BinopMatcher, IrOpcode::Value expected_opcode>
|
||||
struct WasmStackCheckMatcher {
|
||||
explicit WasmStackCheckMatcher(Node* compare) : compare_(compare) {}
|
||||
|
||||
bool Matched() {
|
||||
if (compare_->opcode() != expected_opcode) return false;
|
||||
BinopMatcher m(compare_);
|
||||
return MatchedInternal(m.left(), m.right());
|
||||
}
|
||||
|
||||
private:
|
||||
bool MatchedInternal(const typename BinopMatcher::LeftMatcher& l,
|
||||
const typename BinopMatcher::RightMatcher& r) {
|
||||
// In wasm, the stack check is performed by loading the value given by
|
||||
// the address of a field stored in the instance object. That object is
|
||||
// passed as a parameter.
|
||||
if (l.IsLoad() && r.IsLoadStackPointer()) {
|
||||
LoadMatcher<LoadMatcher<NodeMatcher>> mleft(l.node());
|
||||
if (mleft.object().IsLoad() && mleft.index().Is(0) &&
|
||||
mleft.object().object().IsParameter()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Node* compare_;
|
||||
};
|
||||
|
||||
template <class BinopMatcher, IrOpcode::Value expected_opcode>
|
||||
struct StackCheckMatcher {
|
||||
StackCheckMatcher(Isolate* isolate, Node* compare)
|
||||
|
@ -245,6 +245,10 @@ void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
|
||||
if (effect == nullptr) effect = effect_;
|
||||
if (control == nullptr) control = control_;
|
||||
|
||||
// This instruction sequence is matched in the instruction selector to
|
||||
// load the stack pointer directly on some platforms. Hence, when modifying
|
||||
// please also fix WasmStackCheckMatcher in node-matchers.h
|
||||
|
||||
Node* limit_address = graph()->NewNode(
|
||||
mcgraph()->machine()->Load(MachineType::Pointer()), instance_node_.get(),
|
||||
mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(StackLimitAddress)),
|
||||
|
@ -1724,6 +1724,18 @@ void VisitWord64Compare(InstructionSelector* selector, Node* node,
|
||||
selector->EmitWithContinuation(opcode, cont);
|
||||
return;
|
||||
}
|
||||
WasmStackCheckMatcher<Int64BinopMatcher, IrOpcode::kUint64LessThan> wasm_m(
|
||||
node);
|
||||
if (wasm_m.Matched()) {
|
||||
// This is a wasm stack check. By structure, we know that we can use the
|
||||
// stack pointer directly, as wasm code does not modify the stack at points
|
||||
// where stack checks are performed.
|
||||
Node* left = node->InputAt(0);
|
||||
LocationOperand rsp(InstructionOperand::EXPLICIT, LocationOperand::REGISTER,
|
||||
InstructionSequence::DefaultRepresentation(),
|
||||
RegisterCode::kRegCode_rsp);
|
||||
return VisitCompareWithMemoryOperand(selector, kX64Cmp, left, rsp, cont);
|
||||
}
|
||||
VisitWordCompare(selector, node, kX64Cmp, cont);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user