[test262] Fixing mapped arguments object property test case
https://bugs.webkit.org/show_bug.cgi?id=159398
Patch by Caio Lima <ticaiolima@gmail.com> on 2016-12-24
Reviewed by Saam Barati.
JSTests:
* stress/arguments-bizarre-behaviour-disable-enumerability.js:
* stress/arguments-define-property.js: Added.
(assert):
(testProperties):
* stress/arguments-non-configurable.js: Added.
(assert):
(tryChangeNonConfigurableDescriptor):
(set tryChangeNonConfigurableDescriptor):
(tryChangeWritableOfNonConfigurableDescriptor):
* test262.yaml:
Source/JavaScriptCore:
This patch changes GenericArguments' override mechanism to
implement corret behavior on ECMAScript test262 suite test cases of
mapped arguments object with non-configurable and non-writable
property. Also it is ensuring that arguments[i]
cannot be deleted when argument "i" is {configurable: false}.
The previous implementation is against to the specification for 2 reasons:
1. Every argument in arguments object are {writable: true} by default
(http://www.ecma-international.org/ecma-262/7.0/index.html#sec-createunmappedargumentsobject).
It means that we have to stop mapping a defined property index
if the new property descriptor contains writable (i.e writable is
present) and its value is false (also check
https://tc39.github.io/ecma262/#sec-arguments-exotic-objects-defineownproperty-p-desc).
Previous implementation considers {writable: false} if writable is
not present.
2. When a property is overriden, "delete" operation is always returning true. However
delete operations should follow the specification.
We created an auxilary boolean array named m_modifiedArgumentsDescriptor
to store which arguments[i] descriptor was changed from its default
property descriptor. This modification was necessary because m_overrides
was responsible to keep this information at the same time
of keeping information about arguments mapping. The problem of this apporach was
that we needed to call overridesArgument(i) as soon as the ith argument's property
descriptor was changed and it stops the argument's mapping as sideffect, producing
wrong behavior.
To keep tracking arguments mapping status, we renamed DirectArguments::m_overrides to
DirectArguments::m_mappedArguments and now we it is responsible to manage if an
argument[i] is mapped or not.
With these 2 structures, now it is possible to an argument[i] have its property
descriptor modified and don't stop the mapping as soon as it happens. One example
of that wrong behavior can be found on arguments-bizarre-behaviour-disable-enumerability
test case, that now is fixed by this new mechanism.
* bytecode/PolymorphicAccess.cpp:
(JSC::AccessCase::generateWithGuard):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments):
(JSC::DFG::SpeculativeJIT::compileGetArrayLength):
(JSC::DFG::SpeculativeJIT::compileCreateDirectArguments):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength):
(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateDirectArguments):
* jit/JITOperations.cpp:
(JSC::canAccessArgumentIndexQuickly):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emitDirectArgumentsGetByVal):
* runtime/DirectArguments.cpp:
(JSC::DirectArguments::estimatedSize):
(JSC::DirectArguments::visitChildren):
(JSC::DirectArguments::overrideThings):
(JSC::DirectArguments::overrideThingsIfNecessary):
(JSC::DirectArguments::unmapArgument):
(JSC::DirectArguments::copyToArguments):
(JSC::DirectArguments::overridesSize):
(JSC::DirectArguments::overrideArgument): Deleted.
* runtime/DirectArguments.h:
(JSC::DirectArguments::length):
(JSC::DirectArguments::isMappedArgument):
(JSC::DirectArguments::isMappedArgumentInDFG):
(JSC::DirectArguments::getIndexQuickly):
(JSC::DirectArguments::setIndexQuickly):
(JSC::DirectArguments::overrodeThings):
(JSC::DirectArguments::initModifiedArgumentsDescriptorIfNecessary):
(JSC::DirectArguments::setModifiedArgumentDescriptor):
(JSC::DirectArguments::isModifiedArgumentDescriptor):
(JSC::DirectArguments::offsetOfMappedArguments):
(JSC::DirectArguments::offsetOfModifiedArgumentsDescriptor):
(JSC::DirectArguments::canAccessIndexQuickly): Deleted.
(JSC::DirectArguments::canAccessArgumentIndexQuicklyInDFG): Deleted.
(JSC::DirectArguments::offsetOfOverrides): Deleted.
* runtime/GenericArguments.h:
* runtime/GenericArgumentsInlines.h:
(JSC::GenericArguments<Type>::visitChildren):
(JSC::GenericArguments<Type>::getOwnPropertySlot):
(JSC::GenericArguments<Type>::getOwnPropertySlotByIndex):
(JSC::GenericArguments<Type>::getOwnPropertyNames):
(JSC::GenericArguments<Type>::put):
(JSC::GenericArguments<Type>::putByIndex):
(JSC::GenericArguments<Type>::deleteProperty):
(JSC::GenericArguments<Type>::deletePropertyByIndex):
(JSC::GenericArguments<Type>::defineOwnProperty):
(JSC::GenericArguments<Type>::initModifiedArgumentsDescriptor):
(JSC::GenericArguments<Type>::initModifiedArgumentsDescriptorIfNecessary):
(JSC::GenericArguments<Type>::setModifiedArgumentDescriptor):
(JSC::GenericArguments<Type>::isModifiedArgumentDescriptor):
(JSC::GenericArguments<Type>::copyToArguments):
* runtime/ScopedArguments.cpp:
(JSC::ScopedArguments::visitChildren):
(JSC::ScopedArguments::unmapArgument):
(JSC::ScopedArguments::overrideArgument): Deleted.
* runtime/ScopedArguments.h:
(JSC::ScopedArguments::isMappedArgument):
(JSC::ScopedArguments::isMappedArgumentInDFG):
(JSC::ScopedArguments::getIndexQuickly):
(JSC::ScopedArguments::setIndexQuickly):
(JSC::ScopedArguments::initModifiedArgumentsDescriptorIfNecessary):
(JSC::ScopedArguments::setModifiedArgumentDescriptor):
(JSC::ScopedArguments::isModifiedArgumentDescriptor):
(JSC::ScopedArguments::canAccessIndexQuickly): Deleted.
(JSC::ScopedArguments::canAccessArgumentIndexQuicklyInDFG): Deleted.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@210146 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/ScopedArguments.h b/Source/JavaScriptCore/runtime/ScopedArguments.h
index 8f04624..da96005 100644
--- a/Source/JavaScriptCore/runtime/ScopedArguments.h
+++ b/Source/JavaScriptCore/runtime/ScopedArguments.h
@@ -70,7 +70,7 @@
return internalLength();
}
- bool canAccessIndexQuickly(uint32_t i) const
+ bool isMappedArgument(uint32_t i) const
{
if (i >= m_totalLength)
return false;
@@ -80,14 +80,14 @@
return !!overflowStorage()[i - namedLength].get();
}
- bool canAccessArgumentIndexQuicklyInDFG(uint32_t i) const
+ bool isMappedArgumentInDFG(uint32_t i) const
{
- return canAccessIndexQuickly(i);
+ return isMappedArgument(i);
}
JSValue getIndexQuickly(uint32_t i) const
{
- ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
+ ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
unsigned namedLength = m_table->length();
if (i < namedLength)
return m_scope->variableAt(m_table->get(i)).get();
@@ -96,7 +96,7 @@
void setIndexQuickly(VM& vm, uint32_t i, JSValue value)
{
- ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
+ ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
unsigned namedLength = m_table->length();
if (i < namedLength)
m_scope->variableAt(m_table->get(i)).set(vm, m_scope.get(), value);
@@ -108,12 +108,27 @@
{
return m_callee;
}
-
+
bool overrodeThings() const { return m_overrodeThings; }
void overrideThings(VM&);
void overrideThingsIfNecessary(VM&);
- void overrideArgument(VM&, uint32_t index);
+ void unmapArgument(VM&, uint32_t index);
+ void initModifiedArgumentsDescriptorIfNecessary(VM& vm)
+ {
+ GenericArguments<ScopedArguments>::initModifiedArgumentsDescriptorIfNecessary(vm, m_table->length());
+ }
+
+ void setModifiedArgumentDescriptor(VM& vm, unsigned index)
+ {
+ GenericArguments<ScopedArguments>::setModifiedArgumentDescriptor(vm, index, m_table->length());
+ }
+
+ bool isModifiedArgumentDescriptor(unsigned index)
+ {
+ return GenericArguments<ScopedArguments>::isModifiedArgumentDescriptor(index, m_table->length());
+ }
+
void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
DECLARE_INFO;