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