Title: [221723] trunk/Source/_javascript_Core
Revision
221723
Author
[email protected]
Date
2017-09-07 01:14:30 -0700 (Thu, 07 Sep 2017)

Log Message

[JSC] Remove "malloc" and "free" from JSC/API
https://bugs.webkit.org/show_bug.cgi?id=176331

Reviewed by Keith Miller.

Remove "malloc" and "free" manual calls in JSC/API.

* API/JSValue.mm:
(createStructHandlerMap):
* API/JSWrapperMap.mm:
(parsePropertyAttributes):
(makeSetterName):
(copyPrototypeProperties):
Use RetainPtr<NSString> to keep NSString. We avoid repeated "char*" to "NSString" conversion.

* API/ObjcRuntimeExtras.h:
(adoptSystem):
Add adoptSystem to automate calling system free().

(protocolImplementsProtocol):
(forEachProtocolImplementingProtocol):
(forEachMethodInClass):
(forEachMethodInProtocol):
(forEachPropertyInProtocol):
(StringRange::StringRange):
(StringRange::operator const char* const):
(StringRange::get const):
Use CString for backend.

(StructBuffer::StructBuffer):
(StructBuffer::~StructBuffer):
(StringRange::~StringRange): Deleted.
Use fastAlignedMalloc/astAlignedFree to get aligned memory.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSValue.mm (221722 => 221723)


--- trunk/Source/_javascript_Core/API/JSValue.mm	2017-09-07 07:35:21 UTC (rev 221722)
+++ trunk/Source/_javascript_Core/API/JSValue.mm	2017-09-07 08:14:30 UTC (rev 221723)
@@ -1054,19 +1054,19 @@
             return;
         char idType[3];
         // Check 2nd argument type is "@"
-        char* secondType = method_copyArgumentType(method, 3);
-        if (strcmp(secondType, "@") != 0) {
-            free(secondType);
-            return;
+        {
+            auto secondType = adoptSystem<char[]>(method_copyArgumentType(method, 3));
+            if (strcmp(secondType.get(), "@") != 0)
+                return;
         }
-        free(secondType);
         // Check result type is also "@"
         method_getReturnType(method, idType, 3);
         if (strcmp(idType, "@") != 0)
             return;
-        char* type = method_copyArgumentType(method, 2);
-        structHandlers->add(StringImpl::create(type), (StructTagHandler){ selector, 0 });
-        free(type);
+        {
+            auto type = adoptSystem<char[]>(method_copyArgumentType(method, 2));
+            structHandlers->add(StringImpl::create(type.get()), (StructTagHandler) { selector, 0 });
+        }
     });
 
     // Step 2: find all to<Foo> instance methods in JSValue.
@@ -1081,10 +1081,8 @@
         if (method_getNumberOfArguments(method) != 2)
             return;
         // Try to find a matching valueWith<Foo>:context: method.
-        char* type = method_copyReturnType(method);
-
-        StructHandlers::iterator iter = structHandlers->find(type);
-        free(type);
+        auto type = adoptSystem<char[]>(method_copyReturnType(method));
+        StructHandlers::iterator iter = structHandlers->find(type.get());
         if (iter == structHandlers->end())
             return;
         StructTagHandler& handler = iter->value;

Modified: trunk/Source/_javascript_Core/API/JSWrapperMap.mm (221722 => 221723)


--- trunk/Source/_javascript_Core/API/JSWrapperMap.mm	2017-09-07 07:35:21 UTC (rev 221722)
+++ trunk/Source/_javascript_Core/API/JSWrapperMap.mm	2017-09-07 08:14:30 UTC (rev 221723)
@@ -91,7 +91,7 @@
         while ((c = *(input++)) == ':');
         // Copy the character, converting to upper case if necessary.
         // If the character we copy is '\0', then we're done!
-        if (!(*(output++) = toupper(c)))
+        if (!(*(output++) = toASCIIUpper(c)))
             goto done;
         // Loop over characters other than ':'.
         while ((c = *(input++)) != ':') {
@@ -260,19 +260,25 @@
     [renameMap release];
 }
 
