// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#if !defined(DART_PRECOMPILED_RUNTIME)

#include "vm/deferred_objects.h"

#include "vm/code_patcher.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/deopt_instructions.h"
#include "vm/flags.h"
#include "vm/object.h"

namespace dart {

DECLARE_FLAG(bool, trace_deoptimization);
DECLARE_FLAG(bool, trace_deoptimization_verbose);

void DeferredDouble::Materialize(DeoptContext* deopt_context) {
  DoublePtr* double_slot = reinterpret_cast<DoublePtr*>(slot());
  *double_slot = Double::New(value());

  if (FLAG_trace_deoptimization_verbose) {
    OS::PrintErr("materializing double at %" Px ": %g\n",
                 reinterpret_cast<uword>(slot()), value());
  }
}

void DeferredMint::Materialize(DeoptContext* deopt_context) {
  MintPtr* mint_slot = reinterpret_cast<MintPtr*>(slot());
  ASSERT(!Smi::IsValid(value()));
  Mint& mint = Mint::Handle();
  mint ^= Integer::New(value());
  *mint_slot = mint.ptr();

  if (FLAG_trace_deoptimization_verbose) {
    OS::PrintErr("materializing mint at %" Px ": %" Pd64 "\n",
                 reinterpret_cast<uword>(slot()), value());
  }
}

void DeferredFloat32x4::Materialize(DeoptContext* deopt_context) {
  Float32x4Ptr* float32x4_slot = reinterpret_cast<Float32x4Ptr*>(slot());
  Float32x4Ptr raw_float32x4 = Float32x4::New(value());
  *float32x4_slot = raw_float32x4;

  if (FLAG_trace_deoptimization_verbose) {
    float x = raw_float32x4->untag()->x();
    float y = raw_float32x4->untag()->y();
    float z = raw_float32x4->untag()->z();
    float w = raw_float32x4->untag()->w();
    OS::PrintErr("materializing Float32x4 at %" Px ": %g,%g,%g,%g\n",
                 reinterpret_cast<uword>(slot()), x, y, z, w);
  }
}

void DeferredFloat64x2::Materialize(DeoptContext* deopt_context) {
  Float64x2Ptr* float64x2_slot = reinterpret_cast<Float64x2Ptr*>(slot());
  Float64x2Ptr raw_float64x2 = Float64x2::New(value());
  *float64x2_slot = raw_float64x2;

  if (FLAG_trace_deoptimization_verbose) {
    double x = raw_float64x2->untag()->x();
    double y = raw_float64x2->untag()->y();
    OS::PrintErr("materializing Float64x2 at %" Px ": %g,%g\n",
                 reinterpret_cast<uword>(slot()), x, y);
  }
}

void DeferredInt32x4::Materialize(DeoptContext* deopt_context) {
  Int32x4Ptr* int32x4_slot = reinterpret_cast<Int32x4Ptr*>(slot());
  Int32x4Ptr raw_int32x4 = Int32x4::New(value());
  *int32x4_slot = raw_int32x4;

  if (FLAG_trace_deoptimization_verbose) {
    uint32_t x = raw_int32x4->untag()->x();
    uint32_t y = raw_int32x4->untag()->y();
    uint32_t z = raw_int32x4->untag()->z();
    uint32_t w = raw_int32x4->untag()->w();
    OS::PrintErr("materializing Int32x4 at %" Px ": %x,%x,%x,%x\n",
                 reinterpret_cast<uword>(slot()), x, y, z, w);
  }
}

void DeferredObjectRef::Materialize(DeoptContext* deopt_context) {
  DeferredObject* obj = deopt_context->GetDeferredObject(index());
  *slot() = obj->object();
  if (FLAG_trace_deoptimization_verbose) {
    const Class& cls = Class::Handle(IsolateGroup::Current()->class_table()->At(
        Object::Handle(obj->object()).GetClassId()));
    OS::PrintErr("writing instance of class %s ref at %" Px ".\n",
                 cls.ToCString(), reinterpret_cast<uword>(slot()));
  }
}

void DeferredRetAddr::Materialize(DeoptContext* deopt_context) {
  Thread* thread = deopt_context->thread();
  Zone* zone = deopt_context->zone();
  Function& function = Function::Handle(zone);
  function ^= deopt_context->ObjectAt(index_);
  const Error& error =
      Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function));
  if (!error.IsNull()) {
    Exceptions::PropagateError(error);
  }
  const Code& code = Code::Handle(zone, function.unoptimized_code());

  uword continue_at_pc =
      code.GetPcForDeoptId(deopt_id_, UntaggedPcDescriptors::kDeopt);
  if (continue_at_pc == 0) {
    FATAL2("Can't locate continuation PC for deoptid %" Pd " within %s\n",
           deopt_id_, function.ToFullyQualifiedCString());
  }
  uword* dest_addr = reinterpret_cast<uword*>(slot());
  *dest_addr = continue_at_pc;

  if (FLAG_trace_deoptimization_verbose) {
    OS::PrintErr("materializing return addr at 0x%" Px ": 0x%" Px "\n",
                 reinterpret_cast<uword>(slot()), continue_at_pc);
  }

  uword pc = code.GetPcForDeoptId(deopt_id_, UntaggedPcDescriptors::kIcCall);
  if (pc != 0) {
    // If the deoptimization happened at an IC call, update the IC data
    // to avoid repeated deoptimization at the same site next time around.
    // We cannot use CodePatcher::GetInstanceCallAt because the call site
    // may have switched to from referencing an ICData to a target Code or
    // MegamorphicCache.
    ICData& ic_data = ICData::Handle(zone, function.FindICData(deopt_id_));
    ic_data.AddDeoptReason(deopt_context->deopt_reason());
    // Propagate the reason to all ICData-s with same deopt_id since
    // only unoptimized-code ICData (IC calls) are propagated.
    function.SetDeoptReasonForAll(ic_data.deopt_id(),
                                  deopt_context->deopt_reason());
  } else {
    if (deopt_context->HasDeoptFlag(ICData::kHoisted)) {
      // Prevent excessive deoptimization.
      function.SetProhibitsHoistingCheckClass(true);
    }

    if (deopt_context->HasDeoptFlag(ICData::kGeneralized)) {
      function.SetProhibitsBoundsCheckGeneralization(true);
    }
  }
}

