// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "hydrogen-alias-analysis.h"
#include "hydrogen-load-elimination.h"
#include "hydrogen-instructions.h"
#include "hydrogen-flow-engine.h"

namespace v8 {
namespace internal {

#define GLOBAL true
#define TRACE(x) if (FLAG_trace_load_elimination) PrintF x

static const int kMaxTrackedFields = 16;
static const int kMaxTrackedObjects = 5;

// An element in the field approximation list.
class HFieldApproximation : public ZoneObject {
 public:  // Just a data blob.
  HValue* object_;
  HValue* last_value_;
  HFieldApproximation* next_;

  // Recursively copy the entire linked list of field approximations.
  HFieldApproximation* Copy(Zone* zone) {
    if (this == NULL) return NULL;
    HFieldApproximation* copy = new(zone) HFieldApproximation();
    copy->object_ = this->object_;
    copy->last_value_ = this->last_value_;
    copy->next_ = this->next_->Copy(zone);
    return copy;
  }
};


// The main datastructure used during load/store elimination. Each in-object
// field is tracked separately. For each field, store a list of known field
// values for known objects.
class HLoadEliminationTable : public ZoneObject {
 public:
  HLoadEliminationTable(Zone* zone, HAliasAnalyzer* aliasing)
    : zone_(zone), fields_(kMaxTrackedFields, zone), aliasing_(aliasing) { }

  // The main processing of instructions.
  HLoadEliminationTable* Process(HInstruction* instr, Zone* zone) {
    switch (instr->opcode()) {
      case HValue::kLoadNamedField: {
        HLoadNamedField* l = HLoadNamedField::cast(instr);
        TRACE((" process L%d field %d (o%d)\n",
               instr->id(),
               FieldOf(l->access()),
               l->object()->ActualValue()->id()));
        HValue* result = load(l);
        if (result != instr &&
            result->type().Equals(instr->type()) &&
            result->representation().Equals(instr->representation())) {
          // The load can be replaced with a previous load or a value.
          TRACE(("  replace L%d -> v%d\n", instr->id(), result->id()));
          instr->DeleteAndReplaceWith(result);
        }
        break;
      }
      case HValue::kStoreNamedField: {
        HStoreNamedField* s = HStoreNamedField::cast(instr);
        TRACE((" process S%d field %d (o%d) = v%d\n",
               instr->id(),
               FieldOf(s->access()),
               s->object()->ActualValue()->id(),
               s->value()->id()));
        HValue* result = store(s);
        if (result == NULL) {
          // The store is redundant. Remove it.
          TRACE(("  remove S%d\n", instr->id()));
          instr->DeleteAndReplaceWith(NULL);
        }
        break;
      }
      case HValue::kTransitionElementsKind: {
        HTransitionElementsKind* t = HTransitionElementsKind::cast(instr);
        HValue* object = t->object()->ActualValue();
        KillFieldInternal(object, FieldOf(JSArray::kElementsOffset), NULL);
        KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL);
        break;
      }
      default: {
        if (instr->CheckChangesFlag(kInobjectFields)) {
          TRACE((" kill-all i%d\n", instr->id()));
          Kill();
          break;
        }
        if (instr->CheckChangesFlag(kMaps)) {
          TRACE((" kill-maps i%d\n", instr->id()));
          KillOffset(JSObject::kMapOffset);
        }
        if (instr->CheckChangesFlag(kElementsKind)) {
          TRACE((" kill-elements-kind i%d\n", instr->id()));
          KillOffset(JSObject::kMapOffset);
          KillOffset(JSObject::kElementsOffset);
        }
        if (instr->CheckChangesFlag(kElementsPointer)) {
          TRACE((" kill-elements i%d\n", instr->id()));
          KillOffset(JSObject::kElementsOffset);
        }
        if (instr->CheckChangesFlag(kOsrEntries)) {
          TRACE((" kill-osr i%d\n", instr->id()));
          Kill();
        }
      }
      // Improvements possible:
      // - learn from HCheckMaps for field 0
      // - remove unobservable stores (write-after-write)
      // - track cells
      // - track globals
      // - track roots
    }
    return this;
  }

