Changeset 222421 in webkit for trunk/Source/JavaScriptCore
- Timestamp:
- Sep 22, 2017, 7:08:04 PM (8 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r222417 r222421 1 2017-09-22 Keith Miller <[email protected]> 2 3 Speculatively change iteration protocall to use the same next function 4 https://bugs.webkit.org/show_bug.cgi?id=175653 5 6 Reviewed by Saam Barati. 7 8 This patch speculatively makes a change to the iteration protocall to fetch the next 9 property immediately after calling the Symbol.iterator function. This is, in theory, 10 a breaking change, so we will see if this breaks things (most likely it won't as this 11 is a relatively subtle point). 12 13 See: https://github.com/tc39/ecma262/issues/976 14 15 * builtins/IteratorHelpers.js: 16 (performIteration): 17 * bytecompiler/BytecodeGenerator.cpp: 18 (JSC::BytecodeGenerator::emitEnumeration): 19 (JSC::BytecodeGenerator::emitIteratorNext): 20 (JSC::BytecodeGenerator::emitIteratorNextWithValue): 21 (JSC::BytecodeGenerator::emitDelegateYield): 22 * bytecompiler/BytecodeGenerator.h: 23 * bytecompiler/NodesCodegen.cpp: 24 (JSC::ArrayPatternNode::bindValue const): 25 * inspector/JSInjectedScriptHost.cpp: 26 (Inspector::JSInjectedScriptHost::iteratorEntries): 27 * runtime/IteratorOperations.cpp: 28 (JSC::iteratorNext): 29 (JSC::iteratorStep): 30 (JSC::iteratorClose): 31 (JSC::iteratorForIterable): 32 * runtime/IteratorOperations.h: 33 (JSC::forEachInIterable): 34 * runtime/JSGenericTypedArrayViewConstructorInlines.h: 35 (JSC::constructGenericTypedArrayViewFromIterator): 36 (JSC::constructGenericTypedArrayViewWithArguments): 37 1 38 2017-09-22 Fujii Hironori <[email protected]> 2 39 -
trunk/Source/JavaScriptCore/builtins/IteratorHelpers.js
r208637 r222421 34 34 35 35 let iterator = iterable.@iteratorSymbol(); 36 let next = iterator.next; 36 37 let item; 37 38 let index = 0; 38 39 while (true) { 39 item = iterator.next();40 item = next.@call(iterator); 40 41 if (!@isObject(item)) 41 42 @throwTypeError("Iterator result interface is not an object"); -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r221358 r222421 4316 4316 RefPtr<RegisterID> subject = newTemporary(); 4317 4317 emitNode(subject.get(), subjectNode); 4318 4319 4318 RefPtr<RegisterID> iterator = isForAwait ? emitGetAsyncIterator(subject.get(), node) : emitGetIterator(subject.get(), node); 4319 RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next); 4320 4320 4321 4321 Ref<Label> loopDone = newLabel(); … … 4423 4423 4424 4424 { 4425 emitIteratorNext(value.get(), iterator.get(), node, isForAwait ? EmitAwait::Yes : EmitAwait::No);4425 emitIteratorNext(value.get(), nextMethod.get(), iterator.get(), node, isForAwait ? EmitAwait::Yes : EmitAwait::No); 4426 4426 4427 4427 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), loopDone.get()); … … 4588 4588 } 4589 4589 4590 RegisterID* BytecodeGenerator::emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node, EmitAwait doEmitAwait)4590 RegisterID* BytecodeGenerator::emitIteratorNext(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, const ThrowableExpressionData* node, EmitAwait doEmitAwait) 4591 4591 { 4592 4592 { 4593 RefPtr<RegisterID> next = emitGetById(newTemporary(), iterator, propertyNames().next);4594 4593 CallArguments nextArguments(*this, nullptr); 4595 4594 emitMove(nextArguments.thisRegister(), iterator); 4596 emitCall(dst, next .get(), NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);4595 emitCall(dst, nextMethod, NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No); 4597 4596 4598 4597 if (doEmitAwait == EmitAwait::Yes) … … 4608 4607 } 4609 4608 4610 RegisterID* BytecodeGenerator::emitIteratorNextWithValue(RegisterID* dst, RegisterID* iterator, RegisterID* value, const ThrowableExpressionData* node)4609 RegisterID* BytecodeGenerator::emitIteratorNextWithValue(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, RegisterID* value, const ThrowableExpressionData* node) 4611 4610 { 4612 4611 { 4613 RefPtr<RegisterID> next = emitGetById(newTemporary(), iterator, propertyNames().next);4614 4612 CallArguments nextArguments(*this, nullptr, 1); 4615 4613 emitMove(nextArguments.thisRegister(), iterator); 4616 4614 emitMove(nextArguments.argumentRegister(0), value); 4617 emitCall(dst, next .get(), NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);4615 emitCall(dst, nextMethod, NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No); 4618 4616 } 4619 4617 … … 4917 4915 emitLabel(asyncIteratorNotFound.get()); 4918 4916 4919 RefPtr<RegisterID> commonIterator = emitGetById(newTemporary(), argument, propertyNames().iteratorSymbol); 4920 emitCallIterator(commonIterator.get(), argument, node); 4917 RefPtr<RegisterID> commonIterator = emitGetIterator(argument, node); 4921 4918 emitMove(iterator.get(), commonIterator.get()); 4922 4919 … … 4948 4945 { 4949 4946 RefPtr<RegisterID> iterator = parseMode() == SourceParseMode::AsyncGeneratorBodyMode ? emitGetAsyncIterator(argument, node) : emitGetIterator(argument, node); 4947 RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next); 4950 4948 4951 4949 Ref<Label> loopDone = newLabel(); … … 5045 5043 5046 5044 emitLabel(nextElement.get()); 5047 emitIteratorNextWithValue(value.get(), iterator.get(), value.get(), node);5045 emitIteratorNextWithValue(value.get(), nextMethod.get(), iterator.get(), value.get(), node); 5048 5046 5049 5047 emitLabel(branchOnResult.get()); -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r221622 r222421 781 781 void emitRequireObjectCoercible(RegisterID* value, const String& error); 782 782 783 RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node, JSC::EmitAwait = JSC::EmitAwait::No);784 RegisterID* emitIteratorNextWithValue(RegisterID* dst, RegisterID* iterator, RegisterID* value, const ThrowableExpressionData* node);783 RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, const ThrowableExpressionData* node, JSC::EmitAwait = JSC::EmitAwait::No); 784 RegisterID* emitIteratorNextWithValue(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, RegisterID* value, const ThrowableExpressionData* node); 785 785 void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node, EmitAwait = EmitAwait::No); 786 786 -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r222115 r222421 3945 3945 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No); 3946 3946 } 3947 RefPtr<RegisterID> nextMethod = generator.emitGetById(generator.newTemporary(), iterator.get(), generator.propertyNames().next); 3947 3948 3948 3949 if (m_targetPatterns.isEmpty()) { … … 3963 3964 3964 3965 RefPtr<RegisterID> value = generator.newTemporary(); 3965 generator.emitIteratorNext(value.get(), iterator.get(), this);3966 generator.emitIteratorNext(value.get(), nextMethod.get(), iterator.get(), this); 3966 3967 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done); 3967 3968 generator.emitJumpIfTrue(done.get(), iterationSkipped.get()); … … 3999 4000 4000 4001 RefPtr<RegisterID> value = generator.newTemporary(); 4001 generator.emitIteratorNext(value.get(), iterator.get(), this);4002 generator.emitIteratorNext(value.get(), nextMethod.get(), iterator.get(), this); 4002 4003 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done); 4003 4004 generator.emitJumpIfTrue(done.get(), iterationDone.get()); -
trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
r221822 r222421 587 587 return jsUndefined(); 588 588 589 IterationRecord iterationRecord = { iterator, iterator.get(exec, vm.propertyNames->next) }; 590 589 591 unsigned numberToFetch = 5; 590 592 JSValue numberToFetchArg = exec->argument(1); … … 598 600 599 601 for (unsigned i = 0; i < numberToFetch; ++i) { 600 JSValue next = iteratorStep(exec, iterat or);602 JSValue next = iteratorStep(exec, iterationRecord); 601 603 if (UNLIKELY(scope.exception()) || next.isFalse()) 602 604 break; … … 610 612 if (UNLIKELY(scope.exception())) { 611 613 scope.release(); 612 iteratorClose(exec, iterat or);614 iteratorClose(exec, iterationRecord); 613 615 break; 614 616 } -
trunk/Source/JavaScriptCore/runtime/IteratorOperations.cpp
r218794 r222421 37 37 namespace JSC { 38 38 39 JSValue iteratorNext(ExecState* exec, JSValue iterator, JSValue value)40 { 41 VM& vm = exec->vm(); 42 auto scope = DECLARE_THROW_SCOPE(vm); 43 44 JSValue nextFunction = iterator.get(exec, vm.propertyNames->next);45 RETURN_IF_EXCEPTION(scope, JSValue());39 JSValue iteratorNext(ExecState* exec, IterationRecord iterationRecord, JSValue argument) 40 { 41 VM& vm = exec->vm(); 42 auto scope = DECLARE_THROW_SCOPE(vm); 43 44 JSValue iterator = iterationRecord.iterator; 45 JSValue nextFunction = iterationRecord.nextMethod; 46 46 47 47 CallData nextFunctionCallData; … … 51 51 52 52 MarkedArgumentBuffer nextFunctionArguments; 53 if (! value.isEmpty())54 nextFunctionArguments.append( value);53 if (!argument.isEmpty()) 54 nextFunctionArguments.append(argument); 55 55 JSValue result = call(exec, nextFunction, nextFunctionCallType, nextFunctionCallData, iterator, nextFunctionArguments); 56 56 RETURN_IF_EXCEPTION(scope, JSValue()); … … 62 62 } 63 63 64 JSValue iteratorNext(ExecState* exec, JSValue iterator)65 {66 return iteratorNext(exec, iterator, JSValue());67 }68 69 64 JSValue iteratorValue(ExecState* exec, JSValue iterResult) 70 65 { … … 78 73 } 79 74 80 JSValue iteratorStep(ExecState* exec, JSValue iterator)81 { 82 VM& vm = exec->vm(); 83 auto scope = DECLARE_THROW_SCOPE(vm); 84 85 JSValue result = iteratorNext(exec, iterat or);75 JSValue iteratorStep(ExecState* exec, IterationRecord iterationRecord) 76 { 77 VM& vm = exec->vm(); 78 auto scope = DECLARE_THROW_SCOPE(vm); 79 80 JSValue result = iteratorNext(exec, iterationRecord); 86 81 RETURN_IF_EXCEPTION(scope, JSValue()); 87 82 bool done = iteratorComplete(exec, result); … … 92 87 } 93 88 94 void iteratorClose(ExecState* exec, JSValue iterator)89 void iteratorClose(ExecState* exec, IterationRecord iterationRecord) 95 90 { 96 91 VM& vm = exec->vm(); … … 103 98 catchScope.clearException(); 104 99 } 105 JSValue returnFunction = iterat or.get(exec, vm.propertyNames->returnKeyword);100 JSValue returnFunction = iterationRecord.iterator.get(exec, vm.propertyNames->returnKeyword); 106 101 RETURN_IF_EXCEPTION(throwScope, void()); 107 102 … … 123 118 124 119 MarkedArgumentBuffer returnFunctionArguments; 125 JSValue innerResult = call(exec, returnFunction, returnFunctionCallType, returnFunctionCallData, iterat or, returnFunctionArguments);120 JSValue innerResult = call(exec, returnFunction, returnFunctionCallType, returnFunctionCallData, iterationRecord.iterator, returnFunctionArguments); 126 121 127 122 if (exception) { … … 191 186 } 192 187 193 JSValueiteratorForIterable(ExecState& state, JSObject* object, JSValue iteratorMethod)188 IterationRecord iteratorForIterable(ExecState& state, JSObject* object, JSValue iteratorMethod) 194 189 { 195 190 VM& vm = state.vm(); … … 212 207 } 213 208 214 return iterator; 215 } 216 217 JSValue iteratorForIterable(ExecState* state, JSValue iterable) 209 JSValue nextMethod = iterator.getObject()->get(&state, vm.propertyNames->next); 210 RETURN_IF_EXCEPTION(scope, { }); 211 212 return { iterator, nextMethod }; 213 } 214 215 IterationRecord iteratorForIterable(ExecState* state, JSValue iterable) 218 216 { 219 217 VM& vm = state->vm(); … … 221 219 222 220 JSValue iteratorFunction = iterable.get(state, vm.propertyNames->iteratorSymbol); 223 RETURN_IF_EXCEPTION(scope, JSValue());221 RETURN_IF_EXCEPTION(scope, { }); 224 222 225 223 CallData iteratorFunctionCallData; … … 227 225 if (iteratorFunctionCallType == CallType::None) { 228 226 throwTypeError(state, scope); 229 return JSValue();227 return { }; 230 228 } 231 229 232 230 ArgList iteratorFunctionArguments; 233 231 JSValue iterator = call(state, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments); 234 RETURN_IF_EXCEPTION(scope, JSValue());232 RETURN_IF_EXCEPTION(scope, { }); 235 233 236 234 if (!iterator.isObject()) { 237 235 throwTypeError(state, scope); 238 return JSValue(); 239 } 240 241 return iterator; 236 return { }; 237 } 238 239 JSValue nextMethod = iterator.getObject()->get(state, vm.propertyNames->next); 240 RETURN_IF_EXCEPTION(scope, { }); 241 242 return { iterator, nextMethod }; 242 243 } 243 244 -
trunk/Source/JavaScriptCore/runtime/IteratorOperations.h
r217529 r222421 33 33 namespace JSC { 34 34 35 JSValue iteratorNext(ExecState*, JSValue iterator, JSValue); 36 JSValue iteratorNext(ExecState*, JSValue iterator); 37 JS_EXPORT_PRIVATE JSValue iteratorValue(ExecState*, JSValue iterator); 38 bool iteratorComplete(ExecState*, JSValue iterator); 39 JS_EXPORT_PRIVATE JSValue iteratorStep(ExecState*, JSValue iterator); 40 JS_EXPORT_PRIVATE void iteratorClose(ExecState*, JSValue iterator); 35 struct IterationRecord { 36 JSValue iterator; 37 JSValue nextMethod; 38 }; 39 40 JSValue iteratorNext(ExecState*, IterationRecord, JSValue argument = JSValue()); 41 JS_EXPORT_PRIVATE JSValue iteratorValue(ExecState*, JSValue iterResult); 42 bool iteratorComplete(ExecState*, JSValue iterResult); 43 JS_EXPORT_PRIVATE JSValue iteratorStep(ExecState*, IterationRecord); 44 JS_EXPORT_PRIVATE void iteratorClose(ExecState*, IterationRecord); 41 45 JS_EXPORT_PRIVATE JSObject* createIteratorResultObject(ExecState*, JSValue, bool done); 42 46 … … 44 48 45 49 JS_EXPORT_PRIVATE JSValue iteratorMethod(ExecState&, JSObject*); 46 JS_EXPORT_PRIVATE JSValue iteratorForIterable(ExecState&, JSObject*, JSValue iteratorMethod); 50 JS_EXPORT_PRIVATE IterationRecord iteratorForIterable(ExecState&, JSObject*, JSValue iteratorMethod); 51 JS_EXPORT_PRIVATE IterationRecord iteratorForIterable(ExecState*, JSValue iterable); 47 52 48 53 JS_EXPORT_PRIVATE JSValue iteratorMethod(ExecState&, JSObject*); 49 54 JS_EXPORT_PRIVATE bool hasIteratorMethod(ExecState&, JSValue); 50 51 JS_EXPORT_PRIVATE JSValue iteratorForIterable(ExecState*, JSValue iterable);52 55 53 56 template<typename CallBackType> … … 57 60 auto scope = DECLARE_THROW_SCOPE(vm); 58 61 59 JSValue iterator= iteratorForIterable(exec, iterable);62 IterationRecord iterationRecord = iteratorForIterable(exec, iterable); 60 63 RETURN_IF_EXCEPTION(scope, void()); 61 64 while (true) { 62 JSValue next = iteratorStep(exec, iterat or);65 JSValue next = iteratorStep(exec, iterationRecord); 63 66 if (UNLIKELY(scope.exception()) || next.isFalse()) 64 67 return; … … 70 73 if (UNLIKELY(scope.exception())) { 71 74 scope.release(); 72 iteratorClose(exec, iterat or);75 iteratorClose(exec, iterationRecord); 73 76 return; 74 77 } … … 82 85 auto scope = DECLARE_THROW_SCOPE(vm); 83 86 84 auto iterat or= iteratorForIterable(state, iterable, iteratorMethod);87 auto iterationRecord = iteratorForIterable(state, iterable, iteratorMethod); 85 88 RETURN_IF_EXCEPTION(scope, void()); 86 89 while (true) { 87 JSValue next = iteratorStep(&state, iterat or);90 JSValue next = iteratorStep(&state, iterationRecord); 88 91 if (UNLIKELY(scope.exception()) || next.isFalse()) 89 92 return; … … 95 98 if (UNLIKELY(scope.exception())) { 96 99 scope.release(); 97 iteratorClose(&state, iterat or);100 iteratorClose(&state, iterationRecord); 98 101 return; 99 102 } -
trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h
r221849 r222421 78 78 79 79 template<typename ViewClass> 80 inline JSObject* constructGenericTypedArrayViewFromIterator(ExecState* exec, Structure* structure, JSValue iterator) 81 { 82 VM& vm = exec->vm(); 83 auto scope = DECLARE_THROW_SCOPE(vm); 84 85 if (!iterator.isObject()) 86 return throwTypeError(exec, scope, ASCIILiteral("Symbol.Iterator for the first argument did not return an object.")); 80 inline JSObject* constructGenericTypedArrayViewFromIterator(ExecState* exec, Structure* structure, JSObject* iterable, JSValue iteratorMethod) 81 { 82 VM& vm = exec->vm(); 83 auto scope = DECLARE_THROW_SCOPE(vm); 87 84 88 85 MarkedArgumentBuffer storage; 89 while (true) { 90 JSValue next = iteratorStep(exec, iterator); 91 RETURN_IF_EXCEPTION(scope, nullptr); 92 93 if (next.isFalse()) 94 break; 95 96 JSValue nextItem = iteratorValue(exec, next); 97 RETURN_IF_EXCEPTION(scope, nullptr); 98 99 storage.append(nextItem); 100 } 86 forEachInIterable(*exec, iterable, iteratorMethod, [&] (VM&, ExecState&, JSValue value) { 87 storage.append(value); 88 }); 89 RETURN_IF_EXCEPTION(scope, nullptr); 101 90 102 91 ViewClass* result = ViewClass::createUninitialized(exec, structure, storage.size()); … … 173 162 || hasAnyArrayStorage(object->indexingType()))) { 174 163 175 CallData callData; 176 CallType callType = getCallData(iteratorFunc, callData); 177 if (callType == CallType::None) 178 return throwTypeError(exec, scope, ASCIILiteral("Symbol.Iterator for the first argument cannot be called.")); 179 180 ArgList arguments; 181 JSValue iterator = call(exec, iteratorFunc, callType, callData, object, arguments); 182 RETURN_IF_EXCEPTION(scope, nullptr); 183 184 scope.release(); 185 return constructGenericTypedArrayViewFromIterator<ViewClass>(exec, structure, iterator); 164 return constructGenericTypedArrayViewFromIterator<ViewClass>(exec, structure, object, iteratorFunc); 186 165 } 187 166
Note:
See TracChangeset
for help on using the changeset viewer.