Title: [157420] trunk/Source/_javascript_Core
Revision
157420
Author
[email protected]
Date
2013-10-14 14:08:37 -0700 (Mon, 14 Oct 2013)

Log 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):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (157419 => 157420)


--- trunk/Source/_javascript_Core/ChangeLog	2013-10-14 20:49:59 UTC (rev 157419)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-10-14 21:08:37 UTC (rev 157420)
@@ -1,3 +1,35 @@
+2013-10-11  Oliver Hunt  <[email protected]>
+
+        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):
+
 2013-10-11  Mark Hahnenberg  <[email protected]>
 
         llint_slow_path_put_by_id can deadlock on a ConcurrentJITLock

Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (157419 => 157420)


--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2013-10-14 20:49:59 UTC (rev 157419)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2013-10-14 21:08:37 UTC (rev 157420)
@@ -988,7 +988,7 @@
     return jit.finalize(vm->jitStubs->ctiNativeCall(vm), "imul");
 }
 
-MacroAssemblerCodeRef arrayIteratorNextThunkGenerator(VM* vm)
+static MacroAssemblerCodeRef arrayIteratorNextThunkGenerator(VM* vm, ArrayIterationKind kind)
 {
     typedef SpecializedThunkJIT::TrustedImm32 TrustedImm32;
     typedef SpecializedThunkJIT::TrustedImmPtr TrustedImmPtr;
@@ -1014,7 +1014,7 @@
     jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2);
     
     jit.and32(TrustedImm32(IndexingShapeMask), SpecializedThunkJIT::regT3);
-    
+
     Jump notDone = jit.branch32(SpecializedThunkJIT::Below, SpecializedThunkJIT::regT1, Address(SpecializedThunkJIT::regT2, Butterfly::offsetOfPublicLength()));
     // Return the termination signal to indicate that we've finished
     jit.move(TrustedImmPtr(vm->iterationTerminator.get()), SpecializedThunkJIT::regT0);
@@ -1022,15 +1022,14 @@
     
     notDone.link(&jit);
     
+    if (kind == ArrayIterateKey) {
+        jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
+        jit.returnInt32(SpecializedThunkJIT::regT1);
+        return jit.finalize(vm->jitStubs->ctiNativeCall(vm), "array-iterator-next-key");
+        
+    }
+    ASSERT(kind == ArrayIterateValue);
     
-    Jump notKey = jit.branch32(SpecializedThunkJIT::NotEqual, Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfIterationKind()), TrustedImm32(ArrayIterateKey));
-    // If we're doing key iteration we just need to increment m_nextIndex and return the current value
-    jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
-    jit.returnInt32(SpecializedThunkJIT::regT1);
-    
-    notKey.link(&jit);
-    
-    
     // Okay, now we're returning a value so make sure we're inside the vector size
     jit.appendFailure(jit.branch32(SpecializedThunkJIT::AboveOrEqual, SpecializedThunkJIT::regT1, Address(SpecializedThunkJIT::regT2, Butterfly::offsetOfVectorLength())));
     
@@ -1077,8 +1076,18 @@
     jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
     
-    return jit.finalize(vm->jitStubs->ctiNativeCall(vm), "array-iterator-next");
+    return jit.finalize(vm->jitStubs->ctiNativeCall(vm), "array-iterator-next-value");
 }
+
+MacroAssemblerCodeRef arrayIteratorNextKeyThunkGenerator(VM* vm)
+{
+    return arrayIteratorNextThunkGenerator(vm, ArrayIterateKey);
+}
+
+MacroAssemblerCodeRef arrayIteratorNextValueThunkGenerator(VM* vm)
+{
+    return arrayIteratorNextThunkGenerator(vm, ArrayIterateValue);
+}
     
 }
 

Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.h (157419 => 157420)


