// Copyright 2014 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/runtime/runtime-utils.h"

#include <stdlib.h>
#include <limits>

#include "src/builtins/accessors.h"
#include "src/common/message-template.h"
#include "src/debug/debug.h"
#include "src/execution/arguments-inl.h"
#include "src/execution/isolate-inl.h"
#include "src/logging/counters.h"
#include "src/logging/log.h"
#include "src/objects/elements.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/literal-objects-inl.h"
#include "src/objects/smi.h"
#include "src/objects/struct-inl.h"
#include "src/runtime/runtime.h"

namespace v8 {
namespace internal {


RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
  HandleScope scope(isolate);
  DCHECK_EQ(0, args.length());
  THROW_NEW_ERROR_RETURN_FAILURE(
      isolate, NewReferenceError(MessageTemplate::kUnsupportedSuper));
}


RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
  HandleScope scope(isolate);
  DCHECK_EQ(1, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
  Handle<String> name(constructor->shared().Name(), isolate);
  THROW_NEW_ERROR_RETURN_FAILURE(
      isolate, NewTypeError(MessageTemplate::kConstructorNonCallable, name));
}


RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) {
  HandleScope scope(isolate);
  DCHECK_EQ(0, args.length());
  THROW_NEW_ERROR_RETURN_FAILURE(
      isolate, NewTypeError(MessageTemplate::kStaticPrototype));
}

RUNTIME_FUNCTION(Runtime_ThrowSuperAlreadyCalledError) {
  HandleScope scope(isolate);
  DCHECK_EQ(0, args.length());
  THROW_NEW_ERROR_RETURN_FAILURE(
      isolate, NewReferenceError(MessageTemplate::kSuperAlreadyCalled));
}

RUNTIME_FUNCTION(Runtime_ThrowSuperNotCalled) {
  HandleScope scope(isolate);
  DCHECK_EQ(0, args.length());
  THROW_NEW_ERROR_RETURN_FAILURE(
      isolate, NewReferenceError(MessageTemplate::kSuperNotCalled));
}

namespace {

Object ThrowNotSuperConstructor(Isolate* isolate, Handle<Object> constructor,
                                Handle<JSFunction> function) {
  Handle<String> super_name;
  if (constructor->IsJSFunction()) {
    super_name =
        handle(Handle<JSFunction>::cast(constructor)->shared().Name(), isolate);
  } else if (constructor->IsOddball()) {
    DCHECK(constructor->IsNull(isolate));
    super_name = isolate->factory()->null_string();
  } else {
    super_name = Object::NoSideEffectsToString(isolate, constructor);
  }
  // null constructor
  if (super_name->length() == 0) {
    super_name = isolate->factory()->null_string();
  }
  Handle<String> function_name(function->shared().Name(), isolate);
  // anonymous class
  if (function_name->length() == 0) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate,
        NewTypeError(MessageTemplate::kNotSuperConstructorAnonymousClass,
                     super_name));
  }
  THROW_NEW_ERROR_RETURN_FAILURE(
      isolate, NewTypeError(MessageTemplate::kNotSuperConstructor, super_name,
                            function_name));
}

}  // namespace

RUNTIME_FUNCTION(Runtime_ThrowNotSuperConstructor) {
  HandleScope scope(isolate);
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
  return ThrowNotSuperConstructor(isolate, constructor, function);
}

RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
  DCHECK_EQ(0, args.length());
  return ReadOnlyRoots(isolate).home_object_symbol();
}

