Index: src/data_config.c
===================================================================
--- src/data_config.c	(revision 2805)
+++ src/data_config.c	(working copy)
@@ -28,8 +28,14 @@ static void data_config_free(data_unset *d) {
 	if (ds->string) buffer_free(ds->string);
 #ifdef HAVE_PCRE_H
 	if (ds->regex) pcre_free(ds->regex);
-	if (ds->regex_study) pcre_free(ds->regex_study);
+	if (ds->regex_study) {
+#ifdef PCRE_CONFIG_JIT
+		pcre_free_study(ds->regex_study);
+#else
+		pcre_free(ds->regex_study);
 #endif
+	}
+#endif
 
 	free(d);
 }
Index: src/base.h
===================================================================
--- src/base.h	(revision 2805)
+++ src/base.h	(working copy)
@@ -20,6 +20,10 @@
 # include <inttypes.h>
 #endif
 
+#ifdef HAVE_PCRE_H
+# include <pcre.h>
+#endif
+
 #include "buffer.h"
 #include "array.h"
 #include "chunk.h"
@@ -520,6 +524,10 @@ typedef struct {
 	} stat_cache_engine;
 	unsigned short enable_cores;
 	unsigned short reject_expect_100_with_417;
+
+#if defined(HAVE_PCRE_H) && defined(PCRE_CONFIG_JIT)
+	unsigned short use_pcre_jit;
+#endif
 } server_config;
 
 typedef struct {
@@ -651,10 +659,12 @@ typedef struct server {
 #ifdef USE_OPENSSL
 	int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq, off_t max_bytes);
 #endif
+#if defined(HAVE_PCRE_H) && defined(PCRE_CONFIG_JIT)
+	pcre_jit_stack  *jit_stack;
+#endif
 
 	uid_t uid;
 	gid_t gid;
 } server;
 
-
 #endif
