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.