namespace {

template <typename Dictionary>
Handle<Name> KeyToName(Isolate* isolate, Handle<Object> key);

template <>
Handle<Name> KeyToName<NameDictionary>(Isolate* isolate, Handle<Object> key) {
  DCHECK(key->IsName());
  return Handle<Name>::cast(key);
}

template <>
Handle<Name> KeyToName<NumberDictionary>(Isolate* isolate, Handle<Object> key) {
  DCHECK(key->IsNumber());
  return isolate->factory()->NumberToString(key);
}

inline void SetHomeObject(Isolate* isolate, JSFunction method,
                          JSObject home_object) {
  if (method.shared().needs_home_object()) {
    const int kPropertyIndex = JSFunction::kMaybeHomeObjectDescriptorIndex;
    CHECK_EQ(method.map().instance_descriptors().GetKey(kPropertyIndex),
             ReadOnlyRoots(isolate).home_object_symbol());

    FieldIndex field_index =
        FieldIndex::ForDescriptor(method.map(), kPropertyIndex);
    method.RawFastPropertyAtPut(field_index, home_object);
  }
}

// Gets |index|'th argument which may be a class constructor object, a class
// prototype object or a class method. In the latter case the following
// post-processing may be required:
// 1) set [[HomeObject]] slot to given |home_object| value if the method's
//    shared function info indicates that the method requires that;
// 2) set method's name to a concatenation of |name_prefix| and |key| if the
//    method's shared function info indicates that method does not have a
//    shared name.
template <typename Dictionary>
MaybeHandle<Object> GetMethodAndSetHomeObjectAndName(
    Isolate* isolate, Arguments& args,  // NOLINT(runtime/references)
    Smi index, Handle<JSObject> home_object, Handle<String> name_prefix,
    Handle<Object> key) {
  int int_index = index.value();

  // Class constructor and prototype values do not require post processing.
  if (int_index < ClassBoilerplate::kFirstDynamicArgumentIndex) {
    return args.at<Object>(int_index);
  }

  Handle<JSFunction> method = args.at<JSFunction>(int_index);

  SetHomeObject(isolate, *method, *home_object);

  if (!method->shared().HasSharedName()) {
    // TODO(ishell): method does not have a shared name at this point only if
    // the key is a computed property name. However, the bytecode generator
    // explicitly generates ToName bytecodes to ensure that the computed
    // property name is properly converted to Name. So, we can actually be smart
    // here and avoid converting Smi keys back to Name.
    Handle<Name> name = KeyToName<Dictionary>(isolate, key);
    if (!JSFunction::SetName(method, name, name_prefix)) {
      return MaybeHandle<Object>();
    }
  }
  return method;
}

// Gets |index|'th argument which may be a class constructor object, a class
// prototype object or a class method. In the latter case the following
// post-processing may be required:
// 1) set [[HomeObject]] slot to given |home_object| value if the method's
//    shared function info indicates that the method requires that;
// This is a simplified version of GetMethodWithSharedNameAndSetHomeObject()
// function above that is used when it's guaranteed that the method has
// shared name.
Object GetMethodWithSharedNameAndSetHomeObject(
    Isolate* isolate,
    Arguments& args,  // NOLINT(runtime/references)
    Object index, JSObject home_object) {
  DisallowHeapAllocation no_gc;
  int int_index = Smi::ToInt(index);

  // Class constructor and prototype values do not require post processing.
  if (int_index < ClassBoilerplate::kFirstDynamicArgumentIndex) {
    return args[int_index];
  }

  Handle<JSFunction> method = args.at<JSFunction>(int_index);

  SetHomeObject(isolate, *method, home_object);

  DCHECK(method->shared().HasSharedName());
  return *method;
}

template <typename Dictionary>
Handle<Dictionary> ShallowCopyDictionaryTemplate(
    Isolate* isolate, Handle<Dictionary> dictionary_template) {
  Handle<Map> dictionary_map(dictionary_template->map(), isolate);
  Handle<Dictionary> dictionary =
      Handle<Dictionary>::cast(isolate->factory()->CopyFixedArrayWithMap(
          dictionary_template, dictionary_map));
  // Clone all AccessorPairs in the dictionary.
  int capacity = dictionary->Capacity();
  for (int i = 0; i < capacity; i++) {
    Object value = dictionary->ValueAt(i);
    if (value.IsAccessorPair()) {
      Handle<AccessorPair> pair(AccessorPair::cast(value), isolate);
      pair = AccessorPair::Copy(isolate, pair);
      dictionary->ValueAtPut(i, *pair);
    }
  }
  return dictionary;
}

template <typename Dictionary>
bool SubstituteValues(Isolate* isolate, Handle<Dictionary> dictionary,
                      Handle<JSObject> receiver,
                      Arguments& args,  // NOLINT(runtime/references)
                      bool* install_name_accessor = nullptr) {
  Handle<Name> name_string = isolate->factory()->name_string();

  // Replace all indices with proper methods.
  int capacity = dictionary->Capacity();
  ReadOnlyRoots roots(isolate);
  for (int i = 0; i < capacity; i++) {
    Object maybe_key = dictionary->KeyAt(i);
    if (!Dictionary::IsKey(roots, maybe_key)) continue;
    if (install_name_accessor && *install_name_accessor &&
        (maybe_key == *name_string)) {
      *install_name_accessor = false;
    }
    Handle<Object> key(maybe_key, isolate);
    Handle<Object> value(dictionary->ValueAt(i), isolate);
    if (value->IsAccessorPair()) {
      Handle<AccessorPair> pair = Handle<AccessorPair>::cast(value);
      Object tmp = pair->getter();
      if (tmp.IsSmi()) {
        Handle<Object> result;
        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
            isolate, result,
            GetMethodAndSetHomeObjectAndName<Dictionary>(
                isolate, args, Smi::cast(tmp), receiver,
                isolate->factory()->get_string(), key),
            false);
        pair->set_getter(*result);
      }
      tmp = pair->setter();
      if (tmp.IsSmi()) {
        Handle<Object> result;
        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
            isolate, result,
            GetMethodAndSetHomeObjectAndName<Dictionary>(
                isolate, args, Smi::cast(tmp), receiver,
                isolate->factory()->set_string(), key),
            false);
        pair->set_setter(*result);
      }
    } else if (value->IsSmi()) {
      Handle<Object> result;
      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
          isolate, result,
          GetMethodAndSetHomeObjectAndName<Dictionary>(
              isolate, args, Smi::cast(*value), receiver,
              isolate->factory()->empty_string(), key),
          false);
      dictionary->ValueAtPut(i, *result);
    }
  }
  return true;
}

