// 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.

@generateCppClass
extern class JSArgumentsObject extends JSObject {
}

type JSArgumentsObjectWithLength =
    JSSloppyArgumentsObject|JSStrictArgumentsObject;

@export
macro IsJSArgumentsObjectWithLength(implicit context: Context)(o: Object):
    bool {
  return Is<JSArgumentsObjectWithLength>(o);
}

// Just a starting shape for JSObject; properties can move after initialization.
extern shape JSSloppyArgumentsObject extends JSArgumentsObject {
  length: JSAny;
  callee: JSAny;
}

// Just a starting shape for JSObject; properties can move after initialization.
extern shape JSStrictArgumentsObject extends JSArgumentsObject {
  length: JSAny;
}

// Helper class to access FAST_ and SLOW_SLOPPY_ARGUMENTS_ELEMENTS, dividing
// arguments into two types for a given SloppyArgumentsElements object:
// mapped and unmapped.
//
// For clarity SloppyArgumentsElements fields are qualified with "elements."
// below.
//
// Mapped arguments are actual arguments. Unmapped arguments are values added
// to the arguments object after it was created for the call. Mapped arguments
// are stored in the context at indexes given by elements.mapped_entries[key].
// Unmapped arguments are stored as regular indexed properties in the arguments
// array which can be accessed from elements.arguments.
//
// elements.length is min(number_of_actual_arguments,
// number_of_formal_arguments) for a concrete call to a function.
//
// Once a SloppyArgumentsElements is generated, lookup of an argument with index
// |key| in |elements| works as follows:
//
// If key >= elements.length then attempt to look in the unmapped arguments
// array and return the value at key, missing to the runtime if the unmapped
// arguments array is not a fixed array or if key >= elements.arguments.length.
//
// Otherwise, t = elements.mapped_entries[key]. If t is the hole, then the
// entry has been deleted fron the arguments object, and value is looked up in
// the unmapped arguments array, as described above. Otherwise, t is a Smi
// index into the context array specified at elements.context, and the return
// value is elements.context[t].
//
// A graphic representation of a SloppyArgumentsElements object and a
// corresponding unmapped arguments FixedArray:
//
// SloppyArgumentsElements
// +---+-----------------------+
// | Context context           |
// +---------------------------+
// | FixedArray arguments      +----+ HOLEY_ELEMENTS
// +---------------------------+    v-----+-----------+
// | 0 | Object mapped_entries |    |  0  | the_hole  |
// |...| ...                   |    | ... | ...       |
// |n-1| Object mapped_entries |    | n-1 | the_hole  |
// +---------------------------+    |  n  | element_1 |
//                                  | ... | ...       |
//                                  |n+m-1| element_m |
//                                  +-----------------+
//
// The elements.arguments backing store kind depends on the ElementsKind of
// the outer JSArgumentsObject:
// - FAST_SLOPPY_ARGUMENTS_ELEMENTS: HOLEY_ELEMENTS
// - SLOW_SLOPPY_ARGUMENTS_ELEMENTS: DICTIONARY_ELEMENTS
@export
class SloppyArgumentsElements extends FixedArrayBase {
  context: Context;
  arguments: FixedArray|NumberDictionary;
  mapped_entries[length]: Smi|TheHole;
}

macro NewSloppyArgumentsElements<Iterator: type>(
    length: Smi, context: Context, arguments: FixedArray,
    it: Iterator): SloppyArgumentsElements {
  return new
  SloppyArgumentsElements{length, context, arguments, mapped_entries: ...it};
}

@generateCppClass
@generatePrint
extern class AliasedArgumentsEntry extends Struct {
  aliased_context_slot: Smi;
}

