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

Generated by: LCOV version 1.10