put_by_val_direct need to check the property is index or not for using putDirect / putDirectIndex
https://bugs.webkit.org/show_bug.cgi?id=140426

Reviewed by Darin Adler.

In the put_by_val_direct operation, we use JSObject::putDirect.
However, it only accepts non-index property. For index property, we need to use JSObject::putDirectIndex.
This patch checks toString-ed Identifier is index or not to choose putDirect / putDirectIndex.

* dfg/DFGOperations.cpp:
(JSC::DFG::putByVal):
(JSC::DFG::operationPutByValInternal):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/Identifier.h:
(JSC::isIndex):
(JSC::parseIndex):
* tests/stress/dfg-put-by-val-direct-with-edge-numbers.js: Added.
(lookupWithKey):
(toStringThrowsError.toString):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@182452 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index a0726c1..ff16903 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -69,6 +69,7 @@
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
+    ASSERT(isIndex(index));
     if (direct) {
         RELEASE_ASSERT(baseValue.isObject());
         asObject(baseValue)->putDirectIndex(exec, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
@@ -99,6 +100,8 @@
     JSValue value = JSValue::decode(encodedValue);
 
     if (LIKELY(property.isUInt32())) {
+        // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
+        ASSERT(isIndex(property.asUInt32()));
         putByVal<strict, direct>(exec, baseValue, property.asUInt32(), value);
         return;
     }
@@ -106,7 +109,7 @@
     if (property.isDouble()) {
         double propertyAsDouble = property.asDouble();
         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
-        if (propertyAsDouble == propertyAsUInt32) {
+        if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) {
             putByVal<strict, direct>(exec, baseValue, propertyAsUInt32, value);
             return;
         }
@@ -114,14 +117,18 @@
 
     // Don't put to an object if toString throws an exception.
     auto propertyName = property.toPropertyKey(exec);
-    if (!vm->exception()) {
-        PutPropertySlot slot(baseValue, strict);
-        if (direct) {
-            RELEASE_ASSERT(baseValue.isObject());
+    if (vm->exception())
+        return;
+
+    PutPropertySlot slot(baseValue, strict);
+    if (direct) {
+        RELEASE_ASSERT(baseValue.isObject());
+        if (Optional<uint32_t> index = parseIndex(propertyName))
+            asObject(baseValue)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
+        else
             asObject(baseValue)->putDirect(*vm, propertyName, value, slot);
-        } else
-            baseValue.put(exec, propertyName, value, slot);
-    }
+    } else
+        baseValue.put(exec, propertyName, value, slot);
 }
 
 template<typename ViewClass>
@@ -285,7 +292,7 @@
         } else if (property.isDouble()) {
             double propertyAsDouble = property.asDouble();
             uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
-            if (propertyAsUInt32 == propertyAsDouble)
+            if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32))
                 return getByVal(exec, base, propertyAsUInt32);
         } else if (property.isString()) {
             Structure& structure = *base->structure(vm);