// Copyright 2016 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/builtins/builtins-proxy-gen.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins-utils.h"
#include "src/builtins/builtins.h"

#include "src/counters.h"
#include "src/objects-inl.h"

namespace v8 {
namespace internal {

// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
TF_BUILTIN(ProxyConstructor, CodeStubAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  ThrowTypeError(context, MessageTemplate::kConstructorNotFunction, "Proxy");
}

void ProxiesCodeStubAssembler::GotoIfRevokedProxy(Node* object,
                                                  Label* if_proxy_revoked) {
  Label proxy_not_revoked(this);
  GotoIfNot(IsJSProxy(object), &proxy_not_revoked);
  Branch(IsJSReceiver(LoadObjectField(object, JSProxy::kHandlerOffset)),
         &proxy_not_revoked, if_proxy_revoked);
  BIND(&proxy_not_revoked);
}

Node* ProxiesCodeStubAssembler::AllocateProxy(Node* target, Node* handler,
                                              Node* context) {
  VARIABLE(map, MachineRepresentation::kTagged);

  Label callable_target(this), constructor_target(this), none_target(this),
      create_proxy(this);

  Node* nativeContext = LoadNativeContext(context);

  Branch(IsCallable(target), &callable_target, &none_target);

  BIND(&callable_target);
  {
    // Every object that is a constructor is implicitly callable
    // so it's okay to nest this check here
    GotoIf(IsConstructor(target), &constructor_target);
    map.Bind(
        LoadContextElement(nativeContext, Context::PROXY_CALLABLE_MAP_INDEX));
    Goto(&create_proxy);
  }
  BIND(&constructor_target);
  {
    map.Bind(LoadContextElement(nativeContext,
                                Context::PROXY_CONSTRUCTOR_MAP_INDEX));
    Goto(&create_proxy);
  }
  BIND(&none_target);
  {
    map.Bind(LoadContextElement(nativeContext, Context::PROXY_MAP_INDEX));
    Goto(&create_proxy);
  }

  BIND(&create_proxy);
  Node* proxy = Allocate(JSProxy::kSize);
  StoreMapNoWriteBarrier(proxy, map.value());
  StoreObjectFieldRoot(proxy, JSProxy::kPropertiesOrHashOffset,
                       Heap::kEmptyPropertyDictionaryRootIndex);
  StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kTargetOffset, target);
  StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHandlerOffset, handler);
  StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHashOffset,
                                 UndefinedConstant());

  return proxy;
}

Node* ProxiesCodeStubAssembler::AllocateJSArrayForCodeStubArguments(
    Node* context, CodeStubArguments& args, Node* argc, ParameterMode mode) {
  Node* native_context = LoadNativeContext(context);
  Node* array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
  Node* argc_smi = ParameterToTagged(argc, mode);

  Node* array = AllocateJSArray(PACKED_ELEMENTS, array_map, argc, argc_smi,
                                nullptr, mode);
  Node* elements = LoadElements(array);

  VARIABLE(index, MachineType::PointerRepresentation(),
           IntPtrConstant(FixedArrayBase::kHeaderSize - kHeapObjectTag));
  VariableList list({&index}, zone());
  args.ForEach(list, [=, &index](Node* arg) {
    StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, index.value(),
                        arg);
    Increment(&index, kPointerSize);
  });
  return array;
}

// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
TF_BUILTIN(ProxyConstructor_ConstructStub, ProxiesCodeStubAssembler) {
  int const kTargetArg = 0;
  int const kHandlerArg = 1;

  Node* argc =
      ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
  CodeStubArguments args(this, argc);

  Node* target = args.GetOptionalArgumentValue(kTargetArg);
  Node* handler = args.GetOptionalArgumentValue(kHandlerArg);
  Node* context = Parameter(BuiltinDescriptor::kContext);

  Label throw_proxy_non_object(this, Label::kDeferred),
      throw_proxy_handler_or_target_revoked(this, Label::kDeferred),
      return_create_proxy(this);

  GotoIf(TaggedIsSmi(target), &throw_proxy_non_object);
  GotoIfNot(IsJSReceiver(target), &throw_proxy_non_object);
  GotoIfRevokedProxy(target, &throw_proxy_handler_or_target_revoked);

  GotoIf(TaggedIsSmi(handler), &throw_proxy_non_object);
  GotoIfNot(IsJSReceiver(handler), &throw_proxy_non_object);
  GotoIfRevokedProxy(handler, &throw_proxy_handler_or_target_revoked);

  args.PopAndReturn(AllocateProxy(target, handler, context));

  BIND(&throw_proxy_non_object);
  ThrowTypeError(context, MessageTemplate::kProxyNonObject);

  BIND(&throw_proxy_handler_or_target_revoked);
  ThrowTypeError(context, MessageTemplate::kProxyHandlerOrTargetRevoked);
}

TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) {
  Node* argc = Parameter(Descriptor::kActualArgumentsCount);
  Node* argc_ptr = ChangeInt32ToIntPtr(argc);
  Node* proxy = Parameter(Descriptor::kFunction);
  Node* context = Parameter(Descriptor::kContext);

  CSA_ASSERT(this, IsJSProxy(proxy));
  CSA_ASSERT(this, IsCallable(proxy));

  Label throw_proxy_handler_revoked(this, Label::kDeferred),
      trap_undefined(this);

  // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);

  // 2. If handler is null, throw a TypeError exception.
  CSA_ASSERT(this, IsNullOrJSReceiver(handler));
  GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);

  // 3. Assert: Type(handler) is Object.
  CSA_ASSERT(this, IsJSReceiver(handler));

  // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);

  // 5. Let trap be ? GetMethod(handler, "apply").
  // 6. If trap is undefined, then
  Handle<Name> trap_name = factory()->apply_string();
  Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);

  CodeStubArguments args(this, argc_ptr);
  Node* receiver = args.GetReceiver();

  // 7. Let argArray be CreateArrayFromList(argumentsList).
  Node* array = AllocateJSArrayForCodeStubArguments(context, args, argc_ptr,
                                                    INTPTR_PARAMETERS);

  // 8. Return Call(trap, handler, «target, thisArgument, argArray»).
  Node* result = CallJS(CodeFactory::Call(isolate()), context, trap, handler,
                        target, receiver, array);
  args.PopAndReturn(result);

  BIND(&trap_undefined);
  {
    // 6.a. Return Call(target, thisArgument, argumentsList).
    TailCallStub(CodeFactory::Call(isolate()), context, target, argc);
  }

  BIND(&throw_proxy_handler_revoked);
  { ThrowTypeError(context, MessageTemplate::kProxyRevoked, "apply"); }
}

TF_BUILTIN(ConstructProxy, ProxiesCodeStubAssembler) {
  Node* argc = Parameter(Descriptor::kActualArgumentsCount);
  Node* argc_ptr = ChangeInt32ToIntPtr(argc);
  Node* proxy = Parameter(Descriptor::kFunction);
  Node* new_target = Parameter(Descriptor::kNewTarget);
  Node* context = Parameter(Descriptor::kContext);

  CSA_ASSERT(this, IsJSProxy(proxy));
  CSA_ASSERT(this, IsCallable(proxy));

  Label throw_proxy_handler_revoked(this, Label::kDeferred),
      trap_undefined(this), not_an_object(this, Label::kDeferred);

  // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);

  // 2. If handler is null, throw a TypeError exception.
  CSA_ASSERT(this, IsNullOrJSReceiver(handler));
  GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);

  // 3. Assert: Type(handler) is Object.
  CSA_ASSERT(this, IsJSReceiver(handler));

  // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);

  // 5. Let trap be ? GetMethod(handler, "construct").
  // 6. If trap is undefined, then
  Handle<Name> trap_name = factory()->construct_string();
  Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);

  CodeStubArguments args(this, argc_ptr);

  // 7. Let argArray be CreateArrayFromList(argumentsList).
  Node* array = AllocateJSArrayForCodeStubArguments(context, args, argc_ptr,
                                                    INTPTR_PARAMETERS);

  // 8. Let newObj be ? Call(trap, handler, « target, argArray, newTarget »).
  Node* new_obj = CallJS(CodeFactory::Call(isolate()), context, trap, handler,
                         target, array, new_target);

  // 9. If Type(newObj) is not Object, throw a TypeError exception.
  GotoIf(TaggedIsSmi(new_obj), &not_an_object);
  GotoIfNot(IsJSReceiver(new_obj), &not_an_object);

  // 10. Return newObj.
  args.PopAndReturn(new_obj);

  BIND(&not_an_object);
  {
    ThrowTypeError(context, MessageTemplate::kProxyConstructNonObject, new_obj);
  }

  BIND(&trap_undefined);
  {
    // 6.a. Assert: target has a [[Construct]] internal method.
    CSA_ASSERT(this, IsConstructor(target));

    // 6.b. Return ? Construct(target, argumentsList, newTarget).
    TailCallStub(CodeFactory::Construct(isolate()), context, target, new_target,
                 argc);
  }

  BIND(&throw_proxy_handler_revoked);
  { ThrowTypeError(context, MessageTemplate::kProxyRevoked, "construct"); }
}

