// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/js-inlining-heuristic.h"

#include "src/compiler.h"
#include "src/compiler/node-matchers.h"
#include "src/objects-inl.h"

namespace v8 {
namespace internal {
namespace compiler {

Reduction JSInliningHeuristic::Reduce(Node* node) {
  if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange();

  // Check if we already saw that {node} before, and if so, just skip it.
  if (seen_.find(node->id()) != seen_.end()) return NoChange();
  seen_.insert(node->id());

  Node* callee = node->InputAt(0);
  HeapObjectMatcher match(callee);
  if (!match.HasValue() || !match.Value()->IsJSFunction()) return NoChange();
  Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value());

  // Functions marked with %SetForceInlineFlag are immediately inlined.
  if (function->shared()->force_inline()) {
    return inliner_.ReduceJSCall(node, function);
  }

  // Handling of special inlining modes right away:
  //  - For restricted inlining: stop all handling at this point.
  //  - For stressing inlining: immediately handle all functions.
  switch (mode_) {
    case kRestrictedInlining:
      return NoChange();
    case kStressInlining:
      return inliner_.ReduceJSCall(node, function);
    case kGeneralInlining:
      break;
  }

  // ---------------------------------------------------------------------------
  // Everything below this line is part of the inlining heuristic.
  // ---------------------------------------------------------------------------

  // Built-in functions are handled by the JSBuiltinReducer.
  if (function->shared()->HasBuiltinFunctionId()) return NoChange();

  // Don't inline builtins.
  if (function->shared()->IsBuiltin()) return NoChange();

  // Quick check on source code length to avoid parsing large candidate.
  if (function->shared()->SourceSize() > FLAG_max_inlined_source_size) {
    return NoChange();
  }

  // Quick check on the size of the AST to avoid parsing large candidate.
  if (function->shared()->ast_node_count() > FLAG_max_inlined_nodes) {
    return NoChange();
  }

  // Avoid inlining within or across the boundary of asm.js code.
  if (info_->shared_info()->asm_function()) return NoChange();
  if (function->shared()->asm_function()) return NoChange();

  // Stop inlinining once the maximum allowed level is reached.
  int level = 0;
  for (Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
       frame_state->opcode() == IrOpcode::kFrameState;
       frame_state = NodeProperties::GetFrameStateInput(frame_state, 0)) {
    if (++level > FLAG_max_inlining_levels) return NoChange();
  }

  // Gather feedback on how often this call site has been hit before.
  int calls = -1;  // Same default as CallICNexus::ExtractCallCount.
  if (node->opcode() == IrOpcode::kJSCallFunction) {
    CallFunctionParameters p = CallFunctionParametersOf(node->op());
    if (p.feedback().IsValid()) {
      CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
      calls = nexus.ExtractCallCount();
    }
  } else {
    DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
    CallConstructParameters p = CallConstructParametersOf(node->op());
    if (p.feedback().IsValid()) {
      int const extra_index =
          p.feedback().vector()->GetIndex(p.feedback().slot()) + 1;
      Handle<Object> feedback_extra(p.feedback().vector()->get(extra_index),
                                    function->GetIsolate());
      if (feedback_extra->IsSmi()) {
        calls = Handle<Smi>::cast(feedback_extra)->value();
      }
    }
  }

  // ---------------------------------------------------------------------------
  // Everything above this line is part of the inlining heuristic.
  // ---------------------------------------------------------------------------

  // In the general case we remember the candidate for later.
  candidates_.insert({function, node, calls});
  return NoChange();
}


void JSInliningHeuristic::Finalize() {
  if (candidates_.empty()) return;  // Nothing to do without candidates.
  if (FLAG_trace_turbo_inlining) PrintCandidates();

  // We inline at most one candidate in every iteration of the fixpoint.
  // This is to ensure that we don't consume the full inlining budget
  // on things that aren't called very often.
  // TODO(bmeurer): Use std::priority_queue instead of std::set here.
  while (!candidates_.empty()) {
    if (cumulative_count_ > FLAG_max_inlined_nodes_cumulative) return;
    auto i = candidates_.begin();
    Candidate candidate = *i;
    candidates_.erase(i);
    // Make sure we don't try to inline dead candidate nodes.
    if (!candidate.node->IsDead()) {
      Reduction r = inliner_.ReduceJSCall(candidate.node, candidate.function);
      if (r.Changed()) {
        cumulative_count_ += candidate.function->shared()->ast_node_count();
        return;
      }
    }
  }
}


bool JSInliningHeuristic::CandidateCompare::operator()(
    const Candidate& left, const Candidate& right) const {
  if (left.calls != right.calls) {
    return left.calls > right.calls;
  }
  return left.node < right.node;
}


void JSInliningHeuristic::PrintCandidates() {
  PrintF("Candidates for inlining (size=%zu):\n", candidates_.size());
  for (const Candidate& candidate : candidates_) {
    PrintF("  id:%d, calls:%d, size[source]:%d, size[ast]:%d / %s\n",
           candidate.node->id(), candidate.calls,
           candidate.function->shared()->SourceSize(),
           candidate.function->shared()->ast_node_count(),
           candidate.function->shared()->DebugName()->ToCString().get());
  }
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
