LCOV - code coverage report
Current view: top level - src/runtime - runtime-forin.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 51 61 83.6 %
Date: 2017-04-26 Functions: 5 10 50.0 %

          Line data    Source code
       1             : // Copyright 2015 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/runtime/runtime-utils.h"
       6             : 
       7             : #include "src/arguments.h"
       8             : #include "src/elements.h"
       9             : #include "src/factory.h"
      10             : #include "src/isolate-inl.h"
      11             : #include "src/keys.h"
      12             : #include "src/objects-inl.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : namespace {
      18             : 
      19             : // Returns either a FixedArray or, if the given {receiver} has an enum cache
      20             : // that contains all enumerable properties of the {receiver} and its prototypes
      21             : // have none, the map of the {receiver}. This is used to speed up the check for
      22             : // deletions during a for-in.
      23       88190 : MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) {
      24             :   Isolate* const isolate = receiver->GetIsolate();
      25       88190 :   JSObject::MakePrototypesFast(receiver, kStartAtReceiver, isolate);
      26             :   FastKeyAccumulator accumulator(isolate, receiver,
      27             :                                  KeyCollectionMode::kIncludePrototypes,
      28             :                                  ENUMERABLE_STRINGS);
      29             :   accumulator.set_is_for_in(true);
      30             :   // Test if we have an enum cache for {receiver}.
      31       88190 :   if (!accumulator.is_receiver_simple_enum()) {
      32             :     Handle<FixedArray> keys;
      33      167348 :     ASSIGN_RETURN_ON_EXCEPTION(
      34             :         isolate, keys, accumulator.GetKeys(GetKeysConversion::kConvertToString),
      35             :         HeapObject);
      36             :     // Test again, since cache may have been built by GetKeys() calls above.
      37       83534 :     if (!accumulator.is_receiver_simple_enum()) return keys;
      38             :   }
      39             :   return handle(receiver->map(), isolate);
      40             : }
      41             : 
      42             : // This is a slight modifcation of JSReceiver::HasProperty, dealing with
      43             : // the oddities of JSProxy in for-in filter.
      44      287773 : MaybeHandle<Object> HasEnumerableProperty(Isolate* isolate,
      45             :                                           Handle<JSReceiver> receiver,
      46             :                                           Handle<Object> key) {
      47      287773 :   bool success = false;
      48             :   Maybe<PropertyAttributes> result = Just(ABSENT);
      49             :   LookupIterator it =
      50      287773 :       LookupIterator::PropertyOrElement(isolate, receiver, key, &success);
      51      287773 :   if (!success) return isolate->factory()->undefined_value();
      52      285451 :   for (; it.IsFound(); it.Next()) {
      53      573196 :     switch (it.state()) {
      54             :       case LookupIterator::NOT_FOUND:
      55             :       case LookupIterator::TRANSITION:
      56           0 :         UNREACHABLE();
      57             :       case LookupIterator::JSPROXY: {
      58             :         // For proxies we have to invoke the [[GetOwnProperty]] trap.
      59        1166 :         result = JSProxy::GetPropertyAttributes(&it);
      60        1166 :         if (result.IsNothing()) return MaybeHandle<Object>();
      61        1121 :         if (result.FromJust() == ABSENT) {
      62             :           // Continue lookup on the proxy's prototype.
      63         127 :           Handle<JSProxy> proxy = it.GetHolder<JSProxy>();
      64             :           Handle<Object> prototype;
      65         254 :           ASSIGN_RETURN_ON_EXCEPTION(isolate, prototype,
      66             :                                      JSProxy::GetPrototype(proxy), Object);
      67         127 :           if (prototype->IsNull(isolate)) {
      68             :             return isolate->factory()->undefined_value();
      69             :           }
      70             :           // We already have a stack-check in JSProxy::GetPrototype.
      71             :           return HasEnumerableProperty(
      72         112 :               isolate, Handle<JSReceiver>::cast(prototype), key);
      73         994 :         } else if (result.FromJust() & DONT_ENUM) {
      74             :           return isolate->factory()->undefined_value();
      75             :         } else {
      76         910 :           return it.GetName();
      77             :         }
      78             :       }
      79             :       case LookupIterator::INTERCEPTOR: {
      80      280284 :         result = JSObject::GetPropertyAttributesWithInterceptor(&it);
      81      280284 :         if (result.IsNothing()) return MaybeHandle<Object>();
      82      280284 :         if (result.FromJust() != ABSENT) return it.GetName();
      83             :         continue;
      84             :       }
      85             :       case LookupIterator::ACCESS_CHECK: {
      86        5411 :         if (it.HasAccess()) continue;
      87           0 :         result = JSObject::GetPropertyAttributesWithFailedAccessCheck(&it);
      88           0 :         if (result.IsNothing()) return MaybeHandle<Object>();
      89           0 :         if (result.FromJust() != ABSENT) return it.GetName();
      90             :         return isolate->factory()->undefined_value();
      91             :       }
      92             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
      93             :         // TypedArray out-of-bounds access.
      94             :         return isolate->factory()->undefined_value();
      95             :       case LookupIterator::ACCESSOR:
      96             :       case LookupIterator::DATA:
      97      286335 :         return it.GetName();
      98             :     }
      99             :   }
     100             :   return isolate->factory()->undefined_value();
     101             : }
     102             : 
     103             : }  // namespace
     104             : 
     105             : 
     106       71706 : RUNTIME_FUNCTION(Runtime_ForInEnumerate) {
     107       35853 :   HandleScope scope(isolate);
     108             :   DCHECK_EQ(1, args.length());
     109       71706 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
     110      107559 :   RETURN_RESULT_OR_FAILURE(isolate, Enumerate(receiver));
     111             : }
     112             : 
     113             : 
     114       52337 : RUNTIME_FUNCTION_RETURN_TRIPLE(Runtime_ForInPrepare) {
     115       52337 :   HandleScope scope(isolate);
     116             :   DCHECK_EQ(1, args.length());
     117       52337 :   Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
     118             :   Handle<Object> cache_type;
     119      104674 :   if (!Enumerate(receiver).ToHandle(&cache_type)) {
     120          98 :     return MakeTriple(isolate->heap()->exception(), nullptr, nullptr);
     121             :   }
     122             :   Handle<FixedArray> cache_array;
     123             :   int cache_length;
     124       52239 :   if (cache_type->IsMap()) {
     125        9935 :     Handle<Map> cache_map = Handle<Map>::cast(cache_type);
     126             :     Handle<DescriptorArray> descriptors(cache_map->instance_descriptors(),
     127        9935 :                                         isolate);
     128        9935 :     cache_length = cache_map->EnumLength();
     129       16307 :     if (cache_length && descriptors->HasEnumCache()) {
     130        6372 :       cache_array = handle(descriptors->GetEnumCache(), isolate);
     131             :     } else {
     132        3563 :       cache_array = isolate->factory()->empty_fixed_array();
     133             :       cache_length = 0;
     134             :     }
     135             :   } else {
     136       42304 :     cache_array = Handle<FixedArray>::cast(cache_type);
     137       42304 :     cache_length = cache_array->length();
     138       42304 :     cache_type = handle(Smi::FromInt(1), isolate);
     139             :   }
     140      104478 :   return MakeTriple(*cache_type, *cache_array, Smi::FromInt(cache_length));
     141             : }
     142             : 
     143      575322 : RUNTIME_FUNCTION(Runtime_ForInHasProperty) {
     144      287661 :   HandleScope scope(isolate);
     145             :   DCHECK_EQ(2, args.length());
     146      575322 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
     147      287661 :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
     148             :   Handle<Object> result;
     149      575322 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     150             :       isolate, result, HasEnumerableProperty(isolate, receiver, key));
     151      287616 :   return isolate->heap()->ToBoolean(!result->IsUndefined(isolate));
     152             : }
     153             : 
     154           0 : RUNTIME_FUNCTION(Runtime_ForInFilter) {
     155           0 :   HandleScope scope(isolate);
     156             :   DCHECK_EQ(2, args.length());
     157           0 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
     158           0 :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
     159           0 :   RETURN_RESULT_OR_FAILURE(isolate,
     160           0 :                            HasEnumerableProperty(isolate, receiver, key));
     161             : }
     162             : 
     163             : }  // namespace internal
     164             : }  // namespace v8

Generated by: LCOV version 1.10