/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "write_barrier_elimination.h"

#include "base/arena_allocator.h"
#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"
#include "optimizing/nodes.h"

// TODO(b/310755375, solanes): Disable WBE while we investigate crashes.
constexpr bool kWBEEnabled = false;

namespace art HIDDEN {

class WBEVisitor final : public HGraphVisitor {
 public:
  WBEVisitor(HGraph* graph, OptimizingCompilerStats* stats)
      : HGraphVisitor(graph),
        scoped_allocator_(graph->GetArenaStack()),
        current_write_barriers_(scoped_allocator_.Adapter(kArenaAllocWBE)),
        stats_(stats) {}

  void VisitBasicBlock(HBasicBlock* block) override {
    // We clear the map to perform this optimization only in the same block. Doing it across blocks
    // would entail non-trivial merging of states.
    current_write_barriers_.clear();
    HGraphVisitor::VisitBasicBlock(block);
  }

  void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override {
    DCHECK(!instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC()));

    if (instruction->GetFieldType() != DataType::Type::kReference ||
        instruction->GetValue()->IsNullConstant()) {
      instruction->SetWriteBarrierKind(WriteBarrierKind::kDontEmit);
      return;
    }

    MaybeRecordStat(stats_, MethodCompilationStat::kPossibleWriteBarrier);
    HInstruction* obj = HuntForOriginalReference(instruction->InputAt(0));
    auto it = current_write_barriers_.find(obj);
    if (it != current_write_barriers_.end()) {
      DCHECK(it->second->IsInstanceFieldSet());
      DCHECK(it->second->AsInstanceFieldSet()->GetWriteBarrierKind() !=
             WriteBarrierKind::kDontEmit);
      DCHECK_EQ(it->second->GetBlock(), instruction->GetBlock());
      it->second->AsInstanceFieldSet()->SetWriteBarrierKind(WriteBarrierKind::kEmitNoNullCheck);
      instruction->SetWriteBarrierKind(WriteBarrierKind::kDontEmit);
      MaybeRecordStat(stats_, MethodCompilationStat::kRemovedWriteBarrier);
    } else {
      const bool inserted = current_write_barriers_.insert({obj, instruction}).second;
      DCHECK(inserted);
      DCHECK(instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit);
    }
  }

  void VisitStaticFieldSet(HStaticFieldSet* instruction) override {
    DCHECK(!instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC()));

    if (instruction->GetFieldType() != DataType::Type::kReference ||
        instruction->GetValue()->IsNullConstant()) {
      instruction->SetWriteBarrierKind(WriteBarrierKind::kDontEmit);
      return;
    }

    MaybeRecordStat(stats_, MethodCompilationStat::kPossibleWriteBarrier);
    HInstruction* cls = HuntForOriginalReference(instruction->InputAt(0));
    auto it = current_write_barriers_.find(cls);
    if (it != current_write_barriers_.end()) {
      DCHECK(it->second->IsStaticFieldSet());
      DCHECK(it->second->AsStaticFieldSet()->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit);
      DCHECK_EQ(it->second->GetBlock(), instruction->GetBlock());
      it->second->AsStaticFieldSet()->SetWriteBarrierKind(WriteBarrierKind::kEmitNoNullCheck);
      instruction->SetWriteBarrierKind(WriteBarrierKind::kDontEmit);
      MaybeRecordStat(stats_, MethodCompilationStat::kRemovedWriteBarrier);
    } else {
      const bool inserted = current_write_barriers_.insert({cls, instruction}).second;
      DCHECK(inserted);
      DCHECK(instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit);
    }
  }

  void VisitArraySet(HArraySet* instruction) override {
    if (instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC())) {
      ClearCurrentValues();
    }

    if (instruction->GetComponentType() != DataType::Type::kReference ||
        instruction->GetValue()->IsNullConstant()) {
      instruction->SetWriteBarrierKind(WriteBarrierKind::kDontEmit);
      return;
    }

    HInstruction* arr = HuntForOriginalReference(instruction->InputAt(0));
    MaybeRecordStat(stats_, MethodCompilationStat::kPossibleWriteBarrier);
    auto it = current_write_barriers_.find(arr);
    if (it != current_write_barriers_.end()) {
      DCHECK(it->second->IsArraySet());
      DCHECK(it->second->AsArraySet()->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit);
      DCHECK_EQ(it->second->GetBlock(), instruction->GetBlock());
      // We never skip the null check in ArraySets so that value is already set.
      DCHECK(it->second->AsArraySet()->GetWriteBarrierKind() == WriteBarrierKind::kEmitNoNullCheck);
      instruction->SetWriteBarrierKind(WriteBarrierKind::kDontEmit);
      MaybeRecordStat(stats_, MethodCompilationStat::kRemovedWriteBarrier);
    } else {
      const bool inserted = current_write_barriers_.insert({arr, instruction}).second;
      DCHECK(inserted);
      DCHECK(instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit);
    }
  }

  void VisitInstruction(HInstruction* instruction) override {
    if (instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC())) {
      ClearCurrentValues();
    }
  }

 private:
  void ClearCurrentValues() { current_write_barriers_.clear(); }

  HInstruction* HuntForOriginalReference(HInstruction* ref) const {
    // An original reference can be transformed by instructions like:
    //   i0 NewArray
    //   i1 HInstruction(i0)  <-- NullCheck, BoundType, IntermediateAddress.
    //   i2 ArraySet(i1, index, value)
    DCHECK(ref != nullptr);
    while (ref->IsNullCheck() || ref->IsBoundType() || ref->IsIntermediateAddress()) {
      ref = ref->InputAt(0);
    }
    return ref;
  }

  ScopedArenaAllocator scoped_allocator_;

  // Stores a map of <Receiver, InstructionWhereTheWriteBarrierIs>.
  // `InstructionWhereTheWriteBarrierIs` is used for DCHECKs only.
  ScopedArenaHashMap<HInstruction*, HInstruction*> current_write_barriers_;

  OptimizingCompilerStats* const stats_;

  DISALLOW_COPY_AND_ASSIGN(WBEVisitor);
};

bool WriteBarrierElimination::Run() {
  if (kWBEEnabled) {
    WBEVisitor wbe_visitor(graph_, stats_);
    wbe_visitor.VisitReversePostOrder();
  }
  return true;
}

}  // namespace art
