1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file.
4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/adapters.h"
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/frame-elider.h"
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 {
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal {
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace compiler {
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochFrameElider::FrameElider(InstructionSequence* code) : code_(code) {}
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FrameElider::Run() {
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MarkBlocks();
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PropagateMarks();
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MarkDeConstruction();
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FrameElider::MarkBlocks() {
221b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  for (InstructionBlock* block : instruction_blocks()) {
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (block->needs_frame()) continue;
241b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    for (int i = block->code_start(); i < block->code_end(); ++i) {
251b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      const Instruction* instr = InstructionAt(i);
261b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      if (instr->IsCall() || instr->IsDeoptimizeCall() ||
271b268ca467c924004286c97bac133db489cf43d0Ben Murdoch          instr->arch_opcode() == ArchOpcode::kArchStackPointer) {
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        block->mark_needs_frame();
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FrameElider::PropagateMarks() {
371b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  while (PropagateInOrder() || PropagateReversed()) {
38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FrameElider::MarkDeConstruction() {
431b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  for (InstructionBlock* block : instruction_blocks()) {
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (block->needs_frame()) {
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Special case: The start block needs a frame.
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (block->predecessors().empty()) {
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        block->mark_must_construct_frame();
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Find "frame -> no frame" transitions, inserting frame
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // deconstructions.
511b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      for (RpoNumber& succ : block->successors()) {
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!InstructionBlockAt(succ)->needs_frame()) {
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK_EQ(1U, block->SuccessorCount());
541b268ca467c924004286c97bac133db489cf43d0Ben Murdoch          const Instruction* last =
551b268ca467c924004286c97bac133db489cf43d0Ben Murdoch              InstructionAt(block->last_instruction_index());
561b268ca467c924004286c97bac133db489cf43d0Ben Murdoch          if (last->IsThrow() || last->IsTailCall() ||
571b268ca467c924004286c97bac133db489cf43d0Ben Murdoch              last->IsDeoptimizeCall()) {
581b268ca467c924004286c97bac133db489cf43d0Ben Murdoch            // We need to keep the frame if we exit the block through any
591b268ca467c924004286c97bac133db489cf43d0Ben Murdoch            // of these.
601b268ca467c924004286c97bac133db489cf43d0Ben Murdoch            continue;
611b268ca467c924004286c97bac133db489cf43d0Ben Murdoch          }
621b268ca467c924004286c97bac133db489cf43d0Ben Murdoch          // The only cases when we need to deconstruct are ret and jump.
631b268ca467c924004286c97bac133db489cf43d0Ben Murdoch          DCHECK(last->IsRet() || last->IsJump());
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          block->mark_must_deconstruct_frame();
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Find "no frame -> frame" transitions, inserting frame constructions.
691b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      for (RpoNumber& succ : block->successors()) {
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (InstructionBlockAt(succ)->needs_frame()) {
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK_NE(1U, block->SuccessorCount());
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          InstructionBlockAt(succ)->mark_must_construct_frame();
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool FrameElider::PropagateInOrder() {
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool changed = false;
821b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  for (InstructionBlock* block : instruction_blocks()) {
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    changed |= PropagateIntoBlock(block);
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return changed;
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool FrameElider::PropagateReversed() {
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool changed = false;
911b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  for (InstructionBlock* block : base::Reversed(instruction_blocks())) {
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    changed |= PropagateIntoBlock(block);
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return changed;
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool FrameElider::PropagateIntoBlock(InstructionBlock* block) {
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Already marked, nothing to do...
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (block->needs_frame()) return false;
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Never mark the dummy end node, otherwise we might incorrectly decide to
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // put frame deconstruction code there later,
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (block->successors().empty()) return false;
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Propagate towards the end ("downwards") if there is a predecessor needing
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // a frame, but don't "bleed" from deferred code to non-deferred code.
1081b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  for (RpoNumber& pred : block->predecessors()) {
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (InstructionBlockAt(pred)->needs_frame() &&
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        (!InstructionBlockAt(pred)->IsDeferred() || block->IsDeferred())) {
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      block->mark_needs_frame();
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return true;
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Propagate towards start ("upwards") if there are successors and all of
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // them need a frame.
1181b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  for (RpoNumber& succ : block->successors()) {
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!InstructionBlockAt(succ)->needs_frame()) return false;
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  block->mark_needs_frame();
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst InstructionBlocks& FrameElider::instruction_blocks() const {
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return code_->instruction_blocks();
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochInstructionBlock* FrameElider::InstructionBlockAt(RpoNumber rpo_number) const {
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return code_->InstructionBlockAt(rpo_number);
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochInstruction* FrameElider::InstructionAt(int index) const {
137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return code_->InstructionAt(index);
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace compiler
141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
143