--- trunk/Source/_javascript_Core/jit/ThunkGenerators.h	2013-10-14 20:49:59 UTC (rev 157419)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.h	2013-10-14 21:08:37 UTC (rev 157420)
@@ -58,7 +58,8 @@
 MacroAssemblerCodeRef sqrtThunkGenerator(VM*);
 MacroAssemblerCodeRef powThunkGenerator(VM*);
 MacroAssemblerCodeRef imulThunkGenerator(VM*);
-MacroAssemblerCodeRef arrayIteratorNextThunkGenerator(VM*);
+MacroAssemblerCodeRef arrayIteratorNextKeyThunkGenerator(VM*);
+MacroAssemblerCodeRef arrayIteratorNextValueThunkGenerator(VM*);
 
 }
 #endif // ENABLE(JIT)

Modified: trunk/Source/_javascript_Core/runtime/ArrayIteratorPrototype.cpp (157419 => 157420)


--- trunk/Source/_javascript_Core/runtime/ArrayIteratorPrototype.cpp	2013-10-14 20:49:59 UTC (rev 157419)
+++ trunk/Source/_javascript_Core/runtime/ArrayIteratorPrototype.cpp	2013-10-14 21:08:37 UTC (rev 157420)
@@ -36,7 +36,6 @@
 
 const ClassInfo ArrayIteratorPrototype::s_info = { "Array Iterator", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ArrayIteratorPrototype) };
 
-static EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeNext(ExecState*);
 static EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeIterate(ExecState*);
 
 void ArrayIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
@@ -45,90 +44,9 @@
     ASSERT(inherits(info()));
     vm.prototypeMap.addPrototype(this);
 
-    JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorPrototypeNext, DontEnum, 0, ArrayIteratorNextIntrinsic);
-
     JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, arrayIteratorPrototypeIterate, DontEnum, 0);
 }
 