// TODO(danno): This should be a namespace {} once supported
namespace arguments {

macro NewJSStrictArgumentsObject(implicit context: Context)(
    elements: FixedArray): JSStrictArgumentsObject {
  const map = GetStrictArgumentsMap();
  return new JSStrictArgumentsObject{
    map,
    properties_or_hash: kEmptyFixedArray,
    elements,
    length: elements.length
  };
}

macro NewJSSloppyArgumentsObject(implicit context: Context)(
    elements: FixedArrayBase, callee: JSFunction): JSSloppyArgumentsObject {
  const map = GetSloppyArgumentsMap();
  return new JSSloppyArgumentsObject{
    map,
    properties_or_hash: kEmptyFixedArray,
    elements,
    length: elements.length,
    callee
  };
}

macro NewJSFastAliasedArgumentsObject(implicit context: Context)(
    elements: FixedArrayBase, length: Smi,
    callee: JSFunction): JSSloppyArgumentsObject {
  // TODO(danno): FastAliasedArguments should really be a type for itself
  const map = GetFastAliasedArgumentsMap();
  return new JSSloppyArgumentsObject{
    map,
    properties_or_hash: kEmptyFixedArray,
    elements,
    length,
    callee
  };
}

struct ParameterMapIterator {
  macro Next(): Smi labels NoMore {
    if (this.currentIndex == this.endInterationIndex) goto NoMore;
    this.currentIndex--;
    return Convert<Smi>(this.currentIndex);
  }
  currentIndex: intptr;
  const endInterationIndex: intptr;
}

macro NewParameterMapIterator(
    context: Context, formalParameterCount: intptr,
    mappedCount: intptr): ParameterMapIterator {
  const flags = context.GetScopeInfo().flags;
  let contextHeaderSize: intptr = ContextSlot::MIN_CONTEXT_SLOTS;
  if (flags.has_context_extension_slot) ++contextHeaderSize;
  // Copy the parameter slots and the holes in the arguments.
  // We need to fill in mapped_count slots. They index the context,
  // where parameters are stored in reverse order, at
  //   context_header_size .. context_header_size+argument_count-1
  // The mapped parameter thus need to get indices
  //   context_header_size+parameter_count-1 ..
  //       context_header_size+argument_count-mapped_count
  // We loop from right to left.
  const afterLastContextIndex = contextHeaderSize + formalParameterCount;
  const firstContextIndex = afterLastContextIndex - mappedCount;
  return ParameterMapIterator{
    currentIndex: afterLastContextIndex,
    endInterationIndex: firstContextIndex
  };
}

struct ParameterValueIterator {
  macro Next(): Object labels NoMore() {
    if (this.mapped_count != 0) {
      this.mapped_count--;
      return TheHole;
    }
    if (this.current == this.arguments.length) goto NoMore;
    return this.arguments[this.current++];
  }
  mapped_count: intptr;
  const arguments: Arguments;
  current: intptr;
}

macro NewParameterValueIterator(
    mappedCount: intptr, arguments: Arguments): ParameterValueIterator {
  return ParameterValueIterator{
    mapped_count: mappedCount,
    arguments,
    current: mappedCount
  };
}

macro NewAllArguments(implicit context: Context)(
    frame: FrameWithArguments, argumentCount: intptr): JSArray {
  const map = GetFastPackedElementsJSArrayMap();
  const arguments = GetFrameArguments(frame, argumentCount);
  const it = ArgumentsIterator{arguments, current: 0};
  const elements = NewFixedArray(argumentCount, it);
  return NewJSArray(map, elements);
}

macro NewRestArgumentsElements(
    frame: FrameWithArguments, formalParameterCount: intptr,
    argumentCount: intptr): FixedArray {
  const length = (formalParameterCount >= argumentCount) ?
      0 :
      argumentCount - formalParameterCount;
  const arguments = GetFrameArguments(frame, argumentCount);
  const it = ArgumentsIterator{arguments, current: formalParameterCount};
  return NewFixedArray(length, it);
}

macro NewRestArguments(implicit context: Context)(info: FrameWithArgumentsInfo):
    JSArray {
  const argumentCount = Convert<intptr>(info.argument_count);
  const formalParameterCount = Convert<intptr>(info.formal_parameter_count);
  const map = GetFastPackedElementsJSArrayMap();
  const elements =
      NewRestArgumentsElements(info.frame, formalParameterCount, argumentCount);
  return NewJSArray(map, elements);
}

macro NewStrictArgumentsElements(
    frame: FrameWithArguments, argumentCount: intptr): FixedArray {
  const arguments = GetFrameArguments(frame, argumentCount);
  const it = ArgumentsIterator{arguments, current: 0};
  return NewFixedArray(argumentCount, it);
}

macro NewStrictArguments(implicit context: Context)(
    info: FrameWithArgumentsInfo): JSStrictArgumentsObject {
  const argumentCount = Convert<intptr>(info.argument_count);
  const elements = NewStrictArgumentsElements(info.frame, argumentCount);
  return NewJSStrictArgumentsObject(elements);
}

macro NewSloppyArgumentsElements(
    frame: FrameWithArguments, formalParameterCount: intptr,
    argumentCount: intptr): FixedArray {
  const arguments = GetFrameArguments(frame, argumentCount);
  if (formalParameterCount == 0) {
    const it = ArgumentsIterator{arguments, current: 0};
    return NewFixedArray(argumentCount, it);
  }
  const mappedCount = IntPtrMin(formalParameterCount, argumentCount);
  const it = NewParameterValueIterator(mappedCount, arguments);
  return NewFixedArray(argumentCount, it);
}

macro NewSloppyArguments(implicit context: Context)(
    info: FrameWithArgumentsInfo, callee: JSFunction): JSSloppyArgumentsObject {
  const argumentCount = Convert<intptr>(info.argument_count);
  const formalParameterCount = Convert<intptr>(info.formal_parameter_count);
  const parameterValues = arguments::NewSloppyArgumentsElements(
      info.frame, formalParameterCount, argumentCount);
  if (formalParameterCount == 0) {
    return NewJSSloppyArgumentsObject(parameterValues, callee);
  }
  const mappedCount = IntPtrMin(formalParameterCount, argumentCount);
  let paramIter =
      NewParameterMapIterator(context, formalParameterCount, mappedCount);
  const elementsLength = Convert<Smi>(mappedCount);
  const elements = NewSloppyArgumentsElements(
      elementsLength, context, parameterValues, paramIter);
  const length = Convert<Smi>(argumentCount);
  return NewJSFastAliasedArgumentsObject(elements, length, callee);
}

}  // namespace arguments