void DeferredPcMarker::Materialize(DeoptContext* deopt_context) {
  Thread* thread = deopt_context->thread();
  Zone* zone = deopt_context->zone();
  uword* dest_addr = reinterpret_cast<uword*>(slot());
  Function& function = Function::Handle(zone);
  function ^= deopt_context->ObjectAt(index_);
  ASSERT(!function.IsNull());
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  const Error& error =
      Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function));
  if (!error.IsNull()) {
    Exceptions::PropagateError(error);
  }
  const Code& code = Code::Handle(zone, function.unoptimized_code());
  ASSERT(!code.IsNull());
  ASSERT(function.HasCode());
  *reinterpret_cast<ObjectPtr*>(dest_addr) = code.ptr();

  if (FLAG_trace_deoptimization_verbose) {
    THR_Print("materializing pc marker at 0x%" Px ": %s, %s\n",
              reinterpret_cast<uword>(slot()), code.ToCString(),
              function.ToCString());
  }

  // Increment the deoptimization counter. This effectively increments each
  // function occurring in the optimized frame.
  if (deopt_context->deoptimizing_code()) {
    function.set_deoptimization_counter(function.deoptimization_counter() + 1);
  }
  if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
    THR_Print("Deoptimizing '%s' (count %d)\n",
              function.ToFullyQualifiedCString(),
              function.deoptimization_counter());
  }
  // Clear invocation counter so that hopefully the function gets reoptimized
  // only after more feedback has been collected.
  function.SetUsageCounter(0);
  if (function.HasOptimizedCode()) {
    function.SwitchToUnoptimizedCode();
  }
}