TF_BUILTIN(ProxyHasProperty, ProxiesCodeStubAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* proxy = Parameter(Descriptor::kProxy);
  Node* name = Parameter(Descriptor::kName);

  CSA_ASSERT(this, IsJSProxy(proxy));

  // 1. Assert: IsPropertyKey(P) is true.
  CSA_ASSERT(this, IsName(name));
  CSA_ASSERT(this, Word32Equal(IsPrivateSymbol(name), Int32Constant(0)));

  Label throw_proxy_handler_revoked(this, Label::kDeferred),
      trap_undefined(this),
      if_try_get_own_property_bailout(this, Label::kDeferred),
      trap_not_callable(this, Label::kDeferred), return_true(this),
      return_false(this), check_target_desc(this);

  // 2. Let handler be O.[[ProxyHandler]].
  Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);

  // 3. If handler is null, throw a TypeError exception.
  // 4. Assert: Type(handler) is Object.
  GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);

  // 5. Let target be O.[[ProxyTarget]].
  Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);

  // 6. Let trap be ? GetMethod(handler, "has").
  // 7. If trap is undefined, then (see 7.a below).
  Handle<Name> trap_name = factory()->has_string();
  Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);

  GotoIf(TaggedIsSmi(trap), &trap_not_callable);
  GotoIfNot(IsCallable(trap), &trap_not_callable);

  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, P
  // »)).
  BranchIfToBooleanIsTrue(CallJS(CodeFactory::Call(isolate()), context, trap,
                                 handler, target, name),
                          &return_true, &check_target_desc);

  BIND(&check_target_desc);
  {
    // 9. If booleanTrapResult is false, then (see 9.a. in CheckHasTrapResult).
    CheckHasTrapResult(context, target, proxy, name, &return_false,
                       &if_try_get_own_property_bailout);
  }

  BIND(&if_try_get_own_property_bailout);
  {
    CallRuntime(Runtime::kCheckProxyHasTrap, context, name, target);
    Return(FalseConstant());
  }

  BIND(&trap_undefined);
  {
    // 7.a. Return ? target.[[HasProperty]](P).
    TailCallStub(Builtins::CallableFor(isolate(), Builtins::kHasProperty),
                 context, name, target);
  }

  BIND(&return_false);
  Return(FalseConstant());

  BIND(&return_true);
  Return(TrueConstant());

  BIND(&throw_proxy_handler_revoked);
  ThrowTypeError(context, MessageTemplate::kProxyRevoked, "has");

  BIND(&trap_not_callable);
  ThrowTypeError(context, MessageTemplate::kPropertyNotFunction, trap,
                 StringConstant("has"), proxy);
}

TF_BUILTIN(ProxyGetProperty, ProxiesCodeStubAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* proxy = Parameter(Descriptor::kProxy);
  Node* name = Parameter(Descriptor::kName);
  Node* receiver = Parameter(Descriptor::kReceiverValue);

  CSA_ASSERT(this, IsJSProxy(proxy));

  // 1. Assert: IsPropertyKey(P) is true.
  CSA_ASSERT(this, TaggedIsNotSmi(name));
  CSA_ASSERT(this, IsName(name));
  CSA_ASSERT(this, Word32Equal(IsPrivateSymbol(name), Int32Constant(0)));

  Label throw_proxy_handler_revoked(this, Label::kDeferred),
      trap_undefined(this);

  // 2. Let handler be O.[[ProxyHandler]].
  Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);

  // 3. If handler is null, throw a TypeError exception.
  GotoIf(IsNull(handler), &throw_proxy_handler_revoked);

  // 4. Assert: Type(handler) is Object.
  CSA_ASSERT(this, IsJSReceiver(handler));

  // 5. Let target be O.[[ProxyTarget]].
  Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);

  // 6. Let trap be ? GetMethod(handler, "get").
  // 7. If trap is undefined, then (see 7.a below).
  Handle<Name> trap_name = factory()->get_string();
  Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);

  // 8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »).
  Node* trap_result = CallJS(
      CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
      context, trap, handler, target, name, receiver);

  // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
  Label return_result(this);
  CheckGetSetTrapResult(context, target, proxy, name, trap_result,
                        &return_result, JSProxy::kGet);

  BIND(&return_result);
  {
    // 11. Return trapResult.
    Return(trap_result);
  }

  BIND(&trap_undefined);
  {
    // 7.a. Return ? target.[[Get]](P, Receiver).
    // TODO(mslekova): Introduce GetPropertyWithReceiver stub
    Return(CallRuntime(Runtime::kGetPropertyWithReceiver, context, target, name,
                       receiver));
  }

  BIND(&throw_proxy_handler_revoked);
  ThrowTypeError(context, MessageTemplate::kProxyRevoked, "get");
}