  // Support for global analysis with HFlowEngine: Merge given state with
  // the other incoming state.
  static HLoadEliminationTable* Merge(HLoadEliminationTable* succ_state,
                                      HBasicBlock* succ_block,
                                      HLoadEliminationTable* pred_state,
                                      HBasicBlock* pred_block,
                                      Zone* zone) {
    ASSERT(pred_state != NULL);
    if (succ_state == NULL) {
      return pred_state->Copy(succ_block, pred_block, zone);
    } else {
      return succ_state->Merge(succ_block, pred_state, pred_block, zone);
    }
  }

  // Support for global analysis with HFlowEngine: Given state merged with all
  // the other incoming states, prepare it for use.
  static HLoadEliminationTable* Finish(HLoadEliminationTable* state,
                                       HBasicBlock* block,
                                       Zone* zone) {
    ASSERT(state != NULL);
    return state;
  }

 private:
  // Copy state to successor block.
  HLoadEliminationTable* Copy(HBasicBlock* succ, HBasicBlock* from_block,
                              Zone* zone) {
    HLoadEliminationTable* copy =
        new(zone) HLoadEliminationTable(zone, aliasing_);
    copy->EnsureFields(fields_.length());
    for (int i = 0; i < fields_.length(); i++) {
      copy->fields_[i] = fields_[i]->Copy(zone);
    }
    if (FLAG_trace_load_elimination) {
      TRACE((" copy-to B%d\n", succ->block_id()));
      copy->Print();
    }
    return copy;
  }

  // Merge this state with the other incoming state.
  HLoadEliminationTable* Merge(HBasicBlock* succ, HLoadEliminationTable* that,
                               HBasicBlock* that_block, Zone* zone) {
    if (that->fields_.length() < fields_.length()) {
      // Drop fields not in the other table.
      fields_.Rewind(that->fields_.length());
    }
    for (int i = 0; i < fields_.length(); i++) {
      // Merge the field approximations for like fields.
      HFieldApproximation* approx = fields_[i];
      HFieldApproximation* prev = NULL;
      while (approx != NULL) {
        // TODO(titzer): Merging is O(N * M); sort?
        HFieldApproximation* other = that->Find(approx->object_, i);
        if (other == NULL || !Equal(approx->last_value_, other->last_value_)) {
          // Kill an entry that doesn't agree with the other value.
          if (prev != NULL) {
            prev->next_ = approx->next_;
          } else {
            fields_[i] = approx->next_;
          }
          approx = approx->next_;
          continue;
        }
        prev = approx;
        approx = approx->next_;
      }
    }
    if (FLAG_trace_load_elimination) {
      TRACE((" merge-to B%d\n", succ->block_id()));
      Print();
    }
    return this;
  }

  friend class HLoadEliminationEffects;  // Calls Kill() and others.
  friend class HLoadEliminationPhase;

 private:
  // Process a load instruction, updating internal table state. If a previous
  // load or store for this object and field exists, return the new value with
  // which the load should be replaced. Otherwise, return {instr}.
  HValue* load(HLoadNamedField* instr) {
    // There must be no loads from non observable in-object properties.
    ASSERT(!instr->access().IsInobject() ||
           instr->access().existing_inobject_property());

    int field = FieldOf(instr->access());
    if (field < 0) return instr;

    HValue* object = instr->object()->ActualValue();
    HFieldApproximation* approx = FindOrCreate(object, field);

    if (approx->last_value_ == NULL) {
      // Load is not redundant. Fill out a new entry.
      approx->last_value_ = instr;
      return instr;
    } else if (approx->last_value_->block()->EqualToOrDominates(
        instr->block())) {
      // Eliminate the load. Reuse previously stored value or load instruction.
      return approx->last_value_;
    } else {
      return instr;
    }
  }

  // Process a store instruction, updating internal table state. If a previous
  // store to the same object and field makes this store redundant (e.g. because
  // the stored values are the same), return NULL indicating that this store
  // instruction is redundant. Otherwise, return {instr}.
  HValue* store(HStoreNamedField* instr) {
    if (instr->access().IsInobject() &&
        !instr->access().existing_inobject_property()) {
      TRACE(("  skipping non existing property initialization store\n"));
      return instr;
    }

    int field = FieldOf(instr->access());
    if (field < 0) return KillIfMisaligned(instr);

    HValue* object = instr->object()->ActualValue();
    HValue* value = instr->value();

    if (instr->has_transition()) {
      // A transition introduces a new field and alters the map of the object.
      // Since the field in the object is new, it cannot alias existing entries.
      // TODO(titzer): introduce a constant for the new map and remember it.
      KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL);
    } else {
      // Kill non-equivalent may-alias entries.
      KillFieldInternal(object, field, value);
    }
    HFieldApproximation* approx = FindOrCreate(object, field);

