Changeset 157420 in webkit


Ignore:
Timestamp:
Oct 14, 2013 2:08:37 PM (11 years ago)
Author:
oliver@apple.com
Message:

Separate out array iteration intrinsics
https://bugs.webkit.org/show_bug.cgi?id=122656

Reviewed by Michael Saboff.

Separate out the intrinsics for key and values iteration
of arrays.

This requires moving moving array iteration into the iterator
instance, rather than the prototype, but this is essentially
unobservable so we'll live with it for now.

  • jit/ThunkGenerators.cpp:

(JSC::arrayIteratorNextThunkGenerator):
(JSC::arrayIteratorNextKeyThunkGenerator):
(JSC::arrayIteratorNextValueThunkGenerator):

  • jit/ThunkGenerators.h:
  • runtime/ArrayIteratorPrototype.cpp:

(JSC::ArrayIteratorPrototype::finishCreation):

  • runtime/Intrinsic.h:
  • runtime/JSArrayIterator.cpp:

(JSC::JSArrayIterator::finishCreation):
(JSC::createIteratorResult):
(JSC::arrayIteratorNext):
(JSC::arrayIteratorNextKey):
(JSC::arrayIteratorNextValue):
(JSC::arrayIteratorNextGeneric):

  • runtime/VM.cpp:

(JSC::thunkGeneratorForIntrinsic):

