summaryrefslogtreecommitdiffstats
path: root/byterun/interp.c
diff options
context:
space:
mode:
Diffstat (limited to 'byterun/interp.c')
-rw-r--r--byterun/interp.c61
1 files changed, 58 insertions, 3 deletions
diff --git a/byterun/interp.c b/byterun/interp.c
index 2c5df85d2..6622d4df8 100644
--- a/byterun/interp.c
+++ b/byterun/interp.c
@@ -1032,14 +1032,69 @@ value caml_interprete(code_t prog, asize_t prog_size)
/* Object-oriented operations */
-#define Lookup(obj, lab) \
- Field (Field (Field (obj, 0), ((lab) >> 16) / sizeof (value)), \
- ((lab) / sizeof (value)) & 0xFF)
+#define Lookup(obj, lab) Field (Field (obj, 0), Int_val(lab))
Instruct(GETMETHOD):
accu = Lookup(sp[0], accu);
Next;
+#define CAML_METHOD_CACHE
+#ifdef CAML_METHOD_CACHE
+ Instruct(GETPUBMET): {
+ /* accu == object, pc[0] == tag, pc[1] == cache */
+ value meths = Field (accu, 0);
+ value ofs;
+#ifdef CAML_TEST_CACHE
+ static int calls = 0, hits = 0;
+ if (calls >= 10000000) {
+ fprintf(stderr, "cache hit = %d%%\n", hits / 100000);
+ calls = 0; hits = 0;
+ }
+ calls++;
+#endif
+ *--sp = accu;
+ accu = Val_int(*pc++);
+ ofs = *pc & Field(meths,1);
+ if (*(value*)(((char*)&Field(meths,3)) + ofs) == accu) {
+#ifdef CAML_TEST_CACHE
+ hits++;
+#endif
+ accu = *(value*)(((char*)&Field(meths,2)) + ofs);
+ }
+ else
+ {
+ int li = 3, hi = Field(meths,0), mi;
+ while (li < hi) {
+ mi = ((li+hi) >> 1) | 1;
+ if (accu < Field(meths,mi)) hi = mi-2;
+ else li = mi;
+ }
+ *pc = (li-3)*sizeof(value);
+ accu = Field (meths, li-1);
+ }
+ pc++;
+ Next;
+ }
+#else
+ Instruct(GETPUBMET):
+ *--sp = accu;
+ accu = Val_int(*pc);
+ pc += 2;
+ /* Fallthrough */
+#endif
+ Instruct(GETDYNMET): {
+ /* accu == tag, sp[0] == object, *pc == cache */
+ value meths = Field (sp[0], 0);
+ int li = 3, hi = Field(meths,0), mi;
+ while (li < hi) {
+ mi = ((li+hi) >> 1) | 1;
+ if (accu < Field(meths,mi)) hi = mi-2;
+ else li = mi;
+ }
+ accu = Field (meths, li-1);
+ Next;
+ }
+
/* Debugging and machine control */
Instruct(STOP):