Title: [210208] releases/WebKitGTK/webkit-2.14/Source/_javascript_Core
Revision
210208
Author
[email protected]
Date
2016-12-30 01:39:26 -0800 (Fri, 30 Dec 2016)

Log Message

Merge r208018 - JSFunction::put() should not allow caching of lazily reified properties.
https://bugs.webkit.org/show_bug.cgi?id=164081

Reviewed by Geoffrey Garen.

It is incorrect for JSFunction::put() to return PutPropertySlots that indicates
that its lazily reified properties (e.g. .caller, and .arguments) are cacheable.
The reason for this is:

1. Currently, a cacheable put may only consist of the following types of put
   operations:
   a. putting a new property at an offset in the object storage.
   b. changing the value of an existing property at an offset in the object storage.
   c. invoking the setter for a property at an offset in the object storage.

   Returning a PutPropertySlot that indicates the property is cacheable means that
   the property put must be one of the above operations.

   For lazily reified properties, JSFunction::put() implements complex conditional
   behavior that is different than the set of cacheable put operations above.
   Hence, it should not claim that the property put is cacheable.

2. Cacheable puts are cached on the original structure of the object before the
   put operation.

   Reifying a lazy property will trigger a structure transition.  Even though
   subsequent puts to such a property may be cacheable after the structure
   transition, it is incorrect to indicate that the property put is cacheable
   because the caching is on the original structure, not the new transitioned
   structure.

Also fixed some missing exception checks.

* jit/JITOperations.cpp:
* runtime/JSFunction.cpp:
(JSC::JSFunction::put):
(JSC::JSFunction::reifyLazyPropertyIfNeeded):
(JSC::JSFunction::reifyBoundNameIfNeeded):
* runtime/JSFunction.h:

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/ChangeLog (210207 => 210208)


--- releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/ChangeLog	2016-12-30 09:02:51 UTC (rev 210207)
+++ releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/ChangeLog	2016-12-30 09:39:26 UTC (rev 210208)
@@ -1,3 +1,45 @@
+2016-10-27  Mark Lam  <[email protected]>
+
+        JSFunction::put() should not allow caching of lazily reified properties.
+        https://bugs.webkit.org/show_bug.cgi?id=164081
+
+        Reviewed by Geoffrey Garen.
+
+        It is incorrect for JSFunction::put() to return PutPropertySlots that indicates
+        that its lazily reified properties (e.g. .caller, and .arguments) are cacheable.
+        The reason for this is:
+
+        1. Currently, a cacheable put may only consist of the following types of put
+           operations:
+           a. putting a new property at an offset in the object storage.
+           b. changing the value of an existing property at an offset in the object storage.
+           c. invoking the setter for a property at an offset in the object storage.
+
+           Returning a PutPropertySlot that indicates the property is cacheable means that
+           the property put must be one of the above operations.
+
+           For lazily reified properties, JSFunction::put() implements complex conditional
+           behavior that is different than the set of cacheable put operations above.
+           Hence, it should not claim that the property put is cacheable.
+    
+        2. Cacheable puts are cached on the original structure of the object before the
+           put operation.
+
+           Reifying a lazy property will trigger a structure transition.  Even though
+           subsequent puts to such a property may be cacheable after the structure
+           transition, it is incorrect to indicate that the property put is cacheable
+           because the caching is on the original structure, not the new transitioned
+           structure.
+
+        Also fixed some missing exception checks.
+
+        * jit/JITOperations.cpp:
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::put):
+        (JSC::JSFunction::reifyLazyPropertyIfNeeded):
+        (JSC::JSFunction::reifyBoundNameIfNeeded):
+        * runtime/JSFunction.h:
+
 2016-10-12  Joseph Pecoraro  <[email protected]>
 
         Web Inspector: Improve support for logging Proxy objects in console

Modified: releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/jit/JITOperations.cpp (210207 => 210208)


--- releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/jit/JITOperations.cpp	2016-12-30 09:02:51 UTC (rev 210207)
+++ releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/jit/JITOperations.cpp	2016-12-30 09:39:26 UTC (rev 210208)
@@ -201,6 +201,9 @@
     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
 
     baseValue.getPropertySlot(exec, ident, slot);
+    if (UNLIKELY(vm->exception()))
+        return encodedJSValue();
+
     if (stubInfo->considerCaching(baseValue.structureOrNull()) && !slot.isTaintedByOpaqueObject() && (slot.isCacheableValue() || slot.isCacheableGetter() || slot.isUnset()))
         repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Pure);
 
@@ -398,7 +401,9 @@
 
     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
     baseValue.putInline(exec, ident, value, slot);
-    
+    if (UNLIKELY(vm->exception()))
+        return;
+
     if (accessType != static_cast<AccessType>(stubInfo->accessType))
         return;
     
@@ -423,7 +428,9 @@
 
     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;    
     baseValue.putInline(exec, ident, value, slot);
-    
+    if (UNLIKELY(vm->exception()))
+        return;
+
     if (accessType != static_cast<AccessType>(stubInfo->accessType))
         return;
     

Modified: releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/runtime/JSFunction.cpp (210207 => 210208)


--- releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/runtime/JSFunction.cpp	2016-12-30 09:02:51 UTC (rev 210207)
+++ releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/runtime/JSFunction.cpp	2016-12-30 09:39:26 UTC (rev 210208)
@@ -437,23 +437,26 @@
         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
 
     if (thisObject->isHostOrBuiltinFunction()) {
-        thisObject->reifyBoundNameIfNeeded(vm, exec, propertyName);
+        LazyPropertyType propType = thisObject->reifyBoundNameIfNeeded(vm, exec, propertyName);
+        if (propType == LazyPropertyType::IsLazyProperty)
+            slot.disableCaching();
         return Base::put(thisObject, exec, propertyName, value, slot);
     }
 
     if (propertyName == vm.propertyNames->prototype) {
+        slot.disableCaching();
         // Make sure prototype has been reified, such that it can only be overwritten
         // following the rules set out in ECMA-262 8.12.9.
-        PropertySlot slot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
-        thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, propertyName, slot);
+        PropertySlot getSlot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
+        thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, propertyName, getSlot);
         if (thisObject->m_rareData)
             thisObject->m_rareData->clear("Store to prototype property of a function");
-        // Don't allow this to be cached, since a [[Put]] must clear m_rareData.
-        PutPropertySlot dontCache(thisObject);
         scope.release();
-        return Base::put(thisObject, exec, propertyName, value, dontCache);
+        return Base::put(thisObject, exec, propertyName, value, slot);
     }
+
     if (thisObject->jsExecutable()->isStrictMode() && (propertyName == vm.propertyNames->arguments || propertyName == vm.propertyNames->caller)) {
+        slot.disableCaching();
         // This will trigger the property to be reified, if this is not already the case!
         bool okay = thisObject->hasProperty(exec, propertyName);
         ASSERT_UNUSED(okay, okay);
@@ -461,11 +464,14 @@
         return Base::put(thisObject, exec, propertyName, value, slot);
     }
     if (propertyName == vm.propertyNames->arguments || propertyName == vm.propertyNames->caller) {
+        slot.disableCaching();
         if (slot.isStrictMode())
             throwTypeError(exec, scope, StrictModeReadonlyPropertyWriteError);
         return false;
     }
-    thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
+    LazyPropertyType propType = thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
+    if (propType == LazyPropertyType::IsLazyProperty)
+        slot.disableCaching();
     scope.release();
     return Base::put(thisObject, exec, propertyName, value, slot);
 }
@@ -671,25 +677,28 @@
     rareData->setHasReifiedName();
 }
 
-void JSFunction::reifyLazyPropertyIfNeeded(VM& vm, ExecState* exec, PropertyName propertyName)
+JSFunction::LazyPropertyType JSFunction::reifyLazyPropertyIfNeeded(VM& vm, ExecState* exec, PropertyName propertyName)
 {
     if (propertyName == vm.propertyNames->length) {
         if (!hasReifiedLength())
             reifyLength(vm);
+        return LazyPropertyType::IsLazyProperty;
     } else if (propertyName == vm.propertyNames->name) {
         if (!hasReifiedName())
             reifyName(vm, exec);
+        return LazyPropertyType::IsLazyProperty;
     }
+    return LazyPropertyType::NotLazyProperty;
 }
 
-void JSFunction::reifyBoundNameIfNeeded(VM& vm, ExecState* exec, PropertyName propertyName)
+JSFunction::LazyPropertyType JSFunction::reifyBoundNameIfNeeded(VM& vm, ExecState* exec, PropertyName propertyName)
 {
     const Identifier& nameIdent = vm.propertyNames->name;
     if (propertyName != nameIdent)
-        return;
+        return LazyPropertyType::NotLazyProperty;
 
     if (hasReifiedName())
-        return;
+        return LazyPropertyType::IsLazyProperty;
 
     if (this->inherits(JSBoundFunction::info())) {
         FunctionRareData* rareData = this->rareData(vm);
@@ -698,6 +707,7 @@
         putDirect(vm, nameIdent, jsString(exec, name), initialAttributes);
         rareData->setHasReifiedName();
     }
+    return LazyPropertyType::IsLazyProperty;
 }
 
 } // namespace JSC

Modified: releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/runtime/JSFunction.h (210207 => 210208)


--- releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/runtime/JSFunction.h	2016-12-30 09:02:51 UTC (rev 210207)
+++ releases/WebKitGTK/webkit-2.14/Source/_javascript_Core/runtime/JSFunction.h	2016-12-30 09:39:26 UTC (rev 210208)
@@ -191,10 +191,12 @@
     bool hasReifiedName() const;
     void reifyLength(VM&);
     void reifyName(VM&, ExecState*);
-    void reifyBoundNameIfNeeded(VM&, ExecState*, PropertyName);
     void reifyName(VM&, ExecState*, String name);
-    void reifyLazyPropertyIfNeeded(VM&, ExecState*, PropertyName propertyName);
 
+    enum class LazyPropertyType { NotLazyProperty, IsLazyProperty };
+    LazyPropertyType reifyLazyPropertyIfNeeded(VM&, ExecState*, PropertyName);
+    LazyPropertyType reifyBoundNameIfNeeded(VM&, ExecState*, PropertyName);
+
     friend class LLIntOffsetsExtractor;
 
     static EncodedJSValue argumentsGetter(ExecState*, EncodedJSValue, PropertyName);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to