[Liftoff] Add loop-header stack checks

This is needed to ensure that code can be interrupted. It will be
covered by a test once we support if-constructs in Liftoff.

Drive-by: Separate handling of blocks and loops, as there is only one
line in common.

R=ahaas@chromium.org

Bug: v8:6600
Change-Id: Ic22ca5e65c8d03a5d504289ec2a9e30cb97dc220
Reviewed-on: https://chromium-review.googlesource.com/853858
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50403}
This commit is contained in:
Clemens Hammacher 2018-01-08 13:12:29 +01:00 committed by Commit Bot
parent 1cd6efe7bb
commit d81536564d

View File

@ -322,31 +322,31 @@ class LiftoffCompiler {
BindUnboundLabels(decoder);
}
void Block(Decoder* decoder, Control* new_block) {
// Note: This is called for blocks and loops.
DCHECK_EQ(new_block, decoder->control_at(0));
void Block(Decoder* decoder, Control* block) {
TraceCacheState(decoder);
new_block->label_state.stack_base = __ cache_state()->stack_height();
if (new_block->is_loop()) {
// Before entering a loop, spill all locals to the stack, in order to free
// the cache registers, and to avoid unnecessarily reloading stack values
// into registers at branches.
// TODO(clemensh): Come up with a better strategy here, involving
// pre-analysis of the function.
__ SpillLocals();
// Loop labels bind at the beginning of the block, block labels at the
// end.
__ bind(new_block->label.get());
new_block->label_state.Split(*__ cache_state());
}
block->label_state.stack_base = __ cache_state()->stack_height();
}
void Loop(Decoder* decoder, Control* block) { Block(decoder, block); }
void Loop(Decoder* decoder, Control* loop) {
TraceCacheState(decoder);
loop->label_state.stack_base = __ cache_state()->stack_height();
// Before entering a loop, spill all locals to the stack, in order to free
// the cache registers, and to avoid unnecessarily reloading stack values
// into registers at branches.
// TODO(clemensh): Come up with a better strategy here, involving
// pre-analysis of the function.
__ SpillLocals();
// Loop labels bind at the beginning of the block.
__ bind(loop->label.get());
// Save the current cache state for the merge when jumping to this loop.
loop->label_state.Split(*__ cache_state());
// Execute a stack check in the loop header.
StackCheck(decoder->position());
}
void Try(Decoder* decoder, Control* block) { unsupported(decoder, "try"); }
void If(Decoder* decoder, const Value& cond, Control* if_block) {