Changeset 222425 in webkit


Ignore:
Timestamp:
Sep 23, 2017, 8:05:53 AM (8 years ago)
Author:
gskachkov@gmail.com
Message:

[ESNext] Async iteration - Implement Async Generator - optimization
https://bugs.webkit.org/show_bug.cgi?id=175891

Reviewed by Yusuke Suzuki.

Add small optimization for async generators:

  1. merging async generator queue to async generator itself

generator.@first / generator.@last is enough, by doing so,

we remove one unnecessary object alloc.

  1. merging request with queue.
  • builtins/AsyncGeneratorPrototype.js:

(globalPrivate.asyncGeneratorQueueIsEmpty):
(globalPrivate.asyncGeneratorQueueCreateItem):
(globalPrivate.asyncGeneratorQueueEnqueue):
(globalPrivate.asyncGeneratorQueueDequeue):
(globalPrivate.asyncGeneratorDequeue):
(globalPrivate.isSuspendYieldState):
(globalPrivate.asyncGeneratorEnqueue):

  • builtins/BuiltinNames.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitPutAsyncGeneratorFields):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::FunctionNode::emitBytecode):

Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r222424 r222425  
     12017-09-23  Oleksandr Skachkov  <gskachkov@gmail.com>
     2
     3        [ESNext] Async iteration - Implement Async Generator - optimization
     4        https://bugs.webkit.org/show_bug.cgi?id=175891
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        Add small optimization for async generators:
     9        1. merging async generator queue to async generator itself
     10        generator.@first / generator.@last is enough, by doing so,
     11          we remove one unnecessary object alloc.
     12        2. merging request with queue.
     13
     14        * builtins/AsyncGeneratorPrototype.js:
     15        (globalPrivate.asyncGeneratorQueueIsEmpty):
     16        (globalPrivate.asyncGeneratorQueueCreateItem):
     17        (globalPrivate.asyncGeneratorQueueEnqueue):
     18        (globalPrivate.asyncGeneratorQueueDequeue):
     19        (globalPrivate.asyncGeneratorDequeue):
     20        (globalPrivate.isSuspendYieldState):
     21        (globalPrivate.asyncGeneratorEnqueue):
     22        * builtins/BuiltinNames.h:
     23        * bytecompiler/BytecodeGenerator.cpp:
     24        (JSC::BytecodeGenerator::emitPutAsyncGeneratorFields):
     25        * bytecompiler/BytecodeGenerator.h:
     26        * bytecompiler/NodesCodegen.cpp:
     27        (JSC::FunctionNode::emitBytecode):
     28
    1292017-09-23  Joseph Pecoraro  <pecoraro@apple.com>
    230
  • trunk/Source/JavaScriptCore/builtins/AsyncGeneratorPrototype.js

    r221080 r222425  
    2525
    2626@globalPrivate
    27 function createAsyncGeneratorQueue()
    28 {
    29     "use strict";
    30 
    31     return { first: null, last: null };
    32 }
    33 
    34 @globalPrivate
    35 function asyncGeneratorQueueIsEmpty(queue)
    36 {
    37     "use strict";
    38 
    39     return queue.last === null;
    40 }
    41 
    42 @globalPrivate
    43 function asyncGeneratorQueueCreateItem(value, previous)
    44 {
    45     "use strict";
    46 
    47     return { value, previous, next: null };
    48 }
    49 
    50 @globalPrivate
    51 function asyncGeneratorQueueEnqueue(queue, value)
    52 {
    53     "use strict";
    54 
    55     if (queue.first === null && queue.last === null) {
    56         queue.first = @asyncGeneratorQueueCreateItem(value, null);
    57         queue.last = queue.first;
     27function asyncGeneratorQueueIsEmpty(generator)
     28{
     29    "use strict";
     30
     31    return generator.@asyncGeneratorQueueLast === null;
     32}
     33
     34@globalPrivate
     35function asyncGeneratorQueueEnqueue(generator, item)
     36{
     37    "use strict";
     38
     39    @assert(item.@asyncGeneratorQueueItemNext === null && item.@asyncGeneratorQueueItemPrevious === null);
     40
     41    if (generator.@asyncGeneratorQueueFirst === null) {
     42        @assert(generator.@asyncGeneratorQueueLast === null);
     43
     44        generator.@asyncGeneratorQueueFirst = item;
     45        generator.@asyncGeneratorQueueLast = item;
    5846    } else {
    59         const item = @asyncGeneratorQueueCreateItem(value, queue.last);
    60 
    61         queue.last.next = item;
    62         queue.last = item;
    63     }
    64 
    65 }
    66 
    67 @globalPrivate
    68 function asyncGeneratorQueueDequeue(queue)
    69 {
    70     "use strict";
    71 
    72     if (queue.first === null)
     47        item.@asyncGeneratorQueueItemPrevious = generator.@asyncGeneratorQueueLast;
     48        generator.@asyncGeneratorQueueLast.@asyncGeneratorQueueItemNext = item;
     49        generator.@asyncGeneratorQueueLast = item;
     50    }
     51}
     52
     53@globalPrivate
     54function asyncGeneratorQueueDequeue(generator)
     55{
     56    "use strict";
     57
     58    if (generator.@asyncGeneratorQueueFirst === null)
    7359        return null;
    7460
    75     const result = queue.first;
    76     queue.first = result.next;
    77 
    78     if (queue.first === null)
    79         queue.last = null;
    80 
    81     return result.value;
    82 }
    83 
    84 
    85 @globalPrivate
    86 function asyncGeneratorQueueGetFirstValue(queue)
    87 {
    88     "use strict";
    89 
    90     return queue.first !== null ? queue.first.value : @undefined;
     61    const result = generator.@asyncGeneratorQueueFirst;
     62    generator.@asyncGeneratorQueueFirst = result.@asyncGeneratorQueueItemNext;
     63
     64    if (generator.@asyncGeneratorQueueFirst === null)
     65        generator.@asyncGeneratorQueueLast = null;
     66
     67    return result;
    9168}
    9269
     
    9875    const queue = generator.@asyncGeneratorQueue;
    9976
    100     @assert(queue !== @undefined && !@asyncGeneratorQueueIsEmpty(queue), "Async genetator's Queue is an empty List.");
     77    @assert(!@asyncGeneratorQueueIsEmpty(generator), "Async genetator's Queue is an empty List.");
    10178   
    102     return @asyncGeneratorQueueDequeue(queue);
     79    return @asyncGeneratorQueueDequeue(generator);
    10380}
    10481
     
    11996
    12097    return (generator.@generatorState > 0 && generator.@asyncGeneratorSuspendReason === @AsyncGeneratorSuspendReasonYield)
    121          || generator.@generatorState === @AsyncGeneratorStateSuspendedYield;
     98        || generator.@generatorState === @AsyncGeneratorStateSuspendedYield;
    12299}
    123100
     
    236213        return @undefined;
    237214
    238     const queue = generator.@asyncGeneratorQueue;
    239 
    240     if (@asyncGeneratorQueueIsEmpty(queue))
     215    if (@asyncGeneratorQueueIsEmpty(generator))
    241216        return @undefined;
    242217
    243     const next = @asyncGeneratorQueueGetFirstValue(queue);
     218    const next = generator.@asyncGeneratorQueueFirst;
    244219
    245220    if (next.resumeMode !== @GeneratorResumeModeNormal) {
     
    290265    }
    291266
    292     @asyncGeneratorQueueEnqueue(generator.@asyncGeneratorQueue, {resumeMode, value, promiseCapability});
     267    @asyncGeneratorQueueEnqueue(generator, {resumeMode, value, promiseCapability, @asyncGeneratorQueueItemNext: null, @asyncGeneratorQueueItemPrevious: null});
    293268
    294269    if (!@isExecutionState(generator))
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.h

    r221417 r222425  
    127127    macro(asyncGeneratorSuspendReason) \
    128128    macro(asyncGeneratorQueue) \
     129    macro(asyncGeneratorQueueFirst) \
     130    macro(asyncGeneratorQueueLast) \
     131    macro(asyncGeneratorQueueItemNext) \
     132    macro(asyncGeneratorQueueItemPrevious) \
    129133    macro(promiseCapability) \
    130134    macro(generatorResumeMode) \
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r222421 r222425  
    28722872}
    28732873
    2874 RegisterID* BytecodeGenerator::emitCreateAsyncGeneratorQueue(const JSTextPosition& divot)
    2875 {
    2876     auto varCreateAsyncGeneratorQueue = variable(propertyNames().builtinNames().createAsyncGeneratorQueuePrivateName());
    2877     RefPtr<RegisterID> scope = newTemporary();
    2878     RefPtr<RegisterID> queue = newTemporary();
    2879     moveToDestinationIfNeeded(scope.get(), emitResolveScope(scope.get(), varCreateAsyncGeneratorQueue));
    2880     RefPtr<RegisterID> createAsyncGeneratorQueue = emitGetFromScope(newTemporary(), scope.get(), varCreateAsyncGeneratorQueue, ThrowIfNotFound);
    2881 
    2882     CallArguments args(*this, nullptr, 0);
    2883     emitLoad(args.thisRegister(), jsUndefined());
    2884 
    2885     emitCall(queue.get(), createAsyncGeneratorQueue.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);
    2886 
    2887     return queue.get();
    2888 }
    2889 
    2890 void BytecodeGenerator::emitPutAsyncGeneratorFields(RegisterID* nextFunction, const JSTextPosition& divot)
     2874void BytecodeGenerator::emitPutAsyncGeneratorFields(RegisterID* nextFunction)
    28912875{
    28922876    ASSERT(isAsyncGeneratorFunctionParseMode(parseMode()));
     
    29022886    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().asyncGeneratorSuspendReasonPrivateName(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::None))), PropertyNode::KnownDirect);
    29032887
    2904 
    2905     emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().asyncGeneratorQueuePrivateName(), emitCreateAsyncGeneratorQueue(divot), PropertyNode::KnownDirect);
     2888    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().asyncGeneratorQueueFirstPrivateName(), emitLoad(nullptr, jsNull()), PropertyNode::KnownDirect);
     2889    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().asyncGeneratorQueueLastPrivateName(), emitLoad(nullptr, jsNull()), PropertyNode::KnownDirect);
    29062890}
    29072891
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r222421 r222425  
    608608    private:
    609609        void emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
    610         RegisterID* emitCreateAsyncGeneratorQueue(const JSTextPosition&);
    611610    public:
    612611
     
    705704        void emitPutGeneratorFields(RegisterID* nextFunction);
    706705       
    707         void emitPutAsyncGeneratorFields(RegisterID* nextFunction, const JSTextPosition&);
     706        void emitPutAsyncGeneratorFields(RegisterID* nextFunction);
    708707
    709708        ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r222421 r222425  
    36033603        else {
    36043604            ASSERT(isAsyncGeneratorFunctionParseMode(generator.parseMode()));
    3605             generator.emitPutAsyncGeneratorFields(next.get(), JSTextPosition(startLine(), startStartOffset(), startLineStartOffset()));
     3605            generator.emitPutAsyncGeneratorFields(next.get());
    36063606        }
    36073607       
Note: See TracChangeset for help on using the changeset viewer.