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;
}