LCOV - code coverage report
Current view: top level - src/builtins - builtins-weak-refs.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 63 63 100.0 %
Date: 2019-01-20 Functions: 18 26 69.2 %

          Line data    Source code
       1             : // Copyright 2018 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-utils-inl.h"
       6             : #include "src/counters.h"
       7             : #include "src/objects/js-weak-refs-inl.h"
       8             : 
       9             : namespace v8 {
      10             : namespace internal {
      11             : 
      12        1548 : BUILTIN(WeakFactoryConstructor) {
      13             :   HandleScope scope(isolate);
      14         387 :   Handle<JSFunction> target = args.target();
      15        1161 :   if (args.new_target()->IsUndefined(isolate)) {  // [[Call]]
      16          27 :     THROW_NEW_ERROR_RETURN_FAILURE(
      17             :         isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
      18             :                               handle(target->shared()->Name(), isolate)));
      19             :   }
      20             :   // [[Construct]]
      21         378 :   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
      22             :   Handle<Object> cleanup = args.atOrUndefined(isolate, 1);
      23             : 
      24         756 :   if (!cleanup->IsCallable()) {
      25          72 :     THROW_NEW_ERROR_RETURN_FAILURE(
      26             :         isolate, NewTypeError(MessageTemplate::kWeakRefsCleanupMustBeCallable));
      27             :   }
      28             : 
      29             :   Handle<JSObject> result;
      30         684 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      31             :       isolate, result,
      32             :       JSObject::New(target, new_target, Handle<AllocationSite>::null()));
      33             : 
      34         342 :   Handle<JSWeakFactory> weak_factory = Handle<JSWeakFactory>::cast(result);
      35         684 :   weak_factory->set_native_context(*isolate->native_context());
      36         342 :   weak_factory->set_cleanup(*cleanup);
      37             :   weak_factory->set_flags(
      38             :       JSWeakFactory::ScheduledForCleanupField::encode(false));
      39         342 :   return *weak_factory;
      40             : }
      41             : 
      42        1800 : BUILTIN(WeakFactoryMakeCell) {
      43             :   HandleScope scope(isolate);
      44             :   const char* method_name = "WeakFactory.prototype.makeCell";
      45             : 
      46         927 :   CHECK_RECEIVER(JSWeakFactory, weak_factory, method_name);
      47             : 
      48             :   Handle<Object> target = args.atOrUndefined(isolate, 1);
      49         882 :   if (!target->IsJSReceiver()) {
      50         126 :     THROW_NEW_ERROR_RETURN_FAILURE(
      51             :         isolate,
      52             :         NewTypeError(MessageTemplate::kWeakRefsMakeCellTargetMustBeObject));
      53             :   }
      54         378 :   Handle<JSReceiver> target_receiver = Handle<JSReceiver>::cast(target);
      55             :   Handle<Object> holdings = args.atOrUndefined(isolate, 2);
      56         378 :   if (target->SameValue(*holdings)) {
      57          18 :     THROW_NEW_ERROR_RETURN_FAILURE(
      58             :         isolate,
      59             :         NewTypeError(
      60             :             MessageTemplate::kWeakRefsMakeCellTargetAndHoldingsMustNotBeSame));
      61             :   }
      62             : 
      63             :   // TODO(marja): Realms.
      64             : 
      65        1107 :   Handle<Map> weak_cell_map(isolate->native_context()->js_weak_cell_map(),
      66         369 :                             isolate);
      67             : 
      68             :   // Allocate the JSWeakCell object in the old space, because 1) JSWeakCell
      69             :   // weakness handling is only implemented in the old space 2) they're
      70             :   // supposedly long-living. TODO(marja): Support JSWeakCells in Scavenger.
      71             :   Handle<JSWeakCell> weak_cell =
      72             :       Handle<JSWeakCell>::cast(isolate->factory()->NewJSObjectFromMap(
      73         369 :           weak_cell_map, TENURED, Handle<AllocationSite>::null()));
      74         738 :   weak_cell->set_target(*target_receiver);
      75         369 :   weak_cell->set_holdings(*holdings);
      76         369 :   weak_factory->AddWeakCell(*weak_cell);
      77         369 :   return *weak_cell;
      78             : }
      79             : 
      80         216 : BUILTIN(WeakFactoryCleanupSome) {
      81             :   HandleScope scope(isolate);
      82             :   const char* method_name = "WeakFactory.prototype.cleanupSome";
      83             : 
      84         135 :   CHECK_RECEIVER(JSWeakFactory, weak_factory, method_name);
      85             : 
      86             :   // Don't do set_scheduled_for_cleanup(false); we still have the microtask
      87             :   // scheduled and don't want to schedule another one in case the user never
      88             :   // executes microtasks.
      89          45 :   JSWeakFactory::Cleanup(weak_factory, isolate);
      90          45 :   return ReadOnlyRoots(isolate).undefined_value();
      91             : }
      92             : 
      93        1332 : BUILTIN(WeakFactoryCleanupIteratorNext) {
      94             :   HandleScope scope(isolate);
      95         666 :   CHECK_RECEIVER(JSWeakFactoryCleanupIterator, iterator, "next");
      96             : 
      97         666 :   Handle<JSWeakFactory> weak_factory(iterator->factory(), isolate);
      98         333 :   if (!weak_factory->NeedsCleanup()) {
      99             :     return *isolate->factory()->NewJSIteratorResult(
     100         288 :         handle(ReadOnlyRoots(isolate).undefined_value(), isolate), true);
     101             :   }
     102             :   Handle<JSWeakCell> weak_cell_object =
     103         378 :       handle(weak_factory->PopClearedCell(isolate), isolate);
     104             : 
     105         378 :   return *isolate->factory()->NewJSIteratorResult(weak_cell_object, false);
     106             : }
     107             : 
     108         612 : BUILTIN(WeakCellHoldingsGetter) {
     109             :   HandleScope scope(isolate);
     110         333 :   CHECK_RECEIVER(JSWeakCell, weak_cell, "get WeakCell.holdings");
     111         144 :   return weak_cell->holdings();
     112             : }
     113             : 
     114         468 : BUILTIN(WeakCellClear) {
     115             :   HandleScope scope(isolate);
     116         261 :   CHECK_RECEIVER(JSWeakCell, weak_cell, "WeakCell.prototype.clear");
     117         108 :   weak_cell->Clear(isolate);
     118         108 :   return ReadOnlyRoots(isolate).undefined_value();
     119             : }
     120             : 
     121         612 : BUILTIN(WeakRefConstructor) {
     122             :   HandleScope scope(isolate);
     123         153 :   Handle<JSFunction> target = args.target();
     124         459 :   if (args.new_target()->IsUndefined(isolate)) {  // [[Call]]
     125          27 :     THROW_NEW_ERROR_RETURN_FAILURE(
     126             :         isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
     127             :                               handle(target->shared()->Name(), isolate)));
     128             :   }
     129             :   // [[Construct]]
     130         144 :   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
     131             :   Handle<Object> target_object = args.atOrUndefined(isolate, 1);
     132         288 :   if (!target_object->IsJSReceiver()) {
     133         126 :     THROW_NEW_ERROR_RETURN_FAILURE(
     134             :         isolate,
     135             :         NewTypeError(
     136             :             MessageTemplate::kWeakRefsWeakRefConstructorTargetMustBeObject));
     137             :   }
     138             :   isolate->heap()->AddKeepDuringJobTarget(
     139          81 :       Handle<JSReceiver>::cast(target_object));
     140             : 
     141             :   // TODO(marja): Realms.
     142             : 
     143             :   Handle<JSObject> result;
     144         162 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     145             :       isolate, result,
     146             :       JSObject::New(target, new_target, Handle<AllocationSite>::null()));
     147             : 
     148          81 :   Handle<JSWeakRef> weak_ref = Handle<JSWeakRef>::cast(result);
     149          81 :   weak_ref->set_target(*target_object);
     150          81 :   return *weak_ref;
     151             : }
     152             : 
     153         684 : BUILTIN(WeakRefDeref) {
     154             :   HandleScope scope(isolate);
     155         396 :   CHECK_RECEIVER(JSWeakRef, weak_ref, "WeakRef.prototype.deref");
     156         306 :   if (weak_ref->target()->IsJSReceiver()) {
     157             :     Handle<JSReceiver> target =
     158         198 :         handle(JSReceiver::cast(weak_ref->target()), isolate);
     159             :     // AddKeepDuringJobTarget might allocate and cause a GC, but it won't clear
     160             :     // weak_ref since we hold a Handle to its target.
     161          99 :     isolate->heap()->AddKeepDuringJobTarget(target);
     162             :   } else {
     163             :     DCHECK(weak_ref->target()->IsUndefined(isolate));
     164             :   }
     165         153 :   return weak_ref->target();
     166             : }
     167             : 
     168             : }  // namespace internal
     169      183867 : }  // namespace v8

Generated by: LCOV version 1.10