-static EncodedJSValue createIteratorResult(CallFrame* callFrame, ArrayIterationKind kind, size_t index, JSValue result, bool done)
-{
-    callFrame->setArgument(callFrame->argumentCount() - 1, jsBoolean(done));
-    if (done)
-        return JSValue::encode(callFrame->vm().iterationTerminator.get());
-
-    switch (kind & ~ArrayIterateSparseTag) {
-    case ArrayIterateKey:
-        return JSValue::encode(jsNumber(index));
-
-    case ArrayIterateValue:
-        return JSValue::encode(result);
-
-    case ArrayIterateKeyValue: {
-        MarkedArgumentBuffer args;
-        args.append(jsNumber(index));
-        args.append(result);
-        JSGlobalObject* globalObject = callFrame->callee()->globalObject();
-        return JSValue::encode(constructArray(callFrame, 0, globalObject, args));
-
-    }
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-    return JSValue::encode(JSValue());
-}
-
-EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeNext(CallFrame* callFrame)
-{
-    JSArrayIterator* iterator = jsDynamicCast<JSArrayIterator*>(callFrame->thisValue());
-    if (!iterator)
-        throwTypeError(callFrame, ASCIILiteral("Cannot call ArrayIterator.next() on a non-ArrayIterator object"));
-    JSObject* iteratedObject = iterator->iteratedObject();
-    size_t index = iterator->nextIndex();
-    ArrayIterationKind kind = iterator->iterationKind();
-    JSValue jsLength = JSValue(iteratedObject).get(callFrame, callFrame->propertyNames().length);
-    if (callFrame->hadException())
-        return JSValue::encode(jsNull());
-
-    size_t length = jsLength.toUInt32(callFrame);
-    if (callFrame->hadException())
-        return JSValue::encode(jsNull());
-
-    if (index >= length) {
-        iterator->finish();
-        return createIteratorResult(callFrame, kind, index, jsUndefined(), true);
-    }
-    if (JSValue result = iteratedObject->tryGetIndexQuickly(index)) {
-        iterator->setNextIndex(index + 1);
-        return createIteratorResult(callFrame, kind, index, result, false);
-    }
-    
-    JSValue result = jsUndefined();
-    PropertySlot slot(iteratedObject);
-    if (kind > ArrayIterateSparseTag) {
-        // We assume that the indexed property will be an own property so cache the getOwnProperty
-        // method locally
-        auto getOwnPropertySlotByIndex = iteratedObject->methodTable()->getOwnPropertySlotByIndex;
-        while (index < length) {
-            if (getOwnPropertySlotByIndex(iteratedObject, callFrame, index, slot)) {
-                result = slot.getValue(callFrame, index);
-                break;
-            }
-            if (iteratedObject->getPropertySlot(callFrame, index, slot)) {
-                result = slot.getValue(callFrame, index);
-                break;
-            }
-            index++;
-        }
-    } else if (iteratedObject->getPropertySlot(callFrame, index, slot))
-        result = slot.getValue(callFrame, index);
-
-    if (index == length)
-        iterator->finish();
-    else
-        iterator->setNextIndex(index + 1);
-    return createIteratorResult(callFrame, kind, index, jsUndefined(), index == length);
-}
-
 EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeIterate(CallFrame* callFrame)
 {
     return JSValue::encode(callFrame->thisValue());

Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (157419 => 157420)


--- trunk/Source/_javascript_Core/runtime/Intrinsic.h	2013-10-14 20:49:59 UTC (rev 157419)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h	2013-10-14 21:08:37 UTC (rev 157420)
@@ -49,7 +49,9 @@
     RegExpTestIntrinsic,
     StringPrototypeValueOfIntrinsic,
     IMulIntrinsic,
-    ArrayIteratorNextIntrinsic
+    ArrayIteratorNextValueIntrinsic,
+    ArrayIteratorNextKeyIntrinsic,
+    ArrayIteratorNextGenericIntrinsic
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSArrayIterator.cpp (157419 => 157420)


--- trunk/Source/_javascript_Core/runtime/JSArrayIterator.cpp	2013-10-14 20:49:59 UTC (rev 157419)
+++ trunk/Source/_javascript_Core/runtime/JSArrayIterator.cpp	2013-10-14 21:08:37 UTC (rev 157420)
@@ -34,11 +34,28 @@
 
 const ClassInfo JSArrayIterator::s_info = { "ArrayIterator", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSArrayIterator) };
 
-void JSArrayIterator::finishCreation(VM& vm, JSGlobalObject*, ArrayIterationKind kind, JSObject* iteratedObject)
+static EncodedJSValue JSC_HOST_CALL arrayIteratorNextKey(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayIteratorNextValue(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayIteratorNextGeneric(ExecState*);
+
+void JSArrayIterator::finishCreation(VM& vm, JSGlobalObject* globalObject, ArrayIterationKind kind, JSObject* iteratedObject)
 {
     Base::finishCreation(vm);
+    ASSERT(inherits(info()));
     m_iterationKind = kind;
     m_iteratedObject.set(vm, this, iteratedObject);
+    switch (kind) {
+    case ArrayIterateKey:
+        JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextKey, DontEnum, 0, ArrayIteratorNextKeyIntrinsic);
+        break;
+    case ArrayIterateValue:
+        JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextValue, DontEnum, 0, ArrayIteratorNextValueIntrinsic);
+        break;
+    default:
+        JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextGeneric, DontEnum, 0, ArrayIteratorNextGenericIntrinsic);
+        break;
+    }
+
 }
     
     
@@ -54,4 +71,98 @@
 
 }
 