@export
macro EmitFastNewAllArguments(implicit context: Context)(
    frame: FrameWithArguments, argc: intptr): JSArray {
  return arguments::NewAllArguments(frame, argc);
}

@export
macro EmitFastNewRestArguments(implicit context: Context)(_f: JSFunction):
    JSArray {
  const info = GetFrameWithArgumentsInfo();
  return arguments::NewRestArguments(info);
}

@export
macro EmitFastNewStrictArguments(implicit context: Context)(_f: JSFunction):
    JSStrictArgumentsObject {
  const info = GetFrameWithArgumentsInfo();
  return arguments::NewStrictArguments(info);
}

@export
macro EmitFastNewSloppyArguments(implicit context: Context)(f: JSFunction):
    JSSloppyArgumentsObject {
  const info = GetFrameWithArgumentsInfo();
  return arguments::NewSloppyArguments(info, f);
}

builtin NewSloppyArgumentsElements(
    frame: FrameWithArguments, formalParameterCount: intptr,
    argumentCount: Smi): FixedArray {
  return arguments::NewSloppyArgumentsElements(
      frame, formalParameterCount, Convert<intptr>(argumentCount));
}

builtin NewStrictArgumentsElements(
    frame: FrameWithArguments, _formalParameterCount: intptr,
    argumentCount: Smi): FixedArray {
  return arguments::NewStrictArgumentsElements(
      frame, Convert<intptr>(argumentCount));
}

builtin NewRestArgumentsElements(
    frame: FrameWithArguments, formalParameterCount: intptr,
    argumentCount: Smi): FixedArray {
  return arguments::NewRestArgumentsElements(
      frame, formalParameterCount, Convert<intptr>(argumentCount));
}

macro
AccessSloppyArgumentsCommon(
    receiver: JSObject, keyObject: Object): &Object labels Bailout {
  const key = Cast<Smi>(keyObject) otherwise Bailout;
  const elements =
      Cast<SloppyArgumentsElements>(receiver.elements) otherwise Bailout;

  try {
    if (OutOfBounds(key, elements.length)) goto Unmapped;
    const mappedIndex = elements.mapped_entries[key];
    typeswitch (mappedIndex) {
      case (contextIndex: Smi): {
        return &(elements.context.elements[contextIndex]);
      }
      case (TheHole): {
        goto Unmapped;
      }
    }
  } label Unmapped {
    typeswitch (elements.arguments) {
      case (NumberDictionary): {
        goto Bailout;
      }
      case (arguments: FixedArray): {
        if (OutOfBounds(key, arguments.length)) goto Bailout;
        if (arguments.objects[key] == TheHole) goto Bailout;
        return &(arguments.objects[key]);
      }
    }
  }
}

@export
macro SloppyArgumentsLoad(receiver: JSObject, keyObject: Object):
    JSAny labels Bailout {
  return UnsafeCast<JSAny>(
      *AccessSloppyArgumentsCommon(receiver, keyObject) otherwise Bailout);
}

@export
macro SloppyArgumentsHas(receiver: JSObject, keyObject: Object):
    JSAny labels Bailout {
  AccessSloppyArgumentsCommon(receiver, keyObject) otherwise Bailout;
  return True;
}

@export
macro SloppyArgumentsStore(receiver: JSObject, keyObject: Object, value: JSAny):
    JSAny labels Bailout {
  let destination =
      AccessSloppyArgumentsCommon(receiver, keyObject) otherwise Bailout;
  *destination = value;
  return value;
}