TF_BUILTIN(ProxySetProperty, ProxiesCodeStubAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* proxy = Parameter(Descriptor::kProxy);
  Node* name = Parameter(Descriptor::kName);
  Node* value = Parameter(Descriptor::kValue);
  Node* receiver = Parameter(Descriptor::kReceiverValue);
  Node* language_mode = Parameter(Descriptor::kLanguageMode);

  CSA_ASSERT(this, IsJSProxy(proxy));

  // 1. Assert: IsPropertyKey(P) is true.
  CSA_ASSERT(this, TaggedIsNotSmi(name));
  CSA_ASSERT(this, IsName(name));

  Label throw_proxy_handler_revoked(this, Label::kDeferred),
      trap_undefined(this), failure(this, Label::kDeferred),
      continue_checks(this), success(this),
      private_symbol(this, Label::kDeferred);

  GotoIf(IsPrivateSymbol(name), &private_symbol);

  // 2. Let handler be O.[[ProxyHandler]].
  Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);

  // 3. If handler is null, throw a TypeError exception.
  GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);

  // 4. Assert: Type(handler) is Object.
  CSA_ASSERT(this, IsJSReceiver(handler));

  // 5. Let target be O.[[ProxyTarget]].
  Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);

  // 6. Let trap be ? GetMethod(handler, "set").
  // 7. If trap is undefined, then (see 7.a below).
  Handle<Name> set_string = factory()->set_string();
  Node* trap = GetMethod(context, handler, set_string, &trap_undefined);

  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler,
  // « target, P, V, Receiver »)).
  // 9. If booleanTrapResult is false, return false.
  BranchIfToBooleanIsTrue(
      CallJS(CodeFactory::Call(isolate(),
                               ConvertReceiverMode::kNotNullOrUndefined),
             context, trap, handler, target, name, value, receiver),
      &continue_checks, &failure);

  BIND(&continue_checks);
  {
    // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
    Label return_result(this);
    CheckGetSetTrapResult(context, target, proxy, name, value, &success,
                          JSProxy::kSet);
  }

  BIND(&failure);
  {
    Label if_throw(this, Label::kDeferred);
    Branch(SmiEqual(language_mode, SmiConstant(STRICT)), &if_throw, &success);

    BIND(&if_throw);
    ThrowTypeError(context, MessageTemplate::kProxyTrapReturnedFalsishFor,
                   HeapConstant(set_string), name);
  }

  // 12. Return true.
  BIND(&success);
  Return(value);

  BIND(&private_symbol);
  {
    Label failure(this), throw_error(this, Label::kDeferred);

    Branch(SmiEqual(language_mode, SmiConstant(STRICT)), &throw_error,
           &failure);

    BIND(&failure);
    Return(UndefinedConstant());

    BIND(&throw_error);
    ThrowTypeError(context, MessageTemplate::kProxyPrivate);
  }

  BIND(&trap_undefined);
  {
    // 7.a. Return ? target.[[Set]](P, V, Receiver).
    CallRuntime(Runtime::kSetPropertyWithReceiver, context, target, name, value,
                receiver, language_mode);
    Return(value);
  }

  BIND(&throw_proxy_handler_revoked);
  ThrowTypeError(context, MessageTemplate::kProxyRevoked, "set");
}

