diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/runtime/JSArrayIterator.cpp | |
parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSArrayIterator.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSArrayIterator.cpp | 139 |
1 files changed, 119 insertions, 20 deletions
diff --git a/Source/JavaScriptCore/runtime/JSArrayIterator.cpp b/Source/JavaScriptCore/runtime/JSArrayIterator.cpp index 0abc9d120..d506c4ebd 100644 --- a/Source/JavaScriptCore/runtime/JSArrayIterator.cpp +++ b/Source/JavaScriptCore/runtime/JSArrayIterator.cpp @@ -29,42 +29,141 @@ #include "JSCJSValueInlines.h" #include "JSCellInlines.h" #include "SlotVisitorInlines.h" -#include "StructureInlines.h" namespace JSC { -const ClassInfo JSArrayIterator::s_info = { "Array Iterator", &Base::s_info, 0, CREATE_METHOD_TABLE(JSArrayIterator) }; +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; + } - putDirect(vm, vm.propertyNames->iteratedObjectPrivateName, iteratedObject); - putDirect(vm, vm.propertyNames->arrayIteratorNextIndexPrivateName, jsNumber(0)); - putDirect(vm, vm.propertyNames->arrayIterationKindPrivateName, jsNumber(kind)); } - -ArrayIterationKind JSArrayIterator::kind(ExecState* exec) const + + +void JSArrayIterator::visitChildren(JSCell* cell, SlotVisitor& visitor) { - JSValue kindValue = getDirect(exec->vm(), exec->vm().propertyNames->arrayIterationKindPrivateName); - return static_cast<ArrayIterationKind>(kindValue.asInt32()); + JSArrayIterator* thisObject = jsCast<JSArrayIterator*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); + ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); + + Base::visitChildren(thisObject, visitor); + visitor.append(&thisObject->m_iteratedObject); + } -JSValue JSArrayIterator::iteratedValue(ExecState* exec) const +static EncodedJSValue createIteratorResult(CallFrame* callFrame, ArrayIterationKind kind, size_t index, JSValue result, bool done) { - return getDirect(exec->vm(), exec->vm().propertyNames->iteratedObjectPrivateName); + 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()); } -JSArrayIterator* JSArrayIterator::clone(ExecState* exec) +static inline EncodedJSValue JSC_HOST_CALL arrayIteratorNext(CallFrame* callFrame) { - VM& vm = exec->vm(); - JSValue iteratedObject = getDirect(vm, vm.propertyNames->iteratedObjectPrivateName); - JSValue nextIndex = getDirect(vm, vm.propertyNames->arrayIteratorNextIndexPrivateName); - - auto clone = JSArrayIterator::create(exec, exec->callee()->globalObject()->arrayIteratorStructure(), kind(exec), asObject(iteratedObject)); - clone->putDirect(vm, vm.propertyNames->arrayIteratorNextIndexPrivateName, nextIndex); - return clone; + JSArrayIterator* iterator = jsDynamicCast<JSArrayIterator*>(callFrame->thisValue()); + if (!iterator) { + ASSERT_NOT_REACHED(); + return JSValue::encode(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); } } |