Changeset 210146 in webkit
- Timestamp:
- Dec 24, 2016 1:26:22 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r210137 r210146 1 2016-12-24 Caio Lima <ticaiolima@gmail.com> 2 3 [test262] Fixing mapped arguments object property test case 4 https://bugs.webkit.org/show_bug.cgi?id=159398 5 6 Reviewed by Saam Barati. 7 8 * stress/arguments-bizarre-behaviour-disable-enumerability.js: 9 * stress/arguments-define-property.js: Added. 10 (assert): 11 (testProperties): 12 * stress/arguments-non-configurable.js: Added. 13 (assert): 14 (tryChangeNonConfigurableDescriptor): 15 (set tryChangeNonConfigurableDescriptor): 16 (tryChangeWritableOfNonConfigurableDescriptor): 17 * test262.yaml: 18 19 016-12-20 Caio Lima <ticaiolima@gmail.com> 20 21 [test262] Fixing mapped arguments object property test case 22 https://bugs.webkit.org/show_bug.cgi?id=159398 23 24 Reviewed by . 25 26 * stress/arguments-bizarre-behaviour-disable-enumerability.js: 27 * stress/arguments-define-property.js: Added. 28 (assert): 29 (testProperties): 30 * stress/arguments-non-configurable.js: Added. 31 (assert): 32 (tryChangeNonConfigurableDescriptor): 33 (set tryChangeNonConfigurableDescriptor): 34 (tryChangeWritableOfNonConfigurableDescriptor): 35 * test262.yaml: 36 1 37 2016-12-23 Keith Miller <keith_miller@apple.com> 2 38 -
trunk/JSTests/stress/arguments-bizarre-behaviour-disable-enumerability.js
r180564 r210146 25 25 throw new Error(); 26 26 27 // FIXME: This is totally weird! 28 // https://bugs.webkit.org/show_bug.cgi?id=141952 29 if (Object.getOwnPropertyDescriptor(result[2], 0).enumerable !== true) 27 if (Object.getOwnPropertyDescriptor(result[2], 0).enumerable === true) 30 28 throw new Error(); -
trunk/JSTests/test262.yaml
r208843 r210146 51365 51365 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51366 51366 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-2.js 51367 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51367 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51368 51368 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-3.js 51369 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51369 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51370 51370 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-4.js 51371 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51371 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51372 51372 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-1.js 51373 51373 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51374 51374 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-2.js 51375 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51375 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51376 51376 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-3.js 51377 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51377 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51378 51378 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-4.js 51379 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51379 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51380 51380 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-1.js 51381 51381 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] … … 51383 51383 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51384 51384 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-3.js 51385 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51385 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51386 51386 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-4.js 51387 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51387 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51388 51388 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-5.js 51389 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51389 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51390 51390 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-1.js 51391 51391 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51392 51392 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-2.js 51393 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51393 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51394 51394 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-3.js 51395 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51395 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51396 51396 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-4.js 51397 cmd: runTest262 : fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []51397 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] 51398 51398 - path: test262/test/language/arguments-object/mapped/mapped-arguments-nonwritable-nonconfigurable-1.js 51399 51399 cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [] -
trunk/Source/JavaScriptCore/ChangeLog
r210139 r210146 1 2016-12-24 Caio Lima <ticaiolima@gmail.com> 2 3 [test262] Fixing mapped arguments object property test case 4 https://bugs.webkit.org/show_bug.cgi?id=159398 5 6 Reviewed by Saam Barati. 7 8 This patch changes GenericArguments' override mechanism to 9 implement corret behavior on ECMAScript test262 suite test cases of 10 mapped arguments object with non-configurable and non-writable 11 property. Also it is ensuring that arguments[i] 12 cannot be deleted when argument "i" is {configurable: false}. 13 14 The previous implementation is against to the specification for 2 reasons: 15 16 1. Every argument in arguments object are {writable: true} by default 17 (http://www.ecma-international.org/ecma-262/7.0/index.html#sec-createunmappedargumentsobject). 18 It means that we have to stop mapping a defined property index 19 if the new property descriptor contains writable (i.e writable is 20 present) and its value is false (also check 21 https://tc39.github.io/ecma262/#sec-arguments-exotic-objects-defineownproperty-p-desc). 22 Previous implementation considers {writable: false} if writable is 23 not present. 24 25 2. When a property is overriden, "delete" operation is always returning true. However 26 delete operations should follow the specification. 27 28 We created an auxilary boolean array named m_modifiedArgumentsDescriptor 29 to store which arguments[i] descriptor was changed from its default 30 property descriptor. This modification was necessary because m_overrides 31 was responsible to keep this information at the same time 32 of keeping information about arguments mapping. The problem of this apporach was 33 that we needed to call overridesArgument(i) as soon as the ith argument's property 34 descriptor was changed and it stops the argument's mapping as sideffect, producing 35 wrong behavior. 36 To keep tracking arguments mapping status, we renamed DirectArguments::m_overrides to 37 DirectArguments::m_mappedArguments and now we it is responsible to manage if an 38 argument[i] is mapped or not. 39 With these 2 structures, now it is possible to an argument[i] have its property 40 descriptor modified and don't stop the mapping as soon as it happens. One example 41 of that wrong behavior can be found on arguments-bizarre-behaviour-disable-enumerability 42 test case, that now is fixed by this new mechanism. 43 44 * bytecode/PolymorphicAccess.cpp: 45 (JSC::AccessCase::generateWithGuard): 46 * dfg/DFGSpeculativeJIT.cpp: 47 (JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments): 48 (JSC::DFG::SpeculativeJIT::compileGetArrayLength): 49 (JSC::DFG::SpeculativeJIT::compileCreateDirectArguments): 50 * ftl/FTLAbstractHeapRepository.h: 51 * ftl/FTLLowerDFGToB3.cpp: 52 (JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength): 53 (JSC::FTL::DFG::LowerDFGToB3::compileGetByVal): 54 (JSC::FTL::DFG::LowerDFGToB3::compileCreateDirectArguments): 55 * jit/JITOperations.cpp: 56 (JSC::canAccessArgumentIndexQuickly): 57 * jit/JITPropertyAccess.cpp: 58 (JSC::JIT::emitDirectArgumentsGetByVal): 59 * runtime/DirectArguments.cpp: 60 (JSC::DirectArguments::estimatedSize): 61 (JSC::DirectArguments::visitChildren): 62 (JSC::DirectArguments::overrideThings): 63 (JSC::DirectArguments::overrideThingsIfNecessary): 64 (JSC::DirectArguments::unmapArgument): 65 (JSC::DirectArguments::copyToArguments): 66 (JSC::DirectArguments::overridesSize): 67 (JSC::DirectArguments::overrideArgument): Deleted. 68 * runtime/DirectArguments.h: 69 (JSC::DirectArguments::length): 70 (JSC::DirectArguments::isMappedArgument): 71 (JSC::DirectArguments::isMappedArgumentInDFG): 72 (JSC::DirectArguments::getIndexQuickly): 73 (JSC::DirectArguments::setIndexQuickly): 74 (JSC::DirectArguments::overrodeThings): 75 (JSC::DirectArguments::initModifiedArgumentsDescriptorIfNecessary): 76 (JSC::DirectArguments::setModifiedArgumentDescriptor): 77 (JSC::DirectArguments::isModifiedArgumentDescriptor): 78 (JSC::DirectArguments::offsetOfMappedArguments): 79 (JSC::DirectArguments::offsetOfModifiedArgumentsDescriptor): 80 (JSC::DirectArguments::canAccessIndexQuickly): Deleted. 81 (JSC::DirectArguments::canAccessArgumentIndexQuicklyInDFG): Deleted. 82 (JSC::DirectArguments::offsetOfOverrides): Deleted. 83 * runtime/GenericArguments.h: 84 * runtime/GenericArgumentsInlines.h: 85 (JSC::GenericArguments<Type>::visitChildren): 86 (JSC::GenericArguments<Type>::getOwnPropertySlot): 87 (JSC::GenericArguments<Type>::getOwnPropertySlotByIndex): 88 (JSC::GenericArguments<Type>::getOwnPropertyNames): 89 (JSC::GenericArguments<Type>::put): 90 (JSC::GenericArguments<Type>::putByIndex): 91 (JSC::GenericArguments<Type>::deleteProperty): 92 (JSC::GenericArguments<Type>::deletePropertyByIndex): 93 (JSC::GenericArguments<Type>::defineOwnProperty): 94 (JSC::GenericArguments<Type>::initModifiedArgumentsDescriptor): 95 (JSC::GenericArguments<Type>::initModifiedArgumentsDescriptorIfNecessary): 96 (JSC::GenericArguments<Type>::setModifiedArgumentDescriptor): 97 (JSC::GenericArguments<Type>::isModifiedArgumentDescriptor): 98 (JSC::GenericArguments<Type>::copyToArguments): 99 * runtime/ScopedArguments.cpp: 100 (JSC::ScopedArguments::visitChildren): 101 (JSC::ScopedArguments::unmapArgument): 102 (JSC::ScopedArguments::overrideArgument): Deleted. 103 * runtime/ScopedArguments.h: 104 (JSC::ScopedArguments::isMappedArgument): 105 (JSC::ScopedArguments::isMappedArgumentInDFG): 106 (JSC::ScopedArguments::getIndexQuickly): 107 (JSC::ScopedArguments::setIndexQuickly): 108 (JSC::ScopedArguments::initModifiedArgumentsDescriptorIfNecessary): 109 (JSC::ScopedArguments::setModifiedArgumentDescriptor): 110 (JSC::ScopedArguments::isModifiedArgumentDescriptor): 111 (JSC::ScopedArguments::canAccessIndexQuickly): Deleted. 112 (JSC::ScopedArguments::canAccessArgumentIndexQuicklyInDFG): Deleted. 113 1 114 2016-12-23 Mark Lam <mark.lam@apple.com> 2 115 -
trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp
r209897 r210146 639 639 jit.branchTestPtr( 640 640 CCallHelpers::NonZero, 641 CCallHelpers::Address(baseGPR, DirectArguments::offsetOf Overrides())));641 CCallHelpers::Address(baseGPR, DirectArguments::offsetOfMappedArguments()))); 642 642 jit.load32( 643 643 CCallHelpers::Address(baseGPR, DirectArguments::offsetOfLength()), -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r210023 r210146 6119 6119 m_jit.branchTestPtr( 6120 6120 MacroAssembler::NonZero, 6121 MacroAssembler::Address(baseReg, DirectArguments::offsetOf Overrides())));6121 MacroAssembler::Address(baseReg, DirectArguments::offsetOfMappedArguments()))); 6122 6122 speculationCheck( 6123 6123 ExoticObjectMode, JSValueSource(), 0, … … 6293 6293 m_jit.branchTestPtr( 6294 6294 MacroAssembler::NonZero, 6295 MacroAssembler::Address(baseReg, DirectArguments::offsetOf Overrides())));6295 MacroAssembler::Address(baseReg, DirectArguments::offsetOfMappedArguments()))); 6296 6296 6297 6297 m_jit.load32( … … 6659 6659 6660 6660 m_jit.storePtr( 6661 TrustedImmPtr(0), JITCompiler::Address(resultGPR, DirectArguments::offsetOfOverrides())); 6661 TrustedImmPtr(0), JITCompiler::Address(resultGPR, DirectArguments::offsetOfMappedArguments())); 6662 6663 m_jit.storePtr( 6664 TrustedImmPtr(0), JITCompiler::Address(resultGPR, DirectArguments::offsetOfModifiedArgumentsDescriptor())); 6662 6665 6663 6666 if (lengthIsKnown) { -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
r209146 r210146 52 52 macro(DirectArguments_length, DirectArguments::offsetOfLength()) \ 53 53 macro(DirectArguments_minCapacity, DirectArguments::offsetOfMinCapacity()) \ 54 macro(DirectArguments_overrides, DirectArguments::offsetOfOverrides()) \ 54 macro(DirectArguments_mappedArguments, DirectArguments::offsetOfMappedArguments()) \ 55 macro(DirectArguments_modifiedArgumentsDescriptor, DirectArguments::offsetOfModifiedArgumentsDescriptor()) \ 55 56 macro(GetterSetter_getter, GetterSetter::offsetOfGetter()) \ 56 57 macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \ -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r209846 r210146 3141 3141 speculate( 3142 3142 ExoticObjectMode, noValue(), nullptr, 3143 m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_ overrides)));3143 m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_mappedArguments))); 3144 3144 setInt32(m_out.load32NonNegative(arguments, m_heaps.DirectArguments_length)); 3145 3145 return; … … 3293 3293 speculate( 3294 3294 ExoticObjectMode, noValue(), nullptr, 3295 m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_ overrides)));3295 m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_mappedArguments))); 3296 3296 speculate( 3297 3297 ExoticObjectMode, noValue(), nullptr, … … 4089 4089 m_out.store32(length.value, fastObject, m_heaps.DirectArguments_length); 4090 4090 m_out.store32(m_out.constInt32(minCapacity), fastObject, m_heaps.DirectArguments_minCapacity); 4091 m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_overrides); 4091 m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_mappedArguments); 4092 m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_modifiedArgumentsDescriptor); 4092 4093 4093 4094 ValueFromBlock fastResult = m_out.anchor(fastObject); -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r209764 r210146 1621 1621 case DirectArgumentsType: { 1622 1622 DirectArguments* directArguments = jsCast<DirectArguments*>(&object); 1623 if (directArguments-> canAccessArgumentIndexQuicklyInDFG(index))1623 if (directArguments->isMappedArgumentInDFG(index)) 1624 1624 return true; 1625 1625 break; … … 1627 1627 case ScopedArgumentsType: { 1628 1628 ScopedArguments* scopedArguments = jsCast<ScopedArguments*>(&object); 1629 if (scopedArguments-> canAccessArgumentIndexQuicklyInDFG(index))1629 if (scopedArguments->isMappedArgumentInDFG(index)) 1630 1630 return true; 1631 1631 break; -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r208761 r210146 1459 1459 1460 1460 slowCases.append(branch32(AboveOrEqual, property, Address(base, DirectArguments::offsetOfLength()))); 1461 slowCases.append(branchTestPtr(NonZero, Address(base, DirectArguments::offsetOf Overrides())));1461 slowCases.append(branchTestPtr(NonZero, Address(base, DirectArguments::offsetOfMappedArguments()))); 1462 1462 1463 1463 zeroExtend32ToPtr(property, scratch); -
trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp
r209897 r210146 87 87 { 88 88 DirectArguments* thisObject = jsCast<DirectArguments*>(cell); 89 size_t overridesSize = thisObject->m_overrides ? thisObject->overridesSize() : 0; 90 return Base::estimatedSize(cell) + overridesSize; 89 size_t mappedArgumentsSize = thisObject->m_mappedArguments ? thisObject->mappedArgumentsSize() * sizeof(bool) : 0; 90 size_t modifiedArgumentsSize = thisObject->m_modifiedArgumentsDescriptor ? thisObject->m_length * sizeof(bool) : 0; 91 return Base::estimatedSize(cell) + mappedArgumentsSize + modifiedArgumentsSize; 91 92 } 92 93 … … 96 97 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 97 98 Base::visitChildren(thisObject, visitor); 98 99 99 100 visitor.appendValues(thisObject->storage(), std::max(thisObject->m_length, thisObject->m_minCapacity)); 100 101 visitor.append(thisObject->m_callee); 101 102 102 if (bool* override = thisObject->m_overrides.get()) 103 visitor.markAuxiliary(override); 103 if (thisObject->m_mappedArguments) 104 visitor.markAuxiliary(thisObject->m_mappedArguments.get()); 105 GenericArguments<DirectArguments>::visitChildren(thisCell, visitor); 104 106 } 105 107 … … 111 113 void DirectArguments::overrideThings(VM& vm) 112 114 { 113 RELEASE_ASSERT(!m_ overrides);115 RELEASE_ASSERT(!m_mappedArguments); 114 116 115 117 putDirect(vm, vm.propertyNames->length, jsNumber(m_length), DontEnum); … … 117 119 putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayProtoValuesFunction(), DontEnum); 118 120 119 void* backingStore = vm.heap.tryAllocateAuxiliary(this, overridesSize());121 void* backingStore = vm.heap.tryAllocateAuxiliary(this, mappedArgumentsSize()); 120 122 RELEASE_ASSERT(backingStore); 121 123 bool* overrides = static_cast<bool*>(backingStore); 122 m_ overrides.set(vm, this, overrides);124 m_mappedArguments.set(vm, this, overrides); 123 125 for (unsigned i = m_length; i--;) 124 126 overrides[i] = false; … … 127 129 void DirectArguments::overrideThingsIfNecessary(VM& vm) 128 130 { 129 if (!m_ overrides)131 if (!m_mappedArguments) 130 132 overrideThings(vm); 131 133 } 132 134 133 void DirectArguments:: overrideArgument(VM& vm, unsigned index)135 void DirectArguments::unmapArgument(VM& vm, unsigned index) 134 136 { 135 137 overrideThingsIfNecessary(vm); 136 m_ overrides.get()[index] = true;138 m_mappedArguments.get()[index] = true; 137 139 } 138 140 139 141 void DirectArguments::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length) 140 142 { 141 if (!m_ overrides) {143 if (!m_mappedArguments) { 142 144 unsigned limit = std::min(length + offset, m_length); 143 145 unsigned i; … … 153 155 } 154 156 155 unsigned DirectArguments:: overridesSize()157 unsigned DirectArguments::mappedArgumentsSize() 156 158 { 157 159 // We always allocate something; in the relatively uncommon case of overriding an empty argument we 158 // still allocate so that m_ overrides is non-null. We use that to indicate that the other properties160 // still allocate so that m_mappedArguments is non-null. We use that to indicate that the other properties 159 161 // (length, etc) are overridden. 160 162 return WTF::roundUpToMultipleOf<8>(m_length ? m_length : 1); -
trunk/Source/JavaScriptCore/runtime/DirectArguments.h
r206525 r210146 67 67 uint32_t length(ExecState* exec) const 68 68 { 69 if (UNLIKELY(m_ overrides))69 if (UNLIKELY(m_mappedArguments)) 70 70 return get(exec, exec->propertyNames().length).toUInt32(exec); 71 71 return m_length; 72 72 } 73 73 74 bool canAccessIndexQuickly(uint32_t i) const74 bool isMappedArgument(uint32_t i) const 75 75 { 76 return i < m_length && (!m_ overrides || !m_overrides.get()[i]);76 return i < m_length && (!m_mappedArguments || !m_mappedArguments.get()[i]); 77 77 } 78 78 79 bool canAccessArgumentIndexQuicklyInDFG(uint32_t i) const79 bool isMappedArgumentInDFG(uint32_t i) const 80 80 { 81 81 return i < m_length && !overrodeThings(); … … 84 84 JSValue getIndexQuickly(uint32_t i) const 85 85 { 86 ASSERT_WITH_SECURITY_IMPLICATION( canAccessIndexQuickly(i));86 ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i)); 87 87 return const_cast<DirectArguments*>(this)->storage()[i].get(); 88 88 } … … 90 90 void setIndexQuickly(VM& vm, uint32_t i, JSValue value) 91 91 { 92 ASSERT_WITH_SECURITY_IMPLICATION( canAccessIndexQuickly(i));92 ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i)); 93 93 storage()[i].set(vm, this, value); 94 94 } … … 107 107 108 108 // Methods intended for use by the GenericArguments mixin. 109 bool overrodeThings() const { return !!m_ overrides; }109 bool overrodeThings() const { return !!m_mappedArguments; } 110 110 void overrideThings(VM&); 111 111 void overrideThingsIfNecessary(VM&); 112 void overrideArgument(VM&, unsigned index); 113 112 void unmapArgument(VM&, unsigned index); 113 114 void initModifiedArgumentsDescriptorIfNecessary(VM& vm) 115 { 116 GenericArguments<DirectArguments>::initModifiedArgumentsDescriptorIfNecessary(vm, m_length); 117 } 118 119 void setModifiedArgumentDescriptor(VM& vm, unsigned index) 120 { 121 GenericArguments<DirectArguments>::setModifiedArgumentDescriptor(vm, index, m_length); 122 } 123 124 bool isModifiedArgumentDescriptor(unsigned index) 125 { 126 return GenericArguments<DirectArguments>::isModifiedArgumentDescriptor(index, m_length); 127 } 128 114 129 void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length); 115 130 … … 121 136 static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(DirectArguments, m_length); } 122 137 static ptrdiff_t offsetOfMinCapacity() { return OBJECT_OFFSETOF(DirectArguments, m_minCapacity); } 123 static ptrdiff_t offsetOfOverrides() { return OBJECT_OFFSETOF(DirectArguments, m_overrides); } 138 static ptrdiff_t offsetOfMappedArguments() { return OBJECT_OFFSETOF(DirectArguments, m_mappedArguments); } 139 static ptrdiff_t offsetOfModifiedArgumentsDescriptor() { return OBJECT_OFFSETOF(DirectArguments, m_modifiedArgumentsDescriptor); } 124 140 125 141 static size_t storageOffset() … … 144 160 } 145 161 146 unsigned overridesSize();162 unsigned mappedArgumentsSize(); 147 163 148 164 WriteBarrier<JSFunction> m_callee; 149 165 uint32_t m_length; // Always the actual length of captured arguments and never what was stored into the length property. 150 166 uint32_t m_minCapacity; // The max of this and length determines the capacity of this object. It may be the actual capacity, or maybe something smaller. We arrange it this way to be kind to the JITs. 151 AuxiliaryBarrier<bool*> m_ overrides; // If non-null, it means that length, callee, and caller are fully materialized properties.167 AuxiliaryBarrier<bool*> m_mappedArguments; // If non-null, it means that length, callee, and caller are fully materialized properties. 152 168 }; 153 169 -
trunk/Source/JavaScriptCore/runtime/GenericArguments.h
r206525 r210146 44 44 } 45 45 46 static void visitChildren(JSCell*, SlotVisitor&); 46 47 static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); 47 48 static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); … … 53 54 static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); 54 55 56 void initModifiedArgumentsDescriptor(VM&, unsigned length); 57 void initModifiedArgumentsDescriptorIfNecessary(VM&, unsigned length); 58 void setModifiedArgumentDescriptor(VM&, unsigned index, unsigned length); 59 bool isModifiedArgumentDescriptor(unsigned index, unsigned length); 60 55 61 void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length); 62 63 AuxiliaryBarrier<bool*> m_modifiedArgumentsDescriptor; 56 64 }; 57 65 -
trunk/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h
r208985 r210146 32 32 33 33 template<typename Type> 34 void GenericArguments<Type>::visitChildren(JSCell* thisCell, SlotVisitor& visitor) 35 { 36 Type* thisObject = static_cast<Type*>(thisCell); 37 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 38 39 if (thisObject->m_modifiedArgumentsDescriptor) 40 visitor.markAuxiliary(thisObject->m_modifiedArgumentsDescriptor.get()); 41 } 42 43 template<typename Type> 34 44 bool GenericArguments<Type>::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot& slot) 35 45 { … … 53 63 54 64 std::optional<uint32_t> index = parseIndex(ident); 55 if (index && thisObject->canAccessIndexQuickly(index.value())) {65 if (index && !thisObject->isModifiedArgumentDescriptor(index.value()) && thisObject->isMappedArgument(index.value())) { 56 66 slot.setValue(thisObject, None, thisObject->getIndexQuickly(index.value())); 57 67 return true; 58 68 } 59 69 60 return Base::getOwnPropertySlot(thisObject, exec, ident, slot); 70 bool result = Base::getOwnPropertySlot(thisObject, exec, ident, slot); 71 72 if (index && thisObject->isMappedArgument(index.value())) 73 slot.setValue(thisObject, slot.attributes(), thisObject->getIndexQuickly(index.value())); 74 75 return result; 61 76 } 62 77 … … 66 81 Type* thisObject = jsCast<Type*>(object); 67 82 68 if (thisObject->canAccessIndexQuickly(index)) { 69 JSValue result = thisObject->getIndexQuickly(index); 70 slot.setValue(thisObject, None, result); 83 if (!thisObject->isModifiedArgumentDescriptor(index) && thisObject->isMappedArgument(index)) { 84 slot.setValue(thisObject, None, thisObject->getIndexQuickly(index)); 71 85 return true; 72 86 } 73 87 74 88 bool result = Base::getOwnPropertySlotByIndex(object, exec, index, slot); 89 90 if (thisObject->isMappedArgument(index)) 91 slot.setValue(thisObject, slot.attributes(), thisObject->getIndexQuickly(index)); 92 75 93 return result; 76 94 } … … 83 101 if (array.includeStringProperties()) { 84 102 for (unsigned i = 0; i < thisObject->internalLength(); ++i) { 85 if (!thisObject-> canAccessIndexQuickly(i))103 if (!thisObject->isMappedArgument(i)) 86 104 continue; 87 105 array.add(Identifier::from(exec, i)); … … 119 137 120 138 std::optional<uint32_t> index = parseIndex(ident); 121 if (index && thisObject-> canAccessIndexQuickly(index.value())) {139 if (index && thisObject->isMappedArgument(index.value())) { 122 140 thisObject->setIndexQuickly(vm, index.value(), value); 123 141 return true; … … 132 150 Type* thisObject = jsCast<Type*>(cell); 133 151 VM& vm = exec->vm(); 134 135 if (thisObject-> canAccessIndexQuickly(index)) {152 153 if (thisObject->isMappedArgument(index)) { 136 154 thisObject->setIndexQuickly(vm, index, value); 137 155 return true; … … 154 172 155 173 std::optional<uint32_t> index = parseIndex(ident); 156 if (index && thisObject->canAccessIndexQuickly(index.value())) { 157 thisObject->overrideArgument(vm, index.value()); 174 if (index && !thisObject->isModifiedArgumentDescriptor(index.value()) && thisObject->isMappedArgument(index.value())) { 175 thisObject->unmapArgument(vm, index.value()); 176 thisObject->setModifiedArgumentDescriptor(vm, index.value()); 158 177 return true; 159 178 } … … 167 186 Type* thisObject = jsCast<Type*>(cell); 168 187 VM& vm = exec->vm(); 169 170 if (thisObject->canAccessIndexQuickly(index)) { 171 thisObject->overrideArgument(vm, index); 172 return true; 173 } 174 188 189 if (!thisObject->isModifiedArgumentDescriptor(index) && thisObject->isMappedArgument(index)) { 190 thisObject->unmapArgument(vm, index); 191 thisObject->setModifiedArgumentDescriptor(vm, index); 192 return true; 193 } 194 175 195 return Base::deletePropertyByIndex(cell, exec, index); 176 196 } … … 188 208 else { 189 209 std::optional<uint32_t> optionalIndex = parseIndex(ident); 190 if (optionalIndex && thisObject->canAccessIndexQuickly(optionalIndex.value())) {210 if (optionalIndex) { 191 211 uint32_t index = optionalIndex.value(); 192 if (!descriptor.isAccessorDescriptor() ) {212 if (!descriptor.isAccessorDescriptor() && thisObject->isMappedArgument(optionalIndex.value())) { 193 213 // If the property is not deleted and we are using a non-accessor descriptor, then 194 214 // make sure that the aliased argument sees the value. … … 196 216 thisObject->setIndexQuickly(vm, index, descriptor.value()); 197 217 198 // If the property is not deleted and we are using a non-accessor, writable 199 // descriptor, then we are done. The argument continues to be aliased. Note that we 200 // ignore the request to change enumerability. We appear to have always done so, in 201 // cases where the argument was still aliased. 202 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141952 203 if (descriptor.writable()) 218 // If the property is not deleted and we are using a non-accessor, writable, 219 // configurable and enumerable descriptor and isn't modified, then we are done. 220 // The argument continues to be aliased. 221 if (descriptor.writable() && descriptor.configurable() && descriptor.enumerable() && !thisObject->isModifiedArgumentDescriptor(index)) 204 222 return true; 223 224 if (!thisObject->isModifiedArgumentDescriptor(index)) { 225 // If it is a new entry, we need to put direct to initialize argument[i] descriptor properly 226 JSValue value = thisObject->getIndexQuickly(index); 227 ASSERT(value); 228 object->putDirectMayBeIndex(exec, ident, value); 229 230 thisObject->setModifiedArgumentDescriptor(vm, index); 231 } 205 232 } 206 207 // If the property is a non-deleted argument, then move it into the base object and 208 // then delete it. 209 JSValue value = thisObject->getIndexQuickly(index); 210 ASSERT(value); 211 object->putDirectMayBeIndex(exec, ident, value); 212 thisObject->overrideArgument(vm, index); 213 } 214 } 215 233 234 if (thisObject->isMappedArgument(index)) { 235 // Just unmap arguments if its descriptor contains {writable: false}. 236 // Check https://tc39.github.io/ecma262/#sec-createunmappedargumentsobject 237 // and https://tc39.github.io/ecma262/#sec-createmappedargumentsobject to verify that all data 238 // property from arguments object are {writable: true, configurable: true, enumerable: true} by default 239 if ((descriptor.writablePresent() && !descriptor.writable()) || descriptor.isAccessorDescriptor()) { 240 if (!descriptor.isAccessorDescriptor()) { 241 JSValue value = thisObject->getIndexQuickly(index); 242 ASSERT(value); 243 object->putDirectMayBeIndex(exec, ident, value); 244 } 245 thisObject->unmapArgument(vm, index); 246 thisObject->setModifiedArgumentDescriptor(vm, index); 247 } 248 } 249 } 250 } 251 216 252 // Now just let the normal object machinery do its thing. 217 253 return Base::defineOwnProperty(object, exec, ident, descriptor, shouldThrow); … … 219 255 220 256 template<typename Type> 257 void GenericArguments<Type>::initModifiedArgumentsDescriptor(VM& vm, unsigned argsLength) 258 { 259 RELEASE_ASSERT(!m_modifiedArgumentsDescriptor); 260 261 if (argsLength) { 262 void* backingStore = vm.heap.tryAllocateAuxiliary(this, WTF::roundUpToMultipleOf<8>(argsLength)); 263 RELEASE_ASSERT(backingStore); 264 bool* modifiedArguments = static_cast<bool*>(backingStore); 265 m_modifiedArgumentsDescriptor.set(vm, this, modifiedArguments); 266 for (unsigned i = argsLength; i--;) 267 modifiedArguments[i] = false; 268 } 269 } 270 271 template<typename Type> 272 void GenericArguments<Type>::initModifiedArgumentsDescriptorIfNecessary(VM& vm, unsigned argsLength) 273 { 274 if (!m_modifiedArgumentsDescriptor) 275 initModifiedArgumentsDescriptor(vm, argsLength); 276 } 277 278 template<typename Type> 279 void GenericArguments<Type>::setModifiedArgumentDescriptor(VM& vm, unsigned index, unsigned length) 280 { 281 initModifiedArgumentsDescriptorIfNecessary(vm, length); 282 if (index < length) 283 m_modifiedArgumentsDescriptor.get()[index] = true; 284 } 285 286 template<typename Type> 287 bool GenericArguments<Type>::isModifiedArgumentDescriptor(unsigned index, unsigned length) 288 { 289 if (!m_modifiedArgumentsDescriptor) 290 return false; 291 if (index < length) 292 return m_modifiedArgumentsDescriptor.get()[index]; 293 return false; 294 } 295 296 template<typename Type> 221 297 void GenericArguments<Type>::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length) 222 298 { … … 226 302 Type* thisObject = static_cast<Type*>(this); 227 303 for (unsigned i = 0; i < length; ++i) { 228 if (thisObject-> canAccessIndexQuickly(i + offset))304 if (thisObject->isMappedArgument(i + offset)) 229 305 exec->r(firstElementDest + i) = thisObject->getIndexQuickly(i + offset); 230 306 else { -
trunk/Source/JavaScriptCore/runtime/ScopedArguments.cpp
r209897 r210146 112 112 thisObject->overflowStorage(), thisObject->m_totalLength - thisObject->m_table->length()); 113 113 } 114 115 GenericArguments<ScopedArguments>::visitChildren(cell, visitor); 114 116 } 115 117 … … 136 138 } 137 139 138 void ScopedArguments:: overrideArgument(VM& vm, uint32_t i)140 void ScopedArguments::unmapArgument(VM& vm, uint32_t i) 139 141 { 140 142 ASSERT_WITH_SECURITY_IMPLICATION(i < m_totalLength); -
trunk/Source/JavaScriptCore/runtime/ScopedArguments.h
r206525 r210146 71 71 } 72 72 73 bool canAccessIndexQuickly(uint32_t i) const73 bool isMappedArgument(uint32_t i) const 74 74 { 75 75 if (i >= m_totalLength) … … 81 81 } 82 82 83 bool canAccessArgumentIndexQuicklyInDFG(uint32_t i) const83 bool isMappedArgumentInDFG(uint32_t i) const 84 84 { 85 return canAccessIndexQuickly(i);85 return isMappedArgument(i); 86 86 } 87 87 88 88 JSValue getIndexQuickly(uint32_t i) const 89 89 { 90 ASSERT_WITH_SECURITY_IMPLICATION( canAccessIndexQuickly(i));90 ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i)); 91 91 unsigned namedLength = m_table->length(); 92 92 if (i < namedLength) … … 97 97 void setIndexQuickly(VM& vm, uint32_t i, JSValue value) 98 98 { 99 ASSERT_WITH_SECURITY_IMPLICATION( canAccessIndexQuickly(i));99 ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i)); 100 100 unsigned namedLength = m_table->length(); 101 101 if (i < namedLength) … … 109 109 return m_callee; 110 110 } 111 111 112 112 bool overrodeThings() const { return m_overrodeThings; } 113 113 void overrideThings(VM&); 114 114 void overrideThingsIfNecessary(VM&); 115 void overrideArgument(VM&, uint32_t index);115 void unmapArgument(VM&, uint32_t index); 116 116 117 void initModifiedArgumentsDescriptorIfNecessary(VM& vm) 118 { 119 GenericArguments<ScopedArguments>::initModifiedArgumentsDescriptorIfNecessary(vm, m_table->length()); 120 } 121 122 void setModifiedArgumentDescriptor(VM& vm, unsigned index) 123 { 124 GenericArguments<ScopedArguments>::setModifiedArgumentDescriptor(vm, index, m_table->length()); 125 } 126 127 bool isModifiedArgumentDescriptor(unsigned index) 128 { 129 return GenericArguments<ScopedArguments>::isModifiedArgumentDescriptor(index, m_table->length()); 130 } 131 117 132 void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length); 118 133
Note: See TracChangeset
for help on using the changeset viewer.