LCOV - code coverage report
Current view: top level - src/builtins - builtins-async-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 41 41 100.0 %
Date: 2017-04-26 Functions: 5 5 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             : #include "src/builtins/builtins-utils-gen.h"
       7             : 
       8             : namespace v8 {
       9             : namespace internal {
      10             : 
      11             : using compiler::Node;
      12             : 
      13             : namespace {
      14             : // Describe fields of Context associated with the AsyncIterator unwrap closure.
      15             : class ValueUnwrapContext {
      16             :  public:
      17             :   enum Fields { kDoneSlot = Context::MIN_CONTEXT_SLOTS, kLength };
      18             : };
      19             : 
      20             : }  // namespace
      21             : 
      22         172 : Node* AsyncBuiltinsAssembler::Await(
      23             :     Node* context, Node* generator, Node* value, Node* outer_promise,
      24             :     const NodeGenerator1& create_closure_context, int on_resolve_context_index,
      25             :     int on_reject_context_index, bool is_predicted_as_caught) {
      26             :   // Let promiseCapability be ! NewPromiseCapability(%Promise%).
      27         172 :   Node* const wrapped_value = AllocateAndInitJSPromise(context);
      28             : 
      29             :   // Perform ! Call(promiseCapability.[[Resolve]], undefined, « promise »).
      30         172 :   CallBuiltin(Builtins::kResolveNativePromise, context, wrapped_value, value);
      31             : 
      32         172 :   Node* const native_context = LoadNativeContext(context);
      33             : 
      34         172 :   Node* const closure_context = create_closure_context(native_context);
      35             :   Node* const map = LoadContextElement(
      36         172 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
      37             : 
      38             :   // Load and allocate on_resolve closure
      39             :   Node* const on_resolve_shared_fun =
      40         172 :       LoadContextElement(native_context, on_resolve_context_index);
      41             :   CSA_SLOW_ASSERT(
      42             :       this, HasInstanceType(on_resolve_shared_fun, SHARED_FUNCTION_INFO_TYPE));
      43             :   Node* const on_resolve = AllocateFunctionWithMapAndContext(
      44         172 :       map, on_resolve_shared_fun, closure_context);
      45             : 
      46             :   // Load and allocate on_reject closure
      47             :   Node* const on_reject_shared_fun =
      48         172 :       LoadContextElement(native_context, on_reject_context_index);
      49             :   CSA_SLOW_ASSERT(
      50             :       this, HasInstanceType(on_reject_shared_fun, SHARED_FUNCTION_INFO_TYPE));
      51             :   Node* const on_reject = AllocateFunctionWithMapAndContext(
      52         172 :       map, on_reject_shared_fun, closure_context);
      53             : 
      54             :   Node* const throwaway_promise =
      55         172 :       AllocateAndInitJSPromise(context, wrapped_value);
      56             : 
      57             :   // The Promise will be thrown away and not handled, but it shouldn't trigger
      58             :   // unhandled reject events as its work is done
      59         172 :   PromiseSetHasHandler(throwaway_promise);
      60             : 
      61         172 :   Label do_perform_promise_then(this);
      62         172 :   GotoIfNot(IsDebugActive(), &do_perform_promise_then);
      63             :   {
      64             :     Label common(this);
      65         172 :     GotoIf(TaggedIsSmi(value), &common);
      66         172 :     GotoIfNot(HasInstanceType(value, JS_PROMISE_TYPE), &common);
      67             :     {
      68             :       // Mark the reject handler callback to be a forwarding edge, rather
      69             :       // than a meaningful catch handler
      70             :       Node* const key =
      71         344 :           HeapConstant(factory()->promise_forwarding_handler_symbol());
      72             :       CallRuntime(Runtime::kSetProperty, context, on_reject, key,
      73         172 :                   TrueConstant(), SmiConstant(STRICT));
      74             : 
      75         172 :       if (is_predicted_as_caught) PromiseSetHandledHint(value);
      76             :     }
      77             : 
      78         172 :     Goto(&common);
      79         172 :     BIND(&common);
      80             :     // Mark the dependency to outer Promise in case the throwaway Promise is
      81             :     // found on the Promise stack
      82             :     CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE));
      83             : 
      84         344 :     Node* const key = HeapConstant(factory()->promise_handled_by_symbol());
      85             :     CallRuntime(Runtime::kSetProperty, context, throwaway_promise, key,
      86         172 :                 outer_promise, SmiConstant(STRICT));
      87             :   }
      88             : 
      89         172 :   Goto(&do_perform_promise_then);
      90         172 :   BIND(&do_perform_promise_then);
      91             :   CallBuiltin(Builtins::kPerformNativePromiseThen, context, wrapped_value,
      92         172 :               on_resolve, on_reject, throwaway_promise);
      93             : 
      94         172 :   return wrapped_value;
      95             : }
      96             : 
      97         172 : Node* AsyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context,
      98             :                                                   Node* done) {
      99             :   Node* const map = LoadContextElement(
     100         172 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     101             :   Node* const on_fulfilled_shared = LoadContextElement(
     102         172 :       native_context, Context::ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN);
     103             :   CSA_ASSERT(this,
     104             :              HasInstanceType(on_fulfilled_shared, SHARED_FUNCTION_INFO_TYPE));
     105             :   Node* const closure_context =
     106         172 :       AllocateAsyncIteratorValueUnwrapContext(native_context, done);
     107             :   return AllocateFunctionWithMapAndContext(map, on_fulfilled_shared,
     108         172 :                                            closure_context);
     109             : }
     110             : 
     111         172 : Node* AsyncBuiltinsAssembler::AllocateAsyncIteratorValueUnwrapContext(
     112             :     Node* native_context, Node* done) {
     113             :   CSA_ASSERT(this, IsNativeContext(native_context));
     114             :   CSA_ASSERT(this, IsBoolean(done));
     115             : 
     116             :   Node* const context =
     117         172 :       CreatePromiseContext(native_context, ValueUnwrapContext::kLength);
     118             :   StoreContextElementNoWriteBarrier(context, ValueUnwrapContext::kDoneSlot,
     119         172 :                                     done);
     120         172 :   return context;
     121             : }
     122             : 
     123         172 : TF_BUILTIN(AsyncIteratorValueUnwrap, AsyncBuiltinsAssembler) {
     124             :   Node* const value = Parameter(Descriptor::kValue);
     125             :   Node* const context = Parameter(Descriptor::kContext);
     126             : 
     127          43 :   Node* const done = LoadContextElement(context, ValueUnwrapContext::kDoneSlot);
     128             :   CSA_ASSERT(this, IsBoolean(done));
     129             : 
     130             :   Node* const unwrapped_value = CallStub(
     131          86 :       CodeFactory::CreateIterResultObject(isolate()), context, value, done);
     132             : 
     133          43 :   Return(unwrapped_value);
     134          43 : }
     135             : 
     136             : }  // namespace internal
     137             : }  // namespace v8

Generated by: LCOV version 1.10