bool AddDescriptorsByTemplate(
    Isolate* isolate, Handle<Map> map,
    Handle<DescriptorArray> descriptors_template,
    Handle<NumberDictionary> elements_dictionary_template,
    Handle<JSObject> receiver, Arguments& args) {  // NOLINT(runtime/references)
  int nof_descriptors = descriptors_template->number_of_descriptors();

  Handle<DescriptorArray> descriptors =
      DescriptorArray::Allocate(isolate, nof_descriptors, 0);

  Handle<NumberDictionary> elements_dictionary =
      *elements_dictionary_template ==
              ReadOnlyRoots(isolate).empty_slow_element_dictionary()
          ? elements_dictionary_template
          : ShallowCopyDictionaryTemplate(isolate,
                                          elements_dictionary_template);

  // Count the number of properties that must be in the instance and
  // create the property array to hold the constants.
  int count = 0;
  for (int i = 0; i < nof_descriptors; i++) {
    PropertyDetails details = descriptors_template->GetDetails(i);
    if (details.location() == kDescriptor && details.kind() == kData) {
      count++;
    }
  }
  Handle<PropertyArray> property_array =
      isolate->factory()->NewPropertyArray(count);

  // Read values from |descriptors_template| and store possibly post-processed
  // values into "instantiated" |descriptors| array.
  int field_index = 0;
  for (int i = 0; i < nof_descriptors; i++) {
    Object value = descriptors_template->GetStrongValue(i);
    if (value.IsAccessorPair()) {
      Handle<AccessorPair> pair = AccessorPair::Copy(
          isolate, handle(AccessorPair::cast(value), isolate));
      value = *pair;
    }
    DisallowHeapAllocation no_gc;
    Name name = descriptors_template->GetKey(i);
    DCHECK(name.IsUniqueName());
    PropertyDetails details = descriptors_template->GetDetails(i);
    if (details.location() == kDescriptor) {
      if (details.kind() == kData) {
        if (value.IsSmi()) {
          value = GetMethodWithSharedNameAndSetHomeObject(isolate, args, value,
                                                          *receiver);
        }
        details = details.CopyWithRepresentation(
            value.OptimalRepresentation(isolate));
      } else {
        DCHECK_EQ(kAccessor, details.kind());
        if (value.IsAccessorPair()) {
          AccessorPair pair = AccessorPair::cast(value);
          Object tmp = pair.getter();
          if (tmp.IsSmi()) {
            pair.set_getter(GetMethodWithSharedNameAndSetHomeObject(
                isolate, args, tmp, *receiver));
          }
          tmp = pair.setter();
          if (tmp.IsSmi()) {
            pair.set_setter(GetMethodWithSharedNameAndSetHomeObject(
                isolate, args, tmp, *receiver));
          }
        }
      }
    } else {
      UNREACHABLE();
    }
    DCHECK(value.FitsRepresentation(details.representation()));
    if (details.location() == kDescriptor && details.kind() == kData) {
      details = PropertyDetails(details.kind(), details.attributes(), kField,
                                PropertyConstness::kConst,
                                details.representation(), field_index)
                    .set_pointer(details.pointer());

      property_array->set(field_index, value);
      field_index++;
      descriptors->Set(i, name, MaybeObject::FromObject(FieldType::Any()),
                       details);
    } else {
      descriptors->Set(i, name, MaybeObject::FromObject(value), details);
    }
  }

  map->InitializeDescriptors(isolate, *descriptors,
                             LayoutDescriptor::FastPointerLayout());
  if (elements_dictionary->NumberOfElements() > 0) {
    if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
                                            receiver, args)) {
      return false;
    }
    map->set_elements_kind(DICTIONARY_ELEMENTS);
  }

  // Atomically commit the changes.
  receiver->synchronized_set_map(*map);
  if (elements_dictionary->NumberOfElements() > 0) {
    receiver->set_elements(*elements_dictionary);
  }
  if (property_array->length() > 0) {
    receiver->SetProperties(*property_array);
  }
  return true;
}