-static bool parsePropertyAttributes(objc_property_t property, char*& getterName, char*& setterName)
+struct Property {
+    const char* name;
+    RetainPtr<NSString> getterName;
+    RetainPtr<NSString> setterName;
+};
+
+static bool parsePropertyAttributes(objc_property_t objcProperty, Property& property)
 {
     bool readonly = false;
     unsigned attributeCount;
-    objc_property_attribute_t* attributes = property_copyAttributeList(property, &attributeCount);
+    auto attributes = adoptSystem<objc_property_attribute_t[]>(property_copyAttributeList(objcProperty, &attributeCount));
     if (attributeCount) {
         for (unsigned i = 0; i < attributeCount; ++i) {
             switch (*(attributes[i].name)) {
             case 'G':
-                getterName = strdup(attributes[i].value);
+                property.getterName = @(attributes[i].value);
                 break;
             case 'S':
-                setterName = strdup(attributes[i].value);
+                property.setterName = @(attributes[i].value);
                 break;
             case 'R':
                 readonly = true;
@@ -281,33 +287,28 @@
                 break;
             }
         }
-        free(attributes);
     }
     return readonly;
 }
 
-static char* makeSetterName(const char* name)
+static RetainPtr<NSString> makeSetterName(const char* name)
 {
     size_t nameLength = strlen(name);
-    char* setterName = (char*)malloc(nameLength + 5); // "set" Name ":\0"
-    setterName[0] = 's';
-    setterName[1] = 'e';
-    setterName[2] = 't';
-    setterName[3] = toupper(*name);
-    memcpy(setterName + 4, name + 1, nameLength - 1);
-    setterName[nameLength + 3] = ':';
-    setterName[nameLength + 4] = '\0';
-    return setterName;
+    // "set" Name ":\0"  => nameLength + 5.
+    Vector<char, 128> buffer(nameLength + 5);
+    buffer[0] = 's';
+    buffer[1] = 'e';
+    buffer[2] = 't';
+    buffer[3] = toASCIIUpper(*name);
+    memcpy(buffer.data() + 4, name + 1, nameLength - 1);
+    buffer[nameLength + 3] = ':';
+    buffer[nameLength + 4] = '\0';
+    return @(buffer.data());
 }
 
 static void copyPrototypeProperties(JSContext *context, Class objcClass, Protocol *protocol, JSValue *prototypeValue)
 {
     // First gather propreties into this list, then handle the methods (capturing the accessor methods).
-    struct Property {
-        const char* name;
-        char* getterName;
-        char* setterName;
-    };
     __block Vector<Property> propertyList;
 
     // Map recording the methods used as getters/setters.
@@ -316,24 +317,23 @@
     // Useful value.
     JSValue *undefined = [JSValue valueWithUndefinedInContext:context];
 
-    forEachPropertyInProtocol(protocol, ^(objc_property_t property){
-        char* getterName = 0;
-        char* setterName = 0;
-        bool readonly = parsePropertyAttributes(property, getterName, setterName);
-        const char* name = property_getName(property);
+    forEachPropertyInProtocol(protocol, ^(objc_property_t objcProperty) {
+        const char* name = property_getName(objcProperty);
+        Property property { name, nullptr, nullptr };
+        bool readonly = parsePropertyAttributes(objcProperty, property);
 
-        // Add the names of the getter & setter methods to 
-        if (!getterName)
-            getterName = strdup(name);
-        accessorMethods[@(getterName)] = undefined;
+        // Add the names of the getter & setter methods to
+        if (!property.getterName)
+            property.getterName = @(name);
+        accessorMethods[property.getterName.get()] = undefined;
         if (!readonly) {
-            if (!setterName)
-                setterName = makeSetterName(name);
-            accessorMethods[@(setterName)] = undefined;
+            if (!property.setterName)
+                property.setterName = makeSetterName(name);
+            accessorMethods[property.setterName.get()] = undefined;
         }
 
         // Add the properties to a list.
-        propertyList.append((Property){ name, getterName, setterName });
+        propertyList.append(WTFMove(property));
     });
 
     // Copy methods to the prototype, capturing accessors in the accessorMethods map.
@@ -340,17 +340,13 @@
     copyMethodsToObject(context, objcClass, protocol, YES, prototypeValue, accessorMethods);
 
     // Iterate the propertyList & generate accessor properties.
-    for (size_t i = 0; i < propertyList.size(); ++i) {
-        Property& property = propertyList[i];
-
-        JSValue *getter = accessorMethods[@(property.getterName)];
-        free(property.getterName);
+    for (auto& property : propertyList) {
+        JSValue* getter = accessorMethods[property.getterName.get()];
         ASSERT(![getter isUndefined]);
 
-        JSValue *setter = undefined;
+        JSValue* setter = undefined;
         if (property.setterName) {
-            setter = accessorMethods[@(property.setterName)];
-            free(property.setterName);
+            setter = accessorMethods[property.setterName.get()];
             ASSERT(![setter isUndefined]);
         }
         

Modified: trunk/Source/_javascript_Core/API/ObjcRuntimeExtras.h (221722 => 221723)


--- trunk/Source/_javascript_Core/API/ObjcRuntimeExtras.h	2017-09-07 07:35:21 UTC (rev 221722)
+++ trunk/Source/_javascript_Core/API/ObjcRuntimeExtras.h	2017-09-07 08:14:30 UTC (rev 221723)
@@ -23,22 +23,28 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
+#import <memory>
 #import <objc/Protocol.h>
 #import <objc/runtime.h>
 #import <wtf/HashSet.h>
+#import <wtf/SystemFree.h>
 #import <wtf/Vector.h>
+#import <wtf/text/CString.h>
 
+template<typename T, typename U>
+inline std::unique_ptr<T, WTF::SystemFree<T>> adoptSystem(U value)
+{
+    return std::unique_ptr<T, WTF::SystemFree<T>>(value);
+}
+
 inline bool protocolImplementsProtocol(Protocol *candidate, Protocol *target)
 {
     unsigned protocolProtocolsCount;
-    Protocol ** protocolProtocols = protocol_copyProtocolList(candidate, &protocolProtocolsCount);
+    auto protocolProtocols = adoptSystem<Protocol*[]>(protocol_copyProtocolList(candidate, &protocolProtocolsCount));
     for (unsigned i = 0; i < protocolProtocolsCount; ++i) {
-        if (protocol_isEqual(protocolProtocols[i], target)) {
-            free(protocolProtocols);
+        if (protocol_isEqual(protocolProtocols[i], target))
             return true;
-        }
     }
-    free(protocolProtocols);
     return false;
 }
 
@@ -47,14 +53,15 @@
     ASSERT(cls);
     ASSERT(target);
 
-    Vector<Protocol *> worklist;
+    Vector<Protocol*> worklist;
     HashSet<void*> visited;
 
     // Initially fill the worklist with the Class's protocols.
-    unsigned protocolsCount;
-    Protocol ** protocols = class_copyProtocolList(cls, &protocolsCount);
-    worklist.append(protocols, protocolsCount);
-    free(protocols);
+    {
+        unsigned protocolsCount;
+        auto protocols = adoptSystem<Protocol*[]>(class_copyProtocolList(cls, &protocolsCount));
+        worklist.append(protocols.get(), protocolsCount);
+    }
 
     bool stop = false;
     while (!worklist.isEmpty()) {
@@ -73,9 +80,11 @@
         }
 
         // Add incorporated protocols to the worklist.
-        protocols = protocol_copyProtocolList(protocol, &protocolsCount);
-        worklist.append(protocols, protocolsCount);
-        free(protocols);
+        {
+            unsigned protocolsCount;
+            auto protocols = adoptSystem<Protocol*[]>(protocol_copyProtocolList(protocol, &protocolsCount));
+            worklist.append(protocols.get(), protocolsCount);
+        }
     }
 }
 
@@ -82,28 +91,25 @@
 inline void forEachMethodInClass(Class cls, void (^callback)(Method))
 {
     unsigned count;
-    Method* methods = class_copyMethodList(cls, &count);
+    auto methods = adoptSystem<Method[]>(class_copyMethodList(cls, &count));
     for (unsigned i = 0; i < count; ++i)
         callback(methods[i]);
-    free(methods);
 }
 
 inline void forEachMethodInProtocol(Protocol *protocol, BOOL isRequiredMethod, BOOL isInstanceMethod, void (^callback)(SEL, const char*))
 {
     unsigned count;
-    struct objc_method_description* methods = protocol_copyMethodDescriptionList(protocol, isRequiredMethod, isInstanceMethod, &count);
+    auto methods = adoptSystem<objc_method_description[]>(protocol_copyMethodDescriptionList(protocol, isRequiredMethod, isInstanceMethod, &count));
     for (unsigned i = 0; i < count; ++i)
         callback(methods[i].name, methods[i].types);
-    free(methods);
 }
 
 inline void forEachPropertyInProtocol(Protocol *protocol, void (^callback)(objc_property_t))
 {
     unsigned count;
-    objc_property_t* properties = protocol_copyPropertyList(protocol, &count);
+    auto properties = adoptSystem<objc_property_t[]>(protocol_copyPropertyList(protocol, &count));
     for (unsigned i = 0; i < count; ++i)
         callback(properties[i]);
-    free(properties);
 }
 
 template<char open, char close>
@@ -124,13 +130,14 @@
 class StringRange {
     WTF_MAKE_NONCOPYABLE(StringRange);
 public:
-    StringRange(const char* begin, const char* end) : m_ptr(strndup(begin, end - begin)) { }
-    ~StringRange() { free(m_ptr); }
-    operator const char*() const { return m_ptr; }
-    const char* get() const { return m_ptr; }
+    StringRange(const char* begin, const char* end)
+        : m_string(begin, end - begin)
+    { }
+    operator const char*() const { return m_string.data(); }
+    const char* get() const { return m_string.data(); }
 
 private:
-    char* m_ptr;
+    CString m_string;
 };
 
 class StructBuffer {
@@ -140,16 +147,13 @@
     {
         NSUInteger size, alignment;
         NSGetSizeAndAlignment(encodedType, &size, &alignment);
-        --alignment;
-        m_allocation = static_cast<char*>(malloc(size + alignment));
-        m_buffer = reinterpret_cast<char*>((reinterpret_cast<intptr_t>(m_allocation) + alignment) & ~alignment);
+        m_buffer = fastAlignedMalloc(alignment, size);
     }
 
-    ~StructBuffer() { free(m_allocation); }
+    ~StructBuffer() { fastAlignedFree(m_buffer); }
     operator void*() const { return m_buffer; }
 
 private:
-    void* m_allocation;
     void* m_buffer;
 };
 

Modified: trunk/Source/_javascript_Core/ChangeLog (221722 => 221723)


--- trunk/Source/_javascript_Core/ChangeLog	2017-09-07 07:35:21 UTC (rev 221722)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-09-07 08:14:30 UTC (rev 221723)
@@ -1,3 +1,39 @@
+2017-09-06  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Remove "malloc" and "free" from JSC/API
+        https://bugs.webkit.org/show_bug.cgi?id=176331
+
+        Reviewed by Keith Miller.
+
+        Remove "malloc" and "free" manual calls in JSC/API.
+
+        * API/JSValue.mm:
+        (createStructHandlerMap):
+        * API/JSWrapperMap.mm:
+        (parsePropertyAttributes):
+        (makeSetterName):
+        (copyPrototypeProperties):
+        Use RetainPtr<NSString> to keep NSString. We avoid repeated "char*" to "NSString" conversion.
+
+        * API/ObjcRuntimeExtras.h:
+        (adoptSystem):
+        Add adoptSystem to automate calling system free().
+
+        (protocolImplementsProtocol):
+        (forEachProtocolImplementingProtocol):
+        (forEachMethodInClass):
+        (forEachMethodInProtocol):
+        (forEachPropertyInProtocol):
+        (StringRange::StringRange):
+        (StringRange::operator const char* const):
+        (StringRange::get const):
+        Use CString for backend.
+
+        (StructBuffer::StructBuffer):
+        (StructBuffer::~StructBuffer):
+        (StringRange::~StringRange): Deleted.
+        Use fastAlignedMalloc/astAlignedFree to get aligned memory.
+
 2017-09-06  Mark Lam  <[email protected]>
 
         constructGenericTypedArrayViewWithArguments() is missing an exception check.
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to