Browse Source

[eval] add a second string working pointer if we jump too far

closes #7474
Simon Krajewski 7 years ago
parent
commit
7b23db2926
3 changed files with 68 additions and 21 deletions
  1. 0 2
      src/macro/eval/evalDebugSocket.ml
  2. 62 18
      src/macro/eval/evalString.ml
  3. 6 1
      src/macro/eval/evalValue.ml

+ 0 - 2
src/macro/eval/evalDebugSocket.ml

@@ -181,8 +181,6 @@ let output_inner_vars v access =
 		| VString s -> [
 		| VString s -> [
 			"length",vint s.slength,access ^ ".length";
 			"length",vint s.slength,access ^ ".length";
 			"byteLength",vint (String.length s.sstring),access ^ ".byteLength";
 			"byteLength",vint (String.length s.sstring),access ^ ".byteLength";
-			"charOffset",vint (fst s.soffset),access ^ ".charOffset";
-			"byteOffset",vint (snd s.soffset),access ^ ".byteOffset";
 		]
 		]
 		| VArray va ->
 		| VArray va ->
 			let l = EvalArray.to_list va in
 			let l = EvalArray.to_list va in

+ 62 - 18
src/macro/eval/evalString.ml

@@ -21,17 +21,22 @@ open EvalValue
 
 
 let vstring s = VString s
 let vstring s = VString s
 
 
+let get_offset s =
+	let l = String.length s in
+	if l > 5 then VSOOne (ref (0,0))
+	else VSONone
+
 let create_ascii s =
 let create_ascii s =
 	{
 	{
 		sstring = s;
 		sstring = s;
 		slength = String.length s;
 		slength = String.length s;
-		soffset = (0,0);
+		soffset = get_offset s;
 	}
 	}
 
 
 let create_with_length s length = {
 let create_with_length s length = {
 	sstring = s;
 	sstring = s;
 	slength = length;
 	slength = length;
-	soffset = (0,0);
+	soffset = get_offset s;
 }
 }
 
 
 let create_unknown s =
 let create_unknown s =
@@ -61,22 +66,61 @@ let get_offset s c_index =
 		if c_len = 0 then b_offset else
 		if c_len = 0 then b_offset else
 		rget_b_offset (c_len + 1) (UTF8.prev s.sstring b_offset)
 		rget_b_offset (c_len + 1) (UTF8.prev s.sstring b_offset)
 	in
 	in
-	let (c_index',b_offset') = s.soffset in
-	let b_offset = match c_index - c_index' with
-		| 0 -> b_offset'
-		| 1 -> UTF8.next s.sstring b_offset'
-		| -1 -> UTF8.prev s.sstring b_offset'
-		| diff ->
-			if diff > 0 then
-				get_b_offset diff b_offset'
-			else if c_index + diff < 0 then
-				(* big step backwards, better to start over *)
-				get_b_offset c_index 0
-			else
-				rget_b_offset diff b_offset'
-	in
-	s.soffset <- (c_index,b_offset);
-	b_offset
+	match s.soffset with
+	| VSONone ->
+		get_b_offset c_index 0
+	| VSOOne r1 ->
+		let (c_index1,b_offset1) = !r1 in
+		let diff = c_index - c_index1 in
+		let b_offset = match diff with
+			| 0 -> b_offset1
+			| 1 -> UTF8.next s.sstring b_offset1
+			| -1 -> UTF8.prev s.sstring b_offset1
+			| _ ->
+				if diff > 0 then
+					get_b_offset diff b_offset1
+				else if c_index + diff < 0 then
+					(* big step backwards, better to start over *)
+					get_b_offset c_index 0
+				else
+					rget_b_offset diff b_offset1
+		in
+		(* If our jump is larger than the scientifically determined value 20, upgrade
+		   to two offset pointers. *)
+		if abs diff > 20 then s.soffset <- VSOTwo(r1,ref (c_index,b_offset))
+		else r1 := (c_index,b_offset);
+		b_offset
+	| VSOTwo(r1,r2) ->
+		let (c_index1,b_offset1) = !r1 in
+		let (c_index2,b_offset2) = !r2 in
+		let diff1 = c_index - c_index1 in
+		let diff2 = c_index - c_index2 in
+		let first,b_offset = match diff1,diff2 with
+			| 0,_ -> true,b_offset1
+			| _,0 -> false,b_offset2
+			| 1,_ -> true,UTF8.next s.sstring b_offset1
+			| _,1 -> false,UTF8.next s.sstring b_offset2
+			| -1,_ -> true,UTF8.prev s.sstring b_offset1
+			| _,-1 -> false,UTF8.prev s.sstring b_offset2
+			| _ ->
+				let first,diff,b_offset' = if abs diff1 > abs diff2 then
+					false,diff2,b_offset2
+				else
+					true,diff1,b_offset1
+				in
+				let b_offset = if diff > 0 then
+					get_b_offset diff b_offset'
+				else if c_index + diff < 0 then
+					(* big step backwards, better to start over *)
+					get_b_offset c_index 0
+				else
+					rget_b_offset diff b_offset'
+				in
+				first,b_offset
+		in
+		if first then r1 := (c_index,b_offset)
+		else r2 := (c_index,b_offset);
+		b_offset
 
 
 let char_at s c_index =
 let char_at s c_index =
 	let b_offset = get_offset s c_index in
 	let b_offset = get_offset s c_index in

+ 6 - 1
src/macro/eval/evalValue.ml

@@ -26,6 +26,11 @@ type cmp =
 	| CInf
 	| CInf
 	| CUndef
 	| CUndef
 
 
+type vstring_offset =
+	| VSONone
+	| VSOOne of (int * int) ref
+	| VSOTwo of (int * int) ref * (int * int) ref
+
 type vstring = {
 type vstring = {
 	(* The bytes representation of the string. This is only evaluated if we
 	(* The bytes representation of the string. This is only evaluated if we
 	   need it for something like random access. *)
 	   need it for something like random access. *)
@@ -33,7 +38,7 @@ type vstring = {
 	(* The length of the string. *)
 	(* The length of the string. *)
 	slength : int;
 	slength : int;
 	(* The current (character * byte) offsets. *)
 	(* The current (character * byte) offsets. *)
-	mutable soffset : (int * int);
+	mutable soffset : vstring_offset;
 }
 }
 
 
 type vstring_buffer = {
 type vstring_buffer = {