void DeferredPp::Materialize(DeoptContext* deopt_context) {
  Thread* thread = deopt_context->thread();
  Zone* zone = deopt_context->zone();
  Function& function = Function::Handle(zone);
  function ^= deopt_context->ObjectAt(index_);
  ASSERT(!function.IsNull());
  const Error& error =
      Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function));
  if (!error.IsNull()) {
    Exceptions::PropagateError(error);
  }
  const Code& code = Code::Handle(zone, function.unoptimized_code());
  ASSERT(!code.IsNull());
  ASSERT(code.GetObjectPool() != Object::null());
  *slot() = code.GetObjectPool();

  if (FLAG_trace_deoptimization_verbose) {
    OS::PrintErr("materializing pp at 0x%" Px ": 0x%" Px "\n",
                 reinterpret_cast<uword>(slot()),
                 static_cast<uword>(code.GetObjectPool()));
  }
}

ObjectPtr DeferredObject::object() {
  if (object_ == NULL) {
    Create();
  }
  return object_->ptr();
}

void DeferredObject::Create() {
  if (object_ != NULL) {
    return;
  }

  Class& cls = Class::Handle();
  cls ^= GetClass();

  switch (cls.id()) {
    case kContextCid: {
      const intptr_t num_variables =
          Smi::Cast(Object::Handle(GetLengthOrShape())).Value();
      if (FLAG_trace_deoptimization_verbose) {
        OS::PrintErr(
            "materializing context of length %" Pd " (%" Px ", %" Pd " vars)\n",
            num_variables, reinterpret_cast<uword>(args_), field_count_);
      }
      object_ = &Context::ZoneHandle(Context::New(num_variables));
    } break;
    case kArrayCid: {
      const intptr_t num_elements =
          Smi::Cast(Object::Handle(GetLengthOrShape())).Value();
      if (FLAG_trace_deoptimization_verbose) {
        OS::PrintErr("materializing array of length %" Pd " (%" Px ", %" Pd
                     " elements)\n",
                     num_elements, reinterpret_cast<uword>(args_),
                     field_count_);
      }
      object_ = &Array::ZoneHandle(Array::New(num_elements));
    } break;
    case kRecordCid: {
      const RecordShape shape(Smi::RawCast(GetLengthOrShape()));
      if (FLAG_trace_deoptimization_verbose) {
        OS::PrintErr(
            "materializing record of shape %" Px " (%" Px ", %" Pd " fields)\n",
            shape.AsInt(), reinterpret_cast<uword>(args_), field_count_);
      }
      object_ = &Record::ZoneHandle(Record::New(shape));
    } break;
    default:
      if (IsTypedDataClassId(cls.id())) {
        const intptr_t num_elements =
            Smi::Cast(Object::Handle(GetLengthOrShape())).Value();
        if (FLAG_trace_deoptimization_verbose) {
          OS::PrintErr("materializing typed data cid %" Pd " of length %" Pd
                       " (%" Px ", %" Pd " elements)\n",
                       cls.id(), num_elements, reinterpret_cast<uword>(args_),
                       field_count_);
        }
        object_ =
            &TypedData::ZoneHandle(TypedData::New(cls.id(), num_elements));

      } else {
        if (FLAG_trace_deoptimization_verbose) {
          OS::PrintErr(
              "materializing instance of %s (%" Px ", %" Pd " fields)\n",
              cls.ToCString(), reinterpret_cast<uword>(args_), field_count_);
        }

        object_ = &Instance::ZoneHandle(Instance::New(cls));
      }
  }
}

static intptr_t ToContextIndex(intptr_t offset_in_bytes) {
  intptr_t result = (offset_in_bytes - Context::variable_offset(0)) /
                    Context::kBytesPerElement;
  ASSERT(result >= 0);
  return result;
}