+static EncodedJSValue createIteratorResult(CallFrame* callFrame, ArrayIterationKind kind, size_t index, JSValue result, bool done)
+{
+    callFrame->setArgument(callFrame->argumentCount() - 1, jsBoolean(done));
+    if (done)
+        return JSValue::encode(callFrame->vm().iterationTerminator.get());
+    
+    switch (kind & ~ArrayIterateSparseTag) {
+    case ArrayIterateKey:
+        return JSValue::encode(jsNumber(index));
+        
+    case ArrayIterateValue:
+        return JSValue::encode(result);
+        
+    case ArrayIterateKeyValue: {
+        MarkedArgumentBuffer args;
+        args.append(jsNumber(index));
+        args.append(result);
+        JSGlobalObject* globalObject = callFrame->callee()->globalObject();
+        return JSValue::encode(constructArray(callFrame, 0, globalObject, args));
+        
+    }
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+    return JSValue::encode(JSValue());
 }
+
+static inline EncodedJSValue JSC_HOST_CALL arrayIteratorNext(CallFrame* callFrame)
+{
+    JSArrayIterator* iterator = jsDynamicCast<JSArrayIterator*>(callFrame->thisValue());
+    if (!iterator)
+        throwTypeError(callFrame, ASCIILiteral("Cannot call ArrayIterator.next() on a non-ArrayIterator object"));
+    JSObject* iteratedObject = iterator->iteratedObject();
+    size_t index = iterator->nextIndex();
+    ArrayIterationKind kind = iterator->iterationKind();
+    JSValue jsLength = JSValue(iteratedObject).get(callFrame, callFrame->propertyNames().length);
+    if (callFrame->hadException())
+        return JSValue::encode(jsNull());
+    
+    size_t length = jsLength.toUInt32(callFrame);
+    if (callFrame->hadException())
+        return JSValue::encode(jsNull());
+    
+    if (index >= length) {
+        iterator->finish();
+        return createIteratorResult(callFrame, kind, index, jsUndefined(), true);
+    }
+    if (JSValue result = iteratedObject->tryGetIndexQuickly(index)) {
+        iterator->setNextIndex(index + 1);
+        return createIteratorResult(callFrame, kind, index, result, false);
+    }
+    
+    JSValue result = jsUndefined();
+    PropertySlot slot(iteratedObject);
+    if (kind > ArrayIterateSparseTag) {
+        // We assume that the indexed property will be an own property so cache the getOwnProperty
+        // method locally
+        auto getOwnPropertySlotByIndex = iteratedObject->methodTable()->getOwnPropertySlotByIndex;
+        while (index < length) {
+            if (getOwnPropertySlotByIndex(iteratedObject, callFrame, index, slot)) {
+                result = slot.getValue(callFrame, index);
+                break;
+            }
+            if (iteratedObject->getPropertySlot(callFrame, index, slot)) {
+                result = slot.getValue(callFrame, index);
+                break;
+            }
+            index++;
+        }
+    } else if (iteratedObject->getPropertySlot(callFrame, index, slot))
+        result = slot.getValue(callFrame, index);
+    
+    if (index == length)
+        iterator->finish();
+    else
+        iterator->setNextIndex(index + 1);
+    return createIteratorResult(callFrame, kind, index, jsUndefined(), index == length);
+}
+    
+EncodedJSValue JSC_HOST_CALL arrayIteratorNextKey(CallFrame* callFrame)
+{
+    return arrayIteratorNext(callFrame);
+}
+    
+EncodedJSValue JSC_HOST_CALL arrayIteratorNextValue(CallFrame* callFrame)
+{
+    return arrayIteratorNext(callFrame);
+}
+    
+EncodedJSValue JSC_HOST_CALL arrayIteratorNextGeneric(CallFrame* callFrame)
+{
+    return arrayIteratorNext(callFrame);
+}
+
+}

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (157419 => 157420)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2013-10-14 20:49:59 UTC (rev 157419)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2013-10-14 21:08:37 UTC (rev 157420)
@@ -425,8 +425,10 @@
         return logThunkGenerator;
     case IMulIntrinsic:
         return imulThunkGenerator;
-    case ArrayIteratorNextIntrinsic:
-        return arrayIteratorNextThunkGenerator;
+    case ArrayIteratorNextKeyIntrinsic:
+        return arrayIteratorNextKeyThunkGenerator;
+    case ArrayIteratorNextValueIntrinsic:
+        return arrayIteratorNextValueThunkGenerator;
     default:
         return 0;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to