bool AddDescriptorsByTemplate(
    Isolate* isolate, Handle<Map> map,
    Handle<NameDictionary> properties_dictionary_template,
    Handle<NumberDictionary> elements_dictionary_template,
    Handle<FixedArray> computed_properties, Handle<JSObject> receiver,
    bool install_name_accessor,
    Arguments& args) {  // NOLINT(runtime/references)
  int computed_properties_length = computed_properties->length();

  // Shallow-copy properties template.
  Handle<NameDictionary> properties_dictionary =
      ShallowCopyDictionaryTemplate(isolate, properties_dictionary_template);
  Handle<NumberDictionary> elements_dictionary =
      ShallowCopyDictionaryTemplate(isolate, elements_dictionary_template);

  using ValueKind = ClassBoilerplate::ValueKind;
  using ComputedEntryFlags = ClassBoilerplate::ComputedEntryFlags;

  // Merge computed properties with properties and elements dictionary
  // templates.
  int i = 0;
  while (i < computed_properties_length) {
    int flags = Smi::ToInt(computed_properties->get(i++));

    ValueKind value_kind = ComputedEntryFlags::ValueKindBits::decode(flags);
    int key_index = ComputedEntryFlags::KeyIndexBits::decode(flags);
    Object value = Smi::FromInt(key_index + 1);  // Value follows name.

    Handle<Object> key = args.at<Object>(key_index);
    DCHECK(key->IsName());
    uint32_t element;
    Handle<Name> name = Handle<Name>::cast(key);
    if (name->AsArrayIndex(&element)) {
      ClassBoilerplate::AddToElementsTemplate(
          isolate, elements_dictionary, element, key_index, value_kind, value);

    } else {
      name = isolate->factory()->InternalizeName(name);
      ClassBoilerplate::AddToPropertiesTemplate(
          isolate, properties_dictionary, name, key_index, value_kind, value);
    }
  }

  // Replace all indices with proper methods.
  if (!SubstituteValues<NameDictionary>(isolate, properties_dictionary,
                                        receiver, args,
                                        &install_name_accessor)) {
    return false;
  }
  if (install_name_accessor) {
    PropertyAttributes attribs =
        static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
    PropertyDetails details(kAccessor, attribs, PropertyCellType::kNoCell);
    Handle<NameDictionary> dict = NameDictionary::Add(
        isolate, properties_dictionary, isolate->factory()->name_string(),
        isolate->factory()->function_name_accessor(), details);
    CHECK_EQ(*dict, *properties_dictionary);
  }

  if (elements_dictionary->NumberOfElements() > 0) {
    if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
                                            receiver, args)) {
      return false;
    }
    map->set_elements_kind(DICTIONARY_ELEMENTS);
  }

  // Atomically commit the changes.
  receiver->synchronized_set_map(*map);
  receiver->set_raw_properties_or_hash(*properties_dictionary);
  if (elements_dictionary->NumberOfElements() > 0) {
    receiver->set_elements(*elements_dictionary);
  }
  return true;
}