void ProxiesCodeStubAssembler::CheckGetSetTrapResult(
    Node* context, Node* target, Node* proxy, Node* name, Node* trap_result,
    Label* check_passed, JSProxy::AccessKind access_kind) {
  Node* map = LoadMap(target);
  VARIABLE(var_value, MachineRepresentation::kTagged);
  VARIABLE(var_details, MachineRepresentation::kWord32);
  VARIABLE(var_raw_value, MachineRepresentation::kTagged);

  Label if_found_value(this), check_in_runtime(this, Label::kDeferred);

  Node* instance_type = LoadInstanceType(target);
  TryGetOwnProperty(context, target, target, map, instance_type, name,
                    &if_found_value, &var_value, &var_details, &var_raw_value,
                    check_passed, &check_in_runtime);

  BIND(&if_found_value);
  {
    Label throw_non_configurable_data(this, Label::kDeferred),
        throw_non_configurable_accessor(this, Label::kDeferred),
        check_accessor(this), check_data(this);

    // If targetDesc is not undefined and targetDesc.[[Configurable]] is
    // false, then:
    GotoIfNot(IsSetWord32(var_details.value(),
                          PropertyDetails::kAttributesDontDeleteMask),
              check_passed);

    // If IsDataDescriptor(targetDesc) is true and
    // targetDesc.[[Writable]] is false, then:
    BranchIfAccessorPair(var_raw_value.value(), &check_accessor, &check_data);

    BIND(&check_data);
    {
      Node* read_only = IsSetWord32(var_details.value(),
                                    PropertyDetails::kAttributesReadOnlyMask);
      GotoIfNot(read_only, check_passed);

      // If SameValue(trapResult, targetDesc.[[Value]]) is false,
      // throw a TypeError exception.
      GotoIfNot(SameValue(trap_result, var_value.value()),
                &throw_non_configurable_data);
      Goto(check_passed);
    }

    BIND(&check_accessor);
    {
      Node* accessor_pair = var_raw_value.value();

      if (access_kind == JSProxy::kGet) {
        Label continue_check(this, Label::kDeferred);
        // 10.b. If IsAccessorDescriptor(targetDesc) is true and
        // targetDesc.[[Get]] is undefined, then:
        Node* getter =
            LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
        // Here we check for null as well because if the getter was never
        // defined it's set as null.
        GotoIf(IsUndefined(getter), &continue_check);
        GotoIf(IsNull(getter), &continue_check);
        Goto(check_passed);

        // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
        BIND(&continue_check);
        GotoIfNot(IsUndefined(trap_result), &throw_non_configurable_accessor);
      } else {
        // 11.b.i. If targetDesc.[[Set]] is undefined, throw a TypeError
        // exception.
        Node* setter =
            LoadObjectField(accessor_pair, AccessorPair::kSetterOffset);
        GotoIf(IsUndefined(setter), &throw_non_configurable_accessor);
        GotoIf(IsNull(setter), &throw_non_configurable_accessor);
      }
      Goto(check_passed);
    }

    BIND(&check_in_runtime);
    {
      CallRuntime(Runtime::kCheckProxyGetSetTrapResult, context, name, target,
                  trap_result, SmiConstant(access_kind));
      Return(trap_result);
    }

    BIND(&throw_non_configurable_data);
    {
      ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableData,
                     name, var_value.value(), trap_result);
    }

    BIND(&throw_non_configurable_accessor);
    {
      ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableAccessor,
                     name, trap_result);
    }
  }
}

void ProxiesCodeStubAssembler::CheckHasTrapResult(Node* context, Node* target,
                                                  Node* proxy, Node* name,
                                                  Label* check_passed,
                                                  Label* if_bailout) {
  Node* target_map = LoadMap(target);
  VARIABLE(var_value, MachineRepresentation::kTagged);
  VARIABLE(var_details, MachineRepresentation::kWord32);
  VARIABLE(var_raw_value, MachineRepresentation::kTagged);

  Label if_found_value(this, Label::kDeferred),
      throw_non_configurable(this, Label::kDeferred),
      throw_non_extensible(this, Label::kDeferred);

  // 9.a. Let targetDesc be ? target.[[GetOwnProperty]](P).
  Node* instance_type = LoadInstanceType(target);
  TryGetOwnProperty(context, target, target, target_map, instance_type, name,
                    &if_found_value, &var_value, &var_details, &var_raw_value,
                    check_passed, if_bailout);

  // 9.b. If targetDesc is not undefined, then (see 9.b.i. below).
  BIND(&if_found_value);
  {
    // 9.b.i. If targetDesc.[[Configurable]] is false, throw a TypeError
    // exception.
    Node* non_configurable = IsSetWord32(
        var_details.value(), PropertyDetails::kAttributesDontDeleteMask);
    GotoIf(non_configurable, &throw_non_configurable);

    // 9.b.ii. Let extensibleTarget be ? IsExtensible(target).
    Node* target_extensible = IsExtensibleMap(target_map);

    // 9.b.iii. If extensibleTarget is false, throw a TypeError exception.
    GotoIfNot(target_extensible, &throw_non_extensible);
    Goto(check_passed);
  }

  BIND(&throw_non_configurable);
  { ThrowTypeError(context, MessageTemplate::kProxyHasNonConfigurable, name); }

  BIND(&throw_non_extensible);
  { ThrowTypeError(context, MessageTemplate::kProxyHasNonExtensible, name); }
}

}  // namespace internal
}  // namespace v8