Location:
trunk/Source/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r157413 r157420  
     12013-10-11  Oliver Hunt  <oliver@apple.com>
     2
     3        Separate out array iteration intrinsics
     4        https://bugs.webkit.org/show_bug.cgi?id=122656
     5
     6        Reviewed by Michael Saboff.
     7
     8        Separate out the intrinsics for key and values iteration
     9        of arrays.
     10
     11        This requires moving moving array iteration into the iterator
     12        instance, rather than the prototype, but this is essentially
     13        unobservable so we'll live with it for now.
     14
     15        * jit/ThunkGenerators.cpp:
     16        (JSC::arrayIteratorNextThunkGenerator):
     17        (JSC::arrayIteratorNextKeyThunkGenerator):
     18        (JSC::arrayIteratorNextValueThunkGenerator):
     19        * jit/ThunkGenerators.h:
     20        * runtime/ArrayIteratorPrototype.cpp:
     21        (JSC::ArrayIteratorPrototype::finishCreation):
     22        * runtime/Intrinsic.h:
     23        * runtime/JSArrayIterator.cpp:
     24        (JSC::JSArrayIterator::finishCreation):
     25        (JSC::createIteratorResult):
     26        (JSC::arrayIteratorNext):
     27        (JSC::arrayIteratorNextKey):
     28        (JSC::arrayIteratorNextValue):
     29        (JSC::arrayIteratorNextGeneric):
     30        * runtime/VM.cpp:
     31        (JSC::thunkGeneratorForIntrinsic):
     32
    1332013-10-11  Mark Hahnenberg  <mhahnenberg@apple.com>
    234
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r157317 r157420  
    989989}
    990990
    991 MacroAssemblerCodeRef arrayIteratorNextThunkGenerator(VM* vm)
     991static MacroAssemblerCodeRef arrayIteratorNextThunkGenerator(VM* vm, ArrayIterationKind kind)
    992992{
    993993    typedef SpecializedThunkJIT::TrustedImm32 TrustedImm32;
     
    10151015   
    10161016    jit.and32(TrustedImm32(IndexingShapeMask), SpecializedThunkJIT::regT3);
    1017    
     1017
    10181018    Jump notDone = jit.branch32(SpecializedThunkJIT::Below, SpecializedThunkJIT::regT1, Address(SpecializedThunkJIT::regT2, Butterfly::offsetOfPublicLength()));
    10191019    // Return the termination signal to indicate that we've finished
     
    10231023    notDone.link(&jit);
    10241024   
    1025    
    1026     Jump notKey = jit.branch32(SpecializedThunkJIT::NotEqual, Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfIterationKind()), TrustedImm32(ArrayIterateKey));
    1027     // If we're doing key iteration we just need to increment m_nextIndex and return the current value
    1028     jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
    1029     jit.returnInt32(SpecializedThunkJIT::regT1);
    1030    
    1031     notKey.link(&jit);
    1032    
     1025    if (kind == ArrayIterateKey) {
     1026        jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
     1027        jit.returnInt32(SpecializedThunkJIT::regT1);
     1028        return jit.finalize(vm->jitStubs->ctiNativeCall(vm), "array-iterator-next-key");
     1029       
     1030    }
     1031    ASSERT(kind == ArrayIterateValue);
    10331032   
    10341033    // Okay, now we're returning a value so make sure we're inside the vector size
     
    10781077    jit.returnDouble(SpecializedThunkJIT::fpRegT0);
    10791078   
    1080     return jit.finalize(vm->jitStubs->ctiNativeCall(vm), "array-iterator-next");
     1079    return jit.finalize(vm->jitStubs->ctiNativeCall(vm), "array-iterator-next-value");
     1080}
     1081
     1082MacroAssemblerCodeRef arrayIteratorNextKeyThunkGenerator(VM* vm)
     1083{
     1084    return arrayIteratorNextThunkGenerator(vm, ArrayIterateKey);
     1085}
     1086
     1087MacroAssemblerCodeRef arrayIteratorNextValueThunkGenerator(VM* vm)
     1088{
     1089    return arrayIteratorNextThunkGenerator(vm, ArrayIterateValue);
    10811090}
    10821091   
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.h

    r157317 r157420  
    5959MacroAssemblerCodeRef powThunkGenerator(VM*);
    6060MacroAssemblerCodeRef imulThunkGenerator(VM*);
    61 MacroAssemblerCodeRef arrayIteratorNextThunkGenerator(VM*);
     61MacroAssemblerCodeRef arrayIteratorNextKeyThunkGenerator(VM*);
     62MacroAssemblerCodeRef arrayIteratorNextValueThunkGenerator(VM*);
    6263
    6364}
  • trunk/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp

    r157317 r157420  
    3737const ClassInfo ArrayIteratorPrototype::s_info = { "Array Iterator", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ArrayIteratorPrototype) };
    3838
    39 static EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeNext(ExecState*);
    4039static EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeIterate(ExecState*);
    4140
     
    4645    vm.prototypeMap.addPrototype(this);
    4746
    48     JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorPrototypeNext, DontEnum, 0, ArrayIteratorNextIntrinsic);
    49 
    5047    JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, arrayIteratorPrototypeIterate, DontEnum, 0);
    51 }
    52 
    53 static EncodedJSValue createIteratorResult(CallFrame* callFrame, ArrayIterationKind kind, size_t index, JSValue result, bool done)
    54 {
    55     callFrame->setArgument(callFrame->argumentCount() - 1, jsBoolean(done));
    56     if (done)
    57         return JSValue::encode(callFrame->vm().iterationTerminator.get());
    58 
    59     switch (kind & ~ArrayIterateSparseTag) {
    60     case ArrayIterateKey:
    61         return JSValue::encode(jsNumber(index));
    62 
    63     case ArrayIterateValue:
    64         return JSValue::encode(result);
    65 
    66     case ArrayIterateKeyValue: {
    67         MarkedArgumentBuffer args;
    68         args.append(jsNumber(index));
    69         args.append(result);
    70         JSGlobalObject* globalObject = callFrame->callee()->globalObject();
    71         return JSValue::encode(constructArray(callFrame, 0, globalObject, args));
    72 
    73     }
    74     default:
    75         RELEASE_ASSERT_NOT_REACHED();
    76     }
    77     return JSValue::encode(JSValue());
    78 }
    79 
    80 EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeNext(CallFrame* callFrame)
    81 {
    82     JSArrayIterator* iterator = jsDynamicCast<JSArrayIterator*>(callFrame->thisValue());
    83     if (!iterator)
    84         throwTypeError(callFrame, ASCIILiteral("Cannot call ArrayIterator.next() on a non-ArrayIterator object"));
    85     JSObject* iteratedObject = iterator->iteratedObject();
    86     size_t index = iterator->nextIndex();
    87     ArrayIterationKind kind = iterator->iterationKind();
    88     JSValue jsLength = JSValue(iteratedObject).get(callFrame, callFrame->propertyNames().length);
    89     if (callFrame->hadException())
    90         return JSValue::encode(jsNull());
    91 
    92     size_t length = jsLength.toUInt32(callFrame);
    93     if (callFrame->hadException())
    94         return JSValue::encode(jsNull());
    95 
    96     if (index >= length) {
    97         iterator->finish();
    98         return createIteratorResult(callFrame, kind, index, jsUndefined(), true);
    99     }
    100     if (JSValue result = iteratedObject->tryGetIndexQuickly(index)) {
    101         iterator->setNextIndex(index + 1);
    102         return createIteratorResult(callFrame, kind, index, result, false);
    103     }
    104    
    105     JSValue result = jsUndefined();
    106     PropertySlot slot(iteratedObject);
    107     if (kind > ArrayIterateSparseTag) {
    108         // We assume that the indexed property will be an own property so cache the getOwnProperty
    109         // method locally
    110         auto getOwnPropertySlotByIndex = iteratedObject->methodTable()->getOwnPropertySlotByIndex;
    111         while (index < length) {
    112             if (getOwnPropertySlotByIndex(iteratedObject, callFrame, index, slot)) {
    113                 result = slot.getValue(callFrame, index);
    114                 break;
    115             }
    116             if (iteratedObject->getPropertySlot(callFrame, index, slot)) {
    117                 result = slot.getValue(callFrame, index);
    118                 break;
    119             }
    120             index++;
    121         }
    122     } else if (iteratedObject->getPropertySlot(callFrame, index, slot))
    123         result = slot.getValue(callFrame, index);
    124 
    125     if (index == length)
    126         iterator->finish();
    127     else
    128         iterator->setNextIndex(index + 1);
    129     return createIteratorResult(callFrame, kind, index, jsUndefined(), index == length);
    13048}
    13149
  • trunk/Source/JavaScriptCore/runtime/Intrinsic.h

    r157317 r157420  
    5050    StringPrototypeValueOfIntrinsic,
    5151    IMulIntrinsic,
    52     ArrayIteratorNextIntrinsic
     52    ArrayIteratorNextValueIntrinsic,
     53    ArrayIteratorNextKeyIntrinsic,
     54    ArrayIteratorNextGenericIntrinsic
    5355};
    5456
  • trunk/Source/JavaScriptCore/runtime/JSArrayIterator.cpp

    r157317 r157420  
    3535const ClassInfo JSArrayIterator::s_info = { "ArrayIterator", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSArrayIterator) };
    3636
    37 void JSArrayIterator::finishCreation(VM& vm, JSGlobalObject*, ArrayIterationKind kind, JSObject* iteratedObject)
     37static EncodedJSValue JSC_HOST_CALL arrayIteratorNextKey(ExecState*);
     38static EncodedJSValue JSC_HOST_CALL arrayIteratorNextValue(ExecState*);
     39static EncodedJSValue JSC_HOST_CALL arrayIteratorNextGeneric(ExecState*);
     40
     41void JSArrayIterator::finishCreation(VM& vm, JSGlobalObject* globalObject, ArrayIterationKind kind, JSObject* iteratedObject)
    3842{
    3943    Base::finishCreation(vm);
     44    ASSERT(inherits(info()));
    4045    m_iterationKind = kind;
    4146    m_iteratedObject.set(vm, this, iteratedObject);
     47    switch (kind) {
     48    case ArrayIterateKey:
     49        JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextKey, DontEnum, 0, ArrayIteratorNextKeyIntrinsic);
     50        break;
     51    case ArrayIterateValue:
     52        JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextValue, DontEnum, 0, ArrayIteratorNextValueIntrinsic);
     53        break;
     54    default:
     55        JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextGeneric, DontEnum, 0, ArrayIteratorNextGenericIntrinsic);
     56        break;
     57    }
     58
    4259}
    4360   
     
    5572}
    5673
     74static EncodedJSValue createIteratorResult(CallFrame* callFrame, ArrayIterationKind kind, size_t index, JSValue result, bool done)
     75{
     76    callFrame->setArgument(callFrame->argumentCount() - 1, jsBoolean(done));
     77    if (done)
     78        return JSValue::encode(callFrame->vm().iterationTerminator.get());
     79   
     80    switch (kind & ~ArrayIterateSparseTag) {
     81    case ArrayIterateKey:
     82        return JSValue::encode(jsNumber(index));
     83       
     84    case ArrayIterateValue:
     85        return JSValue::encode(result);
     86       
     87    case ArrayIterateKeyValue: {
     88        MarkedArgumentBuffer args;
     89        args.append(jsNumber(index));
     90        args.append(result);
     91        JSGlobalObject* globalObject = callFrame->callee()->globalObject();
     92        return JSValue::encode(constructArray(callFrame, 0, globalObject, args));
     93       
     94    }
     95    default:
     96        RELEASE_ASSERT_NOT_REACHED();
     97    }
     98    return JSValue::encode(JSValue());
    5799}
     100
     101static inline EncodedJSValue JSC_HOST_CALL arrayIteratorNext(CallFrame* callFrame)
     102{
     103    JSArrayIterator* iterator = jsDynamicCast<JSArrayIterator*>(callFrame->thisValue());
     104    if (!iterator)
     105        throwTypeError(callFrame, ASCIILiteral("Cannot call ArrayIterator.next() on a non-ArrayIterator object"));
     106    JSObject* iteratedObject = iterator->iteratedObject();
     107    size_t index = iterator->nextIndex();
     108    ArrayIterationKind kind = iterator->iterationKind();
     109    JSValue jsLength = JSValue(iteratedObject).get(callFrame, callFrame->propertyNames().length);
     110    if (callFrame->hadException())
     111        return JSValue::encode(jsNull());
     112   
     113    size_t length = jsLength.toUInt32(callFrame);
     114    if (callFrame->hadException())
     115        return JSValue::encode(jsNull());
     116   
     117    if (index >= length) {
     118        iterator->finish();
     119        return createIteratorResult(callFrame, kind, index, jsUndefined(), true);
     120    }
     121    if (JSValue result = iteratedObject->tryGetIndexQuickly(index)) {
     122        iterator->setNextIndex(index + 1);
     123        return createIteratorResult(callFrame, kind, index, result, false);
     124    }
     125   
     126    JSValue result = jsUndefined();
     127    PropertySlot slot(iteratedObject);
     128    if (kind > ArrayIterateSparseTag) {
     129        // We assume that the indexed property will be an own property so cache the getOwnProperty
     130        // method locally
     131        auto getOwnPropertySlotByIndex = iteratedObject->methodTable()->getOwnPropertySlotByIndex;
     132        while (index < length) {
     133            if (getOwnPropertySlotByIndex(iteratedObject, callFrame, index, slot)) {
     134                result = slot.getValue(callFrame, index);
     135                break;
     136            }
     137            if (iteratedObject->getPropertySlot(callFrame, index, slot)) {
     138                result = slot.getValue(callFrame, index);
     139                break;
     140            }
     141            index++;
     142        }
     143    } else if (iteratedObject->getPropertySlot(callFrame, index, slot))
     144        result = slot.getValue(callFrame, index);
     145   
     146    if (index == length)
     147        iterator->finish();
     148    else
     149        iterator->setNextIndex(index + 1);
     150    return createIteratorResult(callFrame, kind, index, jsUndefined(), index == length);
     151}
     152   
     153EncodedJSValue JSC_HOST_CALL arrayIteratorNextKey(CallFrame* callFrame)
     154{
     155    return arrayIteratorNext(callFrame);
     156}
     157   
     158EncodedJSValue JSC_HOST_CALL arrayIteratorNextValue(CallFrame* callFrame)
     159{
     160    return arrayIteratorNext(callFrame);
     161}
     162   
     163EncodedJSValue JSC_HOST_CALL arrayIteratorNextGeneric(CallFrame* callFrame)
     164{
     165    return arrayIteratorNext(callFrame);
     166}
     167
     168}
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r157317 r157420  
    426426    case IMulIntrinsic:
    427427        return imulThunkGenerator;
    428     case ArrayIteratorNextIntrinsic:
    429         return arrayIteratorNextThunkGenerator;
     428    case ArrayIteratorNextKeyIntrinsic:
     429        return arrayIteratorNextKeyThunkGenerator;
     430    case ArrayIteratorNextValueIntrinsic:
     431        return arrayIteratorNextValueThunkGenerator;
    430432    default:
    431433        return 0;
Note: See TracChangeset for help on using the changeset viewer.