Index: src/configfile.c
===================================================================
--- src/configfile.c	(revision 2805)
+++ src/configfile.c	(working copy)
@@ -105,7 +105,14 @@ static int config_insert(server *srv) {
 		{ "ssl.use-sslv3",               NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 62 */
 		{ "ssl.dh-file",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 63 */
 		{ "ssl.ec-curve",                NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 64 */
-
+#if defined(HAVE_PCRE_H) && defined(PCRE_CONFIG_JIT)
+		{ "server.use-pcre-jit",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 65 */
+#else
+		{ "server.use-pcre-jit",
+		  "Your system does not support PCRE JIT"
+		  "Please remove server.use-pcre-jit from your config.",
+		  T_CONFIG_UNSUPPORTED, T_CONFIG_SCOPE_UNSET }, /* 65 */
+#endif
 		{ "server.host",                 "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
 		{ "server.docroot",              "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
 		{ "server.virtual-root",         "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
@@ -150,6 +157,10 @@ static int config_insert(server *srv) {
 	cv[52].destination = &(srv->srvconf.reject_expect_100_with_417);
 	cv[55].destination = srv->srvconf.breakagelog_file;
 
+#if defined(HAVE_PCRE_H) && defined(PCRE_CONFIG_JIT)
+	cv[65].destination = &(srv->srvconf.use_pcre_jit);
+#endif
+
 	srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
 
 	assert(srv->config_storage);
@@ -207,7 +218,6 @@ static int config_insert(server *srv) {
 		cv[61].destination = &(s->set_v6only);
 		cv[54].destination = &(s->defer_accept);
 
-
 		/* 13 max-worker */
 		cv[14].destination = s->document_root;
 		cv[15].destination = &(s->force_lowercase_filenames);
Index: src/configparser.y
===================================================================
--- src/configparser.y	(revision 2805)
+++ src/configparser.y	(working copy)
@@ -471,6 +471,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop
 #ifdef HAVE_PCRE_H
       const char *errptr;
       int erroff, captures;
+      int study_options = 0;
 
       if (NULL == (dc->regex =
           pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) {
@@ -482,7 +483,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop
 
         ctx->ok = 0;
       } else if (NULL == (dc->regex_study =
-          pcre_study(dc->regex, 0, &errptr)) &&
+          pcre_study(dc->regex, study_options, &errptr)) &&
                  errptr != NULL) {
         fprintf(stderr, "studying regex failed: %s -> %s\n",
             rvalue->ptr, errptr);
Index: src/mod_ssi.c
===================================================================
--- src/mod_ssi.c	(revision 2805)
+++ src/mod_ssi.c	(working copy)
@@ -80,8 +80,15 @@ FREE_FUNC(mod_ssi_free) {
 	array_free(p->ssi_vars);
 	array_free(p->ssi_cgi_env);
 #ifdef HAVE_PCRE_H
-	pcre_free(p->ssi_regex);
+	if (p->ssi_regex) pcre_free(p->ssi_regex);
+	if (p->ssi_regex_extra) {
+#ifdef PCRE_CONFIG_JIT
+		pcre_free_study(p->ssi_regex_extra);
+#else
+		pcre_free(p->ssi_regex_extra);
 #endif
+	}
+#endif
 	buffer_free(p->timefmt);
 	buffer_free(p->stat_fn);
 
@@ -98,6 +105,7 @@ SETDEFAULTS_FUNC(mod_ssi_set_defaults) {
 #ifdef HAVE_PCRE_H
 	const char *errptr;
 	int erroff;
+	int study_options = 0;
 #endif
 
 	config_values_t cv[] = {
@@ -108,6 +116,11 @@ SETDEFAULTS_FUNC(mod_ssi_set_defaults) {
 
 	if (!p) return HANDLER_ERROR;
 
+#if defined(HAVE_PCRE_H) && defined(PCRE_CONFIG_JIT)
+	if (srv->srvconf.use_pcre_jit)
+		study_options = PCRE_STUDY_JIT_COMPILE;
+#endif
+
 	p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
 
 	for (i = 0; i < srv->config_context->used; i++) {
@@ -135,6 +148,17 @@ SETDEFAULTS_FUNC(mod_ssi_set_defaults) {
 				erroff, errptr);
 		return HANDLER_ERROR;
 	}
+	if (NULL == (p->ssi_regex_extra = pcre_study(p->ssi_regex, study_options, &errptr))) {
+		log_error_write(srv, __FILE__, __LINE__, "ss",
+				"ssi: pcre study ",
+				errptr);
+		return HANDLER_ERROR;
+	}
+#ifdef PCRE_CONFIG_JIT
+	if (srv->srvconf.use_pcre_jit)
+		pcre_assign_jit_stack(p->ssi_regex_extra, NULL, srv->jit_stack);
+#endif
+
 #else
 	log_error_write(srv, __FILE__, __LINE__, "s",
 			"mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
@@ -1041,7 +1065,7 @@ static int mod_ssi_handle_request(server *srv, con
 	 *
 	 */
 #ifdef HAVE_PCRE_H
-	for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
+	for (i = 0; (n = pcre_exec(p->ssi_regex, p->ssi_regex_extra, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
 		const char **l;
 		/* take everything from last offset to current match pos */
 
Index: src/mod_ssi.h
===================================================================
--- src/mod_ssi.h	(revision 2805)
+++ src/mod_ssi.h	(working copy)
@@ -23,6 +23,7 @@ typedef struct {
 
 #ifdef HAVE_PCRE_H
 	pcre *ssi_regex;
+	pcre_extra *ssi_regex_extra;
 #endif
 	buffer *timefmt;
 	int sizefmt;
Index: src/mod_dirlisting.c
===================================================================
--- src/mod_dirlisting.c	(revision 2805)
+++ src/mod_dirlisting.c	(working copy)
@@ -38,6 +38,7 @@
 typedef struct {
 #ifdef HAVE_PCRE_H
 	pcre *regex;
+	pcre_extra *regex_extra;
 #endif
 	buffer *string;
 } excludes;
@@ -86,12 +87,18 @@ static excludes_buffer *excludes_buffer_init(void)
 	return exb;
 }
 
-static int excludes_buffer_append(excludes_buffer *exb, buffer *string) {
+static int excludes_buffer_append(server *srv, excludes_buffer *exb, buffer *string) {
 #ifdef HAVE_PCRE_H
 	size_t i;
 	const char *errptr;
 	int erroff;
+	int study_options = 0;
 
+#ifdef PCRE_CONFIG_JIT
+	if (srv->srvconf.use_pcre_jit)
+		study_options = PCRE_STUDY_JIT_COMPILE;
+#endif
+
 	if (!string) return -1;
 
 	if (exb->size == 0) {
@@ -119,6 +126,15 @@ static excludes_buffer *excludes_buffer_init(void)
 		return -1;
 	}
 
+	if (NULL == (exb->ptr[exb->used]->regex_extra = pcre_study(exb->ptr[exb->used]->regex,
+						    study_options, &errptr))) {
+		return -1;
+	}
+#ifdef PCRE_CONFIG_JIT
+	if (srv->srvconf.use_pcre_jit)
+		pcre_assign_jit_stack(exb->ptr[exb->used]->regex_extra, NULL, srv->jit_stack);
+#endif
+
 	exb->ptr[exb->used]->string = buffer_init();
 	buffer_copy_string_buffer(exb->ptr[exb->used]->string, string);
 
@@ -139,6 +155,13 @@ static void excludes_buffer_free(excludes_buffer *
 
 	for (i = 0; i < exb->size; i++) {
 		if (exb->ptr[i]->regex) pcre_free(exb->ptr[i]->regex);
+		if (exb->ptr[i]->regex_extra) {
+#ifdef PCRE_CONFIG_JIT
+			pcre_free_study(exb->ptr[i]->regex_extra);
+#else
+			pcre_free(exb->ptr[i]->regex_extra);
+#endif
+		}
 		if (exb->ptr[i]->string) buffer_free(exb->ptr[i]->string);
 		free(exb->ptr[i]);
 	}
@@ -219,7 +242,7 @@ static int parse_config_entry(server *srv, plugin_
 				return HANDLER_ERROR;
 			}
 
-			if (0 != excludes_buffer_append(s->excludes,
+			if (0 != excludes_buffer_append(srv, s->excludes,
 				    ((data_string *)(da->value->data[j]))->value)) {
 #ifdef HAVE_PCRE_H
 				log_error_write(srv, __FILE__, __LINE__, "sb",
Index: src/mod_rewrite.c
===================================================================
--- src/mod_rewrite.c	(revision 2805)
+++ src/mod_rewrite.c	(working copy)
@@ -12,6 +12,7 @@
 #ifdef HAVE_PCRE_H
 typedef struct {
 	pcre *key;
+	pcre_extra *key_extra;
 
 	buffer *value;
 
@@ -68,11 +69,17 @@ static rewrite_rule_buffer *rewrite_rule_buffer_in
 	return kvb;
 }
 
-static int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
+static int rewrite_rule_buffer_append(server *srv, rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
 	size_t i;
 	const char *errptr;
 	int erroff;
+	int study_options = 0;
 
+#ifdef PCRE_CONFIG_JIT
+	if (srv->srvconf.use_pcre_jit)
+		study_options = PCRE_STUDY_JIT_COMPILE;
+#endif
+
 	if (!key) return -1;
 
 	if (kvb->size == 0) {
@@ -96,9 +103,18 @@ static rewrite_rule_buffer *rewrite_rule_buffer_in
 
 	if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
 							    0, &errptr, &erroff, NULL))) {
+		return -1;
+	}
 
+	if (NULL == (kvb->ptr[kvb->used]->key_extra = pcre_study(kvb->ptr[kvb->used]->key,
+							    study_options, &errptr)) &&
+	    errptr != NULL) {
 		return -1;
 	}
+#ifdef PCRE_CONFIG_JIT
+	if (srv->srvconf.use_pcre_jit)
+		pcre_assign_jit_stack(kvb->ptr[kvb->used]->key_extra, NULL, srv->jit_stack);
+#endif
 
 	kvb->ptr[kvb->used]->value = buffer_init();
 	buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
@@ -115,6 +131,13 @@ static void rewrite_rule_buffer_free(rewrite_rule_
 	for (i = 0; i < kvb->size; i++) {
 		if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
 		if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
+		if (kvb->ptr[i]->key_extra) {
+#ifdef PCRE_CONFIG_JIT
+			pcre_free_study(kvb->ptr[i]->key_extra);
+#else
+			pcre_free(kvb->ptr[i]->key_extra);
+#endif
+		}
 		free(kvb->ptr[i]);
 	}
 
@@ -185,7 +208,7 @@ static int parse_config_entry(server *srv, array *
 				return HANDLER_ERROR;
 			}
 
-			if (0 != rewrite_rule_buffer_append(kvb,
+			if (0 != rewrite_rule_buffer_append(srv, kvb,
 							    ((data_string *)(da->value->data[j]))->key,
 							    ((data_string *)(da->value->data[j]))->value,
 							    once)) {
@@ -364,6 +387,7 @@ static int process_rewrite_rules(server *srv, conn
 
 	for (i = 0; i < kvb->used; i++) {
 		pcre *match;
+		pcre_extra *extra;
 		const char *pattern;
 		size_t pattern_len;
 		int n;
@@ -372,10 +396,11 @@ static int process_rewrite_rules(server *srv, conn
 		int ovec[N * 3];
 
 		match       = rule->key;
+		extra       = rule->key_extra;
 		pattern     = rule->value->ptr;
 		pattern_len = rule->value->used - 1;
 
-		if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
+		if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
 			if (n != PCRE_ERROR_NOMATCH) {
 				log_error_write(srv, __FILE__, __LINE__, "sd",
 						"execution error while matching: ", n);
Index: src/mod_trigger_b4_dl.c
===================================================================
--- src/mod_trigger_b4_dl.c	(revision 2805)
+++ src/mod_trigger_b4_dl.c	(working copy)
@@ -42,6 +42,8 @@ typedef struct {
 #if defined(HAVE_PCRE_H)
 	pcre *trigger_regex;
 	pcre *download_regex;
+	pcre_extra *trigger_regex_extra;
+	pcre_extra *download_regex_extra;
 #endif
 #if defined(HAVE_GDBM_H)
 	GDBM_FILE db;
@@ -102,7 +104,21 @@ FREE_FUNC(mod_trigger_b4_dl_free) {
 #if defined(HAVE_PCRE_H)
 			if (s->trigger_regex) pcre_free(s->trigger_regex);
 			if (s->download_regex) pcre_free(s->download_regex);
+			if (s->trigger_regex_extra) {
+#ifdef PCRE_CONFIG_JIT
+				pcre_free_study(s->trigger_regex_extra);
+#else
+				pcre_free(s->trigger_regex_extra);
 #endif
+			}
+			if (s->download_regex_extra) {
+#ifdef PCRE_CONFIG_JIT
+				pcre_free_study(s->download_regex_extra);
+#else
+				pcre_free(s->download_regex_extra);
+#endif
+			}
+#endif
 #if defined(HAVE_GDBM_H)
 			if (s->db) gdbm_close(s->db);
 #endif
@@ -150,8 +166,13 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
 #if defined(HAVE_PCRE_H)
 		const char *errptr;
 		int erroff;
+		int study_options = 0;
+
+#ifdef PCRE_CONFIG_JIT
+		if (srv->srvconf.use_pcre_jit)
+			study_options = PCRE_STUDY_JIT_COMPILE;
 #endif
-
+#endif
 		s = calloc(1, sizeof(plugin_config));
 		s->db_filename    = buffer_init();
 		s->download_url   = buffer_init();
@@ -196,6 +217,17 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
 						s->download_url, "pos:", erroff);
 				return HANDLER_ERROR;
 			}
+			if (NULL == (s->download_regex_extra = pcre_study(s->download_regex,
+								      study_options, &errptr))) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						"studying regex for download-url failed:",
+						s->download_url);
+				return HANDLER_ERROR;
+			}
+#ifdef PCRE_CONFIG_JIT
+			if (srv->srvconf.use_pcre_jit)
+				pcre_assign_jit_stack(s->download_regex_extra, NULL, srv->jit_stack);
+#endif
 		}
 
 		if (!buffer_is_empty(s->trigger_url)) {
@@ -208,6 +240,17 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
 
 				return HANDLER_ERROR;
 			}
+			if (NULL == (s->trigger_regex_extra = pcre_study(s->trigger_regex,
+								      study_options, &errptr))) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						"studying regex for trigger-url failed:",
+						s->trigger_url);
+				return HANDLER_ERROR;
+			}
+#ifdef PCRE_CONFIG_JIT
+			if (srv->srvconf.use_pcre_jit)
+				pcre_assign_jit_stack(s->trigger_regex_extra, NULL, srv->jit_stack);
+#endif
 		}
 #endif
 
@@ -358,7 +401,7 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
 	}
 
 	/* check if URL is a trigger -> insert IP into DB */
-	if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
+	if ((n = pcre_exec(p->conf.trigger_regex, p->conf.trigger_regex_extra, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
 		if (n != PCRE_ERROR_NOMATCH) {
 			log_error_write(srv, __FILE__, __LINE__, "sd",
 					"execution error while matching:", n);
Index: src/keyvalue.c
===================================================================
--- src/keyvalue.c	(revision 2805)
+++ src/keyvalue.c	(working copy)
@@ -319,7 +319,13 @@ int pcre_keyvalue_buffer_append(server *srv, pcre_
 	const char *errptr;
 	int erroff;
 	pcre_keyvalue *kv;
+	int study_options = 0;
+
+#ifdef PCRE_CONFIG_JIT
+	if (srv->srvconf.use_pcre_jit)
+		study_options = PCRE_STUDY_JIT_COMPILE;
 #endif
+#endif
 
 	if (!key) return -1;
 
@@ -351,11 +357,14 @@ int pcre_keyvalue_buffer_append(server *srv, pcre_
 			"rexexp compilation error at ", errptr);
 		return -1;
 	}
-
-	if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
+	if (NULL == (kv->key_extra = pcre_study(kv->key, study_options, &errptr)) &&
 			errptr != NULL) {
 		return -1;
 	}
+#ifdef PCRE_CONFIG_JIT
+	if (srv->srvconf.use_pcre_jit)
+		pcre_assign_jit_stack(kv->key_extra, NULL, srv->jit_stack);
+#endif
 
 	kv->value = buffer_init_string(value);
 
@@ -378,7 +387,13 @@ void pcre_keyvalue_buffer_free(pcre_keyvalue_buffe
 	for (i = 0; i < kvb->size; i++) {
 		kv = kvb->kv[i];
 		if (kv->key) pcre_free(kv->key);
-		if (kv->key_extra) pcre_free(kv->key_extra);
+		if (kv->key_extra) {
+#ifdef PCRE_CONFIG_JIT
+			pcre_free_study(kv->key_extra);
+#else
+			pcre_free(kv->key_extra);
+#endif
+		}
 		if (kv->value) buffer_free(kv->value);
 		free(kv);
 	}
Index: src/server.c
===================================================================
--- src/server.c	(revision 2805)
+++ src/server.c	(working copy)
@@ -250,6 +250,11 @@ static server *server_init(void) {
 
 	srv->split_vals = array_init();
 
+#if defined(HAVE_PCRE_H) && defined(PCRE_CONFIG_JIT)
+	if (srv->srvconf.use_pcre_jit)
+		srv->jit_stack = pcre_jit_stack_alloc(32*1024, 1024*1024);
+#endif
+
 	return srv;
 }
 
@@ -349,6 +354,11 @@ static void server_free(server *srv) {
 	}
 #endif
 
+#if defined(HAVE_PCRE_H) && defined(PCRE_CONFIG_JIT)
+	if (srv->srvconf.use_pcre_jit && srv->jit_stack)
+		pcre_jit_stack_free(srv->jit_stack);
+#endif
+
 	free(srv);
 }
 
@@ -454,6 +464,11 @@ static void show_features (void) {
 #else
       "\t- PCRE support\n"
 #endif
+#if defined(HAVE_PCRE_H) && defined(PCRE_CONFIG_JIT)
+      "\t+ PCRE JIT support\n"
+#else
+      "\t- PCRE JIT support\n"
+#endif
 #ifdef HAVE_MYSQL
       "\t+ mySQL support\n"
 #else
Index: doc/config/lighttpd.conf
===================================================================
--- doc/config/lighttpd.conf	(revision 2805)
+++ doc/config/lighttpd.conf	(working copy)
@@ -262,6 +262,13 @@ server.max-connections = 1024
 #server.max-write-idle = 360
 
 ##
+## Enable JIT (just-in-time) compiling for PCRE regular expressions
+##
+## Default: disable
+##
+#server.use-pcre-jit = "disable"
+
+##
 ##  Traffic Shaping 
 ## -----------------
 ##
