]> git.saurik.com Git - cycript.git/commitdiff
Drastic performance enhancement by using a perfect hash instead of an sqlite3 database.
authorJay Freeman (saurik) <saurik@saurik.com>
Thu, 19 Nov 2009 00:36:56 +0000 (00:36 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Thu, 19 Nov 2009 00:36:56 +0000 (00:36 +0000)
Bridge.cpp [new file with mode: 0644]
Bridge.def
Bridge.sh [new file with mode: 0755]
Darwin-arm.mk
Execute.cpp
Execute.hpp [new file with mode: 0644]
Execute.mk
JavaScript.hpp
Library.cpp
ObjectiveC/Library.mm
iPhone.sh

diff --git a/Bridge.cpp b/Bridge.cpp
new file mode 100644 (file)
index 0000000..13770cd
--- /dev/null
@@ -0,0 +1,45 @@
+/* Cycript - Inlining/Optimizing JavaScript Compiler
+ * Copyright (C) 2009  Jay Freeman (saurik)
+*/
+
+/* Modified BSD License {{{ */
+/*
+ *        Redistribution and use in source and binary
+ * forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the
+ *    above copyright notice, this list of conditions
+ *    and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the
+ *    above copyright notice, this list of conditions
+ *    and the following disclaimer in the documentation
+ *    and/or other materials provided with the
+ *    distribution.
+ * 3. The name of the author may not be used to endorse
+ *    or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/* }}} */
+
+#include <cstdlib>
+#include "Bridge.hpp"
+
+extern "C" struct CYBridgeEntry *CYBridgeHash(const char *data, size_t size) {
+    return CYBridgeHash_(data, size);
+}
index a5852b937cdd49c2cde30b27bc2fc3335ae1de9f..b3792aa6a87e7b803677756e79585fe42efce8e5 100644 (file)
@@ -205,7 +205,7 @@ C UITableViewRowAnimationFade 0
 C UITableViewRowAnimationRight 1
 C UITableViewRowAnimationLeft 2
 C UITableViewRowAnimationTop 3
-C UITableViewRowAnimationTop 4
+C UITableViewRowAnimationBottom 4
 C UITableViewRowAnimationNone 5
 
 V UITableViewIndexSearch @
@@ -424,11 +424,6 @@ V kUIButtonBarButtonTitleVerticalHeight @
 V kUIButtonBarButtonTitleWidth @
 V kUIButtonBarButtonType @
 
-V UIKeyboardAnimationCurveUserInfoKey @
-V UIKeyboardAnimationDurationUserInfoKey @
-V UIKeyboardBoundsUserInfoKey @
-V UIKeyboardCenterBeginUserInfoKey @
-V UIKeyboardCenterEndUserInfoKey @
 V UIKeyboardRequiresInternationalKey @
 
 V UIKeyboardCandidateCorrectionDidChangeNotification @
@@ -678,7 +673,7 @@ V NSMigrationSourceObjectKey @
 V NSMigrationDestinationObjectKey @
 V NSMigrationEntityMappingKey @
 V NSMigrationPropertyMappingKey @
-V NSMigrationPropertyMappingKey @
+V NSMigrationEntityPolicyKey @
 
 C NSManagedObjectResultType 0x00
 C NSManagedObjectIDResultType 0x01
diff --git a/Bridge.sh b/Bridge.sh
new file mode 100755 (executable)
index 0000000..c847095
--- /dev/null
+++ b/Bridge.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+cat << EOF
+%{
+#include <cstring>
+#include "Execute.hpp"
+%}
+
+%language=ANSI-C
+
+%define lookup-function-name CYBridgeHash_
+%define slot-name name_
+
+%struct-type
+%omit-struct-type
+
+%pic
+
+struct CYBridgeEntry {
+    int name_;
+    const char *value_;
+};
+
+%%
+EOF
+
+grep '^[CFV]' "$1" | sed -e 's/^C/0/;s/^F/1/;s/^V/2/' | sed -e 's/"/\\"/g;s/^\([^ ]*\) \([^ ]*\) \(.*\)$/\1\2, "\3"/';
+grep '^[EST]' "$1" | sed -e 's/^S/3/;s/^T/4/;s/^E/5/' | sed -e 's/^5\(.*\)$/4\1 i/;s/"/\\"/g' | sed -e 's/^\([^ ]*\) \([^ ]*\) \(.*\)$/\1\2, "\3"/';
+grep '^:' "$1" | sed -e 's/^: \([^ ]*\) \(.*\)/6\1, "\2"/';
index 4b0cdfb49d88b8a34d7d4d7f5351d4efd3870894..cc970778984f81250b4e5913868d4fb9a78485a0 100644 (file)
@@ -4,7 +4,7 @@ all += #cyrver
 
 arch := iphoneos-arm
 console += -framework UIKit
-depends += apr-lib readline libffi mobilesubstrate sqlite3-lib
+depends += apr-lib readline libffi mobilesubstrate
 #library += -framework CFNetwork
 library += -framework WebCore
 # XXX: all Darwin, maybe all device, should have this
index 1382769ed08a6e10f6594c0460b6cfaeb3f96150..e43cce6e6b15c777db847a90f1e68accca7e2b88 100644 (file)
@@ -37,8 +37,6 @@
 */
 /* }}} */
 
-#include <sqlite3.h>
-
 #include "Internal.hpp"
 
 #include <dlfcn.h>
@@ -50,6 +48,7 @@
 #include "sig/ffi_type.hpp"
 
 #include "Pooling.hpp"
+#include "Execute.hpp"
 
 #include <sys/mman.h>
 
 #include "JavaScript.hpp"
 #include "String.hpp"
 
-char *sqlite3_column_pooled(apr_pool_t *pool, sqlite3_stmt *stmt, int n) {
-    if (const unsigned char *value = sqlite3_column_text(stmt, n))
-        return apr_pstrdup(pool, (const char *) value);
-    else return NULL;
-}
-
 struct CYHooks *hooks_;
 
 /* JavaScript Properties {{{ */
@@ -175,8 +168,6 @@ JSStringRef toJSON_s;
 
 static JSStringRef Result_;
 
-sqlite3 *Bridge_;
-
 void CYFinalize(JSObjectRef object) {
     delete reinterpret_cast<CYData *>(JSObjectGetPrivate(object));
 }
@@ -196,49 +187,27 @@ void Structor_(apr_pool_t *pool, sig::Type *&type) {
     if (type->primitive != sig::struct_P || type->name == NULL)
         return;
 
-    sqlite3_stmt *statement;
-
-    _sqlcall(sqlite3_prepare(Bridge_,
-        "select "
-            "\"bridge\".\"mode\", "
-            "\"bridge\".\"value\" "
-        "from \"bridge\" "
-        "where"
-            " \"bridge\".\"mode\" in (3, 4) and"
-            " \"bridge\".\"name\" = ?"
-        " limit 1"
-    , -1, &statement, NULL));
-
-    _sqlcall(sqlite3_bind_text(statement, 1, type->name, -1, SQLITE_STATIC));
-
-    int mode;
-    const char *value;
-
-    if (_sqlcall(sqlite3_step(statement)) == SQLITE_DONE) {
-        mode = -1;
-        value = NULL;
-    } else {
-        mode = sqlite3_column_int(statement, 0);
-        value = sqlite3_column_pooled(pool, statement, 1);
-    }
-
-    _sqlcall(sqlite3_finalize(statement));
-
-    switch (mode) {
-        default:
-            _assert(false);
-        case -1:
-            break;
-
-        case 3: {
-            sig::Parse(pool, &type->data.signature, value, &Structor_);
-        } break;
-
-        case 4: {
-            sig::Signature signature;
-            sig::Parse(pool, &signature, value, &Structor_);
-            type = signature.elements[0].type;
-        } break;
+    size_t length(strlen(type->name));
+    char keyed[length + 2];
+    memcpy(keyed + 1, type->name, length + 1);
+
+    static const char *modes = "34";
+    for (size_t i(0); i != 2; ++i) {
+        char mode(modes[i]);
+        keyed[0] = mode;
+
+        if (CYBridgeEntry *entry = CYBridgeHash(keyed, length + 1))
+            switch (mode) {
+                case '3':
+                    sig::Parse(pool, &type->data.signature, entry->value_, &Structor_);
+                break;
+
+                case '4': {
+                    sig::Signature signature;
+                    sig::Parse(pool, &signature, entry->value_, &Structor_);
+                    type = signature.elements[0].type;
+                } break;
+            }
     }
 }
 
@@ -968,61 +937,42 @@ static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSSt
         if (JSValueRef value = (*hooks_->RuntimeProperty)(context, name))
             return value;
 
-    sqlite3_stmt *statement;
-
-    _sqlcall(sqlite3_prepare(Bridge_,
-        "select "
-            "\"bridge\".\"mode\", "
-            "\"bridge\".\"value\" "
-        "from \"bridge\" "
-        "where"
-            " \"bridge\".\"name\" = ?"
-        " limit 1"
-    , -1, &statement, NULL));
-
-    _sqlcall(sqlite3_bind_text(statement, 1, name.data, name.size, SQLITE_STATIC));
-
-    int mode;
-    const char *value;
-
-    if (_sqlcall(sqlite3_step(statement)) == SQLITE_DONE) {
-        mode = -1;
-        value = NULL;
-    } else {
-        mode = sqlite3_column_int(statement, 0);
-        value = sqlite3_column_pooled(pool, statement, 1);
+    size_t length(name.size);
+    char keyed[length + 2];
+    memcpy(keyed + 1, name.data, length + 1);
+
+    static const char *modes = "0124";
+    for (size_t i(0); i != 4; ++i) {
+        char mode(modes[i]);
+        keyed[0] = mode;
+
+        if (CYBridgeEntry *entry = CYBridgeHash(keyed, length + 1))
+            switch (mode) {
+                case '0':
+                    return JSEvaluateScript(CYGetJSContext(context), CYJSString(entry->value_), NULL, NULL, 0, NULL);
+
+                case '1':
+                    if (void (*symbol)() = reinterpret_cast<void (*)()>(CYCastSymbol(name.data)))
+                        return CYMakeFunctor(context, symbol, entry->value_);
+                    else return NULL;
+
+                case '2':
+                    if (void *symbol = CYCastSymbol(name.data)) {
+                        // XXX: this is horrendously inefficient
+                        sig::Signature signature;
+                        sig::Parse(pool, &signature, entry->value_, &Structor_);
+                        ffi_cif cif;
+                        sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif);
+                        return CYFromFFI(context, signature.elements[0].type, cif.rtype, symbol);
+                    } else return NULL;
+
+                // XXX: implement case 3
+                case '4':
+                    return CYMakeType(context, entry->value_);
+            }
     }
 
-    _sqlcall(sqlite3_finalize(statement));
-
-    switch (mode) {
-        default:
-            CYThrow("invalid mode from bridge table: %d", mode);
-        case -1:
-            return NULL;
-
-        case 0:
-            return JSEvaluateScript(CYGetJSContext(context), CYJSString(value), NULL, NULL, 0, NULL);
-
-        case 1:
-            if (void (*symbol)() = reinterpret_cast<void (*)()>(CYCastSymbol(name.data)))
-                return CYMakeFunctor(context, symbol, value);
-            else return NULL;
-
-        case 2:
-            if (void *symbol = CYCastSymbol(name.data)) {
-                // XXX: this is horrendously inefficient
-                sig::Signature signature;
-                sig::Parse(pool, &signature, value, &Structor_);
-                ffi_cif cif;
-                sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif);
-                return CYFromFFI(context, signature.elements[0].type, cif.rtype, symbol);
-            } else return NULL;
-
-        // XXX: implement case 3
-        case 4:
-            return CYMakeType(context, value);
-    }
+    return NULL;
 } CYCatch }
 
 static JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1280,8 +1230,6 @@ void CYInitializeDynamic() {
 
     CYInitializeStatic();
 
-    _sqlcall(sqlite3_open("/usr/lib/libcycript.db", &Bridge_));
-
     JSObjectMakeArray$ = reinterpret_cast<JSObjectRef (*)(JSContextRef, size_t, const JSValueRef[], JSValueRef *)>(dlsym(RTLD_DEFAULT, "JSObjectMakeArray"));
 
     JSClassDefinition definition;
diff --git a/Execute.hpp b/Execute.hpp
new file mode 100644 (file)
index 0000000..6653c9b
--- /dev/null
@@ -0,0 +1,50 @@
+/* Cycript - Inlining/Optimizing JavaScript Compiler
+ * Copyright (C) 2009  Jay Freeman (saurik)
+*/
+
+/* Modified BSD License {{{ */
+/*
+ *        Redistribution and use in source and binary
+ * forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the
+ *    above copyright notice, this list of conditions
+ *    and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the
+ *    above copyright notice, this list of conditions
+ *    and the following disclaimer in the documentation
+ *    and/or other materials provided with the
+ *    distribution.
+ * 3. The name of the author may not be used to endorse
+ *    or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/* }}} */
+
+#ifndef CYCRIPT_EXECUTE_HPP
+#define CYCRIPT_EXECUTE_HPP
+
+struct CYBridgeEntry {
+    int name_;
+    const char *value_;
+};
+
+extern "C" struct CYBridgeEntry *CYBridgeHash(const char *data, size_t size);
+
+#endif/*CYCRIPT_EXECUTE_HPP*/
index 1102aa2ec5f11aea93111c2f3de0c701b743934f..86c106ca999d9fa4441a48fc2c24bd6c37f9bf31 100644 (file)
@@ -1,19 +1,14 @@
 CY_EXECUTE :=
 flags += -DCY_EXECUTE
 code += sig/ffi_type.o sig/parse.o sig/copy.o
-code += Execute.o
-library += $(apr) -lffi -lsqlite3
-all += libcycript.db
+code += Execute.o Bridge.o
+library += $(apr) -lffi
 filters += C
 
-extra::
-       cp -pR libcycript.db package/usr/lib
+Bridge.gperf: Bridge.def Bridge.sh
+       ./Bridge.sh Bridge.def >Bridge.gperf
 
-libcycript.db: Bridge.def
-       rm -f libcycript.db
-       { \
-           echo 'create table "bridge" ("mode" int not null, "name" text not null, "value" text null);'; \
-           grep '^[CFV]' Bridge.def | sed -e 's/^C/0/;s/^F/1/;s/^V/2/' | sed -e 's/"/\\"/g;s/^\([^ ]*\) \([^ ]*\) \(.*\)$$/insert into "bridge" ("mode", "name", "value") values (\1, '"'"'\2'"'"', '"'"'\3'"'"');/'; \
-           grep '^:' Bridge.def | sed -e 's/^: \([^ ]*\) \(.*\)/insert into "bridge" ("mode", "name", "value") values (-1, '"'"'\1'"'"', '"'"'\2'"'"');/'; \
-           grep '^[EST]' Bridge.def | sed -e 's/^S/3/;s/^T/4/;s/^E/5/' | sed -e 's/^5\(.*\)$$/4\1 i/' | sed -e 's/^\([^ ]*\) \([^ ]*\) \(.*\)$$/insert into "bridge" ("mode", "name", "value") values (\1, '"'"'\2'"'"', '"'"'\3'"'"');/'; \
-       } | tee libcycript.sql | sqlite3 libcycript.db
+Bridge.hpp: Bridge.gperf
+       gperf $< >$@
+
+Bridge.o: Bridge.hpp
index 9e9c85211df6648e070ebec9ce820506675eeb3f..a3e9f0a7d7021fac0725b1f2f54a692e512bbb15 100644 (file)
@@ -47,7 +47,6 @@
 #include <JavaScriptCore/JSValueRef.h>
 
 #include <ffi.h>
-#include <sqlite3.h>
 
 extern JSStringRef Array_s;
 extern JSStringRef cy_s;
@@ -134,8 +133,6 @@ struct CYHooks {
 
 extern struct CYHooks *hooks_;
 
-char *sqlite3_column_pooled(apr_pool_t *pool, sqlite3_stmt *stmt, int n);
-
 JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, sig::Type *type, ffi_type *ffi, JSObjectRef owner);
 
 void CYFinalize(JSObjectRef object);
index e6ab2a96595e0149ff92e16aa9437269b38707fd..2b85f96653cd67d353edc1d01c20038ce7b779f9 100644 (file)
@@ -59,6 +59,7 @@
 
 #include "Error.hpp"
 #include "String.hpp"
+#include "Execute.hpp"
 
 /* C Strings {{{ */
 template <typename Type_>
index 8642ba1d7d5e80550bcf64e7ec704363a927de77..5984ff6ac35466bae854567aff2ee5946f38e36c 100644 (file)
@@ -66,6 +66,7 @@
 #include "Error.hpp"
 #include "JavaScript.hpp"
 #include "String.hpp"
+#include "Bridge.hpp"
 
 #include <cmath>
 #include <map>
 
 JSValueRef CYSendMessage(apr_pool_t *pool, JSContextRef context, id self, Class super, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception);
 
-extern sqlite3 *Bridge_;
-
 /* Objective-C Pool Release {{{ */
 apr_status_t CYPoolRelease_(void *data) {
     id object(reinterpret_cast<id>(data));
@@ -1406,36 +1405,16 @@ static const char *CYPoolTypeEncoding(apr_pool_t *pool, JSContextRef context, SE
         return method_getTypeEncoding(method);
 
     const char *name(sel_getName(sel));
+    size_t length(strlen(name));
 
-    sqlite3_stmt *statement;
-
-    _sqlcall(sqlite3_prepare(Bridge_,
-        "select "
-            "\"bridge\".\"value\" "
-        "from \"bridge\" "
-        "where"
-            " \"bridge\".\"mode\" = -1 and"
-            " \"bridge\".\"name\" = ?"
-        " limit 1"
-    , -1, &statement, NULL));
-
-    _trace();
-    _sqlcall(sqlite3_bind_text(statement, 1, name, -1, SQLITE_STATIC));
-
-    const char *value;
-    if (_sqlcall(sqlite3_step(statement)) == SQLITE_DONE) {
-    _trace();
-        value = NULL;}
-    else {
-    _trace();
-        value = sqlite3_column_pooled(pool, statement, 0);
-        }
+    char keyed[length + 2];
+    keyed[0] = '6';
+    keyed[length + 1] = '\0';
+    memcpy(keyed + 1, name, length);
 
-    _sqlcall(sqlite3_finalize(statement));
+    if (CYBridgeEntry *entry = CYBridgeHash(keyed, length + 1))
+        return entry->value_;
 
-    if (value != NULL)
-        return value;
-_trace();
     return NULL;
 }
 
index 982a87033326eadb94a2fe2adad648fa5ff9a19b..bd1d514ec8a2fda7a763e8cb02630acf9c678466 100755 (executable)
--- a/iPhone.sh
+++ b/iPhone.sh
@@ -1,2 +1,2 @@
 #!/usr/bin/env bash
-PKG_ARCH=iphoneos-arm /apl/tel/exec.sh :apr-lib:libffi:readline:sqlite3 make -f iPhone.mk "$@"
+PKG_ARCH=iphoneos-arm /apl/tel/exec.sh :apr-lib:libffi:readline make -f iPhone.mk "$@"