LCOV - code coverage report
Current view: top level - src/builtins - builtins-async-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 69 69 100.0 %
Date: 2017-10-20 Functions: 6 6 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-async-gen.h"
       6             : 
       7             : #include "src/builtins/builtins-utils-gen.h"
       8             : #include "src/factory-inl.h"
       9             : #include "src/objects/shared-function-info.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14             : using compiler::Node;
      15             : 
      16             : namespace {
      17             : // Describe fields of Context associated with the AsyncIterator unwrap closure.
      18             : class ValueUnwrapContext {
      19             :  public:
      20             :   enum Fields { kDoneSlot = Context::MIN_CONTEXT_SLOTS, kLength };
      21             : };
      22             : 
      23             : }  // namespace
      24             : 
      25         186 : Node* AsyncBuiltinsAssembler::Await(
      26             :     Node* context, Node* generator, Node* value, Node* outer_promise,
      27             :     int context_length, const ContextInitializer& init_closure_context,
      28             :     Node* on_resolve_context_index, Node* on_reject_context_index,
      29             :     Node* is_predicted_as_caught) {
      30             :   DCHECK_GE(context_length, Context::MIN_CONTEXT_SLOTS);
      31             : 
      32         372 :   Node* const native_context = LoadNativeContext(context);
      33             : 
      34         217 :   static const int kWrappedPromiseOffset = FixedArray::SizeFor(context_length);
      35             :   static const int kThrowawayPromiseOffset =
      36         186 :       kWrappedPromiseOffset + JSPromise::kSizeWithEmbedderFields;
      37             :   static const int kResolveClosureOffset =
      38         186 :       kThrowawayPromiseOffset + JSPromise::kSizeWithEmbedderFields;
      39             :   static const int kRejectClosureOffset =
      40         186 :       kResolveClosureOffset + JSFunction::kSizeWithoutPrototype;
      41             :   static const int kTotalSize =
      42         186 :       kRejectClosureOffset + JSFunction::kSizeWithoutPrototype;
      43             : 
      44         186 :   Node* const base = AllocateInNewSpace(kTotalSize);
      45             :   Node* const closure_context = base;
      46             :   {
      47             :     // Initialize closure context
      48         186 :     InitializeFunctionContext(native_context, closure_context, context_length);
      49         186 :     init_closure_context(closure_context);
      50             :   }
      51             : 
      52             :   // Let promiseCapability be ! NewPromiseCapability(%Promise%).
      53             :   Node* const promise_fun =
      54         372 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
      55             :   CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun)));
      56             :   Node* const promise_map =
      57             :       LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
      58             :   // Assert that the JSPromise map has an instance size is
      59             :   // JSPromise::kSizeWithEmbedderFields.
      60             :   CSA_ASSERT(this, WordEqual(LoadMapInstanceSize(promise_map),
      61             :                              IntPtrConstant(JSPromise::kSizeWithEmbedderFields /
      62             :                                             kPointerSize)));
      63         186 :   Node* const wrapped_value = InnerAllocate(base, kWrappedPromiseOffset);
      64             :   {
      65             :     // Initialize Promise
      66         186 :     StoreMapNoWriteBarrier(wrapped_value, promise_map);
      67             :     InitializeJSObjectFromMap(
      68             :         wrapped_value, promise_map,
      69         186 :         IntPtrConstant(JSPromise::kSizeWithEmbedderFields),
      70         744 :         EmptyFixedArrayConstant(), EmptyFixedArrayConstant());
      71         186 :     PromiseInit(wrapped_value);
      72             :   }
      73             : 
      74         186 :   Node* const throwaway = InnerAllocate(base, kThrowawayPromiseOffset);
      75             :   {
      76             :     // Initialize throwawayPromise
      77         186 :     StoreMapNoWriteBarrier(throwaway, promise_map);
      78             :     InitializeJSObjectFromMap(
      79             :         throwaway, promise_map,
      80             :         IntPtrConstant(JSPromise::kSizeWithEmbedderFields),
      81         744 :         EmptyFixedArrayConstant(), EmptyFixedArrayConstant());
      82         186 :     PromiseInit(throwaway);
      83             :   }
      84             : 
      85         186 :   Node* const on_resolve = InnerAllocate(base, kResolveClosureOffset);
      86             :   {
      87             :     // Initialize resolve handler
      88             :     InitializeNativeClosure(closure_context, native_context, on_resolve,
      89         186 :                             on_resolve_context_index);
      90             :   }
      91             : 
      92         186 :   Node* const on_reject = InnerAllocate(base, kRejectClosureOffset);
      93             :   {
      94             :     // Initialize reject handler
      95             :     InitializeNativeClosure(closure_context, native_context, on_reject,
      96         186 :                             on_reject_context_index);
      97             :   }
      98             : 
      99             :   {
     100             :     // Add PromiseHooks if needed
     101             :     Label next(this);
     102         372 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &next);
     103             :     CallRuntime(Runtime::kPromiseHookInit, context, wrapped_value,
     104             :                 outer_promise);
     105             :     CallRuntime(Runtime::kPromiseHookInit, context, throwaway, wrapped_value);
     106         186 :     Goto(&next);
     107         186 :     BIND(&next);
     108             :   }
     109             : 
     110             :   // Perform ! Call(promiseCapability.[[Resolve]], undefined, « promise »).
     111         186 :   CallBuiltin(Builtins::kResolveNativePromise, context, wrapped_value, value);
     112             : 
     113             :   // The Promise will be thrown away and not handled, but it shouldn't trigger
     114             :   // unhandled reject events as its work is done
     115         186 :   PromiseSetHasHandler(throwaway);
     116             : 
     117             :   Label do_perform_promise_then(this);
     118         372 :   GotoIfNot(IsDebugActive(), &do_perform_promise_then);
     119             :   {
     120             :     Label common(this);
     121         372 :     GotoIf(TaggedIsSmi(value), &common);
     122         372 :     GotoIfNot(HasInstanceType(value, JS_PROMISE_TYPE), &common);
     123             :     {
     124             :       // Mark the reject handler callback to be a forwarding edge, rather
     125             :       // than a meaningful catch handler
     126             :       Node* const key =
     127         186 :           HeapConstant(factory()->promise_forwarding_handler_symbol());
     128             :       CallRuntime(Runtime::kSetProperty, context, on_reject, key,
     129             :                   TrueConstant(),
     130         186 :                   SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
     131             : 
     132         372 :       GotoIf(IsFalse(is_predicted_as_caught), &common);
     133         186 :       PromiseSetHandledHint(value);
     134             :     }
     135             : 
     136         186 :     Goto(&common);
     137         186 :     BIND(&common);
     138             :     // Mark the dependency to outer Promise in case the throwaway Promise is
     139             :     // found on the Promise stack
     140             :     CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE));
     141             : 
     142         186 :     Node* const key = HeapConstant(factory()->promise_handled_by_symbol());
     143             :     CallRuntime(Runtime::kSetProperty, context, throwaway, key, outer_promise,
     144         372 :                 SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
     145             :   }
     146             : 
     147         186 :   Goto(&do_perform_promise_then);
     148         186 :   BIND(&do_perform_promise_then);
     149             : 
     150             :   CallBuiltin(Builtins::kPerformNativePromiseThen, context, wrapped_value,
     151         186 :               on_resolve, on_reject, throwaway);
     152             : 
     153         186 :   return wrapped_value;
     154             : }
     155             : 
     156         372 : void AsyncBuiltinsAssembler::InitializeNativeClosure(Node* context,
     157             :                                                      Node* native_context,
     158             :                                                      Node* function,
     159             :                                                      Node* context_index) {
     160             :   Node* const function_map = LoadContextElement(
     161         744 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     162             :   // Ensure that we don't have to initialize prototype_or_initial_map field of
     163             :   // JSFunction.
     164             :   CSA_ASSERT(this, WordEqual(LoadMapInstanceSize(function_map),
     165             :                              IntPtrConstant(JSFunction::kSizeWithoutPrototype /
     166             :                                             kPointerSize)));
     167         372 :   StoreMapNoWriteBarrier(function, function_map);
     168             :   StoreObjectFieldRoot(function, JSObject::kPropertiesOrHashOffset,
     169         372 :                        Heap::kEmptyFixedArrayRootIndex);
     170             :   StoreObjectFieldRoot(function, JSObject::kElementsOffset,
     171         372 :                        Heap::kEmptyFixedArrayRootIndex);
     172             :   StoreObjectFieldRoot(function, JSFunction::kFeedbackVectorOffset,
     173         372 :                        Heap::kUndefinedCellRootIndex);
     174             : 
     175         744 :   Node* shared_info = LoadContextElement(native_context, context_index);
     176             :   CSA_ASSERT(this, IsSharedFunctionInfo(shared_info));
     177             :   StoreObjectFieldNoWriteBarrier(
     178         372 :       function, JSFunction::kSharedFunctionInfoOffset, shared_info);
     179         372 :   StoreObjectFieldNoWriteBarrier(function, JSFunction::kContextOffset, context);
     180             : 
     181             :   Node* const code =
     182             :       LoadObjectField(shared_info, SharedFunctionInfo::kCodeOffset);
     183         372 :   StoreObjectFieldNoWriteBarrier(function, JSFunction::kCodeOffset, code);
     184         372 : }
     185             : 
     186          93 : Node* AsyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context,
     187             :                                                   Node* done) {
     188             :   Node* const map = LoadContextElement(
     189         186 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     190             :   Node* const on_fulfilled_shared = LoadContextElement(
     191         186 :       native_context, Context::ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN);
     192             :   CSA_ASSERT(this,
     193             :              HasInstanceType(on_fulfilled_shared, SHARED_FUNCTION_INFO_TYPE));
     194             :   Node* const closure_context =
     195          93 :       AllocateAsyncIteratorValueUnwrapContext(native_context, done);
     196             :   return AllocateFunctionWithMapAndContext(map, on_fulfilled_shared,
     197          93 :                                            closure_context);
     198             : }
     199             : 
     200          93 : Node* AsyncBuiltinsAssembler::AllocateAsyncIteratorValueUnwrapContext(
     201             :     Node* native_context, Node* done) {
     202             :   CSA_ASSERT(this, IsNativeContext(native_context));
     203             :   CSA_ASSERT(this, IsBoolean(done));
     204             : 
     205             :   Node* const context =
     206          93 :       CreatePromiseContext(native_context, ValueUnwrapContext::kLength);
     207             :   StoreContextElementNoWriteBarrier(context, ValueUnwrapContext::kDoneSlot,
     208          93 :                                     done);
     209          93 :   return context;
     210             : }
     211             : 
     212         124 : TF_BUILTIN(AsyncIteratorValueUnwrap, AsyncBuiltinsAssembler) {
     213             :   Node* const value = Parameter(Descriptor::kValue);
     214             :   Node* const context = Parameter(Descriptor::kContext);
     215             : 
     216          62 :   Node* const done = LoadContextElement(context, ValueUnwrapContext::kDoneSlot);
     217             :   CSA_ASSERT(this, IsBoolean(done));
     218             : 
     219             :   Node* const unwrapped_value =
     220          31 :       CallBuiltin(Builtins::kCreateIterResultObject, context, value, done);
     221             : 
     222          31 :   Return(unwrapped_value);
     223          31 : }
     224             : 
     225             : }  // namespace internal
     226             : }  // namespace v8

Generated by: LCOV version 1.10