Handle<JSObject> CreateClassPrototype(Isolate* isolate) {
  // For constant tracking we want to avoid the hassle of handling
  // in-object properties, so create a map with no in-object
  // properties.

  // TODO(ishell) Support caching of zero in-object properties map
  // by ObjectLiteralMapFromCache().
  Handle<Map> map = Map::Create(isolate, 0);
  return isolate->factory()->NewJSObjectFromMap(map);
}

bool InitClassPrototype(Isolate* isolate,
                        Handle<ClassBoilerplate> class_boilerplate,
                        Handle<JSObject> prototype,
                        Handle<HeapObject> prototype_parent,
                        Handle<JSFunction> constructor,
                        Arguments& args) {  // NOLINT(runtime/references)
  Handle<Map> map(prototype->map(), isolate);
  map = Map::CopyDropDescriptors(isolate, map);
  map->set_is_prototype_map(true);
  Map::SetPrototype(isolate, map, prototype_parent);
  constructor->set_prototype_or_initial_map(*prototype);
  map->SetConstructor(*constructor);
  Handle<FixedArray> computed_properties(
      class_boilerplate->instance_computed_properties(), isolate);
  Handle<NumberDictionary> elements_dictionary_template(
      NumberDictionary::cast(class_boilerplate->instance_elements_template()),
      isolate);

  Handle<Object> properties_template(
      class_boilerplate->instance_properties_template(), isolate);
  if (properties_template->IsNameDictionary()) {
    Handle<NameDictionary> properties_dictionary_template =
        Handle<NameDictionary>::cast(properties_template);

    map->set_is_dictionary_map(true);
    map->set_is_migration_target(false);
    map->set_may_have_interesting_symbols(true);
    map->set_construction_counter(Map::kNoSlackTracking);

    // We care about name property only for class constructor.
    const bool install_name_accessor = false;

    return AddDescriptorsByTemplate(
        isolate, map, properties_dictionary_template,
        elements_dictionary_template, computed_properties, prototype,
        install_name_accessor, args);
  } else {
    Handle<DescriptorArray> descriptors_template =
        Handle<DescriptorArray>::cast(properties_template);

    // The size of the prototype object is known at this point.
    // So we can create it now and then add the rest instance methods to the
    // map.
    return AddDescriptorsByTemplate(isolate, map, descriptors_template,
                                    elements_dictionary_template, prototype,
                                    args);
  }
}

bool InitClassConstructor(Isolate* isolate,
                          Handle<ClassBoilerplate> class_boilerplate,
                          Handle<HeapObject> constructor_parent,
                          Handle<JSFunction> constructor,
                          Arguments& args) {  // NOLINT(runtime/references)
  Handle<Map> map(constructor->map(), isolate);
  map = Map::CopyDropDescriptors(isolate, map);
  DCHECK(map->is_prototype_map());

  if (!constructor_parent.is_null()) {
    // Set map's prototype without enabling prototype setup mode for superclass
    // because it does not make sense.
    Map::SetPrototype(isolate, map, constructor_parent, false);
  }

  Handle<NumberDictionary> elements_dictionary_template(
      NumberDictionary::cast(class_boilerplate->static_elements_template()),
      isolate);
  Handle<FixedArray> computed_properties(
      class_boilerplate->static_computed_properties(), isolate);

  Handle<Object> properties_template(
      class_boilerplate->static_properties_template(), isolate);

  if (properties_template->IsNameDictionary()) {
    Handle<NameDictionary> properties_dictionary_template =
        Handle<NameDictionary>::cast(properties_template);

    map->set_is_dictionary_map(true);
    map->InitializeDescriptors(isolate,
                               ReadOnlyRoots(isolate).empty_descriptor_array(),
                               LayoutDescriptor::FastPointerLayout());
    map->set_is_migration_target(false);
    map->set_may_have_interesting_symbols(true);
    map->set_construction_counter(Map::kNoSlackTracking);

    bool install_name_accessor =
        class_boilerplate->install_class_name_accessor() != 0;

    return AddDescriptorsByTemplate(
        isolate, map, properties_dictionary_template,
        elements_dictionary_template, computed_properties, constructor,
        install_name_accessor, args);
  } else {
    Handle<DescriptorArray> descriptors_template =
        Handle<DescriptorArray>::cast(properties_template);

    return AddDescriptorsByTemplate(isolate, map, descriptors_template,
                                    elements_dictionary_template, constructor,
                                    args);
  }
}