void DeferredObject::Fill() {
  Create();  // Ensure instance is created.

  Class& cls = Class::Handle();
  cls ^= GetClass();

  switch (cls.id()) {
    case kContextCid: {
      const Context& context = Context::Cast(*object_);

      Smi& offset = Smi::Handle();
      Object& value = Object::Handle();

      for (intptr_t i = 0; i < field_count_; i++) {
        offset ^= GetFieldOffset(i);
        if (offset.Value() == Context::parent_offset()) {
          // Copy parent.
          Context& parent = Context::Handle();
          parent ^= GetValue(i);
          context.set_parent(parent);
          if (FLAG_trace_deoptimization_verbose) {
            OS::PrintErr("    ctx@parent (offset %" Pd ") <- %s\n",
                         offset.Value(), parent.ToCString());
          }
        } else {
          intptr_t context_index = ToContextIndex(offset.Value());
          value = GetValue(i);
          context.SetAt(context_index, value);
          if (FLAG_trace_deoptimization_verbose) {
            OS::PrintErr("    ctx@%" Pd " (offset %" Pd ") <- %s\n",
                         context_index, offset.Value(), value.ToCString());
          }
        }
      }
    } break;
    case kArrayCid: {
      const Array& array = Array::Cast(*object_);

      Smi& offset = Smi::Handle();
      Object& value = Object::Handle();

      for (intptr_t i = 0; i < field_count_; i++) {
        offset ^= GetFieldOffset(i);
        if (offset.Value() == Array::type_arguments_offset()) {
          TypeArguments& type_args = TypeArguments::Handle();
          type_args ^= GetValue(i);
          array.SetTypeArguments(type_args);
          if (FLAG_trace_deoptimization_verbose) {
            OS::PrintErr("    array@type_args (offset %" Pd ") <- %s\n",
                         offset.Value(), type_args.ToCString());
          }
        } else {
          const intptr_t index = Array::index_at_offset(offset.Value());
          value = GetValue(i);
          array.SetAt(index, value);
          if (FLAG_trace_deoptimization_verbose) {
            OS::PrintErr("    array@%" Pd " (offset %" Pd ") <- %s\n", index,
                         offset.Value(), value.ToCString());
          }
        }
      }
    } break;
    case kRecordCid: {
      const Record& record = Record::Cast(*object_);

      Smi& offset = Smi::Handle();
      Object& value = Object::Handle();

      for (intptr_t i = 0; i < field_count_; i++) {
        offset ^= GetFieldOffset(i);
        const intptr_t index = Record::field_index_at_offset(offset.Value());
        value = GetValue(i);
        record.SetFieldAt(index, value);
        if (FLAG_trace_deoptimization_verbose) {
          OS::PrintErr("    record@%" Pd " (offset %" Pd ") <- %s\n", index,
                       offset.Value(), value.ToCString());
        }
      }
    } break;
    default:
      if (IsTypedDataClassId(cls.id())) {
        const TypedData& typed_data = TypedData::Cast(*object_);

        Smi& offset = Smi::Handle();
        Object& value = Object::Handle();
        const auto cid = cls.id();

        for (intptr_t i = 0; i < field_count_; i++) {
          offset ^= GetFieldOffset(i);
          const intptr_t element_offset = offset.Value();
          value = GetValue(i);
          switch (cid) {
            case kTypedDataInt8ArrayCid:
              typed_data.SetInt8(
                  element_offset,
                  static_cast<int8_t>(Integer::Cast(value).AsInt64Value()));
              break;
            case kTypedDataUint8ArrayCid:
            case kTypedDataUint8ClampedArrayCid:
              typed_data.SetUint8(
                  element_offset,
                  static_cast<uint8_t>(Integer::Cast(value).AsInt64Value()));
              break;
            case kTypedDataInt16ArrayCid:
              typed_data.SetInt16(
                  element_offset,
                  static_cast<int16_t>(Integer::Cast(value).AsInt64Value()));
              break;
            case kTypedDataUint16ArrayCid:
              typed_data.SetUint16(
                  element_offset,
                  static_cast<uint16_t>(Integer::Cast(value).AsInt64Value()));
              break;
            case kTypedDataInt32ArrayCid:
              typed_data.SetInt32(
                  element_offset,
                  static_cast<int32_t>(Integer::Cast(value).AsInt64Value()));
              break;
            case kTypedDataUint32ArrayCid:
              typed_data.SetUint32(
                  element_offset,
                  static_cast<uint32_t>(Integer::Cast(value).AsInt64Value()));
              break;
            case kTypedDataInt64ArrayCid:
              typed_data.SetInt64(element_offset,
                                  Integer::Cast(value).AsInt64Value());
              break;
            case kTypedDataUint64ArrayCid:
              typed_data.SetUint64(
                  element_offset,
                  static_cast<uint64_t>(Integer::Cast(value).AsInt64Value()));
              break;
            case kTypedDataFloat32ArrayCid:
              // Although element of Float32 array is represented with Double,
              // it is already converted to 32-bit float via DoubleToFloat
              // instruction before it was stored.
              // Reinterpret double value as float to get the value back.
              typed_data.SetFloat32(
                  element_offset,
                  bit_cast<float, uint32_t>(
                      static_cast<uint32_t>(bit_cast<uint64_t, double>(
                          Double::Cast(value).value()))));
              break;
            case kTypedDataFloat64ArrayCid:
              typed_data.SetFloat64(element_offset,
                                    Double::Cast(value).value());
              break;
            case kTypedDataFloat32x4ArrayCid:
              typed_data.SetFloat32x4(element_offset,
                                      Float32x4::Cast(value).value());
              break;
            case kTypedDataInt32x4ArrayCid:
              typed_data.SetInt32x4(element_offset,
                                    Int32x4::Cast(value).value());
              break;
            case kTypedDataFloat64x2ArrayCid:
              typed_data.SetFloat64x2(element_offset,
                                      Float64x2::Cast(value).value());
              break;
            default:
              UNREACHABLE();
          }
          if (FLAG_trace_deoptimization_verbose) {
            OS::PrintErr("    typed_data (offset %" Pd ") <- %s\n",
                         element_offset, value.ToCString());
          }
        }
      } else {
        const Instance& obj = Instance::Cast(*object_);

        Smi& offset = Smi::Handle();
        Field& field = Field::Handle();
        Object& value = Object::Handle();
        const Array& offset_map = Array::Handle(cls.OffsetToFieldMap());

        for (intptr_t i = 0; i < field_count_; i++) {
          offset ^= GetFieldOffset(i);
          field ^= offset_map.At(offset.Value() / kCompressedWordSize);
          value = GetValue(i);
          ASSERT((value.ptr() != Object::sentinel().ptr()) ||
                 (!field.IsNull() && field.is_late()));
          if (!field.IsNull() && (value.ptr() != Object::sentinel().ptr())) {
            obj.SetField(field, value);
            if (FLAG_trace_deoptimization_verbose) {
              OS::PrintErr("    %s <- %s\n",
                           String::Handle(field.name()).ToCString(),
                           value.ToCString());
            }
          } else {
            // In addition to the type arguments vector we can also have lazy
            // materialization of e.g. _ByteDataView objects which don't have
            // explicit fields in Dart (all accesses to the fields are done via
            // recognized native methods).
            ASSERT(offset.Value() < cls.host_instance_size());
            obj.SetFieldAtOffset(offset.Value(), value);
            if (FLAG_trace_deoptimization_verbose) {
              OS::PrintErr(
                  "    %s @ offset(%" Pd ") <- %s\n",
                  (field.IsNull() ? "null Field"
                                  : String::Handle(field.name()).ToCString()),
                  offset.Value(), value.ToCString());
            }
          }
        }
      }
      break;
  }
}

}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
