LCOV - code coverage report
Current view: top level - src/builtins - builtins-proxy-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 231 231 100.0 %
Date: 2017-10-20 Functions: 20 20 100.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/builtins/builtins-proxy-gen.h"
       6             : #include "src/builtins/builtins-utils-gen.h"
       7             : #include "src/builtins/builtins-utils.h"
       8             : #include "src/builtins/builtins.h"
       9             : 
      10             : #include "src/counters.h"
      11             : #include "src/objects-inl.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16             : // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
      17          93 : TF_BUILTIN(ProxyConstructor, CodeStubAssembler) {
      18             :   Node* context = Parameter(Descriptor::kContext);
      19          31 :   ThrowTypeError(context, MessageTemplate::kConstructorNotFunction, "Proxy");
      20          31 : }
      21             : 
      22          62 : void ProxiesCodeStubAssembler::GotoIfRevokedProxy(Node* object,
      23             :                                                   Label* if_proxy_revoked) {
      24          62 :   Label proxy_not_revoked(this);
      25         124 :   GotoIfNot(IsJSProxy(object), &proxy_not_revoked);
      26             :   Branch(IsJSReceiver(LoadObjectField(object, JSProxy::kHandlerOffset)),
      27         124 :          &proxy_not_revoked, if_proxy_revoked);
      28          62 :   BIND(&proxy_not_revoked);
      29          62 : }
      30             : 
      31          31 : Node* ProxiesCodeStubAssembler::AllocateProxy(Node* target, Node* handler,
      32             :                                               Node* context) {
      33          31 :   VARIABLE(map, MachineRepresentation::kTagged);
      34             : 
      35          31 :   Label callable_target(this), constructor_target(this), none_target(this),
      36          31 :       create_proxy(this);
      37             : 
      38          62 :   Node* nativeContext = LoadNativeContext(context);
      39             : 
      40          62 :   Branch(IsCallable(target), &callable_target, &none_target);
      41             : 
      42          31 :   BIND(&callable_target);
      43             :   {
      44             :     // Every object that is a constructor is implicitly callable
      45             :     // so it's okay to nest this check here
      46          62 :     GotoIf(IsConstructor(target), &constructor_target);
      47             :     map.Bind(
      48          62 :         LoadContextElement(nativeContext, Context::PROXY_CALLABLE_MAP_INDEX));
      49          31 :     Goto(&create_proxy);
      50             :   }
      51          31 :   BIND(&constructor_target);
      52             :   {
      53             :     map.Bind(LoadContextElement(nativeContext,
      54          62 :                                 Context::PROXY_CONSTRUCTOR_MAP_INDEX));
      55          31 :     Goto(&create_proxy);
      56             :   }
      57          31 :   BIND(&none_target);
      58             :   {
      59          62 :     map.Bind(LoadContextElement(nativeContext, Context::PROXY_MAP_INDEX));
      60          31 :     Goto(&create_proxy);
      61             :   }
      62             : 
      63          31 :   BIND(&create_proxy);
      64          31 :   Node* proxy = Allocate(JSProxy::kSize);
      65          31 :   StoreMapNoWriteBarrier(proxy, map.value());
      66             :   StoreObjectFieldRoot(proxy, JSProxy::kPropertiesOrHashOffset,
      67          31 :                        Heap::kEmptyPropertyDictionaryRootIndex);
      68          31 :   StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kTargetOffset, target);
      69          31 :   StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHandlerOffset, handler);
      70             :   StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHashOffset,
      71          62 :                                  UndefinedConstant());
      72             : 
      73          31 :   return proxy;
      74             : }
      75             : 
      76          62 : Node* ProxiesCodeStubAssembler::AllocateJSArrayForCodeStubArguments(
      77             :     Node* context, CodeStubArguments& args, Node* argc, ParameterMode mode) {
      78         124 :   Node* native_context = LoadNativeContext(context);
      79         124 :   Node* array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
      80             :   Node* argc_smi = ParameterToTagged(argc, mode);
      81             : 
      82             :   Node* array = AllocateJSArray(PACKED_ELEMENTS, array_map, argc, argc_smi,
      83          62 :                                 nullptr, mode);
      84         124 :   Node* elements = LoadElements(array);
      85             : 
      86         124 :   VARIABLE(index, MachineType::PointerRepresentation(),
      87             :            IntPtrConstant(FixedArrayBase::kHeaderSize - kHeapObjectTag));
      88          62 :   VariableList list({&index}, zone());
      89          62 :   args.ForEach(list, [=, &index](Node* arg) {
      90             :     StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, index.value(),
      91          62 :                         arg);
      92          62 :     Increment(&index, kPointerSize);
      93         186 :   });
      94          62 :   return array;
      95             : }
      96             : 
      97             : // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
      98         155 : TF_BUILTIN(ProxyConstructor_ConstructStub, ProxiesCodeStubAssembler) {
      99             :   int const kTargetArg = 0;
     100             :   int const kHandlerArg = 1;
     101             : 
     102             :   Node* argc =
     103          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
     104          31 :   CodeStubArguments args(this, argc);
     105             : 
     106          62 :   Node* target = args.GetOptionalArgumentValue(kTargetArg);
     107          62 :   Node* handler = args.GetOptionalArgumentValue(kHandlerArg);
     108             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     109             : 
     110             :   Label throw_proxy_non_object(this, Label::kDeferred),
     111          31 :       throw_proxy_handler_or_target_revoked(this, Label::kDeferred),
     112          31 :       return_create_proxy(this);
     113             : 
     114          62 :   GotoIf(TaggedIsSmi(target), &throw_proxy_non_object);
     115          62 :   GotoIfNot(IsJSReceiver(target), &throw_proxy_non_object);
     116          31 :   GotoIfRevokedProxy(target, &throw_proxy_handler_or_target_revoked);
     117             : 
     118          62 :   GotoIf(TaggedIsSmi(handler), &throw_proxy_non_object);
     119          62 :   GotoIfNot(IsJSReceiver(handler), &throw_proxy_non_object);
     120          31 :   GotoIfRevokedProxy(handler, &throw_proxy_handler_or_target_revoked);
     121             : 
     122          31 :   args.PopAndReturn(AllocateProxy(target, handler, context));
     123             : 
     124          31 :   BIND(&throw_proxy_non_object);
     125          31 :   ThrowTypeError(context, MessageTemplate::kProxyNonObject);
     126             : 
     127          31 :   BIND(&throw_proxy_handler_or_target_revoked);
     128          62 :   ThrowTypeError(context, MessageTemplate::kProxyHandlerOrTargetRevoked);
     129          31 : }
     130             : 
     131         155 : TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) {
     132             :   Node* argc = Parameter(Descriptor::kActualArgumentsCount);
     133          62 :   Node* argc_ptr = ChangeInt32ToIntPtr(argc);
     134             :   Node* proxy = Parameter(Descriptor::kFunction);
     135             :   Node* context = Parameter(Descriptor::kContext);
     136             : 
     137             :   CSA_ASSERT(this, IsJSProxy(proxy));
     138             :   CSA_ASSERT(this, IsCallable(proxy));
     139             : 
     140             :   Label throw_proxy_handler_revoked(this, Label::kDeferred),
     141          31 :       trap_undefined(this);
     142             : 
     143             :   // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
     144          31 :   Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
     145             : 
     146             :   // 2. If handler is null, throw a TypeError exception.
     147             :   CSA_ASSERT(this, IsNullOrJSReceiver(handler));
     148          62 :   GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
     149             : 
     150             :   // 3. Assert: Type(handler) is Object.
     151             :   CSA_ASSERT(this, IsJSReceiver(handler));
     152             : 
     153             :   // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
     154             :   Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
     155             : 
     156             :   // 5. Let trap be ? GetMethod(handler, "apply").
     157             :   // 6. If trap is undefined, then
     158          31 :   Handle<Name> trap_name = factory()->apply_string();
     159          31 :   Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);
     160             : 
     161             :   CodeStubArguments args(this, argc_ptr);
     162          62 :   Node* receiver = args.GetReceiver();
     163             : 
     164             :   // 7. Let argArray be CreateArrayFromList(argumentsList).
     165             :   Node* array = AllocateJSArrayForCodeStubArguments(context, args, argc_ptr,
     166          31 :                                                     INTPTR_PARAMETERS);
     167             : 
     168             :   // 8. Return Call(trap, handler, «target, thisArgument, argArray»).
     169             :   Node* result = CallJS(CodeFactory::Call(isolate()), context, trap, handler,
     170          62 :                         target, receiver, array);
     171          31 :   args.PopAndReturn(result);
     172             : 
     173          31 :   BIND(&trap_undefined);
     174             :   {
     175             :     // 6.a. Return Call(target, thisArgument, argumentsList).
     176          62 :     TailCallStub(CodeFactory::Call(isolate()), context, target, argc);
     177             :   }
     178             : 
     179          31 :   BIND(&throw_proxy_handler_revoked);
     180          62 :   { ThrowTypeError(context, MessageTemplate::kProxyRevoked, "apply"); }
     181          31 : }
     182             : 
     183         155 : TF_BUILTIN(ConstructProxy, ProxiesCodeStubAssembler) {
     184             :   Node* argc = Parameter(Descriptor::kActualArgumentsCount);
     185          62 :   Node* argc_ptr = ChangeInt32ToIntPtr(argc);
     186             :   Node* proxy = Parameter(Descriptor::kFunction);
     187             :   Node* new_target = Parameter(Descriptor::kNewTarget);
     188             :   Node* context = Parameter(Descriptor::kContext);
     189             : 
     190             :   CSA_ASSERT(this, IsJSProxy(proxy));
     191             :   CSA_ASSERT(this, IsCallable(proxy));
     192             : 
     193             :   Label throw_proxy_handler_revoked(this, Label::kDeferred),
     194          31 :       trap_undefined(this), not_an_object(this, Label::kDeferred);
     195             : 
     196             :   // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
     197          31 :   Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
     198             : 
     199             :   // 2. If handler is null, throw a TypeError exception.
     200             :   CSA_ASSERT(this, IsNullOrJSReceiver(handler));
     201          62 :   GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
     202             : 
     203             :   // 3. Assert: Type(handler) is Object.
     204             :   CSA_ASSERT(this, IsJSReceiver(handler));
     205             : 
     206             :   // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
     207             :   Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
     208             : 
     209             :   // 5. Let trap be ? GetMethod(handler, "construct").
     210             :   // 6. If trap is undefined, then
     211          31 :   Handle<Name> trap_name = factory()->construct_string();
     212          31 :   Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);
     213             : 
     214             :   CodeStubArguments args(this, argc_ptr);
     215             : 
     216             :   // 7. Let argArray be CreateArrayFromList(argumentsList).
     217             :   Node* array = AllocateJSArrayForCodeStubArguments(context, args, argc_ptr,
     218          31 :                                                     INTPTR_PARAMETERS);
     219             : 
     220             :   // 8. Let newObj be ? Call(trap, handler, « target, argArray, newTarget »).
     221             :   Node* new_obj = CallJS(CodeFactory::Call(isolate()), context, trap, handler,
     222          62 :                          target, array, new_target);
     223             : 
     224             :   // 9. If Type(newObj) is not Object, throw a TypeError exception.
     225          62 :   GotoIf(TaggedIsSmi(new_obj), &not_an_object);
     226          62 :   GotoIfNot(IsJSReceiver(new_obj), &not_an_object);
     227             : 
     228             :   // 10. Return newObj.
     229          31 :   args.PopAndReturn(new_obj);
     230             : 
     231          31 :   BIND(&not_an_object);
     232             :   {
     233          31 :     ThrowTypeError(context, MessageTemplate::kProxyConstructNonObject, new_obj);
     234             :   }
     235             : 
     236          31 :   BIND(&trap_undefined);
     237             :   {
     238             :     // 6.a. Assert: target has a [[Construct]] internal method.
     239             :     CSA_ASSERT(this, IsConstructor(target));
     240             : 
     241             :     // 6.b. Return ? Construct(target, argumentsList, newTarget).
     242             :     TailCallStub(CodeFactory::Construct(isolate()), context, target, new_target,
     243          62 :                  argc);
     244             :   }
     245             : 
     246          31 :   BIND(&throw_proxy_handler_revoked);
     247          62 :   { ThrowTypeError(context, MessageTemplate::kProxyRevoked, "construct"); }
     248          31 : }
     249             : 
     250         124 : TF_BUILTIN(ProxyHasProperty, ProxiesCodeStubAssembler) {
     251             :   Node* context = Parameter(Descriptor::kContext);
     252             :   Node* proxy = Parameter(Descriptor::kProxy);
     253             :   Node* name = Parameter(Descriptor::kName);
     254             : 
     255             :   CSA_ASSERT(this, IsJSProxy(proxy));
     256             : 
     257             :   // 1. Assert: IsPropertyKey(P) is true.
     258             :   CSA_ASSERT(this, IsName(name));
     259             :   CSA_ASSERT(this, Word32Equal(IsPrivateSymbol(name), Int32Constant(0)));
     260             : 
     261             :   Label throw_proxy_handler_revoked(this, Label::kDeferred),
     262          31 :       trap_undefined(this),
     263          31 :       if_try_get_own_property_bailout(this, Label::kDeferred),
     264          31 :       trap_not_callable(this, Label::kDeferred), return_true(this),
     265          31 :       return_false(this), check_target_desc(this);
     266             : 
     267             :   // 2. Let handler be O.[[ProxyHandler]].
     268          31 :   Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
     269             : 
     270             :   // 3. If handler is null, throw a TypeError exception.
     271             :   // 4. Assert: Type(handler) is Object.
     272          62 :   GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
     273             : 
     274             :   // 5. Let target be O.[[ProxyTarget]].
     275             :   Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
     276             : 
     277             :   // 6. Let trap be ? GetMethod(handler, "has").
     278             :   // 7. If trap is undefined, then (see 7.a below).
     279          31 :   Handle<Name> trap_name = factory()->has_string();
     280          31 :   Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);
     281             : 
     282          62 :   GotoIf(TaggedIsSmi(trap), &trap_not_callable);
     283          62 :   GotoIfNot(IsCallable(trap), &trap_not_callable);
     284             : 
     285             :   // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, P
     286             :   // »)).
     287             :   BranchIfToBooleanIsTrue(CallJS(CodeFactory::Call(isolate()), context, trap,
     288             :                                  handler, target, name),
     289          62 :                           &return_true, &check_target_desc);
     290             : 
     291          31 :   BIND(&check_target_desc);
     292             :   {
     293             :     // 9. If booleanTrapResult is false, then (see 9.a. in CheckHasTrapResult).
     294             :     CheckHasTrapResult(context, target, proxy, name, &return_false,
     295          31 :                        &if_try_get_own_property_bailout);
     296             :   }
     297             : 
     298          31 :   BIND(&if_try_get_own_property_bailout);
     299             :   {
     300             :     CallRuntime(Runtime::kCheckProxyHasTrap, context, name, target);
     301          62 :     Return(FalseConstant());
     302             :   }
     303             : 
     304          31 :   BIND(&trap_undefined);
     305             :   {
     306             :     // 7.a. Return ? target.[[HasProperty]](P).
     307             :     TailCallStub(Builtins::CallableFor(isolate(), Builtins::kHasProperty),
     308          62 :                  context, name, target);
     309             :   }
     310             : 
     311          31 :   BIND(&return_false);
     312          62 :   Return(FalseConstant());
     313             : 
     314          31 :   BIND(&return_true);
     315          62 :   Return(TrueConstant());
     316             : 
     317          31 :   BIND(&throw_proxy_handler_revoked);
     318          31 :   ThrowTypeError(context, MessageTemplate::kProxyRevoked, "has");
     319             : 
     320          31 :   BIND(&trap_not_callable);
     321             :   ThrowTypeError(context, MessageTemplate::kPropertyNotFunction, trap,
     322          93 :                  StringConstant("has"), proxy);
     323          31 : }
     324             : 
     325         124 : TF_BUILTIN(ProxyGetProperty, ProxiesCodeStubAssembler) {
     326             :   Node* context = Parameter(Descriptor::kContext);
     327             :   Node* proxy = Parameter(Descriptor::kProxy);
     328             :   Node* name = Parameter(Descriptor::kName);
     329             :   Node* receiver = Parameter(Descriptor::kReceiverValue);
     330             : 
     331             :   CSA_ASSERT(this, IsJSProxy(proxy));
     332             : 
     333             :   // 1. Assert: IsPropertyKey(P) is true.
     334             :   CSA_ASSERT(this, TaggedIsNotSmi(name));
     335             :   CSA_ASSERT(this, IsName(name));
     336             :   CSA_ASSERT(this, Word32Equal(IsPrivateSymbol(name), Int32Constant(0)));
     337             : 
     338             :   Label throw_proxy_handler_revoked(this, Label::kDeferred),
     339          31 :       trap_undefined(this);
     340             : 
     341             :   // 2. Let handler be O.[[ProxyHandler]].
     342          31 :   Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
     343             : 
     344             :   // 3. If handler is null, throw a TypeError exception.
     345          62 :   GotoIf(IsNull(handler), &throw_proxy_handler_revoked);
     346             : 
     347             :   // 4. Assert: Type(handler) is Object.
     348             :   CSA_ASSERT(this, IsJSReceiver(handler));
     349             : 
     350             :   // 5. Let target be O.[[ProxyTarget]].
     351             :   Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
     352             : 
     353             :   // 6. Let trap be ? GetMethod(handler, "get").
     354             :   // 7. If trap is undefined, then (see 7.a below).
     355          31 :   Handle<Name> trap_name = factory()->get_string();
     356          31 :   Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);
     357             : 
     358             :   // 8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »).
     359             :   Node* trap_result = CallJS(
     360             :       CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
     361          62 :       context, trap, handler, target, name, receiver);
     362             : 
     363             :   // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
     364          31 :   Label return_result(this);
     365             :   CheckGetSetTrapResult(context, target, proxy, name, trap_result,
     366          31 :                         &return_result, JSProxy::kGet);
     367             : 
     368          31 :   BIND(&return_result);
     369             :   {
     370             :     // 11. Return trapResult.
     371          31 :     Return(trap_result);
     372             :   }
     373             : 
     374          31 :   BIND(&trap_undefined);
     375             :   {
     376             :     // 7.a. Return ? target.[[Get]](P, Receiver).
     377             :     // TODO(mslekova): Introduce GetPropertyWithReceiver stub
     378             :     Return(CallRuntime(Runtime::kGetPropertyWithReceiver, context, target, name,
     379          31 :                        receiver));
     380             :   }
     381             : 
     382          31 :   BIND(&throw_proxy_handler_revoked);
     383          62 :   ThrowTypeError(context, MessageTemplate::kProxyRevoked, "get");
     384          31 : }
     385             : 
     386         124 : TF_BUILTIN(ProxySetProperty, ProxiesCodeStubAssembler) {
     387             :   Node* context = Parameter(Descriptor::kContext);
     388             :   Node* proxy = Parameter(Descriptor::kProxy);
     389             :   Node* name = Parameter(Descriptor::kName);
     390             :   Node* value = Parameter(Descriptor::kValue);
     391             :   Node* receiver = Parameter(Descriptor::kReceiverValue);
     392             :   Node* language_mode = Parameter(Descriptor::kLanguageMode);
     393             : 
     394             :   CSA_ASSERT(this, IsJSProxy(proxy));
     395             : 
     396             :   // 1. Assert: IsPropertyKey(P) is true.
     397             :   CSA_ASSERT(this, TaggedIsNotSmi(name));
     398             :   CSA_ASSERT(this, IsName(name));
     399             : 
     400             :   Label throw_proxy_handler_revoked(this, Label::kDeferred),
     401          31 :       trap_undefined(this), failure(this, Label::kDeferred),
     402          31 :       continue_checks(this), success(this),
     403          31 :       private_symbol(this, Label::kDeferred);
     404             : 
     405          62 :   GotoIf(IsPrivateSymbol(name), &private_symbol);
     406             : 
     407             :   // 2. Let handler be O.[[ProxyHandler]].
     408             :   Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
     409             : 
     410             :   // 3. If handler is null, throw a TypeError exception.
     411          62 :   GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
     412             : 
     413             :   // 4. Assert: Type(handler) is Object.
     414             :   CSA_ASSERT(this, IsJSReceiver(handler));
     415             : 
     416             :   // 5. Let target be O.[[ProxyTarget]].
     417             :   Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
     418             : 
     419             :   // 6. Let trap be ? GetMethod(handler, "set").
     420             :   // 7. If trap is undefined, then (see 7.a below).
     421          31 :   Handle<Name> set_string = factory()->set_string();
     422          31 :   Node* trap = GetMethod(context, handler, set_string, &trap_undefined);
     423             : 
     424             :   // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler,
     425             :   // « target, P, V, Receiver »)).
     426             :   // 9. If booleanTrapResult is false, return false.
     427             :   BranchIfToBooleanIsTrue(
     428             :       CallJS(CodeFactory::Call(isolate(),
     429             :                                ConvertReceiverMode::kNotNullOrUndefined),
     430             :              context, trap, handler, target, name, value, receiver),
     431          62 :       &continue_checks, &failure);
     432             : 
     433          31 :   BIND(&continue_checks);
     434             :   {
     435             :     // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
     436             :     Label return_result(this);
     437             :     CheckGetSetTrapResult(context, target, proxy, name, value, &success,
     438          31 :                           JSProxy::kSet);
     439             :   }
     440             : 
     441          31 :   BIND(&failure);
     442             :   {
     443             :     Label if_throw(this, Label::kDeferred);
     444             :     Branch(SmiEqual(language_mode,
     445             :                     SmiConstant(Smi::FromEnum(LanguageMode::kStrict))),
     446          93 :            &if_throw, &success);
     447             : 
     448          31 :     BIND(&if_throw);
     449             :     ThrowTypeError(context, MessageTemplate::kProxyTrapReturnedFalsishFor,
     450          31 :                    HeapConstant(set_string), name);
     451             :   }
     452             : 
     453             :   // 12. Return true.
     454          31 :   BIND(&success);
     455          31 :   Return(value);
     456             : 
     457          31 :   BIND(&private_symbol);
     458             :   {
     459          31 :     Label failure(this), throw_error(this, Label::kDeferred);
     460             : 
     461             :     Branch(SmiEqual(language_mode,
     462             :                     SmiConstant(Smi::FromEnum(LanguageMode::kStrict))),
     463          93 :            &throw_error, &failure);
     464             : 
     465          31 :     BIND(&failure);
     466          62 :     Return(UndefinedConstant());
     467             : 
     468          31 :     BIND(&throw_error);
     469          62 :     ThrowTypeError(context, MessageTemplate::kProxyPrivate);
     470             :   }
     471             : 
     472          31 :   BIND(&trap_undefined);
     473             :   {
     474             :     // 7.a. Return ? target.[[Set]](P, V, Receiver).
     475             :     CallRuntime(Runtime::kSetPropertyWithReceiver, context, target, name, value,
     476             :                 receiver, language_mode);
     477          31 :     Return(value);
     478             :   }
     479             : 
     480          31 :   BIND(&throw_proxy_handler_revoked);
     481          62 :   ThrowTypeError(context, MessageTemplate::kProxyRevoked, "set");
     482          31 : }
     483             : 
     484          62 : void ProxiesCodeStubAssembler::CheckGetSetTrapResult(
     485             :     Node* context, Node* target, Node* proxy, Node* name, Node* trap_result,
     486             :     Label* check_passed, JSProxy::AccessKind access_kind) {
     487         124 :   Node* map = LoadMap(target);
     488          62 :   VARIABLE(var_value, MachineRepresentation::kTagged);
     489         124 :   VARIABLE(var_details, MachineRepresentation::kWord32);
     490         124 :   VARIABLE(var_raw_value, MachineRepresentation::kTagged);
     491             : 
     492          62 :   Label if_found_value(this), check_in_runtime(this, Label::kDeferred);
     493             : 
     494         124 :   Node* instance_type = LoadInstanceType(target);
     495             :   TryGetOwnProperty(context, target, target, map, instance_type, name,
     496             :                     &if_found_value, &var_value, &var_details, &var_raw_value,
     497          62 :                     check_passed, &check_in_runtime);
     498             : 
     499          62 :   BIND(&if_found_value);
     500             :   {
     501             :     Label throw_non_configurable_data(this, Label::kDeferred),
     502          62 :         throw_non_configurable_accessor(this, Label::kDeferred),
     503          62 :         check_accessor(this), check_data(this);
     504             : 
     505             :     // If targetDesc is not undefined and targetDesc.[[Configurable]] is
     506             :     // false, then:
     507             :     GotoIfNot(IsSetWord32(var_details.value(),
     508         124 :                           PropertyDetails::kAttributesDontDeleteMask),
     509         124 :               check_passed);
     510             : 
     511             :     // If IsDataDescriptor(targetDesc) is true and
     512             :     // targetDesc.[[Writable]] is false, then:
     513          62 :     BranchIfAccessorPair(var_raw_value.value(), &check_accessor, &check_data);
     514             : 
     515          62 :     BIND(&check_data);
     516             :     {
     517             :       Node* read_only = IsSetWord32(var_details.value(),
     518         186 :                                     PropertyDetails::kAttributesReadOnlyMask);
     519          62 :       GotoIfNot(read_only, check_passed);
     520             : 
     521             :       // If SameValue(trapResult, targetDesc.[[Value]]) is false,
     522             :       // throw a TypeError exception.
     523             :       BranchIfSameValue(trap_result, var_value.value(), check_passed,
     524          62 :                         &throw_non_configurable_data);
     525             :     }
     526             : 
     527          62 :     BIND(&check_accessor);
     528             :     {
     529          62 :       Node* accessor_pair = var_raw_value.value();
     530             : 
     531          62 :       if (access_kind == JSProxy::kGet) {
     532             :         Label continue_check(this, Label::kDeferred);
     533             :         // 10.b. If IsAccessorDescriptor(targetDesc) is true and
     534             :         // targetDesc.[[Get]] is undefined, then:
     535             :         Node* getter =
     536             :             LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
     537             :         // Here we check for null as well because if the getter was never
     538             :         // defined it's set as null.
     539          62 :         GotoIf(IsUndefined(getter), &continue_check);
     540          62 :         GotoIf(IsNull(getter), &continue_check);
     541          31 :         Goto(check_passed);
     542             : 
     543             :         // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
     544          31 :         BIND(&continue_check);
     545          62 :         GotoIfNot(IsUndefined(trap_result), &throw_non_configurable_accessor);
     546             :       } else {
     547             :         // 11.b.i. If targetDesc.[[Set]] is undefined, throw a TypeError
     548             :         // exception.
     549             :         Node* setter =
     550             :             LoadObjectField(accessor_pair, AccessorPair::kSetterOffset);
     551          62 :         GotoIf(IsUndefined(setter), &throw_non_configurable_accessor);
     552          62 :         GotoIf(IsNull(setter), &throw_non_configurable_accessor);
     553             :       }
     554          62 :       Goto(check_passed);
     555             :     }
     556             : 
     557          62 :     BIND(&check_in_runtime);
     558             :     {
     559             :       CallRuntime(Runtime::kCheckProxyGetSetTrapResult, context, name, target,
     560          62 :                   trap_result, SmiConstant(access_kind));
     561          62 :       Return(trap_result);
     562             :     }
     563             : 
     564          62 :     BIND(&throw_non_configurable_data);
     565             :     {
     566             :       ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableData,
     567          62 :                      name, var_value.value(), trap_result);
     568             :     }
     569             : 
     570          62 :     BIND(&throw_non_configurable_accessor);
     571             :     {
     572             :       ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableAccessor,
     573          62 :                      name, trap_result);
     574          62 :     }
     575          62 :   }
     576          62 : }
     577             : 
     578          31 : void ProxiesCodeStubAssembler::CheckHasTrapResult(Node* context, Node* target,
     579             :                                                   Node* proxy, Node* name,
     580             :                                                   Label* check_passed,
     581             :                                                   Label* if_bailout) {
     582          62 :   Node* target_map = LoadMap(target);
     583          31 :   VARIABLE(var_value, MachineRepresentation::kTagged);
     584          62 :   VARIABLE(var_details, MachineRepresentation::kWord32);
     585          62 :   VARIABLE(var_raw_value, MachineRepresentation::kTagged);
     586             : 
     587          31 :   Label if_found_value(this, Label::kDeferred),
     588          31 :       throw_non_configurable(this, Label::kDeferred),
     589          31 :       throw_non_extensible(this, Label::kDeferred);
     590             : 
     591             :   // 9.a. Let targetDesc be ? target.[[GetOwnProperty]](P).
     592          62 :   Node* instance_type = LoadInstanceType(target);
     593             :   TryGetOwnProperty(context, target, target, target_map, instance_type, name,
     594             :                     &if_found_value, &var_value, &var_details, &var_raw_value,
     595          31 :                     check_passed, if_bailout);
     596             : 
     597             :   // 9.b. If targetDesc is not undefined, then (see 9.b.i. below).
     598          31 :   BIND(&if_found_value);
     599             :   {
     600             :     // 9.b.i. If targetDesc.[[Configurable]] is false, throw a TypeError
     601             :     // exception.
     602             :     Node* non_configurable = IsSetWord32(
     603          93 :         var_details.value(), PropertyDetails::kAttributesDontDeleteMask);
     604          31 :     GotoIf(non_configurable, &throw_non_configurable);
     605             : 
     606             :     // 9.b.ii. Let extensibleTarget be ? IsExtensible(target).
     607          31 :     Node* target_extensible = IsExtensibleMap(target_map);
     608             : 
     609             :     // 9.b.iii. If extensibleTarget is false, throw a TypeError exception.
     610          31 :     GotoIfNot(target_extensible, &throw_non_extensible);
     611          31 :     Goto(check_passed);
     612             :   }
     613             : 
     614          31 :   BIND(&throw_non_configurable);
     615          31 :   { ThrowTypeError(context, MessageTemplate::kProxyHasNonConfigurable, name); }
     616             : 
     617          31 :   BIND(&throw_non_extensible);
     618          62 :   { ThrowTypeError(context, MessageTemplate::kProxyHasNonExtensible, name); }
     619          31 : }
     620             : 
     621             : }  // namespace internal
     622             : }  // namespace v8

Generated by: LCOV version 1.10