// Copyright 2017 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/property-access-builder.h"

#include "src/compilation-dependencies.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/access-info.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/simplified-operator.h"
#include "src/lookup.h"

#include "src/field-index-inl.h"
#include "src/isolate-inl.h"

namespace v8 {
namespace internal {
namespace compiler {

Graph* PropertyAccessBuilder::graph() const { return jsgraph()->graph(); }

Isolate* PropertyAccessBuilder::isolate() const { return jsgraph()->isolate(); }

CommonOperatorBuilder* PropertyAccessBuilder::common() const {
  return jsgraph()->common();
}

SimplifiedOperatorBuilder* PropertyAccessBuilder::simplified() const {
  return jsgraph()->simplified();
}

bool HasOnlyStringMaps(MapHandles const& maps) {
  for (auto map : maps) {
    if (!map->IsStringMap()) return false;
  }
  return true;
}

namespace {

bool HasOnlyNumberMaps(MapHandles const& maps) {
  for (auto map : maps) {
    if (map->instance_type() != HEAP_NUMBER_TYPE) return false;
  }
  return true;
}

bool HasOnlySequentialStringMaps(MapHandles const& maps) {
  for (auto map : maps) {
    if (!map->IsStringMap()) return false;
    if (!StringShape(map->instance_type()).IsSequential()) {
      return false;
    }
  }
  return true;
}

}  // namespace

bool PropertyAccessBuilder::TryBuildStringCheck(MapHandles const& maps,
                                                Node** receiver, Node** effect,
                                                Node* control) {
  if (HasOnlyStringMaps(maps)) {
    if (HasOnlySequentialStringMaps(maps)) {
      *receiver = *effect = graph()->NewNode(simplified()->CheckSeqString(),
                                             *receiver, *effect, control);
    } else {
      // Monormorphic string access (ignoring the fact that there are multiple
      // String maps).
      *receiver = *effect = graph()->NewNode(simplified()->CheckString(),
                                             *receiver, *effect, control);
    }
    return true;
  }
  return false;
}

bool PropertyAccessBuilder::TryBuildNumberCheck(MapHandles const& maps,
                                                Node** receiver, Node** effect,
                                                Node* control) {
  if (HasOnlyNumberMaps(maps)) {
    // Monomorphic number access (we also deal with Smis here).
    *receiver = *effect = graph()->NewNode(simplified()->CheckNumber(),
                                           *receiver, *effect, control);
    return true;
  }
  return false;
}

Node* PropertyAccessBuilder::BuildCheckHeapObject(Node* receiver, Node** effect,
                                                  Node* control) {
  switch (receiver->opcode()) {
    case IrOpcode::kHeapConstant:
    case IrOpcode::kJSCreate:
    case IrOpcode::kJSCreateArguments:
    case IrOpcode::kJSCreateArray:
    case IrOpcode::kJSCreateClosure:
    case IrOpcode::kJSCreateIterResultObject:
    case IrOpcode::kJSCreateLiteralArray:
    case IrOpcode::kJSCreateLiteralObject:
    case IrOpcode::kJSCreateLiteralRegExp:
    case IrOpcode::kJSConvertReceiver:
    case IrOpcode::kJSToName:
    case IrOpcode::kJSToString:
    case IrOpcode::kJSToObject:
    case IrOpcode::kJSTypeOf: {
      return receiver;
    }
    default: {
      return *effect = graph()->NewNode(simplified()->CheckHeapObject(),
                                        receiver, *effect, control);
    }
  }
  UNREACHABLE();
  return nullptr;
}

void PropertyAccessBuilder::BuildCheckMaps(
    Node* receiver, Node** effect, Node* control,
    std::vector<Handle<Map>> const& receiver_maps) {
  HeapObjectMatcher m(receiver);
  if (m.HasValue()) {
    Handle<Map> receiver_map(m.Value()->map(), isolate());
    if (receiver_map->is_stable()) {
      for (Handle<Map> map : receiver_maps) {
        if (map.is_identical_to(receiver_map)) {
          dependencies()->AssumeMapStable(receiver_map);
          return;
        }
      }
    }
  }
  ZoneHandleSet<Map> maps;
  CheckMapsFlags flags = CheckMapsFlag::kNone;
  for (Handle<Map> map : receiver_maps) {
    maps.insert(map, graph()->zone());
    if (map->is_migration_target()) {
      flags |= CheckMapsFlag::kTryMigrateInstance;
    }
  }
  *effect = graph()->NewNode(simplified()->CheckMaps(flags, maps), receiver,
                             *effect, control);
}

void PropertyAccessBuilder::AssumePrototypesStable(
    Handle<Context> native_context,
    std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) {
  // Determine actual holder and perform prototype chain checks.
  for (auto map : receiver_maps) {
    // Perform the implicit ToObject for primitives here.
    // Implemented according to ES6 section 7.3.2 GetV (V, P).
    Handle<JSFunction> constructor;
    if (Map::GetConstructorFunction(map, native_context)
            .ToHandle(&constructor)) {
      map = handle(constructor->initial_map(), holder->GetIsolate());
    }
    dependencies()->AssumePrototypeMapsStable(map, holder);
  }
}

Node* PropertyAccessBuilder::ResolveHolder(
    PropertyAccessInfo const& access_info, Node* receiver) {
  Handle<JSObject> holder;
  if (access_info.holder().ToHandle(&holder)) {
    return jsgraph()->Constant(holder);
  }
  return receiver;
}

Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
    Handle<Name> name, PropertyAccessInfo const& access_info, Node* receiver) {
  // Optimize immutable property loads.
  HeapObjectMatcher m(receiver);
  if (m.HasValue() && m.Value()->IsJSObject()) {
    // TODO(ishell): Use something simpler like
    //
    // Handle<Object> value =
    //     JSObject::FastPropertyAt(Handle<JSObject>::cast(m.Value()),
    //                              Representation::Tagged(), field_index);
    //
    // here, once we have the immutable bit in the access_info.

    // TODO(turbofan): Given that we already have the field_index here, we
    // might be smarter in the future and not rely on the LookupIterator,
    // but for now let's just do what Crankshaft does.
    LookupIterator it(m.Value(), name, LookupIterator::OWN_SKIP_INTERCEPTOR);
    if (it.state() == LookupIterator::DATA) {
      bool is_reaonly_non_configurable =
          it.IsReadOnly() && !it.IsConfigurable();
      if (is_reaonly_non_configurable ||
          (FLAG_track_constant_fields && access_info.IsDataConstantField())) {
        Node* value = jsgraph()->Constant(JSReceiver::GetDataProperty(&it));
        if (!is_reaonly_non_configurable) {
          // It's necessary to add dependency on the map that introduced
          // the field.
          DCHECK(access_info.IsDataConstantField());
          DCHECK(!it.is_dictionary_holder());
          Handle<Map> field_owner_map = it.GetFieldOwnerMap();
          dependencies()->AssumeFieldOwner(field_owner_map);
        }
        return value;
      }
    }
  }
  return nullptr;
}

Node* PropertyAccessBuilder::BuildLoadDataField(
    Handle<Name> name, PropertyAccessInfo const& access_info, Node* receiver,
    Node** effect, Node** control) {
  DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
  receiver = ResolveHolder(access_info, receiver);
  if (Node* value =
          TryBuildLoadConstantDataField(name, access_info, receiver)) {
    return value;
  }

  FieldIndex const field_index = access_info.field_index();
  Type* const field_type = access_info.field_type();
  MachineRepresentation const field_representation =
      access_info.field_representation();
  Node* storage = receiver;
  if (!field_index.is_inobject()) {
    storage = *effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSObjectPropertiesOrHash()),
        storage, *effect, *control);
  }
  FieldAccess field_access = {
      kTaggedBase,
      field_index.offset(),
      name,
      MaybeHandle<Map>(),
      field_type,
      MachineType::TypeForRepresentation(field_representation),
      kFullWriteBarrier};
  if (field_representation == MachineRepresentation::kFloat64) {
    if (!field_index.is_inobject() || field_index.is_hidden_field() ||
        !FLAG_unbox_double_fields) {
      FieldAccess const storage_access = {kTaggedBase,
                                          field_index.offset(),
                                          name,
                                          MaybeHandle<Map>(),
                                          Type::OtherInternal(),
                                          MachineType::TaggedPointer(),
                                          kPointerWriteBarrier};
      storage = *effect = graph()->NewNode(
          simplified()->LoadField(storage_access), storage, *effect, *control);
      field_access.offset = HeapNumber::kValueOffset;
      field_access.name = MaybeHandle<Name>();
    }
  } else if (field_representation == MachineRepresentation::kTaggedPointer) {
    // Remember the map of the field value, if its map is stable. This is
    // used by the LoadElimination to eliminate map checks on the result.
    Handle<Map> field_map;
    if (access_info.field_map().ToHandle(&field_map)) {
      if (field_map->is_stable()) {
        dependencies()->AssumeMapStable(field_map);
        field_access.map = field_map;
      }
    }
  }
  Node* value = *effect = graph()->NewNode(
      simplified()->LoadField(field_access), storage, *effect, *control);
  return value;
}

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