    if (Equal(approx->last_value_, value)) {
      // The store is redundant because the field already has this value.
      return NULL;
    } else {
      // The store is not redundant. Update the entry.
      approx->last_value_ = value;
      return instr;
    }
  }

  // Kill everything in this table.
  void Kill() {
    fields_.Rewind(0);
  }

  // Kill all entries matching the given offset.
  void KillOffset(int offset) {
    int field = FieldOf(offset);
    if (field >= 0 && field < fields_.length()) {
      fields_[field] = NULL;
    }
  }

  // Kill all entries aliasing the given store.
  void KillStore(HStoreNamedField* s) {
    int field = FieldOf(s->access());
    if (field >= 0) {
      KillFieldInternal(s->object()->ActualValue(), field, s->value());
    } else {
      KillIfMisaligned(s);
    }
  }

  // Kill multiple entries in the case of a misaligned store.
  HValue* KillIfMisaligned(HStoreNamedField* instr) {
    HObjectAccess access = instr->access();
    if (access.IsInobject()) {
      int offset = access.offset();
      if ((offset % kPointerSize) != 0) {
        // Kill the field containing the first word of the access.
        HValue* object = instr->object()->ActualValue();
        int field = offset / kPointerSize;
        KillFieldInternal(object, field, NULL);

        // Kill the next field in case of overlap.
        int size = access.representation().size();
        int next_field = (offset + size - 1) / kPointerSize;
        if (next_field != field) KillFieldInternal(object, next_field, NULL);
      }
    }
    return instr;
  }

  // Find an entry for the given object and field pair.
  HFieldApproximation* Find(HValue* object, int field) {
    // Search for a field approximation for this object.
    HFieldApproximation* approx = fields_[field];
    while (approx != NULL) {
      if (aliasing_->MustAlias(object, approx->object_)) return approx;
      approx = approx->next_;
    }
    return NULL;
  }

  // Find or create an entry for the given object and field pair.
  HFieldApproximation* FindOrCreate(HValue* object, int field) {
    EnsureFields(field + 1);

    // Search for a field approximation for this object.
    HFieldApproximation* approx = fields_[field];
    int count = 0;
    while (approx != NULL) {
      if (aliasing_->MustAlias(object, approx->object_)) return approx;
      count++;
      approx = approx->next_;
    }

    if (count >= kMaxTrackedObjects) {
      // Pull the last entry off the end and repurpose it for this object.
      approx = ReuseLastApproximation(field);
    } else {
      // Allocate a new entry.
      approx = new(zone_) HFieldApproximation();
    }

    // Insert the entry at the head of the list.
    approx->object_ = object;
    approx->last_value_ = NULL;
    approx->next_ = fields_[field];
    fields_[field] = approx;

    return approx;
  }

  // Kill all entries for a given field that _may_ alias the given object
  // and do _not_ have the given value.
  void KillFieldInternal(HValue* object, int field, HValue* value) {
    if (field >= fields_.length()) return;  // Nothing to do.

    HFieldApproximation* approx = fields_[field];
    HFieldApproximation* prev = NULL;
    while (approx != NULL) {
      if (aliasing_->MayAlias(object, approx->object_)) {
        if (!Equal(approx->last_value_, value)) {
          // Kill an aliasing entry that doesn't agree on the value.
          if (prev != NULL) {
            prev->next_ = approx->next_;
          } else {
            fields_[field] = approx->next_;
          }
          approx = approx->next_;
          continue;
        }
      }
      prev = approx;
      approx = approx->next_;
    }
  }

  bool Equal(HValue* a, HValue* b) {
    if (a == b) return true;
    if (a != NULL && b != NULL && a->CheckFlag(HValue::kUseGVN)) {
      return a->Equals(b);
    }
    return false;
  }

