// Copyright 2019 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/codegen/pending-optimization-table.h"

#include "src/base/flags.h"
#include "src/execution/isolate-inl.h"
#include "src/heap/heap-inl.h"
#include "src/objects/hash-table.h"
#include "src/objects/js-objects.h"

namespace v8 {
namespace internal {

enum class FunctionStatus : int {
  kPrepareForOptimize = 1 << 0,
  kMarkForOptimize = 1 << 1,
  kAllowHeuristicOptimization = 1 << 2,
};

using FunctionStatusFlags = base::Flags<FunctionStatus>;

void PendingOptimizationTable::PreparedForOptimization(
    Isolate* isolate, Handle<JSFunction> function,
    bool allow_heuristic_optimization) {
  DCHECK(FLAG_testing_d8_test_runner);

  FunctionStatusFlags status = FunctionStatus::kPrepareForOptimize;
  if (allow_heuristic_optimization) {
    status |= FunctionStatus::kAllowHeuristicOptimization;
  }

  Handle<ObjectHashTable> table =
      isolate->heap()->pending_optimize_for_test_bytecode().IsUndefined()
          ? ObjectHashTable::New(isolate, 1)
          : handle(ObjectHashTable::cast(
                       isolate->heap()->pending_optimize_for_test_bytecode()),
                   isolate);
  Handle<Tuple2> tuple = isolate->factory()->NewTuple2(
      handle(function->shared().GetBytecodeArray(), isolate),
      handle(Smi::FromInt(status), isolate), AllocationType::kYoung);
  table =
      ObjectHashTable::Put(table, handle(function->shared(), isolate), tuple);
  isolate->heap()->SetPendingOptimizeForTestBytecode(*table);
}

bool PendingOptimizationTable::IsHeuristicOptimizationAllowed(
    Isolate* isolate, JSFunction function) {
  DCHECK(FLAG_testing_d8_test_runner);

  Handle<Object> table =
      handle(isolate->heap()->pending_optimize_for_test_bytecode(), isolate);
  Handle<Object> entry =
      table->IsUndefined()
          ? handle(ReadOnlyRoots(isolate).the_hole_value(), isolate)
          : handle(Handle<ObjectHashTable>::cast(table)->Lookup(
                       handle(function.shared(), isolate)),
                   isolate);
  if (entry->IsTheHole()) {
    return true;
  }
  DCHECK(entry->IsTuple2());
  DCHECK(Handle<Tuple2>::cast(entry)->value2().IsSmi());
  FunctionStatusFlags status(Smi::ToInt(Handle<Tuple2>::cast(entry)->value2()));
  return status & FunctionStatus::kAllowHeuristicOptimization;
}

void PendingOptimizationTable::MarkedForOptimization(
    Isolate* isolate, Handle<JSFunction> function) {
  DCHECK(FLAG_testing_d8_test_runner);

  Handle<Object> table =
      handle(isolate->heap()->pending_optimize_for_test_bytecode(), isolate);
  Handle<Object> entry =
      table->IsUndefined()
          ? handle(ReadOnlyRoots(isolate).the_hole_value(), isolate)
          : handle(Handle<ObjectHashTable>::cast(table)->Lookup(
                       handle(function->shared(), isolate)),
                   isolate);
  if (entry->IsTheHole()) {
    PrintF("Error: Function ");
    function->ShortPrint();
    PrintF(
        " should be prepared for optimization with "
        "%%PrepareFunctionForOptimization before  "
        "%%OptimizeFunctionOnNextCall / %%OptimizeOSR ");
    UNREACHABLE();
  }

  DCHECK(entry->IsTuple2());
  DCHECK(Handle<Tuple2>::cast(entry)->value2().IsSmi());
  FunctionStatusFlags status(Smi::ToInt(Handle<Tuple2>::cast(entry)->value2()));
  status = status.without(FunctionStatus::kPrepareForOptimize) |
           FunctionStatus::kMarkForOptimize;
  Handle<Tuple2>::cast(entry)->set_value2(Smi::FromInt(status));
  table = ObjectHashTable::Put(Handle<ObjectHashTable>::cast(table),
                               handle(function->shared(), isolate), entry);
  isolate->heap()->SetPendingOptimizeForTestBytecode(*table);
}

void PendingOptimizationTable::FunctionWasOptimized(
    Isolate* isolate, Handle<JSFunction> function) {
  DCHECK(FLAG_testing_d8_test_runner);

  if (isolate->heap()->pending_optimize_for_test_bytecode().IsUndefined()) {
    return;
  }

  Handle<ObjectHashTable> table =
      handle(ObjectHashTable::cast(
                 isolate->heap()->pending_optimize_for_test_bytecode()),
             isolate);
  Handle<Object> value(table->Lookup(handle(function->shared(), isolate)),
                       isolate);
  // Remove only if we have already seen %OptimizeFunctionOnNextCall. If it is
  // optimized for other reasons, still keep holding the bytecode since we may
  // optimize it later.
  if (!value->IsTheHole() &&
      Smi::cast(Handle<Tuple2>::cast(value)->value2()).value() ==
          static_cast<int>(FunctionStatus::kMarkForOptimize)) {
    bool was_present;
    table = table->Remove(isolate, table, handle(function->shared(), isolate),
                          &was_present);
    DCHECK(was_present);
    isolate->heap()->SetPendingOptimizeForTestBytecode(*table);
  }
}

}  // namespace internal
}  // namespace v8