MaybeHandle<Object> DefineClass(
    Isolate* isolate, Handle<ClassBoilerplate> class_boilerplate,
    Handle<Object> super_class, Handle<JSFunction> constructor,
    Arguments& args) {  // NOLINT(runtime/references)
  Handle<Object> prototype_parent;
  Handle<HeapObject> constructor_parent;

  if (super_class->IsTheHole(isolate)) {
    prototype_parent = isolate->initial_object_prototype();
  } else {
    if (super_class->IsNull(isolate)) {
      prototype_parent = isolate->factory()->null_value();
    } else if (super_class->IsConstructor()) {
      DCHECK(!super_class->IsJSFunction() ||
             !IsResumableFunction(
                 Handle<JSFunction>::cast(super_class)->shared().kind()));
      ASSIGN_RETURN_ON_EXCEPTION(
          isolate, prototype_parent,
          Runtime::GetObjectProperty(isolate, super_class,
                                     isolate->factory()->prototype_string()),
          Object);
      if (!prototype_parent->IsNull(isolate) &&
          !prototype_parent->IsJSReceiver()) {
        THROW_NEW_ERROR(
            isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
                                  prototype_parent),
            Object);
      }
      // Create new handle to avoid |constructor_parent| corruption because of
      // |super_class| handle value overwriting via storing to
      // args[ClassBoilerplate::kPrototypeArgumentIndex] below.
      constructor_parent = handle(HeapObject::cast(*super_class), isolate);
    } else {
      THROW_NEW_ERROR(isolate,
                      NewTypeError(MessageTemplate::kExtendsValueNotConstructor,
                                   super_class),
                      Object);
    }
  }

  Handle<JSObject> prototype = CreateClassPrototype(isolate);
  DCHECK_EQ(*constructor, args[ClassBoilerplate::kConstructorArgumentIndex]);
  args.set_at(ClassBoilerplate::kPrototypeArgumentIndex, *prototype);

  if (!InitClassConstructor(isolate, class_boilerplate, constructor_parent,
                            constructor, args) ||
      !InitClassPrototype(isolate, class_boilerplate, prototype,
                          Handle<HeapObject>::cast(prototype_parent),
                          constructor, args)) {
    DCHECK(isolate->has_pending_exception());
    return MaybeHandle<Object>();
  }
  if (FLAG_trace_maps) {
    LOG(isolate,
        MapEvent("InitialMap", Map(), constructor->map(),
                 "init class constructor", constructor->shared().DebugName()));
    LOG(isolate, MapEvent("InitialMap", Map(), prototype->map(),
                          "init class prototype"));
  }

  return prototype;
}

}  // namespace

RUNTIME_FUNCTION(Runtime_DefineClass) {
  HandleScope scope(isolate);
  DCHECK_LE(ClassBoilerplate::kFirstDynamicArgumentIndex, args.length());
  CONVERT_ARG_HANDLE_CHECKED(ClassBoilerplate, class_boilerplate, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 1);
  CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 2);
  DCHECK_EQ(class_boilerplate->arguments_count(), args.length());

  RETURN_RESULT_OR_FAILURE(
      isolate,
      DefineClass(isolate, class_boilerplate, super_class, constructor, args));
}

namespace {

enum class SuperMode { kLoad, kStore };

MaybeHandle<JSReceiver> GetSuperHolder(
    Isolate* isolate, Handle<Object> receiver, Handle<JSObject> home_object,
    SuperMode mode, MaybeHandle<Name> maybe_name, uint32_t index) {
  if (home_object->IsAccessCheckNeeded() &&
      !isolate->MayAccess(handle(isolate->context(), isolate), home_object)) {
    isolate->ReportFailedAccessCheck(home_object);
    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, JSReceiver);
  }

  PrototypeIterator iter(isolate, home_object);
  Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
  if (!proto->IsJSReceiver()) {
    MessageTemplate message = mode == SuperMode::kLoad
                                  ? MessageTemplate::kNonObjectPropertyLoad
                                  : MessageTemplate::kNonObjectPropertyStore;
    Handle<Name> name;
    if (!maybe_name.ToHandle(&name)) {
      name = isolate->factory()->Uint32ToString(index);
    }
    THROW_NEW_ERROR(isolate, NewTypeError(message, name, proto), JSReceiver);
  }
  return Handle<JSReceiver>::cast(proto);
}