  // Remove the last approximation for a field so that it can be reused.
  // We reuse the last entry because it was the first inserted and is thus
  // farthest away from the current instruction.
  HFieldApproximation* ReuseLastApproximation(int field) {
    HFieldApproximation* approx = fields_[field];
    ASSERT(approx != NULL);

    HFieldApproximation* prev = NULL;
    while (approx->next_ != NULL) {
      prev = approx;
      approx = approx->next_;
    }
    if (prev != NULL) prev->next_ = NULL;
    return approx;
  }

  // Compute the field index for the given object access; -1 if not tracked.
  int FieldOf(HObjectAccess access) {
    return access.IsInobject() ? FieldOf(access.offset()) : -1;
  }

  // Compute the field index for the given in-object offset; -1 if not tracked.
  int FieldOf(int offset) {
    if (offset >= kMaxTrackedFields * kPointerSize) return -1;
    // TODO(titzer): track misaligned loads in a separate list?
    if ((offset % kPointerSize) != 0) return -1;  // Ignore misaligned accesses.
    return offset / kPointerSize;
  }

  // Ensure internal storage for the given number of fields.
  void EnsureFields(int num_fields) {
    if (fields_.length() < num_fields) {
      fields_.AddBlock(NULL, num_fields - fields_.length(), zone_);
    }
  }

  // Print this table to stdout.
  void Print() {
    for (int i = 0; i < fields_.length(); i++) {
      PrintF("  field %d: ", i);
      for (HFieldApproximation* a = fields_[i]; a != NULL; a = a->next_) {
        PrintF("[o%d =", a->object_->id());
        if (a->last_value_ != NULL) PrintF(" v%d", a->last_value_->id());
        PrintF("] ");
      }
      PrintF("\n");
    }
  }

  Zone* zone_;
  ZoneList<HFieldApproximation*> fields_;
  HAliasAnalyzer* aliasing_;
};


// Support for HFlowEngine: collect store effects within loops.
class HLoadEliminationEffects : public ZoneObject {
 public:
  explicit HLoadEliminationEffects(Zone* zone)
    : zone_(zone), stores_(5, zone) { }

  inline bool Disabled() {
    return false;  // Effects are _not_ disabled.
  }

  // Process a possibly side-effecting instruction.
  void Process(HInstruction* instr, Zone* zone) {
    if (instr->IsStoreNamedField()) {
      stores_.Add(HStoreNamedField::cast(instr), zone_);
    } else {
      flags_.Add(instr->ChangesFlags());
    }
  }

  // Apply these effects to the given load elimination table.
  void Apply(HLoadEliminationTable* table) {
    // Loads must not be hoisted past the OSR entry, therefore we kill
    // everything if we see an OSR entry.
    if (flags_.Contains(kInobjectFields) || flags_.Contains(kOsrEntries)) {
      table->Kill();
      return;
    }
    if (flags_.Contains(kElementsKind) || flags_.Contains(kMaps)) {
      table->KillOffset(JSObject::kMapOffset);
    }
    if (flags_.Contains(kElementsKind) || flags_.Contains(kElementsPointer)) {
      table->KillOffset(JSObject::kElementsOffset);
    }

    // Kill non-agreeing fields for each store contained in these effects.
    for (int i = 0; i < stores_.length(); i++) {
      table->KillStore(stores_[i]);
    }
  }

  // Union these effects with the other effects.
  void Union(HLoadEliminationEffects* that, Zone* zone) {
    flags_.Add(that->flags_);
    for (int i = 0; i < that->stores_.length(); i++) {
      stores_.Add(that->stores_[i], zone);
    }
  }

 private:
  Zone* zone_;
  GVNFlagSet flags_;
  ZoneList<HStoreNamedField*> stores_;
};


// The main routine of the analysis phase. Use the HFlowEngine for either a
// local or a global analysis.
void HLoadEliminationPhase::Run() {
  HFlowEngine<HLoadEliminationTable, HLoadEliminationEffects>
    engine(graph(), zone());
  HAliasAnalyzer aliasing;
  HLoadEliminationTable* table =
      new(zone()) HLoadEliminationTable(zone(), &aliasing);

  if (GLOBAL) {
    // Perform a global analysis.
    engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table);
  } else {
    // Perform only local analysis.
    for (int i = 0; i < graph()->blocks()->length(); i++) {
      table->Kill();
      engine.AnalyzeOneBlock(graph()->blocks()->at(i), table);
    }
  }
}

} }  // namespace v8::internal