MaybeHandle<Object> LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
                                  Handle<JSObject> home_object,
                                  Handle<Name> name) {
  Handle<JSReceiver> holder;
  ASSIGN_RETURN_ON_EXCEPTION(
      isolate, holder,
      GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad, name, 0),
      Object);
  LookupIterator it(receiver, name, holder);
  Handle<Object> result;
  ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
  return result;
}

MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
                                         Handle<Object> receiver,
                                         Handle<JSObject> home_object,
                                         uint32_t index) {
  Handle<JSReceiver> holder;
  ASSIGN_RETURN_ON_EXCEPTION(
      isolate, holder,
      GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad,
                     MaybeHandle<Name>(), index),
      Object);
  LookupIterator it(isolate, receiver, index, holder);
  Handle<Object> result;
  ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
  return result;
}

}  // anonymous namespace

RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
  HandleScope scope(isolate);
  DCHECK_EQ(3, args.length());
  CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);

  RETURN_RESULT_OR_FAILURE(isolate,
                           LoadFromSuper(isolate, receiver, home_object, name));
}


RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
  HandleScope scope(isolate);
  DCHECK_EQ(3, args.length());
  CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);

  uint32_t index = 0;

  if (key->ToArrayIndex(&index)) {
    RETURN_RESULT_OR_FAILURE(
        isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
  }

  Handle<Name> name;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
                                     Object::ToName(isolate, key));
  // TODO(verwaest): Unify using LookupIterator.
  if (name->AsArrayIndex(&index)) {
    RETURN_RESULT_OR_FAILURE(
        isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
  }
  RETURN_RESULT_OR_FAILURE(isolate,
                           LoadFromSuper(isolate, receiver, home_object, name));
}

namespace {

MaybeHandle<Object> StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
                                 Handle<Object> receiver, Handle<Name> name,
                                 Handle<Object> value) {
  Handle<JSReceiver> holder;
  ASSIGN_RETURN_ON_EXCEPTION(isolate, holder,
                             GetSuperHolder(isolate, receiver, home_object,
                                            SuperMode::kStore, name, 0),
                             Object);
  LookupIterator it(receiver, name, holder);
  MAYBE_RETURN(Object::SetSuperProperty(&it, value, StoreOrigin::kNamed),
               MaybeHandle<Object>());
  return value;
}

MaybeHandle<Object> StoreElementToSuper(Isolate* isolate,
                                        Handle<JSObject> home_object,
                                        Handle<Object> receiver, uint32_t index,
                                        Handle<Object> value) {
  Handle<JSReceiver> holder;
  ASSIGN_RETURN_ON_EXCEPTION(
      isolate, holder,
      GetSuperHolder(isolate, receiver, home_object, SuperMode::kStore,
                     MaybeHandle<Name>(), index),
      Object);
  LookupIterator it(isolate, receiver, index, holder);
  MAYBE_RETURN(Object::SetSuperProperty(&it, value, StoreOrigin::kMaybeKeyed),
               MaybeHandle<Object>());
  return value;
}

}  // anonymous namespace

RUNTIME_FUNCTION(Runtime_StoreToSuper) {
  HandleScope scope(isolate);
  DCHECK_EQ(4, args.length());
  CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
  CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);

  RETURN_RESULT_OR_FAILURE(
      isolate, StoreToSuper(isolate, home_object, receiver, name, value));
}

static MaybeHandle<Object> StoreKeyedToSuper(Isolate* isolate,
                                             Handle<JSObject> home_object,
                                             Handle<Object> receiver,
                                             Handle<Object> key,
                                             Handle<Object> value) {
  uint32_t index = 0;

  if (key->ToArrayIndex(&index)) {
    return StoreElementToSuper(isolate, home_object, receiver, index, value);
  }
  Handle<Name> name;
  ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
                             Object);
  // TODO(verwaest): Unify using LookupIterator.
  if (name->AsArrayIndex(&index)) {
    return StoreElementToSuper(isolate, home_object, receiver, index, value);
  }
  return StoreToSuper(isolate, home_object, receiver, name, value);
}

RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper) {
  HandleScope scope(isolate);
  DCHECK_EQ(4, args.length());
  CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
  CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);

  RETURN_RESULT_OR_FAILURE(
      isolate, StoreKeyedToSuper(isolate, home_object, receiver, key, value));
}

}  // namespace internal
}  // namespace v8
